@godxjp/ui 15.0.1 → 16.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/components/data-entry/index.d.ts +0 -2
- package/dist/components/data-entry/index.js +0 -2
- package/dist/components/data-entry/time-picker.js +75 -76
- package/dist/components/ui/index.d.ts +0 -1
- package/dist/components/ui/index.js +0 -1
- package/dist/styles/alert-layout.css +8 -0
- package/dist/styles/navigation-layout.css +0 -1
- package/package.json +1 -1
- package/dist/components/data-entry/time-input.d.ts +0 -9
- package/dist/components/data-entry/time-input.js +0 -137
- package/dist/components/ui/time-input.d.ts +0 -1
- package/dist/components/ui/time-input.js +0 -1
|
@@ -45,8 +45,6 @@ export { Cascader } from "./cascader";
|
|
|
45
45
|
export type { CascaderProps, TreeOption, TreeFieldNames } from "./cascader";
|
|
46
46
|
export { TreeSelect, SHOW_CHILD, SHOW_PARENT, SHOW_ALL } from "./tree-select";
|
|
47
47
|
export type { TreeSelectProps } from "./tree-select";
|
|
48
|
-
export { TimeInput } from "./time-input";
|
|
49
|
-
export type { TimeInputProps } from "./time-input";
|
|
50
48
|
export { Transfer } from "./transfer";
|
|
51
49
|
export type { TransferProps, TransferItemProp } from "./transfer";
|
|
52
50
|
export { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "./command";
|
|
@@ -35,7 +35,6 @@ import { ColorPicker } from "./color-picker";
|
|
|
35
35
|
import { Upload, collectUploadCommitActions, createUploadItem, useUploadDraft } from "./upload";
|
|
36
36
|
import { Cascader } from "./cascader";
|
|
37
37
|
import { TreeSelect, SHOW_CHILD, SHOW_PARENT, SHOW_ALL } from "./tree-select";
|
|
38
|
-
import { TimeInput } from "./time-input";
|
|
39
38
|
import { Transfer } from "./transfer";
|
|
40
39
|
import {
|
|
41
40
|
Command,
|
|
@@ -101,7 +100,6 @@ export {
|
|
|
101
100
|
Switch,
|
|
102
101
|
TagInput,
|
|
103
102
|
Textarea,
|
|
104
|
-
TimeInput,
|
|
105
103
|
TimePicker,
|
|
106
104
|
Toggle,
|
|
107
105
|
ToggleGroup,
|
|
@@ -5,7 +5,7 @@ import { usePickerLocales, useTranslation } from "../../i18n/use-translation";
|
|
|
5
5
|
import { isValidHhmm, normalizeHhmm } from "../../lib/datetime";
|
|
6
6
|
import { cn } from "../../lib/utils";
|
|
7
7
|
import { Button } from "../general/button";
|
|
8
|
-
import { Popover, PopoverContent, PopoverTrigger } from "../data-display/popover";
|
|
8
|
+
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "../data-display/popover";
|
|
9
9
|
import { Input } from "./input";
|
|
10
10
|
function pad2(n) {
|
|
11
11
|
return String(n).padStart(2, "0");
|
|
@@ -233,59 +233,58 @@ function TimePicker({
|
|
|
233
233
|
setValue("");
|
|
234
234
|
setText("");
|
|
235
235
|
};
|
|
236
|
-
return /* @__PURE__ */ jsxs(
|
|
237
|
-
/* @__PURE__ */ jsx(
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
event.
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
236
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
237
|
+
/* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
238
|
+
/* @__PURE__ */ jsx(
|
|
239
|
+
Input,
|
|
240
|
+
{
|
|
241
|
+
id,
|
|
242
|
+
name,
|
|
243
|
+
value: text,
|
|
244
|
+
disabled,
|
|
245
|
+
placeholder: resolvedPlaceholder,
|
|
246
|
+
inputMode: "numeric",
|
|
247
|
+
autoComplete: "off",
|
|
248
|
+
role: "combobox",
|
|
249
|
+
"aria-expanded": open,
|
|
250
|
+
"aria-haspopup": "dialog",
|
|
251
|
+
className: cn("tabular-nums", "pe-10"),
|
|
252
|
+
onClick: () => {
|
|
253
|
+
if (!disabled) setOpen(true);
|
|
254
|
+
},
|
|
255
|
+
onKeyDown: (event) => {
|
|
256
|
+
if (event.key === "ArrowDown") {
|
|
257
|
+
event.preventDefault();
|
|
258
|
+
setOpen(true);
|
|
259
|
+
} else if (event.key === "Escape" && open) {
|
|
260
|
+
setOpen(false);
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
onChange: (event) => {
|
|
264
|
+
setText(event.target.value);
|
|
265
|
+
const normalized = normalizeHhmm(event.target.value);
|
|
266
|
+
if (normalized) setValue(normalized);
|
|
267
|
+
},
|
|
268
|
+
onBlur: (event) => {
|
|
269
|
+
const normalized = normalizeHhmm(event.target.value);
|
|
270
|
+
setText(normalized ?? (isValidHhmm(value) ? value : ""));
|
|
260
271
|
}
|
|
261
|
-
},
|
|
262
|
-
onChange: (event) => {
|
|
263
|
-
setText(event.target.value);
|
|
264
|
-
const normalized = normalizeHhmm(event.target.value);
|
|
265
|
-
if (normalized) setValue(normalized);
|
|
266
|
-
},
|
|
267
|
-
onBlur: (event) => {
|
|
268
|
-
const normalized = normalizeHhmm(event.target.value);
|
|
269
|
-
setText(normalized ?? (isValidHhmm(value) ? value : ""));
|
|
270
272
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
) : null,
|
|
287
|
-
/* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
288
|
-
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
273
|
+
),
|
|
274
|
+
showClear ? /* @__PURE__ */ jsx(
|
|
275
|
+
Button,
|
|
276
|
+
{
|
|
277
|
+
type: "button",
|
|
278
|
+
variant: "ghost",
|
|
279
|
+
size: "icon",
|
|
280
|
+
disabled,
|
|
281
|
+
tabIndex: -1,
|
|
282
|
+
"aria-label": t("common.clear") ?? "Clear",
|
|
283
|
+
className: "text-muted-foreground absolute inset-y-0 end-0 h-full px-2 hover:bg-transparent",
|
|
284
|
+
onClick: clear,
|
|
285
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-4 shrink-0", "aria-hidden": "true" })
|
|
286
|
+
}
|
|
287
|
+
) : /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
289
288
|
Button,
|
|
290
289
|
{
|
|
291
290
|
type: "button",
|
|
@@ -297,31 +296,31 @@ function TimePicker({
|
|
|
297
296
|
className: "text-muted-foreground absolute inset-y-0 end-0 h-full px-2 hover:bg-transparent",
|
|
298
297
|
children: /* @__PURE__ */ jsx(Clock, { className: "size-4 shrink-0", "aria-hidden": "true" })
|
|
299
298
|
}
|
|
300
|
-
) })
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
299
|
+
) })
|
|
300
|
+
] }) }),
|
|
301
|
+
/* @__PURE__ */ jsx(
|
|
302
|
+
PopoverContent,
|
|
303
|
+
{
|
|
304
|
+
className: "w-auto p-0",
|
|
305
|
+
align: "end",
|
|
306
|
+
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
307
|
+
children: /* @__PURE__ */ jsx(
|
|
308
|
+
TimePickerPanel,
|
|
309
|
+
{
|
|
310
|
+
value: value || "09:00",
|
|
311
|
+
minuteStep,
|
|
312
|
+
use12h,
|
|
313
|
+
onChange: (next) => {
|
|
314
|
+
setValue(next);
|
|
315
|
+
setText(next);
|
|
316
|
+
},
|
|
317
|
+
onDone: () => {
|
|
318
|
+
setOpen(false);
|
|
320
319
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
320
|
+
}
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
)
|
|
325
324
|
] });
|
|
326
325
|
}
|
|
327
326
|
export {
|
|
@@ -21,7 +21,6 @@ export { Separator } from "./separator";
|
|
|
21
21
|
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../feedback/tooltip";
|
|
22
22
|
export * from "./dropdown-menu";
|
|
23
23
|
export * from "./input";
|
|
24
|
-
export * from "./time-input";
|
|
25
24
|
export * from "./label";
|
|
26
25
|
export * from "./pagination";
|
|
27
26
|
export * from "./password-strength";
|
|
@@ -21,7 +21,6 @@ import { Separator } from "./separator";
|
|
|
21
21
|
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../feedback/tooltip";
|
|
22
22
|
export * from "./dropdown-menu";
|
|
23
23
|
export * from "./input";
|
|
24
|
-
export * from "./time-input";
|
|
25
24
|
export * from "./label";
|
|
26
25
|
export * from "./pagination";
|
|
27
26
|
export * from "./password-strength";
|
|
@@ -193,6 +193,14 @@
|
|
|
193
193
|
border-radius: var(--skeleton-radius);
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
/* Drop the self-frame inside a flush CardContent so the Card supplies the single
|
|
197
|
+
* border — mirrors `.ui-data-table-surface` so the skeleton placeholder and the
|
|
198
|
+
* real DataTable it swaps for sit identically (no nested double border). */
|
|
199
|
+
[data-slot="card-content"][data-flush] .ui-skeleton-table {
|
|
200
|
+
border-width: 0;
|
|
201
|
+
border-radius: 0;
|
|
202
|
+
}
|
|
203
|
+
|
|
196
204
|
.ui-skeleton-table-head {
|
|
197
205
|
display: flex;
|
|
198
206
|
align-items: center;
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
type TimeInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "defaultValue"> & {
|
|
3
|
-
value?: string;
|
|
4
|
-
defaultValue?: string;
|
|
5
|
-
onValueChange?: (value: string) => void;
|
|
6
|
-
step?: number;
|
|
7
|
-
};
|
|
8
|
-
export declare function TimeInput({ value: controlledValue, defaultValue, onValueChange, placeholder, step, className, name, id, ...props }: TimeInputProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
-
export type { TimeInputProps };
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import { cn } from "../../lib/utils";
|
|
4
|
-
import { isValidHhmm, normalizeHhmm } from "../../lib/datetime";
|
|
5
|
-
function clampStep(step) {
|
|
6
|
-
if (!step || Number.isNaN(step)) return 1;
|
|
7
|
-
const parsed = Math.max(1, Math.floor(step));
|
|
8
|
-
if (!Number.isFinite(parsed)) return 1;
|
|
9
|
-
return Math.min(59, parsed);
|
|
10
|
-
}
|
|
11
|
-
function applyStep(value, step) {
|
|
12
|
-
const normalized = normalizeHhmm(value);
|
|
13
|
-
if (!normalized) return value;
|
|
14
|
-
const [hourText, minuteText] = normalized.split(":");
|
|
15
|
-
const hour = Number(hourText);
|
|
16
|
-
const minute = Number(minuteText);
|
|
17
|
-
const floored = Math.floor(minute / step) * step;
|
|
18
|
-
const safeMinute = Math.min(59, Math.max(0, floored));
|
|
19
|
-
return `${String(hour).padStart(2, "0")}:${String(safeMinute).padStart(2, "0")}`;
|
|
20
|
-
}
|
|
21
|
-
function maskTime(raw) {
|
|
22
|
-
const digits = raw.replace(/\D/g, "").slice(0, 4);
|
|
23
|
-
if (digits.length <= 2) return digits;
|
|
24
|
-
return `${digits.slice(0, 2)}:${digits.slice(2)}`;
|
|
25
|
-
}
|
|
26
|
-
function stepTime(value, deltaMinutes) {
|
|
27
|
-
const normalized = normalizeHhmm(value) ?? "00:00";
|
|
28
|
-
const [hourText, minuteText] = normalized.split(":");
|
|
29
|
-
const total = (Number(hourText) * 60 + Number(minuteText) + deltaMinutes + 24 * 60) % (24 * 60);
|
|
30
|
-
const hour = Math.floor(total / 60);
|
|
31
|
-
const minute = total % 60;
|
|
32
|
-
return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
|
|
33
|
-
}
|
|
34
|
-
function TimeInput({
|
|
35
|
-
value: controlledValue,
|
|
36
|
-
defaultValue = "",
|
|
37
|
-
onValueChange,
|
|
38
|
-
placeholder,
|
|
39
|
-
step = 1,
|
|
40
|
-
className,
|
|
41
|
-
name,
|
|
42
|
-
id,
|
|
43
|
-
...props
|
|
44
|
-
}) {
|
|
45
|
-
const safeStep = clampStep(step);
|
|
46
|
-
const [internal, setInternal] = React.useState(defaultValue);
|
|
47
|
-
const [displayValue, setDisplayValue] = React.useState(controlledValue ?? defaultValue);
|
|
48
|
-
const isControlled = controlledValue !== void 0;
|
|
49
|
-
const value = isControlled ? controlledValue ?? "" : internal;
|
|
50
|
-
React.useEffect(() => {
|
|
51
|
-
if (!isControlled) return;
|
|
52
|
-
setDisplayValue(controlledValue ?? "");
|
|
53
|
-
}, [controlledValue, isControlled]);
|
|
54
|
-
React.useEffect(() => {
|
|
55
|
-
if (isControlled) return;
|
|
56
|
-
setDisplayValue(internal);
|
|
57
|
-
}, [internal, isControlled]);
|
|
58
|
-
const commit = React.useCallback(
|
|
59
|
-
(next, fromBlur = false) => {
|
|
60
|
-
const normalized = normalizeHhmm(next);
|
|
61
|
-
if (!normalized) return;
|
|
62
|
-
const snapped = applyStep(normalized, safeStep);
|
|
63
|
-
if (!isControlled) {
|
|
64
|
-
setInternal(snapped);
|
|
65
|
-
}
|
|
66
|
-
if (isValidHhmm(snapped)) {
|
|
67
|
-
onValueChange?.(snapped);
|
|
68
|
-
setDisplayValue(snapped);
|
|
69
|
-
}
|
|
70
|
-
if (fromBlur && value !== snapped) {
|
|
71
|
-
onValueChange?.(snapped);
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
[isControlled, onValueChange, safeStep, value]
|
|
75
|
-
);
|
|
76
|
-
const valid = isValidHhmm(value);
|
|
77
|
-
return /* @__PURE__ */ jsx(
|
|
78
|
-
"input",
|
|
79
|
-
{
|
|
80
|
-
id,
|
|
81
|
-
name,
|
|
82
|
-
value: displayValue,
|
|
83
|
-
"data-slot": "time-input",
|
|
84
|
-
className: cn("ui-time-input", className),
|
|
85
|
-
role: "spinbutton",
|
|
86
|
-
"aria-valuemin": 0,
|
|
87
|
-
"aria-valuemax": 24 * 60 - 1,
|
|
88
|
-
"aria-valuenow": valid ? Number(value.slice(0, 2)) * 60 + Number(value.slice(3, 5)) : void 0,
|
|
89
|
-
"aria-valuetext": valid ? value : void 0,
|
|
90
|
-
"aria-invalid": displayValue !== "" && !isValidHhmm(displayValue) ? "true" : void 0,
|
|
91
|
-
placeholder: placeholder ?? "HH:mm",
|
|
92
|
-
inputMode: "numeric",
|
|
93
|
-
autoComplete: "off",
|
|
94
|
-
...props,
|
|
95
|
-
onChange: (event) => {
|
|
96
|
-
const masked = maskTime(event.target.value);
|
|
97
|
-
setDisplayValue(masked);
|
|
98
|
-
const normalized = normalizeHhmm(masked);
|
|
99
|
-
if (normalized) {
|
|
100
|
-
const snapped = applyStep(normalized, safeStep);
|
|
101
|
-
if (!isControlled) {
|
|
102
|
-
setInternal(snapped);
|
|
103
|
-
}
|
|
104
|
-
onValueChange?.(snapped);
|
|
105
|
-
setDisplayValue(snapped);
|
|
106
|
-
}
|
|
107
|
-
props.onChange?.(event);
|
|
108
|
-
},
|
|
109
|
-
onBlur: (event) => {
|
|
110
|
-
commit(event.target.value, true);
|
|
111
|
-
const normalized = normalizeHhmm(event.target.value);
|
|
112
|
-
if (!normalized) {
|
|
113
|
-
setDisplayValue(value);
|
|
114
|
-
}
|
|
115
|
-
props.onBlur?.(event);
|
|
116
|
-
},
|
|
117
|
-
onKeyDown: (event) => {
|
|
118
|
-
if (event.key === "Enter") {
|
|
119
|
-
commit(event.currentTarget.value, true);
|
|
120
|
-
} else if (event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
121
|
-
event.preventDefault();
|
|
122
|
-
const base = isValidHhmm(displayValue) ? displayValue : value || "00:00";
|
|
123
|
-
const next = stepTime(base, event.key === "ArrowUp" ? safeStep : -safeStep);
|
|
124
|
-
setDisplayValue(next);
|
|
125
|
-
if (!isControlled) {
|
|
126
|
-
setInternal(next);
|
|
127
|
-
}
|
|
128
|
-
onValueChange?.(next);
|
|
129
|
-
}
|
|
130
|
-
props.onKeyDown?.(event);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
export {
|
|
136
|
-
TimeInput
|
|
137
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "../data-entry/time-input";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "../data-entry/time-input";
|