@rovula/ui 0.1.20 → 0.1.22
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/cjs/bundle.css +316 -43
- package/dist/cjs/bundle.js +675 -675
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/Badge/Badge.d.ts +40 -0
- package/dist/cjs/types/components/Badge/Badge.stories.d.ts +295 -0
- package/dist/cjs/types/components/Badge/Badge.styles.d.ts +7 -0
- package/dist/cjs/types/components/Badge/index.d.ts +2 -0
- package/dist/cjs/types/components/Dropdown/Dropdown.d.ts +4 -8
- package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +1 -6
- package/dist/cjs/types/components/DropdownMenu/DropdownMenu.d.ts +5 -1
- package/dist/cjs/types/components/DropdownMenu/DropdownMenu.stories.d.ts +45 -30
- package/dist/cjs/types/components/Form/Form.d.ts +2 -1
- package/dist/cjs/types/components/Form/Form.stories.d.ts +4 -0
- package/dist/cjs/types/components/ScrollArea/ScrollArea.d.ts +38 -0
- package/dist/cjs/types/components/ScrollArea/ScrollArea.stories.d.ts +301 -0
- package/dist/cjs/types/index.d.ts +4 -1
- package/dist/cjs/types/patterns/menu/Menu.d.ts +70 -0
- package/dist/cjs/types/{components/Menu → patterns/menu}/Menu.stories.d.ts +17 -10
- package/dist/cjs/types/utils/mergeRefs.d.ts +20 -0
- package/dist/components/Avatar/Avatar.styles.js +2 -2
- package/dist/components/Badge/Badge.js +36 -0
- package/dist/components/Badge/Badge.stories.js +51 -0
- package/dist/components/Badge/Badge.styles.js +62 -0
- package/dist/components/Badge/index.js +2 -0
- package/dist/components/Dropdown/Dropdown.js +54 -163
- package/dist/components/Dropdown/Dropdown.stories.js +29 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +24 -13
- package/dist/components/DropdownMenu/DropdownMenu.stories.js +120 -88
- package/dist/components/Form/Form.js +11 -4
- package/dist/components/Form/Form.stories.js +27 -0
- package/dist/components/ScrollArea/ScrollArea.js +50 -0
- package/dist/components/ScrollArea/ScrollArea.stories.js +56 -0
- package/dist/components/TextInput/TextInput.js +6 -3
- package/dist/esm/bundle.css +316 -43
- package/dist/esm/bundle.js +1545 -1545
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Badge/Badge.d.ts +40 -0
- package/dist/esm/types/components/Badge/Badge.stories.d.ts +295 -0
- package/dist/esm/types/components/Badge/Badge.styles.d.ts +7 -0
- package/dist/esm/types/components/Badge/index.d.ts +2 -0
- package/dist/esm/types/components/Dropdown/Dropdown.d.ts +4 -8
- package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +1 -6
- package/dist/esm/types/components/DropdownMenu/DropdownMenu.d.ts +5 -1
- package/dist/esm/types/components/DropdownMenu/DropdownMenu.stories.d.ts +45 -30
- package/dist/esm/types/components/Form/Form.d.ts +2 -1
- package/dist/esm/types/components/Form/Form.stories.d.ts +4 -0
- package/dist/esm/types/components/ScrollArea/ScrollArea.d.ts +38 -0
- package/dist/esm/types/components/ScrollArea/ScrollArea.stories.d.ts +301 -0
- package/dist/esm/types/index.d.ts +4 -1
- package/dist/esm/types/patterns/menu/Menu.d.ts +70 -0
- package/dist/esm/types/{components/Menu → patterns/menu}/Menu.stories.d.ts +17 -10
- package/dist/esm/types/utils/mergeRefs.d.ts +20 -0
- package/dist/index.d.ts +156 -74
- package/dist/index.js +3 -1
- package/dist/patterns/menu/Menu.js +95 -0
- package/dist/patterns/menu/Menu.stories.js +611 -0
- package/dist/src/theme/global.css +485 -57
- package/dist/utils/mergeRefs.js +42 -0
- package/package.json +1 -1
- package/src/components/Avatar/Avatar.styles.ts +2 -2
- package/src/components/Badge/Badge.stories.tsx +128 -0
- package/src/components/Badge/Badge.styles.ts +70 -0
- package/src/components/Badge/Badge.tsx +103 -0
- package/src/components/Badge/index.ts +3 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +170 -1
- package/src/components/Dropdown/Dropdown.tsx +186 -276
- package/src/components/DropdownMenu/DropdownMenu.stories.tsx +1375 -253
- package/src/components/DropdownMenu/DropdownMenu.tsx +118 -55
- package/src/components/Form/Form.stories.tsx +70 -0
- package/src/components/Form/Form.tsx +23 -0
- package/src/components/ScrollArea/ScrollArea.stories.tsx +229 -0
- package/src/components/ScrollArea/ScrollArea.tsx +72 -0
- package/src/components/TextInput/TextInput.tsx +6 -3
- package/src/index.ts +4 -1
- package/src/patterns/menu/Menu.stories.tsx +1100 -0
- package/src/patterns/menu/Menu.tsx +282 -0
- package/src/theme/global.css +84 -11
- package/src/theme/themes/xspector/baseline.css +1 -1
- package/src/theme/themes/xspector/components/scrollbar.css +12 -0
- package/src/theme/tokens/baseline.css +3 -1
- package/src/theme/tokens/components/badge.css +54 -0
- package/src/theme/tokens/components/dropdown-menu.css +16 -5
- package/src/theme/tokens/components/scrollbar.css +18 -0
- package/src/utils/mergeRefs.ts +46 -0
- package/dist/cjs/types/components/Menu/Menu.d.ts +0 -65
- package/dist/cjs/types/components/Menu/helpers.d.ts +0 -19
- package/dist/cjs/types/components/Menu/index.d.ts +0 -4
- package/dist/components/Menu/Menu.js +0 -64
- package/dist/components/Menu/Menu.stories.js +0 -406
- package/dist/components/Menu/helpers.js +0 -28
- package/dist/components/Menu/index.js +0 -3
- package/dist/esm/types/components/Menu/Menu.d.ts +0 -65
- package/dist/esm/types/components/Menu/helpers.d.ts +0 -19
- package/dist/esm/types/components/Menu/index.d.ts +0 -4
- package/src/components/Menu/Menu.stories.tsx +0 -586
- package/src/components/Menu/Menu.tsx +0 -235
- package/src/components/Menu/helpers.ts +0 -45
- package/src/components/Menu/index.ts +0 -7
- package/src/theme/themes/xspector/components/dropdown-menu.css +0 -28
|
@@ -1,116 +1,148 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from "./DropdownMenu";
|
|
3
4
|
import Button from "../Button/Button";
|
|
4
|
-
import Icon from "../Icon/Icon";
|
|
5
5
|
import ActionButton from "../ActionButton/ActionButton";
|
|
6
|
+
import Icon from "../Icon/Icon";
|
|
7
|
+
import { Input } from "../Input/Input";
|
|
6
8
|
const meta = {
|
|
7
9
|
title: "Components/DropdownMenu",
|
|
8
10
|
component: DropdownMenu,
|
|
9
|
-
// tags: ["autodocs"],
|
|
10
11
|
parameters: {
|
|
11
12
|
layout: "fullscreen",
|
|
12
13
|
},
|
|
13
14
|
decorators: [
|
|
14
|
-
(Story) => (_jsx("div", { className: "p-
|
|
15
|
+
(Story) => (_jsx("div", { className: "p-10 flex gap-8 flex-wrap bg-workspace-surface min-h-screen", children: _jsx(Story, {}) })),
|
|
15
16
|
],
|
|
16
17
|
};
|
|
17
18
|
export default meta;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
render: (
|
|
25
|
-
console.log("args ", args);
|
|
26
|
-
const props = Object.assign({}, args);
|
|
27
|
-
return (_jsx("div", { className: "flex flex-row gap-4 w-full", children: _jsx("div", { className: "flex flex-1 justify-center items-center space-x-2", children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { children: "Open" }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { disabled: true, children: "Option Description" }), _jsxs(DropdownMenuItem, { children: [_jsx(Icon, { type: "heroicons", name: "check", className: "size-4" }), "Option Description"] }), _jsx(DropdownMenuItem, { children: "Option Description" })] })] }) }) }));
|
|
28
|
-
},
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Figma: Normal dropdown / action menu
|
|
21
|
+
// Shows all item states: Default, Hover, Selected, Disabled, Selected+Disabled
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
export const AllStates = {
|
|
24
|
+
name: "All States (Normal)",
|
|
25
|
+
render: () => (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "All States" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsxs(DropdownMenuContent, { className: "relative", style: { position: "static", transform: "none" }, children: [_jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { className: "!bg-[var(--dropdown-menu-hover-bg)]", children: "Option Description (Hover)" }), _jsx(DropdownMenuItem, { selected: true, children: "Option Description" }), _jsx(DropdownMenuItem, { disabled: true, children: "Option Description" }), _jsx(DropdownMenuItem, { selected: true, disabled: true, children: "Option Description" })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { selected: true, children: "Option Description" }), _jsx(DropdownMenuItem, { disabled: true, children: "Option Description" }), _jsx(DropdownMenuItem, { selected: true, disabled: true, children: "Option Description" })] })] })] })] })),
|
|
29
26
|
};
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Figma: Have icon
|
|
29
|
+
// Items with leading icon
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
30
31
|
export const WithIcon = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// value: "Lorem Ipsum",
|
|
34
|
-
// fullwidth: true,
|
|
35
|
-
},
|
|
36
|
-
render: (args) => {
|
|
37
|
-
console.log("args ", args);
|
|
38
|
-
const props = Object.assign({}, args);
|
|
39
|
-
return (_jsx("div", { className: "flex flex-row gap-4 w-full", children: _jsx("div", { className: "flex flex-1 justify-center items-center space-x-2", children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open" }) }), _jsxs(DropdownMenuContent, { children: [_jsxs(DropdownMenuItem, { children: [_jsx(Icon, { type: "heroicons", name: "rocket-launch", className: "size-4" }), _jsx("span", { children: "Option Description" })] }), _jsxs(DropdownMenuItem, { children: [_jsx(Icon, { type: "heroicons", name: "rocket-launch", className: "size-4" }), _jsx("span", { children: "Option Description" })] }), _jsxs(DropdownMenuItem, { disabled: true, children: [_jsx(Icon, { type: "heroicons", name: "rocket-launch", className: "size-4" }), _jsx("span", { children: "Option Description" })] })] })] }) }) }));
|
|
40
|
-
},
|
|
32
|
+
name: "With Icon",
|
|
33
|
+
render: () => (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "All States \u2014 With Icon" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsxs(DropdownMenuContent, { className: "relative", style: { position: "static", transform: "none" }, children: [_jsx(DropdownMenuItem, { icon: _jsx(Icon, { type: "heroicons", name: "rocket-launch", className: "size-4 shrink-0" }), children: "Option Description" }), _jsx(DropdownMenuItem, { className: "!bg-[var(--dropdown-menu-hover-bg)]", icon: _jsx(Icon, { type: "heroicons", name: "rocket-launch", className: "size-4 shrink-0" }), children: "Option Description (Hover)" }), _jsx(DropdownMenuItem, { selected: true, icon: _jsx(Icon, { type: "heroicons", name: "rocket-launch", className: "size-4 shrink-0" }), children: "Option Description (Selected)" }), _jsx(DropdownMenuItem, { disabled: true, icon: _jsx(Icon, { type: "heroicons", name: "rocket-launch", className: "size-4 shrink-0" }), children: "Option Description (Disabled)" }), _jsx(DropdownMenuItem, { selected: true, disabled: true, icon: _jsx(Icon, { type: "heroicons", name: "rocket-launch", className: "size-4 shrink-0" }), children: "Option Description (Selected + Disabled)" })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuItem, { icon: _jsx(Icon, { type: "heroicons", name: "rocket-launch", className: "size-4 shrink-0" }), children: "Launch" }), _jsx(DropdownMenuItem, { icon: _jsx(Icon, { type: "heroicons", name: "pencil", className: "size-4 shrink-0" }), children: "Edit" }), _jsx(DropdownMenuItem, { icon: _jsx(Icon, { type: "heroicons", name: "document-duplicate", className: "size-4 shrink-0" }), children: "Duplicate" }), _jsx(DropdownMenuItem, { disabled: true, icon: _jsx(Icon, { type: "heroicons", name: "trash", className: "size-4 shrink-0" }), children: "Delete" })] })] })] })] })),
|
|
41
34
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
return (
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Figma: Checkbox items (Have icon=No, Checkbox=Yes)
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
export const WithCheckbox = {
|
|
39
|
+
name: "With Checkbox",
|
|
40
|
+
render: () => {
|
|
41
|
+
const [checked1, setChecked1] = useState(false);
|
|
42
|
+
const [checked2, setChecked2] = useState(true);
|
|
43
|
+
const [checked3, setChecked3] = useState(false);
|
|
44
|
+
return (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "All States \u2014 Checkbox" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsxs(DropdownMenuContent, { className: "relative", style: { position: "static", transform: "none" }, children: [_jsx(DropdownMenuCheckboxItem, { children: "Option Description" }), _jsx(DropdownMenuCheckboxItem, { className: "!bg-[var(--dropdown-menu-hover-bg)]", children: "Option Description (Hover)" }), _jsx(DropdownMenuCheckboxItem, { checked: true, children: "Option Description" }), _jsx(DropdownMenuCheckboxItem, { disabled: true, children: "Option Description" }), _jsx(DropdownMenuCheckboxItem, { checked: true, disabled: true, children: "Option Description" })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuCheckboxItem, { checked: checked1, onCheckedChange: setChecked1, children: "Option Description" }), _jsx(DropdownMenuCheckboxItem, { checked: checked2, onCheckedChange: setChecked2, children: "Option Description" }), _jsx(DropdownMenuCheckboxItem, { checked: checked3, onCheckedChange: setChecked3, children: "Option Description" }), _jsx(DropdownMenuCheckboxItem, { disabled: true, children: "Option Description" })] })] })] })] }));
|
|
52
45
|
},
|
|
53
46
|
};
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Figma: Have section (DropdownMenuLabel as section header)
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
export const WithSection = {
|
|
51
|
+
name: "Have Section",
|
|
52
|
+
render: () => (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "With Section Header" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsxs(DropdownMenuContent, { className: "relative", style: { position: "static", transform: "none" }, children: [_jsx(DropdownMenuLabel, { children: "Section Name" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Section Name" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuLabel, { children: "Section Name" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Section Name" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" })] })] })] })] })),
|
|
53
|
+
};
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Figma: Have search
|
|
56
|
+
// Dropdown with search input at the top
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
export const WithSearch = {
|
|
59
|
+
name: "Have Search",
|
|
60
|
+
render: () => {
|
|
61
|
+
const [query, setQuery] = useState("");
|
|
62
|
+
const allOptions = [
|
|
63
|
+
"Option Description",
|
|
64
|
+
"Project Alpha",
|
|
65
|
+
"Project Beta",
|
|
66
|
+
"Project Gamma",
|
|
67
|
+
"Project Delta",
|
|
68
|
+
"Project Epsilon",
|
|
69
|
+
"Project Zeta",
|
|
70
|
+
"Project Eta",
|
|
71
|
+
"Project Theta",
|
|
72
|
+
];
|
|
73
|
+
const filtered = allOptions.filter((o) => o.toLowerCase().includes(query.toLowerCase()));
|
|
74
|
+
return (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "With Search Field" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsxs(DropdownMenuContent, { className: "relative w-[230px]", style: { position: "static", transform: "none" }, onInteractOutside: (e) => e.preventDefault(), children: [_jsxs("div", { className: "flex items-center px-4 py-2 border-b border-[var(--dropdown-menu-seperator-bg)]", children: [_jsx(Icon, { type: "heroicons", name: "magnifying-glass", className: "size-[14px] shrink-0 text-text-g-contrast-medium mr-1" }), _jsx(Input, { variant: "flat", size: "sm", className: "flex-1 !p-0 !ring-0 typography-small1 placeholder:text-text-g-contrast-medium", placeholder: "Search", value: query, onChange: (e) => setQuery(e.target.value) })] }), filtered.map((label) => (_jsx(DropdownMenuItem, { children: label }, label))), filtered.length === 0 && (_jsx("div", { className: "px-4 py-3 typography-subtitle4 text-text-g-contrast-medium", children: "No results found" }))] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { className: "w-[230px]", children: [_jsxs("div", { className: "flex items-center px-4 py-2 border-b border-[var(--dropdown-menu-seperator-bg)]", children: [_jsx(Icon, { type: "heroicons", name: "magnifying-glass", className: "size-[14px] shrink-0 text-text-g-contrast-medium mr-1" }), _jsx(Input, { variant: "flat", size: "sm", className: "flex-1 !p-0 !ring-0 typography-small1 placeholder:text-text-g-contrast-medium", placeholder: "Search" })] }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" })] })] })] })] }));
|
|
64
75
|
},
|
|
65
76
|
};
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Figma: Can scroll — long list, overflow-y scrollable
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
export const CanScroll = {
|
|
81
|
+
name: "Can Scroll",
|
|
82
|
+
render: () => (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Scrollable List" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsx(DropdownMenuContent, { className: "relative max-h-[270px] overflow-y-auto", style: { position: "static", transform: "none" }, children: Array.from({ length: 10 }, (_, i) => (_jsxs(DropdownMenuItem, { children: ["Option Description ", i + 1] }, i))) })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsx(DropdownMenuContent, { className: "max-h-[270px] overflow-y-auto", children: Array.from({ length: 10 }, (_, i) => (_jsxs(DropdownMenuItem, { children: ["Option Description ", i + 1] }, i))) })] })] })] })),
|
|
83
|
+
};
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// Figma: Double scroll — two separate scrollable sections with section headers
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
export const DoubleScroll = {
|
|
88
|
+
name: "Double Scroll",
|
|
89
|
+
render: () => (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Two Scrollable Sections" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsxs(DropdownMenuContent, { className: "relative", style: { position: "static", transform: "none" }, children: [_jsx(DropdownMenuLabel, { children: "Section A" }), _jsx("div", { className: "max-h-[270px] overflow-y-auto", children: Array.from({ length: 5 }, (_, i) => (_jsxs(DropdownMenuItem, { children: ["Option Description ", i + 1] }, i))) }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Section B" }), _jsx("div", { className: "max-h-[216px] overflow-y-auto", children: Array.from({ length: 4 }, (_, i) => (_jsxs(DropdownMenuItem, { children: ["Option Description ", i + 1] }, i))) })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuLabel, { children: "Section A" }), _jsx("div", { className: "max-h-[270px] overflow-y-auto", children: Array.from({ length: 5 }, (_, i) => (_jsxs(DropdownMenuItem, { children: ["Option Description ", i + 1] }, i))) }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Section B" }), _jsx("div", { className: "max-h-[216px] overflow-y-auto", children: Array.from({ length: 4 }, (_, i) => (_jsxs(DropdownMenuItem, { children: ["Option Description ", i + 1] }, i))) })] })] })] })] })),
|
|
90
|
+
};
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Figma: Sub menu (existing, preserved)
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
66
94
|
export const SubMenu = {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// value: "Lorem Ipsum",
|
|
70
|
-
// fullwidth: true,
|
|
71
|
-
},
|
|
72
|
-
render: (args) => {
|
|
73
|
-
console.log("args ", args);
|
|
74
|
-
const props = Object.assign({}, args);
|
|
75
|
-
return (_jsx("div", { className: "flex flex-row gap-4 w-full", children: _jsx("div", { className: "flex flex-1 justify-center items-center space-x-2", children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { children: "Open" }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuLabel, { children: "My Account" }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { children: "Profile" }), _jsx(DropdownMenuItem, { children: "Billing" }), _jsx(DropdownMenuItem, { children: "Team" }), _jsx(DropdownMenuItem, { children: "Subscription" }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuGroup, { children: [_jsxs(DropdownMenuSub, { children: [_jsx(DropdownMenuSubTrigger, { children: _jsx("span", { children: "Invite users" }) }), _jsx(DropdownMenuPortal, { children: _jsxs(DropdownMenuSubContent, { children: [_jsx(DropdownMenuItem, { children: _jsx("span", { children: "Email" }) }), _jsx(DropdownMenuItem, { children: _jsx("span", { children: "Message" }) }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { children: _jsx("span", { children: "More..." }) })] }) })] }), _jsx(DropdownMenuCheckboxItem, { children: "Panel" })] })] })] }) }) }));
|
|
76
|
-
},
|
|
95
|
+
name: "Sub Menu",
|
|
96
|
+
render: () => (_jsx("div", { className: "flex gap-8 items-center flex-wrap", children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuLabel, { children: "My Account" }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { children: "Profile" }), _jsx(DropdownMenuItem, { children: "Billing" }), _jsx(DropdownMenuItem, { children: "Team" }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuGroup, { children: [_jsxs(DropdownMenuSub, { children: [_jsxs(DropdownMenuSubTrigger, { children: [_jsx(Icon, { type: "heroicons", name: "user-group", className: "size-4 shrink-0" }), "Invite users"] }), _jsx(DropdownMenuPortal, { children: _jsxs(DropdownMenuSubContent, { children: [_jsx(DropdownMenuItem, { children: "Email" }), _jsx(DropdownMenuItem, { children: "Message" }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { children: "More..." })] }) })] }), _jsx(DropdownMenuCheckboxItem, { children: "Panel" })] })] })] }) })),
|
|
77
97
|
};
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return (_jsx("div", { className: "flex flex-row gap-4 w-full", children: _jsx("div", { className: "flex flex-1 justify-center items-center space-x-2", children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" })] })] }) }) }));
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Figma: Radio items — single select via DropdownMenuRadioGroup
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
export const WithRadio = {
|
|
102
|
+
name: "With Radio",
|
|
103
|
+
render: () => {
|
|
104
|
+
const [theme, setTheme] = useState("light");
|
|
105
|
+
const [position, setPosition] = useState("top");
|
|
106
|
+
return (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "All States \u2014 Radio" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsx(DropdownMenuContent, { className: "relative", style: { position: "static", transform: "none" }, children: _jsxs(DropdownMenuRadioGroup, { value: "light", children: [_jsx(DropdownMenuRadioItem, { value: "unselected", children: "Option Description" }), _jsx(DropdownMenuRadioItem, { value: "unselected2", className: "!bg-[var(--dropdown-menu-hover-bg)]", children: "Option Description (Hover)" }), _jsx(DropdownMenuRadioItem, { value: "light", children: "Option Description (Selected)" }), _jsx(DropdownMenuRadioItem, { value: "dis", disabled: true, children: "Option Description (Disabled)" }), _jsx(DropdownMenuRadioItem, { value: "light", disabled: true, children: "Option Description (Selected + Disabled)" })] }) })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive \u2014 Theme" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", children: ["Theme: ", theme] }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuLabel, { children: "Theme" }), _jsxs(DropdownMenuRadioGroup, { value: theme, onValueChange: setTheme, children: [_jsx(DropdownMenuRadioItem, { value: "light", children: "Light" }), _jsx(DropdownMenuRadioItem, { value: "dark", children: "Dark" }), _jsx(DropdownMenuRadioItem, { value: "system", children: "System" })] })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive \u2014 Multiple Groups" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuLabel, { children: "Theme" }), _jsxs(DropdownMenuRadioGroup, { value: theme, onValueChange: setTheme, children: [_jsx(DropdownMenuRadioItem, { value: "light", children: "Light" }), _jsx(DropdownMenuRadioItem, { value: "dark", children: "Dark" }), _jsx(DropdownMenuRadioItem, { value: "system", children: "System" })] }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Position" }), _jsxs(DropdownMenuRadioGroup, { value: position, onValueChange: setPosition, children: [_jsx(DropdownMenuRadioItem, { value: "top", children: "Top" }), _jsx(DropdownMenuRadioItem, { value: "bottom", children: "Bottom" }), _jsx(DropdownMenuRadioItem, { value: "right", children: "Right" })] })] })] })] })] }));
|
|
88
107
|
},
|
|
89
108
|
};
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const props = Object.assign({}, args);
|
|
99
|
-
return (_jsx("div", { className: "flex flex-row gap-4 w-full", children: _jsx("div", { className: "flex flex-1 justify-center items-center space-x-2", children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" })] })] }) }) }));
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
// Radio with Icon — single select with leading icon via icon prop
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
export const WithRadioAndIcon = {
|
|
113
|
+
name: "With Radio + Icon",
|
|
114
|
+
render: () => {
|
|
115
|
+
const [theme, setTheme] = useState("dark");
|
|
116
|
+
return (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "All States \u2014 Radio + Icon" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsx(DropdownMenuContent, { className: "relative", style: { position: "static", transform: "none" }, children: _jsxs(DropdownMenuRadioGroup, { value: "dark", children: [_jsx(DropdownMenuRadioItem, { value: "light", icon: _jsx(Icon, { type: "heroicons", name: "sun", className: "size-4 shrink-0" }), children: "Light" }), _jsx(DropdownMenuRadioItem, { value: "system", className: "!bg-[var(--dropdown-menu-hover-bg)]", icon: _jsx(Icon, { type: "heroicons", name: "computer-desktop", className: "size-4 shrink-0" }), children: "System (Hover)" }), _jsx(DropdownMenuRadioItem, { value: "dark", icon: _jsx(Icon, { type: "heroicons", name: "moon", className: "size-4 shrink-0" }), children: "Dark (Selected)" }), _jsx(DropdownMenuRadioItem, { value: "custom", disabled: true, icon: _jsx(Icon, { type: "heroicons", name: "paint-brush", className: "size-4 shrink-0" }), children: "Custom (Disabled)" }), _jsx(DropdownMenuRadioItem, { value: "dark", disabled: true, icon: _jsx(Icon, { type: "heroicons", name: "moon", className: "size-4 shrink-0" }), children: "Dark (Selected + Disabled)" })] }) })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", children: ["Theme: ", theme] }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuLabel, { children: "Theme" }), _jsxs(DropdownMenuRadioGroup, { value: theme, onValueChange: setTheme, children: [_jsx(DropdownMenuRadioItem, { value: "light", icon: _jsx(Icon, { type: "heroicons", name: "sun", className: "size-4 shrink-0" }), children: "Light" }), _jsx(DropdownMenuRadioItem, { value: "dark", icon: _jsx(Icon, { type: "heroicons", name: "moon", className: "size-4 shrink-0" }), children: "Dark" }), _jsx(DropdownMenuRadioItem, { value: "system", icon: _jsx(Icon, { type: "heroicons", name: "computer-desktop", className: "size-4 shrink-0" }), children: "System" }), _jsx(DropdownMenuRadioItem, { value: "custom", disabled: true, icon: _jsx(Icon, { type: "heroicons", name: "paint-brush", className: "size-4" }), children: "Custom" })] })] })] })] })] }));
|
|
100
117
|
},
|
|
101
118
|
};
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
// DropdownMenuShortcut — keyboard shortcut label on the right side of item
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
export const WithShortcut = {
|
|
123
|
+
name: "With Shortcut",
|
|
124
|
+
render: () => (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "All States \u2014 Shortcut" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsxs(DropdownMenuContent, { className: "relative", style: { position: "static", transform: "none" }, children: [_jsxs(DropdownMenuItem, { children: ["New Tab", _jsx(DropdownMenuShortcut, { children: "\u2318T" })] }), _jsxs(DropdownMenuItem, { className: "!bg-[var(--dropdown-menu-hover-bg)]", children: ["New Window (Hover)", _jsx(DropdownMenuShortcut, { children: "\u2318N" })] }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { children: [_jsx(Icon, { type: "heroicons", name: "pencil", className: "size-4 shrink-0" }), "Edit", _jsx(DropdownMenuShortcut, { children: "\u2318E" })] }), _jsxs(DropdownMenuItem, { children: [_jsx(Icon, { type: "heroicons", name: "document-duplicate", className: "size-4 shrink-0" }), "Duplicate", _jsx(DropdownMenuShortcut, { children: "\u2318D" })] }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { disabled: true, children: [_jsx(Icon, { type: "heroicons", name: "trash", className: "size-4 shrink-0" }), "Delete", _jsx(DropdownMenuShortcut, { children: "\u232B" })] })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { className: "w-52", children: [_jsx(DropdownMenuLabel, { children: "Actions" }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { children: ["New Tab", _jsx(DropdownMenuShortcut, { children: "\u2318T" })] }), _jsxs(DropdownMenuItem, { children: ["New Window", _jsx(DropdownMenuShortcut, { children: "\u2318N" })] }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { children: [_jsx(Icon, { type: "heroicons", name: "pencil", className: "size-4 shrink-0" }), "Edit", _jsx(DropdownMenuShortcut, { children: "\u2318E" })] }), _jsxs(DropdownMenuItem, { children: [_jsx(Icon, { type: "heroicons", name: "document-duplicate", className: "size-4 shrink-0" }), "Duplicate", _jsx(DropdownMenuShortcut, { children: "\u2318D" })] }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { disabled: true, children: [_jsx(Icon, { type: "heroicons", name: "trash", className: "size-4 shrink-0" }), "Delete", _jsx(DropdownMenuShortcut, { children: "\u232B" })] })] })] })] })] })),
|
|
125
|
+
};
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// Trigger variants (on icon button, etc.)
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
export const TriggerVariants = {
|
|
130
|
+
name: "Trigger Variants",
|
|
131
|
+
render: () => (_jsxs("div", { className: "flex gap-8 items-center flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Text Trigger" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { children: "Open" }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Button Trigger" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Icon Button Trigger" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" }), _jsx(DropdownMenuItem, { children: "Option Description" })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Horizontal dots" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-horizontal" }) }) }), _jsxs(DropdownMenuContent, { children: [_jsxs(DropdownMenuItem, { children: [_jsx(Icon, { type: "heroicons", name: "pencil", className: "size-4 shrink-0" }), "Edit"] }), _jsxs(DropdownMenuItem, { children: [_jsx(Icon, { type: "heroicons", name: "document-duplicate", className: "size-4 shrink-0" }), "Duplicate"] }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { disabled: true, children: [_jsx(Icon, { type: "heroicons", name: "trash", className: "size-4 shrink-0" }), "Delete"] })] })] })] })] })),
|
|
132
|
+
};
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Complex showcase — real-world patterns combining all item types
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
export const ComplexShowcase = {
|
|
137
|
+
name: "Complex Showcase",
|
|
138
|
+
render: () => {
|
|
139
|
+
const [theme, setTheme] = useState("dark");
|
|
140
|
+
const [density, setDensity] = useState("comfortable");
|
|
141
|
+
const [sortBy, setSortBy] = useState("name");
|
|
142
|
+
const [sortDir, setSortDir] = useState("asc");
|
|
143
|
+
const [showHidden, setShowHidden] = useState(false);
|
|
144
|
+
const [showExtensions, setShowExtensions] = useState(true);
|
|
145
|
+
const [showPreview, setShowPreview] = useState(true);
|
|
146
|
+
return (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "File Manager Actions" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "ellipsis-vertical" }) }) }), _jsxs(DropdownMenuContent, { className: "relative w-[220px]", style: { position: "static", transform: "none" }, children: [_jsx(DropdownMenuItem, { icon: _jsx(Icon, { type: "heroicons", name: "pencil", className: "size-4 shrink-0" }), children: "Rename" }), _jsx(DropdownMenuItem, { icon: _jsx(Icon, { type: "heroicons", name: "document-duplicate", className: "size-4 shrink-0" }), children: "Duplicate" }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Sort By" }), _jsxs(DropdownMenuRadioGroup, { value: "name", children: [_jsx(DropdownMenuRadioItem, { value: "name", children: "Name" }), _jsx(DropdownMenuRadioItem, { value: "date", children: "Date Modified" }), _jsx(DropdownMenuRadioItem, { value: "size", children: "Size" })] }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Show" }), _jsx(DropdownMenuCheckboxItem, { children: "Hidden Files" }), _jsx(DropdownMenuCheckboxItem, { checked: true, children: "File Extensions" }), _jsx(DropdownMenuCheckboxItem, { checked: true, children: "Preview Panel" }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { disabled: true, icon: _jsx(Icon, { type: "heroicons", name: "trash", className: "size-4 shrink-0" }), children: "Delete" })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Editor Settings (Multiple RadioGroups)" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(ActionButton, { variant: "icon", children: _jsx(Icon, { type: "heroicons", name: "cog-6-tooth" }) }) }), _jsxs(DropdownMenuContent, { className: "relative w-[220px]", style: { position: "static", transform: "none" }, children: [_jsx(DropdownMenuLabel, { children: "Theme" }), _jsxs(DropdownMenuRadioGroup, { value: "dark", children: [_jsx(DropdownMenuRadioItem, { value: "light", icon: _jsx(Icon, { type: "heroicons", name: "sun", className: "size-4 shrink-0" }), children: "Light" }), _jsx(DropdownMenuRadioItem, { value: "dark", icon: _jsx(Icon, { type: "heroicons", name: "moon", className: "size-4 shrink-0" }), children: "Dark" }), _jsx(DropdownMenuRadioItem, { value: "system", icon: _jsx(Icon, { type: "heroicons", name: "computer-desktop", className: "size-4 shrink-0" }), children: "System" })] }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Density" }), _jsxs(DropdownMenuRadioGroup, { value: "comfortable", children: [_jsx(DropdownMenuRadioItem, { value: "compact", children: "Compact" }), _jsx(DropdownMenuRadioItem, { value: "comfortable", children: "Comfortable" }), _jsx(DropdownMenuRadioItem, { value: "spacious", children: "Spacious" })] }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Sort Direction" }), _jsxs(DropdownMenuRadioGroup, { value: "asc", children: [_jsx(DropdownMenuRadioItem, { value: "asc", icon: _jsx(Icon, { type: "heroicons", name: "bars-arrow-up", className: "size-4 shrink-0" }), children: "Ascending" }), _jsx(DropdownMenuRadioItem, { value: "desc", icon: _jsx(Icon, { type: "heroicons", name: "bars-arrow-down", className: "size-4 shrink-0" }), children: "Descending" })] })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive \u2014 File Manager" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Options" }) }), _jsxs(DropdownMenuContent, { className: "w-[220px]", children: [_jsx(DropdownMenuItem, { icon: _jsx(Icon, { type: "heroicons", name: "pencil", className: "size-4 shrink-0" }), children: "Rename" }), _jsx(DropdownMenuItem, { icon: _jsx(Icon, { type: "heroicons", name: "document-duplicate", className: "size-4 shrink-0" }), children: "Duplicate" }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Sort By" }), _jsxs(DropdownMenuRadioGroup, { value: sortBy, onValueChange: setSortBy, children: [_jsx(DropdownMenuRadioItem, { value: "name", children: "Name" }), _jsx(DropdownMenuRadioItem, { value: "date", children: "Date Modified" }), _jsx(DropdownMenuRadioItem, { value: "size", children: "Size" })] }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Show" }), _jsx(DropdownMenuCheckboxItem, { checked: showHidden, onCheckedChange: setShowHidden, onSelect: (e) => e.preventDefault(), children: "Hidden Files" }), _jsx(DropdownMenuCheckboxItem, { checked: showExtensions, onCheckedChange: setShowExtensions, onSelect: (e) => e.preventDefault(), children: "File Extensions" }), _jsx(DropdownMenuCheckboxItem, { checked: showPreview, onCheckedChange: setShowPreview, onSelect: (e) => e.preventDefault(), children: "Preview Panel" }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { disabled: true, icon: _jsx(Icon, { type: "heroicons", name: "trash", className: "size-4 shrink-0" }), children: "Delete" })] })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Interactive \u2014 Editor Settings" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Settings" }) }), _jsxs(DropdownMenuContent, { className: "w-[220px]", children: [_jsx(DropdownMenuLabel, { children: "Theme" }), _jsxs(DropdownMenuRadioGroup, { value: theme, onValueChange: setTheme, children: [_jsx(DropdownMenuRadioItem, { value: "light", icon: _jsx(Icon, { type: "heroicons", name: "sun", className: "size-4 shrink-0" }), children: "Light" }), _jsx(DropdownMenuRadioItem, { value: "dark", icon: _jsx(Icon, { type: "heroicons", name: "moon", className: "size-4 shrink-0" }), children: "Dark" }), _jsx(DropdownMenuRadioItem, { value: "system", icon: _jsx(Icon, { type: "heroicons", name: "computer-desktop", className: "size-4 shrink-0" }), children: "System" })] }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Density" }), _jsxs(DropdownMenuRadioGroup, { value: density, onValueChange: setDensity, children: [_jsx(DropdownMenuRadioItem, { value: "compact", children: "Compact" }), _jsx(DropdownMenuRadioItem, { value: "comfortable", children: "Comfortable" }), _jsx(DropdownMenuRadioItem, { value: "spacious", children: "Spacious" })] }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Sort Direction" }), _jsxs(DropdownMenuRadioGroup, { value: sortDir, onValueChange: setSortDir, children: [_jsx(DropdownMenuRadioItem, { value: "asc", icon: _jsx(Icon, { type: "heroicons", name: "bars-arrow-up", className: "size-4 shrink-0" }), children: "Ascending" }), _jsx(DropdownMenuRadioItem, { value: "desc", icon: _jsx(Icon, { type: "heroicons", name: "bars-arrow-down", className: "size-4 shrink-0" }), children: "Descending" })] })] })] })] })] }));
|
|
115
147
|
},
|
|
116
148
|
};
|
|
@@ -9,9 +9,9 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
import React from "react";
|
|
14
|
-
import { FormProvider, useForm, } from "react-hook-form";
|
|
14
|
+
import { FormProvider, useForm, useFormContext, } from "react-hook-form";
|
|
15
15
|
import { yupResolver } from "@hookform/resolvers/yup";
|
|
16
16
|
export const createYupResolver = (schema) => yupResolver(schema);
|
|
17
17
|
export const createControlledForm = ({ methods, defaultValues, controllerRef, }) => {
|
|
@@ -52,8 +52,15 @@ export const useControlledForm = ({ defaultValues, controllerRef, resolver, vali
|
|
|
52
52
|
FormRoot: stableRef.current.FormRoot,
|
|
53
53
|
};
|
|
54
54
|
};
|
|
55
|
+
const FormStateObserver = ({ onFormStateChange, }) => {
|
|
56
|
+
const { formState } = useFormContext();
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
onFormStateChange(formState);
|
|
59
|
+
}, [formState, onFormStateChange]);
|
|
60
|
+
return null;
|
|
61
|
+
};
|
|
55
62
|
const FormInner = (_a, ref) => {
|
|
56
|
-
var { children, defaultValues, methods: externalMethods, controllerRef, onSubmit, onInvalidSubmit, resolver, validationSchema, mode = "onSubmit", reValidateMode = "onChange", noValidate = true } = _a, formProps = __rest(_a, ["children", "defaultValues", "methods", "controllerRef", "onSubmit", "onInvalidSubmit", "resolver", "validationSchema", "mode", "reValidateMode", "noValidate"]);
|
|
63
|
+
var { children, defaultValues, methods: externalMethods, controllerRef, onSubmit, onInvalidSubmit, onFormStateChange, resolver, validationSchema, mode = "onSubmit", reValidateMode = "onChange", noValidate = true } = _a, formProps = __rest(_a, ["children", "defaultValues", "methods", "controllerRef", "onSubmit", "onInvalidSubmit", "onFormStateChange", "resolver", "validationSchema", "mode", "reValidateMode", "noValidate"]);
|
|
57
64
|
const resolvedResolver = resolver !== null && resolver !== void 0 ? resolver : (validationSchema
|
|
58
65
|
? createYupResolver(validationSchema)
|
|
59
66
|
: undefined);
|
|
@@ -82,7 +89,7 @@ const FormInner = (_a, ref) => {
|
|
|
82
89
|
controllerRef.current = null;
|
|
83
90
|
};
|
|
84
91
|
}, [controllerRef, controller]);
|
|
85
|
-
return (_jsx(FormProvider, Object.assign({}, methods, { children:
|
|
92
|
+
return (_jsx(FormProvider, Object.assign({}, methods, { children: _jsxs("form", Object.assign({}, formProps, { noValidate: noValidate, onSubmit: methods.handleSubmit(onSubmit, onInvalidSubmit), children: [onFormStateChange && (_jsx(FormStateObserver, { onFormStateChange: onFormStateChange })), typeof children === "function" ? children(methods) : children] })) })));
|
|
86
93
|
};
|
|
87
94
|
export const Form = React.forwardRef(FormInner);
|
|
88
95
|
export default Form;
|
|
@@ -162,6 +162,33 @@ export const RenderPropsCodeControl = {
|
|
|
162
162
|
} }), _jsx("div", { className: "flex gap-2", children: _jsx(Button, { type: "submit", disabled: !formState.isValid || formState.isSubmitting, isLoading: formState.isSubmitting, children: "Submit with code" }) })] })) }));
|
|
163
163
|
},
|
|
164
164
|
};
|
|
165
|
+
export const FormStateChangeCallback = {
|
|
166
|
+
args: {},
|
|
167
|
+
render: () => {
|
|
168
|
+
const [isFormValid, setIsFormValid] = useState(false);
|
|
169
|
+
const [isDirty, setIsDirty] = useState(false);
|
|
170
|
+
const [submitCount, setSubmitCount] = useState(0);
|
|
171
|
+
const schema = yup.object({
|
|
172
|
+
title: yup.string().required("Title is required"),
|
|
173
|
+
description: yup
|
|
174
|
+
.string()
|
|
175
|
+
.required("Description is required")
|
|
176
|
+
.min(10, "Description must be at least 10 characters"),
|
|
177
|
+
});
|
|
178
|
+
return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "rounded-md border border-bg-stroke1 bg-bg-bg2 p-3 text-xs text-text-g-contrast-medium space-y-1", children: [_jsxs("div", { children: ["Validity:", " ", _jsx("span", { className: isFormValid ? "text-state-success-default" : "text-state-error-default", children: isFormValid ? "valid" : "invalid" })] }), _jsxs("div", { children: ["Dirty: ", isDirty ? "yes" : "no"] }), _jsxs("div", { children: ["Submit count: ", submitCount] })] }), _jsxs(Form, { className: "flex flex-col gap-3", defaultValues: { title: "", description: "" }, mode: "onTouched", reValidateMode: "onChange", validationSchema: schema, onSubmit: (values) => {
|
|
179
|
+
setSubmitCount((prev) => prev + 1);
|
|
180
|
+
// eslint-disable-next-line no-console
|
|
181
|
+
console.log("Submitted:", values);
|
|
182
|
+
}, onFormStateChange: (formState) => {
|
|
183
|
+
setIsFormValid(formState.isValid);
|
|
184
|
+
setIsDirty(formState.isDirty);
|
|
185
|
+
}, children: [_jsx(Field, { name: "title", component: TextInput, componentProps: { label: "Title", required: true } }), _jsx(Field, { name: "description", component: TextInput, componentProps: {
|
|
186
|
+
label: "Description",
|
|
187
|
+
helperText: "At least 10 characters",
|
|
188
|
+
required: true,
|
|
189
|
+
} }), _jsx(Button, { type: "submit", disabled: !isFormValid, children: "Submit" })] })] }));
|
|
190
|
+
},
|
|
191
|
+
};
|
|
165
192
|
export const HigherLayerCodeControl = {
|
|
166
193
|
args: {},
|
|
167
194
|
render: () => {
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
+
import * as React from "react";
|
|
14
|
+
import { cn } from "@/utils/cn";
|
|
15
|
+
const sizeClass = {
|
|
16
|
+
m: "ui-scrollbar ui-scrollbar-m",
|
|
17
|
+
s: "ui-scrollbar ui-scrollbar-s",
|
|
18
|
+
xs: "ui-scrollbar ui-scrollbar-xs",
|
|
19
|
+
};
|
|
20
|
+
const directionClass = {
|
|
21
|
+
vertical: "overflow-y-auto overflow-x-hidden",
|
|
22
|
+
horizontal: "overflow-x-auto overflow-y-hidden",
|
|
23
|
+
both: "overflow-auto",
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* ScrollArea
|
|
27
|
+
*
|
|
28
|
+
* A thin wrapper that applies the design-system scrollbar style to any
|
|
29
|
+
* scrollable container. Use `scrollbarSize` to pick the Figma size variant
|
|
30
|
+
* and `direction` to control which axis scrolls.
|
|
31
|
+
*
|
|
32
|
+
* **Client usage:**
|
|
33
|
+
* ```tsx
|
|
34
|
+
* <ScrollArea className="max-h-[270px]">
|
|
35
|
+
* {items.map(item => <div key={item.id}>{item.label}</div>)}
|
|
36
|
+
* </ScrollArea>
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* For a double-scroll layout (two independent sections inside one dropdown),
|
|
40
|
+
* wrap each section individually:
|
|
41
|
+
* ```tsx
|
|
42
|
+
* <ScrollArea className="max-h-[160px]">...section A items...</ScrollArea>
|
|
43
|
+
* <ScrollArea className="max-h-[160px]">...section B items...</ScrollArea>
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export const ScrollArea = React.forwardRef((_a, ref) => {
|
|
47
|
+
var { className, scrollbarSize = "s", direction = "vertical", children } = _a, props = __rest(_a, ["className", "scrollbarSize", "direction", "children"]);
|
|
48
|
+
return (_jsx("div", Object.assign({ ref: ref, className: cn(directionClass[direction], sizeClass[scrollbarSize], className) }, props, { children: children })));
|
|
49
|
+
});
|
|
50
|
+
ScrollArea.displayName = "ScrollArea";
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ScrollArea } from "./ScrollArea";
|
|
3
|
+
const meta = {
|
|
4
|
+
title: "Components/ScrollArea",
|
|
5
|
+
component: ScrollArea,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: "fullscreen",
|
|
8
|
+
},
|
|
9
|
+
decorators: [
|
|
10
|
+
(Story) => (_jsx("div", { className: "p-10 flex gap-8 flex-wrap bg-workspace-surface min-h-screen", children: _jsx(Story, {}) })),
|
|
11
|
+
],
|
|
12
|
+
};
|
|
13
|
+
export default meta;
|
|
14
|
+
const ITEMS = Array.from({ length: 12 }, (_, i) => `Option Description ${i + 1}`);
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Size variants (Figma: Size=M / S / XS)
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
export const Sizes = {
|
|
19
|
+
name: "Size Variants",
|
|
20
|
+
render: () => (_jsx("div", { className: "flex gap-10 items-start", children: ["m", "s", "xs"].map((size) => (_jsxs("div", { children: [_jsxs("p", { className: "typography-small4 text-text-g-contrast-medium mb-2 uppercase", children: ["Size ", size] }), _jsx(ScrollArea, { scrollbarSize: size, className: "max-h-[270px] w-[200px] rounded-lg bg-modal-surface", children: ITEMS.map((label) => (_jsx("div", { className: "px-4 py-3 typography-subtitle4 text-text-g-contrast-high", children: label }, label))) })] }, size))) })),
|
|
21
|
+
};
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Vertical scroll (Figma: Can Scroll)
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
export const VerticalScroll = {
|
|
26
|
+
name: "Vertical Scroll",
|
|
27
|
+
render: () => (_jsxs("div", { children: [_jsxs("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: ["Single scrollable list \u2014 use", " ", _jsx("code", { className: "text-xs", children: "<ScrollArea className=\"max-h-[...]\">" })] }), _jsx(ScrollArea, { className: "max-h-[270px] w-[230px] rounded-lg bg-modal-surface", children: ITEMS.map((label) => (_jsx("div", { className: "px-4 py-3 typography-subtitle4 text-text-g-contrast-high", children: label }, label))) })] })),
|
|
28
|
+
};
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Horizontal scroll (Figma: Horizontal=Yes)
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
export const HorizontalScroll = {
|
|
33
|
+
name: "Horizontal Scroll",
|
|
34
|
+
render: () => (_jsxs("div", { children: [_jsxs("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: ["Horizontal \u2014 pass", " ", _jsx("code", { className: "text-xs", children: "direction=\"horizontal\"" })] }), _jsx(ScrollArea, { direction: "horizontal", className: "max-w-[300px] rounded-lg bg-modal-surface", children: _jsx("div", { className: "flex", children: ITEMS.map((label) => (_jsx("div", { className: "shrink-0 w-[140px] px-4 py-3 typography-subtitle4 text-text-g-contrast-high border-r border-[var(--dropdown-menu-seperator-bg)]", children: label }, label))) }) })] })),
|
|
35
|
+
};
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Double scroll (Figma: Double Scroll — two independent sections)
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
export const DoubleScroll = {
|
|
40
|
+
name: "Double Scroll",
|
|
41
|
+
render: () => (_jsxs("div", { children: [_jsxs("p", { className: "typography-small4 text-text-g-contrast-medium mb-4", children: ["Two independent scrollable sections inside one container.", _jsx("br", {}), "Wrap each section in its own", " ", _jsx("code", { className: "text-xs", children: "<ScrollArea>" }), "."] }), _jsxs("div", { className: "w-[230px] rounded-lg bg-modal-surface overflow-hidden", children: [_jsx("div", { className: "px-3 pt-4 pb-2 typography-small4 text-text-g-contrast-high", children: "Section A" }), _jsx(ScrollArea, { className: "max-h-[160px]", children: ITEMS.slice(0, 8).map((label) => (_jsx("div", { className: "px-4 py-3 typography-subtitle4 text-text-g-contrast-high", children: label }, label))) }), _jsx("div", { className: "h-px bg-[var(--dropdown-menu-seperator-bg)] my-2" }), _jsx("div", { className: "px-3 pt-2 pb-2 typography-small4 text-text-g-contrast-high", children: "Section B" }), _jsx(ScrollArea, { className: "max-h-[160px]", children: ITEMS.slice(0, 8).map((label) => (_jsx("div", { className: "px-4 py-3 typography-subtitle4 text-text-g-contrast-high", children: label }, label))) })] })] })),
|
|
42
|
+
};
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Usage with DropdownMenu (Figma: Can Scroll / Double Scroll in dropdown)
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
export const WithDropdownMenu = {
|
|
47
|
+
name: "Usage with DropdownMenu",
|
|
48
|
+
render: () => {
|
|
49
|
+
// Inline-import to avoid circular storybook deps — client should import from "@core/ui"
|
|
50
|
+
const { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger,
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
52
|
+
} = require("../DropdownMenu/DropdownMenu");
|
|
53
|
+
const Button = require("../Button/Button").default;
|
|
54
|
+
return (_jsxs("div", { className: "flex gap-8 items-start flex-wrap", children: [_jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Can Scroll" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsx(DropdownMenuContent, { children: _jsx(ScrollArea, { className: "max-h-[270px]", children: ITEMS.map((label) => (_jsx(DropdownMenuItem, { children: label }, label))) }) })] })] }), _jsxs("div", { children: [_jsx("p", { className: "typography-small4 text-text-g-contrast-medium mb-2", children: "Double Scroll" }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Open Menu" }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuLabel, { children: "Section A" }), _jsx(ScrollArea, { className: "max-h-[160px]", children: ITEMS.slice(0, 8).map((label) => (_jsx(DropdownMenuItem, { children: label }, label))) }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: "Section B" }), _jsx(ScrollArea, { className: "max-h-[160px]", children: ITEMS.slice(0, 8).map((label) => (_jsx(DropdownMenuItem, { children: label }, label))) })] })] })] })] }));
|
|
55
|
+
},
|
|
56
|
+
};
|
|
@@ -10,7 +10,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
-
import { forwardRef, useCallback,
|
|
13
|
+
import { forwardRef, useCallback, useMemo, useRef, } from "react";
|
|
14
|
+
import { useStableMergedRef } from "@/utils/mergeRefs";
|
|
14
15
|
import { helperTextVariant, iconActionVariant, inlineEndIconWrapperVariant, inlineStartIconWrapperVariant, inputVariant, labelVariant, searchIconVariant, segmentedIconWrapperVariant, } from "./TextInput.styles";
|
|
15
16
|
import { CircleAlert, CircleX, Search, } from "lucide-react";
|
|
16
17
|
import { cn } from "@/utils/cn";
|
|
@@ -18,6 +19,9 @@ export const TextInput = forwardRef((_a, ref) => {
|
|
|
18
19
|
var { id, label, size = "md", rounded = "normal", variant = "outline", type = "text", iconMode = "solid", helperText, errorMessage, warningMessage, status, fullwidth = true, disabled = false, error = false, warning = false, required = true, isFloatingLabel = true, keepCloseIconOnValue = false, keepFooterSpace = true, hasClearIcon = true, hasSearchIcon = false, startIcon, endIcon, labelClassName, onClickStartIcon, onClickEndIcon, renderStartIcon, renderEndIcon, classes, normalize, format, trimOnCommit, normalizeOnCommit } = _a, props = __rest(_a, ["id", "label", "size", "rounded", "variant", "type", "iconMode", "helperText", "errorMessage", "warningMessage", "status", "fullwidth", "disabled", "error", "warning", "required", "isFloatingLabel", "keepCloseIconOnValue", "keepFooterSpace", "hasClearIcon", "hasSearchIcon", "startIcon", "endIcon", "labelClassName", "onClickStartIcon", "onClickEndIcon", "renderStartIcon", "renderEndIcon", "classes", "normalize", "format", "trimOnCommit", "normalizeOnCommit"]);
|
|
19
20
|
const inputRef = useRef(null);
|
|
20
21
|
const _id = id || `${type}-${label}-input`;
|
|
22
|
+
// Stable merged ref — identity never changes so Headless UI (or any library
|
|
23
|
+
// that watches refs) won't trigger detach/re-attach loops.
|
|
24
|
+
const stableRef = useStableMergedRef(ref, inputRef);
|
|
21
25
|
const hasLeftSectionIcon = !!startIcon || !!renderStartIcon;
|
|
22
26
|
const hasRightSectionIcon = !!endIcon || !!renderEndIcon;
|
|
23
27
|
const feedbackStatus = status ||
|
|
@@ -81,7 +85,6 @@ export const TextInput = forwardRef((_a, ref) => {
|
|
|
81
85
|
warning: isWarning,
|
|
82
86
|
position: "end",
|
|
83
87
|
});
|
|
84
|
-
useImperativeHandle(ref, () => inputRef === null || inputRef === void 0 ? void 0 : inputRef.current);
|
|
85
88
|
const handleChange = useCallback((e) => {
|
|
86
89
|
var _a;
|
|
87
90
|
if (normalize) {
|
|
@@ -183,7 +186,7 @@ export const TextInput = forwardRef((_a, ref) => {
|
|
|
183
186
|
renderEndIcon,
|
|
184
187
|
handleOnClickRightSectionIcon,
|
|
185
188
|
]);
|
|
186
|
-
return (_jsxs("div", { className: `inline-flex flex-col ${fullwidth ? "w-full" : ""}`, children: [_jsxs("div", { className: "relative", children: [_jsx("input", Object.assign({}, props, { placeholder: " ", ref:
|
|
189
|
+
return (_jsxs("div", { className: `inline-flex flex-col ${fullwidth ? "w-full" : ""}`, children: [_jsxs("div", { className: "relative", children: [_jsx("input", Object.assign({}, props, { placeholder: " ", ref: stableRef, type: type, id: _id, disabled: disabled, value: displayValue, className: cn(inputClassname, props.className), onChange: normalize ? handleChange : props.onChange, onBlur: trimOnCommit || normalizeOnCommit ? handleBlur : props.onBlur, onKeyDown: trimOnCommit || normalizeOnCommit ? handleKeyDown : props.onKeyDown })), hasSearchIcon && !hasLeftSectionIcon && (_jsx("div", { className: cn(inlineStartIconWrapperClassname, classes === null || classes === void 0 ? void 0 : classes.iconSearchWrapper), children: _jsx(Search, { className: cn(searchIconClassname, classes === null || classes === void 0 ? void 0 : classes.icon) }) })), startIconElement, hasClearIcon && !hasRightSectionIcon && (_jsx("div", { className: cn(inlineEndIconWrapperClassname, classes === null || classes === void 0 ? void 0 : classes.iconWrapper), style: {
|
|
187
190
|
display: keepCloseIconOnValue && props.value ? "flex" : undefined,
|
|
188
191
|
}, children: _jsx(CircleX, { className: cn(iconActionClassname,
|
|
189
192
|
// 'fill-none stroke-current',
|