Compare commits

...

12 Commits

Author SHA1 Message Date
Satish Gandham 039a8233a1 Optimize select component and cleanup story book 2024-12-30 14:52:11 +05:30
Satish Gandham c06e267206 - Add select component and some cleanup 2024-12-27 13:31:00 +05:30
Satish Gandham 36bf90ca2b Deleted default stories 2024-12-27 13:08:55 +05:30
Satish Gandham 296f579997 Some cleanup 2024-12-20 15:06:25 +05:30
Satish Gandham 2c890af224 Add more tests 2024-12-18 18:17:14 +05:30
Satish Gandham 8d5a549af7 Merge branch 'preview' of https://github.com/makeplane/plane into ui-v2 2024-12-11 13:19:51 +05:30
Satish Gandham c54294388d wip 2024-12-11 13:10:29 +05:30
Satish Gandham 678e06eb62 wip 2024-12-09 12:03:31 +05:30
Satish Gandham 4a7e67dc3d wip 2024-12-06 16:51:09 +05:30
Satish Gandham 526b7061ef Setup unit testing 2024-12-05 18:03:27 +05:30
Satish Gandham 12a499a95a - Add dropdown component
- Setup some tailwind styles
2024-12-04 11:12:51 +05:30
Satish Gandham 171b2c5022 New component library setup with storybook 2024-11-29 16:18:18 +05:30
98 changed files with 69783 additions and 474 deletions
+25
View File
@@ -0,0 +1,25 @@
import type { StorybookConfig } from "@storybook/react-vite";
import { join, dirname } from "path";
/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
*/
function getAbsolutePath(value: string): any {
return dirname(require.resolve(join(value, "package.json")));
}
const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
getAbsolutePath("@storybook/addon-onboarding"),
getAbsolutePath("@storybook/addon-essentials"),
getAbsolutePath("@chromatic-com/storybook"),
getAbsolutePath("@storybook/addon-interactions"),
],
framework: {
name: getAbsolutePath("@storybook/react-vite"),
options: {},
},
};
export default config;
@@ -0,0 +1 @@
<div id="portal-root"></div>
+15
View File
@@ -0,0 +1,15 @@
import type { Preview } from "@storybook/react";
import "../styles/output.css";
const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};
export default preview;
+94
View File
@@ -0,0 +1,94 @@
export const fruits = [
{
id: 1,
name: "Apple",
emoji: "🍎",
description:
"A sweet and crisp fruit, often red or green, great for snacking and baking.",
// disabled: true,
},
{
id: 2,
name: "Banana",
emoji: "🍌",
description:
"A long and curved fruit with a soft, creamy flesh, known for its energy-boosting properties.",
},
{
id: 3,
name: "Cherry",
emoji: "🍒",
description:
"Small, round, and juicy fruits with a sweet or tart flavor, often used in desserts.",
// disabled: true,
},
{
id: 4,
name: "Grapes",
emoji: "🍇",
description:
"Small, juicy fruits that grow in clusters, available in various colors like green, red, and purple.",
},
{
id: 5,
name: "Orange",
emoji: "🍊",
description:
"A citrus fruit known for its tangy and refreshing taste, rich in vitamin C.",
},
{
id: 6,
name: "Strawberry",
emoji: "🍓",
description:
"A red, heart-shaped fruit with a sweet flavor and tiny seeds on its surface.",
},
{
id: 7,
name: "Watermelon",
emoji: "🍉",
description:
"A large, juicy fruit with green rind and red flesh, perfect for summertime snacks.",
},
{
id: 8,
name: "Peach",
emoji: "🍑",
description:
"A soft, fuzzy fruit with a sweet and slightly tangy taste, often enjoyed fresh or in desserts.",
},
{
id: 9,
name: "Pineapple",
emoji: "🍍",
description:
"A tropical fruit with spiky skin and sweet, tangy yellow flesh.",
},
{
id: 10,
name: "Lemon",
emoji: "🍋",
description:
"A bright yellow citrus fruit with a tart flavor, commonly used in drinks and cooking.",
},
{
id: 11,
name: "Mango",
emoji: "🥭",
},
{
id: 12,
name: "Gooseberry",
emoji: "🍇",
},
{
id: 13,
name: "Grapefruit",
emoji: "🍊",
},
{
id: 14,
name: "Guava",
emoji: "🍈",
},
];
+73
View File
@@ -0,0 +1,73 @@
export const vegetables = [
// Add 10 vegetables
{
id: 12,
name: "Carrot",
emoji: "🥕",
description:
"A crunchy orange root vegetable, rich in beta-carotene and vitamin A.",
},
{
id: 13,
name: "Broccoli",
emoji: "🥦",
description:
"A green vegetable with dense, nutritious florets, high in fiber and vitamins.",
},
{
id: 14,
name: "Tomato",
emoji: "🍅",
description:
"Technically a fruit, but commonly used as a vegetable in cooking.",
},
{
id: 15,
name: "Eggplant",
emoji: "🍆",
description:
"A purple vegetable with a meaty texture, popular in Mediterranean cuisine.",
},
{
id: 16,
name: "Corn",
emoji: "🌽",
description:
"Sweet yellow kernels on a cob, enjoyed grilled, boiled, or popped.",
},
{
id: 17,
name: "Bell Pepper",
emoji: "🫑",
description:
"A crisp, colorful vegetable that can be sweet or slightly bitter.",
},
{
id: 18,
name: "Cucumber",
emoji: "🥒",
description:
"A refreshing green vegetable with high water content, often used in salads.",
},
{
id: 19,
name: "Potato",
emoji: "🥔",
description:
"A starchy root vegetable that can be prepared in countless ways.",
},
{
id: 20,
name: "Mushroom",
emoji: "🍄",
description:
"Technically a fungus, but commonly used as a vegetable in cooking.",
},
{
id: 21,
name: "Onion",
emoji: "🧅",
description:
"A pungent bulb vegetable used as a base in many cuisines worldwide.",
},
];
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
testEnvironment: "jsdom",
moduleNameMapper: {
".(css|less|scss)$": "identity-obj-proxy",
},
};
+54
View File
@@ -0,0 +1,54 @@
{
"name": "@plane/ui-v2",
"version": "1.0.0",
"description": "Revamped UI components built using Radix, shared across multiple apps internally",
"author": "Plane",
"license": "MIT",
"private": true,
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"scripts": {
"build": "tsup src/index.ts --format esm --dts --external react --minify",
"dev": "tsup src/index.ts --format esm --watch --dts --external react",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build",
"postcss": "postcss styles/globals.css -o styles/output.css --watch",
"lint": "eslint src --ext .ts,.tsx",
"tcss": "tailwindcss -i ./styles/global.css -o ./styles/output.css --watch",
"start": "yarn dev & yarn storybook & yarn tcss",
"test": "vitest",
"test:ui": "vitest --ui"
},
"devDependencies": {
"@chromatic-com/storybook": "^3.2.2",
"@storybook/addon-essentials": "^8.4.5",
"@storybook/addon-interactions": "^8.4.5",
"@storybook/addon-onboarding": "^8.4.5",
"@storybook/blocks": "^8.4.5",
"@storybook/react": "^8.4.5",
"@storybook/react-vite": "^8.4.5",
"@storybook/test": "^8.4.5",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.14",
"@vitest/ui": "2.1.8",
"autoprefixer": "^10.4.20",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jsdom": "^25.0.1",
"storybook": "^8.4.5",
"tailwindcss": "^3.4.15",
"tsup": "^8.3.5",
"typescript": "^5.7.2",
"vite": "^6.0.1",
"vitest": "^2.1.8"
},
"dependencies": {
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-scroll-area": "^1.2.1",
"@radix-ui/react-select": "^2.1.2"
}
}
+9
View File
@@ -0,0 +1,9 @@
## Philosophy
Components are our core building blocks adhering to our design system. None of these components should ever need any styling in the application.
Only styles you will need in the application are for layouts.
## Composition vs Render props
For any data that needs to be dynamic / comes from the server, we use render props.
@@ -0,0 +1,135 @@
import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test";
import React, { useState } from "react";
import { DropdownMenu } from "./DropdownMenu";
import { DropdownButton } from "./components/DropdownButton";
import { DropdownContent } from "./components/DropdownContent";
import { DropdownItem } from "./components/DropdownItem";
import { fruits } from "../../../data/fruits";
import { vegetables } from "../../../data/vegetables";
// import { SelectDropdown } from "./DropdownMenu-copy";
const fruitsAndVegetables = {
fruits,
vegetables,
};
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta = {
title: "Example/DropdownMenu",
component: DropdownMenu,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
layout: "centered",
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"],
// More on argTypes: https://storybook.js.org/docs/api/argtypes
argTypes: {
items: [1, 2, 3, 4],
},
// Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
args: {},
} satisfies Meta<typeof DropdownMenu>;
export default meta;
type Story = StoryObj<typeof meta>;
export const DefaultDropdown = () => {
return (
<DropdownMenu defaultOpen={true}>
<DropdownButton>
<button>Click me!!</button>
</DropdownButton>
<DropdownContent>
<div>
<h1>Hello</h1>
<p>How are you today?</p>
<DropdownItem onSelect={(e) => console.log(e)}>
Click me again
</DropdownItem>
<DropdownItem onSelect={(e) => e.preventDefault()}>
Click me, I won't close
</DropdownItem>
</div>
</DropdownContent>
</DropdownMenu>
);
};
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const MultiSelect = () => {
const [value, setValue] = useState([fruits[6]]);
const [items, setItems] = useState([
...fruitsAndVegetables.fruits,
...fruitsAndVegetables.vegetables,
]);
const handleSearch = async (query: String) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
// Filters items on the name
const filteredItems = fruitsAndVegetables.fruits.filter((item) =>
item.name.toLowerCase().includes(query.toLowerCase())
);
setItems(filteredItems);
};
return (
<DropdownMenu
items={items}
onSelect={(e, value) => {
e.preventDefault();
console.log(e, value);
}}
renderItem={(item) => <Fruit fruit={item} />}
defaultOpen={true}
onSearch={handleSearch}
// isItemDisabled={(item) => item.id % 2 === 0}
>
<DropdownButton showIcon>
<div className="flex items-center gap-2 justify-between">
<Fruit fruit={fruits[1]} />({value.length})
</div>
</DropdownButton>
{items.length === 0 && (
<DropdownContent>
<div>No items found</div>
</DropdownContent>
)}
</DropdownMenu>
);
};
export const NestedDropdown = () => {
const items = [
{
name: "Vegetables",
children: fruitsAndVegetables.vegetables,
emoji: "🥦",
},
{
name: "Fruits",
children: fruitsAndVegetables.fruits,
emoji: "🍎",
},
];
return (
<div>
<DropdownMenu
defaultOpen={true}
items={items}
renderItem={(item) => <Fruit fruit={item} />}
>
<DropdownButton>
<button className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
Select
</button>
</DropdownButton>
</DropdownMenu>
</div>
);
};
const Fruit = ({ fruit }) => {
return <div>{`${fruit.emoji} ${fruit.name}`}</div>;
};
@@ -0,0 +1,81 @@
import {
act,
fireEvent,
render,
screen,
waitFor,
} from "@testing-library/react";
import React from "react";
import { describe, expect, it, vi } from "vitest";
import { DropdownButton } from "./components/DropdownButton";
import { DropdownMenu } from "./DropdownMenu";
describe("DropdownMenu", () => {
it("should render the dropdown menu", () => {
render(
<DropdownMenu>
<DropdownButton>Click me</DropdownButton>
</DropdownMenu>
);
expect(screen.getByText("Click me")).toHaveTextContent("Click me");
});
it("should render the dropdown arrow", () => {
render(
<DropdownMenu>
<DropdownButton showIcon>Click me</DropdownButton>
</DropdownMenu>
);
expect(screen.getByTestId("dropdown-arrow")).toBeInTheDocument();
});
it("Should not render the dropdown arrow if showIcon is false", () => {
render(
<DropdownMenu>
<DropdownButton>Click me</DropdownButton>
</DropdownMenu>
);
expect(screen.queryByTestId("dropdown-arrow")).not.toBeInTheDocument();
});
it("should render items using render prop", async () => {
type Item = { id: number; label: string; disabled?: boolean };
const items: Item[] = [
{ id: 1, label: "Item 1" },
{ id: 2, label: "Item 2", disabled: true },
];
const onSelectMock = vi.fn();
render(
<DropdownMenu
items={items}
onSelect={onSelectMock}
renderItem={(item) => <div>{item.label}</div>}
defaultOpen
>
<DropdownButton>Click me</DropdownButton>
</DropdownMenu>
);
// Check if items are rendered
expect(screen.getByText("Item 1")).toBeInTheDocument();
expect(screen.getByText("Item 2")).toBeInTheDocument();
// Check if disabled item has correct attributes
const disabledItem = screen.getByText("Item 2");
expect(disabledItem.parentElement).toHaveAttribute("data-disabled");
// Check if the item is clickable and triggers onSelect
const activeItem = screen.getByText("Item 1");
act(() => {
fireEvent(activeItem, new MouseEvent("click", { bubbles: true }));
});
expect(onSelectMock).toHaveBeenCalled();
await waitFor(() => {
expect(screen.queryByText("Item 1")).not.toBeInTheDocument();
});
});
});
@@ -0,0 +1,62 @@
import * as RadixDropdownMenu from "@radix-ui/react-dropdown-menu";
import React, { createContext, useCallback, useState } from "react";
import { DropdownContent } from "./components/DropdownContent";
// Types
type DropdownMenuProps<T> = {
children: React.ReactNode;
items?: T[];
onSelect?: (e: React.MouseEvent, value: T) => void;
renderItem?: (item: T) => React.ReactNode;
defaultOpen?: boolean;
onSearch?: (value: string) => void;
isItemDisabled?: (item: T) => boolean;
onOpenChange?: (open: boolean) => void;
};
type DropdownMenuContextType<T> = {
items?: T[];
onSelect?: (e: React.MouseEvent, value: T) => void;
renderItem?: (item: T) => React.ReactNode;
setOpen?: (open: boolean) => void;
onSearch?: (value: string) => void;
isItemDisabled?: (item: T) => boolean;
};
//@todo: Is it possible to not use any here?
export const DropdownMenuContext = createContext<DropdownMenuContextType<any>>({
items: [],
onSelect: (e, value) => {},
renderItem: (item) => <></>,
});
export const DropdownMenu = <T,>({
children,
items,
onSelect,
renderItem,
defaultOpen = false,
onSearch,
isItemDisabled,
onOpenChange,
}: DropdownMenuProps<T>) => {
const [open, setOpen] = useState(defaultOpen);
const handleOpenChange = useCallback((open: boolean) => {
if (onOpenChange) onOpenChange(open);
setTimeout(() => {
setOpen(open);
}, 16);
}, []);
return (
<DropdownMenuContext.Provider
value={{ items, onSelect, renderItem, setOpen, onSearch, isItemDisabled }}
>
<RadixDropdownMenu.Root open={open} onOpenChange={handleOpenChange}>
{children}
{items && <DropdownContent />}
</RadixDropdownMenu.Root>
</DropdownMenuContext.Provider>
);
};
@@ -0,0 +1,32 @@
import * as RadixDropdownMenu from "@radix-ui/react-dropdown-menu";
import { ChevronDownIcon } from "@radix-ui/react-icons";
import React, { useContext } from "react";
import { DropdownMenuContext } from "../DropdownMenu";
type DropdownButtonProps = {
children: React.ReactNode;
showIcon?: boolean;
label: string;
};
export const DropdownButton = ({
children,
showIcon = false,
label,
}: DropdownButtonProps) => {
const { setOpen } = useContext(DropdownMenuContext);
return (
<RadixDropdownMenu.Trigger
className="inline-flex h-[35px]
items-center justify-between gap-[5px] rounded bg-white px-[15px] text-[13px] leading-none"
aria-label={label}
asChild
>
<div>
{children}
{showIcon && <ChevronDownIcon data-testid="dropdown-arrow" />}
</div>
</RadixDropdownMenu.Trigger>
);
};
@@ -0,0 +1,52 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import React from "react";
import { DropdownMenu } from "../DropdownMenu";
import { DropdownContent } from "./DropdownContent";
import { DropdownButton } from "./DropdownButton";
let portalRoot = document.getElementById("portal");
if (!portalRoot) {
portalRoot = document.createElement("div");
portalRoot.setAttribute("id", "portal");
document.body.appendChild(portalRoot);
console.log("Added");
}
const Item = ({ item }: { item: any }) => {
return <div>{item.label}</div>;
};
describe("DropdownContent", () => {
it("should render the dropdown content", () => {
render(
<DropdownMenu defaultOpen>
<DropdownButton>Click me</DropdownButton>
<DropdownContent
container={document.getElementById("portal") || undefined}
>
Content.........
</DropdownContent>
</DropdownMenu>
);
expect(screen.getByRole("menu")).toHaveTextContent("Content");
});
it("should render dropdown items", () => {
const items = [
{ label: "Item 1", value: "item-1" },
{ label: "Item 2", value: "item-2" },
];
render(
<DropdownMenu
defaultOpen
items={items}
renderItem={(item) => <Item item={item} />}
>
<DropdownButton>Click me</DropdownButton>
<DropdownContent></DropdownContent>
</DropdownMenu>
);
console.log(screen.debug());
});
});
@@ -0,0 +1,128 @@
import * as RadixDropdownMenu from "@radix-ui/react-dropdown-menu";
import * as ScrollArea from "@radix-ui/react-scroll-area";
import React, { useCallback, useContext, useEffect, useState } from "react";
import { DropdownMenuContext } from "../DropdownMenu";
import { DropdownItems } from "./DropdownItems";
export const DropdownContent = ({
children,
container,
}: {
children?: React.ReactNode;
container?: HTMLElement;
}) => {
const { items, renderItem, onSelect, renderGroup, onSearch, isItemDisabled } =
useContext(DropdownMenuContext);
const [groupedItems, setGroupedItems] = useState<{
[key: string]: any[];
}>({});
const [showSearchLoading, setShowSearchLoading] = useState(false);
useEffect(() => {
if (!items) return;
let groupedItems: { [key: string]: any[] } = {};
if (Array.isArray(items)) {
groupedItems.default = items;
} else {
groupedItems = items;
}
setGroupedItems(groupedItems);
}, [open, items]);
const handleSearch = async (query: string) => {
if (!onSearch) return;
try {
setShowSearchLoading(true);
await onSearch(query);
} catch (error) {
console.error(error);
} finally {
setShowSearchLoading(false);
}
};
const handleSelect = useCallback(
(e: any, item: any) => {
onSelect && onSelect(e, item);
},
[onSelect]
);
return (
<RadixDropdownMenu.Portal container={container}>
<RadixDropdownMenu.Content className="p-3 rounded-md bg-white border border-neutral">
{onSearch && (
<div className="relative">
<input
type="text"
placeholder="Search"
className="w-full p-1 border border-neutral rounded-md mb-3 sticky top-0 bg-white z-10"
onChange={(e) => handleSearch(e.target.value)}
/>
{showSearchLoading && (
<div role="status" className="absolute z-20 top-2 right-2">
<svg
aria-hidden="true"
className="w-4 h-4 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600"
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor"
/>
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill"
/>
</svg>
<span className="sr-only">Loading...</span>
</div>
)}
</div>
)}
<ScrollArea.Root className=" ">
<ScrollArea.Viewport className="h-full w-full max-h-[80vh]">
{children}
{Object.keys(groupedItems).map((group) => (
<RadixDropdownMenu.Group key={group}>
{group !== "default" && (
<RadixDropdownMenu.Label>
{renderGroup ? renderGroup(group) : group}
</RadixDropdownMenu.Label>
)}
{renderItem && (
<DropdownItems
items={groupedItems[group]}
onSelect={handleSelect}
renderItem={renderItem}
isItemDisabled={isItemDisabled}
/>
)}
</RadixDropdownMenu.Group>
))}
</ScrollArea.Viewport>
<ScrollArea.Scrollbar
className="flex touch-none select-none bg-blackA3 p-0.5 transition-colors duration-[160ms] ease-out hover:bg-blackA5 data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col"
orientation="vertical"
>
<ScrollArea.Thumb className="relative flex-1 rounded-[10px] bg-mauve10 before:absolute before:left-1/2 before:top-1/2 before:size-full before:min-h-11 before:min-w-11 before:-translate-x-1/2 before:-translate-y-1/2" />
</ScrollArea.Scrollbar>
<ScrollArea.Scrollbar
className="flex touch-none select-none bg-blackA3 p-0.5 transition-colors duration-[160ms] ease-out hover:bg-blackA5 data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col"
orientation="horizontal"
>
<ScrollArea.Thumb className="relative flex-1 rounded-[10px] bg-mauve10 before:absolute before:left-1/2 before:top-1/2 before:size-full before:min-h-[44px] before:min-w-[44px] before:-translate-x-1/2 before:-translate-y-1/2" />
</ScrollArea.Scrollbar>
<ScrollArea.Corner className="bg-blackA5" />
</ScrollArea.Root>
</RadixDropdownMenu.Content>
</RadixDropdownMenu.Portal>
);
};
@@ -0,0 +1,42 @@
import * as RadixDropdownMenu from "@radix-ui/react-dropdown-menu";
import React, { useCallback } from "react";
const DropdownItem_ = ({
children,
onSelect,
disabled,
item,
}: {
children: React.ReactNode;
onSelect: (e: any, item: any) => void;
disabled?: boolean;
item?: any;
}) => {
const handleSelect = useCallback(
(e: any) => {
onSelect(e, item);
},
[onSelect]
);
return (
<RadixDropdownMenu.Item
onSelect={handleSelect}
className="p-1 first:pt-0 last:border-b-0 last:pb-0
rounded
hover:bg-bg-neutral-subtle
focus:bg-bg-neutral-subtle
focus:outline-none
cursor-pointer
data-[disabled]:pointer-events-none
data-[disabled]:opacity-50
data-[disabled]:cursor-not-allowed
"
disabled={disabled}
>
{children}
</RadixDropdownMenu.Item>
);
};
export const DropdownItem = React.memo(DropdownItem_);
@@ -0,0 +1,86 @@
import * as RadixDropdownMenu from "@radix-ui/react-dropdown-menu";
import React, { useCallback } from "react";
import { DropdownItem } from "./DropdownItem";
import * as ScrollArea from "@radix-ui/react-scroll-area";
type Item<T> = T & {
children?: Item<T>[];
disabled?: boolean;
};
type DropdownItemsProps<T> = {
items: Item<T>[];
onSelect: (e: any, item: Item<T>) => void;
renderItem: (item: Item<T>) => React.ReactNode;
isItemDisabled?: (item: Item<T>) => boolean;
};
const DropdownItems_ = <T,>({
items,
onSelect,
renderItem,
isItemDisabled,
}: DropdownItemsProps<T>) => {
const handleSelect = useCallback(
(e: any, item: Item<T>) => {
onSelect(e, item);
},
[onSelect]
);
return (
<>
{items.map((item, index) => {
if (item.children) {
return (
<RadixDropdownMenu.Sub key={index}>
<RadixDropdownMenu.SubTrigger
className="group relative flex h-[25px] select-none items-center rounded-[3px] pr-[5px] text-[13px]
leading-none text-violet11 outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-violet9
data-[highlighted]:data-[state=open]:bg-violet9 data-[state=open]:bg-violet4 data-[disabled]:text-mauve8 data-[highlighted]:data-[state=open]:text-violet1 data-[highlighted]:text-violet1 data-[state=open]:text-violet11"
>
{renderItem(item)}
</RadixDropdownMenu.SubTrigger>
<RadixDropdownMenu.Portal>
<RadixDropdownMenu.SubContent
className="min-w-[220px] rounded-md bg-white p-[5px]
shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)]
will-change-[opacity,transform] data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade
data-[side=right]:animate-slideLeftAndFade data-[side=top]:animate-slideDownAndFade
"
sideOffset={2}
alignOffset={-5}
>
<ScrollArea.Root className=" ">
<ScrollArea.Viewport className="h-full w-full max-h-[80vh]">
<DropdownItems
items={item.children}
onSelect={handleSelect}
renderItem={renderItem}
isItemDisabled={isItemDisabled}
/>
</ScrollArea.Viewport>
</ScrollArea.Root>
</RadixDropdownMenu.SubContent>
</RadixDropdownMenu.Portal>
</RadixDropdownMenu.Sub>
);
}
return (
<DropdownItem
key={index}
onSelect={handleSelect}
disabled={isItemDisabled ? isItemDisabled(item) : item?.disabled}
item={item}
>
{renderItem(item)}
</DropdownItem>
);
})}
</>
);
};
const DropdownItems = React.memo(DropdownItems_);
export { DropdownItems };
@@ -0,0 +1,62 @@
import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test";
import React, { useState } from "react";
import { Select } from "./Select";
import { fruits } from "../../../data/fruits";
import { SelectButton } from "./SelectButton";
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta = {
title: "Example/SelectMenu",
component: Select,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
layout: "centered",
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"],
// More on argTypes: https://storybook.js.org/docs/api/argtypes
argTypes: {
items: [1, 2, 3, 4],
},
// Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
args: { onChange: fn() },
} satisfies Meta<typeof Select>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const SingleSelect = () => {
const [items, setItems] = useState(fruits);
const handleSearch = async (query: String) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
// Filters items on the name
const filteredItems = fruits.filter((item) =>
item.name.toLowerCase().includes(query.toLowerCase())
);
setItems(filteredItems);
};
return (
<Select
items={fruits}
renderItem={Fruit}
onChange={function (value: any): void {
console.log("Selected items", value);
}}
value={[3, 7, 9]}
renderGroup={function (group: string): React.ReactNode {
throw new Error("Function not implemented.");
}}
onSearch={handleSearch}
multiple
defaultOpen
>
<SelectButton>Click Me!!</SelectButton>
</Select>
);
};
const Fruit = ({ item: fruit }) => {
return <div>{`${fruit.emoji} ${fruit.name}`}</div>;
};
@@ -0,0 +1,97 @@
import React, { useCallback } from "react";
import { DropdownMenu } from "../DropdownMenu/DropdownMenu";
import { SelectItem } from "./SelectItem";
type SelectProps = {
items: any[];
onChange: (value: any) => void;
value: any;
renderItem: (item: any) => React.ReactNode;
renderGroup: (group: string) => React.ReactNode;
multiple?: boolean;
keyExtractor?: (item: any) => string;
showSelectedAtTop?: boolean;
defaultOpen?: boolean;
children: React.ReactNode;
onSearch?: (query: String) => void;
};
export const Select = (props: SelectProps) => {
const {
items,
onChange,
renderItem: Item,
renderGroup,
multiple,
value: initialValue = [],
keyExtractor = (item) => item.id,
showSelectedAtTop = true,
defaultOpen = false,
children,
onSearch,
} = props;
const [value, setValue] = React.useState(initialValue);
const [open, setOpen] = React.useState(defaultOpen);
const handleSelect = useCallback(
(e: React.MouseEvent, item: any) => {
const key = keyExtractor(item);
if (multiple) {
e.preventDefault();
e.stopPropagation();
// If values includes item, remove it
if (value.includes(key)) {
setValue(value.filter((v) => v !== key));
} else {
setValue([...value, key]);
}
onChange([...value, key]);
} else {
setValue([key]);
onChange([key]);
}
},
[value]
);
const renderItem_ = useCallback(
(item: any) => {
const key = keyExtractor(item);
const selected = value.includes(key);
return (
<SelectItem item={item} selected={selected} render={Item}></SelectItem>
);
},
[value, keyExtractor]
);
const orderedItems = React.useMemo(() => {
if (showSelectedAtTop && open) {
// Move selected items to the top
return [
...items.filter((item) => value.includes(keyExtractor(item))),
...items.filter((item) => !value.includes(keyExtractor(item))),
];
}
return items;
}, [initialValue, open]);
const handleOpenChange = useCallback((open_: boolean) => {
setOpen(open_);
}, []);
return (
<DropdownMenu
defaultOpen={defaultOpen}
items={orderedItems}
renderItem={renderItem_}
onSelect={handleSelect}
onOpenChange={handleOpenChange}
onSearch={onSearch}
>
{children}
</DropdownMenu>
);
};
@@ -0,0 +1,3 @@
import { DropdownButton } from "../DropdownMenu/components/DropdownButton";
export const SelectButton = DropdownButton;
@@ -0,0 +1,31 @@
/**
* SelectItem
* @description Takes render function, item, and if its selected as a prop
* @param {Function} render
* @param {Object} item
* @param {Boolean} selected
*/
import { CheckIcon } from "@radix-ui/react-icons";
import React from "react";
const EmptyIcon = () => (
<div style={{ width: "15px", height: "15px" }}>&nbsp;</div>
);
type Props = {
item: any;
selected: boolean;
render: any;
};
const SelectItem_ = ({ render: Item, item, selected }: Props) => {
return (
<div className="flex items-center gap-2 justify-between">
<Item item={item} />
{/* Added empty icon to reserve space */}
{selected ? <CheckIcon /> : <EmptyIcon />}
</div>
);
};
export const SelectItem = React.memo(SelectItem_);
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,63 @@
import{R as e,r as f}from"./index-Cqyox1Tj.js";import{D as i,a as d,b as C,c as b,f as m}from"./fruits-CZbL9byb.js";import"./index-DtqWk5t9.js";import"./index-DGXSSr1l.js";const x=[{id:12,name:"Carrot",emoji:"🥕",description:"A crunchy orange root vegetable, rich in beta-carotene and vitamin A."},{id:13,name:"Broccoli",emoji:"🥦",description:"A green vegetable with dense, nutritious florets, high in fiber and vitamins."},{id:14,name:"Tomato",emoji:"🍅",description:"Technically a fruit, but commonly used as a vegetable in cooking."},{id:15,name:"Eggplant",emoji:"🍆",description:"A purple vegetable with a meaty texture, popular in Mediterranean cuisine."},{id:16,name:"Corn",emoji:"🌽",description:"Sweet yellow kernels on a cob, enjoyed grilled, boiled, or popped."},{id:17,name:"Bell Pepper",emoji:"🫑",description:"A crisp, colorful vegetable that can be sweet or slightly bitter."},{id:18,name:"Cucumber",emoji:"🥒",description:"A refreshing green vegetable with high water content, often used in salads."},{id:19,name:"Potato",emoji:"🥔",description:"A starchy root vegetable that can be prepared in countless ways."},{id:20,name:"Mushroom",emoji:"🍄",description:"Technically a fungus, but commonly used as a vegetable in cooking."},{id:21,name:"Onion",emoji:"🧅",description:"A pungent bulb vegetable used as a base in many cuisines worldwide."}],s={fruits:m,vegetables:x},O={title:"Example/DropdownMenu",component:i,parameters:{layout:"centered"},tags:["autodocs"],argTypes:{items:[1,2,3,4]},args:{}},o=()=>e.createElement(i,{defaultOpen:!0},e.createElement(d,null,e.createElement("button",null,"Click me!!")),e.createElement(C,null,e.createElement("div",null,e.createElement("h1",null,"Hello"),e.createElement("p",null,"How are you today?"),e.createElement(b,{onSelect:t=>console.log(t)},"Click me again"),e.createElement(b,{onSelect:t=>t.preventDefault()},"Click me, I won't close")))),r=()=>{const[t,p]=f.useState([m[6]]),[g,k]=f.useState([...s.fruits,...s.vegetables]),A=async n=>{await new Promise(u=>setTimeout(u,1e3));const l=s.fruits.filter(u=>u.name.toLowerCase().includes(n.toLowerCase()));k(l)};return e.createElement(i,{items:g,onSelect:(n,l)=>{n.preventDefault(),console.log(n,l)},renderItem:n=>e.createElement(c,{fruit:n}),defaultOpen:!0,onSearch:A},e.createElement(d,{showIcon:!0},e.createElement("div",{className:"flex items-center gap-2 justify-between"},e.createElement(c,{fruit:m[1]}),"(",t.length,")")),g.length===0&&e.createElement(C,null,e.createElement("div",null,"No items found")))},a=()=>{const t=[{name:"Vegetables",children:s.vegetables,emoji:"🥦"},{name:"Fruits",children:s.fruits,emoji:"🍎"}];return e.createElement("div",null,e.createElement(i,{defaultOpen:!0,items:t,renderItem:p=>e.createElement(c,{fruit:p})},e.createElement(d,null,e.createElement("button",{className:"text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"},"Select"))))},c=({fruit:t})=>e.createElement("div",null,`${t.emoji} ${t.name}`);o.__docgenInfo={description:"",methods:[],displayName:"DefaultDropdown"};r.__docgenInfo={description:"",methods:[],displayName:"MultiSelect"};a.__docgenInfo={description:"",methods:[],displayName:"NestedDropdown"};var w,h,v;o.parameters={...o.parameters,docs:{...(w=o.parameters)==null?void 0:w.docs,source:{originalSource:`() => {
return <DropdownMenu defaultOpen={true}>
<DropdownButton>
<button>Click me!!</button>
</DropdownButton>
<DropdownContent>
<div>
<h1>Hello</h1>
<p>How are you today?</p>
<DropdownItem onSelect={e => console.log(e)}>
Click me again
</DropdownItem>
<DropdownItem onSelect={e => e.preventDefault()}>
Click me, I won't close
</DropdownItem>
</div>
</DropdownContent>
</DropdownMenu>;
}`,...(v=(h=o.parameters)==null?void 0:h.docs)==null?void 0:v.source}}};var D,y,E;r.parameters={...r.parameters,docs:{...(D=r.parameters)==null?void 0:D.docs,source:{originalSource:`() => {
const [value, setValue] = useState([fruits[6]]);
const [items, setItems] = useState([...fruitsAndVegetables.fruits, ...fruitsAndVegetables.vegetables]);
const handleSearch = async (query: String) => {
await new Promise(resolve => setTimeout(resolve, 1000));
// Filters items on the name
const filteredItems = fruitsAndVegetables.fruits.filter(item => item.name.toLowerCase().includes(query.toLowerCase()));
setItems(filteredItems);
};
return <DropdownMenu items={items} onSelect={(e, value) => {
e.preventDefault();
console.log(e, value);
}} renderItem={item => <Fruit fruit={item} />} defaultOpen={true} onSearch={handleSearch}
// isItemDisabled={(item) => item.id % 2 === 0}
>
<DropdownButton showIcon>
<div className="flex items-center gap-2 justify-between">
<Fruit fruit={fruits[1]} />({value.length})
</div>
</DropdownButton>
{items.length === 0 && <DropdownContent>
<div>No items found</div>
</DropdownContent>}
</DropdownMenu>;
}`,...(E=(y=r.parameters)==null?void 0:y.docs)==null?void 0:E.source}}};var S,I,j;a.parameters={...a.parameters,docs:{...(S=a.parameters)==null?void 0:S.docs,source:{originalSource:`() => {
const items = [{
name: "Vegetables",
children: fruitsAndVegetables.vegetables,
emoji: "🥦"
}, {
name: "Fruits",
children: fruitsAndVegetables.fruits,
emoji: "🍎"
}];
return <div>
<DropdownMenu defaultOpen={true} items={items} renderItem={item => <Fruit fruit={item} />}>
<DropdownButton>
<button className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
Select
</button>
</DropdownButton>
</DropdownMenu>
</div>;
}`,...(j=(I=a.parameters)==null?void 0:I.docs)==null?void 0:j.source}}};const _=["DefaultDropdown","MultiSelect","NestedDropdown"];export{o as DefaultDropdown,r as MultiSelect,a as NestedDropdown,_ as __namedExportsOrder,O as default};
@@ -0,0 +1,9 @@
import{f as x}from"./index-B5ZI-g0m.js";import{R as t,r as y}from"./index-Cqyox1Tj.js";import{C as O,D as _,a as b,f as M}from"./fruits-CZbL9byb.js";import"./index-DtqWk5t9.js";import"./index-DGXSSr1l.js";const B=()=>t.createElement("div",{style:{width:"15px",height:"15px"}}," "),l=a=>{const{items:i,onChange:m,renderItem:R,renderGroup:G,multiple:w,value:d=[],keyExtractor:o=e=>e.id,showSelectedAtTop:E=!0,defaultOpen:p=!1,children:v}=a,[n,c]=t.useState(d),[g,C]=t.useState(p),T=(e,u)=>{const r=o(u);w?(e.preventDefault(),e.stopPropagation(),n.includes(r)?c(n.filter(k=>k!==r)):c([...n,r]),m([...n,r])):(c([r]),m([r]))},I=y.useCallback(e=>{const u=o(e),r=n.includes(u);return t.createElement("div",{className:"flex items-center gap-2 justify-between"},t.createElement(R,{fruit:e}),r?t.createElement(O,null):t.createElement(B,null))},[n,o]),N=t.useMemo(()=>E&&g?[...i.filter(e=>n.includes(o(e))),...i.filter(e=>!n.includes(o(e)))]:i,[d,g]),q=y.useCallback(e=>{C(e)},[]);return t.createElement(_,{defaultOpen:p,items:N,renderItem:I,onSelect:T,onOpenChange:q},v)};l.__docgenInfo={description:"",methods:[],displayName:"Select",props:{items:{required:!0,tsType:{name:"Array",elements:[{name:"any"}],raw:"any[]"},description:""},onChange:{required:!0,tsType:{name:"signature",type:"function",raw:"(value: any) => void",signature:{arguments:[{type:{name:"any"},name:"value"}],return:{name:"void"}}},description:""},value:{required:!0,tsType:{name:"any"},description:""},renderItem:{required:!0,tsType:{name:"signature",type:"function",raw:"(item: any) => React.ReactNode",signature:{arguments:[{type:{name:"any"},name:"item"}],return:{name:"ReactReactNode",raw:"React.ReactNode"}}},description:""},renderGroup:{required:!0,tsType:{name:"signature",type:"function",raw:"(group: string) => React.ReactNode",signature:{arguments:[{type:{name:"string"},name:"group"}],return:{name:"ReactReactNode",raw:"React.ReactNode"}}},description:""},multiple:{required:!1,tsType:{name:"boolean"},description:""},keyExtractor:{required:!1,tsType:{name:"signature",type:"function",raw:"(item: any) => string",signature:{arguments:[{type:{name:"any"},name:"item"}],return:{name:"string"}}},description:""},showSelectedAtTop:{required:!1,tsType:{name:"boolean"},description:""},defaultOpen:{required:!1,tsType:{name:"boolean"},description:""},children:{required:!0,tsType:{name:"ReactReactNode",raw:"React.ReactNode"},description:""}}};const D=b,z={title:"Example/SelectMenu",component:l,parameters:{layout:"centered"},tags:["autodocs"],argTypes:{items:[1,2,3,4]},args:{onChange:x()}},s=()=>t.createElement(l,{items:M,renderItem:F,onChange:function(a){console.log("Selected items",a)},value:[3,7,9],renderGroup:function(a){throw new Error("Function not implemented.")},multiple:!0,defaultOpen:!0},t.createElement(D,null,"Click Me!!")),F=({fruit:a})=>t.createElement("div",null,`${a.emoji} ${a.name}`);s.__docgenInfo={description:"",methods:[],displayName:"SingleSelect"};var f,S,h;s.parameters={...s.parameters,docs:{...(f=s.parameters)==null?void 0:f.docs,source:{originalSource:`() => {
return <Select items={fruits} renderItem={Fruit} onChange={function (value: any): void {
console.log("Selected items", value);
}} value={[3, 7, 9]} renderGroup={function (group: string): React.ReactNode {
throw new Error("Function not implemented.");
}} multiple defaultOpen>
<SelectButton>Click Me!!</SelectButton>
</Select>;
}`,...(h=(S=s.parameters)==null?void 0:S.docs)==null?void 0:h.source}}};const H=["SingleSelect"];export{s as SingleSelect,H as __namedExportsOrder,z as default};
@@ -0,0 +1 @@
var s=Object.create,a=Object.defineProperty,c=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,u=Object.getPrototypeOf,O=Object.prototype.hasOwnProperty,l=(e,r)=>function(){return e&&(r=(0,e[o(e)[0]])(e=0)),r},v=(e,r)=>function(){return r||(0,e[o(e)[0]])((r={exports:{}}).exports,r),r.exports},b=(e,r)=>{for(var t in r)a(e,t,{get:r[t],enumerable:!0})},n=(e,r,t,p)=>{if(r&&typeof r=="object"||typeof r=="function")for(let _ of o(r))!O.call(e,_)&&_!==t&&a(e,_,{get:()=>r[_],enumerable:!(p=c(r,_))||p.enumerable});return e},P=(e,r,t)=>(t=e!=null?s(u(e)):{},n(!e||!e.__esModule?a(t,"default",{value:e,enumerable:!0}):t,e)),y=e=>n(a({},"__esModule",{value:!0}),e);export{b as _,P as a,v as b,l as c,y as d};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./DropdownMenu.stories-BDxDk4nE.js","./index-Cqyox1Tj.js","./fruits-CZbL9byb.js","./index-DtqWk5t9.js","./index-DGXSSr1l.js","./Select.stories-MZU715vD.js","./index-B5ZI-g0m.js","./entry-preview-vYpJuD7B.js","./chunk-XP5HYGXS-BGCqD1aY.js","./entry-preview-docs-DhRFChcp.js","./index-CHGET4sZ.js","./preview-D77C14du.js","./index-DrFu-skq.js","./preview-BWzBA1C2.js","./preview-DtwGhum3.js","./preview-C5MXvx14.js","./preview-BA_NYCcE.css"])))=>i.map(i=>d[i]);
import"../sb-preview/runtime.js";(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))u(e);new MutationObserver(e=>{for(const r of e)if(r.type==="childList")for(const i of r.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&u(i)}).observe(document,{childList:!0,subtree:!0});function l(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?r.credentials="include":e.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function u(e){if(e.ep)return;e.ep=!0;const r=l(e);fetch(e.href,r)}})();const R="modulepreload",T=function(t,n){return new URL(t,n).href},p={},_=function(n,l,u){let e=Promise.resolve();if(l&&l.length>0){const i=document.getElementsByTagName("link"),o=document.querySelector("meta[property=csp-nonce]"),d=(o==null?void 0:o.nonce)||(o==null?void 0:o.getAttribute("nonce"));e=Promise.allSettled(l.map(s=>{if(s=T(s,u),s in p)return;p[s]=!0;const a=s.endsWith(".css"),f=a?'[rel="stylesheet"]':"";if(!!u)for(let m=i.length-1;m>=0;m--){const E=i[m];if(E.href===s&&(!a||E.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${s}"]${f}`))return;const c=document.createElement("link");if(c.rel=a?"stylesheet":R,a||(c.as="script"),c.crossOrigin="",c.href=s,d&&c.setAttribute("nonce",d),document.head.appendChild(c),a)return new Promise((m,E)=>{c.addEventListener("load",m),c.addEventListener("error",()=>E(new Error(`Unable to preload CSS for ${s}`)))})}))}function r(i){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=i,window.dispatchEvent(o),!o.defaultPrevented)throw i}return e.then(i=>{for(const o of i||[])o.status==="rejected"&&r(o.reason);return n().catch(r)})},{createBrowserChannel:L}=__STORYBOOK_MODULE_CHANNELS__,{addons:S}=__STORYBOOK_MODULE_PREVIEW_API__,O=L({page:"preview"});S.setChannel(O);window.__STORYBOOK_ADDONS_CHANNEL__=O;window.CONFIG_TYPE==="DEVELOPMENT"&&(window.__STORYBOOK_SERVER_CHANNEL__=O);const P={"./src/components/DropdownMenu/DropdownMenu.stories.tsx":async()=>_(()=>import("./DropdownMenu.stories-BDxDk4nE.js"),__vite__mapDeps([0,1,2,3,4]),import.meta.url),"./src/components/Select/Select.stories.tsx":async()=>_(()=>import("./Select.stories-MZU715vD.js"),__vite__mapDeps([5,6,1,2,3,4]),import.meta.url)};async function y(t){return P[t]()}const{composeConfigs:I,PreviewWeb:w,ClientApi:h}=__STORYBOOK_MODULE_PREVIEW_API__,D=async(t=[])=>{const n=await Promise.all([t[0]??_(()=>import("./entry-preview-vYpJuD7B.js"),__vite__mapDeps([7,8,1,4]),import.meta.url),t[1]??_(()=>import("./entry-preview-docs-DhRFChcp.js"),__vite__mapDeps([9,8,10,1]),import.meta.url),t[2]??_(()=>import("./preview-BpGyWwfw.js"),[],import.meta.url),t[3]??_(()=>import("./preview-aVwhiz9X.js"),[],import.meta.url),t[4]??_(()=>import("./preview-D77C14du.js"),__vite__mapDeps([11,12]),import.meta.url),t[5]??_(()=>import("./preview-DFmD0pui.js"),[],import.meta.url),t[6]??_(()=>import("./preview-CFgKly6U.js"),[],import.meta.url),t[7]??_(()=>import("./preview-BWzBA1C2.js"),__vite__mapDeps([13,12]),import.meta.url),t[8]??_(()=>import("./preview-DGUiP6tS.js"),[],import.meta.url),t[9]??_(()=>import("./preview-DtwGhum3.js"),__vite__mapDeps([14,6]),import.meta.url),t[10]??_(()=>import("./preview-C5MXvx14.js"),__vite__mapDeps([15,16]),import.meta.url)]);return I(n)};window.__STORYBOOK_PREVIEW__=window.__STORYBOOK_PREVIEW__||new w(y,D);window.__STORYBOOK_STORY_STORE__=window.__STORYBOOK_STORY_STORE__||window.__STORYBOOK_PREVIEW__.storyStore;export{_};
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
import{R as e}from"./index-Cqyox1Tj.js";const o={},c=e.createContext(o);function u(n){const t=e.useContext(c);return e.useMemo(function(){return typeof n=="function"?n(t):{...t,...n}},[t,n])}function m(n){let t;return n.disableParentContext?t=typeof n.components=="function"?n.components(o):n.components||o:t=u(n.components),e.createElement(c.Provider,{value:t},n.children)}export{m as MDXProvider,u as useMDXComponents};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
function l(o){for(var f=[],i=1;i<arguments.length;i++)f[i-1]=arguments[i];var n=Array.from(typeof o=="string"?[o]:o);n[n.length-1]=n[n.length-1].replace(/\r?\n([\t ]*)$/,"");var s=n.reduce(function(t,g){var a=g.match(/\n([\t ]+|(?!\s).)/g);return a?t.concat(a.map(function(u){var r,e;return(e=(r=u.match(/[\t ]/g))===null||r===void 0?void 0:r.length)!==null&&e!==void 0?e:0})):t},[]);if(s.length){var d=new RegExp(`
[ ]{`+Math.min.apply(Math,s)+"}","g");n=n.map(function(t){return t.replace(d,`
`)})}n[0]=n[0].replace(/^\r?\n/,"");var c=n[0];return f.forEach(function(t,g){var a=c.match(/(?:^|\n)( *)$/),u=a?a[1]:"",r=t;typeof t=="string"&&t.includes(`
`)&&(r=String(t).split(`
`).map(function(e,h){return h===0?e:""+u+e}).join(`
`)),c+=r+n[g+1]}),c}export{l as d};
@@ -0,0 +1,9 @@
import{a as v,g as y}from"./index-Cqyox1Tj.js";import{r as E}from"./index-DGXSSr1l.js";var s={exports:{}},t={};/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var f;function O(){if(f)return t;f=1;var _=v(),R=Symbol.for("react.element"),c=Symbol.for("react.fragment"),x=Object.prototype.hasOwnProperty,l=_.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,d={key:!0,ref:!0,__self:!0,__source:!0};function u(o,r,a){var e,n={},i=null,p=null;a!==void 0&&(i=""+a),r.key!==void 0&&(i=""+r.key),r.ref!==void 0&&(p=r.ref);for(e in r)x.call(r,e)&&!d.hasOwnProperty(e)&&(n[e]=r[e]);if(o&&o.defaultProps)for(e in r=o.defaultProps,r)n[e]===void 0&&(n[e]=r[e]);return{$$typeof:R,type:o,key:i,ref:p,props:n,_owner:l.current}}return t.Fragment=c,t.jsx=u,t.jsxs=u,t}var m;function j(){return m||(m=1,s.exports=O()),s.exports}var D=j(),q=E();const F=y(q);export{F,D as j,q as r};
@@ -0,0 +1 @@
import{m as l,a as c,G as T,K as b,P as d,g as S,L as B,b as L,v as C,w as H,c as u,E as g,$ as y,y as I,d as h,N as k,e as P,D as W,x as A,C as F,f as x,S as D,R,I as f,h as v,i as E,A as M,F as N,j as q,k as w,l as O,W as U,n as Z,T as j,t as z,o as G,p as J,q as K,r as Q,s as V,u as X,z as Y,B as _,H as $,J as aa,M as sa,V as oa,O as ta,Q as ea,U as ra,X as pa,Y as ia,Z as na,_ as ma,a0 as la,a1 as ca,a2 as Ta,a3 as ba,a4 as da,a5 as Sa,a6 as Ba,a7 as La,a8 as Ca,a9 as Ha,aa as ua,ab as ga,ac as ya,ad as Ia}from"./DocsRenderer-CFRXHY34-BAI5cjJR.js";import"./iframe-DUcCSOHa.js";import"../sb-preview/runtime.js";import"./index-Cqyox1Tj.js";import"./index-DtqWk5t9.js";import"./index-DGXSSr1l.js";import"./index-CHGET4sZ.js";import"./index-DrFu-skq.js";import"./react-18-CNJE3xZy.js";export{l as A,c as ActionBar,T as AddonPanel,b as Badge,d as Bar,S as Blockquote,B as Button,L as ClipboardCode,C as Code,H as DL,u as Div,g as DocumentWrapper,y as EmptyTabContent,I as ErrorFormatter,h as FlexBar,k as Form,P as H1,W as H2,A as H3,F as H4,x as H5,D as H6,R as HR,f as IconButton,v as IconButtonSkeleton,E as Icons,M as Img,N as LI,q as Link,w as ListItem,O as Loader,U as Modal,Z as OL,j as P,z as Placeholder,G as Pre,J as ResetWrapper,K as ScrollArea,Q as Separator,V as Spaced,X as Span,Y as StorybookIcon,_ as StorybookLogo,$ as Symbols,aa as SyntaxHighlighter,sa as TT,oa as TabBar,ta as TabButton,ea as TabWrapper,ra as Table,pa as Tabs,ia as TabsState,na as TooltipLinkList,ma as TooltipMessage,la as TooltipNote,ca as UL,Ta as WithTooltip,ba as WithTooltipPure,da as Zoom,Sa as codeCommon,Ba as components,La as createCopyToClipboardFunction,Ca as getStoryHref,Ha as icons,ua as interleaveSeparators,ga as nameSpaceClassNames,ya as resetComponents,Ia as withReset};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,396 @@
import{d as $}from"./index-DrFu-skq.js";const{useMemo:x,useEffect:f}=__STORYBOOK_MODULE_PREVIEW_API__,{global:p}=__STORYBOOK_MODULE_GLOBAL__;var m="outline",u=i=>{(Array.isArray(i)?i:[i]).forEach(r)},r=i=>{let t=typeof i=="string"?i:i.join(""),o=p.document.getElementById(t);o&&o.parentElement&&o.parentElement.removeChild(o)},b=(i,t)=>{let o=p.document.getElementById(i);if(o)o.innerHTML!==t&&(o.innerHTML=t);else{let n=p.document.createElement("style");n.setAttribute("id",i),n.innerHTML=t,p.document.head.appendChild(n)}};function s(i){return $`
${i} body {
outline: 1px solid #2980b9 !important;
}
${i} article {
outline: 1px solid #3498db !important;
}
${i} nav {
outline: 1px solid #0088c3 !important;
}
${i} aside {
outline: 1px solid #33a0ce !important;
}
${i} section {
outline: 1px solid #66b8da !important;
}
${i} header {
outline: 1px solid #99cfe7 !important;
}
${i} footer {
outline: 1px solid #cce7f3 !important;
}
${i} h1 {
outline: 1px solid #162544 !important;
}
${i} h2 {
outline: 1px solid #314e6e !important;
}
${i} h3 {
outline: 1px solid #3e5e85 !important;
}
${i} h4 {
outline: 1px solid #449baf !important;
}
${i} h5 {
outline: 1px solid #c7d1cb !important;
}
${i} h6 {
outline: 1px solid #4371d0 !important;
}
${i} main {
outline: 1px solid #2f4f90 !important;
}
${i} address {
outline: 1px solid #1a2c51 !important;
}
${i} div {
outline: 1px solid #036cdb !important;
}
${i} p {
outline: 1px solid #ac050b !important;
}
${i} hr {
outline: 1px solid #ff063f !important;
}
${i} pre {
outline: 1px solid #850440 !important;
}
${i} blockquote {
outline: 1px solid #f1b8e7 !important;
}
${i} ol {
outline: 1px solid #ff050c !important;
}
${i} ul {
outline: 1px solid #d90416 !important;
}
${i} li {
outline: 1px solid #d90416 !important;
}
${i} dl {
outline: 1px solid #fd3427 !important;
}
${i} dt {
outline: 1px solid #ff0043 !important;
}
${i} dd {
outline: 1px solid #e80174 !important;
}
${i} figure {
outline: 1px solid #ff00bb !important;
}
${i} figcaption {
outline: 1px solid #bf0032 !important;
}
${i} table {
outline: 1px solid #00cc99 !important;
}
${i} caption {
outline: 1px solid #37ffc4 !important;
}
${i} thead {
outline: 1px solid #98daca !important;
}
${i} tbody {
outline: 1px solid #64a7a0 !important;
}
${i} tfoot {
outline: 1px solid #22746b !important;
}
${i} tr {
outline: 1px solid #86c0b2 !important;
}
${i} th {
outline: 1px solid #a1e7d6 !important;
}
${i} td {
outline: 1px solid #3f5a54 !important;
}
${i} col {
outline: 1px solid #6c9a8f !important;
}
${i} colgroup {
outline: 1px solid #6c9a9d !important;
}
${i} button {
outline: 1px solid #da8301 !important;
}
${i} datalist {
outline: 1px solid #c06000 !important;
}
${i} fieldset {
outline: 1px solid #d95100 !important;
}
${i} form {
outline: 1px solid #d23600 !important;
}
${i} input {
outline: 1px solid #fca600 !important;
}
${i} keygen {
outline: 1px solid #b31e00 !important;
}
${i} label {
outline: 1px solid #ee8900 !important;
}
${i} legend {
outline: 1px solid #de6d00 !important;
}
${i} meter {
outline: 1px solid #e8630c !important;
}
${i} optgroup {
outline: 1px solid #b33600 !important;
}
${i} option {
outline: 1px solid #ff8a00 !important;
}
${i} output {
outline: 1px solid #ff9619 !important;
}
${i} progress {
outline: 1px solid #e57c00 !important;
}
${i} select {
outline: 1px solid #e26e0f !important;
}
${i} textarea {
outline: 1px solid #cc5400 !important;
}
${i} details {
outline: 1px solid #33848f !important;
}
${i} summary {
outline: 1px solid #60a1a6 !important;
}
${i} command {
outline: 1px solid #438da1 !important;
}
${i} menu {
outline: 1px solid #449da6 !important;
}
${i} del {
outline: 1px solid #bf0000 !important;
}
${i} ins {
outline: 1px solid #400000 !important;
}
${i} img {
outline: 1px solid #22746b !important;
}
${i} iframe {
outline: 1px solid #64a7a0 !important;
}
${i} embed {
outline: 1px solid #98daca !important;
}
${i} object {
outline: 1px solid #00cc99 !important;
}
${i} param {
outline: 1px solid #37ffc4 !important;
}
${i} video {
outline: 1px solid #6ee866 !important;
}
${i} audio {
outline: 1px solid #027353 !important;
}
${i} source {
outline: 1px solid #012426 !important;
}
${i} canvas {
outline: 1px solid #a2f570 !important;
}
${i} track {
outline: 1px solid #59a600 !important;
}
${i} map {
outline: 1px solid #7be500 !important;
}
${i} area {
outline: 1px solid #305900 !important;
}
${i} a {
outline: 1px solid #ff62ab !important;
}
${i} em {
outline: 1px solid #800b41 !important;
}
${i} strong {
outline: 1px solid #ff1583 !important;
}
${i} i {
outline: 1px solid #803156 !important;
}
${i} b {
outline: 1px solid #cc1169 !important;
}
${i} u {
outline: 1px solid #ff0430 !important;
}
${i} s {
outline: 1px solid #f805e3 !important;
}
${i} small {
outline: 1px solid #d107b2 !important;
}
${i} abbr {
outline: 1px solid #4a0263 !important;
}
${i} q {
outline: 1px solid #240018 !important;
}
${i} cite {
outline: 1px solid #64003c !important;
}
${i} dfn {
outline: 1px solid #b4005a !important;
}
${i} sub {
outline: 1px solid #dba0c8 !important;
}
${i} sup {
outline: 1px solid #cc0256 !important;
}
${i} time {
outline: 1px solid #d6606d !important;
}
${i} code {
outline: 1px solid #e04251 !important;
}
${i} kbd {
outline: 1px solid #5e001f !important;
}
${i} samp {
outline: 1px solid #9c0033 !important;
}
${i} var {
outline: 1px solid #d90047 !important;
}
${i} mark {
outline: 1px solid #ff0053 !important;
}
${i} bdi {
outline: 1px solid #bf3668 !important;
}
${i} bdo {
outline: 1px solid #6f1400 !important;
}
${i} ruby {
outline: 1px solid #ff7b93 !important;
}
${i} rt {
outline: 1px solid #ff2f54 !important;
}
${i} rp {
outline: 1px solid #803e49 !important;
}
${i} span {
outline: 1px solid #cc2643 !important;
}
${i} br {
outline: 1px solid #db687d !important;
}
${i} wbr {
outline: 1px solid #db175b !important;
}`}var e=(i,t)=>{let{globals:o}=t,n=[!0,"true"].includes(o[m]),d=t.viewMode==="docs",l=x(()=>s(d?'[data-story-block="true"]':".sb-show-main"),[t]);return f(()=>{let a=d?`addon-outline-docs-${t.id}`:"addon-outline";return n?b(a,l):u(a),()=>{u(a)}},[n,l,t]),i()},h=[e],g={[m]:!1};export{h as decorators,g as initialGlobals};
@@ -0,0 +1,2 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./DocsRenderer-CFRXHY34-BAI5cjJR.js","./iframe-DUcCSOHa.js","./index-Cqyox1Tj.js","./index-DtqWk5t9.js","./index-DGXSSr1l.js","./index-CHGET4sZ.js","./index-DrFu-skq.js","./react-18-CNJE3xZy.js"])))=>i.map(i=>d[i]);
import{_ as a}from"./iframe-DUcCSOHa.js";import"../sb-preview/runtime.js";var i=Object.entries(globalThis.TAGS_OPTIONS??{}).reduce((e,r)=>{let[t,o]=r;return o.excludeFromDocsStories&&(e[t]=!0),e},{}),d={docs:{renderer:async()=>{let{DocsRenderer:e}=await a(()=>import("./DocsRenderer-CFRXHY34-BAI5cjJR.js").then(r=>r.ak),__vite__mapDeps([0,1,2,3,4,5,6,7]),import.meta.url);return new e},stories:{filter:e=>{var r;return(e.tags||[]).filter(t=>i[t]).length===0&&!((r=e.parameters.docs)!=null&&r.disable)}}}};export{d as parameters};
@@ -0,0 +1 @@
const e={parameters:{controls:{matchers:{color:/(background|color)$/i,date:/Date$/i}}}};export{e as default};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,34 @@
import{d as Y}from"./index-DrFu-skq.js";const{useEffect:_,useMemo:h}=__STORYBOOK_MODULE_PREVIEW_API__,{global:H}=__STORYBOOK_MODULE_GLOBAL__,{logger:K}=__STORYBOOK_MODULE_CLIENT_LOGGER__;var g="backgrounds",C={light:{name:"light",value:"#F8F8F8"},dark:{name:"dark",value:"#333"}},{document:$,window:T}=H,I=()=>{var r;return!!((r=T==null?void 0:T.matchMedia("(prefers-reduced-motion: reduce)"))!=null&&r.matches)},A=r=>{(Array.isArray(r)?r:[r]).forEach(P)},P=r=>{var t;let e=$.getElementById(r);e&&((t=e.parentElement)==null||t.removeChild(e))},z=(r,e)=>{let t=$.getElementById(r);if(t)t.innerHTML!==e&&(t.innerHTML=e);else{let d=$.createElement("style");d.setAttribute("id",r),d.innerHTML=e,$.head.appendChild(d)}},U=(r,e,t)=>{var a;let d=$.getElementById(r);if(d)d.innerHTML!==e&&(d.innerHTML=e);else{let o=$.createElement("style");o.setAttribute("id",r),o.innerHTML=e;let i=`addon-backgrounds-grid${t?`-docs-${t}`:""}`,n=$.getElementById(i);n?(a=n.parentElement)==null||a.insertBefore(o,n):$.head.appendChild(o)}},j={cellSize:100,cellAmount:10,opacity:.8},w="addon-backgrounds",R="addon-backgrounds-grid",X=I()?"":"transition: background-color 0.3s;",N=(r,e)=>{let{globals:t,parameters:d,viewMode:a,id:o}=e,{options:i=C,disable:n,grid:s=j}=d[g]||{},c=t[g]||{},u=c.value,l=u?i[u]:void 0,b=(l==null?void 0:l.value)||"transparent",f=c.grid||!1,y=!!l&&!n,m=a==="docs"?`#anchor--${o} .docs-story`:".sb-show-main",E=a==="docs"?`#anchor--${o} .docs-story`:".sb-show-main",D=d.layout===void 0||d.layout==="padded",L=a==="docs"?20:D?16:0,{cellAmount:k,cellSize:p,opacity:x,offsetX:v=L,offsetY:S=L}=s,B=a==="docs"?`${w}-docs-${o}`:`${w}-color`,G=a==="docs"?o:null;_(()=>{let O=`
${m} {
background: ${b} !important;
${X}
}`;if(!y){A(B);return}U(B,O,G)},[m,B,G,y,b]);let M=a==="docs"?`${R}-docs-${o}`:`${R}`;return _(()=>{if(!f){A(M);return}let O=[`${p*k}px ${p*k}px`,`${p*k}px ${p*k}px`,`${p}px ${p}px`,`${p}px ${p}px`].join(", "),F=`
${E} {
background-size: ${O} !important;
background-position: ${v}px ${S}px, ${v}px ${S}px, ${v}px ${S}px, ${v}px ${S}px !important;
background-blend-mode: difference !important;
background-image: linear-gradient(rgba(130, 130, 130, ${x}) 1px, transparent 1px),
linear-gradient(90deg, rgba(130, 130, 130, ${x}) 1px, transparent 1px),
linear-gradient(rgba(130, 130, 130, ${x/2}) 1px, transparent 1px),
linear-gradient(90deg, rgba(130, 130, 130, ${x/2}) 1px, transparent 1px) !important;
}
`;z(M,F)},[k,p,E,M,f,v,S,x]),r()},W=(r,e=[],t)=>{if(r==="transparent")return"transparent";if(e.find(a=>a.value===r)||r)return r;let d=e.find(a=>a.name===t);if(d)return d.value;if(t){let a=e.map(o=>o.name).join(", ");K.warn(Y`
Backgrounds Addon: could not find the default color "${t}".
These are the available colors for your story based on your configuration:
${a}.
`)}return"transparent"},q=(r,e)=>{var u;let{globals:t,parameters:d}=e,a=(u=t[g])==null?void 0:u.value,o=d[g],i=h(()=>o.disable?"transparent":W(a,o.values,o.default),[o,a]),n=h(()=>i&&i!=="transparent",[i]),s=e.viewMode==="docs"?`#anchor--${e.id} .docs-story`:".sb-show-main",c=h(()=>`
${s} {
background: ${i} !important;
${I()?"":"transition: background-color 0.3s;"}
}
`,[i,s]);return _(()=>{let l=e.viewMode==="docs"?`addon-backgrounds-docs-${e.id}`:"addon-backgrounds-color";if(!n){A(l);return}U(l,c,e.viewMode==="docs"?e.id:null)},[n,c,e]),r()},J=(r,e)=>{var y;let{globals:t,parameters:d}=e,a=d[g].grid,o=((y=t[g])==null?void 0:y.grid)===!0&&a.disable!==!0,{cellAmount:i,cellSize:n,opacity:s}=a,c=e.viewMode==="docs",u=d.layout===void 0||d.layout==="padded"?16:0,l=a.offsetX??(c?20:u),b=a.offsetY??(c?20:u),f=h(()=>{let m=e.viewMode==="docs"?`#anchor--${e.id} .docs-story`:".sb-show-main",E=[`${n*i}px ${n*i}px`,`${n*i}px ${n*i}px`,`${n}px ${n}px`,`${n}px ${n}px`].join(", ");return`
${m} {
background-size: ${E} !important;
background-position: ${l}px ${b}px, ${l}px ${b}px, ${l}px ${b}px, ${l}px ${b}px !important;
background-blend-mode: difference !important;
background-image: linear-gradient(rgba(130, 130, 130, ${s}) 1px, transparent 1px),
linear-gradient(90deg, rgba(130, 130, 130, ${s}) 1px, transparent 1px),
linear-gradient(rgba(130, 130, 130, ${s/2}) 1px, transparent 1px),
linear-gradient(90deg, rgba(130, 130, 130, ${s/2}) 1px, transparent 1px) !important;
}
`},[n]);return _(()=>{let m=e.viewMode==="docs"?`addon-backgrounds-grid-docs-${e.id}`:"addon-backgrounds-grid";if(!o){A(m);return}z(m,f)},[o,f,e]),r()},V=FEATURES!=null&&FEATURES.backgroundsStoryGlobals?[N]:[J,q],ee={[g]:{grid:{cellSize:20,opacity:.5,cellAmount:5},disable:!1,...!(FEATURES!=null&&FEATURES.backgroundsStoryGlobals)&&{values:Object.values(C)}}},Q={[g]:{value:void 0,grid:!1}},re=FEATURES!=null&&FEATURES.backgroundsStoryGlobals?Q:{[g]:null};export{V as decorators,re as initialGlobals,ee as parameters};
@@ -0,0 +1 @@
var e="viewport",o={[e]:{value:void 0,isRotated:!1}},t={viewport:"reset",viewportRotated:!1},r=FEATURES!=null&&FEATURES.viewportStoryGlobals?o:t;export{r as initialGlobals};
@@ -0,0 +1,7 @@
const{STORY_CHANGED:r}=__STORYBOOK_MODULE_CORE_EVENTS__,{addons:s}=__STORYBOOK_MODULE_PREVIEW_API__,{global:O}=__STORYBOOK_MODULE_GLOBAL__;var d="storybook/highlight",i="storybookHighlight",g=`${d}/add`,E=`${d}/reset`,{document:l}=O,H=(e="#FF4785",t="dashed")=>`
outline: 2px ${t} ${e};
outline-offset: 2px;
box-shadow: 0 0 0 6px rgba(255,255,255,0.6);
`,h=s.getChannel(),T=e=>{let t=i;n();let o=Array.from(new Set(e.elements)),_=l.createElement("style");_.setAttribute("id",t),_.innerHTML=o.map(a=>`${a}{
${H(e.color,e.style)}
}`).join(" "),l.head.appendChild(_)},n=()=>{var o;let e=i,t=l.getElementById(e);t&&((o=t.parentNode)==null||o.removeChild(t))};h.on(r,n);h.on(E,n);h.on(g,T);
@@ -0,0 +1 @@
import{i as r}from"./index-B5ZI-g0m.js";var{step:a}=r({step:(p,t,e)=>t(e)},{intercept:!0}),i={throwPlayFunctionExceptions:!1};export{i as parameters,a as runStep};
@@ -0,0 +1 @@
let l;const S=new Uint8Array(16);function A(){if(!l&&(l=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!l))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return l(S)}const o=[];for(let e=0;e<256;++e)o.push((e+256).toString(16).slice(1));function D(e,t=0){return o[e[t+0]]+o[e[t+1]]+o[e[t+2]]+o[e[t+3]]+"-"+o[e[t+4]]+o[e[t+5]]+"-"+o[e[t+6]]+o[e[t+7]]+"-"+o[e[t+8]]+o[e[t+9]]+"-"+o[e[t+10]]+o[e[t+11]]+o[e[t+12]]+o[e[t+13]]+o[e[t+14]]+o[e[t+15]]}const I=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),m={randomUUID:I};function v(e,t,r){if(m.randomUUID&&!t&&!e)return m.randomUUID();e=e||{};const n=e.random||(e.rng||A)();return n[6]=n[6]&15|64,n[8]=n[8]&63|128,D(n)}const{addons:w}=__STORYBOOK_MODULE_PREVIEW_API__,{ImplicitActionsDuringRendering:U}=__STORYBOOK_MODULE_CORE_EVENTS_PREVIEW_ERRORS__,{global:p}=__STORYBOOK_MODULE_GLOBAL__;var f="storybook/actions",j=`${f}/action-event`,V={depth:10,clearOnStoryChange:!0,limit:50},E=(e,t)=>{let r=Object.getPrototypeOf(e);return!r||t(r)?r:E(r,t)},C=e=>!!(typeof e=="object"&&e&&E(e,t=>/^Synthetic(?:Base)?Event$/.test(t.constructor.name))&&typeof e.persist=="function"),K=e=>{if(C(e)){let t=Object.create(e.constructor.prototype,Object.getOwnPropertyDescriptors(e));t.persist();let r=Object.getOwnPropertyDescriptor(t,"view"),n=r==null?void 0:r.value;return typeof n=="object"&&(n==null?void 0:n.constructor.name)==="Window"&&Object.defineProperty(t,"view",{...r,value:Object.create(n.constructor.prototype)}),t}return e},L=()=>typeof crypto=="object"&&typeof crypto.getRandomValues=="function"?v():Date.now().toString(36)+Math.random().toString(36).substring(2);function u(e,t={}){let r={...V,...t},n=function(...c){var g,O;if(t.implicit){let y=(g="__STORYBOOK_PREVIEW__"in p?p.__STORYBOOK_PREVIEW__:void 0)==null?void 0:g.storyRenders.find(d=>d.phase==="playing"||d.phase==="rendering");if(y){let d=!((O=window==null?void 0:window.FEATURES)!=null&&O.disallowImplicitActionsInRenderV8),R=new U({phase:y.phase,name:e,deprecated:d});if(d)console.warn(R);else throw R}}let i=w.getChannel(),s=L(),a=5,_=c.map(K),b=c.length>1?_:_[0],x={id:s,count:0,data:{name:e,args:b},options:{...r,maxDepth:a+(r.depth||3),allowFunction:r.allowFunction||!1}};i.emit(j,x)};return n.isAction=!0,n.implicit=t.implicit,n}var T=(e,t)=>typeof t[e]>"u"&&!(e in t),B=e=>{let{initialArgs:t,argTypes:r,id:n,parameters:{actions:c}}=e;if(!c||c.disable||!c.argTypesRegex||!r)return{};let i=new RegExp(c.argTypesRegex);return Object.entries(r).filter(([s])=>!!i.test(s)).reduce((s,[a,_])=>(T(a,t)&&(s[a]=u(a,{implicit:!0,id:n})),s),{})},M=e=>{let{initialArgs:t,argTypes:r,parameters:{actions:n}}=e;return n!=null&&n.disable||!r?{}:Object.entries(r).filter(([c,i])=>!!i.action).reduce((c,[i,s])=>(T(i,t)&&(c[i]=u(typeof s.action=="string"?s.action:i)),c),{})},Y=[M,B],h=!1,P=e=>{let{parameters:{actions:t}}=e;if(!(t!=null&&t.disable)&&!h&&"__STORYBOOK_TEST_ON_MOCK_CALL__"in p&&typeof p.__STORYBOOK_TEST_ON_MOCK_CALL__=="function"){let r=p.__STORYBOOK_TEST_ON_MOCK_CALL__;r((n,c)=>{let i=n.getMockName();i!=="spy"&&(!/^next\/.*::/.test(i)||["next/router::useRouter()","next/navigation::useRouter()","next/navigation::redirect","next/cache::","next/headers::cookies().set","next/headers::cookies().delete","next/headers::headers().set","next/headers::headers().delete"].some(s=>i.startsWith(s)))&&u(i)(c)}),h=!0}},N=[P];export{Y as argsEnhancers,N as loaders};
@@ -0,0 +1 @@
import{r as i}from"./index-Cqyox1Tj.js";import{r as m}from"./index-DGXSSr1l.js";var n={},u;function c(){if(u)return n;u=1;var e=m();return n.createRoot=e.createRoot,n.hydrateRoot=e.hydrateRoot,n}var R=c(),s=new Map;function v(){return globalThis.IS_REACT_ACT_ENVIRONMENT}var f=({callback:e,children:t})=>{let r=i.useRef();return i.useLayoutEffect(()=>{r.current!==e&&(r.current=e,e())},[e]),t};typeof Promise.withResolvers>"u"&&(Promise.withResolvers=()=>{let e=null,t=null;return{promise:new Promise((r,o)=>{e=r,t=o}),resolve:e,reject:t}});var d=async(e,t,r)=>{let o=await p(t,r);if(v()){o.render(e);return}let{promise:a,resolve:l}=Promise.withResolvers();return o.render(i.createElement(f,{callback:l},e)),a},w=(e,t)=>{let r=s.get(e);r&&(r.unmount(),s.delete(e))},p=async(e,t)=>{let r=s.get(e);return r||(r=R.createRoot(e,t),s.set(e,r)),r};export{d as renderElement,w as unmountElement};
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svgjs="http://svgjs.com/svgjs" xmlns:xlink="http://www.w3.org/1999/xlink" width="164" height="164" version="1.1"><svg xmlns="http://www.w3.org/2000/svg" width="164" height="164" fill="none" viewBox="0 0 164 164"><path fill="#FF4785" d="M22.467 147.762 17.5 15.402a8.062 8.062 0 0 1 7.553-8.35L137.637.016a8.061 8.061 0 0 1 8.565 8.047v144.23a8.063 8.063 0 0 1-8.424 8.054l-107.615-4.833a8.062 8.062 0 0 1-7.695-7.752Z"/><path fill="#fff" fill-rule="evenodd" d="m128.785.57-15.495.968-.755 18.172a1.203 1.203 0 0 0 1.928 1.008l7.06-5.354 5.962 4.697a1.202 1.202 0 0 0 1.946-.987L128.785.569Zm-12.059 60.856c-2.836 2.203-23.965 3.707-23.965.57.447-11.969-4.912-12.494-7.889-12.494-2.828 0-7.59.855-7.59 7.267 0 6.534 6.96 10.223 15.13 14.553 11.607 6.15 25.654 13.594 25.654 32.326 0 17.953-14.588 27.871-33.194 27.871-19.201 0-35.981-7.769-34.086-34.702.744-3.163 25.156-2.411 25.156 0-.298 11.114 2.232 14.383 8.633 14.383 4.912 0 7.144-2.708 7.144-7.267 0-6.9-7.252-10.973-15.595-15.657C64.827 81.933 51.53 74.468 51.53 57.34c0-17.098 11.76-28.497 32.747-28.497 20.988 0 32.449 11.224 32.449 32.584Z" clip-rule="evenodd"/></svg><style>@media (prefers-color-scheme:light){:root{filter:none}}</style></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+640
View File
@@ -0,0 +1,640 @@
<!doctype html>
<!--suppress HtmlUnknownTarget -->
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Storybook</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-regular.woff2') format('woff2');
}
@font-face {
font-family: 'Nunito Sans';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-italic.woff2') format('woff2');
}
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-bold.woff2') format('woff2');
}
@font-face {
font-family: 'Nunito Sans';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-bold-italic.woff2') format('woff2');
}
</style>
<script>
window.CONFIG_TYPE = 'PRODUCTION';
window.LOGLEVEL = 'info';
window.FRAMEWORK_OPTIONS = {};
window.CHANNEL_OPTIONS = {};
window.FEATURES = {"argTypeTargetsV7":true,"legacyDecoratorFileOrder":false,"disallowImplicitActionsInRenderV8":true};
window.STORIES = [{"titlePrefix":"","directory":"./src","files":"**/*.mdx","importPathMatcher":"^\\.[\\\\/](?:src(?:\\/(?!\\.)(?:(?:(?!(?:^|\\/)\\.).)*?)\\/|\\/|$)(?!\\.)(?=.)[^/]*?\\.mdx)$"},{"titlePrefix":"","directory":"./src","files":"**/*.stories.@(js|jsx|mjs|ts|tsx)","importPathMatcher":"^\\.[\\\\/](?:src(?:\\/(?!\\.)(?:(?:(?!(?:^|\\/)\\.).)*?)\\/|\\/|$)(?!\\.)(?=.)[^/]*?\\.stories\\.(js|jsx|mjs|ts|tsx))$"}];
window.DOCS_OPTIONS = {"defaultName":"Docs","autodocs":"tag"};
window.TAGS_OPTIONS = {"dev-only":{"excludeFromDocsStories":true},"docs-only":{"excludeFromSidebar":true},"test-only":{"excludeFromSidebar":true,"excludeFromDocsStories":true}};
// We do this so that "module && module.hot" etc. in Storybook source code
// doesn't fail (it will simply be disabled)
window.module = undefined;
window.global = window;
</script>
<base target="_parent" />
<style>
/* While we aren't showing the main block yet, but still preparing, we want everything the user
has rendered, which may or may not be in #storybook-root, to be display none */
.sb-show-preparing-story:not(.sb-show-main) > :not(.sb-preparing-story) {
display: none;
}
.sb-show-preparing-docs:not(.sb-show-main) > :not(.sb-preparing-docs) {
display: none;
}
/* Hide our own blocks when we aren't supposed to be showing them */
:not(.sb-show-preparing-story) > .sb-preparing-story,
:not(.sb-show-preparing-docs) > .sb-preparing-docs,
:not(.sb-show-nopreview) > .sb-nopreview,
:not(.sb-show-errordisplay) > .sb-errordisplay {
display: none;
}
.sb-show-main.sb-main-centered {
margin: 0;
display: flex;
align-items: center;
min-height: 100vh;
}
.sb-show-main.sb-main-centered #storybook-root {
box-sizing: border-box;
margin: auto;
padding: 1rem;
max-height: 100%;
/* Hack for centering correctly in IE11 */
}
/* Vertical centering fix for IE11 */
@media screen and (-ms-high-contrast: none), (-ms-high-contrast: active) {
.sb-show-main.sb-main-centered:after {
content: '';
min-height: inherit;
font-size: 0;
}
}
.sb-show-main.sb-main-fullscreen {
margin: 0;
padding: 0;
display: block;
}
.sb-show-main.sb-main-padded {
margin: 0;
padding: 1rem;
display: block;
box-sizing: border-box;
}
.sb-wrapper {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
box-sizing: border-box;
padding: 40px;
font-family:
'Nunito Sans',
-apple-system,
'.SFNSText-Regular',
'San Francisco',
BlinkMacSystemFont,
'Segoe UI',
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
-webkit-font-smoothing: antialiased;
overflow: auto;
}
@media (max-width: 700px) {
.sb-wrapper {
padding: 20px;
}
}
@media (max-width: 500px) {
.sb-wrapper {
padding: 10px;
}
}
.sb-heading {
font-size: 14px;
font-weight: 600;
letter-spacing: 0.2px;
margin: 10px 0;
padding-right: 25px;
}
.sb-nopreview {
display: flex;
align-content: center;
justify-content: center;
box-sizing: border-box;
}
.sb-nopreview_main {
margin: auto;
padding: 30px;
border-radius: 10px;
background: rgba(0, 0, 0, 0.03);
}
.sb-nopreview_heading {
text-align: center;
}
.sb-errordisplay {
background: #f6f9fc;
color: black;
z-index: 999999;
width: 100vw;
min-height: 100vh;
box-sizing: border-box;
& ol {
padding-left: 18px;
margin: 0;
}
& h1 {
font-family: Nunito Sans;
font-size: 22px;
font-weight: 400;
line-height: 30px;
font-weight: normal;
margin: 0;
&::before {
content: '';
display: inline-block;
width: 12px;
height: 12px;
background: #ff4400;
border-radius: 50%;
margin-right: 8px;
}
}
& p,
& ol {
font-family: Nunito Sans;
font-size: 14px;
font-weight: 400;
line-height: 19px;
margin: 0;
}
& li + li {
margin: 0;
padding: 0;
padding-top: 12px;
}
& a {
color: currentColor;
}
}
.sb-errordisplay_main {
margin: auto;
padding: 24px;
display: flex;
box-sizing: border-box;
flex-direction: column;
min-height: 100%;
width: 100%;
border-radius: 6px;
background: white;
border: 1px solid #ff0000;
box-shadow: 0 0 64px rgba(0, 0, 0, 0.1);
gap: 24px;
}
.sb-errordisplay_code {
padding: 10px;
flex: 1;
background: #242424;
color: #c6c6c6;
box-sizing: border-box;
font-size: 14px;
font-weight: 400;
line-height: 19px;
border-radius: 4px;
font-family: 'Operator Mono', 'Fira Code Retina', 'Fira Code', 'FiraCode-Retina', 'Andale Mono',
'Lucida Console', Consolas, Monaco, monospace;
margin: 0;
overflow: auto;
}
.sb-errordisplay pre {
white-space: pre-wrap;
white-space: revert;
}
@-webkit-keyframes sb-rotate360 {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes sb-rotate360 {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@-webkit-keyframes sb-glow {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.4;
}
}
@keyframes sb-glow {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.4;
}
}
/* We display the preparing loaders *over* the rendering story */
.sb-preparing-story,
.sb-preparing-docs {
background-color: white;
/* Maximum possible z-index. It would be better to use stacking contexts to ensure it's always
on top, but this isn't possible as it would require making CSS changes that could affect user code */
z-index: 2147483647;
}
.sb-loader {
-webkit-animation: sb-rotate360 0.7s linear infinite;
animation: sb-rotate360 0.7s linear infinite;
border-color: rgba(97, 97, 97, 0.29);
border-radius: 50%;
border-style: solid;
border-top-color: #646464;
border-width: 2px;
display: inline-block;
height: 32px;
left: 50%;
margin-left: -16px;
margin-top: -16px;
mix-blend-mode: difference;
overflow: hidden;
position: absolute;
top: 50%;
transition: all 200ms ease-out;
vertical-align: top;
width: 32px;
z-index: 4;
}
.sb-previewBlock {
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 4px;
box-shadow: rgba(0, 0, 0, 0.1) 0 1px 3px 0;
margin: 25px auto 40px;
max-width: 600px;
}
.sb-previewBlock_header {
align-items: center;
box-shadow: rgba(0, 0, 0, 0.1) 0 -1px 0 0 inset;
display: flex;
gap: 14px;
height: 40px;
padding: 0 12px;
}
.sb-previewBlock_icon {
-webkit-animation: sb-glow 1.5s ease-in-out infinite;
animation: sb-glow 1.5s ease-in-out infinite;
background: #e6e6e6;
height: 14px;
width: 14px;
}
.sb-previewBlock_icon:last-child {
margin-left: auto;
}
.sb-previewBlock_body {
-webkit-animation: sb-glow 1.5s ease-in-out infinite;
animation: sb-glow 1.5s ease-in-out infinite;
height: 182px;
position: relative;
}
.sb-argstableBlock {
border-collapse: collapse;
border-spacing: 0;
font-size: 13px;
line-height: 20px;
margin: 25px auto 40px;
max-width: 600px;
text-align: left;
width: 100%;
}
.sb-argstableBlock th:first-of-type,
.sb-argstableBlock td:first-of-type {
padding-left: 20px;
}
.sb-argstableBlock th:nth-of-type(2),
.sb-argstableBlock td:nth-of-type(2) {
width: 35%;
}
.sb-argstableBlock th:nth-of-type(3),
.sb-argstableBlock td:nth-of-type(3) {
width: 15%;
}
.sb-argstableBlock th:last-of-type,
.sb-argstableBlock td:last-of-type {
width: 25%;
padding-right: 20px;
}
.sb-argstableBlock th span,
.sb-argstableBlock td span {
-webkit-animation: sb-glow 1.5s ease-in-out infinite;
animation: sb-glow 1.5s ease-in-out infinite;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 0;
box-shadow: none;
color: transparent;
}
.sb-argstableBlock th {
padding: 10px 15px;
}
.sb-argstableBlock-body {
border-radius: 4px;
box-shadow:
rgba(0, 0, 0, 0.1) 0 1px 3px 1px,
rgba(0, 0, 0, 0.065) 0 0 0 1px;
}
.sb-argstableBlock-body tr {
background: transparent;
overflow: hidden;
}
.sb-argstableBlock-body tr:not(:first-child) {
border-top: 1px solid #e6e6e6;
}
.sb-argstableBlock-body tr:first-child td:first-child {
border-top-left-radius: 4px;
}
.sb-argstableBlock-body tr:first-child td:last-child {
border-top-right-radius: 4px;
}
.sb-argstableBlock-body tr:last-child td:first-child {
border-bottom-left-radius: 4px;
}
.sb-argstableBlock-body tr:last-child td:last-child {
border-bottom-right-radius: 4px;
}
.sb-argstableBlock-body td {
background: #fff;
padding-bottom: 10px;
padding-top: 10px;
vertical-align: top;
}
.sb-argstableBlock-body td:not(:first-of-type) {
padding-left: 15px;
padding-right: 15px;
}
.sb-argstableBlock-body button {
-webkit-animation: sb-glow 1.5s ease-in-out infinite;
animation: sb-glow 1.5s ease-in-out infinite;
background-color: rgba(0, 0, 0, 0.1);
border: 0;
border-radius: 0;
box-shadow: none;
color: transparent;
display: inline;
font-size: 12px;
line-height: 1;
padding: 10px 16px;
}
.sb-argstableBlock-summary {
margin-top: 4px;
}
.sb-argstableBlock-code {
margin-right: 4px;
margin-bottom: 4px;
padding: 2px 5px;
}
</style>
<script>
/* globals window */
/* eslint-disable no-underscore-dangle */
try {
if (window.top !== window) {
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.top.__REACT_DEVTOOLS_GLOBAL_HOOK__;
window.__VUE_DEVTOOLS_GLOBAL_HOOK__ = window.top.__VUE_DEVTOOLS_GLOBAL_HOOK__;
window.top.__VUE_DEVTOOLS_CONTEXT__ = window.document;
}
} catch (e) {
// eslint-disable-next-line no-console
console.warn('unable to connect to top frame for connecting dev tools');
}
</script>
<script type="module" crossorigin src="./assets/iframe-DUcCSOHa.js"></script>
</head>
<body>
<div id="portal-root"></div>
<div class="sb-preparing-story sb-wrapper">
<div class="sb-loader"></div>
</div>
<div class="sb-preparing-docs sb-wrapper">
<div class="sb-previewBlock">
<div class="sb-previewBlock_header">
<div class="sb-previewBlock_icon"></div>
<div class="sb-previewBlock_icon"></div>
<div class="sb-previewBlock_icon"></div>
<div class="sb-previewBlock_icon"></div>
</div>
<div class="sb-previewBlock_body">
<div class="sb-loader"></div>
</div>
</div>
<table aria-hidden="true" class="sb-argstableBlock">
<thead class="sb-argstableBlock-head">
<tr>
<th><span>Name</span></th>
<th><span>Description</span></th>
<th><span>Default</span></th>
<th><span>Control </span></th>
</tr>
</thead>
<tbody class="sb-argstableBlock-body">
<tr>
<td><span>propertyName</span><span title="Required">*</span></td>
<td>
<div><span>This is a short description</span></div>
<div class="sb-argstableBlock-summary">
<div><span class="sb-argstableBlock-code">summary</span></div>
</div>
</td>
<td>
<div><span class="sb-argstableBlock-code">defaultValue</span></div>
</td>
<td><button>Set string</button></td>
</tr>
<tr>
<td><span>propertyName</span><span>*</span></td>
<td>
<div><span>This is a short description</span></div>
<div class="sb-argstableBlock-summary">
<div><span class="sb-argstableBlock-code">summary</span></div>
</div>
</td>
<td>
<div><span class="sb-argstableBlock-code">defaultValue</span></div>
</td>
<td><button>Set string</button></td>
</tr>
<tr>
<td><span>propertyName</span><span>*</span></td>
<td>
<div><span>This is a short description</span></div>
<div class="sb-argstableBlock-summary">
<div><span class="sb-argstableBlock-code">summary</span></div>
</div>
</td>
<td>
<div><span class="sb-argstableBlock-code">defaultValue</span></div>
</td>
<td><button>Set string</button></td>
</tr>
</tbody>
</table>
</div>
<div class="sb-nopreview sb-wrapper">
<div class="sb-nopreview_main">
<h1 class="sb-nopreview_heading sb-heading">No Preview</h1>
<p>Sorry, but you either have no stories or none are selected somehow.</p>
<ul>
<li>Please check the Storybook config.</li>
<li>Try reloading the page.</li>
</ul>
<p>
If the problem persists, check the browser console, or the terminal you've run Storybook from.
</p>
</div>
</div>
<div class="sb-errordisplay sb-wrapper">
<div class="sb-errordisplay_main">
<h1 id="error-message"></h1>
<p>
The component failed to render properly, likely due to a configuration issue in Storybook.
Here are some common causes and how you can address them:
</p>
<ol>
<li>
<strong>Missing Context/Providers</strong>: You can use decorators to supply specific
contexts or providers, which are sometimes necessary for components to render correctly. For
detailed instructions on using decorators, please visit the
<a href="https://storybook.js.org/docs/writing-stories/decorators"
>Decorators documentation</a
>.
</li>
<li>
<strong>Misconfigured Webpack or Vite</strong>: Verify that Storybook picks up all necessary
settings for loaders, plugins, and other relevant parameters. You can find step-by-step
guides for configuring
<a href="https://storybook.js.org/docs/builders/webpack">Webpack</a> or
<a href="https://storybook.js.org/docs/builders/vite">Vite</a>
with Storybook.
</li>
<li>
<strong>Missing Environment Variables</strong>: Your Storybook may require specific
environment variables to function as intended. You can set up custom environment variables
as outlined in the
<a href="https://storybook.js.org/docs/configure/environment-variables"
>Environment Variables documentation</a
>.
</li>
</ol>
<pre class="sb-errordisplay_code"><code id="error-stack"></code></pre>
</div>
</div>
<div id="storybook-root"></div>
<div id="storybook-docs"></div>
</body>
</html>
+181
View File
@@ -0,0 +1,181 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>@storybook/core - Storybook</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<link rel="icon" type="image/svg+xml" href="./favicon.svg" />
<style>
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-regular.woff2') format('woff2');
}
@font-face {
font-family: 'Nunito Sans';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-italic.woff2') format('woff2');
}
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-bold.woff2') format('woff2');
}
@font-face {
font-family: 'Nunito Sans';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-bold-italic.woff2') format('woff2');
}
</style>
<link href="./sb-manager/runtime.js" rel="modulepreload" />
<link href="./sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/onboarding-1/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-controls-2/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-actions-3/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-backgrounds-4/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-viewport-5/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-toolbars-6/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-measure-7/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-outline-8/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/chromatic-com-storybook-9/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/interactions-10/manager-bundle.js" rel="modulepreload" />
<style>
#storybook-root[hidden] {
display: none !important;
}
</style>
</head>
<body>
<div id="root"></div>
<script>
window['FEATURES'] = {
"argTypeTargetsV7": true,
"legacyDecoratorFileOrder": false,
"disallowImplicitActionsInRenderV8": true
};
window['REFS'] = {};
window['LOGLEVEL'] = "info";
window['DOCS_OPTIONS'] = {
"defaultName": "Docs",
"autodocs": "tag"
};
window['CONFIG_TYPE'] = "PRODUCTION";
window['TAGS_OPTIONS'] = {
"dev-only": {
"excludeFromDocsStories": true
},
"docs-only": {
"excludeFromSidebar": true
},
"test-only": {
"excludeFromSidebar": true,
"excludeFromDocsStories": true
}
};
window['STORYBOOK_RENDERER'] = "react";
window['STORYBOOK_BUILDER'] = "@storybook/builder-vite";
window['STORYBOOK_FRAMEWORK'] = "/Users/satish/work/plane-ce/node_modules/@storybook/react-vite";
</script>
<script type="module">
import './sb-manager/globals-runtime.js';
import './sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js';
import './sb-addons/onboarding-1/manager-bundle.js';
import './sb-addons/essentials-controls-2/manager-bundle.js';
import './sb-addons/essentials-actions-3/manager-bundle.js';
import './sb-addons/essentials-backgrounds-4/manager-bundle.js';
import './sb-addons/essentials-viewport-5/manager-bundle.js';
import './sb-addons/essentials-toolbars-6/manager-bundle.js';
import './sb-addons/essentials-measure-7/manager-bundle.js';
import './sb-addons/essentials-outline-8/manager-bundle.js';
import './sb-addons/chromatic-com-storybook-9/manager-bundle.js';
import './sb-addons/interactions-10/manager-bundle.js';
import './sb-manager/runtime.js';
</script>
<link href="./sb-preview/runtime.js" rel="prefetch" as="script" />
</body>
</html>
@@ -0,0 +1 @@
{"v":5,"entries":{"example-dropdownmenu--docs":{"id":"example-dropdownmenu--docs","title":"Example/DropdownMenu","name":"Docs","importPath":"./src/components/DropdownMenu/DropdownMenu.stories.tsx","type":"docs","tags":["dev","test","autodocs"],"storiesImports":[]},"example-dropdownmenu--default-dropdown":{"type":"story","id":"example-dropdownmenu--default-dropdown","name":"Default Dropdown","title":"Example/DropdownMenu","importPath":"./src/components/DropdownMenu/DropdownMenu.stories.tsx","componentPath":"./src/components/DropdownMenu/DropdownMenu.tsx","tags":["dev","test","autodocs"]},"example-dropdownmenu--multi-select":{"type":"story","id":"example-dropdownmenu--multi-select","name":"Multi Select","title":"Example/DropdownMenu","importPath":"./src/components/DropdownMenu/DropdownMenu.stories.tsx","componentPath":"./src/components/DropdownMenu/DropdownMenu.tsx","tags":["dev","test","autodocs"]},"example-dropdownmenu--nested-dropdown":{"type":"story","id":"example-dropdownmenu--nested-dropdown","name":"Nested Dropdown","title":"Example/DropdownMenu","importPath":"./src/components/DropdownMenu/DropdownMenu.stories.tsx","componentPath":"./src/components/DropdownMenu/DropdownMenu.tsx","tags":["dev","test","autodocs"]},"example-selectmenu--docs":{"id":"example-selectmenu--docs","title":"Example/SelectMenu","name":"Docs","importPath":"./src/components/Select/Select.stories.tsx","type":"docs","tags":["dev","test","autodocs"],"storiesImports":[]},"example-selectmenu--single-select":{"type":"story","id":"example-selectmenu--single-select","name":"Single Select","title":"Example/SelectMenu","importPath":"./src/components/Select/Select.stories.tsx","componentPath":"./src/components/Select/Select.tsx","tags":["dev","test","autodocs"]}}}
@@ -0,0 +1 @@
{"generatedAt":1735287313274,"hasCustomBabel":false,"hasCustomWebpack":false,"hasStaticDirs":false,"hasStorybookEslint":false,"refCount":0,"testPackages":{"@testing-library/jest-dom":"6.6.3","@testing-library/react":"16.1.0","@testing-library/user-event":null,"@types/jest":"29.5.14","@vitest/ui":"2.1.8","jest":"29.7.0","jest-environment-jsdom":"29.7.0","vitest":"2.1.8"},"monorepo":"Turborepo","packageManager":{"type":"yarn","version":"1.22.22"},"preview":{"usesGlobals":false},"framework":{"name":"@storybook/react-vite","options":{}},"builder":"@storybook/builder-vite","renderer":"@storybook/react","portableStoriesFileCount":0,"storybookVersion":"8.4.7","storybookVersionSpecifier":"^8.4.5","language":"typescript","storybookPackages":{"@chromatic-com/storybook":{"version":"3.2.2"},"@storybook/addon-essentials":{"version":"8.4.7"},"@storybook/addon-interactions":{"version":"8.4.7"},"@storybook/addon-onboarding":{"version":"8.4.7"},"@storybook/blocks":{"version":"8.4.7"},"@storybook/react":{"version":"8.4.7"},"@storybook/react-vite":{"version":"8.4.7"},"@storybook/test":{"version":"8.4.7"},"storybook":{"version":"8.4.7"}},"addons":{"$SNIP/node_modules/@storybook/addon-onboarding":{"version":null},"$SNIP/node_modules/@storybook/addon-essentials":{"version":null},"$SNIP/node_modules/@chromatic-com/storybook":{"version":null},"$SNIP/node_modules/@storybook/addon-interactions":{"version":null}}}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,40 @@
Bundled license information:
filesize/dist/filesize.esm.js:
/**
* filesize
*
* @copyright 2024 Jason Mulligan <jason.mulligan@avoidwork.com>
* @license BSD-3-Clause
* @version 10.1.6
*/
@chromatic-com/storybook/dist/manager.mjs:
/*! Bundled license information:
popper.js/dist/esm/popper.js:
(**!
* @fileOverview Kickass library to create and place poppers near their reference elements.
* @version 1.16.1
* @license
* Copyright (c) 2016 Federico Zivolo and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*)
*/
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
try{
(()=>{var T=__STORYBOOK_API__,{ActiveTabs:_,Consumer:O,ManagerContext:f,Provider:A,RequestResponseError:v,addons:n,combineParameters:P,controlOrMetaKey:k,controlOrMetaSymbol:x,eventMatchesShortcut:M,eventToShortcut:R,experimental_requestResponse:w,isMacLike:C,isShortcutTaken:G,keyToSymbol:I,merge:K,mockChannel:q,optionOrAltSymbol:B,shortcutMatchesShortcut:F,shortcutToHumanString:Y,types:j,useAddonState:E,useArgTypes:H,useArgs:L,useChannel:N,useGlobalTypes:z,useGlobals:D,useParameter:J,useSharedState:Q,useStoryPrepared:U,useStorybookApi:V,useStorybookState:W}=__STORYBOOK_API__;var c=(()=>{let e;return typeof window<"u"?e=window:typeof globalThis<"u"?e=globalThis:typeof window<"u"?e=window:typeof self<"u"?e=self:e={},e})(),S="tag-filters",d="static-filter";n.register(S,e=>{let u=Object.entries(c.TAGS_OPTIONS??{}).reduce((t,r)=>{let[o,i]=r;return i.excludeFromSidebar&&(t[o]=!0),t},{});e.experimental_setFilter(d,t=>{let r=t.tags??[];return(r.includes("dev")||t.type==="docs")&&r.filter(o=>u[o]).length===0})});})();
}catch(e){ console.error("[Storybook] One of your manager-entries failed: " + import.meta.url, e); }
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svgjs="http://svgjs.com/svgjs" xmlns:xlink="http://www.w3.org/1999/xlink" width="164" height="164" version="1.1"><svg xmlns="http://www.w3.org/2000/svg" width="164" height="164" fill="none" viewBox="0 0 164 164"><path fill="#FF4785" d="M22.467 147.762 17.5 15.402a8.062 8.062 0 0 1 7.553-8.35L137.637.016a8.061 8.061 0 0 1 8.565 8.047v144.23a8.063 8.063 0 0 1-8.424 8.054l-107.615-4.833a8.062 8.062 0 0 1-7.695-7.752Z"/><path fill="#fff" fill-rule="evenodd" d="m128.785.57-15.495.968-.755 18.172a1.203 1.203 0 0 0 1.928 1.008l7.06-5.354 5.962 4.697a1.202 1.202 0 0 0 1.946-.987L128.785.569Zm-12.059 60.856c-2.836 2.203-23.965 3.707-23.965.57.447-11.969-4.912-12.494-7.889-12.494-2.828 0-7.59.855-7.59 7.267 0 6.534 6.96 10.223 15.13 14.553 11.607 6.15 25.654 13.594 25.654 32.326 0 17.953-14.588 27.871-33.194 27.871-19.201 0-35.981-7.769-34.086-34.702.744-3.163 25.156-2.411 25.156 0-.298 11.114 2.232 14.383 8.633 14.383 4.912 0 7.144-2.708 7.144-7.267 0-6.9-7.252-10.973-15.595-15.657C64.827 81.933 51.53 74.468 51.53 57.34c0-17.098 11.76-28.497 32.747-28.497 20.988 0 32.449 11.224 32.449 32.584Z" clip-rule="evenodd"/></svg><style>@media (prefers-color-scheme:light){:root{filter:none}}</style></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,48 @@
import ESM_COMPAT_Module from "node:module";
import { fileURLToPath as ESM_COMPAT_fileURLToPath } from 'node:url';
import { dirname as ESM_COMPAT_dirname } from 'node:path';
const __filename = ESM_COMPAT_fileURLToPath(import.meta.url);
const __dirname = ESM_COMPAT_dirname(__filename);
const require = ESM_COMPAT_Module.createRequire(import.meta.url);
// src/manager/globals/globals.ts
var _ = {
react: "__REACT__",
"react-dom": "__REACT_DOM__",
"react-dom/client": "__REACT_DOM_CLIENT__",
"@storybook/icons": "__STORYBOOK_ICONS__",
"storybook/internal/manager-api": "__STORYBOOK_API__",
"@storybook/manager-api": "__STORYBOOK_API__",
"@storybook/core/manager-api": "__STORYBOOK_API__",
"storybook/internal/components": "__STORYBOOK_COMPONENTS__",
"@storybook/components": "__STORYBOOK_COMPONENTS__",
"@storybook/core/components": "__STORYBOOK_COMPONENTS__",
"storybook/internal/channels": "__STORYBOOK_CHANNELS__",
"@storybook/channels": "__STORYBOOK_CHANNELS__",
"@storybook/core/channels": "__STORYBOOK_CHANNELS__",
"storybook/internal/core-errors": "__STORYBOOK_CORE_EVENTS__",
"@storybook/core-events": "__STORYBOOK_CORE_EVENTS__",
"@storybook/core/core-events": "__STORYBOOK_CORE_EVENTS__",
"storybook/internal/manager-errors": "__STORYBOOK_CORE_EVENTS_MANAGER_ERRORS__",
"@storybook/core-events/manager-errors": "__STORYBOOK_CORE_EVENTS_MANAGER_ERRORS__",
"@storybook/core/manager-errors": "__STORYBOOK_CORE_EVENTS_MANAGER_ERRORS__",
"storybook/internal/router": "__STORYBOOK_ROUTER__",
"@storybook/router": "__STORYBOOK_ROUTER__",
"@storybook/core/router": "__STORYBOOK_ROUTER__",
"storybook/internal/theming": "__STORYBOOK_THEMING__",
"@storybook/theming": "__STORYBOOK_THEMING__",
"@storybook/core/theming": "__STORYBOOK_THEMING__",
"storybook/internal/theming/create": "__STORYBOOK_THEMING_CREATE__",
"@storybook/theming/create": "__STORYBOOK_THEMING_CREATE__",
"@storybook/core/theming/create": "__STORYBOOK_THEMING_CREATE__",
"storybook/internal/client-logger": "__STORYBOOK_CLIENT_LOGGER__",
"@storybook/client-logger": "__STORYBOOK_CLIENT_LOGGER__",
"@storybook/core/client-logger": "__STORYBOOK_CLIENT_LOGGER__",
"storybook/internal/types": "__STORYBOOK_TYPES__",
"@storybook/types": "__STORYBOOK_TYPES__",
"@storybook/core/types": "__STORYBOOK_TYPES__"
}, o = Object.keys(_);
export {
o as globalPackages,
_ as globalsNameReferenceMap
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,33 @@
import ESM_COMPAT_Module from "node:module";
import { fileURLToPath as ESM_COMPAT_fileURLToPath } from 'node:url';
import { dirname as ESM_COMPAT_dirname } from 'node:path';
const __filename = ESM_COMPAT_fileURLToPath(import.meta.url);
const __dirname = ESM_COMPAT_dirname(__filename);
const require = ESM_COMPAT_Module.createRequire(import.meta.url);
// src/preview/globals/globals.ts
var _ = {
"@storybook/global": "__STORYBOOK_MODULE_GLOBAL__",
"storybook/internal/channels": "__STORYBOOK_MODULE_CHANNELS__",
"@storybook/channels": "__STORYBOOK_MODULE_CHANNELS__",
"@storybook/core/channels": "__STORYBOOK_MODULE_CHANNELS__",
"storybook/internal/client-logger": "__STORYBOOK_MODULE_CLIENT_LOGGER__",
"@storybook/client-logger": "__STORYBOOK_MODULE_CLIENT_LOGGER__",
"@storybook/core/client-logger": "__STORYBOOK_MODULE_CLIENT_LOGGER__",
"storybook/internal/core-events": "__STORYBOOK_MODULE_CORE_EVENTS__",
"@storybook/core-events": "__STORYBOOK_MODULE_CORE_EVENTS__",
"@storybook/core/core-events": "__STORYBOOK_MODULE_CORE_EVENTS__",
"storybook/internal/preview-errors": "__STORYBOOK_MODULE_CORE_EVENTS_PREVIEW_ERRORS__",
"@storybook/core-events/preview-errors": "__STORYBOOK_MODULE_CORE_EVENTS_PREVIEW_ERRORS__",
"@storybook/core/preview-errors": "__STORYBOOK_MODULE_CORE_EVENTS_PREVIEW_ERRORS__",
"storybook/internal/preview-api": "__STORYBOOK_MODULE_PREVIEW_API__",
"@storybook/preview-api": "__STORYBOOK_MODULE_PREVIEW_API__",
"@storybook/core/preview-api": "__STORYBOOK_MODULE_PREVIEW_API__",
"storybook/internal/types": "__STORYBOOK_MODULE_TYPES__",
"@storybook/types": "__STORYBOOK_MODULE_TYPES__",
"@storybook/core/types": "__STORYBOOK_MODULE_TYPES__"
}, O = Object.keys(_);
export {
O as globalPackages,
_ as globalsNameReferenceMap
};
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
/* src/global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--white: hsl(0, 0%, 100%);
--grey-50: hsl(222, 20%, 96%);
--grey-100: hsl(222, 20%, 94%);
--grey-200: hsl(222, 20%, 86%);
--grey-300: hsl(222, 20%, 80%);
--grey-400: hsl(222, 20%, 60%);
--grey-500: hsl(222, 20%, 50%);
--grey-600: hsl(222, 20%, 40%);
--grey-700: hsl(222, 20%, 34%);
--grey-800: hsl(222, 20%, 20%);
--grey-900: hsl(222, 20%, 10%);
--grey-950: hsl(222, 20%, 8%);
--black: hsl(222, 20%, 6%);
}
+46
View File
@@ -0,0 +1,46 @@
/** @type {import('tailwindcss').Config} */
/*
@todo @aaryan
Do not extend the colors
Explicitly add all the colors we need
*/
module.exports = {
content: ["./src/**/*.tsx"],
theme: {
extend: {
colors: {
white: "var(--white)",
grey: {
50: "var(--grey-50)",
100: "var(--grey-100)",
200: "var(--grey-200)",
300: "var(--grey-300)",
400: "var(--grey-400)",
500: "var(--grey-500)",
600: "var(--grey-600)",
700: "var(--grey-700)",
800: "var(--grey-800)",
900: "var(--grey-900)",
950: "var(--grey-950)",
},
black: "var(--black)",
},
borderColor: {
neutral: {
subtle: "var(--grey-100)",
DEFAULT: "var(--grey-200)",
emphasis: "var(--grey-300)",
},
},
backgroundColor: {
neutral: {
subtle: "var(--grey-100)",
DEFAULT: "var(--grey-200)",
emphasis: "var(--grey-300)",
},
},
},
},
plugins: [],
};
+1
View File
@@ -0,0 +1 @@
import "@testing-library/jest-dom/vitest";
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "@plane/typescript-config/react-library.json",
"compilerOptions": {
"jsx": "react",
"lib": ["esnext", "dom"],
"types": ["vitest/globals"]
},
"include": ["."],
"exclude": ["dist", "build", "node_modules"]
}
+13
View File
@@ -0,0 +1,13 @@
import { defineConfig, Options } from "tsup";
export default defineConfig((options: Options) => ({
entry: ["src/index.ts"],
format: ["esm"],
dts: true,
clean: false,
external: ["react"],
injectStyle: true,
treeshake: true,
...options,
}));
+9
View File
@@ -0,0 +1,9 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true,
environment: "jsdom",
setupFiles: ["./test-setup.ts"],
},
});
+2473 -474
View File
File diff suppressed because it is too large Load Diff