florixui 1.0.0 → 1.1.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/README.md CHANGED
@@ -349,6 +349,32 @@ A bordered surface that groups related content and actions into a single contain
349
349
  </Card>
350
350
  ```
351
351
 
352
+ ### Card Radio Group
353
+
354
+ A radio group whose options are bordered cards — each with an optional icon, a label (plus inline sublabel), and a description. The whole card is clickable and the selected card highlights its border.
355
+
356
+ ```tsx
357
+ <CardRadioGroup
358
+ defaultValue="mastercard"
359
+ items={[
360
+ {
361
+ value: 'mastercard',
362
+ label: 'Mastercard',
363
+ sublabel: '(•••• 4242)',
364
+ description: 'You can use this card with a label and a description.',
365
+ icon: <MastercardIcon />,
366
+ },
367
+ {
368
+ value: 'visa',
369
+ label: 'Visa',
370
+ sublabel: '(•••• 1881)',
371
+ description: 'You can use this card with a label and a description.',
372
+ icon: <VisaIcon />,
373
+ },
374
+ ]}
375
+ />
376
+ ```
377
+
352
378
  ### Chart
353
379
 
354
380
  A theming and tooltip/legend wrapper around Recharts that maps a config object to CSS color variables for consistent, accessible charts.
@@ -412,6 +438,21 @@ A fast, composable command menu with fuzzy search for navigating actions, built
412
438
  </Command>
413
439
  ```
414
440
 
441
+ ### Custom Tabs
442
+
443
+ A higher-level tab strip with two looks — underline and pill — driven by a single items array. Each tab can carry an icon, a numeric count, and a short badge like "New". Built on Radix Tabs for keyboard and a11y support.
444
+
445
+ ```tsx
446
+ const navItems = [
447
+ { value: 'overview', label: 'Overview', icon: <HomeIcon /> },
448
+ { value: 'projects', label: 'Projects', icon: <LayoutPanelTopIcon />, count: 3 },
449
+ { value: 'packages', label: 'Packages', icon: <PackageIcon />, badge: 'New' },
450
+ { value: 'team', label: 'Team', icon: <UsersIcon /> },
451
+ ]
452
+
453
+ <CustomTabs type="underline" defaultValue="overview" items={navItems} />
454
+ ```
455
+
415
456
  ### Data Table
416
457
 
417
458
  A simple, column-driven table with the shadcn data-table look: badge cells, row selection, a row-actions menu, and empty/loading states — no sorting/pagination machinery.
@@ -513,6 +554,30 @@ Displays a menu of actions or options triggered by a button, built on Radix UI w
513
554
  </DropdownMenu>
514
555
  ```
515
556
 
557
+ ### Faceted Filter
558
+
559
+ A controlled filter trigger and popover: a searchable list of options selectable as multi-select checkboxes (default) or single-select. Shows the selection as pills and emits the value(s) via onChange so you can filter your own list or API query.
560
+
561
+ ```tsx
562
+ const [status, setStatus] = useState<string[]>(['backlog', 'todo'])
563
+
564
+ <FacetedFilter
565
+ title="Status"
566
+ options={[
567
+ { value: 'backlog', label: 'Backlog', icon: <CircleDashedIcon />, count: 13 },
568
+ { value: 'todo', label: 'Todo', icon: <CircleIcon />, count: 12 },
569
+ // ...
570
+ ]}
571
+ value={status}
572
+ onChange={setStatus}
573
+ />
574
+
575
+ // then filter your data:
576
+ const filtered = status.length === 0
577
+ ? tasks
578
+ : tasks.filter((t) => status.includes(t.status))
579
+ ```
580
+
516
581
  ### Field
517
582
 
518
583
  Layout primitives that pair a form control with its label, description, and error message in a consistent, accessible structure.
@@ -527,6 +592,56 @@ Layout primitives that pair a form control with its label, description, and erro
527
592
  </Field>
528
593
  ```
529
594
 
595
+ ### File Upload
596
+
597
+ A batteries-included drag-and-drop uploader with validation, previews, and two layouts: a single-image dropzone and a multi-file card grid. Backed by the headless useFileUpload hook.
598
+
599
+ ```tsx
600
+ <FileUpload
601
+ variant="image"
602
+ accept="image/*"
603
+ maxSize={5 * 1024 * 1024}
604
+ />
605
+ ```
606
+
607
+ ### Form Dialog
608
+
609
+ A pre-composed modal for forms: a fixed bordered header (title, description, close button), a scrollable body, and an optional pinned footer for actions. Controlled via open/onClose.
610
+
611
+ ```tsx
612
+ function Example() {
613
+ const [open, setOpen] = useState(false)
614
+ return (
615
+ <>
616
+ <Button onClick={() => setOpen(true)}>Edit profile</Button>
617
+ <FormDialog
618
+ open={open}
619
+ onClose={() => setOpen(false)}
620
+ title="Edit profile"
621
+ description="Update your details. Changes are saved when you submit."
622
+ footer={
623
+ <>
624
+ <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
625
+ <Button onClick={() => setOpen(false)}>Save changes</Button>
626
+ </>
627
+ }
628
+ >
629
+ <form className="grid gap-4">
630
+ <div className="grid gap-2">
631
+ <Label htmlFor="name">Name</Label>
632
+ <Input id="name" defaultValue="Ada Lovelace" />
633
+ </div>
634
+ <div className="grid gap-2">
635
+ <Label htmlFor="bio">Bio</Label>
636
+ <Textarea id="bio" rows={4} />
637
+ </div>
638
+ </form>
639
+ </FormDialog>
640
+ </>
641
+ )
642
+ }
643
+ ```
644
+
530
645
  ### Hover Card
531
646
 
532
647
  Shows rich preview content in a floating card when the user hovers over or focuses a trigger.
@@ -676,6 +791,22 @@ Displays a list of options for the user to pick from, triggered by a button.
676
791
  </Select>
677
792
  ```
678
793
 
794
+ ### Sensor Card
795
+
796
+ A compact info/action card with a left side (icon, mode label, description) and a right side (accent bar + value). Tint it with colorVariant, wrap it with variant, and wire onClick / onValueClick for actions.
797
+
798
+ ```tsx
799
+ <SensorCard
800
+ variant="standalone"
801
+ icon={<BlindsIcon className="size-5 text-primary" />}
802
+ mode="Shades & Curtains"
803
+ description="shade 01"
804
+ value="Active"
805
+ showAccent
806
+ valueColorVariant="primary"
807
+ />
808
+ ```
809
+
679
810
  ### Separator
680
811
 
681
812
  Visually or semantically divides content, either horizontally or vertically.
@@ -721,6 +852,44 @@ A panel that slides in from an edge of the screen to show supplementary content
721
852
  </Sheet>
722
853
  ```
723
854
 
855
+ ### Side Sheet
856
+
857
+ A slide-in panel with a pinned header and a sticky footer — the header and footer stay fixed while the body scrolls between them. Ideal for long configuration forms. Controlled via open/onClose.
858
+
859
+ ```tsx
860
+ function Example() {
861
+ const [open, setOpen] = useState(false)
862
+ return (
863
+ <>
864
+ <Button onClick={() => setOpen(true)}>Open configuration</Button>
865
+ <SideSheet
866
+ open={open}
867
+ onClose={() => setOpen(false)}
868
+ onBack={() => setOpen(false)}
869
+ floating
870
+ title="PID Equation Program Configuration"
871
+ footer={
872
+ <>
873
+ <Button onClick={() => setOpen(false)}>Save</Button>
874
+ <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
875
+ </>
876
+ }
877
+ >
878
+ <AdvancedInput label="Program name" placeholder="Enter program name" required />
879
+ <AdvancedSelect label="PID Equation Type" required options={EQUATION_TYPES} />
880
+
881
+ <SideSheetSection label="Reading VS Target Settings">
882
+ <div className="grid grid-cols-2 gap-4">
883
+ <AdvancedSelect label="Reading Source" options={SOURCES} />
884
+ <AdvancedSelect label="Target Source" options={SOURCES} />
885
+ </div>
886
+ </SideSheetSection>
887
+ </SideSheet>
888
+ </>
889
+ )
890
+ }
891
+ ```
892
+
724
893
  ### Slider
725
894
 
726
895
  Lets users select a value or range from a continuous track by dragging one or more thumbs.
@@ -757,6 +926,20 @@ An animated loading indicator that communicates that content or an action is in
757
926
  <Spinner />
758
927
  ```
759
928
 
929
+ ### Stat Card
930
+
931
+ A dashboard metric card with a title, a bold value, and an optional accessory — a tinted icon, a colored trend delta, a linear progress bar, a sparkline area chart, or a radial ring.
932
+
933
+ ```tsx
934
+ <StatCard
935
+ title="Total Revenue"
936
+ value="$45,231"
937
+ description="+20.1% from last month"
938
+ icon={<DollarSignIcon />}
939
+ color="danger"
940
+ />
941
+ ```
942
+
760
943
  ### Stepper
761
944
 
762
945
  A composable stepper (from Origin UI) for multi-step flows — horizontal or vertical, with numbered indicators, titles, descriptions, and an active/completed state.
@@ -0,0 +1,32 @@
1
+ import { RadioGroup } from '../ui/radio-group';
2
+ import * as React from "react";
3
+ export interface CardRadioItem {
4
+ /** Unique value submitted when this card is selected. */
5
+ value: string;
6
+ /** Primary label. */
7
+ label: React.ReactNode;
8
+ /** Muted text shown inline after the label, e.g. "(Sublabel)". */
9
+ sublabel?: React.ReactNode;
10
+ /** Supporting text shown beneath the label. */
11
+ description?: React.ReactNode;
12
+ /** Optional leading media — an icon, logo, or small illustration. */
13
+ icon?: React.ReactNode;
14
+ /** Disables this individual card. */
15
+ disabled?: boolean;
16
+ }
17
+ export interface CardRadioGroupProps extends Omit<React.ComponentProps<typeof RadioGroup>, "children"> {
18
+ /** The cards to render. */
19
+ items: CardRadioItem[];
20
+ /** Place the radio dot on the leading edge instead of the trailing edge. */
21
+ indicatorPosition?: "start" | "end";
22
+ /** Class for each card. */
23
+ cardClassName?: string;
24
+ }
25
+ /**
26
+ * A radio group whose options are bordered cards, each with an optional icon,
27
+ * a label (+ inline sublabel), and a description. The selected card highlights
28
+ * its border. The whole card is clickable. Control selection with
29
+ * `value`/`onValueChange` or `defaultValue`, like the base RadioGroup.
30
+ */
31
+ declare function CardRadioGroup({ items, indicatorPosition, className, cardClassName, ...props }: CardRadioGroupProps): import("react/jsx-runtime").JSX.Element;
32
+ export { CardRadioGroup };
@@ -0,0 +1,34 @@
1
+ import { Tabs as TabsPrimitive } from 'radix-ui';
2
+ import * as React from "react";
3
+ export type CustomTabsType = "underline" | "pill";
4
+ export interface CustomTabItem {
5
+ /** Unique value for the tab; also used as the trigger's `value`. */
6
+ value: string;
7
+ /** Visible label. */
8
+ label: React.ReactNode;
9
+ /** Optional leading icon. */
10
+ icon?: React.ReactNode;
11
+ /** Optional numeric count rendered as a muted pill after the label. */
12
+ count?: number;
13
+ /** Optional short badge rendered after the label, e.g. "New". */
14
+ badge?: React.ReactNode;
15
+ /** Disables this individual tab. */
16
+ disabled?: boolean;
17
+ }
18
+ export interface CustomTabsProps extends Omit<React.ComponentProps<typeof TabsPrimitive.Root>, "orientation" | "children"> {
19
+ /** Visual style of the tab strip. Defaults to `underline`. */
20
+ type?: CustomTabsType;
21
+ /** The tabs to render. */
22
+ items: CustomTabItem[];
23
+ /** Class for the tab list (the strip itself). */
24
+ listClassName?: string;
25
+ }
26
+ /**
27
+ * A higher-level tab strip with two looks — `underline` and `pill` — driven by
28
+ * a single `items` array. Each item can carry an icon, a numeric `count`, and a
29
+ * short `badge` (e.g. "New"). Built on Radix Tabs, so it stays keyboard- and
30
+ * a11y-friendly; control selection with `value`/`onValueChange` or
31
+ * `defaultValue` just like the primitive.
32
+ */
33
+ declare function CustomTabs({ type, items, className, listClassName, ...props }: CustomTabsProps): import("react/jsx-runtime").JSX.Element;
34
+ export { CustomTabs };
@@ -26,6 +26,12 @@ export interface DataTableProps<TRow> {
26
26
  rowActions?: (row: TRow) => ActionsMenuItem[];
27
27
  loading?: boolean;
28
28
  emptyMessage?: React.ReactNode;
29
+ /** Enable client-side pagination with a footer of page controls. */
30
+ pagination?: boolean;
31
+ /** Rows per page. Default `25`. */
32
+ pageSize?: number;
33
+ /** Page-size options in the footer selector. Default `[25, 50, 100, 200]`. */
34
+ pageSizeOptions?: number[];
29
35
  /** Alternating row backgrounds for easier scanning. */
30
36
  striped?: boolean;
31
37
  /** Keep the header visible while the body scrolls (pair with maxHeight). */
@@ -35,4 +41,4 @@ export interface DataTableProps<TRow> {
35
41
  onRowClick?: (row: TRow) => void;
36
42
  className?: string;
37
43
  }
38
- export declare function DataTable<TRow>({ columns, data, getRowId, selectable, selectedIds, onSelectionChange, rowActions, loading, emptyMessage, striped, stickyHeader, maxHeight, onRowClick, className, }: DataTableProps<TRow>): import("react/jsx-runtime").JSX.Element;
44
+ export declare function DataTable<TRow>({ columns, data, getRowId, selectable, selectedIds, onSelectionChange, rowActions, loading, emptyMessage, pagination, pageSize: pageSizeProp, pageSizeOptions, striped, stickyHeader, maxHeight, onRowClick, className, }: DataTableProps<TRow>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,44 @@
1
+ import * as React from "react";
2
+ export interface FacetedFilterOption {
3
+ /** Value stored in the selection. */
4
+ value: string;
5
+ /** Visible label. */
6
+ label: string;
7
+ /** Optional leading icon. */
8
+ icon?: React.ReactNode;
9
+ /** Optional count shown on the right (e.g. matching rows). */
10
+ count?: number;
11
+ }
12
+ interface BaseProps {
13
+ /** Trigger label, e.g. "Status". */
14
+ title: string;
15
+ options: FacetedFilterOption[];
16
+ /** Placeholder for the search box. Defaults to `title`. */
17
+ searchPlaceholder?: string;
18
+ /** Hide the search box (for short lists). */
19
+ searchable?: boolean;
20
+ /** Max selected pills to show on the trigger before collapsing to a count. */
21
+ maxDisplayed?: number;
22
+ className?: string;
23
+ }
24
+ interface MultiProps extends BaseProps {
25
+ mode?: "multiple";
26
+ /** Selected values. */
27
+ value: string[];
28
+ onChange: (value: string[]) => void;
29
+ }
30
+ interface SingleProps extends BaseProps {
31
+ mode: "single";
32
+ /** Selected value (or null). */
33
+ value: string | null;
34
+ onChange: (value: string | null) => void;
35
+ }
36
+ export type FacetedFilterProps = MultiProps | SingleProps;
37
+ /**
38
+ * A controlled filter trigger + popover: a searchable list of options, each
39
+ * selectable (multi-select checkboxes by default, or single-select with
40
+ * `mode="single"`). Shows the selection as pills on the trigger and emits the
41
+ * value(s) via `onChange` — use it to filter your own list or API query.
42
+ */
43
+ export declare function FacetedFilter(props: FacetedFilterProps): import("react/jsx-runtime").JSX.Element;
44
+ export {};
@@ -0,0 +1,26 @@
1
+ import { FileMetadata, FileWithPreview } from '../../lib/use-file-upload';
2
+ export type FileUploadProps = {
3
+ /**
4
+ * `image` renders a single-image dropzone with an inline preview overlay.
5
+ * `files` renders a multi-file grid with per-file cards. Defaults to `image`.
6
+ */
7
+ variant?: "image" | "files";
8
+ /** `accept` attribute, e.g. `"image/*"` or `".pdf,.png"`. */
9
+ accept?: string;
10
+ /** Maximum size per file, in bytes. */
11
+ maxSize?: number;
12
+ /** Maximum number of files (`files` variant). */
13
+ maxFiles?: number;
14
+ /** Allow more than one file. Forced on for the `files` variant. */
15
+ multiple?: boolean;
16
+ /** Files to seed the uploader with (already-uploaded items). */
17
+ initialFiles?: FileMetadata[];
18
+ /** Disables the dropzone and hides the file input. */
19
+ disabled?: boolean;
20
+ /** Called whenever the file list changes. */
21
+ onFilesChange?: (files: FileWithPreview[]) => void;
22
+ /** Class for the outer wrapper element. */
23
+ className?: string;
24
+ };
25
+ declare function FileUpload({ variant, accept, maxSize, maxFiles, multiple, initialFiles, disabled, onFilesChange, className, }: FileUploadProps): import("react/jsx-runtime").JSX.Element;
26
+ export { FileUpload };
@@ -0,0 +1,30 @@
1
+ import * as React from "react";
2
+ export interface FormDialogProps {
3
+ /** Body content — typically a form. Scrolls when it overflows. */
4
+ children: React.ReactNode;
5
+ /** Heading shown in the (bordered) header. Omit to hide the header. */
6
+ title?: React.ReactNode;
7
+ /** Whether the dialog is open. Controlled. */
8
+ open: boolean;
9
+ /** Called when the dialog requests to close (X, overlay, or Esc). */
10
+ onClose: () => void;
11
+ /** Optional supporting text under the title. */
12
+ description?: React.ReactNode;
13
+ /**
14
+ * When set, the dialog can't be dismissed by clicking the overlay or pressing
15
+ * Escape — only the explicit close button / footer actions close it.
16
+ */
17
+ notDismissable?: boolean;
18
+ /** Footer content, pinned below the scrollable body with a top border. */
19
+ footer?: React.ReactNode;
20
+ /** Class for the dialog content surface. */
21
+ className?: string;
22
+ }
23
+ /**
24
+ * A pre-composed modal for forms: a fixed bordered header (title, description,
25
+ * and a close button), a scrollable body, and an optional pinned footer for
26
+ * actions. Controlled via `open`/`onClose`. Set `notDismissable` to require an
27
+ * explicit action to close.
28
+ */
29
+ declare function FormDialog({ children, title, open, onClose, description, notDismissable, footer, className, }: FormDialogProps): import("react/jsx-runtime").JSX.Element;
30
+ export { FormDialog };
@@ -0,0 +1,45 @@
1
+ import * as React from "react";
2
+ /** Color variant for the accent bar, mode label, icon, and value text. */
3
+ export type SensorCardColorVariant = "primary" | "warning" | "danger" | "muted";
4
+ export interface SensorCardProps {
5
+ /** Leading icon. Falls back to a default based on `mode` ("auto" vs other). */
6
+ icon?: React.ReactNode;
7
+ /** Mode label, e.g. "Manual", "Auto". */
8
+ mode?: string;
9
+ /** Main description / name. */
10
+ description?: string;
11
+ /** Value shown on the right, e.g. "80", "Active", "OFF". */
12
+ value: string;
13
+ /** Show the colored accent bar before the value (active states). */
14
+ showAccent?: boolean;
15
+ /** Color of the accent bar, mode label, and default icon. */
16
+ colorVariant?: SensorCardColorVariant;
17
+ /** Override the accent-bar color only (falls back to `colorVariant`). */
18
+ accentColorVariant?: SensorCardColorVariant;
19
+ /** Color the value text (defaults to the foreground color). */
20
+ valueColorVariant?: SensorCardColorVariant;
21
+ /** Append a "%" to numeric values. Default `true`. */
22
+ showPercentSign?: boolean;
23
+ /** Unit shown above the value in a stacked layout, e.g. "°F", "kPa". */
24
+ unit?: string;
25
+ /** Icon on the left with mode/description stacked beside it. */
26
+ stackedLayout?: boolean;
27
+ /**
28
+ * - `default`: bare row, no Card wrapper (for nesting).
29
+ * - `standalone`: wrapped in a Card with full styling.
30
+ */
31
+ variant?: "default" | "standalone";
32
+ /** Click handler for the whole card. */
33
+ onClick?: () => void;
34
+ /** Click handler for just the value. */
35
+ onValueClick?: () => void;
36
+ className?: string;
37
+ }
38
+ /**
39
+ * A compact info/action card: a left side with an icon, mode label, and
40
+ * description, and a right side with an accent bar and a value. Use
41
+ * `colorVariant` to tint the bar, mode label, and default icon (primary /
42
+ * warning / danger / muted), `variant="standalone"` to wrap it in a Card, and
43
+ * `onClick` / `onValueClick` for actions.
44
+ */
45
+ export declare function SensorCard({ icon, mode, description, value, showAccent, colorVariant, accentColorVariant, valueColorVariant, showPercentSign, unit, stackedLayout, variant, onClick, onValueClick, className, }: SensorCardProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,56 @@
1
+ import * as React from "react";
2
+ export interface SideSheetProps {
3
+ /** Body content — typically a form. Scrolls between the pinned header/footer. */
4
+ children: React.ReactNode;
5
+ /** Heading shown in the pinned header. */
6
+ title?: React.ReactNode;
7
+ /** Whether the sheet is open. Controlled. */
8
+ open: boolean;
9
+ /** Called when the sheet requests to close (back/close, overlay, or Esc). */
10
+ onClose: () => void;
11
+ /** Optional supporting text under the title. */
12
+ description?: React.ReactNode;
13
+ /** Which edge the sheet slides in from. Defaults to `right`. */
14
+ side?: "left" | "right";
15
+ /**
16
+ * Detach the panel from the screen edge — inset with a margin, fully rounded
17
+ * corners, and a shadow, so it reads as a floating card.
18
+ */
19
+ floating?: boolean;
20
+ /**
21
+ * Show a back chevron before the title. Defaults to a close (X) button.
22
+ * When set, the chevron calls `onBack` (falls back to `onClose`).
23
+ */
24
+ onBack?: () => void;
25
+ /**
26
+ * When set, the sheet can't be dismissed by clicking the overlay or pressing
27
+ * Escape — only the header control / footer actions close it.
28
+ */
29
+ notDismissable?: boolean;
30
+ /** Footer content, pinned to the bottom with a top border. Always visible. */
31
+ footer?: React.ReactNode;
32
+ /** Class for the sheet content surface (e.g. width overrides). */
33
+ className?: string;
34
+ }
35
+ /**
36
+ * A slide-in panel with a pinned header and a **sticky footer**: the header
37
+ * (title, description, and a back/close control) and the footer (actions) stay
38
+ * fixed while the body scrolls between them. Controlled via `open`/`onClose`.
39
+ * Set `notDismissable` to require an explicit action to close, pass `onBack` to
40
+ * swap the close button for a back chevron, or `floating` to detach the panel
41
+ * from the screen edge as a rounded, shadowed card.
42
+ */
43
+ declare function SideSheet({ children, title, open, onClose, description, side, floating, onBack, notDismissable, footer, className, }: SideSheetProps): import("react/jsx-runtime").JSX.Element;
44
+ export interface SideSheetSectionProps extends React.ComponentProps<"div"> {
45
+ /** Optional label rendered above the grouped panel, with a divider rule. */
46
+ label?: React.ReactNode;
47
+ /** Optional trailing control beside the label (e.g. an expand button). */
48
+ action?: React.ReactNode;
49
+ }
50
+ /**
51
+ * A labelled, grouped block for the sheet body — a divider-titled `bg-secondary`
52
+ * panel, matching the "Trigger Settings" / "Spray Stages" grouping pattern.
53
+ * Drop form rows in as children.
54
+ */
55
+ declare function SideSheetSection({ label, action, className, children, ...props }: SideSheetSectionProps): import("react/jsx-runtime").JSX.Element;
56
+ export { SideSheet, SideSheetSection };
@@ -0,0 +1,54 @@
1
+ import * as React from "react";
2
+ export type StatCardColor = "primary" | "success" | "warning" | "danger" | "muted";
3
+ export interface StatCardTrend {
4
+ /** Delta text, e.g. "+20.1%". */
5
+ value: string;
6
+ /** Direction — sets the arrow icon and default color. */
7
+ direction?: "up" | "down";
8
+ /** Trailing context, e.g. "from last month". */
9
+ label?: React.ReactNode;
10
+ }
11
+ export interface StatCardProgress {
12
+ /** Completion percentage, 0–100. */
13
+ value: number;
14
+ /** Caption under the bar, left-aligned. */
15
+ caption?: React.ReactNode;
16
+ /** Caption under the bar, right-aligned (e.g. "Target: $10,000"). */
17
+ target?: React.ReactNode;
18
+ }
19
+ export interface StatCardRing {
20
+ /** Filled percentage, 0–100. */
21
+ value: number;
22
+ /** Label inside the ring (defaults to `value%`). */
23
+ label?: React.ReactNode;
24
+ /** Caption beside the ring (e.g. "of 100 GB"). */
25
+ caption?: React.ReactNode;
26
+ }
27
+ export interface StatCardProps {
28
+ /** Small muted heading. */
29
+ title: React.ReactNode;
30
+ /** The headline figure, e.g. "$45,231". */
31
+ value: React.ReactNode;
32
+ /** Muted supporting line under the value. */
33
+ description?: React.ReactNode;
34
+ /** Icon shown in a tinted box at the top-right. */
35
+ icon?: React.ReactNode;
36
+ /** Accent color for the icon box, trend, progress bar, and ring. */
37
+ color?: StatCardColor;
38
+ /** A colored delta with a trend arrow, shown in place of `description`. */
39
+ trend?: StatCardTrend;
40
+ /** A linear progress bar with optional captions, shown under the value. */
41
+ progress?: StatCardProgress;
42
+ /** A small filled area chart (series of numbers), shown under the value. */
43
+ sparkline?: number[];
44
+ /** A radial progress ring shown beside the value. */
45
+ ring?: StatCardRing;
46
+ className?: string;
47
+ }
48
+ /**
49
+ * A dashboard stat card: a muted `title`, a bold `value`, and an optional
50
+ * accessory — a tinted `icon` box, a colored `trend` delta, a linear
51
+ * `progress` bar, a `sparkline` area chart, or a radial `ring`. Tint accessories
52
+ * with `color`.
53
+ */
54
+ export declare function StatCard({ title, value, description, icon, color, trend, progress, sparkline, ring, className, }: StatCardProps): import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,7 @@
1
1
  import { VariantProps } from 'class-variance-authority';
2
2
  import * as React from "react";
3
3
  declare const badgeVariants: (props?: ({
4
- variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" | "link" | "red" | "orange" | "yellow" | "green" | "teal" | "cyan" | "blue" | "purple" | "pink" | "gray" | null | undefined;
4
+ variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | "red" | "orange" | "yellow" | "green" | "teal" | "cyan" | "blue" | "purple" | "pink" | "gray" | null | undefined;
5
5
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
6
6
  declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
7
7
  asChild?: boolean;
@@ -1,7 +1,7 @@
1
1
  import { VariantProps } from 'class-variance-authority';
2
2
  import * as React from "react";
3
3
  declare const buttonVariants: (props?: ({
4
- variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" | "link" | null | undefined;
4
+ variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | null | undefined;
5
5
  size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
6
6
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
7
  declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
@@ -11,7 +11,7 @@ declare function Item({ className, variant, size, asChild, ...props }: React.Com
11
11
  asChild?: boolean;
12
12
  }): import("react/jsx-runtime").JSX.Element;
13
13
  declare const itemMediaVariants: (props?: ({
14
- variant?: "default" | "icon" | "image" | null | undefined;
14
+ variant?: "image" | "default" | "icon" | null | undefined;
15
15
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
16
16
  declare function ItemMedia({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof itemMediaVariants>): import("react/jsx-runtime").JSX.Element;
17
17
  declare function ItemContent({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { cn } from './lib/utils';
2
+ export { useFileUpload, formatBytes, type FileMetadata, type FileWithPreview, type FileUploadOptions, type FileUploadState, type FileUploadActions, } from './lib/use-file-upload';
2
3
  export * from './components/custom/actions-menu';
3
4
  export * from './components/custom/advanced-input';
5
+ export * from './components/custom/file-upload';
4
6
  export * from './components/custom/advanced-select';
5
7
  export * from './components/custom/data-table';
6
8
  export * from './components/custom/date-time-range-picker';