@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
|
@@ -64,7 +64,7 @@ const SelectTrigger = React.forwardRef(({ className, children, size = "md", show
|
|
|
64
64
|
"data-size": size,
|
|
65
65
|
className: cn(
|
|
66
66
|
controlTriggerClass,
|
|
67
|
-
"
|
|
67
|
+
"aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground w-full whitespace-nowrap transition-[color,box-shadow] outline-none *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center",
|
|
68
68
|
className
|
|
69
69
|
),
|
|
70
70
|
...props,
|
|
@@ -75,7 +75,7 @@ const SelectTrigger = React.forwardRef(({ className, children, size = "md", show
|
|
|
75
75
|
ChevronDown,
|
|
76
76
|
{
|
|
77
77
|
"data-slot": "select-chevron",
|
|
78
|
-
className: "
|
|
78
|
+
className: "ui-select-chevron",
|
|
79
79
|
"aria-hidden": "true"
|
|
80
80
|
}
|
|
81
81
|
) }) : null
|
|
@@ -89,9 +89,9 @@ const SelectScrollUpButton = React.forwardRef(({ className, ...props }, ref) =>
|
|
|
89
89
|
{
|
|
90
90
|
ref,
|
|
91
91
|
"data-slot": "select-scroll-up-button",
|
|
92
|
-
className: cn("
|
|
92
|
+
className: cn("ui-select-scroll-button", className),
|
|
93
93
|
...props,
|
|
94
|
-
children: /* @__PURE__ */ jsx(ChevronUp, { className: "
|
|
94
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: "ui-select-scroll-icon", "aria-hidden": "true" })
|
|
95
95
|
}
|
|
96
96
|
));
|
|
97
97
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
@@ -100,9 +100,9 @@ const SelectScrollDownButton = React.forwardRef(({ className, ...props }, ref) =
|
|
|
100
100
|
{
|
|
101
101
|
ref,
|
|
102
102
|
"data-slot": "select-scroll-down-button",
|
|
103
|
-
className: cn("
|
|
103
|
+
className: cn("ui-select-scroll-button", className),
|
|
104
104
|
...props,
|
|
105
|
-
children: /* @__PURE__ */ jsx(ChevronDown, { className: "
|
|
105
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: "ui-select-scroll-icon", "aria-hidden": "true" })
|
|
106
106
|
}
|
|
107
107
|
));
|
|
108
108
|
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
@@ -112,7 +112,7 @@ const SelectContent = React.forwardRef(({ className, children, position = "poppe
|
|
|
112
112
|
ref,
|
|
113
113
|
"data-slot": "select-content",
|
|
114
114
|
className: cn(
|
|
115
|
-
"
|
|
115
|
+
"ui-select-content data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
116
116
|
position === "popper" && "translate-y-1",
|
|
117
117
|
className
|
|
118
118
|
),
|
|
@@ -125,7 +125,7 @@ const SelectContent = React.forwardRef(({ className, children, position = "poppe
|
|
|
125
125
|
{
|
|
126
126
|
"data-slot": "select-viewport",
|
|
127
127
|
className: cn(
|
|
128
|
-
"
|
|
128
|
+
"ui-select-viewport",
|
|
129
129
|
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
130
130
|
),
|
|
131
131
|
children
|
|
@@ -141,7 +141,7 @@ const SelectLabel = React.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
141
141
|
{
|
|
142
142
|
ref,
|
|
143
143
|
"data-slot": "select-label",
|
|
144
|
-
className: cn("
|
|
144
|
+
className: cn("ui-select-label", className),
|
|
145
145
|
...props
|
|
146
146
|
}
|
|
147
147
|
));
|
|
@@ -151,10 +151,7 @@ const SelectItem = React.forwardRef(({ className, children, ...props }, ref) =>
|
|
|
151
151
|
{
|
|
152
152
|
ref,
|
|
153
153
|
"data-slot": "select-item",
|
|
154
|
-
className: cn(
|
|
155
|
-
"focus:bg-accent focus:text-accent-foreground data-[state=checked]:bg-accent data-[state=checked]:text-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm px-2.5 py-1.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[state=checked]:font-medium [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
156
|
-
className
|
|
157
|
-
),
|
|
154
|
+
className: cn("ui-select-item [&_svg:not([class*='text-'])]:text-muted-foreground", className),
|
|
158
155
|
...props,
|
|
159
156
|
children: /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
|
|
160
157
|
}
|
|
@@ -165,7 +162,7 @@ const SelectSeparator = React.forwardRef(({ className, ...props }, ref) => /* @_
|
|
|
165
162
|
{
|
|
166
163
|
ref,
|
|
167
164
|
"data-slot": "select-separator",
|
|
168
|
-
className: cn("
|
|
165
|
+
className: cn("ui-select-separator", className),
|
|
169
166
|
...props
|
|
170
167
|
}
|
|
171
168
|
));
|
|
@@ -293,7 +290,7 @@ function DataSelect({
|
|
|
293
290
|
{
|
|
294
291
|
id,
|
|
295
292
|
"data-testid": dataTestId,
|
|
296
|
-
className: cn(showClear && "
|
|
293
|
+
className: cn(showClear && "ui-control-trigger-affixed", canClear ? void 0 : className),
|
|
297
294
|
showIndicator: !showClear,
|
|
298
295
|
...ariaProps,
|
|
299
296
|
children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
|
|
@@ -311,15 +308,15 @@ function DataSelect({
|
|
|
311
308
|
if (!canClear) return select;
|
|
312
309
|
return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
313
310
|
select,
|
|
314
|
-
showClear ? /* @__PURE__ */ jsx("div", { className: "
|
|
311
|
+
showClear ? /* @__PURE__ */ jsx("div", { className: "ui-control-affix", children: /* @__PURE__ */ jsx(
|
|
315
312
|
"button",
|
|
316
313
|
{
|
|
317
314
|
type: "button",
|
|
318
315
|
"aria-label": clearLabel ?? t("dataEntry.searchSelect.clear"),
|
|
319
316
|
"data-testid": dataTestId ? `${dataTestId}-clear` : void 0,
|
|
320
|
-
className: "
|
|
317
|
+
className: "ui-control-affix-action",
|
|
321
318
|
onClick: () => onValueChange?.("", void 0),
|
|
322
|
-
children: /* @__PURE__ */ jsx(X, { className: "
|
|
319
|
+
children: /* @__PURE__ */ jsx(X, { className: "ui-control-affix-icon", "aria-hidden": "true" })
|
|
323
320
|
}
|
|
324
321
|
) }) : null
|
|
325
322
|
] });
|
|
@@ -25,7 +25,13 @@ const Switch = React.forwardRef(
|
|
|
25
25
|
checked: isChecked,
|
|
26
26
|
onCheckedChange: handleCheckedChange,
|
|
27
27
|
className: cn(
|
|
28
|
-
|
|
28
|
+
// `disabled:cursor-not-allowed disabled:opacity-50` DELETED, not moved (#319):
|
|
29
|
+
// `.ui-switch:disabled, .ui-switch[data-disabled]` in styles/control.css already
|
|
30
|
+
// declares both and reads --disabled-opacity. The utility was layered after
|
|
31
|
+
// components, so it silently outranked that token. Byte-identical: the token
|
|
32
|
+
// defaults to 0.5. (`shadow-xs` STAYS — .ui-switch declares --shadow-sm, so this
|
|
33
|
+
// utility is the switch's real resting elevation, not a duplicate.)
|
|
34
|
+
"peer ui-switch shadow-xs transition-all outline-none",
|
|
29
35
|
className
|
|
30
36
|
),
|
|
31
37
|
...props,
|
|
@@ -4,10 +4,66 @@ export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> &
|
|
|
4
4
|
allowClear?: boolean;
|
|
5
5
|
/** Called after the field is cleared via the inline ✕. */
|
|
6
6
|
onClear?: () => void;
|
|
7
|
+
/**
|
|
8
|
+
* `ghost` strips the field's own border, background and focus ring, for a textarea embedded
|
|
9
|
+
* in a surface that already draws the box (a chat composer inside a Card). The surface then
|
|
10
|
+
* owns focus — give it `focus-within`. Default keeps the standalone control chrome.
|
|
11
|
+
*/
|
|
12
|
+
variant?: "default" | "ghost";
|
|
13
|
+
/**
|
|
14
|
+
* Grow the control with its content instead of holding a fixed `rows` height (default false —
|
|
15
|
+
* the inert default, so every existing `<Textarea>` keeps the geometry it has today).
|
|
16
|
+
*
|
|
17
|
+
* The floor is `minRows` (or `rows`, when that is the only one given) and never undercuts the
|
|
18
|
+
* `--control-height` tier; past `maxRows` the control stops growing and scrolls internally.
|
|
19
|
+
* Sizing is done in CSS by a hidden replica of the text, so it follows a paste, a programmatic
|
|
20
|
+
* value change, a font swap and a container resize — not just typing — and it never writes
|
|
21
|
+
* `style.height` or reads `scrollHeight`. Works controlled and uncontrolled.
|
|
22
|
+
*/
|
|
23
|
+
autoGrow?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Floor in text rows while `autoGrow` (theme default `--textarea-autogrow-min-height-rows`, 1).
|
|
26
|
+
* Ignored when `autoGrow` is false.
|
|
27
|
+
*/
|
|
28
|
+
minRows?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Ceiling in text rows while `autoGrow` (theme default `--textarea-autogrow-max-height-rows`,
|
|
31
|
+
* 8); beyond it the control scrolls internally rather than pushing the page. Pass `0` for no
|
|
32
|
+
* ceiling — only correct inside an owning scroll container. Ignored when `autoGrow` is false.
|
|
33
|
+
*/
|
|
34
|
+
maxRows?: number;
|
|
7
35
|
};
|
|
8
36
|
export declare const Textarea: React.ForwardRefExoticComponent<React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
|
|
9
37
|
/** Show an inline ✕ (top-end) that clears the field while it holds text (default false). */
|
|
10
38
|
allowClear?: boolean;
|
|
11
39
|
/** Called after the field is cleared via the inline ✕. */
|
|
12
40
|
onClear?: () => void;
|
|
41
|
+
/**
|
|
42
|
+
* `ghost` strips the field's own border, background and focus ring, for a textarea embedded
|
|
43
|
+
* in a surface that already draws the box (a chat composer inside a Card). The surface then
|
|
44
|
+
* owns focus — give it `focus-within`. Default keeps the standalone control chrome.
|
|
45
|
+
*/
|
|
46
|
+
variant?: "default" | "ghost";
|
|
47
|
+
/**
|
|
48
|
+
* Grow the control with its content instead of holding a fixed `rows` height (default false —
|
|
49
|
+
* the inert default, so every existing `<Textarea>` keeps the geometry it has today).
|
|
50
|
+
*
|
|
51
|
+
* The floor is `minRows` (or `rows`, when that is the only one given) and never undercuts the
|
|
52
|
+
* `--control-height` tier; past `maxRows` the control stops growing and scrolls internally.
|
|
53
|
+
* Sizing is done in CSS by a hidden replica of the text, so it follows a paste, a programmatic
|
|
54
|
+
* value change, a font swap and a container resize — not just typing — and it never writes
|
|
55
|
+
* `style.height` or reads `scrollHeight`. Works controlled and uncontrolled.
|
|
56
|
+
*/
|
|
57
|
+
autoGrow?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Floor in text rows while `autoGrow` (theme default `--textarea-autogrow-min-height-rows`, 1).
|
|
60
|
+
* Ignored when `autoGrow` is false.
|
|
61
|
+
*/
|
|
62
|
+
minRows?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Ceiling in text rows while `autoGrow` (theme default `--textarea-autogrow-max-height-rows`,
|
|
65
|
+
* 8); beyond it the control scrolls internally rather than pushing the page. Pass `0` for no
|
|
66
|
+
* ceiling — only correct inside an owning scroll container. Ignored when `autoGrow` is false.
|
|
67
|
+
*/
|
|
68
|
+
maxRows?: number;
|
|
13
69
|
} & React.RefAttributes<HTMLTextAreaElement>>;
|
|
@@ -4,10 +4,28 @@ import * as React from "react";
|
|
|
4
4
|
import { X } from "lucide-react";
|
|
5
5
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
-
import { controlMultilineClass } from "../../lib/control-styles.js";
|
|
7
|
+
import { controlMultilineClass, controlMultilineGhostClass } from "../../lib/control-styles.js";
|
|
8
|
+
const UNBOUNDED_ROWS = "infinity";
|
|
8
9
|
const Textarea = React.forwardRef(
|
|
9
|
-
({
|
|
10
|
+
({
|
|
11
|
+
className,
|
|
12
|
+
allowClear = false,
|
|
13
|
+
onClear,
|
|
14
|
+
variant = "default",
|
|
15
|
+
autoGrow = false,
|
|
16
|
+
minRows,
|
|
17
|
+
maxRows,
|
|
18
|
+
rows,
|
|
19
|
+
style,
|
|
20
|
+
value,
|
|
21
|
+
defaultValue,
|
|
22
|
+
onChange,
|
|
23
|
+
onCompositionStart,
|
|
24
|
+
onCompositionEnd,
|
|
25
|
+
...props
|
|
26
|
+
}, ref) => {
|
|
10
27
|
const { t } = useTranslation();
|
|
28
|
+
const base = variant === "ghost" ? controlMultilineGhostClass : controlMultilineClass;
|
|
11
29
|
const innerRef = React.useRef(null);
|
|
12
30
|
const setRefs = React.useCallback(
|
|
13
31
|
(node) => {
|
|
@@ -23,10 +41,39 @@ const Textarea = React.forwardRef(
|
|
|
23
41
|
React.useEffect(() => {
|
|
24
42
|
if (value !== void 0) setHasText(String(value).length > 0);
|
|
25
43
|
}, [value]);
|
|
44
|
+
const [mirror, setMirror] = React.useState(() => String(value ?? defaultValue ?? ""));
|
|
45
|
+
const composing = React.useRef(false);
|
|
46
|
+
const syncMirror = React.useCallback(() => {
|
|
47
|
+
const el = innerRef.current;
|
|
48
|
+
if (!el || composing.current) return;
|
|
49
|
+
setMirror(el.value);
|
|
50
|
+
}, []);
|
|
51
|
+
React.useLayoutEffect(() => {
|
|
52
|
+
if (autoGrow) syncMirror();
|
|
53
|
+
});
|
|
54
|
+
React.useEffect(() => {
|
|
55
|
+
const form = innerRef.current?.form;
|
|
56
|
+
if (!autoGrow || !form) return;
|
|
57
|
+
const onReset = () => {
|
|
58
|
+
queueMicrotask(syncMirror);
|
|
59
|
+
};
|
|
60
|
+
form.addEventListener("reset", onReset);
|
|
61
|
+
return () => form.removeEventListener("reset", onReset);
|
|
62
|
+
}, [autoGrow, syncMirror]);
|
|
26
63
|
const handleChange = (event) => {
|
|
27
64
|
if (value === void 0) setHasText(event.target.value.length > 0);
|
|
65
|
+
if (autoGrow && !composing.current) setMirror(event.target.value);
|
|
28
66
|
onChange?.(event);
|
|
29
67
|
};
|
|
68
|
+
const handleCompositionStart = (event) => {
|
|
69
|
+
composing.current = true;
|
|
70
|
+
onCompositionStart?.(event);
|
|
71
|
+
};
|
|
72
|
+
const handleCompositionEnd = (event) => {
|
|
73
|
+
composing.current = false;
|
|
74
|
+
if (autoGrow) setMirror(event.currentTarget.value);
|
|
75
|
+
onCompositionEnd?.(event);
|
|
76
|
+
};
|
|
30
77
|
const clear = () => {
|
|
31
78
|
const el = innerRef.current;
|
|
32
79
|
if (el) {
|
|
@@ -39,46 +86,62 @@ const Textarea = React.forwardRef(
|
|
|
39
86
|
el.focus();
|
|
40
87
|
}
|
|
41
88
|
setHasText(false);
|
|
89
|
+
if (autoGrow) setMirror("");
|
|
42
90
|
onClear?.();
|
|
43
91
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
const floorRows = minRows ?? (typeof rows === "number" ? rows : void 0);
|
|
93
|
+
const autoGrowVars = autoGrow ? {
|
|
94
|
+
...floorRows === void 0 ? null : { "--textarea-autogrow-min-height-rows": floorRows },
|
|
95
|
+
...maxRows === void 0 ? null : {
|
|
96
|
+
"--textarea-autogrow-max-height-rows": maxRows === 0 ? UNBOUNDED_ROWS : maxRows
|
|
97
|
+
}
|
|
98
|
+
} : void 0;
|
|
99
|
+
const showClear = allowClear && hasText && !props.disabled && !props.readOnly;
|
|
100
|
+
const needsWrapper = allowClear || autoGrow;
|
|
101
|
+
const field = /* @__PURE__ */ jsx(
|
|
102
|
+
"textarea",
|
|
103
|
+
{
|
|
104
|
+
ref: setRefs,
|
|
105
|
+
value,
|
|
106
|
+
defaultValue,
|
|
107
|
+
rows: autoGrow ? 1 : rows,
|
|
108
|
+
onChange: needsWrapper ? handleChange : onChange,
|
|
109
|
+
onCompositionStart: handleCompositionStart,
|
|
110
|
+
onCompositionEnd: handleCompositionEnd,
|
|
111
|
+
style,
|
|
112
|
+
className: cn(base, showClear && "ui-input--trailing-affix", className),
|
|
113
|
+
...props
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
if (!needsWrapper) return field;
|
|
117
|
+
return /* @__PURE__ */ jsxs(
|
|
118
|
+
"span",
|
|
119
|
+
{
|
|
120
|
+
"data-slot": "textarea-affix-wrapper",
|
|
121
|
+
"data-autogrow-value": autoGrow ? mirror : void 0,
|
|
122
|
+
style: autoGrowVars,
|
|
123
|
+
className: cn(
|
|
124
|
+
"relative w-full",
|
|
125
|
+
autoGrow ? "grid" : "block",
|
|
126
|
+
autoGrow && "ui-textarea-autogrow",
|
|
127
|
+
autoGrow && variant === "ghost" && "ui-textarea-autogrow--ghost"
|
|
128
|
+
),
|
|
129
|
+
children: [
|
|
130
|
+
field,
|
|
131
|
+
showClear ? /* @__PURE__ */ jsx(
|
|
132
|
+
"button",
|
|
133
|
+
{
|
|
134
|
+
type: "button",
|
|
135
|
+
tabIndex: -1,
|
|
136
|
+
"aria-label": t("common.clear") ?? "Clear",
|
|
137
|
+
onClick: clear,
|
|
138
|
+
className: "ui-control-inline-affix-action ui-textarea-clear",
|
|
139
|
+
children: /* @__PURE__ */ jsx(X, { className: "ui-control-inline-affix-icon", "aria-hidden": "true" })
|
|
140
|
+
}
|
|
141
|
+
) : null
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
);
|
|
82
145
|
}
|
|
83
146
|
);
|
|
84
147
|
Textarea.displayName = "Textarea";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import { Clock } from "lucide-react";
|
|
4
|
+
import { Clock, X } from "lucide-react";
|
|
5
5
|
import { usePickerLocales, useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { isValidHhmm, normalizeHhmm } from "../../lib/datetime/index.js";
|
|
7
7
|
import { pickFieldA11y } from "../../lib/field-a11y.js";
|
|
@@ -73,40 +73,28 @@ function TimeColumn({
|
|
|
73
73
|
break;
|
|
74
74
|
}
|
|
75
75
|
};
|
|
76
|
-
return /* @__PURE__ */ jsxs("div", { className: "
|
|
77
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
78
|
-
/* @__PURE__ */ jsx(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
),
|
|
99
|
-
onClick: () => {
|
|
100
|
-
onSelect(item);
|
|
101
|
-
},
|
|
102
|
-
onKeyDown: (e) => onKeyDown(e, index),
|
|
103
|
-
children: formatItem(item)
|
|
104
|
-
},
|
|
105
|
-
item
|
|
106
|
-
);
|
|
107
|
-
})
|
|
108
|
-
}
|
|
109
|
-
)
|
|
76
|
+
return /* @__PURE__ */ jsxs("div", { className: "ui-time-picker-column", children: [
|
|
77
|
+
/* @__PURE__ */ jsx("div", { className: "ui-time-picker-column-heading", children: label }),
|
|
78
|
+
/* @__PURE__ */ jsx("div", { ref: listRef, role: "listbox", "aria-label": label, className: "ui-time-picker-column-scroll", children: items.map((item, index) => {
|
|
79
|
+
const isSelected = item === selected;
|
|
80
|
+
return /* @__PURE__ */ jsx(
|
|
81
|
+
"button",
|
|
82
|
+
{
|
|
83
|
+
type: "button",
|
|
84
|
+
role: "option",
|
|
85
|
+
"aria-selected": isSelected,
|
|
86
|
+
"data-selected": isSelected,
|
|
87
|
+
tabIndex: isSelected ? 0 : -1,
|
|
88
|
+
className: "ui-time-picker-option",
|
|
89
|
+
onClick: () => {
|
|
90
|
+
onSelect(item);
|
|
91
|
+
},
|
|
92
|
+
onKeyDown: (e) => onKeyDown(e, index),
|
|
93
|
+
children: formatItem(item)
|
|
94
|
+
},
|
|
95
|
+
item
|
|
96
|
+
);
|
|
97
|
+
}) })
|
|
110
98
|
] });
|
|
111
99
|
}
|
|
112
100
|
function TimePickerPanel({ value, minuteStep, use12h, onChange, onDone }) {
|
|
@@ -132,7 +120,7 @@ function TimePickerPanel({ value, minuteStep, use12h, onChange, onDone }) {
|
|
|
132
120
|
};
|
|
133
121
|
const hourItems = use12h ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 24 }, (_, i) => i);
|
|
134
122
|
const selectedHourItem = use12h ? to12h(hour) : hour;
|
|
135
|
-
return /* @__PURE__ */ jsxs("div", { className: use12h ? "
|
|
123
|
+
return /* @__PURE__ */ jsxs("div", { className: "ui-time-picker-panel", "data-hour-cycle": use12h ? "h12" : "h23", children: [
|
|
136
124
|
/* @__PURE__ */ jsxs("div", { className: "divide-border flex divide-x", children: [
|
|
137
125
|
/* @__PURE__ */ jsx(
|
|
138
126
|
TimeColumn,
|
|
@@ -174,7 +162,7 @@ function TimePickerPanel({ value, minuteStep, use12h, onChange, onDone }) {
|
|
|
174
162
|
}
|
|
175
163
|
)
|
|
176
164
|
] }),
|
|
177
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
165
|
+
/* @__PURE__ */ jsx("div", { className: "ui-time-picker-footer", children: /* @__PURE__ */ jsx(
|
|
178
166
|
Input,
|
|
179
167
|
{
|
|
180
168
|
id: draftId,
|
|
@@ -237,6 +225,7 @@ function TimePicker({
|
|
|
237
225
|
setValue("");
|
|
238
226
|
setText("");
|
|
239
227
|
};
|
|
228
|
+
const showClear = allowClear && text !== "" && !disabled;
|
|
240
229
|
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
241
230
|
/* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsx("div", { className: cn("relative", className), children: /* @__PURE__ */ jsx(
|
|
242
231
|
Input,
|
|
@@ -253,20 +242,31 @@ function TimePicker({
|
|
|
253
242
|
"aria-haspopup": "dialog",
|
|
254
243
|
"aria-controls": open ? dialogId : void 0,
|
|
255
244
|
...fieldA11y,
|
|
256
|
-
className: "tabular-nums",
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
245
|
+
className: cn("tabular-nums", showClear && "ui-control-inline-affix-pair-affixed"),
|
|
246
|
+
trailingIcon: /* @__PURE__ */ jsxs("span", { className: "ui-time-picker-affix", children: [
|
|
247
|
+
showClear ? /* @__PURE__ */ jsx(
|
|
248
|
+
"button",
|
|
249
|
+
{
|
|
250
|
+
type: "button",
|
|
251
|
+
tabIndex: -1,
|
|
252
|
+
"aria-label": t("common.clear") ?? "Clear",
|
|
253
|
+
onClick: clear,
|
|
254
|
+
className: "ui-control-inline-affix-action",
|
|
255
|
+
children: /* @__PURE__ */ jsx(X, { className: "ui-control-inline-affix-icon", "aria-hidden": "true" })
|
|
256
|
+
}
|
|
257
|
+
) : null,
|
|
258
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
259
|
+
"button",
|
|
260
|
+
{
|
|
261
|
+
type: "button",
|
|
262
|
+
disabled,
|
|
263
|
+
tabIndex: -1,
|
|
264
|
+
"aria-label": t("dataEntry.timePicker.openPicker") ?? "Open time picker",
|
|
265
|
+
className: "ui-control-inline-affix-action",
|
|
266
|
+
children: /* @__PURE__ */ jsx(Clock, { className: "ui-control-inline-affix-icon", "aria-hidden": "true" })
|
|
267
|
+
}
|
|
268
|
+
) })
|
|
269
|
+
] }),
|
|
270
270
|
onClick: () => {
|
|
271
271
|
if (!disabled) setOpen(true);
|
|
272
272
|
},
|
|
@@ -295,7 +295,7 @@ function TimePicker({
|
|
|
295
295
|
id: dialogId,
|
|
296
296
|
role: "dialog",
|
|
297
297
|
"aria-label": t("dataEntry.timePicker.openPicker") ?? "Time picker",
|
|
298
|
-
className: "
|
|
298
|
+
className: "ui-time-picker-popover",
|
|
299
299
|
align: "end",
|
|
300
300
|
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
301
301
|
children: /* @__PURE__ */ jsx(
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Toggle } from "../ui/toggle.js";
|
|
2
|
-
export type { ToggleProps } from "../ui/toggle.js";
|
|
2
|
+
export type { ToggleProp, ToggleProps } from "../ui/toggle.js";
|
|
@@ -40,9 +40,9 @@ function TransferPanel({
|
|
|
40
40
|
const toggleKey = (key, checked) => {
|
|
41
41
|
onSelectChange(checked ? [...selectedKeys, key] : selectedKeys.filter((k) => k !== key));
|
|
42
42
|
};
|
|
43
|
-
return /* @__PURE__ */ jsxs("div", { className: "
|
|
44
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
45
|
-
/* @__PURE__ */ jsxs("label", { className: "
|
|
43
|
+
return /* @__PURE__ */ jsxs("div", { className: "ui-transfer-pane", children: [
|
|
44
|
+
/* @__PURE__ */ jsxs("div", { className: "ui-transfer-pane-header", children: [
|
|
45
|
+
/* @__PURE__ */ jsxs("label", { className: "ui-transfer-pane-check", children: [
|
|
46
46
|
/* @__PURE__ */ jsx(
|
|
47
47
|
Checkbox,
|
|
48
48
|
{
|
|
@@ -60,21 +60,20 @@ function TransferPanel({
|
|
|
60
60
|
filtered.length
|
|
61
61
|
] })
|
|
62
62
|
] }),
|
|
63
|
-
showSearch && /* @__PURE__ */ jsx("div", { className: "
|
|
63
|
+
showSearch && /* @__PURE__ */ jsx("div", { className: "ui-transfer-search", "data-disabled": disabled ? "" : void 0, children: /* @__PURE__ */ jsx(
|
|
64
64
|
SearchInput,
|
|
65
65
|
{
|
|
66
66
|
onSearch: setQuery,
|
|
67
67
|
placeholder: searchPlaceholder,
|
|
68
68
|
ariaLabel: searchPlaceholder,
|
|
69
|
-
debounce: 0
|
|
70
|
-
className: disabled ? "pointer-events-none opacity-50" : void 0
|
|
69
|
+
debounce: 0
|
|
71
70
|
}
|
|
72
71
|
) }),
|
|
73
|
-
/* @__PURE__ */ jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsx("ul", { className: "
|
|
72
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsx("ul", { className: "ui-transfer-list", "aria-labelledby": titleId, children: filtered.length === 0 ? /* @__PURE__ */ jsx("li", { className: "ui-transfer-empty", children: emptyText }) : filtered.map((item) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
74
73
|
"label",
|
|
75
74
|
{
|
|
76
75
|
className: cn(
|
|
77
|
-
"
|
|
76
|
+
"ui-transfer-row",
|
|
78
77
|
"hover:bg-accent hover:text-accent-foreground",
|
|
79
78
|
item.disabled && "bg-muted/40 text-muted-foreground pointer-events-none"
|
|
80
79
|
),
|
|
@@ -85,12 +84,12 @@ function TransferPanel({
|
|
|
85
84
|
checked: selectedKeys.includes(item.key),
|
|
86
85
|
disabled: Boolean(disabled) || Boolean(item.disabled),
|
|
87
86
|
onCheckedChange: (v) => toggleKey(item.key, v === true),
|
|
88
|
-
className: "
|
|
87
|
+
className: "ui-transfer-row-check"
|
|
89
88
|
}
|
|
90
89
|
),
|
|
91
|
-
/* @__PURE__ */ jsxs("span", { className: "
|
|
90
|
+
/* @__PURE__ */ jsxs("span", { className: "ui-transfer-row-body", children: [
|
|
92
91
|
/* @__PURE__ */ jsx("span", { className: "block truncate font-medium", children: item.title }),
|
|
93
|
-
item.description && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground block truncate
|
|
92
|
+
item.description && /* @__PURE__ */ jsx("span", { className: "ui-transfer-row-description text-muted-foreground block truncate", children: item.description })
|
|
94
93
|
] })
|
|
95
94
|
]
|
|
96
95
|
}
|
|
@@ -141,7 +140,7 @@ function Transfer({
|
|
|
141
140
|
id,
|
|
142
141
|
...groupA11y,
|
|
143
142
|
"aria-disabled": disabled ? true : void 0,
|
|
144
|
-
className: cn("
|
|
143
|
+
className: cn("ui-transfer", className),
|
|
145
144
|
children: [
|
|
146
145
|
/* @__PURE__ */ jsx(
|
|
147
146
|
TransferPanel,
|
|
@@ -158,7 +157,7 @@ function Transfer({
|
|
|
158
157
|
emptyText: t("dataEntry.transfer.empty")
|
|
159
158
|
}
|
|
160
159
|
),
|
|
161
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
160
|
+
/* @__PURE__ */ jsxs("div", { className: "ui-transfer-actions", children: [
|
|
162
161
|
/* @__PURE__ */ jsx(
|
|
163
162
|
Button,
|
|
164
163
|
{
|
|
@@ -168,7 +167,7 @@ function Transfer({
|
|
|
168
167
|
disabled: Boolean(disabled) || selected[0].length === 0,
|
|
169
168
|
"aria-label": t("dataEntry.transfer.moveRight"),
|
|
170
169
|
onClick: () => move("right"),
|
|
171
|
-
children: /* @__PURE__ */ jsx(ChevronRight, { className: "
|
|
170
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "ui-transfer-action-icon", "aria-hidden": "true" })
|
|
172
171
|
}
|
|
173
172
|
),
|
|
174
173
|
!oneWay && /* @__PURE__ */ jsx(
|
|
@@ -180,7 +179,7 @@ function Transfer({
|
|
|
180
179
|
disabled: Boolean(disabled) || selected[1].length === 0,
|
|
181
180
|
"aria-label": t("dataEntry.transfer.moveLeft"),
|
|
182
181
|
onClick: () => move("left"),
|
|
183
|
-
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "
|
|
182
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "ui-transfer-action-icon", "aria-hidden": "true" })
|
|
184
183
|
}
|
|
185
184
|
)
|
|
186
185
|
] }),
|