@jbpark/ui-kit 10.0.2 → 10.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +7 -0
- package/README.md +7 -0
- package/dist/Alert.d.mts +24 -0
- package/dist/Alert.d.mts.map +1 -0
- package/dist/Alert.mjs +68 -0
- package/dist/Alert.mjs.map +1 -0
- package/dist/Avatar.d.mts +19 -0
- package/dist/Avatar.d.mts.map +1 -0
- package/dist/Avatar.mjs +43 -0
- package/dist/Avatar.mjs.map +1 -0
- package/dist/Badge.d.mts +23 -0
- package/dist/Badge.d.mts.map +1 -0
- package/dist/Badge.mjs +41 -0
- package/dist/Badge.mjs.map +1 -0
- package/dist/Breadcrumb.d.mts +39 -0
- package/dist/Breadcrumb.d.mts.map +1 -0
- package/dist/Breadcrumb.mjs +103 -0
- package/dist/Breadcrumb.mjs.map +1 -0
- package/dist/Button.mjs +1 -1
- package/dist/Pagination.d.mts +53 -0
- package/dist/Pagination.d.mts.map +1 -0
- package/dist/Pagination.mjs +208 -0
- package/dist/Pagination.mjs.map +1 -0
- package/dist/Segmented.d.mts +26 -0
- package/dist/Segmented.d.mts.map +1 -0
- package/dist/Segmented.mjs +57 -0
- package/dist/Segmented.mjs.map +1 -0
- package/dist/Steps.d.mts +28 -0
- package/dist/Steps.d.mts.map +1 -0
- package/dist/Steps.mjs +70 -0
- package/dist/Steps.mjs.map +1 -0
- package/dist/Table.d.mts +48 -0
- package/dist/Table.d.mts.map +1 -0
- package/dist/Table.mjs +119 -0
- package/dist/Table.mjs.map +1 -0
- package/dist/components/atoms/checkbox/checkbox.mjs +3 -2
- package/dist/components/atoms/checkbox/checkbox.mjs.map +1 -1
- package/dist/components/atoms/checkbox/group.mjs +2 -1
- package/dist/components/atoms/checkbox/group.mjs.map +1 -1
- package/dist/components/atoms/color-picker.mjs +1 -1
- package/dist/components/atoms/date-picker.mjs +2 -2
- package/dist/components/atoms/float-button/back-top.mjs +2 -2
- package/dist/components/atoms/index.d.mts +6 -1
- package/dist/components/atoms/input/index.d.mts +3 -1
- package/dist/components/atoms/input/index.d.mts.map +1 -1
- package/dist/components/atoms/input/index.mjs +3 -1
- package/dist/components/atoms/input/index.mjs.map +1 -1
- package/dist/components/atoms/input/number.d.mts +23 -0
- package/dist/components/atoms/input/number.d.mts.map +1 -0
- package/dist/components/atoms/input/number.mjs +71 -0
- package/dist/components/atoms/input/number.mjs.map +1 -0
- package/dist/components/atoms/input/search.d.mts +0 -5
- package/dist/components/atoms/input/search.d.mts.map +1 -1
- package/dist/components/atoms/input/search.mjs +8 -8
- package/dist/components/atoms/input/search.mjs.map +1 -1
- package/dist/components/atoms/popover.mjs +1 -1
- package/dist/components/atoms/progress.d.mts +3 -1
- package/dist/components/atoms/progress.d.mts.map +1 -1
- package/dist/components/atoms/progress.mjs +2 -2
- package/dist/components/atoms/progress.mjs.map +1 -1
- package/dist/components/atoms/radio/group.mjs +1 -1
- package/dist/components/atoms/radio/radio.mjs +3 -2
- package/dist/components/atoms/radio/radio.mjs.map +1 -1
- package/dist/components/atoms/rich-text-editor/rich-text-editor.d.mts +6 -1
- package/dist/components/atoms/rich-text-editor/rich-text-editor.d.mts.map +1 -1
- package/dist/components/atoms/rich-text-editor/rich-text-editor.mjs +7 -2
- package/dist/components/atoms/rich-text-editor/rich-text-editor.mjs.map +1 -1
- package/dist/components/atoms/rich-text-editor/toolbar-presets.mjs +1 -1
- package/dist/components/atoms/select-multiple.d.mts +29 -0
- package/dist/components/atoms/select-multiple.d.mts.map +1 -0
- package/dist/components/atoms/select-multiple.mjs +97 -0
- package/dist/components/atoms/select-multiple.mjs.map +1 -0
- package/dist/components/atoms/select-searchable-options.d.mts +21 -0
- package/dist/components/atoms/select-searchable-options.d.mts.map +1 -0
- package/dist/components/atoms/select-searchable-options.mjs +62 -0
- package/dist/components/atoms/select-searchable-options.mjs.map +1 -0
- package/dist/components/atoms/select-searchable.d.mts +22 -0
- package/dist/components/atoms/select-searchable.d.mts.map +1 -0
- package/dist/components/atoms/select-searchable.mjs +65 -0
- package/dist/components/atoms/select-searchable.mjs.map +1 -0
- package/dist/components/atoms/select.d.mts +8 -2
- package/dist/components/atoms/select.d.mts.map +1 -1
- package/dist/components/atoms/select.mjs +12 -2
- package/dist/components/atoms/select.mjs.map +1 -1
- package/dist/components/atoms/skeleton/skeleton.d.mts +3 -1
- package/dist/components/atoms/skeleton/skeleton.d.mts.map +1 -1
- package/dist/components/atoms/skeleton/skeleton.mjs +2 -2
- package/dist/components/atoms/skeleton/skeleton.mjs.map +1 -1
- package/dist/components/atoms/slider/slider.mjs +1 -1
- package/dist/components/atoms/switch.mjs +1 -1
- package/dist/components/atoms/tooltip.d.mts +21 -0
- package/dist/components/atoms/tooltip.d.mts.map +1 -0
- package/dist/components/atoms/tooltip.mjs +78 -0
- package/dist/components/atoms/tooltip.mjs.map +1 -0
- package/dist/components/atoms/typography/paragraph.mjs +1 -0
- package/dist/components/atoms/typography/paragraph.mjs.map +1 -1
- package/dist/components/atoms/typography/title.mjs +1 -0
- package/dist/components/atoms/typography/title.mjs.map +1 -1
- package/dist/components/molecules/collapse.d.mts +8 -8
- package/dist/components/molecules/collapse.d.mts.map +1 -1
- package/dist/components/molecules/collapse.mjs +11 -2
- package/dist/components/molecules/collapse.mjs.map +1 -1
- package/dist/components/molecules/dropdown.mjs +1 -1
- package/dist/components/molecules/index.d.mts +15 -10
- package/dist/components/molecules/marquees/marquees.mjs +1 -1
- package/dist/components/molecules/menu/item/item.mjs +1 -1
- package/dist/components/molecules/menu/menu.d.mts +1 -1
- package/dist/components/molecules/menu/menu.d.mts.map +1 -1
- package/dist/components/molecules/menu/menu.mjs +5 -2
- package/dist/components/molecules/menu/menu.mjs.map +1 -1
- package/dist/components/molecules/tabs.d.mts +41 -0
- package/dist/components/molecules/tabs.d.mts.map +1 -0
- package/dist/components/molecules/tabs.mjs +55 -0
- package/dist/components/molecules/tabs.mjs.map +1 -0
- package/dist/components/molecules/upload.mjs +3 -2
- package/dist/components/molecules/upload.mjs.map +1 -1
- package/dist/components/organisms/drawer.d.mts +1 -1
- package/dist/components/organisms/drawer.d.mts.map +1 -1
- package/dist/components/organisms/drawer.mjs +10 -4
- package/dist/components/organisms/drawer.mjs.map +1 -1
- package/dist/components/organisms/index.d.mts +6 -5
- package/dist/components/organisms/list/list.mjs +1 -1
- package/dist/components/organisms/modal.d.mts.map +1 -1
- package/dist/components/organisms/modal.mjs +8 -5
- package/dist/components/organisms/modal.mjs.map +1 -1
- package/dist/components/organisms/toast.d.mts.map +1 -1
- package/dist/components/organisms/toast.mjs +3 -2
- package/dist/components/organisms/toast.mjs.map +1 -1
- package/dist/components/templates/empty.mjs +1 -0
- package/dist/components/templates/empty.mjs.map +1 -1
- package/dist/components/templates/layout/content.mjs +1 -0
- package/dist/components/templates/layout/content.mjs.map +1 -1
- package/dist/components/templates/layout/footer.mjs +1 -0
- package/dist/components/templates/layout/footer.mjs.map +1 -1
- package/dist/components/templates/layout/header.mjs +1 -0
- package/dist/components/templates/layout/header.mjs.map +1 -1
- package/dist/components/templates/layout/layout.mjs +1 -0
- package/dist/components/templates/layout/layout.mjs.map +1 -1
- package/dist/components/templates/layout/sider.mjs +4 -2
- package/dist/components/templates/layout/sider.mjs.map +1 -1
- package/dist/components/templates/page-header.mjs +1 -0
- package/dist/components/templates/page-header.mjs.map +1 -1
- package/dist/components/templates/result.mjs +1 -0
- package/dist/components/templates/result.mjs.map +1 -1
- package/dist/core/accordion.mjs +1 -1
- package/dist/core/button.d.mts +1 -1
- package/dist/core/calendar.mjs +1 -1
- package/dist/core/checkbox.mjs +1 -1
- package/dist/core/combobox.d.mts +7 -0
- package/dist/core/combobox.d.mts.map +1 -0
- package/dist/core/combobox.mjs +99 -0
- package/dist/core/combobox.mjs.map +1 -0
- package/dist/core/dialog.mjs +1 -1
- package/dist/core/dialog.mjs.map +1 -1
- package/dist/core/drawer.mjs.map +1 -1
- package/dist/core/field.mjs +2 -4
- package/dist/core/field.mjs.map +1 -1
- package/dist/core/index.d.mts +4 -1
- package/dist/core/radio-group.mjs +1 -1
- package/dist/core/select.mjs +28 -23
- package/dist/core/select.mjs.map +1 -1
- package/dist/core/tabs.d.mts +9 -0
- package/dist/core/tabs.d.mts.map +1 -0
- package/dist/core/tabs.mjs +59 -0
- package/dist/core/tabs.mjs.map +1 -0
- package/dist/core/tooltip.d.mts +2 -0
- package/dist/core/tooltip.mjs +41 -0
- package/dist/core/tooltip.mjs.map +1 -0
- package/dist/index.d.mts +40 -29
- package/dist/index.mjs +12 -2
- package/dist/lib/z-layers.mjs +21 -0
- package/dist/lib/z-layers.mjs.map +1 -1
- package/dist/providers/config/dark-mode.mjs +2 -10
- package/dist/providers/config/dark-mode.mjs.map +1 -1
- package/dist/style.css +388 -16
- package/package.json +42 -2
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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":"
|
|
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
|
|
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\
|
|
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,
|
|
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;
|
|
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 = {
|