@cystackapp/ui 1.4.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +77 -47
- package/dist/assets/background-pattern-grid.svg.js +7 -0
- package/dist/assets/empty-cloud.svg.js +5 -0
- package/dist/components/accordion/Accordion.d.ts +20 -0
- package/dist/components/accordion/Accordion.js +36 -0
- package/dist/components/accordion/AccordionTestStory.d.ts +3 -0
- package/dist/components/alert/Alert.d.ts +15 -0
- package/dist/components/alert/Alert.js +54 -0
- package/dist/components/avatar/Avatar.d.ts +13 -0
- package/dist/components/avatar/Avatar.js +64 -0
- package/dist/components/background-pattern/BackgroundPatternGrid.d.ts +1 -0
- package/dist/components/background-pattern/BackgroundPatternGrid.js +6 -0
- package/dist/components/badge/Badge.d.ts +1 -1
- package/dist/components/badge/Badge.js +3 -3
- package/dist/components/badge/BadgeTestStory.d.ts +1 -1
- package/dist/components/badge/variants/BadgeMore.d.ts +1 -1
- package/dist/components/badge/variants/BadgeMoreTestStory.d.ts +1 -1
- package/dist/components/badge/variants/BadgeTag.d.ts +1 -1
- package/dist/components/badge/variants/BadgeTag.js +1 -1
- package/dist/components/banner/Banner.d.ts +9 -0
- package/dist/components/banner/Banner.js +21 -0
- package/dist/components/breadcrumb/Breadcrumb.d.ts +13 -0
- package/dist/components/breadcrumb/Breadcrumb.js +36 -0
- package/dist/components/button/Button.d.ts +21 -0
- package/dist/components/button/Button.js +49 -0
- package/dist/components/button/ButtonLoader.d.ts +7 -0
- package/dist/components/button/ButtonLoader.js +44 -0
- package/dist/components/button/ButtonTestStory.d.ts +5 -0
- package/dist/components/button/button-variants.d.ts +13 -0
- package/dist/components/button/button-variants.js +58 -0
- package/dist/components/card/Card.d.ts +91 -0
- package/dist/components/card/Card.js +56 -0
- package/dist/components/card/Card.stories-ct.d.ts +1 -0
- package/dist/components/card/CardBody.d.ts +9 -0
- package/dist/components/card/CardBody.js +16 -0
- package/dist/components/card/CardHeader.d.ts +15 -0
- package/dist/components/card/CardHeader.js +79 -0
- package/dist/components/card/types.d.ts +1 -0
- package/dist/components/chart/chart-legend/ChartLegend.d.ts +38 -0
- package/dist/components/chart/chart-legend/ChartLegend.js +57 -0
- package/dist/components/chart/chart-legend/ChartLegendItem.d.ts +19 -0
- package/dist/components/chart/chart-legend/ChartLegendItem.js +30 -0
- package/dist/components/chart/chart-legend/types.d.ts +49 -0
- package/dist/components/chart/donut-chart/DonutChart.d.ts +55 -0
- package/dist/components/chart/donut-chart/DonutChart.js +110 -0
- package/dist/components/chart/donut-chart/DonutSegments.d.ts +25 -0
- package/dist/components/chart/donut-chart/DonutSegments.js +51 -0
- package/dist/components/chart/donut-chart/donut-tooltip.d.ts +20 -0
- package/dist/components/chart/donut-chart/donut-tooltip.js +37 -0
- package/dist/components/chart/types.d.ts +8 -0
- package/dist/components/checkbox/Checkbox.d.ts +6 -0
- package/dist/components/checkbox/Checkbox.js +72 -0
- package/dist/components/checkbox/CheckboxTestStory.d.ts +7 -0
- package/dist/components/collapsible/Collapsible.d.ts +21 -0
- package/dist/components/collapsible/Collapsible.js +50 -0
- package/dist/components/combobox/Combobox.d.ts +1 -1
- package/dist/components/divider/Divider.d.ts +9 -0
- package/dist/components/divider/Divider.js +28 -0
- package/dist/components/drawer/Drawer.d.ts +8 -0
- package/dist/components/drawer/Drawer.js +68 -0
- package/dist/components/dropdown/Dropdown.d.ts +45 -0
- package/dist/components/dropdown/Dropdown.js +133 -0
- package/dist/components/dropdown/DropdownMenu.d.ts +20 -0
- package/dist/components/dropdown/DropdownMenu.js +78 -0
- package/dist/components/dropdown/DropdownMenuItem.d.ts +13 -0
- package/dist/components/dropdown/DropdownMenuItem.js +49 -0
- package/dist/components/dropdown/DropdownTestStory.d.ts +5 -0
- package/dist/components/dropdown/dropdown-utils.d.ts +4 -0
- package/dist/components/dropdown/dropdown-utils.js +14 -0
- package/dist/components/dropdown/types.d.ts +48 -0
- package/dist/components/dropdown/use-dropdown-keyboard.d.ts +12 -0
- package/dist/components/dropdown/use-dropdown-keyboard.js +49 -0
- package/dist/components/empty-state/EmptyState.d.ts +26 -0
- package/dist/components/empty-state/EmptyState.js +36 -0
- package/dist/components/error-state/ErrorState.d.ts +1 -1
- package/dist/components/featured-icon/FeaturedIcon.d.ts +12 -0
- package/dist/components/featured-icon/FeaturedIcon.js +44 -0
- package/dist/components/form-field/FormField.d.ts +13 -0
- package/dist/components/form-field/FormField.js +21 -0
- package/dist/components/input/Input.d.ts +11 -0
- package/dist/components/input/Input.js +39 -0
- package/dist/components/keyboard-shortcut-label/KeyboardShortcutLabel.d.ts +8 -0
- package/dist/components/keyboard-shortcut-label/KeyboardShortcutLabel.js +18 -0
- package/dist/components/loading-state/Loader.d.ts +20 -0
- package/dist/components/loading-state/Loader.js +38 -0
- package/dist/components/loading-state/LoadingState.d.ts +15 -0
- package/dist/components/loading-state/LoadingState.js +47 -0
- package/dist/components/loading-state/locale/en.json.d.ts +6 -0
- package/dist/components/loading-state/locale/en.json.js +7 -0
- package/dist/components/loading-state/locale/vi.json.d.ts +6 -0
- package/dist/components/loading-state/locale/vi.json.js +7 -0
- package/dist/components/media/Media.d.ts +7 -0
- package/dist/components/media/Media.js +25 -0
- package/dist/components/modal/Modal.d.ts +9 -0
- package/dist/components/modal/Modal.js +68 -0
- package/dist/components/modal/helpers/HeaderIcon.d.ts +8 -0
- package/dist/components/modal/helpers/HeaderIcon.js +32 -0
- package/dist/components/modal/helpers/Title.d.ts +6 -0
- package/dist/components/modal/helpers/Title.js +9 -0
- package/dist/components/modal/helpers/circles-sm.svg.js +5 -0
- package/dist/components/modal/modal-context.d.ts +2 -0
- package/dist/components/modal/modal-context.js +9 -0
- package/dist/components/modal/use-click-outside-modal.d.ts +2 -0
- package/dist/components/modal/use-click-outside-modal.js +15 -0
- package/dist/components/notification/NotificationBanner.d.ts +9 -0
- package/dist/components/notification/NotificationBanner.js +97 -0
- package/dist/components/notification/icons.d.ts +5 -0
- package/dist/components/notification/icons.js +29 -0
- package/dist/components/notification/index.d.ts +4 -0
- package/dist/components/notification/index.js +26 -0
- package/dist/components/notification/locale/en.json.d.ts +8 -0
- package/dist/components/notification/locale/en.json.js +7 -0
- package/dist/components/notification/locale/vi.json.d.ts +8 -0
- package/dist/components/notification/locale/vi.json.js +7 -0
- package/dist/components/operating-system-icon/OperatingSystemIcon.d.ts +6 -0
- package/dist/components/operating-system-icon/OperatingSystemIcon.js +19 -0
- package/dist/components/operating-system-icon/assets/logo-android.svg.js +5 -0
- package/dist/components/operating-system-icon/assets/logo-apple.svg.js +5 -0
- package/dist/components/operating-system-icon/assets/logo-ubuntu.svg.js +5 -0
- package/dist/components/operating-system-icon/assets/logo-windows-10.svg.js +5 -0
- package/dist/components/page-title/PageTitle.d.ts +1 -1
- package/dist/components/popover/Popover.d.ts +1 -1
- package/dist/components/progress-bar/ProgressBar.d.ts +9 -0
- package/dist/components/progress-bar/ProgressBar.js +31 -0
- package/dist/components/radio/Radio.d.ts +4 -0
- package/dist/components/radio/Radio.js +55 -0
- package/dist/components/searchbox/Searchbox.d.ts +7 -0
- package/dist/components/searchbox/Searchbox.js +15 -0
- package/dist/components/select/Select.d.ts +11 -0
- package/dist/components/select/Select.js +44 -0
- package/dist/components/skeleton/Skeleton.d.ts +14 -0
- package/dist/components/skeleton/Skeleton.js +12 -0
- package/dist/components/switch/Switch.d.ts +1 -1
- package/dist/components/table/Table.d.ts +32 -0
- package/dist/components/table/Table.js +128 -0
- package/dist/components/table/TableActionButton.d.ts +15 -0
- package/dist/components/table/TableActionButton.js +50 -0
- package/dist/components/table/TableCell.d.ts +8 -0
- package/dist/components/table/TableCell.js +26 -0
- package/dist/components/table/TableHeader.d.ts +15 -0
- package/dist/components/table/TableHeader.js +36 -0
- package/dist/components/table/TableHeaderCell.d.ts +10 -0
- package/dist/components/table/TableHeaderCell.js +35 -0
- package/dist/components/table/TablePagination.d.ts +6 -0
- package/dist/components/table/TablePagination.js +69 -0
- package/dist/components/table/TableRow.d.ts +12 -0
- package/dist/components/table/TableRow.js +9 -0
- package/dist/components/table/expandable/ExpandableTable.d.ts +30 -0
- package/dist/components/table/expandable/ExpandableTable.js +156 -0
- package/dist/components/table/hooks/use-fit-page-height.d.ts +14 -0
- package/dist/components/table/hooks/use-fit-page-height.js +21 -0
- package/dist/components/table/hooks/use-row-selection.d.ts +27 -0
- package/dist/components/table/hooks/use-row-selection.js +35 -0
- package/dist/components/table/locale/en.json.d.ts +13 -0
- package/dist/components/table/locale/en.json.js +21 -0
- package/dist/components/table/locale/vi.json.d.ts +13 -0
- package/dist/components/table/locale/vi.json.js +21 -0
- package/dist/components/table/table-utils.d.ts +10 -0
- package/dist/components/table/table-utils.js +10 -0
- package/dist/components/table/types.d.ts +84 -0
- package/dist/components/tabs/Tabs.d.ts +27 -0
- package/dist/components/tabs/Tabs.js +75 -0
- package/dist/components/tabs/TabsTestStory.d.ts +4 -0
- package/dist/components/tags-input/TagsInput.d.ts +18 -0
- package/dist/components/tags-input/TagsInput.js +78 -0
- package/dist/components/tags-input/TagsInputTestStory.d.ts +3 -0
- package/dist/components/textarea/Textarea.d.ts +7 -0
- package/dist/components/textarea/Textarea.js +36 -0
- package/dist/components/toast/ToastSlice.d.ts +11 -0
- package/dist/components/toast/ToastSlice.js +103 -0
- package/dist/components/toast/icons.d.ts +8 -0
- package/dist/components/toast/icons.js +19 -0
- package/dist/components/toast/index.d.ts +4 -0
- package/dist/components/toast/index.js +35 -0
- package/dist/components/toast/types.d.ts +14 -0
- package/dist/components/toast/use-toast-list.d.ts +4 -0
- package/dist/components/toast/use-toast-list.js +27 -0
- package/dist/components/tooltip/Tooltip.d.ts +1 -1
- package/dist/filters/FilterDropdown.d.ts +9 -0
- package/dist/filters/FilterDropdown.js +57 -0
- package/dist/filters/types.d.ts +11 -0
- package/dist/filters/url-params.d.ts +5 -0
- package/dist/filters/url-params.js +20 -0
- package/dist/filters/use-filters.d.ts +13 -0
- package/dist/filters/use-filters.js +63 -0
- package/dist/hooks/use-countdown.d.ts +4 -0
- package/dist/hooks/use-countdown.js +18 -0
- package/dist/i18n/resources.js +23 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +141 -38
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +421 -350
- package/dist/test-utils/expect-visibility.d.ts +45 -0
- package/dist/utils/key-typeguard.d.ts +5 -0
- package/dist/utils/key-typeguard.js +6 -0
- package/dist/utils/observable.d.ts +7 -0
- package/dist/utils/observable.js +22 -0
- package/dist/utils/use-debounce.d.ts +1 -0
- package/dist/utils/use-debounce.js +11 -0
- package/package.json +30 -7
- package/theme.css +7 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BadgeColor } from '../badge/badge-utils';
|
|
2
|
+
export interface TagsInputProps {
|
|
3
|
+
tags: string[];
|
|
4
|
+
onTagsChange: (tags: string[]) => void;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
/** Marks the field as in an error state — switches the focus ring to error-v2. */
|
|
8
|
+
invalid?: boolean;
|
|
9
|
+
/** Fixed badge color for every tag. Defaults to a per-tag auto color. */
|
|
10
|
+
color?: BadgeColor;
|
|
11
|
+
/** Controlled text of the inner input (e.g. to drive an external search). */
|
|
12
|
+
value?: string;
|
|
13
|
+
onValueChange?: (value: string) => void;
|
|
14
|
+
/** Overrides the default removal behavior for a single tag. */
|
|
15
|
+
onRemove?: (tag: string) => void;
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const TagsInput: ({ tags, onTagsChange, placeholder, disabled, invalid, color, value, onValueChange, onRemove, className, }: TagsInputProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { jsxs as S, jsx as p } from "react/jsx-runtime";
|
|
2
|
+
import { useRef as T, useState as A } from "react";
|
|
3
|
+
import { cn as B } from "../../utils/cn.js";
|
|
4
|
+
import { Badge as D } from "../badge/Badge.js";
|
|
5
|
+
import { getBadgeAutoColor as E } from "../badge/variants/BadgeTag.js";
|
|
6
|
+
const l = {
|
|
7
|
+
default: "border-gray-v2-300 focus-within:border-brand-v2 focus-within:outline-brand-v2",
|
|
8
|
+
invalid: "border-error-v2-300 focus-within:border-error-v2 focus-within:outline-error-v2",
|
|
9
|
+
disabled: "bg-gray-v2-50 border-gray-v2-300 cursor-not-allowed"
|
|
10
|
+
}, _ = ({
|
|
11
|
+
tags: t,
|
|
12
|
+
onTagsChange: s,
|
|
13
|
+
placeholder: m,
|
|
14
|
+
disabled: o,
|
|
15
|
+
invalid: v,
|
|
16
|
+
color: h,
|
|
17
|
+
value: a,
|
|
18
|
+
onValueChange: n,
|
|
19
|
+
onRemove: c,
|
|
20
|
+
className: x
|
|
21
|
+
}) => {
|
|
22
|
+
const d = T(null), [g, w] = A(""), i = a !== void 0 ? a : g, u = (r) => {
|
|
23
|
+
w(r), n == null || n(r);
|
|
24
|
+
}, f = (r) => {
|
|
25
|
+
o || (c ? c(t[r]) : s(t.filter((e, k) => k !== r)));
|
|
26
|
+
}, y = (r) => {
|
|
27
|
+
var e;
|
|
28
|
+
r.target === r.currentTarget && ((e = d.current) == null || e.focus());
|
|
29
|
+
}, b = (r) => {
|
|
30
|
+
if (r.key === "Enter") {
|
|
31
|
+
r.preventDefault();
|
|
32
|
+
const e = i.trim();
|
|
33
|
+
if (e.length === 0) return;
|
|
34
|
+
s([...t, e]), u("");
|
|
35
|
+
}
|
|
36
|
+
r.key === "Backspace" && i.length === 0 && t.length > 0 && f(t.length - 1);
|
|
37
|
+
};
|
|
38
|
+
return /* @__PURE__ */ S(
|
|
39
|
+
"div",
|
|
40
|
+
{
|
|
41
|
+
onClick: y,
|
|
42
|
+
className: B(
|
|
43
|
+
"bg-white rounded-lg border shadow-xs flex flex-wrap items-center gap-1.5 px-3 py-2 min-h-10 text-md transition-all outline outline-transparent cursor-text",
|
|
44
|
+
v ? l.invalid : l.default,
|
|
45
|
+
{ [l.disabled]: o },
|
|
46
|
+
x
|
|
47
|
+
),
|
|
48
|
+
children: [
|
|
49
|
+
t.map((r, e) => /* @__PURE__ */ p(
|
|
50
|
+
D,
|
|
51
|
+
{
|
|
52
|
+
color: h ?? E(r),
|
|
53
|
+
size: "sm",
|
|
54
|
+
onClose: o ? void 0 : () => f(e),
|
|
55
|
+
children: r
|
|
56
|
+
},
|
|
57
|
+
`${r}-${e}`
|
|
58
|
+
)),
|
|
59
|
+
/* @__PURE__ */ p(
|
|
60
|
+
"input",
|
|
61
|
+
{
|
|
62
|
+
ref: d,
|
|
63
|
+
type: "text",
|
|
64
|
+
disabled: o,
|
|
65
|
+
value: i,
|
|
66
|
+
onChange: (r) => u(r.target.value),
|
|
67
|
+
onKeyDown: b,
|
|
68
|
+
placeholder: o ? void 0 : m,
|
|
69
|
+
className: "flex-1 min-w-16 bg-transparent outline-none text-gray-v2-900 placeholder:text-gray-v2-500 disabled:text-gray-v2-400 disabled:cursor-not-allowed"
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
export {
|
|
77
|
+
_ as TagsInput
|
|
78
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { TextareaHTMLAttributes } from 'react';
|
|
2
|
+
interface Props extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
3
|
+
/** Marks the textarea as in an error state — switches the focus ring to error-v2. */
|
|
4
|
+
invalid?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare const Textarea: import('react').ForwardRefExoticComponent<Props & import('react').RefAttributes<HTMLTextAreaElement>>;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as l } from "react";
|
|
3
|
+
import { cn as s } from "../../utils/cn.js";
|
|
4
|
+
const e = {
|
|
5
|
+
default: "border-gray-v2-300 focus-within:border-brand-v2 focus-within:outline-brand-v2",
|
|
6
|
+
invalid: "border-error-v2-300 focus-within:border-error-v2 focus-within:outline-error-v2",
|
|
7
|
+
disabled: "bg-gray-v2-50 border-gray-v2-300 cursor-not-allowed"
|
|
8
|
+
}, c = l(
|
|
9
|
+
({ invalid: a, className: i, disabled: r, rows: n = 4, ...o }, d) => /* @__PURE__ */ t(
|
|
10
|
+
"span",
|
|
11
|
+
{
|
|
12
|
+
className: s(
|
|
13
|
+
"bg-white rounded-lg border shadow-xs flex px-3 py-2.5 text-md transition-all outline outline-transparent",
|
|
14
|
+
a ? e.invalid : e.default,
|
|
15
|
+
{ [e.disabled]: r },
|
|
16
|
+
i
|
|
17
|
+
),
|
|
18
|
+
children: /* @__PURE__ */ t(
|
|
19
|
+
"textarea",
|
|
20
|
+
{
|
|
21
|
+
ref: d,
|
|
22
|
+
disabled: r,
|
|
23
|
+
"aria-invalid": a,
|
|
24
|
+
rows: n,
|
|
25
|
+
className: "flex-1 min-w-0 bg-transparent outline-none resize-y text-gray-v2-900 placeholder:text-gray-v2-500 disabled:text-gray-v2-400 disabled:cursor-not-allowed disabled:resize-none",
|
|
26
|
+
...o,
|
|
27
|
+
placeholder: r ? void 0 : o.placeholder
|
|
28
|
+
}
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
);
|
|
33
|
+
c.displayName = "Textarea";
|
|
34
|
+
export {
|
|
35
|
+
c as Textarea
|
|
36
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { InternalToastProps } from './types';
|
|
2
|
+
import { Observable } from '../../utils/observable';
|
|
3
|
+
interface Props {
|
|
4
|
+
toast: InternalToastProps;
|
|
5
|
+
observable: Observable<InternalToastProps>;
|
|
6
|
+
}
|
|
7
|
+
/** A slice of toast. Freshly out of the toaster, crunchy on the outside, soft and tender on the inside.
|
|
8
|
+
* Or is it just notification's UI.
|
|
9
|
+
*/
|
|
10
|
+
export declare const ToastSlice: ({ toast, observable }: Props) => import("react").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { jsxs as c, jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import { useState as f, useRef as y, useMemo as T, useCallback as p, useEffect as l } from "react";
|
|
3
|
+
import { XClose as x } from "@untitled-ui/icons-react";
|
|
4
|
+
import { Button as w } from "../button/Button.js";
|
|
5
|
+
import { iconByToastType as B, styleToastType as N } from "./icons.js";
|
|
6
|
+
import { cn as m } from "../../utils/cn.js";
|
|
7
|
+
const k = 4e3, W = ({ toast: e, observable: r }) => {
|
|
8
|
+
var a, d;
|
|
9
|
+
const [h, g] = f(!1), n = y(null), o = T(() => ["peach"].includes(e.type) ? "gradient" : "normal", [e.type]), s = p(
|
|
10
|
+
(t) => {
|
|
11
|
+
r.notify({ ...t, status: "dismissed" });
|
|
12
|
+
},
|
|
13
|
+
[r]
|
|
14
|
+
), u = p(
|
|
15
|
+
(t) => {
|
|
16
|
+
r.notify({ ...t, status: "destroyed" });
|
|
17
|
+
},
|
|
18
|
+
[r]
|
|
19
|
+
);
|
|
20
|
+
return l(() => {
|
|
21
|
+
g(!0);
|
|
22
|
+
}, []), l(() => {
|
|
23
|
+
const t = setTimeout(() => {
|
|
24
|
+
s(e);
|
|
25
|
+
}, k);
|
|
26
|
+
return () => clearTimeout(t);
|
|
27
|
+
}, [e, s]), /* @__PURE__ */ c(
|
|
28
|
+
"div",
|
|
29
|
+
{
|
|
30
|
+
ref: n,
|
|
31
|
+
style: h ? e.status === "dismissed" ? (
|
|
32
|
+
// The last state before toast is destroyed
|
|
33
|
+
{
|
|
34
|
+
height: 0,
|
|
35
|
+
minHeight: 0,
|
|
36
|
+
opacity: 0,
|
|
37
|
+
marginBottom: 0,
|
|
38
|
+
paddingTop: 0,
|
|
39
|
+
paddingBottom: 0,
|
|
40
|
+
borderWidth: 0
|
|
41
|
+
}
|
|
42
|
+
) : (
|
|
43
|
+
// The stable state
|
|
44
|
+
{
|
|
45
|
+
height: (d = n.current) == null ? void 0 : d.offsetHeight,
|
|
46
|
+
marginBottom: "0.75rem",
|
|
47
|
+
paddingTop: "0.75rem",
|
|
48
|
+
paddingBottom: "0.75rem",
|
|
49
|
+
borderWidth: "1px"
|
|
50
|
+
}
|
|
51
|
+
) : (
|
|
52
|
+
// The first state: before toast is mounted
|
|
53
|
+
{
|
|
54
|
+
transform: "translate(0, -100%)",
|
|
55
|
+
height: (a = n.current) == null ? void 0 : a.offsetHeight,
|
|
56
|
+
marginBottom: "0.75rem",
|
|
57
|
+
paddingTop: "0.75rem",
|
|
58
|
+
paddingBottom: "0.75rem",
|
|
59
|
+
borderWidth: "1px"
|
|
60
|
+
}
|
|
61
|
+
),
|
|
62
|
+
className: m(
|
|
63
|
+
"px-6 flex items-center gap-3 rounded-md duration-300 ease-out shadow-sm-01 min-h-16 overflow-hidden",
|
|
64
|
+
N[e.type],
|
|
65
|
+
o === "gradient" && "text-white"
|
|
66
|
+
),
|
|
67
|
+
onTransitionEnd: (t) => {
|
|
68
|
+
t.target === t.currentTarget && t.propertyName === "height" && u(e);
|
|
69
|
+
},
|
|
70
|
+
children: [
|
|
71
|
+
B[e.type],
|
|
72
|
+
/* @__PURE__ */ c("div", { className: "flex flex-col", children: [
|
|
73
|
+
/* @__PURE__ */ i("span", { className: "text-md font-medium w-80 min-h-[1em] wrap-break-words", children: e.message }),
|
|
74
|
+
e.detail ? /* @__PURE__ */ i(
|
|
75
|
+
"span",
|
|
76
|
+
{
|
|
77
|
+
className: m(
|
|
78
|
+
"text-sm w-80 min-h-[1em] wrap-break-words line-clamp-3",
|
|
79
|
+
o === "gradient" ? "text-white" : "text-gray-v2-500"
|
|
80
|
+
),
|
|
81
|
+
children: e.detail
|
|
82
|
+
}
|
|
83
|
+
) : null
|
|
84
|
+
] }),
|
|
85
|
+
/* @__PURE__ */ i(
|
|
86
|
+
w,
|
|
87
|
+
{
|
|
88
|
+
variant: "tertiary",
|
|
89
|
+
color: "gray",
|
|
90
|
+
onClick: () => s(e),
|
|
91
|
+
className: m(
|
|
92
|
+
o === "gradient" && "text-white hover:bg-transparent"
|
|
93
|
+
),
|
|
94
|
+
children: /* @__PURE__ */ i(x, { className: "size-5 shrink-0 text-gray-v2-400" })
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
export {
|
|
102
|
+
W as ToastSlice
|
|
103
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { InfoCircle as r, XCircle as s, CheckCircle as i } from "@untitled-ui/icons-react";
|
|
3
|
+
const a = {
|
|
4
|
+
success: "bg-white border-success-v2-500",
|
|
5
|
+
error: "bg-white border-error-v2-500",
|
|
6
|
+
warning: "bg-white border-warning-v2-500",
|
|
7
|
+
info: "bg-white border-blue-v2-500",
|
|
8
|
+
peach: "bg-gradient-to-br from-[#d74874] to-[#da805f] border-transparent"
|
|
9
|
+
}, c = {
|
|
10
|
+
success: /* @__PURE__ */ e(i, { className: "text-success-v2-500 size-6 shrink-0" }),
|
|
11
|
+
error: /* @__PURE__ */ e(s, { className: "text-error-v2-500 size-6 shrink-0" }),
|
|
12
|
+
warning: /* @__PURE__ */ e(r, { className: "text-warning-v2-500 size-6 shrink-0" }),
|
|
13
|
+
info: /* @__PURE__ */ e(r, { className: "text-blue-v2-500 size-6 shrink-0" }),
|
|
14
|
+
peach: /* @__PURE__ */ e(r, { className: "text-white size-6 shrink-0" })
|
|
15
|
+
};
|
|
16
|
+
export {
|
|
17
|
+
c as iconByToastType,
|
|
18
|
+
a as styleToastType
|
|
19
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { WrittenOnTheToast } from './types';
|
|
2
|
+
/** Where we store the newly cooked toasts. When a toast is created, it will appear here. */
|
|
3
|
+
export declare const Toaster: () => import("react").JSX.Element;
|
|
4
|
+
export declare const createToast: (newToast: WrittenOnTheToast) => void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect as a } from "react";
|
|
3
|
+
import { ToastSlice as n } from "./ToastSlice.js";
|
|
4
|
+
import { useToastList as i } from "./use-toast-list.js";
|
|
5
|
+
import { Observable as c } from "../../utils/observable.js";
|
|
6
|
+
const l = () => window.isSecureContext ? crypto.randomUUID() : crypto.getRandomValues(new Uint32Array(1))[0].toString(), e = new c(), s = /* @__PURE__ */ new Set(), b = () => {
|
|
7
|
+
const o = i(e);
|
|
8
|
+
return a(() => {
|
|
9
|
+
const t = Symbol();
|
|
10
|
+
return s.add(t), () => {
|
|
11
|
+
s.delete(t);
|
|
12
|
+
};
|
|
13
|
+
}, []), /* @__PURE__ */ r("div", { className: "flex flex-col", children: o.map((t) => /* @__PURE__ */ r(
|
|
14
|
+
n,
|
|
15
|
+
{
|
|
16
|
+
toast: t,
|
|
17
|
+
observable: e
|
|
18
|
+
},
|
|
19
|
+
`toast-${t.id}`
|
|
20
|
+
)) });
|
|
21
|
+
}, T = (o) => {
|
|
22
|
+
process.env.NODE_ENV !== "production" && s.size === 0 && console.warn(
|
|
23
|
+
"[Toaster] createToast was called but no <Toaster> is mounted. This toast will be lost."
|
|
24
|
+
);
|
|
25
|
+
const t = {
|
|
26
|
+
...o,
|
|
27
|
+
id: l(),
|
|
28
|
+
status: "stable"
|
|
29
|
+
};
|
|
30
|
+
e.notify(t);
|
|
31
|
+
};
|
|
32
|
+
export {
|
|
33
|
+
b as Toaster,
|
|
34
|
+
T as createToast
|
|
35
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export type ToastType = "error" | "warning" | "success" | "info" | "peach";
|
|
3
|
+
type ToastStatus = "stable" | "dismissed" | "destroyed";
|
|
4
|
+
/** The name is Bon, Jambon. */
|
|
5
|
+
export interface WrittenOnTheToast {
|
|
6
|
+
type: ToastType;
|
|
7
|
+
message: string;
|
|
8
|
+
detail?: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export interface InternalToastProps extends WrittenOnTheToast {
|
|
11
|
+
id: string;
|
|
12
|
+
status: ToastStatus;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useState as d, useEffect as f } from "react";
|
|
2
|
+
import { flushSync as m } from "react-dom";
|
|
3
|
+
const c = (i) => {
|
|
4
|
+
const [u, r] = d([]);
|
|
5
|
+
return f(() => i.subscribe((s) => {
|
|
6
|
+
if (s.status === "dismissed") {
|
|
7
|
+
r(
|
|
8
|
+
(t) => t.map(
|
|
9
|
+
(e) => e.id === s.id ? { ...e, status: "dismissed" } : e
|
|
10
|
+
)
|
|
11
|
+
);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (s.status === "destroyed") {
|
|
15
|
+
r((t) => t.filter((e) => e.id !== s.id));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
m(() => {
|
|
20
|
+
r((t) => [...t, s]);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}), [i]), u;
|
|
24
|
+
};
|
|
25
|
+
export {
|
|
26
|
+
c as useToastList
|
|
27
|
+
};
|
|
@@ -7,5 +7,5 @@ interface Props {
|
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
className?: string;
|
|
9
9
|
}
|
|
10
|
-
export declare const Tooltip: ({ content, children, position, disabled, className, }: Props) => import("react
|
|
10
|
+
export declare const Tooltip: ({ content, children, position, disabled, className, }: Props) => import("react").JSX.Element;
|
|
11
11
|
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FilterOption } from './types';
|
|
2
|
+
export interface FilterDropdownProps {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string | undefined;
|
|
5
|
+
options: FilterOption[];
|
|
6
|
+
onChange: (value: string | undefined) => void;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const FilterDropdown: ({ label, value, options, onChange, disabled, }: FilterDropdownProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as r, jsxs as m } from "react/jsx-runtime";
|
|
2
|
+
import { XClose as b, ChevronDown as v } from "@untitled-ui/icons-react";
|
|
3
|
+
import { cn as g } from "../utils/cn.js";
|
|
4
|
+
import { Dropdown as p } from "../components/dropdown/Dropdown.js";
|
|
5
|
+
const u = ({
|
|
6
|
+
label: n,
|
|
7
|
+
value: t,
|
|
8
|
+
options: i,
|
|
9
|
+
onChange: a,
|
|
10
|
+
disabled: o = !1
|
|
11
|
+
}) => {
|
|
12
|
+
var s;
|
|
13
|
+
const c = i.map((e) => ({
|
|
14
|
+
id: e.value,
|
|
15
|
+
label: e.label,
|
|
16
|
+
icon: e.icon
|
|
17
|
+
})), d = ((s = i.find((e) => e.value === t)) == null ? void 0 : s.label) ?? t, l = t !== void 0;
|
|
18
|
+
return /* @__PURE__ */ r(
|
|
19
|
+
p,
|
|
20
|
+
{
|
|
21
|
+
items: c,
|
|
22
|
+
selected: t,
|
|
23
|
+
onSelect: (e) => a(e.id),
|
|
24
|
+
disabled: o,
|
|
25
|
+
children: /* @__PURE__ */ m(
|
|
26
|
+
"button",
|
|
27
|
+
{
|
|
28
|
+
type: "button",
|
|
29
|
+
disabled: o,
|
|
30
|
+
className: g(
|
|
31
|
+
"inline-flex items-center justify-between gap-2 min-h-10 rounded-lg border border-gray-v2-300 bg-white px-3 py-2 text-sm font-semibold text-gray-v2-700 shadow-xs transition-all outline-2 outline-transparent hover:bg-gray-v2-50 focus:outline-brand-v2-400",
|
|
32
|
+
o && "cursor-not-allowed bg-gray-v2-50 text-gray-v2-400 border-gray-v2-200"
|
|
33
|
+
),
|
|
34
|
+
children: [
|
|
35
|
+
/* @__PURE__ */ r("span", { children: l ? `${n}: ${d}` : n }),
|
|
36
|
+
l ? /* @__PURE__ */ r(
|
|
37
|
+
"span",
|
|
38
|
+
{
|
|
39
|
+
role: "button",
|
|
40
|
+
"aria-label": "Clear filter",
|
|
41
|
+
tabIndex: -1,
|
|
42
|
+
onClick: (e) => {
|
|
43
|
+
e.stopPropagation(), a(void 0);
|
|
44
|
+
},
|
|
45
|
+
className: "inline-flex shrink-0 items-center rounded text-gray-v2-500 hover:text-gray-v2-700",
|
|
46
|
+
children: /* @__PURE__ */ r(b, { className: "h-5 w-5" })
|
|
47
|
+
}
|
|
48
|
+
) : /* @__PURE__ */ r(v, { className: "h-5 w-5 shrink-0 text-gray-v2-500" })
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
export {
|
|
56
|
+
u as FilterDropdown
|
|
57
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface FilterOption {
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
export interface ParamCodec<T> {
|
|
8
|
+
serialize: (value: T) => string | null;
|
|
9
|
+
deserialize: (raw: string) => T;
|
|
10
|
+
debounceMs?: number;
|
|
11
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ParamCodec } from './types';
|
|
2
|
+
export declare const stringCodec: ParamCodec<string | undefined>;
|
|
3
|
+
export declare const numberCodec: ParamCodec<number | undefined>;
|
|
4
|
+
export declare const csvCodec: ParamCodec<string[]>;
|
|
5
|
+
export declare const searchCodec: ParamCodec<string | undefined>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const i = {
|
|
2
|
+
serialize: (e) => e !== void 0 ? e : null,
|
|
3
|
+
deserialize: (e) => e
|
|
4
|
+
}, s = {
|
|
5
|
+
serialize: (e) => e !== void 0 ? String(e) : null,
|
|
6
|
+
deserialize: (e) => Number(e)
|
|
7
|
+
}, l = {
|
|
8
|
+
serialize: (e) => e.length > 0 ? e.join(",") : null,
|
|
9
|
+
deserialize: (e) => e.split(",")
|
|
10
|
+
}, n = {
|
|
11
|
+
serialize: (e) => e || null,
|
|
12
|
+
deserialize: (e) => e,
|
|
13
|
+
debounceMs: 300
|
|
14
|
+
};
|
|
15
|
+
export {
|
|
16
|
+
l as csvCodec,
|
|
17
|
+
s as numberCodec,
|
|
18
|
+
n as searchCodec,
|
|
19
|
+
i as stringCodec
|
|
20
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ParamCodec } from './types';
|
|
2
|
+
interface UseFiltersOptions<T extends Record<string, unknown>> {
|
|
3
|
+
urlSync?: {
|
|
4
|
+
[K in keyof T]?: ParamCodec<T[K]>;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export declare function useFilters<T extends Record<string, unknown>>(defaults: T, options?: UseFiltersOptions<T>): {
|
|
8
|
+
params: T;
|
|
9
|
+
debouncedParams: T;
|
|
10
|
+
setParam: <K extends keyof T>(key: K, value: T[K]) => void;
|
|
11
|
+
reset: (keys?: Array<keyof T>) => void;
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { useState as f, useRef as y } from "react";
|
|
2
|
+
function d(r, e, i) {
|
|
3
|
+
return e ? Object.fromEntries(
|
|
4
|
+
Object.keys(r).map((n) => {
|
|
5
|
+
const S = e[n], m = i.get(n), w = S && m !== null ? S.deserialize(m) : r[n];
|
|
6
|
+
return [n, w];
|
|
7
|
+
})
|
|
8
|
+
) : r;
|
|
9
|
+
}
|
|
10
|
+
function h(r, e) {
|
|
11
|
+
const i = new URLSearchParams(window.location.search);
|
|
12
|
+
e !== null ? i.set(r, e) : i.delete(r);
|
|
13
|
+
const n = i.toString(), S = n ? `${window.location.pathname}?${n}` : window.location.pathname;
|
|
14
|
+
window.history.replaceState(null, "", S);
|
|
15
|
+
}
|
|
16
|
+
function R(r, e) {
|
|
17
|
+
const [i, n] = f(
|
|
18
|
+
() => d(
|
|
19
|
+
r,
|
|
20
|
+
e == null ? void 0 : e.urlSync,
|
|
21
|
+
new URLSearchParams(window.location.search)
|
|
22
|
+
)
|
|
23
|
+
), [S, m] = f(
|
|
24
|
+
() => d(
|
|
25
|
+
r,
|
|
26
|
+
e == null ? void 0 : e.urlSync,
|
|
27
|
+
new URLSearchParams(window.location.search)
|
|
28
|
+
)
|
|
29
|
+
), w = y({});
|
|
30
|
+
function b(l, s) {
|
|
31
|
+
var a;
|
|
32
|
+
n((o) => ({ ...o, [l]: s }));
|
|
33
|
+
const u = (a = e == null ? void 0 : e.urlSync) == null ? void 0 : a[l], c = u == null ? void 0 : u.debounceMs, t = String(l);
|
|
34
|
+
c !== void 0 ? (clearTimeout(w.current[t]), w.current[t] = setTimeout(() => {
|
|
35
|
+
m((o) => ({ ...o, [l]: s }));
|
|
36
|
+
}, c)) : m((o) => ({ ...o, [l]: s })), u && h(t, u.serialize(s));
|
|
37
|
+
}
|
|
38
|
+
function P(l) {
|
|
39
|
+
const s = l ?? Object.keys(r);
|
|
40
|
+
n((c) => {
|
|
41
|
+
const t = { ...c };
|
|
42
|
+
for (const a of s) t[a] = r[a];
|
|
43
|
+
return t;
|
|
44
|
+
}), m((c) => {
|
|
45
|
+
const t = { ...c };
|
|
46
|
+
for (const a of s) {
|
|
47
|
+
const o = String(a);
|
|
48
|
+
clearTimeout(w.current[o]), delete w.current[o], t[a] = r[a];
|
|
49
|
+
}
|
|
50
|
+
return t;
|
|
51
|
+
});
|
|
52
|
+
const u = e == null ? void 0 : e.urlSync;
|
|
53
|
+
if (u)
|
|
54
|
+
for (const c of s) {
|
|
55
|
+
const t = u[c];
|
|
56
|
+
t && h(String(c), t.serialize(r[c]));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { params: i, debouncedParams: S, setParam: b, reset: P };
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
R as useFilters
|
|
63
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useState as u, useEffect as c, useCallback as f } from "react";
|
|
2
|
+
function l(e) {
|
|
3
|
+
const [t, r] = u(e);
|
|
4
|
+
c(() => {
|
|
5
|
+
if (t === 0) return;
|
|
6
|
+
const n = setInterval(() => {
|
|
7
|
+
r((o) => o - 1);
|
|
8
|
+
}, 1e3);
|
|
9
|
+
return () => clearInterval(n);
|
|
10
|
+
}, [t]);
|
|
11
|
+
const s = f(() => {
|
|
12
|
+
r(e);
|
|
13
|
+
}, [e]);
|
|
14
|
+
return { secondsLeft: t, reset: s };
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
l as useCountdown
|
|
18
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import o from "../components/loading-state/locale/en.json.js";
|
|
2
|
+
import n from "../components/notification/locale/en.json.js";
|
|
3
|
+
import t from "../components/table/locale/en.json.js";
|
|
4
|
+
import e from "../components/loading-state/locale/vi.json.js";
|
|
5
|
+
import i from "../components/notification/locale/vi.json.js";
|
|
6
|
+
import m from "../components/table/locale/vi.json.js";
|
|
7
|
+
const l = {
|
|
8
|
+
en: {
|
|
9
|
+
// --- Flat namespace keys matching folder paths (for i18n-ally) ---
|
|
10
|
+
"components/loading-state": o,
|
|
11
|
+
"components/notification": n,
|
|
12
|
+
"components/table": t
|
|
13
|
+
},
|
|
14
|
+
vi: {
|
|
15
|
+
// --- Flat namespace keys matching folder paths (for i18n-ally) ---
|
|
16
|
+
"components/loading-state": e,
|
|
17
|
+
"components/notification": i,
|
|
18
|
+
"components/table": m
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
export {
|
|
22
|
+
l as resources
|
|
23
|
+
};
|