@godxjp/ui-mcp 0.9.0 → 0.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.
- package/dist/index.js +180 -220
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -191,6 +191,75 @@ import { Button } from "@godxjp/ui/general";
|
|
|
191
191
|
storyPath: "layout/Inline.stories.tsx",
|
|
192
192
|
rules: [2]
|
|
193
193
|
},
|
|
194
|
+
{
|
|
195
|
+
name: "Flex",
|
|
196
|
+
group: "layout",
|
|
197
|
+
tagline: "Token-spaced flex primitive with explicit direction, alignment, justification, and wrapping controls.",
|
|
198
|
+
props: [
|
|
199
|
+
{
|
|
200
|
+
name: "direction",
|
|
201
|
+
type: '"row" | "col"',
|
|
202
|
+
defaultValue: '"col"',
|
|
203
|
+
description: "Main axis direction. Use row for horizontal runs, col for vertical stacks."
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
name: "gap",
|
|
207
|
+
type: '"xs" | "sm" | "md" | "lg" | "xl"',
|
|
208
|
+
defaultValue: '"md"',
|
|
209
|
+
description: "Token gap between children, shared with Stack and Inline."
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: "align",
|
|
213
|
+
type: '"start" | "center" | "end" | "stretch" | "baseline"',
|
|
214
|
+
description: "Cross-axis alignment, emitted as a data attribute for the layout CSS."
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: "justify",
|
|
218
|
+
type: '"start" | "center" | "end" | "between" | "around" | "evenly"',
|
|
219
|
+
description: "Main-axis distribution, emitted as a data attribute for the layout CSS."
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
name: "wrap",
|
|
223
|
+
type: "boolean",
|
|
224
|
+
defaultValue: "false",
|
|
225
|
+
description: "Allows children to wrap onto additional flex lines."
|
|
226
|
+
}
|
|
227
|
+
],
|
|
228
|
+
usage: [
|
|
229
|
+
'DO import from `@godxjp/ui/layout` and reach for Flex when the axis, alignment, justification, or wrap behavior is part of the component contract: `import { Flex } from "@godxjp/ui/layout"`.',
|
|
230
|
+
"DO keep spacing on the `gap` prop instead of raw `gap-*`, `space-*`, or padding utilities. Flex uses the same token scale as Stack and Inline, so spacing remains tied to the design system.",
|
|
231
|
+
'DO use `direction="row"` with `wrap` for responsive control rows, chip clusters, and action groups that need more control than Inline exposes.',
|
|
232
|
+
'DO use `direction="col"` for vertical groupings that need explicit `align` or `justify` behavior. If all you need is a vertical gap, Stack is the thinner alias.',
|
|
233
|
+
"DON'T override the axis with `className` after choosing a direction prop. Keep the layout intent in props so catalog guidance and data attributes stay accurate.",
|
|
234
|
+
"Flex is a plain div with React.HTMLAttributes<HTMLDivElement>; pass `id`, `role`, `aria-*`, `data-*`, and structural className values as needed, but do not use it as a semantic form or button wrapper."
|
|
235
|
+
],
|
|
236
|
+
useCases: [
|
|
237
|
+
"Toolbar internals where controls should sit in a row, wrap on narrow widths, and stay vertically centered.",
|
|
238
|
+
"Card headers that need title content on the left and actions on the right via `justify='between'` without hand-rolling flex utility classes.",
|
|
239
|
+
"Empty-state or loading blocks that center content on both axes using `align='center'` and `justify='center'`.",
|
|
240
|
+
"Form sub-sections where a vertical group needs stretched children or centered helper content beyond what Stack exposes.",
|
|
241
|
+
"Badge, chip, or tag clusters where wrapping is required but the caller also needs a larger token gap than Inline's default.",
|
|
242
|
+
"Low-level layout composition inside custom components where Stack and Inline are too opinionated but raw flex classes would duplicate the primitive."
|
|
243
|
+
],
|
|
244
|
+
related: [
|
|
245
|
+
"Stack \u2014 thin `direction='col'` alias of Flex. Use Stack for ordinary vertical block spacing; use Flex when you need align, justify, or wrap control.",
|
|
246
|
+
"Inline \u2014 thin `direction='row'` alias of Flex with wrapping and centered alignment. Use Inline for simple horizontal groups; use Flex for explicit axis/distribution control.",
|
|
247
|
+
"ResponsiveGrid \u2014 use for equal-width, multi-column tile layouts. Flex arranges children on one flex axis and does not provide column-count behavior.",
|
|
248
|
+
"PageContainer \u2014 page scaffold and padding context. Flex is an inner layout primitive used inside page sections, cards, dialogs, and toolbars."
|
|
249
|
+
],
|
|
250
|
+
example: `import { Flex } from "@godxjp/ui/layout";
|
|
251
|
+
import { Button } from "@godxjp/ui/general";
|
|
252
|
+
|
|
253
|
+
<Flex direction="row" gap="sm" align="center" justify="between" wrap>
|
|
254
|
+
<SearchSummary />
|
|
255
|
+
<Flex direction="row" gap="xs" align="center" wrap>
|
|
256
|
+
<Button variant="outline">\u30EA\u30BB\u30C3\u30C8</Button>
|
|
257
|
+
<Button>\u9069\u7528</Button>
|
|
258
|
+
</Flex>
|
|
259
|
+
</Flex>`,
|
|
260
|
+
storyPath: "layout/Flex.stories.tsx",
|
|
261
|
+
rules: [2, 40]
|
|
262
|
+
},
|
|
194
263
|
{
|
|
195
264
|
name: "ResponsiveGrid",
|
|
196
265
|
group: "layout",
|
|
@@ -811,7 +880,7 @@ function MyShell({ children }: { content: React.ReactNode }) {
|
|
|
811
880
|
],
|
|
812
881
|
useCases: [
|
|
813
882
|
'Primary form submission in a Dialog or Sheet (e.g. `<Button type="submit" disabled={form.processing}>\u4FDD\u5B58</Button>`) \u2014 the `disabled` prop greys it out and blocks pointer events, preventing double-submit during async operations.',
|
|
814
|
-
'Destructive confirmation inside a Dialog \u2014 pair `
|
|
883
|
+
'Destructive confirmation inside a Dialog \u2014 pair `tone="destructive"` Button as the confirm action and `variant="outline"` as Cancel; never use `variant="default"` for a delete action.',
|
|
815
884
|
'Icon-only toolbar actions in a DataTable column (edit, delete, copy) using `size="icon-sm"` + `variant="ghost"` + a Lucide icon child \u2014 gives equal-width square targets that don\'t distort the row.',
|
|
816
885
|
"Navigation links styled as buttons (e.g. 'New Invoice', 'Back to list') using `asChild` + Inertia `<Link>` \u2014 preserves SPA navigation while using the button's visual treatment.",
|
|
817
886
|
"Async mutation trigger in an accounting workflow (e.g. 'Sync from MF', 'Export CSV') \u2014 disable on processing state; pair with `MutationFeedback` for error/retry UI rather than inline `try/catch` alerts.",
|
|
@@ -1224,7 +1293,7 @@ import { ResponsiveGrid } from "@godxjp/ui/layout";
|
|
|
1224
1293
|
],
|
|
1225
1294
|
useCases: [
|
|
1226
1295
|
'Category or tier labels on table rows \u2014 e.g. plan tier (`<Badge variant="secondary">Pro</Badge>`), document type (`<Badge variant="outline">Invoice</Badge>`), or locale tag (`<Badge variant="secondary">EN</Badge>`).',
|
|
1227
|
-
'Approval or review state in an accounting list where the value is not a lifecycle key in Badge\'s STATUS_MAP \u2014 e.g. a custom approval tier like `<Badge
|
|
1296
|
+
'Approval or review state in an accounting list where the value is not a lifecycle key in Badge\'s STATUS_MAP \u2014 e.g. a custom approval tier like `<Badge tone="success">\u627F\u8A8D\u6E08</Badge>` or `<Badge tone="warning">\u8981\u78BA\u8A8D</Badge>`.',
|
|
1228
1297
|
"Inline count or highlight next to a heading or nav item \u2014 e.g. `<Badge variant=\"destructive\">3</Badge>` beside 'Overdue invoices' to draw attention to a non-zero count.",
|
|
1229
1298
|
'Feature flags or experiment variant labels on admin records \u2014 e.g. `<Badge variant="outline">A/B</Badge>` alongside a campaign row to indicate it is in a split test.',
|
|
1230
1299
|
"Read-only metadata chips inside a Descriptions.Item or Card header where a lifecycle icon would be visually heavy \u2014 e.g. currency code, payment method, or region tag."
|
|
@@ -1236,7 +1305,7 @@ import { ResponsiveGrid } from "@godxjp/ui/layout";
|
|
|
1236
1305
|
|
|
1237
1306
|
<Badge variant="secondary">A/B</Badge>
|
|
1238
1307
|
<Badge status="active">\u516C\u958B\u4E2D</Badge>
|
|
1239
|
-
<Badge status="\u30D7\u30EC\u30DF\u30A2\u30E0"
|
|
1308
|
+
<Badge status="\u30D7\u30EC\u30DF\u30A2\u30E0" tone="success" icon={null}>\u30D7\u30EC\u30DF\u30A2\u30E0</Badge>`,
|
|
1240
1309
|
storyPath: "data-display/Badge.stories.tsx",
|
|
1241
1310
|
rules: [35]
|
|
1242
1311
|
},
|
|
@@ -1356,7 +1425,7 @@ import { ResponsiveGrid } from "@godxjp/ui/layout";
|
|
|
1356
1425
|
"DON'T use Progress for editable numeric input or range selection \u2014 it has no callbacks, no interactivity, and no form `name` prop. Use Slider (bounded range input) or Input (free-form number) for data-entry scenarios."
|
|
1357
1426
|
],
|
|
1358
1427
|
useCases: [
|
|
1359
|
-
'Budget utilisation in an accounting dashboard \u2014 show how much of a monthly budget has been consumed, switching to `
|
|
1428
|
+
'Budget utilisation in an accounting dashboard \u2014 show how much of a monthly budget has been consumed, switching to `tone="warning"` when the figure crosses 80%.',
|
|
1360
1429
|
'Invoice payment progress \u2014 display the proportion of an invoice total that has been settled (e.g. partial payments), with a label like `"\xA545,000 / \xA560,000 \u652F\u6255\u6E08"` computed before passing `value`.',
|
|
1361
1430
|
"Storage or quota indicator in an admin panel \u2014 visualise disk usage, API quota, or seat licence consumption against a fixed limit.",
|
|
1362
1431
|
"Sync / import job completion feedback \u2014 surface the completion percentage of a long-running background job (polling the server) without giving the user an interactive control.",
|
|
@@ -1675,7 +1744,7 @@ import { ResponsiveGrid } from "@godxjp/ui/layout";
|
|
|
1675
1744
|
example: `import { FormField, Input } from "@godxjp/ui/data-entry";
|
|
1676
1745
|
|
|
1677
1746
|
<FormField id="coupon-name" label="\u30AF\u30FC\u30DD\u30F3\u540D" required error={errors.name} helper="\u6700\u592750\u6587\u5B57">
|
|
1678
|
-
<Input id="coupon-name" placeholder="\u6625\u306E\u82B1\u7C89\u75C7\u5BFE\u7B5615%OFF" value={name}
|
|
1747
|
+
<Input id="coupon-name" placeholder="\u6625\u306E\u82B1\u7C89\u75C7\u5BFE\u7B5615%OFF" value={name} onValueChange={(e) => setName(e.target.value)} />
|
|
1679
1748
|
</FormField>`,
|
|
1680
1749
|
storyPath: "data-entry/FormField.stories.tsx",
|
|
1681
1750
|
rules: [23]
|
|
@@ -1718,7 +1787,7 @@ import { ResponsiveGrid } from "@godxjp/ui/layout";
|
|
|
1718
1787
|
],
|
|
1719
1788
|
example: `import { Input } from "@godxjp/ui/data-entry";
|
|
1720
1789
|
|
|
1721
|
-
<Input id="qty" type="number" placeholder="\u4F8B: 500" value={value}
|
|
1790
|
+
<Input id="qty" type="number" placeholder="\u4F8B: 500" value={value} onValueChange={(e) => setValue(e.target.value)} />`,
|
|
1722
1791
|
storyPath: "data-entry/Input.stories.tsx",
|
|
1723
1792
|
rules: []
|
|
1724
1793
|
},
|
|
@@ -1916,7 +1985,7 @@ export function StatusSelect({ value, onChange }) {
|
|
|
1916
1985
|
return (
|
|
1917
1986
|
<Select
|
|
1918
1987
|
value={value}
|
|
1919
|
-
|
|
1988
|
+
onValueChange={onChange}
|
|
1920
1989
|
options={[
|
|
1921
1990
|
{ value: "draft", label: "Draft" },
|
|
1922
1991
|
{ value: "sent", label: "Sent" },
|
|
@@ -1935,7 +2004,7 @@ export function CurrencySelect({ value, onChange }) {
|
|
|
1935
2004
|
return (
|
|
1936
2005
|
<Select
|
|
1937
2006
|
value={value}
|
|
1938
|
-
|
|
2007
|
+
onValueChange={onChange}
|
|
1939
2008
|
showSearch
|
|
1940
2009
|
options={[
|
|
1941
2010
|
{ value: "JPY", label: "Japanese Yen", group: "Asia" },
|
|
@@ -1961,7 +2030,7 @@ export function AccountSelect({ value, onChange, selectedLabel }) {
|
|
|
1961
2030
|
return (
|
|
1962
2031
|
<Select
|
|
1963
2032
|
value={value}
|
|
1964
|
-
|
|
2033
|
+
onValueChange={onChange}
|
|
1965
2034
|
loadOptions={loadOptions}
|
|
1966
2035
|
selectedLabel={selectedLabel}
|
|
1967
2036
|
placeholder="Search accounts\u2026"
|
|
@@ -2084,7 +2153,7 @@ export function PrioritySelect({ value, onValueChange }) {
|
|
|
2084
2153
|
],
|
|
2085
2154
|
example: `import { Textarea } from "@godxjp/ui/data-entry";
|
|
2086
2155
|
|
|
2087
|
-
<Textarea id="notes" rows={4} placeholder="\u81EA\u7531\u8A18\u8FF0" value={notes}
|
|
2156
|
+
<Textarea id="notes" rows={4} placeholder="\u81EA\u7531\u8A18\u8FF0" value={notes} onValueChange={(e) => setNotes(e.target.value)} />`,
|
|
2088
2157
|
storyPath: "data-entry/Textarea.stories.tsx",
|
|
2089
2158
|
rules: []
|
|
2090
2159
|
},
|
|
@@ -2320,7 +2389,7 @@ export function InvoiceDueDateField() {
|
|
|
2320
2389
|
id="due-date"
|
|
2321
2390
|
name="due_date"
|
|
2322
2391
|
value={dueDate}
|
|
2323
|
-
|
|
2392
|
+
onValueChange={setDueDate}
|
|
2324
2393
|
fromDate={new Date()}
|
|
2325
2394
|
placeholder="yyyy-mm-dd"
|
|
2326
2395
|
/>
|
|
@@ -2465,7 +2534,7 @@ import { Button } from "@godxjp/ui/general";
|
|
|
2465
2534
|
}
|
|
2466
2535
|
],
|
|
2467
2536
|
usage: [
|
|
2468
|
-
'DO compose with sub-parts in order: wrap text content in `<Alert.Content>` (or bare `<AlertContent>`), then `<Alert.Title>` + `<Alert.Description>` inside it, then `<Alert.Actions>` for any retry/CTA buttons. Example: `<Alert
|
|
2537
|
+
'DO compose with sub-parts in order: wrap text content in `<Alert.Content>` (or bare `<AlertContent>`), then `<Alert.Title>` + `<Alert.Description>` inside it, then `<Alert.Actions>` for any retry/CTA buttons. Example: `<Alert tone="destructive"><Alert.Content><Alert.Title>Error</Alert.Title><Alert.Description>{msg}</Alert.Description></Alert.Content><Alert.Actions><Button \u2026/></Alert.Actions></Alert>`.',
|
|
2469
2538
|
"DO use `Alert.QueryError` (alias `AlertQueryError`) for TanStack Query / API failure surfaces \u2014 it already renders humanError(error), an i18n title, and an optional Retry button. Never hand-roll that pattern.",
|
|
2470
2539
|
'DON\'T pass raw action elements directly as top-level children of `<Alert>` without wrapping them in `<Alert.Actions>` \u2014 the layout slot only activates correctly via the `data-slot="alert-actions"` wrapper.',
|
|
2471
2540
|
'DON\'T hand-roll a dismiss \u2715 button \u2014 pass `onDismiss` to `<Alert>` and the component renders its own accessible dismiss button with `aria-label="Dismiss"`. The `onDismiss` handler may return a Promise.',
|
|
@@ -2473,12 +2542,12 @@ import { Button } from "@godxjp/ui/general";
|
|
|
2473
2542
|
"DO NOT use `Alert` for transient ephemeral feedback (e.g. 'saved successfully'). Use `toast()` from sonner + `<Toaster>` for that. `Alert` is for persistent, page-scoped banners that stay visible until the user acts or dismisses."
|
|
2474
2543
|
],
|
|
2475
2544
|
useCases: [
|
|
2476
|
-
'Page-level error banner after a form submission fails server-side validation \u2014 `
|
|
2545
|
+
'Page-level error banner after a form submission fails server-side validation \u2014 `tone="destructive"` with `Alert.Title` summarising the error and `Alert.Description` listing field issues, paired with `onDismiss` so the user can clear it.',
|
|
2477
2546
|
"Inline warning at the top of an accounting invoice list when the OAuth token for the MF sync is about to expire \u2014 `variant=\"warning\"` with an `Alert.Actions` containing a 'Reconnect' Button.",
|
|
2478
|
-
'Success confirmation banner rendered after a bulk-import job completes and the user returns to the list page \u2014 `
|
|
2547
|
+
'Success confirmation banner rendered after a bulk-import job completes and the user returns to the list page \u2014 `tone="success"` with `Alert.Description` showing the record count imported.',
|
|
2479
2548
|
"TanStack Query data-fetch failure inside a Card body \u2014 use `<Alert.QueryError error={error} onRetry={refetch} />` instead of writing a custom error state.",
|
|
2480
2549
|
"Informational notice at the top of a settings page when a feature is in beta or requires a plan upgrade \u2014 `variant=\"default\"` (Info icon) with a short description and an `Alert.Actions` 'Learn more' link.",
|
|
2481
|
-
'Dismissible billing-overdue notice at the top of the dashboard \u2014 `
|
|
2550
|
+
'Dismissible billing-overdue notice at the top of the dashboard \u2014 `tone="destructive"` with `onDismiss` that sets a session flag so it does not reappear until the next login.'
|
|
2482
2551
|
],
|
|
2483
2552
|
related: [
|
|
2484
2553
|
"Toaster \u2014 use for transient, auto-dismissing feedback ('Record saved', 'Deleted'). Alert is for persistent page-scoped banners; Toaster is for fire-and-forget notifications triggered by toast() from sonner.",
|
|
@@ -2488,7 +2557,7 @@ import { Button } from "@godxjp/ui/general";
|
|
|
2488
2557
|
],
|
|
2489
2558
|
example: `import { Alert, AlertTitle, AlertDescription } from "@godxjp/ui/feedback";
|
|
2490
2559
|
|
|
2491
|
-
<Alert
|
|
2560
|
+
<Alert tone="warning">
|
|
2492
2561
|
<AlertTitle>3 \u4EF6\u306E\u6253\u523B\u6F0F\u308C\u304C\u3042\u308A\u307E\u3059</AlertTitle>
|
|
2493
2562
|
<AlertDescription>\u672C\u65E5\u4E2D\u306B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002</AlertDescription>
|
|
2494
2563
|
</Alert>`,
|
|
@@ -2809,7 +2878,7 @@ import { SearchInput, Select, SelectTrigger, SelectValue, SelectContent, SelectI
|
|
|
2809
2878
|
],
|
|
2810
2879
|
example: `import { Pagination } from "@godxjp/ui/navigation";
|
|
2811
2880
|
|
|
2812
|
-
<Pagination current={page} total={filtered.length} pageSize={10} showTotal
|
|
2881
|
+
<Pagination current={page} total={filtered.length} pageSize={10} showTotal onValueChange={(p) => setPage(p)} />`,
|
|
2813
2882
|
storyPath: "navigation/Pagination.stories.tsx",
|
|
2814
2883
|
rules: [40]
|
|
2815
2884
|
},
|
|
@@ -2855,7 +2924,7 @@ import { Button } from "@godxjp/ui/general";
|
|
|
2855
2924
|
<DropdownMenuContent>
|
|
2856
2925
|
<DropdownMenuItem>\u7DE8\u96C6</DropdownMenuItem>
|
|
2857
2926
|
<DropdownMenuSeparator />
|
|
2858
|
-
<DropdownMenuItem
|
|
2927
|
+
<DropdownMenuItem tone="destructive">\u524A\u9664</DropdownMenuItem>
|
|
2859
2928
|
</DropdownMenuContent>
|
|
2860
2929
|
</DropdownMenu>`,
|
|
2861
2930
|
storyPath: "navigation/DropdownMenu.stories.tsx",
|
|
@@ -3110,7 +3179,7 @@ export function ShiftStartField() {
|
|
|
3110
3179
|
id="shift-start"
|
|
3111
3180
|
name="shift_start"
|
|
3112
3181
|
value={startTime}
|
|
3113
|
-
|
|
3182
|
+
onValueChange={setStartTime}
|
|
3114
3183
|
minuteStep={15}
|
|
3115
3184
|
className="w-36"
|
|
3116
3185
|
/>
|
|
@@ -3230,7 +3299,7 @@ export function InvoicePeriodFilter() {
|
|
|
3230
3299
|
id="invoice-period"
|
|
3231
3300
|
name="period"
|
|
3232
3301
|
value={range}
|
|
3233
|
-
|
|
3302
|
+
onValueChange={setRange}
|
|
3234
3303
|
fromDate={new Date(2020, 0, 1)}
|
|
3235
3304
|
toDate={new Date(2030, 11, 31)}
|
|
3236
3305
|
/>
|
|
@@ -3386,7 +3455,7 @@ function RegionPicker() {
|
|
|
3386
3455
|
<Cascader
|
|
3387
3456
|
options={REGIONS}
|
|
3388
3457
|
value={path}
|
|
3389
|
-
|
|
3458
|
+
onValueChange={(v) => setPath(v as string[])}
|
|
3390
3459
|
showSearch
|
|
3391
3460
|
placeholder="Select region\u2026"
|
|
3392
3461
|
/>
|
|
@@ -3402,7 +3471,7 @@ function MultiRegionPicker() {
|
|
|
3402
3471
|
options={REGIONS}
|
|
3403
3472
|
multiple
|
|
3404
3473
|
value={paths}
|
|
3405
|
-
|
|
3474
|
+
onValueChange={(v) => setPaths(v as string[][])}
|
|
3406
3475
|
showSearch
|
|
3407
3476
|
/>
|
|
3408
3477
|
);
|
|
@@ -3419,7 +3488,7 @@ function MultiRegionPicker() {
|
|
|
3419
3488
|
<Cascader
|
|
3420
3489
|
options={REGIONS}
|
|
3421
3490
|
changeOnSelect
|
|
3422
|
-
|
|
3491
|
+
onValueChange={(v) => console.log("path", v)}
|
|
3423
3492
|
/>
|
|
3424
3493
|
\`}`,
|
|
3425
3494
|
storyPath: "data-entry/Cascader.stories.tsx",
|
|
@@ -3582,7 +3651,7 @@ export function AccountPicker() {
|
|
|
3582
3651
|
id="account-picker"
|
|
3583
3652
|
treeData={accountTree}
|
|
3584
3653
|
value={account}
|
|
3585
|
-
|
|
3654
|
+
onValueChange={(v) => setAccount(v as string | undefined)}
|
|
3586
3655
|
showSearch
|
|
3587
3656
|
treeDefaultExpandAll
|
|
3588
3657
|
placeholder="Select account\u2026"
|
|
@@ -3600,7 +3669,7 @@ export function DepartmentFilter() {
|
|
|
3600
3669
|
id="dept-filter"
|
|
3601
3670
|
treeData={accountTree}
|
|
3602
3671
|
value={selected}
|
|
3603
|
-
|
|
3672
|
+
onValueChange={(v) => setSelected(v as string[])}
|
|
3604
3673
|
treeCheckable
|
|
3605
3674
|
showCheckedStrategy={TreeSelect.SHOW_PARENT}
|
|
3606
3675
|
showSearch
|
|
@@ -3673,7 +3742,7 @@ export function DepartmentFilter() {
|
|
|
3673
3742
|
}
|
|
3674
3743
|
],
|
|
3675
3744
|
usage: [
|
|
3676
|
-
"DO own `targetKeys` in state and update it inside `onChange`: `const [targetKeys, setTargetKeys] = useState<string[]>([]);
|
|
3745
|
+
"DO own `targetKeys` in state and update it inside `onChange`: `const [targetKeys, setTargetKeys] = useState<string[]>([]); onValueChange={(next) => setTargetKeys(next)}`.",
|
|
3677
3746
|
"DO NOT hand-roll a two-panel checkbox picker \u2014 Transfer ships the full shuttle UX (select-all header, indeterminate state, search, move buttons, empty state) out of the box.",
|
|
3678
3747
|
"DO enable `showSearch` for lists longer than ~10 items; the built-in SearchInput filters by both `title` and `description` text content, including ReactNode content via `reactNodeText`.",
|
|
3679
3748
|
"DO use `oneWay={true}` for append-only flows (e.g. adding permissions to a role) where items must never be moved back.",
|
|
@@ -3712,7 +3781,7 @@ export function AccountMapping() {
|
|
|
3712
3781
|
<Transfer
|
|
3713
3782
|
dataSource={ALL_ACCOUNTS}
|
|
3714
3783
|
targetKeys={targetKeys}
|
|
3715
|
-
|
|
3784
|
+
onValueChange={(nextKeys) => setTargetKeys(nextKeys)}
|
|
3716
3785
|
titles={["Available Accounts", "Mapped Accounts"]}
|
|
3717
3786
|
showSearch
|
|
3718
3787
|
/>
|
|
@@ -3842,7 +3911,7 @@ export function AvatarUploadForm() {
|
|
|
3842
3911
|
<Upload
|
|
3843
3912
|
variant="avatar-crop"
|
|
3844
3913
|
value={items}
|
|
3845
|
-
|
|
3914
|
+
onValueChange={setItems}
|
|
3846
3915
|
onUpload={handleUpload}
|
|
3847
3916
|
maxSizeBytes={5 * 1024 * 1024}
|
|
3848
3917
|
/>
|
|
@@ -3859,7 +3928,7 @@ export function DocumentUploadDropzone() {
|
|
|
3859
3928
|
<Upload
|
|
3860
3929
|
variant="dropzone"
|
|
3861
3930
|
value={items}
|
|
3862
|
-
|
|
3931
|
+
onValueChange={setItems}
|
|
3863
3932
|
accept=".pdf,.xlsx"
|
|
3864
3933
|
maxCount={10}
|
|
3865
3934
|
maxSizeBytes={20 * 1024 * 1024}
|
|
@@ -3948,7 +4017,7 @@ export function AvatarField() {
|
|
|
3948
4017
|
|
|
3949
4018
|
return (
|
|
3950
4019
|
<>
|
|
3951
|
-
<input type="file" accept="image/*"
|
|
4020
|
+
<input type="file" accept="image/*" onValueChange={handleFileChange} />
|
|
3952
4021
|
<UploadCropDialog
|
|
3953
4022
|
open={cropFile !== null}
|
|
3954
4023
|
onOpenChange={(open) => { if (!open) setCropFile(null); }}
|
|
@@ -4004,7 +4073,7 @@ export function AvatarField() {
|
|
|
4004
4073
|
}
|
|
4005
4074
|
],
|
|
4006
4075
|
usage: [
|
|
4007
|
-
"DO wrap in FormField when a label or validation message is needed \u2014 pass the same id to both FormField and ColorPicker so htmlFor wires up correctly: `<FormField id='brand' label='Brand color'><ColorPicker id='brand' value={v}
|
|
4076
|
+
"DO wrap in FormField when a label or validation message is needed \u2014 pass the same id to both FormField and ColorPicker so htmlFor wires up correctly: `<FormField id='brand' label='Brand color'><ColorPicker id='brand' value={v} onValueChange={setV} /></FormField>`.",
|
|
4008
4077
|
"DO use controlled mode (value + onChange) \u2014 there is no defaultValue/uncontrolled path; always supply value.",
|
|
4009
4078
|
"DON'T pass an invalid or empty string to value \u2014 the component will flash the invalid color on the preview swatch. Always initialize state to a valid 3- or 6-digit hex (e.g. '#2563eb').",
|
|
4010
4079
|
"The hex Input is a live draft field \u2014 onChange is NOT called until the user presses Enter or blurs; only then is the value validated and the parent notified. Do not rely on onChange firing on every keystroke.",
|
|
@@ -4034,7 +4103,7 @@ export function BrandColorField() {
|
|
|
4034
4103
|
<ColorPicker
|
|
4035
4104
|
id="brand-color"
|
|
4036
4105
|
value={color}
|
|
4037
|
-
|
|
4106
|
+
onValueChange={setColor}
|
|
4038
4107
|
/>
|
|
4039
4108
|
</FormField>
|
|
4040
4109
|
);
|
|
@@ -4043,7 +4112,7 @@ export function BrandColorField() {
|
|
|
4043
4112
|
// Compact swatch-only variant (no hex input)
|
|
4044
4113
|
export function SwatchOnly() {
|
|
4045
4114
|
const [color, setColor] = useState("#16a34a");
|
|
4046
|
-
return <ColorPicker value={color}
|
|
4115
|
+
return <ColorPicker value={color} onValueChange={setColor} showHexInput={false} />;
|
|
4047
4116
|
}
|
|
4048
4117
|
|
|
4049
4118
|
// Disabled state
|
|
@@ -4976,7 +5045,7 @@ export function ControlledExample() {
|
|
|
4976
5045
|
name="permissions"
|
|
4977
5046
|
options={PERMISSIONS}
|
|
4978
5047
|
value={selected}
|
|
4979
|
-
|
|
5048
|
+
onValueChange={setSelected}
|
|
4980
5049
|
/>
|
|
4981
5050
|
);
|
|
4982
5051
|
}`,
|
|
@@ -5213,7 +5282,7 @@ function LegacyAccountPicker({ value, onChange }) {
|
|
|
5213
5282
|
return (
|
|
5214
5283
|
<SearchSelect
|
|
5215
5284
|
value={value}
|
|
5216
|
-
|
|
5285
|
+
onValueChange={onChange}
|
|
5217
5286
|
options={[
|
|
5218
5287
|
{ value: "acc-001", label: "Cash", sublabel: "Current assets", group: "Assets" },
|
|
5219
5288
|
{ value: "acc-002", label: "Accounts Receivable", group: "Assets" },
|
|
@@ -5237,7 +5306,7 @@ function LegacyVendorPicker({ value, currentVendorName, onChange }) {
|
|
|
5237
5306
|
return (
|
|
5238
5307
|
<SearchSelect
|
|
5239
5308
|
value={value}
|
|
5240
|
-
|
|
5309
|
+
onValueChange={onChange}
|
|
5241
5310
|
loadOptions={fetchVendors}
|
|
5242
5311
|
selectedLabel={currentVendorName}
|
|
5243
5312
|
placeholder="Select vendor"
|
|
@@ -5326,7 +5395,7 @@ import { Autocomplete } from "@godxjp/ui/data-entry";
|
|
|
5326
5395
|
|
|
5327
5396
|
// \u2705 Replace with:
|
|
5328
5397
|
// import { Select } from "@godxjp/ui/data-entry";
|
|
5329
|
-
// <Select options={options} showSearch placeholder="Search\u2026"
|
|
5398
|
+
// <Select options={options} showSearch placeholder="Search\u2026" onValueChange={setValue} value={value} />
|
|
5330
5399
|
|
|
5331
5400
|
// Legacy usage (backward compat only):
|
|
5332
5401
|
import { Autocomplete } from "@godxjp/ui/data-entry";
|
|
@@ -5840,10 +5909,10 @@ export function LegacyInvoiceHeader() {
|
|
|
5840
5909
|
],
|
|
5841
5910
|
useCases: [
|
|
5842
5911
|
"App shell / top-nav language switcher that persists the user's locale preference via AppProvider and localStorage without any extra state.",
|
|
5843
|
-
"Settings page 'Language' field where locale is part of a form submitted to the backend \u2014 use controlled mode: value={form.locale}
|
|
5912
|
+
"Settings page 'Language' field where locale is part of a form submitted to the backend \u2014 use controlled mode: value={form.locale} onValueChange={(v) => form.setLocale(v)}.",
|
|
5844
5913
|
"Onboarding wizard step that lets the user pick their language before the rest of the app is configured \u2014 mount with AppProvider persist={false} and a controlled value to keep state local to the wizard.",
|
|
5845
5914
|
"Admin user-profile form where locale is one of several preferences (alongside timezone and date/time format) \u2014 pair with TimezonePicker, DateFormatPicker, TimeFormatPicker under the same AppProvider.",
|
|
5846
|
-
"Storybook / test harness where AppProvider is not present \u2014 render in fully controlled mode: <LocalePicker value='en'
|
|
5915
|
+
"Storybook / test harness where AppProvider is not present \u2014 render in fully controlled mode: <LocalePicker value='en' onValueChange={fn} />.",
|
|
5847
5916
|
"Localization QA tool that cycles through locales programmatically \u2014 drive via controlled value to switch the UI language without user interaction."
|
|
5848
5917
|
],
|
|
5849
5918
|
related: [
|
|
@@ -5875,7 +5944,7 @@ export function LocaleField() {
|
|
|
5875
5944
|
return (
|
|
5876
5945
|
<div className="flex flex-col gap-1.5">
|
|
5877
5946
|
<label htmlFor="locale-picker">Language</label>
|
|
5878
|
-
<LocalePicker id="locale-picker" value={locale}
|
|
5947
|
+
<LocalePicker id="locale-picker" value={locale} onValueChange={setLocale} />
|
|
5879
5948
|
</div>
|
|
5880
5949
|
);
|
|
5881
5950
|
}\`}`,
|
|
@@ -5916,7 +5985,7 @@ export function LocaleField() {
|
|
|
5916
5985
|
],
|
|
5917
5986
|
usage: [
|
|
5918
5987
|
"DO: Wrap with <AppProvider> and omit value/onChange \u2014 the picker reads and writes context automatically. This is the canonical zero-prop usage: <TimezonePicker />.",
|
|
5919
|
-
"DO: Pass value + onChange for fully controlled standalone usage (e.g. a form field that posts the timezone string): <TimezonePicker value={tz}
|
|
5988
|
+
"DO: Pass value + onChange for fully controlled standalone usage (e.g. a form field that posts the timezone string): <TimezonePicker value={tz} onValueChange={setTz} />. AppProvider is not required in this mode.",
|
|
5920
5989
|
"DON'T: Omit BOTH AppProvider context AND controlled props \u2014 the component throws at runtime: 'TimezonePicker requires <AppProvider> or controlled value + onChange'.",
|
|
5921
5990
|
"DO: Pass options={['Asia/Tokyo', 'UTC']} to restrict the list. The current value is automatically prepended if it is missing from the list, so the picker never shows an empty/invalid selection.",
|
|
5922
5991
|
"DON'T: Hand-roll a timezone <select> or a custom combobox \u2014 TimezonePicker already handles locale-aware labels (translated city + GMT offset), the full IANA list, and ARIA semantics.",
|
|
@@ -5945,7 +6014,7 @@ export function TimezoneField() {
|
|
|
5945
6014
|
return (
|
|
5946
6015
|
<TimezonePicker
|
|
5947
6016
|
value={tz}
|
|
5948
|
-
|
|
6017
|
+
onValueChange={setTz}
|
|
5949
6018
|
options={["Asia/Tokyo", "Asia/Ho_Chi_Minh", "UTC"]}
|
|
5950
6019
|
/>
|
|
5951
6020
|
);
|
|
@@ -6053,7 +6122,7 @@ export function ExportDialog() {
|
|
|
6053
6122
|
return (
|
|
6054
6123
|
<div className="flex items-center gap-2">
|
|
6055
6124
|
<label htmlFor="export-fmt">Export date format</label>
|
|
6056
|
-
<DateFormatPicker id="export-fmt" value={fmt}
|
|
6125
|
+
<DateFormatPicker id="export-fmt" value={fmt} onValueChange={setFmt} />
|
|
6057
6126
|
</div>
|
|
6058
6127
|
);
|
|
6059
6128
|
}\`}`,
|
|
@@ -6093,7 +6162,7 @@ export function ExportDialog() {
|
|
|
6093
6162
|
],
|
|
6094
6163
|
usage: [
|
|
6095
6164
|
"DO use inside <AppProvider> with no extra props to let it read/write the global time-format automatically: <AppProvider defaultTimeFormat='24h'><TimeFormatPicker /></AppProvider>",
|
|
6096
|
-
"DO switch to fully controlled mode when you need to manage the value yourself \u2014 supply BOTH value and onChange, or the component will throw: <TimeFormatPicker value={fmt}
|
|
6165
|
+
"DO switch to fully controlled mode when you need to manage the value yourself \u2014 supply BOTH value and onChange, or the component will throw: <TimeFormatPicker value={fmt} onValueChange={setFmt} />",
|
|
6097
6166
|
"DON'T omit both AppProvider and controlled props \u2014 the component throws an Error at render time: 'TimeFormatPicker requires <AppProvider> or controlled value + onChange'. There is no silent fallback.",
|
|
6098
6167
|
"DON'T hand-roll a time-format <select> \u2014 the locale-aware labels (e.g. '24 gi\u1EDD' for vi, '24-hour' for en) are generated internally from the i18n layer; reinventing this loses those translations.",
|
|
6099
6168
|
"DO wire a <label htmlFor={id}> when using the id prop for accessibility; the SelectTrigger already sets aria-label from i18n but a visible label improves discoverability.",
|
|
@@ -6136,7 +6205,7 @@ export function SettingsForm() {
|
|
|
6136
6205
|
return (
|
|
6137
6206
|
<div>
|
|
6138
6207
|
<label htmlFor="time-fmt">Time format</label>
|
|
6139
|
-
<TimeFormatPicker id="time-fmt" value={fmt}
|
|
6208
|
+
<TimeFormatPicker id="time-fmt" value={fmt} onValueChange={setFmt} />
|
|
6140
6209
|
</div>
|
|
6141
6210
|
);
|
|
6142
6211
|
}\`}
|
|
@@ -6568,194 +6637,85 @@ function componentsByGroup(group) {
|
|
|
6568
6637
|
// src/data/prop-vocabulary.ts
|
|
6569
6638
|
var PROP_VOCABULARY = [
|
|
6570
6639
|
{
|
|
6571
|
-
name: "
|
|
6572
|
-
concept: "
|
|
6573
|
-
values: ["
|
|
6574
|
-
usedBy: [
|
|
6575
|
-
"InputSize",
|
|
6576
|
-
"CheckboxGroupSize",
|
|
6577
|
-
"ColorPickerSize",
|
|
6578
|
-
"MediaUploadSize",
|
|
6579
|
-
"ProgressSize",
|
|
6580
|
-
"RadioGroupSize",
|
|
6581
|
-
"RateSize",
|
|
6582
|
-
"TransferSize",
|
|
6583
|
-
"SegmentedControlSize (subset)",
|
|
6584
|
-
"SpaceSize (+ number)",
|
|
6585
|
-
"FlexGap (+ number)",
|
|
6586
|
-
"GridGap (+ number)",
|
|
6587
|
-
"MasonryGap (+ number)"
|
|
6588
|
-
]
|
|
6589
|
-
},
|
|
6590
|
-
{
|
|
6591
|
-
name: "SizeWithXSProp",
|
|
6592
|
-
concept: 'Extension of `SizeProp` with `"x-small"` for compact icon-bar / table-row contexts.',
|
|
6593
|
-
values: ["x-small", "small", "default", "large"],
|
|
6594
|
-
usedBy: ["ButtonSize"]
|
|
6640
|
+
name: "ValueProp<T = string>",
|
|
6641
|
+
concept: "Abstract controlled value.",
|
|
6642
|
+
values: ["generic"],
|
|
6643
|
+
usedBy: ["CheckboxGroup", "Upload", "Cascader", "TreeSelect", "Tabs", "SearchSelect"]
|
|
6595
6644
|
},
|
|
6596
6645
|
{
|
|
6597
|
-
name: "
|
|
6598
|
-
concept: "
|
|
6599
|
-
values: ["
|
|
6600
|
-
usedBy: ["
|
|
6646
|
+
name: "DefaultValueProp<T = string>",
|
|
6647
|
+
concept: "Abstract uncontrolled initial value.",
|
|
6648
|
+
values: ["generic"],
|
|
6649
|
+
usedBy: ["CheckboxGroup", "Upload", "Cascader", "TreeSelect", "Tabs"]
|
|
6601
6650
|
},
|
|
6602
6651
|
{
|
|
6603
|
-
name: "
|
|
6604
|
-
concept: "
|
|
6605
|
-
values: ["
|
|
6606
|
-
usedBy: ["
|
|
6607
|
-
notes: 'Form errors use `"error"` (not `"destructive"`) \u2014 different concern from destructive actions.'
|
|
6652
|
+
name: "OnValueChangeProp<T = string>",
|
|
6653
|
+
concept: "Callback for abstract value changes. DOM events continue to use onChange.",
|
|
6654
|
+
values: ["(value: T) => void"],
|
|
6655
|
+
usedBy: ["CheckboxGroup", "Upload", "Cascader", "TreeSelect", "Transfer", "settings pickers"]
|
|
6608
6656
|
},
|
|
6609
6657
|
{
|
|
6610
|
-
name: "
|
|
6611
|
-
concept: "
|
|
6612
|
-
values: ["
|
|
6613
|
-
usedBy: ["
|
|
6614
|
-
},
|
|
6615
|
-
{
|
|
6616
|
-
name: "HelpToneProp",
|
|
6617
|
-
concept: "Help-line / Alert colour ladder. Adds `info` + `warn` to StatusProp.",
|
|
6618
|
-
values: ["default", "info", "warn", "error", "success"],
|
|
6619
|
-
usedBy: ["FieldHelpTone"]
|
|
6620
|
-
},
|
|
6621
|
-
{
|
|
6622
|
-
name: "OrientationProp",
|
|
6623
|
-
concept: "Layout axis.",
|
|
6624
|
-
values: ["horizontal", "vertical"],
|
|
6625
|
-
usedBy: [
|
|
6626
|
-
"AnchorOrientation",
|
|
6627
|
-
"MenuOrientation",
|
|
6628
|
-
"RadioGroupOrientation",
|
|
6629
|
-
"CheckboxGroupOrientation",
|
|
6630
|
-
"SegmentedControlOrientation",
|
|
6631
|
-
"StepsOrientation",
|
|
6632
|
-
"TabsOrientation"
|
|
6633
|
-
]
|
|
6658
|
+
name: "OpenProp / DefaultOpenProp / OnOpenChangeProp",
|
|
6659
|
+
concept: "Disclosure state.",
|
|
6660
|
+
values: ["boolean", "(open: boolean) => void"],
|
|
6661
|
+
usedBy: ["Dialog", "Sheet", "Popover"]
|
|
6634
6662
|
},
|
|
6635
6663
|
{
|
|
6636
|
-
name: "
|
|
6637
|
-
concept: "
|
|
6638
|
-
values: ["
|
|
6639
|
-
usedBy: ["
|
|
6640
|
-
|
|
6641
|
-
{
|
|
6642
|
-
name: "SideProp",
|
|
6643
|
-
concept: "Edge a floating panel docks against.",
|
|
6644
|
-
values: ["top", "right", "bottom", "left"],
|
|
6645
|
-
usedBy: ["SheetSide", "TabsPlacement", "TableStickySide (subset)"]
|
|
6646
|
-
},
|
|
6647
|
-
{
|
|
6648
|
-
name: "PlacementProp",
|
|
6649
|
-
concept: "Extension of SideProp with a centred anchor (Tabs placement, Tour spotlight).",
|
|
6650
|
-
values: ["top", "right", "bottom", "left", "center"],
|
|
6651
|
-
usedBy: ["TourPlacement"]
|
|
6652
|
-
},
|
|
6653
|
-
{
|
|
6654
|
-
name: "PaddingProp",
|
|
6655
|
-
concept: "Outer gutter scale for surface containers.",
|
|
6656
|
-
values: ["tight", "default", "cozy", "none"],
|
|
6657
|
-
usedBy: ["CardPadding", "PageHeaderPadding", "PageContentPadding"]
|
|
6664
|
+
name: "SizeProp",
|
|
6665
|
+
concept: "Shared public size names.",
|
|
6666
|
+
values: ["xs", "sm", "md", "lg"],
|
|
6667
|
+
usedBy: ["Button", "Steps", "Switch"],
|
|
6668
|
+
notes: "Component-specific subsets must be documented. Old alias small is sm."
|
|
6658
6669
|
},
|
|
6659
6670
|
{
|
|
6660
|
-
name: "
|
|
6661
|
-
concept: "
|
|
6662
|
-
values: ["
|
|
6663
|
-
usedBy: ["
|
|
6671
|
+
name: "ToneProp",
|
|
6672
|
+
concept: "Semantic status/color intent.",
|
|
6673
|
+
values: ["default", "success", "warning", "destructive", "info", "muted", "neutral"],
|
|
6674
|
+
usedBy: ["Badge", "Alert"],
|
|
6675
|
+
notes: "Status values belong in tone, not variant."
|
|
6664
6676
|
},
|
|
6665
6677
|
{
|
|
6666
|
-
name: "
|
|
6667
|
-
concept: "
|
|
6668
|
-
values: ["
|
|
6669
|
-
usedBy: ["
|
|
6670
|
-
notes: "
|
|
6678
|
+
name: "GapProp",
|
|
6679
|
+
concept: "Shared layout gap scale.",
|
|
6680
|
+
values: ["xs", "sm", "md", "lg", "xl"],
|
|
6681
|
+
usedBy: ["Stack", "Inline"],
|
|
6682
|
+
notes: "Inline uses an Exclude<GapProp, 'xl'> subset."
|
|
6671
6683
|
},
|
|
6672
6684
|
{
|
|
6673
|
-
name: "
|
|
6674
|
-
concept: "
|
|
6675
|
-
values: ["
|
|
6676
|
-
usedBy: ["
|
|
6685
|
+
name: "TitleProp",
|
|
6686
|
+
concept: "Primary heading text.",
|
|
6687
|
+
values: ["React.ReactNode"],
|
|
6688
|
+
usedBy: ["PageContainer", "PageHeader", "EmptyState", "Dialog"]
|
|
6677
6689
|
},
|
|
6678
6690
|
{
|
|
6679
|
-
name: "
|
|
6680
|
-
concept: "
|
|
6681
|
-
values: ["
|
|
6682
|
-
usedBy: ["
|
|
6683
|
-
notes: 'Cascade: `<Form loading>` sets a default for every nested `<FormField>`. Per-field `loading` overrides Form\'s. `true` \u2192 spinner (default). `{ kind: "skeleton" }` \u2192 use for INITIAL fetch state. UX nuance: skeleton on init, spinner on save.'
|
|
6691
|
+
name: "DensityProp",
|
|
6692
|
+
concept: "Page/subtree density.",
|
|
6693
|
+
values: ["compact", "default", "comfortable"],
|
|
6694
|
+
usedBy: ["PageContainer"]
|
|
6684
6695
|
}
|
|
6685
6696
|
];
|
|
6686
6697
|
function findVocab(name) {
|
|
6687
|
-
const normalized = name.trim().toLowerCase().replace(/prop
|
|
6688
|
-
return PROP_VOCABULARY.find(
|
|
6689
|
-
(v) => v.name.toLowerCase().replace(/prop$/i, "") === normalized
|
|
6690
|
-
);
|
|
6698
|
+
const normalized = name.trim().toLowerCase().replace(/prop(?:<.*>)?$/i, "");
|
|
6699
|
+
return PROP_VOCABULARY.find((v) => v.name.toLowerCase().replace(/prop(?:<.*>)?$/i, "") === normalized);
|
|
6691
6700
|
}
|
|
6692
6701
|
|
|
6693
6702
|
// src/data/tokens.ts
|
|
6694
6703
|
var TOKENS = [
|
|
6695
|
-
|
|
6696
|
-
{ name: "--
|
|
6697
|
-
{ name: "--
|
|
6698
|
-
{ name: "--
|
|
6699
|
-
{ name: "--
|
|
6700
|
-
{ name: "--
|
|
6701
|
-
{ name: "--
|
|
6702
|
-
{ name: "--
|
|
6703
|
-
{ name: "--
|
|
6704
|
-
{ name: "--
|
|
6705
|
-
{ name: "--
|
|
6706
|
-
{ name: "--
|
|
6707
|
-
{ name: "--
|
|
6708
|
-
{ name: "--
|
|
6709
|
-
{ name: "--
|
|
6710
|
-
{ name: "--success", category: "color", role: "Success semantic slot" },
|
|
6711
|
-
{ name: "--warning", category: "color", role: "Warning semantic slot" },
|
|
6712
|
-
{ name: "--destructive", category: "color", role: "Danger / destructive action slot" },
|
|
6713
|
-
{ name: "--info", category: "color", role: "Info / neutral notice slot" },
|
|
6714
|
-
{ name: "--attention", category: "color", role: "Attention / non-destructive alert slot" },
|
|
6715
|
-
// Spacing — fixed scale
|
|
6716
|
-
{ name: "--spacing-1", category: "spacing", role: "4px", value: "0.25rem" },
|
|
6717
|
-
{ name: "--spacing-2", category: "spacing", role: "8px", value: "0.5rem" },
|
|
6718
|
-
{ name: "--spacing-3", category: "spacing", role: "12px", value: "0.75rem" },
|
|
6719
|
-
{ name: "--spacing-4", category: "spacing", role: "16px", value: "1rem" },
|
|
6720
|
-
{ name: "--spacing-5", category: "spacing", role: "20px", value: "1.25rem" },
|
|
6721
|
-
{ name: "--spacing-6", category: "spacing", role: "24px", value: "1.5rem" },
|
|
6722
|
-
{ name: "--spacing-8", category: "spacing", role: "32px", value: "2rem" },
|
|
6723
|
-
// Typography — fixed scale
|
|
6724
|
-
{ name: "--text-2xs", category: "typography", role: "10px", value: "0.625rem" },
|
|
6725
|
-
{ name: "--text-xs", category: "typography", role: "12px", value: "0.75rem" },
|
|
6726
|
-
{ name: "--text-sm", category: "typography", role: "14px", value: "0.875rem" },
|
|
6727
|
-
{ name: "--text-base", category: "typography", role: "16px", value: "1rem" },
|
|
6728
|
-
{ name: "--text-lg", category: "typography", role: "18px", value: "1.125rem" },
|
|
6729
|
-
{ name: "--text-xl", category: "typography", role: "20px", value: "1.25rem" },
|
|
6730
|
-
{ name: "--text-2xl", category: "typography", role: "24px", value: "1.5rem" },
|
|
6731
|
-
{ name: "--font-mono", category: "typography", role: "Monospace stack" },
|
|
6732
|
-
// Radius — fixed scale
|
|
6733
|
-
{ name: "--radius-sm", category: "radius", role: "Small (chips, inputs)", value: "0.25rem" },
|
|
6734
|
-
{ name: "--radius-md", category: "radius", role: "Medium (cards)", value: "0.5rem" },
|
|
6735
|
-
{ name: "--radius-lg", category: "radius", role: "Large (dialogs)", value: "0.75rem" },
|
|
6736
|
-
{ name: "--radius-full", category: "radius", role: "Pill / circle", value: "9999px" },
|
|
6737
|
-
// Breakpoints — mobile-first min-widths
|
|
6738
|
-
{ name: "--breakpoint-xs", category: "breakpoint", role: "Mobile-first base (\u22650px)", value: "0" },
|
|
6739
|
-
{ name: "--breakpoint-sm", category: "breakpoint", role: "Phone landscape / tablet portrait", value: "640px" },
|
|
6740
|
-
{ name: "--breakpoint-md", category: "breakpoint", role: "Tablet landscape", value: "768px" },
|
|
6741
|
-
{ name: "--breakpoint-lg", category: "breakpoint", role: "Laptop", value: "1024px" },
|
|
6742
|
-
{ name: "--breakpoint-xl", category: "breakpoint", role: "Desktop", value: "1280px" },
|
|
6743
|
-
{ name: "--breakpoint-xxl", category: "breakpoint", role: "Wide desktop", value: "1536px" },
|
|
6744
|
-
// Density — rebound by `data-density`
|
|
6745
|
-
{ name: "--density-element", category: "density", role: "Element height (Input/Button)", axis: "data-density" },
|
|
6746
|
-
{ name: "--density-element-sm", category: "density", role: "Small element", axis: "data-density" },
|
|
6747
|
-
{ name: "--density-element-lg", category: "density", role: "Large element", axis: "data-density" },
|
|
6748
|
-
{ name: "--density-card", category: "density", role: "Card padding", axis: "data-density" },
|
|
6749
|
-
{ name: "--density-page", category: "density", role: "Page (PageContent) padding", axis: "data-density" },
|
|
6750
|
-
{ name: "--density-section", category: "density", role: "Section padding (cozy variant)", axis: "data-density" },
|
|
6751
|
-
{ name: "--header-height", category: "density", role: "Topbar height", axis: "data-density" },
|
|
6752
|
-
{ name: "--sidebar-width", category: "density", role: "Sidebar width (expanded)", axis: "data-density" },
|
|
6753
|
-
{ name: "--sidebar-width-collapsed", category: "density", role: "Sidebar icon-only width", axis: "data-density" },
|
|
6754
|
-
{ name: "--touch-target-min", category: "density", role: "Mobile touch target (does NOT scale)", value: "44px" },
|
|
6755
|
-
// Motion — fixed timings
|
|
6756
|
-
{ name: "--transition-base", category: "motion", role: "Standard transition duration", value: "200ms" },
|
|
6757
|
-
{ name: "--ease-out", category: "motion", role: "Out easing curve", value: "cubic-bezier(0, 0, 0.2, 1)" },
|
|
6758
|
-
{ name: "--ease-in-out", category: "motion", role: "In-out easing", value: "cubic-bezier(0.4, 0, 0.2, 1)" }
|
|
6704
|
+
{ name: "--wa-*", category: "primitive", tier: "primitive", role: "Neutral decorative Japanese accent primitives for charts/tags/decoration only." },
|
|
6705
|
+
{ name: "--chart-1..6", category: "primitive", tier: "primitive", role: "Neutral decorative chart primitives; @theme chart colors reference these tokens." },
|
|
6706
|
+
{ name: "--space-0..12", category: "primitive", tier: "primitive", role: "Raw spacing scale." },
|
|
6707
|
+
{ name: "--font-size-*", category: "primitive", tier: "primitive", role: "Raw typography scale." },
|
|
6708
|
+
{ name: "--primary", category: "semantic", tier: "semantic", role: "Brand/action color role." },
|
|
6709
|
+
{ name: "--success", category: "semantic", tier: "semantic", role: "Success status role." },
|
|
6710
|
+
{ name: "--warning", category: "semantic", tier: "semantic", role: "Warning status role." },
|
|
6711
|
+
{ name: "--destructive", category: "semantic", tier: "semantic", role: "Destructive/error status role." },
|
|
6712
|
+
{ name: "--info", category: "semantic", tier: "semantic", role: "Information status role." },
|
|
6713
|
+
{ name: "--attention", category: "semantic", tier: "semantic", role: "Attention status role." },
|
|
6714
|
+
{ name: "--badge-space-*", category: "component", tier: "component", role: "Badge spacing." },
|
|
6715
|
+
{ name: "--card-*", category: "component", tier: "component", role: "Card surface, border, spacing, and typography." },
|
|
6716
|
+
{ name: "--control-*", category: "component", tier: "component", role: "Shared form control heights, padding, icons, and focus chrome." },
|
|
6717
|
+
{ name: "--table-*", category: "component", tier: "component", role: "Table row/cell sizing." },
|
|
6718
|
+
{ name: "--dialog-* / --alert-* / --skeleton-*", category: "component", tier: "component", role: "Feedback component sizing and spacing." }
|
|
6759
6719
|
];
|
|
6760
6720
|
function tokensByCategory(category) {
|
|
6761
6721
|
return TOKENS.filter((t) => t.category === category);
|
|
@@ -6839,7 +6799,7 @@ var PATTERNS = [
|
|
|
6839
6799
|
// 2) Badge renders grey with a \u25CB (no colour) for localized/tier labels
|
|
6840
6800
|
// Cause: it auto-maps only English lifecycle keys. (@godxjp/ui >= 6.1)
|
|
6841
6801
|
// \u274C <Badge status="\u30D7\u30EC\u30DF\u30A2\u30E0" />
|
|
6842
|
-
// \u2705 <Badge status="\u30D7\u30EC\u30DF\u30A2\u30E0"
|
|
6802
|
+
// \u2705 <Badge status="\u30D7\u30EC\u30DF\u30A2\u30E0" tone="success" icon={null} /> // tier \u2192 pill, no icon
|
|
6843
6803
|
// \u2705 <Badge status="active">\u516C\u958B\u4E2D</Badge> // lifecycle \u2192 keep icon
|
|
6844
6804
|
|
|
6845
6805
|
// 3) Table text collapses to one char per line, or a chip wraps
|
|
@@ -6990,11 +6950,11 @@ export function DeleteProjectDialog({ open, onOpenChange, slug }: { open: boolea
|
|
|
6990
6950
|
<DialogDescription>\u3053\u306E\u64CD\u4F5C\u306F\u53D6\u308A\u6D88\u305B\u307E\u305B\u3093\u3002\u78BA\u8A8D\u306E\u305F\u3081\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D "{slug}" \u3068\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002</DialogDescription>
|
|
6991
6951
|
</DialogHeader>
|
|
6992
6952
|
<Stack gap="md">
|
|
6993
|
-
<Input value={confirm}
|
|
6953
|
+
<Input value={confirm} onValueChange={(e) => setConfirm(e.target.value)} placeholder={slug} />
|
|
6994
6954
|
</Stack>
|
|
6995
6955
|
<DialogFooter>
|
|
6996
6956
|
<Button variant="outline" onClick={() => onOpenChange(false)}>\u30AD\u30E3\u30F3\u30BB\u30EB</Button>
|
|
6997
|
-
<Button
|
|
6957
|
+
<Button tone="destructive" disabled={confirm !== slug} onClick={() => { toast.success("\u524A\u9664\u3057\u307E\u3057\u305F"); onOpenChange(false); }}>\u5B8C\u5168\u306B\u524A\u9664</Button>
|
|
6998
6958
|
</DialogFooter>
|
|
6999
6959
|
</DialogContent>
|
|
7000
6960
|
</Dialog>
|
|
@@ -7060,7 +7020,7 @@ function Coupons({ coupons }: { coupons: Coupon[] }) {
|
|
|
7060
7020
|
// ColumnDef = { key, header, render?, align?: "left"|"center"|"right", sortable?, width? }
|
|
7061
7021
|
const columns: ColumnDef<Coupon>[] = [
|
|
7062
7022
|
{ key: "name", header: "\u30AF\u30FC\u30DD\u30F3\u540D", render: (c) => <span className="font-medium">{c.name}</span> },
|
|
7063
|
-
{ key: "scope", header: "\u30B9\u30B3\u30FC\u30D7", render: (c) => <Badge status={c.scope}
|
|
7023
|
+
{ key: "scope", header: "\u30B9\u30B3\u30FC\u30D7", render: (c) => <Badge status={c.scope} tone="info" icon={null} /> },
|
|
7064
7024
|
{ key: "status", header: "\u30B9\u30C6\u30FC\u30BF\u30B9", render: (c) => <Badge status={c.status} /> },
|
|
7065
7025
|
{ key: "valid", header: "\u6709\u52B9\u671F\u9593", render: (c) => \`\${formatDate(c.validFrom)} \u301C \${formatDate(c.validTo)}\` },
|
|
7066
7026
|
{ key: "usage", header: "\u5229\u7528\u6570", align: "right", render: (c) => c.usage.toLocaleString() },
|
|
@@ -7102,7 +7062,7 @@ function Coupons({ coupons }: { coupons: Coupon[] }) {
|
|
|
7102
7062
|
</Card>
|
|
7103
7063
|
|
|
7104
7064
|
{filtered.length > PAGE_SIZE && (
|
|
7105
|
-
<Pagination current={page} total={filtered.length} pageSize={PAGE_SIZE} showTotal
|
|
7065
|
+
<Pagination current={page} total={filtered.length} pageSize={PAGE_SIZE} showTotal onValueChange={(p) => setPage(p)} />
|
|
7106
7066
|
)}
|
|
7107
7067
|
</Stack>
|
|
7108
7068
|
</PageContainer>
|
|
@@ -7158,7 +7118,7 @@ function MemberShow({ id }: { id: string }) {
|
|
|
7158
7118
|
{/* Descriptions is COMPOUND \u2014 value goes in children, not a prop */}
|
|
7159
7119
|
<Descriptions columns={2}>
|
|
7160
7120
|
<Descriptions.Item label="\u6C0F\u540D">{member.name}</Descriptions.Item>
|
|
7161
|
-
<Descriptions.Item label="\u30E9\u30F3\u30AF"><Badge status={member.rank}
|
|
7121
|
+
<Descriptions.Item label="\u30E9\u30F3\u30AF"><Badge status={member.rank} tone="info" icon={null} /></Descriptions.Item>
|
|
7162
7122
|
<Descriptions.Item label="\u30B9\u30C6\u30FC\u30BF\u30B9"><Badge status={member.status} /></Descriptions.Item>
|
|
7163
7123
|
<Descriptions.Item label="\u767B\u9332\u65E5">{formatDate(member.registeredAt)}</Descriptions.Item>
|
|
7164
7124
|
</Descriptions>
|
|
@@ -7221,12 +7181,12 @@ const seeded = (n: number) => { const x = Math.sin((n + 1) * 99.71) * 1e4; retur
|
|
|
7221
7181
|
<Badge status="active">\u516C\u958B\u4E2D</Badge> // green \u2713 \u516C\u958B\u4E2D
|
|
7222
7182
|
|
|
7223
7183
|
// 2) Unknown label \u2014 set tone explicitly (no icon, since the key is unknown):
|
|
7224
|
-
<Badge status="\u516C\u958B\u4E2D"
|
|
7184
|
+
<Badge status="\u516C\u958B\u4E2D" tone="success" />
|
|
7225
7185
|
|
|
7226
7186
|
// 3) Tier / category \u2014 coloured pill, drop the misleading glyph with icon={null}:
|
|
7227
|
-
<Badge status="\u30D7\u30EC\u30DF\u30A2\u30E0"
|
|
7228
|
-
<Badge status="\u30B4\u30FC\u30EB\u30C9"
|
|
7229
|
-
<Badge status="\u6CD5\u4EBA\u5171\u901A"
|
|
7187
|
+
<Badge status="\u30D7\u30EC\u30DF\u30A2\u30E0" tone="success" icon={null} />
|
|
7188
|
+
<Badge status="\u30B4\u30FC\u30EB\u30C9" tone="warning" icon={null} />
|
|
7189
|
+
<Badge status="\u6CD5\u4EBA\u5171\u901A" tone="info" icon={null} />
|
|
7230
7190
|
|
|
7231
7191
|
// tone: "success" | "warning" | "destructive" | "info" | "neutral" (import type BadgeTone)
|
|
7232
7192
|
// RULE: a chip never wraps \u2014 it is pinned white-space: nowrap, so it stays one line in
|