@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.
Files changed (176) hide show
  1. package/README.ko.md +7 -0
  2. package/README.md +7 -0
  3. package/dist/Alert.d.mts +24 -0
  4. package/dist/Alert.d.mts.map +1 -0
  5. package/dist/Alert.mjs +68 -0
  6. package/dist/Alert.mjs.map +1 -0
  7. package/dist/Avatar.d.mts +19 -0
  8. package/dist/Avatar.d.mts.map +1 -0
  9. package/dist/Avatar.mjs +43 -0
  10. package/dist/Avatar.mjs.map +1 -0
  11. package/dist/Badge.d.mts +23 -0
  12. package/dist/Badge.d.mts.map +1 -0
  13. package/dist/Badge.mjs +41 -0
  14. package/dist/Badge.mjs.map +1 -0
  15. package/dist/Breadcrumb.d.mts +39 -0
  16. package/dist/Breadcrumb.d.mts.map +1 -0
  17. package/dist/Breadcrumb.mjs +103 -0
  18. package/dist/Breadcrumb.mjs.map +1 -0
  19. package/dist/Button.mjs +1 -1
  20. package/dist/Pagination.d.mts +53 -0
  21. package/dist/Pagination.d.mts.map +1 -0
  22. package/dist/Pagination.mjs +208 -0
  23. package/dist/Pagination.mjs.map +1 -0
  24. package/dist/Segmented.d.mts +26 -0
  25. package/dist/Segmented.d.mts.map +1 -0
  26. package/dist/Segmented.mjs +57 -0
  27. package/dist/Segmented.mjs.map +1 -0
  28. package/dist/Steps.d.mts +28 -0
  29. package/dist/Steps.d.mts.map +1 -0
  30. package/dist/Steps.mjs +70 -0
  31. package/dist/Steps.mjs.map +1 -0
  32. package/dist/Table.d.mts +48 -0
  33. package/dist/Table.d.mts.map +1 -0
  34. package/dist/Table.mjs +119 -0
  35. package/dist/Table.mjs.map +1 -0
  36. package/dist/components/atoms/checkbox/checkbox.mjs +3 -2
  37. package/dist/components/atoms/checkbox/checkbox.mjs.map +1 -1
  38. package/dist/components/atoms/checkbox/group.mjs +2 -1
  39. package/dist/components/atoms/checkbox/group.mjs.map +1 -1
  40. package/dist/components/atoms/color-picker.mjs +1 -1
  41. package/dist/components/atoms/date-picker.mjs +2 -2
  42. package/dist/components/atoms/float-button/back-top.mjs +2 -2
  43. package/dist/components/atoms/index.d.mts +6 -1
  44. package/dist/components/atoms/input/index.d.mts +3 -1
  45. package/dist/components/atoms/input/index.d.mts.map +1 -1
  46. package/dist/components/atoms/input/index.mjs +3 -1
  47. package/dist/components/atoms/input/index.mjs.map +1 -1
  48. package/dist/components/atoms/input/number.d.mts +23 -0
  49. package/dist/components/atoms/input/number.d.mts.map +1 -0
  50. package/dist/components/atoms/input/number.mjs +71 -0
  51. package/dist/components/atoms/input/number.mjs.map +1 -0
  52. package/dist/components/atoms/input/search.d.mts +0 -5
  53. package/dist/components/atoms/input/search.d.mts.map +1 -1
  54. package/dist/components/atoms/input/search.mjs +8 -8
  55. package/dist/components/atoms/input/search.mjs.map +1 -1
  56. package/dist/components/atoms/popover.mjs +1 -1
  57. package/dist/components/atoms/progress.d.mts +3 -1
  58. package/dist/components/atoms/progress.d.mts.map +1 -1
  59. package/dist/components/atoms/progress.mjs +2 -2
  60. package/dist/components/atoms/progress.mjs.map +1 -1
  61. package/dist/components/atoms/radio/group.mjs +1 -1
  62. package/dist/components/atoms/radio/radio.mjs +3 -2
  63. package/dist/components/atoms/radio/radio.mjs.map +1 -1
  64. package/dist/components/atoms/rich-text-editor/rich-text-editor.d.mts +6 -1
  65. package/dist/components/atoms/rich-text-editor/rich-text-editor.d.mts.map +1 -1
  66. package/dist/components/atoms/rich-text-editor/rich-text-editor.mjs +7 -2
  67. package/dist/components/atoms/rich-text-editor/rich-text-editor.mjs.map +1 -1
  68. package/dist/components/atoms/rich-text-editor/toolbar-presets.mjs +1 -1
  69. package/dist/components/atoms/select-multiple.d.mts +29 -0
  70. package/dist/components/atoms/select-multiple.d.mts.map +1 -0
  71. package/dist/components/atoms/select-multiple.mjs +97 -0
  72. package/dist/components/atoms/select-multiple.mjs.map +1 -0
  73. package/dist/components/atoms/select-searchable-options.d.mts +21 -0
  74. package/dist/components/atoms/select-searchable-options.d.mts.map +1 -0
  75. package/dist/components/atoms/select-searchable-options.mjs +62 -0
  76. package/dist/components/atoms/select-searchable-options.mjs.map +1 -0
  77. package/dist/components/atoms/select-searchable.d.mts +22 -0
  78. package/dist/components/atoms/select-searchable.d.mts.map +1 -0
  79. package/dist/components/atoms/select-searchable.mjs +65 -0
  80. package/dist/components/atoms/select-searchable.mjs.map +1 -0
  81. package/dist/components/atoms/select.d.mts +8 -2
  82. package/dist/components/atoms/select.d.mts.map +1 -1
  83. package/dist/components/atoms/select.mjs +12 -2
  84. package/dist/components/atoms/select.mjs.map +1 -1
  85. package/dist/components/atoms/skeleton/skeleton.d.mts +3 -1
  86. package/dist/components/atoms/skeleton/skeleton.d.mts.map +1 -1
  87. package/dist/components/atoms/skeleton/skeleton.mjs +2 -2
  88. package/dist/components/atoms/skeleton/skeleton.mjs.map +1 -1
  89. package/dist/components/atoms/slider/slider.mjs +1 -1
  90. package/dist/components/atoms/switch.mjs +1 -1
  91. package/dist/components/atoms/tooltip.d.mts +21 -0
  92. package/dist/components/atoms/tooltip.d.mts.map +1 -0
  93. package/dist/components/atoms/tooltip.mjs +78 -0
  94. package/dist/components/atoms/tooltip.mjs.map +1 -0
  95. package/dist/components/atoms/typography/paragraph.mjs +1 -0
  96. package/dist/components/atoms/typography/paragraph.mjs.map +1 -1
  97. package/dist/components/atoms/typography/title.mjs +1 -0
  98. package/dist/components/atoms/typography/title.mjs.map +1 -1
  99. package/dist/components/molecules/collapse.d.mts +8 -8
  100. package/dist/components/molecules/collapse.d.mts.map +1 -1
  101. package/dist/components/molecules/collapse.mjs +11 -2
  102. package/dist/components/molecules/collapse.mjs.map +1 -1
  103. package/dist/components/molecules/dropdown.mjs +1 -1
  104. package/dist/components/molecules/index.d.mts +15 -10
  105. package/dist/components/molecules/marquees/marquees.mjs +1 -1
  106. package/dist/components/molecules/menu/item/item.mjs +1 -1
  107. package/dist/components/molecules/menu/menu.d.mts +1 -1
  108. package/dist/components/molecules/menu/menu.d.mts.map +1 -1
  109. package/dist/components/molecules/menu/menu.mjs +5 -2
  110. package/dist/components/molecules/menu/menu.mjs.map +1 -1
  111. package/dist/components/molecules/tabs.d.mts +41 -0
  112. package/dist/components/molecules/tabs.d.mts.map +1 -0
  113. package/dist/components/molecules/tabs.mjs +55 -0
  114. package/dist/components/molecules/tabs.mjs.map +1 -0
  115. package/dist/components/molecules/upload.mjs +3 -2
  116. package/dist/components/molecules/upload.mjs.map +1 -1
  117. package/dist/components/organisms/drawer.d.mts +1 -1
  118. package/dist/components/organisms/drawer.d.mts.map +1 -1
  119. package/dist/components/organisms/drawer.mjs +10 -4
  120. package/dist/components/organisms/drawer.mjs.map +1 -1
  121. package/dist/components/organisms/index.d.mts +6 -5
  122. package/dist/components/organisms/list/list.mjs +1 -1
  123. package/dist/components/organisms/modal.d.mts.map +1 -1
  124. package/dist/components/organisms/modal.mjs +8 -5
  125. package/dist/components/organisms/modal.mjs.map +1 -1
  126. package/dist/components/organisms/toast.d.mts.map +1 -1
  127. package/dist/components/organisms/toast.mjs +3 -2
  128. package/dist/components/organisms/toast.mjs.map +1 -1
  129. package/dist/components/templates/empty.mjs +1 -0
  130. package/dist/components/templates/empty.mjs.map +1 -1
  131. package/dist/components/templates/layout/content.mjs +1 -0
  132. package/dist/components/templates/layout/content.mjs.map +1 -1
  133. package/dist/components/templates/layout/footer.mjs +1 -0
  134. package/dist/components/templates/layout/footer.mjs.map +1 -1
  135. package/dist/components/templates/layout/header.mjs +1 -0
  136. package/dist/components/templates/layout/header.mjs.map +1 -1
  137. package/dist/components/templates/layout/layout.mjs +1 -0
  138. package/dist/components/templates/layout/layout.mjs.map +1 -1
  139. package/dist/components/templates/layout/sider.mjs +4 -2
  140. package/dist/components/templates/layout/sider.mjs.map +1 -1
  141. package/dist/components/templates/page-header.mjs +1 -0
  142. package/dist/components/templates/page-header.mjs.map +1 -1
  143. package/dist/components/templates/result.mjs +1 -0
  144. package/dist/components/templates/result.mjs.map +1 -1
  145. package/dist/core/accordion.mjs +1 -1
  146. package/dist/core/button.d.mts +1 -1
  147. package/dist/core/calendar.mjs +1 -1
  148. package/dist/core/checkbox.mjs +1 -1
  149. package/dist/core/combobox.d.mts +7 -0
  150. package/dist/core/combobox.d.mts.map +1 -0
  151. package/dist/core/combobox.mjs +99 -0
  152. package/dist/core/combobox.mjs.map +1 -0
  153. package/dist/core/dialog.mjs +1 -1
  154. package/dist/core/dialog.mjs.map +1 -1
  155. package/dist/core/drawer.mjs.map +1 -1
  156. package/dist/core/field.mjs +2 -4
  157. package/dist/core/field.mjs.map +1 -1
  158. package/dist/core/index.d.mts +4 -1
  159. package/dist/core/radio-group.mjs +1 -1
  160. package/dist/core/select.mjs +28 -23
  161. package/dist/core/select.mjs.map +1 -1
  162. package/dist/core/tabs.d.mts +9 -0
  163. package/dist/core/tabs.d.mts.map +1 -0
  164. package/dist/core/tabs.mjs +59 -0
  165. package/dist/core/tabs.mjs.map +1 -0
  166. package/dist/core/tooltip.d.mts +2 -0
  167. package/dist/core/tooltip.mjs +41 -0
  168. package/dist/core/tooltip.mjs.map +1 -0
  169. package/dist/index.d.mts +40 -29
  170. package/dist/index.mjs +12 -2
  171. package/dist/lib/z-layers.mjs +21 -0
  172. package/dist/lib/z-layers.mjs.map +1 -1
  173. package/dist/providers/config/dark-mode.mjs +2 -10
  174. package/dist/providers/config/dark-mode.mjs.map +1 -1
  175. package/dist/style.css +388 -16
  176. 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
@@ -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"}
@@ -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"}
@@ -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"}