@jbpark/ui-kit 10.0.2 → 10.2.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/README.ko.md +7 -0
- package/README.md +7 -0
- package/dist/Alert.d.mts +24 -0
- package/dist/Alert.d.mts.map +1 -0
- package/dist/Alert.mjs +68 -0
- package/dist/Alert.mjs.map +1 -0
- package/dist/Avatar.d.mts +19 -0
- package/dist/Avatar.d.mts.map +1 -0
- package/dist/Avatar.mjs +43 -0
- package/dist/Avatar.mjs.map +1 -0
- package/dist/Badge.d.mts +23 -0
- package/dist/Badge.d.mts.map +1 -0
- package/dist/Badge.mjs +41 -0
- package/dist/Badge.mjs.map +1 -0
- package/dist/Breadcrumb.d.mts +39 -0
- package/dist/Breadcrumb.d.mts.map +1 -0
- package/dist/Breadcrumb.mjs +103 -0
- package/dist/Breadcrumb.mjs.map +1 -0
- package/dist/Button.mjs +1 -1
- package/dist/Pagination.d.mts +53 -0
- package/dist/Pagination.d.mts.map +1 -0
- package/dist/Pagination.mjs +208 -0
- package/dist/Pagination.mjs.map +1 -0
- package/dist/Segmented.d.mts +26 -0
- package/dist/Segmented.d.mts.map +1 -0
- package/dist/Segmented.mjs +57 -0
- package/dist/Segmented.mjs.map +1 -0
- package/dist/Steps.d.mts +28 -0
- package/dist/Steps.d.mts.map +1 -0
- package/dist/Steps.mjs +70 -0
- package/dist/Steps.mjs.map +1 -0
- package/dist/Table.d.mts +48 -0
- package/dist/Table.d.mts.map +1 -0
- package/dist/Table.mjs +119 -0
- package/dist/Table.mjs.map +1 -0
- package/dist/components/atoms/checkbox/checkbox.mjs +3 -2
- package/dist/components/atoms/checkbox/checkbox.mjs.map +1 -1
- package/dist/components/atoms/checkbox/group.mjs +2 -1
- package/dist/components/atoms/checkbox/group.mjs.map +1 -1
- package/dist/components/atoms/color-picker.mjs +1 -1
- package/dist/components/atoms/date-picker.mjs +2 -2
- package/dist/components/atoms/float-button/back-top.mjs +2 -2
- package/dist/components/atoms/index.d.mts +6 -1
- package/dist/components/atoms/input/index.d.mts +3 -1
- package/dist/components/atoms/input/index.d.mts.map +1 -1
- package/dist/components/atoms/input/index.mjs +3 -1
- package/dist/components/atoms/input/index.mjs.map +1 -1
- package/dist/components/atoms/input/number.d.mts +23 -0
- package/dist/components/atoms/input/number.d.mts.map +1 -0
- package/dist/components/atoms/input/number.mjs +71 -0
- package/dist/components/atoms/input/number.mjs.map +1 -0
- package/dist/components/atoms/input/search.d.mts +0 -5
- package/dist/components/atoms/input/search.d.mts.map +1 -1
- package/dist/components/atoms/input/search.mjs +8 -8
- package/dist/components/atoms/input/search.mjs.map +1 -1
- package/dist/components/atoms/popover.mjs +1 -1
- package/dist/components/atoms/progress.d.mts +3 -1
- package/dist/components/atoms/progress.d.mts.map +1 -1
- package/dist/components/atoms/progress.mjs +2 -2
- package/dist/components/atoms/progress.mjs.map +1 -1
- package/dist/components/atoms/radio/group.mjs +1 -1
- package/dist/components/atoms/radio/radio.mjs +3 -2
- package/dist/components/atoms/radio/radio.mjs.map +1 -1
- package/dist/components/atoms/rich-text-editor/rich-text-editor.d.mts +6 -1
- package/dist/components/atoms/rich-text-editor/rich-text-editor.d.mts.map +1 -1
- package/dist/components/atoms/rich-text-editor/rich-text-editor.mjs +7 -2
- package/dist/components/atoms/rich-text-editor/rich-text-editor.mjs.map +1 -1
- package/dist/components/atoms/rich-text-editor/toolbar-presets.mjs +1 -1
- package/dist/components/atoms/select-multiple.d.mts +29 -0
- package/dist/components/atoms/select-multiple.d.mts.map +1 -0
- package/dist/components/atoms/select-multiple.mjs +97 -0
- package/dist/components/atoms/select-multiple.mjs.map +1 -0
- package/dist/components/atoms/select-searchable-options.d.mts +21 -0
- package/dist/components/atoms/select-searchable-options.d.mts.map +1 -0
- package/dist/components/atoms/select-searchable-options.mjs +62 -0
- package/dist/components/atoms/select-searchable-options.mjs.map +1 -0
- package/dist/components/atoms/select-searchable.d.mts +22 -0
- package/dist/components/atoms/select-searchable.d.mts.map +1 -0
- package/dist/components/atoms/select-searchable.mjs +65 -0
- package/dist/components/atoms/select-searchable.mjs.map +1 -0
- package/dist/components/atoms/select.d.mts +8 -2
- package/dist/components/atoms/select.d.mts.map +1 -1
- package/dist/components/atoms/select.mjs +12 -2
- package/dist/components/atoms/select.mjs.map +1 -1
- package/dist/components/atoms/skeleton/skeleton.d.mts +3 -1
- package/dist/components/atoms/skeleton/skeleton.d.mts.map +1 -1
- package/dist/components/atoms/skeleton/skeleton.mjs +2 -2
- package/dist/components/atoms/skeleton/skeleton.mjs.map +1 -1
- package/dist/components/atoms/slider/slider.mjs +1 -1
- package/dist/components/atoms/switch.mjs +1 -1
- package/dist/components/atoms/tooltip.d.mts +21 -0
- package/dist/components/atoms/tooltip.d.mts.map +1 -0
- package/dist/components/atoms/tooltip.mjs +78 -0
- package/dist/components/atoms/tooltip.mjs.map +1 -0
- package/dist/components/atoms/typography/paragraph.mjs +1 -0
- package/dist/components/atoms/typography/paragraph.mjs.map +1 -1
- package/dist/components/atoms/typography/title.mjs +1 -0
- package/dist/components/atoms/typography/title.mjs.map +1 -1
- package/dist/components/molecules/collapse.d.mts +8 -8
- package/dist/components/molecules/collapse.d.mts.map +1 -1
- package/dist/components/molecules/collapse.mjs +11 -2
- package/dist/components/molecules/collapse.mjs.map +1 -1
- package/dist/components/molecules/dropdown.mjs +1 -1
- package/dist/components/molecules/index.d.mts +15 -10
- package/dist/components/molecules/marquees/marquees.mjs +1 -1
- package/dist/components/molecules/menu/item/item.mjs +1 -1
- package/dist/components/molecules/menu/menu.d.mts +1 -1
- package/dist/components/molecules/menu/menu.d.mts.map +1 -1
- package/dist/components/molecules/menu/menu.mjs +5 -2
- package/dist/components/molecules/menu/menu.mjs.map +1 -1
- package/dist/components/molecules/tabs.d.mts +41 -0
- package/dist/components/molecules/tabs.d.mts.map +1 -0
- package/dist/components/molecules/tabs.mjs +55 -0
- package/dist/components/molecules/tabs.mjs.map +1 -0
- package/dist/components/molecules/upload.mjs +3 -2
- package/dist/components/molecules/upload.mjs.map +1 -1
- package/dist/components/organisms/drawer.d.mts +1 -1
- package/dist/components/organisms/drawer.d.mts.map +1 -1
- package/dist/components/organisms/drawer.mjs +10 -4
- package/dist/components/organisms/drawer.mjs.map +1 -1
- package/dist/components/organisms/index.d.mts +6 -5
- package/dist/components/organisms/list/list.mjs +1 -1
- package/dist/components/organisms/modal.d.mts.map +1 -1
- package/dist/components/organisms/modal.mjs +8 -5
- package/dist/components/organisms/modal.mjs.map +1 -1
- package/dist/components/organisms/toast.d.mts.map +1 -1
- package/dist/components/organisms/toast.mjs +3 -2
- package/dist/components/organisms/toast.mjs.map +1 -1
- package/dist/components/templates/empty.mjs +1 -0
- package/dist/components/templates/empty.mjs.map +1 -1
- package/dist/components/templates/layout/content.mjs +1 -0
- package/dist/components/templates/layout/content.mjs.map +1 -1
- package/dist/components/templates/layout/footer.mjs +1 -0
- package/dist/components/templates/layout/footer.mjs.map +1 -1
- package/dist/components/templates/layout/header.mjs +1 -0
- package/dist/components/templates/layout/header.mjs.map +1 -1
- package/dist/components/templates/layout/layout.mjs +1 -0
- package/dist/components/templates/layout/layout.mjs.map +1 -1
- package/dist/components/templates/layout/sider.mjs +4 -2
- package/dist/components/templates/layout/sider.mjs.map +1 -1
- package/dist/components/templates/page-header.mjs +1 -0
- package/dist/components/templates/page-header.mjs.map +1 -1
- package/dist/components/templates/result.mjs +1 -0
- package/dist/components/templates/result.mjs.map +1 -1
- package/dist/core/accordion.mjs +1 -1
- package/dist/core/button.d.mts +1 -1
- package/dist/core/calendar.mjs +1 -1
- package/dist/core/checkbox.mjs +1 -1
- package/dist/core/combobox.d.mts +7 -0
- package/dist/core/combobox.d.mts.map +1 -0
- package/dist/core/combobox.mjs +99 -0
- package/dist/core/combobox.mjs.map +1 -0
- package/dist/core/dialog.mjs +1 -1
- package/dist/core/dialog.mjs.map +1 -1
- package/dist/core/drawer.mjs.map +1 -1
- package/dist/core/field.mjs +2 -4
- package/dist/core/field.mjs.map +1 -1
- package/dist/core/index.d.mts +4 -1
- package/dist/core/radio-group.mjs +1 -1
- package/dist/core/select.mjs +28 -23
- package/dist/core/select.mjs.map +1 -1
- package/dist/core/tabs.d.mts +9 -0
- package/dist/core/tabs.d.mts.map +1 -0
- package/dist/core/tabs.mjs +59 -0
- package/dist/core/tabs.mjs.map +1 -0
- package/dist/core/tooltip.d.mts +2 -0
- package/dist/core/tooltip.mjs +41 -0
- package/dist/core/tooltip.mjs.map +1 -0
- package/dist/index.d.mts +40 -29
- package/dist/index.mjs +12 -2
- package/dist/lib/z-layers.mjs +21 -0
- package/dist/lib/z-layers.mjs.map +1 -1
- package/dist/providers/config/dark-mode.mjs +2 -10
- package/dist/providers/config/dark-mode.mjs.map +1 -1
- package/dist/style.css +388 -16
- package/package.json +42 -2
package/README.ko.md
CHANGED
|
@@ -145,6 +145,13 @@ function App() {
|
|
|
145
145
|
해당 요소에 `isolation: isolate`를 적용해 Base UI 포털이 앱 내부의 z-index와
|
|
146
146
|
경쟁하지 않고 페이지 콘텐츠 위에 표시되도록 합니다.
|
|
147
147
|
|
|
148
|
+
반대 방향으로도 효과가 있습니다. 오버레이(Modal, Drawer, Select, Popover)와
|
|
149
|
+
페이지 흐름 안에 고정되는 요소(sticky/fixed `Layout.Header`, `FloatButton`,
|
|
150
|
+
Dropdown 메뉴)는 모두 `z-index: 1000`을 씁니다. 루트를 격리하지 않으면 이
|
|
151
|
+
요소들이 z-index가 더 낮은 앱 자체의 다이얼로그(예: shadcn의 `z-50`)를 덮습니다.
|
|
152
|
+
`data-ui-root`를 지정하면 `body`로 포털되는 앱의 오버레이가 이 요소들을 포함한
|
|
153
|
+
앱 전체를 덮습니다.
|
|
154
|
+
|
|
148
155
|
### 개별 컴포넌트 import
|
|
149
156
|
|
|
150
157
|
```tsx
|
package/README.md
CHANGED
|
@@ -145,6 +145,13 @@ Put `data-ui-root` on your application layout root. The included stylesheet
|
|
|
145
145
|
applies `isolation: isolate` there so Base UI portals render above page content
|
|
146
146
|
without competing with z-index values inside the app.
|
|
147
147
|
|
|
148
|
+
It also works in the other direction. Overlays (Modal, Drawer, Select,
|
|
149
|
+
Popover) and in-flow chrome (sticky/fixed `Layout.Header`, `FloatButton`,
|
|
150
|
+
Dropdown menus) share `z-index: 1000`. Without an isolated root, that
|
|
151
|
+
chrome paints over your own dialogs if they use a lower z-index (for example
|
|
152
|
+
shadcn's `z-50`). With `data-ui-root`, any overlay you portal to `body`
|
|
153
|
+
covers the whole app, including this chrome.
|
|
154
|
+
|
|
148
155
|
### Import Individual Components
|
|
149
156
|
|
|
150
157
|
```tsx
|
package/dist/Alert.d.mts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/components/molecules/alert.d.ts
|
|
2
|
+
type Status = 'info' | 'success' | 'warning' | 'error';
|
|
3
|
+
interface Props extends Omit<React.ComponentPropsWithRef<'div'>, 'title'> {
|
|
4
|
+
status?: Status;
|
|
5
|
+
variant?: 'outlined' | 'filled';
|
|
6
|
+
title: React.ReactNode;
|
|
7
|
+
description?: React.ReactNode;
|
|
8
|
+
/** Pass `null` to hide the status icon. */
|
|
9
|
+
icon?: React.ReactNode;
|
|
10
|
+
action?: React.ReactNode;
|
|
11
|
+
closable?: boolean;
|
|
12
|
+
onClose?: () => void;
|
|
13
|
+
classNames?: {
|
|
14
|
+
icon?: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
action?: string;
|
|
18
|
+
close?: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
declare const Alert: ({ status, variant, title, description, icon, action, closable, onClose, className, classNames, role, ...props }: Props) => import("react").JSX.Element | null;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { Props, Alert as default };
|
|
24
|
+
//# sourceMappingURL=Alert.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.d.mts","names":[],"sources":["../src/components/molecules/alert.tsx"],"mappings":";KAWK;UAEY,cAAc,KAC7B,MAAM;EAGN,SAAS;EACT;EACA,OAAO,MAAM;EACb,cAAc,MAAM;;EAEpB,OAAO,MAAM;EACb,SAAS,MAAM;EACf;EACA;EACA;IACE;IACA;IACA;IACA;IACA;;;cAWE,UAAS,QAAA,SAAA,OAAA,aAAA,MAAA,QAAA,UAAA,SAAA,WAAA,YAAA,SAAA,SAaZ,0BAAK,IAAA"}
|
package/dist/Alert.mjs
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "./utils.mjs";
|
|
3
|
+
import { DEFAULT_LOCALE, useConfig } from "./providers/config/context.mjs";
|
|
4
|
+
import Button from "./Button.mjs";
|
|
5
|
+
import { Check, Info, OctagonAlert, OctagonX, X } from "lucide-react";
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/molecules/alert.tsx
|
|
9
|
+
const STATUS_ICONS = {
|
|
10
|
+
info: /* @__PURE__ */ jsx(Info, {}),
|
|
11
|
+
success: /* @__PURE__ */ jsx(Check, {}),
|
|
12
|
+
warning: /* @__PURE__ */ jsx(OctagonAlert, {}),
|
|
13
|
+
error: /* @__PURE__ */ jsx(OctagonX, {})
|
|
14
|
+
};
|
|
15
|
+
const Alert = ({ status = "info", variant = "outlined", title, description, icon, action, closable = false, onClose, className, classNames, role = "status", ...props }) => {
|
|
16
|
+
const { locale } = useConfig();
|
|
17
|
+
const [visible, setVisible] = useState(true);
|
|
18
|
+
const renderedIcon = icon === void 0 ? STATUS_ICONS[status] : icon;
|
|
19
|
+
if (!visible) return null;
|
|
20
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
21
|
+
...props,
|
|
22
|
+
"data-slot": "alert",
|
|
23
|
+
"data-status": status,
|
|
24
|
+
"data-variant": variant,
|
|
25
|
+
role,
|
|
26
|
+
className: cn("flex w-full items-start gap-3 rounded-lg border p-4", className),
|
|
27
|
+
children: [
|
|
28
|
+
renderedIcon && /* @__PURE__ */ jsx("span", {
|
|
29
|
+
"aria-hidden": "true",
|
|
30
|
+
className: cn("mt-0.5 shrink-0 [&_svg]:size-5", classNames?.icon),
|
|
31
|
+
children: renderedIcon
|
|
32
|
+
}),
|
|
33
|
+
/* @__PURE__ */ jsxs("div", {
|
|
34
|
+
className: "min-w-0 flex-1",
|
|
35
|
+
children: [
|
|
36
|
+
/* @__PURE__ */ jsx("div", {
|
|
37
|
+
className: cn("text-sm font-semibold", classNames?.title),
|
|
38
|
+
children: title
|
|
39
|
+
}),
|
|
40
|
+
description && /* @__PURE__ */ jsx("div", {
|
|
41
|
+
className: cn("text-muted-foreground mt-1 text-sm", classNames?.description),
|
|
42
|
+
children: description
|
|
43
|
+
}),
|
|
44
|
+
action && /* @__PURE__ */ jsx("div", {
|
|
45
|
+
className: cn("mt-3", classNames?.action),
|
|
46
|
+
children: action
|
|
47
|
+
})
|
|
48
|
+
]
|
|
49
|
+
}),
|
|
50
|
+
closable && /* @__PURE__ */ jsx(Button, {
|
|
51
|
+
variant: "text",
|
|
52
|
+
shape: "circle",
|
|
53
|
+
size: "small",
|
|
54
|
+
"aria-label": locale.close ?? DEFAULT_LOCALE.close,
|
|
55
|
+
icon: /* @__PURE__ */ jsx(X, {}),
|
|
56
|
+
className: classNames?.close,
|
|
57
|
+
onClick: () => {
|
|
58
|
+
onClose?.();
|
|
59
|
+
setVisible(false);
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
]
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
//#endregion
|
|
66
|
+
export { Alert as default };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=Alert.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.mjs","names":[],"sources":["../src/components/molecules/alert.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\n\nimport { Check, Info, OctagonAlert, OctagonX, X } from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\ntype Status = 'info' | 'success' | 'warning' | 'error';\n\nexport interface Props extends Omit<\n React.ComponentPropsWithRef<'div'>,\n 'title'\n> {\n status?: Status;\n variant?: 'outlined' | 'filled';\n title: React.ReactNode;\n description?: React.ReactNode;\n /** Pass `null` to hide the status icon. */\n icon?: React.ReactNode;\n action?: React.ReactNode;\n closable?: boolean;\n onClose?: () => void;\n classNames?: {\n icon?: string;\n title?: string;\n description?: string;\n action?: string;\n close?: string;\n };\n}\n\nconst STATUS_ICONS: Record<Status, React.ReactNode> = {\n info: <Info />,\n success: <Check />,\n warning: <OctagonAlert />,\n error: <OctagonX />,\n};\n\nconst Alert = ({\n status = 'info',\n variant = 'outlined',\n title,\n description,\n icon,\n action,\n closable = false,\n onClose,\n className,\n classNames,\n role = 'status',\n ...props\n}: Props) => {\n const { locale } = useConfig();\n const [visible, setVisible] = useState(true);\n const renderedIcon = icon === undefined ? STATUS_ICONS[status] : icon;\n\n if (!visible) {\n return null;\n }\n\n return (\n <div\n {...props}\n data-slot=\"alert\"\n data-status={status}\n data-variant={variant}\n role={role}\n className={cn(\n 'flex w-full items-start gap-3 rounded-lg border p-4',\n className,\n //\n )}\n >\n {renderedIcon && (\n <span\n aria-hidden=\"true\"\n className={cn(\n 'mt-0.5 shrink-0 [&_svg]:size-5',\n classNames?.icon,\n //\n )}\n >\n {renderedIcon}\n </span>\n )}\n <div className=\"min-w-0 flex-1\">\n <div\n className={cn(\n 'text-sm font-semibold',\n classNames?.title,\n //\n )}\n >\n {title}\n </div>\n {description && (\n <div\n className={cn(\n 'text-muted-foreground mt-1 text-sm',\n classNames?.description,\n //\n )}\n >\n {description}\n </div>\n )}\n {action && (\n <div\n className={cn(\n 'mt-3',\n classNames?.action,\n //\n )}\n >\n {action}\n </div>\n )}\n </div>\n {closable && (\n <Button\n variant=\"text\"\n shape=\"circle\"\n size=\"small\"\n aria-label={locale.close ?? DEFAULT_LOCALE.close}\n icon={<X />}\n className={classNames?.close}\n onClick={() => {\n onClose?.();\n setVisible(false);\n }}\n />\n )}\n </div>\n );\n};\n\nexport default Alert;\n"],"mappings":";;;;;;;;AAmCA,MAAM,eAAgD;CACpD,MAAM,oBAAC,MAAD,CAAO,CAAA;CACb,SAAS,oBAAC,OAAD,CAAQ,CAAA;CACjB,SAAS,oBAAC,cAAD,CAAe,CAAA;CACxB,OAAO,oBAAC,UAAD,CAAW,CAAA;AACpB;AAEA,MAAM,SAAS,EACb,SAAS,QACT,UAAU,YACV,OACA,aACA,MACA,QACA,WAAW,OACX,SACA,WACA,YACA,OAAO,UACP,GAAG,YACQ;CACX,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,CAAC,SAAS,cAAc,SAAS,IAAI;CAC3C,MAAM,eAAe,SAAS,KAAA,IAAY,aAAa,UAAU;CAEjE,IAAI,CAAC,SACH,OAAO;CAGT,OACE,qBAAC,OAAD;EACE,GAAI;EACJ,aAAU;EACV,eAAa;EACb,gBAAc;EACR;EACN,WAAW,GACT,uDACA,SAEF;EAVF,UAAA;GAYG,gBACC,oBAAC,QAAD;IACE,eAAY;IACZ,WAAW,GACT,kCACA,YAAY,IAEd;IAEC,UAAA;GACG,CAAA;GAER,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,oBAAC,OAAD;MACE,WAAW,GACT,yBACA,YAAY,KAEd;MAEC,UAAA;KACE,CAAA;KACJ,eACC,oBAAC,OAAD;MACE,WAAW,GACT,sCACA,YAAY,WAEd;MAEC,UAAA;KACE,CAAA;KAEN,UACC,oBAAC,OAAD;MACE,WAAW,GACT,QACA,YAAY,MAEd;MAEC,UAAA;KACE,CAAA;IAEJ;;GACJ,YACC,oBAAC,QAAD;IACE,SAAQ;IACR,OAAM;IACN,MAAK;IACL,cAAY,OAAO,SAAS,eAAe;IAC3C,MAAM,oBAAC,GAAD,CAAI,CAAA;IACV,WAAW,YAAY;IACvB,eAAe;KACb,UAAU;KACV,WAAW,KAAK;IAClB;GACD,CAAA;EAEA;;AAET"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ComponentSize } from "./providers/config/types.mjs";
|
|
2
|
+
//#region src/components/atoms/avatar.d.ts
|
|
3
|
+
interface Props extends Omit<React.ComponentPropsWithoutRef<'span'>, 'children'> {
|
|
4
|
+
src?: string;
|
|
5
|
+
/** A person's name or image description. Use an empty string for a decorative avatar. */
|
|
6
|
+
alt: string;
|
|
7
|
+
/** Initials, an icon, or other content shown until the image loads or if it fails. */
|
|
8
|
+
fallback?: React.ReactNode;
|
|
9
|
+
size?: ComponentSize;
|
|
10
|
+
loading?: 'eager' | 'lazy';
|
|
11
|
+
classNames?: {
|
|
12
|
+
image?: string;
|
|
13
|
+
fallback?: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
declare const Avatar: ({ src, alt, fallback, size, loading, className, classNames, ...props }: Props) => import("react").JSX.Element;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { Props, Avatar as default };
|
|
19
|
+
//# sourceMappingURL=Avatar.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Avatar.d.mts","names":[],"sources":["../src/components/atoms/avatar.tsx"],"mappings":";;UAciB,cAAc,KAC7B,MAAM;EAGN;;EAEA;;EAEA,WAAW,MAAM;EACjB,OAAO;EACP;EACA;IACE;IACA;;;cAIE,WAAU,KAAA,KAAA,UAAA,MAAA,SAAA,WAAA,eAAA,SASb,0BAAK,IAAA"}
|
package/dist/Avatar.mjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "./utils.mjs";
|
|
3
|
+
import { useConfig } from "./providers/config/context.mjs";
|
|
4
|
+
import { Avatar as Avatar$1 } from "@base-ui/react/avatar";
|
|
5
|
+
import { UserRound } from "lucide-react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/atoms/avatar.tsx
|
|
8
|
+
const sizes = {
|
|
9
|
+
small: "size-8 text-xs",
|
|
10
|
+
middle: "size-10 text-sm",
|
|
11
|
+
large: "size-12 text-base"
|
|
12
|
+
};
|
|
13
|
+
const Avatar = ({ src, alt, fallback, size, loading, className, classNames, ...props }) => {
|
|
14
|
+
const { componentSize } = useConfig();
|
|
15
|
+
const resolvedSize = size ?? componentSize ?? "middle";
|
|
16
|
+
return /* @__PURE__ */ jsxs(Avatar$1.Root, {
|
|
17
|
+
"data-slot": "avatar",
|
|
18
|
+
role: alt ? "img" : void 0,
|
|
19
|
+
"aria-label": alt || void 0,
|
|
20
|
+
"aria-hidden": alt ? void 0 : true,
|
|
21
|
+
className: cn(`bg-muted text-muted-foreground relative inline-flex shrink-0
|
|
22
|
+
overflow-hidden rounded-full`, sizes[resolvedSize], className),
|
|
23
|
+
...props,
|
|
24
|
+
children: [/* @__PURE__ */ jsx(Avatar$1.Fallback, {
|
|
25
|
+
className: cn("absolute inset-0 flex items-center justify-center font-medium", classNames?.fallback),
|
|
26
|
+
children: fallback ?? /* @__PURE__ */ jsx(UserRound, {
|
|
27
|
+
"aria-hidden": "true",
|
|
28
|
+
className: "size-1/2"
|
|
29
|
+
})
|
|
30
|
+
}), src && /* @__PURE__ */ jsx(Avatar$1.Image, {
|
|
31
|
+
src,
|
|
32
|
+
alt: "",
|
|
33
|
+
loading,
|
|
34
|
+
keepMounted: true,
|
|
35
|
+
className: cn(`absolute inset-0 size-full object-cover data-error:invisible
|
|
36
|
+
data-loading:invisible`, classNames?.image)
|
|
37
|
+
})]
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
//#endregion
|
|
41
|
+
export { Avatar as default };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=Avatar.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Avatar.mjs","names":["BaseAvatar"],"sources":["../src/components/atoms/avatar.tsx"],"sourcesContent":["'use client';\n\nimport { Avatar as BaseAvatar } from '@base-ui/react/avatar';\nimport { UserRound } from 'lucide-react';\n\nimport { type ComponentSize, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nconst sizes: Record<ComponentSize, string> = {\n small: 'size-8 text-xs',\n middle: 'size-10 text-sm',\n large: 'size-12 text-base',\n};\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'span'>,\n 'children'\n> {\n src?: string;\n /** A person's name or image description. Use an empty string for a decorative avatar. */\n alt: string;\n /** Initials, an icon, or other content shown until the image loads or if it fails. */\n fallback?: React.ReactNode;\n size?: ComponentSize;\n loading?: 'eager' | 'lazy';\n classNames?: {\n image?: string;\n fallback?: string;\n };\n}\n\nconst Avatar = ({\n src,\n alt,\n fallback,\n size,\n loading,\n className,\n classNames,\n ...props\n}: Props) => {\n const { componentSize } = useConfig();\n const resolvedSize = size ?? componentSize ?? 'middle';\n\n return (\n <BaseAvatar.Root\n data-slot=\"avatar\"\n role={alt ? 'img' : undefined}\n aria-label={alt || undefined}\n aria-hidden={alt ? undefined : true}\n className={cn(\n `bg-muted text-muted-foreground relative inline-flex shrink-0\n overflow-hidden rounded-full`,\n sizes[resolvedSize],\n className,\n //\n )}\n {...props}\n >\n <BaseAvatar.Fallback\n className={cn(\n 'absolute inset-0 flex items-center justify-center font-medium',\n classNames?.fallback,\n //\n )}\n >\n {fallback ?? <UserRound aria-hidden=\"true\" className=\"size-1/2\" />}\n </BaseAvatar.Fallback>\n {src && (\n <BaseAvatar.Image\n src={src}\n alt=\"\"\n loading={loading}\n keepMounted\n className={cn(\n `absolute inset-0 size-full object-cover data-error:invisible\n data-loading:invisible`,\n classNames?.image,\n //\n )}\n />\n )}\n </BaseAvatar.Root>\n );\n};\n\nexport default Avatar;\n"],"mappings":";;;;;;;AAQA,MAAM,QAAuC;CAC3C,OAAO;CACP,QAAQ;CACR,OAAO;AACT;AAmBA,MAAM,UAAU,EACd,KACA,KACA,UACA,MACA,SACA,WACA,YACA,GAAG,YACQ;CACX,MAAM,EAAE,kBAAkB,UAAU;CACpC,MAAM,eAAe,QAAQ,iBAAiB;CAE9C,OACE,qBAACA,SAAW,MAAZ;EACE,aAAU;EACV,MAAM,MAAM,QAAQ,KAAA;EACpB,cAAY,OAAO,KAAA;EACnB,eAAa,MAAM,KAAA,IAAY;EAC/B,WAAW,GACT;uCAEA,MAAM,eACN,SAEF;EACA,GAAI;EAZN,UAAA,CAcE,oBAACA,SAAW,UAAZ;GACE,WAAW,GACT,iEACA,YAAY,QAEd;GAEC,UAAA,YAAY,oBAAC,WAAD;IAAW,eAAY;IAAO,WAAU;GAAY,CAAA;EAC9C,CAAA,GACpB,OACC,oBAACA,SAAW,OAAZ;GACO;GACL,KAAI;GACK;GACT,aAAA;GACA,WAAW,GACT;qCAEA,YAAY,KAEd;EACD,CAAA,CAEY;;AAErB"}
|
package/dist/Badge.d.mts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/components/atoms/badge.d.ts
|
|
2
|
+
type BadgeColor = 'primary' | 'success' | 'warning' | 'danger';
|
|
3
|
+
interface Props extends Omit<React.ComponentPropsWithoutRef<'span'>, 'color'> {
|
|
4
|
+
/** Number shown in the indicator. Zero is hidden unless `showZero` is true. */
|
|
5
|
+
count?: number;
|
|
6
|
+
/** Show a small status dot instead of the count. */
|
|
7
|
+
dot?: boolean;
|
|
8
|
+
/** Highest number shown before displaying `maxCount+`. */
|
|
9
|
+
maxCount?: number;
|
|
10
|
+
showZero?: boolean;
|
|
11
|
+
color?: BadgeColor;
|
|
12
|
+
/** Pixel inset from the wrapped element's top and inline end edges. */
|
|
13
|
+
offset?: readonly [number, number];
|
|
14
|
+
/** Accessible name for the indicator, especially useful for a status dot. */
|
|
15
|
+
indicatorLabel?: string;
|
|
16
|
+
classNames?: {
|
|
17
|
+
indicator?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
declare const Badge: ({ count, dot, maxCount, showZero, color, offset, indicatorLabel, className, classNames, children, ...props }: Props) => import("react").JSX.Element | null;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { Props, Badge as default };
|
|
23
|
+
//# sourceMappingURL=Badge.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Badge.d.mts","names":[],"sources":["../src/components/atoms/badge.tsx"],"mappings":";KAEK;UASY,cAAc,KAC7B,MAAM;;EAIN;;EAEA;;EAEA;EACA;EACA,QAAQ;;EAER;;EAEA;EACA;IACE;;;cAIE,UAAS,OAAA,KAAA,UAAA,UAAA,OAAA,QAAA,gBAAA,WAAA,YAAA,aAAA,SAYZ,0BAAK,IAAA"}
|
package/dist/Badge.mjs
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { cn } from "./utils.mjs";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/atoms/badge.tsx
|
|
4
|
+
const colors = {
|
|
5
|
+
primary: "bg-primary text-primary-foreground",
|
|
6
|
+
success: "bg-green-600 text-white dark:bg-green-500",
|
|
7
|
+
warning: "bg-yellow-500 text-black",
|
|
8
|
+
danger: "bg-destructive text-white"
|
|
9
|
+
};
|
|
10
|
+
const Badge = ({ count, dot = false, maxCount = 99, showZero = false, color = "danger", offset, indicatorLabel, className, classNames, children, ...props }) => {
|
|
11
|
+
const hasChildren = children != null;
|
|
12
|
+
const visible = dot || count != null && (count !== 0 || showZero);
|
|
13
|
+
const displayCount = count != null && count > maxCount ? `${maxCount}+` : count;
|
|
14
|
+
if (!visible && !hasChildren) return null;
|
|
15
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
16
|
+
...props,
|
|
17
|
+
"data-slot": "badge",
|
|
18
|
+
className: cn("relative inline-flex w-fit align-middle", className),
|
|
19
|
+
children: [children, visible && /* @__PURE__ */ jsx("span", {
|
|
20
|
+
"data-slot": "badge-indicator",
|
|
21
|
+
"data-color": color,
|
|
22
|
+
"data-dot": dot || void 0,
|
|
23
|
+
role: indicatorLabel ? "img" : void 0,
|
|
24
|
+
"aria-label": indicatorLabel,
|
|
25
|
+
"aria-hidden": dot && !indicatorLabel ? true : void 0,
|
|
26
|
+
className: cn(`pointer-events-none z-10 inline-flex shrink-0 items-center
|
|
27
|
+
justify-center rounded-full font-medium whitespace-nowrap
|
|
28
|
+
tabular-nums`, dot ? "size-2" : "min-h-5 min-w-5 px-1 text-xs", hasChildren && `absolute end-0 top-0 translate-x-1/2 -translate-y-1/2
|
|
29
|
+
rtl:-translate-x-1/2`, colors[color], classNames?.indicator),
|
|
30
|
+
style: hasChildren ? {
|
|
31
|
+
top: offset?.[1] ?? 0,
|
|
32
|
+
insetInlineEnd: offset?.[0] ?? 0
|
|
33
|
+
} : void 0,
|
|
34
|
+
children: !dot && displayCount
|
|
35
|
+
})]
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { Badge as default };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=Badge.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Badge.mjs","names":[],"sources":["../src/components/atoms/badge.tsx"],"sourcesContent":["import { cn } from '@repo/ui/utils';\n\ntype BadgeColor = 'primary' | 'success' | 'warning' | 'danger';\n\nconst colors: Record<BadgeColor, string> = {\n primary: 'bg-primary text-primary-foreground',\n success: 'bg-green-600 text-white dark:bg-green-500',\n warning: 'bg-yellow-500 text-black',\n danger: 'bg-destructive text-white',\n};\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'span'>,\n 'color'\n> {\n /** Number shown in the indicator. Zero is hidden unless `showZero` is true. */\n count?: number;\n /** Show a small status dot instead of the count. */\n dot?: boolean;\n /** Highest number shown before displaying `maxCount+`. */\n maxCount?: number;\n showZero?: boolean;\n color?: BadgeColor;\n /** Pixel inset from the wrapped element's top and inline end edges. */\n offset?: readonly [number, number];\n /** Accessible name for the indicator, especially useful for a status dot. */\n indicatorLabel?: string;\n classNames?: {\n indicator?: string;\n };\n}\n\nconst Badge = ({\n count,\n dot = false,\n maxCount = 99,\n showZero = false,\n color = 'danger',\n offset,\n indicatorLabel,\n className,\n classNames,\n children,\n ...props\n}: Props) => {\n const hasChildren = children != null;\n const visible = dot || (count != null && (count !== 0 || showZero));\n const displayCount =\n count != null && count > maxCount ? `${maxCount}+` : count;\n\n if (!visible && !hasChildren) {\n return null;\n }\n\n return (\n <span\n {...props}\n data-slot=\"badge\"\n className={cn('relative inline-flex w-fit align-middle', className)}\n >\n {children}\n {visible && (\n <span\n data-slot=\"badge-indicator\"\n data-color={color}\n data-dot={dot || undefined}\n role={indicatorLabel ? 'img' : undefined}\n aria-label={indicatorLabel}\n aria-hidden={dot && !indicatorLabel ? true : undefined}\n className={cn(\n `pointer-events-none z-10 inline-flex shrink-0 items-center\n justify-center rounded-full font-medium whitespace-nowrap\n tabular-nums`,\n dot ? 'size-2' : 'min-h-5 min-w-5 px-1 text-xs',\n hasChildren &&\n `absolute end-0 top-0 translate-x-1/2 -translate-y-1/2\n rtl:-translate-x-1/2`,\n colors[color],\n classNames?.indicator,\n //\n )}\n style={\n hasChildren\n ? { top: offset?.[1] ?? 0, insetInlineEnd: offset?.[0] ?? 0 }\n : undefined\n }\n >\n {!dot && displayCount}\n </span>\n )}\n </span>\n );\n};\n\nexport default Badge;\n"],"mappings":";;;AAIA,MAAM,SAAqC;CACzC,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ;AACV;AAuBA,MAAM,SAAS,EACb,OACA,MAAM,OACN,WAAW,IACX,WAAW,OACX,QAAQ,UACR,QACA,gBACA,WACA,YACA,UACA,GAAG,YACQ;CACX,MAAM,cAAc,YAAY;CAChC,MAAM,UAAU,OAAQ,SAAS,SAAS,UAAU,KAAK;CACzD,MAAM,eACJ,SAAS,QAAQ,QAAQ,WAAW,GAAG,SAAS,KAAK;CAEvD,IAAI,CAAC,WAAW,CAAC,aACf,OAAO;CAGT,OACE,qBAAC,QAAD;EACE,GAAI;EACJ,aAAU;EACV,WAAW,GAAG,2CAA2C,SAAS;EAHpE,UAAA,CAKG,UACA,WACC,oBAAC,QAAD;GACE,aAAU;GACV,cAAY;GACZ,YAAU,OAAO,KAAA;GACjB,MAAM,iBAAiB,QAAQ,KAAA;GAC/B,cAAY;GACZ,eAAa,OAAO,CAAC,iBAAiB,OAAO,KAAA;GAC7C,WAAW,GACT;;2BAGA,MAAM,WAAW,gCACjB,eACE;qCAEF,OAAO,QACP,YAAY,SAEd;GACA,OACE,cACI;IAAE,KAAK,SAAS,MAAM;IAAG,gBAAgB,SAAS,MAAM;GAAE,IAC1D,KAAA;GAGL,UAAA,CAAC,OAAO;EACL,CAAA,CAEJ;;AAEV"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//#region src/components/molecules/breadcrumb.d.ts
|
|
2
|
+
interface Item {
|
|
3
|
+
key?: React.Key;
|
|
4
|
+
title: React.ReactNode;
|
|
5
|
+
href?: string;
|
|
6
|
+
target?: React.HTMLAttributeAnchorTarget;
|
|
7
|
+
rel?: string;
|
|
8
|
+
onClick?: React.MouseEventHandler<HTMLElement>;
|
|
9
|
+
className?: string;
|
|
10
|
+
'aria-label'?: string;
|
|
11
|
+
/** Decorative icon placed before the title. */
|
|
12
|
+
icon?: React.ReactNode;
|
|
13
|
+
/** Overrides the separator after this item. */
|
|
14
|
+
separator?: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
interface Props extends Omit<React.ComponentPropsWithoutRef<'nav'>, 'children'> {
|
|
17
|
+
items: Item[];
|
|
18
|
+
separator?: React.ReactNode;
|
|
19
|
+
/** Collapse middle items when the trail has more than this many entries. */
|
|
20
|
+
maxItems?: number;
|
|
21
|
+
itemsBeforeCollapse?: number;
|
|
22
|
+
itemsAfterCollapse?: number;
|
|
23
|
+
expandText?: string;
|
|
24
|
+
/** Render custom router links. The renderer owns aria-current for the last item. */
|
|
25
|
+
itemRender?: (item: Item, index: number, isCurrent: boolean) => React.ReactNode;
|
|
26
|
+
classNames?: {
|
|
27
|
+
list?: string;
|
|
28
|
+
item?: string;
|
|
29
|
+
link?: string;
|
|
30
|
+
current?: string;
|
|
31
|
+
separator?: string;
|
|
32
|
+
collapsed?: string;
|
|
33
|
+
popup?: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
declare const Breadcrumb: ({ items, separator, maxItems, itemsBeforeCollapse, itemsAfterCollapse, expandText, itemRender, className, classNames, dir, "aria-label": ariaLabel, ...props }: Props) => import("react").JSX.Element;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { Item, Props, Breadcrumb as default };
|
|
39
|
+
//# sourceMappingURL=Breadcrumb.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Breadcrumb.d.mts","names":[],"sources":["../src/components/molecules/breadcrumb.tsx"],"mappings":";UAUiB;EACf,MAAM,MAAM;EACZ,OAAO,MAAM;EACb;EACA,SAAS,MAAM;EACf;EACA,UAAU,MAAM,kBAAkB;EAClC;EACA;;EAEA,OAAO,MAAM;;EAEb,YAAY,MAAM;;UAGH,cAAc,KAC7B,MAAM;EAGN,OAAO;EACP,YAAY,MAAM;;EAElB;EACA;EACA;EACA;;EAEA,cACE,MAAM,MACN,eACA,uBACG,MAAM;EACX;IACE;IACA;IACA;IACA;IACA;IACA;IACA;;;cAOE,eAAc,OAAA,WAAA,UAAA,qBAAA,oBAAA,YAAA,YAAA,WAAA,YAAA,mBAAA,cAAA,SAajB,0BAAK,IAAA"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "./utils.mjs";
|
|
3
|
+
import { useConfig } from "./providers/config/context.mjs";
|
|
4
|
+
import Button from "./Button.mjs";
|
|
5
|
+
import Popover from "./components/atoms/popover.mjs";
|
|
6
|
+
import { Fragment } from "react";
|
|
7
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/molecules/breadcrumb.tsx
|
|
9
|
+
const safeCount = (value, minimum) => Number.isFinite(value) ? Math.max(minimum, Math.floor(value)) : minimum;
|
|
10
|
+
const Breadcrumb = ({ items, separator = "/", maxItems = 8, itemsBeforeCollapse = 1, itemsAfterCollapse = 1, expandText = "Show path", itemRender, className, classNames, dir, "aria-label": ariaLabel, ...props }) => {
|
|
11
|
+
const { direction } = useConfig();
|
|
12
|
+
const limit = safeCount(maxItems, 3);
|
|
13
|
+
const before = Math.min(safeCount(itemsBeforeCollapse, 1), limit - 2);
|
|
14
|
+
const after = Math.min(safeCount(itemsAfterCollapse, 1), limit - before - 1);
|
|
15
|
+
const collapsed = items.length > limit && items.length - before - after > 0;
|
|
16
|
+
const visibleIndices = collapsed ? [...Array.from({ length: before }, (_, index) => index), ...Array.from({ length: after }, (_, index) => items.length - after + index)] : items.map((_, index) => index);
|
|
17
|
+
const hiddenIndices = collapsed ? Array.from({ length: items.length - before - after }, (_, index) => before + index) : [];
|
|
18
|
+
const renderItem = (index) => {
|
|
19
|
+
const item = items[index];
|
|
20
|
+
const isCurrent = index === items.length - 1;
|
|
21
|
+
if (itemRender) return itemRender(item, index, isCurrent);
|
|
22
|
+
const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [item.icon != null && /* @__PURE__ */ jsx("span", {
|
|
23
|
+
"data-slot": "breadcrumb-icon",
|
|
24
|
+
"aria-hidden": "true",
|
|
25
|
+
className: "inline-flex shrink-0",
|
|
26
|
+
children: item.icon
|
|
27
|
+
}), item.title] });
|
|
28
|
+
const itemClassName = cn("inline-flex items-center gap-1.5 rounded-sm", (item.href !== void 0 || item.onClick) && "hover:text-foreground focus-visible:outline-ring focus-visible:outline-2", isCurrent ? "text-foreground font-medium" : "text-muted-foreground", (item.href !== void 0 || item.onClick) && classNames?.link, isCurrent && classNames?.current, item.className);
|
|
29
|
+
if (item.href !== void 0) return /* @__PURE__ */ jsx("a", {
|
|
30
|
+
href: item.href,
|
|
31
|
+
target: item.target,
|
|
32
|
+
rel: item.rel,
|
|
33
|
+
onClick: item.onClick,
|
|
34
|
+
"aria-label": item["aria-label"],
|
|
35
|
+
"aria-current": isCurrent ? "page" : void 0,
|
|
36
|
+
className: itemClassName,
|
|
37
|
+
children: content
|
|
38
|
+
});
|
|
39
|
+
if (item.onClick) return /* @__PURE__ */ jsx(Button, {
|
|
40
|
+
variant: "text",
|
|
41
|
+
size: "small",
|
|
42
|
+
onClick: item.onClick,
|
|
43
|
+
"aria-label": item["aria-label"],
|
|
44
|
+
"aria-current": isCurrent ? "page" : void 0,
|
|
45
|
+
className: cn("h-auto px-0 py-0 font-normal", itemClassName),
|
|
46
|
+
children: content
|
|
47
|
+
});
|
|
48
|
+
return /* @__PURE__ */ jsx("span", {
|
|
49
|
+
"aria-label": item["aria-label"],
|
|
50
|
+
"aria-current": isCurrent ? "page" : void 0,
|
|
51
|
+
className: itemClassName,
|
|
52
|
+
children: content
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
const renderSeparator = (index) => /* @__PURE__ */ jsx("li", {
|
|
56
|
+
"data-slot": "breadcrumb-separator",
|
|
57
|
+
"aria-hidden": "true",
|
|
58
|
+
className: cn("text-muted-foreground mx-2 shrink-0", classNames?.separator),
|
|
59
|
+
children: items[index]?.separator ?? separator
|
|
60
|
+
});
|
|
61
|
+
return /* @__PURE__ */ jsx("nav", {
|
|
62
|
+
...props,
|
|
63
|
+
"data-slot": "breadcrumb",
|
|
64
|
+
dir: dir ?? direction,
|
|
65
|
+
"aria-label": ariaLabel ?? "Breadcrumb",
|
|
66
|
+
className: cn("text-sm", className),
|
|
67
|
+
children: /* @__PURE__ */ jsx("ol", {
|
|
68
|
+
"data-slot": "breadcrumb-list",
|
|
69
|
+
className: cn("m-0 flex min-w-0 flex-wrap items-center p-0", classNames?.list),
|
|
70
|
+
children: visibleIndices.map((index, position) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
71
|
+
position > 0 && renderSeparator(collapsed && position === before ? index - 1 : visibleIndices[position - 1]),
|
|
72
|
+
/* @__PURE__ */ jsx("li", {
|
|
73
|
+
"data-slot": "breadcrumb-item",
|
|
74
|
+
className: cn("inline-flex min-w-0 items-center", classNames?.item),
|
|
75
|
+
children: renderItem(index)
|
|
76
|
+
}),
|
|
77
|
+
collapsed && position === before - 1 && /* @__PURE__ */ jsxs(Fragment$1, { children: [renderSeparator(index), /* @__PURE__ */ jsx("li", {
|
|
78
|
+
"data-slot": "breadcrumb-collapsed",
|
|
79
|
+
className: classNames?.collapsed,
|
|
80
|
+
children: /* @__PURE__ */ jsx(Popover, {
|
|
81
|
+
placement: "bottom",
|
|
82
|
+
className: classNames?.popup,
|
|
83
|
+
content: /* @__PURE__ */ jsx("ol", {
|
|
84
|
+
className: "m-0 grid list-none gap-1 p-0",
|
|
85
|
+
children: hiddenIndices.map((hiddenIndex) => /* @__PURE__ */ jsx("li", { children: renderItem(hiddenIndex) }, items[hiddenIndex]?.key ?? hiddenIndex))
|
|
86
|
+
}),
|
|
87
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
88
|
+
variant: "text",
|
|
89
|
+
size: "small",
|
|
90
|
+
"aria-label": expandText,
|
|
91
|
+
className: "h-auto px-1",
|
|
92
|
+
children: "…"
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
})] })
|
|
96
|
+
] }, items[index]?.key ?? index))
|
|
97
|
+
})
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
//#endregion
|
|
101
|
+
export { Breadcrumb as default };
|
|
102
|
+
|
|
103
|
+
//# sourceMappingURL=Breadcrumb.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Breadcrumb.mjs","names":[],"sources":["../src/components/molecules/breadcrumb.tsx"],"sourcesContent":["'use client';\n\nimport { Fragment } from 'react';\n\nimport { useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\nimport Popover from '../atoms/popover';\n\nexport interface Item {\n key?: React.Key;\n title: React.ReactNode;\n href?: string;\n target?: React.HTMLAttributeAnchorTarget;\n rel?: string;\n onClick?: React.MouseEventHandler<HTMLElement>;\n className?: string;\n 'aria-label'?: string;\n /** Decorative icon placed before the title. */\n icon?: React.ReactNode;\n /** Overrides the separator after this item. */\n separator?: React.ReactNode;\n}\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'nav'>,\n 'children'\n> {\n items: Item[];\n separator?: React.ReactNode;\n /** Collapse middle items when the trail has more than this many entries. */\n maxItems?: number;\n itemsBeforeCollapse?: number;\n itemsAfterCollapse?: number;\n expandText?: string;\n /** Render custom router links. The renderer owns aria-current for the last item. */\n itemRender?: (\n item: Item,\n index: number,\n isCurrent: boolean,\n ) => React.ReactNode;\n classNames?: {\n list?: string;\n item?: string;\n link?: string;\n current?: string;\n separator?: string;\n collapsed?: string;\n popup?: string;\n };\n}\n\nconst safeCount = (value: number, minimum: number) =>\n Number.isFinite(value) ? Math.max(minimum, Math.floor(value)) : minimum;\n\nconst Breadcrumb = ({\n items,\n separator = '/',\n maxItems = 8,\n itemsBeforeCollapse = 1,\n itemsAfterCollapse = 1,\n expandText = 'Show path',\n itemRender,\n className,\n classNames,\n dir,\n 'aria-label': ariaLabel,\n ...props\n}: Props) => {\n const { direction } = useConfig();\n const limit = safeCount(maxItems, 3);\n const before = Math.min(safeCount(itemsBeforeCollapse, 1), limit - 2);\n const after = Math.min(safeCount(itemsAfterCollapse, 1), limit - before - 1);\n const collapsed = items.length > limit && items.length - before - after > 0;\n const visibleIndices = collapsed\n ? [\n ...Array.from({ length: before }, (_, index) => index),\n ...Array.from(\n { length: after },\n (_, index) => items.length - after + index,\n ),\n ]\n : items.map((_, index) => index);\n const hiddenIndices = collapsed\n ? Array.from(\n { length: items.length - before - after },\n (_, index) => before + index,\n )\n : [];\n\n const renderItem = (index: number) => {\n const item = items[index]!;\n const isCurrent = index === items.length - 1;\n\n if (itemRender) {\n return itemRender(item, index, isCurrent);\n }\n\n const content = (\n <>\n {item.icon != null && (\n <span\n data-slot=\"breadcrumb-icon\"\n aria-hidden=\"true\"\n className=\"inline-flex shrink-0\"\n >\n {item.icon}\n </span>\n )}\n {item.title}\n </>\n );\n const itemClassName = cn(\n 'inline-flex items-center gap-1.5 rounded-sm',\n (item.href !== undefined || item.onClick) &&\n 'hover:text-foreground focus-visible:outline-ring focus-visible:outline-2',\n isCurrent ? 'text-foreground font-medium' : 'text-muted-foreground',\n (item.href !== undefined || item.onClick) && classNames?.link,\n isCurrent && classNames?.current,\n item.className,\n //\n );\n\n if (item.href !== undefined) {\n return (\n <a\n href={item.href}\n target={item.target}\n rel={item.rel}\n onClick={item.onClick}\n aria-label={item['aria-label']}\n aria-current={isCurrent ? 'page' : undefined}\n className={itemClassName}\n >\n {content}\n </a>\n );\n }\n\n if (item.onClick) {\n return (\n <Button\n variant=\"text\"\n size=\"small\"\n onClick={item.onClick}\n aria-label={item['aria-label']}\n aria-current={isCurrent ? 'page' : undefined}\n className={cn('h-auto px-0 py-0 font-normal', itemClassName)}\n >\n {content}\n </Button>\n );\n }\n\n return (\n <span\n aria-label={item['aria-label']}\n aria-current={isCurrent ? 'page' : undefined}\n className={itemClassName}\n >\n {content}\n </span>\n );\n };\n\n const renderSeparator = (index: number) => (\n <li\n data-slot=\"breadcrumb-separator\"\n aria-hidden=\"true\"\n className={cn(\n 'text-muted-foreground mx-2 shrink-0',\n classNames?.separator,\n //\n )}\n >\n {items[index]?.separator ?? separator}\n </li>\n );\n\n return (\n <nav\n {...props}\n data-slot=\"breadcrumb\"\n dir={dir ?? direction}\n aria-label={ariaLabel ?? 'Breadcrumb'}\n className={cn(\n 'text-sm',\n className, //\n )}\n >\n <ol\n data-slot=\"breadcrumb-list\"\n className={cn(\n 'm-0 flex min-w-0 flex-wrap items-center p-0',\n classNames?.list,\n //\n )}\n >\n {visibleIndices.map((index, position) => (\n <Fragment key={items[index]?.key ?? index}>\n {position > 0 &&\n renderSeparator(\n collapsed && position === before\n ? index - 1\n : visibleIndices[position - 1]!,\n )}\n <li\n data-slot=\"breadcrumb-item\"\n className={cn(\n 'inline-flex min-w-0 items-center',\n classNames?.item, //\n )}\n >\n {renderItem(index)}\n </li>\n {collapsed && position === before - 1 && (\n <>\n {renderSeparator(index)}\n <li\n data-slot=\"breadcrumb-collapsed\"\n className={classNames?.collapsed}\n >\n <Popover\n placement=\"bottom\"\n className={classNames?.popup}\n content={\n <ol className=\"m-0 grid list-none gap-1 p-0\">\n {hiddenIndices.map(hiddenIndex => (\n <li key={items[hiddenIndex]?.key ?? hiddenIndex}>\n {renderItem(hiddenIndex)}\n </li>\n ))}\n </ol>\n }\n >\n <Button\n variant=\"text\"\n size=\"small\"\n aria-label={expandText}\n className=\"h-auto px-1\"\n >\n …\n </Button>\n </Popover>\n </li>\n </>\n )}\n </Fragment>\n ))}\n </ol>\n </nav>\n );\n};\n\nexport default Breadcrumb;\n"],"mappings":"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"}
|
package/dist/Button.mjs
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { cn } from "./utils.mjs";
|
|
3
3
|
import { useConfig } from "./providers/config/context.mjs";
|
|
4
4
|
import { Button as Button$1 } from "./core/button.mjs";
|
|
5
|
-
import "react";
|
|
6
5
|
import { LoaderCircle } from "lucide-react";
|
|
6
|
+
import "react";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
//#region src/components/atoms/button.tsx
|
|
9
9
|
const Core = Button$1;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/components/molecules/pagination.d.ts
|
|
2
|
+
interface Props extends Omit<React.ComponentPropsWithoutRef<'nav'>, 'children' | 'onChange'> {
|
|
3
|
+
/** Total number of items, not pages. */
|
|
4
|
+
total: number;
|
|
5
|
+
/** Controlled number of items per page. */
|
|
6
|
+
pageSize?: number;
|
|
7
|
+
defaultPageSize?: number;
|
|
8
|
+
onPageSizeChange?: (pageSize: number) => void;
|
|
9
|
+
pageSizeOptions?: number[];
|
|
10
|
+
showSizeChanger?: boolean;
|
|
11
|
+
/** Render the total and the 1-based inclusive range of visible items. */
|
|
12
|
+
showTotal?: (total: number, range: [number, number]) => React.ReactNode;
|
|
13
|
+
showQuickJumper?: boolean;
|
|
14
|
+
/** 1-based controlled page. */
|
|
15
|
+
page?: number;
|
|
16
|
+
defaultPage?: number;
|
|
17
|
+
onChange?: (page: number) => void;
|
|
18
|
+
siblingCount?: number;
|
|
19
|
+
boundaryCount?: number;
|
|
20
|
+
showFirstLast?: boolean;
|
|
21
|
+
hideOnSinglePage?: boolean;
|
|
22
|
+
/** Render available page controls as links to these URLs. */
|
|
23
|
+
getPageHref?: (page: number) => string;
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
size?: 'small' | 'middle' | 'large';
|
|
26
|
+
labels?: {
|
|
27
|
+
navigation?: string;
|
|
28
|
+
page?: (page: number) => string;
|
|
29
|
+
previous?: string;
|
|
30
|
+
next?: string;
|
|
31
|
+
first?: string;
|
|
32
|
+
last?: string;
|
|
33
|
+
pageSize?: string;
|
|
34
|
+
jump?: string;
|
|
35
|
+
go?: string;
|
|
36
|
+
};
|
|
37
|
+
classNames?: {
|
|
38
|
+
item?: string;
|
|
39
|
+
active?: string;
|
|
40
|
+
previous?: string;
|
|
41
|
+
next?: string;
|
|
42
|
+
first?: string;
|
|
43
|
+
last?: string;
|
|
44
|
+
ellipsis?: string;
|
|
45
|
+
total?: string;
|
|
46
|
+
sizeChanger?: string;
|
|
47
|
+
jumper?: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
declare const Pagination: ({ total, pageSize, defaultPageSize, onPageSizeChange, pageSizeOptions, showSizeChanger, showTotal, showQuickJumper, page, defaultPage, onChange, siblingCount, boundaryCount, showFirstLast, hideOnSinglePage, getPageHref, disabled, size, labels, className, classNames, "aria-label": ariaLabel, ...props }: Props) => import("react").JSX.Element | null;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { Props, Pagination as default };
|
|
53
|
+
//# sourceMappingURL=Pagination.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pagination.d.mts","names":[],"sources":["../src/components/molecules/pagination.tsx"],"mappings":";UAoBiB,cAAc,KAC7B,MAAM;;EAIN;;EAEA;EACA;EACA,oBAAoB;EACpB;EACA;;EAEA,aAAa,eAAe,4BAA4B,MAAM;EAC9D;;EAEA;EACA;EACA,YAAY;EACZ;EACA;EACA;EACA;;EAEA,eAAe;EACf;EACA;EACA;IACE;IACA,QAAQ;IACR;IACA;IACA;IACA;IACA;IACA;IACA;;EAEF;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;cAkEE,eAAc,OAAA,UAAA,iBAAA,kBAAA,iBAAA,iBAAA,WAAA,iBAAA,MAAA,aAAA,UAAA,cAAA,eAAA,eAAA,kBAAA,aAAA,UAAA,MAAA,QAAA,WAAA,0BAAA,cAAA,SAwBjB,0BAAK,IAAA"}
|