@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
|
@@ -2,23 +2,7 @@ import type { MasterDetailProp } from "../../props/components/layout.prop.js";
|
|
|
2
2
|
export type MasterDetailProps = MasterDetailProp;
|
|
3
3
|
/**
|
|
4
4
|
* Token-owned master-detail composition: a selectable collection beside the detail surface it
|
|
5
|
-
* drives.
|
|
6
|
-
*
|
|
7
|
-
* are all tokens, so a consumer never authors grid tracks or per-screen spacing (gh#223).
|
|
8
|
-
*
|
|
9
|
-
* `rail` chooses which region keeps the fixed track: `detail` (default) is the canonical fluid
|
|
10
|
-
* list + fixed detail rail; `master` is the leading navigator rail. Either way `master` comes
|
|
11
|
-
* first in DOM order, so below the threshold the regions stack list-then-detail.
|
|
12
|
-
*
|
|
13
|
-
* `masterViewport` bounds the collection (gh#231): `auto` (default) lets it grow with its content
|
|
14
|
-
* exactly as before, while `compact`/`standard` cap its block size with a token and scroll it
|
|
15
|
-
* INSIDE the region — the only thing that stops a long real collection from pushing the detail
|
|
16
|
-
* thousands of pixels below the fold once the layout stacks.
|
|
17
|
-
*
|
|
18
|
-
* SELECTION AND KEYBOARD STAY WITH THE CALLER — deliberately. The controls inside `master` may be
|
|
19
|
-
* a listbox, a tablist, a link list or toggle buttons, and only the caller knows which APG pattern
|
|
20
|
-
* applies; a layout that imposed one would fight it. What the layout DOES own is the wiring those
|
|
21
|
-
* patterns need: two named landmark regions, a stable `detailId` for `aria-controls`, and a
|
|
22
|
-
* `tabIndex={-1}` detail region so the app can move focus to the new detail after a selection.
|
|
5
|
+
* drives. Either way `master` comes first in DOM order, so below the threshold the regions stack
|
|
6
|
+
* list-then-detail.
|
|
23
7
|
*/
|
|
24
8
|
export declare function MasterDetail({ master, children, rail, railWidth, masterViewport, collapseBelow, masterLabel, detailLabel, detailId, }: MasterDetailProps): import("react").JSX.Element;
|
|
@@ -95,7 +95,6 @@ function PageContainerRoot({
|
|
|
95
95
|
children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", children: breadcrumb.map((item, i) => {
|
|
96
96
|
const isLast = i === breadcrumb.length - 1;
|
|
97
97
|
return (
|
|
98
|
-
// The package's own breadcrumb item hook (gh#319): same
|
|
99
98
|
// `--space-inline-xs` gap the previous `.ui-inline-xs` gave, and it brings
|
|
100
99
|
// `.ui-breadcrumb-item svg { 0.75rem }` with it, so the separator glyph no
|
|
101
100
|
// longer carries a `size-3` literal. It also drops `.ui-inline-xs`'s
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import type { ResponsiveGridColumnsProp, ResponsiveGridPresetProp } from "../../props/components/layout.prop.js";
|
|
3
|
+
import type { GapProp } from "../../props/vocabulary/layout.prop.js";
|
|
3
4
|
export type ResponsiveGridProps = {
|
|
5
|
+
/** Gap between cells, the same steps as Flex. Default `md`. */
|
|
6
|
+
gap?: GapProp;
|
|
7
|
+
/** Optional structural class override. */
|
|
8
|
+
className?: string;
|
|
4
9
|
columns?: ResponsiveGridColumnsProp;
|
|
5
10
|
/**
|
|
6
11
|
* Named column geometry for a recognised collection shape — see `ResponsiveGridPresetProp`.
|
|
@@ -10,4 +15,4 @@ export type ResponsiveGridProps = {
|
|
|
10
15
|
preset?: ResponsiveGridPresetProp;
|
|
11
16
|
children: ReactNode;
|
|
12
17
|
};
|
|
13
|
-
export declare function ResponsiveGrid({ columns, preset, children }: ResponsiveGridProps): import("react").JSX.Element;
|
|
18
|
+
export declare function ResponsiveGrid({ columns, gap, preset, className, children, }: ResponsiveGridProps): import("react").JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/utils.js";
|
|
2
3
|
const RESPONSIVE_GRID_PRESET_COLUMNS = {
|
|
3
4
|
"pricing-plans": { sm: 3, md: 3, lg: 3 }
|
|
4
5
|
};
|
|
@@ -23,9 +24,15 @@ function toStyle(resolved) {
|
|
|
23
24
|
"--responsive-grid-lg": resolved.lg
|
|
24
25
|
};
|
|
25
26
|
}
|
|
26
|
-
function ResponsiveGrid({
|
|
27
|
+
function ResponsiveGrid({
|
|
28
|
+
columns = 4,
|
|
29
|
+
gap,
|
|
30
|
+
preset,
|
|
31
|
+
className,
|
|
32
|
+
children
|
|
33
|
+
}) {
|
|
27
34
|
const resolved = preset ? RESPONSIVE_GRID_PRESET_COLUMNS[preset] : resolveColumns(columns);
|
|
28
|
-
return /* @__PURE__ */ jsx("div", { className: "ui-responsive-grid-scope", children: /* @__PURE__ */ jsx("div", { className: "ui-responsive-grid", style: toStyle(resolved), children }) });
|
|
35
|
+
return /* @__PURE__ */ jsx("div", { className: "ui-responsive-grid-scope", children: /* @__PURE__ */ jsx("div", { className: cn("ui-responsive-grid", className), "data-gap": gap, style: toStyle(resolved), children }) });
|
|
29
36
|
}
|
|
30
37
|
export {
|
|
31
38
|
ResponsiveGrid
|
|
@@ -2,24 +2,12 @@ import * as React from "react";
|
|
|
2
2
|
import type { ServiceRolePanelProp } from "../../props/components/layout.prop.js";
|
|
3
3
|
export type { ServiceRoleItemProp, ServiceRolePanelProp, ServiceRolePanelProp as ServiceRolePanelProps, } from "../../props/components/layout.prop.js";
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* - **Selection** as the controlled triad (`value`/`defaultValue`/`onValueChange`, defaulting to
|
|
14
|
-
* the first role). Each role row is a real `Button` carrying `aria-current`, and selecting moves
|
|
15
|
-
* focus-target wiring through `MasterDetail`'s `detailId`/`tabIndex={-1}` detail region.
|
|
16
|
-
* - **Destructive confirmation built in**: `onDeleteRole`'s presence arms a per-role delete
|
|
17
|
-
* affordance behind the package `AlertDialog` (variant `destructive`); the handler fires only
|
|
18
|
-
* after the user confirms. Roles marked `locked` (system roles) never offer deletion and show a
|
|
19
|
-
* localized lock badge; `readOnly` hides every mutating affordance.
|
|
20
|
-
* - **Lifecycle states** mirror the DataTable #216 vocabulary and precedence:
|
|
21
|
-
* `loading` → `denied` → `error` → `empty` → content.
|
|
22
|
-
* - **Domain-neutral**: the roles and the detail surface (`children`, node or render-function) are
|
|
23
|
-
* consumer-supplied; no platform role or permission is encoded.
|
|
5
|
+
* What the panel adds is exactly the contract every service-role screen kept re-deriving: -
|
|
6
|
+
* **Selection** as the controlled triad (`value`/`defaultValue`/`onValueChange`, defaulting to the
|
|
7
|
+
* first role). Each role row is a real `Button` carrying `aria-current`, and selecting moves
|
|
8
|
+
* focus-target wiring through `MasterDetail`'s `detailId`/`tabIndex={-1}` detail region. -
|
|
9
|
+
* **Destructive confirmation built in**: `onDeleteRole`'s presence arms a per-role delete
|
|
10
|
+
* affordance behind the package `AlertDialog` (variant `destructive`); the handler fires only
|
|
11
|
+
* after the user confirms.
|
|
24
12
|
*/
|
|
25
13
|
export declare const ServiceRolePanel: React.ForwardRefExoticComponent<ServiceRolePanelProp & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -14,14 +14,12 @@ type SidebarItemProps = {
|
|
|
14
14
|
sub?: boolean;
|
|
15
15
|
onActivate?: (id: string) => void;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* The row content stays library-composed — see {@link SidebarLinkProp}. Applied only when
|
|
18
|
+
* `item.href` is set.
|
|
19
19
|
*/
|
|
20
20
|
linkComponent?: SidebarLinkComponentProp;
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
* library injects its composed icon + label + badge as that element's children (gh#213). Use it
|
|
24
|
-
* when you compose `SidebarItem` by hand instead of passing `sections` + `linkComponent`.
|
|
22
|
+
* Use it when you compose `SidebarItem` by hand instead of passing `sections` + `linkComponent`.
|
|
25
23
|
*/
|
|
26
24
|
asChild?: boolean;
|
|
27
25
|
/** @deprecated Use `linkComponent` / `asChild` — see {@link SidebarProp.renderItem}. */
|
|
@@ -32,27 +30,7 @@ export declare function SidebarSection({ label, collapsed, children, className,
|
|
|
32
30
|
export declare function SidebarItem({ item, active, sub, onActivate, linkComponent: LinkComponent, asChild, renderItem, children, ...props }: SidebarItemProps & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onClick">): React.JSX.Element;
|
|
33
31
|
export { createSidebarLink } from "./sidebar-link.js";
|
|
34
32
|
/**
|
|
35
|
-
* Sidebar — data-driven vertical nav rail.
|
|
36
|
-
*
|
|
37
|
-
* ROUTER LINKS (gh#213): pass `linkComponent` and the LIBRARY keeps composing every row (icon slot,
|
|
38
|
-
* label, badge, active state, the icon-only collapsed rail and its tooltip name) — the consumer
|
|
39
|
-
* supplies only the link ELEMENT. Use {@link createSidebarLink} to adapt a router `Link`, or
|
|
40
|
-
* `SidebarItem asChild` when composing rows by hand. `renderItem` is DEPRECATED: it left row content
|
|
41
|
-
* to the consumer, so a `<Link>{item.label}</Link>` dropped every icon and badge.
|
|
42
|
-
*
|
|
43
|
-
* THEMING (gh#228): the row/label and the nav ICON read SEPARATE component tokens, so a service can
|
|
44
|
-
* match a canonical shell's darker 16px icons without page-local CSS and without re-tinting every
|
|
45
|
-
* muted text globally:
|
|
46
|
-
*
|
|
47
|
-
* - `--sidebar-nav-item-foreground` (row + label, incl. sub rows) · default `hsl(var(--muted-foreground))`
|
|
48
|
-
* - `--sidebar-nav-item-hover-foreground` · default `hsl(var(--foreground))`
|
|
49
|
-
* - `--sidebar-nav-item-disabled-foreground` · default = the resting row colour
|
|
50
|
-
* - `--sidebar-nav-icon-foreground` (`.sb-icon`, incl. the collapsed rail + group triggers) ·
|
|
51
|
-
* default `currentColor` = the row colour
|
|
52
|
-
* - `--sidebar-nav-icon-{hover,active,disabled}-foreground` · each defaults to the base icon knob
|
|
53
|
-
*
|
|
54
|
-
* The active row keeps `--sidebar-item-active-background` / `--sidebar-item-active-foreground`.
|
|
55
|
-
* These are COLOUR knobs only — icon size stays `--sidebar-nav-icon-size` (16px) and row geometry
|
|
56
|
-
* stays `--sidebar-nav-item-height` / `-gap` / `-padding-x`.
|
|
33
|
+
* Sidebar — data-driven vertical nav rail. Use {@link createSidebarLink} to adapt a router `Link`,
|
|
34
|
+
* or `SidebarItem asChild` when composing rows by hand.
|
|
57
35
|
*/
|
|
58
36
|
export declare function Sidebar({ ariaLabel: ariaLabelCamel, activeId, onSelect, sections, product, onProductClick, brand, collapsed, children, linkComponent, renderItem, footer, "aria-label": ariaLabel, }: SidebarProp): React.JSX.Element;
|
|
@@ -37,7 +37,6 @@ function SidebarRowContent({
|
|
|
37
37
|
!sub ? /* @__PURE__ */ jsx(SidebarIcon, { icon: item.icon }) : null,
|
|
38
38
|
/* @__PURE__ */ jsx("span", { className: "sb-label", children: item.label }),
|
|
39
39
|
showBadge ? (
|
|
40
|
-
// `data-tone` is emitted ONLY for the emphasis tone (rule #44: present-when-on,
|
|
41
40
|
// absent-when-off), so a rail that never sets `badgeTone` renders the exact same node it
|
|
42
41
|
// always did and no consumer selector has to out-specify a marker meaning "unchanged".
|
|
43
42
|
/* @__PURE__ */ jsx(
|
|
@@ -4,13 +4,6 @@ export type SplitPaneProps = {
|
|
|
4
4
|
/**
|
|
5
5
|
* Aside (trailing) panel content. Pass `null` to CLOSE the rail: no `<aside>` element is
|
|
6
6
|
* rendered, the grid drops to one full-width column and the gap goes with it.
|
|
7
|
-
*
|
|
8
|
-
* Closing this way — rather than dropping the whole `SplitPane` at the call site — is what
|
|
9
|
-
* keeps `children` MOUNTED. The three wrappers below are rendered unconditionally, so the
|
|
10
|
-
* main column sits at the same depth and the same slot in the React tree in both states and
|
|
11
|
-
* React reuses its DOM node instead of remounting it. A collapsible thread/detail panel that
|
|
12
|
-
* swapped `<SplitPane>{page}</SplitPane>` for a bare `{page}` changed the tree depth, which
|
|
13
|
-
* remounted the page and threw the reader to the bottom of a scrolled list.
|
|
14
7
|
*/
|
|
15
8
|
aside: ReactNode | null;
|
|
16
9
|
/**
|
|
@@ -2,19 +2,6 @@ import type { TopbarProp } from "../../props/components/layout.prop.js";
|
|
|
2
2
|
export type { TopbarProp, TopbarProp as TopbarProps } from "../../props/components/layout.prop.js";
|
|
3
3
|
/**
|
|
4
4
|
* Topbar — a PURE SLOT bar. It positions three clusters (`start` / `center` / `end`) and owns the
|
|
5
|
-
* bar's flex layout; it does NOT bake any chrome.
|
|
6
|
-
* box, notification bell, or language picker — the CONSUMER composes those from real primitives
|
|
7
|
-
* (a brand mark `Avatar`, a `Button` search trigger, `AppSettingPicker` for locale/theme, a
|
|
8
|
-
* `DropdownMenu` user menu) and drops them into a slot. Whether a control is icon-only, labelled,
|
|
9
|
-
* bordered, etc. is that control's OWN configuration — never the shell's to dictate.
|
|
10
|
-
*
|
|
11
|
-
* <Topbar
|
|
12
|
-
* start={<><SidebarToggle /><Avatar className="rounded-md"><AvatarFallback>C</AvatarFallback></Avatar></>}
|
|
13
|
-
* center={<Button variant="outline" onClick={openSearch}><Search />検索</Button>}
|
|
14
|
-
* end={<><AppSettingPicker kind="locale" /><UserMenu /></>}
|
|
15
|
-
* />
|
|
16
|
-
*
|
|
17
|
-
* Use it as `AppShell`'s `topbar` slot, or place it directly. For full custom content, pass
|
|
18
|
-
* `children` instead of the three slots.
|
|
5
|
+
* bar's flex layout; it does NOT bake any chrome.
|
|
19
6
|
*/
|
|
20
7
|
export declare function Topbar({ start, center, end, className, children, ...props }: TopbarProp): import("react").JSX.Element;
|
|
@@ -142,9 +142,7 @@ const AppSettingPicker = React.forwardRef(
|
|
|
142
142
|
"ui-app-setting-picker-icon hover:bg-accent hover:text-accent-foreground"
|
|
143
143
|
) : (
|
|
144
144
|
// Labeled: sized to a per-kind width from `sm` up; below `sm` it hugs its content and
|
|
145
|
-
//
|
|
146
|
-
// `w-full` — so a labeled picker dropped into a narrow topbar no longer stretches to
|
|
147
|
-
// fill the bar (gh#165). A form field that wants a full-width control passes
|
|
145
|
+
// A form field that wants a full-width control passes
|
|
148
146
|
// `className="w-full"`, which wins over `w-auto`.
|
|
149
147
|
// `compact` drops the per-kind width entirely so the trigger hugs its value.
|
|
150
148
|
cn("w-auto max-w-full", !isCompact && "ui-app-setting-picker-trigger")
|
|
@@ -2,12 +2,7 @@ import type { ToolbarGroupProp, ToolbarProp } from "../../props/components/navig
|
|
|
2
2
|
export type { FilterBarChipProp, FilterBarChipProp as FilterBarChipProps, FilterBarFilterProp, FilterBarFilterProp as FilterBarFilterProps, FilterBarOverflowProp, FilterBarSearchProp, FilterBarSearchProp as FilterBarSearchProps, ToolbarGroupProp, ToolbarGroupProp as ToolbarGroupProps, ToolbarGroupProp as FilterBarGroupProp, ToolbarGroupProp as FilterBarGroupProps, ToolbarProp, ToolbarProp as ToolbarProps, ToolbarProp as FilterBarProp, ToolbarProp as FilterBarProps, } from "../../props/components/navigation.prop.js";
|
|
3
3
|
export declare function Toolbar({ onClear, hasActiveFilters, sticky, overflow, search, filters, chips, onChipRemove, actions, resultCount, loading, disabled, error, className, children, }: ToolbarProp): import("react").JSX.Element;
|
|
4
4
|
export declare function ToolbarGroup({ label, controlId, className, children }: ToolbarGroupProp): import("react").JSX.Element;
|
|
5
|
-
/**
|
|
6
|
-
* Canonical list-page filter strip.
|
|
7
|
-
*
|
|
8
|
-
* `Toolbar` remains available for backwards compatibility. `FilterBar` is the
|
|
9
|
-
* public domain-neutral name used by application design specifications.
|
|
10
|
-
*/
|
|
5
|
+
/** Canonical list-page filter strip. `Toolbar` remains available for backwards compatibility. */
|
|
11
6
|
export declare const FilterBar: typeof Toolbar;
|
|
12
7
|
/** Labelled control group for {@link FilterBar}. */
|
|
13
8
|
export declare const FilterBarGroup: typeof ToolbarGroup;
|
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Build visible page numbers with ellipsis — Ant Design / MUI pagination style.
|
|
3
|
-
*
|
|
4
|
-
* The item count is CONSTANT wherever the current page sits. The earlier version
|
|
5
|
-
* derived the window straight from `current ± siblingCount` and let it collapse
|
|
6
|
-
* against the edges, so a 1,060-page list opened as `1 2 … 1060` — four controls
|
|
7
|
-
* with a wide empty gap, and both a bad target size and a bad sense of scale
|
|
8
|
-
* (reported 2026-08-24). Ant Design and MUI both solve this by CLAMPING the
|
|
9
|
-
* window instead of shrinking it: near an edge the window slides inward so the
|
|
10
|
-
* strip keeps its full width. Same list now opens as `1 2 3 4 5 … 1060`.
|
|
11
|
-
*
|
|
12
|
-
* Slots = `boundaryCount * 2` edges + `siblingCount * 2 + 1` around current + 2
|
|
13
|
-
* ellipsis positions. With the defaults that is 7 controls.
|
|
2
|
+
* Build visible page numbers with ellipsis — Ant Design / MUI pagination style. The item count is
|
|
3
|
+
* CONSTANT wherever the current page sits.
|
|
14
4
|
*/
|
|
15
5
|
export declare function buildPageRange(current: number, totalPages: number, siblingCount?: number, boundaryCount?: number): (number | "ellipsis")[];
|
|
@@ -1,30 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* `TabsList` scrolls its own overflow (gh#175) so long localized labels never clip. That fixed
|
|
6
|
-
* clipping but not the SCROLL POSITION: after a responsive resize / route re-render the strip kept
|
|
7
|
-
* (or shifted) its internal `scrollLeft`, so the ACTIVE trigger — typically the FIRST one — could
|
|
8
|
-
* end up completely outside the scrollport while still carrying `data-state="active"` /
|
|
9
|
-
* `aria-selected="true"`. A tab you cannot see is a tab you cannot use.
|
|
10
|
-
*
|
|
11
|
-
* The fix observes the strip (size changes) and its triggers (`data-state` changes) and scrolls the
|
|
12
|
-
* element that must stay reachable back into view. Deliberate constraints:
|
|
13
|
-
*
|
|
14
|
-
* - **Never fights the user.** The scroll only runs when the target is NOT already fully inside the
|
|
15
|
-
* scrollport, so an intentional manual/touch scroll that leaves the active tab visible is left
|
|
16
|
-
* alone, and a click (target is under the pointer) or arrow-key move (the browser already
|
|
17
|
-
* scrolled focus into view) is a no-op.
|
|
18
|
-
* - **Focus wins over selection.** With `activationMode="manual"` the roving focus can sit on a
|
|
19
|
-
* trigger that is not the selected one; yanking the strip to the selected tab would strand the
|
|
20
|
-
* keyboard user. The focused trigger inside the list is therefore the preferred target.
|
|
21
|
-
* - **Reduced motion.** `prefers-reduced-motion: reduce` downgrades every correction to an instant
|
|
22
|
-
* jump; resize corrections are instant regardless (a smooth animation mid-resize reads as jank).
|
|
23
|
-
* - **RTL / vertical safe.** All geometry is physical viewport rects and the scroll uses
|
|
24
|
-
* `scrollIntoView({ block: "nearest", inline: "nearest" })`, which resolves direction natively —
|
|
25
|
-
* so a first trigger in `dir="rtl"` (visually on the right) and a vertical rail both work
|
|
26
|
-
* without direction branches. `nearest` also means no ancestor/page scroll when the strip is
|
|
27
|
-
* already where it should be.
|
|
3
|
+
* A tab you cannot see is a tab you cannot use. The fix observes the strip (size changes) and its
|
|
4
|
+
* triggers (`data-state` changes) and scrolls the element that must stay reachable back into view.
|
|
28
5
|
*/
|
|
29
6
|
/** Minimal rect shape — only the edges the visibility test needs. */
|
|
30
7
|
export type TabsScrollBox = {
|
|
@@ -36,10 +13,6 @@ export type TabsScrollBox = {
|
|
|
36
13
|
/**
|
|
37
14
|
* True when `trigger` sits entirely inside the `scrollport` box. Pure geometry — physical viewport
|
|
38
15
|
* coordinates, so it is direction- and orientation-agnostic (LTR, RTL, vertical rail alike).
|
|
39
|
-
*
|
|
40
|
-
* A zero-area scrollport (unmounted, `display:none`, or an environment without layout such as
|
|
41
|
-
* jsdom) reports `true`: there is no measurable overflow to correct, and scrolling a hidden strip
|
|
42
|
-
* would be meaningless.
|
|
43
16
|
*/
|
|
44
17
|
export declare function isTabFullyVisible(scrollport: TabsScrollBox, trigger: TabsScrollBox): boolean;
|
|
45
18
|
/**
|
|
@@ -56,13 +29,6 @@ export declare function prefersReducedMotion(): boolean;
|
|
|
56
29
|
*/
|
|
57
30
|
export declare function syncActiveTabIntoView(list: HTMLElement | null, behavior?: ScrollBehavior): HTMLElement | null;
|
|
58
31
|
/**
|
|
59
|
-
* Wires the two signals that can strand the active tab off-screen:
|
|
60
|
-
*
|
|
61
|
-
* - a `ResizeObserver` on the strip — a responsive width change (1440 → 1024 → 390) keeps/shifts
|
|
62
|
-
* the old `scrollLeft`; the observer's initial delivery also covers first mount at a new width;
|
|
63
|
-
* - a `MutationObserver` on descendant `data-state` — the selected tab changing from outside the
|
|
64
|
-
* strip (router/URL state, a controlled parent) must bring the newly-selected trigger into view.
|
|
65
|
-
*
|
|
66
32
|
* Resize corrections are instant; a selection change animates unless reduced motion is requested.
|
|
67
33
|
* Both observers are optional: without them (SSR, ancient runtimes) the component degrades to the
|
|
68
34
|
* pre-fix behaviour instead of throwing.
|
|
@@ -34,9 +34,8 @@ function Tabs({
|
|
|
34
34
|
value,
|
|
35
35
|
defaultValue: value === void 0 ? resolvedDefault : void 0,
|
|
36
36
|
className: cn(
|
|
37
|
-
// Structure only.
|
|
37
|
+
// Structure only.
|
|
38
38
|
// live in src/styles/navigation-layout.css so the gap reads --tabs-root-gap and a service
|
|
39
|
-
// can retune the tab rhythm without forking this file (#319).
|
|
40
39
|
"group/tabs flex data-[orientation=horizontal]:flex-col",
|
|
41
40
|
className
|
|
42
41
|
),
|
|
@@ -50,7 +49,6 @@ function Tabs({
|
|
|
50
49
|
className: cn(
|
|
51
50
|
// The padding override is an arbitrary value reading the knob (never `p-0`): it must
|
|
52
51
|
// stay a UTILITY so tailwind-merge still drops the strip's own padding step, and a
|
|
53
|
-
// components-layer rule could not beat that utility anyway (#319).
|
|
54
52
|
variant === "line" && "h-auto w-full justify-start border-b p-[var(--tabs-list-line-space-inset)]",
|
|
55
53
|
variant === "card" && "w-full justify-start",
|
|
56
54
|
listClassName
|
|
@@ -63,7 +61,6 @@ function Tabs({
|
|
|
63
61
|
className: cn(
|
|
64
62
|
// Geometry only — the active underline is the token-owned `::after` bar the
|
|
65
63
|
// line variant already owns (never a second, hand-rolled border-b indicator).
|
|
66
|
-
// Token-reading arbitrary values, not Tailwind steps (#319): they have to stay
|
|
67
64
|
// utilities so tailwind-merge keeps dropping the pill trigger's own radius /
|
|
68
65
|
// padding steps from the base class list.
|
|
69
66
|
// `card` adds NOTHING here — its list is forwarded as data-variant="default", so
|
|
@@ -112,10 +109,10 @@ const TabsList = React.forwardRef(({ className, variant = "default", ...props },
|
|
|
112
109
|
// `min-w-0 max-w-full` let the list shrink to (and never exceed) whatever width its
|
|
113
110
|
// ancestors actually give it instead of forcing them wider; horizontal orientation then
|
|
114
111
|
// scrolls its own overflow rather than clipping/hiding long localized labels in a narrow
|
|
115
|
-
//
|
|
112
|
+
// Hidden scrollbar keeps the strip visually clean while staying
|
|
116
113
|
// swipeable on touch and reachable via keyboard (arrow-key roving focus still scrolls the
|
|
117
114
|
// newly-focused trigger into view natively); `useKeepActiveTabVisible` above re-pins the
|
|
118
|
-
//
|
|
115
|
+
// Vertical
|
|
119
116
|
// orientation is untouched — it already stacks in a column and is sized by its own
|
|
120
117
|
// `h-*`/`w-*` overrides.
|
|
121
118
|
// justify-center-SAFE: the strip is a centred flex box that also scrolls. Plain `center`
|
|
@@ -138,12 +135,11 @@ const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
138
135
|
"data-slot": "tabs-trigger",
|
|
139
136
|
className: cn(
|
|
140
137
|
// The SELECTED-state ring (`ring-1 ring-primary/25`) is scoped to the default/card lists —
|
|
141
|
-
// the `line` variant is underline-only (gh#248) and must NEVER paint a surrounding ring, or
|
|
142
138
|
// it competes with (and at equal specificity overrides) the `:focus-visible` ring. The
|
|
143
139
|
// focus-visible ring/outline below is deliberately left unscoped: every variant keeps a
|
|
144
140
|
// visible keyboard focus indicator (WCAG 2.4.7). The line indicator itself lives in
|
|
145
141
|
// src/styles/navigation-layout.css so it reads the --tabs-indicator-* tokens.
|
|
146
|
-
"text-muted-foreground ring-offset-background hover:text-foreground
|
|
142
|
+
"text-muted-foreground ring-offset-background hover:text-foreground ui-focus-ring data-[state=active]:bg-background data-[state=active]:text-foreground group-data-[variant=default]/tabs-list:data-[state=active]:ring-primary/25 relative inline-flex flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-3 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start group-data-[variant=line]/tabs-list:border-e-0 group-data-[variant=line]/tabs-list:border-b-0 focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=default]/tabs-list:data-[state=active]:ring-1 group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none",
|
|
147
143
|
className
|
|
148
144
|
),
|
|
149
145
|
...props
|
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import type { DataStateProp } from "../../props/components/query.prop.js";
|
|
3
3
|
export type { DataStateProp, DataStateProp as DataStateProps, } from "../../props/components/query.prop.js";
|
|
4
4
|
/**
|
|
5
|
-
* Query lifecycle widget — orchestrates skeleton / error / empty / success for one `useQuery`
|
|
6
|
-
* Not a visual component; prefer `@godxjp/ui/query`.
|
|
5
|
+
* Query lifecycle widget — orchestrates skeleton / error / empty / success for one `useQuery`
|
|
6
|
+
* block. Not a visual component; prefer `@godxjp/ui/query`.
|
|
7
7
|
*/
|
|
8
8
|
export declare function DataState<T>({ query, skeleton, prerequisite, empty, isEmpty, errorRenderer, showRetry, onRetry, onAuthError, children, }: DataStateProp<T>): React.JSX.Element;
|
|
@@ -4,9 +4,6 @@ export type { CredentialRevealProp, CredentialRevealProp as CredentialRevealProp
|
|
|
4
4
|
/**
|
|
5
5
|
* CredentialReveal — one-time secret surface (device credential / API key / service-account
|
|
6
6
|
* secret). Masked by default with a show/hide toggle, a copy button that confirms the copy, an
|
|
7
|
-
* optional download, and an optional acknowledge action to pair with a Dialog.
|
|
8
|
-
* real @godxjp/ui primitives (Alert · Button · Text). Reveal is a controlled boolean triad
|
|
9
|
-
* (`revealed` / `defaultRevealed` / `onRevealedChange`); everything user-facing is routed through
|
|
10
|
-
* `t()`, and the copy confirmation is announced via an `aria-live` region.
|
|
7
|
+
* optional download, and an optional acknowledge action to pair with a Dialog.
|
|
11
8
|
*/
|
|
12
9
|
export declare const CredentialReveal: React.ForwardRefExoticComponent<CredentialRevealProp & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -2,8 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
|
|
3
3
|
/**
|
|
4
4
|
* HoverCard root. Defaults to a SNAPPY 200ms open / 100ms close (Radix's raw 700/300 default felt
|
|
5
|
-
* laggy); consumers can still pass `openDelay`/`closeDelay`.
|
|
6
|
-
* intentional — it prevents accidental triggering as the pointer passes over the trigger.
|
|
5
|
+
* laggy); consumers can still pass `openDelay`/`closeDelay`.
|
|
7
6
|
*/
|
|
8
7
|
export declare function HoverCard({ openDelay, closeDelay, ...props }: React.ComponentProps<typeof HoverCardPrimitive.Root>): React.JSX.Element;
|
|
9
8
|
export declare const HoverCardTrigger: React.ForwardRefExoticComponent<HoverCardPrimitive.HoverCardTriggerProps & React.RefAttributes<HTMLAnchorElement>>;
|
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
export type { SeparatorProp, SeparatorProp as SeparatorProps, } from "../../props/components/layout.prop.js";
|
|
3
3
|
/**
|
|
4
|
-
* Separator — a tokenized horizontal/vertical rule, optionally INTERRUPTED by a localized label
|
|
5
|
-
* (gh#308): a message stream's day divider, a "new messages" unread watermark, an auth
|
|
6
|
-
* conjunction. Before #308 the only labelled rule in the library was the auth-scoped
|
|
7
|
-
* `AuthDivider`, so a chat stream had to either misuse it (inheriting the `--auth-shell-divider-*`
|
|
8
|
-
* type ramp) or hand-roll a `<div>` grid; `AuthDivider` is now a thin preset over this.
|
|
9
|
-
*
|
|
10
4
|
* ACCESSIBILITY — the whole point of the labelled form is that the label is ANNOUNCED, exactly
|
|
11
|
-
* ONCE. Without a label the rule stays `decorative` (Radix emits `role="none"`), which is right:
|
|
12
|
-
*
|
|
13
|
-
* so Radix emits a real `role="separator"` (plus `aria-orientation` when vertical, which is what
|
|
14
|
-
* the ARIA default already implies for horizontal), the label string becomes the separator's
|
|
15
|
-
* accessible NAME via `aria-label`, and the visible label node is `aria-hidden` — otherwise the
|
|
16
|
-
* same string would be announced twice, once as the name and again as the content. A consumer who
|
|
17
|
-
* explicitly passes `decorative` still wins; when they force `decorative` on a labelled rule the
|
|
18
|
-
* name is dropped (a `role="none"` element may not carry one) and the visible text is left in the
|
|
19
|
-
* tree instead, so it is still read once and never as a nameless blank rule.
|
|
5
|
+
* ONCE. Without a label the rule stays `decorative` (Radix emits `role="none"`), which is right: a
|
|
6
|
+
* section rule carries no information.
|
|
20
7
|
*/
|
|
21
8
|
export declare const Separator: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
|
|
22
9
|
orientation?: import("../../props/index.js").OrientationProp;
|
|
@@ -7,11 +7,7 @@ export declare const ToggleGroup: React.ForwardRefExoticComponent<((Omit<ToggleG
|
|
|
7
7
|
variant?: ToggleGroupVariant;
|
|
8
8
|
size?: ToggleGroupSize;
|
|
9
9
|
}) & React.RefAttributes<HTMLDivElement>>;
|
|
10
|
-
/**
|
|
11
|
-
* `variant`/`size` come from the group through context; the COUNT stays per item, because the
|
|
12
|
-
* number is per-item data (gh#312). Same vocabulary as `Toggle` and `Button` — one counter pill
|
|
13
|
-
* for the whole library.
|
|
14
|
-
*/
|
|
10
|
+
/** Same vocabulary as `Toggle` and `Button` — one counter pill for the whole library. */
|
|
15
11
|
export type ToggleGroupItemProp = React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> & ToggleCountFields & {
|
|
16
12
|
variant?: ToggleGroupVariant;
|
|
17
13
|
size?: ToggleGroupSize;
|
|
@@ -6,23 +6,18 @@ declare const toggleVariants: (props?: ({
|
|
|
6
6
|
size?: "lg" | "md" | "sm" | null | undefined;
|
|
7
7
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* than two that drift (gh#312). Not exported on its own — it is folded into `ToggleProp` and
|
|
12
|
-
* `ToggleGroupItemProp` so there is one public name per component.
|
|
9
|
+
* Not exported on its own — it is folded into `ToggleProp` and `ToggleGroupItemProp` so there is
|
|
10
|
+
* one public name per component.
|
|
13
11
|
*/
|
|
14
12
|
type ToggleCountFields = {
|
|
15
13
|
/**
|
|
16
14
|
* Optional numeric count rendered as a borderless counter pill after the label — the SAME
|
|
17
15
|
* vocabulary `Button` already defines, so a counted segmented toggle and a counted filter tab
|
|
18
16
|
* read identically. Formatted with `Intl.NumberFormat` in the active locale (never `String(n)`,
|
|
19
|
-
* never a hand-rolled thousands separator).
|
|
20
|
-
* Badge is a status chip with its own surface, so it double-borders the chip and puts two boxes
|
|
21
|
-
* where there is one control. The pill takes its colour from the toggle's OWN pressed state, so
|
|
22
|
-
* pressed and unpressed chips differ without reading the number.
|
|
17
|
+
* never a hand-rolled thousands separator).
|
|
23
18
|
*/
|
|
24
19
|
count?: number;
|
|
25
|
-
/** Cap for `count` — beyond it the pill shows `{overflowCount}+` (e.g. `99+`).
|
|
20
|
+
/** Cap for `count` — beyond it the pill shows `{overflowCount}+` (e.g. `99+`). */
|
|
26
21
|
overflowCount?: number;
|
|
27
22
|
/** Render the pill when `count` is 0. Default `true`, matching Button. */
|
|
28
23
|
showZero?: boolean;
|
|
@@ -30,31 +25,11 @@ type ToggleCountFields = {
|
|
|
30
25
|
* Localized description of what the count MEANS, folded into the accessible name so the control
|
|
31
26
|
* never announces as a bare number ("👍 3" → "thumbs up, 3 reactions"). Supply it whenever the
|
|
32
27
|
* visible label is an icon or an emoji; with a text label the label itself already carries the
|
|
33
|
-
* meaning.
|
|
28
|
+
* meaning.
|
|
34
29
|
*/
|
|
35
30
|
countLabel?: string;
|
|
36
31
|
};
|
|
37
|
-
/**
|
|
38
|
-
* Counter pill shared by `Toggle` and `ToggleGroupItem`.
|
|
39
|
-
*
|
|
40
|
-
* ACCESSIBLE NAME. The digits live INSIDE the same `button[aria-pressed]` — one tab stop, one
|
|
41
|
-
* focus ring, one name. The name always comes out as "<label>, <count> <unit>" ("Unread, 12",
|
|
42
|
-
* "Thích, 3 lượt"), by one of two routes:
|
|
43
|
-
*
|
|
44
|
-
* • Name from CONTENTS (the usual text chip). The visible digits are `aria-hidden`, and an
|
|
45
|
-
* `sr-only` sibling carries ", 12 unit". The separator is explicit on purpose: the accessible
|
|
46
|
-
* name is a CONCATENATION of descendant text, and whether a browser inserts a space between
|
|
47
|
-
* two inline boxes is a layout detail no test can rely on — without it the control can
|
|
48
|
-
* announce "Unread12".
|
|
49
|
-
* • Name from `aria-label` (an icon or emoji chip). Contents are ignored for the name, so the
|
|
50
|
-
* same ", 12 unit" tail is folded into the label instead.
|
|
51
|
-
*
|
|
52
|
-
* Either way the count is announced exactly ONCE — the visible digits are hidden from the a11y
|
|
53
|
-
* tree precisely so they cannot be counted twice — and there is deliberately no `aria-live`: a
|
|
54
|
-
* count that ticks up as other people react is not this control's status, and a live region here
|
|
55
|
-
* would fire on every socket message. A product that wants the change announced owns its own
|
|
56
|
-
* live region.
|
|
57
|
-
*/
|
|
32
|
+
/** Counter pill shared by `Toggle` and `ToggleGroupItem`. ACCESSIBLE NAME. */
|
|
58
33
|
declare function useCounterPill({ count, overflowCount, showZero, countLabel, ariaLabel, }: ToggleCountFields & {
|
|
59
34
|
ariaLabel?: string;
|
|
60
35
|
}): {
|
|
@@ -1,28 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The canonical GoDX brand mark, as email-safe markup.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the capsule path is byte-identical to the component's, so the two can never diverge). A capsule
|
|
7
|
-
* WITHOUT the internal glyph is the incomplete mark and must not ship. The ARTWORK matches the
|
|
8
|
-
* canonical SCR-302 raster exactly; only the rendered BOX is email-specific — the canonical email
|
|
9
|
-
* header sets it at 22px (`--email-mark-width`) beside the "GoDX" wordmark, where the web
|
|
10
|
-
* `<Logo mark="godx" />` box is 32px.
|
|
11
|
-
*
|
|
12
|
-
* Nothing here references an external or relative asset: an email template has no base URL it can
|
|
13
|
-
* trust, remote images are blocked by default in most clients, and a `cid:` attachment needs
|
|
14
|
-
* transport support. So the mark is delivered three ways, in order of fidelity:
|
|
15
|
-
*
|
|
16
|
-
* 1. `svg` — inline `<svg>`. Apple Mail, iOS Mail, Thunderbird, Samsung Mail. Best fidelity.
|
|
17
|
-
* 2. `dataUri` — the same SVG as a `data:` URL for `<img src>`. No network fetch.
|
|
18
|
-
* 3. `tableHtml` — bulletproof `<table>`/`<div>` markup with background-color + border-radius.
|
|
19
|
-
* Renders everywhere; degrades to a square emerald block with a light bar in Outlook's Word
|
|
20
|
-
* renderer (which drops `border-radius`) — still recognisably the mark, never a broken image.
|
|
21
|
-
*
|
|
22
|
-
* Colours come from `EMAIL_COLORS` (derived from `--brand` / `--brand-foreground`, the roles
|
|
23
|
-
* `--logo-godx-color` points at), so a re-themed identity role re-tints the mark. NOT `--success`:
|
|
24
|
-
* that is the wakatake STATUS green, and binding identity to it rendered the mark ~ΔE76 17 away
|
|
25
|
-
* from the canonical emerald until gh#250 introduced the dedicated `--brand` role.
|
|
2
|
+
* The canonical GoDX brand mark, as email-safe markup. The mark is an emerald CAPSULE with an
|
|
3
|
+
* internal light GLYPH bar — the same artwork the React `<Logo mark="godx" />` paints, at the same
|
|
4
|
+
* 32×32 viewBox and the same coordinates (a test asserts the capsule path is byte-identical to the
|
|
5
|
+
* component's, so the two can never diverge).
|
|
26
6
|
*/
|
|
27
7
|
import { type EmailHex } from "./color.js";
|
|
28
8
|
/** A rounded rectangle in the mark's 32×32 coordinate space. */
|
|
@@ -39,11 +19,6 @@ export declare const EMAIL_BRAND_MARK_VIEWBOX = "0 0 32 32";
|
|
|
39
19
|
export declare const EMAIL_BRAND_MARK_CAPSULE: EmailBrandMarkRect;
|
|
40
20
|
/** The internal light glyph bar inside the capsule. */
|
|
41
21
|
export declare const EMAIL_BRAND_MARK_GLYPH: EmailBrandMarkRect;
|
|
42
|
-
/**
|
|
43
|
-
* Path data for a rounded rectangle, in the exact serialisation the canonical mark uses — so the
|
|
44
|
-
* generated capsule string equals the artwork shipped by `<Logo mark="godx" />` character for
|
|
45
|
-
* character.
|
|
46
|
-
*/
|
|
47
22
|
export declare function roundedRectPath({ x, y, width, height, radius }: EmailBrandMarkRect): string;
|
|
48
23
|
/** Options for rendering the mark. Every default comes from the token contract. */
|
|
49
24
|
export interface EmailBrandMarkOptions {
|
|
@@ -68,13 +43,10 @@ export interface EmailBrandMarkOptions {
|
|
|
68
43
|
export declare function emailBrandMarkSvg(o?: EmailBrandMarkOptions): string;
|
|
69
44
|
/**
|
|
70
45
|
* The mark as a `data:image/svg+xml` URL for `<img src>`. Percent-encoded (not base64) so it stays
|
|
71
|
-
* readable in a template and needs no `Buffer`/`btoa`.
|
|
46
|
+
* readable in a template and needs no `Buffer`/`btoa`.
|
|
72
47
|
*/
|
|
73
48
|
export declare function emailBrandMarkDataUri(o?: EmailBrandMarkOptions): string;
|
|
74
|
-
/**
|
|
75
|
-
* Bulletproof `<table>` markup for clients with no SVG support. Uses only `background-color`,
|
|
76
|
-
* `border-radius`, fixed cell sizes and `font-size:0` — the intersection every client renders.
|
|
77
|
-
*/
|
|
49
|
+
/** Bulletproof `<table>` markup for clients with no SVG support. */
|
|
78
50
|
export declare function emailBrandMarkTableHtml(o?: EmailBrandMarkOptions): string;
|
|
79
51
|
/** The canonical mark at its default size and colours, in all three delivery forms. */
|
|
80
52
|
export interface EmailBrandMark {
|
package/dist/email/color.d.ts
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Email colour contract — semantic web roles resolved to LITERAL hex.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* properties, and every colour must appear inline as `#rrggbb` on the element that paints it. The
|
|
6
|
-
* web tokens, meanwhile, are HSL channel triplets (`--primary: 204 100% 39%`) so they can be
|
|
7
|
-
* alpha-composed. This module bridges the two — the triplets are GENERATED from
|
|
8
|
-
* src/tokens/foundation.css (scripts/gen-email-tokens.mjs) and converted here, at module load, by
|
|
9
|
-
* the same `hslToHex` a consumer can call on its own brand roles. There is no hex literal in this
|
|
10
|
-
* directory, so an email palette that drifts from the web palette is structurally impossible.
|
|
2
|
+
* Email colour contract — semantic web roles resolved to LITERAL hex. HTML email has no cascade
|
|
3
|
+
* worth trusting: Gmail strips <style>, Outlook ignores custom properties, and every colour must
|
|
4
|
+
* appear inline as `#rrggbb` on the element that paints it.
|
|
11
5
|
*/
|
|
12
6
|
import { EMAIL_COLOR_SOURCE } from "./tokens.generated.js";
|
|
13
7
|
/**
|
|
@@ -19,14 +13,10 @@ export type EmailColorToken = keyof typeof EMAIL_COLOR_SOURCE;
|
|
|
19
13
|
export type EmailHex = `#${string}`;
|
|
20
14
|
/**
|
|
21
15
|
* Convert a CSS HSL channel triplet (`"204 100% 39%"` — the shape every `@godxjp/ui` colour role
|
|
22
|
-
* uses) into the `#rrggbb` literal an email client needs.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* `hslToHex(getComputedStyle(el).getPropertyValue("--primary"))`.
|
|
27
|
-
*
|
|
28
|
-
* @throws if the input is not a bare `H S% L%` triplet (a hex or `hsl(...)` wrapper is rejected
|
|
29
|
-
* rather than silently mis-parsed).
|
|
16
|
+
* uses) into the `#rrggbb` literal an email client needs. Consumers with a custom brand role can
|
|
17
|
+
* call this directly: `hslToHex(getComputedStyle(el).getPropertyValue("--primary"))`. @throws if
|
|
18
|
+
* the input is not a bare `H S% L%` triplet (a hex or `hsl(...)` wrapper is rejected rather than
|
|
19
|
+
* silently mis-parsed).
|
|
30
20
|
*/
|
|
31
21
|
export declare function hslToHex(triplet: string): EmailHex;
|
|
32
22
|
/**
|