@godxjp/ui 19.6.0 → 20.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -2
- package/dist/app/theme-axes.d.ts +2 -0
- package/dist/app/theme-axes.js +45 -0
- package/dist/components/charts/chart-cartesian.d.ts +2 -1
- package/dist/components/charts/chart-cartesian.js +52 -3
- package/dist/components/charts/chart-category-axis.d.ts +55 -0
- package/dist/components/charts/chart-category-axis.js +93 -0
- package/dist/components/charts/chart-frame.d.ts +10 -1
- package/dist/components/charts/chart-frame.js +19 -3
- package/dist/components/charts/compact-bar-trend.d.ts +1 -1
- package/dist/components/charts/compact-bar-trend.js +2 -0
- package/dist/components/charts/pie-chart.d.ts +1 -1
- package/dist/components/charts/pie-chart.js +12 -1
- package/dist/components/charts/recharts-peer.d.ts +49 -0
- package/dist/components/charts/recharts-peer.js +45 -0
- package/dist/components/data-display/card.d.ts +14 -3
- package/dist/components/data-display/card.js +22 -4
- package/dist/components/data-display/code-block.js +6 -2
- package/dist/components/data-display/collapsible.d.ts +23 -4
- package/dist/components/data-display/collapsible.js +119 -4
- package/dist/components/data-display/data-table.d.ts +39 -4
- package/dist/components/data-display/data-table.js +802 -270
- package/dist/components/data-display/descriptions.d.ts +27 -6
- package/dist/components/data-display/descriptions.js +58 -17
- package/dist/components/data-display/index.d.ts +5 -1
- package/dist/components/data-display/index.js +4 -0
- package/dist/components/data-display/legend.d.ts +15 -0
- package/dist/components/data-display/legend.js +11 -0
- package/dist/components/data-display/list-row.d.ts +10 -1
- package/dist/components/data-display/list-row.js +8 -2
- package/dist/components/data-display/popover.d.ts +60 -7
- package/dist/components/data-display/popover.js +268 -39
- package/dist/components/data-display/progress.d.ts +50 -2
- package/dist/components/data-display/progress.js +57 -9
- package/dist/components/data-display/range-timeline.d.ts +38 -0
- package/dist/components/data-display/range-timeline.js +161 -0
- package/dist/components/data-display/scroll-area.js +13 -2
- package/dist/components/data-display/service-launcher-card.js +10 -10
- package/dist/components/data-display/table.d.ts +11 -3
- package/dist/components/data-display/table.js +48 -18
- package/dist/components/data-display/tree-list.js +4 -9
- package/dist/components/data-entry/calendar.d.ts +2 -2
- package/dist/components/data-entry/calendar.js +79 -33
- package/dist/components/data-entry/cascader.d.ts +1 -1
- package/dist/components/data-entry/cascader.js +188 -24
- package/dist/components/data-entry/checkbox.d.ts +19 -6
- package/dist/components/data-entry/checkbox.js +55 -16
- package/dist/components/data-entry/choice-option.d.ts +1 -1
- package/dist/components/data-entry/color-picker.d.ts +1 -1
- package/dist/components/data-entry/color-picker.js +17 -5
- package/dist/components/data-entry/control-appearance.d.ts +64 -0
- package/dist/components/data-entry/control-appearance.js +39 -0
- package/dist/components/data-entry/control-surface.d.ts +61 -0
- package/dist/components/data-entry/control-surface.js +39 -0
- package/dist/components/data-entry/date-picker.d.ts +1 -1
- package/dist/components/data-entry/date-picker.js +344 -113
- package/dist/components/data-entry/date-range-picker.d.ts +2 -2
- package/dist/components/data-entry/date-range-picker.js +278 -140
- package/dist/components/data-entry/field.js +0 -1
- package/dist/components/data-entry/form-field.d.ts +1 -1
- package/dist/components/data-entry/form-field.js +39 -4
- package/dist/components/data-entry/form.d.ts +4 -0
- package/dist/components/data-entry/form.js +5 -3
- package/dist/components/data-entry/index.d.ts +7 -3
- package/dist/components/data-entry/index.js +10 -1
- package/dist/components/data-entry/input-otp.d.ts +1 -1
- package/dist/components/data-entry/input.d.ts +12 -34
- package/dist/components/data-entry/input.js +92 -24
- package/dist/components/data-entry/label.d.ts +3 -2
- package/dist/components/data-entry/label.js +23 -10
- package/dist/components/data-entry/month-picker.d.ts +2 -2
- package/dist/components/data-entry/month-picker.js +47 -10
- package/dist/components/data-entry/month-range-picker.d.ts +2 -2
- package/dist/components/data-entry/month-range-picker.js +51 -11
- package/dist/components/data-entry/number-input.d.ts +7 -0
- package/dist/components/data-entry/number-input.js +147 -98
- package/dist/components/data-entry/password-input.d.ts +1 -1
- package/dist/components/data-entry/radio.d.ts +1 -1
- package/dist/components/data-entry/radio.js +61 -13
- package/dist/components/data-entry/search-input.d.ts +1 -1
- package/dist/components/data-entry/search-input.js +16 -2
- package/dist/components/data-entry/search-select.d.ts +2 -2
- package/dist/components/data-entry/search-select.js +209 -78
- package/dist/components/data-entry/select.d.ts +22 -4
- package/dist/components/data-entry/select.js +215 -163
- package/dist/components/data-entry/slider.d.ts +9 -1
- package/dist/components/data-entry/slider.js +87 -9
- package/dist/components/data-entry/switch.d.ts +3 -0
- package/dist/components/data-entry/switch.js +29 -3
- package/dist/components/data-entry/textarea.d.ts +14 -56
- package/dist/components/data-entry/textarea.js +80 -33
- package/dist/components/data-entry/time-picker.d.ts +2 -2
- package/dist/components/data-entry/time-picker.js +333 -109
- package/dist/components/data-entry/time-range-picker.d.ts +5 -0
- package/dist/components/data-entry/time-range-picker.js +89 -0
- package/dist/components/data-entry/transfer.d.ts +1 -1
- package/dist/components/data-entry/transfer.js +99 -31
- package/dist/components/data-entry/tree-select-strategy.d.ts +1 -1
- package/dist/components/data-entry/tree-select.d.ts +1 -1
- package/dist/components/data-entry/tree-select.js +197 -92
- package/dist/components/data-entry/tree-utils.d.ts +1 -1
- package/dist/components/data-entry/tree-utils.js +7 -14
- package/dist/components/data-entry/upload-files.d.ts +2 -0
- package/dist/components/data-entry/upload-files.js +31 -0
- package/dist/components/data-entry/upload-request.d.ts +4 -0
- package/dist/components/data-entry/upload-request.js +53 -0
- package/dist/components/data-entry/upload-types.d.ts +28 -0
- package/dist/components/data-entry/upload-types.js +2 -0
- package/dist/components/data-entry/upload.d.ts +2 -2
- package/dist/components/data-entry/upload.js +482 -117
- package/dist/components/feedback/dialog.d.ts +105 -38
- package/dist/components/feedback/dialog.js +268 -193
- package/dist/components/feedback/overlay-close-focus.d.ts +31 -0
- package/dist/components/feedback/overlay-close-focus.js +31 -0
- package/dist/components/feedback/overlay-header-tone.d.ts +1 -1
- package/dist/components/feedback/sheet.d.ts +53 -11
- package/dist/components/feedback/sheet.js +150 -81
- package/dist/components/feedback/tooltip.d.ts +51 -7
- package/dist/components/feedback/tooltip.js +107 -25
- package/dist/components/general/button.d.ts +1 -1
- package/dist/components/general/button.js +7 -3
- package/dist/components/general/index.d.ts +1 -0
- package/dist/components/general/index.js +2 -0
- package/dist/components/general/logo.d.ts +17 -0
- package/dist/components/general/logo.js +22 -16
- package/dist/components/general/typography.d.ts +3 -0
- package/dist/components/general/typography.js +15 -1
- package/dist/components/general/visually-hidden.d.ts +3 -0
- package/dist/components/general/visually-hidden.js +9 -0
- package/dist/components/layout/app-launcher.d.ts +34 -0
- package/dist/components/layout/app-launcher.js +228 -0
- package/dist/components/layout/app-shell.d.ts +3 -1
- package/dist/components/layout/app-shell.js +69 -12
- package/dist/components/layout/aspect-ratio.js +0 -1
- package/dist/components/layout/auth-divider.js +0 -1
- package/dist/components/layout/breadcrumb.d.ts +14 -2
- package/dist/components/layout/breadcrumb.js +46 -4
- package/dist/components/layout/flex.d.ts +1 -1
- package/dist/components/layout/flex.js +41 -3
- package/dist/components/layout/index.d.ts +3 -0
- package/dist/components/layout/index.js +5 -1
- package/dist/components/layout/nav-surface.d.ts +26 -0
- package/dist/components/layout/nav-surface.js +17 -0
- package/dist/components/layout/org-switcher.d.ts +5 -1
- package/dist/components/layout/org-switcher.js +25 -4
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +5 -3
- package/dist/components/layout/responsive-grid.d.ts +16 -2
- package/dist/components/layout/responsive-grid.js +29 -2
- package/dist/components/layout/separator.js +0 -1
- package/dist/components/layout/sidebar.js +4 -1
- package/dist/components/layout/split-pane.d.ts +14 -1
- package/dist/components/layout/split-pane.js +26 -13
- package/dist/components/layout/topbar-item.d.ts +3 -0
- package/dist/components/layout/topbar-item.js +19 -5
- package/dist/components/layout/topbar.d.ts +1 -1
- package/dist/components/layout/topbar.js +27 -6
- package/dist/components/navigation/app-setting-picker.js +21 -2
- package/dist/components/navigation/app-setting-toggle.d.ts +16 -0
- package/dist/components/navigation/app-setting-toggle.js +96 -0
- package/dist/components/navigation/dropdown-menu.d.ts +227 -18
- package/dist/components/navigation/dropdown-menu.js +402 -118
- package/dist/components/navigation/index.d.ts +2 -0
- package/dist/components/navigation/index.js +2 -0
- package/dist/components/navigation/pagination-utils.d.ts +2 -1
- package/dist/components/navigation/pagination.d.ts +2 -2
- package/dist/components/navigation/pagination.js +155 -83
- package/dist/components/navigation/steps.d.ts +2 -2
- package/dist/components/navigation/steps.js +29 -4
- package/dist/components/navigation/tabs.d.ts +29 -16
- package/dist/components/navigation/tabs.js +374 -144
- package/dist/components/ui/accordion.d.ts +50 -5
- package/dist/components/ui/accordion.js +239 -33
- package/dist/components/ui/aspect-ratio.d.ts +23 -2
- package/dist/components/ui/aspect-ratio.js +15 -13
- package/dist/components/ui/avatar.d.ts +29 -4
- package/dist/components/ui/avatar.js +111 -25
- package/dist/components/ui/hover-card.d.ts +42 -4
- package/dist/components/ui/hover-card.js +183 -27
- package/dist/components/ui/input-otp.d.ts +26 -28
- package/dist/components/ui/input-otp.js +50 -7
- package/dist/components/ui/label.js +0 -1
- package/dist/components/ui/password-input.d.ts +36 -2
- package/dist/components/ui/password-input.js +27 -7
- package/dist/components/ui/rating.d.ts +25 -0
- package/dist/components/ui/rating.js +67 -27
- package/dist/components/ui/segmented.d.ts +12 -3
- package/dist/components/ui/segmented.js +17 -2
- package/dist/components/ui/separator.d.ts +12 -2
- package/dist/components/ui/separator.js +30 -9
- package/dist/components/ui/tag-input.d.ts +45 -0
- package/dist/components/ui/tag-input.js +109 -27
- package/dist/components/ui/toggle-group.d.ts +50 -5
- package/dist/components/ui/toggle-group.js +79 -20
- package/dist/components/ui/toggle.d.ts +31 -5
- package/dist/components/ui/toggle.js +42 -3
- package/dist/form/form-context.d.ts +29 -0
- package/dist/form/form-context.js +44 -4
- package/dist/form/form-field-array.d.ts +22 -0
- package/dist/form/form-field-array.js +50 -0
- package/dist/form/form-field-control.d.ts +2 -1
- package/dist/form/form-field-control.js +116 -40
- package/dist/form/form-root.d.ts +2 -1
- package/dist/form/form-root.js +142 -23
- package/dist/form/index.d.ts +3 -1
- package/dist/form/index.js +12 -1
- package/dist/i18n/messages/en.json +64 -5
- package/dist/i18n/messages/ja.json +64 -5
- package/dist/i18n/messages/vi.json +64 -5
- package/dist/inertia/index.d.ts +20 -0
- package/dist/inertia/index.js +60 -1
- package/dist/lib/control-styles.d.ts +25 -3
- package/dist/lib/control-styles.js +9 -3
- package/dist/lib/datetime/picker-format.d.ts +8 -0
- package/dist/lib/datetime/picker-format.js +54 -0
- package/dist/lib/slot.d.ts +32 -0
- package/dist/lib/slot.js +22 -0
- package/dist/lib/variants.d.ts +22 -3
- package/dist/lib/variants.js +56 -1
- package/dist/props/components/app.prop.d.ts +25 -1
- package/dist/props/components/charts.prop.d.ts +21 -0
- package/dist/props/components/data-display.prop.d.ts +72 -4
- package/dist/props/components/data-entry.prop.d.ts +718 -46
- package/dist/props/components/form.prop.d.ts +142 -4
- package/dist/props/components/general.prop.d.ts +17 -1
- package/dist/props/components/index.d.ts +3 -3
- package/dist/props/components/layout.prop.d.ts +281 -11
- package/dist/props/components/navigation.prop.d.ts +114 -4
- package/dist/props/registry.d.ts +397 -11
- package/dist/props/registry.js +526 -11
- package/dist/props/vocabulary/content.prop.d.ts +1 -1
- package/dist/props/vocabulary/data.prop.d.ts +179 -1
- package/dist/props/vocabulary/index.d.ts +5 -5
- package/dist/props/vocabulary/interaction.prop.d.ts +68 -3
- package/dist/props/vocabulary/layout.prop.d.ts +57 -1
- package/dist/props/vocabulary/navigation.prop.d.ts +40 -0
- package/dist/props/vocabulary/shared.prop.d.ts +33 -0
- package/dist/styles/badge-layout.css +2 -1
- package/dist/styles/card-layout.css +26 -4
- package/dist/styles/chart-layout.css +15 -0
- package/dist/styles/control.css +657 -15
- package/dist/styles/core.css +5 -2
- package/dist/styles/data-display-layout.css +313 -6
- package/dist/styles/data-entry-layout.css +13 -0
- package/dist/styles/focus-ring.css +4 -0
- package/dist/styles/index.css +5 -2
- package/dist/styles/layout.css +327 -4
- package/dist/styles/navigation-layout.css +227 -0
- package/dist/styles/shell-layout.css +369 -13
- package/dist/styles/table-layout.css +95 -6
- package/dist/styles/text-layout.css +10 -4
- package/dist/tokens/base.css +2 -1
- package/dist/tokens/components/badge.css +1 -0
- package/dist/tokens/components/chart.css +6 -0
- package/dist/tokens/components/control.css +79 -2
- package/dist/tokens/components/data-display.css +20 -0
- package/dist/tokens/components/descriptions.css +11 -0
- package/dist/tokens/components/flex.css +8 -0
- package/dist/tokens/components/navigation.css +55 -0
- package/dist/tokens/components/shell.css +53 -3
- package/dist/tokens/components/table.css +14 -0
- package/dist/tokens/foundation.css +2 -0
- package/dist/tokens/semantic/layout.css +9 -0
- package/docs/COMPONENTS.md +9 -3
- package/docs/CONSUMER-RULES.md +13 -0
- package/docs/DESIGN-AUTHORITY.md +145 -83
- package/docs/DEVELOPMENT.md +4 -3
- package/docs/FORMS.md +151 -6
- package/docs/FRAME-COVERAGE-REPORT.md +32 -17
- package/docs/README.md +15 -15
- package/docs/STANDARDS-vocabulary-tokens.md +1 -1
- package/docs/TESTING.md +15 -6
- package/docs/WHAT-BELONGS-HERE.md +179 -0
- package/docs/charts/cjk-category-axis.tsx +81 -0
- package/docs/data-display/card/index.tsx +22 -0
- package/docs/data-display/data-table/examples/antd-parity.tsx +257 -0
- package/docs/data-display/data-table/index.tsx +23 -0
- package/docs/data-display/descriptions.tsx +41 -0
- package/docs/data-display/legend.tsx +145 -0
- package/docs/data-display/progress.tsx +32 -0
- package/docs/data-display/scroll-area.tsx +31 -25
- package/docs/data-display/table.tsx +104 -45
- package/docs/data-display/timeline.tsx +41 -0
- package/docs/data-entry/date-picker.tsx +85 -0
- package/docs/data-entry/date-range-picker.tsx +26 -0
- package/docs/data-entry/form-dynamic-fields.tsx +199 -0
- package/docs/data-entry/form.tsx +74 -4
- package/docs/data-entry/input-otp.tsx +24 -0
- package/docs/data-entry/input.tsx +46 -1
- package/docs/data-entry/month-range-picker.tsx +1 -1
- package/docs/data-entry/segmented.tsx +1 -1
- package/docs/data-entry/select.tsx +29 -2
- package/docs/data-entry/switch.tsx +41 -0
- package/docs/data-entry/textarea.tsx +38 -0
- package/docs/data-entry/time-picker.tsx +85 -1
- package/docs/data-entry/time-range-picker.tsx +55 -0
- package/docs/data-entry/transfer.tsx +17 -0
- package/docs/data-entry/upload.tsx +56 -12
- package/docs/feedback/sheet.tsx +1 -1
- package/docs/feedback/tooltip.tsx +1 -1
- package/docs/general/activity.tsx +2 -2
- package/docs/general/button/index.tsx +14 -1
- package/docs/general/typography.tsx +14 -1
- package/docs/layout/app-launcher.tsx +151 -0
- package/docs/layout/app-shell-arrangements.tsx +225 -0
- package/docs/layout/app-shell.tsx +11 -0
- package/docs/layout/aspect-ratio.tsx +1 -1
- package/docs/layout/flex.tsx +50 -0
- package/docs/layout/responsive-grid.tsx +21 -1
- package/docs/layout/topbar.tsx +5 -9
- package/docs/navigation/app-setting-picker.tsx +37 -1
- package/docs/navigation/app-setting-toggle.tsx +111 -0
- package/docs/navigation/breadcrumb.tsx +48 -0
- package/docs/navigation/dropdown-menu.tsx +21 -0
- package/docs/navigation/pagination.tsx +52 -0
- package/docs/navigation/steps.tsx +37 -0
- package/docs/navigation/tabs.tsx +97 -1
- package/docs/query/button-refetch.tsx +1 -0
- package/package.json +28 -8
- package/scripts/_agent-setup.mjs +182 -3
- package/scripts/consumer-rule.md +98 -0
- package/scripts/guinea-pig-skill.md +322 -0
- package/scripts/init-guinea-pig.mjs +84 -0
- package/scripts/postinstall.mjs +13 -2
- package/scripts/ui-audit.mjs +351 -37
- /package/dist/tokens/{antd.generated.css → derived.css} +0 -0
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import { Check, ChevronRight, ChevronsUpDown, Minus, X } from "lucide-react";
|
|
4
|
+
import { Check, ChevronRight, ChevronsUpDown, Loader2, Minus, X } from "lucide-react";
|
|
5
5
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
7
|
import { pickFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
|
|
8
|
-
import {
|
|
8
|
+
import { controlSurfaceTriggerClass } from "../../lib/control-styles.js";
|
|
9
|
+
import {
|
|
10
|
+
applyMaxTagCount,
|
|
11
|
+
controlSurfaceAttrs,
|
|
12
|
+
resolveAllowClear,
|
|
13
|
+
resolveAriaInvalid
|
|
14
|
+
} from "./control-surface.js";
|
|
9
15
|
import { Popover, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
|
|
10
16
|
import { ScrollArea, ScrollBar } from "../data-display/scroll-area.js";
|
|
11
17
|
import { Command, CommandInput } from "./command.js";
|
|
@@ -15,7 +21,8 @@ import {
|
|
|
15
21
|
getNodeByPath,
|
|
16
22
|
normalizeTreeOptions,
|
|
17
23
|
pathKey,
|
|
18
|
-
pathsEqual
|
|
24
|
+
pathsEqual,
|
|
25
|
+
reactNodeText
|
|
19
26
|
} from "./tree-utils.js";
|
|
20
27
|
function pathInValues(path, values) {
|
|
21
28
|
return values.some((v) => pathsEqual(v, path));
|
|
@@ -66,6 +73,41 @@ function aggregateCheckState(node, path, values) {
|
|
|
66
73
|
if (total === 0 || selected === 0) return "none";
|
|
67
74
|
return selected === total ? "checked" : "indeterminate";
|
|
68
75
|
}
|
|
76
|
+
function leafPathsUnder(node, path) {
|
|
77
|
+
const out = [];
|
|
78
|
+
const walk = (current, prefix) => {
|
|
79
|
+
const isLeaf = (current.children?.length ?? 0) === 0 || current.isLeaf === true;
|
|
80
|
+
if (isLeaf) {
|
|
81
|
+
out.push(prefix);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
for (const child of current.children) walk(child, [...prefix, child.value]);
|
|
85
|
+
};
|
|
86
|
+
walk(node, path);
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
function collapseToParents(values, options) {
|
|
90
|
+
const representative = /* @__PURE__ */ new Map();
|
|
91
|
+
const walk = (nodes, prefix) => {
|
|
92
|
+
for (const node of nodes) {
|
|
93
|
+
const path = [...prefix, node.value];
|
|
94
|
+
const hasChildren = (node.children?.length ?? 0) > 0 && node.isLeaf !== true;
|
|
95
|
+
if (!hasChildren) continue;
|
|
96
|
+
if (aggregateCheckState(node, path, values) === "checked") {
|
|
97
|
+
for (const leaf of leafPathsUnder(node, path)) representative.set(pathKey(leaf), path);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
walk(node.children, path);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
walk(options, []);
|
|
104
|
+
const out = [];
|
|
105
|
+
for (const value of values) {
|
|
106
|
+
const shown = representative.get(pathKey(value)) ?? value;
|
|
107
|
+
if (!out.some((existing) => pathsEqual(existing, shown))) out.push(shown);
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
69
111
|
function Cascader({
|
|
70
112
|
options: optionsProp,
|
|
71
113
|
value,
|
|
@@ -76,25 +118,76 @@ function Cascader({
|
|
|
76
118
|
showSearch,
|
|
77
119
|
placeholder,
|
|
78
120
|
disabled,
|
|
121
|
+
readOnly,
|
|
122
|
+
name,
|
|
79
123
|
className,
|
|
80
124
|
id,
|
|
81
125
|
expandTrigger = "click",
|
|
82
126
|
fieldNames,
|
|
83
|
-
allowClear
|
|
127
|
+
allowClear,
|
|
128
|
+
size,
|
|
129
|
+
status,
|
|
130
|
+
variant,
|
|
131
|
+
loading = false,
|
|
132
|
+
open: openProp,
|
|
133
|
+
defaultOpen = false,
|
|
134
|
+
onOpenChange,
|
|
135
|
+
showCheckedStrategy = "SHOW_CHILD",
|
|
136
|
+
loadData,
|
|
137
|
+
displayRender,
|
|
138
|
+
optionRender,
|
|
139
|
+
maxTagCount,
|
|
140
|
+
maxTagPlaceholder,
|
|
141
|
+
notFoundContent,
|
|
142
|
+
autoClearSearchValue = true,
|
|
143
|
+
search: searchProp,
|
|
144
|
+
onSearchChange,
|
|
84
145
|
...ariaProps
|
|
85
146
|
}) {
|
|
86
147
|
const { t } = useTranslation();
|
|
87
148
|
const fieldA11y = pickFieldA11y(ariaProps);
|
|
88
|
-
const identity = useFieldIdentity({ id, "data-field": fieldA11y["data-field"] });
|
|
149
|
+
const identity = useFieldIdentity({ id, name, "data-field": fieldA11y["data-field"] });
|
|
150
|
+
const resolvedName = name ?? identity.name;
|
|
89
151
|
const reactId = React.useId();
|
|
90
152
|
const panelId = `${id ?? reactId}-panel`;
|
|
91
153
|
const options = React.useMemo(
|
|
92
154
|
() => normalizeTreeOptions(optionsProp, fieldNames),
|
|
93
155
|
[optionsProp, fieldNames]
|
|
94
156
|
);
|
|
95
|
-
const [
|
|
157
|
+
const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
|
|
158
|
+
const isOpenControlled = openProp !== void 0;
|
|
159
|
+
const open = isOpenControlled ? openProp : internalOpen;
|
|
160
|
+
const setOpen = React.useCallback(
|
|
161
|
+
(next) => {
|
|
162
|
+
if (!isOpenControlled) setInternalOpen(next);
|
|
163
|
+
onOpenChange?.(next);
|
|
164
|
+
},
|
|
165
|
+
[isOpenControlled, onOpenChange]
|
|
166
|
+
);
|
|
96
167
|
const [activePath, setActivePath] = React.useState([]);
|
|
97
|
-
const [
|
|
168
|
+
const [internalSearch, setInternalSearch] = React.useState("");
|
|
169
|
+
const isSearchControlled = searchProp !== void 0;
|
|
170
|
+
const search = isSearchControlled ? searchProp : internalSearch;
|
|
171
|
+
const setSearch = React.useCallback(
|
|
172
|
+
(next) => {
|
|
173
|
+
if (!isSearchControlled) setInternalSearch(next);
|
|
174
|
+
onSearchChange?.(next);
|
|
175
|
+
},
|
|
176
|
+
[isSearchControlled, onSearchChange]
|
|
177
|
+
);
|
|
178
|
+
const requestedLoads = React.useRef(/* @__PURE__ */ new Set());
|
|
179
|
+
const requestLoad = React.useCallback(
|
|
180
|
+
(path, chain) => {
|
|
181
|
+
if (!loadData) return;
|
|
182
|
+
const node = chain.at(-1);
|
|
183
|
+
if (!node || node.isLeaf === true || (node.children?.length ?? 0) > 0) return;
|
|
184
|
+
const key = pathKey(path);
|
|
185
|
+
if (requestedLoads.current.has(key)) return;
|
|
186
|
+
requestedLoads.current.add(key);
|
|
187
|
+
void loadData(chain);
|
|
188
|
+
},
|
|
189
|
+
[loadData]
|
|
190
|
+
);
|
|
98
191
|
const isControlledSingle = !multiple && value !== void 0;
|
|
99
192
|
const isControlledMulti = multiple && value !== void 0;
|
|
100
193
|
const [internalSingle, setInternalSingle] = React.useState(
|
|
@@ -106,14 +199,52 @@ function Cascader({
|
|
|
106
199
|
const singleValue = isControlledSingle ? value : internalSingle;
|
|
107
200
|
const multiValue = isControlledMulti ? value : internalMulti;
|
|
108
201
|
const resolvedPlaceholder = placeholder ?? t("dataEntry.cascader.placeholder");
|
|
202
|
+
const hasValue = multiple ? multiValue.length > 0 : singleValue.length > 0;
|
|
109
203
|
const displayLabel = React.useMemo(() => {
|
|
110
204
|
if (multiple) {
|
|
111
205
|
if (!multiValue.length) return null;
|
|
112
|
-
|
|
206
|
+
const shown = showCheckedStrategy === "SHOW_PARENT" ? collapseToParents(multiValue, options) : multiValue;
|
|
207
|
+
const items = shown.map((path) => {
|
|
208
|
+
const chain2 = getNodeByPath(options, path);
|
|
209
|
+
const labels = chain2.map((node) => reactNodeText(node.label));
|
|
210
|
+
return {
|
|
211
|
+
value: pathKey(path),
|
|
212
|
+
label: displayRender ? displayRender(labels, chain2) : formatPathLabels(chain2)
|
|
213
|
+
};
|
|
214
|
+
});
|
|
215
|
+
const { visible, omitted, overflow } = applyMaxTagCount(
|
|
216
|
+
items,
|
|
217
|
+
maxTagCount,
|
|
218
|
+
maxTagPlaceholder
|
|
219
|
+
);
|
|
220
|
+
const body = visible.map((item, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
221
|
+
index > 0 ? ", " : null,
|
|
222
|
+
item.label
|
|
223
|
+
] }, item.value));
|
|
224
|
+
if (omitted.length === 0) return body;
|
|
225
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
226
|
+
body,
|
|
227
|
+
", ",
|
|
228
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "cascader-overflow", children: overflow ?? t("dataEntry.selection.overflow", { count: omitted.length }) })
|
|
229
|
+
] });
|
|
113
230
|
}
|
|
114
231
|
if (!singleValue.length) return null;
|
|
115
|
-
|
|
116
|
-
|
|
232
|
+
const chain = getNodeByPath(options, singleValue);
|
|
233
|
+
return displayRender ? displayRender(
|
|
234
|
+
chain.map((node) => reactNodeText(node.label)),
|
|
235
|
+
chain
|
|
236
|
+
) : formatPathLabels(chain);
|
|
237
|
+
}, [
|
|
238
|
+
multiple,
|
|
239
|
+
multiValue,
|
|
240
|
+
singleValue,
|
|
241
|
+
options,
|
|
242
|
+
showCheckedStrategy,
|
|
243
|
+
displayRender,
|
|
244
|
+
maxTagCount,
|
|
245
|
+
maxTagPlaceholder,
|
|
246
|
+
t
|
|
247
|
+
]);
|
|
117
248
|
const setSingleValue = (path) => {
|
|
118
249
|
if (!isControlledSingle) setInternalSingle(path);
|
|
119
250
|
onValueChange?.(path, getNodeByPath(options, path));
|
|
@@ -122,7 +253,7 @@ function Cascader({
|
|
|
122
253
|
setSingleValue(path);
|
|
123
254
|
setOpen(false);
|
|
124
255
|
setActivePath([]);
|
|
125
|
-
setSearch("");
|
|
256
|
+
if (autoClearSearchValue) setSearch("");
|
|
126
257
|
};
|
|
127
258
|
const commitMulti = (paths) => {
|
|
128
259
|
if (!isControlledMulti) setInternalMulti(paths);
|
|
@@ -143,6 +274,11 @@ function Cascader({
|
|
|
143
274
|
}, [options, activePath]);
|
|
144
275
|
const handleSelectNode = (node, path) => {
|
|
145
276
|
const hasChildren = (node.children?.length ?? 0) > 0 && node.isLeaf !== true;
|
|
277
|
+
requestLoad(path, getNodeByPath(options, path));
|
|
278
|
+
if (loadData && node.isLeaf === false && !(node.children?.length ?? 0)) {
|
|
279
|
+
setActivePath(path);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
146
282
|
if (multiple) {
|
|
147
283
|
if (hasChildren && !changeOnSelect) setActivePath(path);
|
|
148
284
|
else if (!node.disableCheckbox) commitMulti(togglePath(multiValue, path));
|
|
@@ -161,11 +297,12 @@ function Cascader({
|
|
|
161
297
|
[options, search, isSearching]
|
|
162
298
|
);
|
|
163
299
|
const handleOpenChange = (next) => {
|
|
300
|
+
if (readOnly && next) return;
|
|
164
301
|
setOpen(next);
|
|
165
302
|
if (next) {
|
|
166
303
|
setActivePath(multiple ? [] : singleValue);
|
|
167
304
|
} else {
|
|
168
|
-
setSearch("");
|
|
305
|
+
if (autoClearSearchValue) setSearch("");
|
|
169
306
|
setActivePath([]);
|
|
170
307
|
}
|
|
171
308
|
};
|
|
@@ -208,7 +345,11 @@ function Cascader({
|
|
|
208
345
|
// deeper column but keeps its own. Never collapse on the column's mouseleave
|
|
209
346
|
// — moving the pointer toward the next column would strand the deeper levels
|
|
210
347
|
// and make a depth-3 leaf unreachable.
|
|
211
|
-
expandTrigger === "hover" && !node.disabled ? () =>
|
|
348
|
+
expandTrigger === "hover" && !node.disabled ? () => {
|
|
349
|
+
const loadable = node.isLeaf === false && !(node.children?.length ?? 0);
|
|
350
|
+
requestLoad(path, getNodeByPath(options, path));
|
|
351
|
+
setActivePath(hasChildren || loadable ? path : path.slice(0, -1));
|
|
352
|
+
} : void 0
|
|
212
353
|
),
|
|
213
354
|
onClick: () => !node.disabled && handleSelectNode(node, path),
|
|
214
355
|
children: [
|
|
@@ -222,8 +363,8 @@ function Cascader({
|
|
|
222
363
|
}
|
|
223
364
|
),
|
|
224
365
|
!multiple && selected && /* @__PURE__ */ jsx(Check, { className: "ui-cascader-option-icon", "aria-hidden": "true" }),
|
|
225
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-start", children: node.label }),
|
|
226
|
-
hasChildren && /* @__PURE__ */ jsx(ChevronRight, { className: "ui-cascader-option-chevron", "aria-hidden": "true" })
|
|
366
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-start", children: optionRender ? optionRender(node) : node.label }),
|
|
367
|
+
(hasChildren || loadData && node.isLeaf === false) && /* @__PURE__ */ jsx(ChevronRight, { className: "ui-cascader-option-chevron", "aria-hidden": "true" })
|
|
227
368
|
]
|
|
228
369
|
}
|
|
229
370
|
) }, node.value);
|
|
@@ -233,7 +374,9 @@ function Cascader({
|
|
|
233
374
|
)) }),
|
|
234
375
|
/* @__PURE__ */ jsx(ScrollBar, { orientation: "horizontal" })
|
|
235
376
|
] });
|
|
236
|
-
const
|
|
377
|
+
const clearControl = resolveAllowClear(allowClear, true, t("dataEntry.cascader.clear"));
|
|
378
|
+
const showClear = clearControl.enabled && hasValue && !disabled && !readOnly && !loading;
|
|
379
|
+
const surface = controlSurfaceAttrs({ variant, status, size });
|
|
237
380
|
return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
238
381
|
/* @__PURE__ */ jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
|
|
239
382
|
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
@@ -247,17 +390,31 @@ function Cascader({
|
|
|
247
390
|
"aria-haspopup": "listbox",
|
|
248
391
|
"aria-controls": open ? panelId : void 0,
|
|
249
392
|
...fieldA11y,
|
|
393
|
+
...surface,
|
|
394
|
+
"aria-invalid": resolveAriaInvalid(fieldA11y["aria-invalid"], status),
|
|
395
|
+
"aria-busy": loading || void 0,
|
|
396
|
+
"aria-readonly": readOnly || void 0,
|
|
250
397
|
disabled,
|
|
251
398
|
className: cn(
|
|
252
|
-
|
|
399
|
+
controlSurfaceTriggerClass,
|
|
253
400
|
"w-full justify-start",
|
|
254
401
|
// Reserve trailing room for the single clear-or-chevron overlay rendered below.
|
|
255
402
|
"ui-control-trigger-affixed",
|
|
256
|
-
!
|
|
403
|
+
!hasValue && "text-muted-foreground"
|
|
257
404
|
),
|
|
258
|
-
children: /* @__PURE__ */ jsx("span", { className: "truncate", children: displayLabel
|
|
405
|
+
children: /* @__PURE__ */ jsx("span", { className: "truncate", children: hasValue ? displayLabel : resolvedPlaceholder })
|
|
259
406
|
}
|
|
260
407
|
) }),
|
|
408
|
+
resolvedName ? (multiple ? multiValue : singleValue.length ? [singleValue] : []).map((path, index) => /* @__PURE__ */ jsx(
|
|
409
|
+
"input",
|
|
410
|
+
{
|
|
411
|
+
type: "hidden",
|
|
412
|
+
name: resolvedName,
|
|
413
|
+
value: path.join("/"),
|
|
414
|
+
readOnly: true
|
|
415
|
+
},
|
|
416
|
+
`${pathKey(path)}-${index}`
|
|
417
|
+
)) : null,
|
|
261
418
|
/* @__PURE__ */ jsxs(PopoverContent, { id: panelId, className: "ui-cascader-popover", align: "start", children: [
|
|
262
419
|
showSearch && /* @__PURE__ */ jsx(Command, { shouldFilter: false, children: /* @__PURE__ */ jsx(
|
|
263
420
|
CommandInput,
|
|
@@ -273,7 +430,7 @@ function Cascader({
|
|
|
273
430
|
className: "ui-cascader-panel",
|
|
274
431
|
role: "listbox",
|
|
275
432
|
"aria-multiselectable": multiple ? true : void 0,
|
|
276
|
-
children: searchResults.length === 0 ? /* @__PURE__ */ jsx("p", { className: "ui-cascader-empty", children: t("dataEntry.cascader.empty") }) : searchResults.map(({ path, labels }) => {
|
|
433
|
+
children: searchResults.length === 0 ? /* @__PURE__ */ jsx("p", { className: "ui-cascader-empty", children: notFoundContent ?? t("dataEntry.cascader.empty") }) : searchResults.map(({ path, labels }) => {
|
|
277
434
|
const label = labels.join(" / ");
|
|
278
435
|
const selected = multiple ? pathInValues(path, multiValue) : pathsEqual(path, singleValue);
|
|
279
436
|
return /* @__PURE__ */ jsxs(
|
|
@@ -307,14 +464,21 @@ function Cascader({
|
|
|
307
464
|
) }) : renderCascadeColumns()
|
|
308
465
|
] })
|
|
309
466
|
] }),
|
|
310
|
-
/* @__PURE__ */ jsx("div", { className: "ui-control-affix ui-cascader-affix", children:
|
|
467
|
+
/* @__PURE__ */ jsx("div", { className: "ui-control-affix ui-cascader-affix", children: loading ? /* @__PURE__ */ jsx(
|
|
468
|
+
Loader2,
|
|
469
|
+
{
|
|
470
|
+
"data-slot": "cascader-loading",
|
|
471
|
+
className: "ui-control-affix-icon ui-control-affix-indicator animate-spin",
|
|
472
|
+
"aria-hidden": "true"
|
|
473
|
+
}
|
|
474
|
+
) : showClear ? /* @__PURE__ */ jsx(
|
|
311
475
|
"button",
|
|
312
476
|
{
|
|
313
477
|
type: "button",
|
|
314
|
-
"aria-label":
|
|
478
|
+
"aria-label": clearControl.label,
|
|
315
479
|
className: "ui-control-affix-action",
|
|
316
480
|
onClick: clearValue,
|
|
317
|
-
children: /* @__PURE__ */ jsx(X, { className: "ui-control-affix-icon", "aria-hidden": "true" })
|
|
481
|
+
children: clearControl.clearIcon ?? /* @__PURE__ */ jsx(X, { className: "ui-control-affix-icon", "aria-hidden": "true" })
|
|
318
482
|
}
|
|
319
483
|
) : /* @__PURE__ */ jsx(
|
|
320
484
|
ChevronsUpDown,
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
3
2
|
import { CheckboxGroup } from "./checkbox-group.js";
|
|
4
3
|
/**
|
|
5
4
|
* Decorative checkbox glyph — a non-interactive `<span>`, NOT the real {@link Checkbox} (which is a
|
|
6
|
-
* `<
|
|
7
|
-
* be invalid HTML (Cascader's option rows). Shares
|
|
8
|
-
* drift apart from the real control's rendering again.
|
|
5
|
+
* real `<input>` wrapped by react-aria-components). Used where the row itself is the interactive
|
|
6
|
+
* element and a nested control would be invalid HTML (Cascader's option rows). Shares
|
|
7
|
+
* {@link CheckboxGlyph} so "partial" can never drift apart from the real control's rendering again.
|
|
9
8
|
*/
|
|
10
9
|
export declare function CheckboxVisual({ checked, indeterminate, disabled, className, }: {
|
|
11
10
|
checked: boolean;
|
|
@@ -13,7 +12,21 @@ export declare function CheckboxVisual({ checked, indeterminate, disabled, class
|
|
|
13
12
|
disabled?: boolean;
|
|
14
13
|
className?: string;
|
|
15
14
|
}): React.JSX.Element;
|
|
16
|
-
/**
|
|
17
|
-
|
|
15
|
+
/**
|
|
16
|
+
* The PUBLIC prop shape, unchanged from the @radix-ui/react-checkbox era: `checked` /
|
|
17
|
+
* `defaultChecked` accept the tri-state `"indeterminate"`, `onCheckedChange` reports it back, and
|
|
18
|
+
* `disabled` / `required` keep their HTML spelling. react-aria-components spells the same four
|
|
19
|
+
* `isSelected` + `isIndeterminate` / `defaultSelected` / `onChange` / `isDisabled` / `isRequired`;
|
|
20
|
+
* that translation happens INSIDE this component and none of those names reach a consumer.
|
|
21
|
+
*/
|
|
22
|
+
interface CheckboxRootProps extends Omit<React.ComponentPropsWithoutRef<"button">, "checked" | "defaultChecked" | "onChange"> {
|
|
23
|
+
checked?: boolean | "indeterminate";
|
|
24
|
+
defaultChecked?: boolean | "indeterminate";
|
|
25
|
+
onCheckedChange?: (checked: boolean | "indeterminate") => void;
|
|
26
|
+
required?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** Checkbox — dùng standalone hoặc `Checkbox.Group` với `options` (theo quy ước phổ biến). */
|
|
29
|
+
export declare const Checkbox: React.ForwardRefExoticComponent<CheckboxRootProps & React.RefAttributes<HTMLLabelElement>> & {
|
|
18
30
|
Group: typeof CheckboxGroup;
|
|
19
31
|
};
|
|
32
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import
|
|
4
|
+
import { Checkbox as AriaCheckbox } from "react-aria-components";
|
|
5
5
|
import { Check, Minus } from "lucide-react";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
7
|
import { useFieldIdentity } from "../../lib/field-a11y.js";
|
|
@@ -28,44 +28,83 @@ function CheckboxVisual({
|
|
|
28
28
|
}
|
|
29
29
|
);
|
|
30
30
|
}
|
|
31
|
-
const CheckboxRoot = React.forwardRef((
|
|
31
|
+
const CheckboxRoot = React.forwardRef((props, ref) => {
|
|
32
|
+
const {
|
|
33
|
+
className,
|
|
34
|
+
checked,
|
|
35
|
+
defaultChecked,
|
|
36
|
+
onCheckedChange,
|
|
37
|
+
disabled,
|
|
38
|
+
required,
|
|
39
|
+
value,
|
|
40
|
+
tabIndex,
|
|
41
|
+
"data-field": ownField,
|
|
42
|
+
...rest
|
|
43
|
+
} = props;
|
|
32
44
|
const identity = useFieldIdentity({
|
|
33
45
|
id: props.id,
|
|
34
46
|
name: props.name,
|
|
35
|
-
"data-field":
|
|
47
|
+
"data-field": ownField
|
|
36
48
|
});
|
|
49
|
+
const fieldKey = ownField ?? identity["data-field"];
|
|
50
|
+
const inputRef = React.useRef(null);
|
|
51
|
+
React.useLayoutEffect(() => {
|
|
52
|
+
const input = inputRef.current;
|
|
53
|
+
if (!input) return;
|
|
54
|
+
if (fieldKey === void 0) {
|
|
55
|
+
input.removeAttribute("data-field");
|
|
56
|
+
} else {
|
|
57
|
+
input.setAttribute("data-field", fieldKey);
|
|
58
|
+
}
|
|
59
|
+
}, [fieldKey]);
|
|
37
60
|
const [uncontrolled, setUncontrolled] = React.useState(
|
|
38
|
-
|
|
61
|
+
defaultChecked ?? false
|
|
39
62
|
);
|
|
40
|
-
const state =
|
|
63
|
+
const state = checked ?? uncontrolled;
|
|
64
|
+
const invalid = props["aria-invalid"];
|
|
41
65
|
return /* @__PURE__ */ jsx(
|
|
42
|
-
|
|
66
|
+
AriaCheckbox,
|
|
43
67
|
{
|
|
68
|
+
...rest,
|
|
44
69
|
ref,
|
|
70
|
+
inputRef,
|
|
45
71
|
"data-slot": "checkbox",
|
|
72
|
+
"data-state": state === "indeterminate" ? "indeterminate" : state ? "checked" : "unchecked",
|
|
73
|
+
name: identity.name ?? props.name,
|
|
74
|
+
value,
|
|
75
|
+
isSelected: state === true,
|
|
76
|
+
isIndeterminate: state === "indeterminate",
|
|
77
|
+
isDisabled: disabled,
|
|
78
|
+
isRequired: required,
|
|
79
|
+
isInvalid: invalid !== void 0 && invalid !== false && invalid !== "false",
|
|
80
|
+
excludeFromTabOrder: tabIndex !== void 0 && tabIndex < 0,
|
|
46
81
|
className: cn(
|
|
47
82
|
// `disabled:cursor-not-allowed disabled:opacity-50` and the checked fill are DELETED, not
|
|
48
83
|
// moved: `.ui-checkbox:disabled, .ui-checkbox[data-disabled]` and
|
|
49
84
|
// `.ui-checkbox[data-state="checked"]` in styles/control.css already declare both, reading
|
|
50
85
|
// --disabled-opacity and --checkbox-checked-background. Utilities are layered AFTER
|
|
51
86
|
// components in Tailwind v4, so these literals were silently OUTRANKING those knobs — a
|
|
52
|
-
// service overriding --checkbox-checked-background got no fill change at all.
|
|
53
|
-
// `data-
|
|
54
|
-
// both knobs default to exactly the values these utilities hard-coded.
|
|
55
|
-
|
|
87
|
+
// service overriding --checkbox-checked-background got no fill change at all. `data-state`
|
|
88
|
+
// above and react-aria's own `data-disabled` keep those CSS rules matching. Rendering is
|
|
89
|
+
// unchanged: both knobs default to exactly the values these utilities hard-coded.
|
|
90
|
+
//
|
|
91
|
+
// `inline-flex items-center justify-center` is NEW and load-bearing: the root used to be a
|
|
92
|
+
// `<button>` (inline-block, so `.ui-checkbox`'s width/height applied and the glyph centred
|
|
93
|
+
// itself). react-aria's root is a `<label>`, which is `display:inline` — without this the
|
|
94
|
+
// 16px box collapses to nothing. CheckboxVisual already carries the same three for the
|
|
95
|
+
// same reason.
|
|
96
|
+
"peer ui-checkbox data-[invalid]:border-destructive data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground inline-flex shrink-0 items-center justify-center shadow-xs transition-shadow outline-none",
|
|
56
97
|
className
|
|
57
98
|
),
|
|
58
|
-
|
|
59
|
-
...identity,
|
|
60
|
-
onCheckedChange: (next) => {
|
|
99
|
+
onChange: (next) => {
|
|
61
100
|
setUncontrolled(next);
|
|
62
|
-
|
|
101
|
+
onCheckedChange?.(next);
|
|
63
102
|
},
|
|
64
|
-
children: /* @__PURE__ */ jsx(
|
|
103
|
+
children: /* @__PURE__ */ jsx("span", { "data-slot": "checkbox-indicator", className: "ui-choice-indicator", children: state ? /* @__PURE__ */ jsx(CheckboxGlyph, { state }) : null })
|
|
65
104
|
}
|
|
66
105
|
);
|
|
67
106
|
});
|
|
68
|
-
CheckboxRoot.displayName =
|
|
107
|
+
CheckboxRoot.displayName = "Checkbox";
|
|
69
108
|
const Checkbox = Object.assign(CheckboxRoot, {
|
|
70
109
|
Group: CheckboxGroup
|
|
71
110
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type * as React from "react";
|
|
2
|
-
/** Shared option shape —
|
|
2
|
+
/** Shared option shape — the conventional `CheckboxOptionType` / `Radio` options entry. */
|
|
3
3
|
export type ChoiceOption = {
|
|
4
4
|
label: React.ReactNode;
|
|
5
5
|
value: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { ColorPickerProp } from "../../props/components/data-entry.prop.js";
|
|
3
3
|
export type { ColorPickerProp, ColorPickerProp as ColorPickerProps, } from "../../props/components/data-entry.prop.js";
|
|
4
|
-
export declare function ColorPicker({ value, onValueChange, disabled, className, id, showHexInput, ...ariaProps }: ColorPickerProp): React.JSX.Element;
|
|
4
|
+
export declare function ColorPicker({ value: valueProp, defaultValue, onValueChange, disabled, name, className, id, showHexInput, ...ariaProps }: ColorPickerProp): React.JSX.Element;
|
|
@@ -3,26 +3,35 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
-
import { resolveFieldA11y } from "../../lib/field-a11y.js";
|
|
6
|
+
import { resolveFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
|
|
7
7
|
import { controlIconClass } from "../../lib/control-styles.js";
|
|
8
8
|
import { Input } from "./input.js";
|
|
9
9
|
const HEX_PATTERN = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
|
10
|
+
const NATIVE_COLOR_FALLBACK = "#000000";
|
|
10
11
|
function normalizeHex(value) {
|
|
11
12
|
if (!value.startsWith("#")) return `#${value}`;
|
|
12
13
|
return value;
|
|
13
14
|
}
|
|
14
15
|
function ColorPicker({
|
|
15
|
-
value
|
|
16
|
+
value: valueProp,
|
|
17
|
+
defaultValue,
|
|
16
18
|
onValueChange,
|
|
17
19
|
disabled,
|
|
20
|
+
name,
|
|
18
21
|
className,
|
|
19
22
|
id,
|
|
20
23
|
showHexInput = true,
|
|
21
24
|
...ariaProps
|
|
22
25
|
}) {
|
|
23
26
|
const { t } = useTranslation();
|
|
27
|
+
const isControlled = valueProp !== void 0;
|
|
28
|
+
const [internalValue, setInternalValue] = React.useState(defaultValue ?? "");
|
|
29
|
+
const value = isControlled ? valueProp : internalValue;
|
|
24
30
|
const [draft, setDraft] = React.useState(null);
|
|
25
31
|
const display = draft ?? value;
|
|
32
|
+
const swatchValue = HEX_PATTERN.test(display) ? display : HEX_PATTERN.test(value) ? value : NATIVE_COLOR_FALLBACK;
|
|
33
|
+
const identity = useFieldIdentity({ id, name, "data-field": ariaProps["data-field"] });
|
|
34
|
+
const resolvedName = name ?? identity.name;
|
|
26
35
|
const swatchA11y = resolveFieldA11y(ariaProps, t("dataEntry.colorPicker.ariaLabel"));
|
|
27
36
|
const commit = (next) => {
|
|
28
37
|
const normalized = normalizeHex(next);
|
|
@@ -31,6 +40,7 @@ function ColorPicker({
|
|
|
31
40
|
return;
|
|
32
41
|
}
|
|
33
42
|
setDraft(null);
|
|
43
|
+
if (!isControlled) setInternalValue(normalized);
|
|
34
44
|
onValueChange?.(normalized);
|
|
35
45
|
};
|
|
36
46
|
return /* @__PURE__ */ jsxs("div", { className: cn("ui-color-picker", className), children: [
|
|
@@ -39,7 +49,7 @@ function ColorPicker({
|
|
|
39
49
|
"div",
|
|
40
50
|
{
|
|
41
51
|
className: "ui-color-picker-preview",
|
|
42
|
-
style: { backgroundColor:
|
|
52
|
+
style: { backgroundColor: swatchValue },
|
|
43
53
|
"aria-hidden": "true"
|
|
44
54
|
}
|
|
45
55
|
),
|
|
@@ -48,10 +58,11 @@ function ColorPicker({
|
|
|
48
58
|
{
|
|
49
59
|
id,
|
|
50
60
|
type: "color",
|
|
51
|
-
value:
|
|
61
|
+
value: swatchValue,
|
|
52
62
|
disabled,
|
|
53
63
|
onChange: (event) => commit(event.target.value),
|
|
54
64
|
className: "ui-color-picker-input",
|
|
65
|
+
"data-field": ariaProps["data-field"] ?? identity["data-field"],
|
|
55
66
|
...swatchA11y
|
|
56
67
|
}
|
|
57
68
|
)
|
|
@@ -71,7 +82,8 @@ function ColorPicker({
|
|
|
71
82
|
className: "ui-color-picker-hex",
|
|
72
83
|
spellCheck: false
|
|
73
84
|
}
|
|
74
|
-
)
|
|
85
|
+
),
|
|
86
|
+
resolvedName ? /* @__PURE__ */ jsx("input", { type: "hidden", name: resolvedName, value, readOnly: true }) : null
|
|
75
87
|
] });
|
|
76
88
|
}
|
|
77
89
|
export {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import type { ControlStatusProp, ControlVariantProp } from "../../props/vocabulary/index.js";
|
|
3
|
+
import type { ControlCountProp } from "../../props/components/data-entry.prop.js";
|
|
4
|
+
/**
|
|
5
|
+
* The two appearance axes Ant Design puts on every text field — `status` and `variant` — resolved
|
|
6
|
+
* once, here, so Input / Textarea / NumberInput / PasswordInput / SearchInput cannot drift into
|
|
7
|
+
* three different spellings of "this field is wrong".
|
|
8
|
+
*
|
|
9
|
+
* WHY A HELPER AND NOT A CLASS PER COMPONENT. `status` has a SECOND half that is not paint:
|
|
10
|
+
* `error` must also report `aria-invalid`, or the red boundary is a lie to a screen reader. That
|
|
11
|
+
* pairing is the thing worth keeping in one place; the CSS is the easy half.
|
|
12
|
+
*/
|
|
13
|
+
export type ControlAppearanceInput = {
|
|
14
|
+
status?: ControlStatusProp;
|
|
15
|
+
variant?: ControlVariantProp;
|
|
16
|
+
"aria-invalid"?: React.AriaAttributes["aria-invalid"];
|
|
17
|
+
};
|
|
18
|
+
export type ControlAppearanceAttributes = {
|
|
19
|
+
"data-status"?: ControlStatusProp;
|
|
20
|
+
"data-variant"?: ControlVariantProp;
|
|
21
|
+
"aria-invalid"?: React.AriaAttributes["aria-invalid"];
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* `status="error"` REPORTS `aria-invalid` — unless the caller (or FormField, which injects it)
|
|
25
|
+
* already said something, in which case the explicit value wins and nothing is overwritten.
|
|
26
|
+
* `status="warning"` deliberately reports nothing: a warning is not a validity failure, and
|
|
27
|
+
* antd does not announce one either (es/_util/statusUtils.js only reaches for the class name).
|
|
28
|
+
*/
|
|
29
|
+
export declare function controlAppearanceAttributes({ status, variant, "aria-invalid": ariaInvalid, }: ControlAppearanceInput): ControlAppearanceAttributes;
|
|
30
|
+
/**
|
|
31
|
+
* The chrome utilities a variant carries, kept in the COMPONENT rather than in `control.css`.
|
|
32
|
+
*
|
|
33
|
+
* A Tailwind utility lives in `@layer utilities`, which outranks `@layer components` no matter
|
|
34
|
+
* how specific the component rule is — so `bg-background` baked unconditionally into the class
|
|
35
|
+
* list would silently defeat `filled` and `borderless` and no gate would notice. The outlined
|
|
36
|
+
* field therefore keeps exactly the utilities it always had, and the other two simply do not
|
|
37
|
+
* receive them; their surface comes from `.ui-control--filled` / `.ui-control--borderless`.
|
|
38
|
+
*/
|
|
39
|
+
export declare const CONTROL_VARIANT_CHROME_CLASS: Record<ControlVariantProp, string>;
|
|
40
|
+
/**
|
|
41
|
+
* The status BOUNDARY, for the same cascade-layer reason — and this one was measured the hard way.
|
|
42
|
+
*
|
|
43
|
+
* `.ui-control[data-status="warning"] { border-color: … }` in `@layer components` renders exactly
|
|
44
|
+
* nothing: `border-input` is a utility, utilities are a later layer, and a later layer wins over
|
|
45
|
+
* any specificity. In Chromium the warned field measured `rgb(144 135 127)` — the resting border —
|
|
46
|
+
* with the component rule in place and no error anywhere. Painting it from a utility instead puts
|
|
47
|
+
* the two declarations in the SAME layer, where `data-[status=…]` (0,2,0) genuinely outranks
|
|
48
|
+
* `border-input` (0,1,0). It is also the mechanism the library already used for the invalid state
|
|
49
|
+
* (`aria-invalid:border-destructive`), so the two states now paint the same way.
|
|
50
|
+
*
|
|
51
|
+
* The `--focus-*` reassignments stay in `control.css`: those are custom properties, and no utility
|
|
52
|
+
* competes for them.
|
|
53
|
+
*/
|
|
54
|
+
export declare const CONTROL_STATUS_CHROME_CLASS = "data-[status=error]:border-destructive data-[status=warning]:border-warning";
|
|
55
|
+
/** Default `count.strategy` — code points, so a surrogate pair counts once. */
|
|
56
|
+
export declare function countCodePoints(value: string): number;
|
|
57
|
+
export type ResolvedControlCount = {
|
|
58
|
+
count: number;
|
|
59
|
+
max?: number;
|
|
60
|
+
exceeded: boolean;
|
|
61
|
+
content: React.ReactNode;
|
|
62
|
+
};
|
|
63
|
+
/** `null` when the counter is switched off (no `count`, or `count.show === false`). */
|
|
64
|
+
export declare function resolveControlCount(config: ControlCountProp | undefined, value: string): ResolvedControlCount | null;
|