pentatrion-design 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/main.ts +33 -0
- package/.storybook/manager.ts +8 -0
- package/.storybook/preview-head.html +2 -0
- package/.storybook/preview.ts +26 -0
- package/.storybook/public/bg-map.jpg +0 -0
- package/.storybook/public/favicon-32x32.png +0 -0
- package/.storybook/public/favicon.svg +28 -0
- package/.storybook/public/movies.json +2153 -0
- package/.storybook/public/population.json +1178 -0
- package/.storybook/public/town-74.geojson +8995 -0
- package/.storybook/public/town-74.json +4062 -0
- package/.storybook/theme.ts +14 -0
- package/Makefile +14 -0
- package/README.md +40 -0
- package/TODO.md +5 -0
- package/dist/index.d.ts +1110 -0
- package/dist/index.js +3707 -0
- package/dist/redux/index.d.ts +43 -0
- package/dist/redux/index.js +583 -0
- package/dist/types.d-DlHa_IaW.d.ts +14 -0
- package/images/logo-shadow.svg +173 -0
- package/images/logo.svg +76 -0
- package/package.json +85 -0
- package/postcss.config.js +7 -0
- package/src/components/autocomplete/Autocomplete.stories.tsx +89 -0
- package/src/components/autocomplete/Autocomplete.tsx +316 -0
- package/src/components/autocomplete/AutocompleteOption.tsx +35 -0
- package/src/components/autocomplete/LazyAutocomplete.tsx +130 -0
- package/src/components/autocomplete/SimpleAutocomplete.tsx +74 -0
- package/src/components/autocomplete/index.ts +6 -0
- package/src/components/autocomplete/useAutocompleteContext.ts +20 -0
- package/src/components/autocomplete/util.ts +19 -0
- package/src/components/badge/Badge.stories.tsx +72 -0
- package/src/components/badge/Badge.tsx +70 -0
- package/src/components/button/Button.stories.tsx +189 -0
- package/src/components/button/Button.test.tsx +20 -0
- package/src/components/button/Button.tsx +200 -0
- package/src/components/button/ButtonGroup.stories.tsx +46 -0
- package/src/components/button/ButtonGroup.tsx +29 -0
- package/src/components/button/index.ts +2 -0
- package/src/components/card/Card.stories.tsx +21 -0
- package/src/components/card/config.ts +4 -0
- package/src/components/card/index.ts +1 -0
- package/src/components/code/Code.tsx +15 -0
- package/src/components/context-menu/ContextMenu.stories.tsx +22 -0
- package/src/components/context-menu/ContextMenu.tsx +175 -0
- package/src/components/context-menu/ContextMenuItem.tsx +34 -0
- package/src/components/context-menu/index.ts +2 -0
- package/src/components/dialog/Dialog.stories.tsx +270 -0
- package/src/components/dialog/Dialog.tsx +46 -0
- package/src/components/dialog/index.ts +1 -0
- package/src/components/dialog/util.ts +29 -0
- package/src/components/dropdown-menu/DropdownMenu.stories.tsx +19 -0
- package/src/components/dropdown-menu/DropdownMenu.tsx +12 -0
- package/src/components/dropdown-menu/DropdownMenuContent.tsx +46 -0
- package/src/components/dropdown-menu/DropdownMenuItem.tsx +33 -0
- package/src/components/dropdown-menu/DropdownMenuTrigger.tsx +42 -0
- package/src/components/dropdown-menu/index.ts +7 -0
- package/src/components/dropdown-menu/interface.d.ts +13 -0
- package/src/components/dropdown-menu/useDropdownMenu.tsx +115 -0
- package/src/components/dropdown-menu/useDropdownMenuContext.ts +16 -0
- package/src/components/dropdown-menu-nested/DropdownMenuNested.stories.tsx +33 -0
- package/src/components/dropdown-menu-nested/DropdownMenuNested.tsx +19 -0
- package/src/components/dropdown-menu-nested/MenuContext.ts +15 -0
- package/src/components/dropdown-menu-nested/MenuItem.tsx +43 -0
- package/src/components/dropdown-menu-nested/MenuItemWithChildren.tsx +204 -0
- package/src/components/dropdown-menu-nested/index.ts +3 -0
- package/src/components/flash/Flash.stories.tsx +34 -0
- package/src/components/flash/Flash.tsx +24 -0
- package/src/components/highlight/Highlight.stories.tsx +128 -0
- package/src/components/highlight/Highlight.tsx +29 -0
- package/src/components/href/Href.stories.tsx +55 -0
- package/src/components/href/Href.tsx +18 -0
- package/src/components/input/Checkbox.stories.tsx +52 -0
- package/src/components/input/Checkbox.tsx +41 -0
- package/src/components/input/Input.stories.tsx +103 -0
- package/src/components/input/Input.test.tsx +10 -0
- package/src/components/input/Input.tsx +60 -0
- package/src/components/input/RadioGroup.stories.tsx +76 -0
- package/src/components/input/RadioGroup.tsx +84 -0
- package/src/components/input/Toggle.stories.tsx +29 -0
- package/src/components/input/Toggle.tsx +35 -0
- package/src/components/input/index.ts +4 -0
- package/src/components/input-field/InputField.stories.tsx +227 -0
- package/src/components/input-field/InputField.tsx +62 -0
- package/src/components/loader/Loader.stories.tsx +37 -0
- package/src/components/loader/Loader.tsx +54 -0
- package/src/components/modal/Components.tsx +58 -0
- package/src/components/modal/Modal.stories.tsx +113 -0
- package/src/components/modal/Modal.tsx +13 -0
- package/src/components/modal/ModalContent.tsx +46 -0
- package/src/components/modal/ModalTrigger.tsx +41 -0
- package/src/components/modal/index.ts +7 -0
- package/src/components/modal/interface.d.ts +10 -0
- package/src/components/modal/useModal.ts +48 -0
- package/src/components/modal/useModalContext.ts +16 -0
- package/src/components/notification/Notification.stories.tsx +51 -0
- package/src/components/notification/NotificationsContext.ts +79 -0
- package/src/components/notification/NotificationsProvider.tsx +58 -0
- package/src/components/notification/index.ts +2 -0
- package/src/components/popover/Components.tsx +45 -0
- package/src/components/popover/Popover.stories.tsx +46 -0
- package/src/components/popover/Popover.test.tsx +21 -0
- package/src/components/popover/Popover.tsx +12 -0
- package/src/components/popover/PopoverContent.tsx +46 -0
- package/src/components/popover/PopoverTrigger.tsx +42 -0
- package/src/components/popover/index.ts +7 -0
- package/src/components/popover/interface.d.ts +13 -0
- package/src/components/popover/usePopover.tsx +80 -0
- package/src/components/popover/usePopoverContext.ts +16 -0
- package/src/components/portal/Portal.tsx +12 -0
- package/src/components/quick-settings/QuickSettings.stories.tsx +182 -0
- package/src/components/resize-area/ResizeArea.stories.css +40 -0
- package/src/components/resize-area/ResizeArea.stories.tsx +30 -0
- package/src/components/resize-area/ResizeArea.tsx +79 -0
- package/src/components/scroll/Scroll.stories.tsx +81 -0
- package/src/components/scroll/Scroll.tsx +111 -0
- package/src/components/select/Select.stories.tsx +248 -0
- package/src/components/select/Select.tsx +362 -0
- package/src/components/select/SelectOption.tsx +29 -0
- package/src/components/select/SelectSelection.tsx +13 -0
- package/src/components/select/index.ts +5 -0
- package/src/components/select/interface.d.ts +36 -0
- package/src/components/select/useSelectContext.ts +19 -0
- package/src/components/select/util.ts +12 -0
- package/src/components/snack/Snack.stories.tsx +33 -0
- package/src/components/snack/Snack.tsx +47 -0
- package/src/components/sortable/Sortable.stories.tsx +98 -0
- package/src/components/sortable/Sortable.tsx +37 -0
- package/src/components/sortable/index.ts +2 -0
- package/src/components/sortable/types.d.ts +12 -0
- package/src/components/steps/Step.tsx +41 -0
- package/src/components/steps/Steps.stories.tsx +141 -0
- package/src/components/steps/Steps.tsx +49 -0
- package/src/components/steps/index.ts +3 -0
- package/src/components/steps/util.ts +3 -0
- package/src/components/table/Table.stories.tsx +36 -0
- package/src/components/table/Table.tsx +13 -0
- package/src/components/table/TableBody.tsx +9 -0
- package/src/components/table/TableCell.tsx +16 -0
- package/src/components/table/TableFooter.tsx +9 -0
- package/src/components/table/TableHeader.tsx +14 -0
- package/src/components/table/TableHeaderCell.tsx +14 -0
- package/src/components/table/TableRow.tsx +14 -0
- package/src/components/table/index.ts +7 -0
- package/src/components/tabs/Tabs.stories.tsx +66 -0
- package/src/components/tabs/Tabs.tsx +80 -0
- package/src/components/tooltip/SimpleTooltip.tsx +17 -0
- package/src/components/tooltip/Tooltip.stories.tsx +129 -0
- package/src/components/tooltip/Tooltip.test.tsx +18 -0
- package/src/components/tooltip/Tooltip.tsx +13 -0
- package/src/components/tooltip/TooltipContent.tsx +41 -0
- package/src/components/tooltip/TooltipTrigger.tsx +36 -0
- package/src/components/tooltip/index.ts +6 -0
- package/src/components/tooltip/interface.d.ts +15 -0
- package/src/components/tooltip/useTooltip.ts +87 -0
- package/src/components/tooltip/useTooltipContext.ts +16 -0
- package/src/env.d.ts +27 -0
- package/src/hooks/index.ts +13 -0
- package/src/hooks/useCombinedRefs.test.tsx +42 -0
- package/src/hooks/useCombinedRefs.ts +21 -0
- package/src/hooks/useCopyToClipboard.ts +28 -0
- package/src/hooks/useDebounce.ts +59 -0
- package/src/hooks/useEventCallback.ts +13 -0
- package/src/hooks/useEventListener.ts +86 -0
- package/src/hooks/useFetch.tsx +21 -0
- package/src/hooks/useIsClosing.ts +25 -0
- package/src/hooks/useIsMounted.tsx +16 -0
- package/src/hooks/useIsomorphicLayoutEffect.ts +4 -0
- package/src/hooks/useNotifications.tsx +13 -0
- package/src/hooks/useOnClickOutside.ts +35 -0
- package/src/hooks/usePrevious.ts +9 -0
- package/src/hooks/useRipple.test.tsx +52 -0
- package/src/hooks/useRipple.tsx +79 -0
- package/src/index.css +14 -0
- package/src/index.ts +39 -0
- package/src/lib/arrUtil.ts +8 -0
- package/src/lib/error.ts +18 -0
- package/src/lib/fetch.test.ts +107 -0
- package/src/lib/fetch.ts +115 -0
- package/src/lib/index.ts +3 -0
- package/src/lib/tailwindVariants.ts +35 -0
- package/src/redux/index.ts +1 -0
- package/src/redux/notification/components/NotificationConsumer.tsx +52 -0
- package/src/redux/notification/errorCatcherMiddleware.ts +17 -0
- package/src/redux/notification/hooks/useNotification.ts +26 -0
- package/src/redux/notification/index.ts +5 -0
- package/src/redux/notification/notificationSlice.ts +68 -0
- package/src/styles/Animation.stories.tsx +43 -0
- package/src/styles/Shadow.stories.tsx +43 -0
- package/src/styles/Themes.stories.tsx +31 -0
- package/src/styles/Typography.stories.tsx +101 -0
- package/src/tailwind/base.css +188 -0
- package/src/tailwind/components-input-outline.css +62 -0
- package/src/tailwind/components-resize-area.css +112 -0
- package/src/tailwind/components-step.css +161 -0
- package/src/tailwind/components.css +51 -0
- package/src/tailwind/keyframes.ts +69 -0
- package/src/tailwind/pentatrionTw.ts +147 -0
- package/src/tailwind/utilities-dialog.css +103 -0
- package/src/tailwind/utilities.css +3 -0
- package/src/types.d.ts +12 -0
- package/tailwind.config.js +18 -0
- package/tests/README.md +32 -0
- package/tests/setup.ts +1 -0
- package/tsconfig.json +14 -0
- package/tsup.config.ts +23 -0
- package/vite.config.ts +24 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useInteractions } from "@floating-ui/react";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
|
|
4
|
+
interface SelectContext {
|
|
5
|
+
activeIndex: number | null;
|
|
6
|
+
selectedIndex: number | null;
|
|
7
|
+
getItemProps: ReturnType<typeof useInteractions>["getItemProps"];
|
|
8
|
+
handleSelect: (index: number | null) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const SelectContext = createContext<SelectContext | null>(null);
|
|
12
|
+
|
|
13
|
+
export default function useSelect() {
|
|
14
|
+
const context = useContext(SelectContext);
|
|
15
|
+
if (context === null) {
|
|
16
|
+
throw new Error("Select components must be wrapped in <Select>");
|
|
17
|
+
}
|
|
18
|
+
return context;
|
|
19
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function isValidMultiMode<V>(value: any, multiple: boolean): value is V & any[] {
|
|
2
|
+
if (!multiple) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
if (value !== undefined && !Array.isArray(value)) {
|
|
7
|
+
console.warn("[Select] Incorrect usage : if using multiple mode, value must be an array");
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Meta } from "@storybook/react";
|
|
2
|
+
import Snack from "./Snack";
|
|
3
|
+
const meta = {
|
|
4
|
+
title: "Components/Snack",
|
|
5
|
+
component: Snack,
|
|
6
|
+
} satisfies Meta<typeof Snack>;
|
|
7
|
+
export default meta;
|
|
8
|
+
|
|
9
|
+
export const Basic = () => {
|
|
10
|
+
return (
|
|
11
|
+
<div className="ll-snack-bar fixed bottom-0 left-0 right-0 z-notification">
|
|
12
|
+
<div className="snack-bar-inner mb-4 mx-4 flex flex-col gap-4 items-center">
|
|
13
|
+
<Snack id={"a"} content="Hello world" expiration={-1} color="yellow" canClose={true} />
|
|
14
|
+
<Snack
|
|
15
|
+
id={"b"}
|
|
16
|
+
content="Basic notification"
|
|
17
|
+
expiration={-1}
|
|
18
|
+
color="yellow"
|
|
19
|
+
canClose={false}
|
|
20
|
+
withLoader={true}
|
|
21
|
+
/>
|
|
22
|
+
<Snack id={"c"} content="Error message" expiration={-1} color="red" />
|
|
23
|
+
<Snack id={"c"} content="Warning message" expiration={-1} color="orange" />
|
|
24
|
+
<Snack
|
|
25
|
+
id={"c"}
|
|
26
|
+
content="Lorem ipsum dolor sit, amet consectetur adipisicing elit. Laudantium fuga totam facilis veritatis eaque ea ad laboriosam debitis accusantium, quos placeat magni architecto enim tempore, unde quae! Unde, voluptatum sint?"
|
|
27
|
+
expiration={-1}
|
|
28
|
+
color="blue"
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
|
|
4
|
+
import { Button } from "../button";
|
|
5
|
+
import { useEventCallback } from "~/hooks";
|
|
6
|
+
import { Dialog } from "../dialog";
|
|
7
|
+
import Loader from "../loader/Loader";
|
|
8
|
+
import { Message } from "~/types.d";
|
|
9
|
+
|
|
10
|
+
export type SnackProps = Partial<Message> & {
|
|
11
|
+
onRemove?: () => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default function Snack({
|
|
15
|
+
expiration = 5000,
|
|
16
|
+
content = "",
|
|
17
|
+
color = "yellow",
|
|
18
|
+
withLoader = false,
|
|
19
|
+
canClose = false,
|
|
20
|
+
onRemove = () => {},
|
|
21
|
+
}: SnackProps) {
|
|
22
|
+
const onRemoveStable = useEventCallback(onRemove);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (expiration === -1) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const timeoutId = setTimeout(() => onRemoveStable(), expiration);
|
|
30
|
+
return () => void clearTimeout(timeoutId);
|
|
31
|
+
}, [onRemoveStable, expiration]);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Dialog className={clsx("animate-fade-in", "ll-snack")} placement="top" color={color}>
|
|
35
|
+
<div className="w-fit min-w-60 px-2 py-1 flex items-center">
|
|
36
|
+
<span className="pr-4 flex-1">{content}</span>
|
|
37
|
+
{withLoader && <Loader size="small" color="gray" />}
|
|
38
|
+
|
|
39
|
+
{canClose && (
|
|
40
|
+
<Button icon variant="text" color="gray" onClick={onRemove}>
|
|
41
|
+
<i className="fe-cancel"></i>
|
|
42
|
+
</Button>
|
|
43
|
+
)}
|
|
44
|
+
</div>
|
|
45
|
+
</Dialog>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Meta } from "@storybook/react";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { ItemInterface, ReactSortable } from "react-sortablejs";
|
|
4
|
+
import { Button } from "../button";
|
|
5
|
+
import { Input } from "../input";
|
|
6
|
+
import { Sortable } from ".";
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
title: "Components/Sortable",
|
|
10
|
+
component: Sortable,
|
|
11
|
+
} satisfies Meta;
|
|
12
|
+
export default meta;
|
|
13
|
+
|
|
14
|
+
export interface Item extends ItemInterface {
|
|
15
|
+
id: number;
|
|
16
|
+
name: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const data: Item[] = [
|
|
20
|
+
{
|
|
21
|
+
id: 0,
|
|
22
|
+
name: "Rare Wind",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 1,
|
|
26
|
+
name: "Saint Petersburg",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 2,
|
|
30
|
+
name: "Deep Blue",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: 3,
|
|
34
|
+
name: "Ripe Malinka",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 4,
|
|
38
|
+
name: "Near Moon",
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const twClasses = {
|
|
43
|
+
item: "row-item rounded-2xl p-2 flex items-center [&.sortable-chosen]:shadow",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* ReactSortable mutate state, it can't be used with redux.
|
|
48
|
+
* see: https://github.com/SortableJS/react-sortablejs/issues/237
|
|
49
|
+
*/
|
|
50
|
+
export const BasicOriginal = () => {
|
|
51
|
+
const [items, setItems] = useState(data);
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<ReactSortable list={items} setList={setItems} animation={200} handle=".handle">
|
|
55
|
+
{items.map((item) => (
|
|
56
|
+
<div key={item.id} className={twClasses.item}>
|
|
57
|
+
<Button icon variant="text" color="gray" className="handle cursor-row-resize mr-2">
|
|
58
|
+
<i className="fe-braille"></i>
|
|
59
|
+
</Button>
|
|
60
|
+
{item.name}
|
|
61
|
+
</div>
|
|
62
|
+
))}
|
|
63
|
+
</ReactSortable>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const Basic = () => {
|
|
68
|
+
const [items, setItems] = useState(data);
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<Sortable list={items} setList={setItems} animation={200} handle=".handle">
|
|
72
|
+
{items.map((item) => (
|
|
73
|
+
<div key={item.id} className={twClasses.item}>
|
|
74
|
+
<Button icon variant="text" color="gray" className="handle cursor-row-resize mr-2">
|
|
75
|
+
<i className="fe-braille"></i>
|
|
76
|
+
</Button>
|
|
77
|
+
{item.name}
|
|
78
|
+
</div>
|
|
79
|
+
))}
|
|
80
|
+
</Sortable>
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const WithInputs = () => {
|
|
85
|
+
const [items, setItems] = useState(data);
|
|
86
|
+
return (
|
|
87
|
+
<Sortable list={items} setList={setItems} animation={200} handle=".handle">
|
|
88
|
+
{items.map((item) => (
|
|
89
|
+
<div key={item.id} className={twClasses.item}>
|
|
90
|
+
<Button icon variant="text" color="gray" className="handle cursor-row-resize mr-2">
|
|
91
|
+
<i className="fe-braille"></i>
|
|
92
|
+
</Button>
|
|
93
|
+
<Input className="flex-1" defaultValue={item.name} />
|
|
94
|
+
</div>
|
|
95
|
+
))}
|
|
96
|
+
</Sortable>
|
|
97
|
+
);
|
|
98
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { arrayEquals } from "~/lib";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import {
|
|
4
|
+
ItemInterface,
|
|
5
|
+
ReactSortable,
|
|
6
|
+
ReactSortableProps,
|
|
7
|
+
Sortable as SortableLib,
|
|
8
|
+
Store,
|
|
9
|
+
} from "react-sortablejs";
|
|
10
|
+
|
|
11
|
+
export default function Sortable<T extends ItemInterface>({
|
|
12
|
+
children,
|
|
13
|
+
list,
|
|
14
|
+
setList,
|
|
15
|
+
...rest
|
|
16
|
+
}: ReactSortableProps<T>) {
|
|
17
|
+
const mutableList = useMemo(() => {
|
|
18
|
+
return list.map((item) => ({ ...item }));
|
|
19
|
+
}, [list]);
|
|
20
|
+
|
|
21
|
+
function handleList(updatedList: T[], sortable: SortableLib | null, store: Store) {
|
|
22
|
+
if (
|
|
23
|
+
!arrayEquals(
|
|
24
|
+
updatedList.map((l) => l.id),
|
|
25
|
+
mutableList.map((l) => l.id),
|
|
26
|
+
)
|
|
27
|
+
) {
|
|
28
|
+
setList(updatedList, sortable, store);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<ReactSortable list={mutableList} setList={handleList} {...rest}>
|
|
34
|
+
{children}
|
|
35
|
+
</ReactSortable>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface SortableItem<I> {
|
|
2
|
+
/** The unique id associated with your item. It's recommended this is the same as the key prop for your list item. */
|
|
3
|
+
id: string | number;
|
|
4
|
+
/** When true, the item is selected using MultiDrag */
|
|
5
|
+
selected?: boolean;
|
|
6
|
+
/** When true, the item is deemed "chosen", which basically just a mousedown event. */
|
|
7
|
+
chosen?: boolean;
|
|
8
|
+
/** When true, it will not be possible to pick this item up in the list. */
|
|
9
|
+
filtered?: boolean;
|
|
10
|
+
|
|
11
|
+
data: I;
|
|
12
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef, ReactNode } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
interface Props extends ComponentPropsWithoutRef<"li"> {
|
|
4
|
+
icon?: ReactNode;
|
|
5
|
+
status?: "done" | "current" | "todo";
|
|
6
|
+
|
|
7
|
+
/** choose center if content height is less than ll-circle height */
|
|
8
|
+
align?: "start" | "center";
|
|
9
|
+
|
|
10
|
+
markerClassName?: string;
|
|
11
|
+
contentClassName?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default function Step({
|
|
15
|
+
status = "todo",
|
|
16
|
+
className,
|
|
17
|
+
children,
|
|
18
|
+
markerClassName,
|
|
19
|
+
contentClassName,
|
|
20
|
+
align = "start",
|
|
21
|
+
icon = null,
|
|
22
|
+
...rest
|
|
23
|
+
}: Props) {
|
|
24
|
+
return (
|
|
25
|
+
<li className={clsx(["ll-step", `status-${status}`, `align-${align}`, className])} {...rest}>
|
|
26
|
+
<div className="marker-container">
|
|
27
|
+
<div
|
|
28
|
+
className={clsx([
|
|
29
|
+
"marker",
|
|
30
|
+
"relative z-[1] inline-flex items-center justify-center rounded-full ",
|
|
31
|
+
["done", "current"].includes(status) && "active",
|
|
32
|
+
markerClassName,
|
|
33
|
+
])}
|
|
34
|
+
>
|
|
35
|
+
{icon}
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
<div className={clsx(["content", contentClassName])}>{children}</div>
|
|
39
|
+
</li>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { Meta } from "@storybook/react";
|
|
2
|
+
import Steps from "./Steps";
|
|
3
|
+
import Step from "./Step";
|
|
4
|
+
import { Input } from "../input";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { ReactSortable } from "react-sortablejs";
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
title: "Components/Steps",
|
|
10
|
+
component: Steps,
|
|
11
|
+
} satisfies Meta<typeof Steps>;
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
|
|
15
|
+
export const Context = () => {
|
|
16
|
+
return (
|
|
17
|
+
<div className="grid grid-cols-1 gap-8">
|
|
18
|
+
<Steps direction="horizontal" lineStyle="dotted">
|
|
19
|
+
<Step icon="A" status="done">
|
|
20
|
+
<h4 className="text-sm">Step 1</h4>
|
|
21
|
+
<p className="text-xs">Some desc text</p>
|
|
22
|
+
</Step>
|
|
23
|
+
<Step icon="B" status="current">
|
|
24
|
+
<h4 className="text-sm">Step 2</h4>
|
|
25
|
+
</Step>
|
|
26
|
+
<Step icon="C" status="todo">
|
|
27
|
+
<h4 className="text-sm">Step 3</h4>
|
|
28
|
+
<p className="text-xs">Another description</p>
|
|
29
|
+
</Step>
|
|
30
|
+
<Step icon="D" status="todo">
|
|
31
|
+
<h4 className="text-sm">Step 4</h4>
|
|
32
|
+
</Step>
|
|
33
|
+
</Steps>
|
|
34
|
+
<Steps direction="horizontal" markerType="bullet">
|
|
35
|
+
<Step status="done">
|
|
36
|
+
<h4 className="text-sm">Step 1</h4>
|
|
37
|
+
<p className="text-xs">Some desc text</p>
|
|
38
|
+
</Step>
|
|
39
|
+
<Step status="current">
|
|
40
|
+
<h4 className="text-sm">Step 2</h4>
|
|
41
|
+
</Step>
|
|
42
|
+
<Step status="todo">
|
|
43
|
+
<h4 className="text-sm">Step 3</h4>
|
|
44
|
+
<p className="text-xs">Another description</p>
|
|
45
|
+
</Step>
|
|
46
|
+
<Step status="todo">
|
|
47
|
+
<h4 className="text-sm">Step 4</h4>
|
|
48
|
+
</Step>
|
|
49
|
+
</Steps>
|
|
50
|
+
<Steps lineStyle="dotted">
|
|
51
|
+
<Step icon="A" status="done">
|
|
52
|
+
<h4 className="text-sm">Step 1</h4>
|
|
53
|
+
<p className="text-xs">Some desc text</p>
|
|
54
|
+
</Step>
|
|
55
|
+
<Step icon="B" status="current" align="center">
|
|
56
|
+
<Input defaultValue="Hello world" />
|
|
57
|
+
</Step>
|
|
58
|
+
<Step icon="C" status="todo">
|
|
59
|
+
<h4 className="text-sm">Step 3</h4>
|
|
60
|
+
<p className="text-xs">
|
|
61
|
+
Some desc text
|
|
62
|
+
<br />
|
|
63
|
+
with much more content
|
|
64
|
+
</p>
|
|
65
|
+
</Step>
|
|
66
|
+
<Step icon="D" status="todo">
|
|
67
|
+
<Input defaultValue="Hello world" />
|
|
68
|
+
</Step>
|
|
69
|
+
</Steps>
|
|
70
|
+
<Steps markerType="bullet" lineStyle="dotted">
|
|
71
|
+
<Step status="done">
|
|
72
|
+
<h4 className="text-sm">Step 1</h4>
|
|
73
|
+
<p className="text-xs">Some desc text</p>
|
|
74
|
+
</Step>
|
|
75
|
+
<Step icon="B" status="current">
|
|
76
|
+
<Input defaultValue="Hello world" />
|
|
77
|
+
</Step>
|
|
78
|
+
<Step icon="C" status="todo">
|
|
79
|
+
<Input defaultValue="Hello world" />
|
|
80
|
+
</Step>
|
|
81
|
+
<Step icon="D" status="todo">
|
|
82
|
+
<Input defaultValue="Hello world" />
|
|
83
|
+
</Step>
|
|
84
|
+
</Steps>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
interface Item {
|
|
90
|
+
id: number;
|
|
91
|
+
name: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const data: Item[] = [
|
|
95
|
+
{
|
|
96
|
+
id: 0,
|
|
97
|
+
name: "Rare Wind",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 1,
|
|
101
|
+
name: "Saint Petersburg",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
id: 2,
|
|
105
|
+
name: "Deep Blue",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: 3,
|
|
109
|
+
name: "Ripe Malinka",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 4,
|
|
113
|
+
name: "Near Moon",
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
export const WithSortable = () => {
|
|
118
|
+
const [items, setItems] = useState(data);
|
|
119
|
+
return (
|
|
120
|
+
<Steps markerType="bullet" lineStyle="dotted" associateLineWithStep={false}>
|
|
121
|
+
<ReactSortable
|
|
122
|
+
list={items}
|
|
123
|
+
setList={setItems}
|
|
124
|
+
animation={200}
|
|
125
|
+
handle=".handle"
|
|
126
|
+
className="ll-sortable"
|
|
127
|
+
>
|
|
128
|
+
{items.map((item, index) => (
|
|
129
|
+
<Step
|
|
130
|
+
key={item.id}
|
|
131
|
+
icon={index + 1}
|
|
132
|
+
status={index < items.length - 1 ? "done" : "current"}
|
|
133
|
+
markerClassName="handle"
|
|
134
|
+
>
|
|
135
|
+
<Input defaultValue={item.name} />
|
|
136
|
+
</Step>
|
|
137
|
+
))}
|
|
138
|
+
</ReactSortable>
|
|
139
|
+
</Steps>
|
|
140
|
+
);
|
|
141
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
|
|
4
|
+
interface Props extends ComponentPropsWithoutRef<"ul"> {
|
|
5
|
+
direction?: "horizontal" | "vertical";
|
|
6
|
+
lineStyle?: "solid" | "dashed" | "dotted";
|
|
7
|
+
markerType?: "circle" | "bullet";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* if your Step is multiline keep it false
|
|
11
|
+
* better render and add line-space
|
|
12
|
+
*
|
|
13
|
+
* if your Steps are Sortable and eash Step si only one line
|
|
14
|
+
* and steps are vertical
|
|
15
|
+
* set it to true, line will not be animated when sorting
|
|
16
|
+
*/
|
|
17
|
+
associateLineWithStep?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const stepsVariants = {
|
|
21
|
+
direction: {
|
|
22
|
+
horizontal: "",
|
|
23
|
+
vertical: "",
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default function Steps({
|
|
28
|
+
direction = "vertical",
|
|
29
|
+
lineStyle = "solid",
|
|
30
|
+
markerType = "circle",
|
|
31
|
+
associateLineWithStep = true,
|
|
32
|
+
className,
|
|
33
|
+
...rest
|
|
34
|
+
}: Props) {
|
|
35
|
+
return (
|
|
36
|
+
<ul
|
|
37
|
+
{...rest}
|
|
38
|
+
className={clsx(["ll-steps", className])}
|
|
39
|
+
data-global-line={(!associateLineWithStep).toString()}
|
|
40
|
+
data-direction={direction}
|
|
41
|
+
data-marker={markerType}
|
|
42
|
+
style={{
|
|
43
|
+
"--line-style": lineStyle,
|
|
44
|
+
"--line-space": associateLineWithStep ? "4px" : "0px",
|
|
45
|
+
// "--step-circle-radius": markerType === "circle" ? "18px" : "9px",
|
|
46
|
+
}}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Table, TableBody, TableCell, TableHeader, TableHeaderCell, TableRow } from ".";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: "Components/Tables",
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const Basic = () => {
|
|
8
|
+
return (
|
|
9
|
+
<Table>
|
|
10
|
+
<TableHeader>
|
|
11
|
+
<TableRow>
|
|
12
|
+
<TableHeaderCell>ID</TableHeaderCell>
|
|
13
|
+
<TableHeaderCell>Name</TableHeaderCell>
|
|
14
|
+
<TableHeaderCell>Loremium</TableHeaderCell>
|
|
15
|
+
</TableRow>
|
|
16
|
+
</TableHeader>
|
|
17
|
+
<TableBody>
|
|
18
|
+
<TableRow>
|
|
19
|
+
<TableCell label="ID">Lorem ipsum</TableCell>
|
|
20
|
+
<TableCell label="Name">Lorem ipsum</TableCell>
|
|
21
|
+
<TableCell label="Description">Loremium</TableCell>
|
|
22
|
+
</TableRow>
|
|
23
|
+
<TableRow>
|
|
24
|
+
<TableCell label="ID">Lorem ipsum</TableCell>
|
|
25
|
+
<TableCell label="Name">Lorem ipsum</TableCell>
|
|
26
|
+
<TableCell label="Description">Loremium</TableCell>
|
|
27
|
+
</TableRow>
|
|
28
|
+
<TableRow>
|
|
29
|
+
<TableCell label="ID">Lorem ipsum</TableCell>
|
|
30
|
+
<TableCell label="Name">Lorem ipsum</TableCell>
|
|
31
|
+
<TableCell label="Description">Loremium</TableCell>
|
|
32
|
+
</TableRow>
|
|
33
|
+
</TableBody>
|
|
34
|
+
</Table>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ReactNode, ComponentProps } from "react";
|
|
2
|
+
|
|
3
|
+
interface Props extends ComponentProps<"table"> {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export default function Table({ children, ...props }: Props) {
|
|
8
|
+
return (
|
|
9
|
+
<table className="w-full" {...props}>
|
|
10
|
+
{children}
|
|
11
|
+
</table>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
import { ReactNode, ComponentProps } from "react";
|
|
3
|
+
|
|
4
|
+
interface Props extends ComponentProps<"td"> {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
label?: ReactNode | string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function Table({ children, className, label, ...props }: Props) {
|
|
10
|
+
return (
|
|
11
|
+
<td className={clsx("p-2 block lg:table-cell", className)} {...props}>
|
|
12
|
+
{label && <p className="font-medium text-sm text-gray-6 lg:hidden">{label}</p>}
|
|
13
|
+
{children}
|
|
14
|
+
</td>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
import { ComponentProps, ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
interface Props extends ComponentProps<"thead"> {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function Table({ children, className, ...props }: Props) {
|
|
9
|
+
return (
|
|
10
|
+
<thead className={clsx("hidden lg:table-header-group", className)} {...props}>
|
|
11
|
+
{children}
|
|
12
|
+
</thead>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
import { ReactNode, ComponentProps } from "react";
|
|
3
|
+
|
|
4
|
+
interface Props extends ComponentProps<"th"> {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function Table({ children, className, ...props }: Props) {
|
|
9
|
+
return (
|
|
10
|
+
<th className={clsx("text-left font-bold p-2", className)} {...props}>
|
|
11
|
+
{children}
|
|
12
|
+
</th>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
import { ComponentProps, ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
interface Props extends ComponentProps<"tr"> {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function Table({ children, className, ...props }: Props) {
|
|
9
|
+
return (
|
|
10
|
+
<tr className={clsx("border-b border-gray-3 block lg:table-row", className)} {...props}>
|
|
11
|
+
{children}
|
|
12
|
+
</tr>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as Table } from "./Table";
|
|
2
|
+
export { default as TableBody } from "./TableBody";
|
|
3
|
+
export { default as TableCell } from "./TableCell";
|
|
4
|
+
export { default as TableHeader } from "./TableHeader";
|
|
5
|
+
export { default as TableHeaderCell } from "./TableHeaderCell";
|
|
6
|
+
export { default as TableRow } from "./TableRow";
|
|
7
|
+
export { default as TableFooter } from "./TableFooter";
|