@jbpark/ui-kit 10.0.1 → 10.1.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 +40 -25
- package/README.md +40 -25
- 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/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/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 +2 -1
- 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 +1 -1
- package/dist/components/atoms/float-button/back-top.mjs +1 -1
- package/dist/components/atoms/index.d.mts +2 -1
- package/dist/components/atoms/input/search.mjs +3 -1
- package/dist/components/atoms/input/search.mjs.map +1 -1
- package/dist/components/atoms/popover.mjs +1 -1
- package/dist/components/atoms/radio/group.mjs +1 -1
- package/dist/components/atoms/radio/radio.mjs +2 -1
- package/dist/components/atoms/radio/radio.mjs.map +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 +11 -1
- package/dist/components/atoms/select.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/dropdown.mjs +1 -1
- package/dist/components/molecules/index.d.mts +13 -10
- package/dist/components/molecules/marquees/marquees.mjs +1 -1
- package/dist/components/molecules/menu/menu.mjs +2 -1
- package/dist/components/molecules/menu/menu.mjs.map +1 -1
- package/dist/components/molecules/tabs.d.mts +37 -0
- package/dist/components/molecules/tabs.d.mts.map +1 -0
- package/dist/components/molecules/tabs.mjs +51 -0
- package/dist/components/molecules/tabs.mjs.map +1 -0
- package/dist/components/molecules/upload.mjs +2 -1
- package/dist/components/molecules/upload.mjs.map +1 -1
- package/dist/components/organisms/drawer.d.mts.map +1 -1
- package/dist/components/organisms/drawer.mjs +7 -2
- 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 +7 -4
- 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 +2 -1
- 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 +3 -1
- 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/badge.d.mts +1 -1
- package/dist/core/button.d.mts +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.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/select.mjs +27 -22
- 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 +31 -26
- package/dist/index.mjs +7 -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 +195 -16
- package/package.json +17 -2
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "./utils.mjs";
|
|
3
|
+
import { useConfig } from "./providers/config/context.mjs";
|
|
4
|
+
import Button from "./Button.mjs";
|
|
5
|
+
import Input from "./components/atoms/input/index.mjs";
|
|
6
|
+
import Select from "./components/atoms/select.mjs";
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
//#region src/components/molecules/pagination.tsx
|
|
11
|
+
const clampPage = (page, pageCount) => Math.min(Math.max(1, Number.isFinite(page) ? Math.floor(page) : 1), Math.max(1, pageCount));
|
|
12
|
+
const normalizePageSize = (value) => Number.isFinite(value) && value >= 1 ? Math.floor(value) : 10;
|
|
13
|
+
const getPageItems = (page, pageCount, siblingCount, boundaryCount) => {
|
|
14
|
+
if (pageCount === 0) return [];
|
|
15
|
+
const pages = /* @__PURE__ */ new Set();
|
|
16
|
+
for (let index = 1; index <= boundaryCount && index <= pageCount; index++) {
|
|
17
|
+
pages.add(index);
|
|
18
|
+
pages.add(pageCount - index + 1);
|
|
19
|
+
}
|
|
20
|
+
for (let index = Math.max(1, page - siblingCount); index <= Math.min(pageCount, page + siblingCount); index++) pages.add(index);
|
|
21
|
+
const sorted = [...pages].sort((a, b) => a - b);
|
|
22
|
+
const items = [];
|
|
23
|
+
let previous = 0;
|
|
24
|
+
for (const current of sorted) {
|
|
25
|
+
const gap = current - previous;
|
|
26
|
+
if (gap === 2) items.push(previous + 1);
|
|
27
|
+
else if (gap > 2) items.push("start-ellipsis");
|
|
28
|
+
items.push(current);
|
|
29
|
+
previous = current;
|
|
30
|
+
}
|
|
31
|
+
const finalGap = pageCount - previous;
|
|
32
|
+
if (finalGap === 1) items.push(pageCount);
|
|
33
|
+
else if (finalGap > 1) items.push("end-ellipsis");
|
|
34
|
+
return items;
|
|
35
|
+
};
|
|
36
|
+
const Pagination = ({ total, pageSize, defaultPageSize = 10, onPageSizeChange, pageSizeOptions = [
|
|
37
|
+
10,
|
|
38
|
+
20,
|
|
39
|
+
50,
|
|
40
|
+
100
|
|
41
|
+
], showSizeChanger = false, showTotal, showQuickJumper = false, page, defaultPage = 1, onChange, siblingCount = 1, boundaryCount = 1, showFirstLast = false, hideOnSinglePage = false, getPageHref, disabled = false, size, labels, className, classNames, "aria-label": ariaLabel, ...props }) => {
|
|
42
|
+
const { componentSize, direction } = useConfig();
|
|
43
|
+
const safeTotal = Number.isFinite(total) ? Math.max(0, Math.floor(total)) : 0;
|
|
44
|
+
const [internalPageSize, setInternalPageSize] = useState(() => normalizePageSize(defaultPageSize));
|
|
45
|
+
const safePageSize = normalizePageSize(pageSize ?? internalPageSize);
|
|
46
|
+
const pageCount = Math.ceil(safeTotal / safePageSize);
|
|
47
|
+
const [jumpValue, setJumpValue] = useState("");
|
|
48
|
+
const [internal, setInternal] = useState({
|
|
49
|
+
page: clampPage(defaultPage, pageCount),
|
|
50
|
+
pageCount
|
|
51
|
+
});
|
|
52
|
+
if (page === void 0 && internal.pageCount !== pageCount) setInternal({
|
|
53
|
+
page: clampPage(internal.page, pageCount),
|
|
54
|
+
pageCount
|
|
55
|
+
});
|
|
56
|
+
const currentPage = clampPage(page ?? internal.page, pageCount);
|
|
57
|
+
const resolvedSize = size ?? componentSize ?? "middle";
|
|
58
|
+
const items = getPageItems(currentPage, pageCount, Number.isFinite(siblingCount) ? Math.max(0, Math.floor(siblingCount)) : 1, Number.isFinite(boundaryCount) ? Math.max(0, Math.floor(boundaryCount)) : 1);
|
|
59
|
+
const sizeOptions = Array.from(new Set([...pageSizeOptions, safePageSize].filter((value) => Number.isInteger(value) && value > 0))).sort((a, b) => a - b);
|
|
60
|
+
const range = safeTotal === 0 ? [0, 0] : [(currentPage - 1) * safePageSize + 1, Math.min(currentPage * safePageSize, safeTotal)];
|
|
61
|
+
const goToPage = (next) => {
|
|
62
|
+
if (disabled || pageCount === 0 || next < 1 || next > pageCount || next === currentPage) return;
|
|
63
|
+
if (page === void 0) setInternal({
|
|
64
|
+
page: next,
|
|
65
|
+
pageCount
|
|
66
|
+
});
|
|
67
|
+
onChange?.(next);
|
|
68
|
+
};
|
|
69
|
+
const changePageSize = (next) => {
|
|
70
|
+
if (disabled || next === safePageSize) return;
|
|
71
|
+
if (pageSize === void 0) setInternalPageSize(next);
|
|
72
|
+
if (page === void 0) setInternal({
|
|
73
|
+
page: 1,
|
|
74
|
+
pageCount: Math.ceil(safeTotal / next)
|
|
75
|
+
});
|
|
76
|
+
onPageSizeChange?.(next);
|
|
77
|
+
if (currentPage !== 1) onChange?.(1);
|
|
78
|
+
};
|
|
79
|
+
const jumpToPage = (event) => {
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
if (!/^\d+$/.test(jumpValue.trim())) return;
|
|
82
|
+
const next = Number(jumpValue.trim());
|
|
83
|
+
if (!Number.isSafeInteger(next) || next < 1 || next > pageCount) return;
|
|
84
|
+
goToPage(next);
|
|
85
|
+
setJumpValue("");
|
|
86
|
+
};
|
|
87
|
+
const handlePageClick = (next, event) => {
|
|
88
|
+
if (getPageHref && (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0)) return;
|
|
89
|
+
if (getPageHref && next === currentPage) event.preventDefault();
|
|
90
|
+
goToPage(next);
|
|
91
|
+
};
|
|
92
|
+
const linkProps = (target, isDisabled) => getPageHref && !isDisabled ? {
|
|
93
|
+
render: /* @__PURE__ */ jsx("a", { href: getPageHref(target) }),
|
|
94
|
+
nativeButton: false,
|
|
95
|
+
role: "link"
|
|
96
|
+
} : {};
|
|
97
|
+
if (hideOnSinglePage && pageCount <= 1) return null;
|
|
98
|
+
return /* @__PURE__ */ jsxs("nav", {
|
|
99
|
+
...props,
|
|
100
|
+
"data-slot": "pagination",
|
|
101
|
+
"aria-label": ariaLabel ?? labels?.navigation ?? "Pagination",
|
|
102
|
+
className: cn("flex flex-wrap items-center gap-1", className),
|
|
103
|
+
children: [
|
|
104
|
+
showTotal && /* @__PURE__ */ jsx("span", {
|
|
105
|
+
"data-slot": "pagination-total",
|
|
106
|
+
className: cn("text-muted-foreground me-2 text-sm", classNames?.total),
|
|
107
|
+
children: showTotal(safeTotal, range)
|
|
108
|
+
}),
|
|
109
|
+
showFirstLast && /* @__PURE__ */ jsx(Button, {
|
|
110
|
+
...linkProps(1, disabled || pageCount === 0 || currentPage === 1),
|
|
111
|
+
icon: direction === "rtl" ? /* @__PURE__ */ jsx(ChevronsRight, {}) : /* @__PURE__ */ jsx(ChevronsLeft, {}),
|
|
112
|
+
size: resolvedSize,
|
|
113
|
+
variant: "outlined",
|
|
114
|
+
"aria-label": labels?.first ?? "First page",
|
|
115
|
+
disabled: disabled || pageCount === 0 || currentPage === 1,
|
|
116
|
+
className: cn(classNames?.item, classNames?.first),
|
|
117
|
+
onClick: (event) => handlePageClick(1, event)
|
|
118
|
+
}),
|
|
119
|
+
/* @__PURE__ */ jsx(Button, {
|
|
120
|
+
...linkProps(currentPage - 1, disabled || pageCount === 0 || currentPage === 1),
|
|
121
|
+
icon: direction === "rtl" ? /* @__PURE__ */ jsx(ChevronRight, {}) : /* @__PURE__ */ jsx(ChevronLeft, {}),
|
|
122
|
+
size: resolvedSize,
|
|
123
|
+
variant: "outlined",
|
|
124
|
+
"aria-label": labels?.previous ?? "Previous page",
|
|
125
|
+
disabled: disabled || pageCount === 0 || currentPage === 1,
|
|
126
|
+
className: cn(classNames?.item, classNames?.previous),
|
|
127
|
+
onClick: (event) => handlePageClick(currentPage - 1, event)
|
|
128
|
+
}),
|
|
129
|
+
items.map((item, index) => typeof item === "number" ? /* @__PURE__ */ jsx(Button, {
|
|
130
|
+
...linkProps(item, disabled),
|
|
131
|
+
size: resolvedSize,
|
|
132
|
+
variant: item === currentPage ? "solid" : "outlined",
|
|
133
|
+
color: item === currentPage ? "primary" : "default",
|
|
134
|
+
"aria-current": item === currentPage ? "page" : void 0,
|
|
135
|
+
"aria-label": labels?.page?.(item) ?? `Page ${item}`,
|
|
136
|
+
disabled,
|
|
137
|
+
className: cn("min-w-8", classNames?.item, item === currentPage && classNames?.active),
|
|
138
|
+
onClick: (event) => handlePageClick(item, event),
|
|
139
|
+
children: item
|
|
140
|
+
}, item) : /* @__PURE__ */ jsx("span", {
|
|
141
|
+
"aria-hidden": "true",
|
|
142
|
+
className: cn(`text-muted-foreground inline-flex min-w-6 items-center
|
|
143
|
+
justify-center`, classNames?.ellipsis),
|
|
144
|
+
children: "…"
|
|
145
|
+
}, `${item}-${index}`)),
|
|
146
|
+
/* @__PURE__ */ jsx(Button, {
|
|
147
|
+
...linkProps(currentPage + 1, disabled || pageCount === 0 || currentPage === pageCount),
|
|
148
|
+
icon: direction === "rtl" ? /* @__PURE__ */ jsx(ChevronLeft, {}) : /* @__PURE__ */ jsx(ChevronRight, {}),
|
|
149
|
+
size: resolvedSize,
|
|
150
|
+
variant: "outlined",
|
|
151
|
+
"aria-label": labels?.next ?? "Next page",
|
|
152
|
+
disabled: disabled || pageCount === 0 || currentPage === pageCount,
|
|
153
|
+
className: cn(classNames?.item, classNames?.next),
|
|
154
|
+
onClick: (event) => handlePageClick(currentPage + 1, event)
|
|
155
|
+
}),
|
|
156
|
+
showFirstLast && /* @__PURE__ */ jsx(Button, {
|
|
157
|
+
...linkProps(pageCount, disabled || pageCount === 0 || currentPage === pageCount),
|
|
158
|
+
icon: direction === "rtl" ? /* @__PURE__ */ jsx(ChevronsLeft, {}) : /* @__PURE__ */ jsx(ChevronsRight, {}),
|
|
159
|
+
size: resolvedSize,
|
|
160
|
+
variant: "outlined",
|
|
161
|
+
"aria-label": labels?.last ?? "Last page",
|
|
162
|
+
disabled: disabled || pageCount === 0 || currentPage === pageCount,
|
|
163
|
+
className: cn(classNames?.item, classNames?.last),
|
|
164
|
+
onClick: (event) => handlePageClick(pageCount, event)
|
|
165
|
+
}),
|
|
166
|
+
showSizeChanger && /* @__PURE__ */ jsx("div", {
|
|
167
|
+
"data-slot": "pagination-size-changer",
|
|
168
|
+
className: cn("ms-2 min-w-24", classNames?.sizeChanger),
|
|
169
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
170
|
+
value: String(safePageSize),
|
|
171
|
+
options: sizeOptions.map((value) => ({
|
|
172
|
+
value: String(value),
|
|
173
|
+
label: `${value} / page`
|
|
174
|
+
})),
|
|
175
|
+
onChange: (value) => changePageSize(Number(value)),
|
|
176
|
+
disabled,
|
|
177
|
+
"aria-label": labels?.pageSize ?? "Items per page"
|
|
178
|
+
})
|
|
179
|
+
}),
|
|
180
|
+
showQuickJumper && /* @__PURE__ */ jsxs("form", {
|
|
181
|
+
"data-slot": "pagination-jumper",
|
|
182
|
+
className: cn("ms-2 flex items-center gap-1", classNames?.jumper),
|
|
183
|
+
onSubmit: jumpToPage,
|
|
184
|
+
noValidate: true,
|
|
185
|
+
children: [/* @__PURE__ */ jsx(Input, {
|
|
186
|
+
type: "text",
|
|
187
|
+
inputMode: "numeric",
|
|
188
|
+
autoComplete: "off",
|
|
189
|
+
"aria-label": labels?.jump ?? "Jump to page",
|
|
190
|
+
value: jumpValue,
|
|
191
|
+
onChange: (event) => setJumpValue(event.target.value),
|
|
192
|
+
disabled: disabled || pageCount === 0,
|
|
193
|
+
className: "w-16"
|
|
194
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
195
|
+
htmlType: "submit",
|
|
196
|
+
size: resolvedSize,
|
|
197
|
+
variant: "outlined",
|
|
198
|
+
disabled: disabled || pageCount === 0,
|
|
199
|
+
children: labels?.go ?? "Go"
|
|
200
|
+
})]
|
|
201
|
+
})
|
|
202
|
+
]
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
//#endregion
|
|
206
|
+
export { Pagination as default };
|
|
207
|
+
|
|
208
|
+
//# sourceMappingURL=Pagination.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pagination.mjs","names":[],"sources":["../src/components/molecules/pagination.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\n\nimport {\n ChevronLeft,\n ChevronRight,\n ChevronsLeft,\n ChevronsRight,\n} from 'lucide-react';\n\nimport { useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\nimport Input from '../atoms/input';\nimport Select from '../atoms/select';\n\ntype PageItem = number | 'start-ellipsis' | 'end-ellipsis';\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'nav'>,\n 'children' | 'onChange'\n> {\n /** Total number of items, not pages. */\n total: number;\n /** Controlled number of items per page. */\n pageSize?: number;\n defaultPageSize?: number;\n onPageSizeChange?: (pageSize: number) => void;\n pageSizeOptions?: number[];\n showSizeChanger?: boolean;\n /** Render the total and the 1-based inclusive range of visible items. */\n showTotal?: (total: number, range: [number, number]) => React.ReactNode;\n showQuickJumper?: boolean;\n /** 1-based controlled page. */\n page?: number;\n defaultPage?: number;\n onChange?: (page: number) => void;\n siblingCount?: number;\n boundaryCount?: number;\n showFirstLast?: boolean;\n hideOnSinglePage?: boolean;\n /** Render available page controls as links to these URLs. */\n getPageHref?: (page: number) => string;\n disabled?: boolean;\n size?: 'small' | 'middle' | 'large';\n labels?: {\n navigation?: string;\n page?: (page: number) => string;\n previous?: string;\n next?: string;\n first?: string;\n last?: string;\n pageSize?: string;\n jump?: string;\n go?: string;\n };\n classNames?: {\n item?: string;\n active?: string;\n previous?: string;\n next?: string;\n first?: string;\n last?: string;\n ellipsis?: string;\n total?: string;\n sizeChanger?: string;\n jumper?: string;\n };\n}\n\nconst clampPage = (page: number, pageCount: number) =>\n Math.min(\n Math.max(1, Number.isFinite(page) ? Math.floor(page) : 1),\n Math.max(1, pageCount),\n );\n\nconst normalizePageSize = (value: number) =>\n Number.isFinite(value) && value >= 1 ? Math.floor(value) : 10;\n\nconst getPageItems = (\n page: number,\n pageCount: number,\n siblingCount: number,\n boundaryCount: number,\n): PageItem[] => {\n if (pageCount === 0) {\n return [];\n }\n\n const pages = new Set<number>();\n\n for (let index = 1; index <= boundaryCount && index <= pageCount; index++) {\n pages.add(index);\n pages.add(pageCount - index + 1);\n }\n\n for (\n let index = Math.max(1, page - siblingCount);\n index <= Math.min(pageCount, page + siblingCount);\n index++\n ) {\n pages.add(index);\n }\n\n const sorted = [...pages].sort((a, b) => a - b);\n const items: PageItem[] = [];\n let previous = 0;\n\n for (const current of sorted) {\n const gap = current - previous;\n\n if (gap === 2) {\n items.push(previous + 1);\n } else if (gap > 2) {\n items.push('start-ellipsis');\n }\n\n items.push(current);\n previous = current;\n }\n\n const finalGap = pageCount - previous;\n\n if (finalGap === 1) {\n items.push(pageCount);\n } else if (finalGap > 1) {\n items.push('end-ellipsis');\n }\n\n return items;\n};\n\nconst Pagination = ({\n total,\n pageSize,\n defaultPageSize = 10,\n onPageSizeChange,\n pageSizeOptions = [10, 20, 50, 100],\n showSizeChanger = false,\n showTotal,\n showQuickJumper = false,\n page,\n defaultPage = 1,\n onChange,\n siblingCount = 1,\n boundaryCount = 1,\n showFirstLast = false,\n hideOnSinglePage = false,\n getPageHref,\n disabled = false,\n size,\n labels,\n className,\n classNames,\n 'aria-label': ariaLabel,\n ...props\n}: Props) => {\n const { componentSize, direction } = useConfig();\n const safeTotal = Number.isFinite(total) ? Math.max(0, Math.floor(total)) : 0;\n const [internalPageSize, setInternalPageSize] = useState(() =>\n normalizePageSize(defaultPageSize),\n );\n const safePageSize = normalizePageSize(pageSize ?? internalPageSize);\n const pageCount = Math.ceil(safeTotal / safePageSize);\n const [jumpValue, setJumpValue] = useState('');\n const [internal, setInternal] = useState({\n page: clampPage(defaultPage, pageCount),\n pageCount,\n });\n\n // React retries this render with the adjusted state when the available\n // range changes. Controlled callers still own their page prop.\n if (page === undefined && internal.pageCount !== pageCount) {\n setInternal({ page: clampPage(internal.page, pageCount), pageCount });\n }\n\n const currentPage = clampPage(page ?? internal.page, pageCount);\n const resolvedSize = size ?? componentSize ?? 'middle';\n const safeSiblingCount = Number.isFinite(siblingCount)\n ? Math.max(0, Math.floor(siblingCount))\n : 1;\n const safeBoundaryCount = Number.isFinite(boundaryCount)\n ? Math.max(0, Math.floor(boundaryCount))\n : 1;\n const items = getPageItems(\n currentPage,\n pageCount,\n safeSiblingCount,\n safeBoundaryCount,\n );\n const sizeOptions = Array.from(\n new Set(\n [...pageSizeOptions, safePageSize].filter(\n value => Number.isInteger(value) && value > 0,\n ),\n ),\n ).sort((a, b) => a - b);\n const range: [number, number] =\n safeTotal === 0\n ? [0, 0]\n : [\n (currentPage - 1) * safePageSize + 1,\n Math.min(currentPage * safePageSize, safeTotal),\n ];\n\n const goToPage = (next: number) => {\n if (\n disabled ||\n pageCount === 0 ||\n next < 1 ||\n next > pageCount ||\n next === currentPage\n ) {\n return;\n }\n\n if (page === undefined) {\n setInternal({ page: next, pageCount });\n }\n\n onChange?.(next);\n };\n\n const changePageSize = (next: number) => {\n if (disabled || next === safePageSize) {\n return;\n }\n\n if (pageSize === undefined) {\n setInternalPageSize(next);\n }\n\n if (page === undefined) {\n setInternal({ page: 1, pageCount: Math.ceil(safeTotal / next) });\n }\n\n onPageSizeChange?.(next);\n\n if (currentPage !== 1) {\n onChange?.(1);\n }\n };\n\n const jumpToPage = (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n if (!/^\\d+$/.test(jumpValue.trim())) {\n return;\n }\n\n const next = Number(jumpValue.trim());\n\n if (!Number.isSafeInteger(next) || next < 1 || next > pageCount) {\n return;\n }\n\n goToPage(next);\n setJumpValue('');\n };\n\n const handlePageClick = (next: number, event: React.MouseEvent) => {\n if (\n getPageHref &&\n (event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey ||\n event.button !== 0)\n ) {\n return;\n }\n\n if (getPageHref && next === currentPage) {\n event.preventDefault();\n }\n\n goToPage(next);\n };\n\n const linkProps = (target: number, isDisabled: boolean) =>\n getPageHref && !isDisabled\n ? {\n render: <a href={getPageHref(target)} />,\n nativeButton: false,\n role: 'link',\n }\n : {};\n\n if (hideOnSinglePage && pageCount <= 1) {\n return null;\n }\n\n return (\n <nav\n {...props}\n data-slot=\"pagination\"\n aria-label={ariaLabel ?? labels?.navigation ?? 'Pagination'}\n className={cn(\n 'flex flex-wrap items-center gap-1',\n className,\n //\n )}\n >\n {showTotal && (\n <span\n data-slot=\"pagination-total\"\n className={cn(\n 'text-muted-foreground me-2 text-sm',\n classNames?.total,\n //\n )}\n >\n {showTotal(safeTotal, range)}\n </span>\n )}\n {showFirstLast && (\n <Button\n {...linkProps(1, disabled || pageCount === 0 || currentPage === 1)}\n icon={direction === 'rtl' ? <ChevronsRight /> : <ChevronsLeft />}\n size={resolvedSize}\n variant=\"outlined\"\n aria-label={labels?.first ?? 'First page'}\n disabled={disabled || pageCount === 0 || currentPage === 1}\n className={cn(\n classNames?.item,\n classNames?.first,\n //\n )}\n onClick={event => handlePageClick(1, event)}\n />\n )}\n <Button\n {...linkProps(\n currentPage - 1,\n disabled || pageCount === 0 || currentPage === 1,\n )}\n icon={direction === 'rtl' ? <ChevronRight /> : <ChevronLeft />}\n size={resolvedSize}\n variant=\"outlined\"\n aria-label={labels?.previous ?? 'Previous page'}\n disabled={disabled || pageCount === 0 || currentPage === 1}\n className={cn(\n classNames?.item,\n classNames?.previous,\n //\n )}\n onClick={event => handlePageClick(currentPage - 1, event)}\n />\n {items.map((item, index) =>\n typeof item === 'number' ? (\n <Button\n key={item}\n {...linkProps(item, disabled)}\n size={resolvedSize}\n variant={item === currentPage ? 'solid' : 'outlined'}\n color={item === currentPage ? 'primary' : 'default'}\n aria-current={item === currentPage ? 'page' : undefined}\n aria-label={labels?.page?.(item) ?? `Page ${item}`}\n disabled={disabled}\n className={cn(\n 'min-w-8',\n classNames?.item,\n item === currentPage && classNames?.active,\n //\n )}\n onClick={event => handlePageClick(item, event)}\n >\n {item}\n </Button>\n ) : (\n <span\n key={`${item}-${index}`}\n aria-hidden=\"true\"\n className={cn(\n `text-muted-foreground inline-flex min-w-6 items-center\n justify-center`,\n classNames?.ellipsis,\n //\n )}\n >\n …\n </span>\n ),\n )}\n <Button\n {...linkProps(\n currentPage + 1,\n disabled || pageCount === 0 || currentPage === pageCount,\n )}\n icon={direction === 'rtl' ? <ChevronLeft /> : <ChevronRight />}\n size={resolvedSize}\n variant=\"outlined\"\n aria-label={labels?.next ?? 'Next page'}\n disabled={disabled || pageCount === 0 || currentPage === pageCount}\n className={cn(\n classNames?.item,\n classNames?.next,\n //\n )}\n onClick={event => handlePageClick(currentPage + 1, event)}\n />\n {showFirstLast && (\n <Button\n {...linkProps(\n pageCount,\n disabled || pageCount === 0 || currentPage === pageCount,\n )}\n icon={direction === 'rtl' ? <ChevronsLeft /> : <ChevronsRight />}\n size={resolvedSize}\n variant=\"outlined\"\n aria-label={labels?.last ?? 'Last page'}\n disabled={disabled || pageCount === 0 || currentPage === pageCount}\n className={cn(\n classNames?.item,\n classNames?.last,\n //\n )}\n onClick={event => handlePageClick(pageCount, event)}\n />\n )}\n {showSizeChanger && (\n <div\n data-slot=\"pagination-size-changer\"\n className={cn(\n 'ms-2 min-w-24',\n classNames?.sizeChanger,\n //\n )}\n >\n <Select\n value={String(safePageSize)}\n options={sizeOptions.map(value => ({\n value: String(value),\n label: `${value} / page`,\n }))}\n onChange={value => changePageSize(Number(value))}\n disabled={disabled}\n aria-label={labels?.pageSize ?? 'Items per page'}\n />\n </div>\n )}\n {showQuickJumper && (\n <form\n data-slot=\"pagination-jumper\"\n className={cn(\n 'ms-2 flex items-center gap-1',\n classNames?.jumper,\n //\n )}\n onSubmit={jumpToPage}\n noValidate\n >\n <Input\n type=\"text\"\n inputMode=\"numeric\"\n autoComplete=\"off\"\n aria-label={labels?.jump ?? 'Jump to page'}\n value={jumpValue}\n onChange={event => setJumpValue(event.target.value)}\n disabled={disabled || pageCount === 0}\n className=\"w-16\"\n />\n <Button\n htmlType=\"submit\"\n size={resolvedSize}\n variant=\"outlined\"\n disabled={disabled || pageCount === 0}\n >\n {labels?.go ?? 'Go'}\n </Button>\n </form>\n )}\n </nav>\n );\n};\n\nexport default Pagination;\n"],"mappings":";;;;;;;;;;AAwEA,MAAM,aAAa,MAAc,cAC/B,KAAK,IACH,KAAK,IAAI,GAAG,OAAO,SAAS,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,GACxD,KAAK,IAAI,GAAG,SAAS,CACvB;AAEF,MAAM,qBAAqB,UACzB,OAAO,SAAS,KAAK,KAAK,SAAS,IAAI,KAAK,MAAM,KAAK,IAAI;AAE7D,MAAM,gBACJ,MACA,WACA,cACA,kBACe;CACf,IAAI,cAAc,GAChB,OAAO,CAAC;CAGV,MAAM,wBAAQ,IAAI,IAAY;CAE9B,KAAK,IAAI,QAAQ,GAAG,SAAS,iBAAiB,SAAS,WAAW,SAAS;EACzE,MAAM,IAAI,KAAK;EACf,MAAM,IAAI,YAAY,QAAQ,CAAC;CACjC;CAEA,KACE,IAAI,QAAQ,KAAK,IAAI,GAAG,OAAO,YAAY,GAC3C,SAAS,KAAK,IAAI,WAAW,OAAO,YAAY,GAChD,SAEA,MAAM,IAAI,KAAK;CAGjB,MAAM,SAAS,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CAC9C,MAAM,QAAoB,CAAC;CAC3B,IAAI,WAAW;CAEf,KAAK,MAAM,WAAW,QAAQ;EAC5B,MAAM,MAAM,UAAU;EAEtB,IAAI,QAAQ,GACV,MAAM,KAAK,WAAW,CAAC;OAClB,IAAI,MAAM,GACf,MAAM,KAAK,gBAAgB;EAG7B,MAAM,KAAK,OAAO;EAClB,WAAW;CACb;CAEA,MAAM,WAAW,YAAY;CAE7B,IAAI,aAAa,GACf,MAAM,KAAK,SAAS;MACf,IAAI,WAAW,GACpB,MAAM,KAAK,cAAc;CAG3B,OAAO;AACT;AAEA,MAAM,cAAc,EAClB,OACA,UACA,kBAAkB,IAClB,kBACA,kBAAkB;CAAC;CAAI;CAAI;CAAI;AAAG,GAClC,kBAAkB,OAClB,WACA,kBAAkB,OAClB,MACA,cAAc,GACd,UACA,eAAe,GACf,gBAAgB,GAChB,gBAAgB,OAChB,mBAAmB,OACnB,aACA,WAAW,OACX,MACA,QACA,WACA,YACA,cAAc,WACd,GAAG,YACQ;CACX,MAAM,EAAE,eAAe,cAAc,UAAU;CAC/C,MAAM,YAAY,OAAO,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC,IAAI;CAC5E,MAAM,CAAC,kBAAkB,uBAAuB,eAC9C,kBAAkB,eAAe,CACnC;CACA,MAAM,eAAe,kBAAkB,YAAY,gBAAgB;CACnE,MAAM,YAAY,KAAK,KAAK,YAAY,YAAY;CACpD,MAAM,CAAC,WAAW,gBAAgB,SAAS,EAAE;CAC7C,MAAM,CAAC,UAAU,eAAe,SAAS;EACvC,MAAM,UAAU,aAAa,SAAS;EACtC;CACF,CAAC;CAID,IAAI,SAAS,KAAA,KAAa,SAAS,cAAc,WAC/C,YAAY;EAAE,MAAM,UAAU,SAAS,MAAM,SAAS;EAAG;CAAU,CAAC;CAGtE,MAAM,cAAc,UAAU,QAAQ,SAAS,MAAM,SAAS;CAC9D,MAAM,eAAe,QAAQ,iBAAiB;CAO9C,MAAM,QAAQ,aACZ,aACA,WARuB,OAAO,SAAS,YAAY,IACjD,KAAK,IAAI,GAAG,KAAK,MAAM,YAAY,CAAC,IACpC,GACsB,OAAO,SAAS,aAAa,IACnD,KAAK,IAAI,GAAG,KAAK,MAAM,aAAa,CAAC,IACrC,CAMJ;CACA,MAAM,cAAc,MAAM,KACxB,IAAI,IACF,CAAC,GAAG,iBAAiB,YAAY,CAAC,CAAC,QACjC,UAAS,OAAO,UAAU,KAAK,KAAK,QAAQ,CAC9C,CACF,CACF,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CACtB,MAAM,QACJ,cAAc,IACV,CAAC,GAAG,CAAC,IACL,EACG,cAAc,KAAK,eAAe,GACnC,KAAK,IAAI,cAAc,cAAc,SAAS,CAChD;CAEN,MAAM,YAAY,SAAiB;EACjC,IACE,YACA,cAAc,KACd,OAAO,KACP,OAAO,aACP,SAAS,aAET;EAGF,IAAI,SAAS,KAAA,GACX,YAAY;GAAE,MAAM;GAAM;EAAU,CAAC;EAGvC,WAAW,IAAI;CACjB;CAEA,MAAM,kBAAkB,SAAiB;EACvC,IAAI,YAAY,SAAS,cACvB;EAGF,IAAI,aAAa,KAAA,GACf,oBAAoB,IAAI;EAG1B,IAAI,SAAS,KAAA,GACX,YAAY;GAAE,MAAM;GAAG,WAAW,KAAK,KAAK,YAAY,IAAI;EAAE,CAAC;EAGjE,mBAAmB,IAAI;EAEvB,IAAI,gBAAgB,GAClB,WAAW,CAAC;CAEhB;CAEA,MAAM,cAAc,UAA4C;EAC9D,MAAM,eAAe;EAErB,IAAI,CAAC,QAAQ,KAAK,UAAU,KAAK,CAAC,GAChC;EAGF,MAAM,OAAO,OAAO,UAAU,KAAK,CAAC;EAEpC,IAAI,CAAC,OAAO,cAAc,IAAI,KAAK,OAAO,KAAK,OAAO,WACpD;EAGF,SAAS,IAAI;EACb,aAAa,EAAE;CACjB;CAEA,MAAM,mBAAmB,MAAc,UAA4B;EACjE,IACE,gBACC,MAAM,WACL,MAAM,WACN,MAAM,YACN,MAAM,UACN,MAAM,WAAW,IAEnB;EAGF,IAAI,eAAe,SAAS,aAC1B,MAAM,eAAe;EAGvB,SAAS,IAAI;CACf;CAEA,MAAM,aAAa,QAAgB,eACjC,eAAe,CAAC,aACZ;EACE,QAAQ,oBAAC,KAAD,EAAG,MAAM,YAAY,MAAM,EAAI,CAAA;EACvC,cAAc;EACd,MAAM;CACR,IACA,CAAC;CAEP,IAAI,oBAAoB,aAAa,GACnC,OAAO;CAGT,OACE,qBAAC,OAAD;EACE,GAAI;EACJ,aAAU;EACV,cAAY,aAAa,QAAQ,cAAc;EAC/C,WAAW,GACT,qCACA,SAEF;EARF,UAAA;GAUG,aACC,oBAAC,QAAD;IACE,aAAU;IACV,WAAW,GACT,sCACA,YAAY,KAEd;IAEC,UAAA,UAAU,WAAW,KAAK;GACvB,CAAA;GAEP,iBACC,oBAAC,QAAD;IACE,GAAI,UAAU,GAAG,YAAY,cAAc,KAAK,gBAAgB,CAAC;IACjE,MAAM,cAAc,QAAQ,oBAAC,eAAD,CAAgB,CAAA,IAAI,oBAAC,cAAD,CAAe,CAAA;IAC/D,MAAM;IACN,SAAQ;IACR,cAAY,QAAQ,SAAS;IAC7B,UAAU,YAAY,cAAc,KAAK,gBAAgB;IACzD,WAAW,GACT,YAAY,MACZ,YAAY,KAEd;IACA,UAAS,UAAS,gBAAgB,GAAG,KAAK;GAC3C,CAAA;GAEH,oBAAC,QAAD;IACE,GAAI,UACF,cAAc,GACd,YAAY,cAAc,KAAK,gBAAgB,CACjD;IACA,MAAM,cAAc,QAAQ,oBAAC,cAAD,CAAe,CAAA,IAAI,oBAAC,aAAD,CAAc,CAAA;IAC7D,MAAM;IACN,SAAQ;IACR,cAAY,QAAQ,YAAY;IAChC,UAAU,YAAY,cAAc,KAAK,gBAAgB;IACzD,WAAW,GACT,YAAY,MACZ,YAAY,QAEd;IACA,UAAS,UAAS,gBAAgB,cAAc,GAAG,KAAK;GACzD,CAAA;GACA,MAAM,KAAK,MAAM,UAChB,OAAO,SAAS,WACd,oBAAC,QAAD;IAEE,GAAI,UAAU,MAAM,QAAQ;IAC5B,MAAM;IACN,SAAS,SAAS,cAAc,UAAU;IAC1C,OAAO,SAAS,cAAc,YAAY;IAC1C,gBAAc,SAAS,cAAc,SAAS,KAAA;IAC9C,cAAY,QAAQ,OAAO,IAAI,KAAK,QAAQ;IAClC;IACV,WAAW,GACT,WACA,YAAY,MACZ,SAAS,eAAe,YAAY,MAEtC;IACA,UAAS,UAAS,gBAAgB,MAAM,KAAK;IAE5C,UAAA;GACK,GAjBD,IAiBC,IAER,oBAAC,QAAD;IAEE,eAAY;IACZ,WAAW,GACT;iCAEA,YAAY,QAEd;IACD,UAAA;GAEK,GAVC,GAAG,KAAK,GAAG,OAUZ,CAEV;GACA,oBAAC,QAAD;IACE,GAAI,UACF,cAAc,GACd,YAAY,cAAc,KAAK,gBAAgB,SACjD;IACA,MAAM,cAAc,QAAQ,oBAAC,aAAD,CAAc,CAAA,IAAI,oBAAC,cAAD,CAAe,CAAA;IAC7D,MAAM;IACN,SAAQ;IACR,cAAY,QAAQ,QAAQ;IAC5B,UAAU,YAAY,cAAc,KAAK,gBAAgB;IACzD,WAAW,GACT,YAAY,MACZ,YAAY,IAEd;IACA,UAAS,UAAS,gBAAgB,cAAc,GAAG,KAAK;GACzD,CAAA;GACA,iBACC,oBAAC,QAAD;IACE,GAAI,UACF,WACA,YAAY,cAAc,KAAK,gBAAgB,SACjD;IACA,MAAM,cAAc,QAAQ,oBAAC,cAAD,CAAe,CAAA,IAAI,oBAAC,eAAD,CAAgB,CAAA;IAC/D,MAAM;IACN,SAAQ;IACR,cAAY,QAAQ,QAAQ;IAC5B,UAAU,YAAY,cAAc,KAAK,gBAAgB;IACzD,WAAW,GACT,YAAY,MACZ,YAAY,IAEd;IACA,UAAS,UAAS,gBAAgB,WAAW,KAAK;GACnD,CAAA;GAEF,mBACC,oBAAC,OAAD;IACE,aAAU;IACV,WAAW,GACT,iBACA,YAAY,WAEd;IAEA,UAAA,oBAAC,QAAD;KACE,OAAO,OAAO,YAAY;KAC1B,SAAS,YAAY,KAAI,WAAU;MACjC,OAAO,OAAO,KAAK;MACnB,OAAO,GAAG,MAAM;KAClB,EAAE;KACF,WAAU,UAAS,eAAe,OAAO,KAAK,CAAC;KACrC;KACV,cAAY,QAAQ,YAAY;IACjC,CAAA;GACE,CAAA;GAEN,mBACC,qBAAC,QAAD;IACE,aAAU;IACV,WAAW,GACT,gCACA,YAAY,MAEd;IACA,UAAU;IACV,YAAA;IARF,UAAA,CAUE,oBAAC,OAAD;KACE,MAAK;KACL,WAAU;KACV,cAAa;KACb,cAAY,QAAQ,QAAQ;KAC5B,OAAO;KACP,WAAU,UAAS,aAAa,MAAM,OAAO,KAAK;KAClD,UAAU,YAAY,cAAc;KACpC,WAAU;IACX,CAAA,GACD,oBAAC,QAAD;KACE,UAAS;KACT,MAAM;KACN,SAAQ;KACR,UAAU,YAAY,cAAc;KAEnC,UAAA,QAAQ,MAAM;IACT,CAAA,CACJ;;EAEL;;AAET"}
|
package/dist/Table.d.mts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Props as Props$1 } from "./Pagination.mjs";
|
|
2
|
+
//#region src/components/organisms/table.d.ts
|
|
3
|
+
type PaginationOptions = Omit<Props$1, 'total'> & ({
|
|
4
|
+
mode?: 'client';
|
|
5
|
+
total?: never;
|
|
6
|
+
} | {
|
|
7
|
+
mode: 'server';
|
|
8
|
+
total: number;
|
|
9
|
+
});
|
|
10
|
+
interface Column<T> {
|
|
11
|
+
key: React.Key;
|
|
12
|
+
title: React.ReactNode;
|
|
13
|
+
/** Field displayed when render is omitted. */
|
|
14
|
+
dataIndex?: keyof T;
|
|
15
|
+
render?: (record: T, index: number) => React.ReactNode;
|
|
16
|
+
align?: 'left' | 'center' | 'right';
|
|
17
|
+
width?: string | number;
|
|
18
|
+
className?: string;
|
|
19
|
+
headerClassName?: string;
|
|
20
|
+
}
|
|
21
|
+
interface Props<T> extends Omit<React.ComponentPropsWithoutRef<'table'>, 'children'> {
|
|
22
|
+
columns: Column<T>[];
|
|
23
|
+
data?: T[];
|
|
24
|
+
/** Use a stable key when rows may be reordered or paged. */
|
|
25
|
+
rowKey?: (record: T, index: number) => React.Key;
|
|
26
|
+
caption?: React.ReactNode;
|
|
27
|
+
loading?: boolean;
|
|
28
|
+
empty?: React.ReactNode;
|
|
29
|
+
size?: 'small' | 'middle' | 'large';
|
|
30
|
+
bordered?: boolean;
|
|
31
|
+
striped?: boolean;
|
|
32
|
+
hoverable?: boolean;
|
|
33
|
+
/** true paginates data locally; server mode expects current-page data. */
|
|
34
|
+
pagination?: boolean | PaginationOptions;
|
|
35
|
+
classNames?: {
|
|
36
|
+
container?: string;
|
|
37
|
+
header?: string;
|
|
38
|
+
body?: string;
|
|
39
|
+
row?: string;
|
|
40
|
+
cell?: string;
|
|
41
|
+
empty?: string;
|
|
42
|
+
pagination?: string;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
declare const Table: <T>({ columns, data, rowKey, loading, empty, size, bordered, striped, hoverable, pagination, caption, className, classNames, ...props }: Props<T>) => import("react").JSX.Element;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { Column, PaginationOptions, Props, Table as default };
|
|
48
|
+
//# sourceMappingURL=Table.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Table.d.mts","names":[],"sources":["../src/components/organisms/table.tsx"],"mappings":";;KAaY,oBAAoB,KAAK;EAChC;EAAiB;;EAAoB;EAAgB;;UAEzC,OAAO;EACtB,KAAK,MAAM;EACX,OAAO,MAAM;;EAEb,kBAAkB;EAClB,UAAU,QAAQ,GAAG,kBAAkB,MAAM;EAC7C;EACA;EACA;EACA;;UAGe,MAAM,WAAW,KAChC,MAAM;EAGN,SAAS,OAAO;EAChB,OAAO;;EAEP,UAAU,QAAQ,GAAG,kBAAkB,MAAM;EAC7C,UAAU,MAAM;EAChB;EACA,QAAQ,MAAM;EACd;EACA;EACA;EACA;;EAEA,uBAAuB;EACvB;IACE;IACA;IACA;IACA;IACA;IACA;IACA;;;cAaE,QAAS,KAAI,SAAA,MAAA,QAAA,SAAA,OAAA,MAAA,UAAA,SAAA,WAAA,YAAA,SAAA,WAAA,eAAA,SAehB,MAAM,uBAAE,IAAA"}
|
package/dist/Table.mjs
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "./utils.mjs";
|
|
3
|
+
import { useConfig } from "./providers/config/context.mjs";
|
|
4
|
+
import Skeleton from "./components/atoms/skeleton/index.mjs";
|
|
5
|
+
import Pagination from "./Pagination.mjs";
|
|
6
|
+
import Empty from "./components/templates/empty.mjs";
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
//#region src/components/organisms/table.tsx
|
|
10
|
+
const clampPage = (page, pageCount) => Math.min(Math.max(1, Number.isFinite(page) ? Math.floor(page) : 1), Math.max(1, pageCount));
|
|
11
|
+
const normalizePageSize = (value) => Number.isFinite(value) && value >= 1 ? Math.floor(value) : 10;
|
|
12
|
+
const Table = ({ columns, data = [], rowKey, loading = false, empty, size, bordered = false, striped = false, hoverable = true, pagination = false, caption, className, classNames, ...props }) => {
|
|
13
|
+
const { componentSize } = useConfig();
|
|
14
|
+
const { mode = "client", total: serverTotal, page: controlledPage, defaultPage = 1, pageSize: controlledPageSize, defaultPageSize = 10, onChange, onPageSizeChange, ...paginationProps } = typeof pagination === "object" ? pagination : {};
|
|
15
|
+
const [internal, setInternal] = useState(() => ({
|
|
16
|
+
page: defaultPage,
|
|
17
|
+
pageSize: normalizePageSize(defaultPageSize),
|
|
18
|
+
pageCount: 0
|
|
19
|
+
}));
|
|
20
|
+
const pageSize = normalizePageSize(controlledPageSize ?? internal.pageSize);
|
|
21
|
+
const total = mode === "server" ? serverTotal ?? 0 : data.length;
|
|
22
|
+
const pageCount = Math.ceil(total / pageSize);
|
|
23
|
+
if (pagination && controlledPage === void 0 && internal.pageCount !== pageCount) setInternal((current) => ({
|
|
24
|
+
...current,
|
|
25
|
+
page: clampPage(current.page, pageCount),
|
|
26
|
+
pageCount
|
|
27
|
+
}));
|
|
28
|
+
const page = clampPage(controlledPage ?? internal.page, pageCount);
|
|
29
|
+
const visibleData = pagination && mode === "client" ? data.slice((page - 1) * pageSize, page * pageSize) : data;
|
|
30
|
+
const cellPadding = {
|
|
31
|
+
small: "px-3 py-2",
|
|
32
|
+
middle: "px-4 py-3",
|
|
33
|
+
large: "px-5 py-4"
|
|
34
|
+
}[size ?? componentSize ?? "middle"];
|
|
35
|
+
const handlePageChange = (next) => {
|
|
36
|
+
if (controlledPage === void 0) setInternal((current) => ({
|
|
37
|
+
...current,
|
|
38
|
+
page: next
|
|
39
|
+
}));
|
|
40
|
+
onChange?.(next);
|
|
41
|
+
};
|
|
42
|
+
const handlePageSizeChange = (next) => {
|
|
43
|
+
if (controlledPageSize === void 0 || controlledPage === void 0) setInternal((current) => ({
|
|
44
|
+
...current,
|
|
45
|
+
page: controlledPage === void 0 ? 1 : current.page,
|
|
46
|
+
pageSize: controlledPageSize === void 0 ? next : current.pageSize,
|
|
47
|
+
pageCount: Math.ceil(total / next)
|
|
48
|
+
}));
|
|
49
|
+
onPageSizeChange?.(next);
|
|
50
|
+
};
|
|
51
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
52
|
+
"data-slot": "table-container",
|
|
53
|
+
className: cn("w-full overflow-x-auto", bordered && "rounded-md border", classNames?.container),
|
|
54
|
+
children: /* @__PURE__ */ jsxs("table", {
|
|
55
|
+
...props,
|
|
56
|
+
"data-slot": "table",
|
|
57
|
+
"aria-busy": loading || void 0,
|
|
58
|
+
className: cn("w-full min-w-max border-collapse text-sm", className),
|
|
59
|
+
children: [
|
|
60
|
+
caption && /* @__PURE__ */ jsx("caption", {
|
|
61
|
+
className: "mb-2 text-start",
|
|
62
|
+
children: caption
|
|
63
|
+
}),
|
|
64
|
+
/* @__PURE__ */ jsx("thead", {
|
|
65
|
+
"data-slot": "table-header",
|
|
66
|
+
className: cn("bg-muted/50 border-b", classNames?.header),
|
|
67
|
+
children: /* @__PURE__ */ jsx("tr", { children: columns.map((column) => /* @__PURE__ */ jsx("th", {
|
|
68
|
+
scope: "col",
|
|
69
|
+
style: { width: column.width },
|
|
70
|
+
className: cn("text-foreground font-medium", cellPadding, column.align === "center" && "text-center", column.align === "right" && "text-right", column.align === void 0 && "text-start", bordered && "border-e last:border-e-0", classNames?.cell, column.headerClassName),
|
|
71
|
+
children: column.title
|
|
72
|
+
}, column.key)) })
|
|
73
|
+
}),
|
|
74
|
+
/* @__PURE__ */ jsx("tbody", {
|
|
75
|
+
"data-slot": "table-body",
|
|
76
|
+
className: classNames?.body,
|
|
77
|
+
children: loading ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
|
|
78
|
+
colSpan: Math.max(columns.length, 1),
|
|
79
|
+
className: cellPadding,
|
|
80
|
+
children: /* @__PURE__ */ jsx(Skeleton, {
|
|
81
|
+
count: 3,
|
|
82
|
+
className: "py-2"
|
|
83
|
+
})
|
|
84
|
+
}) }) : visibleData.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
|
|
85
|
+
colSpan: Math.max(columns.length, 1),
|
|
86
|
+
className: cn(cellPadding, classNames?.empty),
|
|
87
|
+
children: empty ?? /* @__PURE__ */ jsx(Empty, {})
|
|
88
|
+
}) }) : visibleData.map((record, index) => /* @__PURE__ */ jsx("tr", {
|
|
89
|
+
"data-slot": "table-row",
|
|
90
|
+
className: cn("border-b last:border-b-0", striped && "even:bg-muted/30", hoverable && "hover:bg-muted/50", classNames?.row),
|
|
91
|
+
children: columns.map((column) => {
|
|
92
|
+
const value = column.dataIndex === void 0 ? void 0 : record[column.dataIndex];
|
|
93
|
+
return /* @__PURE__ */ jsx("td", {
|
|
94
|
+
"data-slot": "table-cell",
|
|
95
|
+
className: cn(cellPadding, column.align === "center" && "text-center", column.align === "right" && "text-right", bordered && "border-e last:border-e-0", classNames?.cell, column.className),
|
|
96
|
+
children: column.render ? column.render(record, index) : value == null ? null : String(value)
|
|
97
|
+
}, column.key);
|
|
98
|
+
})
|
|
99
|
+
}, rowKey?.(record, index) ?? index))
|
|
100
|
+
})
|
|
101
|
+
]
|
|
102
|
+
})
|
|
103
|
+
}), pagination && /* @__PURE__ */ jsx("div", {
|
|
104
|
+
"data-slot": "table-pagination",
|
|
105
|
+
className: cn("mt-4 flex justify-end", classNames?.pagination),
|
|
106
|
+
children: /* @__PURE__ */ jsx(Pagination, {
|
|
107
|
+
...paginationProps,
|
|
108
|
+
total,
|
|
109
|
+
page,
|
|
110
|
+
pageSize,
|
|
111
|
+
onChange: handlePageChange,
|
|
112
|
+
onPageSizeChange: handlePageSizeChange
|
|
113
|
+
})
|
|
114
|
+
})] });
|
|
115
|
+
};
|
|
116
|
+
//#endregion
|
|
117
|
+
export { Table as default };
|
|
118
|
+
|
|
119
|
+
//# sourceMappingURL=Table.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Table.mjs","names":[],"sources":["../src/components/organisms/table.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\n\nimport { useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport Skeleton from '../atoms/skeleton';\nimport Pagination, {\n type Props as PaginationProps,\n} from '../molecules/pagination';\nimport Empty from '../templates/empty';\n\nexport type PaginationOptions = Omit<PaginationProps, 'total'> &\n ({ mode?: 'client'; total?: never } | { mode: 'server'; total: number });\n\nexport interface Column<T> {\n key: React.Key;\n title: React.ReactNode;\n /** Field displayed when render is omitted. */\n dataIndex?: keyof T;\n render?: (record: T, index: number) => React.ReactNode;\n align?: 'left' | 'center' | 'right';\n width?: string | number;\n className?: string;\n headerClassName?: string;\n}\n\nexport interface Props<T> extends Omit<\n React.ComponentPropsWithoutRef<'table'>,\n 'children'\n> {\n columns: Column<T>[];\n data?: T[];\n /** Use a stable key when rows may be reordered or paged. */\n rowKey?: (record: T, index: number) => React.Key;\n caption?: React.ReactNode;\n loading?: boolean;\n empty?: React.ReactNode;\n size?: 'small' | 'middle' | 'large';\n bordered?: boolean;\n striped?: boolean;\n hoverable?: boolean;\n /** true paginates data locally; server mode expects current-page data. */\n pagination?: boolean | PaginationOptions;\n classNames?: {\n container?: string;\n header?: string;\n body?: string;\n row?: string;\n cell?: string;\n empty?: string;\n pagination?: string;\n };\n}\n\nconst clampPage = (page: number, pageCount: number) =>\n Math.min(\n Math.max(1, Number.isFinite(page) ? Math.floor(page) : 1),\n Math.max(1, pageCount),\n );\n\nconst normalizePageSize = (value: number) =>\n Number.isFinite(value) && value >= 1 ? Math.floor(value) : 10;\n\nconst Table = <T,>({\n columns,\n data = [],\n rowKey,\n loading = false,\n empty,\n size,\n bordered = false,\n striped = false,\n hoverable = true,\n pagination = false,\n caption,\n className,\n classNames,\n ...props\n}: Props<T>) => {\n const { componentSize } = useConfig();\n const paginationOptions: PaginationOptions =\n typeof pagination === 'object' ? pagination : {};\n const {\n mode = 'client',\n total: serverTotal,\n page: controlledPage,\n defaultPage = 1,\n pageSize: controlledPageSize,\n defaultPageSize = 10,\n onChange,\n onPageSizeChange,\n ...paginationProps\n } = paginationOptions;\n const [internal, setInternal] = useState(() => ({\n page: defaultPage,\n pageSize: normalizePageSize(defaultPageSize),\n pageCount: 0,\n }));\n const pageSize = normalizePageSize(controlledPageSize ?? internal.pageSize);\n const total = mode === 'server' ? (serverTotal ?? 0) : data.length;\n const pageCount = Math.ceil(total / pageSize);\n\n if (\n pagination &&\n controlledPage === undefined &&\n internal.pageCount !== pageCount\n ) {\n setInternal(current => ({\n ...current,\n page: clampPage(current.page, pageCount),\n pageCount,\n }));\n }\n\n const page = clampPage(controlledPage ?? internal.page, pageCount);\n const visibleData =\n pagination && mode === 'client'\n ? data.slice((page - 1) * pageSize, page * pageSize)\n : data;\n const resolvedSize = size ?? componentSize ?? 'middle';\n const cellPadding = {\n small: 'px-3 py-2',\n middle: 'px-4 py-3',\n large: 'px-5 py-4',\n }[resolvedSize];\n\n const handlePageChange = (next: number) => {\n if (controlledPage === undefined) {\n setInternal(current => ({ ...current, page: next }));\n }\n\n onChange?.(next);\n };\n\n const handlePageSizeChange = (next: number) => {\n if (controlledPageSize === undefined || controlledPage === undefined) {\n setInternal(current => ({\n ...current,\n page: controlledPage === undefined ? 1 : current.page,\n pageSize: controlledPageSize === undefined ? next : current.pageSize,\n pageCount: Math.ceil(total / next),\n }));\n }\n\n onPageSizeChange?.(next);\n };\n\n return (\n <>\n <div\n data-slot=\"table-container\"\n className={cn(\n 'w-full overflow-x-auto',\n bordered && 'rounded-md border',\n classNames?.container,\n //\n )}\n >\n <table\n {...props}\n data-slot=\"table\"\n aria-busy={loading || undefined}\n className={cn(\n 'w-full min-w-max border-collapse text-sm',\n className,\n //\n )}\n >\n {caption && <caption className=\"mb-2 text-start\">{caption}</caption>}\n <thead\n data-slot=\"table-header\"\n className={cn(\n 'bg-muted/50 border-b',\n classNames?.header,\n //\n )}\n >\n <tr>\n {columns.map(column => (\n <th\n key={column.key}\n scope=\"col\"\n style={{ width: column.width }}\n className={cn(\n 'text-foreground font-medium',\n cellPadding,\n column.align === 'center' && 'text-center',\n column.align === 'right' && 'text-right',\n column.align === undefined && 'text-start',\n bordered && 'border-e last:border-e-0',\n classNames?.cell,\n column.headerClassName,\n //\n )}\n >\n {column.title}\n </th>\n ))}\n </tr>\n </thead>\n <tbody data-slot=\"table-body\" className={classNames?.body}>\n {loading ? (\n <tr>\n <td\n colSpan={Math.max(columns.length, 1)}\n className={cellPadding}\n >\n <Skeleton count={3} className=\"py-2\" />\n </td>\n </tr>\n ) : visibleData.length === 0 ? (\n <tr>\n <td\n colSpan={Math.max(columns.length, 1)}\n className={cn(cellPadding, classNames?.empty)}\n >\n {empty ?? <Empty />}\n </td>\n </tr>\n ) : (\n visibleData.map((record, index) => (\n <tr\n key={rowKey?.(record, index) ?? index}\n data-slot=\"table-row\"\n className={cn(\n 'border-b last:border-b-0',\n striped && 'even:bg-muted/30',\n hoverable && 'hover:bg-muted/50',\n classNames?.row,\n //\n )}\n >\n {columns.map(column => {\n const value =\n column.dataIndex === undefined\n ? undefined\n : record[column.dataIndex];\n\n return (\n <td\n key={column.key}\n data-slot=\"table-cell\"\n className={cn(\n cellPadding,\n column.align === 'center' && 'text-center',\n column.align === 'right' && 'text-right',\n bordered && 'border-e last:border-e-0',\n classNames?.cell,\n column.className,\n //\n )}\n >\n {column.render\n ? column.render(record, index)\n : value == null\n ? null\n : String(value)}\n </td>\n );\n })}\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n {pagination && (\n <div\n data-slot=\"table-pagination\"\n className={cn(\n 'mt-4 flex justify-end',\n classNames?.pagination,\n //\n )}\n >\n <Pagination\n {...paginationProps}\n total={total}\n page={page}\n pageSize={pageSize}\n onChange={handlePageChange}\n onPageSizeChange={handlePageSizeChange}\n />\n </div>\n )}\n </>\n );\n};\n\nexport default Table;\n"],"mappings":"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"}
|
|
@@ -4,8 +4,8 @@ import { checkbox_exports } from "../../../core/checkbox.mjs";
|
|
|
4
4
|
import { label_exports } from "../../../core/label.mjs";
|
|
5
5
|
import { useId, useRef } from "react";
|
|
6
6
|
import { Square, SquareCheck } from "lucide-react";
|
|
7
|
-
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
7
|
import { useControllableState, useKeyPress } from "@jbpark/use-hooks";
|
|
8
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region src/components/atoms/checkbox/checkbox.tsx
|
|
10
10
|
const { Checkbox: CoreCheckbox } = checkbox_exports;
|
|
11
11
|
const { Label: CoreLabel } = label_exports;
|
|
@@ -74,6 +74,7 @@ const Checkbox = ({ placement = "left", value: _value = "", children, className,
|
|
|
74
74
|
children
|
|
75
75
|
})] });
|
|
76
76
|
return /* @__PURE__ */ jsx("div", {
|
|
77
|
+
"data-slot": "checkbox-field",
|
|
77
78
|
className: cn("flex items-center gap-x-2", placement === "right" && "flex-row-reverse", cursorClassName, className),
|
|
78
79
|
...props,
|
|
79
80
|
children: renderContent
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkbox.mjs","names":["checkbox","label"],"sources":["../../../../src/components/atoms/checkbox/checkbox.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useRef } from 'react';\n\nimport { useControllableState, useKeyPress } from '@jbpark/use-hooks';\nimport { Square, SquareCheck } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { checkbox, label } from '../../../core';\nimport { type OptionValue } from './group';\n\nconst { Checkbox: CoreCheckbox } = checkbox;\nconst { Label: CoreLabel } = label;\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'onChange'\n> {\n placement?: 'left' | 'right';\n defaultChecked?: boolean;\n checked?: boolean;\n value?: OptionValue;\n /** Native form field name — participates in `FormData` when set. */\n name?: string;\n disabled?: boolean;\n icons?: Partial<{ checked: React.ReactNode; unchecked: React.ReactNode }>;\n children?: React.ReactNode;\n onChange?: (checked: boolean) => void;\n}\n\nconst Checkbox = ({\n placement = 'left',\n value: _value = '',\n children,\n className,\n icons,\n disabled,\n defaultChecked,\n checked: _checked,\n name,\n onChange: _onChange = () => {},\n ...props\n}: Props) => {\n const [checked, setChecked] = useControllableState<boolean>({\n value: _checked,\n defaultValue: defaultChecked ?? false,\n onChange: _onChange,\n });\n\n const id = useId();\n const itemValue = String(_value);\n\n const cursorClassName = disabled ? 'cursor-not-allowed' : 'cursor-pointer';\n\n const onChange = (next: boolean) => {\n if (disabled) {\n return;\n }\n\n setChecked(next);\n };\n\n const iconTriggerRef = useRef<HTMLSpanElement>(null);\n\n useKeyPress(\n ['Enter', 'space'],\n event => {\n event.preventDefault();\n onChange(!checked);\n },\n { target: iconTriggerRef, enabled: !!icons && !disabled },\n );\n\n const renderContent = icons ? (\n <>\n <input\n id={id}\n hidden\n type=\"checkbox\"\n name={name}\n value={itemValue}\n checked={checked}\n disabled={disabled}\n onChange={e => {\n onChange(e.target.checked);\n }}\n />\n <span\n ref={iconTriggerRef}\n role=\"checkbox\"\n aria-checked={checked}\n aria-disabled={disabled}\n tabIndex={disabled ? -1 : 0}\n className={cn(cursorClassName, disabled && 'opacity-50')}\n onClick={() => {\n onChange(!checked);\n }}\n >\n {checked\n ? (icons.checked ?? <SquareCheck />)\n : (icons.unchecked ?? <Square />)}\n </span>\n {children && (\n <label\n className={cn(cursorClassName, disabled && 'opacity-50')}\n htmlFor={id}\n >\n {children}\n </label>\n )}\n </>\n ) : (\n <>\n <CoreCheckbox\n id={id}\n name={name}\n value={itemValue}\n checked={checked}\n disabled={disabled}\n // Keep the atom's established 4px radius after the Base UI migration;\n // tailwind-merge lets this override the core primitive's radius (#361).\n className={cn('rounded-sm', cursorClassName)}\n onCheckedChange={onChange}\n />\n {children && (\n <CoreLabel htmlFor={id} className={cn(cursorClassName, 'text-left')}>\n {children}\n </CoreLabel>\n )}\n </>\n );\n\n return (\n <div\n className={cn(\n 'flex items-center gap-x-2',\n placement === 'right' && 'flex-row-reverse',\n cursorClassName,\n className,\n //\n )}\n {...props}\n >\n {renderContent}\n </div>\n );\n};\n\nexport default Checkbox;\n"],"mappings":";;;;;;;;;AAYA,MAAM,EAAE,UAAU,iBAAiBA;AACnC,MAAM,EAAE,OAAO,cAAcC;AAkB7B,MAAM,YAAY,EAChB,YAAY,QACZ,OAAO,SAAS,IAChB,UACA,WACA,OACA,UACA,gBACA,SAAS,UACT,MACA,UAAU,kBAAkB,CAAC,GAC7B,GAAG,YACQ;CACX,MAAM,CAAC,SAAS,cAAc,qBAA8B;EAC1D,OAAO;EACP,cAAc,kBAAkB;EAChC,UAAU;CACZ,CAAC;CAED,MAAM,KAAK,MAAM;CACjB,MAAM,YAAY,OAAO,MAAM;CAE/B,MAAM,kBAAkB,WAAW,uBAAuB;CAE1D,MAAM,YAAY,SAAkB;EAClC,IAAI,UACF;EAGF,WAAW,IAAI;CACjB;CAEA,MAAM,iBAAiB,OAAwB,IAAI;CAEnD,YACE,CAAC,SAAS,OAAO,IACjB,UAAS;EACP,MAAM,eAAe;EACrB,SAAS,CAAC,OAAO;CACnB,GACA;EAAE,QAAQ;EAAgB,SAAS,CAAC,CAAC,SAAS,CAAC;CAAS,CAC1D;CAEA,MAAM,gBAAgB,QACpB,qBAAA,YAAA,EAAA,UAAA;EACE,oBAAC,SAAD;GACM;GACJ,QAAA;GACA,MAAK;GACC;GACN,OAAO;GACE;GACC;GACV,WAAU,MAAK;IACb,SAAS,EAAE,OAAO,OAAO;GAC3B;EACD,CAAA;EACD,oBAAC,QAAD;GACE,KAAK;GACL,MAAK;GACL,gBAAc;GACd,iBAAe;GACf,UAAU,WAAW,KAAK;GAC1B,WAAW,GAAG,iBAAiB,YAAY,YAAY;GACvD,eAAe;IACb,SAAS,CAAC,OAAO;GACnB;GAEC,UAAA,UACI,MAAM,WAAW,oBAAC,aAAD,CAAc,CAAA,IAC/B,MAAM,aAAa,oBAAC,QAAD,CAAS,CAAA;EAC7B,CAAA;EACL,YACC,oBAAC,SAAD;GACE,WAAW,GAAG,iBAAiB,YAAY,YAAY;GACvD,SAAS;GAER;EACI,CAAA;CAET,EAAA,CAAA,IAEF,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,cAAD;EACM;EACE;EACN,OAAO;EACE;EACC;EAGV,WAAW,GAAG,cAAc,eAAe;EAC3C,iBAAiB;CAClB,CAAA,GACA,YACC,oBAAC,WAAD;EAAW,SAAS;EAAI,WAAW,GAAG,iBAAiB,WAAW;EAC/D;CACQ,CAAA,CAEb,EAAA,CAAA;CAGJ,OACE,oBAAC,OAAD;EACE,WAAW,GACT,6BACA,cAAc,WAAW,oBACzB,iBACA,SAEF;EACA,GAAI;EAEH,UAAA;CACE,CAAA;AAET"}
|
|
1
|
+
{"version":3,"file":"checkbox.mjs","names":["checkbox","label"],"sources":["../../../../src/components/atoms/checkbox/checkbox.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useRef } from 'react';\n\nimport { useControllableState, useKeyPress } from '@jbpark/use-hooks';\nimport { Square, SquareCheck } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { checkbox, label } from '../../../core';\nimport { type OptionValue } from './group';\n\nconst { Checkbox: CoreCheckbox } = checkbox;\nconst { Label: CoreLabel } = label;\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'onChange'\n> {\n placement?: 'left' | 'right';\n defaultChecked?: boolean;\n checked?: boolean;\n value?: OptionValue;\n /** Native form field name — participates in `FormData` when set. */\n name?: string;\n disabled?: boolean;\n icons?: Partial<{ checked: React.ReactNode; unchecked: React.ReactNode }>;\n children?: React.ReactNode;\n onChange?: (checked: boolean) => void;\n}\n\nconst Checkbox = ({\n placement = 'left',\n value: _value = '',\n children,\n className,\n icons,\n disabled,\n defaultChecked,\n checked: _checked,\n name,\n onChange: _onChange = () => {},\n ...props\n}: Props) => {\n const [checked, setChecked] = useControllableState<boolean>({\n value: _checked,\n defaultValue: defaultChecked ?? false,\n onChange: _onChange,\n });\n\n const id = useId();\n const itemValue = String(_value);\n\n const cursorClassName = disabled ? 'cursor-not-allowed' : 'cursor-pointer';\n\n const onChange = (next: boolean) => {\n if (disabled) {\n return;\n }\n\n setChecked(next);\n };\n\n const iconTriggerRef = useRef<HTMLSpanElement>(null);\n\n useKeyPress(\n ['Enter', 'space'],\n event => {\n event.preventDefault();\n onChange(!checked);\n },\n { target: iconTriggerRef, enabled: !!icons && !disabled },\n );\n\n const renderContent = icons ? (\n <>\n <input\n id={id}\n hidden\n type=\"checkbox\"\n name={name}\n value={itemValue}\n checked={checked}\n disabled={disabled}\n onChange={e => {\n onChange(e.target.checked);\n }}\n />\n <span\n ref={iconTriggerRef}\n role=\"checkbox\"\n aria-checked={checked}\n aria-disabled={disabled}\n tabIndex={disabled ? -1 : 0}\n className={cn(cursorClassName, disabled && 'opacity-50')}\n onClick={() => {\n onChange(!checked);\n }}\n >\n {checked\n ? (icons.checked ?? <SquareCheck />)\n : (icons.unchecked ?? <Square />)}\n </span>\n {children && (\n <label\n className={cn(cursorClassName, disabled && 'opacity-50')}\n htmlFor={id}\n >\n {children}\n </label>\n )}\n </>\n ) : (\n <>\n <CoreCheckbox\n id={id}\n name={name}\n value={itemValue}\n checked={checked}\n disabled={disabled}\n // Keep the atom's established 4px radius after the Base UI migration;\n // tailwind-merge lets this override the core primitive's radius (#361).\n className={cn('rounded-sm', cursorClassName)}\n onCheckedChange={onChange}\n />\n {children && (\n <CoreLabel htmlFor={id} className={cn(cursorClassName, 'text-left')}>\n {children}\n </CoreLabel>\n )}\n </>\n );\n\n return (\n <div\n data-slot=\"checkbox-field\"\n className={cn(\n 'flex items-center gap-x-2',\n placement === 'right' && 'flex-row-reverse',\n cursorClassName,\n className,\n //\n )}\n {...props}\n >\n {renderContent}\n </div>\n );\n};\n\nexport default Checkbox;\n"],"mappings":";;;;;;;;;AAYA,MAAM,EAAE,UAAU,iBAAiBA;AACnC,MAAM,EAAE,OAAO,cAAcC;AAkB7B,MAAM,YAAY,EAChB,YAAY,QACZ,OAAO,SAAS,IAChB,UACA,WACA,OACA,UACA,gBACA,SAAS,UACT,MACA,UAAU,kBAAkB,CAAC,GAC7B,GAAG,YACQ;CACX,MAAM,CAAC,SAAS,cAAc,qBAA8B;EAC1D,OAAO;EACP,cAAc,kBAAkB;EAChC,UAAU;CACZ,CAAC;CAED,MAAM,KAAK,MAAM;CACjB,MAAM,YAAY,OAAO,MAAM;CAE/B,MAAM,kBAAkB,WAAW,uBAAuB;CAE1D,MAAM,YAAY,SAAkB;EAClC,IAAI,UACF;EAGF,WAAW,IAAI;CACjB;CAEA,MAAM,iBAAiB,OAAwB,IAAI;CAEnD,YACE,CAAC,SAAS,OAAO,IACjB,UAAS;EACP,MAAM,eAAe;EACrB,SAAS,CAAC,OAAO;CACnB,GACA;EAAE,QAAQ;EAAgB,SAAS,CAAC,CAAC,SAAS,CAAC;CAAS,CAC1D;CAEA,MAAM,gBAAgB,QACpB,qBAAA,YAAA,EAAA,UAAA;EACE,oBAAC,SAAD;GACM;GACJ,QAAA;GACA,MAAK;GACC;GACN,OAAO;GACE;GACC;GACV,WAAU,MAAK;IACb,SAAS,EAAE,OAAO,OAAO;GAC3B;EACD,CAAA;EACD,oBAAC,QAAD;GACE,KAAK;GACL,MAAK;GACL,gBAAc;GACd,iBAAe;GACf,UAAU,WAAW,KAAK;GAC1B,WAAW,GAAG,iBAAiB,YAAY,YAAY;GACvD,eAAe;IACb,SAAS,CAAC,OAAO;GACnB;GAEC,UAAA,UACI,MAAM,WAAW,oBAAC,aAAD,CAAc,CAAA,IAC/B,MAAM,aAAa,oBAAC,QAAD,CAAS,CAAA;EAC7B,CAAA;EACL,YACC,oBAAC,SAAD;GACE,WAAW,GAAG,iBAAiB,YAAY,YAAY;GACvD,SAAS;GAER;EACI,CAAA;CAET,EAAA,CAAA,IAEF,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,cAAD;EACM;EACE;EACN,OAAO;EACE;EACC;EAGV,WAAW,GAAG,cAAc,eAAe;EAC3C,iBAAiB;CAClB,CAAA,GACA,YACC,oBAAC,WAAD;EAAW,SAAS;EAAI,WAAW,GAAG,iBAAiB,WAAW;EAC/D;CACQ,CAAA,CAEb,EAAA,CAAA;CAGJ,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,6BACA,cAAc,WAAW,oBACzB,iBACA,SAEF;EACA,GAAI;EAEH,UAAA;CACE,CAAA;AAET"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { cn } from "../../../utils.mjs";
|
|
3
3
|
import Checkbox from "./checkbox.mjs";
|
|
4
4
|
import { normalizeOptions, warnOnDuplicateOptionValues } from "../option-group.mjs";
|
|
5
|
-
import { jsx } from "react/jsx-runtime";
|
|
6
5
|
import { useControllableState } from "@jbpark/use-hooks";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
7
|
//#region src/components/atoms/checkbox/group.tsx
|
|
8
8
|
const Group = ({ orientation = "vertical", placement = "left", className, classNames = {}, options: _options = [], name, disabled, defaultValue, value: _value, onChange: _onChange = () => {}, ...props }) => {
|
|
9
9
|
const [value, setValue] = useControllableState({
|
|
@@ -18,6 +18,7 @@ const Group = ({ orientation = "vertical", placement = "left", className, classN
|
|
|
18
18
|
setValue(nextValue);
|
|
19
19
|
};
|
|
20
20
|
return /* @__PURE__ */ jsx("ul", {
|
|
21
|
+
"data-slot": "checkbox-group",
|
|
21
22
|
...props,
|
|
22
23
|
className: cn("m-0 flex list-none gap-2 p-0", orientation === "vertical" && "flex-col", className),
|
|
23
24
|
children: options.map((item, index) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group.mjs","names":[],"sources":["../../../../src/components/atoms/checkbox/group.tsx"],"sourcesContent":["'use client';\n\nimport { useControllableState } from '@jbpark/use-hooks';\n\nimport { cn } from '@repo/ui/utils';\n\nimport {\n type Option,\n type OptionGroupClassNames,\n type OptionValue,\n type Options,\n normalizeOptions,\n warnOnDuplicateOptionValues,\n} from '../option-group';\nimport Checkbox from './checkbox';\n\nexport type { OptionValue };\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'ul'>,\n 'onChange' | 'defaultValue' | 'value'\n> {\n options?: Options;\n orientation?: 'vertical' | 'horizontal';\n placement?: 'left' | 'right';\n classNames?: OptionGroupClassNames;\n defaultValue?: OptionValue[];\n value?: OptionValue[];\n /** Native form field name, shared across every option's checkbox. */\n name?: string;\n disabled?: boolean;\n onChange?: (values: OptionValue[]) => void;\n}\n\nconst Group = ({\n orientation = 'vertical',\n placement = 'left',\n className,\n classNames = {},\n options: _options = [],\n name,\n disabled,\n defaultValue,\n value: _value,\n onChange: _onChange = () => {},\n ...props\n}: Props) => {\n const [value, setValue] = useControllableState<OptionValue[]>({\n value: _value,\n defaultValue: defaultValue ?? [],\n onChange: _onChange,\n });\n\n const options: Option[] = normalizeOptions(_options);\n warnOnDuplicateOptionValues(options, 'Checkbox.Group');\n\n const onChange = (checked: boolean, optionValue: OptionValue) => {\n const nextValue = checked\n ? [...value, optionValue]\n : value.filter(v => v !== optionValue);\n\n setValue(nextValue);\n };\n\n return (\n <ul\n {...props}\n className={cn(\n // Spacing comes from `gap`, not `space-y`'s child margins, so the\n // per-item `m-0` reset below can neutralise host list styles without\n // also wiping out the group's own spacing.\n 'm-0 flex list-none gap-2 p-0',\n orientation === 'vertical' && 'flex-col',\n className,\n )}\n >\n {options.map((item: Option, index) => {\n const checked = value.includes(item.value);\n\n return (\n <li\n key={`${index}-${String(item.value)}`}\n // `m-0` completes the list reset the `ul` above starts (#253) —\n // see Radio.Group for the host rule this guards against.\n className={cn('m-0 flex', classNames?.wrapper)}\n >\n <Checkbox\n placement={placement}\n className={cn(classNames?.item)}\n name={name}\n value={item.value}\n checked={checked}\n disabled={disabled || item.disabled}\n onChange={checked => onChange(checked, item.value)}\n >\n {item.label}\n </Checkbox>\n </li>\n );\n })}\n </ul>\n );\n};\n\nexport default Group;\n"],"mappings":";;;;;;;AAkCA,MAAM,SAAS,EACb,cAAc,YACd,YAAY,QACZ,WACA,aAAa,CAAC,GACd,SAAS,WAAW,CAAC,GACrB,MACA,UACA,cACA,OAAO,QACP,UAAU,kBAAkB,CAAC,GAC7B,GAAG,YACQ;CACX,MAAM,CAAC,OAAO,YAAY,qBAAoC;EAC5D,OAAO;EACP,cAAc,gBAAgB,CAAC;EAC/B,UAAU;CACZ,CAAC;CAED,MAAM,UAAoB,iBAAiB,QAAQ;CACnD,4BAA4B,SAAS,gBAAgB;CAErD,MAAM,YAAY,SAAkB,gBAA6B;EAC/D,MAAM,YAAY,UACd,CAAC,GAAG,OAAO,WAAW,IACtB,MAAM,QAAO,MAAK,MAAM,WAAW;EAEvC,SAAS,SAAS;CACpB;CAEA,OACE,oBAAC,MAAD;EACE,GAAI;EACJ,WAAW,GAIT,gCACA,gBAAgB,cAAc,YAC9B,SACF;EAEC,UAAA,QAAQ,KAAK,MAAc,UAAU;GACpC,MAAM,UAAU,MAAM,SAAS,KAAK,KAAK;GAEzC,OACE,oBAAC,MAAD;IAIE,WAAW,GAAG,YAAY,YAAY,OAAO;IAE7C,UAAA,oBAAC,UAAD;KACa;KACX,WAAW,GAAG,YAAY,IAAI;KACxB;KACN,OAAO,KAAK;KACH;KACT,UAAU,YAAY,KAAK;KAC3B,WAAU,YAAW,SAAS,SAAS,KAAK,KAAK;KAEhD,UAAA,KAAK;IACE,CAAA;GACR,GAhBG,GAAG,MAAM,GAAG,OAAO,KAAK,KAAK,GAgBhC;EAER,CAAC;CACC,CAAA;AAER"}
|
|
1
|
+
{"version":3,"file":"group.mjs","names":[],"sources":["../../../../src/components/atoms/checkbox/group.tsx"],"sourcesContent":["'use client';\n\nimport { useControllableState } from '@jbpark/use-hooks';\n\nimport { cn } from '@repo/ui/utils';\n\nimport {\n type Option,\n type OptionGroupClassNames,\n type OptionValue,\n type Options,\n normalizeOptions,\n warnOnDuplicateOptionValues,\n} from '../option-group';\nimport Checkbox from './checkbox';\n\nexport type { OptionValue };\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'ul'>,\n 'onChange' | 'defaultValue' | 'value'\n> {\n options?: Options;\n orientation?: 'vertical' | 'horizontal';\n placement?: 'left' | 'right';\n classNames?: OptionGroupClassNames;\n defaultValue?: OptionValue[];\n value?: OptionValue[];\n /** Native form field name, shared across every option's checkbox. */\n name?: string;\n disabled?: boolean;\n onChange?: (values: OptionValue[]) => void;\n}\n\nconst Group = ({\n orientation = 'vertical',\n placement = 'left',\n className,\n classNames = {},\n options: _options = [],\n name,\n disabled,\n defaultValue,\n value: _value,\n onChange: _onChange = () => {},\n ...props\n}: Props) => {\n const [value, setValue] = useControllableState<OptionValue[]>({\n value: _value,\n defaultValue: defaultValue ?? [],\n onChange: _onChange,\n });\n\n const options: Option[] = normalizeOptions(_options);\n warnOnDuplicateOptionValues(options, 'Checkbox.Group');\n\n const onChange = (checked: boolean, optionValue: OptionValue) => {\n const nextValue = checked\n ? [...value, optionValue]\n : value.filter(v => v !== optionValue);\n\n setValue(nextValue);\n };\n\n return (\n <ul\n data-slot=\"checkbox-group\"\n {...props}\n className={cn(\n // Spacing comes from `gap`, not `space-y`'s child margins, so the\n // per-item `m-0` reset below can neutralise host list styles without\n // also wiping out the group's own spacing.\n 'm-0 flex list-none gap-2 p-0',\n orientation === 'vertical' && 'flex-col',\n className,\n )}\n >\n {options.map((item: Option, index) => {\n const checked = value.includes(item.value);\n\n return (\n <li\n key={`${index}-${String(item.value)}`}\n // `m-0` completes the list reset the `ul` above starts (#253) —\n // see Radio.Group for the host rule this guards against.\n className={cn('m-0 flex', classNames?.wrapper)}\n >\n <Checkbox\n placement={placement}\n className={cn(classNames?.item)}\n name={name}\n value={item.value}\n checked={checked}\n disabled={disabled || item.disabled}\n onChange={checked => onChange(checked, item.value)}\n >\n {item.label}\n </Checkbox>\n </li>\n );\n })}\n </ul>\n );\n};\n\nexport default Group;\n"],"mappings":";;;;;;;AAkCA,MAAM,SAAS,EACb,cAAc,YACd,YAAY,QACZ,WACA,aAAa,CAAC,GACd,SAAS,WAAW,CAAC,GACrB,MACA,UACA,cACA,OAAO,QACP,UAAU,kBAAkB,CAAC,GAC7B,GAAG,YACQ;CACX,MAAM,CAAC,OAAO,YAAY,qBAAoC;EAC5D,OAAO;EACP,cAAc,gBAAgB,CAAC;EAC/B,UAAU;CACZ,CAAC;CAED,MAAM,UAAoB,iBAAiB,QAAQ;CACnD,4BAA4B,SAAS,gBAAgB;CAErD,MAAM,YAAY,SAAkB,gBAA6B;EAC/D,MAAM,YAAY,UACd,CAAC,GAAG,OAAO,WAAW,IACtB,MAAM,QAAO,MAAK,MAAM,WAAW;EAEvC,SAAS,SAAS;CACpB;CAEA,OACE,oBAAC,MAAD;EACE,aAAU;EACV,GAAI;EACJ,WAAW,GAIT,gCACA,gBAAgB,cAAc,YAC9B,SACF;EAEC,UAAA,QAAQ,KAAK,MAAc,UAAU;GACpC,MAAM,UAAU,MAAM,SAAS,KAAK,KAAK;GAEzC,OACE,oBAAC,MAAD;IAIE,WAAW,GAAG,YAAY,YAAY,OAAO;IAE7C,UAAA,oBAAC,UAAD;KACa;KACX,WAAW,GAAG,YAAY,IAAI;KACxB;KACN,OAAO,KAAK;KACH;KACT,UAAU,YAAY,KAAK;KAC3B,WAAU,YAAW,SAAS,SAAS,KAAK,KAAK;KAEhD,UAAA,KAAK;IACE,CAAA;GACR,GAhBG,GAAG,MAAM,GAAG,OAAO,KAAK,KAAK,GAgBhC;EAER,CAAC;CACC,CAAA;AAER"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../utils.mjs";
|
|
3
3
|
import Popover from "./popover.mjs";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
4
|
import { useControllableState } from "@jbpark/use-hooks";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { HexColorPicker } from "react-colorful";
|
|
7
7
|
//#region src/components/atoms/color-picker.tsx
|
|
8
8
|
const ColorPicker = ({ defaultValue, value: _value, showText, disabled, className, onChange: _onChange = () => {}, open: _open, defaultOpen, onOpenChange, ...props }) => {
|
|
@@ -5,8 +5,8 @@ import Button from "../../Button.mjs";
|
|
|
5
5
|
import Popover from "./popover.mjs";
|
|
6
6
|
import { useState } from "react";
|
|
7
7
|
import { CalendarIcon } from "lucide-react";
|
|
8
|
-
import { jsx } from "react/jsx-runtime";
|
|
9
8
|
import { useControllableState } from "@jbpark/use-hooks";
|
|
9
|
+
import { jsx } from "react/jsx-runtime";
|
|
10
10
|
import { format } from "date-fns";
|
|
11
11
|
//#region src/components/atoms/date-picker.tsx
|
|
12
12
|
const { Calendar } = calendar_exports;
|
|
@@ -4,8 +4,8 @@ import { DEFAULT_LOCALE, useConfig } from "../../../providers/config/context.mjs
|
|
|
4
4
|
import FloatButton from "./float-button.mjs";
|
|
5
5
|
import { useRef } from "react";
|
|
6
6
|
import { ArrowUp } from "lucide-react";
|
|
7
|
-
import { jsx } from "react/jsx-runtime";
|
|
8
7
|
import { useMergedRef, useWindowScroll } from "@jbpark/use-hooks";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
9
|
//#region src/components/atoms/float-button/back-top.tsx
|
|
10
10
|
const BackTop = ({ ref, visibilityHeight = 450, className, onClick, ...props }) => {
|
|
11
11
|
const { locale } = useConfig();
|
|
@@ -16,4 +16,5 @@ import Skeleton from "./skeleton/index.mjs";
|
|
|
16
16
|
import Slider from "./slider/slider.mjs";
|
|
17
17
|
import Spin from "./spin.mjs";
|
|
18
18
|
import Switch from "./switch.mjs";
|
|
19
|
-
|
|
19
|
+
import Tooltip from "./tooltip.mjs";
|
|
20
|
+
export { Button, Checkbox, ColorPicker, DatePicker, FloatButton, Input, Popover, Progress, Radio, RichTextEditor, Select, Skeleton, Slider, Spin, Switch, Tag, Tooltip, Typography };
|
|
@@ -5,8 +5,8 @@ import { input_exports } from "../../../core/input.mjs";
|
|
|
5
5
|
import Button from "../../../Button.mjs";
|
|
6
6
|
import { useRef, useState } from "react";
|
|
7
7
|
import { CircleX, Search } from "lucide-react";
|
|
8
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
8
|
import { useMergedRef } from "@jbpark/use-hooks";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
//#region src/components/atoms/input/search.tsx
|
|
11
11
|
const { Input: Core } = input_exports;
|
|
12
12
|
const Search$1 = ({ ref, className, defaultValue, value, disabled, allowClear = true, onChange, onKeyDown: _onKeyDown, onSearch: _onSearch, ...props }) => {
|
|
@@ -28,6 +28,7 @@ const Search$1 = ({ ref, className, defaultValue, value, disabled, allowClear =
|
|
|
28
28
|
if (inputRef.current) _onSearch?.(inputRef.current.value);
|
|
29
29
|
};
|
|
30
30
|
return /* @__PURE__ */ jsxs("div", {
|
|
31
|
+
"data-slot": "input-search",
|
|
31
32
|
className: cn("flex items-center", "rounded-md", className),
|
|
32
33
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
33
34
|
className: cn("relative grow", "inline-flex items-center"),
|
|
@@ -51,6 +52,7 @@ const Search$1 = ({ ref, className, defaultValue, value, disabled, allowClear =
|
|
|
51
52
|
}
|
|
52
53
|
}), /* @__PURE__ */ jsx("button", {
|
|
53
54
|
type: "button",
|
|
55
|
+
"data-slot": "input-search-clear",
|
|
54
56
|
"aria-label": locale.clear ?? DEFAULT_LOCALE.clear,
|
|
55
57
|
disabled,
|
|
56
58
|
className: cn("absolute right-2", "shrink-0 cursor-pointer", "disabled:cursor-not-allowed disabled:opacity-50", (!allowClear || !hasValue) && "hidden"),
|