@usetheo/ui 0.15.0 → 0.17.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.
@@ -0,0 +1,15 @@
1
+ import type { AnchorHTMLAttributes, HTMLAttributes } from "react";
2
+ interface BreadcrumbLinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
3
+ /** Render the consumer's element (e.g. a router <Link>) instead of a native anchor. */
4
+ asChild?: boolean;
5
+ }
6
+ declare const Breadcrumb: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>> & {
7
+ List: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLOListElement> & import("react").RefAttributes<HTMLOListElement>>;
8
+ Item: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLLIElement> & import("react").RefAttributes<HTMLLIElement>>;
9
+ Link: import("react").ForwardRefExoticComponent<BreadcrumbLinkProps & import("react").RefAttributes<HTMLAnchorElement>>;
10
+ Page: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>;
11
+ Separator: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLLIElement> & import("react").RefAttributes<HTMLLIElement>>;
12
+ Ellipsis: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>;
13
+ };
14
+ export { Breadcrumb };
15
+ export type { BreadcrumbLinkProps };
@@ -0,0 +1 @@
1
+ export { Breadcrumb, type BreadcrumbLinkProps } from "./breadcrumb.js";
@@ -0,0 +1,53 @@
1
+ import { Command as CommandPrimitive } from "cmdk";
2
+ import type { ComponentPropsWithoutRef, HTMLAttributes, ReactNode } from "react";
3
+ interface ComboboxProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
4
+ /** Selected value (controlled). */
5
+ value?: string;
6
+ onValueChange?: (value: string) => void;
7
+ /** Listbox visibility (controlled). */
8
+ open?: boolean;
9
+ defaultOpen?: boolean;
10
+ onOpenChange?: (open: boolean) => void;
11
+ /** Set false to disable cmdk's internal filter (async mode — consumer filters). */
12
+ shouldFilter?: boolean;
13
+ children: ReactNode;
14
+ }
15
+ type ComboboxInputProps = ComponentPropsWithoutRef<typeof CommandPrimitive.Input>;
16
+ interface ComboboxContentProps extends HTMLAttributes<HTMLDivElement> {
17
+ /** Async fetch in flight: shows the loading slot and hides items/empty. */
18
+ loading?: boolean;
19
+ }
20
+ type ComboboxItemProps = ComponentPropsWithoutRef<typeof CommandPrimitive.Item>;
21
+ declare const Combobox: import("react").ForwardRefExoticComponent<ComboboxProps & import("react").RefAttributes<HTMLDivElement>> & {
22
+ Input: import("react").ForwardRefExoticComponent<Omit<Omit<Pick<Pick<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "key" | keyof import("react").InputHTMLAttributes<HTMLInputElement>> & {
23
+ ref?: React.Ref<HTMLInputElement>;
24
+ } & {
25
+ asChild?: boolean;
26
+ }, "asChild" | "key" | keyof import("react").InputHTMLAttributes<HTMLInputElement>>, "type" | "value" | "onChange"> & {
27
+ value?: string;
28
+ onValueChange?: (search: string) => void;
29
+ } & import("react").RefAttributes<HTMLInputElement>, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
30
+ Content: import("react").ForwardRefExoticComponent<ComboboxContentProps & import("react").RefAttributes<HTMLDivElement>>;
31
+ Item: import("react").ForwardRefExoticComponent<Omit<{
32
+ children?: React.ReactNode;
33
+ } & Omit<Pick<Pick<import("react").DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof HTMLAttributes<HTMLDivElement>> & {
34
+ ref?: React.Ref<HTMLDivElement>;
35
+ } & {
36
+ asChild?: boolean;
37
+ }, "asChild" | "key" | keyof HTMLAttributes<HTMLDivElement>>, "disabled" | "value" | "onSelect"> & {
38
+ disabled?: boolean;
39
+ onSelect?: (value: string) => void;
40
+ value?: string;
41
+ keywords?: string[];
42
+ forceMount?: boolean;
43
+ } & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
44
+ Empty: import("react").ForwardRefExoticComponent<Omit<{
45
+ children?: React.ReactNode;
46
+ } & Pick<Pick<import("react").DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof HTMLAttributes<HTMLDivElement>> & {
47
+ ref?: React.Ref<HTMLDivElement>;
48
+ } & {
49
+ asChild?: boolean;
50
+ }, "asChild" | "key" | keyof HTMLAttributes<HTMLDivElement>> & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
51
+ };
52
+ export { Combobox };
53
+ export type { ComboboxProps, ComboboxContentProps, ComboboxInputProps, ComboboxItemProps };
@@ -0,0 +1 @@
1
+ export { Combobox, type ComboboxContentProps, type ComboboxInputProps, type ComboboxItemProps, type ComboboxProps, } from "./combobox.js";
@@ -0,0 +1 @@
1
+ export { Slider, type SliderMark, type SliderProps } from "./slider.js";
@@ -0,0 +1,24 @@
1
+ import * as SliderPrimitive from "@radix-ui/react-slider";
2
+ import type { ComponentPropsWithoutRef, ReactNode } from "react";
3
+ /**
4
+ * Slider — range input primitive over Radix Slider.
5
+ *
6
+ * Single thumb: `defaultValue={[5]}`. Range: `defaultValue={[20, 80]}` (one
7
+ * thumb per array entry). `marks` renders labelled, clickable points over the
8
+ * track (Mantine-shaped `{value, label?}`); clicking a mark sets the value in
9
+ * single mode and is a no-op in range mode (which thumb to move is ambiguous).
10
+ *
11
+ * <Slider aria-label="Top K" min={1} max={100} defaultValue={[5]}
12
+ * marks={[{ value: 1 }, { value: 50 }, { value: 100 }]} />
13
+ */
14
+ interface SliderMark {
15
+ value: number;
16
+ label?: ReactNode;
17
+ }
18
+ interface SliderProps extends ComponentPropsWithoutRef<typeof SliderPrimitive.Root> {
19
+ /** Labelled, clickable points rendered over the track. Values outside [min, max] are skipped. */
20
+ marks?: SliderMark[];
21
+ }
22
+ declare const Slider: import("react").ForwardRefExoticComponent<SliderProps & import("react").RefAttributes<HTMLSpanElement>>;
23
+ export { Slider };
24
+ export type { SliderMark, SliderProps };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  export { cn } from "./lib/cn.js";
2
2
  export { Button, buttonVariants, type ButtonProps } from "./components/primitives/button/index.js";
3
3
  export { Badge, badgeVariants, type BadgeProps } from "./components/primitives/badge/index.js";
4
+ export { Breadcrumb, type BreadcrumbLinkProps, } from "./components/primitives/breadcrumb/index.js";
5
+ export { Combobox, type ComboboxContentProps, type ComboboxInputProps, type ComboboxItemProps, type ComboboxProps, } from "./components/primitives/combobox/index.js";
6
+ export { Slider, type SliderMark, type SliderProps, } from "./components/primitives/slider/index.js";
4
7
  export { UpdateBanner, type UpdateBannerProps, } from "./components/primitives/update-banner/index.js";
5
8
  export { Card } from "./components/primitives/card/index.js";
6
9
  export { Input, type InputProps } from "./components/primitives/input/index.js";
package/dist/index.js CHANGED
@@ -2,9 +2,11 @@ import { clsx } from 'clsx';
2
2
  import { extendTailwindMerge } from 'tailwind-merge';
3
3
  import { Slot } from '@radix-ui/react-slot';
4
4
  import { cva } from 'class-variance-authority';
5
- import { forwardRef, createContext, useId, Children, isValidElement, cloneElement, Fragment as Fragment$1, useContext, useEffect, useState, useRef, useCallback, useMemo } from 'react';
5
+ import { forwardRef, createContext, useState, useRef, useId, useCallback, useEffect, useMemo, Children, isValidElement, cloneElement, Fragment as Fragment$1, useContext, createElement } from 'react';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
- import { ArrowUpCircle, X, AlertCircle, ChevronDown, ChevronUp, Check, Minus, Circle, ChevronRight, ChevronsUpDown, Copy, TrendingDown, TrendingUp, ArrowUpRight, Loader2, TriangleAlert, CheckCircle2, Info, ChevronsLeft, ChevronLeft, ChevronsRight, Search, Filter, GitCommit, GitBranch, Activity, Plus, Lock, EyeOff, Eye, Trash2, GitPullRequest, Server, ExternalLink, Globe, ShieldCheck, ShieldX, Clock, RotateCcw, ArrowDownLeft, MoreHorizontal } from 'lucide-react';
7
+ import { Loader2, Check, ArrowUpCircle, X, AlertCircle, ChevronDown, ChevronUp, Minus, Circle, ChevronRight, ChevronsUpDown, Copy, TrendingDown, TrendingUp, ArrowUpRight, TriangleAlert, CheckCircle2, Info, ChevronsLeft, ChevronLeft, ChevronsRight, Search, Filter, GitCommit, GitBranch, Activity, Plus, Lock, EyeOff, Eye, Trash2, GitPullRequest, Server, ExternalLink, Globe, ShieldCheck, ShieldX, Clock, RotateCcw, ArrowDownLeft, MoreHorizontal } from 'lucide-react';
8
+ import { Command, useCommandState } from 'cmdk';
9
+ import * as SliderPrimitive from '@radix-ui/react-slider';
8
10
  import * as DialogPrimitive from '@radix-ui/react-dialog';
9
11
  import * as TabsPrimitive from '@radix-ui/react-tabs';
10
12
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
@@ -17,7 +19,6 @@ import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
17
19
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
18
20
  import * as SwitchPrimitive from '@radix-ui/react-switch';
19
21
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
20
- import { Command } from 'cmdk';
21
22
 
22
23
  // src/lib/cn.ts
23
24
  var twMerge = extendTailwindMerge({
@@ -189,6 +190,431 @@ var Dot = forwardRef(
189
190
  Dot.displayName = "Badge.Dot";
190
191
  var BadgeWithDot = Badge;
191
192
  BadgeWithDot.Dot = Dot;
193
+
194
+ // src/lib/safe-href.ts
195
+ var DANGEROUS_PROTOCOL_PATTERNS = [
196
+ /^javascript:/i,
197
+ /^vbscript:/i,
198
+ /^data:text\/html/i
199
+ ];
200
+ function safeHref(url) {
201
+ if (url === null || url === void 0) return void 0;
202
+ const trimmed = url.trim();
203
+ if (trimmed.length === 0) return void 0;
204
+ for (const pattern of DANGEROUS_PROTOCOL_PATTERNS) {
205
+ if (pattern.test(trimmed)) return void 0;
206
+ }
207
+ return url;
208
+ }
209
+ function sub(tag, slot, displayName, baseClass, attrs, defaultChildren) {
210
+ const Component = forwardRef(
211
+ ({ className, children, ...props }, ref) => createElement(
212
+ tag,
213
+ {
214
+ "data-slot": slot,
215
+ ref,
216
+ ...attrs,
217
+ className: cn(baseClass, className),
218
+ ...props
219
+ },
220
+ children ?? defaultChildren
221
+ )
222
+ );
223
+ Component.displayName = displayName;
224
+ return Component;
225
+ }
226
+ var Root = forwardRef((props, ref) => /* @__PURE__ */ jsx("nav", { "data-slot": "breadcrumb", ref, "aria-label": "breadcrumb", ...props }));
227
+ Root.displayName = "Breadcrumb";
228
+ var List = sub(
229
+ "ol",
230
+ "breadcrumb-list",
231
+ "Breadcrumb.List",
232
+ "flex flex-wrap items-center gap-1.5 break-words text-body-sm text-muted-foreground sm:gap-2.5"
233
+ );
234
+ var Item = sub(
235
+ "li",
236
+ "breadcrumb-item",
237
+ "Breadcrumb.Item",
238
+ "inline-flex items-center gap-1.5"
239
+ );
240
+ var Link = forwardRef(
241
+ ({ asChild, className, href, ...props }, ref) => {
242
+ const Comp = asChild ? Slot : "a";
243
+ return /* @__PURE__ */ jsx(
244
+ Comp,
245
+ {
246
+ "data-slot": "breadcrumb-link",
247
+ ref,
248
+ className: cn("transition-colors hover:text-foreground", className),
249
+ href: asChild ? href : safeHref(href),
250
+ ...props
251
+ }
252
+ );
253
+ }
254
+ );
255
+ Link.displayName = "Breadcrumb.Link";
256
+ var Page = sub(
257
+ "span",
258
+ "breadcrumb-page",
259
+ "Breadcrumb.Page",
260
+ "font-normal text-foreground",
261
+ { role: "link", "aria-disabled": "true", "aria-current": "page" }
262
+ );
263
+ var Separator = sub(
264
+ "li",
265
+ "breadcrumb-separator",
266
+ "Breadcrumb.Separator",
267
+ "[&>svg]:size-3.5",
268
+ { role: "presentation", "aria-hidden": "true" },
269
+ /* @__PURE__ */ jsx(ChevronRight, {})
270
+ );
271
+ var Ellipsis = sub(
272
+ "span",
273
+ "breadcrumb-ellipsis",
274
+ "Breadcrumb.Ellipsis",
275
+ "flex size-9 items-center justify-center",
276
+ { role: "presentation", "aria-hidden": "true" },
277
+ /* @__PURE__ */ jsxs(Fragment, { children: [
278
+ /* @__PURE__ */ jsx(MoreHorizontal, { className: "size-4" }),
279
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "More" })
280
+ ] })
281
+ );
282
+ var Breadcrumb = Object.assign(Root, {
283
+ List,
284
+ Item,
285
+ Link,
286
+ Page,
287
+ Separator,
288
+ Ellipsis
289
+ });
290
+ var inputVariants = cva(
291
+ [
292
+ "flex w-full rounded-md border border-input bg-card",
293
+ "text-foreground placeholder:text-muted-foreground",
294
+ "transition-[box-shadow,border-color] duration-base ease-out-soft",
295
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
296
+ "focus-visible:border-primary",
297
+ "disabled:cursor-not-allowed disabled:opacity-50",
298
+ "file:border-0 file:bg-transparent file:font-medium file:text-body-sm"
299
+ ],
300
+ {
301
+ variants: {
302
+ size: {
303
+ sm: "h-8 px-2.5 py-1 text-body-sm",
304
+ // md: density-tunable via CSS var. Comfortable (default) = 36px.
305
+ md: "h-[var(--theo-control-h,2.25rem)] px-[var(--theo-control-px,0.875rem)] py-1.5 text-body-sm",
306
+ lg: "h-11 px-4 py-2.5 text-body-md"
307
+ }
308
+ },
309
+ defaultVariants: { size: "md" }
310
+ }
311
+ );
312
+ var Input = forwardRef(
313
+ ({ className, type = "text", size, ...props }, ref) => /* @__PURE__ */ jsx(
314
+ "input",
315
+ {
316
+ "data-slot": "input",
317
+ "data-size": size,
318
+ ref,
319
+ type,
320
+ className: cn(inputVariants({ size }), className),
321
+ ...props
322
+ }
323
+ )
324
+ );
325
+ Input.displayName = "Input";
326
+ var ComboboxContext = createContext(null);
327
+ function composeRefs(local, forwarded) {
328
+ return (node) => {
329
+ local.current = node;
330
+ if (typeof forwarded === "function") forwarded(node);
331
+ else if (forwarded) forwarded.current = node;
332
+ };
333
+ }
334
+ function useComboboxContext(sub2) {
335
+ const ctx = useContext(ComboboxContext);
336
+ if (!ctx) throw new Error(`<Combobox.${sub2}> must be used inside <Combobox>`);
337
+ return ctx;
338
+ }
339
+ var Root2 = forwardRef(
340
+ ({
341
+ className,
342
+ children,
343
+ value,
344
+ onValueChange,
345
+ open: openProp,
346
+ defaultOpen = false,
347
+ onOpenChange,
348
+ shouldFilter = true,
349
+ "aria-label": ariaLabel,
350
+ ...props
351
+ }, ref) => {
352
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
353
+ const open = openProp ?? uncontrolledOpen;
354
+ const rootRef = useRef(null);
355
+ const listId = useId();
356
+ const setOpen = useCallback(
357
+ (next) => {
358
+ setUncontrolledOpen(next);
359
+ onOpenChange?.(next);
360
+ },
361
+ [onOpenChange]
362
+ );
363
+ const select = useCallback(
364
+ (next) => {
365
+ onValueChange?.(next);
366
+ setOpen(false);
367
+ },
368
+ [onValueChange, setOpen]
369
+ );
370
+ useEffect(() => {
371
+ if (!open) return;
372
+ const onMouseDown = (event) => {
373
+ if (rootRef.current && !rootRef.current.contains(event.target)) {
374
+ setOpen(false);
375
+ }
376
+ };
377
+ document.addEventListener("mousedown", onMouseDown);
378
+ return () => document.removeEventListener("mousedown", onMouseDown);
379
+ }, [open, setOpen]);
380
+ return /* @__PURE__ */ jsx(ComboboxContext.Provider, { value: { open, setOpen, value, select, listId }, children: /* @__PURE__ */ jsx(
381
+ "div",
382
+ {
383
+ "data-slot": "combobox",
384
+ ref: composeRefs(rootRef, ref),
385
+ className: cn("relative w-full", className),
386
+ ...props,
387
+ children: /* @__PURE__ */ jsx(Command, { label: ariaLabel, shouldFilter, children })
388
+ }
389
+ ) });
390
+ }
391
+ );
392
+ Root2.displayName = "Combobox";
393
+ var Input2 = forwardRef(
394
+ ({ className, onFocus, onKeyDown, onValueChange, ...props }, ref) => {
395
+ const { open, setOpen, listId } = useComboboxContext("Input");
396
+ const innerRef = useRef(null);
397
+ useEffect(() => {
398
+ const el = innerRef.current;
399
+ if (!el) return;
400
+ el.setAttribute("aria-expanded", String(open));
401
+ if (open) el.setAttribute("aria-controls", listId);
402
+ else el.removeAttribute("aria-controls");
403
+ });
404
+ return /* @__PURE__ */ jsx(
405
+ Command.Input,
406
+ {
407
+ "data-slot": "combobox-input",
408
+ ref: composeRefs(innerRef, ref),
409
+ className: cn(inputVariants({ size: "md" }), className),
410
+ onFocus: (event) => {
411
+ setOpen(true);
412
+ onFocus?.(event);
413
+ },
414
+ onKeyDown: (event) => {
415
+ if (event.key === "Escape") setOpen(false);
416
+ onKeyDown?.(event);
417
+ },
418
+ onValueChange: (search) => {
419
+ if (!open) setOpen(true);
420
+ onValueChange?.(search);
421
+ },
422
+ ...props
423
+ }
424
+ );
425
+ }
426
+ );
427
+ Input2.displayName = "Combobox.Input";
428
+ var Content = forwardRef(
429
+ ({ className, children, loading, ...props }, ref) => {
430
+ const { open, listId } = useComboboxContext("Content");
431
+ const resultCount = useCommandState((state) => state.filtered.count);
432
+ const listRef = useRef(null);
433
+ useEffect(() => {
434
+ const el = listRef.current;
435
+ if (!el) return;
436
+ el.setAttribute("id", listId);
437
+ if (resultCount === 0) {
438
+ el.setAttribute("role", "presentation");
439
+ el.removeAttribute("aria-label");
440
+ } else {
441
+ el.setAttribute("role", "listbox");
442
+ if (!el.getAttribute("aria-label")) el.setAttribute("aria-label", "Suggestions");
443
+ }
444
+ });
445
+ if (!open) return null;
446
+ return /* @__PURE__ */ jsx(
447
+ "div",
448
+ {
449
+ "data-slot": "combobox-content",
450
+ ref,
451
+ className: cn(
452
+ "absolute top-full z-50 mt-1 w-full rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md",
453
+ className
454
+ ),
455
+ ...props,
456
+ children: loading ? /* @__PURE__ */ jsxs(
457
+ "div",
458
+ {
459
+ "data-slot": "combobox-loading",
460
+ id: listId,
461
+ "aria-busy": "true",
462
+ className: "flex items-center justify-center gap-2 px-3 py-6 text-body-sm text-muted-foreground",
463
+ children: [
464
+ /* @__PURE__ */ jsx(Loader2, { "aria-hidden": true, className: "size-4 animate-spin" }),
465
+ "Loading\u2026"
466
+ ]
467
+ }
468
+ ) : /* @__PURE__ */ jsx(Command.List, { ref: listRef, className: "max-h-64 overflow-y-auto", children })
469
+ }
470
+ );
471
+ }
472
+ );
473
+ Content.displayName = "Combobox.Content";
474
+ var Item2 = forwardRef(
475
+ ({ className, children, value, onSelect, ...props }, ref) => {
476
+ const ctx = useComboboxContext("Item");
477
+ const selected = value !== void 0 && ctx.value === value;
478
+ return /* @__PURE__ */ jsxs(
479
+ Command.Item,
480
+ {
481
+ "data-slot": "combobox-item",
482
+ "data-selected-value": selected ? "true" : void 0,
483
+ ref,
484
+ value,
485
+ onSelect: (selectedValue) => {
486
+ ctx.select(selectedValue);
487
+ onSelect?.(selectedValue);
488
+ },
489
+ className: cn(
490
+ "flex cursor-pointer items-center gap-2 rounded-md px-3 py-2 text-body-sm",
491
+ "data-[selected=true]:bg-accent/10 data-[selected=true]:text-foreground",
492
+ className
493
+ ),
494
+ ...props,
495
+ children: [
496
+ children,
497
+ /* @__PURE__ */ jsx(
498
+ Check,
499
+ {
500
+ "aria-hidden": true,
501
+ className: cn("ml-auto size-4", selected ? "opacity-100" : "opacity-0")
502
+ }
503
+ )
504
+ ]
505
+ }
506
+ );
507
+ }
508
+ );
509
+ Item2.displayName = "Combobox.Item";
510
+ var Empty = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
511
+ Command.Empty,
512
+ {
513
+ "data-slot": "combobox-empty",
514
+ ref,
515
+ className: cn("px-3 py-6 text-center text-body-sm text-muted-foreground", className),
516
+ ...props
517
+ }
518
+ ));
519
+ Empty.displayName = "Combobox.Empty";
520
+ var Combobox = Object.assign(Root2, { Input: Input2, Content, Item: Item2, Empty });
521
+ var Slider = forwardRef(
522
+ ({
523
+ className,
524
+ defaultValue,
525
+ value,
526
+ min = 0,
527
+ max = 100,
528
+ marks,
529
+ disabled,
530
+ onValueChange,
531
+ "aria-label": ariaLabel,
532
+ "aria-labelledby": ariaLabelledby,
533
+ ...props
534
+ }, ref) => {
535
+ const clamp = (entries) => entries?.map((entry) => Math.min(Math.max(entry, min), max));
536
+ const [internalValue, setInternalValue] = useState(clamp(defaultValue));
537
+ const clampedValue = clamp(value) ?? internalValue;
538
+ const thumbCount = useMemo(() => {
539
+ if (Array.isArray(value)) return value.length;
540
+ if (Array.isArray(defaultValue)) return defaultValue.length;
541
+ return 1;
542
+ }, [value, defaultValue]);
543
+ const span = max - min || 1;
544
+ const visibleMarks = (marks ?? []).filter((mark) => mark.value >= min && mark.value <= max);
545
+ const isRange = thumbCount > 1;
546
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "slider", className: cn("relative w-full", visibleMarks.length > 0 && "pb-5"), children: [
547
+ /* @__PURE__ */ jsxs(
548
+ SliderPrimitive.Root,
549
+ {
550
+ ref,
551
+ "data-slot": "slider-root",
552
+ value: clampedValue,
553
+ min,
554
+ max,
555
+ disabled,
556
+ onValueChange: (next) => {
557
+ if (value === void 0) setInternalValue(next);
558
+ onValueChange?.(next);
559
+ },
560
+ className: cn(
561
+ "relative flex w-full touch-none select-none items-center",
562
+ "data-[disabled]:opacity-50",
563
+ "data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
564
+ className
565
+ ),
566
+ ...props,
567
+ children: [
568
+ /* @__PURE__ */ jsx(
569
+ SliderPrimitive.Track,
570
+ {
571
+ "data-slot": "slider-track",
572
+ className: "relative grow overflow-hidden rounded-full bg-muted data-[orientation=horizontal]:h-1.5 data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-1.5",
573
+ children: /* @__PURE__ */ jsx(
574
+ SliderPrimitive.Range,
575
+ {
576
+ "data-slot": "slider-range",
577
+ className: "absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
578
+ }
579
+ )
580
+ }
581
+ ),
582
+ Array.from({ length: thumbCount }, (_, index) => /* @__PURE__ */ jsx(
583
+ SliderPrimitive.Thumb,
584
+ {
585
+ "aria-label": isRange && ariaLabel ? `${ariaLabel} (${index + 1} of ${thumbCount})` : ariaLabel,
586
+ "aria-labelledby": ariaLabelledby,
587
+ "data-slot": "slider-thumb",
588
+ className: "block size-4 shrink-0 rounded-full border border-primary bg-background shadow-sm transition-[box-shadow] hover:ring-4 hover:ring-ring/50 focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50"
589
+ },
590
+ index
591
+ ))
592
+ ]
593
+ }
594
+ ),
595
+ visibleMarks.map((mark) => /* @__PURE__ */ jsx(
596
+ "button",
597
+ {
598
+ type: "button",
599
+ "data-slot": "slider-mark",
600
+ disabled,
601
+ tabIndex: -1,
602
+ "aria-hidden": "true",
603
+ style: { left: `${(mark.value - min) / span * 100}%` },
604
+ className: "-translate-x-1/2 absolute top-4 cursor-pointer text-body-sm text-muted-foreground disabled:cursor-default",
605
+ onClick: () => {
606
+ if (disabled || isRange) return;
607
+ if (value === void 0) setInternalValue([mark.value]);
608
+ onValueChange?.([mark.value]);
609
+ },
610
+ children: mark.label ?? mark.value
611
+ },
612
+ mark.value
613
+ ))
614
+ ] });
615
+ }
616
+ );
617
+ Slider.displayName = "Slider";
192
618
  var UpdateBanner = forwardRef(
193
619
  ({
194
620
  currentVersion,
@@ -264,7 +690,7 @@ var UpdateBanner = forwardRef(
264
690
  UpdateBanner.displayName = "UpdateBanner";
265
691
  var CardContext = createContext({ size: "md" });
266
692
  var useCardSize = () => useContext(CardContext).size;
267
- var Root = forwardRef(
693
+ var Root4 = forwardRef(
268
694
  ({ className, size = "md", ...props }, ref) => /* @__PURE__ */ jsx(CardContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx(
269
695
  "div",
270
696
  {
@@ -279,7 +705,7 @@ var Root = forwardRef(
279
705
  }
280
706
  ) })
281
707
  );
282
- Root.displayName = "Card";
708
+ Root4.displayName = "Card";
283
709
  var headerPadBySize = {
284
710
  sm: "gap-1 p-3 pb-1.5",
285
711
  md: "gap-1.5 p-5 pb-2.5",
@@ -381,49 +807,13 @@ var Footer = forwardRef(
381
807
  }
382
808
  );
383
809
  Footer.displayName = "Card.Footer";
384
- var Card = /* @__PURE__ */ Object.assign(Root, {
810
+ var Card = /* @__PURE__ */ Object.assign(Root4, {
385
811
  Header,
386
812
  Title,
387
813
  Description,
388
814
  Body,
389
815
  Footer
390
816
  });
391
- var inputVariants = cva(
392
- [
393
- "flex w-full rounded-md border border-input bg-card",
394
- "text-foreground placeholder:text-muted-foreground",
395
- "transition-[box-shadow,border-color] duration-base ease-out-soft",
396
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
397
- "focus-visible:border-primary",
398
- "disabled:cursor-not-allowed disabled:opacity-50",
399
- "file:border-0 file:bg-transparent file:font-medium file:text-body-sm"
400
- ],
401
- {
402
- variants: {
403
- size: {
404
- sm: "h-8 px-2.5 py-1 text-body-sm",
405
- // md: density-tunable via CSS var. Comfortable (default) = 36px.
406
- md: "h-[var(--theo-control-h,2.25rem)] px-[var(--theo-control-px,0.875rem)] py-1.5 text-body-sm",
407
- lg: "h-11 px-4 py-2.5 text-body-md"
408
- }
409
- },
410
- defaultVariants: { size: "md" }
411
- }
412
- );
413
- var Input = forwardRef(
414
- ({ className, type = "text", size, ...props }, ref) => /* @__PURE__ */ jsx(
415
- "input",
416
- {
417
- "data-slot": "input",
418
- "data-size": size,
419
- ref,
420
- type,
421
- className: cn(inputVariants({ size }), className),
422
- ...props
423
- }
424
- )
425
- );
426
- Input.displayName = "Input";
427
817
  var Overlay2 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
428
818
  DialogPrimitive.Overlay,
429
819
  {
@@ -439,7 +829,7 @@ var Overlay2 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
439
829
  }
440
830
  ));
441
831
  Overlay2.displayName = "Dialog.Overlay";
442
- var Content2 = forwardRef(
832
+ var Content3 = forwardRef(
443
833
  ({ className, children, hideCloseButton, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
444
834
  /* @__PURE__ */ jsx(Overlay2, {}),
445
835
  /* @__PURE__ */ jsxs(
@@ -478,7 +868,7 @@ var Content2 = forwardRef(
478
868
  )
479
869
  ] })
480
870
  );
481
- Content2.displayName = "Dialog.Content";
871
+ Content3.displayName = "Dialog.Content";
482
872
  var Header2 = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-1.5 p-6 pb-3 text-left", className), ...props });
483
873
  Header2.displayName = "Dialog.Header";
484
874
  var Body2 = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("px-6 pb-6 text-body-md text-muted-foreground", className), ...props });
@@ -516,7 +906,7 @@ Description3.displayName = "Dialog.Description";
516
906
  var Dialog = /* @__PURE__ */ Object.assign(DialogPrimitive.Root, {
517
907
  Trigger: DialogPrimitive.Trigger,
518
908
  Close: DialogPrimitive.Close,
519
- Content: Content2,
909
+ Content: Content3,
520
910
  Overlay: Overlay2,
521
911
  Header: Header2,
522
912
  Body: Body2,
@@ -524,7 +914,7 @@ var Dialog = /* @__PURE__ */ Object.assign(DialogPrimitive.Root, {
524
914
  Title: Title3,
525
915
  Description: Description3
526
916
  });
527
- var List2 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
917
+ var List3 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
528
918
  TabsPrimitive.List,
529
919
  {
530
920
  "data-slot": "tabs-list",
@@ -536,7 +926,7 @@ var List2 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
536
926
  ...props
537
927
  }
538
928
  ));
539
- List2.displayName = "Tabs.List";
929
+ List3.displayName = "Tabs.List";
540
930
  var Trigger3 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
541
931
  TabsPrimitive.Trigger,
542
932
  {
@@ -558,7 +948,7 @@ var Trigger3 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
558
948
  }
559
949
  ));
560
950
  Trigger3.displayName = "Tabs.Trigger";
561
- var Content4 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
951
+ var Content5 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
562
952
  TabsPrimitive.Content,
563
953
  {
564
954
  "data-slot": "tabs-content",
@@ -570,16 +960,16 @@ var Content4 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
570
960
  ...props
571
961
  }
572
962
  ));
573
- Content4.displayName = "Tabs.Content";
963
+ Content5.displayName = "Tabs.Content";
574
964
  var Tabs = /* @__PURE__ */ Object.assign(TabsPrimitive.Root, {
575
- List: List2,
965
+ List: List3,
576
966
  Trigger: Trigger3,
577
- Content: Content4
967
+ Content: Content5
578
968
  });
579
969
  var Provider2 = TooltipPrimitive.Provider;
580
- var Root5 = TooltipPrimitive.Root;
970
+ var Root8 = TooltipPrimitive.Root;
581
971
  var Trigger5 = TooltipPrimitive.Trigger;
582
- var Content6 = forwardRef(({ className, sideOffset = 6, ...props }, ref) => /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(
972
+ var Content7 = forwardRef(({ className, sideOffset = 6, ...props }, ref) => /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(
583
973
  TooltipPrimitive.Content,
584
974
  {
585
975
  "data-slot": "tooltip-content",
@@ -597,7 +987,7 @@ var Content6 = forwardRef(({ className, sideOffset = 6, ...props }, ref) => /* @
597
987
  ...props
598
988
  }
599
989
  ) }));
600
- Content6.displayName = "Tooltip.Content";
990
+ Content7.displayName = "Tooltip.Content";
601
991
  var Tooltip = ({
602
992
  label,
603
993
  side = "top",
@@ -605,15 +995,15 @@ var Tooltip = ({
605
995
  delayDuration = 200,
606
996
  children,
607
997
  ...rootProps
608
- }) => /* @__PURE__ */ jsx(Provider2, { delayDuration, children: /* @__PURE__ */ jsxs(Root5, { ...rootProps, children: [
998
+ }) => /* @__PURE__ */ jsx(Provider2, { delayDuration, children: /* @__PURE__ */ jsxs(Root8, { ...rootProps, children: [
609
999
  /* @__PURE__ */ jsx(Trigger5, { asChild: true, children }),
610
- /* @__PURE__ */ jsx(Content6, { side, align, children: label })
1000
+ /* @__PURE__ */ jsx(Content7, { side, align, children: label })
611
1001
  ] }) });
612
1002
  var TooltipWithStatics = Tooltip;
613
1003
  TooltipWithStatics.Provider = Provider2;
614
- TooltipWithStatics.Root = Root5;
1004
+ TooltipWithStatics.Root = Root8;
615
1005
  TooltipWithStatics.Trigger = Trigger5;
616
- TooltipWithStatics.Content = Content6;
1006
+ TooltipWithStatics.Content = Content7;
617
1007
  var ScrollAreaRoot = forwardRef(
618
1008
  ({ className, children, orientation = "vertical", size = "thin", type = "hover", ...props }, ref) => /* @__PURE__ */ jsxs(
619
1009
  ScrollAreaPrimitive.Root,
@@ -1463,7 +1853,7 @@ var Textarea = forwardRef(
1463
1853
  )
1464
1854
  );
1465
1855
  Textarea.displayName = "Textarea";
1466
- var Root15 = forwardRef(
1856
+ var Root18 = forwardRef(
1467
1857
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1468
1858
  "aside",
1469
1859
  {
@@ -1477,7 +1867,7 @@ var Root15 = forwardRef(
1477
1867
  }
1478
1868
  )
1479
1869
  );
1480
- Root15.displayName = "Sidebar";
1870
+ Root18.displayName = "Sidebar";
1481
1871
  var Header3 = forwardRef(
1482
1872
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1483
1873
  "div",
@@ -1506,7 +1896,7 @@ var Section = forwardRef(
1506
1896
  )
1507
1897
  );
1508
1898
  Section.displayName = "Sidebar.Section";
1509
- var Item3 = forwardRef(
1899
+ var Item5 = forwardRef(
1510
1900
  ({ className, icon: Icon2, active, count, as = "button", href, children, ...props }, ref) => {
1511
1901
  const classes = cn(
1512
1902
  "group flex w-full items-center gap-3 rounded-lg px-2 py-2",
@@ -1566,7 +1956,7 @@ var Item3 = forwardRef(
1566
1956
  );
1567
1957
  }
1568
1958
  );
1569
- Item3.displayName = "Sidebar.Item";
1959
+ Item5.displayName = "Sidebar.Item";
1570
1960
  var Footer3 = forwardRef(
1571
1961
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1572
1962
  "div",
@@ -1579,13 +1969,13 @@ var Footer3 = forwardRef(
1579
1969
  )
1580
1970
  );
1581
1971
  Footer3.displayName = "Sidebar.Footer";
1582
- var Sidebar = /* @__PURE__ */ Object.assign(Root15, {
1972
+ var Sidebar = /* @__PURE__ */ Object.assign(Root18, {
1583
1973
  Header: Header3,
1584
1974
  Section,
1585
- Item: Item3,
1975
+ Item: Item5,
1586
1976
  Footer: Footer3
1587
1977
  });
1588
- var Root16 = forwardRef(
1978
+ var Root19 = forwardRef(
1589
1979
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1590
1980
  "header",
1591
1981
  {
@@ -1599,7 +1989,7 @@ var Root16 = forwardRef(
1599
1989
  }
1600
1990
  )
1601
1991
  );
1602
- Root16.displayName = "TopNav";
1992
+ Root19.displayName = "TopNav";
1603
1993
  var Left = forwardRef(
1604
1994
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1605
1995
  "div",
@@ -1734,7 +2124,7 @@ var ModeSwitcher = forwardRef(
1734
2124
  }
1735
2125
  );
1736
2126
  ModeSwitcher.displayName = "TopNav.ModeSwitcher";
1737
- var TopNav = /* @__PURE__ */ Object.assign(Root16, {
2127
+ var TopNav = /* @__PURE__ */ Object.assign(Root19, {
1738
2128
  Left,
1739
2129
  Center,
1740
2130
  Right,
@@ -1774,7 +2164,7 @@ var sheetVariants = cva(
1774
2164
  defaultVariants: { side: "right" }
1775
2165
  }
1776
2166
  );
1777
- var Content9 = forwardRef(
2167
+ var Content10 = forwardRef(
1778
2168
  ({ className, children, hideCloseButton, side = "right", ...props }, ref) => /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
1779
2169
  /* @__PURE__ */ jsx(Overlay4, {}),
1780
2170
  /* @__PURE__ */ jsxs(
@@ -1806,7 +2196,7 @@ var Content9 = forwardRef(
1806
2196
  )
1807
2197
  ] })
1808
2198
  );
1809
- Content9.displayName = "Sheet.Content";
2199
+ Content10.displayName = "Sheet.Content";
1810
2200
  var Header4 = ({ className, ...props }) => /* @__PURE__ */ jsx(
1811
2201
  "div",
1812
2202
  {
@@ -1851,7 +2241,7 @@ Description6.displayName = "Sheet.Description";
1851
2241
  var Sheet = DialogPrimitive.Root;
1852
2242
  Sheet.Trigger = DialogPrimitive.Trigger;
1853
2243
  Sheet.Close = DialogPrimitive.Close;
1854
- Sheet.Content = Content9;
2244
+ Sheet.Content = Content10;
1855
2245
  Sheet.Overlay = Overlay4;
1856
2246
  Sheet.Header = Header4;
1857
2247
  Sheet.Body = Body3;
@@ -2030,7 +2420,7 @@ var alignClass = {
2030
2420
  center: "text-center",
2031
2421
  right: "text-right"
2032
2422
  };
2033
- var Root18 = forwardRef(
2423
+ var Root21 = forwardRef(
2034
2424
  ({ className, density = "default", children, ...props }, ref) => /* @__PURE__ */ jsx(TableDensityContext.Provider, { value: density, children: /* @__PURE__ */ jsx(
2035
2425
  "table",
2036
2426
  {
@@ -2042,7 +2432,7 @@ var Root18 = forwardRef(
2042
2432
  }
2043
2433
  ) })
2044
2434
  );
2045
- Root18.displayName = "Table";
2435
+ Root21.displayName = "Table";
2046
2436
  var Header5 = forwardRef(
2047
2437
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2048
2438
  "thead",
@@ -2162,7 +2552,7 @@ var HeaderCell = forwardRef(
2162
2552
  }
2163
2553
  );
2164
2554
  HeaderCell.displayName = "Table.HeaderCell";
2165
- var Table = Object.assign(Root18, { Header: Header5, Body: Body4, Row, Cell, HeaderCell });
2555
+ var Table = Object.assign(Root21, { Header: Header5, Body: Body4, Row, Cell, HeaderCell });
2166
2556
 
2167
2557
  // src/lib/env.ts
2168
2558
  function readNodeEnv() {
@@ -2539,7 +2929,7 @@ var StatTile = forwardRef(
2539
2929
  }
2540
2930
  );
2541
2931
  StatTile.displayName = "StatTile";
2542
- var Root19 = forwardRef(
2932
+ var Root22 = forwardRef(
2543
2933
  ({ className, title = "Danger Zone", children, ...props }, ref) => /* @__PURE__ */ jsxs(
2544
2934
  "section",
2545
2935
  {
@@ -2555,7 +2945,7 @@ var Root19 = forwardRef(
2555
2945
  }
2556
2946
  )
2557
2947
  );
2558
- Root19.displayName = "DangerZone";
2948
+ Root22.displayName = "DangerZone";
2559
2949
  var Action2 = forwardRef(
2560
2950
  ({ className, title, description, action, ...props }, ref) => /* @__PURE__ */ jsxs(
2561
2951
  "div",
@@ -2578,7 +2968,7 @@ var Action2 = forwardRef(
2578
2968
  )
2579
2969
  );
2580
2970
  Action2.displayName = "DangerZone.Action";
2581
- var DangerZone = Object.assign(Root19, { Action: Action2 });
2971
+ var DangerZone = Object.assign(Root22, { Action: Action2 });
2582
2972
  var ConfirmDialog = forwardRef(
2583
2973
  ({
2584
2974
  open,
@@ -3090,7 +3480,7 @@ var Portal6 = DropdownMenuPrimitive.Portal;
3090
3480
  var Group3 = DropdownMenuPrimitive.Group;
3091
3481
  var Sub2 = DropdownMenuPrimitive.Sub;
3092
3482
  var RadioGroup3 = DropdownMenuPrimitive.RadioGroup;
3093
- var Content11 = forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
3483
+ var Content12 = forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
3094
3484
  DropdownMenuPrimitive.Content,
3095
3485
  {
3096
3486
  "data-slot": "dropdown-menu-content",
@@ -3106,8 +3496,8 @@ var Content11 = forwardRef(({ className, sideOffset = 4, ...props }, ref) => /*
3106
3496
  ...props
3107
3497
  }
3108
3498
  ) }));
3109
- Content11.displayName = "DropdownMenu.Content";
3110
- var Item5 = forwardRef(
3499
+ Content12.displayName = "DropdownMenu.Content";
3500
+ var Item7 = forwardRef(
3111
3501
  ({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
3112
3502
  DropdownMenuPrimitive.Item,
3113
3503
  {
@@ -3126,7 +3516,7 @@ var Item5 = forwardRef(
3126
3516
  }
3127
3517
  )
3128
3518
  );
3129
- Item5.displayName = "DropdownMenu.Item";
3519
+ Item7.displayName = "DropdownMenu.Item";
3130
3520
  var CheckboxItem2 = forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(
3131
3521
  DropdownMenuPrimitive.CheckboxItem,
3132
3522
  {
@@ -3184,7 +3574,7 @@ var Label4 = forwardRef(
3184
3574
  )
3185
3575
  );
3186
3576
  Label4.displayName = "DropdownMenu.Label";
3187
- var Separator3 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3577
+ var Separator4 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3188
3578
  DropdownMenuPrimitive.Separator,
3189
3579
  {
3190
3580
  "data-slot": "dropdown-menu-separator",
@@ -3193,7 +3583,7 @@ var Separator3 = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ js
3193
3583
  ...props
3194
3584
  }
3195
3585
  ));
3196
- Separator3.displayName = "DropdownMenu.Separator";
3586
+ Separator4.displayName = "DropdownMenu.Separator";
3197
3587
  var Shortcut = ({ className, ...props }) => /* @__PURE__ */ jsx(
3198
3588
  "span",
3199
3589
  {
@@ -3241,12 +3631,12 @@ SubContent2.displayName = "DropdownMenu.SubContent";
3241
3631
  var DropdownMenu = Object.assign(DropdownMenuPrimitive.Root, {
3242
3632
  Trigger: Trigger9,
3243
3633
  Portal: Portal6,
3244
- Content: Content11,
3245
- Item: Item5,
3634
+ Content: Content12,
3635
+ Item: Item7,
3246
3636
  CheckboxItem: CheckboxItem2,
3247
3637
  RadioItem: RadioItem2,
3248
3638
  Label: Label4,
3249
- Separator: Separator3,
3639
+ Separator: Separator4,
3250
3640
  Shortcut,
3251
3641
  Group: Group3,
3252
3642
  Sub: Sub2,
@@ -4067,22 +4457,6 @@ var DeploymentRow = forwardRef(
4067
4457
  }
4068
4458
  );
4069
4459
  DeploymentRow.displayName = "DeploymentRow";
4070
-
4071
- // src/lib/safe-href.ts
4072
- var DANGEROUS_PROTOCOL_PATTERNS = [
4073
- /^javascript:/i,
4074
- /^vbscript:/i,
4075
- /^data:text\/html/i
4076
- ];
4077
- function safeHref(url) {
4078
- if (url === null || url === void 0) return void 0;
4079
- const trimmed = url.trim();
4080
- if (trimmed.length === 0) return void 0;
4081
- for (const pattern of DANGEROUS_PROTOCOL_PATTERNS) {
4082
- if (pattern.test(trimmed)) return void 0;
4083
- }
4084
- return url;
4085
- }
4086
4460
  var statusToVariant2 = {
4087
4461
  queued: "warning",
4088
4462
  building: "primary",
@@ -4707,4 +5081,4 @@ function CommandPalette({
4707
5081
  ] }) });
4708
5082
  }
4709
5083
 
4710
- export { AccountMenu, ActionBar, Alert, Avatar, BadgeWithDot as Badge, Button, Card, Checkbox, CodeBlock, CommandPalette, ConfirmDialog, CopyButton, DangerZone, DataTable, DeploymentRow, Dialog, DomainConfig, DropdownMenu, EmptyState, EnvVarEditor, FormField, Input, Label, LoginSplit, MetricCard, MetricsPanel, PageShell, Pagination, PinInput, PlanBadge, PreviewEnvCard, Progress, ProjectCard, RadioGroup, RollbackUI, ScrollArea, Select, Sheet, Sidebar, Skeleton, SocialAuthRow, StatTile, StatusDot, StatusIndicator, Switch, Table, Tabs, TaskHeader, Textarea, Timestamp, Toast, Toaster, TooltipWithStatics as Tooltip, TopNav, UpdateBanner, avatarVariants, badgeVariants, buttonVariants, cn, computePageRange, isNearBottom, sheetVariants, useStickToBottom, useToast };
5084
+ export { AccountMenu, ActionBar, Alert, Avatar, BadgeWithDot as Badge, Breadcrumb, Button, Card, Checkbox, CodeBlock, Combobox, CommandPalette, ConfirmDialog, CopyButton, DangerZone, DataTable, DeploymentRow, Dialog, DomainConfig, DropdownMenu, EmptyState, EnvVarEditor, FormField, Input, Label, LoginSplit, MetricCard, MetricsPanel, PageShell, Pagination, PinInput, PlanBadge, PreviewEnvCard, Progress, ProjectCard, RadioGroup, RollbackUI, ScrollArea, Select, Sheet, Sidebar, Skeleton, Slider, SocialAuthRow, StatTile, StatusDot, StatusIndicator, Switch, Table, Tabs, TaskHeader, Textarea, Timestamp, Toast, Toaster, TooltipWithStatics as Tooltip, TopNav, UpdateBanner, avatarVariants, badgeVariants, buttonVariants, cn, computePageRange, isNearBottom, sheetVariants, useStickToBottom, useToast };
package/package.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "@usetheo/ui",
3
- "version": "0.15.0",
4
- "packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be",
3
+ "version": "0.17.0",
5
4
  "type": "module",
6
5
  "license": "Apache-2.0",
7
6
  "description": "Violet Forge design system — generic React components + primitives (the non-AI foundation of @theokit/ui).",
@@ -22,18 +21,6 @@
22
21
  "engines": {
23
22
  "node": ">=20"
24
23
  },
25
- "scripts": {
26
- "typecheck": "tsc --noEmit",
27
- "lint": "biome check src",
28
- "lint:ci": "biome check src",
29
- "format:check": "biome format src",
30
- "test": "vitest run",
31
- "test:run": "vitest run",
32
- "build": "tsup && tsc -p tsconfig.dts.json",
33
- "prepublishOnly": "npm run build",
34
- "registry:build": "tsx scripts/build-registry.ts",
35
- "registry:validate": "tsx scripts/validate-registry.ts"
36
- },
37
24
  "peerDependencies": {
38
25
  "react": ">=18",
39
26
  "react-dom": ">=18"
@@ -47,6 +34,7 @@
47
34
  "@radix-ui/react-radio-group": "^1.3.8",
48
35
  "@radix-ui/react-scroll-area": "^1.2.10",
49
36
  "@radix-ui/react-select": "^2.2.6",
37
+ "@radix-ui/react-slider": "^1.4.3",
50
38
  "@radix-ui/react-slot": "^1.1.2",
51
39
  "@radix-ui/react-switch": "^1.2.6",
52
40
  "@radix-ui/react-tabs": "^1.1.3",
@@ -72,6 +60,7 @@
72
60
  "react": ">=18.2.0 <20",
73
61
  "react-dom": ">=18.2.0 <20",
74
62
  "tailwindcss": "^4.0.0",
63
+ "ts-prune": "^0.10.3",
75
64
  "tsup": "^8.3.5",
76
65
  "tsx": "^4.19.2",
77
66
  "typescript": "^5.7.3",
@@ -79,5 +68,16 @@
79
68
  "vitest": "^4.1.8",
80
69
  "vitest-axe": "^0.1.0"
81
70
  },
82
- "_provenance": "seeded from theo-ui @ 2b46eca (2026-07-03, pivot M-B)"
83
- }
71
+ "_provenance": "seeded from theo-ui @ 2b46eca (2026-07-03, pivot M-B)",
72
+ "scripts": {
73
+ "typecheck": "tsc --noEmit",
74
+ "lint": "biome check src",
75
+ "lint:ci": "biome check src",
76
+ "format:check": "biome format src",
77
+ "test": "vitest run",
78
+ "test:run": "vitest run",
79
+ "build": "tsup && tsc -p tsconfig.dts.json",
80
+ "registry:build": "tsx scripts/build-registry.ts",
81
+ "registry:validate": "tsx scripts/validate-registry.ts"
82
+ }
83
+ }