@godxjp/ui 28.9.0 → 28.10.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 (232) hide show
  1. package/agent/START-HERE.md +193 -0
  2. package/agent/anti-ai-tells.json +158 -0
  3. package/agent/components/Accordion.json +60 -0
  4. package/agent/components/AccountChip.json +59 -0
  5. package/agent/components/Actions.json +78 -0
  6. package/agent/components/Activity.json +80 -0
  7. package/agent/components/Affix.json +78 -0
  8. package/agent/components/Alert.json +65 -0
  9. package/agent/components/AlertDialog.json +109 -0
  10. package/agent/components/AlertDialogRoot.json +52 -0
  11. package/agent/components/Anchor.json +119 -0
  12. package/agent/components/AppLauncher.json +95 -0
  13. package/agent/components/AppProvider.json +105 -0
  14. package/agent/components/AppSettingPicker.json +88 -0
  15. package/agent/components/AppSettingToggle.json +70 -0
  16. package/agent/components/AppShell.json +159 -0
  17. package/agent/components/AreaChart.json +105 -0
  18. package/agent/components/AspectRatio.json +38 -0
  19. package/agent/components/Attachments.json +76 -0
  20. package/agent/components/AuthAccountSummary.json +64 -0
  21. package/agent/components/AuthDivider.json +35 -0
  22. package/agent/components/AuthFooter.json +48 -0
  23. package/agent/components/AuthIdentity.json +42 -0
  24. package/agent/components/AuthShell.json +108 -0
  25. package/agent/components/AuthStack.json +21 -0
  26. package/agent/components/Avatar.json +89 -0
  27. package/agent/components/Badge.json +96 -0
  28. package/agent/components/Banner.json +48 -0
  29. package/agent/components/BarChart.json +108 -0
  30. package/agent/components/BranchScopePicker.json +89 -0
  31. package/agent/components/Breadcrumb.json +54 -0
  32. package/agent/components/Button.json +133 -0
  33. package/agent/components/Calendar.json +259 -0
  34. package/agent/components/Callout.json +46 -0
  35. package/agent/components/Card.json +112 -0
  36. package/agent/components/CardBar.json +49 -0
  37. package/agent/components/CardContent.json +51 -0
  38. package/agent/components/Carousel.json +50 -0
  39. package/agent/components/Cascader.json +209 -0
  40. package/agent/components/CenteredShell.json +66 -0
  41. package/agent/components/ChatBubble.json +100 -0
  42. package/agent/components/ChatBubbleList.json +64 -0
  43. package/agent/components/ChatComposer.json +160 -0
  44. package/agent/components/ChatSuggestion.json +86 -0
  45. package/agent/components/Checkbox.json +68 -0
  46. package/agent/components/CheckboxGroup.json +96 -0
  47. package/agent/components/CodeBlock.json +64 -0
  48. package/agent/components/Collapsible.json +74 -0
  49. package/agent/components/ColorPicker.json +87 -0
  50. package/agent/components/Command.json +168 -0
  51. package/agent/components/CommandPalette.json +84 -0
  52. package/agent/components/CompactBarTrend.json +101 -0
  53. package/agent/components/Conversations.json +82 -0
  54. package/agent/components/CredentialReveal.json +93 -0
  55. package/agent/components/DataState.json +79 -0
  56. package/agent/components/DataTable.json +268 -0
  57. package/agent/components/DatePicker.json +275 -0
  58. package/agent/components/Descriptions.json +67 -0
  59. package/agent/components/Dialog.json +78 -0
  60. package/agent/components/DraggablePanel.json +106 -0
  61. package/agent/components/DropdownMenu.json +102 -0
  62. package/agent/components/EmptyState.json +83 -0
  63. package/agent/components/ErrorSurface.json +128 -0
  64. package/agent/components/FeatureList.json +43 -0
  65. package/agent/components/Field.json +64 -0
  66. package/agent/components/FilterBar.json +99 -0
  67. package/agent/components/Flex.json +153 -0
  68. package/agent/components/FloatButton.json +91 -0
  69. package/agent/components/Form.json +87 -0
  70. package/agent/components/FormErrors.json +51 -0
  71. package/agent/components/FormField.json +137 -0
  72. package/agent/components/FormFieldArray.json +39 -0
  73. package/agent/components/FormFieldControl.json +129 -0
  74. package/agent/components/FormRoot.json +122 -0
  75. package/agent/components/Heading.json +61 -0
  76. package/agent/components/HoverCard.json +55 -0
  77. package/agent/components/Icon.json +60 -0
  78. package/agent/components/InfiniteQueryState.json +58 -0
  79. package/agent/components/Input.json +122 -0
  80. package/agent/components/InputOTP.json +106 -0
  81. package/agent/components/Label.json +43 -0
  82. package/agent/components/LegalDocumentShell.json +102 -0
  83. package/agent/components/Legend.json +42 -0
  84. package/agent/components/LineChart.json +103 -0
  85. package/agent/components/Link.json +41 -0
  86. package/agent/components/ListRow.json +92 -0
  87. package/agent/components/Logo.json +85 -0
  88. package/agent/components/Marquee.json +91 -0
  89. package/agent/components/Masonry.json +82 -0
  90. package/agent/components/MasterDetail.json +95 -0
  91. package/agent/components/MegaMenu.json +120 -0
  92. package/agent/components/MobileShell.json +73 -0
  93. package/agent/components/NavList.json +63 -0
  94. package/agent/components/NumberInput.json +158 -0
  95. package/agent/components/OrgSwitcher.json +89 -0
  96. package/agent/components/OverlayPortalProvider.json +42 -0
  97. package/agent/components/PageContainer.json +181 -0
  98. package/agent/components/Pagination.json +132 -0
  99. package/agent/components/Paragraph.json +40 -0
  100. package/agent/components/PasswordInput.json +79 -0
  101. package/agent/components/PasswordStrength.json +51 -0
  102. package/agent/components/PermissionMatrix.json +81 -0
  103. package/agent/components/PieChart.json +99 -0
  104. package/agent/components/Popover.json +110 -0
  105. package/agent/components/PrefetchLink.json +65 -0
  106. package/agent/components/Progress.json +79 -0
  107. package/agent/components/Prose.json +57 -0
  108. package/agent/components/QrCode.json +62 -0
  109. package/agent/components/Radio.json +98 -0
  110. package/agent/components/RadioGroup.json +91 -0
  111. package/agent/components/RangeTimeline.json +80 -0
  112. package/agent/components/Rating.json +92 -0
  113. package/agent/components/ResizablePanel.json +69 -0
  114. package/agent/components/ResponsiveGrid.json +77 -0
  115. package/agent/components/Reveal.json +70 -0
  116. package/agent/components/ScrollArea.json +104 -0
  117. package/agent/components/SearchInput.json +98 -0
  118. package/agent/components/Segmented.json +96 -0
  119. package/agent/components/Select.json +397 -0
  120. package/agent/components/Separator.json +86 -0
  121. package/agent/components/ServiceCatalogCta.json +46 -0
  122. package/agent/components/ServiceLauncherCard.json +86 -0
  123. package/agent/components/ServiceRolePanel.json +83 -0
  124. package/agent/components/Sheet.json +85 -0
  125. package/agent/components/Sidebar.json +118 -0
  126. package/agent/components/Skeleton.json +57 -0
  127. package/agent/components/SkeletonArticle.json +71 -0
  128. package/agent/components/SkeletonAvatar.json +50 -0
  129. package/agent/components/SkeletonButton.json +57 -0
  130. package/agent/components/SkeletonForm.json +52 -0
  131. package/agent/components/SkeletonImage.json +37 -0
  132. package/agent/components/SkeletonInput.json +51 -0
  133. package/agent/components/SkeletonNode.json +42 -0
  134. package/agent/components/SkeletonRows.json +49 -0
  135. package/agent/components/SkeletonTable.json +45 -0
  136. package/agent/components/Slider.json +160 -0
  137. package/agent/components/SplitPane.json +66 -0
  138. package/agent/components/StatCard.json +83 -0
  139. package/agent/components/Steps.json +95 -0
  140. package/agent/components/Swatch.json +41 -0
  141. package/agent/components/Switch.json +81 -0
  142. package/agent/components/Table.json +112 -0
  143. package/agent/components/Tabs.json +158 -0
  144. package/agent/components/TagInput.json +105 -0
  145. package/agent/components/Text.json +201 -0
  146. package/agent/components/Textarea.json +126 -0
  147. package/agent/components/ThoughtChain.json +76 -0
  148. package/agent/components/Thumbnail.json +70 -0
  149. package/agent/components/TimePicker.json +200 -0
  150. package/agent/components/TimeRangePicker.json +90 -0
  151. package/agent/components/Timeline.json +47 -0
  152. package/agent/components/TimelineGrid.json +92 -0
  153. package/agent/components/Title.json +67 -0
  154. package/agent/components/Toaster.json +42 -0
  155. package/agent/components/Toggle.json +90 -0
  156. package/agent/components/ToggleGroup.json +102 -0
  157. package/agent/components/Toolbar.json +120 -0
  158. package/agent/components/Tooltip.json +110 -0
  159. package/agent/components/Topbar.json +83 -0
  160. package/agent/components/TopbarItem.json +79 -0
  161. package/agent/components/Transfer.json +141 -0
  162. package/agent/components/Tree.json +185 -0
  163. package/agent/components/TreeSelect.json +232 -0
  164. package/agent/components/TwoFactorSetup.json +79 -0
  165. package/agent/components/Typography.json +42 -0
  166. package/agent/components/Upload.json +221 -0
  167. package/agent/components/UploadCropDialog.json +60 -0
  168. package/agent/components/VisuallyHidden.json +20 -0
  169. package/agent/components/Welcome.json +65 -0
  170. package/agent/components/formatDate.json +46 -0
  171. package/agent/components/inertiaUpload.json +32 -0
  172. package/agent/components/useZodForm.json +39 -0
  173. package/agent/components-index.json +884 -0
  174. package/agent/components.json +15507 -0
  175. package/agent/index.json +56 -0
  176. package/agent/llms.txt +32 -0
  177. package/agent/patterns/account-recovery-settings.json +19 -0
  178. package/agent/patterns/async-data-state.json +20 -0
  179. package/agent/patterns/auth-recovery-panels.json +29 -0
  180. package/agent/patterns/badge-coloring.json +14 -0
  181. package/agent/patterns/common-fixes.json +16 -0
  182. package/agent/patterns/confirm-destructive.json +11 -0
  183. package/agent/patterns/data-table-page.json +18 -0
  184. package/agent/patterns/deferred-loading.json +12 -0
  185. package/agent/patterns/error-pages.json +28 -0
  186. package/agent/patterns/inertia-detail-page.json +13 -0
  187. package/agent/patterns/inertia-list-page.json +15 -0
  188. package/agent/patterns/inertia-persistent-layout.json +14 -0
  189. package/agent/patterns/organization-memberships.json +19 -0
  190. package/agent/patterns/page-sections.json +18 -0
  191. package/agent/patterns/settings-page-responsive.json +18 -0
  192. package/agent/patterns/settings-section-rows.json +23 -0
  193. package/agent/patterns/signup-form.json +13 -0
  194. package/agent/patterns/topbar-account-chip.json +18 -0
  195. package/agent/patterns/transactional-email.json +22 -0
  196. package/agent/patterns-index.json +323 -0
  197. package/agent/patterns.json +342 -0
  198. package/agent/rules.json +237 -0
  199. package/agent/tokens.json +8422 -0
  200. package/agent/vocabulary.json +198 -0
  201. package/dist/components/data-entry/input.js +8 -1
  202. package/dist/components/layout/flex.d.ts +2 -2
  203. package/dist/components/layout/flex.js +2 -0
  204. package/dist/components/ui/tag-input.d.ts +10 -0
  205. package/dist/components/ui/tag-input.js +35 -2
  206. package/dist/contracts/measurement.json +1 -1
  207. package/dist/i18n/messages/en.json +23 -1
  208. package/dist/i18n/messages/ja.json +21 -1
  209. package/dist/i18n/messages/vi.json +21 -1
  210. package/dist/props/components/data-entry.prop.d.ts +21 -2
  211. package/dist/props/components/layout.prop.d.ts +42 -0
  212. package/dist/props/registry.d.ts +9 -0
  213. package/dist/props/registry.js +6 -0
  214. package/dist/styles/card-layout.css +4 -4
  215. package/dist/styles/control.css +31 -2
  216. package/dist/styles/data-display-layout.css +1 -1
  217. package/dist/styles/layout.css +17 -0
  218. package/dist/styles/navigation-layout.css +3 -1
  219. package/dist/styles/shell-layout.css +2 -0
  220. package/dist/styles/table-layout.css +50 -9
  221. package/dist/tokens/components/segmented.css +5 -1
  222. package/dist/tokens/components/table.css +2 -1
  223. package/docs/COMPOSITION-VS-COMPONENT.md +41 -0
  224. package/docs/DESIGN-AUTHORITY.md +14 -0
  225. package/docs/DEVELOPMENT.md +81 -6
  226. package/docs/data-entry/tag-input.tsx +37 -0
  227. package/docs/layout/flex.tsx +40 -0
  228. package/docs/roadmap/website-components.md +34 -0
  229. package/docs/showcase/marketing-page.tsx +54 -45
  230. package/docs/showcase/table-pagination.tsx +88 -18
  231. package/docs/showcase/theme-customization.tsx +25 -2
  232. package/package.json +6 -4
@@ -0,0 +1,198 @@
1
+ [
2
+ {
3
+ "concept": "Abstract controlled value.",
4
+ "name": "ValueProp<T = string>",
5
+ "usedBy": [
6
+ "CheckboxGroup",
7
+ "Upload",
8
+ "Cascader",
9
+ "TreeSelect",
10
+ "Tabs",
11
+ "SearchSelect"
12
+ ],
13
+ "values": [
14
+ "generic"
15
+ ]
16
+ },
17
+ {
18
+ "concept": "Abstract uncontrolled initial value.",
19
+ "name": "DefaultValueProp<T = string>",
20
+ "usedBy": [
21
+ "CheckboxGroup",
22
+ "Upload",
23
+ "Cascader",
24
+ "TreeSelect",
25
+ "Tabs"
26
+ ],
27
+ "values": [
28
+ "generic"
29
+ ]
30
+ },
31
+ {
32
+ "concept": "Callback for abstract value changes. DOM events continue to use onChange.",
33
+ "name": "OnValueChangeProp<T = string>",
34
+ "usedBy": [
35
+ "CheckboxGroup",
36
+ "Upload",
37
+ "Cascader",
38
+ "TreeSelect",
39
+ "Transfer",
40
+ "settings pickers"
41
+ ],
42
+ "values": [
43
+ "(value: T) => void"
44
+ ]
45
+ },
46
+ {
47
+ "concept": "Disclosure state.",
48
+ "name": "OpenProp / DefaultOpenProp / OnOpenChangeProp",
49
+ "usedBy": [
50
+ "Dialog",
51
+ "Sheet",
52
+ "Popover"
53
+ ],
54
+ "values": [
55
+ "boolean",
56
+ "(open: boolean) => void"
57
+ ]
58
+ },
59
+ {
60
+ "concept": "Shared public size names.",
61
+ "name": "SizeProp",
62
+ "notes": "Component-specific subsets must be documented. Old alias small is sm.",
63
+ "usedBy": [
64
+ "Button",
65
+ "Steps",
66
+ "Switch"
67
+ ],
68
+ "values": [
69
+ "xs",
70
+ "sm",
71
+ "md",
72
+ "lg"
73
+ ]
74
+ },
75
+ {
76
+ "concept": "Semantic status/color intent.",
77
+ "name": "ToneProp",
78
+ "notes": "Status values belong in tone, not variant.",
79
+ "usedBy": [
80
+ "Badge",
81
+ "Alert"
82
+ ],
83
+ "values": [
84
+ "default",
85
+ "success",
86
+ "warning",
87
+ "destructive",
88
+ "info",
89
+ "muted",
90
+ "neutral"
91
+ ]
92
+ },
93
+ {
94
+ "concept": "Shared layout gap scale.",
95
+ "name": "GapProp",
96
+ "notes": "The single shared gap scale on Flex — the one layout primitive (default direction=\"row\"; use direction=\"col\" for vertical rhythm; these replaced the removed Stack/Inline).",
97
+ "usedBy": [
98
+ "Flex"
99
+ ],
100
+ "values": [
101
+ "xs",
102
+ "sm",
103
+ "md",
104
+ "lg",
105
+ "xl"
106
+ ]
107
+ },
108
+ {
109
+ "concept": "Primary heading text.",
110
+ "name": "TitleProp",
111
+ "usedBy": [
112
+ "PageContainer",
113
+ "PageHeader",
114
+ "EmptyState",
115
+ "Dialog"
116
+ ],
117
+ "values": [
118
+ "React.ReactNode"
119
+ ]
120
+ },
121
+ {
122
+ "concept": "Page/subtree density.",
123
+ "name": "DensityProp",
124
+ "usedBy": [
125
+ "PageContainer"
126
+ ],
127
+ "values": [
128
+ "compact",
129
+ "default",
130
+ "comfortable"
131
+ ]
132
+ },
133
+ {
134
+ "concept": "Named whole-page SHELL contract for CenteredShell — the page measure, section rhythm, chrome flatness and hero heading tier, all owned by component tokens.",
135
+ "name": "CenteredShellPresetProp",
136
+ "notes": "public-landing is the PUBLIC marketing/product landing geometry: one 67.5rem measure shared by the header bar, the centred column and the footer, the section rhythm, flat elevation-free cards and the hero h1 tier. \"default\" emits NO data-preset at all, so the existing shell box is untouched. Pair with `Flex hideBelow`/`hideFrom` for header region visibility — a landing must never own a page-local media query or a max-width wrapper.",
137
+ "usedBy": [
138
+ "CenteredShell"
139
+ ],
140
+ "values": [
141
+ "default",
142
+ "public-landing"
143
+ ]
144
+ },
145
+ {
146
+ "concept": "Named collection contract for a table — how a dense collection behaves when its container gets narrow.",
147
+ "name": "TablePresetProp",
148
+ "notes": "action-collection swaps the desktop intrinsic column widths for table-layout: fixed + the token-owned column PRIORITY measures below `collapseBelow`, so a five-column approval queue keeps every column — including row actions — inside a 390px frame with no page-local CSS, no hidden column and no horizontal scroll. It changes the SIZING model only: no display change, no role rewriting, no card transformation, so table semantics and screen-reader navigation are identical at every width. ONE contract, two entry points: the `Table` primitive (mark `priority` on each TableHead/TableCell yourself) and the TanStack `DataTable` (mark `priority` on the ColumnDef; it stamps both cells for you, and additionally releases the surface's `--table-surface-min-inline-size` floor). Both read the same `--table-action-collection-*` tokens — there is no parallel DataTable family.",
149
+ "usedBy": [
150
+ "Table",
151
+ "DataTable"
152
+ ],
153
+ "values": [
154
+ "default",
155
+ "action-collection"
156
+ ]
157
+ },
158
+ {
159
+ "concept": "Relative importance of a table column, used by the action-collection preset to allocate the narrow-frame measure.",
160
+ "name": "TableColumnPriorityProp",
161
+ "notes": "On the raw `Table`, set it on BOTH the TableHead and the TableCell of a column; on `DataTable` set it once on the `ColumnDef` and it is stamped onto the <th> and every <td>. `actions` reserves its measure first so the row-action affordance can never be pushed outside the viewport; a column with no priority takes the remaining space (the free-text column).",
162
+ "usedBy": [
163
+ "Table",
164
+ "DataTable"
165
+ ],
166
+ "values": [
167
+ "primary",
168
+ "secondary",
169
+ "meta",
170
+ "actions"
171
+ ]
172
+ },
173
+ {
174
+ "concept": "Named hosted-identity FLOW MEASURE for AuthShell — the card max-width plus the desktop and mobile page gutters, all owned by component tokens.",
175
+ "name": "AuthShellPresetProp",
176
+ "notes": "Orthogonal to AuthShell's `variant` (which owns control density + heading size) and applied after it, so `variant=\"canonical\" preset=\"device-authorization\"` composes. device-authorization = 380px card / 5px inline gutter at 390; context-selection = 25rem card, edge-to-edge on mobile. Selecting a preset REPLACES any consumer-side --auth-shell-card-max-width override — a page-local width is the anti-pattern these presets exist to remove.",
177
+ "usedBy": [
178
+ "AuthShell"
179
+ ],
180
+ "values": [
181
+ "default",
182
+ "device-authorization",
183
+ "context-selection"
184
+ ]
185
+ },
186
+ {
187
+ "concept": "Avatar geometry — WHAT the identity mark represents: a person or an entity. Deliberately NOT the control ShapeProp (default|pill|sharp), whose `sharp` is --radius-sharp: 0 and cannot express the rounded rect an entity mark needs.",
188
+ "name": "AvatarShapeProp",
189
+ "notes": "circle (default, inert) = the round --radius-pill person avatar on the muted surface; square = the entity-header organization/service mark — a compact rounded square on the brand surface driven by --avatar-square-{radius,size,background,foreground}. Choose by meaning, never by look: a className=\"rounded-md bg-primary\" override on the call site is the anti-pattern this prop removes.",
190
+ "usedBy": [
191
+ "Avatar"
192
+ ],
193
+ "values": [
194
+ "circle",
195
+ "square"
196
+ ]
197
+ }
198
+ ]
@@ -13,7 +13,14 @@ import {
13
13
  } from "./control-appearance.js";
14
14
  import { resolveAllowClear } from "./control-surface.js";
15
15
  const inputBaseClass = [
16
- "ui-control ui-input w-full rounded-[var(--control-radius)] transition-[color,box-shadow]",
16
+ // PER-EDGE RADIUS THROUGH A KNOB, because a joined control has to square one side (gh#841).
17
+ // `rounded-[var(--control-radius)]` is a UTILITY, and Tailwind v4 orders utilities after
18
+ // `@layer components` — so `.ui-input-group:has(…) .ui-input { border-start-start-radius: 0 }`
19
+ // resolved, was catalogued, and lost: the field kept 6px on its leading corners and drew a
20
+ // rounded edge exactly where the addon meets it. Fifth instance of the gh#366/#375/#819 trap.
21
+ // The repair is gh#366's: emit the value FROM a token as a utility, and let the components
22
+ // layer decide WHICH token — a custom property has no utility competing with it.
23
+ "ui-control ui-input w-full rounded-s-[var(--input-radius-start,var(--control-radius))] rounded-e-[var(--input-radius-end,var(--control-radius))] transition-[color,box-shadow]",
17
24
  "selection:bg-primary selection:text-primary-foreground",
18
25
  "placeholder:text-muted-foreground",
19
26
  "aria-invalid:border-destructive",
@@ -1,3 +1,3 @@
1
1
  import type { FlexProp } from "../../props/components/layout.prop.js";
2
- export type { FlexAlignProp, FlexDirectionProp, FlexJustifyProp, FlexMarkerProp, FlexProp, FlexProp as FlexProps, } from "../../props/components/layout.prop.js";
3
- export declare function Flex({ as: Element, direction, marker, grow, shrink, surface, bleed, reveal, gap, gapRaw, pad, padRaw, align, justify, wrap, hideBelow, hideFrom, hideBelowRaw, hideFromRaw, fill, width, className, style, children, ...props }: FlexProp): import("react").JSX.Element;
2
+ export type { FlexAlignProp, FlexDirectionProp, FlexJustifyProp, FlexMarkerProp, FlexMeasureProp, FlexProp, FlexProp as FlexProps, } from "../../props/components/layout.prop.js";
3
+ export declare function Flex({ as: Element, direction, marker, grow, shrink, surface, bleed, reveal, gap, gapRaw, pad, padRaw, align, justify, wrap, hideBelow, hideFrom, hideBelowRaw, hideFromRaw, fill, width, measure, className, style, children, ...props }: FlexProp): import("react").JSX.Element;
@@ -33,6 +33,7 @@ function Flex({
33
33
  hideFromRaw,
34
34
  fill = false,
35
35
  width,
36
+ measure,
36
37
  className,
37
38
  style,
38
39
  children,
@@ -81,6 +82,7 @@ function Flex({
81
82
  "data-hide-from-raw": fromRaw,
82
83
  "data-fill": fill ? "" : void 0,
83
84
  "data-width-raw": width === void 0 ? void 0 : "",
85
+ "data-measure": measure,
84
86
  "data-gap-raw": gapRaw,
85
87
  className: cn("ui-flex", gapRaw === void 0 ? flexGapClass[gap] : void 0, className),
86
88
  "data-pad-raw": padRaw === void 0 ? void 0 : "",
@@ -40,6 +40,16 @@ export type TagInputProps = {
40
40
  maxTagCount?: MaxTagCountProp;
41
41
  /** The node standing in for what `maxTagCount` hid (antd `maxTagPlaceholder`). */
42
42
  maxTagPlaceholder?: MaxTagPlaceholderProp;
43
+ /**
44
+ * antd `maxTagTextLength` — cut each chip's TEXT to this many characters; the value is
45
+ * untouched and stays in `title` and in the remover's accessible name.
46
+ *
47
+ * It was declared on the public prop type and never destructured here, so a 71-character
48
+ * identifier set the chip's width and the chip set the row's, painting outside the control
49
+ * (gh#840). Declared and inert is the same defect as absent, with a worse failure mode:
50
+ * a consumer reads the prop, passes it, and watches nothing happen.
51
+ */
52
+ maxTagTextLength?: number;
43
53
  /** Render one chip yourself (antd `tagRender`) — receives the value and an `onClose` remover. */
44
54
  tagRender?: (props: {
45
55
  value: string;
@@ -30,6 +30,7 @@ const TagInput = React.forwardRef(
30
30
  onClear,
31
31
  maxTagCount,
32
32
  maxTagPlaceholder,
33
+ maxTagTextLength,
33
34
  tagRender,
34
35
  tokenSeparators = [","]
35
36
  }, ref) => {
@@ -95,6 +96,12 @@ const TagInput = React.forwardRef(
95
96
  disabled && "ui-tag-input-disabled",
96
97
  className
97
98
  ),
99
+ onMouseDown: (event) => {
100
+ if (event.target !== event.currentTarget) return;
101
+ event.preventDefault();
102
+ const field = event.currentTarget.querySelector(".ui-tag-input-field");
103
+ field?.focus();
104
+ },
98
105
  children: [
99
106
  tags.length > 0 ? /* @__PURE__ */ jsxs("ul", { role: "list", className: "ui-tag-input-list", "data-slot": "tag-input-list", children: [
100
107
  visibleChips.map((chip) => /* @__PURE__ */ jsx(
@@ -110,7 +117,14 @@ const TagInput = React.forwardRef(
110
117
  disabled: Boolean(disabled) || Boolean(readOnly),
111
118
  onClose: () => removeAt(chip.index)
112
119
  }) : /* @__PURE__ */ jsxs(Fragment, { children: [
113
- chip.value,
120
+ /* @__PURE__ */ jsx(
121
+ "span",
122
+ {
123
+ className: "ui-tag-input-chip-label",
124
+ title: maxTagTextLength && chip.value.length > maxTagTextLength ? chip.value : void 0,
125
+ children: maxTagTextLength && chip.value.length > maxTagTextLength ? `${chip.value.slice(0, maxTagTextLength)}\u2026` : chip.value
126
+ }
127
+ ),
114
128
  !disabled && !readOnly ? /* @__PURE__ */ jsx(
115
129
  "button",
116
130
  {
@@ -125,7 +139,26 @@ const TagInput = React.forwardRef(
125
139
  },
126
140
  chip.value
127
141
  )),
128
- omittedChips.length > 0 ? /* @__PURE__ */ jsx("li", { role: "listitem", className: "ui-tag-input-chip", "data-slot": "tag-input-overflow", children: overflow ?? t("dataEntry.selection.overflow", { count: omittedChips.length }) }) : null
142
+ omittedChips.length > 0 ? (
143
+ /* `+N` NAMES WHAT IT HIDES (gh#840). It used to be a bare `<li role="listitem">` with
144
+ no title, no tabindex and no role — so a reader who saw `+1` had no way, by mouse
145
+ or by keyboard, to learn which tag it stood for. antd's `maxTagPlaceholder` exists
146
+ for exactly this; the default now carries the omitted values itself. */
147
+ /* @__PURE__ */ jsx(
148
+ "li",
149
+ {
150
+ role: "listitem",
151
+ className: "ui-tag-input-chip",
152
+ "data-slot": "tag-input-overflow",
153
+ tabIndex: 0,
154
+ title: omittedChips.map((c) => c.value).join(", "),
155
+ "aria-label": t("ui.tagInput.overflowLabel", {
156
+ tags: omittedChips.map((c) => c.value).join(", ")
157
+ }),
158
+ children: overflow ?? t("dataEntry.selection.overflow", { count: omittedChips.length })
159
+ }
160
+ )
161
+ ) : null
129
162
  ] }) : null,
130
163
  /* @__PURE__ */ jsx(
131
164
  "input",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
3
- "version": "28.9.0",
3
+ "version": "28.10.0",
4
4
  "targetSize": {
5
5
  "standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
6
6
  "min": 24,
@@ -364,7 +364,8 @@
364
364
  "tagInput": {
365
365
  "inputLabel": "Add tags",
366
366
  "removeTag": "Remove {tag}",
367
- "tagCount": "{count} tags"
367
+ "tagCount": "{count} tags",
368
+ "overflowLabel": "Hidden tags: {tags}"
368
369
  },
369
370
  "passwordInput": {
370
371
  "show": "Show password",
@@ -1173,5 +1174,26 @@
1173
1174
  "address": "Chiyoda, Tokyo",
1174
1175
  "rights": "Example Works. A fictional company, for documentation only."
1175
1176
  }
1177
+ },
1178
+ "showcase": {
1179
+ "pagination": {
1180
+ "recordCount": {
1181
+ "one": "{count} record",
1182
+ "other": "{count} records"
1183
+ },
1184
+ "loadMore": {
1185
+ "one": "Load {count} more",
1186
+ "other": "Load {count} more"
1187
+ }
1188
+ },
1189
+ "flexMeasure": {
1190
+ "title": "measure — full-bleed outside, a measured column inside",
1191
+ "lead": "A band is a <section> carrying the edge-to-edge paint around one Flex that measure centres and caps at --page-measure-*. The gutter stays pad's job: measure adds none. narrow (42rem) and medium (48rem) are reading measures; wide (72rem) is the marketing one."
1192
+ },
1193
+ "tagInput": {
1194
+ "longIdTitle": "Long identifiers and +N",
1195
+ "ledgerLabel": "Ledger ID",
1196
+ "ledgerHelper": "A 71-character identifier still stays inside the control"
1197
+ }
1176
1198
  }
1177
1199
  }
@@ -357,7 +357,8 @@
357
357
  "tagInput": {
358
358
  "inputLabel": "タグを追加",
359
359
  "removeTag": "{tag} を削除",
360
- "tagCount": "{count} 件のタグ"
360
+ "tagCount": "{count} 件のタグ",
361
+ "overflowLabel": "非表示のタグ: {tags}"
361
362
  },
362
363
  "passwordInput": {
363
364
  "show": "パスワードを表示",
@@ -1155,5 +1156,24 @@
1155
1156
  "address": "東京都千代田区",
1156
1157
  "rights": "Example Works · ドキュメント用の架空の会社です。"
1157
1158
  }
1159
+ },
1160
+ "showcase": {
1161
+ "pagination": {
1162
+ "recordCount": {
1163
+ "other": "{count} 件"
1164
+ },
1165
+ "loadMore": {
1166
+ "other": "さらに {count} 件を読み込む"
1167
+ }
1168
+ },
1169
+ "flexMeasure": {
1170
+ "title": "measure · 全幅の外、測度の内",
1171
+ "lead": "帯は塗りを持つ <section> で、その内側の一列を measure が中央寄せし --page-measure-* で止める。余白は pad の担当で measure は足さない。narrow(42rem)と medium(48rem)は読み物の測度、wide(72rem)はマーケティングの測度。"
1172
+ },
1173
+ "tagInput": {
1174
+ "longIdTitle": "長い識別子と「+N」",
1175
+ "ledgerLabel": "台帳ID",
1176
+ "ledgerHelper": "71文字の識別子でも行からはみ出さない"
1177
+ }
1158
1178
  }
1159
1179
  }
@@ -358,7 +358,8 @@
358
358
  "tagInput": {
359
359
  "inputLabel": "Thêm thẻ",
360
360
  "removeTag": "Xóa {tag}",
361
- "tagCount": "{count} thẻ"
361
+ "tagCount": "{count} thẻ",
362
+ "overflowLabel": "Thẻ đang ẩn: {tags}"
362
363
  },
363
364
  "passwordInput": {
364
365
  "show": "Hiện mật khẩu",
@@ -1156,5 +1157,24 @@
1156
1157
  "address": "Chiyoda, Tokyo",
1157
1158
  "rights": "Example Works. Một công ty hư cấu, chỉ dùng cho tài liệu."
1158
1159
  }
1160
+ },
1161
+ "showcase": {
1162
+ "pagination": {
1163
+ "recordCount": {
1164
+ "other": "{count} bản ghi"
1165
+ },
1166
+ "loadMore": {
1167
+ "other": "Tải thêm {count}"
1168
+ }
1169
+ },
1170
+ "flexMeasure": {
1171
+ "title": "measure — tràn viền bên ngoài, cột đo bên trong",
1172
+ "lead": "Một dải là <section> mang phần nền tràn viền, bao quanh một Flex được measure canh giữa và chặn ở --page-measure-*. Lề vẫn do pad giữ: measure không thêm lề. narrow (42rem) và medium (48rem) là measure cho nội dung đọc; wide (72rem) là measure cho trang marketing."
1173
+ },
1174
+ "tagInput": {
1175
+ "longIdTitle": "Định danh dài và +N",
1176
+ "ledgerLabel": "Mã sổ cái",
1177
+ "ledgerHelper": "Định danh 71 ký tự vẫn nằm trong khung"
1178
+ }
1159
1179
  }
1160
1180
  }
@@ -157,9 +157,28 @@ export type InputProp = Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"
157
157
  prefix?: React.ReactNode;
158
158
  /** antd `suffix` — content pinned INSIDE the end of the field (%, 円, a hint glyph). */
159
159
  suffix?: React.ReactNode;
160
- /** antd `addonBefore` — a segment welded OUTSIDE the start of the box (`https://`, a currency). */
160
+ /**
161
+ * antd `addonBefore` — a LABEL segment welded OUTSIDE the start of the box (`https://`, a
162
+ * currency code, a unit). For a glyph, use `prefix`: it sits INSIDE the field, so there is one
163
+ * box, one border and no seam to get wrong.
164
+ *
165
+ * KEPT, NOT DEPRECATED — the verdict gh#841 asked for, so the next reviewer does not re-litigate
166
+ * it. Verified in `ant-design@master`, not on the docs page: `components/input/Input.tsx` marks
167
+ * both addons `@deprecated Use Space.Compact instead` on the type AND fires a dev-time
168
+ * `devUseWarning('Input').deprecated(…)` for each, while still rendering them; both locale docs
169
+ * strike the rows through and the `addon` demo is flagged `debug`, i.e. hidden from the
170
+ * published page. So the deprecation is real, and it is a REFACTOR onto `Space.Compact` —
171
+ * a component this library does not have. Deprecating a prop whose replacement does not exist
172
+ * would leave the joined control with no supported spelling at all, and removing a public prop
173
+ * is breaking. `Input addonBefore` IS this library's joined control: it renders the
174
+ * `.ui-input-group` that squares the seam (gh#841). If a `Space`/compact primitive is ever
175
+ * ported, revisit this line — the antd steer is then followable and this becomes a migration.
176
+ */
161
177
  addonBefore?: React.ReactNode;
162
- /** antd `addonAfter` — a segment welded OUTSIDE the end of the box (`.com`, a unit, a button). */
178
+ /**
179
+ * antd `addonAfter` — a segment welded OUTSIDE the end of the box (`.com`, a unit, a button).
180
+ * Deprecated upstream alongside `addonBefore`, and kept for the reason written there.
181
+ */
163
182
  addonAfter?: React.ReactNode;
164
183
  /** Character counter — antd `count`. */
165
184
  count?: ControlCountProp;
@@ -126,6 +126,16 @@ export type FlexDirectionProp = "row" | "col";
126
126
  export type FlexMarkerProp = "disc" | "decimal" | "none";
127
127
  export type FlexAlignProp = "start" | "center" | "end" | "stretch" | "baseline";
128
128
  export type FlexJustifyProp = "start" | "center" | "end" | "between" | "around" | "evenly";
129
+ /**
130
+ * The bounded inline MEASURE of a centred column, named for the `--page-measure-*` token it reads
131
+ * — the same three words `PageContainer measure` uses, plus the marketing step that has no
132
+ * `PageContainer` branch (gh#839).
133
+ *
134
+ * It is the token family, not a new one: `narrow` (42rem) and `medium` (48rem) bracket
135
+ * Bringhurst's 45–75 character reading band, `wide` (72rem) is the MARKETING measure. Do not give
136
+ * a reading column `wide` — that rule is `--page-measure-wide`'s own, and it travels with the word.
137
+ */
138
+ export type FlexMeasureProp = "narrow" | "medium" | "wide";
129
139
  /** @see Flex */
130
140
  export type FlexProp = React.HTMLAttributes<HTMLElement> & {
131
141
  /**
@@ -295,6 +305,38 @@ export type FlexProp = React.HTMLAttributes<HTMLElement> & {
295
305
  * call site đều ĐẾM ĐƯỢC, nên một kho đang trôi khỏi thang tự lộ ra bằng con số.
296
306
  */
297
307
  width?: WidthProp;
308
+ /**
309
+ * CENTRE this box and CAP it at a page measure — the inner half of "full-bleed outside, measured
310
+ * column inside" (gh#839).
311
+ *
312
+ * ## Why it is here and not on `PageContainer`
313
+ *
314
+ * `--page-measure-wide` shipped in 28.8.0 with no prop that reads it, and `PageContainer
315
+ * measure="wide"` was deliberately refused: a marketing page is a stack of full-bleed
316
+ * `<section>`s, and `PageContainer` owns page padding plus a header/toolbar/footer scaffold, so
317
+ * the pages that are the prop's proof could not have consumed it. That reasoning holds and is
318
+ * not reopened here. What it left behind is that NOTHING owned the centred inner column, and
319
+ * three unrelated pages each hand-wrote the same four declarations for it —
320
+ * `docs/showcase/marketing-page.tsx` as an inline `style` constant, `acme-website.tsx` as
321
+ * `.tx-shell` and `futurelastic-web.tsx` as `.fl-shell`. By `docs/TOKENS.md` a shape that
322
+ * appears in more than one place is tier 1.
323
+ *
324
+ * ## What it does, and what it deliberately does NOT
325
+ *
326
+ * `margin-inline: auto` + `inline-size: 100%` + `max-inline-size: var(--page-measure-{value})`.
327
+ * It does **not** add a gutter: the page inset is `pad={{ inline: 6 }}`, which already exists,
328
+ * and two owners for one padding is how a measure and a gutter drift apart. It is a MAX, so
329
+ * below the cap the box is fluid and nothing binds at 390px.
330
+ *
331
+ * An explicit `width` wins (it lands in the style attribute), which is the right order: a fixed
332
+ * column is a stronger statement than a cap.
333
+ *
334
+ * ## When NOT to reach for it
335
+ *
336
+ * Inside a `Card`, a `Dialog` or any surface that already owns its measure. This is PAGE
337
+ * geometry; a Flex that is a row of controls has no business carrying it.
338
+ */
339
+ measure?: FlexMeasureProp;
298
340
  };
299
341
  /** Container column counts; omitted steps inherit from the previous step. Base defaults to 1. */
300
342
  export type ResponsiveGridColumnsProp = number | {
@@ -786,6 +786,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
786
786
  readonly file: "components/layout.prop.ts";
787
787
  readonly vocabulary: readonly [];
788
788
  };
789
+ readonly FlexMeasureProp: {
790
+ readonly group: "layout";
791
+ readonly file: "components/layout.prop.ts";
792
+ readonly vocabulary: readonly [];
793
+ };
789
794
  readonly FlexProp: {
790
795
  readonly group: "layout";
791
796
  readonly file: "components/layout.prop.ts";
@@ -821,6 +826,10 @@ export declare const COMPONENT_PROP_REGISTRY: {
821
826
  readonly field: "hideFrom";
822
827
  readonly local: true;
823
828
  readonly reason: "Inverse of hideBelow — keeps a compact-only region off the wide layout.";
829
+ }, {
830
+ readonly field: "measure";
831
+ readonly local: true;
832
+ readonly reason: 'The CENTRED, CAPPED column (narrow | medium | wide), backed by --page-measure-* — the inner half of "full-bleed outside, measured column inside" (gh#839). Same word and same three token steps as PageContainer `measure`, on the primitive a full-bleed <section> can actually use: PageContainer owns page padding and a header scaffold, which is why measure="wide" was refused there, and the refusal left the centred column with no owner at all — three showcases hand-wrote the same four declarations. It adds NO gutter (that is `pad`), and an explicit `width` wins over it.';
824
833
  }];
825
834
  };
826
835
  readonly ResponsiveGridFlowProp: {
@@ -795,6 +795,7 @@ const COMPONENT_PROP_REGISTRY = {
795
795
  FlexMarkerProp: { group: "layout", file: "components/layout.prop.ts", vocabulary: [] },
796
796
  FlexAlignProp: { group: "layout", file: "components/layout.prop.ts", vocabulary: [] },
797
797
  FlexJustifyProp: { group: "layout", file: "components/layout.prop.ts", vocabulary: [] },
798
+ FlexMeasureProp: { group: "layout", file: "components/layout.prop.ts", vocabulary: [] },
798
799
  FlexProp: {
799
800
  group: "layout",
800
801
  file: "components/layout.prop.ts",
@@ -824,6 +825,11 @@ const COMPONENT_PROP_REGISTRY = {
824
825
  field: "hideFrom",
825
826
  local: true,
826
827
  reason: "Inverse of hideBelow \u2014 keeps a compact-only region off the wide layout."
828
+ },
829
+ {
830
+ field: "measure",
831
+ local: true,
832
+ reason: 'The CENTRED, CAPPED column (narrow | medium | wide), backed by --page-measure-* \u2014 the inner half of "full-bleed outside, measured column inside" (gh#839). Same word and same three token steps as PageContainer `measure`, on the primitive a full-bleed <section> can actually use: PageContainer owns page padding and a header scaffold, which is why measure="wide" was refused there, and the refusal left the centred column with no owner at all \u2014 three showcases hand-wrote the same four declarations. It adds NO gutter (that is `pad`), and an explicit `width` wins over it.'
827
833
  }
828
834
  ]
829
835
  },
@@ -264,13 +264,13 @@
264
264
  padding-bottom: var(--card-space-body-y);
265
265
  }
266
266
 
267
- [data-slot="card"]:has([data-slot="card-header"] [data-slot="card-action"])
268
- [data-slot="card-content"]:not([data-tight]):not([data-flush]) {
267
+ [data-slot="card-header"]:has([data-slot="card-action"])
268
+ + [data-slot="card-content"]:not([data-tight]):not([data-flush]) {
269
269
  padding-top: 0;
270
270
  }
271
271
 
272
- [data-slot="card"]:has([data-slot="card-header"] [data-slot="card-description"])
273
- [data-slot="card-content"]:not([data-tight]):not([data-flush]) {
272
+ [data-slot="card-header"]:has([data-slot="card-description"])
273
+ + [data-slot="card-content"]:not([data-tight]):not([data-flush]) {
274
274
  padding-top: var(--card-space-body-y);
275
275
  }
276
276