@godxjp/ui 18.15.4 → 19.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/dist/app/app-provider.d.ts +1 -1
- package/dist/app/app-provider.js +3 -0
- 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 +70 -72
- package/dist/components/data-entry/checkbox-group.js +12 -5
- package/dist/components/data-entry/checkbox.js +30 -13
- package/dist/components/data-entry/command.d.ts +6 -6
- package/dist/components/data-entry/date-picker.js +34 -17
- package/dist/components/data-entry/date-range-picker.js +19 -13
- package/dist/components/data-entry/form-field.d.ts +1 -1
- package/dist/components/data-entry/form-field.js +22 -5
- package/dist/components/data-entry/index.d.ts +2 -1
- package/dist/components/data-entry/input.js +18 -22
- package/dist/components/data-entry/label.js +4 -2
- package/dist/components/data-entry/month-picker.js +20 -17
- package/dist/components/data-entry/month-range-picker.js +26 -19
- package/dist/components/data-entry/radio.js +25 -6
- package/dist/components/data-entry/search-select.d.ts +1 -1
- package/dist/components/data-entry/search-select.js +37 -31
- package/dist/components/data-entry/select.d.ts +8 -0
- package/dist/components/data-entry/select.js +68 -26
- package/dist/components/data-entry/switch.js +16 -2
- package/dist/components/data-entry/textarea.d.ts +56 -0
- package/dist/components/data-entry/textarea.js +110 -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 +19 -23
- 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/lib/field-a11y.d.ts +52 -0
- package/dist/lib/field-a11y.js +17 -2
- package/dist/props/components/app.prop.d.ts +15 -0
- package/dist/props/components/data-display.prop.d.ts +85 -3
- package/dist/props/components/data-entry.prop.d.ts +35 -2
- 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 +85 -68
- package/scripts/ui-audit.mjs +51 -2
|
@@ -20,7 +20,7 @@ const PopoverContent = React.forwardRef(({ className, align = "center", sideOffs
|
|
|
20
20
|
align,
|
|
21
21
|
sideOffset,
|
|
22
22
|
className: cn(
|
|
23
|
-
"
|
|
23
|
+
"ui-popover-content origin-[var(--radix-popover-content-transform-origin)]",
|
|
24
24
|
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
25
25
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
26
26
|
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
@@ -31,14 +31,7 @@ const PopoverContent = React.forwardRef(({ className, align = "center", sideOffs
|
|
|
31
31
|
}
|
|
32
32
|
) }));
|
|
33
33
|
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
34
|
-
const PopoverHeader = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
35
|
-
"div",
|
|
36
|
-
{
|
|
37
|
-
"data-slot": "popover-header",
|
|
38
|
-
className: cn("flex flex-col gap-1 text-sm", className),
|
|
39
|
-
...props
|
|
40
|
-
}
|
|
41
|
-
);
|
|
34
|
+
const PopoverHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { "data-slot": "popover-header", className: cn("ui-popover-header", className), ...props });
|
|
42
35
|
const PopoverTitle = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { "data-slot": "popover-title", className: cn("font-medium", className), ...props });
|
|
43
36
|
const PopoverDescription = ({
|
|
44
37
|
className,
|
|
@@ -5,4 +5,4 @@ export type QrCodeProps = QrCodeProp & Omit<React.ComponentPropsWithoutRef<"svg"
|
|
|
5
5
|
* Renders a QR code entirely in-process. The encoded value is never sent to a network service,
|
|
6
6
|
* written to an element attribute, or included in accessible text.
|
|
7
7
|
*/
|
|
8
|
-
export declare const QrCode: React.ForwardRefExoticComponent<QrCodeProp & Omit<Omit<React.SVGProps<SVGSVGElement>, "ref">, "
|
|
8
|
+
export declare const QrCode: React.ForwardRefExoticComponent<QrCodeProp & Omit<Omit<React.SVGProps<SVGSVGElement>, "ref">, "children" | "role" | "style" | "type" | keyof QrCodeProp> & React.RefAttributes<SVGSVGElement>>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
3
|
-
|
|
3
|
+
import type { ScrollAreaProp } from "../../props/components/data-display.prop.js";
|
|
4
|
+
export type ScrollAreaProps = ScrollAreaProp & Omit<React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>, keyof ScrollAreaProp>;
|
|
5
|
+
export declare const ScrollArea: React.ForwardRefExoticComponent<ScrollAreaProp & Omit<Omit<ScrollAreaPrimitive.ScrollAreaProps & React.RefAttributes<HTMLDivElement>, "ref">, keyof ScrollAreaProp> & React.RefAttributes<HTMLDivElement>>;
|
|
4
6
|
export declare const ScrollBar: React.ForwardRefExoticComponent<Omit<ScrollAreaPrimitive.ScrollAreaScrollbarProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -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,
|
|
@@ -4,7 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
import { Check, ChevronRight, ChevronsUpDown, Minus, X } from "lucide-react";
|
|
5
5
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
-
import { pickFieldA11y } from "../../lib/field-a11y.js";
|
|
7
|
+
import { pickFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
|
|
8
8
|
import { controlOpenRingClass } from "../../lib/control-styles.js";
|
|
9
9
|
import { Button } from "../general/button.js";
|
|
10
10
|
import { Popover, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
|
|
@@ -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
|
|
@@ -86,6 +86,7 @@ function Cascader({
|
|
|
86
86
|
}) {
|
|
87
87
|
const { t } = useTranslation();
|
|
88
88
|
const fieldA11y = pickFieldA11y(ariaProps);
|
|
89
|
+
const identity = useFieldIdentity({ id, "data-field": fieldA11y["data-field"] });
|
|
89
90
|
const reactId = React.useId();
|
|
90
91
|
const panelId = `${id ?? reactId}-panel`;
|
|
91
92
|
const options = React.useMemo(
|
|
@@ -175,13 +176,13 @@ function Cascader({
|
|
|
175
176
|
else commitSingle([]);
|
|
176
177
|
};
|
|
177
178
|
const renderCascadeColumns = () => /* @__PURE__ */ jsxs(ScrollArea, { className: "w-full", children: [
|
|
178
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
179
|
+
/* @__PURE__ */ jsx("div", { className: "ui-cascader-columns", children: columns.map((col, colIndex) => /* @__PURE__ */ jsx(
|
|
179
180
|
"ul",
|
|
180
181
|
{
|
|
181
182
|
role: "listbox",
|
|
182
183
|
"aria-orientation": "vertical",
|
|
183
184
|
"aria-multiselectable": multiple ? true : void 0,
|
|
184
|
-
className: "
|
|
185
|
+
className: "ui-cascader-column",
|
|
185
186
|
children: col.map((node) => {
|
|
186
187
|
const path = [...activePath.slice(0, colIndex), node.value];
|
|
187
188
|
const hasChildren = (node.children?.length ?? 0) > 0 && node.isLeaf !== true;
|
|
@@ -197,11 +198,11 @@ function Cascader({
|
|
|
197
198
|
"aria-haspopup": hasChildren ? "menu" : void 0,
|
|
198
199
|
"aria-expanded": hasChildren ? active : void 0,
|
|
199
200
|
disabled: node.disabled,
|
|
201
|
+
"data-disabled": node.disabled ? "" : void 0,
|
|
200
202
|
className: cn(
|
|
201
|
-
"
|
|
203
|
+
"ui-cascader-option",
|
|
202
204
|
"hover:bg-accent hover:text-accent-foreground",
|
|
203
|
-
active && "bg-accent/70 font-medium"
|
|
204
|
-
node.disabled && "pointer-events-none opacity-50"
|
|
205
|
+
active && "bg-accent/70 font-medium"
|
|
205
206
|
),
|
|
206
207
|
onMouseEnter: (
|
|
207
208
|
// Hover-expand: a parent opens its children column; a leaf collapses any
|
|
@@ -221,9 +222,9 @@ function Cascader({
|
|
|
221
222
|
className: "me-1"
|
|
222
223
|
}
|
|
223
224
|
),
|
|
224
|
-
!multiple && selected && /* @__PURE__ */ jsx(Check, { className: "
|
|
225
|
+
!multiple && selected && /* @__PURE__ */ jsx(Check, { className: "ui-cascader-option-icon", "aria-hidden": "true" }),
|
|
225
226
|
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-start", children: node.label }),
|
|
226
|
-
hasChildren && /* @__PURE__ */ jsx(ChevronRight, { className: "
|
|
227
|
+
hasChildren && /* @__PURE__ */ jsx(ChevronRight, { className: "ui-cascader-option-chevron", "aria-hidden": "true" })
|
|
227
228
|
]
|
|
228
229
|
}
|
|
229
230
|
) }, node.value);
|
|
@@ -240,6 +241,7 @@ function Cascader({
|
|
|
240
241
|
Button,
|
|
241
242
|
{
|
|
242
243
|
id,
|
|
244
|
+
"data-field": fieldA11y["data-field"] ?? identity["data-field"],
|
|
243
245
|
type: "button",
|
|
244
246
|
variant: "outline",
|
|
245
247
|
role: "combobox",
|
|
@@ -252,81 +254,77 @@ function Cascader({
|
|
|
252
254
|
"w-full justify-start font-normal",
|
|
253
255
|
controlOpenRingClass,
|
|
254
256
|
// Reserve trailing room for the single clear-or-chevron overlay rendered below.
|
|
255
|
-
"
|
|
257
|
+
"ui-control-trigger-affixed",
|
|
256
258
|
!displayLabel && "text-muted-foreground"
|
|
257
259
|
),
|
|
258
260
|
children: /* @__PURE__ */ jsx("span", { className: "truncate", children: displayLabel ?? resolvedPlaceholder })
|
|
259
261
|
}
|
|
260
262
|
) }),
|
|
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
|
-
)
|
|
263
|
+
/* @__PURE__ */ jsxs(PopoverContent, { id: panelId, className: "ui-cascader-popover", align: "start", children: [
|
|
264
|
+
showSearch && /* @__PURE__ */ jsx(Command, { shouldFilter: false, children: /* @__PURE__ */ jsx(
|
|
265
|
+
CommandInput,
|
|
266
|
+
{
|
|
267
|
+
placeholder: t("dataEntry.cascader.searchPlaceholder"),
|
|
268
|
+
value: search,
|
|
269
|
+
onValueChange: setSearch
|
|
270
|
+
}
|
|
271
|
+
) }),
|
|
272
|
+
isSearching ? /* @__PURE__ */ jsx(ScrollArea, { className: "ui-cascader-list", children: /* @__PURE__ */ jsx(
|
|
273
|
+
"div",
|
|
274
|
+
{
|
|
275
|
+
className: "ui-cascader-panel",
|
|
276
|
+
role: "listbox",
|
|
277
|
+
"aria-multiselectable": multiple ? true : void 0,
|
|
278
|
+
children: searchResults.length === 0 ? /* @__PURE__ */ jsx("p", { className: "ui-cascader-empty", children: t("dataEntry.cascader.empty") }) : searchResults.map(({ path, labels }) => {
|
|
279
|
+
const label = labels.join(" / ");
|
|
280
|
+
const selected = multiple ? pathInValues(path, multiValue) : pathsEqual(path, singleValue);
|
|
281
|
+
return /* @__PURE__ */ jsxs(
|
|
282
|
+
"button",
|
|
283
|
+
{
|
|
284
|
+
type: "button",
|
|
285
|
+
role: "option",
|
|
286
|
+
"aria-selected": selected,
|
|
287
|
+
className: cn(
|
|
288
|
+
"ui-cascader-result",
|
|
289
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
290
|
+
selected && "bg-accent/60"
|
|
291
|
+
),
|
|
292
|
+
onClick: () => handleSelectNode({ value: path.at(-1), label }, path),
|
|
293
|
+
children: [
|
|
294
|
+
multiple ? /* @__PURE__ */ jsx(CheckboxVisual, { checked: selected, className: "me-2" }) : /* @__PURE__ */ jsx(
|
|
295
|
+
Check,
|
|
296
|
+
{
|
|
297
|
+
className: "ui-cascader-result-icon",
|
|
298
|
+
"data-selected": selected ? "true" : "false",
|
|
299
|
+
"aria-hidden": "true"
|
|
300
|
+
}
|
|
301
|
+
),
|
|
302
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-start", children: label })
|
|
303
|
+
]
|
|
304
|
+
},
|
|
305
|
+
pathKey(path)
|
|
306
|
+
);
|
|
307
|
+
})
|
|
308
|
+
}
|
|
309
|
+
) }) : renderCascadeColumns()
|
|
310
|
+
] })
|
|
319
311
|
] }),
|
|
320
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
312
|
+
/* @__PURE__ */ jsx("div", { className: "ui-control-affix ui-cascader-affix", children: showClear ? /* @__PURE__ */ jsx(
|
|
321
313
|
"button",
|
|
322
314
|
{
|
|
323
315
|
type: "button",
|
|
324
316
|
"aria-label": t("dataEntry.cascader.clear"),
|
|
325
|
-
className: "
|
|
317
|
+
className: "ui-control-affix-action",
|
|
326
318
|
onClick: clearValue,
|
|
327
|
-
children: /* @__PURE__ */ jsx(X, { className: "
|
|
319
|
+
children: /* @__PURE__ */ jsx(X, { className: "ui-control-affix-icon", "aria-hidden": "true" })
|
|
320
|
+
}
|
|
321
|
+
) : /* @__PURE__ */ jsx(
|
|
322
|
+
ChevronsUpDown,
|
|
323
|
+
{
|
|
324
|
+
className: "ui-control-affix-icon ui-control-affix-indicator",
|
|
325
|
+
"aria-hidden": "true"
|
|
328
326
|
}
|
|
329
|
-
)
|
|
327
|
+
) })
|
|
330
328
|
] });
|
|
331
329
|
}
|
|
332
330
|
export {
|