@godxjp/ui 21.0.0 → 22.0.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.
Files changed (103) hide show
  1. package/dist/app/app-provider.js +2 -1
  2. package/dist/components/data-display/badge.d.ts +28 -1
  3. package/dist/components/data-display/badge.js +2 -0
  4. package/dist/components/data-display/data-table.d.ts +18 -2
  5. package/dist/components/data-display/data-table.js +4 -0
  6. package/dist/components/data-display/index.d.ts +1 -1
  7. package/dist/components/data-display/popover.d.ts +19 -1
  8. package/dist/components/data-display/popover.js +9 -1
  9. package/dist/components/data-display/progress.d.ts +37 -0
  10. package/dist/components/data-display/progress.js +57 -5
  11. package/dist/components/data-entry/date-picker.d.ts +10 -3
  12. package/dist/components/data-entry/date-picker.js +503 -238
  13. package/dist/components/data-entry/form-field.d.ts +1 -1
  14. package/dist/components/data-entry/form-field.js +4 -1
  15. package/dist/components/data-entry/form.js +10 -1
  16. package/dist/components/data-entry/index.d.ts +0 -6
  17. package/dist/components/data-entry/index.js +0 -6
  18. package/dist/components/data-entry/label.d.ts +14 -1
  19. package/dist/components/data-entry/label.js +6 -1
  20. package/dist/components/data-entry/radio.d.ts +27 -6
  21. package/dist/components/data-entry/radio.js +88 -43
  22. package/dist/components/data-entry/search-select.js +8 -1
  23. package/dist/components/data-entry/select.js +2 -0
  24. package/dist/components/data-entry/switch.d.ts +6 -3
  25. package/dist/components/data-entry/switch.js +34 -11
  26. package/dist/components/layout/mobile-shell.d.ts +1 -1
  27. package/dist/components/layout/mobile-shell.js +2 -0
  28. package/dist/components/navigation/menubar.d.ts +10 -3
  29. package/dist/components/navigation/steps.d.ts +1 -1
  30. package/dist/components/navigation/steps.js +3 -1
  31. package/dist/components/navigation/tabs-scroll.d.ts +27 -0
  32. package/dist/components/navigation/tabs-scroll.js +52 -1
  33. package/dist/components/navigation/tabs.d.ts +2 -2
  34. package/dist/components/navigation/tabs.js +88 -23
  35. package/dist/components/ui/index.d.ts +0 -1
  36. package/dist/components/ui/index.js +0 -1
  37. package/dist/components/ui/segmented.d.ts +15 -1
  38. package/dist/components/ui/segmented.js +13 -6
  39. package/dist/i18n/messages/en.json +3 -2
  40. package/dist/i18n/messages/ja.json +3 -2
  41. package/dist/i18n/messages/vi.json +3 -2
  42. package/dist/lib/datetime/picker-format.d.ts +18 -0
  43. package/dist/lib/datetime/picker-format.js +35 -1
  44. package/dist/lib/field-a11y.d.ts +12 -0
  45. package/dist/lib/field-a11y.js +14 -1
  46. package/dist/props/components/data-display.prop.d.ts +7 -0
  47. package/dist/props/components/data-entry.prop.d.ts +180 -99
  48. package/dist/props/components/index.d.ts +1 -1
  49. package/dist/props/components/layout.prop.d.ts +12 -1
  50. package/dist/props/components/navigation.prop.d.ts +76 -1
  51. package/dist/props/registry.d.ts +16 -16
  52. package/dist/props/registry.js +16 -15
  53. package/dist/props/vocabulary/data.prop.d.ts +12 -0
  54. package/dist/props/vocabulary/index.d.ts +2 -2
  55. package/dist/props/vocabulary/layout.prop.d.ts +11 -0
  56. package/dist/styles/badge-layout.css +4 -0
  57. package/dist/styles/card-layout.css +6 -6
  58. package/dist/styles/control.css +15 -6
  59. package/dist/styles/data-display-layout.css +76 -13
  60. package/dist/styles/focus-ring.css +4 -2
  61. package/dist/styles/navigation-layout.css +25 -0
  62. package/dist/styles/shell-layout.css +5 -0
  63. package/dist/styles/table-layout.css +34 -0
  64. package/dist/tokens/components/data-display.css +9 -0
  65. package/dist/tokens/components/navigation.css +6 -0
  66. package/dist/tokens/components/segmented.css +0 -2
  67. package/dist/tokens/components/shell.css +2 -0
  68. package/dist/tokens/components/table.css +3 -0
  69. package/dist/tokens/foundation.css +7 -0
  70. package/docs/COMPONENTS.md +14 -14
  71. package/docs/CONSUMER-RULES.md +24 -1
  72. package/docs/FRAME-COVERAGE-REPORT.md +3 -6
  73. package/docs/TOKENS.md +65 -0
  74. package/docs/data-display/badge.tsx +37 -0
  75. package/docs/data-display/data-table/index.tsx +18 -0
  76. package/docs/data-display/popover.tsx +41 -1
  77. package/docs/data-display/progress.tsx +28 -0
  78. package/docs/data-entry/calendar.tsx +2 -2
  79. package/docs/data-entry/date-picker.tsx +143 -3
  80. package/docs/data-entry/form/examples/invoice-form.tsx +2 -2
  81. package/docs/data-entry/form-field/examples/a11y-contract.tsx +3 -5
  82. package/docs/data-entry/form.tsx +4 -4
  83. package/docs/data-entry/number-input.tsx +31 -0
  84. package/docs/data-entry/segmented.tsx +103 -1
  85. package/docs/layout/mobile-shell.tsx +5 -0
  86. package/docs/navigation/tabs.tsx +149 -0
  87. package/docs/roadmap/antd-parity.md +35 -34
  88. package/docs/roadmap/parity-audit-data-entry.md +178 -165
  89. package/docs/roadmap/parity-backlog.md +6 -7
  90. package/docs/showcase/acme-portal.tsx +7 -0
  91. package/package.json +11 -23
  92. package/scripts/ui-audit.mjs +17 -4
  93. package/dist/components/data-entry/date-range-picker.d.ts +0 -11
  94. package/dist/components/data-entry/date-range-picker.js +0 -349
  95. package/dist/components/data-entry/month-picker.d.ts +0 -10
  96. package/dist/components/data-entry/month-picker.js +0 -241
  97. package/dist/components/data-entry/month-range-picker.d.ts +0 -10
  98. package/dist/components/data-entry/month-range-picker.js +0 -301
  99. package/dist/components/ui/date-range-picker.d.ts +0 -1
  100. package/dist/components/ui/date-range-picker.js +0 -2
  101. package/docs/data-entry/date-range-picker.tsx +0 -175
  102. package/docs/data-entry/month-picker.tsx +0 -101
  103. package/docs/data-entry/month-range-picker.tsx +0 -115
@@ -23,19 +23,18 @@ compared against, or successive waves will silently measure against different ta
23
23
 
24
24
  ## P0 — fix first, regardless of which strategy wins
25
25
 
26
- | # | Defect | Evidence | Why P0 |
27
- | --- | --- | --- | --- |
28
- | 1 | **`NumberInput` corrupts values 10× in comma-decimal locales, including shipped `vi`** | formats via `Intl.NumberFormat` (`number-input.tsx:100`), parses via hardcoded `replace(/,/g,"")` (`:41`), `handleBlur` re-parses the displayed draft (`:220`). `Intl.NumberFormat("vi",{useGrouping:false}).format(1.5)` → `"1,5"` → parses back as `15` | Silent money/quantity corruption. Focus-then-blur is enough. Keep the NFKC 全角 fold — it is correct. |
29
- | 2 | **`Timeline` hardcodes English screen-reader status text** | `SR_PREFIX = {done:"Completed: ",…}` `timeline.tsx:31-35`, injected `:107`; `grep timeline src/i18n/messages/en.json` → 0 hits | A ja/vi product announces English. Violates the mandatory i18n gate. |
30
- | 3 | **`PasswordStrength` is hardcoded English end-to-end** | `password-strength.tsx:4-8,75,106,113,119-133`; never imports `useTranslation`; `labels` overrides only 3 of ~10 strings | Same gate; and consumers cannot work around it. |
26
+ | # | Defect | Evidence | Why P0 |
27
+ | --- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
28
+ | 1 | **`NumberInput` corrupts values 10× in comma-decimal locales, including shipped `vi`** | formats via `Intl.NumberFormat` (`number-input.tsx:100`), parses via hardcoded `replace(/,/g,"")` (`:41`), `handleBlur` re-parses the displayed draft (`:220`). `Intl.NumberFormat("vi",{useGrouping:false}).format(1.5)` → `"1,5"` → parses back as `15` | Silent money/quantity corruption. Focus-then-blur is enough. Keep the NFKC 全角 fold — it is correct. |
29
+ | 2 | **`Timeline` hardcodes English screen-reader status text** | `SR_PREFIX = {done:"Completed: ",…}` `timeline.tsx:31-35`, injected `:107`; `grep timeline src/i18n/messages/en.json` → 0 hits | A ja/vi product announces English. Violates the mandatory i18n gate. |
30
+ | 3 | **`PasswordStrength` is hardcoded English end-to-end** | `password-strength.tsx:4-8,75,106,113,119-133`; never imports `useTranslation`; `labels` overrides only 3 of ~10 strings | Same gate; and consumers cannot work around it. |
31
31
 
32
32
  ## P1 — grouped by owning file, so one agent owns one group
33
33
 
34
34
  **`data-entry`** — `Slider` missing `aria-valuetext` (`slider.tsx:138-157`) · `SearchInput` Enter does
35
35
  not commit (no `onKeyDown` in the file; `:59-63`) · `ColorPicker` has no `size`/`status`/`variant`
36
36
  and no `presets` (`data-entry.prop.ts:893-908`) · `PasswordStrength` uses `role="img"` instead of
37
- `role="meter"` (`:74-76`) · `Upload showUploadList` boolean-only (`:1196`) · `DateRangePicker
38
- disabled` scalar, cannot lock one end (`:787`) · no `defaultPickerValue` on either date picker ·
37
+ `role="meter"` (`:74-76`) · `Upload showUploadList` boolean-only (`:1196`) ·
39
38
  `Transfer` has no `status` (`:1413-1459`) · `Cascader` search uncapped (`cascader.tsx:389-393`) ·
40
39
  `Select` lacks `fieldNames` although `Cascader` and `TreeSelect` both have it · `NumberInput` has
41
40
  no `stringMode`.
@@ -112,6 +112,13 @@ const THEME = `
112
112
  --warning: 41 73% 53%; --warning-foreground: 217 61% 12%; /* = brand gold */
113
113
  --destructive: 12 83% 44%; --destructive-foreground: 0 0% 100%;
114
114
  --info: 217 69% 47%; --info-foreground: 0 0% 100%;
115
+ /* A TRACK IS A QUIET SURFACE, AND THIS THEME REPOINTED --secondary AT AN ACTION COLOUR.
116
+ Progress reads --progress-track-background, which defaults to hsl(var(--secondary)) — a pale
117
+ neutral in the stock palette. Here --secondary is the navy BUTTON, so the bar's track came out
118
+ near-black and the fill (a MARK: nothing is written on it, so SC 1.4.11 asks 3:1 against the
119
+ track) measured 2.50:1 success / 2.90:1 warning on it. Naming the track is the fix; the fills
120
+ then sit on --muted like everywhere else. Any theme that repurposes --secondary owes this line. */
121
+ --progress-track-background: hsl(var(--muted));
115
122
  /* Shape - base radius + exact ACME steps; re-declare the intermediates so the scope re-resolves */
116
123
  --radius: 0.875rem; /* 14px card */
117
124
  --radius-xs: 4px; --radius-sm: 6px; --radius-md: 10px;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "21.0.0",
4
- "godxUiMcp": "21.0.0",
3
+ "version": "22.0.0",
4
+ "godxUiMcp": "22.0.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -213,10 +213,6 @@
213
213
  "types": "./dist/components/data-entry/date-picker.d.ts",
214
214
  "import": "./dist/components/data-entry/date-picker.js"
215
215
  },
216
- "./ui/date-range-picker": {
217
- "types": "./dist/components/data-entry/date-range-picker.d.ts",
218
- "import": "./dist/components/data-entry/date-range-picker.js"
219
- },
220
216
  "./ui/time-picker": {
221
217
  "types": "./dist/components/data-entry/time-picker.d.ts",
222
218
  "import": "./dist/components/data-entry/time-picker.js"
@@ -350,16 +346,17 @@
350
346
  "check:layout-nav-closure": "for frames in layout-flex,layout-app-shell,layout-aspect-ratio,layout-auth-shell layout-page-container,layout-resizable-panel,layout-separator,layout-sidebar layout-split-pane,layout-topbar,navigation-breadcrumb,navigation-app-setting-picker navigation-context-menu,navigation-dropdown-menu,navigation-menubar,navigation-navigation-menu navigation-steps,navigation-toolbar,navigation-tabs,navigation-pagination; do FRAMES=$frames node scripts/check-layout-nav-closure.mjs || exit 1; done",
351
347
  "check:display-runtime-evidence": "node scripts/check-display-runtime-evidence.mjs",
352
348
  "check:data-table-pagination-wrap": "node scripts/check-data-table-pagination-wrap.mjs",
349
+ "check:tabs-overflow-menu": "node scripts/check-tabs-overflow-menu.mjs",
353
350
  "check:button-icon-xs": "node scripts/check-button-icon-xs.mjs",
354
351
  "check:timeline-title-fill": "node scripts/check-timeline-title-fill.mjs",
355
352
  "check:descriptions-label-value-step": "node scripts/check-descriptions-label-value-step.mjs",
356
353
  "check:frame-contracts": "pnpm check:component-api-manifest && pnpm audit:component-cases && pnpm check:frame-coverage && pnpm check:frame-coverage-ledger && pnpm check:screen-reader-evidence && pnpm check:data-entry-owner-source && pnpm check:display-runtime-evidence",
357
354
  "check:final-touch-rtl": "node scripts/check-final-touch-rtl.mjs",
358
- "check:frame-runtime": "pnpm check:data-entry-frame-runtime && pnpm check:data-entry-touch-aria && pnpm check:layout-nav-frames && pnpm check:provider-feedback-query-runtime && pnpm check:layout-nav-closure && pnpm check:final-touch-rtl && pnpm check:data-table-pagination-wrap && pnpm check:button-icon-xs && pnpm check:timeline-title-fill && pnpm check:descriptions-label-value-step",
359
- "verify": "pnpm typecheck && pnpm lint && pnpm format && pnpm build && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:no-external-assets && pnpm check:token-scale-bypass && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:frame-coverage && pnpm test",
360
- "verify:static": "pnpm build && pnpm check:packed-public-contract && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:token-scale-bypass && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:mcp-prop-sync && pnpm check:contrast && pnpm check:visual-audit && pnpm test",
355
+ "check:frame-runtime": "pnpm check:data-entry-frame-runtime && pnpm check:data-entry-touch-aria && pnpm check:layout-nav-frames && pnpm check:provider-feedback-query-runtime && pnpm check:layout-nav-closure && pnpm check:final-touch-rtl && pnpm check:data-table-pagination-wrap && pnpm check:tabs-overflow-menu && pnpm check:button-icon-xs && pnpm check:timeline-title-fill && pnpm check:descriptions-label-value-step",
356
+ "verify": "pnpm typecheck && pnpm lint && pnpm format && pnpm build && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:no-external-assets && pnpm check:token-scale-bypass && pnpm check:radix-surface && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:disclosure-duplication && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:frame-coverage && pnpm test",
357
+ "verify:static": "pnpm build && pnpm check:packed-public-contract && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:token-scale-bypass && pnpm check:radix-surface && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:disclosure-duplication && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:mcp-prop-sync && pnpm check:contrast && pnpm check:visual-audit && pnpm test",
361
358
  "verify:ci": "pnpm verify:ci:static && pnpm check:frame-contracts && pnpm test",
362
- "verify:ci:static": "pnpm build && pnpm check:packed-public-contract && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:registry && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:no-external-assets && pnpm check:token-scale-bypass && pnpm check:no-antd-runtime && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:gate-coverage && pnpm check:mcp-prop-sync && pnpm check:catalog-contradictions",
359
+ "verify:ci:static": "pnpm build && pnpm check:packed-public-contract && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:registry && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:no-external-assets && pnpm check:token-scale-bypass && pnpm check:no-antd-runtime && pnpm check:radix-surface && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:disclosure-duplication && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:gate-coverage && pnpm check:mcp-prop-sync && pnpm check:catalog-contradictions && pnpm check:catalog-snippets",
363
360
  "verify:browser": "pnpm check:contrast && pnpm check:text-ink-clip && pnpm check:visual-audit",
364
361
  "verify:release": "pnpm verify:static && pnpm check:frame-contracts && pnpm check:frame-coverage && pnpm check:frame-axe",
365
362
  "verify:publish-tree": "pnpm build && pnpm check:packed-public-contract && pnpm check:use-client && pnpm check:dist-tokens-resolve",
@@ -383,6 +380,7 @@
383
380
  "check:no-hardcoded-geometry": "node scripts/check-no-hardcoded-geometry.mjs",
384
381
  "check:no-external-assets": "node scripts/check-no-external-assets.mjs",
385
382
  "check:no-hardcoded-css-values": "node scripts/check-no-hardcoded-css-values.mjs",
383
+ "check:disclosure-duplication": "node scripts/check-disclosure-duplication.mjs",
386
384
  "check:no-inline-magic-numbers": "node scripts/check-no-inline-magic-numbers.mjs",
387
385
  "check:no-tailwind-class-assertions": "node scripts/check-no-tailwind-class-assertions.mjs",
388
386
  "check:control-sizing": "node scripts/check-control-sizing.mjs",
@@ -390,6 +388,7 @@
390
388
  "check:typography": "node scripts/check-typography.mjs",
391
389
  "gen:component-tokens": "node scripts/gen-component-tokens.mjs",
392
390
  "check:no-antd-runtime": "node scripts/check-no-antd-runtime.mjs",
391
+ "check:radix-surface": "node scripts/check-radix-surface.mjs",
393
392
  "gen:email-tokens": "node scripts/gen-email-tokens.mjs",
394
393
  "check:core-isolation": "node scripts/check-core-isolation.mjs",
395
394
  "check:no-consumer-coupling": "node scripts/check-no-consumer-coupling.mjs",
@@ -414,7 +413,8 @@
414
413
  "check:frame-geometry": "node scripts/frame-geometry.mjs",
415
414
  "postinstall": "node scripts/postinstall.mjs",
416
415
  "init-agent": "node scripts/init-agent-kit.mjs",
417
- "check:use-client": "node scripts/check-use-client.mjs"
416
+ "check:use-client": "node scripts/check-use-client.mjs",
417
+ "check:catalog-snippets": "node scripts/audit-catalog-snippets.mjs"
418
418
  },
419
419
  "peerDependencies": {
420
420
  "@axe-core/playwright": "*",
@@ -449,31 +449,19 @@
449
449
  "@fontsource/m-plus-2": "^5.3.0",
450
450
  "@fontsource/noto-sans-jp": "^5.3.0",
451
451
  "@radix-ui/react-accordion": "^1.2.20",
452
- "@radix-ui/react-alert-dialog": "^1.1.23",
453
- "@radix-ui/react-aspect-ratio": "^1.1.15",
454
452
  "@radix-ui/react-avatar": "^1.2.6",
455
- "@radix-ui/react-checkbox": "^1.3.11",
456
453
  "@radix-ui/react-collapsible": "^1.1.20",
457
- "@radix-ui/react-context": "^1.2.2",
458
454
  "@radix-ui/react-context-menu": "^2.3.7",
459
- "@radix-ui/react-dialog": "^1.1.23",
460
- "@radix-ui/react-dropdown-menu": "^2.1.24",
461
- "@radix-ui/react-hover-card": "^1.1.23",
462
455
  "@radix-ui/react-label": "^2.1.15",
463
456
  "@radix-ui/react-menubar": "^1.1.24",
464
457
  "@radix-ui/react-navigation-menu": "^1.2.22",
465
- "@radix-ui/react-popover": "^1.1.23",
466
- "@radix-ui/react-radio-group": "^1.4.7",
467
458
  "@radix-ui/react-scroll-area": "^1.2.18",
468
459
  "@radix-ui/react-select": "^2.3.7",
469
460
  "@radix-ui/react-separator": "^1.1.15",
470
461
  "@radix-ui/react-slider": "^1.4.7",
471
462
  "@radix-ui/react-slot": "^1.3.3",
472
- "@radix-ui/react-switch": "^1.3.7",
473
- "@radix-ui/react-tabs": "^1.1.21",
474
463
  "@radix-ui/react-toggle": "^1.1.18",
475
464
  "@radix-ui/react-toggle-group": "^1.1.19",
476
- "@radix-ui/react-tooltip": "^1.2.16",
477
465
  "@react-aria/utils": "^3.34.1",
478
466
  "@tanstack/react-table": "^9.2.4",
479
467
  "class-variance-authority": "^0.7.1",
@@ -33,7 +33,20 @@ const PALETTE =
33
33
  * Emoji in product text — Unicode "Extended_Pictographic" set (UTS #51). Catches
34
34
  * ✅🎉🔥🚀 etc. but NOT typographic punctuation (· — × ✓), which have their own rules.
35
35
  */
36
- const EMOJI = /\p{Extended_Pictographic}/u;
36
+ /*
37
+ * EMOJI — pictographs, but NOT the three typographic marks that happen to carry the property.
38
+ *
39
+ * `\p{Extended_Pictographic}` includes U+00A9 ©, U+00AE ® and U+2122 ™. All three are
40
+ * `Emoji_Presentation=No`: they default to TEXT presentation, they have been in typography since
41
+ * long before emoji existed, and none of the reasons in this rule's message applies to them — a
42
+ * copyright line does not "break on Win/Linux" and does not pollute an accessible name. The
43
+ * catalog's own CenteredShell recipe was flagged for the `©` in its footer, which is unavoidable
44
+ * product copy, and every consumer with a footer would be flagged for the same thing.
45
+ *
46
+ * Followed by U+FE0F they are asking for emoji presentation on purpose, and then they ARE emoji —
47
+ * so that spelling is still caught.
48
+ */
49
+ const EMOJI = /[\u00A9\u00AE\u2122]\uFE0F|(?![\u00A9\u00AE\u2122])\p{Extended_Pictographic}/u;
37
50
  /** Regional-indicator pairs = emoji flags (🇯🇵) — broken on Win/Linux; use Intl.DisplayNames. */
38
51
  const EMOJI_FLAG = /\p{Regional_Indicator}/u;
39
52
 
@@ -169,7 +182,7 @@ const RULES = [
169
182
  spansElement: true,
170
183
  test: new RegExp(
171
184
  "<(?:Checkbox\\.Group|Upload|Cascader|TreeSelect|Transfer|Select|SearchSelect|DatePicker|" +
172
- `DateRangePicker|TimePicker|ColorPicker|LocalePicker|TimezonePicker|DateFormatPicker|TimeFormatPicker)\\b${ATTRS}\\bonChange=`,
185
+ `TimePicker|ColorPicker|LocalePicker|TimezonePicker|DateFormatPicker|TimeFormatPicker)\\b${ATTRS}\\bonChange=`,
173
186
  "g",
174
187
  ),
175
188
  message:
@@ -729,8 +742,8 @@ const CARD_FLUSH = new RegExp(
729
742
  // legitimately, so they are NOT matched. Whole-file pass (the pair spans lines).
730
743
  const BARE_FIELD = new RegExp(
731
744
  `<(?:label|Label)\\b${ATTRS}>[\\s\\S]{0,240}?</(?:label|Label)>\\s*` +
732
- "<(?:Input|Select|Textarea|NumberInput|SearchInput|SearchSelect|DatePicker|DateRangePicker|" +
733
- "TimePicker|MonthPicker|MonthRangePicker|Cascader|TreeSelect|input)\\b",
745
+ "<(?:Input|Select|Textarea|NumberInput|SearchInput|SearchSelect|DatePicker|" +
746
+ "TimePicker|Cascader|TreeSelect|input)\\b",
734
747
  "g",
735
748
  );
736
749
 
@@ -1,11 +0,0 @@
1
- import * as React from "react";
2
- import type { DateRangePickerProp } from "../../props/components/data-entry.prop.js";
3
- export type { DateRangePickerProp, DateRangePickerProp as DateRangePickerProps, } from "../../props/components/data-entry.prop.js";
4
- /**
5
- * DateRangePicker — WAI-ARIA date-range combobox rendered as ONE input-styled control
6
- * (the established RangePicker convention): `[ from → to ✕ 📅 ]`. The two inner fields stay
7
- * real, typeable ISO `yyyy-MM-dd` inputs (form-submittable via `${name}_from` /
8
- * `${name}_to`, screen-reader friendly, e2e-testable by filling either input); the
9
- * range calendar is the visual affordance.
10
- */
11
- export declare function DateRangePicker({ value: valueProp, defaultValue, onValueChange, placeholder, disabled, className, id, name, locale: localeProp, showToday, showClose, fromDate, toDate, disabledDate, cellRender, allowClear, format, parseFormat, minDate, maxDate, showWeek, presets, needConfirm, allowEmpty, order, open: openProp, defaultOpen, onOpenChange, inputReadOnly, preserveInvalidOnBlur, placement, renderExtraFooter, size, status, variant, ref, ...ariaProps }: DateRangePickerProp): React.JSX.Element;
@@ -1,349 +0,0 @@
1
- "use client";
2
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import * as React from "react";
4
- import { ArrowRight, CalendarIcon, X } from "lucide-react";
5
- import { usePickerLocales, useTranslation } from "../../i18n/use-translation.js";
6
- import { toIsoDate } from "../../lib/datetime/index.js";
7
- import {
8
- formatPickerDate,
9
- parsePickerDate,
10
- pickerDateAllowed
11
- } from "../../lib/datetime/picker-format.js";
12
- import { Button } from "../general/button.js";
13
- import { Flex } from "../layout/flex.js";
14
- import {
15
- CONTROL_VARIANT_CHROME_CLASS,
16
- CONTROL_STATUS_CHROME_CLASS,
17
- controlAppearanceAttributes
18
- } from "./control-appearance.js";
19
- import { useControlledLatch } from "../../lib/hooks.js";
20
- import { pickGroupFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
21
- import { cn } from "../../lib/utils.js";
22
- import { resolveAllowClear } from "./control-surface.js";
23
- import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
24
- import { Calendar } from "./calendar.js";
25
- const ISO_HINT = "yyyy-mm-dd";
26
- function DateRangePicker({
27
- value: valueProp,
28
- defaultValue,
29
- onValueChange,
30
- placeholder,
31
- disabled,
32
- className,
33
- id,
34
- name,
35
- locale: localeProp,
36
- showToday,
37
- showClose,
38
- fromDate,
39
- toDate,
40
- disabledDate,
41
- cellRender,
42
- allowClear,
43
- format,
44
- parseFormat,
45
- minDate,
46
- maxDate,
47
- showWeek,
48
- presets,
49
- needConfirm = false,
50
- allowEmpty = [true, true],
51
- order = true,
52
- open: openProp,
53
- defaultOpen = false,
54
- onOpenChange,
55
- inputReadOnly,
56
- preserveInvalidOnBlur,
57
- placement = "bottom-start",
58
- renderExtraFooter,
59
- size,
60
- status,
61
- variant = "outlined",
62
- ref,
63
- ...ariaProps
64
- }) {
65
- const { t } = useTranslation();
66
- const { dayPickerLocale, locale } = usePickerLocales(localeProp);
67
- const appearance = controlAppearanceAttributes({ status, variant });
68
- const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
69
- const open = !disabled && (openProp ?? internalOpen);
70
- const [pending, setPending] = React.useState();
71
- const [hasPending, setHasPending] = React.useState(false);
72
- const setOpen = (next) => {
73
- if (disabled && next) return;
74
- if (openProp === void 0) setInternalOpen(next);
75
- onOpenChange?.(next);
76
- if (!next) {
77
- setHasPending(false);
78
- setPending(void 0);
79
- }
80
- };
81
- const minimum = minDate ?? fromDate;
82
- const maximum = maxDate ?? toDate;
83
- const allowed = (date) => pickerDateAllowed(date, minimum, maximum, disabledDate);
84
- const display = (date) => formatPickerDate(date, format, locale);
85
- const parse = (text) => parsePickerDate(text, format, parseFormat);
86
- const groupA11y = pickGroupFieldA11y(ariaProps);
87
- const autoId = React.useId();
88
- const groupId = id ?? autoId;
89
- const fromId = `${groupId}-from`;
90
- const toId = `${groupId}-to`;
91
- const identity = useFieldIdentity({ id: groupId, name, "data-field": groupA11y["data-field"] });
92
- const rangeField = groupA11y["data-field"] ?? identity["data-field"];
93
- const rangeName = name ?? identity.name;
94
- const isControlled = useControlledLatch(valueProp !== void 0);
95
- const [internalValue, setInternalValue] = React.useState(defaultValue);
96
- const value = isControlled ? valueProp : internalValue;
97
- const working = hasPending ? pending : value;
98
- const [fromText, setFromText] = React.useState(() => display(value?.from));
99
- const [toText, setToText] = React.useState(() => display(value?.to));
100
- React.useEffect(() => {
101
- setFromText(formatPickerDate(value?.from, format, locale));
102
- setToText(formatPickerDate(value?.to, format, locale));
103
- }, [value?.from, value?.to, format, locale]);
104
- const resolvedPlaceholder = placeholder ?? t("dataEntry.dateRangePicker.placeholder") ?? ISO_HINT;
105
- const emit = (next) => {
106
- if (!isControlled) setInternalValue(next);
107
- onValueChange?.(next);
108
- };
109
- const clearControl = resolveAllowClear(allowClear, true, t("common.clear") ?? "Clear");
110
- const showClear = clearControl.enabled && allowEmpty.every(Boolean) && Boolean(value?.from || value?.to) && !disabled;
111
- const clear = () => {
112
- emit(void 0);
113
- setFromText("");
114
- setToText("");
115
- };
116
- const validRange = (next) => Boolean(
117
- next && (next.from ? allowed(next.from) : allowEmpty[0]) && (next.to ? allowed(next.to) : allowEmpty[1])
118
- );
119
- const choose = (range) => {
120
- let next = range;
121
- if (next?.from && !allowed(next.from) || next?.to && !allowed(next.to)) return;
122
- if (order && next?.from && next.to && next.from > next.to)
123
- next = { from: next.to, to: next.from };
124
- if (needConfirm) {
125
- setPending(next);
126
- setHasPending(true);
127
- } else emit(next);
128
- };
129
- const commitEdge = (edge, raw) => {
130
- const trimmed = raw.trim();
131
- const parsed = parse(trimmed);
132
- if (trimmed && (!parsed || !allowed(parsed))) return;
133
- if (!trimmed && !allowEmpty[edge === "from" ? 0 : 1]) return;
134
- const next = { from: working?.from, to: working?.to, [edge]: parsed };
135
- choose(next.from || next.to ? next : void 0);
136
- };
137
- const sharedKeyHandlers = {
138
- onKeyDown: (event) => {
139
- if (event.key === "ArrowDown") {
140
- event.preventDefault();
141
- setOpen(true);
142
- } else if (event.key === "Escape" && open) {
143
- setOpen(false);
144
- }
145
- }
146
- };
147
- const innerInputClass = "ui-month-picker-input";
148
- return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
149
- (format || needConfirm || preserveInvalidOnBlur) && rangeName ? /* @__PURE__ */ jsxs(Fragment, { children: [
150
- /* @__PURE__ */ jsx(
151
- "input",
152
- {
153
- type: "hidden",
154
- disabled,
155
- name: `${rangeName}_from`,
156
- value: toIsoDate(value?.from)
157
- }
158
- ),
159
- /* @__PURE__ */ jsx(
160
- "input",
161
- {
162
- type: "hidden",
163
- disabled,
164
- name: `${rangeName}_to`,
165
- value: toIsoDate(value?.to)
166
- }
167
- )
168
- ] }) : null,
169
- /* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs(
170
- "div",
171
- {
172
- role: "group",
173
- id: groupId,
174
- ...groupA11y,
175
- "data-field": rangeField,
176
- "data-size": size,
177
- ...appearance,
178
- "aria-disabled": disabled ? true : void 0,
179
- "data-state": open ? "open" : "closed",
180
- className: cn(
181
- // One input-styled shell for the whole range — the shared composite-field box, so
182
- // this and the month range picker cannot drift into two slightly different fields.
183
- "ui-control ui-control-composite-field",
184
- "aria-invalid:border-destructive",
185
- CONTROL_VARIANT_CHROME_CLASS[variant],
186
- CONTROL_STATUS_CHROME_CLASS,
187
- className
188
- ),
189
- onClick: () => {
190
- if (!disabled) setOpen(true);
191
- },
192
- children: [
193
- /* @__PURE__ */ jsx(
194
- "input",
195
- {
196
- id: fromId,
197
- "data-field": rangeField ? `${rangeField}_from` : void 0,
198
- name: !format && !needConfirm && !preserveInvalidOnBlur && rangeName ? `${rangeName}_from` : void 0,
199
- ref,
200
- readOnly: inputReadOnly,
201
- value: fromText,
202
- disabled,
203
- placeholder: resolvedPlaceholder,
204
- inputMode: "numeric",
205
- autoComplete: "off",
206
- "aria-label": t("dataEntry.dateRangePicker.from") ?? "From",
207
- className: innerInputClass,
208
- ...sharedKeyHandlers,
209
- onChange: (event) => {
210
- setFromText(event.target.value);
211
- commitEdge("from", event.target.value);
212
- },
213
- onBlur: (event) => {
214
- const parsed = parse(event.target.value);
215
- const accepted = parsed && allowed(parsed) ? parsed : void 0;
216
- if (!preserveInvalidOnBlur)
217
- setFromText(accepted ? display(accepted) : display(value?.from));
218
- }
219
- }
220
- ),
221
- /* @__PURE__ */ jsx(ArrowRight, { className: "ui-month-picker-separator-icon", "aria-hidden": "true" }),
222
- /* @__PURE__ */ jsx(
223
- "input",
224
- {
225
- id: toId,
226
- "data-field": rangeField ? `${rangeField}_to` : void 0,
227
- name: !format && !needConfirm && !preserveInvalidOnBlur && rangeName ? `${rangeName}_to` : void 0,
228
- readOnly: inputReadOnly,
229
- value: toText,
230
- disabled,
231
- placeholder: resolvedPlaceholder,
232
- inputMode: "numeric",
233
- autoComplete: "off",
234
- "aria-label": t("dataEntry.dateRangePicker.to") ?? "To",
235
- className: innerInputClass,
236
- ...sharedKeyHandlers,
237
- onChange: (event) => {
238
- setToText(event.target.value);
239
- commitEdge("to", event.target.value);
240
- },
241
- onBlur: (event) => {
242
- const parsed = parse(event.target.value);
243
- const accepted = parsed && allowed(parsed) ? parsed : void 0;
244
- if (!preserveInvalidOnBlur)
245
- setToText(accepted ? display(accepted) : display(value?.to));
246
- }
247
- }
248
- ),
249
- showClear ? /* @__PURE__ */ jsx(
250
- "button",
251
- {
252
- type: "button",
253
- tabIndex: -1,
254
- "aria-label": clearControl.label,
255
- className: "text-muted-foreground hover:text-foreground shrink-0",
256
- onClick: (event) => {
257
- event.stopPropagation();
258
- event.currentTarget.closest("div")?.querySelector("input:not([type=hidden])")?.focus();
259
- clear();
260
- },
261
- children: clearControl.clearIcon ?? /* @__PURE__ */ jsx(X, { className: "ui-month-picker-icon", "aria-hidden": "true" })
262
- }
263
- ) : /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
264
- "button",
265
- {
266
- type: "button",
267
- disabled,
268
- tabIndex: -1,
269
- "aria-label": t("dataEntry.dateRangePicker.openCalendar") ?? "Open calendar",
270
- className: "text-muted-foreground hover:text-foreground shrink-0",
271
- children: /* @__PURE__ */ jsx(CalendarIcon, { className: "ui-month-picker-icon", "aria-hidden": "true" })
272
- }
273
- ) }),
274
- /* @__PURE__ */ jsxs(
275
- PopoverContent,
276
- {
277
- className: "ui-control-panel-flush",
278
- side: placement.startsWith("top") ? "top" : "bottom",
279
- align: placement.endsWith("end") ? "end" : "start",
280
- onClick: (event) => event.stopPropagation(),
281
- onOpenAutoFocus: (event) => event.preventDefault(),
282
- children: [
283
- presets?.length ? /* @__PURE__ */ jsx(Flex, { wrap: true, gap: "xs", pad: "sm", children: presets.map((preset, index) => /* @__PURE__ */ jsx(
284
- Button,
285
- {
286
- type: "button",
287
- variant: "ghost",
288
- size: "sm",
289
- onClick: () => {
290
- const range = typeof preset.value === "function" ? preset.value() : preset.value;
291
- if (validRange(range)) choose(range);
292
- },
293
- children: preset.label
294
- },
295
- index
296
- )) }) : null,
297
- /* @__PURE__ */ jsx(
298
- Calendar,
299
- {
300
- mode: "range",
301
- selected: working,
302
- defaultMonth: working?.from,
303
- showWeekNumber: showWeek,
304
- numberOfMonths: 2,
305
- onSelect: (range) => {
306
- choose(range);
307
- setFromText(display(range?.from));
308
- setToText(display(range?.to));
309
- },
310
- locale: dayPickerLocale,
311
- disabled: [
312
- ...minimum ? [{ before: minimum }] : [],
313
- ...maximum ? [{ after: maximum }] : [],
314
- ...disabledDate ? [disabledDate] : []
315
- ],
316
- cellRender,
317
- startMonth: minimum,
318
- endMonth: maximum,
319
- showToday,
320
- showClose,
321
- onClose: () => setOpen(false)
322
- }
323
- ),
324
- needConfirm ? /* @__PURE__ */ jsx(Flex, { pad: "sm", justify: "end", children: /* @__PURE__ */ jsx(
325
- Button,
326
- {
327
- type: "button",
328
- disabled: !validRange(working),
329
- onClick: () => {
330
- if (validRange(working)) {
331
- emit(working);
332
- setOpen(false);
333
- }
334
- },
335
- children: t("dataEntry.timePicker.confirm")
336
- }
337
- ) }) : null,
338
- renderExtraFooter?.()
339
- ]
340
- }
341
- )
342
- ]
343
- }
344
- ) })
345
- ] });
346
- }
347
- export {
348
- DateRangePicker
349
- };
@@ -1,10 +0,0 @@
1
- import * as React from "react";
2
- import type { MonthPickerProp } from "../../props/components/data-entry.prop.js";
3
- export type { MonthPickerProp, MonthPickerProp as MonthPickerProps, } from "../../props/components/data-entry.prop.js";
4
- /**
5
- * MonthPicker — year/month (`yyyy/MM`) input with a 12-cell month grid
6
- * popover: a year header with chevrons over a 3×4 grid of the twelve months.
7
- * The field stays a real, typeable input (form-submittable via `name` as
8
- * `yyyy-MM`); the grid is the visual affordance.
9
- */
10
- export declare function MonthPicker({ value: valueProp, defaultValue, onValueChange, placeholder, disabled, className, id, name, fromYear, toYear, allowClear, open: openProp, defaultOpen, onOpenChange, status, variant, size, inputReadOnly, preserveInvalidOnBlur, placement, renderExtraFooter, ref, ...ariaProps }: MonthPickerProp): React.JSX.Element;