@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
@@ -10,7 +10,7 @@ import { TextStyleKit } from "@tiptap/extension-text-style";
10
10
  import { EditorContent, useEditor } from "@tiptap/react";
11
11
  import StarterKit from "@tiptap/starter-kit";
12
12
  //#region src/components/atoms/rich-text-editor/rich-text-editor.tsx
13
- const RichTextEditor = ({ value = "", placeholder = "Enter text...", className, classNames, toolbar = false, toolbarItems, onChange }) => {
13
+ const RichTextEditor = ({ value = "", placeholder = "Enter text...", className, classNames, toolbar = false, toolbarItems, onUpdate, onCommit, onChange }) => {
14
14
  const presets = toolbar === true ? DEFAULT_TOOLBAR_PRESETS : toolbar || [];
15
15
  const showToolbar = presets.length > 0 || (toolbarItems?.length ?? 0) > 0;
16
16
  const editor = useEditor({
@@ -25,8 +25,13 @@ const RichTextEditor = ({ value = "", placeholder = "Enter text...", className,
25
25
  })
26
26
  ],
27
27
  content: value,
28
+ onUpdate: ({ editor: e }) => {
29
+ onUpdate?.(e.getHTML());
30
+ },
28
31
  onBlur: ({ editor: e }) => {
29
- onChange?.(e.getHTML());
32
+ const html = e.getHTML();
33
+ onCommit?.(html);
34
+ onChange?.(html);
30
35
  },
31
36
  shouldRerenderOnTransaction: showToolbar
32
37
  });
@@ -1 +1 @@
1
- {"version":3,"file":"rich-text-editor.mjs","names":[],"sources":["../../../../src/components/atoms/rich-text-editor/rich-text-editor.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\n\nimport Placeholder from '@tiptap/extension-placeholder';\nimport { TextStyleKit } from '@tiptap/extension-text-style';\nimport { EditorContent, useEditor } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { RICH_TEXT_CONTENT_CLASSES } from './content-classes';\nimport Toolbar from './toolbar';\nimport { DEFAULT_TOOLBAR_PRESETS } from './toolbar-presets';\nimport type { ToolbarItem, ToolbarPreset } from './types';\n\nexport interface Props {\n value?: string;\n placeholder?: string;\n className?: string;\n classNames?: {\n toolbar?: string;\n content?: string;\n };\n /**\n * `true` shows every built-in preset; an array shows only the listed\n * presets, in the given order. Omitted or `false` renders no toolbar,\n * matching the original (toolbar-less) output.\n */\n toolbar?: boolean | ToolbarPreset[];\n /** Extra buttons appended after the built-in presets. */\n toolbarItems?: ToolbarItem[];\n onChange?: (value: string) => void;\n}\n\nconst RichTextEditor = ({\n value = '',\n placeholder = 'Enter text...',\n className,\n classNames,\n toolbar = false,\n toolbarItems,\n onChange,\n}: Props) => {\n const presets = toolbar === true ? DEFAULT_TOOLBAR_PRESETS : toolbar || [];\n const showToolbar = presets.length > 0 || (toolbarItems?.length ?? 0) > 0;\n\n const editor = useEditor({\n // SSR renders every exported component without effects running, so the\n // editor must not touch the DOM during that first pass — deferring\n // creation to mount keeps `renderToStaticMarkup` from throwing.\n immediatelyRender: false,\n extensions: [\n StarterKit,\n Placeholder.configure({ placeholder }),\n TextStyleKit.configure({\n fontFamily: false,\n lineHeight: false,\n backgroundColor: false,\n }),\n ],\n content: value,\n onBlur: ({ editor: e }) => {\n onChange?.(e.getHTML());\n },\n // @tiptap/react v3 only re-renders on selection/transaction changes when\n // explicitly opted in — the toolbar's isActive()/getAttributes() reads\n // need that to reflect the caret position live.\n shouldRerenderOnTransaction: showToolbar,\n });\n\n useEffect(() => {\n if (!editor) {\n return;\n }\n\n const current = editor.getHTML();\n\n if (current !== value) {\n editor.commands.setContent(value, { emitUpdate: false });\n }\n }, [value, editor]);\n\n return (\n <div\n data-slot=\"rich-text-editor\"\n className={cn(\n 'border-input bg-background text-foreground rounded border text-sm',\n className,\n //\n )}\n >\n {showToolbar && editor && (\n <Toolbar\n editor={editor}\n presets={presets}\n items={toolbarItems}\n className={classNames?.toolbar}\n />\n )}\n <div\n data-slot=\"rich-text-editor-content\"\n className={cn(\n 'min-h-20 px-3 py-2',\n RICH_TEXT_CONTENT_CLASSES,\n classNames?.content,\n //\n )}\n >\n <EditorContent editor={editor} />\n </div>\n </div>\n );\n};\n\nexport default RichTextEditor;\n"],"mappings":";;;;;;;;;;;;AAmCA,MAAM,kBAAkB,EACtB,QAAQ,IACR,cAAc,iBACd,WACA,YACA,UAAU,OACV,cACA,eACW;CACX,MAAM,UAAU,YAAY,OAAO,0BAA0B,WAAW,CAAC;CACzE,MAAM,cAAc,QAAQ,SAAS,MAAM,cAAc,UAAU,KAAK;CAExE,MAAM,SAAS,UAAU;EAIvB,mBAAmB;EACnB,YAAY;GACV;GACA,YAAY,UAAU,EAAE,YAAY,CAAC;GACrC,aAAa,UAAU;IACrB,YAAY;IACZ,YAAY;IACZ,iBAAiB;GACnB,CAAC;EACH;EACA,SAAS;EACT,SAAS,EAAE,QAAQ,QAAQ;GACzB,WAAW,EAAE,QAAQ,CAAC;EACxB;EAIA,6BAA6B;CAC/B,CAAC;CAED,gBAAgB;EACd,IAAI,CAAC,QACH;EAKF,IAFgB,OAAO,QAEb,MAAM,OACd,OAAO,SAAS,WAAW,OAAO,EAAE,YAAY,MAAM,CAAC;CAE3D,GAAG,CAAC,OAAO,MAAM,CAAC;CAElB,OACE,qBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,qEACA,SAEF;EANF,UAAA,CAQG,eAAe,UACd,oBAAC,SAAD;GACU;GACC;GACT,OAAO;GACP,WAAW,YAAY;EACxB,CAAA,GAEH,oBAAC,OAAD;GACE,aAAU;GACV,WAAW,GACT,sBACA,2BACA,YAAY,OAEd;GAEA,UAAA,oBAAC,eAAD,EAAuB,OAAS,CAAA;EAC7B,CAAA,CACF;;AAET"}
1
+ {"version":3,"file":"rich-text-editor.mjs","names":[],"sources":["../../../../src/components/atoms/rich-text-editor/rich-text-editor.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\n\nimport Placeholder from '@tiptap/extension-placeholder';\nimport { TextStyleKit } from '@tiptap/extension-text-style';\nimport { EditorContent, useEditor } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { RICH_TEXT_CONTENT_CLASSES } from './content-classes';\nimport Toolbar from './toolbar';\nimport { DEFAULT_TOOLBAR_PRESETS } from './toolbar-presets';\nimport type { ToolbarItem, ToolbarPreset } from './types';\n\nexport interface Props {\n value?: string;\n placeholder?: string;\n className?: string;\n classNames?: {\n toolbar?: string;\n content?: string;\n };\n /**\n * `true` shows every built-in preset; an array shows only the listed\n * presets, in the given order. Omitted or `false` renders no toolbar,\n * matching the original (toolbar-less) output.\n */\n toolbar?: boolean | ToolbarPreset[];\n /** Extra buttons appended after the built-in presets. */\n toolbarItems?: ToolbarItem[];\n /** Called after each document edit with the current HTML. */\n onUpdate?: (value: string) => void;\n /** Called when the editor loses focus with the current HTML. */\n onCommit?: (value: string) => void;\n /** @deprecated Use `onCommit` for the existing blur-only behavior. */\n onChange?: (value: string) => void;\n}\n\nconst RichTextEditor = ({\n value = '',\n placeholder = 'Enter text...',\n className,\n classNames,\n toolbar = false,\n toolbarItems,\n onUpdate,\n onCommit,\n onChange,\n}: Props) => {\n const presets = toolbar === true ? DEFAULT_TOOLBAR_PRESETS : toolbar || [];\n const showToolbar = presets.length > 0 || (toolbarItems?.length ?? 0) > 0;\n\n const editor = useEditor({\n // SSR renders every exported component without effects running, so the\n // editor must not touch the DOM during that first pass — deferring\n // creation to mount keeps `renderToStaticMarkup` from throwing.\n immediatelyRender: false,\n extensions: [\n StarterKit,\n Placeholder.configure({ placeholder }),\n TextStyleKit.configure({\n fontFamily: false,\n lineHeight: false,\n backgroundColor: false,\n }),\n ],\n content: value,\n onUpdate: ({ editor: e }) => {\n onUpdate?.(e.getHTML());\n },\n onBlur: ({ editor: e }) => {\n const html = e.getHTML();\n\n onCommit?.(html);\n onChange?.(html);\n },\n // @tiptap/react v3 only re-renders on selection/transaction changes when\n // explicitly opted in — the toolbar's isActive()/getAttributes() reads\n // need that to reflect the caret position live.\n shouldRerenderOnTransaction: showToolbar,\n });\n\n useEffect(() => {\n if (!editor) {\n return;\n }\n\n const current = editor.getHTML();\n\n if (current !== value) {\n editor.commands.setContent(value, { emitUpdate: false });\n }\n }, [value, editor]);\n\n return (\n <div\n data-slot=\"rich-text-editor\"\n className={cn(\n 'border-input bg-background text-foreground rounded border text-sm',\n className,\n //\n )}\n >\n {showToolbar && editor && (\n <Toolbar\n editor={editor}\n presets={presets}\n items={toolbarItems}\n className={classNames?.toolbar}\n />\n )}\n <div\n data-slot=\"rich-text-editor-content\"\n className={cn(\n 'min-h-20 px-3 py-2',\n RICH_TEXT_CONTENT_CLASSES,\n classNames?.content,\n //\n )}\n >\n <EditorContent editor={editor} />\n </div>\n </div>\n );\n};\n\nexport default RichTextEditor;\n"],"mappings":";;;;;;;;;;;;AAwCA,MAAM,kBAAkB,EACtB,QAAQ,IACR,cAAc,iBACd,WACA,YACA,UAAU,OACV,cACA,UACA,UACA,eACW;CACX,MAAM,UAAU,YAAY,OAAO,0BAA0B,WAAW,CAAC;CACzE,MAAM,cAAc,QAAQ,SAAS,MAAM,cAAc,UAAU,KAAK;CAExE,MAAM,SAAS,UAAU;EAIvB,mBAAmB;EACnB,YAAY;GACV;GACA,YAAY,UAAU,EAAE,YAAY,CAAC;GACrC,aAAa,UAAU;IACrB,YAAY;IACZ,YAAY;IACZ,iBAAiB;GACnB,CAAC;EACH;EACA,SAAS;EACT,WAAW,EAAE,QAAQ,QAAQ;GAC3B,WAAW,EAAE,QAAQ,CAAC;EACxB;EACA,SAAS,EAAE,QAAQ,QAAQ;GACzB,MAAM,OAAO,EAAE,QAAQ;GAEvB,WAAW,IAAI;GACf,WAAW,IAAI;EACjB;EAIA,6BAA6B;CAC/B,CAAC;CAED,gBAAgB;EACd,IAAI,CAAC,QACH;EAKF,IAFgB,OAAO,QAEb,MAAM,OACd,OAAO,SAAS,WAAW,OAAO,EAAE,YAAY,MAAM,CAAC;CAE3D,GAAG,CAAC,OAAO,MAAM,CAAC;CAElB,OACE,qBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,qEACA,SAEF;EANF,UAAA,CAQG,eAAe,UACd,oBAAC,SAAD;GACU;GACC;GACT,OAAO;GACP,WAAW,YAAY;EACxB,CAAA,GAEH,oBAAC,OAAD;GACE,aAAU;GACV,WAAW,GACT,sBACA,2BACA,YAAY,OAEd;GAEA,UAAA,oBAAC,eAAD,EAAuB,OAAS,CAAA;EAC7B,CAAA,CACF;;AAET"}
@@ -5,8 +5,8 @@ import ColorPicker from "../color-picker.mjs";
5
5
  import Input from "../input/index.mjs";
6
6
  import ToolbarButton from "./toolbar-button.mjs";
7
7
  import Select from "../select.mjs";
8
- import { useState } from "react";
9
8
  import { Bold, Code, Code2, Italic, Link, List, ListOrdered, Minus, Quote, Redo2, Strikethrough, Underline, Undo2 } from "lucide-react";
9
+ import { useState } from "react";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
11
  //#region src/components/atoms/rich-text-editor/toolbar-presets.tsx
12
12
  const FONT_SIZE_OPTIONS = [
@@ -0,0 +1,29 @@
1
+ import { RootProps } from "../../core/combobox.mjs";
2
+ import "../../core/index.mjs";
3
+ import { ClassNames, Option, OptionGroup } from "./select-searchable-options.mjs";
4
+ import { ReactNode } from "react";
5
+ //#region src/components/atoms/select-multiple.d.ts
6
+ interface Props extends Omit<RootProps<string, Option, true>, 'children' | 'items' | 'filteredItems' | 'onValueChange' | 'itemToStringLabel' | 'itemToStringValue' | 'isItemEqualToValue'> {
7
+ searchable: true;
8
+ multiple: true;
9
+ /** Accessible name for the multi-select input. */
10
+ label: string;
11
+ options: (Option | OptionGroup)[];
12
+ placeholder?: string;
13
+ searchPlaceholder?: string;
14
+ emptyText?: ReactNode;
15
+ allowClear?: boolean;
16
+ /** Instructions announced when a selected chip receives focus. */
17
+ chipDescription?: string;
18
+ /** Instructions announced on the input when chips are selected. */
19
+ inputDescription?: (selectedCount: number) => string;
20
+ className?: string;
21
+ classNames?: ClassNames & {
22
+ chips?: string;
23
+ chip?: string;
24
+ };
25
+ onChange?: (values: string[]) => void;
26
+ }
27
+ //#endregion
28
+ export { Props };
29
+ //# sourceMappingURL=select-multiple.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-multiple.d.mts","names":[],"sources":["../../../src/components/atoms/select-multiple.tsx"],"mappings":";;;;;UAgCiB,cAAc,KAC7B,kBAA2B;EAS3B;EACA;;EAEA;EACA,UAAU,SAAS;EACnB;EACA;EACA,YAAY;EACZ;;EAEA;;EAEA,oBAAoB;EACpB;EACA,aAAa;IACX;IACA;;EAEF,YAAY"}
@@ -0,0 +1,97 @@
1
+ "use client";
2
+ import { cn } from "../../utils.mjs";
3
+ import { DEFAULT_LOCALE, useConfig } from "../../providers/config/context.mjs";
4
+ import { combobox_exports } from "../../core/combobox.mjs";
5
+ import { selectTriggerStyles } from "../../core/select.mjs";
6
+ import Button from "../../Button.mjs";
7
+ import Input from "./input/index.mjs";
8
+ import SearchableOptions, { useSelectItems } from "./select-searchable-options.mjs";
9
+ import { ChevronDownIcon, XIcon } from "lucide-react";
10
+ import { useMemo } from "react";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ //#region src/components/atoms/select-multiple.tsx
13
+ const { Combobox: Core, ComboboxChip, ComboboxChipRemove, ComboboxChips, ComboboxClear, ComboboxContent, ComboboxInput, ComboboxInputGroup, ComboboxTrigger, ComboboxValue } = combobox_exports;
14
+ const MultipleSelect = ({ label, options, placeholder = "Select options", searchPlaceholder = "Search...", emptyText = "No results found.", allowClear = true, chipDescription = "Press Backspace or Delete to remove", inputDescription = (count) => `${count} selected. From the start of the input, press Left Arrow to focus selected options`, className, classNames, onChange, onOpenChange, searchable: _searchable, multiple, ...props }) => {
15
+ const { locale } = useConfig();
16
+ const items = useSelectItems(options);
17
+ const labels = useMemo(() => {
18
+ const result = /* @__PURE__ */ new Map();
19
+ options.forEach((option) => {
20
+ if ("options" in option) option.options.forEach((item) => result.set(item.value, item.label));
21
+ else result.set(option.value, option.label);
22
+ });
23
+ return result;
24
+ }, [options]);
25
+ return /* @__PURE__ */ jsxs(Core, {
26
+ items,
27
+ multiple,
28
+ onValueChange: (values) => onChange?.(values),
29
+ onOpenChange: (open, details) => {
30
+ if (!open && details.reason === "item-press") details.cancel();
31
+ onOpenChange?.(open, details);
32
+ },
33
+ ...props,
34
+ children: [/* @__PURE__ */ jsxs(ComboboxInputGroup, {
35
+ "data-slot": "select-multiple-input-group",
36
+ className: cn(selectTriggerStyles, "h-auto min-h-9 w-full max-w-64 flex-wrap gap-1 py-1", className),
37
+ children: [
38
+ /* @__PURE__ */ jsx(ComboboxValue, { children: (values) => /* @__PURE__ */ jsxs(ComboboxChips, {
39
+ "aria-label": values.length > 0 ? `${label} selected options` : void 0,
40
+ className: cn("flex min-w-0 flex-1 flex-wrap items-center gap-1", classNames?.chips),
41
+ children: [values.map((value) => {
42
+ const name = labels.get(value) ?? value;
43
+ return /* @__PURE__ */ jsxs(ComboboxChip, {
44
+ "data-slot": "select-chip",
45
+ "aria-label": name,
46
+ "aria-description": chipDescription,
47
+ className: cn(`bg-accent text-accent-foreground flex min-w-0
48
+ items-center gap-1 rounded-sm ps-2 pe-1 text-xs
49
+ outline-none`, "focus-visible:ring-ring/50 focus-visible:ring-[3px]", classNames?.chip),
50
+ children: [/* @__PURE__ */ jsx("span", {
51
+ className: "max-w-40 truncate",
52
+ children: name
53
+ }), /* @__PURE__ */ jsx(ComboboxChipRemove, {
54
+ "data-slot": "select-chip-remove",
55
+ "aria-label": `${locale.clear ?? DEFAULT_LOCALE.clear} ${name}`,
56
+ className: "hover:bg-background/70 flex size-5 shrink-0\n items-center justify-center rounded-sm",
57
+ children: /* @__PURE__ */ jsx(XIcon, { className: "size-3" })
58
+ })]
59
+ }, value);
60
+ }), /* @__PURE__ */ jsx(ComboboxInput, { render: /* @__PURE__ */ jsx(Input, {
61
+ "aria-label": label,
62
+ "aria-description": values.length > 0 ? inputDescription(values.length) : void 0,
63
+ placeholder: values.length > 0 ? searchPlaceholder : placeholder,
64
+ className: cn(`h-6 min-w-16 flex-1 border-0 bg-transparent px-0 py-0
65
+ shadow-none focus-visible:border-0 focus-visible:ring-0`, classNames?.input)
66
+ }) })]
67
+ }) }),
68
+ allowClear && /* @__PURE__ */ jsx(ComboboxClear, {
69
+ "data-slot": "select-multiple-clear",
70
+ render: /* @__PURE__ */ jsx(Button, {
71
+ variant: "text",
72
+ size: "icon-sm",
73
+ icon: /* @__PURE__ */ jsx(XIcon, {}),
74
+ "aria-label": locale.clear ?? DEFAULT_LOCALE.clear
75
+ })
76
+ }),
77
+ /* @__PURE__ */ jsx(ComboboxTrigger, { render: /* @__PURE__ */ jsx(Button, {
78
+ variant: "text",
79
+ size: "icon-sm",
80
+ icon: /* @__PURE__ */ jsx(ChevronDownIcon, {}),
81
+ "aria-label": locale.expand ?? DEFAULT_LOCALE.expand
82
+ }) })
83
+ ]
84
+ }), /* @__PURE__ */ jsx(ComboboxContent, {
85
+ "aria-label": label,
86
+ className: classNames?.content,
87
+ children: /* @__PURE__ */ jsx(SearchableOptions, {
88
+ emptyText,
89
+ classNames
90
+ })
91
+ })]
92
+ });
93
+ };
94
+ //#endregion
95
+ export { MultipleSelect as default };
96
+
97
+ //# sourceMappingURL=select-multiple.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-multiple.mjs","names":["combobox","select.selectTriggerStyles"],"sources":["../../../src/components/atoms/select-multiple.tsx"],"sourcesContent":["'use client';\n\nimport { type ReactNode, useMemo } from 'react';\n\nimport { ChevronDownIcon, XIcon } from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { combobox, select } from '../../core';\nimport Button from './button';\nimport Input from './input';\nimport SearchableOptions, {\n type ClassNames,\n type Option,\n type OptionGroup,\n useSelectItems,\n} from './select-searchable-options';\n\nconst {\n Combobox: Core,\n ComboboxChip,\n ComboboxChipRemove,\n ComboboxChips,\n ComboboxClear,\n ComboboxContent,\n ComboboxInput,\n ComboboxInputGroup,\n ComboboxTrigger,\n ComboboxValue,\n} = combobox;\n\nexport interface Props extends Omit<\n combobox.RootProps<string, Option, true>,\n | 'children'\n | 'items'\n | 'filteredItems'\n | 'onValueChange'\n | 'itemToStringLabel'\n | 'itemToStringValue'\n | 'isItemEqualToValue'\n> {\n searchable: true;\n multiple: true;\n /** Accessible name for the multi-select input. */\n label: string;\n options: (Option | OptionGroup)[];\n placeholder?: string;\n searchPlaceholder?: string;\n emptyText?: ReactNode;\n allowClear?: boolean;\n /** Instructions announced when a selected chip receives focus. */\n chipDescription?: string;\n /** Instructions announced on the input when chips are selected. */\n inputDescription?: (selectedCount: number) => string;\n className?: string;\n classNames?: ClassNames & {\n chips?: string;\n chip?: string;\n };\n onChange?: (values: string[]) => void;\n}\n\nconst MultipleSelect = ({\n label,\n options,\n placeholder = 'Select options',\n searchPlaceholder = 'Search...',\n emptyText = 'No results found.',\n allowClear = true,\n chipDescription = 'Press Backspace or Delete to remove',\n inputDescription = count =>\n `${count} selected. From the start of the input, press Left Arrow to focus selected options`,\n className,\n classNames,\n onChange,\n onOpenChange,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Do not forward the public mode switch to Base UI.\n searchable: _searchable,\n multiple,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n const items = useSelectItems(options);\n const labels = useMemo(() => {\n const result = new Map<string, string>();\n\n options.forEach(option => {\n if ('options' in option) {\n option.options.forEach(item => result.set(item.value, item.label));\n } else {\n result.set(option.value, option.label);\n }\n });\n\n return result;\n }, [options]);\n\n return (\n <Core\n items={items}\n multiple={multiple}\n onValueChange={values => onChange?.(values)}\n onOpenChange={(open, details) => {\n if (!open && details.reason === 'item-press') {\n details.cancel();\n }\n\n onOpenChange?.(open, details);\n }}\n {...props}\n >\n <ComboboxInputGroup\n data-slot=\"select-multiple-input-group\"\n className={cn(\n select.selectTriggerStyles,\n 'h-auto min-h-9 w-full max-w-64 flex-wrap gap-1 py-1',\n className,\n )}\n >\n <ComboboxValue>\n {(values: string[]) => (\n <ComboboxChips\n aria-label={\n values.length > 0 ? `${label} selected options` : undefined\n }\n className={cn(\n 'flex min-w-0 flex-1 flex-wrap items-center gap-1',\n classNames?.chips,\n )}\n >\n {values.map(value => {\n const name = labels.get(value) ?? value;\n\n return (\n <ComboboxChip\n key={value}\n data-slot=\"select-chip\"\n aria-label={name}\n aria-description={chipDescription}\n className={cn(\n `bg-accent text-accent-foreground flex min-w-0\n items-center gap-1 rounded-sm ps-2 pe-1 text-xs\n outline-none`,\n 'focus-visible:ring-ring/50 focus-visible:ring-[3px]',\n classNames?.chip,\n )}\n >\n <span className=\"max-w-40 truncate\">{name}</span>\n <ComboboxChipRemove\n data-slot=\"select-chip-remove\"\n aria-label={`${locale.clear ?? DEFAULT_LOCALE.clear} ${name}`}\n className=\"hover:bg-background/70 flex size-5 shrink-0\n items-center justify-center rounded-sm\"\n >\n <XIcon className=\"size-3\" />\n </ComboboxChipRemove>\n </ComboboxChip>\n );\n })}\n <ComboboxInput\n render={\n <Input\n aria-label={label}\n aria-description={\n values.length > 0\n ? inputDescription(values.length)\n : undefined\n }\n placeholder={\n values.length > 0 ? searchPlaceholder : placeholder\n }\n className={cn(\n `h-6 min-w-16 flex-1 border-0 bg-transparent px-0 py-0\n shadow-none focus-visible:border-0 focus-visible:ring-0`,\n classNames?.input,\n )}\n />\n }\n />\n </ComboboxChips>\n )}\n </ComboboxValue>\n {allowClear && (\n <ComboboxClear\n data-slot=\"select-multiple-clear\"\n render={\n <Button\n variant=\"text\"\n size=\"icon-sm\"\n icon={<XIcon />}\n aria-label={locale.clear ?? DEFAULT_LOCALE.clear}\n />\n }\n />\n )}\n <ComboboxTrigger\n render={\n <Button\n variant=\"text\"\n size=\"icon-sm\"\n icon={<ChevronDownIcon />}\n aria-label={locale.expand ?? DEFAULT_LOCALE.expand}\n />\n }\n />\n </ComboboxInputGroup>\n <ComboboxContent aria-label={label} className={classNames?.content}>\n <SearchableOptions emptyText={emptyText} classNames={classNames} />\n </ComboboxContent>\n </Core>\n );\n};\n\nexport default MultipleSelect;\n"],"mappings":";;;;;;;;;;;;AAmBA,MAAM,EACJ,UAAU,MACV,cACA,oBACA,eACA,eACA,iBACA,eACA,oBACA,iBACA,kBACEA;AAiCJ,MAAM,kBAAkB,EACtB,OACA,SACA,cAAc,kBACd,oBAAoB,aACpB,YAAY,qBACZ,aAAa,MACb,kBAAkB,uCAClB,oBAAmB,UACjB,GAAG,MAAM,qFACX,WACA,YACA,UACA,cAEA,YAAY,aACZ,UACA,GAAG,YACQ;CACX,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,QAAQ,eAAe,OAAO;CACpC,MAAM,SAAS,cAAc;EAC3B,MAAM,yBAAS,IAAI,IAAoB;EAEvC,QAAQ,SAAQ,WAAU;GACxB,IAAI,aAAa,QACf,OAAO,QAAQ,SAAQ,SAAQ,OAAO,IAAI,KAAK,OAAO,KAAK,KAAK,CAAC;QAEjE,OAAO,IAAI,OAAO,OAAO,OAAO,KAAK;EAEzC,CAAC;EAED,OAAO;CACT,GAAG,CAAC,OAAO,CAAC;CAEZ,OACE,qBAAC,MAAD;EACS;EACG;EACV,gBAAe,WAAU,WAAW,MAAM;EAC1C,eAAe,MAAM,YAAY;GAC/B,IAAI,CAAC,QAAQ,QAAQ,WAAW,cAC9B,QAAQ,OAAO;GAGjB,eAAe,MAAM,OAAO;EAC9B;EACA,GAAI;EAXN,UAAA,CAaE,qBAAC,oBAAD;GACE,aAAU;GACV,WAAW,GACTC,qBACA,uDACA,SACF;GANF,UAAA;IAQE,oBAAC,eAAD,EAAA,WACI,WACA,qBAAC,eAAD;KACE,cACE,OAAO,SAAS,IAAI,GAAG,MAAM,qBAAqB,KAAA;KAEpD,WAAW,GACT,oDACA,YAAY,KACd;KAPF,UAAA,CASG,OAAO,KAAI,UAAS;MACnB,MAAM,OAAO,OAAO,IAAI,KAAK,KAAK;MAElC,OACE,qBAAC,cAAD;OAEE,aAAU;OACV,cAAY;OACZ,oBAAkB;OAClB,WAAW,GACT;;qCAGA,uDACA,YAAY,IACd;OAXF,UAAA,CAaE,oBAAC,QAAD;QAAM,WAAU;QAAqB,UAAA;OAAW,CAAA,GAChD,oBAAC,oBAAD;QACE,aAAU;QACV,cAAY,GAAG,OAAO,SAAS,eAAe,MAAM,GAAG;QACvD,WAAU;QAGV,UAAA,oBAAC,OAAD,EAAO,WAAU,SAAU,CAAA;OACT,CAAA,CACR;MArBP,GAAA,KAqBO;KAElB,CAAC,GACD,oBAAC,eAAD,EACE,QACE,oBAAC,OAAD;MACE,cAAY;MACZ,oBACE,OAAO,SAAS,IACZ,iBAAiB,OAAO,MAAM,IAC9B,KAAA;MAEN,aACE,OAAO,SAAS,IAAI,oBAAoB;MAE1C,WAAW,GACT;gFAEA,YAAY,KACd;KACD,CAAA,EAEJ,CAAA,CACY;IAEJ,CAAA,EAAA,CAAA;IACd,cACC,oBAAC,eAAD;KACE,aAAU;KACV,QACE,oBAAC,QAAD;MACE,SAAQ;MACR,MAAK;MACL,MAAM,oBAAC,OAAD,CAAQ,CAAA;MACd,cAAY,OAAO,SAAS,eAAe;KAC5C,CAAA;IAEJ,CAAA;IAEH,oBAAC,iBAAD,EACE,QACE,oBAAC,QAAD;KACE,SAAQ;KACR,MAAK;KACL,MAAM,oBAAC,iBAAD,CAAkB,CAAA;KACxB,cAAY,OAAO,UAAU,eAAe;IAC7C,CAAA,EAEJ,CAAA;GACiB;EACpB,CAAA,GAAA,oBAAC,iBAAD;GAAiB,cAAY;GAAO,WAAW,YAAY;GACzD,UAAA,oBAAC,mBAAD;IAA8B;IAAuB;GAAa,CAAA;EACnD,CAAA,CACb;;AAEV"}
@@ -0,0 +1,21 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/components/atoms/select-searchable-options.d.ts
3
+ interface Option {
4
+ value: string;
5
+ label: string;
6
+ disabled?: boolean;
7
+ }
8
+ interface OptionGroup {
9
+ label: string;
10
+ options: Option[];
11
+ }
12
+ interface ClassNames {
13
+ input?: string;
14
+ content?: string;
15
+ list?: string;
16
+ item?: string;
17
+ empty?: string;
18
+ }
19
+ //#endregion
20
+ export { ClassNames, Option, OptionGroup };
21
+ //# sourceMappingURL=select-searchable-options.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-searchable-options.d.mts","names":[],"sources":["../../../src/components/atoms/select-searchable-options.tsx"],"mappings":";;UAgBiB;EACf;EACA;EACA;;UAGe;EACf;EACA,SAAS;;UAGM;EACf;EACA;EACA;EACA;EACA"}
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ import { combobox_exports } from "../../core/combobox.mjs";
3
+ import { useMemo } from "react";
4
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/components/atoms/select-searchable-options.tsx
6
+ const { ComboboxCollection, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxItem, ComboboxList, createItems } = combobox_exports;
7
+ const isGroup = (option) => {
8
+ return "options" in option && Array.isArray(option.options);
9
+ };
10
+ const useSelectItems = (options) => {
11
+ const groups = useMemo(() => {
12
+ const result = [];
13
+ options.forEach((option, index) => {
14
+ if (isGroup(option)) result.push({
15
+ key: index,
16
+ value: option.label,
17
+ items: option.options,
18
+ grouped: true
19
+ });
20
+ else {
21
+ const previous = result.at(-1);
22
+ if (previous && !previous.grouped) previous.items.push(option);
23
+ else result.push({
24
+ key: index,
25
+ value: "",
26
+ items: [option],
27
+ grouped: false
28
+ });
29
+ }
30
+ });
31
+ return result;
32
+ }, [options]);
33
+ return useMemo(() => createItems(groups, {
34
+ getValue: (option) => option.value,
35
+ getLabel: (option) => option.label
36
+ }), [groups]);
37
+ };
38
+ const SearchableOptions = ({ emptyText, classNames }) => {
39
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ComboboxEmpty, {
40
+ className: classNames?.empty,
41
+ children: emptyText
42
+ }), /* @__PURE__ */ jsx(ComboboxList, {
43
+ className: classNames?.list,
44
+ children: (group) => /* @__PURE__ */ jsxs(ComboboxGroup, {
45
+ items: group.items,
46
+ children: [group.grouped && /* @__PURE__ */ jsx(ComboboxGroupLabel, {
47
+ "data-slot": "combobox-group-label",
48
+ className: "text-muted-foreground px-2 py-1.5 text-xs",
49
+ children: group.value
50
+ }), /* @__PURE__ */ jsx(ComboboxCollection, { children: (option) => /* @__PURE__ */ jsx(ComboboxItem, {
51
+ value: option.value,
52
+ disabled: option.disabled,
53
+ className: classNames?.item,
54
+ children: option.label
55
+ }, option.value) })]
56
+ }, group.key)
57
+ })] });
58
+ };
59
+ //#endregion
60
+ export { SearchableOptions as default, useSelectItems };
61
+
62
+ //# sourceMappingURL=select-searchable-options.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-searchable-options.mjs","names":["combobox"],"sources":["../../../src/components/atoms/select-searchable-options.tsx"],"sourcesContent":["'use client';\n\nimport { type ReactNode, useMemo } from 'react';\n\nimport { combobox } from '../../core';\n\nconst {\n ComboboxCollection,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxGroupLabel,\n ComboboxItem,\n ComboboxList,\n createItems,\n} = combobox;\n\nexport interface Option {\n value: string;\n label: string;\n disabled?: boolean;\n}\n\nexport interface OptionGroup {\n label: string;\n options: Option[];\n}\n\nexport interface ClassNames {\n input?: string;\n content?: string;\n list?: string;\n item?: string;\n empty?: string;\n}\n\ninterface ItemsGroup {\n key: number;\n value: string;\n items: Option[];\n grouped: boolean;\n}\n\nconst isGroup = (option: Option | OptionGroup): option is OptionGroup => {\n return 'options' in option && Array.isArray(option.options);\n};\n\nexport const useSelectItems = (options: (Option | OptionGroup)[]) => {\n const groups = useMemo(() => {\n const result: ItemsGroup[] = [];\n\n options.forEach((option, index) => {\n if (isGroup(option)) {\n result.push({\n key: index,\n value: option.label,\n items: option.options,\n grouped: true,\n });\n } else {\n const previous = result.at(-1);\n\n if (previous && !previous.grouped) {\n previous.items.push(option);\n } else {\n result.push({\n key: index,\n value: '',\n items: [option],\n grouped: false,\n });\n }\n }\n });\n\n return result;\n }, [options]);\n const items = useMemo(\n () =>\n createItems<Option, string>(groups, {\n getValue: option => option.value,\n getLabel: option => option.label,\n }),\n [groups],\n );\n\n return items;\n};\n\ninterface Props {\n emptyText: ReactNode;\n classNames?: ClassNames;\n}\n\nconst SearchableOptions = ({ emptyText, classNames }: Props) => {\n return (\n <>\n <ComboboxEmpty className={classNames?.empty}>{emptyText}</ComboboxEmpty>\n <ComboboxList className={classNames?.list}>\n {(group: ItemsGroup) => (\n <ComboboxGroup key={group.key} items={group.items}>\n {group.grouped && (\n <ComboboxGroupLabel\n data-slot=\"combobox-group-label\"\n className=\"text-muted-foreground px-2 py-1.5 text-xs\"\n >\n {group.value}\n </ComboboxGroupLabel>\n )}\n <ComboboxCollection>\n {(option: Option) => (\n <ComboboxItem\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n className={classNames?.item}\n >\n {option.label}\n </ComboboxItem>\n )}\n </ComboboxCollection>\n </ComboboxGroup>\n )}\n </ComboboxList>\n </>\n );\n};\n\nexport default SearchableOptions;\n"],"mappings":";;;;;AAMA,MAAM,EACJ,oBACA,eACA,eACA,oBACA,cACA,cACA,gBACEA;AA4BJ,MAAM,WAAW,WAAwD;CACvE,OAAO,aAAa,UAAU,MAAM,QAAQ,OAAO,OAAO;AAC5D;AAEA,MAAa,kBAAkB,YAAsC;CACnE,MAAM,SAAS,cAAc;EAC3B,MAAM,SAAuB,CAAC;EAE9B,QAAQ,SAAS,QAAQ,UAAU;GACjC,IAAI,QAAQ,MAAM,GAChB,OAAO,KAAK;IACV,KAAK;IACL,OAAO,OAAO;IACd,OAAO,OAAO;IACd,SAAS;GACX,CAAC;QACI;IACL,MAAM,WAAW,OAAO,GAAG,EAAE;IAE7B,IAAI,YAAY,CAAC,SAAS,SACxB,SAAS,MAAM,KAAK,MAAM;SAE1B,OAAO,KAAK;KACV,KAAK;KACL,OAAO;KACP,OAAO,CAAC,MAAM;KACd,SAAS;IACX,CAAC;GAEL;EACF,CAAC;EAED,OAAO;CACT,GAAG,CAAC,OAAO,CAAC;CAUZ,OATc,cAEV,YAA4B,QAAQ;EAClC,WAAU,WAAU,OAAO;EAC3B,WAAU,WAAU,OAAO;CAC7B,CAAC,GACH,CAAC,MAAM,CAGE;AACb;AAOA,MAAM,qBAAqB,EAAE,WAAW,iBAAwB;CAC9D,OACE,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,eAAD;EAAe,WAAW,YAAY;EAAQ,UAAA;CAAyB,CAAA,GACvE,oBAAC,cAAD;EAAc,WAAW,YAAY;EACjC,WAAA,UACA,qBAAC,eAAD;GAA+B,OAAO,MAAM;GAA5C,UAAA,CACG,MAAM,WACL,oBAAC,oBAAD;IACE,aAAU;IACV,WAAU;IAET,UAAA,MAAM;GACW,CAAA,GAEtB,oBAAC,oBAAD,EAAA,WACI,WACA,oBAAC,cAAD;IAEE,OAAO,OAAO;IACd,UAAU,OAAO;IACjB,WAAW,YAAY;IAEtB,UAAA,OAAO;GACI,GANP,OAAO,KAMA,EAEE,CAAA,CACP;EArBK,GAAA,MAAM,GAqBX;CAEL,CAAA,CACd,EAAA,CAAA;AAEN"}
@@ -0,0 +1,22 @@
1
+ import { RootProps } from "../../core/combobox.mjs";
2
+ import "../../core/index.mjs";
3
+ import { ClassNames, Option, OptionGroup } from "./select-searchable-options.mjs";
4
+ import { ReactNode } from "react";
5
+ //#region src/components/atoms/select-searchable.d.ts
6
+ interface Props extends Omit<RootProps<string, Option>, 'children' | 'items' | 'multiple' | 'filteredItems' | 'onValueChange' | 'itemToStringLabel' | 'itemToStringValue' | 'isItemEqualToValue'> {
7
+ searchable: true;
8
+ multiple?: false;
9
+ /** Accessible name for the trigger and search popup. */
10
+ label: string;
11
+ options: (Option | OptionGroup)[];
12
+ placeholder?: string;
13
+ searchPlaceholder?: string;
14
+ emptyText?: ReactNode;
15
+ allowClear?: boolean;
16
+ className?: string;
17
+ classNames?: ClassNames;
18
+ onChange?: (value: string | null) => void;
19
+ }
20
+ //#endregion
21
+ export { Props };
22
+ //# sourceMappingURL=select-searchable.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-searchable.d.mts","names":[],"sources":["../../../src/components/atoms/select-searchable.tsx"],"mappings":";;;;;UA6BiB,cAAc,KAC7B,kBAA2B;EAU3B;EACA;;EAEA;EACA,UAAU,SAAS;EACnB;EACA;EACA,YAAY;EACZ;EACA;EACA,aAAa;EACb,YAAY"}
@@ -0,0 +1,65 @@
1
+ "use client";
2
+ import { cn } from "../../utils.mjs";
3
+ import { DEFAULT_LOCALE, useConfig } from "../../providers/config/context.mjs";
4
+ import { combobox_exports } from "../../core/combobox.mjs";
5
+ import { selectTriggerStyles } from "../../core/select.mjs";
6
+ import Button from "../../Button.mjs";
7
+ import Input from "./input/index.mjs";
8
+ import SearchableOptions, { useSelectItems } from "./select-searchable-options.mjs";
9
+ import { ChevronDownIcon, XIcon } from "lucide-react";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ //#region src/components/atoms/select-searchable.tsx
12
+ const { Combobox: Core, ComboboxClear, ComboboxContent, ComboboxIcon, ComboboxInput, ComboboxTrigger, ComboboxValue } = combobox_exports;
13
+ const SearchableSelect = ({ label, options, placeholder, searchPlaceholder = "Search...", emptyText = "No results found.", allowClear = true, className, classNames, onChange, searchable: _searchable, multiple: _multiple, ...props }) => {
14
+ const { locale } = useConfig();
15
+ const items = useSelectItems(options);
16
+ return /* @__PURE__ */ jsxs(Core, {
17
+ items,
18
+ onValueChange: (value) => onChange?.(value),
19
+ ...props,
20
+ children: [/* @__PURE__ */ jsxs(ComboboxTrigger, {
21
+ "data-slot": "select-trigger",
22
+ "data-size": "default",
23
+ "aria-label": label,
24
+ className: cn(selectTriggerStyles, "w-full max-w-48", className),
25
+ children: [/* @__PURE__ */ jsx("span", {
26
+ "data-slot": "select-value",
27
+ className: "min-w-0 flex-1 truncate text-start",
28
+ children: /* @__PURE__ */ jsx(ComboboxValue, { placeholder })
29
+ }), /* @__PURE__ */ jsx(ComboboxIcon, {
30
+ className: "opacity-50",
31
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, {})
32
+ })]
33
+ }), /* @__PURE__ */ jsxs(ComboboxContent, {
34
+ "aria-label": label,
35
+ className: classNames?.content,
36
+ children: [/* @__PURE__ */ jsx("div", {
37
+ className: "border-b p-1",
38
+ children: /* @__PURE__ */ jsxs("div", {
39
+ className: "relative flex items-center",
40
+ children: [/* @__PURE__ */ jsx(ComboboxInput, { render: /* @__PURE__ */ jsx(Input, {
41
+ "aria-label": `${label} search`,
42
+ placeholder: searchPlaceholder,
43
+ className: cn(allowClear && "pe-8", classNames?.input)
44
+ }) }), allowClear && /* @__PURE__ */ jsx(ComboboxClear, {
45
+ "data-slot": "combobox-clear",
46
+ render: /* @__PURE__ */ jsx(Button, {
47
+ variant: "text",
48
+ size: "icon-sm",
49
+ icon: /* @__PURE__ */ jsx(XIcon, {}),
50
+ "aria-label": locale.clear ?? DEFAULT_LOCALE.clear,
51
+ className: "absolute end-0"
52
+ })
53
+ })]
54
+ })
55
+ }), /* @__PURE__ */ jsx(SearchableOptions, {
56
+ emptyText,
57
+ classNames
58
+ })]
59
+ })]
60
+ });
61
+ };
62
+ //#endregion
63
+ export { SearchableSelect as default };
64
+
65
+ //# sourceMappingURL=select-searchable.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-searchable.mjs","names":["combobox","select.selectTriggerStyles"],"sources":["../../../src/components/atoms/select-searchable.tsx"],"sourcesContent":["'use client';\n\nimport { type ReactNode } from 'react';\n\nimport { ChevronDownIcon, XIcon } from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { combobox, select } from '../../core';\nimport Button from './button';\nimport Input from './input';\nimport SearchableOptions, {\n type ClassNames,\n type Option,\n type OptionGroup,\n useSelectItems,\n} from './select-searchable-options';\n\nconst {\n Combobox: Core,\n ComboboxClear,\n ComboboxContent,\n ComboboxIcon,\n ComboboxInput,\n ComboboxTrigger,\n ComboboxValue,\n} = combobox;\n\nexport interface Props extends Omit<\n combobox.RootProps<string, Option>,\n | 'children'\n | 'items'\n | 'multiple'\n | 'filteredItems'\n | 'onValueChange'\n | 'itemToStringLabel'\n | 'itemToStringValue'\n | 'isItemEqualToValue'\n> {\n searchable: true;\n multiple?: false;\n /** Accessible name for the trigger and search popup. */\n label: string;\n options: (Option | OptionGroup)[];\n placeholder?: string;\n searchPlaceholder?: string;\n emptyText?: ReactNode;\n allowClear?: boolean;\n className?: string;\n classNames?: ClassNames;\n onChange?: (value: string | null) => void;\n}\n\nconst SearchableSelect = ({\n label,\n options,\n placeholder,\n searchPlaceholder = 'Search...',\n emptyText = 'No results found.',\n allowClear = true,\n className,\n classNames,\n onChange,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Do not forward the public mode switch to Base UI.\n searchable: _searchable,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- The single-select primitive fixes this mode internally.\n multiple: _multiple,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n const items = useSelectItems(options);\n\n return (\n <Core items={items} onValueChange={value => onChange?.(value)} {...props}>\n <ComboboxTrigger\n data-slot=\"select-trigger\"\n data-size=\"default\"\n aria-label={label}\n className={cn(select.selectTriggerStyles, 'w-full max-w-48', className)}\n >\n <span\n data-slot=\"select-value\"\n className=\"min-w-0 flex-1 truncate text-start\"\n >\n <ComboboxValue placeholder={placeholder} />\n </span>\n <ComboboxIcon className=\"opacity-50\">\n <ChevronDownIcon />\n </ComboboxIcon>\n </ComboboxTrigger>\n <ComboboxContent aria-label={label} className={classNames?.content}>\n <div className=\"border-b p-1\">\n <div className=\"relative flex items-center\">\n <ComboboxInput\n render={\n <Input\n aria-label={`${label} search`}\n placeholder={searchPlaceholder}\n className={cn(allowClear && 'pe-8', classNames?.input)}\n />\n }\n />\n {allowClear && (\n <ComboboxClear\n data-slot=\"combobox-clear\"\n render={\n <Button\n variant=\"text\"\n size=\"icon-sm\"\n icon={<XIcon />}\n aria-label={locale.clear ?? DEFAULT_LOCALE.clear}\n className=\"absolute end-0\"\n />\n }\n />\n )}\n </div>\n </div>\n <SearchableOptions emptyText={emptyText} classNames={classNames} />\n </ComboboxContent>\n </Core>\n );\n};\n\nexport default SearchableSelect;\n"],"mappings":";;;;;;;;;;;AAmBA,MAAM,EACJ,UAAU,MACV,eACA,iBACA,cACA,eACA,iBACA,kBACEA;AA2BJ,MAAM,oBAAoB,EACxB,OACA,SACA,aACA,oBAAoB,aACpB,YAAY,qBACZ,aAAa,MACb,WACA,YACA,UAEA,YAAY,aAEZ,UAAU,WACV,GAAG,YACQ;CACX,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,QAAQ,eAAe,OAAO;CAEpC,OACE,qBAAC,MAAD;EAAa;EAAO,gBAAe,UAAS,WAAW,KAAK;EAAG,GAAI;EAAnE,UAAA,CACE,qBAAC,iBAAD;GACE,aAAU;GACV,aAAU;GACV,cAAY;GACZ,WAAW,GAAGC,qBAA4B,mBAAmB,SAAS;GAJxE,UAAA,CAME,oBAAC,QAAD;IACE,aAAU;IACV,WAAU;IAEV,UAAA,oBAAC,eAAD,EAA4B,YAAc,CAAA;GACtC,CAAA,GACN,oBAAC,cAAD;IAAc,WAAU;IACtB,UAAA,oBAAC,iBAAD,CAAkB,CAAA;GACN,CAAA,CACC;EACjB,CAAA,GAAA,qBAAC,iBAAD;GAAiB,cAAY;GAAO,WAAW,YAAY;GAA3D,UAAA,CACE,oBAAC,OAAD;IAAK,WAAU;IACb,UAAA,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,oBAAC,eAAD,EACE,QACE,oBAAC,OAAD;MACE,cAAY,GAAG,MAAM;MACrB,aAAa;MACb,WAAW,GAAG,cAAc,QAAQ,YAAY,KAAK;KACtD,CAAA,EAEJ,CAAA,GACA,cACC,oBAAC,eAAD;MACE,aAAU;MACV,QACE,oBAAC,QAAD;OACE,SAAQ;OACR,MAAK;OACL,MAAM,oBAAC,OAAD,CAAQ,CAAA;OACd,cAAY,OAAO,SAAS,eAAe;OAC3C,WAAU;MACX,CAAA;KAEJ,CAAA,CAEA;;GACF,CAAA,GACL,oBAAC,mBAAD;IAA8B;IAAuB;GAAa,CAAA,CACnD;EACb,CAAA,CAAA;;AAEV"}
@@ -1,23 +1,29 @@
1
1
  import { Select as Select$1 } from "../../core/select.mjs";
2
2
  import "../../core/index.mjs";
3
+ import { Props as Props$1 } from "./select-multiple.mjs";
4
+ import { Props as Props$2 } from "./select-searchable.mjs";
3
5
  import React from "react";
4
6
  //#region src/components/atoms/select.d.ts
5
7
  declare const Core: typeof Select$1;
6
8
  interface Option {
7
9
  label: React.ReactNode;
8
10
  value: string;
11
+ disabled?: boolean;
9
12
  }
10
13
  interface OptionGroup {
11
14
  label: React.ReactNode;
12
15
  options: Option[];
13
16
  }
14
- interface Props extends Omit<React.ComponentProps<typeof Core>, 'onValueChange'> {
17
+ interface StaticProps extends Omit<React.ComponentProps<typeof Core>, 'onValueChange' | 'items'> {
18
+ searchable?: false;
15
19
  placeholder?: string;
16
20
  className?: string;
17
21
  options?: (Option | OptionGroup)[];
18
22
  onChange?: (value: string) => void;
23
+ 'aria-label'?: string;
19
24
  }
20
- declare const Select: ({ className, placeholder, options, onChange, ...props }: Props) => React.JSX.Element;
25
+ type Props = StaticProps | Props$2 | Props$1;
26
+ declare const Select: (props: Props) => React.JSX.Element;
21
27
  //#endregion
22
28
  export { Props, Select as default };
23
29
  //# sourceMappingURL=select.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"select.d.mts","names":[],"sources":["../../../src/components/atoms/select.tsx"],"mappings":";;;;cAOU,aAAI;UASJ;EACR,OAAO,MAAM;EACb;;UAGQ;EACR,OAAO,MAAM;EACb,SAAS;;UAOM,cAAc,KAC7B,MAAM,sBAAsB;EAG5B;EACA;EACA,WAAW,SAAS;EACpB,YAAY;;cAGR,WAAU,WAAA,aAAA,SAAA,aAAA,SAMb,UAAK,MAAA,IAAA"}
1
+ {"version":3,"file":"select.d.mts","names":[],"sources":["../../../src/components/atoms/select.tsx"],"mappings":";;;;;;cAWU,aAAI;UASJ;EACR,OAAO,MAAM;EACb;EACA;;UAGQ;EACR,OAAO,MAAM;EACb,SAAS;;UAOD,oBAAoB,KAC5B,MAAM,sBAAsB;EAG5B;EACA;EACA;EACA,WAAW,SAAS;EACpB,YAAY;EACZ;;KAGU,QAAQ,cAAc,UAAkB;cA8D9C,SAAU,OAAO,UAAK,MAAA,IAAA"}
@@ -1,5 +1,7 @@
1
1
  import { cn } from "../../utils.mjs";
2
2
  import { select_exports } from "../../core/select.mjs";
3
+ import MultipleSelect from "./select-multiple.mjs";
4
+ import SearchableSelect from "./select-searchable.mjs";
3
5
  import "react";
4
6
  import { jsx, jsxs } from "react/jsx-runtime";
5
7
  //#region src/components/atoms/select.tsx
@@ -7,26 +9,34 @@ const { Select: Core, SelectContent, SelectGroup, SelectItem, SelectLabel, Selec
7
9
  const isGroup = (option) => {
8
10
  return "options" in option && Array.isArray(option.options);
9
11
  };
10
- const Select = ({ className, placeholder, options, onChange, ...props }) => {
12
+ const StaticSelect = ({ searchable: _searchable, className, placeholder, options, onChange, "aria-label": ariaLabel, ...props }) => {
11
13
  const items = options?.flatMap((option) => isGroup(option) ? option.options : option);
12
14
  return /* @__PURE__ */ jsxs(Core, {
15
+ ...props,
13
16
  items,
14
17
  onValueChange: (value) => {
15
18
  if (value !== null) onChange?.(value);
16
19
  },
17
- ...props,
18
20
  children: [/* @__PURE__ */ jsx(SelectTrigger, {
21
+ "aria-label": ariaLabel,
19
22
  className: cn("w-full max-w-48", className),
20
23
  children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
21
24
  }), /* @__PURE__ */ jsx(SelectContent, { children: options?.map((option, index) => isGroup(option) ? /* @__PURE__ */ jsxs(SelectGroup, { children: [/* @__PURE__ */ jsx(SelectLabel, { children: option.label }), option.options.map((item) => /* @__PURE__ */ jsx(SelectItem, {
22
25
  value: item.value,
26
+ disabled: item.disabled,
23
27
  children: item.label
24
28
  }, item.value))] }, index) : /* @__PURE__ */ jsx(SelectItem, {
25
29
  value: option.value,
30
+ disabled: option.disabled,
26
31
  children: option.label
27
32
  }, option.value)) })]
28
33
  });
29
34
  };
35
+ const Select = (props) => {
36
+ if (props.multiple) return /* @__PURE__ */ jsx(MultipleSelect, { ...props });
37
+ if (props.searchable) return /* @__PURE__ */ jsx(SearchableSelect, { ...props });
38
+ return /* @__PURE__ */ jsx(StaticSelect, { ...props });
39
+ };
30
40
  //#endregion
31
41
  export { Select as default };
32
42
 
@@ -1 +1 @@
1
- {"version":3,"file":"select.mjs","names":["select"],"sources":["../../../src/components/atoms/select.tsx"],"sourcesContent":["import React from 'react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { select } from '../../core';\n\nconst {\n Select: Core,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n SelectValue,\n} = select;\n\ninterface Option {\n label: React.ReactNode;\n value: string;\n}\n\ninterface OptionGroup {\n label: React.ReactNode;\n options: Option[];\n}\n\nconst isGroup = (option: Option | OptionGroup): option is OptionGroup => {\n return 'options' in option && Array.isArray(option.options);\n};\n\nexport interface Props extends Omit<\n React.ComponentProps<typeof Core>,\n 'onValueChange'\n> {\n placeholder?: string;\n className?: string;\n options?: (Option | OptionGroup)[];\n onChange?: (value: string) => void;\n}\n\nconst Select = ({\n className,\n placeholder,\n options,\n onChange,\n ...props\n}: Props) => {\n const items = options?.flatMap(option =>\n isGroup(option) ? option.options : option,\n );\n\n return (\n <Core\n items={items}\n onValueChange={value => {\n if (value !== null) {\n onChange?.(value);\n }\n }}\n {...props}\n >\n <SelectTrigger className={cn('w-full max-w-48', className)}>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent>\n {options?.map((option, index) =>\n isGroup(option) ? (\n <SelectGroup key={index}>\n <SelectLabel>{option.label}</SelectLabel>\n {option.options.map(item => (\n <SelectItem key={item.value} value={item.value}>\n {item.label}\n </SelectItem>\n ))}\n </SelectGroup>\n ) : (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ),\n )}\n </SelectContent>\n </Core>\n );\n};\n\nexport default Select;\n"],"mappings":";;;;;AAMA,MAAM,EACJ,QAAQ,MACR,eACA,aACA,YACA,aACA,eACA,gBACEA;AAYJ,MAAM,WAAW,WAAwD;CACvE,OAAO,aAAa,UAAU,MAAM,QAAQ,OAAO,OAAO;AAC5D;AAYA,MAAM,UAAU,EACd,WACA,aACA,SACA,UACA,GAAG,YACQ;CACX,MAAM,QAAQ,SAAS,SAAQ,WAC7B,QAAQ,MAAM,IAAI,OAAO,UAAU,MACrC;CAEA,OACE,qBAAC,MAAD;EACS;EACP,gBAAe,UAAS;GACtB,IAAI,UAAU,MACZ,WAAW,KAAK;EAEpB;EACA,GAAI;EAPN,UAAA,CASE,oBAAC,eAAD;GAAe,WAAW,GAAG,mBAAmB,SAAS;GACvD,UAAA,oBAAC,aAAD,EAA0B,YAAc,CAAA;EAC3B,CAAA,GACf,oBAAC,eAAD,EAAA,UACG,SAAS,KAAK,QAAQ,UACrB,QAAQ,MAAM,IACZ,qBAAC,aAAD,EAAA,UAAA,CACE,oBAAC,aAAD,EAAA,UAAc,OAAO,MAAmB,CAAA,GACvC,OAAO,QAAQ,KAAI,SAClB,oBAAC,YAAD;GAA6B,OAAO,KAAK;GACtC,UAAA,KAAK;EACI,GAFK,KAAK,KAEV,CACb,CACU,EAAA,GAPK,KAOL,IAEb,oBAAC,YAAD;GAA+B,OAAO,OAAO;GAC1C,UAAA,OAAO;EACE,GAFK,OAAO,KAEZ,CAEhB,EACa,CAAA,CACX;;AAEV"}
1
+ {"version":3,"file":"select.mjs","names":["select"],"sources":["../../../src/components/atoms/select.tsx"],"sourcesContent":["import React from 'react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { select } from '../../core';\nimport MultipleSelect, { type Props as MultipleProps } from './select-multiple';\nimport SearchableSelect, {\n type Props as SearchableProps,\n} from './select-searchable';\n\nconst {\n Select: Core,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n SelectValue,\n} = select;\n\ninterface Option {\n label: React.ReactNode;\n value: string;\n disabled?: boolean;\n}\n\ninterface OptionGroup {\n label: React.ReactNode;\n options: Option[];\n}\n\nconst isGroup = (option: Option | OptionGroup): option is OptionGroup => {\n return 'options' in option && Array.isArray(option.options);\n};\n\ninterface StaticProps extends Omit<\n React.ComponentProps<typeof Core>,\n 'onValueChange' | 'items'\n> {\n searchable?: false;\n placeholder?: string;\n className?: string;\n options?: (Option | OptionGroup)[];\n onChange?: (value: string) => void;\n 'aria-label'?: string;\n}\n\nexport type Props = StaticProps | SearchableProps | MultipleProps;\n\nconst StaticSelect = ({\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Do not forward the public mode switch to Base UI.\n searchable: _searchable,\n className,\n placeholder,\n options,\n onChange,\n 'aria-label': ariaLabel,\n ...props\n}: StaticProps) => {\n const items = options?.flatMap(option =>\n isGroup(option) ? option.options : option,\n );\n\n return (\n <Core\n {...props}\n items={items}\n onValueChange={value => {\n if (value !== null) {\n onChange?.(value);\n }\n }}\n >\n <SelectTrigger\n aria-label={ariaLabel}\n className={cn('w-full max-w-48', className)}\n >\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent>\n {options?.map((option, index) =>\n isGroup(option) ? (\n <SelectGroup key={index}>\n <SelectLabel>{option.label}</SelectLabel>\n {option.options.map(item => (\n <SelectItem\n key={item.value}\n value={item.value}\n disabled={item.disabled}\n >\n {item.label}\n </SelectItem>\n ))}\n </SelectGroup>\n ) : (\n <SelectItem\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n >\n {option.label}\n </SelectItem>\n ),\n )}\n </SelectContent>\n </Core>\n );\n};\n\nconst Select = (props: Props) => {\n if (props.multiple) {\n return <MultipleSelect {...props} />;\n }\n\n if (props.searchable) {\n return <SearchableSelect {...props} />;\n }\n\n return <StaticSelect {...props} />;\n};\n\nexport default Select;\n"],"mappings":";;;;;;;AAUA,MAAM,EACJ,QAAQ,MACR,eACA,aACA,YACA,aACA,eACA,gBACEA;AAaJ,MAAM,WAAW,WAAwD;CACvE,OAAO,aAAa,UAAU,MAAM,QAAQ,OAAO,OAAO;AAC5D;AAgBA,MAAM,gBAAgB,EAEpB,YAAY,aACZ,WACA,aACA,SACA,UACA,cAAc,WACd,GAAG,YACc;CACjB,MAAM,QAAQ,SAAS,SAAQ,WAC7B,QAAQ,MAAM,IAAI,OAAO,UAAU,MACrC;CAEA,OACE,qBAAC,MAAD;EACE,GAAI;EACG;EACP,gBAAe,UAAS;GACtB,IAAI,UAAU,MACZ,WAAW,KAAK;EAEpB;EAPF,UAAA,CASE,oBAAC,eAAD;GACE,cAAY;GACZ,WAAW,GAAG,mBAAmB,SAAS;GAE1C,UAAA,oBAAC,aAAD,EAA0B,YAAc,CAAA;EAC3B,CAAA,GACf,oBAAC,eAAD,EAAA,UACG,SAAS,KAAK,QAAQ,UACrB,QAAQ,MAAM,IACZ,qBAAC,aAAD,EAAA,UAAA,CACE,oBAAC,aAAD,EAAA,UAAc,OAAO,MAAmB,CAAA,GACvC,OAAO,QAAQ,KAAI,SAClB,oBAAC,YAAD;GAEE,OAAO,KAAK;GACZ,UAAU,KAAK;GAEd,UAAA,KAAK;EACI,GALL,KAAK,KAKA,CACb,CACU,EAAA,GAXK,KAWL,IAEb,oBAAC,YAAD;GAEE,OAAO,OAAO;GACd,UAAU,OAAO;GAEhB,UAAA,OAAO;EACE,GALL,OAAO,KAKF,CAEhB,EACa,CAAA,CACX;;AAEV;AAEA,MAAM,UAAU,UAAiB;CAC/B,IAAI,MAAM,UACR,OAAO,oBAAC,gBAAD,EAAgB,GAAI,MAAQ,CAAA;CAGrC,IAAI,MAAM,YACR,OAAO,oBAAC,kBAAD,EAAkB,GAAI,MAAQ,CAAA;CAGvC,OAAO,oBAAC,cAAD,EAAc,GAAI,MAAQ,CAAA;AACnC"}
@@ -6,6 +6,8 @@ interface Props extends React.ComponentPropsWithoutRef<'div'> {
6
6
  size?: 'default' | 'small' | 'large';
7
7
  count?: number;
8
8
  gap?: number;
9
+ orientation?: 'horizontal' | 'vertical';
10
+ /** @deprecated Use `orientation`. */
9
11
  direction?: 'horizontal' | 'vertical';
10
12
  width?: string | number | (string | number)[];
11
13
  height?: string | number | (string | number)[];
@@ -15,7 +17,7 @@ interface Props extends React.ComponentPropsWithoutRef<'div'> {
15
17
  item?: string;
16
18
  };
17
19
  }
18
- declare const Skeleton: ({ active, loading, avatar, size, direction, count, gap, className, classNames, style, width, height, children, ...props }: Props) => string | number | bigint | boolean | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | import("react").JSX.Element | null;
20
+ declare const Skeleton: ({ active, loading, avatar, size, orientation, direction, count, gap, className, classNames, style, width, height, children, ...props }: Props) => string | number | bigint | boolean | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | import("react").JSX.Element | null;
19
21
  //#endregion
20
22
  export { Props, Skeleton as default };
21
23
  //# sourceMappingURL=skeleton.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skeleton.d.mts","names":[],"sources":["../../../../src/components/atoms/skeleton/skeleton.tsx"],"mappings":";UAaiB,cAAc,MAAM;EACnC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;IACE;IACA;IACA;;;cAUE,aAAY,QAAA,SAAA,QAAA,MAAA,WAAA,OAAA,KAAA,WAAA,YAAA,OAAA,OAAA,QAAA,aAAA,SAef,+CAAK,yBAAA,aAAA,6DAAA,8BAAA,+CAAA,8BAAA,yBAAA,iDAAA,IAAA"}
1
+ {"version":3,"file":"skeleton.d.mts","names":[],"sources":["../../../../src/components/atoms/skeleton/skeleton.tsx"],"mappings":";UAaiB,cAAc,MAAM;EACnC;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;EACA;IACE;IACA;IACA;;;cAUE,aAAY,QAAA,SAAA,QAAA,MAAA,aAAA,WAAA,OAAA,KAAA,WAAA,YAAA,OAAA,OAAA,QAAA,aAAA,SAgBf,+CAAK,yBAAA,aAAA,6DAAA,8BAAA,+CAAA,8BAAA,yBAAA,iDAAA,IAAA"}
@@ -13,7 +13,7 @@ const SIZES = {
13
13
  default: "w-60 h-6",
14
14
  large: "w-72 h-8"
15
15
  };
16
- const Skeleton = ({ active = true, loading = true, avatar, size = "default", direction = "vertical", count = 1, gap = 6, className, classNames = {}, style, width, height, children, ...props }) => {
16
+ const Skeleton = ({ active = true, loading = true, avatar, size = "default", orientation, direction = "vertical", count = 1, gap = 6, className, classNames = {}, style, width, height, children, ...props }) => {
17
17
  const { locale } = useConfig();
18
18
  if (!loading) return children ?? null;
19
19
  return /* @__PURE__ */ jsxs("div", {
@@ -23,7 +23,7 @@ const Skeleton = ({ active = true, loading = true, avatar, size = "default", dir
23
23
  style,
24
24
  ...props,
25
25
  children: [avatar && /* @__PURE__ */ jsx(Core, { className: cn("h-12 w-12", "rounded-xl", !active && "animate-none", classNames.avatar) }), /* @__PURE__ */ jsx("div", {
26
- className: cn("flex min-w-0 grow", direction === "vertical" && "flex-col", classNames.wrapper),
26
+ className: cn("flex min-w-0 grow", (orientation ?? direction) === "vertical" && "flex-col", classNames.wrapper),
27
27
  style: { gap },
28
28
  children: Array.from({ length: count }).map((_, index) => {
29
29
  const itemWidth = getValueAtIndex(width, index);
@@ -1 +1 @@
1
- {"version":3,"file":"skeleton.mjs","names":["skeleton"],"sources":["../../../../src/components/atoms/skeleton/skeleton.tsx"],"sourcesContent":["'use client';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { skeleton } from '../../../core';\n\nconst { Skeleton: Core } = skeleton;\n\nconst getValueAtIndex = <T,>(value: T | T[], index: number) => {\n return Array.isArray(value) ? (value[index] ?? value[0]) : value;\n};\n\nexport interface Props extends React.ComponentPropsWithoutRef<'div'> {\n active?: boolean;\n loading?: boolean;\n avatar?: boolean;\n size?: 'default' | 'small' | 'large';\n count?: number;\n gap?: number;\n direction?: 'horizontal' | 'vertical';\n width?: string | number | (string | number)[];\n height?: string | number | (string | number)[];\n classNames?: {\n wrapper?: string;\n avatar?: string;\n item?: string;\n };\n}\n\nconst SIZES = {\n small: 'w-48 h-4',\n default: 'w-60 h-6',\n large: 'w-72 h-8',\n};\n\nconst Skeleton = ({\n active = true,\n loading = true,\n avatar,\n size = 'default',\n direction = 'vertical',\n count = 1,\n gap = 6,\n className,\n classNames = {},\n style,\n width,\n height,\n children,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n\n // Not wrapping `children` here (unlike Spin's overlay mode) — Skeleton\n // is meant to swap in arbitrary real content once loading finishes,\n // which can include elements with strict parent requirements (e.g. a\n // `<tr>`), so adding a wrapper div could produce invalid markup.\n // `className`/`style`/rest props only ever describe the skeleton's own\n // placeholder markup, so there's nothing for them to apply to here.\n if (!loading) {\n return children ?? null;\n }\n\n return (\n <div\n role=\"status\"\n aria-label={locale.loading ?? DEFAULT_LOCALE.loading}\n className={cn('flex items-center gap-3', className)}\n style={style}\n {...props}\n >\n {avatar && (\n <Core\n className={cn(\n 'h-12 w-12',\n 'rounded-xl',\n !active && 'animate-none',\n classNames.avatar,\n )}\n />\n )}\n <div\n className={cn(\n 'flex min-w-0 grow',\n direction === 'vertical' && 'flex-col',\n classNames.wrapper,\n )}\n style={{\n gap,\n }}\n >\n {Array.from({ length: count }).map((_, index) => {\n const itemWidth = getValueAtIndex(width, index);\n const itemHeight = getValueAtIndex(height, index);\n\n return (\n <Core\n key={index}\n className={cn(\n 'rounded-md',\n !active && 'animate-none',\n // SIZES are fixed widths; cap them so a narrow container\n // shrinks the placeholder instead of being overflowed.\n SIZES[size],\n 'max-w-full',\n classNames.item,\n //\n )}\n style={{\n width: itemWidth,\n height: itemHeight,\n }}\n />\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default Skeleton;\n"],"mappings":";;;;;;AAOA,MAAM,EAAE,UAAU,SAASA;AAE3B,MAAM,mBAAuB,OAAgB,UAAkB;CAC7D,OAAO,MAAM,QAAQ,KAAK,IAAK,MAAM,UAAU,MAAM,KAAM;AAC7D;AAmBA,MAAM,QAAQ;CACZ,OAAO;CACP,SAAS;CACT,OAAO;AACT;AAEA,MAAM,YAAY,EAChB,SAAS,MACT,UAAU,MACV,QACA,OAAO,WACP,YAAY,YACZ,QAAQ,GACR,MAAM,GACN,WACA,aAAa,CAAC,GACd,OACA,OACA,QACA,UACA,GAAG,YACQ;CACX,MAAM,EAAE,WAAW,UAAU;CAQ7B,IAAI,CAAC,SACH,OAAO,YAAY;CAGrB,OACE,qBAAC,OAAD;EACE,MAAK;EACL,cAAY,OAAO,WAAW,eAAe;EAC7C,WAAW,GAAG,2BAA2B,SAAS;EAC3C;EACP,GAAI;EALN,UAAA,CAOG,UACC,oBAAC,MAAD,EACE,WAAW,GACT,aACA,cACA,CAAC,UAAU,gBACX,WAAW,MACb,EACD,CAAA,GAEH,oBAAC,OAAD;GACE,WAAW,GACT,qBACA,cAAc,cAAc,YAC5B,WAAW,OACb;GACA,OAAO,EACL,IACF;GAEC,UAAA,MAAM,KAAK,EAAE,QAAQ,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,UAAU;IAC/C,MAAM,YAAY,gBAAgB,OAAO,KAAK;IAC9C,MAAM,aAAa,gBAAgB,QAAQ,KAAK;IAEhD,OACE,oBAAC,MAAD;KAEE,WAAW,GACT,cACA,CAAC,UAAU,gBAGX,MAAM,OACN,cACA,WAAW,IAEb;KACA,OAAO;MACL,OAAO;MACP,QAAQ;KACV;IACD,GAfM,KAeN;GAEL,CAAC;EACE,CAAA,CACF;;AAET"}
1
+ {"version":3,"file":"skeleton.mjs","names":["skeleton"],"sources":["../../../../src/components/atoms/skeleton/skeleton.tsx"],"sourcesContent":["'use client';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { skeleton } from '../../../core';\n\nconst { Skeleton: Core } = skeleton;\n\nconst getValueAtIndex = <T,>(value: T | T[], index: number) => {\n return Array.isArray(value) ? (value[index] ?? value[0]) : value;\n};\n\nexport interface Props extends React.ComponentPropsWithoutRef<'div'> {\n active?: boolean;\n loading?: boolean;\n avatar?: boolean;\n size?: 'default' | 'small' | 'large';\n count?: number;\n gap?: number;\n orientation?: 'horizontal' | 'vertical';\n /** @deprecated Use `orientation`. */\n direction?: 'horizontal' | 'vertical';\n width?: string | number | (string | number)[];\n height?: string | number | (string | number)[];\n classNames?: {\n wrapper?: string;\n avatar?: string;\n item?: string;\n };\n}\n\nconst SIZES = {\n small: 'w-48 h-4',\n default: 'w-60 h-6',\n large: 'w-72 h-8',\n};\n\nconst Skeleton = ({\n active = true,\n loading = true,\n avatar,\n size = 'default',\n orientation,\n direction = 'vertical',\n count = 1,\n gap = 6,\n className,\n classNames = {},\n style,\n width,\n height,\n children,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n\n // Not wrapping `children` here (unlike Spin's overlay mode) — Skeleton\n // is meant to swap in arbitrary real content once loading finishes,\n // which can include elements with strict parent requirements (e.g. a\n // `<tr>`), so adding a wrapper div could produce invalid markup.\n // `className`/`style`/rest props only ever describe the skeleton's own\n // placeholder markup, so there's nothing for them to apply to here.\n if (!loading) {\n return children ?? null;\n }\n\n return (\n <div\n role=\"status\"\n aria-label={locale.loading ?? DEFAULT_LOCALE.loading}\n className={cn('flex items-center gap-3', className)}\n style={style}\n {...props}\n >\n {avatar && (\n <Core\n className={cn(\n 'h-12 w-12',\n 'rounded-xl',\n !active && 'animate-none',\n classNames.avatar,\n )}\n />\n )}\n <div\n className={cn(\n 'flex min-w-0 grow',\n (orientation ?? direction) === 'vertical' && 'flex-col',\n classNames.wrapper,\n )}\n style={{\n gap,\n }}\n >\n {Array.from({ length: count }).map((_, index) => {\n const itemWidth = getValueAtIndex(width, index);\n const itemHeight = getValueAtIndex(height, index);\n\n return (\n <Core\n key={index}\n className={cn(\n 'rounded-md',\n !active && 'animate-none',\n // SIZES are fixed widths; cap them so a narrow container\n // shrinks the placeholder instead of being overflowed.\n SIZES[size],\n 'max-w-full',\n classNames.item,\n //\n )}\n style={{\n width: itemWidth,\n height: itemHeight,\n }}\n />\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default Skeleton;\n"],"mappings":";;;;;;AAOA,MAAM,EAAE,UAAU,SAASA;AAE3B,MAAM,mBAAuB,OAAgB,UAAkB;CAC7D,OAAO,MAAM,QAAQ,KAAK,IAAK,MAAM,UAAU,MAAM,KAAM;AAC7D;AAqBA,MAAM,QAAQ;CACZ,OAAO;CACP,SAAS;CACT,OAAO;AACT;AAEA,MAAM,YAAY,EAChB,SAAS,MACT,UAAU,MACV,QACA,OAAO,WACP,aACA,YAAY,YACZ,QAAQ,GACR,MAAM,GACN,WACA,aAAa,CAAC,GACd,OACA,OACA,QACA,UACA,GAAG,YACQ;CACX,MAAM,EAAE,WAAW,UAAU;CAQ7B,IAAI,CAAC,SACH,OAAO,YAAY;CAGrB,OACE,qBAAC,OAAD;EACE,MAAK;EACL,cAAY,OAAO,WAAW,eAAe;EAC7C,WAAW,GAAG,2BAA2B,SAAS;EAC3C;EACP,GAAI;EALN,UAAA,CAOG,UACC,oBAAC,MAAD,EACE,WAAW,GACT,aACA,cACA,CAAC,UAAU,gBACX,WAAW,MACb,EACD,CAAA,GAEH,oBAAC,OAAD;GACE,WAAW,GACT,sBACC,eAAe,eAAe,cAAc,YAC7C,WAAW,OACb;GACA,OAAO,EACL,IACF;GAEC,UAAA,MAAM,KAAK,EAAE,QAAQ,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,UAAU;IAC/C,MAAM,YAAY,gBAAgB,OAAO,KAAK;IAC9C,MAAM,aAAa,gBAAgB,QAAQ,KAAK;IAEhD,OACE,oBAAC,MAAD;KAEE,WAAW,GACT,cACA,CAAC,UAAU,gBAGX,MAAM,OACN,cACA,WAAW,IAEb;KACA,OAAO;MACL,OAAO;MACP,QAAQ;KACV;IACD,GAfM,KAeN;GAEL,CAAC;EACE,CAAA,CACF;;AAET"}
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { cn } from "../../../utils.mjs";
3
3
  import { slider_exports } from "../../../core/slider.mjs";
4
- import { jsx } from "react/jsx-runtime";
5
4
  import { useControllableState } from "@jbpark/use-hooks";
5
+ import { jsx } from "react/jsx-runtime";
6
6
  //#region src/components/atoms/slider/slider.tsx
7
7
  const { Slider: Core } = slider_exports;
8
8
  const toArray = (value) => {
@@ -2,8 +2,8 @@
2
2
  import { cn } from "../../utils.mjs";
3
3
  import { useConfig } from "../../providers/config/context.mjs";
4
4
  import { switch_exports } from "../../core/switch.mjs";
5
- import { jsx, jsxs } from "react/jsx-runtime";
6
5
  import { useControllableState } from "@jbpark/use-hooks";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region src/components/atoms/switch.tsx
8
8
  const { Switch: Core } = switch_exports;
9
9
  const sizeConfig = {