@godxjp/ui 18.15.4 → 19.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/date-format-labels.d.ts +1 -1
- package/dist/app/time-format-labels.d.ts +1 -1
- package/dist/components/data-display/badge.d.ts +1 -1
- package/dist/components/data-display/card.d.ts +4 -13
- package/dist/components/data-display/card.js +2 -15
- package/dist/components/data-display/data-table.d.ts +3 -8
- package/dist/components/data-display/data-table.js +106 -68
- package/dist/components/data-display/descriptions.js +34 -5
- package/dist/components/data-display/empty-state.js +1 -1
- package/dist/components/data-display/permission-matrix.js +7 -7
- package/dist/components/data-display/popover.js +2 -9
- package/dist/components/data-display/qr-code.d.ts +1 -1
- package/dist/components/data-display/scroll-area.d.ts +3 -1
- package/dist/components/data-display/scroll-area.js +150 -16
- package/dist/components/data-display/table.js +12 -3
- package/dist/components/data-entry/branch-scope-picker.js +4 -4
- package/dist/components/data-entry/calendar.js +15 -24
- package/dist/components/data-entry/cascader.js +67 -71
- package/dist/components/data-entry/checkbox.js +9 -1
- package/dist/components/data-entry/command.d.ts +6 -6
- package/dist/components/data-entry/date-picker.js +28 -15
- package/dist/components/data-entry/date-range-picker.js +10 -10
- package/dist/components/data-entry/form-field.js +7 -3
- package/dist/components/data-entry/index.d.ts +2 -1
- package/dist/components/data-entry/input.js +8 -19
- package/dist/components/data-entry/label.js +4 -2
- package/dist/components/data-entry/month-picker.js +16 -15
- package/dist/components/data-entry/month-range-picker.js +17 -16
- package/dist/components/data-entry/radio.js +6 -1
- package/dist/components/data-entry/search-select.js +29 -29
- package/dist/components/data-entry/select.js +15 -18
- package/dist/components/data-entry/switch.js +7 -1
- package/dist/components/data-entry/textarea.d.ts +56 -0
- package/dist/components/data-entry/textarea.js +103 -40
- package/dist/components/data-entry/time-picker.js +52 -52
- package/dist/components/data-entry/toggle-group.d.ts +1 -0
- package/dist/components/data-entry/toggle.d.ts +1 -1
- package/dist/components/data-entry/transfer.js +14 -15
- package/dist/components/data-entry/tree-select.js +16 -22
- package/dist/components/data-entry/upload-crop-dialog.js +4 -4
- package/dist/components/data-entry/upload.d.ts +1 -1
- package/dist/components/data-entry/upload.js +46 -46
- package/dist/components/feedback/alert.js +7 -14
- package/dist/components/feedback/dialog.d.ts +23 -32
- package/dist/components/feedback/dialog.js +16 -13
- package/dist/components/feedback/sheet.d.ts +1 -1
- package/dist/components/feedback/sheet.js +14 -14
- package/dist/components/feedback/skeleton.js +13 -10
- package/dist/components/feedback/sonner.d.ts +1 -1
- package/dist/components/feedback/sonner.js +17 -8
- package/dist/components/feedback/tooltip.js +1 -1
- package/dist/components/general/activity.d.ts +44 -0
- package/dist/components/general/activity.js +65 -0
- package/dist/components/general/button.d.ts +2 -2
- package/dist/components/general/button.js +11 -24
- package/dist/components/general/index.d.ts +2 -0
- package/dist/components/general/index.js +2 -0
- package/dist/components/layout/app-shell.js +5 -3
- package/dist/components/layout/auth-divider.d.ts +9 -2
- package/dist/components/layout/auth-divider.js +7 -11
- package/dist/components/layout/index.d.ts +1 -0
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +32 -20
- package/dist/components/layout/resizable.d.ts +12 -12
- package/dist/components/layout/separator.d.ts +1 -0
- package/dist/components/layout/service-role-panel.js +47 -42
- package/dist/components/layout/sidebar.js +13 -1
- package/dist/components/layout/split-pane.d.ts +12 -1
- package/dist/components/layout/split-pane.js +13 -4
- package/dist/components/navigation/app-setting-picker.js +5 -14
- package/dist/components/navigation/dropdown-menu.js +10 -16
- package/dist/components/navigation/menubar.d.ts +3 -6
- package/dist/components/navigation/pagination-utils.d.ts +15 -2
- package/dist/components/navigation/pagination-utils.js +27 -21
- package/dist/components/navigation/pagination.d.ts +4 -4
- package/dist/components/navigation/pagination.js +2 -2
- package/dist/components/navigation/steps.js +31 -67
- package/dist/components/navigation/tabs.js +17 -5
- package/dist/components/query/infinite-query-state.js +2 -2
- package/dist/components/ui/accordion.d.ts +1 -1
- package/dist/components/ui/avatar.d.ts +1 -1
- package/dist/components/ui/avatar.js +29 -10
- package/dist/components/ui/input-otp.d.ts +8 -6
- package/dist/components/ui/rating.js +1 -1
- package/dist/components/ui/separator.d.ts +27 -2
- package/dist/components/ui/separator.js +42 -11
- package/dist/components/ui/toggle-group.d.ts +15 -5
- package/dist/components/ui/toggle-group.js +43 -18
- package/dist/components/ui/toggle.d.ts +66 -5
- package/dist/components/ui/toggle.js +64 -9
- package/dist/i18n/messages/en.json +8 -0
- package/dist/i18n/messages/ja.json +8 -0
- package/dist/i18n/messages/vi.json +8 -0
- package/dist/lib/control-styles.d.ts +14 -0
- package/dist/lib/control-styles.js +2 -0
- package/dist/props/components/data-display.prop.d.ts +85 -3
- package/dist/props/components/data-entry.prop.d.ts +17 -0
- package/dist/props/components/general.prop.d.ts +52 -1
- package/dist/props/components/layout.prop.d.ts +137 -2
- package/dist/props/registry.d.ts +116 -5
- package/dist/props/registry.js +165 -4
- package/dist/props/vocabulary/index.d.ts +2 -2
- package/dist/props/vocabulary/interaction.prop.d.ts +15 -0
- package/dist/props/vocabulary/layout.prop.d.ts +8 -0
- package/dist/styles/alert-layout.css +69 -3
- package/dist/styles/badge-layout.css +2 -2
- package/dist/styles/base.css +6 -0
- package/dist/styles/card-layout.css +25 -8
- package/dist/styles/control.css +1150 -29
- package/dist/styles/data-display-layout.css +185 -11
- package/dist/styles/data-entry-layout.css +352 -1
- package/dist/styles/density.css +2 -2
- package/dist/styles/dialog-layout.css +203 -4
- package/dist/styles/focus-ring.css +155 -0
- package/dist/styles/form-layout.css +50 -5
- package/dist/styles/index.css +1 -0
- package/dist/styles/layout.css +412 -23
- package/dist/styles/motion.css +178 -0
- package/dist/styles/navigation-layout.css +398 -22
- package/dist/styles/shell-layout.css +137 -39
- package/dist/styles/table-layout.css +153 -22
- package/dist/styles/toggle.css +59 -0
- package/dist/tokens/base.css +5 -0
- package/dist/tokens/components/activity.css +64 -0
- package/dist/tokens/components/badge.css +7 -0
- package/dist/tokens/components/card.css +14 -10
- package/dist/tokens/components/chart.css +1 -1
- package/dist/tokens/components/control.css +358 -8
- package/dist/tokens/components/data-display.css +75 -0
- package/dist/tokens/components/data-entry.css +25 -0
- package/dist/tokens/components/descriptions.css +22 -0
- package/dist/tokens/components/feedback.css +143 -4
- package/dist/tokens/components/form.css +16 -0
- package/dist/tokens/components/legal-document.css +5 -1
- package/dist/tokens/components/navigation.css +109 -0
- package/dist/tokens/components/scroll-area.css +21 -0
- package/dist/tokens/components/separator.css +52 -0
- package/dist/tokens/components/shell.css +132 -20
- package/dist/tokens/components/table.css +52 -3
- package/dist/tokens/components/toggle.css +82 -0
- package/dist/tokens/components/upload.css +107 -0
- package/dist/tokens/foundation.css +171 -10
- package/dist/tokens/semantic/layout.css +120 -1
- package/package.json +84 -68
- package/scripts/ui-audit.mjs +51 -2
|
@@ -3,19 +3,153 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
const ANCHOR_OFFSET_TOKEN = "--scroll-area-anchor-offset";
|
|
7
|
+
const ANCHOR_OFFSET_FALLBACK_PX = 48;
|
|
8
|
+
const ROOT_FONT_SIZE_FALLBACK_PX = 16;
|
|
9
|
+
function cssLengthToPx(value, rootFontSize) {
|
|
10
|
+
const match = /^(-?\d*\.?\d+)(px|rem|em)?$/.exec(value.trim());
|
|
11
|
+
if (match == null) return void 0;
|
|
12
|
+
const amount = Number(match[1]);
|
|
13
|
+
if (!Number.isFinite(amount)) return void 0;
|
|
14
|
+
return match[2] === "rem" || match[2] === "em" ? amount * rootFontSize : amount;
|
|
15
|
+
}
|
|
16
|
+
function readAnchorOffset(element) {
|
|
17
|
+
if (typeof window === "undefined" || typeof window.getComputedStyle !== "function") {
|
|
18
|
+
return ANCHOR_OFFSET_FALLBACK_PX;
|
|
17
19
|
}
|
|
18
|
-
|
|
20
|
+
const rootFontSize = cssLengthToPx(
|
|
21
|
+
window.getComputedStyle(element.ownerDocument.documentElement).fontSize || "",
|
|
22
|
+
ROOT_FONT_SIZE_FALLBACK_PX
|
|
23
|
+
) ?? ROOT_FONT_SIZE_FALLBACK_PX;
|
|
24
|
+
const declared = window.getComputedStyle(element).getPropertyValue(ANCHOR_OFFSET_TOKEN);
|
|
25
|
+
return cssLengthToPx(declared, rootFontSize) ?? ANCHOR_OFFSET_FALLBACK_PX;
|
|
26
|
+
}
|
|
27
|
+
function resolveRowContainer(root) {
|
|
28
|
+
let container = root;
|
|
29
|
+
while (container.children.length === 1 && container.firstElementChild) {
|
|
30
|
+
container = container.firstElementChild;
|
|
31
|
+
}
|
|
32
|
+
return container;
|
|
33
|
+
}
|
|
34
|
+
function findAnchorChild(root, scrollTop) {
|
|
35
|
+
const children = resolveRowContainer(root).children;
|
|
36
|
+
let low = 0;
|
|
37
|
+
let high = children.length - 1;
|
|
38
|
+
let found = null;
|
|
39
|
+
while (low <= high) {
|
|
40
|
+
const mid = Math.floor((low + high) / 2);
|
|
41
|
+
const child = children[mid];
|
|
42
|
+
if (!(child instanceof HTMLElement)) break;
|
|
43
|
+
if (child.offsetTop + child.offsetHeight > scrollTop) {
|
|
44
|
+
found = child;
|
|
45
|
+
high = mid - 1;
|
|
46
|
+
} else {
|
|
47
|
+
low = mid + 1;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return found;
|
|
51
|
+
}
|
|
52
|
+
function setScrollOffset(element, top) {
|
|
53
|
+
if (typeof element.scrollTo === "function") element.scrollTo({ top, behavior: "instant" });
|
|
54
|
+
else element.scrollTop = top;
|
|
55
|
+
}
|
|
56
|
+
function useBottomAnchor(viewport, enabled, offset, onAnchoredChange) {
|
|
57
|
+
const onAnchoredChangeRef = React.useRef(onAnchoredChange);
|
|
58
|
+
React.useEffect(() => {
|
|
59
|
+
onAnchoredChangeRef.current = onAnchoredChange;
|
|
60
|
+
}, [onAnchoredChange]);
|
|
61
|
+
React.useEffect(() => {
|
|
62
|
+
if (!viewport || !enabled) return;
|
|
63
|
+
const content = viewport.firstElementChild ?? viewport;
|
|
64
|
+
const band = offset ?? readAnchorOffset(viewport);
|
|
65
|
+
let anchored = true;
|
|
66
|
+
let record = null;
|
|
67
|
+
const distanceFromBottom = () => viewport.scrollHeight - viewport.clientHeight - viewport.scrollTop;
|
|
68
|
+
const setAnchored = (next) => {
|
|
69
|
+
if (anchored === next) return;
|
|
70
|
+
anchored = next;
|
|
71
|
+
onAnchoredChangeRef.current?.(next);
|
|
72
|
+
};
|
|
73
|
+
const remember = () => {
|
|
74
|
+
const node = findAnchorChild(content, viewport.scrollTop);
|
|
75
|
+
record = node ? { node, top: node.offsetTop - viewport.scrollTop } : null;
|
|
76
|
+
};
|
|
77
|
+
const pinToBottom = () => {
|
|
78
|
+
setScrollOffset(viewport, Math.max(0, viewport.scrollHeight - viewport.clientHeight));
|
|
79
|
+
};
|
|
80
|
+
const handleScroll = () => {
|
|
81
|
+
setAnchored(distanceFromBottom() <= band);
|
|
82
|
+
remember();
|
|
83
|
+
};
|
|
84
|
+
const handleContentChange = () => {
|
|
85
|
+
if (anchored) {
|
|
86
|
+
pinToBottom();
|
|
87
|
+
} else if (record && viewport.contains(record.node)) {
|
|
88
|
+
const target = Math.max(0, record.node.offsetTop - record.top);
|
|
89
|
+
if (target !== viewport.scrollTop) setScrollOffset(viewport, target);
|
|
90
|
+
setAnchored(distanceFromBottom() <= band);
|
|
91
|
+
}
|
|
92
|
+
remember();
|
|
93
|
+
};
|
|
94
|
+
pinToBottom();
|
|
95
|
+
remember();
|
|
96
|
+
viewport.addEventListener("scroll", handleScroll, { passive: true });
|
|
97
|
+
const observers = [];
|
|
98
|
+
if (typeof MutationObserver !== "undefined") {
|
|
99
|
+
const mutationObserver = new MutationObserver(handleContentChange);
|
|
100
|
+
mutationObserver.observe(content, { childList: true, subtree: true, characterData: true });
|
|
101
|
+
observers.push(mutationObserver);
|
|
102
|
+
}
|
|
103
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
104
|
+
const resizeObserver = new ResizeObserver(handleContentChange);
|
|
105
|
+
resizeObserver.observe(viewport);
|
|
106
|
+
resizeObserver.observe(content);
|
|
107
|
+
observers.push(resizeObserver);
|
|
108
|
+
}
|
|
109
|
+
return () => {
|
|
110
|
+
viewport.removeEventListener("scroll", handleScroll);
|
|
111
|
+
for (const observer of observers) observer.disconnect();
|
|
112
|
+
};
|
|
113
|
+
}, [viewport, enabled, offset]);
|
|
114
|
+
}
|
|
115
|
+
const ScrollArea = React.forwardRef(
|
|
116
|
+
({ className, children, viewportRef, anchor = "none", anchorOffset, onAnchoredChange, ...props }, ref) => {
|
|
117
|
+
const [viewport, setViewport] = React.useState(null);
|
|
118
|
+
const attachViewport = React.useCallback(
|
|
119
|
+
(node) => {
|
|
120
|
+
setViewport(node);
|
|
121
|
+
if (typeof viewportRef === "function") viewportRef(node);
|
|
122
|
+
else if (viewportRef)
|
|
123
|
+
viewportRef.current = node;
|
|
124
|
+
},
|
|
125
|
+
[viewportRef]
|
|
126
|
+
);
|
|
127
|
+
useBottomAnchor(viewport, anchor === "bottom", anchorOffset, onAnchoredChange);
|
|
128
|
+
return /* @__PURE__ */ jsxs(
|
|
129
|
+
ScrollAreaPrimitive.Root,
|
|
130
|
+
{
|
|
131
|
+
ref,
|
|
132
|
+
className: cn("relative overflow-hidden", className),
|
|
133
|
+
...props,
|
|
134
|
+
children: [
|
|
135
|
+
/* @__PURE__ */ jsx(
|
|
136
|
+
ScrollAreaPrimitive.Viewport,
|
|
137
|
+
{
|
|
138
|
+
ref: attachViewport,
|
|
139
|
+
tabIndex: 0,
|
|
140
|
+
"data-slot": "scroll-area-viewport",
|
|
141
|
+
"data-anchor": anchor,
|
|
142
|
+
className: "size-full rounded-[inherit]",
|
|
143
|
+
children
|
|
144
|
+
}
|
|
145
|
+
),
|
|
146
|
+
/* @__PURE__ */ jsx(ScrollBar, {}),
|
|
147
|
+
/* @__PURE__ */ jsx(ScrollAreaPrimitive.Corner, {})
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
);
|
|
19
153
|
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
20
154
|
const ScrollBar = React.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx(
|
|
21
155
|
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
@@ -23,13 +157,13 @@ const ScrollBar = React.forwardRef(({ className, orientation = "vertical", ...pr
|
|
|
23
157
|
ref,
|
|
24
158
|
orientation,
|
|
25
159
|
className: cn(
|
|
26
|
-
"flex touch-none transition-colors select-none",
|
|
27
|
-
orientation === "vertical" && "h-full
|
|
28
|
-
orientation === "horizontal" && "
|
|
160
|
+
"ui-scroll-area-bar flex touch-none transition-colors select-none",
|
|
161
|
+
orientation === "vertical" && "ui-scroll-area-bar--vertical h-full border-s border-s-transparent",
|
|
162
|
+
orientation === "horizontal" && "ui-scroll-area-bar--horizontal flex-col border-t border-t-transparent",
|
|
29
163
|
className
|
|
30
164
|
),
|
|
31
165
|
...props,
|
|
32
|
-
children: /* @__PURE__ */ jsx(ScrollAreaPrimitive.ScrollAreaThumb, { className: "bg-border relative flex-1
|
|
166
|
+
children: /* @__PURE__ */ jsx(ScrollAreaPrimitive.ScrollAreaThumb, { className: "ui-scroll-area-thumb bg-border relative flex-1" })
|
|
33
167
|
}
|
|
34
168
|
));
|
|
35
169
|
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
|
@@ -34,7 +34,7 @@ const Table = React.forwardRef(
|
|
|
34
34
|
{
|
|
35
35
|
ref,
|
|
36
36
|
"data-slot": "table",
|
|
37
|
-
className: cn("w-full caption-bottom
|
|
37
|
+
className: cn("w-full caption-bottom", bordered && "ui-table-bordered", className),
|
|
38
38
|
...props
|
|
39
39
|
}
|
|
40
40
|
)
|
|
@@ -45,14 +45,23 @@ const Table = React.forwardRef(
|
|
|
45
45
|
Table.displayName = "Table";
|
|
46
46
|
const TableHeader = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
|
|
47
47
|
TableHeader.displayName = "TableHeader";
|
|
48
|
-
const TableBody = React.forwardRef(({ className, ...props }, ref) =>
|
|
48
|
+
const TableBody = React.forwardRef(({ className, ...props }, ref) => (
|
|
49
|
+
// "The last row draws no rule" is an idiom, not a service-tunable constant, so it is a CSS
|
|
50
|
+
// rule (`[data-slot="table-body"] .ui-table-row:last-child`) rather than a utility. That only
|
|
51
|
+
// works because TableRow's own bottom rule moved to `.ui-table-row` in the same layer: while
|
|
52
|
+
// the row carried a `border-b` UTILITY, no `components` rule could ever zero it (gh#412).
|
|
53
|
+
/* @__PURE__ */ jsx("tbody", { ref, "data-slot": "table-body", className: cn(className), ...props })
|
|
54
|
+
));
|
|
49
55
|
TableBody.displayName = "TableBody";
|
|
50
56
|
const TableRow = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
51
57
|
"tr",
|
|
52
58
|
{
|
|
53
59
|
ref,
|
|
54
60
|
className: cn(
|
|
55
|
-
|
|
61
|
+
// The row rule itself is `.ui-table-row` in table-layout.css (--table-row-border-width),
|
|
62
|
+
// NOT a `border-b` utility — a utility sits in `@layer utilities` and would outrank the
|
|
63
|
+
// `components` rule that has to zero it on the last row (gh#319).
|
|
64
|
+
"ui-table-row hover:bg-accent/70 data-[state=selected]:bg-primary/[0.06] transition-colors",
|
|
56
65
|
className
|
|
57
66
|
),
|
|
58
67
|
...props
|
|
@@ -66,7 +66,7 @@ const BranchScopePicker = React.forwardRef(
|
|
|
66
66
|
id: rootId,
|
|
67
67
|
"data-slot": "branch-scope-picker",
|
|
68
68
|
"data-readonly": readOnly || void 0,
|
|
69
|
-
className: cn("ui-branch-scope-picker
|
|
69
|
+
className: cn("ui-branch-scope-picker", className),
|
|
70
70
|
children
|
|
71
71
|
}
|
|
72
72
|
);
|
|
@@ -113,7 +113,7 @@ const BranchScopePicker = React.forwardRef(
|
|
|
113
113
|
return surface(
|
|
114
114
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
115
115
|
/* @__PURE__ */ jsx(Text, { size: "sm", weight: "medium", children: value.mode === "all" ? resolvedAllLabel : resolvedSelectedLabel }),
|
|
116
|
-
value.mode === "selected" && /* @__PURE__ */ jsx("div", { className: "
|
|
116
|
+
value.mode === "selected" && /* @__PURE__ */ jsx("div", { className: "ui-branch-scope-picker-badges", children: selectedBranches.map((branch) => /* @__PURE__ */ jsx(Badge, { variant: "outline", children: branch.name }, branch.id)) })
|
|
117
117
|
] })
|
|
118
118
|
);
|
|
119
119
|
}
|
|
@@ -145,7 +145,7 @@ const BranchScopePicker = React.forwardRef(
|
|
|
145
145
|
"aria-errormessage": invalid ? mergeAriaIds(errorId, fieldA11y["aria-errormessage"]) : void 0
|
|
146
146
|
}
|
|
147
147
|
),
|
|
148
|
-
value.mode === "selected" && /* @__PURE__ */ jsxs("div", { className: "
|
|
148
|
+
value.mode === "selected" && /* @__PURE__ */ jsxs("div", { className: "ui-branch-scope-picker-subset", children: [
|
|
149
149
|
searchable && branches.length > 0 && /* @__PURE__ */ jsx(
|
|
150
150
|
SearchInput,
|
|
151
151
|
{
|
|
@@ -169,7 +169,7 @@ const BranchScopePicker = React.forwardRef(
|
|
|
169
169
|
role: "group",
|
|
170
170
|
"aria-label": t("dataEntry.branchScope.listLabel"),
|
|
171
171
|
tabIndex: 0,
|
|
172
|
-
className: "
|
|
172
|
+
className: "ui-branch-scope-picker-list",
|
|
173
173
|
children: /* @__PURE__ */ jsx(
|
|
174
174
|
CheckboxGroup,
|
|
175
175
|
{
|
|
@@ -23,50 +23,41 @@ function Calendar({
|
|
|
23
23
|
...labels,
|
|
24
24
|
labelNav: labels?.labelNav ?? (() => `${ariaLabel ?? "Calendar"} navigation`)
|
|
25
25
|
},
|
|
26
|
-
className: cn("
|
|
26
|
+
className: cn("ui-calendar", className),
|
|
27
27
|
classNames: {
|
|
28
|
-
months: cn("
|
|
29
|
-
month: cn("
|
|
30
|
-
month_caption: cn(
|
|
31
|
-
|
|
32
|
-
classNames?.month_caption
|
|
33
|
-
),
|
|
34
|
-
caption_label: cn("text-sm font-medium", classNames?.caption_label),
|
|
28
|
+
months: cn("ui-calendar-months", classNames?.months),
|
|
29
|
+
month: cn("ui-calendar-month", classNames?.month),
|
|
30
|
+
month_caption: cn("ui-calendar-caption", classNames?.month_caption),
|
|
31
|
+
caption_label: cn("ui-calendar-caption-label", classNames?.caption_label),
|
|
35
32
|
// z-10 is load-bearing: `month` below is position:relative and later in the DOM, so
|
|
36
33
|
// without a z-index it paints OVER these buttons — they render but never receive the
|
|
37
34
|
// click (the month caption swallows it) and the calendar looks frozen.
|
|
38
|
-
nav: cn(
|
|
39
|
-
"absolute inset-x-0 top-3 z-10 flex items-center justify-between px-1",
|
|
40
|
-
classNames?.nav
|
|
41
|
-
),
|
|
35
|
+
nav: cn("ui-calendar-nav", classNames?.nav),
|
|
42
36
|
button_previous: cn(
|
|
43
37
|
buttonVariants({ variant: "outline" }),
|
|
44
38
|
controlIconSmClass,
|
|
45
|
-
"
|
|
39
|
+
"ui-calendar-nav-button",
|
|
46
40
|
classNames?.button_previous
|
|
47
41
|
),
|
|
48
42
|
button_next: cn(
|
|
49
43
|
buttonVariants({ variant: "outline" }),
|
|
50
44
|
controlIconSmClass,
|
|
51
|
-
"
|
|
45
|
+
"ui-calendar-nav-button",
|
|
52
46
|
classNames?.button_next
|
|
53
47
|
),
|
|
54
|
-
month_grid: cn("
|
|
48
|
+
month_grid: cn("ui-calendar-grid", classNames?.month_grid),
|
|
55
49
|
weekdays: cn("flex", classNames?.weekdays),
|
|
56
|
-
weekday: cn(
|
|
57
|
-
|
|
58
|
-
classNames?.weekday
|
|
59
|
-
),
|
|
60
|
-
week: cn("mt-2 flex w-full", classNames?.week),
|
|
50
|
+
weekday: cn("ui-calendar-weekday", classNames?.weekday),
|
|
51
|
+
week: cn("ui-calendar-week", classNames?.week),
|
|
61
52
|
day: cn(
|
|
62
|
-
"
|
|
53
|
+
"ui-calendar-day",
|
|
63
54
|
"[&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50",
|
|
64
55
|
"[&:has([aria-selected].day-range-end)]:rounded-e-md",
|
|
65
56
|
classNames?.day
|
|
66
57
|
),
|
|
67
58
|
day_button: cn(
|
|
68
59
|
buttonVariants({ variant: "ghost" }),
|
|
69
|
-
"
|
|
60
|
+
"ui-calendar-day-button",
|
|
70
61
|
classNames?.day_button
|
|
71
62
|
),
|
|
72
63
|
range_start: cn("day-range-start rounded-s-md", classNames?.range_start),
|
|
@@ -88,14 +79,14 @@ function Calendar({
|
|
|
88
79
|
"day-outside text-muted-foreground aria-selected:text-muted-foreground",
|
|
89
80
|
classNames?.outside
|
|
90
81
|
),
|
|
91
|
-
disabled: cn("
|
|
82
|
+
disabled: cn("ui-calendar-day-disabled", classNames?.disabled),
|
|
92
83
|
hidden: cn("invisible", classNames?.hidden),
|
|
93
84
|
...classNames
|
|
94
85
|
},
|
|
95
86
|
components: {
|
|
96
87
|
Chevron: ({ orientation, className: chevronClassName }) => {
|
|
97
88
|
const Icon = orientation === "left" ? ChevronLeft : ChevronRight;
|
|
98
|
-
return /* @__PURE__ */ jsx(Icon, { className: cn("
|
|
89
|
+
return /* @__PURE__ */ jsx(Icon, { className: cn("ui-calendar-chevron", chevronClassName), "aria-hidden": "true" });
|
|
99
90
|
}
|
|
100
91
|
},
|
|
101
92
|
...props,
|
|
@@ -38,12 +38,12 @@ function CheckboxVisual({
|
|
|
38
38
|
"aria-hidden": "true",
|
|
39
39
|
"data-slot": "checkbox",
|
|
40
40
|
"data-state": state,
|
|
41
|
+
"data-disabled": disabled ? "" : void 0,
|
|
41
42
|
className: cn(
|
|
42
43
|
"ui-checkbox inline-flex items-center justify-center",
|
|
43
44
|
// The shared CSS fills the box for [data-state=checked]; mirror that fill for the
|
|
44
45
|
// indeterminate ("some children selected") state so a partial parent reads as partial.
|
|
45
46
|
"data-[state=indeterminate]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground",
|
|
46
|
-
disabled && "cursor-not-allowed opacity-50",
|
|
47
47
|
className
|
|
48
48
|
),
|
|
49
49
|
children: indeterminate ? /* @__PURE__ */ jsx(Minus, { className: "ui-checkbox-icon", "aria-hidden": "true" }) : checked ? /* @__PURE__ */ jsx(Check, { className: "ui-checkbox-icon", "aria-hidden": "true" }) : null
|
|
@@ -175,13 +175,13 @@ function Cascader({
|
|
|
175
175
|
else commitSingle([]);
|
|
176
176
|
};
|
|
177
177
|
const renderCascadeColumns = () => /* @__PURE__ */ jsxs(ScrollArea, { className: "w-full", children: [
|
|
178
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
178
|
+
/* @__PURE__ */ jsx("div", { className: "ui-cascader-columns", children: columns.map((col, colIndex) => /* @__PURE__ */ jsx(
|
|
179
179
|
"ul",
|
|
180
180
|
{
|
|
181
181
|
role: "listbox",
|
|
182
182
|
"aria-orientation": "vertical",
|
|
183
183
|
"aria-multiselectable": multiple ? true : void 0,
|
|
184
|
-
className: "
|
|
184
|
+
className: "ui-cascader-column",
|
|
185
185
|
children: col.map((node) => {
|
|
186
186
|
const path = [...activePath.slice(0, colIndex), node.value];
|
|
187
187
|
const hasChildren = (node.children?.length ?? 0) > 0 && node.isLeaf !== true;
|
|
@@ -197,11 +197,11 @@ function Cascader({
|
|
|
197
197
|
"aria-haspopup": hasChildren ? "menu" : void 0,
|
|
198
198
|
"aria-expanded": hasChildren ? active : void 0,
|
|
199
199
|
disabled: node.disabled,
|
|
200
|
+
"data-disabled": node.disabled ? "" : void 0,
|
|
200
201
|
className: cn(
|
|
201
|
-
"
|
|
202
|
+
"ui-cascader-option",
|
|
202
203
|
"hover:bg-accent hover:text-accent-foreground",
|
|
203
|
-
active && "bg-accent/70 font-medium"
|
|
204
|
-
node.disabled && "pointer-events-none opacity-50"
|
|
204
|
+
active && "bg-accent/70 font-medium"
|
|
205
205
|
),
|
|
206
206
|
onMouseEnter: (
|
|
207
207
|
// Hover-expand: a parent opens its children column; a leaf collapses any
|
|
@@ -221,9 +221,9 @@ function Cascader({
|
|
|
221
221
|
className: "me-1"
|
|
222
222
|
}
|
|
223
223
|
),
|
|
224
|
-
!multiple && selected && /* @__PURE__ */ jsx(Check, { className: "
|
|
224
|
+
!multiple && selected && /* @__PURE__ */ jsx(Check, { className: "ui-cascader-option-icon", "aria-hidden": "true" }),
|
|
225
225
|
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-start", children: node.label }),
|
|
226
|
-
hasChildren && /* @__PURE__ */ jsx(ChevronRight, { className: "
|
|
226
|
+
hasChildren && /* @__PURE__ */ jsx(ChevronRight, { className: "ui-cascader-option-chevron", "aria-hidden": "true" })
|
|
227
227
|
]
|
|
228
228
|
}
|
|
229
229
|
) }, node.value);
|
|
@@ -252,81 +252,77 @@ function Cascader({
|
|
|
252
252
|
"w-full justify-start font-normal",
|
|
253
253
|
controlOpenRingClass,
|
|
254
254
|
// Reserve trailing room for the single clear-or-chevron overlay rendered below.
|
|
255
|
-
"
|
|
255
|
+
"ui-control-trigger-affixed",
|
|
256
256
|
!displayLabel && "text-muted-foreground"
|
|
257
257
|
),
|
|
258
258
|
children: /* @__PURE__ */ jsx("span", { className: "truncate", children: displayLabel ?? resolvedPlaceholder })
|
|
259
259
|
}
|
|
260
260
|
) }),
|
|
261
|
-
/* @__PURE__ */ jsxs(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
"
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
"
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
]
|
|
310
|
-
},
|
|
311
|
-
pathKey(path)
|
|
312
|
-
);
|
|
313
|
-
})
|
|
314
|
-
}
|
|
315
|
-
) }) : renderCascadeColumns()
|
|
316
|
-
]
|
|
317
|
-
}
|
|
318
|
-
)
|
|
261
|
+
/* @__PURE__ */ jsxs(PopoverContent, { id: panelId, className: "ui-cascader-popover", align: "start", children: [
|
|
262
|
+
showSearch && /* @__PURE__ */ jsx(Command, { shouldFilter: false, children: /* @__PURE__ */ jsx(
|
|
263
|
+
CommandInput,
|
|
264
|
+
{
|
|
265
|
+
placeholder: t("dataEntry.cascader.searchPlaceholder"),
|
|
266
|
+
value: search,
|
|
267
|
+
onValueChange: setSearch
|
|
268
|
+
}
|
|
269
|
+
) }),
|
|
270
|
+
isSearching ? /* @__PURE__ */ jsx(ScrollArea, { className: "ui-cascader-list", children: /* @__PURE__ */ jsx(
|
|
271
|
+
"div",
|
|
272
|
+
{
|
|
273
|
+
className: "ui-cascader-panel",
|
|
274
|
+
role: "listbox",
|
|
275
|
+
"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 }) => {
|
|
277
|
+
const label = labels.join(" / ");
|
|
278
|
+
const selected = multiple ? pathInValues(path, multiValue) : pathsEqual(path, singleValue);
|
|
279
|
+
return /* @__PURE__ */ jsxs(
|
|
280
|
+
"button",
|
|
281
|
+
{
|
|
282
|
+
type: "button",
|
|
283
|
+
role: "option",
|
|
284
|
+
"aria-selected": selected,
|
|
285
|
+
className: cn(
|
|
286
|
+
"ui-cascader-result",
|
|
287
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
288
|
+
selected && "bg-accent/60"
|
|
289
|
+
),
|
|
290
|
+
onClick: () => handleSelectNode({ value: path.at(-1), label }, path),
|
|
291
|
+
children: [
|
|
292
|
+
multiple ? /* @__PURE__ */ jsx(CheckboxVisual, { checked: selected, className: "me-2" }) : /* @__PURE__ */ jsx(
|
|
293
|
+
Check,
|
|
294
|
+
{
|
|
295
|
+
className: "ui-cascader-result-icon",
|
|
296
|
+
"data-selected": selected ? "true" : "false",
|
|
297
|
+
"aria-hidden": "true"
|
|
298
|
+
}
|
|
299
|
+
),
|
|
300
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-start", children: label })
|
|
301
|
+
]
|
|
302
|
+
},
|
|
303
|
+
pathKey(path)
|
|
304
|
+
);
|
|
305
|
+
})
|
|
306
|
+
}
|
|
307
|
+
) }) : renderCascadeColumns()
|
|
308
|
+
] })
|
|
319
309
|
] }),
|
|
320
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
310
|
+
/* @__PURE__ */ jsx("div", { className: "ui-control-affix ui-cascader-affix", children: showClear ? /* @__PURE__ */ jsx(
|
|
321
311
|
"button",
|
|
322
312
|
{
|
|
323
313
|
type: "button",
|
|
324
314
|
"aria-label": t("dataEntry.cascader.clear"),
|
|
325
|
-
className: "
|
|
315
|
+
className: "ui-control-affix-action",
|
|
326
316
|
onClick: clearValue,
|
|
327
|
-
children: /* @__PURE__ */ jsx(X, { className: "
|
|
317
|
+
children: /* @__PURE__ */ jsx(X, { className: "ui-control-affix-icon", "aria-hidden": "true" })
|
|
318
|
+
}
|
|
319
|
+
) : /* @__PURE__ */ jsx(
|
|
320
|
+
ChevronsUpDown,
|
|
321
|
+
{
|
|
322
|
+
className: "ui-control-affix-icon ui-control-affix-indicator",
|
|
323
|
+
"aria-hidden": "true"
|
|
328
324
|
}
|
|
329
|
-
)
|
|
325
|
+
) })
|
|
330
326
|
] });
|
|
331
327
|
}
|
|
332
328
|
export {
|
|
@@ -11,7 +11,15 @@ const CheckboxRoot = React.forwardRef(({ className, ...props }, ref) => /* @__PU
|
|
|
11
11
|
ref,
|
|
12
12
|
"data-slot": "checkbox",
|
|
13
13
|
className: cn(
|
|
14
|
-
|
|
14
|
+
// `disabled:cursor-not-allowed disabled:opacity-50` and the checked fill are DELETED, not
|
|
15
|
+
// moved (#319): `.ui-checkbox:disabled, .ui-checkbox[data-disabled]` and
|
|
16
|
+
// `.ui-checkbox[data-state="checked"]` in styles/control.css already declare both, reading
|
|
17
|
+
// --disabled-opacity and --checkbox-checked-background. Utilities are layered AFTER
|
|
18
|
+
// components in Tailwind v4, so these literals were silently OUTRANKING those knobs — a
|
|
19
|
+
// service overriding --checkbox-checked-background got no fill change at all. Radix sets
|
|
20
|
+
// `data-state`/`data-disabled` on the root, so the CSS rules match. Rendering is unchanged:
|
|
21
|
+
// both knobs default to exactly the values these utilities hard-coded.
|
|
22
|
+
"peer ui-checkbox aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground shrink-0 shadow-xs transition-shadow outline-none",
|
|
15
23
|
className
|
|
16
24
|
),
|
|
17
25
|
...props,
|
|
@@ -5,7 +5,7 @@ export declare const Command: React.ForwardRefExoticComponent<Omit<{
|
|
|
5
5
|
ref?: React.Ref<HTMLDivElement>;
|
|
6
6
|
} & {
|
|
7
7
|
asChild?: boolean;
|
|
8
|
-
}, "key" | keyof React.HTMLAttributes<HTMLDivElement
|
|
8
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
9
9
|
label?: string;
|
|
10
10
|
shouldFilter?: boolean;
|
|
11
11
|
filter?: (value: string, search: string, keywords?: string[]) => number;
|
|
@@ -20,7 +20,7 @@ export declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pic
|
|
|
20
20
|
ref?: React.Ref<HTMLInputElement>;
|
|
21
21
|
} & {
|
|
22
22
|
asChild?: boolean;
|
|
23
|
-
}, "
|
|
23
|
+
}, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "type" | "value"> & {
|
|
24
24
|
value?: string;
|
|
25
25
|
onValueChange?: (search: string) => void;
|
|
26
26
|
} & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -30,7 +30,7 @@ export declare const CommandList: React.ForwardRefExoticComponent<Omit<{
|
|
|
30
30
|
ref?: React.Ref<HTMLDivElement>;
|
|
31
31
|
} & {
|
|
32
32
|
asChild?: boolean;
|
|
33
|
-
}, "key" | keyof React.HTMLAttributes<HTMLDivElement
|
|
33
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
34
34
|
label?: string;
|
|
35
35
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
36
36
|
export declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
|
|
@@ -39,14 +39,14 @@ export declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
|
|
|
39
39
|
ref?: React.Ref<HTMLDivElement>;
|
|
40
40
|
} & {
|
|
41
41
|
asChild?: boolean;
|
|
42
|
-
}, "key" | keyof React.HTMLAttributes<HTMLDivElement
|
|
42
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
43
43
|
export declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
|
|
44
44
|
children?: React.ReactNode;
|
|
45
45
|
} & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
46
46
|
ref?: React.Ref<HTMLDivElement>;
|
|
47
47
|
} & {
|
|
48
48
|
asChild?: boolean;
|
|
49
|
-
}, "key" | keyof React.HTMLAttributes<HTMLDivElement
|
|
49
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "heading" | "value"> & {
|
|
50
50
|
heading?: React.ReactNode;
|
|
51
51
|
value?: string;
|
|
52
52
|
forceMount?: boolean;
|
|
@@ -57,7 +57,7 @@ export declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
|
|
|
57
57
|
ref?: React.Ref<HTMLDivElement>;
|
|
58
58
|
} & {
|
|
59
59
|
asChild?: boolean;
|
|
60
|
-
}, "key" | keyof React.HTMLAttributes<HTMLDivElement
|
|
60
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "disabled" | "onSelect" | "value"> & {
|
|
61
61
|
disabled?: boolean;
|
|
62
62
|
onSelect?: (value: string) => void;
|
|
63
63
|
value?: string;
|