@annondeveloper/ui-kit 0.2.0 → 0.2.1
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/README.md +1463 -127
- package/dist/form.js +1 -2
- package/dist/form.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +123 -65
- package/dist/index.js.map +1 -1
- package/package.json +24 -26
- package/src/components/animated-counter.tsx +6 -4
- package/src/components/color-input.tsx +27 -14
- package/src/components/command-bar.tsx +2 -1
- package/src/components/copy-block.tsx +7 -12
- package/src/components/data-table.tsx +7 -12
- package/src/components/diff-viewer.tsx +21 -0
- package/src/components/heatmap-calendar.tsx +6 -1
- package/src/components/infinite-scroll.tsx +8 -3
- package/src/components/live-feed.tsx +2 -0
- package/src/components/log-viewer.tsx +2 -0
- package/src/components/notification-stack.tsx +8 -1
- package/src/components/sortable-list.tsx +17 -13
- package/src/components/step-wizard.tsx +9 -1
- package/src/components/streaming-text.tsx +6 -9
- package/src/theme.css +6 -0
package/dist/form.js
CHANGED
|
@@ -131,8 +131,7 @@ function RHFToggleSwitch({
|
|
|
131
131
|
{
|
|
132
132
|
enabled: !!field.value,
|
|
133
133
|
onChange: field.onChange,
|
|
134
|
-
disabled
|
|
135
|
-
label
|
|
134
|
+
disabled
|
|
136
135
|
}
|
|
137
136
|
),
|
|
138
137
|
label && /* @__PURE__ */ jsx("span", { className: "text-sm text-[hsl(var(--text-primary))]", children: label })
|
package/dist/form.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/form-integration.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"sources":["../src/form-integration.tsx"],"names":[],"mappings":"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","file":"form.js","sourcesContent":["'use client'\n\nimport type React from 'react'\nimport { Controller, type Control, type FieldValues, type Path, type RegisterOptions } from 'react-hook-form'\nimport { FormInput, INPUT_CLS } from './components/form-input'\nimport { Select, type SelectOption } from './components/select'\nimport { Checkbox } from './components/checkbox'\nimport { ToggleSwitch } from './components/toggle-switch'\nimport { cn } from './utils'\n\n// ── Shared error display ──────────────────────────────────────────────────\n\nfunction FieldError({ message }: { message?: string }) {\n if (!message) return null\n return (\n <p className=\"mt-1 text-xs text-[hsl(var(--status-critical))]\">{message}</p>\n )\n}\n\n// ── RHFFormInput ──────────────────────────────────────────────────────────\n\nexport interface RHFFormInputProps<T extends FieldValues> {\n control: Control<T>\n name: Path<T>\n rules?: RegisterOptions<T, Path<T>>\n label: string\n type?: string\n placeholder?: string\n required?: boolean\n disabled?: boolean\n hint?: string\n className?: string\n autoComplete?: string\n}\n\n/**\n * FormInput wrapper for react-hook-form.\n * Shows validation errors from fieldState.error automatically.\n */\nexport function RHFFormInput<T extends FieldValues>({\n control, name, rules, label, type = 'text',\n placeholder, required, disabled, hint, className, autoComplete,\n}: RHFFormInputProps<T>): React.JSX.Element {\n return (\n <Controller\n control={control}\n name={name}\n rules={rules}\n render={({ field, fieldState }) => (\n <div className={cn('space-y-1.5', className)}>\n <FormInput\n label={label}\n value={field.value ?? ''}\n onChange={field.onChange}\n type={type}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n hint={fieldState.error ? undefined : hint}\n autoComplete={autoComplete}\n />\n <FieldError message={fieldState.error?.message} />\n </div>\n )}\n />\n )\n}\n\n// ── RHFSelect ─────────────────────────────────────────────────────────────\n\nexport interface RHFSelectProps<T extends FieldValues> {\n control: Control<T>\n name: Path<T>\n rules?: RegisterOptions<T, Path<T>>\n options: SelectOption[]\n placeholder?: string\n disabled?: boolean\n className?: string\n label?: string\n}\n\n/**\n * Select wrapper for react-hook-form.\n * Shows validation errors from fieldState.error automatically.\n */\nexport function RHFSelect<T extends FieldValues>({\n control, name, rules, options, placeholder, disabled, className, label,\n}: RHFSelectProps<T>): React.JSX.Element {\n return (\n <Controller\n control={control}\n name={name}\n rules={rules}\n render={({ field, fieldState }) => (\n <div className={cn('space-y-1.5', className)}>\n {label && (\n <label className=\"mb-1.5 block text-xs font-medium uppercase tracking-wider text-[hsl(var(--text-secondary))]\">\n {label}\n </label>\n )}\n <Select\n value={field.value ?? ''}\n onValueChange={field.onChange}\n options={options}\n placeholder={placeholder}\n disabled={disabled}\n className={fieldState.error ? 'border-[hsl(var(--status-critical))]' : undefined}\n />\n <FieldError message={fieldState.error?.message} />\n </div>\n )}\n />\n )\n}\n\n// ── RHFCheckbox ───────────────────────────────────────────────────────────\n\nexport interface RHFCheckboxProps<T extends FieldValues> {\n control: Control<T>\n name: Path<T>\n rules?: RegisterOptions<T, Path<T>>\n label?: string\n disabled?: boolean\n className?: string\n}\n\n/**\n * Checkbox wrapper for react-hook-form.\n * Shows validation errors from fieldState.error automatically.\n */\nexport function RHFCheckbox<T extends FieldValues>({\n control, name, rules, label, disabled, className,\n}: RHFCheckboxProps<T>): React.JSX.Element {\n return (\n <Controller\n control={control}\n name={name}\n rules={rules}\n render={({ field, fieldState }) => (\n <div className={cn('space-y-1', className)}>\n <div className=\"flex items-center gap-2\">\n <Checkbox\n checked={!!field.value}\n onChange={(e) => field.onChange(e.target.checked)}\n disabled={disabled}\n />\n {label && (\n <span className=\"text-sm text-[hsl(var(--text-primary))]\">{label}</span>\n )}\n </div>\n <FieldError message={fieldState.error?.message} />\n </div>\n )}\n />\n )\n}\n\n// ── RHFToggleSwitch ───────────────────────────────────────────────────────\n\nexport interface RHFToggleSwitchProps<T extends FieldValues> {\n control: Control<T>\n name: Path<T>\n rules?: RegisterOptions<T, Path<T>>\n label?: string\n disabled?: boolean\n className?: string\n}\n\n/**\n * ToggleSwitch wrapper for react-hook-form.\n * Shows validation errors from fieldState.error automatically.\n */\nexport function RHFToggleSwitch<T extends FieldValues>({\n control, name, rules, label, disabled, className,\n}: RHFToggleSwitchProps<T>): React.JSX.Element {\n return (\n <Controller\n control={control}\n name={name}\n rules={rules}\n render={({ field, fieldState }) => (\n <div className={cn('space-y-1', className)}>\n <div className=\"flex items-center gap-2\">\n <ToggleSwitch\n enabled={!!field.value}\n onChange={field.onChange}\n disabled={disabled}\n />\n {label && (\n <span className=\"text-sm text-[hsl(var(--text-primary))]\">{label}</span>\n )}\n </div>\n <FieldError message={fieldState.error?.message} />\n </div>\n )}\n />\n )\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1300,6 +1300,8 @@ interface InfiniteScrollProps<T> {
|
|
|
1300
1300
|
itemHeight?: number;
|
|
1301
1301
|
/** Content to display when items array is empty. */
|
|
1302
1302
|
emptyState?: React.ReactNode;
|
|
1303
|
+
/** Function to derive a stable key for each item. Falls back to index. */
|
|
1304
|
+
getItemKey?: (item: T, index: number) => string | number;
|
|
1303
1305
|
/** Additional class name for the scroll container. */
|
|
1304
1306
|
className?: string;
|
|
1305
1307
|
}
|
|
@@ -1308,7 +1310,7 @@ interface InfiniteScrollProps<T> {
|
|
|
1308
1310
|
* Supports optional height-based virtualization, loading indicators, scroll-to-top,
|
|
1309
1311
|
* empty states, and skeleton placeholders. No scroll event listeners used.
|
|
1310
1312
|
*/
|
|
1311
|
-
declare function InfiniteScroll<T>({ items, renderItem, loadMore, hasMore, isLoading, threshold, itemHeight, emptyState, className, }: InfiniteScrollProps<T>): React.JSX.Element;
|
|
1313
|
+
declare function InfiniteScroll<T>({ items, renderItem, loadMore, hasMore, isLoading, threshold, itemHeight, getItemKey, emptyState, className, }: InfiniteScrollProps<T>): React.JSX.Element;
|
|
1312
1314
|
|
|
1313
1315
|
/** Props for the ColorInput component. */
|
|
1314
1316
|
interface ColorInputProps {
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cn, clamp } from './chunk-2DWZVHZS.js';
|
|
1
|
+
import { cn, Select, clamp } from './chunk-2DWZVHZS.js';
|
|
2
2
|
export { Checkbox, FormInput, INPUT_CLS, LABEL_CLS, Select, TEXTAREA_CLS, ToggleSwitch, clamp, cn, defaultUtilColorMap, fmtBps, fmtBytes, fmtCompact, fmtDuration, fmtPct, fmtRelative, fmtSpeed, fmtUptime, fmtUtil, stripCidr, utilColor } from './chunk-2DWZVHZS.js';
|
|
3
3
|
import { forwardRef, useRef, useState, useEffect, useCallback, useMemo } from 'react';
|
|
4
4
|
import { Loader2, Check, Copy, AlertTriangle, Search, X, Filter, List, AlignJustify, LayoutList, Columns3, Download, ChevronUp, ChevronDown, ChevronsUpDown, TrendingUp, TrendingDown, ArrowDown, ChevronRight, Play, Pause, XCircle, CheckCircle2, Info, Plus, Sparkles, Hash, Regex, ArrowUp, Minus, WifiOff, Clock, CornerDownLeft, GripVertical, ChevronLeft, Eye, EyeOff } from 'lucide-react';
|
|
@@ -328,10 +328,14 @@ function AnimatedCounter({
|
|
|
328
328
|
const prevRef = useRef(value);
|
|
329
329
|
const rafRef = useRef(null);
|
|
330
330
|
const [displayed, setDisplayed] = useState(value);
|
|
331
|
+
const decimalPlacesRef = useRef(
|
|
332
|
+
Number.isInteger(value) ? 0 : value.toString().split(".")[1]?.length ?? 1
|
|
333
|
+
);
|
|
331
334
|
useEffect(() => {
|
|
332
335
|
const from = prevRef.current;
|
|
333
336
|
const to = value;
|
|
334
337
|
prevRef.current = value;
|
|
338
|
+
decimalPlacesRef.current = Number.isInteger(to) ? 0 : to.toString().split(".")[1]?.length ?? 1;
|
|
335
339
|
if (reduced || from === to) {
|
|
336
340
|
setDisplayed(to);
|
|
337
341
|
return;
|
|
@@ -356,9 +360,7 @@ function AnimatedCounter({
|
|
|
356
360
|
}
|
|
357
361
|
};
|
|
358
362
|
}, [value, duration, reduced]);
|
|
359
|
-
const formatted = format ? format(displayed) :
|
|
360
|
-
value.toString().split(".")[1]?.length ?? 1
|
|
361
|
-
);
|
|
363
|
+
const formatted = format ? format(displayed) : decimalPlacesRef.current === 0 ? Math.round(displayed).toString() : displayed.toFixed(decimalPlacesRef.current);
|
|
362
364
|
return /* @__PURE__ */ jsx("span", { className: cn("tabular-nums", className), children: formatted });
|
|
363
365
|
}
|
|
364
366
|
function SuccessCheckmark({ size = 20, className }) {
|
|
@@ -1012,15 +1014,12 @@ function DataTable({
|
|
|
1012
1014
|
] }),
|
|
1013
1015
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1014
1016
|
/* @__PURE__ */ jsx(
|
|
1015
|
-
|
|
1017
|
+
Select,
|
|
1016
1018
|
{
|
|
1017
|
-
value: pageSize,
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
size,
|
|
1022
|
-
" / page"
|
|
1023
|
-
] }, size))
|
|
1019
|
+
value: String(pageSize),
|
|
1020
|
+
onValueChange: (v) => table.setPageSize(Number(v)),
|
|
1021
|
+
options: PAGE_SIZES.map((size) => ({ value: String(size), label: `${size} / page` })),
|
|
1022
|
+
className: "w-[110px] text-[12px]"
|
|
1024
1023
|
}
|
|
1025
1024
|
),
|
|
1026
1025
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
@@ -2484,6 +2483,8 @@ function LogViewer({
|
|
|
2484
2483
|
onScroll: checkAtBottom,
|
|
2485
2484
|
className: "overflow-y-auto",
|
|
2486
2485
|
style: { maxHeight },
|
|
2486
|
+
"aria-live": "polite",
|
|
2487
|
+
"aria-atomic": "false",
|
|
2487
2488
|
children: filtered.map((entry, i) => /* @__PURE__ */ jsxs(
|
|
2488
2489
|
"div",
|
|
2489
2490
|
{
|
|
@@ -2850,6 +2851,10 @@ function StreamingText({
|
|
|
2850
2851
|
const containerRef = useRef(null);
|
|
2851
2852
|
const prevStreamingRef = useRef(isStreaming);
|
|
2852
2853
|
const [copied, setCopied] = useState(false);
|
|
2854
|
+
const copyTimerRef = useRef(null);
|
|
2855
|
+
useEffect(() => () => {
|
|
2856
|
+
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
2857
|
+
}, []);
|
|
2853
2858
|
useEffect(() => {
|
|
2854
2859
|
if (prevStreamingRef.current && !isStreaming) {
|
|
2855
2860
|
onComplete?.();
|
|
@@ -2865,7 +2870,8 @@ function StreamingText({
|
|
|
2865
2870
|
const handleCopy = useCallback(() => {
|
|
2866
2871
|
void navigator.clipboard.writeText(text).then(() => {
|
|
2867
2872
|
setCopied(true);
|
|
2868
|
-
|
|
2873
|
+
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
2874
|
+
copyTimerRef.current = setTimeout(() => setCopied(false), 2e3);
|
|
2869
2875
|
});
|
|
2870
2876
|
}, [text]);
|
|
2871
2877
|
const formatted = formatSegments(text);
|
|
@@ -2883,7 +2889,8 @@ function StreamingText({
|
|
|
2883
2889
|
className: "inline-block w-[2px] h-[1.1em] align-text-bottom ml-0.5 bg-[hsl(var(--brand-primary))]",
|
|
2884
2890
|
style: reduced ? { opacity: 1 } : {
|
|
2885
2891
|
animation: `streaming-cursor-blink ${speed}ms step-end infinite`
|
|
2886
|
-
}
|
|
2892
|
+
},
|
|
2893
|
+
"aria-hidden": "true"
|
|
2887
2894
|
}
|
|
2888
2895
|
),
|
|
2889
2896
|
/* @__PURE__ */ jsx(AnimatePresence, { children: showCursor && !isStreaming && text.length > 0 && /* @__PURE__ */ jsx(
|
|
@@ -2916,13 +2923,7 @@ function StreamingText({
|
|
|
2916
2923
|
"aria-label": copied ? "Copied" : "Copy to clipboard",
|
|
2917
2924
|
children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-3.5" }) : /* @__PURE__ */ jsx(Copy, { className: "size-3.5" })
|
|
2918
2925
|
}
|
|
2919
|
-
) })
|
|
2920
|
-
showCursor && isStreaming && !reduced && /* @__PURE__ */ jsx("style", { children: `
|
|
2921
|
-
@keyframes streaming-cursor-blink {
|
|
2922
|
-
0%, 100% { opacity: 1; }
|
|
2923
|
-
50% { opacity: 0; }
|
|
2924
|
-
}
|
|
2925
|
-
` })
|
|
2926
|
+
) })
|
|
2926
2927
|
] });
|
|
2927
2928
|
}
|
|
2928
2929
|
var DOT_SIZES = { sm: "size-1.5", md: "size-2" };
|
|
@@ -3191,6 +3192,8 @@ function LiveFeed({
|
|
|
3191
3192
|
ref: scrollRef,
|
|
3192
3193
|
onScroll: handleScroll,
|
|
3193
3194
|
className: "flex-1 overflow-y-auto",
|
|
3195
|
+
"aria-live": "polite",
|
|
3196
|
+
"aria-atomic": "false",
|
|
3194
3197
|
children: visibleItems.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12 text-sm text-[hsl(var(--text-tertiary))]", children: emptyMessage }) : /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: visibleItems.map((item) => /* @__PURE__ */ jsx(
|
|
3195
3198
|
motion.div,
|
|
3196
3199
|
{
|
|
@@ -3257,7 +3260,25 @@ function LiveFeed({
|
|
|
3257
3260
|
) })
|
|
3258
3261
|
] });
|
|
3259
3262
|
}
|
|
3263
|
+
var MAX_LINES = 2e3;
|
|
3260
3264
|
function computeDiff(oldLines, newLines) {
|
|
3265
|
+
if (oldLines.length > MAX_LINES || newLines.length > MAX_LINES) {
|
|
3266
|
+
const result2 = oldLines.map((l, i2) => ({
|
|
3267
|
+
type: l === (newLines[i2] ?? "") ? "unchanged" : "removed",
|
|
3268
|
+
content: l,
|
|
3269
|
+
oldLineNo: i2 + 1,
|
|
3270
|
+
newLineNo: i2 + 1
|
|
3271
|
+
}));
|
|
3272
|
+
for (let i2 = oldLines.length; i2 < newLines.length; i2++) {
|
|
3273
|
+
result2.push({
|
|
3274
|
+
type: "added",
|
|
3275
|
+
content: newLines[i2],
|
|
3276
|
+
oldLineNo: void 0,
|
|
3277
|
+
newLineNo: i2 + 1
|
|
3278
|
+
});
|
|
3279
|
+
}
|
|
3280
|
+
return result2;
|
|
3281
|
+
}
|
|
3261
3282
|
const m = oldLines.length;
|
|
3262
3283
|
const n = newLines.length;
|
|
3263
3284
|
const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
|
|
@@ -3499,8 +3520,13 @@ function toDateKey(d) {
|
|
|
3499
3520
|
return d.toISOString().slice(0, 10);
|
|
3500
3521
|
}
|
|
3501
3522
|
function parseDate(s) {
|
|
3523
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) {
|
|
3524
|
+
return /* @__PURE__ */ new Date();
|
|
3525
|
+
}
|
|
3502
3526
|
const [y, m, d] = s.split("-").map(Number);
|
|
3503
|
-
|
|
3527
|
+
const date = new Date(y, m - 1, d);
|
|
3528
|
+
if (isNaN(date.getTime())) return /* @__PURE__ */ new Date();
|
|
3529
|
+
return date;
|
|
3504
3530
|
}
|
|
3505
3531
|
function HeatmapCalendar({
|
|
3506
3532
|
data,
|
|
@@ -3629,6 +3655,12 @@ var TYPE_ICON_COLOR = {
|
|
|
3629
3655
|
warning: "text-[hsl(var(--status-warning))]",
|
|
3630
3656
|
error: "text-[hsl(var(--status-critical))]"
|
|
3631
3657
|
};
|
|
3658
|
+
var TYPE_PROGRESS_BG = {
|
|
3659
|
+
info: "bg-[hsl(var(--brand-secondary))]",
|
|
3660
|
+
success: "bg-[hsl(var(--status-ok))]",
|
|
3661
|
+
warning: "bg-[hsl(var(--status-warning))]",
|
|
3662
|
+
error: "bg-[hsl(var(--status-critical))]"
|
|
3663
|
+
};
|
|
3632
3664
|
var POSITION_CLASSES = {
|
|
3633
3665
|
"top-right": "top-4 right-4",
|
|
3634
3666
|
"top-left": "top-4 left-4",
|
|
@@ -3768,7 +3800,7 @@ function NotificationCard({
|
|
|
3768
3800
|
duration > 0 && /* @__PURE__ */ jsx("div", { className: "h-0.5 bg-[hsl(var(--bg-overlay))]", children: /* @__PURE__ */ jsx(
|
|
3769
3801
|
"div",
|
|
3770
3802
|
{
|
|
3771
|
-
className: cn("h-full transition-[width] duration-100",
|
|
3803
|
+
className: cn("h-full transition-[width] duration-100", TYPE_PROGRESS_BG[type]),
|
|
3772
3804
|
style: { width: `${progress}%` }
|
|
3773
3805
|
}
|
|
3774
3806
|
) })
|
|
@@ -4416,7 +4448,8 @@ function CommandBar({
|
|
|
4416
4448
|
const [recentIds, setRecentIds] = useState(() => {
|
|
4417
4449
|
if (typeof window === "undefined") return [];
|
|
4418
4450
|
try {
|
|
4419
|
-
|
|
4451
|
+
const raw = JSON.parse(localStorage.getItem(recentKey) ?? "[]");
|
|
4452
|
+
return Array.isArray(raw) ? raw.filter((x) => typeof x === "string" && x.length < 256).slice(0, maxRecent) : [];
|
|
4420
4453
|
} catch {
|
|
4421
4454
|
return [];
|
|
4422
4455
|
}
|
|
@@ -4667,12 +4700,16 @@ function SortableList({
|
|
|
4667
4700
|
const containerRef = useRef(null);
|
|
4668
4701
|
const startPos = useRef({ x: 0, y: 0 });
|
|
4669
4702
|
const dragItemId = useRef(null);
|
|
4703
|
+
const dragIdxRef = useRef(null);
|
|
4704
|
+
const overIdxRef = useRef(null);
|
|
4670
4705
|
const handlePointerDown = useCallback(
|
|
4671
4706
|
(index) => (e) => {
|
|
4672
4707
|
e.preventDefault();
|
|
4673
4708
|
if (e.button !== 0) return;
|
|
4674
4709
|
setDragIdx(index);
|
|
4675
4710
|
setOverIdx(index);
|
|
4711
|
+
dragIdxRef.current = index;
|
|
4712
|
+
overIdxRef.current = index;
|
|
4676
4713
|
dragItemId.current = items[index]?.id ?? null;
|
|
4677
4714
|
startPos.current = { x: e.clientX, y: e.clientY };
|
|
4678
4715
|
const handlePointerMove = (ev) => {
|
|
@@ -4685,6 +4722,7 @@ function SortableList({
|
|
|
4685
4722
|
const midY = rect.top + rect.height / 2;
|
|
4686
4723
|
const isOver = direction === "vertical" ? ev.clientY < midY + rect.height / 2 && ev.clientY > midY - rect.height / 2 : ev.clientX < midX + rect.width / 2 && ev.clientX > midX - rect.width / 2;
|
|
4687
4724
|
if (isOver) {
|
|
4725
|
+
overIdxRef.current = i;
|
|
4688
4726
|
setOverIdx(i);
|
|
4689
4727
|
break;
|
|
4690
4728
|
}
|
|
@@ -4693,18 +4731,18 @@ function SortableList({
|
|
|
4693
4731
|
const handlePointerUp = () => {
|
|
4694
4732
|
document.removeEventListener("pointermove", handlePointerMove);
|
|
4695
4733
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4734
|
+
const prev = dragIdxRef.current;
|
|
4735
|
+
const over = overIdxRef.current;
|
|
4736
|
+
if (prev !== null && over !== null && prev !== over) {
|
|
4737
|
+
const newItems = [...items];
|
|
4738
|
+
const [moved] = newItems.splice(prev, 1);
|
|
4739
|
+
if (moved) newItems.splice(over, 0, moved);
|
|
4740
|
+
onReorder(newItems);
|
|
4741
|
+
}
|
|
4742
|
+
dragIdxRef.current = null;
|
|
4743
|
+
overIdxRef.current = null;
|
|
4744
|
+
setDragIdx(null);
|
|
4745
|
+
setOverIdx(null);
|
|
4708
4746
|
};
|
|
4709
4747
|
document.addEventListener("pointermove", handlePointerMove);
|
|
4710
4748
|
document.addEventListener("pointerup", handlePointerUp);
|
|
@@ -4840,6 +4878,7 @@ function InfiniteScroll({
|
|
|
4840
4878
|
isLoading = false,
|
|
4841
4879
|
threshold = 200,
|
|
4842
4880
|
itemHeight,
|
|
4881
|
+
getItemKey,
|
|
4843
4882
|
emptyState,
|
|
4844
4883
|
className
|
|
4845
4884
|
}) {
|
|
@@ -4848,6 +4887,10 @@ function InfiniteScroll({
|
|
|
4848
4887
|
const sentinelRef = useRef(null);
|
|
4849
4888
|
const [showScrollTop, setShowScrollTop] = useState(false);
|
|
4850
4889
|
const loadingRef = useRef(false);
|
|
4890
|
+
const loadMoreRef = useRef(loadMore);
|
|
4891
|
+
useEffect(() => {
|
|
4892
|
+
loadMoreRef.current = loadMore;
|
|
4893
|
+
}, [loadMore]);
|
|
4851
4894
|
useEffect(() => {
|
|
4852
4895
|
const sentinel = sentinelRef.current;
|
|
4853
4896
|
if (!sentinel) return;
|
|
@@ -4856,7 +4899,7 @@ function InfiniteScroll({
|
|
|
4856
4899
|
const entry = entries[0];
|
|
4857
4900
|
if (entry?.isIntersecting && hasMore && !isLoading && !loadingRef.current) {
|
|
4858
4901
|
loadingRef.current = true;
|
|
4859
|
-
const result =
|
|
4902
|
+
const result = loadMoreRef.current();
|
|
4860
4903
|
if (result && typeof result.then === "function") {
|
|
4861
4904
|
result.then(() => {
|
|
4862
4905
|
loadingRef.current = false;
|
|
@@ -4875,7 +4918,7 @@ function InfiniteScroll({
|
|
|
4875
4918
|
);
|
|
4876
4919
|
observer.observe(sentinel);
|
|
4877
4920
|
return () => observer.disconnect();
|
|
4878
|
-
}, [hasMore, isLoading,
|
|
4921
|
+
}, [hasMore, isLoading, threshold]);
|
|
4879
4922
|
useEffect(() => {
|
|
4880
4923
|
if (!isLoading) loadingRef.current = false;
|
|
4881
4924
|
}, [isLoading]);
|
|
@@ -4934,7 +4977,7 @@ function InfiniteScroll({
|
|
|
4934
4977
|
children: [
|
|
4935
4978
|
virtualizedContent ? /* @__PURE__ */ jsx("div", { style: { height: virtualizedContent.totalHeight, position: "relative" }, children: /* @__PURE__ */ jsx("div", { style: { position: "absolute", top: virtualizedContent.offsetTop, left: 0, right: 0 }, children: virtualizedContent.visibleItems.map((item, i) => /* @__PURE__ */ jsx("div", { style: { height: itemHeight }, children: renderItem(item, virtualizedContent.startIdx + i) }, virtualizedContent.startIdx + i)) }) }) : (
|
|
4936
4979
|
/* Non-virtualized rendering */
|
|
4937
|
-
items.map((item, index) => /* @__PURE__ */ jsx("div", { children: renderItem(item, index) }, index))
|
|
4980
|
+
items.map((item, index) => /* @__PURE__ */ jsx("div", { children: renderItem(item, index) }, getItemKey ? getItemKey(item, index) : index))
|
|
4938
4981
|
),
|
|
4939
4982
|
isLoading && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-6 gap-2", children: [
|
|
4940
4983
|
/* @__PURE__ */ jsx(Loader2, { className: "h-5 w-5 text-[hsl(var(--brand-primary))] animate-spin" }),
|
|
@@ -5025,6 +5068,9 @@ function formatColor(hex, fmt) {
|
|
|
5025
5068
|
const { h, s, l } = rgbToHsl(r, g, b);
|
|
5026
5069
|
return `hsl(${Math.round(h * 360)}, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%)`;
|
|
5027
5070
|
}
|
|
5071
|
+
function isSafeColor(c) {
|
|
5072
|
+
return /^#[0-9a-f]{3,8}$/i.test(c) || /^rgba?\(\s*[\d.]+/.test(c) || /^hsla?\(\s*[\d.]+/.test(c);
|
|
5073
|
+
}
|
|
5028
5074
|
var RECENT_COLORS_KEY = "ui-kit-recent-colors";
|
|
5029
5075
|
var MAX_RECENT = 8;
|
|
5030
5076
|
function ColorInput({
|
|
@@ -5037,16 +5083,23 @@ function ColorInput({
|
|
|
5037
5083
|
className
|
|
5038
5084
|
}) {
|
|
5039
5085
|
const prefersReducedMotion = useReducedMotion();
|
|
5086
|
+
const isValidHex = /^#[0-9a-f]{3,8}$/i.test(value);
|
|
5087
|
+
const safeValue = isValidHex ? value : "#000000";
|
|
5040
5088
|
const [open, setOpen] = useState(false);
|
|
5041
5089
|
const [copied, setCopied] = useState(false);
|
|
5042
5090
|
const [textInput, setTextInput] = useState("");
|
|
5043
5091
|
const [alpha, setAlpha] = useState(1);
|
|
5044
5092
|
const panelRef = useRef(null);
|
|
5045
5093
|
const satAreaRef = useRef(null);
|
|
5094
|
+
const copyTimerRef = useRef(null);
|
|
5095
|
+
useEffect(() => () => {
|
|
5096
|
+
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
5097
|
+
}, []);
|
|
5046
5098
|
const [recentColors, setRecentColors] = useState(() => {
|
|
5047
5099
|
if (typeof window === "undefined") return [];
|
|
5048
5100
|
try {
|
|
5049
|
-
|
|
5101
|
+
const raw = JSON.parse(localStorage.getItem(RECENT_COLORS_KEY) ?? "[]");
|
|
5102
|
+
return Array.isArray(raw) ? raw.filter((x) => typeof x === "string" && x.length < 256).slice(0, MAX_RECENT) : [];
|
|
5050
5103
|
} catch {
|
|
5051
5104
|
return [];
|
|
5052
5105
|
}
|
|
@@ -5061,11 +5114,11 @@ function ColorInput({
|
|
|
5061
5114
|
return updated;
|
|
5062
5115
|
});
|
|
5063
5116
|
}, []);
|
|
5064
|
-
const { r, g, b } = useMemo(() => hexToRgb(
|
|
5117
|
+
const { r, g, b } = useMemo(() => hexToRgb(safeValue), [safeValue]);
|
|
5065
5118
|
const hsl = useMemo(() => rgbToHsl(r, g, b), [r, g, b]);
|
|
5066
5119
|
useEffect(() => {
|
|
5067
|
-
setTextInput(formatColor(
|
|
5068
|
-
}, [
|
|
5120
|
+
setTextInput(formatColor(safeValue, format));
|
|
5121
|
+
}, [safeValue, format]);
|
|
5069
5122
|
useEffect(() => {
|
|
5070
5123
|
if (!open) return;
|
|
5071
5124
|
const handler = (e) => {
|
|
@@ -5131,16 +5184,17 @@ function ColorInput({
|
|
|
5131
5184
|
onChange(rgbToHex(rgb.r, rgb.g, rgb.b));
|
|
5132
5185
|
return;
|
|
5133
5186
|
}
|
|
5134
|
-
setTextInput(formatColor(
|
|
5135
|
-
}, [textInput,
|
|
5187
|
+
setTextInput(formatColor(safeValue, format));
|
|
5188
|
+
}, [textInput, safeValue, format, onChange]);
|
|
5136
5189
|
const handleCopy = useCallback(async () => {
|
|
5137
5190
|
try {
|
|
5138
|
-
await navigator.clipboard.writeText(formatColor(
|
|
5191
|
+
await navigator.clipboard.writeText(formatColor(safeValue, format));
|
|
5139
5192
|
setCopied(true);
|
|
5140
|
-
|
|
5193
|
+
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
5194
|
+
copyTimerRef.current = setTimeout(() => setCopied(false), 1500);
|
|
5141
5195
|
} catch {
|
|
5142
5196
|
}
|
|
5143
|
-
}, [
|
|
5197
|
+
}, [safeValue, format]);
|
|
5144
5198
|
const markerX = hsl.s * 100;
|
|
5145
5199
|
const markerY = (1 - (hsl.l - 0.05) / 0.9) * 100;
|
|
5146
5200
|
return /* @__PURE__ */ jsxs("div", { ref: panelRef, className: cn("relative inline-block", className), children: [
|
|
@@ -5160,7 +5214,7 @@ function ColorInput({
|
|
|
5160
5214
|
"span",
|
|
5161
5215
|
{
|
|
5162
5216
|
className: "h-5 w-5 rounded-md border border-[hsl(var(--border-subtle))]",
|
|
5163
|
-
style: { backgroundColor:
|
|
5217
|
+
style: { backgroundColor: isSafeColor(safeValue) ? safeValue : void 0 }
|
|
5164
5218
|
}
|
|
5165
5219
|
),
|
|
5166
5220
|
/* @__PURE__ */ jsx("span", { className: "font-mono text-xs text-[hsl(var(--text-primary))]", children: formatColor(value, format) })
|
|
@@ -5198,7 +5252,7 @@ function ColorInput({
|
|
|
5198
5252
|
style: {
|
|
5199
5253
|
left: `${markerX}%`,
|
|
5200
5254
|
top: `${Math.max(0, Math.min(100, markerY))}%`,
|
|
5201
|
-
backgroundColor:
|
|
5255
|
+
backgroundColor: isSafeColor(safeValue) ? safeValue : void 0
|
|
5202
5256
|
}
|
|
5203
5257
|
}
|
|
5204
5258
|
)
|
|
@@ -5228,7 +5282,7 @@ function ColorInput({
|
|
|
5228
5282
|
onChange: (e) => setAlpha(Number(e.target.value) / 100),
|
|
5229
5283
|
className: "w-full h-3 rounded-full appearance-none cursor-pointer",
|
|
5230
5284
|
style: {
|
|
5231
|
-
background: `linear-gradient(to right, transparent, ${
|
|
5285
|
+
background: `linear-gradient(to right, transparent, ${isSafeColor(safeValue) ? safeValue : "#000"})`
|
|
5232
5286
|
}
|
|
5233
5287
|
}
|
|
5234
5288
|
) }),
|
|
@@ -5278,7 +5332,7 @@ function ColorInput({
|
|
|
5278
5332
|
"h-6 w-6 rounded-md border transition-all",
|
|
5279
5333
|
value === color ? "border-[hsl(var(--brand-primary))] ring-2 ring-[hsl(var(--brand-primary)/0.3)] scale-110" : "border-[hsl(var(--border-subtle))] hover:scale-110"
|
|
5280
5334
|
),
|
|
5281
|
-
style: { backgroundColor: color },
|
|
5335
|
+
style: { backgroundColor: isSafeColor(color) ? color : void 0 },
|
|
5282
5336
|
title: color
|
|
5283
5337
|
},
|
|
5284
5338
|
color
|
|
@@ -5294,7 +5348,7 @@ function ColorInput({
|
|
|
5294
5348
|
"h-6 w-6 rounded-md border border-[hsl(var(--border-subtle))]",
|
|
5295
5349
|
"hover:scale-110 transition-transform"
|
|
5296
5350
|
),
|
|
5297
|
-
style: { backgroundColor: color },
|
|
5351
|
+
style: { backgroundColor: isSafeColor(color) ? color : void 0 },
|
|
5298
5352
|
title: color
|
|
5299
5353
|
},
|
|
5300
5354
|
color
|
|
@@ -5345,6 +5399,8 @@ function StepWizard({
|
|
|
5345
5399
|
const [direction, setDirection] = useState(1);
|
|
5346
5400
|
const [isComplete, setIsComplete] = useState(false);
|
|
5347
5401
|
const contentRef = useRef(null);
|
|
5402
|
+
const wizardRef = useRef(null);
|
|
5403
|
+
const validatingRef = useRef(false);
|
|
5348
5404
|
useEffect(() => {
|
|
5349
5405
|
try {
|
|
5350
5406
|
sessionStorage.setItem(sessionKey, JSON.stringify({
|
|
@@ -5362,20 +5418,25 @@ function StepWizard({
|
|
|
5362
5418
|
onStepChange?.(idx);
|
|
5363
5419
|
}, [currentStep, onStepChange]);
|
|
5364
5420
|
const handleNext = useCallback(async () => {
|
|
5421
|
+
if (validatingRef.current) return;
|
|
5365
5422
|
const step = steps[currentStep];
|
|
5366
5423
|
if (step?.validate) {
|
|
5424
|
+
validatingRef.current = true;
|
|
5367
5425
|
setIsValidating(true);
|
|
5368
5426
|
try {
|
|
5369
5427
|
const valid = await step.validate();
|
|
5370
5428
|
if (!valid) {
|
|
5371
5429
|
setIsValidating(false);
|
|
5430
|
+
validatingRef.current = false;
|
|
5372
5431
|
return;
|
|
5373
5432
|
}
|
|
5374
5433
|
} catch {
|
|
5375
5434
|
setIsValidating(false);
|
|
5435
|
+
validatingRef.current = false;
|
|
5376
5436
|
return;
|
|
5377
5437
|
}
|
|
5378
5438
|
setIsValidating(false);
|
|
5439
|
+
validatingRef.current = false;
|
|
5379
5440
|
}
|
|
5380
5441
|
setCompleted((prev) => new Set(prev).add(currentStep));
|
|
5381
5442
|
if (currentStep < totalSteps - 1) {
|
|
@@ -5403,6 +5464,7 @@ function StepWizard({
|
|
|
5403
5464
|
}, [completed, allowSkip, currentStep, goToStep]);
|
|
5404
5465
|
useEffect(() => {
|
|
5405
5466
|
const handler = (e) => {
|
|
5467
|
+
if (!wizardRef.current?.contains(e.target)) return;
|
|
5406
5468
|
if (e.key === "Enter" && !e.shiftKey && !(e.target instanceof HTMLTextAreaElement)) {
|
|
5407
5469
|
handleNext();
|
|
5408
5470
|
}
|
|
@@ -5422,7 +5484,7 @@ function StepWizard({
|
|
|
5422
5484
|
})
|
|
5423
5485
|
};
|
|
5424
5486
|
const isHorizontal = orientation === "horizontal";
|
|
5425
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", className), children: [
|
|
5487
|
+
return /* @__PURE__ */ jsxs("div", { ref: wizardRef, className: cn("flex flex-col", className), children: [
|
|
5426
5488
|
/* @__PURE__ */ jsx("div", { className: cn(
|
|
5427
5489
|
"mb-6",
|
|
5428
5490
|
isHorizontal ? "flex items-center" : "flex flex-col gap-1"
|
|
@@ -5588,6 +5650,10 @@ function CopyBlock({
|
|
|
5588
5650
|
const [isCollapsed, setIsCollapsed] = useState(true);
|
|
5589
5651
|
const [needsCollapse, setNeedsCollapse] = useState(false);
|
|
5590
5652
|
const contentRef = useRef(null);
|
|
5653
|
+
const copyTimerRef = useRef(null);
|
|
5654
|
+
useEffect(() => () => {
|
|
5655
|
+
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
5656
|
+
}, []);
|
|
5591
5657
|
useEffect(() => {
|
|
5592
5658
|
if (!maxHeight || !contentRef.current) return;
|
|
5593
5659
|
setNeedsCollapse(contentRef.current.scrollHeight > maxHeight);
|
|
@@ -5597,18 +5663,10 @@ function CopyBlock({
|
|
|
5597
5663
|
try {
|
|
5598
5664
|
await navigator.clipboard.writeText(content);
|
|
5599
5665
|
setCopied(true);
|
|
5600
|
-
|
|
5666
|
+
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
5667
|
+
copyTimerRef.current = setTimeout(() => setCopied(false), 2e3);
|
|
5601
5668
|
} catch {
|
|
5602
|
-
|
|
5603
|
-
textarea.value = content;
|
|
5604
|
-
textarea.style.position = "fixed";
|
|
5605
|
-
textarea.style.opacity = "0";
|
|
5606
|
-
document.body.appendChild(textarea);
|
|
5607
|
-
textarea.select();
|
|
5608
|
-
document.execCommand("copy");
|
|
5609
|
-
document.body.removeChild(textarea);
|
|
5610
|
-
setCopied(true);
|
|
5611
|
-
setTimeout(() => setCopied(false), 2e3);
|
|
5669
|
+
console.warn("Clipboard API not available");
|
|
5612
5670
|
}
|
|
5613
5671
|
}, [content]);
|
|
5614
5672
|
const shouldCollapse = maxHeight && needsCollapse && isCollapsed;
|