@kjaniec-dev/ui 0.4.0 → 0.4.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/dist/index.cjs +268 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +267 -90
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
|
-
import * as
|
|
3
|
+
import * as React17 from 'react';
|
|
4
4
|
import { cva } from 'class-variance-authority';
|
|
5
5
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
|
+
// src/lib/cn.ts
|
|
7
8
|
function cn(...inputs) {
|
|
8
9
|
return twMerge(clsx(inputs));
|
|
9
10
|
}
|
|
@@ -37,7 +38,7 @@ var buttonVariants = cva(
|
|
|
37
38
|
defaultVariants: { variant: "primary", size: "md" }
|
|
38
39
|
}
|
|
39
40
|
);
|
|
40
|
-
var Button =
|
|
41
|
+
var Button = React17.forwardRef(
|
|
41
42
|
({ className, variant, size, loading, leadingIcon, trailingIcon, children, disabled, ...props }, ref) => {
|
|
42
43
|
return /* @__PURE__ */ jsxs(
|
|
43
44
|
"button",
|
|
@@ -84,7 +85,7 @@ var badgeVariants = cva(
|
|
|
84
85
|
defaultVariants: { variant: "neutral" }
|
|
85
86
|
}
|
|
86
87
|
);
|
|
87
|
-
var Badge =
|
|
88
|
+
var Badge = React17.forwardRef(
|
|
88
89
|
({ className, variant, dot, children, ...props }, ref) => /* @__PURE__ */ jsxs("span", { ref, className: cn(badgeVariants({ variant }), className), ...props, children: [
|
|
89
90
|
dot && /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-current", "aria-hidden": true }),
|
|
90
91
|
children
|
|
@@ -111,7 +112,7 @@ var iconColor = {
|
|
|
111
112
|
warning: "text-warning",
|
|
112
113
|
danger: "text-danger"
|
|
113
114
|
};
|
|
114
|
-
var Alert =
|
|
115
|
+
var Alert = React17.forwardRef(
|
|
115
116
|
({ className, variant = "info", icon, title, children, ...props }, ref) => /* @__PURE__ */ jsxs("div", { ref, role: "alert", className: cn(alertVariants({ variant }), className), ...props, children: [
|
|
116
117
|
icon && /* @__PURE__ */ jsx("span", { className: cn("shrink-0 mt-0.5 [&_svg]:h-[1.15rem] [&_svg]:w-[1.15rem]", iconColor[variant ?? "info"]), children: icon }),
|
|
117
118
|
/* @__PURE__ */ jsxs("div", { className: "text-foreground", children: [
|
|
@@ -121,7 +122,7 @@ var Alert = React16.forwardRef(
|
|
|
121
122
|
] })
|
|
122
123
|
);
|
|
123
124
|
Alert.displayName = "Alert";
|
|
124
|
-
var Spinner =
|
|
125
|
+
var Spinner = React17.forwardRef(
|
|
125
126
|
({ className, size = 24, style, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
126
127
|
"span",
|
|
127
128
|
{
|
|
@@ -138,7 +139,7 @@ var Spinner = React16.forwardRef(
|
|
|
138
139
|
)
|
|
139
140
|
);
|
|
140
141
|
Spinner.displayName = "Spinner";
|
|
141
|
-
var Progress =
|
|
142
|
+
var Progress = React17.forwardRef(
|
|
142
143
|
({ className, value = 0, tone = "primary", barClassName, ...props }, ref) => {
|
|
143
144
|
const pct = Math.max(0, Math.min(100, value));
|
|
144
145
|
return /* @__PURE__ */ jsx(
|
|
@@ -146,6 +147,7 @@ var Progress = React16.forwardRef(
|
|
|
146
147
|
{
|
|
147
148
|
ref,
|
|
148
149
|
role: "progressbar",
|
|
150
|
+
"aria-label": props["aria-label"] ?? "Progress",
|
|
149
151
|
"aria-valuenow": pct,
|
|
150
152
|
"aria-valuemin": 0,
|
|
151
153
|
"aria-valuemax": 100,
|
|
@@ -168,7 +170,7 @@ var Progress = React16.forwardRef(
|
|
|
168
170
|
);
|
|
169
171
|
Progress.displayName = "Progress";
|
|
170
172
|
var baseField = "w-full font-sans text-sm text-foreground bg-surface border rounded-kj-md px-[0.85rem] transition-[border-color,box-shadow] duration-150 placeholder:text-muted-foreground focus:outline-none focus:border-ring focus:ring-[3px] focus:ring-ring/30 disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed";
|
|
171
|
-
var Input =
|
|
173
|
+
var Input = React17.forwardRef(
|
|
172
174
|
({ className, error, leadingIcon, style, ...props }, ref) => {
|
|
173
175
|
const field = /* @__PURE__ */ jsx(
|
|
174
176
|
"input",
|
|
@@ -193,7 +195,7 @@ var Input = React16.forwardRef(
|
|
|
193
195
|
}
|
|
194
196
|
);
|
|
195
197
|
Input.displayName = "Input";
|
|
196
|
-
var Textarea =
|
|
198
|
+
var Textarea = React17.forwardRef(
|
|
197
199
|
({ className, error, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
198
200
|
"textarea",
|
|
199
201
|
{
|
|
@@ -210,14 +212,14 @@ var Textarea = React16.forwardRef(
|
|
|
210
212
|
)
|
|
211
213
|
);
|
|
212
214
|
Textarea.displayName = "Textarea";
|
|
213
|
-
var Label =
|
|
215
|
+
var Label = React17.forwardRef(
|
|
214
216
|
({ className, required, children, ...props }, ref) => /* @__PURE__ */ jsxs("label", { ref, className: cn("text-[0.8rem] font-semibold text-foreground", className), ...props, children: [
|
|
215
217
|
children,
|
|
216
218
|
required && /* @__PURE__ */ jsx("span", { className: "text-danger", children: " *" })
|
|
217
219
|
] })
|
|
218
220
|
);
|
|
219
221
|
Label.displayName = "Label";
|
|
220
|
-
var Hint =
|
|
222
|
+
var Hint = React17.forwardRef(
|
|
221
223
|
({ className, error, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
222
224
|
"span",
|
|
223
225
|
{
|
|
@@ -228,12 +230,12 @@ var Hint = React16.forwardRef(
|
|
|
228
230
|
)
|
|
229
231
|
);
|
|
230
232
|
Hint.displayName = "Hint";
|
|
231
|
-
var Field =
|
|
233
|
+
var Field = React17.forwardRef(
|
|
232
234
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col gap-1.5", className), ...props })
|
|
233
235
|
);
|
|
234
236
|
Field.displayName = "Field";
|
|
235
237
|
var chevron = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E";
|
|
236
|
-
var Select =
|
|
238
|
+
var Select = React17.forwardRef(
|
|
237
239
|
({ className, error, style, children, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
238
240
|
"select",
|
|
239
241
|
{
|
|
@@ -261,9 +263,9 @@ var Select = React16.forwardRef(
|
|
|
261
263
|
)
|
|
262
264
|
);
|
|
263
265
|
Select.displayName = "Select";
|
|
264
|
-
var Checkbox =
|
|
266
|
+
var Checkbox = React17.forwardRef(
|
|
265
267
|
({ className, label, id, ...props }, ref) => {
|
|
266
|
-
const autoId =
|
|
268
|
+
const autoId = React17.useId();
|
|
267
269
|
const inputId = id ?? autoId;
|
|
268
270
|
return /* @__PURE__ */ jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
|
|
269
271
|
/* @__PURE__ */ jsx("input", { ref, id: inputId, type: "checkbox", className: "peer sr-only", ...props }),
|
|
@@ -273,9 +275,9 @@ var Checkbox = React16.forwardRef(
|
|
|
273
275
|
}
|
|
274
276
|
);
|
|
275
277
|
Checkbox.displayName = "Checkbox";
|
|
276
|
-
var Radio =
|
|
278
|
+
var Radio = React17.forwardRef(
|
|
277
279
|
({ className, label, id, ...props }, ref) => {
|
|
278
|
-
const autoId =
|
|
280
|
+
const autoId = React17.useId();
|
|
279
281
|
const inputId = id ?? autoId;
|
|
280
282
|
return /* @__PURE__ */ jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
|
|
281
283
|
/* @__PURE__ */ jsx("input", { ref, id: inputId, type: "radio", className: "peer sr-only", ...props }),
|
|
@@ -285,9 +287,9 @@ var Radio = React16.forwardRef(
|
|
|
285
287
|
}
|
|
286
288
|
);
|
|
287
289
|
Radio.displayName = "Radio";
|
|
288
|
-
var Switch =
|
|
290
|
+
var Switch = React17.forwardRef(
|
|
289
291
|
({ className, label, id, ...props }, ref) => {
|
|
290
|
-
const autoId =
|
|
292
|
+
const autoId = React17.useId();
|
|
291
293
|
const inputId = id ?? autoId;
|
|
292
294
|
return /* @__PURE__ */ jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
|
|
293
295
|
/* @__PURE__ */ jsx("input", { ref, id: inputId, type: "checkbox", role: "switch", className: "peer sr-only", ...props }),
|
|
@@ -297,7 +299,7 @@ var Switch = React16.forwardRef(
|
|
|
297
299
|
}
|
|
298
300
|
);
|
|
299
301
|
Switch.displayName = "Switch";
|
|
300
|
-
var Slider =
|
|
302
|
+
var Slider = React17.forwardRef(
|
|
301
303
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
302
304
|
"input",
|
|
303
305
|
{
|
|
@@ -350,7 +352,7 @@ function Segmented({
|
|
|
350
352
|
}
|
|
351
353
|
);
|
|
352
354
|
}
|
|
353
|
-
var Card =
|
|
355
|
+
var Card = React17.forwardRef(
|
|
354
356
|
({ as: Tag = "div", className, elevated, interactive, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
355
357
|
Tag,
|
|
356
358
|
{
|
|
@@ -366,23 +368,23 @@ var Card = React16.forwardRef(
|
|
|
366
368
|
)
|
|
367
369
|
);
|
|
368
370
|
Card.displayName = "Card";
|
|
369
|
-
var CardHeader =
|
|
371
|
+
var CardHeader = React17.forwardRef(
|
|
370
372
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-[1.35rem] flex flex-col gap-1", className), ...props })
|
|
371
373
|
);
|
|
372
374
|
CardHeader.displayName = "CardHeader";
|
|
373
|
-
var CardTitle =
|
|
375
|
+
var CardTitle = React17.forwardRef(
|
|
374
376
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("h3", { ref, className: cn("m-0 text-base font-bold tracking-[-0.01em]", className), ...props })
|
|
375
377
|
);
|
|
376
378
|
CardTitle.displayName = "CardTitle";
|
|
377
|
-
var CardDescription =
|
|
379
|
+
var CardDescription = React17.forwardRef(
|
|
378
380
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("p", { ref, className: cn("m-0 text-[0.85rem] text-muted-foreground", className), ...props })
|
|
379
381
|
);
|
|
380
382
|
CardDescription.displayName = "CardDescription";
|
|
381
|
-
var CardContent =
|
|
383
|
+
var CardContent = React17.forwardRef(
|
|
382
384
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("px-[1.35rem] pb-[1.35rem]", className), ...props })
|
|
383
385
|
);
|
|
384
386
|
CardContent.displayName = "CardContent";
|
|
385
|
-
var CardFooter =
|
|
387
|
+
var CardFooter = React17.forwardRef(
|
|
386
388
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
387
389
|
"div",
|
|
388
390
|
{
|
|
@@ -393,7 +395,7 @@ var CardFooter = React16.forwardRef(
|
|
|
393
395
|
)
|
|
394
396
|
);
|
|
395
397
|
CardFooter.displayName = "CardFooter";
|
|
396
|
-
var Stat =
|
|
398
|
+
var Stat = React17.forwardRef(
|
|
397
399
|
({ className, label, value, delta, trend, ...props }, ref) => /* @__PURE__ */ jsxs(Card, { ref, className: cn("p-[1.35rem] flex flex-col gap-2", className), ...props, children: [
|
|
398
400
|
/* @__PURE__ */ jsx("span", { className: "text-[0.78rem] font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: label }),
|
|
399
401
|
/* @__PURE__ */ jsx("span", { className: "text-[2rem] font-bold tracking-[-0.03em] tabular-nums leading-none", children: value }),
|
|
@@ -433,7 +435,7 @@ var avatarVariants = cva(
|
|
|
433
435
|
defaultVariants: { size: "md", tone: "secondary" }
|
|
434
436
|
}
|
|
435
437
|
);
|
|
436
|
-
var Avatar =
|
|
438
|
+
var Avatar = React17.forwardRef(
|
|
437
439
|
({ className, size, tone, src, alt, status, children, ...props }, ref) => {
|
|
438
440
|
const node = /* @__PURE__ */ jsx("span", { ref, className: cn(avatarVariants({ size, tone }), "overflow-hidden", className), ...props, children: src ? /* @__PURE__ */ jsx("img", { src, alt, className: "h-full w-full object-cover" }) : children });
|
|
439
441
|
if (!status) return node;
|
|
@@ -444,20 +446,20 @@ var Avatar = React16.forwardRef(
|
|
|
444
446
|
}
|
|
445
447
|
);
|
|
446
448
|
Avatar.displayName = "Avatar";
|
|
447
|
-
var AvatarGroup =
|
|
449
|
+
var AvatarGroup = React17.forwardRef(
|
|
448
450
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex [&>*:not(:first-child)]:-ml-2.5", className), ...props })
|
|
449
451
|
);
|
|
450
452
|
AvatarGroup.displayName = "AvatarGroup";
|
|
451
|
-
var TabsContext =
|
|
453
|
+
var TabsContext = React17.createContext(null);
|
|
452
454
|
function useTabs() {
|
|
453
|
-
const ctx =
|
|
455
|
+
const ctx = React17.useContext(TabsContext);
|
|
454
456
|
if (!ctx) throw new Error("Tabs.* must be used within <Tabs>");
|
|
455
457
|
return ctx;
|
|
456
458
|
}
|
|
457
459
|
function Tabs({ value, defaultValue, onValueChange, className, children, ...props }) {
|
|
458
|
-
const [internal, setInternal] =
|
|
460
|
+
const [internal, setInternal] = React17.useState(defaultValue ?? "");
|
|
459
461
|
const current = value ?? internal;
|
|
460
|
-
const setValue =
|
|
462
|
+
const setValue = React17.useCallback(
|
|
461
463
|
(v) => {
|
|
462
464
|
if (value === void 0) setInternal(v);
|
|
463
465
|
onValueChange?.(v);
|
|
@@ -466,11 +468,51 @@ function Tabs({ value, defaultValue, onValueChange, className, children, ...prop
|
|
|
466
468
|
);
|
|
467
469
|
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { value: current, setValue }, children: /* @__PURE__ */ jsx("div", { className, ...props, children }) });
|
|
468
470
|
}
|
|
469
|
-
var TabsList =
|
|
470
|
-
({ className, ...props }, ref) =>
|
|
471
|
+
var TabsList = React17.forwardRef(
|
|
472
|
+
({ className, onKeyDown, ...props }, ref) => {
|
|
473
|
+
const handleKeyDown = (e) => {
|
|
474
|
+
const container = e.currentTarget;
|
|
475
|
+
const tabs = Array.from(container.querySelectorAll('[role="tab"]'));
|
|
476
|
+
if (tabs.length === 0) return;
|
|
477
|
+
const activeIndex = tabs.findIndex((tab) => tab.getAttribute("aria-selected") === "true");
|
|
478
|
+
let newIndex = activeIndex;
|
|
479
|
+
if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
480
|
+
e.preventDefault();
|
|
481
|
+
newIndex = (activeIndex + 1) % tabs.length;
|
|
482
|
+
tabs[newIndex].focus();
|
|
483
|
+
tabs[newIndex].click();
|
|
484
|
+
} else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
|
|
485
|
+
e.preventDefault();
|
|
486
|
+
newIndex = (activeIndex - 1 + tabs.length) % tabs.length;
|
|
487
|
+
tabs[newIndex].focus();
|
|
488
|
+
tabs[newIndex].click();
|
|
489
|
+
} else if (e.key === "Home") {
|
|
490
|
+
e.preventDefault();
|
|
491
|
+
newIndex = 0;
|
|
492
|
+
tabs[newIndex].focus();
|
|
493
|
+
tabs[newIndex].click();
|
|
494
|
+
} else if (e.key === "End") {
|
|
495
|
+
e.preventDefault();
|
|
496
|
+
newIndex = tabs.length - 1;
|
|
497
|
+
tabs[newIndex].focus();
|
|
498
|
+
tabs[newIndex].click();
|
|
499
|
+
}
|
|
500
|
+
onKeyDown?.(e);
|
|
501
|
+
};
|
|
502
|
+
return /* @__PURE__ */ jsx(
|
|
503
|
+
"div",
|
|
504
|
+
{
|
|
505
|
+
ref,
|
|
506
|
+
role: "tablist",
|
|
507
|
+
onKeyDown: handleKeyDown,
|
|
508
|
+
className: cn("flex gap-1 border-b border-border", className),
|
|
509
|
+
...props
|
|
510
|
+
}
|
|
511
|
+
);
|
|
512
|
+
}
|
|
471
513
|
);
|
|
472
514
|
TabsList.displayName = "TabsList";
|
|
473
|
-
var TabsTrigger =
|
|
515
|
+
var TabsTrigger = React17.forwardRef(
|
|
474
516
|
({ className, value, children, ...props }, ref) => {
|
|
475
517
|
const { value: current, setValue } = useTabs();
|
|
476
518
|
const active = current === value;
|
|
@@ -480,10 +522,14 @@ var TabsTrigger = React16.forwardRef(
|
|
|
480
522
|
ref,
|
|
481
523
|
type: "button",
|
|
482
524
|
role: "tab",
|
|
525
|
+
id: `tabs-trigger-${value}`,
|
|
526
|
+
"aria-controls": `tabs-panel-${value}`,
|
|
483
527
|
"aria-selected": active,
|
|
528
|
+
tabIndex: active ? 0 : -1,
|
|
484
529
|
onClick: () => setValue(value),
|
|
485
530
|
className: cn(
|
|
486
|
-
"relative px-[0.9rem] py-2.5 text-sm font-semibold cursor-pointer transition-colors duration-150",
|
|
531
|
+
"relative px-[0.9rem] py-2.5 text-sm font-semibold cursor-pointer transition-colors duration-150 outline-none",
|
|
532
|
+
"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:rounded-sm",
|
|
487
533
|
"after:content-[''] after:absolute after:left-[0.9rem] after:right-[0.9rem] after:-bottom-px after:h-0.5 after:rounded-sm after:transition-colors",
|
|
488
534
|
active ? "text-foreground after:bg-primary" : "text-muted-foreground hover:text-foreground after:bg-transparent",
|
|
489
535
|
className
|
|
@@ -495,18 +541,30 @@ var TabsTrigger = React16.forwardRef(
|
|
|
495
541
|
}
|
|
496
542
|
);
|
|
497
543
|
TabsTrigger.displayName = "TabsTrigger";
|
|
498
|
-
var TabsContent =
|
|
544
|
+
var TabsContent = React17.forwardRef(
|
|
499
545
|
({ className, value, ...props }, ref) => {
|
|
500
546
|
const { value: current } = useTabs();
|
|
501
|
-
|
|
502
|
-
|
|
547
|
+
const active = current === value;
|
|
548
|
+
if (!active) return null;
|
|
549
|
+
return /* @__PURE__ */ jsx(
|
|
550
|
+
"div",
|
|
551
|
+
{
|
|
552
|
+
ref,
|
|
553
|
+
role: "tabpanel",
|
|
554
|
+
id: `tabs-panel-${value}`,
|
|
555
|
+
"aria-labelledby": `tabs-trigger-${value}`,
|
|
556
|
+
tabIndex: 0,
|
|
557
|
+
className: cn("pt-5 text-[0.9rem] text-muted-foreground outline-none", className),
|
|
558
|
+
...props
|
|
559
|
+
}
|
|
560
|
+
);
|
|
503
561
|
}
|
|
504
562
|
);
|
|
505
563
|
TabsContent.displayName = "TabsContent";
|
|
506
|
-
var AccordionContext =
|
|
564
|
+
var AccordionContext = React17.createContext(null);
|
|
507
565
|
function Accordion({ type = "single", defaultValue = [], className, children, ...props }) {
|
|
508
|
-
const [open, setOpen] =
|
|
509
|
-
const toggle =
|
|
566
|
+
const [open, setOpen] = React17.useState(defaultValue);
|
|
567
|
+
const toggle = React17.useCallback(
|
|
510
568
|
(v) => {
|
|
511
569
|
setOpen((prev) => {
|
|
512
570
|
const isOpen = prev.includes(v);
|
|
@@ -518,15 +576,15 @@ function Accordion({ type = "single", defaultValue = [], className, children, ..
|
|
|
518
576
|
);
|
|
519
577
|
return /* @__PURE__ */ jsx(AccordionContext.Provider, { value: { open, toggle }, children: /* @__PURE__ */ jsx("div", { className: cn("border border-border rounded-kj-lg overflow-hidden", className), ...props, children }) });
|
|
520
578
|
}
|
|
521
|
-
var ItemContext =
|
|
522
|
-
var AccordionItem =
|
|
579
|
+
var ItemContext = React17.createContext("");
|
|
580
|
+
var AccordionItem = React17.forwardRef(
|
|
523
581
|
({ className, value, ...props }, ref) => /* @__PURE__ */ jsx(ItemContext.Provider, { value, children: /* @__PURE__ */ jsx("div", { ref, className: cn("border-t border-border first:border-t-0", className), ...props }) })
|
|
524
582
|
);
|
|
525
583
|
AccordionItem.displayName = "AccordionItem";
|
|
526
|
-
var AccordionTrigger =
|
|
584
|
+
var AccordionTrigger = React17.forwardRef(
|
|
527
585
|
({ className, children, ...props }, ref) => {
|
|
528
|
-
const ctx =
|
|
529
|
-
const value =
|
|
586
|
+
const ctx = React17.useContext(AccordionContext);
|
|
587
|
+
const value = React17.useContext(ItemContext);
|
|
530
588
|
const isOpen = ctx.open.includes(value);
|
|
531
589
|
return /* @__PURE__ */ jsxs(
|
|
532
590
|
"button",
|
|
@@ -563,10 +621,10 @@ var AccordionTrigger = React16.forwardRef(
|
|
|
563
621
|
}
|
|
564
622
|
);
|
|
565
623
|
AccordionTrigger.displayName = "AccordionTrigger";
|
|
566
|
-
var AccordionContent =
|
|
624
|
+
var AccordionContent = React17.forwardRef(
|
|
567
625
|
({ className, children, ...props }, ref) => {
|
|
568
|
-
const ctx =
|
|
569
|
-
const value =
|
|
626
|
+
const ctx = React17.useContext(AccordionContext);
|
|
627
|
+
const value = React17.useContext(ItemContext);
|
|
570
628
|
const isOpen = ctx.open.includes(value);
|
|
571
629
|
return /* @__PURE__ */ jsx(
|
|
572
630
|
"div",
|
|
@@ -580,11 +638,11 @@ var AccordionContent = React16.forwardRef(
|
|
|
580
638
|
}
|
|
581
639
|
);
|
|
582
640
|
AccordionContent.displayName = "AccordionContent";
|
|
583
|
-
var MenuContext =
|
|
641
|
+
var MenuContext = React17.createContext(null);
|
|
584
642
|
function DropdownMenu({ children, className }) {
|
|
585
|
-
const [open, setOpen] =
|
|
586
|
-
const ref =
|
|
587
|
-
|
|
643
|
+
const [open, setOpen] = React17.useState(false);
|
|
644
|
+
const ref = React17.useRef(null);
|
|
645
|
+
React17.useEffect(() => {
|
|
588
646
|
if (!open) return;
|
|
589
647
|
const onDoc = (e) => {
|
|
590
648
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -599,8 +657,23 @@ function DropdownMenu({ children, className }) {
|
|
|
599
657
|
}, [open]);
|
|
600
658
|
return /* @__PURE__ */ jsx(MenuContext.Provider, { value: { open, setOpen }, children: /* @__PURE__ */ jsx("div", { ref, className: cn("relative inline-block", className), children }) });
|
|
601
659
|
}
|
|
602
|
-
var DropdownMenuTrigger =
|
|
603
|
-
const ctx =
|
|
660
|
+
var DropdownMenuTrigger = React17.forwardRef(({ onClick, asChild, ...props }, ref) => {
|
|
661
|
+
const ctx = React17.useContext(MenuContext);
|
|
662
|
+
if (asChild) {
|
|
663
|
+
const child = React17.Children.only(props.children);
|
|
664
|
+
return React17.cloneElement(child, {
|
|
665
|
+
ref,
|
|
666
|
+
...props,
|
|
667
|
+
...child.props,
|
|
668
|
+
onClick: (e) => {
|
|
669
|
+
ctx.setOpen(!ctx.open);
|
|
670
|
+
onClick?.(e);
|
|
671
|
+
child.props.onClick?.(e);
|
|
672
|
+
},
|
|
673
|
+
"aria-haspopup": "menu",
|
|
674
|
+
"aria-expanded": ctx.open
|
|
675
|
+
});
|
|
676
|
+
}
|
|
604
677
|
return /* @__PURE__ */ jsx(
|
|
605
678
|
"button",
|
|
606
679
|
{
|
|
@@ -618,14 +691,46 @@ var DropdownMenuTrigger = React16.forwardRef(({ onClick, ...props }, ref) => {
|
|
|
618
691
|
});
|
|
619
692
|
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
|
|
620
693
|
function DropdownMenuContent({ className, align = "start", children, ...props }) {
|
|
621
|
-
const ctx =
|
|
694
|
+
const ctx = React17.useContext(MenuContext);
|
|
695
|
+
const ref = React17.useRef(null);
|
|
696
|
+
React17.useEffect(() => {
|
|
697
|
+
if (!ctx.open) return;
|
|
698
|
+
const container = ref.current;
|
|
699
|
+
if (container) {
|
|
700
|
+
const items = Array.from(container.querySelectorAll('[role="menuitem"]'));
|
|
701
|
+
if (items.length > 0) {
|
|
702
|
+
setTimeout(() => items[0].focus(), 50);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}, [ctx.open]);
|
|
706
|
+
const handleKeyDown = (e) => {
|
|
707
|
+
const container = ref.current;
|
|
708
|
+
if (!container) return;
|
|
709
|
+
const items = Array.from(container.querySelectorAll('[role="menuitem"]'));
|
|
710
|
+
if (items.length === 0) return;
|
|
711
|
+
const currentIndex = items.indexOf(document.activeElement);
|
|
712
|
+
if (e.key === "ArrowDown") {
|
|
713
|
+
e.preventDefault();
|
|
714
|
+
const nextIndex = (currentIndex + 1) % items.length;
|
|
715
|
+
items[nextIndex].focus();
|
|
716
|
+
} else if (e.key === "ArrowUp") {
|
|
717
|
+
e.preventDefault();
|
|
718
|
+
const prevIndex = (currentIndex - 1 + items.length) % items.length;
|
|
719
|
+
items[prevIndex].focus();
|
|
720
|
+
} else if (e.key === "Tab" || e.key === "Escape") {
|
|
721
|
+
ctx.setOpen(false);
|
|
722
|
+
}
|
|
723
|
+
};
|
|
622
724
|
if (!ctx.open) return null;
|
|
623
725
|
return /* @__PURE__ */ jsx(
|
|
624
726
|
"div",
|
|
625
727
|
{
|
|
728
|
+
ref,
|
|
626
729
|
role: "menu",
|
|
730
|
+
tabIndex: -1,
|
|
731
|
+
onKeyDown: handleKeyDown,
|
|
627
732
|
className: cn(
|
|
628
|
-
"absolute top-[calc(100%+6px)] z-40 min-w-[200px] p-1.5 rounded-kj-md bg-surface border border-border shadow-kj-lg",
|
|
733
|
+
"absolute top-[calc(100%+6px)] z-40 min-w-[200px] p-1.5 rounded-kj-md bg-surface border border-border shadow-kj-lg outline-none",
|
|
629
734
|
"animate-[kjpop_.12s_ease]",
|
|
630
735
|
align === "end" ? "right-0" : "left-0",
|
|
631
736
|
className
|
|
@@ -635,9 +740,9 @@ function DropdownMenuContent({ className, align = "start", children, ...props })
|
|
|
635
740
|
}
|
|
636
741
|
);
|
|
637
742
|
}
|
|
638
|
-
var DropdownMenuItem =
|
|
743
|
+
var DropdownMenuItem = React17.forwardRef(
|
|
639
744
|
({ className, danger, icon, children, onClick, ...props }, ref) => {
|
|
640
|
-
const ctx =
|
|
745
|
+
const ctx = React17.useContext(MenuContext);
|
|
641
746
|
return /* @__PURE__ */ jsxs(
|
|
642
747
|
"button",
|
|
643
748
|
{
|
|
@@ -667,11 +772,11 @@ DropdownMenuItem.displayName = "DropdownMenuItem";
|
|
|
667
772
|
function DropdownMenuSeparator({ className }) {
|
|
668
773
|
return /* @__PURE__ */ jsx("div", { className: cn("h-px bg-border my-1.5", className), role: "separator" });
|
|
669
774
|
}
|
|
670
|
-
var Breadcrumb =
|
|
775
|
+
var Breadcrumb = React17.forwardRef(
|
|
671
776
|
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx("nav", { ref, "aria-label": "Breadcrumb", className: cn("flex items-center gap-1.5 text-[0.85rem] text-muted-foreground", className), ...props, children })
|
|
672
777
|
);
|
|
673
778
|
Breadcrumb.displayName = "Breadcrumb";
|
|
674
|
-
var BreadcrumbItem =
|
|
779
|
+
var BreadcrumbItem = React17.forwardRef(
|
|
675
780
|
({ className, current, children, ...props }, ref) => {
|
|
676
781
|
if (current) {
|
|
677
782
|
return /* @__PURE__ */ jsx("span", { "aria-current": "page", className: cn("text-foreground font-semibold", className), children });
|
|
@@ -718,27 +823,27 @@ function Pagination({ page, pageCount, onPageChange, className }) {
|
|
|
718
823
|
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Next", disabled: page >= pageCount, onClick: () => onPageChange(page + 1), children: /* @__PURE__ */ jsx(Chevron, { dir: "right" }) })
|
|
719
824
|
] });
|
|
720
825
|
}
|
|
721
|
-
var TableWrap =
|
|
826
|
+
var TableWrap = React17.forwardRef(
|
|
722
827
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("border border-border rounded-kj-lg overflow-hidden", className), ...props })
|
|
723
828
|
);
|
|
724
829
|
TableWrap.displayName = "TableWrap";
|
|
725
|
-
var Table =
|
|
830
|
+
var Table = React17.forwardRef(
|
|
726
831
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("table", { ref, className: cn("w-full border-collapse text-[0.85rem]", className), ...props })
|
|
727
832
|
);
|
|
728
833
|
Table.displayName = "Table";
|
|
729
|
-
var TableHeader =
|
|
834
|
+
var TableHeader = React17.forwardRef(
|
|
730
835
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className, ...props })
|
|
731
836
|
);
|
|
732
837
|
TableHeader.displayName = "TableHeader";
|
|
733
|
-
var TableBody =
|
|
838
|
+
var TableBody = React17.forwardRef(
|
|
734
839
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("tbody", { ref, className, ...props })
|
|
735
840
|
);
|
|
736
841
|
TableBody.displayName = "TableBody";
|
|
737
|
-
var TableRow =
|
|
842
|
+
var TableRow = React17.forwardRef(
|
|
738
843
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("tr", { ref, className: cn("transition-colors hover:bg-muted/50", className), ...props })
|
|
739
844
|
);
|
|
740
845
|
TableRow.displayName = "TableRow";
|
|
741
|
-
var TableHead =
|
|
846
|
+
var TableHead = React17.forwardRef(
|
|
742
847
|
({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
743
848
|
"th",
|
|
744
849
|
{
|
|
@@ -753,7 +858,7 @@ var TableHead = React16.forwardRef(
|
|
|
753
858
|
)
|
|
754
859
|
);
|
|
755
860
|
TableHead.displayName = "TableHead";
|
|
756
|
-
var TableCell =
|
|
861
|
+
var TableCell = React17.forwardRef(
|
|
757
862
|
({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
758
863
|
"td",
|
|
759
864
|
{
|
|
@@ -786,14 +891,68 @@ function Tooltip({ content, children, className }) {
|
|
|
786
891
|
)
|
|
787
892
|
] });
|
|
788
893
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
894
|
+
var ModalContext = React17.createContext(null);
|
|
895
|
+
function Modal({ open, onClose, children, width = 440, className, showClose = true }) {
|
|
896
|
+
const titleId = React17.useId();
|
|
897
|
+
const descId = React17.useId();
|
|
898
|
+
const containerRef = React17.useRef(null);
|
|
899
|
+
const lastActiveElement = React17.useRef(null);
|
|
900
|
+
React17.useEffect(() => {
|
|
901
|
+
if (!open) {
|
|
902
|
+
if (lastActiveElement.current) {
|
|
903
|
+
lastActiveElement.current.focus();
|
|
904
|
+
lastActiveElement.current = null;
|
|
905
|
+
}
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
lastActiveElement.current = document.activeElement;
|
|
909
|
+
const container = containerRef.current;
|
|
910
|
+
if (container) {
|
|
911
|
+
const focusables = container.querySelectorAll(
|
|
912
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
913
|
+
);
|
|
914
|
+
if (focusables.length > 0) {
|
|
915
|
+
setTimeout(() => focusables[0].focus(), 50);
|
|
916
|
+
} else {
|
|
917
|
+
container.focus();
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
const handleKeyDown = (e) => {
|
|
921
|
+
if (e.key === "Escape") {
|
|
922
|
+
onClose();
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
if (e.key === "Tab") {
|
|
926
|
+
const container2 = containerRef.current;
|
|
927
|
+
if (!container2) return;
|
|
928
|
+
const focusables = Array.from(
|
|
929
|
+
container2.querySelectorAll(
|
|
930
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
931
|
+
)
|
|
932
|
+
);
|
|
933
|
+
if (focusables.length === 0) {
|
|
934
|
+
e.preventDefault();
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
const first = focusables[0];
|
|
938
|
+
const last = focusables[focusables.length - 1];
|
|
939
|
+
if (e.shiftKey) {
|
|
940
|
+
if (document.activeElement === first || document.activeElement === container2) {
|
|
941
|
+
last.focus();
|
|
942
|
+
e.preventDefault();
|
|
943
|
+
}
|
|
944
|
+
} else {
|
|
945
|
+
if (document.activeElement === last) {
|
|
946
|
+
first.focus();
|
|
947
|
+
e.preventDefault();
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
794
953
|
document.body.style.overflow = "hidden";
|
|
795
954
|
return () => {
|
|
796
|
-
document.removeEventListener("keydown",
|
|
955
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
797
956
|
document.body.style.overflow = "";
|
|
798
957
|
};
|
|
799
958
|
}, [open, onClose]);
|
|
@@ -806,35 +965,53 @@ function Modal({ open, onClose, children, width = 440, className }) {
|
|
|
806
965
|
"bg-[color-mix(in_oklch,#09090b_55%,transparent)]",
|
|
807
966
|
open ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
|
|
808
967
|
),
|
|
809
|
-
children: /* @__PURE__ */ jsx(
|
|
968
|
+
children: /* @__PURE__ */ jsx(ModalContext.Provider, { value: { titleId, descId }, children: /* @__PURE__ */ jsxs(
|
|
810
969
|
"div",
|
|
811
970
|
{
|
|
971
|
+
ref: containerRef,
|
|
812
972
|
role: "dialog",
|
|
813
973
|
"aria-modal": "true",
|
|
974
|
+
"aria-labelledby": titleId,
|
|
975
|
+
"aria-describedby": descId,
|
|
976
|
+
tabIndex: -1,
|
|
814
977
|
style: { maxWidth: width },
|
|
815
978
|
className: cn(
|
|
816
|
-
"w-full p-7 rounded-kj-2xl bg-surface border border-border shadow-kj-lg transition-transform duration-200",
|
|
979
|
+
"relative w-full p-7 rounded-kj-2xl bg-surface border border-border shadow-kj-lg transition-transform duration-200 outline-none",
|
|
817
980
|
open ? "scale-100 translate-y-0" : "scale-95 translate-y-2",
|
|
818
981
|
className
|
|
819
982
|
),
|
|
820
|
-
children
|
|
983
|
+
children: [
|
|
984
|
+
showClose && /* @__PURE__ */ jsx(
|
|
985
|
+
"button",
|
|
986
|
+
{
|
|
987
|
+
type: "button",
|
|
988
|
+
onClick: onClose,
|
|
989
|
+
"aria-label": "Close",
|
|
990
|
+
className: "absolute top-4 right-4 p-1.5 rounded-kj-sm text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer",
|
|
991
|
+
children: /* @__PURE__ */ jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
992
|
+
}
|
|
993
|
+
),
|
|
994
|
+
children
|
|
995
|
+
]
|
|
821
996
|
}
|
|
822
|
-
)
|
|
997
|
+
) })
|
|
823
998
|
}
|
|
824
999
|
);
|
|
825
1000
|
}
|
|
826
|
-
function ModalTitle({ className, ...props }) {
|
|
827
|
-
|
|
1001
|
+
function ModalTitle({ className, id, ...props }) {
|
|
1002
|
+
const ctx = React17.useContext(ModalContext);
|
|
1003
|
+
return /* @__PURE__ */ jsx("h3", { id: id ?? ctx?.titleId, className: cn("m-0 mb-2 text-[1.15rem] font-bold tracking-[-0.01em]", className), ...props });
|
|
828
1004
|
}
|
|
829
|
-
function ModalDescription({ className, ...props }) {
|
|
830
|
-
|
|
1005
|
+
function ModalDescription({ className, id, ...props }) {
|
|
1006
|
+
const ctx = React17.useContext(ModalContext);
|
|
1007
|
+
return /* @__PURE__ */ jsx("p", { id: id ?? ctx?.descId, className: cn("m-0 text-[0.9rem] text-muted-foreground", className), ...props });
|
|
831
1008
|
}
|
|
832
1009
|
function ModalActions({ className, ...props }) {
|
|
833
1010
|
return /* @__PURE__ */ jsx("div", { className: cn("flex gap-2.5 justify-end mt-6", className), ...props });
|
|
834
1011
|
}
|
|
835
|
-
var ToastContext =
|
|
1012
|
+
var ToastContext = React17.createContext(null);
|
|
836
1013
|
function useToast() {
|
|
837
|
-
const ctx =
|
|
1014
|
+
const ctx = React17.useContext(ToastContext);
|
|
838
1015
|
if (!ctx) throw new Error("useToast must be used within <ToastProvider>");
|
|
839
1016
|
return ctx;
|
|
840
1017
|
}
|
|
@@ -855,13 +1032,13 @@ var toneBorder = {
|
|
|
855
1032
|
danger: "border-l-danger"
|
|
856
1033
|
};
|
|
857
1034
|
function ToastProvider({ children }) {
|
|
858
|
-
const [items, setItems] =
|
|
859
|
-
const idRef =
|
|
860
|
-
const remove =
|
|
1035
|
+
const [items, setItems] = React17.useState([]);
|
|
1036
|
+
const idRef = React17.useRef(0);
|
|
1037
|
+
const remove = React17.useCallback((id) => {
|
|
861
1038
|
setItems((prev) => prev.map((t) => t.id === id ? { ...t, leaving: true } : t));
|
|
862
1039
|
setTimeout(() => setItems((prev) => prev.filter((t) => t.id !== id)), 250);
|
|
863
1040
|
}, []);
|
|
864
|
-
const toast =
|
|
1041
|
+
const toast = React17.useCallback(
|
|
865
1042
|
({ message, tone = "default", duration = 3200 }) => {
|
|
866
1043
|
const id = ++idRef.current;
|
|
867
1044
|
setItems((prev) => [...prev, { id, message, tone, duration }]);
|
|
@@ -891,7 +1068,7 @@ function ToastProvider({ children }) {
|
|
|
891
1068
|
)) })
|
|
892
1069
|
] });
|
|
893
1070
|
}
|
|
894
|
-
var PageHeader =
|
|
1071
|
+
var PageHeader = React17.forwardRef(
|
|
895
1072
|
({ eyebrow, title, description, actions }, ref) => /* @__PURE__ */ jsx("header", { ref, className: "py-12 md:py-16", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6 md:flex-row md:items-end md:justify-between", children: [
|
|
896
1073
|
/* @__PURE__ */ jsxs("div", { className: "space-y-3 max-w-2xl", children: [
|
|
897
1074
|
eyebrow && /* @__PURE__ */ jsx("p", { className: "font-mono text-xs font-bold uppercase tracking-[0.2em] text-primary", children: eyebrow }),
|