@gerege-systems/ui 0.11.2
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/LICENSE +21 -0
- package/README.md +234 -0
- package/dist-lib/__tests__/helpers/color.d.ts +9 -0
- package/dist-lib/__tests__/helpers/theme.d.ts +18 -0
- package/dist-lib/components/ui/Accordion.d.ts +21 -0
- package/dist-lib/components/ui/Accordion.js +71 -0
- package/dist-lib/components/ui/Accordion.js.map +1 -0
- package/dist-lib/components/ui/Alert.d.ts +51 -0
- package/dist-lib/components/ui/Alert.js +79 -0
- package/dist-lib/components/ui/Alert.js.map +1 -0
- package/dist-lib/components/ui/Avatar.d.ts +52 -0
- package/dist-lib/components/ui/Avatar.js +94 -0
- package/dist-lib/components/ui/Avatar.js.map +1 -0
- package/dist-lib/components/ui/Badge.d.ts +26 -0
- package/dist-lib/components/ui/Badge.js +76 -0
- package/dist-lib/components/ui/Badge.js.map +1 -0
- package/dist-lib/components/ui/Breadcrumbs.d.ts +33 -0
- package/dist-lib/components/ui/Breadcrumbs.js +52 -0
- package/dist-lib/components/ui/Breadcrumbs.js.map +1 -0
- package/dist-lib/components/ui/Button.d.ts +52 -0
- package/dist-lib/components/ui/Button.js +131 -0
- package/dist-lib/components/ui/Button.js.map +1 -0
- package/dist-lib/components/ui/Calendar.d.ts +15 -0
- package/dist-lib/components/ui/Calendar.js +139 -0
- package/dist-lib/components/ui/Calendar.js.map +1 -0
- package/dist-lib/components/ui/Card.d.ts +39 -0
- package/dist-lib/components/ui/Card.js +97 -0
- package/dist-lib/components/ui/Card.js.map +1 -0
- package/dist-lib/components/ui/Carousel.d.ts +27 -0
- package/dist-lib/components/ui/Carousel.js +174 -0
- package/dist-lib/components/ui/Carousel.js.map +1 -0
- package/dist-lib/components/ui/Chart.d.ts +87 -0
- package/dist-lib/components/ui/Chart.js +487 -0
- package/dist-lib/components/ui/Chart.js.map +1 -0
- package/dist-lib/components/ui/Checkbox.d.ts +28 -0
- package/dist-lib/components/ui/Checkbox.js +70 -0
- package/dist-lib/components/ui/Checkbox.js.map +1 -0
- package/dist-lib/components/ui/Combobox.d.ts +67 -0
- package/dist-lib/components/ui/Combobox.js +195 -0
- package/dist-lib/components/ui/Combobox.js.map +1 -0
- package/dist-lib/components/ui/CommandPalette.d.ts +112 -0
- package/dist-lib/components/ui/CommandPalette.js +179 -0
- package/dist-lib/components/ui/CommandPalette.js.map +1 -0
- package/dist-lib/components/ui/ContextMenu.d.ts +50 -0
- package/dist-lib/components/ui/ContextMenu.js +165 -0
- package/dist-lib/components/ui/ContextMenu.js.map +1 -0
- package/dist-lib/components/ui/DataGrid.d.ts +79 -0
- package/dist-lib/components/ui/DataGrid.js +99 -0
- package/dist-lib/components/ui/DataGrid.js.map +1 -0
- package/dist-lib/components/ui/DatePicker.d.ts +45 -0
- package/dist-lib/components/ui/DatePicker.js +193 -0
- package/dist-lib/components/ui/DatePicker.js.map +1 -0
- package/dist-lib/components/ui/DesignSystemProvider.d.ts +147 -0
- package/dist-lib/components/ui/DesignSystemProvider.js +135 -0
- package/dist-lib/components/ui/DesignSystemProvider.js.map +1 -0
- package/dist-lib/components/ui/Dialog.d.ts +77 -0
- package/dist-lib/components/ui/Dialog.js +165 -0
- package/dist-lib/components/ui/Dialog.js.map +1 -0
- package/dist-lib/components/ui/Drawer.d.ts +44 -0
- package/dist-lib/components/ui/Drawer.js +132 -0
- package/dist-lib/components/ui/Drawer.js.map +1 -0
- package/dist-lib/components/ui/DropdownMenu.d.ts +47 -0
- package/dist-lib/components/ui/DropdownMenu.js +169 -0
- package/dist-lib/components/ui/DropdownMenu.js.map +1 -0
- package/dist-lib/components/ui/EmptyState.d.ts +48 -0
- package/dist-lib/components/ui/EmptyState.js +46 -0
- package/dist-lib/components/ui/EmptyState.js.map +1 -0
- package/dist-lib/components/ui/ErrorState.d.ts +51 -0
- package/dist-lib/components/ui/ErrorState.js +69 -0
- package/dist-lib/components/ui/ErrorState.js.map +1 -0
- package/dist-lib/components/ui/FileUpload.d.ts +26 -0
- package/dist-lib/components/ui/FileUpload.js +111 -0
- package/dist-lib/components/ui/FileUpload.js.map +1 -0
- package/dist-lib/components/ui/Form.d.ts +36 -0
- package/dist-lib/components/ui/Form.js +131 -0
- package/dist-lib/components/ui/Form.js.map +1 -0
- package/dist-lib/components/ui/Icon.d.ts +34 -0
- package/dist-lib/components/ui/Icon.js +32 -0
- package/dist-lib/components/ui/Icon.js.map +1 -0
- package/dist-lib/components/ui/IconButton.d.ts +34 -0
- package/dist-lib/components/ui/IconButton.js +64 -0
- package/dist-lib/components/ui/IconButton.js.map +1 -0
- package/dist-lib/components/ui/Input.d.ts +54 -0
- package/dist-lib/components/ui/Input.js +158 -0
- package/dist-lib/components/ui/Input.js.map +1 -0
- package/dist-lib/components/ui/Kbd.d.ts +16 -0
- package/dist-lib/components/ui/Kbd.js +24 -0
- package/dist-lib/components/ui/Kbd.js.map +1 -0
- package/dist-lib/components/ui/MultiSelect.d.ts +64 -0
- package/dist-lib/components/ui/MultiSelect.js +210 -0
- package/dist-lib/components/ui/MultiSelect.js.map +1 -0
- package/dist-lib/components/ui/Pagination.d.ts +55 -0
- package/dist-lib/components/ui/Pagination.js +153 -0
- package/dist-lib/components/ui/Pagination.js.map +1 -0
- package/dist-lib/components/ui/Popover.d.ts +16 -0
- package/dist-lib/components/ui/Popover.js +35 -0
- package/dist-lib/components/ui/Popover.js.map +1 -0
- package/dist-lib/components/ui/Progress.d.ts +40 -0
- package/dist-lib/components/ui/Progress.js +100 -0
- package/dist-lib/components/ui/Progress.js.map +1 -0
- package/dist-lib/components/ui/RadioGroup.d.ts +27 -0
- package/dist-lib/components/ui/RadioGroup.js +81 -0
- package/dist-lib/components/ui/RadioGroup.js.map +1 -0
- package/dist-lib/components/ui/RelativeTime.d.ts +19 -0
- package/dist-lib/components/ui/RelativeTime.js +31 -0
- package/dist-lib/components/ui/RelativeTime.js.map +1 -0
- package/dist-lib/components/ui/ScrollArea.d.ts +21 -0
- package/dist-lib/components/ui/ScrollArea.js +60 -0
- package/dist-lib/components/ui/ScrollArea.js.map +1 -0
- package/dist-lib/components/ui/Select.d.ts +61 -0
- package/dist-lib/components/ui/Select.js +139 -0
- package/dist-lib/components/ui/Select.js.map +1 -0
- package/dist-lib/components/ui/Separator.d.ts +13 -0
- package/dist-lib/components/ui/Separator.js +26 -0
- package/dist-lib/components/ui/Separator.js.map +1 -0
- package/dist-lib/components/ui/Sheet.d.ts +55 -0
- package/dist-lib/components/ui/Sheet.js +136 -0
- package/dist-lib/components/ui/Sheet.js.map +1 -0
- package/dist-lib/components/ui/Sidebar.d.ts +91 -0
- package/dist-lib/components/ui/Sidebar.js +212 -0
- package/dist-lib/components/ui/Sidebar.js.map +1 -0
- package/dist-lib/components/ui/Skeleton.d.ts +37 -0
- package/dist-lib/components/ui/Skeleton.js +29 -0
- package/dist-lib/components/ui/Skeleton.js.map +1 -0
- package/dist-lib/components/ui/Slider.d.ts +33 -0
- package/dist-lib/components/ui/Slider.js +64 -0
- package/dist-lib/components/ui/Slider.js.map +1 -0
- package/dist-lib/components/ui/Snackbar.d.ts +21 -0
- package/dist-lib/components/ui/Snackbar.js +57 -0
- package/dist-lib/components/ui/Snackbar.js.map +1 -0
- package/dist-lib/components/ui/Spinner.d.ts +23 -0
- package/dist-lib/components/ui/Spinner.js +54 -0
- package/dist-lib/components/ui/Spinner.js.map +1 -0
- package/dist-lib/components/ui/Stepper.d.ts +40 -0
- package/dist-lib/components/ui/Stepper.js +111 -0
- package/dist-lib/components/ui/Stepper.js.map +1 -0
- package/dist-lib/components/ui/Switch.d.ts +33 -0
- package/dist-lib/components/ui/Switch.js +80 -0
- package/dist-lib/components/ui/Switch.js.map +1 -0
- package/dist-lib/components/ui/Table.d.ts +71 -0
- package/dist-lib/components/ui/Table.js +179 -0
- package/dist-lib/components/ui/Table.js.map +1 -0
- package/dist-lib/components/ui/Tabs.d.ts +32 -0
- package/dist-lib/components/ui/Tabs.js +91 -0
- package/dist-lib/components/ui/Tabs.js.map +1 -0
- package/dist-lib/components/ui/TagInput.d.ts +39 -0
- package/dist-lib/components/ui/TagInput.js +111 -0
- package/dist-lib/components/ui/TagInput.js.map +1 -0
- package/dist-lib/components/ui/Textarea.d.ts +34 -0
- package/dist-lib/components/ui/Textarea.js +88 -0
- package/dist-lib/components/ui/Textarea.js.map +1 -0
- package/dist-lib/components/ui/Timeline.d.ts +33 -0
- package/dist-lib/components/ui/Timeline.js +56 -0
- package/dist-lib/components/ui/Timeline.js.map +1 -0
- package/dist-lib/components/ui/Toast.d.ts +53 -0
- package/dist-lib/components/ui/Toast.js +158 -0
- package/dist-lib/components/ui/Toast.js.map +1 -0
- package/dist-lib/components/ui/Tooltip.d.ts +38 -0
- package/dist-lib/components/ui/Tooltip.js +60 -0
- package/dist-lib/components/ui/Tooltip.js.map +1 -0
- package/dist-lib/components/ui/TopNav.d.ts +37 -0
- package/dist-lib/components/ui/TopNav.js +69 -0
- package/dist-lib/components/ui/TopNav.js.map +1 -0
- package/dist-lib/components/ui/Tree.d.ts +51 -0
- package/dist-lib/components/ui/Tree.js +170 -0
- package/dist-lib/components/ui/Tree.js.map +1 -0
- package/dist-lib/hooks/use-debounce.d.ts +19 -0
- package/dist-lib/hooks/use-debounce.js +36 -0
- package/dist-lib/hooks/use-debounce.js.map +1 -0
- package/dist-lib/hooks/use-delayed-loading.d.ts +21 -0
- package/dist-lib/hooks/use-delayed-loading.js +20 -0
- package/dist-lib/hooks/use-delayed-loading.js.map +1 -0
- package/dist-lib/hooks/use-field-ids.d.ts +30 -0
- package/dist-lib/hooks/use-field-ids.js +18 -0
- package/dist-lib/hooks/use-field-ids.js.map +1 -0
- package/dist-lib/hooks/use-media-query.d.ts +11 -0
- package/dist-lib/hooks/use-media-query.js +22 -0
- package/dist-lib/hooks/use-media-query.js.map +1 -0
- package/dist-lib/hooks/use-modifier-key.d.ts +13 -0
- package/dist-lib/hooks/use-modifier-key.js +19 -0
- package/dist-lib/hooks/use-modifier-key.js.map +1 -0
- package/dist-lib/hooks/use-strings.d.ts +5 -0
- package/dist-lib/hooks/use-strings.js +12 -0
- package/dist-lib/hooks/use-strings.js.map +1 -0
- package/dist-lib/hooks/use-toast.d.ts +48 -0
- package/dist-lib/hooks/use-toast.js +67 -0
- package/dist-lib/hooks/use-toast.js.map +1 -0
- package/dist-lib/icon.d.ts +8 -0
- package/dist-lib/icon.js +7 -0
- package/dist-lib/icon.js.map +1 -0
- package/dist-lib/icons/index.d.ts +80 -0
- package/dist-lib/icons/index.js +163 -0
- package/dist-lib/icons/index.js.map +1 -0
- package/dist-lib/illustrations/index.d.ts +10 -0
- package/dist-lib/illustrations/index.js +114 -0
- package/dist-lib/illustrations/index.js.map +1 -0
- package/dist-lib/index.d.ts +68 -0
- package/dist-lib/index.js +291 -0
- package/dist-lib/index.js.map +1 -0
- package/dist-lib/lib/cva.d.ts +6 -0
- package/dist-lib/lib/format.d.ts +65 -0
- package/dist-lib/lib/format.js +95 -0
- package/dist-lib/lib/format.js.map +1 -0
- package/dist-lib/lib/return-focus.d.ts +11 -0
- package/dist-lib/lib/return-focus.js +12 -0
- package/dist-lib/lib/return-focus.js.map +1 -0
- package/dist-lib/lib/strings.d.ts +190 -0
- package/dist-lib/lib/strings.js +141 -0
- package/dist-lib/lib/strings.js.map +1 -0
- package/dist-lib/lib/strings.mn.d.ts +3 -0
- package/dist-lib/lib/strings.mn.js +115 -0
- package/dist-lib/lib/strings.mn.js.map +1 -0
- package/dist-lib/lib/utils.d.ts +11 -0
- package/dist-lib/lib/utils.js +10 -0
- package/dist-lib/lib/utils.js.map +1 -0
- package/dist-lib/styles.css +1 -0
- package/dist-lib/theme.css +840 -0
- package/package.json +158 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
|
+
export interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Predefined silhouette presets. */
|
|
4
|
+
variant?: 'text' | 'circle' | 'card' | 'avatar';
|
|
5
|
+
/**
|
|
6
|
+
* Render nothing until this many ms have elapsed, so sub-300ms loads never
|
|
7
|
+
* flash a placeholder. Default 300. Pass 0 to render immediately.
|
|
8
|
+
*/
|
|
9
|
+
delay?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Once shown, keep the placeholder mounted for at least this many ms so it
|
|
12
|
+
* never flickers. Default 500.
|
|
13
|
+
*/
|
|
14
|
+
minVisible?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Animated placeholder. Use `variant="text"` / `variant="avatar"` for common
|
|
18
|
+
* shapes; pass `className` directly for one-off sizes.
|
|
19
|
+
*
|
|
20
|
+
* @example List item
|
|
21
|
+
* <div className="flex items-center gap-3">
|
|
22
|
+
* <Skeleton variant="avatar" />
|
|
23
|
+
* <div className="space-y-1.5 flex-1">
|
|
24
|
+
* <Skeleton variant="text" className="w-1/3" />
|
|
25
|
+
* <Skeleton variant="text" className="w-1/2" />
|
|
26
|
+
* </div>
|
|
27
|
+
* </div>
|
|
28
|
+
*
|
|
29
|
+
* @example Card
|
|
30
|
+
* <Skeleton variant="card" className="h-32" />
|
|
31
|
+
*
|
|
32
|
+
* @do Match the silhouette of the eventual content so the layout doesn't
|
|
33
|
+
* shift when data arrives.
|
|
34
|
+
* @dont Pass `delay={0}` for data that usually arrives in under 300ms — the
|
|
35
|
+
* default delay exists so fast loads never flash a placeholder.
|
|
36
|
+
*/
|
|
37
|
+
export declare const Skeleton: import('react').ForwardRefExoticComponent<SkeletonProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef as l } from "react";
|
|
4
|
+
import { cn as s } from "../../lib/utils.js";
|
|
5
|
+
import { useDelayedLoading as m } from "../../hooks/use-delayed-loading.js";
|
|
6
|
+
const c = l(function({ className: o, variant: e, delay: r = 300, minVisible: d = 500, ...u }, n) {
|
|
7
|
+
return m(r, { minVisible: d }) ? /* @__PURE__ */ t(
|
|
8
|
+
"div",
|
|
9
|
+
{
|
|
10
|
+
ref: n,
|
|
11
|
+
"aria-hidden": !0,
|
|
12
|
+
className: s(
|
|
13
|
+
"bg-background-muted animate-pulse",
|
|
14
|
+
e === "text" && "h-3 rounded-sm",
|
|
15
|
+
e === "circle" && "aspect-square rounded-full",
|
|
16
|
+
e === "avatar" && "size-8 rounded-full",
|
|
17
|
+
e === "card" && "rounded-lg",
|
|
18
|
+
!e && "rounded-md",
|
|
19
|
+
o
|
|
20
|
+
),
|
|
21
|
+
...u
|
|
22
|
+
}
|
|
23
|
+
) : null;
|
|
24
|
+
});
|
|
25
|
+
c.displayName = "Skeleton";
|
|
26
|
+
export {
|
|
27
|
+
c as Skeleton
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=Skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Skeleton.js","sources":["../../../src/components/ui/Skeleton.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef, type HTMLAttributes } from 'react';\nimport { cn } from '@/lib/utils';\nimport { useDelayedLoading } from '@/hooks/use-delayed-loading';\n\nexport interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {\n /** Predefined silhouette presets. */\n variant?: 'text' | 'circle' | 'card' | 'avatar';\n /**\n * Render nothing until this many ms have elapsed, so sub-300ms loads never\n * flash a placeholder. Default 300. Pass 0 to render immediately.\n */\n delay?: number;\n /**\n * Once shown, keep the placeholder mounted for at least this many ms so it\n * never flickers. Default 500.\n */\n minVisible?: number;\n}\n\n/**\n * Animated placeholder. Use `variant=\"text\"` / `variant=\"avatar\"` for common\n * shapes; pass `className` directly for one-off sizes.\n *\n * @example List item\n * <div className=\"flex items-center gap-3\">\n * <Skeleton variant=\"avatar\" />\n * <div className=\"space-y-1.5 flex-1\">\n * <Skeleton variant=\"text\" className=\"w-1/3\" />\n * <Skeleton variant=\"text\" className=\"w-1/2\" />\n * </div>\n * </div>\n *\n * @example Card\n * <Skeleton variant=\"card\" className=\"h-32\" />\n *\n * @do Match the silhouette of the eventual content so the layout doesn't\n * shift when data arrives.\n * @dont Pass `delay={0}` for data that usually arrives in under 300ms — the\n * default delay exists so fast loads never flash a placeholder.\n */\nexport const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(function Skeleton(\n { className, variant, delay = 300, minVisible = 500, ...props },\n ref,\n) {\n const show = useDelayedLoading(delay, { minVisible });\n if (!show) return null;\n return (\n <div\n ref={ref}\n aria-hidden\n className={cn(\n 'bg-background-muted animate-pulse',\n variant === 'text' && 'h-3 rounded-sm',\n variant === 'circle' && 'aspect-square rounded-full',\n variant === 'avatar' && 'size-8 rounded-full',\n variant === 'card' && 'rounded-lg',\n !variant && 'rounded-md',\n className,\n )}\n {...props}\n />\n );\n});\nSkeleton.displayName = 'Skeleton';\n"],"names":["Skeleton","forwardRef","className","variant","delay","minVisible","props","ref","useDelayedLoading","jsx","cn"],"mappings":";;;;;AA0CO,MAAMA,IAAWC,EAA0C,SAChE,EAAE,WAAAC,GAAW,SAAAC,GAAS,OAAAC,IAAQ,KAAK,YAAAC,IAAa,KAAK,GAAGC,EAAA,GACxDC,GACA;AAEA,SADaC,EAAkBJ,GAAO,EAAE,YAAAC,GAAY,IAGlD,gBAAAI;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAF;AAAA,MACA,eAAW;AAAA,MACX,WAAWG;AAAA,QACT;AAAA,QACAP,MAAY,UAAU;AAAA,QACtBA,MAAY,YAAY;AAAA,QACxBA,MAAY,YAAY;AAAA,QACxBA,MAAY,UAAU;AAAA,QACtB,CAACA,KAAW;AAAA,QACZD;AAAA,MAAA;AAAA,MAED,GAAGI;AAAA,IAAA;AAAA,EAAA,IAdU;AAiBpB,CAAC;AACDN,EAAS,cAAc;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
|
+
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
3
|
+
export interface SliderProps extends Omit<ComponentPropsWithoutRef<typeof SliderPrimitive.Root>, 'value' | 'defaultValue'> {
|
|
4
|
+
/**
|
|
5
|
+
* Controlled value. Pass `[n]` for a single-thumb slider, `[a, b]` for a range slider.
|
|
6
|
+
*/
|
|
7
|
+
value?: number[];
|
|
8
|
+
defaultValue?: number[];
|
|
9
|
+
/** Inline label rendered above the slider. */
|
|
10
|
+
label?: ReactNode;
|
|
11
|
+
/** Show the numeric value next to the label. */
|
|
12
|
+
showValue?: boolean;
|
|
13
|
+
/** Format the displayed value (e.g. `(v) => \`${v}%\``). */
|
|
14
|
+
formatValue?: (value: number) => string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Single- or range-thumb slider. Pass one item in `value` for a single
|
|
18
|
+
* thumb, two for a range.
|
|
19
|
+
*
|
|
20
|
+
* @example Single value
|
|
21
|
+
* <Slider label="Volume" showValue defaultValue={[60]} max={100} step={1} />
|
|
22
|
+
*
|
|
23
|
+
* @example Price range
|
|
24
|
+
* <Slider label="Price"
|
|
25
|
+
* defaultValue={[50, 250]}
|
|
26
|
+
* min={0} max={500} step={10}
|
|
27
|
+
* formatValue={(v) => \`$\${v}\`}
|
|
28
|
+
* showValue />
|
|
29
|
+
*
|
|
30
|
+
* @do Use `showValue` when the absolute number matters (price, volume, weight).
|
|
31
|
+
* @dont Hide the value when users will need to reason about exact thresholds.
|
|
32
|
+
*/
|
|
33
|
+
export declare const Slider: import('react').ForwardRefExoticComponent<SliderProps & import('react').RefAttributes<HTMLSpanElement>>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as u, jsx as i } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef as k, useState as R, useId as j } from "react";
|
|
4
|
+
import * as s from "@radix-ui/react-slider";
|
|
5
|
+
import { cn as h } from "../../lib/utils.js";
|
|
6
|
+
import { useStrings as I } from "../../hooks/use-strings.js";
|
|
7
|
+
const z = k(
|
|
8
|
+
function({
|
|
9
|
+
className: N,
|
|
10
|
+
label: e,
|
|
11
|
+
showValue: b,
|
|
12
|
+
formatValue: o = (l) => String(l),
|
|
13
|
+
value: n,
|
|
14
|
+
defaultValue: g,
|
|
15
|
+
onValueChange: a,
|
|
16
|
+
...v
|
|
17
|
+
}, y) {
|
|
18
|
+
const [l, S] = R(g ?? [0]), p = n !== void 0, r = p ? n : l, d = r.length > 1, c = j(), f = I(), m = typeof e == "string" ? e : void 0, w = (t) => d ? t === 0 ? f.slider.minimum : f.slider.maximum : m ?? v["aria-label"] ?? f.slider.value;
|
|
19
|
+
return /* @__PURE__ */ u("div", { className: h("flex flex-col gap-2", N), children: [
|
|
20
|
+
(e || b) && /* @__PURE__ */ u("div", { className: "flex items-center justify-between", children: [
|
|
21
|
+
e && /* @__PURE__ */ i("span", { id: c, className: "text-foreground text-sm font-medium", children: e }),
|
|
22
|
+
b && /* @__PURE__ */ i("span", { className: "tabular text-foreground-muted font-mono text-xs", children: d ? `${o(r[0])} – ${o(r[1])}` : o(r[0]) })
|
|
23
|
+
] }),
|
|
24
|
+
/* @__PURE__ */ u(
|
|
25
|
+
s.Root,
|
|
26
|
+
{
|
|
27
|
+
ref: y,
|
|
28
|
+
value: n,
|
|
29
|
+
defaultValue: g,
|
|
30
|
+
onValueChange: (t) => {
|
|
31
|
+
p || S(t), a == null || a(t);
|
|
32
|
+
},
|
|
33
|
+
className: "relative flex w-full touch-none items-center py-3.5 select-none",
|
|
34
|
+
"aria-labelledby": e && !m ? c : void 0,
|
|
35
|
+
...v,
|
|
36
|
+
children: [
|
|
37
|
+
/* @__PURE__ */ i(s.Track, { className: "bg-background-muted relative h-1 w-full grow overflow-hidden rounded-full", children: /* @__PURE__ */ i(s.Range, { className: "bg-accent absolute h-full" }) }),
|
|
38
|
+
r.map((t, x) => /* @__PURE__ */ i(
|
|
39
|
+
s.Thumb,
|
|
40
|
+
{
|
|
41
|
+
className: h(
|
|
42
|
+
"border-accent bg-card relative block size-4 rounded-full border-2 shadow-sm",
|
|
43
|
+
// 44px touch target without growing the visible thumb.
|
|
44
|
+
'before:absolute before:top-1/2 before:left-1/2 before:size-11 before:-translate-x-1/2 before:-translate-y-1/2 before:rounded-full before:content-[""]',
|
|
45
|
+
"focus-visible:ring-ring focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
46
|
+
"transition-transform duration-[var(--duration-fast)] ease-[var(--ease-out)]",
|
|
47
|
+
"hover:scale-110 data-[disabled]:pointer-events-none data-[disabled]:opacity-50"
|
|
48
|
+
),
|
|
49
|
+
"aria-label": w(x),
|
|
50
|
+
"aria-labelledby": !d && e && !m ? c : void 0
|
|
51
|
+
},
|
|
52
|
+
x
|
|
53
|
+
))
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
] });
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
z.displayName = "Slider";
|
|
61
|
+
export {
|
|
62
|
+
z as Slider
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=Slider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Slider.js","sources":["../../../src/components/ui/Slider.tsx"],"sourcesContent":["'use client';\n\nimport {\n forwardRef,\n useId,\n useState,\n type ComponentPropsWithoutRef,\n type ElementRef,\n type ReactNode,\n} from 'react';\nimport * as SliderPrimitive from '@radix-ui/react-slider';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\n\nexport interface SliderProps extends Omit<\n ComponentPropsWithoutRef<typeof SliderPrimitive.Root>,\n 'value' | 'defaultValue'\n> {\n /**\n * Controlled value. Pass `[n]` for a single-thumb slider, `[a, b]` for a range slider.\n */\n value?: number[];\n defaultValue?: number[];\n /** Inline label rendered above the slider. */\n label?: ReactNode;\n /** Show the numeric value next to the label. */\n showValue?: boolean;\n /** Format the displayed value (e.g. `(v) => \\`${v}%\\``). */\n formatValue?: (value: number) => string;\n}\n\n/**\n * Single- or range-thumb slider. Pass one item in `value` for a single\n * thumb, two for a range.\n *\n * @example Single value\n * <Slider label=\"Volume\" showValue defaultValue={[60]} max={100} step={1} />\n *\n * @example Price range\n * <Slider label=\"Price\"\n * defaultValue={[50, 250]}\n * min={0} max={500} step={10}\n * formatValue={(v) => \\`$\\${v}\\`}\n * showValue />\n *\n * @do Use `showValue` when the absolute number matters (price, volume, weight).\n * @dont Hide the value when users will need to reason about exact thresholds.\n */\nexport const Slider = forwardRef<ElementRef<typeof SliderPrimitive.Root>, SliderProps>(\n function Slider(\n {\n className,\n label,\n showValue,\n formatValue = (v) => String(v),\n value,\n defaultValue,\n onValueChange,\n ...props\n },\n ref,\n ) {\n // Uncontrolled sliders track their own value so `showValue` stays live.\n const [internal, setInternal] = useState<number[]>(defaultValue ?? [0]);\n const isControlled = value !== undefined;\n const currentValue = isControlled ? value : internal;\n const isRange = currentValue.length > 1;\n const labelId = useId();\n const strings = useStrings();\n // Only a string label can double as aria-label; ReactNode labels are\n // referenced by id instead.\n const stringLabel = typeof label === 'string' ? label : undefined;\n const thumbLabel = (i: number) =>\n isRange\n ? i === 0\n ? strings.slider.minimum\n : strings.slider.maximum\n : (stringLabel ?? props['aria-label'] ?? strings.slider.value);\n\n return (\n <div className={cn('flex flex-col gap-2', className)}>\n {(label || showValue) && (\n <div className=\"flex items-center justify-between\">\n {label && (\n <span id={labelId} className=\"text-foreground text-sm font-medium\">\n {label}\n </span>\n )}\n {showValue && (\n <span className=\"tabular text-foreground-muted font-mono text-xs\">\n {isRange\n ? `${formatValue(currentValue[0])} – ${formatValue(currentValue[1])}`\n : formatValue(currentValue[0])}\n </span>\n )}\n </div>\n )}\n\n <SliderPrimitive.Root\n ref={ref}\n value={value}\n defaultValue={defaultValue}\n onValueChange={(v) => {\n if (!isControlled) setInternal(v);\n onValueChange?.(v);\n }}\n className=\"relative flex w-full touch-none items-center py-3.5 select-none\"\n aria-labelledby={label && !stringLabel ? labelId : undefined}\n {...props}\n >\n <SliderPrimitive.Track className=\"bg-background-muted relative h-1 w-full grow overflow-hidden rounded-full\">\n <SliderPrimitive.Range className=\"bg-accent absolute h-full\" />\n </SliderPrimitive.Track>\n {currentValue.map((_, i) => (\n <SliderPrimitive.Thumb\n key={i}\n className={cn(\n 'border-accent bg-card relative block size-4 rounded-full border-2 shadow-sm',\n // 44px touch target without growing the visible thumb.\n 'before:absolute before:top-1/2 before:left-1/2 before:size-11 before:-translate-x-1/2 before:-translate-y-1/2 before:rounded-full before:content-[\"\"]',\n 'focus-visible:ring-ring focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2',\n 'transition-transform duration-[var(--duration-fast)] ease-[var(--ease-out)]',\n 'hover:scale-110 data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n )}\n aria-label={thumbLabel(i)}\n aria-labelledby={!isRange && label && !stringLabel ? labelId : undefined}\n />\n ))}\n </SliderPrimitive.Root>\n </div>\n );\n },\n);\n\nSlider.displayName = 'Slider';\n"],"names":["Slider","forwardRef","className","label","showValue","formatValue","v","value","defaultValue","onValueChange","props","ref","internal","setInternal","useState","isControlled","currentValue","isRange","labelId","useId","strings","useStrings","stringLabel","thumbLabel","i","cn","jsxs","SliderPrimitive","jsx","_"],"mappings":";;;;;;AAgDO,MAAMA,IAASC;AAAA,EACpB,SACE;AAAA,IACE,WAAAC;AAAA,IACA,OAAAC;AAAA,IACA,WAAAC;AAAA,IACA,aAAAC,IAAc,CAACC,MAAM,OAAOA,CAAC;AAAA,IAC7B,OAAAC;AAAA,IACA,cAAAC;AAAA,IACA,eAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,GACA;AAEA,UAAM,CAACC,GAAUC,CAAW,IAAIC,EAAmBN,KAAgB,CAAC,CAAC,CAAC,GAChEO,IAAeR,MAAU,QACzBS,IAAeD,IAAeR,IAAQK,GACtCK,IAAUD,EAAa,SAAS,GAChCE,IAAUC,EAAA,GACVC,IAAUC,EAAA,GAGVC,IAAc,OAAOnB,KAAU,WAAWA,IAAQ,QAClDoB,IAAa,CAACC,MAClBP,IACIO,MAAM,IACJJ,EAAQ,OAAO,UACfA,EAAQ,OAAO,UAChBE,KAAeZ,EAAM,YAAY,KAAKU,EAAQ,OAAO;AAE5D,6BACG,OAAA,EAAI,WAAWK,EAAG,uBAAuBvB,CAAS,GAC/C,UAAA;AAAA,OAAAC,KAASC,MACT,gBAAAsB,EAAC,OAAA,EAAI,WAAU,qCACZ,UAAA;AAAA,QAAAvB,uBACE,QAAA,EAAK,IAAIe,GAAS,WAAU,uCAC1B,UAAAf,GACH;AAAA,QAEDC,uBACE,QAAA,EAAK,WAAU,mDACb,UAAAa,IACG,GAAGZ,EAAYW,EAAa,CAAC,CAAC,CAAC,MAAMX,EAAYW,EAAa,CAAC,CAAC,CAAC,KACjEX,EAAYW,EAAa,CAAC,CAAC,EAAA,CACjC;AAAA,MAAA,GAEJ;AAAA,MAGF,gBAAAU;AAAA,QAACC,EAAgB;AAAA,QAAhB;AAAA,UACC,KAAAhB;AAAA,UACA,OAAAJ;AAAA,UACA,cAAAC;AAAA,UACA,eAAe,CAACF,MAAM;AACpB,YAAKS,KAAcF,EAAYP,CAAC,GAChCG,KAAA,QAAAA,EAAgBH;AAAA,UAClB;AAAA,UACA,WAAU;AAAA,UACV,mBAAiBH,KAAS,CAACmB,IAAcJ,IAAU;AAAA,UAClD,GAAGR;AAAA,UAEJ,UAAA;AAAA,YAAA,gBAAAkB,EAACD,EAAgB,OAAhB,EAAsB,WAAU,6EAC/B,UAAA,gBAAAC,EAACD,EAAgB,OAAhB,EAAsB,WAAU,4BAAA,CAA4B,EAAA,CAC/D;AAAA,YACCX,EAAa,IAAI,CAACa,GAAGL,MACpB,gBAAAI;AAAA,cAACD,EAAgB;AAAA,cAAhB;AAAA,gBAEC,WAAWF;AAAA,kBACT;AAAA;AAAA,kBAEA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBAAA;AAAA,gBAEF,cAAYF,EAAWC,CAAC;AAAA,gBACxB,mBAAiB,CAACP,KAAWd,KAAS,CAACmB,IAAcJ,IAAU;AAAA,cAAA;AAAA,cAV1DM;AAAA,YAAA,CAYR;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IACH,GACF;AAAA,EAEJ;AACF;AAEAxB,EAAO,cAAc;"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { VariantProps } from '../../lib/cva.js';
|
|
3
|
+
declare const snackbar: (props?: ({
|
|
4
|
+
variant?: "default" | "success" | "warning" | "danger" | "info" | null | undefined;
|
|
5
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
|
+
export interface SnackbarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'>, VariantProps<typeof snackbar> {
|
|
7
|
+
/** Headline. */
|
|
8
|
+
title?: ReactNode;
|
|
9
|
+
/** Action button rendered on the right. */
|
|
10
|
+
action?: ReactNode;
|
|
11
|
+
/** Show a close (×) button on the right. */
|
|
12
|
+
onClose?: () => void;
|
|
13
|
+
/** Override the variant's default icon. Pass `false` to hide. */
|
|
14
|
+
icon?: ReactNode | false;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Persistent inline notification. Unlike Toast, Snackbar does **not** auto-
|
|
18
|
+
* dismiss. Pair with an `action` button or an `onClose` handler.
|
|
19
|
+
*/
|
|
20
|
+
export declare const Snackbar: import('react').ForwardRefExoticComponent<SnackbarProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as i, jsx as e } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef as m } from "react";
|
|
4
|
+
import { X as b, XCircle as g, AlertTriangle as x, CheckCircle2 as h, Info as p } from "../../icons/index.js";
|
|
5
|
+
import { cn as v } from "../../lib/utils.js";
|
|
6
|
+
import { useStrings as k } from "../../hooks/use-strings.js";
|
|
7
|
+
import { cva as N } from "class-variance-authority";
|
|
8
|
+
const w = N(
|
|
9
|
+
[
|
|
10
|
+
"relative pointer-events-auto w-full max-w-md",
|
|
11
|
+
"flex items-start gap-3 rounded-md border bg-card p-3 shadow-md",
|
|
12
|
+
"text-sm text-foreground"
|
|
13
|
+
],
|
|
14
|
+
{
|
|
15
|
+
variants: {
|
|
16
|
+
variant: {
|
|
17
|
+
default: "border-border",
|
|
18
|
+
info: "border-info-border-soft",
|
|
19
|
+
success: "border-success-border-soft",
|
|
20
|
+
warning: "border-warning-border-soft",
|
|
21
|
+
danger: "border-danger-border-soft"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: { variant: "default" }
|
|
25
|
+
}
|
|
26
|
+
), z = {
|
|
27
|
+
default: null,
|
|
28
|
+
info: /* @__PURE__ */ e(p, { className: "text-info-text mt-0.5 size-4 shrink-0", "aria-hidden": !0 }),
|
|
29
|
+
success: /* @__PURE__ */ e(h, { className: "text-success-text mt-0.5 size-4 shrink-0", "aria-hidden": !0 }),
|
|
30
|
+
warning: /* @__PURE__ */ e(x, { className: "text-warning-text mt-0.5 size-4 shrink-0", "aria-hidden": !0 }),
|
|
31
|
+
danger: /* @__PURE__ */ e(g, { className: "text-danger-text mt-0.5 size-4 shrink-0", "aria-hidden": !0 })
|
|
32
|
+
}, S = m(function({ className: o, variant: r = "default", title: t, action: d, onClose: s, icon: a, children: n, ...c }, l) {
|
|
33
|
+
const u = k(), f = a === !1 ? null : a ?? z[r ?? "default"];
|
|
34
|
+
return /* @__PURE__ */ i("div", { ref: l, role: "status", className: v(w({ variant: r }), o), ...c, children: [
|
|
35
|
+
f,
|
|
36
|
+
/* @__PURE__ */ i("div", { className: "min-w-0 flex-1", children: [
|
|
37
|
+
t && /* @__PURE__ */ e("p", { className: "font-medium", children: t }),
|
|
38
|
+
n && /* @__PURE__ */ e("p", { className: "text-foreground-muted", children: n })
|
|
39
|
+
] }),
|
|
40
|
+
d,
|
|
41
|
+
s && /* @__PURE__ */ e(
|
|
42
|
+
"button",
|
|
43
|
+
{
|
|
44
|
+
type: "button",
|
|
45
|
+
onClick: s,
|
|
46
|
+
"aria-label": u.snackbar.dismiss,
|
|
47
|
+
className: "text-foreground-muted hover:bg-background-muted hover:text-foreground focus-visible:ring-ring focus-visible:ring-offset-card rounded p-1 outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
48
|
+
children: /* @__PURE__ */ e(b, { className: "size-4", "aria-hidden": !0 })
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
] });
|
|
52
|
+
});
|
|
53
|
+
S.displayName = "Snackbar";
|
|
54
|
+
export {
|
|
55
|
+
S as Snackbar
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=Snackbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Snackbar.js","sources":["../../../src/components/ui/Snackbar.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { CheckCircle2, Info, AlertTriangle, XCircle, X } from '@/icons';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\nimport { cva, type VariantProps } from '@/lib/cva';\n\nconst snackbar = cva(\n [\n 'relative pointer-events-auto w-full max-w-md',\n 'flex items-start gap-3 rounded-md border bg-card p-3 shadow-md',\n 'text-sm text-foreground',\n ],\n {\n variants: {\n variant: {\n default: 'border-border',\n info: 'border-info-border-soft',\n success: 'border-success-border-soft',\n warning: 'border-warning-border-soft',\n danger: 'border-danger-border-soft',\n },\n },\n defaultVariants: { variant: 'default' },\n },\n);\n\nconst iconForVariant: Record<NonNullable<VariantProps<typeof snackbar>['variant']>, ReactNode> = {\n default: null,\n info: <Info className=\"text-info-text mt-0.5 size-4 shrink-0\" aria-hidden />,\n success: <CheckCircle2 className=\"text-success-text mt-0.5 size-4 shrink-0\" aria-hidden />,\n warning: <AlertTriangle className=\"text-warning-text mt-0.5 size-4 shrink-0\" aria-hidden />,\n danger: <XCircle className=\"text-danger-text mt-0.5 size-4 shrink-0\" aria-hidden />,\n};\n\nexport interface SnackbarProps\n extends Omit<HTMLAttributes<HTMLDivElement>, 'title'>, VariantProps<typeof snackbar> {\n /** Headline. */\n title?: ReactNode;\n /** Action button rendered on the right. */\n action?: ReactNode;\n /** Show a close (×) button on the right. */\n onClose?: () => void;\n /** Override the variant's default icon. Pass `false` to hide. */\n icon?: ReactNode | false;\n}\n\n/**\n * Persistent inline notification. Unlike Toast, Snackbar does **not** auto-\n * dismiss. Pair with an `action` button or an `onClose` handler.\n */\nexport const Snackbar = forwardRef<HTMLDivElement, SnackbarProps>(function Snackbar(\n { className, variant = 'default', title, action, onClose, icon, children, ...props },\n ref,\n) {\n const strings = useStrings();\n const renderedIcon = icon === false ? null : (icon ?? iconForVariant[variant ?? 'default']);\n\n return (\n <div ref={ref} role=\"status\" className={cn(snackbar({ variant }), className)} {...props}>\n {renderedIcon}\n <div className=\"min-w-0 flex-1\">\n {title && <p className=\"font-medium\">{title}</p>}\n {children && <p className=\"text-foreground-muted\">{children}</p>}\n </div>\n {action}\n {onClose && (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={strings.snackbar.dismiss}\n className=\"text-foreground-muted hover:bg-background-muted hover:text-foreground focus-visible:ring-ring focus-visible:ring-offset-card rounded p-1 outline-none focus-visible:ring-2 focus-visible:ring-offset-2\"\n >\n <X className=\"size-4\" aria-hidden />\n </button>\n )}\n </div>\n );\n});\nSnackbar.displayName = 'Snackbar';\n"],"names":["snackbar","cva","iconForVariant","jsx","Info","CheckCircle2","AlertTriangle","XCircle","Snackbar","forwardRef","className","variant","title","action","onClose","icon","children","props","ref","strings","useStrings","renderedIcon","jsxs","cn","X"],"mappings":";;;;;;;AAQA,MAAMA,IAAWC;AAAA,EACf;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAAA,EAEF;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,QACT,QAAQ;AAAA,MAAA;AAAA,IACV;AAAA,IAEF,iBAAiB,EAAE,SAAS,UAAA;AAAA,EAAU;AAE1C,GAEMC,IAA2F;AAAA,EAC/F,SAAS;AAAA,EACT,MAAM,gBAAAC,EAACC,GAAA,EAAK,WAAU,yCAAwC,eAAW,IAAC;AAAA,EAC1E,SAAS,gBAAAD,EAACE,GAAA,EAAa,WAAU,4CAA2C,eAAW,IAAC;AAAA,EACxF,SAAS,gBAAAF,EAACG,GAAA,EAAc,WAAU,4CAA2C,eAAW,IAAC;AAAA,EACzF,QAAQ,gBAAAH,EAACI,GAAA,EAAQ,WAAU,2CAA0C,eAAW,GAAA,CAAC;AACnF,GAkBaC,IAAWC,EAA0C,SAChE,EAAE,WAAAC,GAAW,SAAAC,IAAU,WAAW,OAAAC,GAAO,QAAAC,GAAQ,SAAAC,GAAS,MAAAC,GAAM,UAAAC,GAAU,GAAGC,EAAA,GAC7EC,GACA;AACA,QAAMC,IAAUC,EAAA,GACVC,IAAeN,MAAS,KAAQ,OAAQA,KAAQb,EAAeS,KAAW,SAAS;AAEzF,SACE,gBAAAW,EAAC,OAAA,EAAI,KAAAJ,GAAU,MAAK,UAAS,WAAWK,EAAGvB,EAAS,EAAE,SAAAW,GAAS,GAAGD,CAAS,GAAI,GAAGO,GAC/E,UAAA;AAAA,IAAAI;AAAA,IACD,gBAAAC,EAAC,OAAA,EAAI,WAAU,kBACZ,UAAA;AAAA,MAAAV,KAAS,gBAAAT,EAAC,KAAA,EAAE,WAAU,eAAe,UAAAS,GAAM;AAAA,MAC3CI,KAAY,gBAAAb,EAAC,KAAA,EAAE,WAAU,yBAAyB,UAAAa,EAAA,CAAS;AAAA,IAAA,GAC9D;AAAA,IACCH;AAAA,IACAC,KACC,gBAAAX;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAASW;AAAA,QACT,cAAYK,EAAQ,SAAS;AAAA,QAC7B,WAAU;AAAA,QAEV,UAAA,gBAAAhB,EAACqB,GAAA,EAAE,WAAU,UAAS,eAAW,GAAA,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EACpC,GAEJ;AAEJ,CAAC;AACDhB,EAAS,cAAc;"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SVGProps } from 'react';
|
|
2
|
+
export interface SpinnerProps extends SVGProps<SVGSVGElement> {
|
|
3
|
+
/** Visual weight. */
|
|
4
|
+
tone?: 'accent' | 'neutral' | 'on-accent';
|
|
5
|
+
/** Pixel size. */
|
|
6
|
+
size?: 'sm' | 'md' | 'lg';
|
|
7
|
+
/** Accessible label. Required unless `decorative` is true. */
|
|
8
|
+
label?: string;
|
|
9
|
+
/** Hide from assistive tech (set when a parent already announces busy state). */
|
|
10
|
+
decorative?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Small indeterminate progress indicator. Use when the operation duration is
|
|
14
|
+
* unknown and Progress isn't appropriate.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* <Spinner label="Loading users" />
|
|
18
|
+
* <Button loading>Saving…</Button> // uses Spinner internally
|
|
19
|
+
*
|
|
20
|
+
* @do Provide a `label` so the busy state is announced.
|
|
21
|
+
* @dont Use a Spinner for tasks that take 300ms+; use Skeleton instead.
|
|
22
|
+
*/
|
|
23
|
+
export declare const Spinner: import('react').ForwardRefExoticComponent<Omit<SpinnerProps, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as l, jsx as n } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef as p } from "react";
|
|
4
|
+
import { cn as d } from "../../lib/utils.js";
|
|
5
|
+
import { useStrings as m } from "../../hooks/use-strings.js";
|
|
6
|
+
const u = { sm: "size-3.5", md: "size-4", lg: "size-6" }, f = {
|
|
7
|
+
accent: "text-accent",
|
|
8
|
+
neutral: "text-foreground-subtle",
|
|
9
|
+
"on-accent": "text-on-accent"
|
|
10
|
+
}, x = p(function({ className: t, tone: o = "accent", size: r = "md", label: i, decorative: e, ...s }, a) {
|
|
11
|
+
const c = m();
|
|
12
|
+
return /* @__PURE__ */ l(
|
|
13
|
+
"svg",
|
|
14
|
+
{
|
|
15
|
+
ref: a,
|
|
16
|
+
viewBox: "0 0 24 24",
|
|
17
|
+
role: e ? void 0 : "status",
|
|
18
|
+
"aria-label": e ? void 0 : i ?? c.spinner.loading,
|
|
19
|
+
"aria-hidden": e || void 0,
|
|
20
|
+
"data-motion-keep": "",
|
|
21
|
+
className: d("animate-spin", u[r], f[o], t),
|
|
22
|
+
...s,
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ n(
|
|
25
|
+
"circle",
|
|
26
|
+
{
|
|
27
|
+
cx: "12",
|
|
28
|
+
cy: "12",
|
|
29
|
+
r: "10",
|
|
30
|
+
stroke: "currentColor",
|
|
31
|
+
strokeWidth: "2.5",
|
|
32
|
+
strokeOpacity: 0.2,
|
|
33
|
+
fill: "none"
|
|
34
|
+
}
|
|
35
|
+
),
|
|
36
|
+
/* @__PURE__ */ n(
|
|
37
|
+
"path",
|
|
38
|
+
{
|
|
39
|
+
d: "M12 2a10 10 0 0 1 10 10",
|
|
40
|
+
stroke: "currentColor",
|
|
41
|
+
strokeWidth: "2.5",
|
|
42
|
+
strokeLinecap: "round",
|
|
43
|
+
fill: "none"
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
x.displayName = "Spinner";
|
|
51
|
+
export {
|
|
52
|
+
x as Spinner
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=Spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Spinner.js","sources":["../../../src/components/ui/Spinner.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef, type SVGProps } from 'react';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\n\nexport interface SpinnerProps extends SVGProps<SVGSVGElement> {\n /** Visual weight. */\n tone?: 'accent' | 'neutral' | 'on-accent';\n /** Pixel size. */\n size?: 'sm' | 'md' | 'lg';\n /** Accessible label. Required unless `decorative` is true. */\n label?: string;\n /** Hide from assistive tech (set when a parent already announces busy state). */\n decorative?: boolean;\n}\n\nconst sizeMap = { sm: 'size-3.5', md: 'size-4', lg: 'size-6' };\nconst toneMap = {\n accent: 'text-accent',\n neutral: 'text-foreground-subtle',\n 'on-accent': 'text-on-accent',\n};\n\n/**\n * Small indeterminate progress indicator. Use when the operation duration is\n * unknown and Progress isn't appropriate.\n *\n * @example\n * <Spinner label=\"Loading users\" />\n * <Button loading>Saving…</Button> // uses Spinner internally\n *\n * @do Provide a `label` so the busy state is announced.\n * @dont Use a Spinner for tasks that take 300ms+; use Skeleton instead.\n */\nexport const Spinner = forwardRef<SVGSVGElement, SpinnerProps>(function Spinner(\n { className, tone = 'accent', size = 'md', label, decorative, ...props },\n ref,\n) {\n const strings = useStrings();\n return (\n <svg\n ref={ref}\n viewBox=\"0 0 24 24\"\n role={decorative ? undefined : 'status'}\n aria-label={decorative ? undefined : (label ?? strings.spinner.loading)}\n aria-hidden={decorative || undefined}\n // Under prefers-reduced-motion theme.css swaps the spin for a slow\n // (1.6s) opacity pulse via this attribute — busy state stays perceivable.\n data-motion-keep=\"\"\n className={cn('animate-spin', sizeMap[size], toneMap[tone], className)}\n {...props}\n >\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeOpacity={0.2}\n fill=\"none\"\n />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n fill=\"none\"\n />\n </svg>\n );\n});\nSpinner.displayName = 'Spinner';\n"],"names":["sizeMap","toneMap","Spinner","forwardRef","className","tone","size","label","decorative","props","ref","strings","useStrings","jsxs","cn","jsx"],"mappings":";;;;;AAiBA,MAAMA,IAAU,EAAE,IAAI,YAAY,IAAI,UAAU,IAAI,SAAA,GAC9CC,IAAU;AAAA,EACd,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,aAAa;AACf,GAaaC,IAAUC,EAAwC,SAC7D,EAAE,WAAAC,GAAW,MAAAC,IAAO,UAAU,MAAAC,IAAO,MAAM,OAAAC,GAAO,YAAAC,GAAY,GAAGC,EAAA,GACjEC,GACA;AACA,QAAMC,IAAUC,EAAA;AAChB,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAH;AAAA,MACA,SAAQ;AAAA,MACR,MAAMF,IAAa,SAAY;AAAA,MAC/B,cAAYA,IAAa,SAAaD,KAASI,EAAQ,QAAQ;AAAA,MAC/D,eAAaH,KAAc;AAAA,MAG3B,oBAAiB;AAAA,MACjB,WAAWM,EAAG,gBAAgBd,EAAQM,CAAI,GAAGL,EAAQI,CAAI,GAAGD,CAAS;AAAA,MACpE,GAAGK;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAM;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,IAAG;AAAA,YACH,IAAG;AAAA,YACH,GAAE;AAAA,YACF,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAe;AAAA,YACf,MAAK;AAAA,UAAA;AAAA,QAAA;AAAA,QAEP,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,GAAE;AAAA,YACF,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,YACd,MAAK;AAAA,UAAA;AAAA,QAAA;AAAA,MACP;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;AACDb,EAAQ,cAAc;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface Step {
|
|
3
|
+
/** Step heading. */
|
|
4
|
+
title: ReactNode;
|
|
5
|
+
/** Optional secondary description, only shown in vertical orientation. */
|
|
6
|
+
description?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export interface StepperProps extends HTMLAttributes<HTMLOListElement> {
|
|
9
|
+
/** Ordered list of steps. */
|
|
10
|
+
steps: Step[];
|
|
11
|
+
/** 0-indexed active step. Steps before it are marked complete. */
|
|
12
|
+
current: number;
|
|
13
|
+
/** Layout direction. */
|
|
14
|
+
orientation?: 'horizontal' | 'vertical';
|
|
15
|
+
/** sr-only state words announced after each title (i18n). */
|
|
16
|
+
stateLabels?: {
|
|
17
|
+
complete: string;
|
|
18
|
+
current: string;
|
|
19
|
+
upcoming: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Multi-step progress indicator. Use the horizontal variant in narrow flows
|
|
24
|
+
* (top of an onboarding modal) and vertical for deeper context.
|
|
25
|
+
*
|
|
26
|
+
* @example Onboarding
|
|
27
|
+
* <Stepper
|
|
28
|
+
* current={step}
|
|
29
|
+
* steps={[
|
|
30
|
+
* { title: 'Workspace' },
|
|
31
|
+
* { title: 'Invite team' },
|
|
32
|
+
* { title: 'Connect data' },
|
|
33
|
+
* { title: 'Done' },
|
|
34
|
+
* ]}
|
|
35
|
+
* />
|
|
36
|
+
*
|
|
37
|
+
* @do Keep titles 1–2 words. Save explanations for the page body.
|
|
38
|
+
* @dont Use Stepper for free-form navigation. It implies a linear flow.
|
|
39
|
+
*/
|
|
40
|
+
export declare const Stepper: import('react').ForwardRefExoticComponent<StepperProps & import('react').RefAttributes<HTMLOListElement>>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef as b } from "react";
|
|
4
|
+
import { Check as h } from "../../icons/index.js";
|
|
5
|
+
import { cn as e } from "../../lib/utils.js";
|
|
6
|
+
import { useStrings as N } from "../../hooks/use-strings.js";
|
|
7
|
+
const z = b(function({
|
|
8
|
+
steps: i,
|
|
9
|
+
current: a,
|
|
10
|
+
orientation: t = "horizontal",
|
|
11
|
+
stateLabels: p,
|
|
12
|
+
className: d,
|
|
13
|
+
"aria-label": f,
|
|
14
|
+
...x
|
|
15
|
+
}, u) {
|
|
16
|
+
const n = N(), g = p ?? {
|
|
17
|
+
complete: n.stepper.complete,
|
|
18
|
+
current: n.stepper.current,
|
|
19
|
+
upcoming: n.stepper.upcoming
|
|
20
|
+
};
|
|
21
|
+
return /* @__PURE__ */ s(
|
|
22
|
+
"ol",
|
|
23
|
+
{
|
|
24
|
+
ref: u,
|
|
25
|
+
"aria-label": f ?? n.stepper.label,
|
|
26
|
+
className: e(
|
|
27
|
+
t === "horizontal" ? "flex w-full items-center" : "flex flex-col gap-6",
|
|
28
|
+
d
|
|
29
|
+
),
|
|
30
|
+
...x,
|
|
31
|
+
children: i.map((o, r) => {
|
|
32
|
+
const l = r < a ? "complete" : r === a ? "current" : "upcoming", m = r === i.length - 1;
|
|
33
|
+
return /* @__PURE__ */ c(
|
|
34
|
+
"li",
|
|
35
|
+
{
|
|
36
|
+
"aria-current": l === "current" ? "step" : void 0,
|
|
37
|
+
className: e(
|
|
38
|
+
t === "horizontal" ? "flex flex-1 items-center gap-3 last:flex-initial" : "flex items-start gap-3"
|
|
39
|
+
),
|
|
40
|
+
children: [
|
|
41
|
+
/* @__PURE__ */ c(
|
|
42
|
+
"div",
|
|
43
|
+
{
|
|
44
|
+
className: e(
|
|
45
|
+
t === "horizontal" ? "flex items-center gap-3" : "flex flex-col items-center"
|
|
46
|
+
),
|
|
47
|
+
children: [
|
|
48
|
+
/* @__PURE__ */ s(
|
|
49
|
+
"span",
|
|
50
|
+
{
|
|
51
|
+
"aria-hidden": !0,
|
|
52
|
+
className: e(
|
|
53
|
+
"inline-flex size-7 items-center justify-center rounded-full text-xs font-semibold transition-colors",
|
|
54
|
+
l === "complete" && "bg-accent text-on-accent",
|
|
55
|
+
l === "current" && "bg-card border-accent text-accent border-2",
|
|
56
|
+
l === "upcoming" && "bg-background-muted text-foreground-subtle border-border border"
|
|
57
|
+
),
|
|
58
|
+
children: l === "complete" ? /* @__PURE__ */ s(h, { className: "size-4" }) : r + 1
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
t === "vertical" && !m && /* @__PURE__ */ s(
|
|
62
|
+
"span",
|
|
63
|
+
{
|
|
64
|
+
className: e(
|
|
65
|
+
"mt-1 min-h-6 w-px flex-1",
|
|
66
|
+
r < a ? "bg-accent" : "bg-border"
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ c("div", { className: e("flex flex-col", t === "horizontal" && "min-w-0"), children: [
|
|
74
|
+
/* @__PURE__ */ c(
|
|
75
|
+
"span",
|
|
76
|
+
{
|
|
77
|
+
className: e(
|
|
78
|
+
"text-sm font-medium",
|
|
79
|
+
l === "upcoming" ? "text-foreground-subtle" : "text-foreground"
|
|
80
|
+
),
|
|
81
|
+
children: [
|
|
82
|
+
o.title,
|
|
83
|
+
/* @__PURE__ */ c("span", { className: "sr-only", children: [
|
|
84
|
+
", ",
|
|
85
|
+
g[l]
|
|
86
|
+
] })
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
),
|
|
90
|
+
t === "vertical" && o.description && /* @__PURE__ */ s("p", { className: "text-foreground-muted mt-0.5 text-xs", children: o.description })
|
|
91
|
+
] }),
|
|
92
|
+
t === "horizontal" && !m && /* @__PURE__ */ s(
|
|
93
|
+
"span",
|
|
94
|
+
{
|
|
95
|
+
"aria-hidden": !0,
|
|
96
|
+
className: e("mx-2 h-px flex-1", r < a ? "bg-accent" : "bg-border")
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
r
|
|
102
|
+
);
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
z.displayName = "Stepper";
|
|
108
|
+
export {
|
|
109
|
+
z as Stepper
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=Stepper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stepper.js","sources":["../../../src/components/ui/Stepper.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { Check } from '@/icons';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\n\nexport interface Step {\n /** Step heading. */\n title: ReactNode;\n /** Optional secondary description, only shown in vertical orientation. */\n description?: ReactNode;\n}\n\nexport interface StepperProps extends HTMLAttributes<HTMLOListElement> {\n /** Ordered list of steps. */\n steps: Step[];\n /** 0-indexed active step. Steps before it are marked complete. */\n current: number;\n /** Layout direction. */\n orientation?: 'horizontal' | 'vertical';\n /** sr-only state words announced after each title (i18n). */\n stateLabels?: { complete: string; current: string; upcoming: string };\n}\n\n/**\n * Multi-step progress indicator. Use the horizontal variant in narrow flows\n * (top of an onboarding modal) and vertical for deeper context.\n *\n * @example Onboarding\n * <Stepper\n * current={step}\n * steps={[\n * { title: 'Workspace' },\n * { title: 'Invite team' },\n * { title: 'Connect data' },\n * { title: 'Done' },\n * ]}\n * />\n *\n * @do Keep titles 1–2 words. Save explanations for the page body.\n * @dont Use Stepper for free-form navigation. It implies a linear flow.\n */\nexport const Stepper = forwardRef<HTMLOListElement, StepperProps>(function Stepper(\n {\n steps,\n current,\n orientation = 'horizontal',\n stateLabels: stateLabelsProp,\n className,\n 'aria-label': ariaLabel,\n ...props\n },\n ref,\n) {\n const strings = useStrings();\n const stateLabels = stateLabelsProp ?? {\n complete: strings.stepper.complete,\n current: strings.stepper.current,\n upcoming: strings.stepper.upcoming,\n };\n return (\n <ol\n ref={ref}\n aria-label={ariaLabel ?? strings.stepper.label}\n className={cn(\n orientation === 'horizontal' ? 'flex w-full items-center' : 'flex flex-col gap-6',\n className,\n )}\n {...props}\n >\n {steps.map((step, i) => {\n const state = i < current ? 'complete' : i === current ? 'current' : 'upcoming';\n const isLast = i === steps.length - 1;\n return (\n <li\n key={i}\n aria-current={state === 'current' ? 'step' : undefined}\n className={cn(\n orientation === 'horizontal'\n ? 'flex flex-1 items-center gap-3 last:flex-initial'\n : 'flex items-start gap-3',\n )}\n >\n <div\n className={cn(\n orientation === 'horizontal'\n ? 'flex items-center gap-3'\n : 'flex flex-col items-center',\n )}\n >\n <span\n aria-hidden\n className={cn(\n 'inline-flex size-7 items-center justify-center rounded-full text-xs font-semibold transition-colors',\n state === 'complete' && 'bg-accent text-on-accent',\n state === 'current' && 'bg-card border-accent text-accent border-2',\n state === 'upcoming' &&\n 'bg-background-muted text-foreground-subtle border-border border',\n )}\n >\n {state === 'complete' ? <Check className=\"size-4\" /> : i + 1}\n </span>\n {orientation === 'vertical' && !isLast && (\n <span\n className={cn(\n 'mt-1 min-h-6 w-px flex-1',\n i < current ? 'bg-accent' : 'bg-border',\n )}\n />\n )}\n </div>\n <div className={cn('flex flex-col', orientation === 'horizontal' && 'min-w-0')}>\n <span\n className={cn(\n 'text-sm font-medium',\n state === 'upcoming' ? 'text-foreground-subtle' : 'text-foreground',\n )}\n >\n {step.title}\n <span className=\"sr-only\">, {stateLabels[state]}</span>\n </span>\n {orientation === 'vertical' && step.description && (\n <p className=\"text-foreground-muted mt-0.5 text-xs\">{step.description}</p>\n )}\n </div>\n {orientation === 'horizontal' && !isLast && (\n <span\n aria-hidden\n className={cn('mx-2 h-px flex-1', i < current ? 'bg-accent' : 'bg-border')}\n />\n )}\n </li>\n );\n })}\n </ol>\n );\n});\nStepper.displayName = 'Stepper';\n"],"names":["Stepper","forwardRef","steps","current","orientation","stateLabelsProp","className","ariaLabel","props","ref","strings","useStrings","stateLabels","jsx","cn","step","i","state","isLast","jsxs","Check"],"mappings":";;;;;;AA2CO,MAAMA,IAAUC,EAA2C,SAChE;AAAA,EACE,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,aAAaC;AAAA,EACb,WAAAC;AAAA,EACA,cAAcC;AAAA,EACd,GAAGC;AACL,GACAC,GACA;AACA,QAAMC,IAAUC,EAAA,GACVC,IAAcP,KAAmB;AAAA,IACrC,UAAUK,EAAQ,QAAQ;AAAA,IAC1B,SAASA,EAAQ,QAAQ;AAAA,IACzB,UAAUA,EAAQ,QAAQ;AAAA,EAAA;AAE5B,SACE,gBAAAG;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAJ;AAAA,MACA,cAAYF,KAAaG,EAAQ,QAAQ;AAAA,MACzC,WAAWI;AAAA,QACTV,MAAgB,eAAe,6BAA6B;AAAA,QAC5DE;AAAA,MAAA;AAAA,MAED,GAAGE;AAAA,MAEH,UAAAN,EAAM,IAAI,CAACa,GAAMC,MAAM;AACtB,cAAMC,IAAQD,IAAIb,IAAU,aAAaa,MAAMb,IAAU,YAAY,YAC/De,IAASF,MAAMd,EAAM,SAAS;AACpC,eACE,gBAAAiB;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,gBAAcF,MAAU,YAAY,SAAS;AAAA,YAC7C,WAAWH;AAAA,cACTV,MAAgB,eACZ,qDACA;AAAA,YAAA;AAAA,YAGN,UAAA;AAAA,cAAA,gBAAAe;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAWL;AAAA,oBACTV,MAAgB,eACZ,4BACA;AAAA,kBAAA;AAAA,kBAGN,UAAA;AAAA,oBAAA,gBAAAS;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,eAAW;AAAA,wBACX,WAAWC;AAAA,0BACT;AAAA,0BACAG,MAAU,cAAc;AAAA,0BACxBA,MAAU,aAAa;AAAA,0BACvBA,MAAU,cACR;AAAA,wBAAA;AAAA,wBAGH,gBAAU,aAAa,gBAAAJ,EAACO,KAAM,WAAU,UAAS,IAAKJ,IAAI;AAAA,sBAAA;AAAA,oBAAA;AAAA,oBAE5DZ,MAAgB,cAAc,CAACc,KAC9B,gBAAAL;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,WAAWC;AAAA,0BACT;AAAA,0BACAE,IAAIb,IAAU,cAAc;AAAA,wBAAA;AAAA,sBAC9B;AAAA,oBAAA;AAAA,kBACF;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGJ,gBAAAgB,EAAC,SAAI,WAAWL,EAAG,iBAAiBV,MAAgB,gBAAgB,SAAS,GAC3E,UAAA;AAAA,gBAAA,gBAAAe;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAWL;AAAA,sBACT;AAAA,sBACAG,MAAU,aAAa,2BAA2B;AAAA,oBAAA;AAAA,oBAGnD,UAAA;AAAA,sBAAAF,EAAK;AAAA,sBACN,gBAAAI,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA;AAAA,wBAAA;AAAA,wBAAGP,EAAYK,CAAK;AAAA,sBAAA,EAAA,CAAE;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEjDb,MAAgB,cAAcW,EAAK,iCACjC,KAAA,EAAE,WAAU,wCAAwC,UAAAA,EAAK,YAAA,CAAY;AAAA,cAAA,GAE1E;AAAA,cACCX,MAAgB,gBAAgB,CAACc,KAChC,gBAAAL;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,eAAW;AAAA,kBACX,WAAWC,EAAG,oBAAoBE,IAAIb,IAAU,cAAc,WAAW;AAAA,gBAAA;AAAA,cAAA;AAAA,YAC3E;AAAA,UAAA;AAAA,UAtDGa;AAAA,QAAA;AAAA,MA0DX,CAAC;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AACDhB,EAAQ,cAAc;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
|
+
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
|
3
|
+
export interface SwitchProps extends Omit<ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>, 'asChild'> {
|
|
4
|
+
/** Inline label rendered to the right. */
|
|
5
|
+
label?: ReactNode;
|
|
6
|
+
/** Secondary description rendered below the label. */
|
|
7
|
+
description?: ReactNode;
|
|
8
|
+
/** Position the label before the switch instead of after. */
|
|
9
|
+
labelPosition?: 'before' | 'after';
|
|
10
|
+
/** Visual size. */
|
|
11
|
+
size?: 'sm' | 'md';
|
|
12
|
+
/** Hide the label visually while keeping it accessible. */
|
|
13
|
+
hideLabel?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Binary on/off toggle for instant-apply settings. Use Checkbox when the
|
|
17
|
+
* choice is part of a form that needs explicit submission.
|
|
18
|
+
*
|
|
19
|
+
* @example Instant toggle
|
|
20
|
+
* <Switch label="Email digest" checked={on} onCheckedChange={setOn} />
|
|
21
|
+
*
|
|
22
|
+
* @example With description
|
|
23
|
+
* <Switch label="Two-factor authentication"
|
|
24
|
+
* description="Required for admins on production accounts."
|
|
25
|
+
* checked={tfa}
|
|
26
|
+
* onCheckedChange={setTfa} />
|
|
27
|
+
*
|
|
28
|
+
* @do Use Switch when the change takes effect immediately. Pair with
|
|
29
|
+
* a toast confirming the new state.
|
|
30
|
+
* @dont Use Switch inside a form that requires submission — Checkbox
|
|
31
|
+
* better matches that mental model.
|
|
32
|
+
*/
|
|
33
|
+
export declare const Switch: import('react').ForwardRefExoticComponent<SwitchProps & import('react').RefAttributes<HTMLButtonElement>>;
|