@timbal-ai/timbal-react 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -1
- package/LICENSE +201 -0
- package/README.md +20 -11
- package/dist/app.cjs +1675 -1218
- package/dist/app.d.cts +22 -6
- package/dist/app.d.ts +22 -6
- package/dist/app.esm.js +26 -8
- package/dist/{chart-artifact-BZp7nmaf.d.ts → chart-artifact-Q5QgMtbj.d.ts} +107 -28
- package/dist/{chart-artifact-CX-rh9nq.d.cts → chart-artifact-WDEW9dHT.d.cts} +107 -28
- package/dist/{chat-DCms8pJ_.d.cts → chat-ClmzWzCX.d.cts} +2 -0
- package/dist/{chat-DCms8pJ_.d.ts → chat-ClmzWzCX.d.ts} +2 -0
- package/dist/chat.cjs +868 -511
- package/dist/chat.d.cts +1 -1
- package/dist/chat.d.ts +1 -1
- package/dist/chat.esm.js +3 -3
- package/dist/{chunk-YXZ22OJN.esm.js → chunk-GQBYZRD7.esm.js} +670 -402
- package/dist/{chunk-XCM3V6RK.esm.js → chunk-OFWC4MIY.esm.js} +2 -2
- package/dist/{chunk-6HWMJNZT.esm.js → chunk-OH23AX2V.esm.js} +757 -56
- package/dist/{chunk-4AKJ6FKE.esm.js → chunk-QU7ET55D.esm.js} +120 -23
- package/dist/{chunk-FRZOEYBO.esm.js → chunk-THBA27QY.esm.js} +4 -4
- package/dist/{chunk-JEAUF54A.esm.js → chunk-UCGVL7ZY.esm.js} +1 -1
- package/dist/{chunk-P3KDAYX6.esm.js → chunk-VXMM2HX7.esm.js} +1 -1
- package/dist/{chunk-TK2AGIME.esm.js → chunk-YCXN67SD.esm.js} +565 -480
- package/dist/{pill-segmented-tabs-Ba5q0feL.d.cts → circular-progress-Ci8L-Hfa.d.cts} +230 -6
- package/dist/{pill-segmented-tabs-Ba5q0feL.d.ts → circular-progress-Ci8L-Hfa.d.ts} +230 -6
- package/dist/index.cjs +2850 -1689
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.esm.js +41 -11
- package/dist/studio.cjs +1089 -732
- package/dist/studio.d.cts +2 -2
- package/dist/studio.d.ts +2 -2
- package/dist/studio.esm.js +5 -5
- package/dist/styles.css +14 -16
- package/dist/ui.cjs +880 -71
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.esm.js +28 -4
- package/dist/{welcome-CRqOPKMp.d.cts → welcome-BFGRoNfK.d.cts} +1 -1
- package/dist/{welcome-DlHUa3OL.d.ts → welcome-DXqsGTwH.d.ts} +1 -1
- package/package.json +1 -1
- package/vite/local-dev.d.ts +5 -1
- package/vite/local-dev.mjs +17 -13
|
@@ -9,14 +9,13 @@ import {
|
|
|
9
9
|
TIMBAL_V2_MODAL_SURFACE,
|
|
10
10
|
TIMBAL_V2_SWITCH_THUMB,
|
|
11
11
|
TIMBAL_V2_SWITCH_TRACK_OFF,
|
|
12
|
-
buttonVariants,
|
|
13
12
|
cn,
|
|
14
13
|
controlClass,
|
|
15
14
|
controlSurfaceClass,
|
|
16
15
|
overlayItemClass,
|
|
17
16
|
overlayListPanelClass,
|
|
18
17
|
overlaySurfaceClass
|
|
19
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-QU7ET55D.esm.js";
|
|
20
19
|
|
|
21
20
|
// src/ui/dropdown-menu.tsx
|
|
22
21
|
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
|
|
@@ -1451,8 +1450,11 @@ function CommandShortcut({
|
|
|
1451
1450
|
|
|
1452
1451
|
// src/ui/calendar.tsx
|
|
1453
1452
|
import * as React from "react";
|
|
1454
|
-
import { ChevronLeftIcon as ChevronLeftIcon2, ChevronRightIcon as ChevronRightIcon5 } from "lucide-react";
|
|
1455
|
-
import {
|
|
1453
|
+
import { ChevronDownIcon as ChevronDownIcon3, ChevronLeftIcon as ChevronLeftIcon2, ChevronRightIcon as ChevronRightIcon5 } from "lucide-react";
|
|
1454
|
+
import {
|
|
1455
|
+
DayPicker,
|
|
1456
|
+
getDefaultClassNames
|
|
1457
|
+
} from "react-day-picker";
|
|
1456
1458
|
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1457
1459
|
function Calendar({
|
|
1458
1460
|
className,
|
|
@@ -1460,56 +1462,71 @@ function Calendar({
|
|
|
1460
1462
|
showOutsideDays = true,
|
|
1461
1463
|
...props
|
|
1462
1464
|
}) {
|
|
1465
|
+
const defaults = getDefaultClassNames();
|
|
1463
1466
|
return /* @__PURE__ */ jsx17(
|
|
1464
1467
|
DayPicker,
|
|
1465
1468
|
{
|
|
1466
1469
|
showOutsideDays,
|
|
1467
|
-
className: cn("p-
|
|
1470
|
+
className: cn("p-4", className),
|
|
1468
1471
|
classNames: {
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1472
|
+
root: cn("w-fit", defaults.root),
|
|
1473
|
+
months: cn("relative flex flex-col gap-4 sm:flex-row", defaults.months),
|
|
1474
|
+
month: cn("flex w-full flex-col gap-3", defaults.month),
|
|
1475
|
+
nav: cn(
|
|
1476
|
+
"absolute inset-x-0 top-0 flex items-center justify-between",
|
|
1477
|
+
defaults.nav
|
|
1478
|
+
),
|
|
1479
|
+
button_previous: cn(navButtonClass, defaults.button_previous),
|
|
1480
|
+
button_next: cn(navButtonClass, defaults.button_next),
|
|
1481
|
+
month_caption: cn(
|
|
1482
|
+
"flex h-10 items-center justify-center",
|
|
1483
|
+
defaults.month_caption
|
|
1484
|
+
),
|
|
1485
|
+
caption_label: cn("text-sm font-semibold", defaults.caption_label),
|
|
1486
|
+
dropdowns: cn(
|
|
1487
|
+
"flex h-10 items-center justify-center gap-1.5 text-sm font-semibold",
|
|
1488
|
+
defaults.dropdowns
|
|
1489
|
+
),
|
|
1490
|
+
dropdown_root: cn(
|
|
1491
|
+
"relative rounded-md border border-border focus-within:ring-2 focus-within:ring-foreground/10",
|
|
1492
|
+
defaults.dropdown_root
|
|
1477
1493
|
),
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1494
|
+
dropdown: cn("absolute inset-0 bg-popover opacity-0", defaults.dropdown),
|
|
1495
|
+
month_grid: cn("border-separate border-spacing-y-1", defaults.month_grid),
|
|
1496
|
+
weekdays: cn(defaults.weekdays),
|
|
1497
|
+
weekday: cn(
|
|
1498
|
+
"size-10 pb-2 text-xs font-medium text-muted-foreground",
|
|
1499
|
+
defaults.weekday
|
|
1500
|
+
),
|
|
1501
|
+
week: cn(defaults.week),
|
|
1502
|
+
week_number_header: cn("size-10", defaults.week_number_header),
|
|
1503
|
+
week_number: cn(
|
|
1504
|
+
"text-xs text-muted-foreground",
|
|
1505
|
+
defaults.week_number
|
|
1481
1506
|
),
|
|
1482
|
-
month_grid: "w-full border-collapse",
|
|
1483
|
-
weekdays: "flex",
|
|
1484
|
-
weekday: "w-9 rounded-md text-[0.8rem] font-normal text-muted-foreground",
|
|
1485
|
-
week: "mt-2 flex w-full",
|
|
1486
1507
|
day: cn(
|
|
1487
|
-
"relative size-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1508
|
+
"relative size-10 p-0 text-center text-sm focus-within:relative focus-within:z-10",
|
|
1509
|
+
defaults.day
|
|
1510
|
+
),
|
|
1511
|
+
range_start: cn("rounded-l-md", defaults.range_start),
|
|
1512
|
+
range_middle: cn("rounded-none", defaults.range_middle),
|
|
1513
|
+
range_end: cn("rounded-r-md", defaults.range_end),
|
|
1514
|
+
today: cn(
|
|
1515
|
+
"[&>button]:font-semibold [&>button:not([data-selected-single=true]):not([data-range-middle=true])]:text-primary",
|
|
1516
|
+
defaults.today
|
|
1494
1517
|
),
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1518
|
+
outside: cn(
|
|
1519
|
+
"text-muted-foreground/60 aria-selected:text-muted-foreground",
|
|
1520
|
+
defaults.outside
|
|
1498
1521
|
),
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
range_end: "day-range-end rounded-r-md",
|
|
1502
|
-
selected: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
|
|
1503
|
-
today: "bg-accent text-accent-foreground",
|
|
1504
|
-
outside: "day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground",
|
|
1505
|
-
disabled: "text-muted-foreground opacity-50",
|
|
1506
|
-
hidden: "invisible",
|
|
1522
|
+
disabled: cn("text-muted-foreground opacity-50", defaults.disabled),
|
|
1523
|
+
hidden: cn("invisible", defaults.hidden),
|
|
1507
1524
|
...classNames
|
|
1508
1525
|
},
|
|
1509
1526
|
components: {
|
|
1510
|
-
Chevron: ({ orientation, className:
|
|
1511
|
-
const Icon = orientation === "left" ? ChevronLeftIcon2 : ChevronRightIcon5;
|
|
1512
|
-
return /* @__PURE__ */ jsx17(Icon, { className: cn("size-4",
|
|
1527
|
+
Chevron: ({ orientation, className: chevronClass, ...chevronProps }) => {
|
|
1528
|
+
const Icon = orientation === "left" ? ChevronLeftIcon2 : orientation === "right" ? ChevronRightIcon5 : ChevronDownIcon3;
|
|
1529
|
+
return /* @__PURE__ */ jsx17(Icon, { className: cn("size-4", chevronClass), ...chevronProps });
|
|
1513
1530
|
},
|
|
1514
1531
|
DayButton: CalendarDayButton
|
|
1515
1532
|
},
|
|
@@ -1517,6 +1534,12 @@ function Calendar({
|
|
|
1517
1534
|
}
|
|
1518
1535
|
);
|
|
1519
1536
|
}
|
|
1537
|
+
var navButtonClass = cn(
|
|
1538
|
+
"inline-flex size-8 items-center justify-center rounded-md text-muted-foreground transition-colors",
|
|
1539
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
1540
|
+
"disabled:pointer-events-none disabled:opacity-40",
|
|
1541
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10"
|
|
1542
|
+
);
|
|
1520
1543
|
function CalendarDayButton({
|
|
1521
1544
|
className,
|
|
1522
1545
|
day,
|
|
@@ -1527,25 +1550,26 @@ function CalendarDayButton({
|
|
|
1527
1550
|
React.useEffect(() => {
|
|
1528
1551
|
if (modifiers.focused) ref.current?.focus();
|
|
1529
1552
|
}, [modifiers.focused]);
|
|
1553
|
+
const isSingle = modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle;
|
|
1530
1554
|
return /* @__PURE__ */ jsx17(
|
|
1531
1555
|
"button",
|
|
1532
1556
|
{
|
|
1533
1557
|
ref,
|
|
1534
1558
|
type: "button",
|
|
1535
1559
|
"data-day": day.date.toLocaleDateString(),
|
|
1536
|
-
"data-selected-single":
|
|
1537
|
-
"data-range-start": modifiers.range_start,
|
|
1538
|
-
"data-range-end": modifiers.range_end,
|
|
1539
|
-
"data-range-middle": modifiers.range_middle,
|
|
1560
|
+
"data-selected-single": isSingle || void 0,
|
|
1561
|
+
"data-range-start": modifiers.range_start || void 0,
|
|
1562
|
+
"data-range-end": modifiers.range_end || void 0,
|
|
1563
|
+
"data-range-middle": modifiers.range_middle || void 0,
|
|
1540
1564
|
className: cn(
|
|
1541
|
-
"inline-flex items-center justify-center
|
|
1565
|
+
"inline-flex size-full items-center justify-center rounded-md text-sm font-normal transition-colors",
|
|
1542
1566
|
"hover:bg-accent hover:text-accent-foreground",
|
|
1543
|
-
"focus-visible:
|
|
1567
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
|
|
1544
1568
|
"disabled:pointer-events-none disabled:opacity-50",
|
|
1545
|
-
"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground",
|
|
1546
|
-
"data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground",
|
|
1547
|
-
"data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground",
|
|
1548
|
-
"data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground",
|
|
1569
|
+
"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[selected-single=true]:hover:bg-primary",
|
|
1570
|
+
"data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground",
|
|
1571
|
+
"data-[range-start=true]:rounded-l-md data-[range-start=true]:rounded-r-none data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground",
|
|
1572
|
+
"data-[range-end=true]:rounded-r-md data-[range-end=true]:rounded-l-none data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground",
|
|
1549
1573
|
className
|
|
1550
1574
|
),
|
|
1551
1575
|
...props
|
|
@@ -1554,7 +1578,7 @@ function CalendarDayButton({
|
|
|
1554
1578
|
}
|
|
1555
1579
|
|
|
1556
1580
|
// src/ui/combobox.tsx
|
|
1557
|
-
import { ChevronDownIcon as
|
|
1581
|
+
import { ChevronDownIcon as ChevronDownIcon4 } from "lucide-react";
|
|
1558
1582
|
import { jsx as jsx18, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1559
1583
|
function Combobox({
|
|
1560
1584
|
...props
|
|
@@ -1580,7 +1604,7 @@ function ComboboxTrigger({
|
|
|
1580
1604
|
...props,
|
|
1581
1605
|
children: [
|
|
1582
1606
|
/* @__PURE__ */ jsx18("span", { className: "truncate", children }),
|
|
1583
|
-
/* @__PURE__ */ jsx18(
|
|
1607
|
+
/* @__PURE__ */ jsx18(ChevronDownIcon4, { className: "size-4 shrink-0 opacity-50" })
|
|
1584
1608
|
]
|
|
1585
1609
|
}
|
|
1586
1610
|
);
|
|
@@ -1950,7 +1974,7 @@ function InputGroupText({
|
|
|
1950
1974
|
|
|
1951
1975
|
// src/ui/accordion.tsx
|
|
1952
1976
|
import { Accordion as AccordionPrimitive } from "radix-ui";
|
|
1953
|
-
import { ChevronDownIcon as
|
|
1977
|
+
import { ChevronDownIcon as ChevronDownIcon5 } from "lucide-react";
|
|
1954
1978
|
import { jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1955
1979
|
function Accordion({
|
|
1956
1980
|
...props
|
|
@@ -1988,7 +2012,7 @@ function AccordionTrigger({
|
|
|
1988
2012
|
...props,
|
|
1989
2013
|
children: [
|
|
1990
2014
|
children,
|
|
1991
|
-
/* @__PURE__ */ jsx24(
|
|
2015
|
+
/* @__PURE__ */ jsx24(ChevronDownIcon5, { className: "pointer-events-none size-4 shrink-0 text-muted-foreground transition-transform duration-200" })
|
|
1992
2016
|
]
|
|
1993
2017
|
}
|
|
1994
2018
|
) });
|
|
@@ -3227,6 +3251,673 @@ function Toaster() {
|
|
|
3227
3251
|
] });
|
|
3228
3252
|
}
|
|
3229
3253
|
|
|
3254
|
+
// src/ui/avatar-group.tsx
|
|
3255
|
+
import * as React4 from "react";
|
|
3256
|
+
import { jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3257
|
+
var spacingClass = {
|
|
3258
|
+
sm: "-space-x-2",
|
|
3259
|
+
md: "-space-x-3"
|
|
3260
|
+
};
|
|
3261
|
+
function AvatarGroup({
|
|
3262
|
+
className,
|
|
3263
|
+
children,
|
|
3264
|
+
max,
|
|
3265
|
+
spacing = "sm",
|
|
3266
|
+
...props
|
|
3267
|
+
}) {
|
|
3268
|
+
const items = React4.Children.toArray(children);
|
|
3269
|
+
const overflow = typeof max === "number" ? items.length - max : 0;
|
|
3270
|
+
const visible = typeof max === "number" ? items.slice(0, max) : items;
|
|
3271
|
+
return /* @__PURE__ */ jsxs18(
|
|
3272
|
+
"div",
|
|
3273
|
+
{
|
|
3274
|
+
"data-slot": "avatar-group",
|
|
3275
|
+
className: cn(
|
|
3276
|
+
"flex items-center",
|
|
3277
|
+
spacingClass[spacing],
|
|
3278
|
+
"[&>*]:rounded-full [&>*]:ring-2 [&>*]:ring-background",
|
|
3279
|
+
className
|
|
3280
|
+
),
|
|
3281
|
+
...props,
|
|
3282
|
+
children: [
|
|
3283
|
+
visible,
|
|
3284
|
+
overflow > 0 ? /* @__PURE__ */ jsxs18(
|
|
3285
|
+
"span",
|
|
3286
|
+
{
|
|
3287
|
+
"aria-label": `${overflow} more`,
|
|
3288
|
+
className: "inline-flex size-8 items-center justify-center rounded-full bg-muted text-xs font-medium text-muted-foreground ring-2 ring-background",
|
|
3289
|
+
children: [
|
|
3290
|
+
"+",
|
|
3291
|
+
overflow
|
|
3292
|
+
]
|
|
3293
|
+
}
|
|
3294
|
+
) : null
|
|
3295
|
+
]
|
|
3296
|
+
}
|
|
3297
|
+
);
|
|
3298
|
+
}
|
|
3299
|
+
|
|
3300
|
+
// src/ui/stepper.tsx
|
|
3301
|
+
import { CheckIcon as CheckIcon5 } from "lucide-react";
|
|
3302
|
+
import { jsx as jsx42, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3303
|
+
function Stepper({
|
|
3304
|
+
steps,
|
|
3305
|
+
current,
|
|
3306
|
+
orientation = "horizontal",
|
|
3307
|
+
className,
|
|
3308
|
+
...props
|
|
3309
|
+
}) {
|
|
3310
|
+
const isVertical = orientation === "vertical";
|
|
3311
|
+
return /* @__PURE__ */ jsx42(
|
|
3312
|
+
"ol",
|
|
3313
|
+
{
|
|
3314
|
+
"data-slot": "stepper",
|
|
3315
|
+
className: cn(
|
|
3316
|
+
"flex",
|
|
3317
|
+
isVertical ? "flex-col gap-0" : "items-start gap-2",
|
|
3318
|
+
className
|
|
3319
|
+
),
|
|
3320
|
+
...props,
|
|
3321
|
+
children: steps.map((step, index) => {
|
|
3322
|
+
const complete = index < current;
|
|
3323
|
+
const active = index === current;
|
|
3324
|
+
const last = index === steps.length - 1;
|
|
3325
|
+
const connectorFilled = index < current;
|
|
3326
|
+
return /* @__PURE__ */ jsxs19(
|
|
3327
|
+
"li",
|
|
3328
|
+
{
|
|
3329
|
+
"aria-current": active ? "step" : void 0,
|
|
3330
|
+
className: cn(
|
|
3331
|
+
"flex min-w-0",
|
|
3332
|
+
isVertical ? "gap-3" : "flex-1 flex-col gap-1.5",
|
|
3333
|
+
last && !isVertical && "flex-none"
|
|
3334
|
+
),
|
|
3335
|
+
children: [
|
|
3336
|
+
/* @__PURE__ */ jsxs19("div", { className: cn("flex items-center gap-2", isVertical && "flex-col"), children: [
|
|
3337
|
+
/* @__PURE__ */ jsx42(
|
|
3338
|
+
"span",
|
|
3339
|
+
{
|
|
3340
|
+
className: cn(
|
|
3341
|
+
"inline-flex size-7 shrink-0 items-center justify-center rounded-full border text-xs font-medium transition-colors",
|
|
3342
|
+
complete && "border-primary bg-primary text-primary-foreground",
|
|
3343
|
+
active && "border-primary text-primary",
|
|
3344
|
+
!complete && !active && "border-border text-muted-foreground"
|
|
3345
|
+
),
|
|
3346
|
+
children: complete ? /* @__PURE__ */ jsx42(CheckIcon5, { className: "size-3.5", "aria-hidden": true }) : index + 1
|
|
3347
|
+
}
|
|
3348
|
+
),
|
|
3349
|
+
!last ? /* @__PURE__ */ jsx42(
|
|
3350
|
+
"span",
|
|
3351
|
+
{
|
|
3352
|
+
"aria-hidden": true,
|
|
3353
|
+
className: cn(
|
|
3354
|
+
isVertical ? "w-px flex-1" : "h-px flex-1",
|
|
3355
|
+
connectorFilled ? "bg-primary" : "bg-border",
|
|
3356
|
+
isVertical && "min-h-6"
|
|
3357
|
+
)
|
|
3358
|
+
}
|
|
3359
|
+
) : null
|
|
3360
|
+
] }),
|
|
3361
|
+
/* @__PURE__ */ jsxs19("div", { className: cn("min-w-0", isVertical && "pb-4"), children: [
|
|
3362
|
+
/* @__PURE__ */ jsx42(
|
|
3363
|
+
"p",
|
|
3364
|
+
{
|
|
3365
|
+
className: cn(
|
|
3366
|
+
"truncate text-sm font-medium",
|
|
3367
|
+
active ? "text-foreground" : "text-muted-foreground"
|
|
3368
|
+
),
|
|
3369
|
+
children: step.label
|
|
3370
|
+
}
|
|
3371
|
+
),
|
|
3372
|
+
step.description ? /* @__PURE__ */ jsx42("p", { className: "truncate text-xs text-muted-foreground", children: step.description }) : null
|
|
3373
|
+
] })
|
|
3374
|
+
]
|
|
3375
|
+
},
|
|
3376
|
+
step.id
|
|
3377
|
+
);
|
|
3378
|
+
})
|
|
3379
|
+
}
|
|
3380
|
+
);
|
|
3381
|
+
}
|
|
3382
|
+
|
|
3383
|
+
// src/ui/timeline.tsx
|
|
3384
|
+
import { jsx as jsx43, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3385
|
+
var dotToneClass = {
|
|
3386
|
+
default: "border-border bg-card",
|
|
3387
|
+
primary: "border-primary bg-primary",
|
|
3388
|
+
success: "border-emerald-500 bg-emerald-500",
|
|
3389
|
+
warn: "border-amber-500 bg-amber-500",
|
|
3390
|
+
danger: "border-destructive bg-destructive"
|
|
3391
|
+
};
|
|
3392
|
+
function Timeline({ items, className, ...props }) {
|
|
3393
|
+
return /* @__PURE__ */ jsx43("ol", { "data-slot": "timeline", className: cn("flex flex-col", className), ...props, children: items.map((item, index) => {
|
|
3394
|
+
const last = index === items.length - 1;
|
|
3395
|
+
const tone = item.tone ?? "default";
|
|
3396
|
+
return /* @__PURE__ */ jsxs20("li", { className: "relative flex gap-3 pb-5 last:pb-0", children: [
|
|
3397
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex flex-col items-center", children: [
|
|
3398
|
+
/* @__PURE__ */ jsx43(
|
|
3399
|
+
"span",
|
|
3400
|
+
{
|
|
3401
|
+
className: cn(
|
|
3402
|
+
"z-[1] mt-0.5 inline-flex size-3 shrink-0 items-center justify-center rounded-full border-2",
|
|
3403
|
+
dotToneClass[tone],
|
|
3404
|
+
item.icon && "size-6"
|
|
3405
|
+
),
|
|
3406
|
+
children: item.icon
|
|
3407
|
+
}
|
|
3408
|
+
),
|
|
3409
|
+
!last ? /* @__PURE__ */ jsx43("span", { "aria-hidden": true, className: "w-px flex-1 bg-border" }) : null
|
|
3410
|
+
] }),
|
|
3411
|
+
/* @__PURE__ */ jsxs20("div", { className: "min-w-0 flex-1 pb-0.5", children: [
|
|
3412
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-start justify-between gap-2", children: [
|
|
3413
|
+
/* @__PURE__ */ jsx43("p", { className: "text-sm font-medium text-foreground", children: item.title }),
|
|
3414
|
+
item.meta ? /* @__PURE__ */ jsx43("span", { className: "shrink-0 text-xs text-muted-foreground tabular-nums", children: item.meta }) : null
|
|
3415
|
+
] }),
|
|
3416
|
+
item.description ? /* @__PURE__ */ jsx43("p", { className: "mt-0.5 text-sm text-muted-foreground", children: item.description }) : null
|
|
3417
|
+
] })
|
|
3418
|
+
] }, item.id);
|
|
3419
|
+
}) });
|
|
3420
|
+
}
|
|
3421
|
+
|
|
3422
|
+
// src/ui/rating.tsx
|
|
3423
|
+
import * as React5 from "react";
|
|
3424
|
+
import { StarIcon } from "lucide-react";
|
|
3425
|
+
import { jsx as jsx44 } from "react/jsx-runtime";
|
|
3426
|
+
var sizeClass = { sm: "size-4", md: "size-5", lg: "size-6" };
|
|
3427
|
+
function Rating({
|
|
3428
|
+
value: valueProp,
|
|
3429
|
+
defaultValue = 0,
|
|
3430
|
+
onChange,
|
|
3431
|
+
max = 5,
|
|
3432
|
+
readOnly = false,
|
|
3433
|
+
disabled = false,
|
|
3434
|
+
size = "md",
|
|
3435
|
+
label = "Rating",
|
|
3436
|
+
className
|
|
3437
|
+
}) {
|
|
3438
|
+
const [uncontrolled, setUncontrolled] = React5.useState(defaultValue);
|
|
3439
|
+
const isControlled = valueProp !== void 0;
|
|
3440
|
+
const value = isControlled ? valueProp : uncontrolled;
|
|
3441
|
+
const [hover, setHover] = React5.useState(null);
|
|
3442
|
+
const interactive = !readOnly && !disabled;
|
|
3443
|
+
const shown = hover ?? value;
|
|
3444
|
+
const set = (next) => {
|
|
3445
|
+
if (!interactive) return;
|
|
3446
|
+
if (!isControlled) setUncontrolled(next);
|
|
3447
|
+
onChange?.(next);
|
|
3448
|
+
};
|
|
3449
|
+
if (!interactive) {
|
|
3450
|
+
return /* @__PURE__ */ jsx44(
|
|
3451
|
+
"span",
|
|
3452
|
+
{
|
|
3453
|
+
"data-slot": "rating",
|
|
3454
|
+
role: "img",
|
|
3455
|
+
"aria-label": `${label}: ${value} of ${max}`,
|
|
3456
|
+
className: cn("inline-flex items-center gap-0.5", disabled && "opacity-50", className),
|
|
3457
|
+
children: Array.from({ length: max }, (_, i) => /* @__PURE__ */ jsx44(
|
|
3458
|
+
StarIcon,
|
|
3459
|
+
{
|
|
3460
|
+
"aria-hidden": true,
|
|
3461
|
+
className: cn(
|
|
3462
|
+
sizeClass[size],
|
|
3463
|
+
i < value ? "fill-amber-400 text-amber-400" : "fill-transparent text-muted-foreground/40"
|
|
3464
|
+
)
|
|
3465
|
+
},
|
|
3466
|
+
i
|
|
3467
|
+
))
|
|
3468
|
+
}
|
|
3469
|
+
);
|
|
3470
|
+
}
|
|
3471
|
+
return /* @__PURE__ */ jsx44(
|
|
3472
|
+
"span",
|
|
3473
|
+
{
|
|
3474
|
+
"data-slot": "rating",
|
|
3475
|
+
role: "radiogroup",
|
|
3476
|
+
"aria-label": label,
|
|
3477
|
+
className: cn("inline-flex items-center gap-0.5", className),
|
|
3478
|
+
onMouseLeave: () => setHover(null),
|
|
3479
|
+
children: Array.from({ length: max }, (_, i) => {
|
|
3480
|
+
const unit = i + 1;
|
|
3481
|
+
const filled = unit <= shown;
|
|
3482
|
+
return /* @__PURE__ */ jsx44(
|
|
3483
|
+
"button",
|
|
3484
|
+
{
|
|
3485
|
+
type: "button",
|
|
3486
|
+
role: "radio",
|
|
3487
|
+
"aria-checked": unit === value,
|
|
3488
|
+
"aria-label": `${unit} ${unit === 1 ? "star" : "stars"}`,
|
|
3489
|
+
onClick: () => set(unit === value ? 0 : unit),
|
|
3490
|
+
onMouseEnter: () => setHover(unit),
|
|
3491
|
+
onFocus: () => setHover(unit),
|
|
3492
|
+
onBlur: () => setHover(null),
|
|
3493
|
+
className: "rounded-sm p-0.5 transition-transform hover:scale-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
|
|
3494
|
+
children: /* @__PURE__ */ jsx44(
|
|
3495
|
+
StarIcon,
|
|
3496
|
+
{
|
|
3497
|
+
className: cn(
|
|
3498
|
+
sizeClass[size],
|
|
3499
|
+
"transition-colors",
|
|
3500
|
+
filled ? "fill-amber-400 text-amber-400" : "fill-transparent text-muted-foreground/40"
|
|
3501
|
+
)
|
|
3502
|
+
}
|
|
3503
|
+
)
|
|
3504
|
+
},
|
|
3505
|
+
i
|
|
3506
|
+
);
|
|
3507
|
+
})
|
|
3508
|
+
}
|
|
3509
|
+
);
|
|
3510
|
+
}
|
|
3511
|
+
|
|
3512
|
+
// src/ui/number-field.tsx
|
|
3513
|
+
import * as React6 from "react";
|
|
3514
|
+
import { MinusIcon as MinusIcon2, PlusIcon } from "lucide-react";
|
|
3515
|
+
import { jsx as jsx45, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3516
|
+
var heightClass = { sm: "h-9", default: "h-10" };
|
|
3517
|
+
var stepButtonClass = "inline-flex aspect-square h-full items-center justify-center text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:pointer-events-none disabled:opacity-40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-foreground/15";
|
|
3518
|
+
function clamp(n, min, max) {
|
|
3519
|
+
if (typeof min === "number" && n < min) return min;
|
|
3520
|
+
if (typeof max === "number" && n > max) return max;
|
|
3521
|
+
return n;
|
|
3522
|
+
}
|
|
3523
|
+
function NumberField({
|
|
3524
|
+
value: valueProp,
|
|
3525
|
+
defaultValue = 0,
|
|
3526
|
+
onValueChange,
|
|
3527
|
+
min,
|
|
3528
|
+
max,
|
|
3529
|
+
step = 1,
|
|
3530
|
+
size = "default",
|
|
3531
|
+
disabled,
|
|
3532
|
+
ariaLabel,
|
|
3533
|
+
className,
|
|
3534
|
+
...inputProps
|
|
3535
|
+
}) {
|
|
3536
|
+
const [uncontrolled, setUncontrolled] = React6.useState(defaultValue);
|
|
3537
|
+
const isControlled = valueProp !== void 0;
|
|
3538
|
+
const value = isControlled ? valueProp : uncontrolled;
|
|
3539
|
+
const commit = (next) => {
|
|
3540
|
+
const clamped = clamp(next, min, max);
|
|
3541
|
+
if (!isControlled) setUncontrolled(clamped);
|
|
3542
|
+
onValueChange?.(clamped);
|
|
3543
|
+
};
|
|
3544
|
+
return /* @__PURE__ */ jsxs21(
|
|
3545
|
+
"div",
|
|
3546
|
+
{
|
|
3547
|
+
"data-slot": "number-field",
|
|
3548
|
+
className: cn(
|
|
3549
|
+
controlSurfaceClass,
|
|
3550
|
+
"inline-flex w-full items-stretch overflow-hidden rounded-lg p-0",
|
|
3551
|
+
heightClass[size],
|
|
3552
|
+
disabled && "opacity-50",
|
|
3553
|
+
className
|
|
3554
|
+
),
|
|
3555
|
+
children: [
|
|
3556
|
+
/* @__PURE__ */ jsx45(
|
|
3557
|
+
"button",
|
|
3558
|
+
{
|
|
3559
|
+
type: "button",
|
|
3560
|
+
tabIndex: -1,
|
|
3561
|
+
"aria-hidden": true,
|
|
3562
|
+
disabled: disabled || typeof min === "number" && value <= min,
|
|
3563
|
+
onClick: () => commit(value - step),
|
|
3564
|
+
className: cn(stepButtonClass, "border-r border-border"),
|
|
3565
|
+
children: /* @__PURE__ */ jsx45(MinusIcon2, { className: "size-4" })
|
|
3566
|
+
}
|
|
3567
|
+
),
|
|
3568
|
+
/* @__PURE__ */ jsx45(
|
|
3569
|
+
"input",
|
|
3570
|
+
{
|
|
3571
|
+
type: "number",
|
|
3572
|
+
inputMode: "decimal",
|
|
3573
|
+
role: "spinbutton",
|
|
3574
|
+
"aria-label": ariaLabel,
|
|
3575
|
+
"aria-valuenow": value,
|
|
3576
|
+
"aria-valuemin": min,
|
|
3577
|
+
"aria-valuemax": max,
|
|
3578
|
+
value: Number.isNaN(value) ? "" : value,
|
|
3579
|
+
disabled,
|
|
3580
|
+
onChange: (e) => {
|
|
3581
|
+
const next = e.target.valueAsNumber;
|
|
3582
|
+
if (Number.isNaN(next)) {
|
|
3583
|
+
if (!isControlled) setUncontrolled(Number.NaN);
|
|
3584
|
+
return;
|
|
3585
|
+
}
|
|
3586
|
+
commit(next);
|
|
3587
|
+
},
|
|
3588
|
+
className: "w-full min-w-0 [appearance:textfield] bg-transparent px-2 text-center text-sm text-foreground outline-none disabled:cursor-not-allowed [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none",
|
|
3589
|
+
...inputProps
|
|
3590
|
+
}
|
|
3591
|
+
),
|
|
3592
|
+
/* @__PURE__ */ jsx45(
|
|
3593
|
+
"button",
|
|
3594
|
+
{
|
|
3595
|
+
type: "button",
|
|
3596
|
+
tabIndex: -1,
|
|
3597
|
+
"aria-hidden": true,
|
|
3598
|
+
disabled: disabled || typeof max === "number" && value >= max,
|
|
3599
|
+
onClick: () => commit(value + step),
|
|
3600
|
+
className: cn(stepButtonClass, "border-l border-border"),
|
|
3601
|
+
children: /* @__PURE__ */ jsx45(PlusIcon, { className: "size-4" })
|
|
3602
|
+
}
|
|
3603
|
+
)
|
|
3604
|
+
]
|
|
3605
|
+
}
|
|
3606
|
+
);
|
|
3607
|
+
}
|
|
3608
|
+
|
|
3609
|
+
// src/ui/tag-input.tsx
|
|
3610
|
+
import * as React7 from "react";
|
|
3611
|
+
import { XIcon as XIcon3 } from "lucide-react";
|
|
3612
|
+
import { jsx as jsx46, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
3613
|
+
function TagInput({
|
|
3614
|
+
value: valueProp,
|
|
3615
|
+
defaultValue = [],
|
|
3616
|
+
onChange,
|
|
3617
|
+
placeholder,
|
|
3618
|
+
separators = ["Enter", ","],
|
|
3619
|
+
dedupe = true,
|
|
3620
|
+
max,
|
|
3621
|
+
disabled,
|
|
3622
|
+
ariaLabel,
|
|
3623
|
+
className,
|
|
3624
|
+
inputClassName
|
|
3625
|
+
}) {
|
|
3626
|
+
const [uncontrolled, setUncontrolled] = React7.useState(defaultValue);
|
|
3627
|
+
const isControlled = valueProp !== void 0;
|
|
3628
|
+
const tags = isControlled ? valueProp : uncontrolled;
|
|
3629
|
+
const [draft, setDraft] = React7.useState("");
|
|
3630
|
+
const setTags = (next) => {
|
|
3631
|
+
if (!isControlled) setUncontrolled(next);
|
|
3632
|
+
onChange?.(next);
|
|
3633
|
+
};
|
|
3634
|
+
const addTag = (raw) => {
|
|
3635
|
+
const tag = raw.trim();
|
|
3636
|
+
if (!tag) return;
|
|
3637
|
+
if (typeof max === "number" && tags.length >= max) return;
|
|
3638
|
+
if (dedupe && tags.some((t) => t.toLowerCase() === tag.toLowerCase())) {
|
|
3639
|
+
setDraft("");
|
|
3640
|
+
return;
|
|
3641
|
+
}
|
|
3642
|
+
setTags([...tags, tag]);
|
|
3643
|
+
setDraft("");
|
|
3644
|
+
};
|
|
3645
|
+
const removeAt = (index) => {
|
|
3646
|
+
setTags(tags.filter((_, i) => i !== index));
|
|
3647
|
+
};
|
|
3648
|
+
const handleKeyDown = (event) => {
|
|
3649
|
+
if (separators.includes(event.key)) {
|
|
3650
|
+
event.preventDefault();
|
|
3651
|
+
addTag(draft);
|
|
3652
|
+
} else if (event.key === "Backspace" && draft === "" && tags.length > 0) {
|
|
3653
|
+
removeAt(tags.length - 1);
|
|
3654
|
+
}
|
|
3655
|
+
};
|
|
3656
|
+
return /* @__PURE__ */ jsxs22(
|
|
3657
|
+
"div",
|
|
3658
|
+
{
|
|
3659
|
+
"data-slot": "tag-input",
|
|
3660
|
+
className: cn(
|
|
3661
|
+
controlSurfaceClass,
|
|
3662
|
+
"flex min-h-10 w-full flex-wrap items-center gap-1.5 rounded-lg px-2 py-1.5",
|
|
3663
|
+
disabled && "pointer-events-none opacity-50",
|
|
3664
|
+
className
|
|
3665
|
+
),
|
|
3666
|
+
children: [
|
|
3667
|
+
tags.map((tag, index) => /* @__PURE__ */ jsxs22(
|
|
3668
|
+
"span",
|
|
3669
|
+
{
|
|
3670
|
+
className: "inline-flex items-center gap-1 rounded-md bg-muted py-0.5 pl-2 pr-1 text-xs font-medium text-foreground",
|
|
3671
|
+
children: [
|
|
3672
|
+
tag,
|
|
3673
|
+
/* @__PURE__ */ jsx46(
|
|
3674
|
+
"button",
|
|
3675
|
+
{
|
|
3676
|
+
type: "button",
|
|
3677
|
+
"aria-label": `Remove ${tag}`,
|
|
3678
|
+
onClick: () => removeAt(index),
|
|
3679
|
+
className: "inline-flex size-4 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-foreground/10 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/20",
|
|
3680
|
+
children: /* @__PURE__ */ jsx46(XIcon3, { className: "size-3", "aria-hidden": true })
|
|
3681
|
+
}
|
|
3682
|
+
)
|
|
3683
|
+
]
|
|
3684
|
+
},
|
|
3685
|
+
`${tag}-${index}`
|
|
3686
|
+
)),
|
|
3687
|
+
/* @__PURE__ */ jsx46(
|
|
3688
|
+
"input",
|
|
3689
|
+
{
|
|
3690
|
+
type: "text",
|
|
3691
|
+
"aria-label": ariaLabel ?? placeholder ?? "Add tag",
|
|
3692
|
+
value: draft,
|
|
3693
|
+
disabled,
|
|
3694
|
+
placeholder: tags.length === 0 ? placeholder : void 0,
|
|
3695
|
+
onChange: (e) => setDraft(e.target.value),
|
|
3696
|
+
onKeyDown: handleKeyDown,
|
|
3697
|
+
onBlur: () => addTag(draft),
|
|
3698
|
+
className: cn(
|
|
3699
|
+
"min-w-[6rem] flex-1 bg-transparent text-sm text-foreground outline-none placeholder:text-muted-foreground/70",
|
|
3700
|
+
inputClassName
|
|
3701
|
+
)
|
|
3702
|
+
}
|
|
3703
|
+
)
|
|
3704
|
+
]
|
|
3705
|
+
}
|
|
3706
|
+
);
|
|
3707
|
+
}
|
|
3708
|
+
|
|
3709
|
+
// src/ui/banner.tsx
|
|
3710
|
+
import { XIcon as XIcon4 } from "lucide-react";
|
|
3711
|
+
import { jsx as jsx47, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
3712
|
+
var bannerToneClass = {
|
|
3713
|
+
default: "border-border bg-muted/50 text-foreground",
|
|
3714
|
+
primary: "border-primary/20 bg-primary/10 text-foreground",
|
|
3715
|
+
success: "border-emerald-500/25 bg-emerald-500/10 text-foreground [&_[data-banner-icon]]:text-emerald-600 dark:[&_[data-banner-icon]]:text-emerald-400",
|
|
3716
|
+
warn: "border-amber-500/25 bg-amber-500/10 text-foreground [&_[data-banner-icon]]:text-amber-600 dark:[&_[data-banner-icon]]:text-amber-400",
|
|
3717
|
+
danger: "border-destructive/25 bg-destructive/10 text-foreground [&_[data-banner-icon]]:text-destructive"
|
|
3718
|
+
};
|
|
3719
|
+
function Banner({
|
|
3720
|
+
tone = "default",
|
|
3721
|
+
icon,
|
|
3722
|
+
title,
|
|
3723
|
+
actions,
|
|
3724
|
+
onDismiss,
|
|
3725
|
+
className,
|
|
3726
|
+
children,
|
|
3727
|
+
...props
|
|
3728
|
+
}) {
|
|
3729
|
+
return /* @__PURE__ */ jsxs23(
|
|
3730
|
+
"div",
|
|
3731
|
+
{
|
|
3732
|
+
"data-slot": "banner",
|
|
3733
|
+
role: "status",
|
|
3734
|
+
className: cn(
|
|
3735
|
+
"flex w-full items-start gap-3 rounded-lg border px-4 py-3 text-sm",
|
|
3736
|
+
bannerToneClass[tone],
|
|
3737
|
+
className
|
|
3738
|
+
),
|
|
3739
|
+
...props,
|
|
3740
|
+
children: [
|
|
3741
|
+
icon ? /* @__PURE__ */ jsx47("span", { "data-banner-icon": true, className: "mt-0.5 shrink-0 [&_svg]:size-4", children: icon }) : null,
|
|
3742
|
+
/* @__PURE__ */ jsxs23("div", { className: "min-w-0 flex-1", children: [
|
|
3743
|
+
title ? /* @__PURE__ */ jsx47("p", { className: "font-medium", children: title }) : null,
|
|
3744
|
+
children ? /* @__PURE__ */ jsx47("div", { className: cn("text-muted-foreground", title && "mt-0.5"), children }) : null
|
|
3745
|
+
] }),
|
|
3746
|
+
actions ? /* @__PURE__ */ jsx47("div", { className: "flex shrink-0 items-center gap-2", children: actions }) : null,
|
|
3747
|
+
onDismiss ? /* @__PURE__ */ jsx47(
|
|
3748
|
+
"button",
|
|
3749
|
+
{
|
|
3750
|
+
type: "button",
|
|
3751
|
+
"aria-label": "Dismiss",
|
|
3752
|
+
onClick: onDismiss,
|
|
3753
|
+
className: "-mr-1 -mt-0.5 inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-foreground/10 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
|
|
3754
|
+
children: /* @__PURE__ */ jsx47(XIcon4, { className: "size-4", "aria-hidden": true })
|
|
3755
|
+
}
|
|
3756
|
+
) : null
|
|
3757
|
+
]
|
|
3758
|
+
}
|
|
3759
|
+
);
|
|
3760
|
+
}
|
|
3761
|
+
|
|
3762
|
+
// src/ui/copy-button.tsx
|
|
3763
|
+
import * as React8 from "react";
|
|
3764
|
+
import { CheckIcon as CheckIcon6, CopyIcon } from "lucide-react";
|
|
3765
|
+
import { jsx as jsx48, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
3766
|
+
function CopyButton({
|
|
3767
|
+
value,
|
|
3768
|
+
timeout = 1500,
|
|
3769
|
+
onCopied,
|
|
3770
|
+
className,
|
|
3771
|
+
children,
|
|
3772
|
+
onClick,
|
|
3773
|
+
...props
|
|
3774
|
+
}) {
|
|
3775
|
+
const [copied, setCopied] = React8.useState(false);
|
|
3776
|
+
const timer = React8.useRef(void 0);
|
|
3777
|
+
React8.useEffect(() => () => clearTimeout(timer.current), []);
|
|
3778
|
+
const handleClick = async (event) => {
|
|
3779
|
+
onClick?.(event);
|
|
3780
|
+
if (event.defaultPrevented) return;
|
|
3781
|
+
try {
|
|
3782
|
+
await navigator.clipboard.writeText(value);
|
|
3783
|
+
setCopied(true);
|
|
3784
|
+
onCopied?.(value);
|
|
3785
|
+
clearTimeout(timer.current);
|
|
3786
|
+
timer.current = setTimeout(() => setCopied(false), timeout);
|
|
3787
|
+
} catch {
|
|
3788
|
+
}
|
|
3789
|
+
};
|
|
3790
|
+
const Icon = copied ? CheckIcon6 : CopyIcon;
|
|
3791
|
+
return /* @__PURE__ */ jsxs24(
|
|
3792
|
+
"button",
|
|
3793
|
+
{
|
|
3794
|
+
type: "button",
|
|
3795
|
+
"data-slot": "copy-button",
|
|
3796
|
+
"data-copied": copied || void 0,
|
|
3797
|
+
"aria-label": copied ? "Copied" : "Copy",
|
|
3798
|
+
onClick: handleClick,
|
|
3799
|
+
className: cn(
|
|
3800
|
+
"inline-flex items-center justify-center gap-1.5 rounded-md text-sm font-medium text-muted-foreground transition-colors",
|
|
3801
|
+
"hover:bg-accent hover:text-foreground data-[copied=true]:text-emerald-600 dark:data-[copied=true]:text-emerald-400",
|
|
3802
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
|
|
3803
|
+
children ? "h-8 px-2" : "size-8",
|
|
3804
|
+
className
|
|
3805
|
+
),
|
|
3806
|
+
...props,
|
|
3807
|
+
children: [
|
|
3808
|
+
/* @__PURE__ */ jsx48(Icon, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
3809
|
+
children
|
|
3810
|
+
]
|
|
3811
|
+
}
|
|
3812
|
+
);
|
|
3813
|
+
}
|
|
3814
|
+
|
|
3815
|
+
// src/ui/snippet.tsx
|
|
3816
|
+
import { jsx as jsx49, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
3817
|
+
function Snippet({
|
|
3818
|
+
children,
|
|
3819
|
+
symbol,
|
|
3820
|
+
hideCopy = false,
|
|
3821
|
+
className,
|
|
3822
|
+
...props
|
|
3823
|
+
}) {
|
|
3824
|
+
return /* @__PURE__ */ jsxs25(
|
|
3825
|
+
"div",
|
|
3826
|
+
{
|
|
3827
|
+
"data-slot": "snippet",
|
|
3828
|
+
className: cn(
|
|
3829
|
+
"flex items-center gap-2 rounded-lg border border-border bg-muted/40 py-1.5 pl-3 pr-1.5 font-mono text-sm",
|
|
3830
|
+
className
|
|
3831
|
+
),
|
|
3832
|
+
...props,
|
|
3833
|
+
children: [
|
|
3834
|
+
symbol ? /* @__PURE__ */ jsx49("span", { "aria-hidden": true, className: "select-none text-muted-foreground", children: symbol }) : null,
|
|
3835
|
+
/* @__PURE__ */ jsx49("code", { className: "min-w-0 flex-1 truncate text-foreground", children }),
|
|
3836
|
+
hideCopy ? null : /* @__PURE__ */ jsx49(CopyButton, { value: children, className: "size-7 shrink-0" })
|
|
3837
|
+
]
|
|
3838
|
+
}
|
|
3839
|
+
);
|
|
3840
|
+
}
|
|
3841
|
+
|
|
3842
|
+
// src/ui/circular-progress.tsx
|
|
3843
|
+
import { jsx as jsx50, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
3844
|
+
var toneClass = {
|
|
3845
|
+
primary: "text-primary",
|
|
3846
|
+
success: "text-emerald-500",
|
|
3847
|
+
warn: "text-amber-500",
|
|
3848
|
+
danger: "text-destructive"
|
|
3849
|
+
};
|
|
3850
|
+
function CircularProgress({
|
|
3851
|
+
value = 0,
|
|
3852
|
+
max = 100,
|
|
3853
|
+
size = 40,
|
|
3854
|
+
thickness = 4,
|
|
3855
|
+
showLabel = false,
|
|
3856
|
+
label,
|
|
3857
|
+
tone = "primary",
|
|
3858
|
+
className,
|
|
3859
|
+
...props
|
|
3860
|
+
}) {
|
|
3861
|
+
const indeterminate = value === null || value === void 0;
|
|
3862
|
+
const radius = (size - thickness) / 2;
|
|
3863
|
+
const circumference = 2 * Math.PI * radius;
|
|
3864
|
+
const pct = indeterminate ? 0.25 : Math.min(Math.max(value / max, 0), 1);
|
|
3865
|
+
const dashOffset = circumference * (1 - pct);
|
|
3866
|
+
return /* @__PURE__ */ jsxs26(
|
|
3867
|
+
"div",
|
|
3868
|
+
{
|
|
3869
|
+
"data-slot": "circular-progress",
|
|
3870
|
+
role: "progressbar",
|
|
3871
|
+
"aria-valuenow": indeterminate ? void 0 : Math.round(pct * 100),
|
|
3872
|
+
"aria-valuemin": 0,
|
|
3873
|
+
"aria-valuemax": 100,
|
|
3874
|
+
className: cn("relative inline-flex shrink-0", className),
|
|
3875
|
+
style: { width: size, height: size },
|
|
3876
|
+
...props,
|
|
3877
|
+
children: [
|
|
3878
|
+
/* @__PURE__ */ jsxs26(
|
|
3879
|
+
"svg",
|
|
3880
|
+
{
|
|
3881
|
+
width: size,
|
|
3882
|
+
height: size,
|
|
3883
|
+
viewBox: `0 0 ${size} ${size}`,
|
|
3884
|
+
className: cn(toneClass[tone], indeterminate && "animate-spin"),
|
|
3885
|
+
children: [
|
|
3886
|
+
/* @__PURE__ */ jsx50(
|
|
3887
|
+
"circle",
|
|
3888
|
+
{
|
|
3889
|
+
cx: size / 2,
|
|
3890
|
+
cy: size / 2,
|
|
3891
|
+
r: radius,
|
|
3892
|
+
fill: "none",
|
|
3893
|
+
strokeWidth: thickness,
|
|
3894
|
+
className: "stroke-current opacity-15"
|
|
3895
|
+
}
|
|
3896
|
+
),
|
|
3897
|
+
/* @__PURE__ */ jsx50(
|
|
3898
|
+
"circle",
|
|
3899
|
+
{
|
|
3900
|
+
cx: size / 2,
|
|
3901
|
+
cy: size / 2,
|
|
3902
|
+
r: radius,
|
|
3903
|
+
fill: "none",
|
|
3904
|
+
strokeWidth: thickness,
|
|
3905
|
+
strokeLinecap: "round",
|
|
3906
|
+
strokeDasharray: circumference,
|
|
3907
|
+
strokeDashoffset: dashOffset,
|
|
3908
|
+
transform: `rotate(-90 ${size / 2} ${size / 2})`,
|
|
3909
|
+
className: cn("stroke-current", !indeterminate && "transition-[stroke-dashoffset] duration-500")
|
|
3910
|
+
}
|
|
3911
|
+
)
|
|
3912
|
+
]
|
|
3913
|
+
}
|
|
3914
|
+
),
|
|
3915
|
+
showLabel && !indeterminate ? /* @__PURE__ */ jsx50("span", { className: "absolute inset-0 flex items-center justify-center text-[0.7rem] font-medium tabular-nums text-foreground", children: label ?? `${Math.round(pct * 100)}%` }) : null
|
|
3916
|
+
]
|
|
3917
|
+
}
|
|
3918
|
+
);
|
|
3919
|
+
}
|
|
3920
|
+
|
|
3230
3921
|
export {
|
|
3231
3922
|
DropdownMenu,
|
|
3232
3923
|
DropdownMenuTrigger,
|
|
@@ -3435,5 +4126,15 @@ export {
|
|
|
3435
4126
|
ToastDescription,
|
|
3436
4127
|
toast,
|
|
3437
4128
|
useToast,
|
|
3438
|
-
Toaster
|
|
4129
|
+
Toaster,
|
|
4130
|
+
AvatarGroup,
|
|
4131
|
+
Stepper,
|
|
4132
|
+
Timeline,
|
|
4133
|
+
Rating,
|
|
4134
|
+
NumberField,
|
|
4135
|
+
TagInput,
|
|
4136
|
+
Banner,
|
|
4137
|
+
CopyButton,
|
|
4138
|
+
Snippet,
|
|
4139
|
+
CircularProgress
|
|
3439
4140
|
};
|