@alpic-ai/ui 0.0.0-dev.fffc79a → 0.0.0-dev.g01173d7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/accordion-card.d.mts +4 -5
- package/dist/components/accordion.d.mts +4 -5
- package/dist/components/alert.d.mts +6 -8
- package/dist/components/attachment-tile.d.mts +1 -3
- package/dist/components/avatar.d.mts +5 -7
- package/dist/components/badge.d.mts +2 -4
- package/dist/components/breadcrumb.d.mts +8 -9
- package/dist/components/button.d.mts +2 -4
- package/dist/components/card.d.mts +7 -8
- package/dist/components/checkbox.d.mts +1 -2
- package/dist/components/collapsible.d.mts +3 -4
- package/dist/components/combobox.d.mts +12 -11
- package/dist/components/combobox.mjs +7 -4
- package/dist/components/command.d.mts +8 -9
- package/dist/components/copyable.d.mts +2 -3
- package/dist/components/description-list.d.mts +4 -5
- package/dist/components/dialog.d.mts +12 -14
- package/dist/components/dropdown-menu.d.mts +14 -16
- package/dist/components/form.d.mts +68 -16
- package/dist/components/form.mjs +114 -4
- package/dist/components/github-button.d.mts +1 -2
- package/dist/components/input-group.d.mts +4 -6
- package/dist/components/input.d.mts +1 -2
- package/dist/components/label.d.mts +1 -2
- package/dist/components/page-loader.d.mts +1 -3
- package/dist/components/pagination.d.mts +1 -2
- package/dist/components/popover.d.mts +4 -5
- package/dist/components/radio-group.d.mts +2 -3
- package/dist/components/scroll-area.d.mts +2 -3
- package/dist/components/select-trigger-variants.d.mts +1 -3
- package/dist/components/select.d.mts +8 -9
- package/dist/components/separator.d.mts +1 -2
- package/dist/components/sheet.d.mts +9 -10
- package/dist/components/shimmer-text.d.mts +10 -0
- package/dist/components/shimmer-text.mjs +22 -0
- package/dist/components/sidebar.d.mts +23 -25
- package/dist/components/skeleton.d.mts +2 -4
- package/dist/components/sonner.d.mts +2 -3
- package/dist/components/spinner.d.mts +3 -5
- package/dist/components/status-dot.d.mts +2 -4
- package/dist/components/switch.d.mts +1 -2
- package/dist/components/table.d.mts +8 -9
- package/dist/components/table.mjs +3 -3
- package/dist/components/tabs.d.mts +9 -11
- package/dist/components/tabs.mjs +4 -4
- package/dist/components/tag.d.mts +3 -5
- package/dist/components/task-progress.d.mts +25 -0
- package/dist/components/task-progress.mjs +66 -0
- package/dist/components/textarea.d.mts +1 -2
- package/dist/components/toggle-group.d.mts +3 -5
- package/dist/components/tooltip-icon-button.d.mts +1 -2
- package/dist/components/tooltip.d.mts +4 -5
- package/dist/components/tooltip.mjs +1 -1
- package/dist/components/typography.d.mts +4 -5
- package/dist/components/wizard.d.mts +33 -0
- package/dist/components/wizard.mjs +46 -0
- package/package.json +13 -13
- package/src/components/combobox.tsx +9 -2
- package/src/components/form.tsx +164 -3
- package/src/components/shimmer-text.tsx +23 -0
- package/src/components/table.tsx +2 -3
- package/src/components/tabs.tsx +4 -4
- package/src/components/task-progress.tsx +107 -0
- package/src/components/tooltip.tsx +1 -1
- package/src/components/wizard.tsx +69 -0
- package/src/stories/form.stories.tsx +64 -2
- package/src/stories/tabs.stories.tsx +4 -2
- package/src/stories/task-progress.stories.tsx +81 -0
- package/src/stories/wizard.stories.tsx +64 -0
- package/src/styles/tokens.css +11 -4
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
1
|
import { VariantProps } from "class-variance-authority";
|
|
3
2
|
import * as React from "react";
|
|
4
3
|
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
|
|
5
|
-
import * as _$class_variance_authority_types0 from "class-variance-authority/types";
|
|
6
4
|
|
|
7
5
|
//#region src/components/toggle-group.d.ts
|
|
8
6
|
declare const toggleGroupItemVariants: (props?: ({
|
|
9
7
|
variant?: "default" | "outline" | null | undefined;
|
|
10
8
|
size?: "default" | "sm" | null | undefined;
|
|
11
|
-
} &
|
|
9
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
12
10
|
type ToggleGroupContextValue = VariantProps<typeof toggleGroupItemVariants>;
|
|
13
11
|
declare function ToggleGroup({
|
|
14
12
|
className,
|
|
@@ -16,13 +14,13 @@ declare function ToggleGroup({
|
|
|
16
14
|
size,
|
|
17
15
|
children,
|
|
18
16
|
...props
|
|
19
|
-
}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & ToggleGroupContextValue):
|
|
17
|
+
}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & ToggleGroupContextValue): import("react/jsx-runtime").JSX.Element;
|
|
20
18
|
declare function ToggleGroupItem({
|
|
21
19
|
className,
|
|
22
20
|
children,
|
|
23
21
|
variant,
|
|
24
22
|
size,
|
|
25
23
|
...props
|
|
26
|
-
}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleGroupItemVariants>):
|
|
24
|
+
}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleGroupItemVariants>): import("react/jsx-runtime").JSX.Element;
|
|
27
25
|
//#endregion
|
|
28
26
|
export { ToggleGroup, ToggleGroupItem, toggleGroupItemVariants };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Button } from "./button.mjs";
|
|
2
|
-
import * as _$react from "react";
|
|
3
2
|
import { ComponentPropsWithRef } from "react";
|
|
4
3
|
|
|
5
4
|
//#region src/components/tooltip-icon-button.d.ts
|
|
@@ -7,6 +6,6 @@ type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
|
|
|
7
6
|
tooltip: string;
|
|
8
7
|
side?: "top" | "bottom" | "left" | "right";
|
|
9
8
|
};
|
|
10
|
-
declare const TooltipIconButton:
|
|
9
|
+
declare const TooltipIconButton: import("react").ForwardRefExoticComponent<Omit<TooltipIconButtonProps, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
|
|
11
10
|
//#endregion
|
|
12
11
|
export { TooltipIconButton, type TooltipIconButtonProps };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
4
3
|
|
|
@@ -6,18 +5,18 @@ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
|
6
5
|
declare function TooltipProvider({
|
|
7
6
|
delayDuration,
|
|
8
7
|
...props
|
|
9
|
-
}: React.ComponentProps<typeof TooltipPrimitive.Provider>):
|
|
8
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Provider>): import("react/jsx-runtime").JSX.Element;
|
|
10
9
|
declare function Tooltip({
|
|
11
10
|
...props
|
|
12
|
-
}: React.ComponentProps<typeof TooltipPrimitive.Root>):
|
|
11
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
|
|
13
12
|
declare function TooltipTrigger({
|
|
14
13
|
...props
|
|
15
|
-
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>):
|
|
14
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>): import("react/jsx-runtime").JSX.Element;
|
|
16
15
|
declare function TooltipContent({
|
|
17
16
|
className,
|
|
18
17
|
sideOffset,
|
|
19
18
|
children,
|
|
20
19
|
...props
|
|
21
|
-
}: React.ComponentProps<typeof TooltipPrimitive.Content>):
|
|
20
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Content>): import("react/jsx-runtime").JSX.Element;
|
|
22
21
|
//#endregion
|
|
23
22
|
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
|
@@ -26,7 +26,7 @@ function TooltipContent({ className, sideOffset = 6, children, ...props }) {
|
|
|
26
26
|
return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(TooltipPrimitive.Content, {
|
|
27
27
|
"data-slot": "tooltip-content",
|
|
28
28
|
sideOffset,
|
|
29
|
-
className: cn("bg-inverted text-inverted-foreground dark:bg-subtle dark:text-foreground", "z-50 w-fit rounded-md px-3 py-2 shadow-lg dark:shadow-none dark:drop-shadow-[0_0_0.5px_var(--color-border)]", "type-text-xs font-semibold text-balance text-center", "animate-in fade-in-0 zoom-in-95", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", "origin-(--radix-tooltip-content-transform-origin)", className),
|
|
29
|
+
className: cn("bg-inverted text-inverted-foreground dark:bg-subtle dark:text-foreground", "z-50 w-fit rounded-md px-3 py-2 shadow-lg dark:shadow-none dark:drop-shadow-[0_0_0.5px_var(--color-border)]", "type-text-xs font-semibold text-balance text-center whitespace-pre-line", "animate-in fade-in-0 zoom-in-95", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", "origin-(--radix-tooltip-content-transform-origin)", className),
|
|
30
30
|
...props,
|
|
31
31
|
children: [children, /* @__PURE__ */ jsx(TooltipPrimitive.Arrow, { className: "bg-inverted fill-inverted dark:bg-subtle dark:fill-subtle z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })]
|
|
32
32
|
}) });
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
1
|
import { ReactNode } from "react";
|
|
3
2
|
|
|
4
3
|
//#region src/components/typography.d.ts
|
|
@@ -8,27 +7,27 @@ declare function H1({
|
|
|
8
7
|
}: {
|
|
9
8
|
children: ReactNode;
|
|
10
9
|
className?: string;
|
|
11
|
-
}):
|
|
10
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
12
11
|
declare function H2({
|
|
13
12
|
children,
|
|
14
13
|
className
|
|
15
14
|
}: {
|
|
16
15
|
children: ReactNode;
|
|
17
16
|
className?: string;
|
|
18
|
-
}):
|
|
17
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
19
18
|
declare function H3({
|
|
20
19
|
children,
|
|
21
20
|
className
|
|
22
21
|
}: {
|
|
23
22
|
children: ReactNode;
|
|
24
23
|
className?: string;
|
|
25
|
-
}):
|
|
24
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
26
25
|
declare function H4({
|
|
27
26
|
children,
|
|
28
27
|
className
|
|
29
28
|
}: {
|
|
30
29
|
children: ReactNode;
|
|
31
30
|
className?: string;
|
|
32
|
-
}):
|
|
31
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
33
32
|
//#endregion
|
|
34
33
|
export { H1, H2, H3, H4 };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/components/wizard.d.ts
|
|
4
|
+
interface WizardStep {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
}
|
|
8
|
+
interface WizardStepsProps {
|
|
9
|
+
steps: readonly WizardStep[];
|
|
10
|
+
activeIdx: number;
|
|
11
|
+
onSelect: (idx: number) => void;
|
|
12
|
+
ariaLabel?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
declare function WizardSteps({
|
|
16
|
+
steps,
|
|
17
|
+
activeIdx,
|
|
18
|
+
onSelect,
|
|
19
|
+
ariaLabel,
|
|
20
|
+
className
|
|
21
|
+
}: WizardStepsProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
interface WizardProgressProps extends React.ComponentProps<"div"> {
|
|
23
|
+
current: number;
|
|
24
|
+
total: number;
|
|
25
|
+
}
|
|
26
|
+
declare function WizardProgress({
|
|
27
|
+
current,
|
|
28
|
+
total,
|
|
29
|
+
className,
|
|
30
|
+
...props
|
|
31
|
+
}: WizardProgressProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { WizardProgress, type WizardStep, WizardSteps };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.mjs";
|
|
3
|
+
import { TabsNav, TabsNavList, TabsNavTrigger } from "./tabs.mjs";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/wizard.tsx
|
|
6
|
+
function WizardSteps({ steps, activeIdx, onSelect, ariaLabel = "Wizard steps", className }) {
|
|
7
|
+
return /* @__PURE__ */ jsx(TabsNav, {
|
|
8
|
+
orientation: "vertical",
|
|
9
|
+
"aria-label": ariaLabel,
|
|
10
|
+
className,
|
|
11
|
+
children: /* @__PURE__ */ jsx(TabsNavList, { children: steps.map((step, idx) => /* @__PURE__ */ jsx(TabsNavTrigger, {
|
|
12
|
+
active: idx === activeIdx,
|
|
13
|
+
asChild: true,
|
|
14
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
15
|
+
type: "button",
|
|
16
|
+
onClick: () => onSelect(idx),
|
|
17
|
+
className: "w-full justify-start text-left",
|
|
18
|
+
children: step.label
|
|
19
|
+
})
|
|
20
|
+
}, step.id)) })
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function WizardProgress({ current, total, className, ...props }) {
|
|
24
|
+
const percent = total > 0 ? Math.round(current / total * 100) : 0;
|
|
25
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
26
|
+
className: cn("flex flex-col gap-1.5 px-2", className),
|
|
27
|
+
...props,
|
|
28
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
29
|
+
className: "text-muted-foreground flex items-center justify-between text-xs",
|
|
30
|
+
children: [/* @__PURE__ */ jsxs("span", { children: [
|
|
31
|
+
"Step ",
|
|
32
|
+
current,
|
|
33
|
+
"/",
|
|
34
|
+
total
|
|
35
|
+
] }), /* @__PURE__ */ jsxs("span", { children: [percent, "%"] })]
|
|
36
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
37
|
+
className: "bg-muted h-1.5 overflow-hidden rounded-full",
|
|
38
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
39
|
+
className: "bg-primary h-full transition-all",
|
|
40
|
+
style: { width: `${percent}%` }
|
|
41
|
+
})
|
|
42
|
+
})]
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { WizardProgress, WizardSteps };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alpic-ai/ui",
|
|
3
|
-
"version": "0.0.0-dev.
|
|
3
|
+
"version": "0.0.0-dev.g01173d7",
|
|
4
4
|
"description": "Alpic design system — shared UI components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
"src"
|
|
24
24
|
],
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"lucide-react": "^1.
|
|
27
|
-
"react": "^19.2.
|
|
28
|
-
"react-dom": "^19.2.
|
|
29
|
-
"react-hook-form": "^7.
|
|
26
|
+
"lucide-react": "^1.17.0",
|
|
27
|
+
"react": "^19.2.6",
|
|
28
|
+
"react-dom": "^19.2.6",
|
|
29
|
+
"react-hook-form": "^7.77.0",
|
|
30
30
|
"sonner": "^2.0.7",
|
|
31
|
-
"tailwindcss": "^4.
|
|
31
|
+
"tailwindcss": "^4.3.0",
|
|
32
32
|
"tw-animate-css": "^1.4.0"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
@@ -52,19 +52,19 @@
|
|
|
52
52
|
"class-variance-authority": "^0.7.1",
|
|
53
53
|
"clsx": "^2.1.1",
|
|
54
54
|
"cmdk": "^1.1.1",
|
|
55
|
-
"tailwind-merge": "^3.
|
|
55
|
+
"tailwind-merge": "^3.6.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@ladle/react": "^5.1.1",
|
|
59
|
-
"@tailwindcss/postcss": "^4.
|
|
60
|
-
"@types/react": "19.2.
|
|
59
|
+
"@tailwindcss/postcss": "^4.3.0",
|
|
60
|
+
"@types/react": "19.2.15",
|
|
61
61
|
"@types/react-dom": "19.2.3",
|
|
62
|
-
"lucide-react": "^1.
|
|
63
|
-
"react-hook-form": "^7.
|
|
62
|
+
"lucide-react": "^1.17.0",
|
|
63
|
+
"react-hook-form": "^7.77.0",
|
|
64
64
|
"shx": "^0.4.0",
|
|
65
65
|
"sonner": "^2.0.7",
|
|
66
|
-
"tailwindcss": "^4.
|
|
67
|
-
"tsdown": "^0.
|
|
66
|
+
"tailwindcss": "^4.3.0",
|
|
67
|
+
"tsdown": "^0.22.1",
|
|
68
68
|
"tw-animate-css": "^1.4.0",
|
|
69
69
|
"typescript": "^6.0.3"
|
|
70
70
|
},
|
|
@@ -21,6 +21,8 @@ interface ComboboxContextValue {
|
|
|
21
21
|
isSelected: (itemValue: string) => boolean;
|
|
22
22
|
open: boolean;
|
|
23
23
|
onOpenChange: (open: boolean) => void;
|
|
24
|
+
/** Resolves a selected value to a display label (e.g. for multi-select tags). Defaults to the value. */
|
|
25
|
+
getOptionLabel?: (value: string) => string;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
const ComboboxContext = createContext<ComboboxContextValue | null>(null);
|
|
@@ -40,6 +42,8 @@ interface ComboboxBaseProps {
|
|
|
40
42
|
open?: boolean;
|
|
41
43
|
defaultOpen?: boolean;
|
|
42
44
|
onOpenChange?: (open: boolean) => void;
|
|
45
|
+
/** Resolves a selected value to a display label (e.g. for multi-select tags). Defaults to the value. */
|
|
46
|
+
getOptionLabel?: (value: string) => string;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
interface ComboboxSingleProps extends ComboboxBaseProps {
|
|
@@ -65,6 +69,7 @@ function Combobox(props: ComboboxProps) {
|
|
|
65
69
|
open: controlledOpen,
|
|
66
70
|
defaultOpen = false,
|
|
67
71
|
onOpenChange: controlledOnOpenChange,
|
|
72
|
+
getOptionLabel,
|
|
68
73
|
} = props;
|
|
69
74
|
|
|
70
75
|
// Single mode state
|
|
@@ -175,8 +180,9 @@ function Combobox(props: ComboboxProps) {
|
|
|
175
180
|
isSelected,
|
|
176
181
|
open,
|
|
177
182
|
onOpenChange,
|
|
183
|
+
getOptionLabel,
|
|
178
184
|
}),
|
|
179
|
-
[multiple, singleValue, multiValues, onSelect, onDeselect, isSelected, open, onOpenChange],
|
|
185
|
+
[multiple, singleValue, multiValues, onSelect, onDeselect, isSelected, open, onOpenChange, getOptionLabel],
|
|
180
186
|
);
|
|
181
187
|
|
|
182
188
|
return (
|
|
@@ -229,6 +235,7 @@ function ComboboxTrigger({ className, size, placeholder, children, ...props }: C
|
|
|
229
235
|
/* ── Tags (internal, for multi-select trigger) ────────────────────────────── */
|
|
230
236
|
|
|
231
237
|
function ComboboxTags({ values, onDeselect }: { values: string[]; onDeselect: (value: string) => void }) {
|
|
238
|
+
const { getOptionLabel } = useComboboxContext();
|
|
232
239
|
return (
|
|
233
240
|
<>
|
|
234
241
|
{values.map((tagValue) => (
|
|
@@ -237,7 +244,7 @@ function ComboboxTags({ values, onDeselect }: { values: string[]; onDeselect: (v
|
|
|
237
244
|
onClick={(event) => event.stopPropagation()}
|
|
238
245
|
onDismiss={() => onDeselect(tagValue)}
|
|
239
246
|
>
|
|
240
|
-
{tagValue}
|
|
247
|
+
{getOptionLabel ? getOptionLabel(tagValue) : tagValue}
|
|
241
248
|
</TagDismissible>
|
|
242
249
|
))}
|
|
243
250
|
</>
|
package/src/components/form.tsx
CHANGED
|
@@ -14,8 +14,10 @@ import {
|
|
|
14
14
|
} from "react-hook-form";
|
|
15
15
|
|
|
16
16
|
import { cn } from "../lib/cn";
|
|
17
|
+
import { Checkbox } from "./checkbox";
|
|
17
18
|
import { Input, type InputProps } from "./input";
|
|
18
19
|
import { Label } from "./label";
|
|
20
|
+
import { RadioGroup, RadioGroupItem } from "./radio-group";
|
|
19
21
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select";
|
|
20
22
|
import { Textarea, type TextareaProps } from "./textarea";
|
|
21
23
|
import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip";
|
|
@@ -141,7 +143,7 @@ function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
|
141
143
|
<p
|
|
142
144
|
data-slot="form-description"
|
|
143
145
|
id={formDescriptionId}
|
|
144
|
-
className={cn("text-muted-foreground text-sm", className)}
|
|
146
|
+
className={cn("text-muted-foreground type-text-sm whitespace-pre-line", className)}
|
|
145
147
|
{...props}
|
|
146
148
|
/>
|
|
147
149
|
);
|
|
@@ -220,10 +222,10 @@ function InputField<TFieldValues extends FieldValues, TName extends FieldPath<TF
|
|
|
220
222
|
{label}
|
|
221
223
|
</FormLabel>
|
|
222
224
|
)}
|
|
225
|
+
{description && <FormDescription>{description}</FormDescription>}
|
|
223
226
|
<FormControl>
|
|
224
227
|
<Input {...inputProps} {...field} />
|
|
225
228
|
</FormControl>
|
|
226
|
-
{description && <FormDescription>{description}</FormDescription>}
|
|
227
229
|
<FormMessage />
|
|
228
230
|
</FormItem>
|
|
229
231
|
)}
|
|
@@ -257,10 +259,10 @@ function TextareaField<TFieldValues extends FieldValues, TName extends FieldPath
|
|
|
257
259
|
{label}
|
|
258
260
|
</FormLabel>
|
|
259
261
|
)}
|
|
262
|
+
{description && <FormDescription>{description}</FormDescription>}
|
|
260
263
|
<FormControl>
|
|
261
264
|
<Textarea {...textareaProps} {...field} />
|
|
262
265
|
</FormControl>
|
|
263
|
-
{description && <FormDescription>{description}</FormDescription>}
|
|
264
266
|
<FormMessage />
|
|
265
267
|
</FormItem>
|
|
266
268
|
)}
|
|
@@ -303,6 +305,7 @@ function SelectField<TFieldValues extends FieldValues, TName extends FieldPath<T
|
|
|
303
305
|
{label}
|
|
304
306
|
</FormLabel>
|
|
305
307
|
)}
|
|
308
|
+
{description && <FormDescription>{description}</FormDescription>}
|
|
306
309
|
<Select value={field.value} onValueChange={field.onChange}>
|
|
307
310
|
<FormControl>
|
|
308
311
|
<SelectTrigger>
|
|
@@ -317,7 +320,56 @@ function SelectField<TFieldValues extends FieldValues, TName extends FieldPath<T
|
|
|
317
320
|
))}
|
|
318
321
|
</SelectContent>
|
|
319
322
|
</Select>
|
|
323
|
+
<FormMessage />
|
|
324
|
+
</FormItem>
|
|
325
|
+
)}
|
|
326
|
+
/>
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
interface RadioFieldProps<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>
|
|
331
|
+
extends FormFieldBaseProps<TFieldValues, TName> {
|
|
332
|
+
options: SelectFieldOption[];
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function RadioField<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>({
|
|
336
|
+
control,
|
|
337
|
+
name,
|
|
338
|
+
rules,
|
|
339
|
+
required,
|
|
340
|
+
label,
|
|
341
|
+
description,
|
|
342
|
+
tooltip,
|
|
343
|
+
options,
|
|
344
|
+
}: RadioFieldProps<TFieldValues, TName>) {
|
|
345
|
+
return (
|
|
346
|
+
<FormField
|
|
347
|
+
control={control}
|
|
348
|
+
name={name}
|
|
349
|
+
rules={rules}
|
|
350
|
+
render={({ field }) => (
|
|
351
|
+
<FormItem>
|
|
352
|
+
{label && (
|
|
353
|
+
<FormLabel required={required} tooltip={tooltip}>
|
|
354
|
+
{label}
|
|
355
|
+
</FormLabel>
|
|
356
|
+
)}
|
|
320
357
|
{description && <FormDescription>{description}</FormDescription>}
|
|
358
|
+
<FormControl>
|
|
359
|
+
<RadioGroup value={field.value ?? ""} onValueChange={field.onChange} onBlur={field.onBlur}>
|
|
360
|
+
{options.map((option) => {
|
|
361
|
+
const itemId = `${field.name}-${option.value}`;
|
|
362
|
+
return (
|
|
363
|
+
<div key={option.value} className="flex items-center gap-2">
|
|
364
|
+
<RadioGroupItem id={itemId} value={option.value} disabled={option.disabled} />
|
|
365
|
+
<Label htmlFor={itemId} className="type-text-sm font-normal">
|
|
366
|
+
{option.label}
|
|
367
|
+
</Label>
|
|
368
|
+
</div>
|
|
369
|
+
);
|
|
370
|
+
})}
|
|
371
|
+
</RadioGroup>
|
|
372
|
+
</FormControl>
|
|
321
373
|
<FormMessage />
|
|
322
374
|
</FormItem>
|
|
323
375
|
)}
|
|
@@ -325,8 +377,116 @@ function SelectField<TFieldValues extends FieldValues, TName extends FieldPath<T
|
|
|
325
377
|
);
|
|
326
378
|
}
|
|
327
379
|
|
|
380
|
+
interface ChecklistFieldProps<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>
|
|
381
|
+
extends FormFieldBaseProps<TFieldValues, TName> {
|
|
382
|
+
options: SelectFieldOption[];
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function ChecklistField<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>({
|
|
386
|
+
control,
|
|
387
|
+
name,
|
|
388
|
+
rules,
|
|
389
|
+
required,
|
|
390
|
+
label,
|
|
391
|
+
description,
|
|
392
|
+
tooltip,
|
|
393
|
+
options,
|
|
394
|
+
}: ChecklistFieldProps<TFieldValues, TName>) {
|
|
395
|
+
return (
|
|
396
|
+
<FormField
|
|
397
|
+
control={control}
|
|
398
|
+
name={name}
|
|
399
|
+
rules={rules}
|
|
400
|
+
render={({ field }) => {
|
|
401
|
+
const selected: string[] = Array.isArray(field.value) ? field.value : [];
|
|
402
|
+
const toggle = (value: string, checked: boolean) => {
|
|
403
|
+
if (checked) {
|
|
404
|
+
field.onChange([...selected, value]);
|
|
405
|
+
} else {
|
|
406
|
+
field.onChange(selected.filter((existing) => existing !== value));
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
return (
|
|
410
|
+
<FormItem>
|
|
411
|
+
{label && (
|
|
412
|
+
<FormLabel required={required} tooltip={tooltip}>
|
|
413
|
+
{label}
|
|
414
|
+
</FormLabel>
|
|
415
|
+
)}
|
|
416
|
+
{description && <FormDescription>{description}</FormDescription>}
|
|
417
|
+
<FormControl>
|
|
418
|
+
<fieldset className="m-0 flex flex-col gap-2 border-0 p-0" onBlur={field.onBlur}>
|
|
419
|
+
{options.map((option) => {
|
|
420
|
+
const itemId = `${field.name}-${option.value}`;
|
|
421
|
+
const checked = selected.includes(option.value);
|
|
422
|
+
return (
|
|
423
|
+
<div key={option.value} className="flex items-start gap-2">
|
|
424
|
+
<Checkbox
|
|
425
|
+
id={itemId}
|
|
426
|
+
checked={checked}
|
|
427
|
+
onCheckedChange={(next) => toggle(option.value, Boolean(next))}
|
|
428
|
+
disabled={option.disabled}
|
|
429
|
+
/>
|
|
430
|
+
<Label htmlFor={itemId} className="type-text-sm font-normal leading-tight">
|
|
431
|
+
{option.label}
|
|
432
|
+
</Label>
|
|
433
|
+
</div>
|
|
434
|
+
);
|
|
435
|
+
})}
|
|
436
|
+
</fieldset>
|
|
437
|
+
</FormControl>
|
|
438
|
+
<FormMessage />
|
|
439
|
+
</FormItem>
|
|
440
|
+
);
|
|
441
|
+
}}
|
|
442
|
+
/>
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
interface CheckboxFieldProps<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>
|
|
447
|
+
extends Omit<FormFieldBaseProps<TFieldValues, TName>, "required"> {}
|
|
448
|
+
|
|
449
|
+
function CheckboxField<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>({
|
|
450
|
+
control,
|
|
451
|
+
name,
|
|
452
|
+
rules,
|
|
453
|
+
label,
|
|
454
|
+
description,
|
|
455
|
+
tooltip,
|
|
456
|
+
}: CheckboxFieldProps<TFieldValues, TName>) {
|
|
457
|
+
return (
|
|
458
|
+
<FormField
|
|
459
|
+
control={control}
|
|
460
|
+
name={name}
|
|
461
|
+
rules={rules}
|
|
462
|
+
render={({ field }) => (
|
|
463
|
+
<FormItem className="gap-1.5">
|
|
464
|
+
<div className="flex items-start gap-2">
|
|
465
|
+
<FormControl>
|
|
466
|
+
<Checkbox
|
|
467
|
+
checked={field.value ?? false}
|
|
468
|
+
onCheckedChange={(next) => field.onChange(Boolean(next))}
|
|
469
|
+
onBlur={field.onBlur}
|
|
470
|
+
/>
|
|
471
|
+
</FormControl>
|
|
472
|
+
{label && (
|
|
473
|
+
<FormLabel tooltip={tooltip} className="font-normal">
|
|
474
|
+
{label}
|
|
475
|
+
</FormLabel>
|
|
476
|
+
)}
|
|
477
|
+
</div>
|
|
478
|
+
{description && <FormDescription className="ml-6">{description}</FormDescription>}
|
|
479
|
+
<FormMessage className="ml-6" />
|
|
480
|
+
</FormItem>
|
|
481
|
+
)}
|
|
482
|
+
/>
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
|
|
328
486
|
export type { SelectFieldOption };
|
|
329
487
|
export {
|
|
488
|
+
CheckboxField,
|
|
489
|
+
ChecklistField,
|
|
330
490
|
Form,
|
|
331
491
|
FormControl,
|
|
332
492
|
FormDescription,
|
|
@@ -337,6 +497,7 @@ export {
|
|
|
337
497
|
FormLabel,
|
|
338
498
|
FormMessage,
|
|
339
499
|
InputField,
|
|
500
|
+
RadioField,
|
|
340
501
|
SelectField,
|
|
341
502
|
TextareaField,
|
|
342
503
|
useFormField,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type React from "react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../lib/cn";
|
|
6
|
+
|
|
7
|
+
const shimmerStyle: React.CSSProperties = {
|
|
8
|
+
background: `linear-gradient(90deg, #0000 calc(50% - 60px), var(--color-foreground), #0000 calc(50% + 60px)), linear-gradient(color-mix(in oklab, var(--color-muted-foreground) 70%, transparent), color-mix(in oklab, var(--color-muted-foreground) 70%, transparent))`,
|
|
9
|
+
backgroundSize: "250% 100%, auto",
|
|
10
|
+
backgroundRepeat: "no-repeat, padding-box",
|
|
11
|
+
WebkitBackgroundClip: "text",
|
|
12
|
+
WebkitTextFillColor: "transparent",
|
|
13
|
+
backgroundClip: "text",
|
|
14
|
+
animation: "shimmer-text 2.5s linear infinite",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function ShimmerText({ children, className }: { children: string | number; className?: string }) {
|
|
18
|
+
return (
|
|
19
|
+
<span className={cn(className)} style={shimmerStyle}>
|
|
20
|
+
{children}
|
|
21
|
+
</span>
|
|
22
|
+
);
|
|
23
|
+
}
|
package/src/components/table.tsx
CHANGED
|
@@ -44,7 +44,6 @@ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
|
|
44
44
|
"border-b border-border-secondary transition-colors",
|
|
45
45
|
"data-[state=selected]:bg-muted",
|
|
46
46
|
"[@media(hover:hover)]:hover:bg-background-hover dark:[@media(hover:hover)]:hover:bg-muted",
|
|
47
|
-
"[@media(hover:hover)]:[&:hover_button:hover]:bg-subtle",
|
|
48
47
|
className,
|
|
49
48
|
)}
|
|
50
49
|
{...props}
|
|
@@ -58,7 +57,7 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|
|
58
57
|
data-slot="table-head"
|
|
59
58
|
className={cn(
|
|
60
59
|
"h-11 px-6 py-3 bg-muted text-left align-middle type-text-xs font-semibold text-placeholder dark:text-subtle-foreground whitespace-nowrap",
|
|
61
|
-
"[&:has([role=checkbox])]:w-px [&:has([role=checkbox])]:
|
|
60
|
+
"[&:has([role=checkbox])]:w-px [&:has([role=checkbox])]:px-0",
|
|
62
61
|
className,
|
|
63
62
|
)}
|
|
64
63
|
{...props}
|
|
@@ -82,7 +81,7 @@ function TableCell({ className, interactive = false, ...props }: TableCellProps)
|
|
|
82
81
|
className={cn(
|
|
83
82
|
"align-middle",
|
|
84
83
|
interactive ? "h-px p-0" : "px-6 py-2",
|
|
85
|
-
"[&:has([role=checkbox])]:w-px [&:has([role=checkbox])]:
|
|
84
|
+
"[&:has([role=checkbox])]:w-px [&:has([role=checkbox])]:px-0",
|
|
86
85
|
className,
|
|
87
86
|
)}
|
|
88
87
|
{...props}
|
package/src/components/tabs.tsx
CHANGED
|
@@ -44,10 +44,10 @@ const tabsTriggerVariants = cva(
|
|
|
44
44
|
"data-[state=active]:border-b-2 data-[state=active]:border-foreground data-[state=active]:text-foreground",
|
|
45
45
|
],
|
|
46
46
|
pill: [
|
|
47
|
-
"rounded-
|
|
48
|
-
"text-
|
|
49
|
-
"[@media(hover:hover)]:hover:bg-accent [@media(hover:hover)]:hover:text-
|
|
50
|
-
"data-[state=active]:bg-accent data-[state=active]:text-
|
|
47
|
+
"rounded-md px-2 py-1.5",
|
|
48
|
+
"text-quaternary-foreground",
|
|
49
|
+
"[@media(hover:hover)]:hover:bg-accent [@media(hover:hover)]:hover:text-muted-foreground",
|
|
50
|
+
"data-[state=active]:bg-accent data-[state=active]:text-muted-foreground",
|
|
51
51
|
],
|
|
52
52
|
},
|
|
53
53
|
},
|