@godxjp/ui 19.0.0 → 19.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -128
- package/dist/app/app-provider.d.ts +1 -1
- package/dist/app/app-provider.js +3 -0
- package/dist/app/theme-axes.d.ts +4 -15
- package/dist/app/timezones.d.ts +1 -4
- package/dist/components/charts/area-chart.d.ts +2 -3
- package/dist/components/charts/bar-chart.d.ts +2 -3
- package/dist/components/charts/chart-frame.d.ts +7 -16
- package/dist/components/charts/chart-summary.d.ts +2 -2
- package/dist/components/charts/compact-bar-trend.d.ts +9 -24
- package/dist/components/charts/index.d.ts +1 -6
- package/dist/components/data-display/badge.d.ts +2 -12
- package/dist/components/data-display/card.d.ts +21 -41
- package/dist/components/data-display/carousel.d.ts +1 -2
- package/dist/components/data-display/code-block.d.ts +4 -0
- package/dist/components/data-display/code-block.js +24 -0
- package/dist/components/data-display/data-table.d.ts +15 -37
- package/dist/components/data-display/data-table.js +1 -3
- package/dist/components/data-display/descriptions.d.ts +2 -6
- package/dist/components/data-display/descriptions.js +0 -2
- package/dist/components/data-display/index.d.ts +4 -0
- package/dist/components/data-display/index.js +4 -0
- package/dist/components/data-display/list-row.d.ts +3 -22
- package/dist/components/data-display/permission-matrix.d.ts +7 -20
- package/dist/components/data-display/progress.d.ts +1 -1
- package/dist/components/data-display/prose.d.ts +4 -0
- package/dist/components/data-display/prose.js +20 -0
- package/dist/components/data-display/service-launcher-card.d.ts +3 -10
- package/dist/components/data-display/table.d.ts +20 -80
- package/dist/components/data-display/table.js +0 -3
- package/dist/components/data-display/timeline.d.ts +3 -5
- package/dist/components/data-entry/branch-scope-picker.d.ts +2 -19
- package/dist/components/data-entry/branch-scope-picker.js +0 -1
- package/dist/components/data-entry/calendar.d.ts +3 -2
- package/dist/components/data-entry/calendar.js +58 -3
- package/dist/components/data-entry/cascader.js +3 -1
- package/dist/components/data-entry/checkbox-group.js +12 -5
- package/dist/components/data-entry/checkbox.js +30 -21
- package/dist/components/data-entry/command-palette.d.ts +8 -22
- package/dist/components/data-entry/date-picker.d.ts +4 -5
- package/dist/components/data-entry/date-picker.js +12 -3
- package/dist/components/data-entry/date-range-picker.d.ts +1 -1
- package/dist/components/data-entry/date-range-picker.js +17 -6
- package/dist/components/data-entry/form-errors.d.ts +7 -18
- package/dist/components/data-entry/form-field.d.ts +1 -1
- package/dist/components/data-entry/form-field.js +15 -6
- package/dist/components/data-entry/form.d.ts +1 -9
- package/dist/components/data-entry/input.d.ts +16 -14
- package/dist/components/data-entry/input.js +13 -3
- package/dist/components/data-entry/month-picker.js +6 -4
- package/dist/components/data-entry/month-range-picker.d.ts +4 -6
- package/dist/components/data-entry/month-range-picker.js +11 -5
- package/dist/components/data-entry/number-input.d.ts +1 -5
- package/dist/components/data-entry/number-input.js +1 -0
- package/dist/components/data-entry/radio.js +19 -6
- package/dist/components/data-entry/search-select.d.ts +3 -5
- package/dist/components/data-entry/search-select.js +8 -2
- package/dist/components/data-entry/select.d.ts +15 -2
- package/dist/components/data-entry/select.js +57 -10
- package/dist/components/data-entry/switch.js +9 -2
- package/dist/components/data-entry/textarea.d.ts +10 -16
- package/dist/components/data-entry/textarea.js +8 -1
- package/dist/components/data-entry/time-picker.d.ts +3 -5
- package/dist/components/data-entry/tree-select.js +3 -1
- package/dist/components/data-entry/upload-types.d.ts +1 -5
- package/dist/components/data-entry/use-upload-draft.d.ts +0 -4
- package/dist/components/feedback/dialog.d.ts +6 -15
- package/dist/components/feedback/overlay-header-tone.d.ts +1 -1
- package/dist/components/feedback/sheet.d.ts +3 -10
- package/dist/components/feedback/sheet.js +1 -1
- package/dist/components/feedback/sonner.js +2 -3
- package/dist/components/general/activity.d.ts +4 -30
- package/dist/components/general/button.js +1 -10
- package/dist/components/general/logo.d.ts +6 -28
- package/dist/components/general/reveal.d.ts +3 -9
- package/dist/components/general/typography.d.ts +1 -3
- package/dist/components/layout/account-chip.d.ts +8 -0
- package/dist/components/layout/account-chip.js +45 -0
- package/dist/components/layout/auth-divider.d.ts +2 -9
- package/dist/components/layout/auth-shell.d.ts +1 -14
- package/dist/components/layout/breadcrumb.d.ts +1 -5
- package/dist/components/layout/centered-shell.d.ts +4 -18
- package/dist/components/layout/error-surface.d.ts +11 -28
- package/dist/components/layout/error-surface.js +4 -1
- package/dist/components/layout/index.d.ts +2 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/components/layout/legal-document-shell.d.ts +5 -28
- package/dist/components/layout/master-detail.d.ts +2 -18
- package/dist/components/layout/page-container.js +0 -1
- package/dist/components/layout/responsive-grid.d.ts +6 -1
- package/dist/components/layout/responsive-grid.js +9 -2
- package/dist/components/layout/service-role-panel.d.ts +7 -19
- package/dist/components/layout/sidebar.d.ts +5 -27
- package/dist/components/layout/sidebar.js +0 -1
- package/dist/components/layout/split-pane.d.ts +0 -7
- package/dist/components/layout/topbar.d.ts +1 -14
- package/dist/components/navigation/app-setting-picker.js +1 -3
- package/dist/components/navigation/filter-bar.d.ts +1 -6
- package/dist/components/navigation/pagination-utils.d.ts +2 -12
- package/dist/components/navigation/tabs-scroll.d.ts +2 -36
- package/dist/components/navigation/tabs.js +4 -8
- package/dist/components/query/data-state.d.ts +2 -2
- package/dist/components/ui/credential-reveal.d.ts +1 -4
- package/dist/components/ui/hover-card.d.ts +1 -2
- package/dist/components/ui/separator.d.ts +2 -15
- package/dist/components/ui/toggle-group.d.ts +1 -5
- package/dist/components/ui/toggle.d.ts +6 -31
- package/dist/email/brand-mark.d.ts +6 -34
- package/dist/email/color.d.ts +7 -17
- package/dist/email/geometry.d.ts +4 -8
- package/dist/email/index.d.ts +4 -48
- package/dist/email/inline-style.d.ts +3 -9
- package/dist/email/urgency.d.ts +2 -7
- package/dist/form/form-context.d.ts +2 -5
- package/dist/form/form-root.d.ts +1 -2
- package/dist/i18n/messages/en.json +4 -0
- package/dist/i18n/messages/ja.json +4 -0
- package/dist/i18n/messages/vi.json +4 -0
- package/dist/inertia/index.d.ts +2 -10
- package/dist/lib/control-styles.d.ts +10 -21
- package/dist/lib/control-styles.js +4 -6
- package/dist/lib/datetime/format-date.d.ts +1 -4
- package/dist/lib/field-a11y.d.ts +31 -36
- package/dist/lib/field-a11y.js +16 -2
- package/dist/lib/format.d.ts +4 -8
- package/dist/lib/hooks.d.ts +6 -12
- package/dist/lib/permission-grid.d.ts +3 -18
- package/dist/lib/query-error.d.ts +3 -3
- package/dist/props/components/app.prop.d.ts +19 -27
- package/dist/props/components/charts.prop.d.ts +2 -3
- package/dist/props/components/data-display.prop.d.ts +48 -72
- package/dist/props/components/data-entry.prop.d.ts +41 -30
- package/dist/props/components/form.prop.d.ts +2 -6
- package/dist/props/components/general.prop.d.ts +11 -27
- package/dist/props/components/layout.prop.d.ts +89 -260
- package/dist/props/components/navigation.prop.d.ts +27 -42
- package/dist/props/registry.d.ts +31 -0
- package/dist/props/registry.js +33 -0
- package/dist/props/vocabulary/data.prop.d.ts +18 -49
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +10 -12
- package/dist/props/vocabulary/layout.prop.d.ts +8 -30
- package/dist/props/vocabulary/shared.prop.d.ts +3 -2
- package/dist/styles/alert-layout.css +1 -32
- package/dist/styles/badge-layout.css +4 -18
- package/dist/styles/base.css +14 -113
- package/dist/styles/card-layout.css +6 -128
- package/dist/styles/chart-layout.css +2 -17
- package/dist/styles/control.css +380 -458
- package/dist/styles/core.css +21 -0
- package/dist/styles/data-display-layout.css +175 -94
- package/dist/styles/data-entry-layout.css +0 -45
- package/dist/styles/density.css +1 -30
- package/dist/styles/dialog-layout.css +5 -69
- package/dist/styles/focus-ring.css +13 -87
- package/dist/styles/fonts.css +1 -31
- package/dist/styles/form-layout.css +7 -91
- package/dist/styles/index.css +2 -20
- package/dist/styles/layout.css +38 -456
- package/dist/styles/logo-layout.css +1 -35
- package/dist/styles/motion.css +3 -42
- package/dist/styles/navigation-layout.css +3 -50
- package/dist/styles/shell-layout.css +37 -403
- package/dist/styles/table-layout.css +16 -274
- package/dist/styles/text-layout.css +7 -21
- package/dist/styles/toggle.css +1 -23
- package/dist/theme/dxs.canonical.css +1 -55
- package/dist/theme/example.service.css +1 -26
- package/dist/theme/famgia.service.css +5 -15
- package/dist/tokens/axes.css +3 -40
- package/dist/tokens/base.css +1 -4
- package/dist/tokens/components/activity.css +6 -42
- package/dist/tokens/components/badge.css +4 -13
- package/dist/tokens/components/banner.css +4 -9
- package/dist/tokens/components/card.css +32 -88
- package/dist/tokens/components/chart.css +9 -26
- package/dist/tokens/components/control.css +37 -222
- package/dist/tokens/components/data-display.css +28 -79
- package/dist/tokens/components/data-entry.css +5 -19
- package/dist/tokens/components/descriptions.css +7 -27
- package/dist/tokens/components/email.css +38 -84
- package/dist/tokens/components/error-surface.css +2 -18
- package/dist/tokens/components/feedback.css +27 -124
- package/dist/tokens/components/form.css +13 -45
- package/dist/tokens/components/legal-document.css +16 -41
- package/dist/tokens/components/list-row.css +11 -36
- package/dist/tokens/components/logo.css +2 -57
- package/dist/tokens/components/navigation.css +16 -94
- package/dist/tokens/components/scroll-area.css +2 -18
- package/dist/tokens/components/separator.css +8 -30
- package/dist/tokens/components/sheet.css +3 -14
- package/dist/tokens/components/shell.css +53 -307
- package/dist/tokens/components/sidebar.css +5 -22
- package/dist/tokens/components/table.css +19 -140
- package/dist/tokens/components/toggle.css +3 -65
- package/dist/tokens/components/upload.css +7 -43
- package/dist/tokens/foundation.css +108 -383
- package/dist/tokens/semantic/layout.css +33 -207
- package/docs/CANONICAL-CONTRACTS.md +206 -0
- package/docs/COMPONENTS.md +157 -0
- package/docs/COMPOSITION-VS-COMPONENT.md +105 -0
- package/docs/CONSUMER-RULES.md +14 -0
- package/docs/CUSTOMER-THEMING.md +162 -0
- package/docs/DATETIME.md +69 -0
- package/docs/DEVELOPMENT.md +173 -0
- package/docs/FORMS.md +143 -0
- package/docs/FRAME-A11Y-CI.md +267 -0
- package/docs/FRAME-COVERAGE-LEDGER.md +123 -0
- package/docs/FRAME-COVERAGE-REPORT.md +140 -0
- package/docs/FRAME-COVERAGE-STANDARD.md +65 -0
- package/docs/FRAME-COVERAGE.md +29 -0
- package/docs/PROPS-REGISTRY.md +61 -0
- package/docs/PROPS-VOCABULARY.md +100 -0
- package/docs/README.md +60 -0
- package/docs/REGISTRY.md +70 -0
- package/docs/SPACING.md +56 -0
- package/docs/STANDARDS-vocabulary-tokens.md +48 -0
- package/docs/TESTING.md +98 -0
- package/docs/TOKENS.md +347 -0
- package/docs/asset-modules.d.ts +46 -0
- package/docs/assets/cover-terrain.svg +6 -0
- package/docs/assets/portrait-amber.svg +5 -0
- package/docs/assets/portrait-clay.svg +5 -0
- package/docs/assets/portrait-indigo.svg +5 -0
- package/docs/assets/portrait-iris.svg +5 -0
- package/docs/assets/portrait-moss.svg +5 -0
- package/docs/assets/portrait-plum.svg +5 -0
- package/docs/assets/portrait-slate.svg +5 -0
- package/docs/charts/compact-bar-trend.tsx +328 -0
- package/docs/charts/size-tiers.tsx +192 -0
- package/docs/data-display/accordion.tsx +99 -0
- package/docs/data-display/avatar.tsx +355 -0
- package/docs/data-display/badge.tsx +247 -0
- package/docs/data-display/card/examples/detail-panel.tsx +106 -0
- package/docs/data-display/card/index.md +3 -0
- package/docs/data-display/card/index.tsx +285 -0
- package/docs/data-display/carousel.tsx +156 -0
- package/docs/data-display/charts.tsx +198 -0
- package/docs/data-display/code-block.tsx +90 -0
- package/docs/data-display/collapsible.tsx +162 -0
- package/docs/data-display/credential-reveal.tsx +145 -0
- package/docs/data-display/data-table/examples/approval-queue.tsx +212 -0
- package/docs/data-display/data-table/examples/grid-features.tsx +158 -0
- package/docs/data-display/data-table/examples/list-page.tsx +175 -0
- package/docs/data-display/data-table/index.md +5 -0
- package/docs/data-display/data-table/index.tsx +295 -0
- package/docs/data-display/descriptions.tsx +143 -0
- package/docs/data-display/empty-state.tsx +164 -0
- package/docs/data-display/hover-card.tsx +181 -0
- package/docs/data-display/list-row.tsx +420 -0
- package/docs/data-display/permission-matrix.tsx +184 -0
- package/docs/data-display/popover-touch.tsx +27 -0
- package/docs/data-display/popover.tsx +245 -0
- package/docs/data-display/progress.tsx +84 -0
- package/docs/data-display/prose.tsx +105 -0
- package/docs/data-display/qr-code.tsx +68 -0
- package/docs/data-display/scroll-area.tsx +271 -0
- package/docs/data-display/service-launcher-card.tsx +145 -0
- package/docs/data-display/stat-card.tsx +99 -0
- package/docs/data-display/table.tsx +251 -0
- package/docs/data-display/timeline.tsx +112 -0
- package/docs/data-display/touch-actions.tsx +36 -0
- package/docs/data-display/tree-list.tsx +107 -0
- package/docs/data-entry/branch-scope-picker.tsx +123 -0
- package/docs/data-entry/calendar.tsx +180 -0
- package/docs/data-entry/cascader.tsx +378 -0
- package/docs/data-entry/checkbox.tsx +256 -0
- package/docs/data-entry/color-picker.tsx +117 -0
- package/docs/data-entry/command-palette.tsx +179 -0
- package/docs/data-entry/command.tsx +262 -0
- package/docs/data-entry/country-picker-recipe.tsx +170 -0
- package/docs/data-entry/date-picker.tsx +191 -0
- package/docs/data-entry/date-range-picker.tsx +149 -0
- package/docs/data-entry/form/examples/employee-settings.tsx +267 -0
- package/docs/data-entry/form/examples/invoice-form.tsx +387 -0
- package/docs/data-entry/form-field/examples/a11y-contract.tsx +240 -0
- package/docs/data-entry/form-field/examples/create-form.tsx +105 -0
- package/docs/data-entry/form-field/index.md +8 -0
- package/docs/data-entry/form-field/index.tsx +326 -0
- package/docs/data-entry/form-inertia.tsx +80 -0
- package/docs/data-entry/form-root.tsx +102 -0
- package/docs/data-entry/form.tsx +724 -0
- package/docs/data-entry/input-otp.tsx +231 -0
- package/docs/data-entry/input.tsx +114 -0
- package/docs/data-entry/label.tsx +100 -0
- package/docs/data-entry/month-picker.tsx +101 -0
- package/docs/data-entry/month-range-picker.tsx +115 -0
- package/docs/data-entry/number-input.tsx +240 -0
- package/docs/data-entry/password-input.tsx +106 -0
- package/docs/data-entry/password-strength.tsx +97 -0
- package/docs/data-entry/radio-group.tsx +95 -0
- package/docs/data-entry/rating.tsx +87 -0
- package/docs/data-entry/search-input.tsx +120 -0
- package/docs/data-entry/select-async-contracts.tsx +108 -0
- package/docs/data-entry/select-matrix.tsx +204 -0
- package/docs/data-entry/select.tsx +369 -0
- package/docs/data-entry/slider.tsx +130 -0
- package/docs/data-entry/switch.tsx +67 -0
- package/docs/data-entry/tag-input.tsx +108 -0
- package/docs/data-entry/textarea.tsx +209 -0
- package/docs/data-entry/time-picker.tsx +99 -0
- package/docs/data-entry/toggle-count.tsx +293 -0
- package/docs/data-entry/toggle-group.tsx +225 -0
- package/docs/data-entry/toggle.tsx +127 -0
- package/docs/data-entry/transfer.tsx +97 -0
- package/docs/data-entry/tree-select.tsx +204 -0
- package/docs/data-entry/upload.tsx +184 -0
- package/docs/feedback/alert-dialog.tsx +270 -0
- package/docs/feedback/alert.tsx +248 -0
- package/docs/feedback/banner.tsx +183 -0
- package/docs/feedback/danger-confirm.tsx +88 -0
- package/docs/feedback/dialog-touch.tsx +24 -0
- package/docs/feedback/dialog.tsx +193 -0
- package/docs/feedback/sheet.tsx +410 -0
- package/docs/feedback/skeleton.tsx +111 -0
- package/docs/feedback/toast.tsx +135 -0
- package/docs/feedback/tooltip.tsx +171 -0
- package/docs/feedback/two-factor-setup.tsx +68 -0
- package/docs/foundation/_email-specimen.ts +274 -0
- package/docs/foundation/colors.tsx +202 -0
- package/docs/foundation/density.tsx +232 -0
- package/docs/foundation/email-tokens.tsx +306 -0
- package/docs/foundation/radius-shadow.tsx +152 -0
- package/docs/foundation/spacing.tsx +211 -0
- package/docs/foundation/typography.tsx +147 -0
- package/docs/general/activity.tsx +224 -0
- package/docs/general/button/examples/destructive-confirm.tsx +90 -0
- package/docs/general/button/examples/form-actions.tsx +85 -0
- package/docs/general/button/examples/toolbar.tsx +160 -0
- package/docs/general/button/index.md +12 -0
- package/docs/general/button/index.tsx +211 -0
- package/docs/general/logo.tsx +131 -0
- package/docs/general/reveal.tsx +41 -0
- package/docs/general/typography.tsx +152 -0
- package/docs/layout/account-chip.tsx +72 -0
- package/docs/layout/admin-collection.tsx +122 -0
- package/docs/layout/app-shell.tsx +374 -0
- package/docs/layout/aspect-ratio.tsx +119 -0
- package/docs/layout/auth-account-summary.tsx +103 -0
- package/docs/layout/auth-divider.tsx +28 -0
- package/docs/layout/auth-footer.tsx +37 -0
- package/docs/layout/auth-identity.tsx +36 -0
- package/docs/layout/auth-recovery/examples/mfa-challenge.md +41 -0
- package/docs/layout/auth-recovery/examples/mfa-challenge.tsx +254 -0
- package/docs/layout/auth-recovery/examples/mobile-390.md +25 -0
- package/docs/layout/auth-recovery/examples/mobile-390.tsx +82 -0
- package/docs/layout/auth-recovery/examples/password-recovery.md +24 -0
- package/docs/layout/auth-recovery/examples/password-recovery.tsx +197 -0
- package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.md +27 -0
- package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.tsx +156 -0
- package/docs/layout/auth-recovery/index.md +140 -0
- package/docs/layout/auth-recovery/index.tsx +96 -0
- package/docs/layout/auth-shell-context.tsx +103 -0
- package/docs/layout/auth-shell-device.tsx +112 -0
- package/docs/layout/auth-shell-registration.tsx +335 -0
- package/docs/layout/auth-shell-variants.tsx +139 -0
- package/docs/layout/auth-shell.tsx +59 -0
- package/docs/layout/auth-stack.tsx +40 -0
- package/docs/layout/centered-shell.tsx +102 -0
- package/docs/layout/error-surface/examples/application-403.tsx +84 -0
- package/docs/layout/error-surface/examples/application-404.tsx +77 -0
- package/docs/layout/error-surface/examples/system-500.tsx +47 -0
- package/docs/layout/error-surface/examples/system-503.tsx +48 -0
- package/docs/layout/error-surface/index.md +153 -0
- package/docs/layout/error-surface/index.tsx +239 -0
- package/docs/layout/flex.tsx +262 -0
- package/docs/layout/legal-document-shell/_data.ts +110 -0
- package/docs/layout/legal-document-shell/examples/desktop-1440.md +12 -0
- package/docs/layout/legal-document-shell/examples/desktop-1440.tsx +83 -0
- package/docs/layout/legal-document-shell/examples/mobile-390.md +22 -0
- package/docs/layout/legal-document-shell/examples/mobile-390.tsx +70 -0
- package/docs/layout/legal-document-shell/examples/tablet-1024.md +3 -0
- package/docs/layout/legal-document-shell/examples/tablet-1024.tsx +84 -0
- package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.md +18 -0
- package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.tsx +61 -0
- package/docs/layout/legal-document-shell/index.md +51 -0
- package/docs/layout/legal-document-shell/index.tsx +101 -0
- package/docs/layout/master-detail.tsx +387 -0
- package/docs/layout/org-switcher.tsx +131 -0
- package/docs/layout/page-container.tsx +946 -0
- package/docs/layout/resizable-panel.tsx +419 -0
- package/docs/layout/responsive-grid.tsx +235 -0
- package/docs/layout/separator.tsx +327 -0
- package/docs/layout/service-role-panel.tsx +144 -0
- package/docs/layout/sidebar.tsx +586 -0
- package/docs/layout/split-pane.tsx +451 -0
- package/docs/layout/topbar.tsx +347 -0
- package/docs/navigation/app-setting-picker.tsx +141 -0
- package/docs/navigation/breadcrumb.tsx +128 -0
- package/docs/navigation/context-menu.tsx +117 -0
- package/docs/navigation/dropdown-menu.tsx +213 -0
- package/docs/navigation/filter-bar.tsx +227 -0
- package/docs/navigation/menubar.tsx +141 -0
- package/docs/navigation/navigation-menu.tsx +165 -0
- package/docs/navigation/pagination.tsx +241 -0
- package/docs/navigation/steps.tsx +263 -0
- package/docs/navigation/tabs-rtl.tsx +28 -0
- package/docs/navigation/tabs.tsx +308 -0
- package/docs/navigation/toolbar.tsx +339 -0
- package/docs/providers/app-provider.tsx +191 -0
- package/docs/providers/format-date.tsx +230 -0
- package/docs/query/button-refetch.tsx +160 -0
- package/docs/query/data-state.tsx +192 -0
- package/docs/query/infinite-query-state.tsx +93 -0
- package/docs/query/mutation-feedback.tsx +70 -0
- package/docs/query/prefetch-link.tsx +262 -0
- package/docs/query/touch-actions.tsx +68 -0
- package/docs/showcase/acme-portal.tsx +441 -0
- package/docs/showcase/acme-website.tsx +455 -0
- package/docs/showcase/case1-warehouse-dashboard.tsx +343 -0
- package/docs/showcase/case2-employee-me.tsx +441 -0
- package/docs/showcase/case3-approval-workflow.tsx +527 -0
- package/docs/showcase/case4-login.tsx +307 -0
- package/docs/showcase/case5-shift-calendar.tsx +795 -0
- package/docs/showcase/case6-agency-handy.tsx +1072 -0
- package/docs/showcase/futurelastic-web.tsx +390 -0
- package/docs/showcase/org-switcher.tsx +313 -0
- package/docs/showcase/permission-matrix.tsx +343 -0
- package/docs/showcase/public-landing.tsx +210 -0
- package/docs/showcase/settings-account-sections.tsx +559 -0
- package/docs/showcase/settings-security-mfa.tsx +145 -0
- package/docs/showcase/table-approval-queue.tsx +199 -0
- package/docs/showcase/table-bulk-actions.tsx +460 -0
- package/docs/showcase/table-compact-kintone.tsx +438 -0
- package/docs/showcase/table-conditional-format.tsx +367 -0
- package/docs/showcase/table-crud-list.tsx +544 -0
- package/docs/showcase/table-density.tsx +340 -0
- package/docs/showcase/table-expandable-rows.tsx +471 -0
- package/docs/showcase/table-filter-chips.tsx +461 -0
- package/docs/showcase/table-footer-totals.tsx +311 -0
- package/docs/showcase/table-grouped-subtotals.tsx +388 -0
- package/docs/showcase/table-master-detail.tsx +479 -0
- package/docs/showcase/table-pagination.tsx +320 -0
- package/docs/showcase/table-states.tsx +363 -0
- package/docs/showcase/table-sticky-columns.tsx +373 -0
- package/docs/showcase/table-tree-rows.tsx +444 -0
- package/docs/showcase/table-view-tabs.tsx +488 -0
- package/package.json +10 -11
- package/scripts/_agent-setup.mjs +16 -2
- package/scripts/audit-hook.mjs +3 -13
- package/scripts/init-agent-kit.mjs +1 -14
- package/scripts/postinstall.mjs +12 -12
- package/scripts/ui-audit.mjs +93 -31
- package/scripts/visual-audit-rules.mjs +51 -7
- package/scripts/visual-audit.mjs +118 -47
|
@@ -1,24 +1,78 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
3
4
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
4
|
-
import { DayPicker } from "react-day-picker";
|
|
5
|
+
import { DayPicker, dateMatchModifiers } from "react-day-picker";
|
|
6
|
+
import { useTranslation } from "../../i18n/use-translation.js";
|
|
5
7
|
import { cn } from "../../lib/utils.js";
|
|
6
8
|
import { controlIconSmClass } from "../../lib/control-styles.js";
|
|
7
|
-
import { buttonVariants } from "../general/button.js";
|
|
9
|
+
import { Button, buttonVariants } from "../general/button.js";
|
|
10
|
+
const startOfDay = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
11
|
+
const startOfMonth = (date) => new Date(date.getFullYear(), date.getMonth(), 1);
|
|
12
|
+
const endOfMonth = (date) => new Date(date.getFullYear(), date.getMonth() + 1, 0);
|
|
13
|
+
const sameDay = (a, b) => startOfDay(a).getTime() === startOfDay(b).getTime();
|
|
8
14
|
function Calendar({
|
|
9
15
|
className,
|
|
10
16
|
classNames,
|
|
11
17
|
showOutsideDays = true,
|
|
12
18
|
"aria-label": ariaLabel,
|
|
13
19
|
labels,
|
|
20
|
+
showToday = false,
|
|
21
|
+
showClose = false,
|
|
22
|
+
onClose,
|
|
23
|
+
footer,
|
|
24
|
+
month: monthProp,
|
|
25
|
+
onMonthChange,
|
|
14
26
|
...props
|
|
15
27
|
}) {
|
|
28
|
+
const { t } = useTranslation();
|
|
29
|
+
const [month, setMonth] = React.useState(monthProp ?? props.defaultMonth);
|
|
30
|
+
const today = startOfDay(props.today ?? /* @__PURE__ */ new Date());
|
|
31
|
+
const todayDisabled = props.startMonth != null && today < startOfMonth(props.startMonth) || props.endMonth != null && today > endOfMonth(props.endMonth) || props.disabled != null && dateMatchModifiers(today, props.disabled);
|
|
32
|
+
const modifiers = { today: true };
|
|
33
|
+
const selectToday = (event) => {
|
|
34
|
+
setMonth(startOfMonth(today));
|
|
35
|
+
onMonthChange?.(startOfMonth(today));
|
|
36
|
+
if (props.mode === "single") {
|
|
37
|
+
props.onSelect?.(today, today, modifiers, event);
|
|
38
|
+
} else if (props.mode === "multiple") {
|
|
39
|
+
const current = props.selected ?? [];
|
|
40
|
+
const next = current.some((day) => sameDay(day, today)) ? current : [...current, today];
|
|
41
|
+
props.onSelect?.(next, today, modifiers, event);
|
|
42
|
+
} else if (props.mode === "range") {
|
|
43
|
+
const from = props.selected?.from;
|
|
44
|
+
const to = props.selected?.to;
|
|
45
|
+
const next = from && !to ? today < from ? { from: today, to: from } : { from, to: today } : { from: today, to: void 0 };
|
|
46
|
+
props.onSelect?.(next, today, modifiers, event);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const actions = showToday || showClose ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
50
|
+
showToday ? /* @__PURE__ */ jsx(
|
|
51
|
+
Button,
|
|
52
|
+
{
|
|
53
|
+
type: "button",
|
|
54
|
+
variant: "ghost",
|
|
55
|
+
size: "sm",
|
|
56
|
+
className: "ui-calendar-footer-today",
|
|
57
|
+
disabled: todayDisabled,
|
|
58
|
+
onClick: selectToday,
|
|
59
|
+
children: t("dataEntry.calendar.today") ?? "Today"
|
|
60
|
+
}
|
|
61
|
+
) : null,
|
|
62
|
+
showClose ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: onClose, children: t("dataEntry.calendar.close") ?? "Close" }) : null
|
|
63
|
+
] }) : void 0;
|
|
16
64
|
const rangeDefaults = props.mode === "range" ? { resetOnSelect: props.resetOnSelect ?? true } : null;
|
|
17
65
|
return /* @__PURE__ */ jsx(
|
|
18
66
|
DayPicker,
|
|
19
67
|
{
|
|
20
68
|
showOutsideDays,
|
|
21
69
|
"aria-label": ariaLabel,
|
|
70
|
+
month: showToday ? monthProp ?? month : monthProp,
|
|
71
|
+
onMonthChange: (next) => {
|
|
72
|
+
setMonth(next);
|
|
73
|
+
onMonthChange?.(next);
|
|
74
|
+
},
|
|
75
|
+
footer: footer ?? actions,
|
|
22
76
|
labels: {
|
|
23
77
|
...labels,
|
|
24
78
|
labelNav: labels?.labelNav ?? (() => `${ariaLabel ?? "Calendar"} navigation`)
|
|
@@ -81,6 +135,7 @@ function Calendar({
|
|
|
81
135
|
),
|
|
82
136
|
disabled: cn("ui-calendar-day-disabled", classNames?.disabled),
|
|
83
137
|
hidden: cn("invisible", classNames?.hidden),
|
|
138
|
+
footer: cn("ui-calendar-footer", classNames?.footer),
|
|
84
139
|
...classNames
|
|
85
140
|
},
|
|
86
141
|
components: {
|
|
@@ -4,7 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
import { Check, ChevronRight, ChevronsUpDown, Minus, X } from "lucide-react";
|
|
5
5
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
-
import { pickFieldA11y } from "../../lib/field-a11y.js";
|
|
7
|
+
import { pickFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
|
|
8
8
|
import { controlOpenRingClass } from "../../lib/control-styles.js";
|
|
9
9
|
import { Button } from "../general/button.js";
|
|
10
10
|
import { Popover, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
|
|
@@ -86,6 +86,7 @@ function Cascader({
|
|
|
86
86
|
}) {
|
|
87
87
|
const { t } = useTranslation();
|
|
88
88
|
const fieldA11y = pickFieldA11y(ariaProps);
|
|
89
|
+
const identity = useFieldIdentity({ id, "data-field": fieldA11y["data-field"] });
|
|
89
90
|
const reactId = React.useId();
|
|
90
91
|
const panelId = `${id ?? reactId}-panel`;
|
|
91
92
|
const options = React.useMemo(
|
|
@@ -240,6 +241,7 @@ function Cascader({
|
|
|
240
241
|
Button,
|
|
241
242
|
{
|
|
242
243
|
id,
|
|
244
|
+
"data-field": fieldA11y["data-field"] ?? identity["data-field"],
|
|
243
245
|
type: "button",
|
|
244
246
|
variant: "outline",
|
|
245
247
|
role: "combobox",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
|
-
import { pickGroupFieldA11y } from "../../lib/field-a11y.js";
|
|
5
|
+
import { pickGroupFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
|
|
6
6
|
import { Checkbox } from "./checkbox.js";
|
|
7
7
|
import { Field } from "./field.js";
|
|
8
8
|
import { choiceGroupClassName } from "./choice-option.js";
|
|
@@ -33,6 +33,10 @@ function CheckboxGroup({
|
|
|
33
33
|
const reactId = React.useId();
|
|
34
34
|
const [value, setValue] = useControllableArray(controlledValue, defaultValue);
|
|
35
35
|
const groupA11y = pickGroupFieldA11y(ariaProps);
|
|
36
|
+
const identity = useFieldIdentity({ id, name, "data-field": groupA11y["data-field"] });
|
|
37
|
+
const resolvedName = name ?? identity.name;
|
|
38
|
+
const resolvedField = groupA11y["data-field"] ?? identity["data-field"];
|
|
39
|
+
const optionDomId = (optionValue, index) => id ? `${id}-${optionValue}` : `${reactId}-${optionValue}-${index}`;
|
|
36
40
|
const toggle = (optionValue) => {
|
|
37
41
|
const next = value.includes(optionValue) ? value.filter((v) => v !== optionValue) : [...value, optionValue];
|
|
38
42
|
setValue(next);
|
|
@@ -45,17 +49,19 @@ function CheckboxGroup({
|
|
|
45
49
|
role: "group",
|
|
46
50
|
id,
|
|
47
51
|
...groupA11y,
|
|
52
|
+
"data-field": resolvedField,
|
|
48
53
|
"aria-disabled": disabled ? true : void 0,
|
|
49
54
|
"data-orientation": orientation,
|
|
50
55
|
className: choiceGroupClassName(orientation, className),
|
|
51
56
|
children: options.map((opt, index) => {
|
|
52
|
-
const
|
|
57
|
+
const optionId = optionDomId(opt.value, index);
|
|
53
58
|
const checked = value.includes(opt.value);
|
|
54
|
-
return /* @__PURE__ */ jsx(Field, { id:
|
|
59
|
+
return /* @__PURE__ */ jsx(Field, { id: optionId, label: opt.label, description: opt.description, children: /* @__PURE__ */ jsx(
|
|
55
60
|
Checkbox,
|
|
56
61
|
{
|
|
57
|
-
id:
|
|
58
|
-
name,
|
|
62
|
+
id: optionId,
|
|
63
|
+
name: resolvedName,
|
|
64
|
+
"data-field": resolvedField,
|
|
59
65
|
value: opt.value,
|
|
60
66
|
checked,
|
|
61
67
|
disabled: Boolean(disabled) || Boolean(opt.disabled),
|
|
@@ -74,6 +80,7 @@ function CheckboxGroup({
|
|
|
74
80
|
role: "group",
|
|
75
81
|
id,
|
|
76
82
|
...groupA11y,
|
|
83
|
+
"data-field": resolvedField,
|
|
77
84
|
"aria-disabled": disabled ? true : void 0,
|
|
78
85
|
"data-orientation": orientation,
|
|
79
86
|
className: cn(choiceGroupClassName(orientation), className),
|
|
@@ -4,28 +4,37 @@ import * as React from "react";
|
|
|
4
4
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
5
5
|
import { Check } from "lucide-react";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import { useFieldIdentity } from "../../lib/field-a11y.js";
|
|
7
8
|
import { CheckboxGroup } from "./checkbox-group.js";
|
|
8
|
-
const CheckboxRoot = React.forwardRef(({ className, ...props }, ref) =>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"data-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
9
|
+
const CheckboxRoot = React.forwardRef(({ className, ...props }, ref) => {
|
|
10
|
+
const identity = useFieldIdentity({
|
|
11
|
+
id: props.id,
|
|
12
|
+
name: props.name,
|
|
13
|
+
"data-field": props["data-field"]
|
|
14
|
+
});
|
|
15
|
+
return /* @__PURE__ */ jsx(
|
|
16
|
+
CheckboxPrimitive.Root,
|
|
17
|
+
{
|
|
18
|
+
ref,
|
|
19
|
+
"data-slot": "checkbox",
|
|
20
|
+
className: cn(
|
|
21
|
+
// `disabled:cursor-not-allowed disabled:opacity-50` and the checked fill are DELETED, not
|
|
22
|
+
// moved (#319): `.ui-checkbox:disabled, .ui-checkbox[data-disabled]` and
|
|
23
|
+
// `.ui-checkbox[data-state="checked"]` in styles/control.css already declare both, reading
|
|
24
|
+
// --disabled-opacity and --checkbox-checked-background. Utilities are layered AFTER
|
|
25
|
+
// components in Tailwind v4, so these literals were silently OUTRANKING those knobs — a
|
|
26
|
+
// service overriding --checkbox-checked-background got no fill change at all. Radix sets
|
|
27
|
+
// `data-state`/`data-disabled` on the root, so the CSS rules match. Rendering is unchanged:
|
|
28
|
+
// both knobs default to exactly the values these utilities hard-coded.
|
|
29
|
+
"peer ui-checkbox aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground shrink-0 shadow-xs transition-shadow outline-none",
|
|
30
|
+
className
|
|
31
|
+
),
|
|
32
|
+
...props,
|
|
33
|
+
...identity,
|
|
34
|
+
children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, { "data-slot": "checkbox-indicator", className: "ui-choice-indicator", children: /* @__PURE__ */ jsx(Check, { className: "ui-checkbox-icon", "aria-hidden": "true" }) })
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
});
|
|
29
38
|
CheckboxRoot.displayName = CheckboxPrimitive.Root.displayName;
|
|
30
39
|
const Checkbox = Object.assign(CheckboxRoot, {
|
|
31
40
|
Group: CheckboxGroup
|
|
@@ -31,7 +31,7 @@ export type CommandPaletteProps = {
|
|
|
31
31
|
onOpenChange?: (open: boolean) => void;
|
|
32
32
|
/**
|
|
33
33
|
* Controlled search-box query. Pairs with `onSearchChange`; leave it out for the uncontrolled
|
|
34
|
-
* palette (seeded by `defaultSearch`).
|
|
34
|
+
* palette (seeded by `defaultSearch`).
|
|
35
35
|
*/
|
|
36
36
|
search?: string;
|
|
37
37
|
/** Initial uncontrolled query, and the value the palette resets to when it closes. Default `""`. */
|
|
@@ -45,8 +45,6 @@ export type CommandPaletteProps = {
|
|
|
45
45
|
* Whether the palette filters `groups` itself (cmdk's client-side fuzzy match). Set `false` when
|
|
46
46
|
* the QUERY is answered by a server and `groups` already holds the matches — otherwise every row
|
|
47
47
|
* is scored a second time against the same string and late-arriving matches are dropped.
|
|
48
|
-
*
|
|
49
|
-
* It also decides who owns the empty node; see the component doc block. Default `true`.
|
|
50
48
|
*/
|
|
51
49
|
shouldFilter?: boolean;
|
|
52
50
|
loading?: boolean;
|
|
@@ -55,24 +53,12 @@ export type CommandPaletteProps = {
|
|
|
55
53
|
shortcut?: boolean;
|
|
56
54
|
};
|
|
57
55
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* matches none of them. Unchanged.
|
|
66
|
-
* - **`shouldFilter={false}` (server-side)** — the PALETTE owns it, derived synchronously from
|
|
67
|
-
* props: the empty node renders when `groups` carries no items, and never while `loading` or
|
|
68
|
-
* `error` is set. cmdk's own empty node cannot be trusted here, because it is driven by a
|
|
69
|
-
* scheduled count of the items that have REGISTERED in the DOM, not by what the consumer knows —
|
|
70
|
-
* so an async group that populates a frame late flips it on and off and any assertion over it
|
|
71
|
-
* races. Reading `groups` instead makes "did we render the empty state?" a pure function of the
|
|
72
|
-
* props at that render, which is what a contract test can assert.
|
|
73
|
-
*
|
|
74
|
-
* The practical consequence for search-as-you-type: hold `loading` true for the whole in-flight
|
|
75
|
-
* window. While it is true the palette shows `labels.loading` and never claims "no results" —
|
|
76
|
-
* a request that has not answered yet is not an empty result.
|
|
56
|
+
* Unchanged. - **`shouldFilter={false}` (server-side)** — the PALETTE owns it, derived
|
|
57
|
+
* synchronously from props: the empty node renders when `groups` carries no items, and never while
|
|
58
|
+
* `loading` or `error` is set. cmdk's own empty node cannot be trusted here, because it is driven
|
|
59
|
+
* by a scheduled count of the items that have REGISTERED in the DOM, not by what the consumer
|
|
60
|
+
* knows — so an async group that populates a frame late flips it on and off and any assertion over
|
|
61
|
+
* it races. Reading `groups` instead makes "did we render the empty state?" a pure function of the
|
|
62
|
+
* props at that render, which is what a contract test can assert.
|
|
77
63
|
*/
|
|
78
64
|
export declare function CommandPalette({ groups, labels, onSelect, open: controlledOpen, defaultOpen, onOpenChange, search: controlledSearch, defaultSearch, onSearchChange, shouldFilter, loading, error, trigger, shortcut, }: CommandPaletteProps): React.JSX.Element;
|
|
@@ -2,9 +2,8 @@ import * as React from "react";
|
|
|
2
2
|
import type { DatePickerProp } from "../../props/components/data-entry.prop.js";
|
|
3
3
|
export type { DatePickerProp, DatePickerProp as DatePickerProps, } from "../../props/components/data-entry.prop.js";
|
|
4
4
|
/**
|
|
5
|
-
* DatePicker — WAI-ARIA date combobox. A real, typeable `<input>` holds the value as an
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* popover is the visual affordance; typing and the calendar stay in sync.
|
|
5
|
+
* DatePicker — WAI-ARIA date combobox. A real, typeable `<input>` holds the value as an ISO-8601
|
|
6
|
+
* `yyyy-MM-dd` string (the international standard): it is form-submittable (give it a `name`),
|
|
7
|
+
* screen-reader friendly, and e2e-testable by simply filling the input.
|
|
9
8
|
*/
|
|
10
|
-
export declare function DatePicker({ value: valueProp, defaultValue, onValueChange, placeholder, disabled, className, id, name, locale: localeProp, fromDate, toDate, allowClear, ...ariaProps }: DatePickerProp): React.JSX.Element;
|
|
9
|
+
export declare function DatePicker({ value: valueProp, defaultValue, onValueChange, placeholder, disabled, className, id, name, locale: localeProp, showToday, showClose, fromDate, toDate, allowClear, ...ariaProps }: DatePickerProp): React.JSX.Element;
|
|
@@ -5,7 +5,7 @@ import { CalendarIcon, X } from "lucide-react";
|
|
|
5
5
|
import { usePickerLocales, useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { parseDateInput, toIsoDate } from "../../lib/datetime/parse.js";
|
|
7
7
|
import { useControlledLatch } from "../../lib/hooks.js";
|
|
8
|
-
import { pickFieldA11y } from "../../lib/field-a11y.js";
|
|
8
|
+
import { pickFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
|
|
9
9
|
import { cn } from "../../lib/utils.js";
|
|
10
10
|
import { Input } from "./input.js";
|
|
11
11
|
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
|
|
@@ -21,6 +21,8 @@ function DatePicker({
|
|
|
21
21
|
id,
|
|
22
22
|
name,
|
|
23
23
|
locale: localeProp,
|
|
24
|
+
showToday,
|
|
25
|
+
showClose,
|
|
24
26
|
fromDate,
|
|
25
27
|
toDate,
|
|
26
28
|
allowClear = true,
|
|
@@ -30,6 +32,9 @@ function DatePicker({
|
|
|
30
32
|
const { dayPickerLocale } = usePickerLocales(localeProp);
|
|
31
33
|
const [open, setOpen] = React.useState(false);
|
|
32
34
|
const fieldA11y = pickFieldA11y(ariaProps);
|
|
35
|
+
const identity = useFieldIdentity({ id, name, "data-field": fieldA11y["data-field"] });
|
|
36
|
+
const resolvedName = name ?? identity.name;
|
|
37
|
+
const resolvedField = fieldA11y["data-field"] ?? identity["data-field"];
|
|
33
38
|
const reactId = React.useId();
|
|
34
39
|
const dialogId = `${id ?? reactId}-dialog`;
|
|
35
40
|
const isControlled = useControlledLatch(valueProp !== void 0);
|
|
@@ -66,7 +71,8 @@ function DatePicker({
|
|
|
66
71
|
Input,
|
|
67
72
|
{
|
|
68
73
|
id,
|
|
69
|
-
name,
|
|
74
|
+
name: resolvedName,
|
|
75
|
+
"data-field": resolvedField,
|
|
70
76
|
value: text,
|
|
71
77
|
disabled,
|
|
72
78
|
placeholder: resolvedPlaceholder,
|
|
@@ -149,7 +155,10 @@ function DatePicker({
|
|
|
149
155
|
...toDate ? [{ after: toDate }] : []
|
|
150
156
|
],
|
|
151
157
|
startMonth: fromDate,
|
|
152
|
-
endMonth: toDate
|
|
158
|
+
endMonth: toDate,
|
|
159
|
+
showToday,
|
|
160
|
+
showClose,
|
|
161
|
+
onClose: () => setOpen(false)
|
|
153
162
|
}
|
|
154
163
|
)
|
|
155
164
|
}
|
|
@@ -8,4 +8,4 @@ export type { DateRangePickerProp, DateRangePickerProp as DateRangePickerProps,
|
|
|
8
8
|
* `${name}_to`, screen-reader friendly, e2e-testable by filling either input); the
|
|
9
9
|
* range calendar is the visual affordance.
|
|
10
10
|
*/
|
|
11
|
-
export declare function DateRangePicker({ value: valueProp, defaultValue, onValueChange, placeholder, disabled, className, id, name, locale: localeProp, fromDate, toDate, allowClear, ...ariaProps }: DateRangePickerProp): React.JSX.Element;
|
|
11
|
+
export declare function DateRangePicker({ value: valueProp, defaultValue, onValueChange, placeholder, disabled, className, id, name, locale: localeProp, showToday, showClose, fromDate, toDate, allowClear, ...ariaProps }: DateRangePickerProp): React.JSX.Element;
|
|
@@ -5,7 +5,7 @@ import { ArrowRight, CalendarIcon, X } from "lucide-react";
|
|
|
5
5
|
import { usePickerLocales, useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { parseDateInput, toIsoDate } from "../../lib/datetime/index.js";
|
|
7
7
|
import { useControlledLatch } from "../../lib/hooks.js";
|
|
8
|
-
import { pickGroupFieldA11y } from "../../lib/field-a11y.js";
|
|
8
|
+
import { pickGroupFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
|
|
9
9
|
import { cn } from "../../lib/utils.js";
|
|
10
10
|
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
|
|
11
11
|
import { Calendar } from "./calendar.js";
|
|
@@ -20,6 +20,8 @@ function DateRangePicker({
|
|
|
20
20
|
id,
|
|
21
21
|
name,
|
|
22
22
|
locale: localeProp,
|
|
23
|
+
showToday,
|
|
24
|
+
showClose,
|
|
23
25
|
fromDate,
|
|
24
26
|
toDate,
|
|
25
27
|
allowClear = true,
|
|
@@ -33,6 +35,9 @@ function DateRangePicker({
|
|
|
33
35
|
const groupId = id ?? autoId;
|
|
34
36
|
const fromId = `${groupId}-from`;
|
|
35
37
|
const toId = `${groupId}-to`;
|
|
38
|
+
const identity = useFieldIdentity({ id: groupId, name, "data-field": groupA11y["data-field"] });
|
|
39
|
+
const rangeField = groupA11y["data-field"] ?? identity["data-field"];
|
|
40
|
+
const rangeName = name ?? identity.name;
|
|
36
41
|
const isControlled = useControlledLatch(valueProp !== void 0);
|
|
37
42
|
const [internalValue, setInternalValue] = React.useState(defaultValue);
|
|
38
43
|
const value = isControlled ? valueProp : internalValue;
|
|
@@ -77,13 +82,14 @@ function DateRangePicker({
|
|
|
77
82
|
role: "group",
|
|
78
83
|
id: groupId,
|
|
79
84
|
...groupA11y,
|
|
85
|
+
"data-field": rangeField,
|
|
80
86
|
"aria-disabled": disabled ? true : void 0,
|
|
87
|
+
"data-state": open ? "open" : "closed",
|
|
81
88
|
className: cn(
|
|
82
89
|
// One input-styled shell for the whole range — the shared composite-field box, so
|
|
83
90
|
// this and the month range picker cannot drift into two slightly different fields.
|
|
84
91
|
"ui-control ui-control-composite-field",
|
|
85
|
-
"
|
|
86
|
-
open && "border-ring ring-ring/50 ring-[3px]",
|
|
92
|
+
"aria-invalid:border-destructive",
|
|
87
93
|
className
|
|
88
94
|
),
|
|
89
95
|
onClick: () => {
|
|
@@ -94,7 +100,8 @@ function DateRangePicker({
|
|
|
94
100
|
"input",
|
|
95
101
|
{
|
|
96
102
|
id: fromId,
|
|
97
|
-
|
|
103
|
+
"data-field": rangeField ? `${rangeField}_from` : void 0,
|
|
104
|
+
name: rangeName ? `${rangeName}_from` : void 0,
|
|
98
105
|
value: fromText,
|
|
99
106
|
disabled,
|
|
100
107
|
placeholder: resolvedPlaceholder,
|
|
@@ -118,7 +125,8 @@ function DateRangePicker({
|
|
|
118
125
|
"input",
|
|
119
126
|
{
|
|
120
127
|
id: toId,
|
|
121
|
-
|
|
128
|
+
"data-field": rangeField ? `${rangeField}_to` : void 0,
|
|
129
|
+
name: rangeName ? `${rangeName}_to` : void 0,
|
|
122
130
|
value: toText,
|
|
123
131
|
disabled,
|
|
124
132
|
placeholder: resolvedPlaceholder,
|
|
@@ -186,7 +194,10 @@ function DateRangePicker({
|
|
|
186
194
|
...toDate ? [{ after: toDate }] : []
|
|
187
195
|
],
|
|
188
196
|
startMonth: fromDate,
|
|
189
|
-
endMonth: toDate
|
|
197
|
+
endMonth: toDate,
|
|
198
|
+
showToday,
|
|
199
|
+
showClose,
|
|
200
|
+
onClose: () => setOpen(false)
|
|
190
201
|
}
|
|
191
202
|
)
|
|
192
203
|
}
|
|
@@ -3,10 +3,9 @@ import type { FormErrorsProp, FormErrorsProviderProp } from "../../props/compone
|
|
|
3
3
|
import type { ErrorBagProp } from "../../props/vocabulary/index.js";
|
|
4
4
|
export type { FormErrorsProp, FormErrorsProp as FormErrorsProps, FormErrorsProviderProp, FormErrorsProviderProp as FormErrorsProviderProps, } from "../../props/components/data-entry.prop.js";
|
|
5
5
|
/**
|
|
6
|
-
* Registry shared by a `Form` with its FormFields and `<FormErrors />`. Each mounted
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* duplicate names and unmount order stay correct.
|
|
6
|
+
* Registry shared by a `Form` with its FormFields and `<FormErrors />`. Each mounted `FormField
|
|
7
|
+
* name="…"` CLAIMS its error-bag key (it is the visible owner of that message); `<FormErrors />`
|
|
8
|
+
* renders only the unclaimed remainder.
|
|
10
9
|
*/
|
|
11
10
|
interface FormErrorsRegistryValue {
|
|
12
11
|
errors: ErrorBagProp;
|
|
@@ -19,18 +18,9 @@ export declare function useFormErrorsRegistry(): FormErrorsRegistryValue | null;
|
|
|
19
18
|
/** First message of a bag entry — Laravel arrays surface their first message on the field. */
|
|
20
19
|
export declare function firstBagMessage(entry: string | string[] | undefined): string | undefined;
|
|
21
20
|
/**
|
|
22
|
-
* FormErrorsProvider — one shared error registry (error bag + claim set) over a region.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* 1. `Form errors={…}` renders this provider itself (both `<form>` and `asChild` modes) —
|
|
26
|
-
* the single-form case needs nothing else.
|
|
27
|
-
* 2. An edit screen split into several sibling Card+Form sections (the standard exseli shape)
|
|
28
|
-
* wraps the REGION in `<FormErrorsProvider errors={…}>` instead: Forms **without** their own
|
|
29
|
-
* `errors` join the surrounding registry, every `FormField name="…"` inside claims into it,
|
|
30
|
-
* and one `<FormErrors />` anywhere in the region renders the unclaimed remainder.
|
|
31
|
-
*
|
|
32
|
-
* A nested Form WITH its own `errors` starts a new registry that shadows this one — its claims
|
|
33
|
-
* and messages stay inside it.
|
|
21
|
+
* FormErrorsProvider — one shared error registry (error bag + claim set) over a region. 兄弟 Form 群で
|
|
22
|
+
* 1 つのエラーバッグを共有するための公開プロバイダ。Two ways to get one: 1. `Form errors={…}` renders this provider itself
|
|
23
|
+
* (both `<form>` and `asChild` modes) — the single-form case needs nothing else. 2.
|
|
34
24
|
*/
|
|
35
25
|
export declare function FormErrorsProvider({ errors, children }: FormErrorsProviderProp): React.JSX.Element;
|
|
36
26
|
/** FormField calls this to claim its error-bag key while mounted (no-op outside a Form). */
|
|
@@ -39,7 +29,6 @@ export declare function useClaimErrorKey(name: string | undefined): void;
|
|
|
39
29
|
* FormErrors — renders the error-bag entries no mounted `FormField name="…"` displays: server
|
|
40
30
|
* validation errors attached to hidden/derived fields (an `action_mode`, a `page`, a source-record
|
|
41
31
|
* id) that would otherwise fail silently. Place it inside a `Form errors={…}` — typically above
|
|
42
|
-
* the fields; it renders nothing while every entry is claimed or the bag is empty.
|
|
43
|
-
* `Alert tone="destructive"` (role="alert"), so appearing messages are announced assertively.
|
|
32
|
+
* the fields; it renders nothing while every entry is claimed or the bag is empty.
|
|
44
33
|
*/
|
|
45
34
|
export declare function FormErrors({ errors: errorsProp, title, className }: FormErrorsProp): React.JSX.Element | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { FormFieldProp } from "../../props/components/data-entry.prop.js";
|
|
3
3
|
export type { FormFieldProp, FormFieldProp as FormFieldProps, } from "../../props/components/data-entry.prop.js";
|
|
4
|
-
export declare function FormField({ id, name, label, required, helper, error: errorProp, labelAddon, layout: layoutProp, labelWidth: labelWidthProp, controlWidth: controlWidthProp, colSpan, className, children, staticText, }: FormFieldProp): React.JSX.Element;
|
|
4
|
+
export declare function FormField({ id, name, field, label, required, helper, error: errorProp, labelAddon, layout: layoutProp, labelWidth: labelWidthProp, controlWidth: controlWidthProp, colSpan, className, children, staticText, }: FormFieldProp): React.JSX.Element;
|
|
@@ -3,7 +3,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Label } from "../data-entry/label.js";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
-
import { FieldNameContext, mergeAriaIds } from "../../lib/field-a11y.js";
|
|
6
|
+
import { FieldIdentityContext, FieldNameContext, mergeAriaIds } from "../../lib/field-a11y.js";
|
|
7
|
+
import { useOptionalAppContext } from "../../app/app-provider.js";
|
|
7
8
|
import { useFormLayout } from "./form.js";
|
|
8
9
|
import { firstBagMessage, useClaimErrorKey, useFormErrorsRegistry } from "./form-errors.js";
|
|
9
10
|
const toCssLength = (v) => typeof v === "number" ? `${v}px` : v;
|
|
@@ -11,6 +12,7 @@ const FOCUSABLE_SELECTOR = 'input:not([type="hidden"]), select, textarea, button
|
|
|
11
12
|
function FormField({
|
|
12
13
|
id,
|
|
13
14
|
name,
|
|
15
|
+
field,
|
|
14
16
|
label,
|
|
15
17
|
required,
|
|
16
18
|
helper,
|
|
@@ -38,6 +40,8 @@ function FormField({
|
|
|
38
40
|
const labelId = `${resolvedId}-label`;
|
|
39
41
|
const helperId = helper ? `${resolvedId}-helper` : void 0;
|
|
40
42
|
const errorId = error ? `${resolvedId}-error` : void 0;
|
|
43
|
+
const fieldKey = field ?? name ?? id;
|
|
44
|
+
const emitFieldNames = useOptionalAppContext()?.emitFieldNames ?? false;
|
|
41
45
|
const isStatic = staticText !== void 0;
|
|
42
46
|
if (!isStatic && typeof process !== "undefined" && process.env?.NODE_ENV !== "production" && !React.isValidElement(children)) {
|
|
43
47
|
console.warn(
|
|
@@ -48,21 +52,26 @@ function FormField({
|
|
|
48
52
|
() => ({ labelId, label: typeof label === "string" ? label : void 0 }),
|
|
49
53
|
[labelId, label]
|
|
50
54
|
);
|
|
55
|
+
const fieldIdentityContext = React.useMemo(
|
|
56
|
+
() => fieldKey === void 0 ? null : { emitName: emitFieldNames },
|
|
57
|
+
[fieldKey, emitFieldNames]
|
|
58
|
+
);
|
|
51
59
|
const childProps = React.isValidElement(children) ? children.props : void 0;
|
|
52
60
|
const mergeIds = mergeAriaIds;
|
|
53
61
|
const childWithA11y = isStatic ? (
|
|
54
|
-
// Byte-for-byte the same value typography as `Descriptions.Item`'s `dd` (gh#294), so a
|
|
55
62
|
// read-only FormField row and a Descriptions value are indistinguishable when mixed. That
|
|
56
|
-
// used to be two copies of the literal `text-sm` kept in sync by this comment; both call sites
|
|
57
|
-
// now read the SAME token pair (#319), so a service retunes both from one place and they
|
|
58
63
|
// cannot drift. --descriptions-value-line-height is the mandatory companion: `text-sm` also
|
|
59
|
-
// set Tailwind's `--text-sm--line-height`, which the theme never remaps (the gh#260 bug).
|
|
60
64
|
/* @__PURE__ */ jsx("span", { className: "text-[length:var(--descriptions-value-font-size)] leading-[var(--descriptions-value-line-height)] break-all", children: staticText })
|
|
61
65
|
) : React.isValidElement(children) ? React.cloneElement(children, {
|
|
62
66
|
// The label is associated via aria-labelledby (not <label for>): composite
|
|
63
67
|
// controls (Radio.Group, checkbox lists, range pairs) have no labelable root,
|
|
64
68
|
// and a dangling `for` triggers Chrome's "Incorrect use of <label>" issue.
|
|
65
69
|
id: childProps?.id ?? resolvedId,
|
|
70
|
+
// Read the child's own value first in BOTH cases: cloneElement
|
|
71
|
+
// overwrites every key present in the config bag, `undefined` included, so a bare
|
|
72
|
+
// `"data-field": fieldKey` would erase a value the control set for itself.
|
|
73
|
+
"data-field": childProps?.["data-field"] ?? fieldKey,
|
|
74
|
+
...emitFieldNames ? { name: childProps?.name ?? fieldKey } : void 0,
|
|
66
75
|
"aria-labelledby": childProps?.["aria-labelledby"] ?? labelId,
|
|
67
76
|
// Redundant `aria-label` fallback (belt-and-suspenders): the accessible name is the
|
|
68
77
|
// SAME string as the visible label, just reachable even if an aria-labelledby lookup
|
|
@@ -125,7 +134,7 @@ function FormField({
|
|
|
125
134
|
labelAddon
|
|
126
135
|
] }),
|
|
127
136
|
/* @__PURE__ */ jsxs("div", { "data-slot": "form-field-control", className: "ui-form-field-control", children: [
|
|
128
|
-
isStatic ? childWithA11y : /* @__PURE__ */ jsx(FieldNameContext.Provider, { value: fieldNameContext, children: childWithA11y }),
|
|
137
|
+
isStatic ? childWithA11y : /* @__PURE__ */ jsx(FieldNameContext.Provider, { value: fieldNameContext, children: /* @__PURE__ */ jsx(FieldIdentityContext.Provider, { value: fieldIdentityContext, children: childWithA11y }) }),
|
|
129
138
|
helper ? /* @__PURE__ */ jsx("p", { id: helperId, className: "text-muted-foreground text-xs", children: helper }) : null,
|
|
130
139
|
error ? /* @__PURE__ */ jsx("p", { id: errorId, role: "alert", className: "text-destructive text-xs", children: error }) : null
|
|
131
140
|
] })
|
|
@@ -14,15 +14,7 @@ export declare function useFormLayout(): FormLayoutContextValue | null;
|
|
|
14
14
|
/**
|
|
15
15
|
* Form — Ant-style layout container. Renders a `<form>` and provides layout (vertical/horizontal),
|
|
16
16
|
* label/control width, label alignment, and a responsive collapse breakpoint to every FormField
|
|
17
|
-
* inside it.
|
|
18
|
-
* responsive multi-column grid via `columns` (reuses ResponsiveGrid — mobile-first, 1 col on small).
|
|
19
|
-
*
|
|
20
|
-
* `asChild` renders the caller's own element instead of a `<form>`, keeping only the layout
|
|
21
|
-
* context. Routing libraries own the form element — Inertia's `<Form action method>` and
|
|
22
|
-
* TanStack Form both render their own — so without this every such consumer has to choose
|
|
23
|
-
* between the router's submission handling and the design system's field layout, and ends up
|
|
24
|
-
* hand-rolling label columns per field. Two `<form>` elements cannot nest, so wrapping is not
|
|
25
|
-
* an option: `<Form asChild layout="horizontal" labelWidth={174}><InertiaForm …/></Form>`.
|
|
17
|
+
* inside it.
|
|
26
18
|
*/
|
|
27
19
|
export declare const Form: React.ForwardRefExoticComponent<React.FormHTMLAttributes<HTMLFormElement> & {
|
|
28
20
|
layout?: FormLayoutProp;
|
|
@@ -1,37 +1,39 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
export type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
2
|
+
export type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
3
|
+
/** Control height tier: `md` (default) or `sm`, the same tiers as SelectTrigger and NumberInput. */
|
|
4
|
+
size?: "sm" | "md";
|
|
3
5
|
/** Show an inline ✕ that clears the field while it holds text (default false). */
|
|
4
6
|
allowClear?: boolean;
|
|
5
7
|
/** Called after the field is cleared via the inline ✕. */
|
|
6
8
|
onClear?: () => void;
|
|
7
9
|
/**
|
|
8
|
-
* A leading affordance pinned inside the start of the field — e.g. a mail or
|
|
9
|
-
*
|
|
10
|
-
* input keeps the keyboard focus. Pairs with `trailingIcon`/`allowClear`.
|
|
10
|
+
* A leading affordance pinned inside the start of the field — e.g. a mail or search icon (the
|
|
11
|
+
* common auth/search pattern). Decorative by default; the input keeps the keyboard focus.
|
|
11
12
|
*/
|
|
12
13
|
leadingIcon?: React.ReactNode;
|
|
13
14
|
/**
|
|
14
|
-
* A trailing affordance pinned inside the field — e.g. a calendar / clock popover
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* A trailing affordance pinned inside the field — e.g. a calendar / clock popover trigger
|
|
16
|
+
* button. ONE trailing icon shows at a time: when `allowClear` and the field holds a value the
|
|
17
|
+
* clear ✕ REPLACES this icon; otherwise this icon shows.
|
|
17
18
|
*/
|
|
18
19
|
trailingIcon?: React.ReactNode;
|
|
19
20
|
};
|
|
20
|
-
export declare const Input: React.ForwardRefExoticComponent<React.InputHTMLAttributes<HTMLInputElement> & {
|
|
21
|
+
export declare const Input: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
22
|
+
/** Control height tier: `md` (default) or `sm`, the same tiers as SelectTrigger and NumberInput. */
|
|
23
|
+
size?: "sm" | "md";
|
|
21
24
|
/** Show an inline ✕ that clears the field while it holds text (default false). */
|
|
22
25
|
allowClear?: boolean;
|
|
23
26
|
/** Called after the field is cleared via the inline ✕. */
|
|
24
27
|
onClear?: () => void;
|
|
25
28
|
/**
|
|
26
|
-
* A leading affordance pinned inside the start of the field — e.g. a mail or
|
|
27
|
-
*
|
|
28
|
-
* input keeps the keyboard focus. Pairs with `trailingIcon`/`allowClear`.
|
|
29
|
+
* A leading affordance pinned inside the start of the field — e.g. a mail or search icon (the
|
|
30
|
+
* common auth/search pattern). Decorative by default; the input keeps the keyboard focus.
|
|
29
31
|
*/
|
|
30
32
|
leadingIcon?: React.ReactNode;
|
|
31
33
|
/**
|
|
32
|
-
* A trailing affordance pinned inside the field — e.g. a calendar / clock popover
|
|
33
|
-
*
|
|
34
|
-
*
|
|
34
|
+
* A trailing affordance pinned inside the field — e.g. a calendar / clock popover trigger
|
|
35
|
+
* button. ONE trailing icon shows at a time: when `allowClear` and the field holds a value the
|
|
36
|
+
* clear ✕ REPLACES this icon; otherwise this icon shows.
|
|
35
37
|
*/
|
|
36
38
|
trailingIcon?: React.ReactNode;
|
|
37
39
|
} & React.RefAttributes<HTMLInputElement>>;
|