@kjaniec-dev/ui 0.3.1 → 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 +281 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -5
- package/dist/index.d.ts +16 -5
- package/dist/index.js +280 -91
- 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,14 +352,15 @@ function Segmented({
|
|
|
350
352
|
}
|
|
351
353
|
);
|
|
352
354
|
}
|
|
353
|
-
var Card =
|
|
354
|
-
({ as: Tag = "div", className, elevated, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
355
|
+
var Card = React17.forwardRef(
|
|
356
|
+
({ as: Tag = "div", className, elevated, interactive, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
355
357
|
Tag,
|
|
356
358
|
{
|
|
357
359
|
ref,
|
|
358
360
|
className: cn(
|
|
359
361
|
"bg-card text-card-foreground rounded-kj-xl overflow-hidden border",
|
|
360
362
|
elevated ? "border-transparent shadow-kj-lg" : "border-border shadow-kj-sm",
|
|
363
|
+
interactive && "cursor-pointer transition-all duration-300 hover:-translate-y-1 hover:shadow-kj-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
361
364
|
className
|
|
362
365
|
),
|
|
363
366
|
...props
|
|
@@ -365,23 +368,23 @@ var Card = React16.forwardRef(
|
|
|
365
368
|
)
|
|
366
369
|
);
|
|
367
370
|
Card.displayName = "Card";
|
|
368
|
-
var CardHeader =
|
|
371
|
+
var CardHeader = React17.forwardRef(
|
|
369
372
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-[1.35rem] flex flex-col gap-1", className), ...props })
|
|
370
373
|
);
|
|
371
374
|
CardHeader.displayName = "CardHeader";
|
|
372
|
-
var CardTitle =
|
|
375
|
+
var CardTitle = React17.forwardRef(
|
|
373
376
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("h3", { ref, className: cn("m-0 text-base font-bold tracking-[-0.01em]", className), ...props })
|
|
374
377
|
);
|
|
375
378
|
CardTitle.displayName = "CardTitle";
|
|
376
|
-
var CardDescription =
|
|
379
|
+
var CardDescription = React17.forwardRef(
|
|
377
380
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("p", { ref, className: cn("m-0 text-[0.85rem] text-muted-foreground", className), ...props })
|
|
378
381
|
);
|
|
379
382
|
CardDescription.displayName = "CardDescription";
|
|
380
|
-
var CardContent =
|
|
383
|
+
var CardContent = React17.forwardRef(
|
|
381
384
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("px-[1.35rem] pb-[1.35rem]", className), ...props })
|
|
382
385
|
);
|
|
383
386
|
CardContent.displayName = "CardContent";
|
|
384
|
-
var CardFooter =
|
|
387
|
+
var CardFooter = React17.forwardRef(
|
|
385
388
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
386
389
|
"div",
|
|
387
390
|
{
|
|
@@ -392,7 +395,7 @@ var CardFooter = React16.forwardRef(
|
|
|
392
395
|
)
|
|
393
396
|
);
|
|
394
397
|
CardFooter.displayName = "CardFooter";
|
|
395
|
-
var Stat =
|
|
398
|
+
var Stat = React17.forwardRef(
|
|
396
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: [
|
|
397
400
|
/* @__PURE__ */ jsx("span", { className: "text-[0.78rem] font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: label }),
|
|
398
401
|
/* @__PURE__ */ jsx("span", { className: "text-[2rem] font-bold tracking-[-0.03em] tabular-nums leading-none", children: value }),
|
|
@@ -432,7 +435,7 @@ var avatarVariants = cva(
|
|
|
432
435
|
defaultVariants: { size: "md", tone: "secondary" }
|
|
433
436
|
}
|
|
434
437
|
);
|
|
435
|
-
var Avatar =
|
|
438
|
+
var Avatar = React17.forwardRef(
|
|
436
439
|
({ className, size, tone, src, alt, status, children, ...props }, ref) => {
|
|
437
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 });
|
|
438
441
|
if (!status) return node;
|
|
@@ -443,20 +446,20 @@ var Avatar = React16.forwardRef(
|
|
|
443
446
|
}
|
|
444
447
|
);
|
|
445
448
|
Avatar.displayName = "Avatar";
|
|
446
|
-
var AvatarGroup =
|
|
449
|
+
var AvatarGroup = React17.forwardRef(
|
|
447
450
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex [&>*:not(:first-child)]:-ml-2.5", className), ...props })
|
|
448
451
|
);
|
|
449
452
|
AvatarGroup.displayName = "AvatarGroup";
|
|
450
|
-
var TabsContext =
|
|
453
|
+
var TabsContext = React17.createContext(null);
|
|
451
454
|
function useTabs() {
|
|
452
|
-
const ctx =
|
|
455
|
+
const ctx = React17.useContext(TabsContext);
|
|
453
456
|
if (!ctx) throw new Error("Tabs.* must be used within <Tabs>");
|
|
454
457
|
return ctx;
|
|
455
458
|
}
|
|
456
459
|
function Tabs({ value, defaultValue, onValueChange, className, children, ...props }) {
|
|
457
|
-
const [internal, setInternal] =
|
|
460
|
+
const [internal, setInternal] = React17.useState(defaultValue ?? "");
|
|
458
461
|
const current = value ?? internal;
|
|
459
|
-
const setValue =
|
|
462
|
+
const setValue = React17.useCallback(
|
|
460
463
|
(v) => {
|
|
461
464
|
if (value === void 0) setInternal(v);
|
|
462
465
|
onValueChange?.(v);
|
|
@@ -465,11 +468,51 @@ function Tabs({ value, defaultValue, onValueChange, className, children, ...prop
|
|
|
465
468
|
);
|
|
466
469
|
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { value: current, setValue }, children: /* @__PURE__ */ jsx("div", { className, ...props, children }) });
|
|
467
470
|
}
|
|
468
|
-
var TabsList =
|
|
469
|
-
({ 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
|
+
}
|
|
470
513
|
);
|
|
471
514
|
TabsList.displayName = "TabsList";
|
|
472
|
-
var TabsTrigger =
|
|
515
|
+
var TabsTrigger = React17.forwardRef(
|
|
473
516
|
({ className, value, children, ...props }, ref) => {
|
|
474
517
|
const { value: current, setValue } = useTabs();
|
|
475
518
|
const active = current === value;
|
|
@@ -479,10 +522,14 @@ var TabsTrigger = React16.forwardRef(
|
|
|
479
522
|
ref,
|
|
480
523
|
type: "button",
|
|
481
524
|
role: "tab",
|
|
525
|
+
id: `tabs-trigger-${value}`,
|
|
526
|
+
"aria-controls": `tabs-panel-${value}`,
|
|
482
527
|
"aria-selected": active,
|
|
528
|
+
tabIndex: active ? 0 : -1,
|
|
483
529
|
onClick: () => setValue(value),
|
|
484
530
|
className: cn(
|
|
485
|
-
"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",
|
|
486
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",
|
|
487
534
|
active ? "text-foreground after:bg-primary" : "text-muted-foreground hover:text-foreground after:bg-transparent",
|
|
488
535
|
className
|
|
@@ -494,18 +541,30 @@ var TabsTrigger = React16.forwardRef(
|
|
|
494
541
|
}
|
|
495
542
|
);
|
|
496
543
|
TabsTrigger.displayName = "TabsTrigger";
|
|
497
|
-
var TabsContent =
|
|
544
|
+
var TabsContent = React17.forwardRef(
|
|
498
545
|
({ className, value, ...props }, ref) => {
|
|
499
546
|
const { value: current } = useTabs();
|
|
500
|
-
|
|
501
|
-
|
|
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
|
+
);
|
|
502
561
|
}
|
|
503
562
|
);
|
|
504
563
|
TabsContent.displayName = "TabsContent";
|
|
505
|
-
var AccordionContext =
|
|
564
|
+
var AccordionContext = React17.createContext(null);
|
|
506
565
|
function Accordion({ type = "single", defaultValue = [], className, children, ...props }) {
|
|
507
|
-
const [open, setOpen] =
|
|
508
|
-
const toggle =
|
|
566
|
+
const [open, setOpen] = React17.useState(defaultValue);
|
|
567
|
+
const toggle = React17.useCallback(
|
|
509
568
|
(v) => {
|
|
510
569
|
setOpen((prev) => {
|
|
511
570
|
const isOpen = prev.includes(v);
|
|
@@ -517,15 +576,15 @@ function Accordion({ type = "single", defaultValue = [], className, children, ..
|
|
|
517
576
|
);
|
|
518
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 }) });
|
|
519
578
|
}
|
|
520
|
-
var ItemContext =
|
|
521
|
-
var AccordionItem =
|
|
579
|
+
var ItemContext = React17.createContext("");
|
|
580
|
+
var AccordionItem = React17.forwardRef(
|
|
522
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 }) })
|
|
523
582
|
);
|
|
524
583
|
AccordionItem.displayName = "AccordionItem";
|
|
525
|
-
var AccordionTrigger =
|
|
584
|
+
var AccordionTrigger = React17.forwardRef(
|
|
526
585
|
({ className, children, ...props }, ref) => {
|
|
527
|
-
const ctx =
|
|
528
|
-
const value =
|
|
586
|
+
const ctx = React17.useContext(AccordionContext);
|
|
587
|
+
const value = React17.useContext(ItemContext);
|
|
529
588
|
const isOpen = ctx.open.includes(value);
|
|
530
589
|
return /* @__PURE__ */ jsxs(
|
|
531
590
|
"button",
|
|
@@ -562,10 +621,10 @@ var AccordionTrigger = React16.forwardRef(
|
|
|
562
621
|
}
|
|
563
622
|
);
|
|
564
623
|
AccordionTrigger.displayName = "AccordionTrigger";
|
|
565
|
-
var AccordionContent =
|
|
624
|
+
var AccordionContent = React17.forwardRef(
|
|
566
625
|
({ className, children, ...props }, ref) => {
|
|
567
|
-
const ctx =
|
|
568
|
-
const value =
|
|
626
|
+
const ctx = React17.useContext(AccordionContext);
|
|
627
|
+
const value = React17.useContext(ItemContext);
|
|
569
628
|
const isOpen = ctx.open.includes(value);
|
|
570
629
|
return /* @__PURE__ */ jsx(
|
|
571
630
|
"div",
|
|
@@ -579,11 +638,11 @@ var AccordionContent = React16.forwardRef(
|
|
|
579
638
|
}
|
|
580
639
|
);
|
|
581
640
|
AccordionContent.displayName = "AccordionContent";
|
|
582
|
-
var MenuContext =
|
|
641
|
+
var MenuContext = React17.createContext(null);
|
|
583
642
|
function DropdownMenu({ children, className }) {
|
|
584
|
-
const [open, setOpen] =
|
|
585
|
-
const ref =
|
|
586
|
-
|
|
643
|
+
const [open, setOpen] = React17.useState(false);
|
|
644
|
+
const ref = React17.useRef(null);
|
|
645
|
+
React17.useEffect(() => {
|
|
587
646
|
if (!open) return;
|
|
588
647
|
const onDoc = (e) => {
|
|
589
648
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -598,8 +657,23 @@ function DropdownMenu({ children, className }) {
|
|
|
598
657
|
}, [open]);
|
|
599
658
|
return /* @__PURE__ */ jsx(MenuContext.Provider, { value: { open, setOpen }, children: /* @__PURE__ */ jsx("div", { ref, className: cn("relative inline-block", className), children }) });
|
|
600
659
|
}
|
|
601
|
-
var DropdownMenuTrigger =
|
|
602
|
-
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
|
+
}
|
|
603
677
|
return /* @__PURE__ */ jsx(
|
|
604
678
|
"button",
|
|
605
679
|
{
|
|
@@ -617,14 +691,46 @@ var DropdownMenuTrigger = React16.forwardRef(({ onClick, ...props }, ref) => {
|
|
|
617
691
|
});
|
|
618
692
|
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
|
|
619
693
|
function DropdownMenuContent({ className, align = "start", children, ...props }) {
|
|
620
|
-
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
|
+
};
|
|
621
724
|
if (!ctx.open) return null;
|
|
622
725
|
return /* @__PURE__ */ jsx(
|
|
623
726
|
"div",
|
|
624
727
|
{
|
|
728
|
+
ref,
|
|
625
729
|
role: "menu",
|
|
730
|
+
tabIndex: -1,
|
|
731
|
+
onKeyDown: handleKeyDown,
|
|
626
732
|
className: cn(
|
|
627
|
-
"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",
|
|
628
734
|
"animate-[kjpop_.12s_ease]",
|
|
629
735
|
align === "end" ? "right-0" : "left-0",
|
|
630
736
|
className
|
|
@@ -634,9 +740,9 @@ function DropdownMenuContent({ className, align = "start", children, ...props })
|
|
|
634
740
|
}
|
|
635
741
|
);
|
|
636
742
|
}
|
|
637
|
-
var DropdownMenuItem =
|
|
743
|
+
var DropdownMenuItem = React17.forwardRef(
|
|
638
744
|
({ className, danger, icon, children, onClick, ...props }, ref) => {
|
|
639
|
-
const ctx =
|
|
745
|
+
const ctx = React17.useContext(MenuContext);
|
|
640
746
|
return /* @__PURE__ */ jsxs(
|
|
641
747
|
"button",
|
|
642
748
|
{
|
|
@@ -666,11 +772,11 @@ DropdownMenuItem.displayName = "DropdownMenuItem";
|
|
|
666
772
|
function DropdownMenuSeparator({ className }) {
|
|
667
773
|
return /* @__PURE__ */ jsx("div", { className: cn("h-px bg-border my-1.5", className), role: "separator" });
|
|
668
774
|
}
|
|
669
|
-
var Breadcrumb =
|
|
775
|
+
var Breadcrumb = React17.forwardRef(
|
|
670
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 })
|
|
671
777
|
);
|
|
672
778
|
Breadcrumb.displayName = "Breadcrumb";
|
|
673
|
-
var BreadcrumbItem =
|
|
779
|
+
var BreadcrumbItem = React17.forwardRef(
|
|
674
780
|
({ className, current, children, ...props }, ref) => {
|
|
675
781
|
if (current) {
|
|
676
782
|
return /* @__PURE__ */ jsx("span", { "aria-current": "page", className: cn("text-foreground font-semibold", className), children });
|
|
@@ -717,27 +823,27 @@ function Pagination({ page, pageCount, onPageChange, className }) {
|
|
|
717
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" }) })
|
|
718
824
|
] });
|
|
719
825
|
}
|
|
720
|
-
var TableWrap =
|
|
826
|
+
var TableWrap = React17.forwardRef(
|
|
721
827
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("border border-border rounded-kj-lg overflow-hidden", className), ...props })
|
|
722
828
|
);
|
|
723
829
|
TableWrap.displayName = "TableWrap";
|
|
724
|
-
var Table =
|
|
830
|
+
var Table = React17.forwardRef(
|
|
725
831
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("table", { ref, className: cn("w-full border-collapse text-[0.85rem]", className), ...props })
|
|
726
832
|
);
|
|
727
833
|
Table.displayName = "Table";
|
|
728
|
-
var TableHeader =
|
|
834
|
+
var TableHeader = React17.forwardRef(
|
|
729
835
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className, ...props })
|
|
730
836
|
);
|
|
731
837
|
TableHeader.displayName = "TableHeader";
|
|
732
|
-
var TableBody =
|
|
838
|
+
var TableBody = React17.forwardRef(
|
|
733
839
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("tbody", { ref, className, ...props })
|
|
734
840
|
);
|
|
735
841
|
TableBody.displayName = "TableBody";
|
|
736
|
-
var TableRow =
|
|
842
|
+
var TableRow = React17.forwardRef(
|
|
737
843
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("tr", { ref, className: cn("transition-colors hover:bg-muted/50", className), ...props })
|
|
738
844
|
);
|
|
739
845
|
TableRow.displayName = "TableRow";
|
|
740
|
-
var TableHead =
|
|
846
|
+
var TableHead = React17.forwardRef(
|
|
741
847
|
({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
742
848
|
"th",
|
|
743
849
|
{
|
|
@@ -752,7 +858,7 @@ var TableHead = React16.forwardRef(
|
|
|
752
858
|
)
|
|
753
859
|
);
|
|
754
860
|
TableHead.displayName = "TableHead";
|
|
755
|
-
var TableCell =
|
|
861
|
+
var TableCell = React17.forwardRef(
|
|
756
862
|
({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
757
863
|
"td",
|
|
758
864
|
{
|
|
@@ -785,14 +891,68 @@ function Tooltip({ content, children, className }) {
|
|
|
785
891
|
)
|
|
786
892
|
] });
|
|
787
893
|
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
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);
|
|
793
953
|
document.body.style.overflow = "hidden";
|
|
794
954
|
return () => {
|
|
795
|
-
document.removeEventListener("keydown",
|
|
955
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
796
956
|
document.body.style.overflow = "";
|
|
797
957
|
};
|
|
798
958
|
}, [open, onClose]);
|
|
@@ -805,35 +965,53 @@ function Modal({ open, onClose, children, width = 440, className }) {
|
|
|
805
965
|
"bg-[color-mix(in_oklch,#09090b_55%,transparent)]",
|
|
806
966
|
open ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
|
|
807
967
|
),
|
|
808
|
-
children: /* @__PURE__ */ jsx(
|
|
968
|
+
children: /* @__PURE__ */ jsx(ModalContext.Provider, { value: { titleId, descId }, children: /* @__PURE__ */ jsxs(
|
|
809
969
|
"div",
|
|
810
970
|
{
|
|
971
|
+
ref: containerRef,
|
|
811
972
|
role: "dialog",
|
|
812
973
|
"aria-modal": "true",
|
|
974
|
+
"aria-labelledby": titleId,
|
|
975
|
+
"aria-describedby": descId,
|
|
976
|
+
tabIndex: -1,
|
|
813
977
|
style: { maxWidth: width },
|
|
814
978
|
className: cn(
|
|
815
|
-
"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",
|
|
816
980
|
open ? "scale-100 translate-y-0" : "scale-95 translate-y-2",
|
|
817
981
|
className
|
|
818
982
|
),
|
|
819
|
-
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
|
+
]
|
|
820
996
|
}
|
|
821
|
-
)
|
|
997
|
+
) })
|
|
822
998
|
}
|
|
823
999
|
);
|
|
824
1000
|
}
|
|
825
|
-
function ModalTitle({ className, ...props }) {
|
|
826
|
-
|
|
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 });
|
|
827
1004
|
}
|
|
828
|
-
function ModalDescription({ className, ...props }) {
|
|
829
|
-
|
|
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 });
|
|
830
1008
|
}
|
|
831
1009
|
function ModalActions({ className, ...props }) {
|
|
832
1010
|
return /* @__PURE__ */ jsx("div", { className: cn("flex gap-2.5 justify-end mt-6", className), ...props });
|
|
833
1011
|
}
|
|
834
|
-
var ToastContext =
|
|
1012
|
+
var ToastContext = React17.createContext(null);
|
|
835
1013
|
function useToast() {
|
|
836
|
-
const ctx =
|
|
1014
|
+
const ctx = React17.useContext(ToastContext);
|
|
837
1015
|
if (!ctx) throw new Error("useToast must be used within <ToastProvider>");
|
|
838
1016
|
return ctx;
|
|
839
1017
|
}
|
|
@@ -854,13 +1032,13 @@ var toneBorder = {
|
|
|
854
1032
|
danger: "border-l-danger"
|
|
855
1033
|
};
|
|
856
1034
|
function ToastProvider({ children }) {
|
|
857
|
-
const [items, setItems] =
|
|
858
|
-
const idRef =
|
|
859
|
-
const remove =
|
|
1035
|
+
const [items, setItems] = React17.useState([]);
|
|
1036
|
+
const idRef = React17.useRef(0);
|
|
1037
|
+
const remove = React17.useCallback((id) => {
|
|
860
1038
|
setItems((prev) => prev.map((t) => t.id === id ? { ...t, leaving: true } : t));
|
|
861
1039
|
setTimeout(() => setItems((prev) => prev.filter((t) => t.id !== id)), 250);
|
|
862
1040
|
}, []);
|
|
863
|
-
const toast =
|
|
1041
|
+
const toast = React17.useCallback(
|
|
864
1042
|
({ message, tone = "default", duration = 3200 }) => {
|
|
865
1043
|
const id = ++idRef.current;
|
|
866
1044
|
setItems((prev) => [...prev, { id, message, tone, duration }]);
|
|
@@ -890,7 +1068,18 @@ function ToastProvider({ children }) {
|
|
|
890
1068
|
)) })
|
|
891
1069
|
] });
|
|
892
1070
|
}
|
|
1071
|
+
var PageHeader = React17.forwardRef(
|
|
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: [
|
|
1073
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3 max-w-2xl", children: [
|
|
1074
|
+
eyebrow && /* @__PURE__ */ jsx("p", { className: "font-mono text-xs font-bold uppercase tracking-[0.2em] text-primary", children: eyebrow }),
|
|
1075
|
+
/* @__PURE__ */ jsx("h1", { className: "font-sans text-4xl font-bold tracking-tight text-foreground sm:text-5xl md:text-6xl", children: title }),
|
|
1076
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-base leading-relaxed text-muted-foreground sm:text-lg", children: description })
|
|
1077
|
+
] }),
|
|
1078
|
+
actions && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-3", children: actions })
|
|
1079
|
+
] }) })
|
|
1080
|
+
);
|
|
1081
|
+
PageHeader.displayName = "PageHeader";
|
|
893
1082
|
|
|
894
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, Avatar, AvatarGroup, Badge, Breadcrumb, BreadcrumbItem, BreadcrumbSeparator, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, Field, Hint, Input, Label, Modal, ModalActions, ModalDescription, ModalTitle, Pagination, Progress, Radio, Segmented, Select, Slider, Spinner, Stat, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, TableWrap, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ToastProvider, Tooltip, badgeVariants, buttonVariants, cn, sliderThumbCSS, useToast };
|
|
1083
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, Avatar, AvatarGroup, Badge, Breadcrumb, BreadcrumbItem, BreadcrumbSeparator, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, Field, Hint, Input, Label, Modal, ModalActions, ModalDescription, ModalTitle, PageHeader, Pagination, Progress, Radio, Segmented, Select, Slider, Spinner, Stat, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, TableWrap, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ToastProvider, Tooltip, badgeVariants, buttonVariants, cn, sliderThumbCSS, useToast };
|
|
895
1084
|
//# sourceMappingURL=index.js.map
|
|
896
1085
|
//# sourceMappingURL=index.js.map
|