@nexub/react 7.3.0 → 7.5.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/accessibility.json +1 -1
- package/dist/components/Avatar/Avatar.d.ts +3 -0
- package/dist/components/Avatar/Avatar.js +28 -5
- package/dist/components/Avatar/index.d.ts +1 -1
- package/dist/components/Button/Button.d.ts +2 -1
- package/dist/components/Button/Button.js +37 -7
- package/dist/components/Combobox/Combobox.d.ts +6 -9
- package/dist/components/Combobox/Combobox.js +30 -9
- package/dist/components/DataTable/DataTable.d.ts +5 -1
- package/dist/components/DataTable/DataTable.js +6 -2
- package/dist/components/DatePicker/DatePicker.d.ts +16 -1
- package/dist/components/DatePicker/DatePicker.js +100 -26
- package/dist/components/FileUpload/FileUpload.js +86 -32
- package/dist/components/Input/Input.d.ts +6 -0
- package/dist/components/Input/Input.js +47 -5
- package/dist/components/Progress/Progress.d.ts +4 -0
- package/dist/components/Progress/Progress.js +73 -20
- package/dist/components/Select/Select.d.ts +18 -3
- package/dist/components/Select/Select.js +170 -71
- package/dist/components/Skeleton/Skeleton.d.ts +9 -0
- package/dist/components/Skeleton/Skeleton.js +18 -1
- package/dist/components/Skeleton/index.d.ts +2 -2
- package/dist/components/Skeleton/index.js +2 -1
- package/dist/components/Slider/Slider.d.ts +10 -0
- package/dist/components/Slider/Slider.js +48 -3
- package/dist/components/Slider/index.d.ts +1 -1
- package/dist/components/Switch/Switch.d.ts +6 -0
- package/dist/components/Switch/Switch.js +29 -2
- package/dist/components/Toast/Toaster.js +68 -23
- package/dist/components/Toast/index.d.ts +1 -1
- package/dist/components/Toast/useToast.d.ts +18 -1
- package/dist/components/Toast/useToast.js +14 -0
- package/dist/hooks/useAsyncAction.d.ts +27 -0
- package/dist/hooks/useAsyncAction.js +36 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.js +4 -1
- package/dist/styles.css +1 -1
- package/package.json +6 -6
|
@@ -5,6 +5,7 @@ import { Upload, X } from "@nexub/icons";
|
|
|
5
5
|
import { cn } from "../../utils/cn.js";
|
|
6
6
|
import { useLocale, useNexubMessages } from "../NexubProvider/NexubProvider.js";
|
|
7
7
|
import { Progress } from "../Progress/Progress.js";
|
|
8
|
+
import { SPRING_MS } from "../Motion/useMotion.js";
|
|
8
9
|
function formatFileSize(bytes, locale) {
|
|
9
10
|
const [value, unit] = bytes < 1024 ? [bytes, "byte"] : bytes < 1024 * 1024 ? [bytes / 1024, "kilobyte"] : [bytes / (1024 * 1024), "megabyte"];
|
|
10
11
|
return new Intl.NumberFormat(locale, { style: "unit", unit, unitDisplay: "short", maximumFractionDigits: 1 }).format(value);
|
|
@@ -27,7 +28,7 @@ function useFileUpload() {
|
|
|
27
28
|
return ctx;
|
|
28
29
|
}
|
|
29
30
|
const Root = React.forwardRef(
|
|
30
|
-
({ className, accept, maxFiles, maxSize, onFilesChange, onReject, validate, children, ...props }, ref) => {
|
|
31
|
+
({ className, accept, maxFiles, maxSize, onFilesChange, onReject, validate, onPaste, children, ...props }, ref) => {
|
|
31
32
|
const [files, setFiles] = React.useState([]);
|
|
32
33
|
const [rejections, setRejections] = React.useState([]);
|
|
33
34
|
const [isDragging, setIsDragging] = React.useState(false);
|
|
@@ -65,7 +66,22 @@ const Root = React.forwardRef(
|
|
|
65
66
|
() => ({ accept, maxFiles, maxSize, onFilesChange, files, rejections, addFiles, removeFile, isDragging, setIsDragging }),
|
|
66
67
|
[accept, maxFiles, maxSize, onFilesChange, files, rejections, addFiles, removeFile, isDragging, setIsDragging]
|
|
67
68
|
);
|
|
68
|
-
return /* @__PURE__ */ jsx(FileUploadContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
69
|
+
return /* @__PURE__ */ jsx(FileUploadContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
70
|
+
"div",
|
|
71
|
+
{
|
|
72
|
+
ref,
|
|
73
|
+
className: cn("flex flex-col gap-4", className),
|
|
74
|
+
onPaste: (e) => {
|
|
75
|
+
onPaste?.(e);
|
|
76
|
+
const pasted = Array.from(e.clipboardData?.files ?? []);
|
|
77
|
+
if (e.defaultPrevented || !pasted.length) return;
|
|
78
|
+
e.preventDefault();
|
|
79
|
+
addFiles(pasted);
|
|
80
|
+
},
|
|
81
|
+
...props,
|
|
82
|
+
children
|
|
83
|
+
}
|
|
84
|
+
) });
|
|
69
85
|
}
|
|
70
86
|
);
|
|
71
87
|
Root.displayName = "FileUpload.Root";
|
|
@@ -140,7 +156,7 @@ const List = React.forwardRef(
|
|
|
140
156
|
({ className, ...props }, ref) => {
|
|
141
157
|
const { files } = useFileUpload();
|
|
142
158
|
if (files.length === 0) return null;
|
|
143
|
-
return /* @__PURE__ */ jsx("ul", { ref, className: cn("flex flex-col
|
|
159
|
+
return /* @__PURE__ */ jsx("ul", { ref, className: cn("flex flex-col", className), ...props });
|
|
144
160
|
}
|
|
145
161
|
);
|
|
146
162
|
List.displayName = "FileUpload.List";
|
|
@@ -149,40 +165,78 @@ const Item = React.forwardRef(({ className, index, progress, onCancel, error, ..
|
|
|
149
165
|
const messages = useNexubMessages();
|
|
150
166
|
const { locale } = useLocale();
|
|
151
167
|
const file = files[index];
|
|
168
|
+
const [exiting, setExiting] = React.useState(null);
|
|
169
|
+
const [entered, setEntered] = React.useState(false);
|
|
170
|
+
const [thumb, setThumb] = React.useState();
|
|
171
|
+
React.useEffect(() => {
|
|
172
|
+
if (!file?.type.startsWith("image/") || typeof URL.createObjectURL !== "function") return;
|
|
173
|
+
const url = URL.createObjectURL(file);
|
|
174
|
+
setThumb(url);
|
|
175
|
+
return () => {
|
|
176
|
+
URL.revokeObjectURL(url);
|
|
177
|
+
setThumb(void 0);
|
|
178
|
+
};
|
|
179
|
+
}, [file]);
|
|
180
|
+
const isExiting = !!file && exiting === file;
|
|
181
|
+
React.useEffect(() => {
|
|
182
|
+
if (!isExiting) return;
|
|
183
|
+
const t = setTimeout(() => removeFile(index), SPRING_MS.effects.default + 50);
|
|
184
|
+
return () => clearTimeout(t);
|
|
185
|
+
}, [isExiting, index, removeFile]);
|
|
152
186
|
if (!file) return null;
|
|
153
187
|
const uploading = progress !== void 0 && progress < 100;
|
|
154
188
|
const percent = Math.round(Math.max(0, Math.min(100, progress ?? 0)));
|
|
155
|
-
return
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
className
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
uploading && /* @__PURE__ */ jsx(Progress, { value: percent, size: "sm", className: "mt-1.5", "aria-label": messages.uploadProgress(file.name, percent) }),
|
|
172
|
-
error && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-1 text-xs text-[var(--color-error)]", children: error })
|
|
173
|
-
] }),
|
|
174
|
-
/* @__PURE__ */ jsx(
|
|
175
|
-
"button",
|
|
189
|
+
return (
|
|
190
|
+
// nx-list-item: grows in on add, collapses out on remove (grid rows, spring tokens).
|
|
191
|
+
/* @__PURE__ */ jsx(
|
|
192
|
+
"li",
|
|
193
|
+
{
|
|
194
|
+
ref,
|
|
195
|
+
className: "nx-list-item",
|
|
196
|
+
"data-state": isExiting ? "exit" : entered ? void 0 : "enter",
|
|
197
|
+
onAnimationEnd: (e) => {
|
|
198
|
+
if (e.target !== e.currentTarget) return;
|
|
199
|
+
if (isExiting) removeFile(index);
|
|
200
|
+
else setEntered(true);
|
|
201
|
+
},
|
|
202
|
+
...props,
|
|
203
|
+
children: /* @__PURE__ */ jsx("div", { className: "nx-list-item-inner", children: /* @__PURE__ */ jsx("div", { className: "[li:not(:last-child)>.nx-list-item-inner>&]:pb-2", children: /* @__PURE__ */ jsxs(
|
|
204
|
+
"div",
|
|
176
205
|
{
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
children:
|
|
206
|
+
className: cn(
|
|
207
|
+
"flex items-center justify-between gap-3 rounded-shape-container border border-[var(--color-outline-variant)] bg-[var(--color-surface)] p-3",
|
|
208
|
+
className
|
|
209
|
+
),
|
|
210
|
+
children: [
|
|
211
|
+
thumb && /* @__PURE__ */ jsx("img", { src: thumb, alt: "", className: "h-10 w-10 shrink-0 rounded-shape-min object-cover" }),
|
|
212
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
213
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-[var(--color-on-surface)]", children: file.name }),
|
|
214
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-[var(--color-on-surface-muted)]", children: [
|
|
215
|
+
formatFileSize(file.size, locale),
|
|
216
|
+
uploading && ` \xB7 ${percent}%`
|
|
217
|
+
] }),
|
|
218
|
+
uploading && /* @__PURE__ */ jsx(Progress, { value: percent, size: "sm", className: "mt-1.5", "aria-label": messages.uploadProgress(file.name, percent) }),
|
|
219
|
+
error && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-1 text-xs text-[var(--color-error)]", children: error })
|
|
220
|
+
] }),
|
|
221
|
+
/* @__PURE__ */ jsx(
|
|
222
|
+
"button",
|
|
223
|
+
{
|
|
224
|
+
type: "button",
|
|
225
|
+
onClick: () => {
|
|
226
|
+
if (uploading && onCancel) return onCancel();
|
|
227
|
+
setEntered(true);
|
|
228
|
+
setExiting(file);
|
|
229
|
+
},
|
|
230
|
+
"aria-label": uploading && onCancel ? messages.cancelUpload(file.name) : messages.removeFile(file.name),
|
|
231
|
+
className: "nx-state-layer shrink-0 rounded-full p-1 text-[var(--color-on-surface-muted)] hover:text-[var(--color-on-surface)] transition-colors",
|
|
232
|
+
children: /* @__PURE__ */ jsx(X, { size: "sm", "aria-hidden": "true" })
|
|
233
|
+
}
|
|
234
|
+
)
|
|
235
|
+
]
|
|
182
236
|
}
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
|
|
237
|
+
) }) })
|
|
238
|
+
}
|
|
239
|
+
)
|
|
186
240
|
);
|
|
187
241
|
});
|
|
188
242
|
Item.displayName = "FileUpload.Item";
|
|
@@ -17,5 +17,11 @@ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElem
|
|
|
17
17
|
leadingIcon?: React.ReactNode;
|
|
18
18
|
trailingIcon?: React.ReactNode;
|
|
19
19
|
wrapperClassName?: string;
|
|
20
|
+
/** Shows a clear button while there is a value. Clearing fires `onChange` with "". */
|
|
21
|
+
clearable?: boolean;
|
|
22
|
+
/** Shows a "12/80" counter; needs `maxLength`. Announced politely near the limit. */
|
|
23
|
+
showCount?: boolean;
|
|
24
|
+
/** Spinner in the trailing slot and `aria-busy` on the input. */
|
|
25
|
+
loading?: boolean;
|
|
20
26
|
}
|
|
21
27
|
export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
3
|
import * as React from "react";
|
|
4
|
+
import { X } from "@nexub/icons";
|
|
3
5
|
import { cva } from "class-variance-authority";
|
|
4
6
|
import { cn } from "../../utils/cn.js";
|
|
5
7
|
import { field, fieldDisabledWithin, fieldFocusWithin, fieldInvalid } from "../../utils/control.js";
|
|
8
|
+
import { useMergedRefs } from "../../hooks/useMergedRefs.js";
|
|
9
|
+
import { useNexubMessages } from "../NexubProvider/NexubProvider.js";
|
|
10
|
+
import { IconButton } from "../IconButton/IconButton.js";
|
|
11
|
+
import { Spinner } from "../Spinner/Spinner.js";
|
|
6
12
|
const inputVariants = cva(
|
|
7
13
|
[
|
|
8
14
|
// The wrapper owns ALL focus styling (border + ring). Strip every possible
|
|
@@ -67,6 +73,7 @@ const addonVariants = cva(
|
|
|
67
73
|
}
|
|
68
74
|
}
|
|
69
75
|
);
|
|
76
|
+
const nearLimit = (length, max) => length >= max - Math.max(1, Math.ceil(max * 0.1));
|
|
70
77
|
const Input = React.forwardRef(
|
|
71
78
|
({
|
|
72
79
|
className,
|
|
@@ -78,26 +85,61 @@ const Input = React.forwardRef(
|
|
|
78
85
|
trailingIcon,
|
|
79
86
|
wrapperClassName,
|
|
80
87
|
disabled,
|
|
88
|
+
clearable,
|
|
89
|
+
showCount,
|
|
90
|
+
loading,
|
|
81
91
|
...props
|
|
82
92
|
}, ref) => {
|
|
83
93
|
const hasAddon = Boolean(leadingAddon ?? trailingAddon);
|
|
94
|
+
const messages = useNexubMessages();
|
|
95
|
+
const innerRef = React.useRef(null);
|
|
96
|
+
const mergedRef = useMergedRefs(ref, innerRef);
|
|
97
|
+
const countId = React.useId();
|
|
98
|
+
const [uncontrolledLength, setLength] = React.useState(String(props.defaultValue ?? "").length);
|
|
99
|
+
const length = props.value !== void 0 && props.value !== null ? String(props.value).length : uncontrolledLength;
|
|
100
|
+
const max = props.maxLength;
|
|
101
|
+
const counting = Boolean(showCount && max !== void 0 && max >= 0);
|
|
102
|
+
const handleChange = (e) => {
|
|
103
|
+
setLength(e.target.value.length);
|
|
104
|
+
props.onChange?.(e);
|
|
105
|
+
};
|
|
106
|
+
const clear = () => {
|
|
107
|
+
const el = innerRef.current;
|
|
108
|
+
if (!el) return;
|
|
109
|
+
Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set?.call(el, "");
|
|
110
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
111
|
+
el.focus();
|
|
112
|
+
};
|
|
84
113
|
const inputEl = /* @__PURE__ */ jsx(
|
|
85
114
|
"input",
|
|
86
115
|
{
|
|
87
|
-
ref,
|
|
88
116
|
className: cn(inputVariants({ size }), className),
|
|
89
117
|
"aria-invalid": invalid ?? void 0,
|
|
118
|
+
"aria-busy": loading || void 0,
|
|
90
119
|
disabled,
|
|
91
|
-
...props
|
|
120
|
+
...props,
|
|
121
|
+
"aria-describedby": [props["aria-describedby"], counting && countId].filter(Boolean).join(" ") || void 0,
|
|
122
|
+
onChange: handleChange,
|
|
123
|
+
ref: mergedRef
|
|
92
124
|
}
|
|
93
125
|
);
|
|
126
|
+
const showClear = clearable && length > 0 && !disabled && !props.readOnly;
|
|
127
|
+
const trailing = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
128
|
+
counting && /* @__PURE__ */ jsxs("span", { className: "shrink-0 text-label-sm tabular-nums text-[var(--color-on-surface-muted)]", children: [
|
|
129
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: `${length}/${max}` }),
|
|
130
|
+
/* @__PURE__ */ jsx("span", { id: countId, className: "sr-only", "aria-live": nearLimit(length, max) ? "polite" : "off", children: messages.characterCount(length, max) })
|
|
131
|
+
] }),
|
|
132
|
+
loading && /* @__PURE__ */ jsx(Spinner, { size: "sm", className: "shrink-0" }),
|
|
133
|
+
showClear && /* @__PURE__ */ jsx(IconButton, { size: "xs", label: messages.clear, onClick: clear, className: "-me-1.5", children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4", "aria-hidden": "true" }) }),
|
|
134
|
+
trailingIcon && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[var(--color-on-surface-variant)]", children: trailingIcon })
|
|
135
|
+
] });
|
|
94
136
|
if (hasAddon) {
|
|
95
137
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex w-full overflow-hidden", field, fieldFocusWithin, invalid && fieldInvalid), children: [
|
|
96
138
|
leadingAddon && /* @__PURE__ */ jsx("span", { className: cn(addonVariants({ side: "leading" })), children: leadingAddon }),
|
|
97
139
|
/* @__PURE__ */ jsxs("div", { className: cn(inputWrapperVariants({ size, invalid }), "rounded-none border-0 shadow-none focus-within:shadow-none", wrapperClassName), children: [
|
|
98
140
|
leadingIcon && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[var(--color-on-surface-variant)]", children: leadingIcon }),
|
|
99
141
|
inputEl,
|
|
100
|
-
|
|
142
|
+
trailing
|
|
101
143
|
] }),
|
|
102
144
|
trailingAddon && /* @__PURE__ */ jsx("span", { className: cn(addonVariants({ side: "trailing" })), children: trailingAddon })
|
|
103
145
|
] });
|
|
@@ -105,7 +147,7 @@ const Input = React.forwardRef(
|
|
|
105
147
|
return /* @__PURE__ */ jsxs("div", { className: cn(inputWrapperVariants({ size, invalid }), wrapperClassName), children: [
|
|
106
148
|
leadingIcon && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[var(--color-on-surface-variant)]", children: leadingIcon }),
|
|
107
149
|
inputEl,
|
|
108
|
-
|
|
150
|
+
trailing
|
|
109
151
|
] });
|
|
110
152
|
}
|
|
111
153
|
);
|
|
@@ -13,5 +13,9 @@ export interface ProgressProps extends Omit<React.HTMLAttributes<HTMLDivElement>
|
|
|
13
13
|
max?: number;
|
|
14
14
|
tone?: ToneValue;
|
|
15
15
|
animated?: boolean;
|
|
16
|
+
/** `circular` draws a ring; same value/max/indeterminate semantics. @default 'linear' */
|
|
17
|
+
variant?: 'linear' | 'circular';
|
|
18
|
+
/** Linear only: splits the bar into N equal steps, filled up to the value. */
|
|
19
|
+
segments?: number;
|
|
16
20
|
}
|
|
17
21
|
export declare const Progress: React.ForwardRefExoticComponent<ProgressProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { cva } from "class-variance-authority";
|
|
5
5
|
import { cn } from "../../utils/cn.js";
|
|
@@ -43,6 +43,18 @@ const progressFillVariants = cva(
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
);
|
|
46
|
+
const ringTone = {
|
|
47
|
+
neutral: "stroke-[var(--color-outline)]",
|
|
48
|
+
info: "stroke-[var(--color-info)]",
|
|
49
|
+
success: "stroke-[var(--color-success)]",
|
|
50
|
+
warning: "stroke-[var(--color-warning)]",
|
|
51
|
+
danger: "stroke-[var(--color-error)]",
|
|
52
|
+
leap: "stroke-[var(--color-leap)]",
|
|
53
|
+
bookub: "stroke-[var(--color-bookub)]",
|
|
54
|
+
payub: "stroke-[var(--color-payub)]",
|
|
55
|
+
founderub: "stroke-[var(--color-founderub)]"
|
|
56
|
+
};
|
|
57
|
+
const ringSize = { sm: "size-6", md: "size-10", lg: "size-16" };
|
|
46
58
|
const Progress = React.forwardRef(
|
|
47
59
|
({
|
|
48
60
|
className,
|
|
@@ -51,6 +63,8 @@ const Progress = React.forwardRef(
|
|
|
51
63
|
value,
|
|
52
64
|
max = 100,
|
|
53
65
|
animated = false,
|
|
66
|
+
variant = "linear",
|
|
67
|
+
segments,
|
|
54
68
|
...props
|
|
55
69
|
}, ref) => {
|
|
56
70
|
const isIndeterminate = value === void 0 || value === null;
|
|
@@ -60,31 +74,70 @@ const Progress = React.forwardRef(
|
|
|
60
74
|
useIsomorphicLayoutEffect(() => {
|
|
61
75
|
fillRef.current?.style.setProperty("width", `${percentage}%`);
|
|
62
76
|
}, [percentage]);
|
|
63
|
-
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
"div",
|
|
77
|
+
const aria = {
|
|
78
|
+
role: "progressbar",
|
|
79
|
+
"aria-valuenow": isIndeterminate ? void 0 : clampedValue,
|
|
80
|
+
"aria-valuemin": 0,
|
|
81
|
+
"aria-valuemax": max
|
|
82
|
+
};
|
|
83
|
+
if (variant === "circular") {
|
|
84
|
+
return /* @__PURE__ */ jsx("div", { ref, ...aria, className: cn("inline-flex", ringSize[size ?? "md"], className), ...props, children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 36 36", className: cn("size-full -rotate-90", isIndeterminate && "animate-spin motion-reduce:animate-none"), "aria-hidden": "true", children: [
|
|
85
|
+
/* @__PURE__ */ jsx("circle", { cx: "18", cy: "18", r: "15", fill: "none", strokeWidth: "4", className: "stroke-[var(--color-surface-container-high)]" }),
|
|
86
|
+
/* @__PURE__ */ jsx(
|
|
87
|
+
"circle",
|
|
75
88
|
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
89
|
+
cx: "18",
|
|
90
|
+
cy: "18",
|
|
91
|
+
r: "15",
|
|
92
|
+
fill: "none",
|
|
93
|
+
strokeWidth: "4",
|
|
94
|
+
strokeLinecap: "round",
|
|
95
|
+
pathLength: 100,
|
|
96
|
+
strokeDasharray: `${isIndeterminate ? 25 : percentage} 100`,
|
|
97
|
+
className: cn("transition-all duration-spatial-default ease-spatial-default", ringTone[tone]),
|
|
82
98
|
"data-part": "fill",
|
|
83
99
|
"data-indeterminate": isIndeterminate || void 0
|
|
84
100
|
}
|
|
85
101
|
)
|
|
102
|
+
] }) });
|
|
103
|
+
}
|
|
104
|
+
if (segments && segments > 0 && !isIndeterminate) {
|
|
105
|
+
const filled = Math.round(percentage / 100 * segments);
|
|
106
|
+
return /* @__PURE__ */ jsx(
|
|
107
|
+
"div",
|
|
108
|
+
{
|
|
109
|
+
ref,
|
|
110
|
+
...aria,
|
|
111
|
+
className: cn(progressTrackVariants({ size }), "flex gap-1 bg-transparent", className),
|
|
112
|
+
...props,
|
|
113
|
+
children: Array.from({ length: segments }, (_, i) => /* @__PURE__ */ jsx(
|
|
114
|
+
"div",
|
|
115
|
+
{
|
|
116
|
+
"data-part": "segment",
|
|
117
|
+
"data-filled": i < filled || void 0,
|
|
118
|
+
className: cn(
|
|
119
|
+
"flex-1",
|
|
120
|
+
i < filled ? progressFillVariants({ tone }) : "rounded-full bg-[var(--color-surface-container-high)]"
|
|
121
|
+
)
|
|
122
|
+
},
|
|
123
|
+
i
|
|
124
|
+
))
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return /* @__PURE__ */ jsx("div", { ref, ...aria, className: cn(progressTrackVariants({ size }), className), ...props, children: /* @__PURE__ */ jsx(
|
|
129
|
+
"div",
|
|
130
|
+
{
|
|
131
|
+
className: cn(
|
|
132
|
+
progressFillVariants({ tone }),
|
|
133
|
+
animated && "animate-pulse",
|
|
134
|
+
isIndeterminate && "animate-[nx-progress-indeterminate_1.4s_ease-in-out_infinite]"
|
|
135
|
+
),
|
|
136
|
+
ref: fillRef,
|
|
137
|
+
"data-part": "fill",
|
|
138
|
+
"data-indeterminate": isIndeterminate || void 0
|
|
86
139
|
}
|
|
87
|
-
);
|
|
140
|
+
) });
|
|
88
141
|
}
|
|
89
142
|
);
|
|
90
143
|
Progress.displayName = "Progress";
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import * as RadixSelect from '@radix-ui/react-select';
|
|
3
|
+
export interface SelectRootProps extends RadixSelect.SelectProps {
|
|
4
|
+
/** Shows a clear button on the Trigger while there is a value; clearing calls `onValueChange('')` and shows the placeholder. */
|
|
5
|
+
clearable?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface SelectContentProps extends RadixSelect.SelectContentProps {
|
|
8
|
+
/** A filter field at the top; items whose text (or `textValue`) doesn't match are hidden. Typing on an item moves to the field. */
|
|
9
|
+
searchable?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface SelectItemProps extends RadixSelect.SelectItemProps {
|
|
12
|
+
/** A secondary line under the label: the option's accessible description, not part of its name. */
|
|
13
|
+
description?: React.ReactNode;
|
|
14
|
+
}
|
|
3
15
|
export declare const Select: {
|
|
4
|
-
Root:
|
|
16
|
+
Root: {
|
|
17
|
+
({ clearable, value, defaultValue, onValueChange, onOpenChange, ...props }: SelectRootProps): React.JSX.Element;
|
|
18
|
+
displayName: string;
|
|
19
|
+
};
|
|
5
20
|
Group: React.ForwardRefExoticComponent<RadixSelect.SelectGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
6
21
|
Value: React.ForwardRefExoticComponent<RadixSelect.SelectValueProps & React.RefAttributes<HTMLSpanElement>>;
|
|
7
22
|
Trigger: React.ForwardRefExoticComponent<RadixSelect.SelectTriggerProps & {
|
|
@@ -9,8 +24,8 @@ export declare const Select: {
|
|
|
9
24
|
} & React.RefAttributes<HTMLButtonElement>>;
|
|
10
25
|
ScrollUpButton: React.ForwardRefExoticComponent<RadixSelect.SelectScrollUpButtonProps & React.RefAttributes<HTMLDivElement>>;
|
|
11
26
|
ScrollDownButton: React.ForwardRefExoticComponent<RadixSelect.SelectScrollDownButtonProps & React.RefAttributes<HTMLDivElement>>;
|
|
12
|
-
Content: React.ForwardRefExoticComponent<
|
|
27
|
+
Content: React.ForwardRefExoticComponent<SelectContentProps & React.RefAttributes<HTMLDivElement>>;
|
|
13
28
|
Label: React.ForwardRefExoticComponent<RadixSelect.SelectLabelProps & React.RefAttributes<HTMLDivElement>>;
|
|
14
|
-
Item: React.ForwardRefExoticComponent<
|
|
29
|
+
Item: React.ForwardRefExoticComponent<SelectItemProps & React.RefAttributes<HTMLDivElement>>;
|
|
15
30
|
Separator: React.ForwardRefExoticComponent<RadixSelect.SelectSeparatorProps & React.RefAttributes<HTMLDivElement>>;
|
|
16
31
|
};
|