@pk-design/react-tailwind 1.1.5 → 1.1.7
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/dist/react-tailwind.cjs.js +94 -664
- package/dist/react-tailwind.cjs.js.map +1 -1
- package/dist/react-tailwind.es.js +95 -665
- package/dist/react-tailwind.es.js.map +1 -1
- package/dist/types/components/PasswordInput/PasswordInput.d.ts +1 -1
- package/dist/types/components/VirtualizedDataTable/VirtualizedRow.d.ts +5 -3
- package/package.json +8 -5
- package/dist/types/components/RangeInput/-backup.d.ts +0 -10
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import React__default, { forwardRef, useMemo,
|
|
4
|
+
import React__default, { forwardRef, useMemo, useId, useRef, useState, useEffect, Fragment as Fragment$1, useCallback, useImperativeHandle, createContext, useContext } from 'react';
|
|
5
5
|
import { Dialog, DialogBackdrop, DialogPanel, DialogTitle, Menu, MenuButton, MenuItems, MenuItem, RadioGroup as RadioGroup$1, Radio as Radio$1, Combobox, ComboboxInput, ComboboxButton, ComboboxOptions, ComboboxOption, TabGroup, TabList, Tab, TabPanels, TabPanel, Transition } from '@headlessui/react';
|
|
6
|
+
import { FixedSizeList } from 'react-window';
|
|
6
7
|
|
|
7
8
|
const buildClassName = (...classes) => twMerge(classes.filter(Boolean));
|
|
8
9
|
|
|
@@ -223,7 +224,7 @@ const TypeClassMap = {
|
|
|
223
224
|
const Alert = (props) => {
|
|
224
225
|
const { type = 'info', className = '', message, children, removable = false, onRemove = () => { }, ...restProps } = props;
|
|
225
226
|
const Icon = AlertTypeIconMap[type] || SvgInfo;
|
|
226
|
-
return (jsxs("div", { className: buildClassName(className, 'flex items-center justify-between rounded-md p-3 text-sm ring-1 ring-inset gap-2', TypeClassMap[type]), ...restProps, children: [jsxs("span", { className: "inline-flex items-center gap-2", children: [jsx(Icon, { className: "size-5", "data-testid": `alert-${type}-icon` }), jsx("span", { className: "pr-2 inline-flex items-center", children: message || children })] }), removable && (jsx(Button, { iconOnly: true, size: "xs", variant: "plain", theme: "secondary", className: "hover:bg-black/5 text-gray-600 dark:hover:bg-black/5 dark:text-gray-600", onClick: () => onRemove(), "data-testid": "alert-remove-btn", children: jsx(SvgX, { className: "size-4.5", "data-testid": "alert-remove-icon" }) }))] }));
|
|
227
|
+
return (jsxs("div", { className: buildClassName(className, 'flex items-center justify-between rounded-md p-3 text-sm ring-1 ring-inset gap-2', TypeClassMap[type]), ...restProps, children: [jsxs("span", { className: "inline-flex items-center gap-2", children: [jsx(Icon, { className: "size-5", "data-testid": `alert-${type}-icon` }), jsx("span", { className: "pr-2 inline-flex items-center", children: message || children })] }), removable && (jsx(Button, { iconOnly: true, "aria-label": "Dismiss alert", size: "xs", variant: "plain", theme: "secondary", className: "hover:bg-black/5 text-gray-600 dark:hover:bg-black/5 dark:text-gray-600", onClick: () => onRemove(), "data-testid": "alert-remove-btn", children: jsx(SvgX, { className: "size-4.5", "data-testid": "alert-remove-icon" }) }))] }));
|
|
227
228
|
};
|
|
228
229
|
Alert.displayName = 'Alert';
|
|
229
230
|
|
|
@@ -236,7 +237,12 @@ const ThemeClassMap = {
|
|
|
236
237
|
};
|
|
237
238
|
const Badge = forwardRef((props, ref) => {
|
|
238
239
|
const { theme = 'info', className = '', children, removable = false, rounded = false, onRemove = () => { }, ...restProps } = props;
|
|
239
|
-
return (jsxs(TextContent, { ref: ref, className: buildClassName(className, 'inline-flex items-center pl-3 py-1 text-xs font-medium ring-1 ring-inset', ThemeClassMap[theme], rounded ? 'rounded-full' : 'rounded-md'), "data-testid": `badge-${theme}`, ...restProps, children: [jsx(TextContent, { className: "pr-3 inline-flex items-center", children: children }), removable ? (jsx(SvgX, { className: "size-5 px-0.5 mr-1 hover:bg-slate-200 dark:hover:bg-white/10 rounded-sm cursor-pointer text-gray-600 dark:text-gray-300", role: "button", onClick: () => onRemove()
|
|
240
|
+
return (jsxs(TextContent, { ref: ref, className: buildClassName(className, 'inline-flex items-center pl-3 py-1 text-xs font-medium ring-1 ring-inset', ThemeClassMap[theme], rounded ? 'rounded-full' : 'rounded-md'), "data-testid": `badge-${theme}`, ...restProps, children: [jsx(TextContent, { className: "pr-3 inline-flex items-center", children: children }), removable ? (jsx(SvgX, { className: "size-5 px-0.5 mr-1 hover:bg-slate-200 dark:hover:bg-white/10 rounded-sm cursor-pointer text-gray-600 dark:text-gray-300", role: "button", tabIndex: 0, "aria-label": "Remove", onClick: () => onRemove(), onKeyDown: (e) => {
|
|
241
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
242
|
+
e.preventDefault();
|
|
243
|
+
onRemove();
|
|
244
|
+
}
|
|
245
|
+
} })) : null] }));
|
|
240
246
|
});
|
|
241
247
|
Badge.displayName = 'Badge';
|
|
242
248
|
|
|
@@ -340,7 +346,7 @@ var SvgSlash = function SvgSlash(props) {
|
|
|
340
346
|
const Breadcrumb = ({ items, render }) => {
|
|
341
347
|
const count = items.length;
|
|
342
348
|
const isLast = (index) => index === count - 1;
|
|
343
|
-
return (jsx("
|
|
349
|
+
return (jsx("nav", { "aria-label": "Breadcrumb", className: "flex flex-wrap items-center gap-2", "data-testid": "breadcrumb-container", children: items.map((item, index) => (jsxs("span", { className: "inline-flex gap-2 items-center dark:text-white", "data-testid": `breadcrumb-item-${item.key}`, children: [jsx("span", { className: "font-medium", ...(isLast(index) ? { 'aria-current': 'page' } : {}), children: isLast(index) ? item.text : render(item) }), !isLast(index) && (jsx(SvgSlash, { "data-testid": `breadcrumb-divider-${index}`, className: "size-4" }))] }, item.key))) }));
|
|
344
350
|
};
|
|
345
351
|
Breadcrumb.displayName = 'Breadcrumb';
|
|
346
352
|
|
|
@@ -367,7 +373,8 @@ const Checkbox = forwardRef((props, ref) => {
|
|
|
367
373
|
const { id, name, label, labelClass = '', wrapperClass = '', containerClass = '', error, disabled = false, className = '',
|
|
368
374
|
// Checkbox-only props removed from rest
|
|
369
375
|
...rest } = props;
|
|
370
|
-
const
|
|
376
|
+
const generatedId = useId();
|
|
377
|
+
const checkboxId = (_a = id !== null && id !== void 0 ? id : name) !== null && _a !== void 0 ? _a : generatedId;
|
|
371
378
|
return (jsxs("div", { className: buildClassName(wrapperClass), children: [jsxs("div", { className: buildClassName('flex items-center', containerClass), children: [jsxs("label", { htmlFor: checkboxId, className: buildClassName('inline-flex items-center relative select-none', disabled ? 'cursor-not-allowed opacity-70' : 'cursor-pointer'), children: [jsx("input", { ref: ref, ...rest, id: checkboxId, name: name, type: "checkbox", disabled: disabled, "aria-checked": rest.checked, className: buildClassName('peer size-4.5 cursor-pointer transition-all appearance-none rounded', 'border focus:ring-2 focus:ring-offset-2', 'checked:bg-blue-600 checked:border-blue-600', 'focus:ring-blue-500 dark:focus:ring-offset-gray-900', disabled
|
|
372
379
|
? 'border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-800 pointer-events-none'
|
|
373
380
|
: 'bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500 hover:shadow-md', className) }), jsx("span", { className: "absolute text-white opacity-0 peer-checked:opacity-100 \n top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2", children: jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-3.25 w-3.25", viewBox: "0 0 20 20", fill: "currentColor", stroke: "currentColor", strokeWidth: "1", children: jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }) })] }), label && (jsx(Label, { htmlFor: checkboxId, className: buildClassName(disabled
|
|
@@ -378,15 +385,8 @@ Checkbox.displayName = 'Checkbox';
|
|
|
378
385
|
|
|
379
386
|
const CheckboxGroup = (props) => {
|
|
380
387
|
const { name, options, label, labelClass = '', labelWrapperClass = '', labelHint, containerClass = '', value = [], onChange, inline = false, } = props;
|
|
381
|
-
const
|
|
382
|
-
const
|
|
383
|
-
/**
|
|
384
|
-
* Normalize options (strings → {label, value})
|
|
385
|
-
*/
|
|
386
|
-
useEffect(() => {
|
|
387
|
-
const normalized = options.map((opt) => typeof opt === 'string' ? { label: opt, value: opt } : opt);
|
|
388
|
-
setItems(normalized);
|
|
389
|
-
}, [options]);
|
|
388
|
+
const groupId = useId();
|
|
389
|
+
const items = useMemo(() => options.map((opt) => typeof opt === 'string' ? { label: opt, value: opt } : opt), [options]);
|
|
390
390
|
/**
|
|
391
391
|
* Group-level change handler. Converts raw checkbox change events
|
|
392
392
|
* into a typed updated values array.
|
|
@@ -537,14 +537,14 @@ const Pagination = ({ page: currentPage, limit, total, onChange, className, elli
|
|
|
537
537
|
onChange({ page: nextVal });
|
|
538
538
|
};
|
|
539
539
|
if (ellipsis) {
|
|
540
|
-
return (jsxs("div", { "data-testid": "pagination-container", className: buildClassName('flex items-center justify-between bg-white dark:bg-gray-800 px-4 py-3 sm:px-6', className), children: [jsxs("div", { className: "flex flex-1 justify-between sm:hidden", children: [jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "data-testid": "ellipsis-mobile-prev-btn", children: [jsx("span", { children: "Previous" }), jsx(SvgChevronLeft, { className: "size-4" })] }), jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "data-testid": "ellipsis-mobile-next-btn", children: [jsx("span", { children: "Next" }), jsx(SvgChevronRight, { className: "size-4" })] })] }), jsxs("div", { className: "hidden sm:flex sm:flex-1 sm:items-center sm:justify-between", children: [jsxs("p", { "data-testid": "pagination-summary", className: "text-sm text-gray-600 dark:text-gray-400 flex items-center gap-1", children: ["Showing", jsx("span", { className: "font-medium", children: total === 0 ? 0 : Math.max(currentPage * limit - limit + 1, 1) }), "to", jsx("span", { className: "font-medium", children: Math.min(currentPage * limit, total) }), "of", jsx("span", { className: "font-medium", children: total }), "results"] }), jsxs("ul", { className: "flex items-center space-x-2 text-sm", children: [jsx("li", { children: jsx(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "data-testid": "ellipsis-
|
|
540
|
+
return (jsxs("div", { "data-testid": "pagination-container", className: buildClassName('flex items-center justify-between bg-white dark:bg-gray-800 px-4 py-3 sm:px-6', className), children: [jsxs("div", { className: "flex flex-1 justify-between sm:hidden", children: [jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "data-testid": "ellipsis-mobile-prev-btn", children: [jsx("span", { children: "Previous" }), jsx(SvgChevronLeft, { className: "size-4" })] }), jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "data-testid": "ellipsis-mobile-next-btn", children: [jsx("span", { children: "Next" }), jsx(SvgChevronRight, { className: "size-4" })] })] }), jsxs("div", { className: "hidden sm:flex sm:flex-1 sm:items-center sm:justify-between", children: [jsxs("p", { "data-testid": "pagination-summary", className: "text-sm text-gray-600 dark:text-gray-400 flex items-center gap-1", children: ["Showing", jsx("span", { className: "font-medium", children: total === 0 ? 0 : Math.max(currentPage * limit - limit + 1, 1) }), "to", jsx("span", { className: "font-medium", children: Math.min(currentPage * limit, total) }), "of", jsx("span", { className: "font-medium", children: total }), "results"] }), jsxs("ul", { className: "flex items-center space-x-2 text-sm", children: [jsx("li", { children: jsx(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "data-testid": "ellipsis-prev-btn", children: "Prev" }) }), range.map((page, idx) => {
|
|
541
541
|
if (page === DOTS) {
|
|
542
542
|
return (jsx("li", { "data-testid": `page-${page}`, className: "px-2 py-1 text-gray-400", children: "\u2026" }, `${page}-${idx}`));
|
|
543
543
|
}
|
|
544
544
|
return (jsx("li", { children: jsx(Button, { size: "xs", theme: page === currentPage ? 'primary' : 'secondary', variant: page === currentPage ? 'default' : 'plain', "aria-current": page === currentPage ? 'page' : undefined, onClick: () => handlePageChange(page), children: page }) }, `${page}-${idx}`));
|
|
545
|
-
}), jsx("li", { children: jsx(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "data-testid": "ellipsis-
|
|
545
|
+
}), jsx("li", { children: jsx(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "data-testid": "ellipsis-next-btn", children: "Next" }) })] })] })] }));
|
|
546
546
|
}
|
|
547
|
-
return (jsxs("div", { "data-testid": "pagination-container", className: buildClassName('flex items-center justify-between bg-white dark:bg-gray-800 px-4 py-3 sm:px-6', className), children: [jsxs("div", { className: "flex flex-1 justify-between sm:hidden", children: [jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "data-testid": "mobile-prev-btn", children: [jsx("span", { children: "Previous" }), jsx(SvgChevronLeft, { className: "size-4" })] }), jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "data-testid": "mobile-next-btn", children: [jsx("span", { children: "Next" }), jsx(SvgChevronRight, { className: "size-4" })] })] }), jsxs("div", { className: "hidden sm:flex sm:flex-1 sm:items-center sm:justify-between", children: [jsxs("p", { "data-testid": "pagination-summary", className: "text-sm text-gray-600 dark:text-gray-400 flex items-center gap-1", children: ["Showing", jsx("span", { className: "font-medium", children: total === 0 ? 0 : Math.max(currentPage * limit - limit + 1, 1) }), "to", jsx("span", { className: "font-medium", children: Math.min(currentPage * limit, total) }), "of", jsx("span", { className: "font-medium", children: total }), "results"] }), jsxs("nav", { className: "isolate inline-flex items-center rounded-md", "aria-label": "Pagination", children: [jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "data-testid": "
|
|
547
|
+
return (jsxs("div", { "data-testid": "pagination-container", className: buildClassName('flex items-center justify-between bg-white dark:bg-gray-800 px-4 py-3 sm:px-6', className), children: [jsxs("div", { className: "flex flex-1 justify-between sm:hidden", children: [jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "data-testid": "mobile-prev-btn", children: [jsx("span", { children: "Previous" }), jsx(SvgChevronLeft, { className: "size-4" })] }), jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "data-testid": "mobile-next-btn", children: [jsx("span", { children: "Next" }), jsx(SvgChevronRight, { className: "size-4" })] })] }), jsxs("div", { className: "hidden sm:flex sm:flex-1 sm:items-center sm:justify-between", children: [jsxs("p", { "data-testid": "pagination-summary", className: "text-sm text-gray-600 dark:text-gray-400 flex items-center gap-1", children: ["Showing", jsx("span", { className: "font-medium", children: total === 0 ? 0 : Math.max(currentPage * limit - limit + 1, 1) }), "to", jsx("span", { className: "font-medium", children: Math.min(currentPage * limit, total) }), "of", jsx("span", { className: "font-medium", children: total }), "results"] }), jsxs("nav", { className: "isolate inline-flex items-center rounded-md", "aria-label": "Pagination", children: [jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "data-testid": "prev-btn", children: [jsx("span", { className: "sr-only", children: "Previous" }), jsx(SvgChevronLeft, { className: "size-4" })] }), pages.map((page) => (jsx(Button, { size: "xs", theme: page === currentPage ? 'primary' : 'secondary', variant: page === currentPage ? 'default' : 'plain', "aria-current": page === currentPage ? 'page' : undefined, onClick: () => handlePageChange(page), children: jsx("span", { className: "size-4 block", children: page }) }, page))), jsxs(Button, { size: "xs", theme: "secondary", variant: "plain", disabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "data-testid": "next-btn", children: [jsx("span", { className: "sr-only", children: "Next" }), jsx(SvgChevronRight, { className: "size-4" })] })] })] })] }));
|
|
548
548
|
};
|
|
549
549
|
|
|
550
550
|
function get(obj, path, defaultValue) {
|
|
@@ -733,9 +733,13 @@ const autoSortItems = (items, column, sort) => {
|
|
|
733
733
|
};
|
|
734
734
|
const DataTable = ({ items, columns, sorting = {}, onSort, loading, pagination = null, setPagination = () => { }, emptyMessage = 'No data found', containerClass = '', wrapperClass = '', layout = 'auto', }) => {
|
|
735
735
|
const internalSorting = useRef({});
|
|
736
|
+
const [sortedItems, setSortedItems] = useState(items);
|
|
737
|
+
useEffect(() => {
|
|
738
|
+
setSortedItems(items);
|
|
739
|
+
}, [items]);
|
|
736
740
|
const doAutoSort = (column) => {
|
|
737
741
|
internalSorting.current = updateSortQuery(internalSorting.current, column.name, column.type);
|
|
738
|
-
autoSortItems(items, column, internalSorting.current[column.name]);
|
|
742
|
+
setSortedItems(autoSortItems(items, column, internalSorting.current[column.name]));
|
|
739
743
|
};
|
|
740
744
|
const handleSort = (column) => {
|
|
741
745
|
if (!column.sortable)
|
|
@@ -744,7 +748,7 @@ const DataTable = ({ items, columns, sorting = {}, onSort, loading, pagination =
|
|
|
744
748
|
};
|
|
745
749
|
return (jsxs("div", { className: buildClassName('w-full rounded-lg relative', containerClass), children: [jsx("div", { className: buildClassName('overflow-x-auto overflow-y-hidden rounded-lg border border-gray-200 dark:border-gray-800', wrapperClass, pagination && 'rounded-b-none border-b-0'), children: jsxs(Table, { className: "relative w-full max-w-full h-fit", layout: layout, children: [jsx(TableHead, { children: columns.map((column) => (jsx(TableHeaderCell, { align: column.headerAlign, style: { width: column.width || 'auto' }, className: buildClassName('bg-gray-50 dark:bg-gray-800', column.sticky === 'left' &&
|
|
746
750
|
'sticky left-0 z-10 shadow-[2px_0_6px_rgba(0,0,0,0.06)]', column.sticky === 'right' &&
|
|
747
|
-
'sticky right-0 z-10 shadow-[-2px_0_6px_rgba(0,0,0,0.06)]'), children: jsxs(TextContent, { role: column.sortable ? 'button' : undefined, className: buildClassName('group', column.sortable && 'inline-flex items-center gap-2 cursor-pointer select-none'), onClick: () => handleSort(column), children: [jsx(TextContent, { className: "shrink-0", children: column.label }), column.sortable ? getSortIcon(sorting[column.name]) : null] }) }, column.name))) }), jsx(TableBody, { loading: loading, colSize: columns.length, rowSize: (pagination === null || pagination === void 0 ? void 0 : pagination.limit) || 5, children: !loading &&
|
|
751
|
+
'sticky right-0 z-10 shadow-[-2px_0_6px_rgba(0,0,0,0.06)]'), children: jsxs(TextContent, { role: column.sortable ? 'button' : undefined, className: buildClassName('group', column.sortable && 'inline-flex items-center gap-2 cursor-pointer select-none'), onClick: () => handleSort(column), children: [jsx(TextContent, { className: "shrink-0", children: column.label }), column.sortable ? getSortIcon(sorting[column.name]) : null] }) }, column.name))) }), jsx(TableBody, { loading: loading, colSize: columns.length, rowSize: (pagination === null || pagination === void 0 ? void 0 : pagination.limit) || 5, children: !loading && sortedItems.length === 0 ? (jsx(EmptyTableRow, { colSpan: columns.length, children: emptyMessage })) : (sortedItems.map((item) => (jsx(TableRow, { className: "group", children: columns.map((column) => {
|
|
748
752
|
var _a;
|
|
749
753
|
return (jsx(TableCell, { align: column.align, className: buildClassName(column.sticky === 'left' &&
|
|
750
754
|
'sticky left-0 z-10 shadow-[2px_0_6px_rgba(0,0,0,0.06)]', column.sticky === 'right' &&
|
|
@@ -858,7 +862,7 @@ Input.displayName = 'Input';
|
|
|
858
862
|
const PASSWORD_TYPE = 'password';
|
|
859
863
|
const PASSWORD_PLACEHOLDER = '••••••••••';
|
|
860
864
|
const PasswordInput = (props) => {
|
|
861
|
-
const {
|
|
865
|
+
const { ...inputProps } = props;
|
|
862
866
|
const [showPassword, setShowPassword] = useState(false);
|
|
863
867
|
return (jsx(Input, { ...inputProps, type: showPassword ? 'text' : PASSWORD_TYPE, placeholder: PASSWORD_PLACEHOLDER, rightGroup: jsx(Button, { theme: "secondary", variant: "plain", size: "xs", className: "px-1 mr-1", type: "button", onClick: () => setShowPassword(() => !showPassword), tabIndex: -1, children: showPassword ? (jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: "1.5", stroke: "currentColor", className: "size-4", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88" }) })) : (jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: "1.5", stroke: "currentColor", className: "size-4", children: [jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" }), jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" })] })) }) }));
|
|
864
868
|
};
|
|
@@ -868,8 +872,9 @@ const Radio = forwardRef((props, ref) => {
|
|
|
868
872
|
const { id, name, label, labelClass = '', wrapperClass = '', containerClass = '', error, disabled = false, className = '',
|
|
869
873
|
// RadioButton-only props removed from rest
|
|
870
874
|
...rest } = props;
|
|
871
|
-
const
|
|
872
|
-
|
|
875
|
+
const generatedId = useId();
|
|
876
|
+
const radioId = (_a = id !== null && id !== void 0 ? id : name) !== null && _a !== void 0 ? _a : generatedId;
|
|
877
|
+
return (jsxs("div", { className: buildClassName(wrapperClass), children: [jsxs("div", { className: buildClassName('flex items-center gap-2', containerClass), children: [jsx("div", { className: "grid place-items-center", children: jsx("input", { ref: ref, ...rest, id: radioId, name: name, type: "radio", disabled: disabled, "aria-checked": rest.checked, className: buildClassName('peer transition-all col-start-1 row-start-1 appearance-none shrink-0 size-4.5 rounded-full', 'border focus:ring-2 focus:ring-offset-2', 'checked:border-5 checked:bg-white', 'focus:ring-blue-500 checked:focus:ring-blue-600 dark:focus:ring-offset-gray-800', disabled
|
|
873
878
|
? 'border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-800 pointer-events-none'
|
|
874
879
|
: buildClassName('bg-white dark:bg-gray-700 border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500', 'checked:border-blue-600 checked:hover:border-blue-600 dark:checked:border-blue-600 dark:checked:hover:border-blue-600'), className) }) }), label && (jsx(Label, { htmlFor: radioId, className: buildClassName(disabled
|
|
875
880
|
? 'cursor-not-allowed text-gray-400 dark:text-gray-500'
|
|
@@ -878,16 +883,9 @@ const Radio = forwardRef((props, ref) => {
|
|
|
878
883
|
|
|
879
884
|
const RadioGroup = (props) => {
|
|
880
885
|
const { name, label, labelClass, labelWrapperClass, labelHint, containerClass, options, value, row, error, showErrorMessage, onChange, } = props;
|
|
881
|
-
const
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
return options === null || options === void 0 ? void 0 : options.map((option) => {
|
|
885
|
-
if (typeof option === 'string') {
|
|
886
|
-
return { label: option, value: option };
|
|
887
|
-
}
|
|
888
|
-
return option;
|
|
889
|
-
});
|
|
890
|
-
});
|
|
886
|
+
const items = useMemo(() => {
|
|
887
|
+
var _a;
|
|
888
|
+
return (_a = options === null || options === void 0 ? void 0 : options.map((option) => typeof option === 'string' ? { label: option, value: option } : option)) !== null && _a !== void 0 ? _a : [];
|
|
891
889
|
}, [options]);
|
|
892
890
|
return (jsxs("div", { className: buildClassName(containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between mb-4', labelWrapperClass), children: [jsx(Label, { className: labelClass, children: label }), labelHint] })), jsx("div", { className: buildClassName('flex gap-4', row ? 'flex-row items-center' : 'flex-col items-start'), children: items.map((item) => (jsx(Radio, { name: name, id: `${name}-${item.value}`, label: item.label, value: item.value, checked: value === item.value, onChange: onChange }, item.value))) }), showErrorMessage && error && (jsx("div", { className: "mt-1", children: jsx(TextContent, { error: true, small: true, children: error }) }))] }));
|
|
893
891
|
};
|
|
@@ -981,35 +979,53 @@ const RangeSlider = ({ label, labelHint, labelClass = '', containerClass = '', c
|
|
|
981
979
|
const activeThumbRef = useRef(null);
|
|
982
980
|
// State for UI styling
|
|
983
981
|
const [activeThumbState, setActiveThumbState] = useState(null);
|
|
982
|
+
// Keep prop values in refs so drag handlers always use latest values (no stale closure)
|
|
983
|
+
const valueMinRef = useRef(valueMin);
|
|
984
|
+
const valueMaxRef = useRef(valueMax);
|
|
985
|
+
const onChangeRef = useRef(onChange);
|
|
986
|
+
valueMinRef.current = valueMin;
|
|
987
|
+
valueMaxRef.current = valueMax;
|
|
988
|
+
onChangeRef.current = onChange;
|
|
984
989
|
const hasError = !isEmpty(error);
|
|
985
990
|
const percent = (v) => ((v - min) / (max - min)) * 100;
|
|
986
|
-
//
|
|
987
|
-
//
|
|
988
|
-
|
|
989
|
-
const pointerMoveHandler = (e) => {
|
|
991
|
+
// Stable handler references registered on window — these never change identity
|
|
992
|
+
// so removeEventListener always finds the right listener to remove.
|
|
993
|
+
const stablePointerMoveRef = useRef((e) => {
|
|
990
994
|
if (!trackRef.current || !activeThumbRef.current)
|
|
991
995
|
return;
|
|
992
996
|
const rect = trackRef.current.getBoundingClientRect();
|
|
993
997
|
const x = Math.min(Math.max(e.clientX - rect.left, 0), rect.width);
|
|
994
998
|
const rawVal = min + (x / rect.width) * (max - min);
|
|
995
999
|
if (activeThumbRef.current === 'min') {
|
|
996
|
-
|
|
1000
|
+
onChangeRef.current(Math.min(rawVal, valueMaxRef.current - 1), valueMaxRef.current);
|
|
997
1001
|
}
|
|
998
1002
|
else {
|
|
999
|
-
|
|
1003
|
+
onChangeRef.current(valueMinRef.current, Math.max(rawVal, valueMinRef.current + 1));
|
|
1000
1004
|
}
|
|
1001
|
-
};
|
|
1002
|
-
const
|
|
1005
|
+
});
|
|
1006
|
+
const stablePointerUpRef = useRef(() => {
|
|
1003
1007
|
activeThumbRef.current = null;
|
|
1004
1008
|
setActiveThumbState(null);
|
|
1005
|
-
window.removeEventListener('pointermove',
|
|
1006
|
-
window.removeEventListener('pointerup',
|
|
1007
|
-
};
|
|
1008
|
-
|
|
1009
|
+
window.removeEventListener('pointermove', stablePointerMoveRef.current);
|
|
1010
|
+
window.removeEventListener('pointerup', stablePointerUpRef.current);
|
|
1011
|
+
});
|
|
1012
|
+
// Remove listeners on unmount in case a drag is in progress
|
|
1013
|
+
useEffect(() => {
|
|
1014
|
+
const move = stablePointerMoveRef.current;
|
|
1015
|
+
const up = stablePointerUpRef.current;
|
|
1016
|
+
return () => {
|
|
1017
|
+
window.removeEventListener('pointermove', move);
|
|
1018
|
+
window.removeEventListener('pointerup', up);
|
|
1019
|
+
};
|
|
1020
|
+
}, []);
|
|
1021
|
+
// ---------------------------------------------
|
|
1022
|
+
// Pointer Move (drag)
|
|
1023
|
+
// ---------------------------------------------
|
|
1024
|
+
const startDrag = (thumb) => (_e) => {
|
|
1009
1025
|
activeThumbRef.current = thumb;
|
|
1010
1026
|
setActiveThumbState(thumb);
|
|
1011
|
-
window.addEventListener('pointermove',
|
|
1012
|
-
window.addEventListener('pointerup',
|
|
1027
|
+
window.addEventListener('pointermove', stablePointerMoveRef.current);
|
|
1028
|
+
window.addEventListener('pointerup', stablePointerUpRef.current);
|
|
1013
1029
|
};
|
|
1014
1030
|
// ---------------------------------------------
|
|
1015
1031
|
// Click Track to move closest thumb
|
|
@@ -1071,6 +1087,9 @@ const useDebounce = (value, delay) => {
|
|
|
1071
1087
|
};
|
|
1072
1088
|
const useDebounceFn = (fn, ms) => {
|
|
1073
1089
|
const timeout = useRef(null);
|
|
1090
|
+
useEffect(() => {
|
|
1091
|
+
return () => clearTimeout(timeout.current);
|
|
1092
|
+
}, []);
|
|
1074
1093
|
return useCallback((...args) => {
|
|
1075
1094
|
clearTimeout(timeout.current);
|
|
1076
1095
|
timeout.current = setTimeout(() => fn(...args), ms);
|
|
@@ -1235,7 +1254,7 @@ const SelectBox = forwardRef((props, forwardedRef) => {
|
|
|
1235
1254
|
console.error('onAdd handler error', err);
|
|
1236
1255
|
}
|
|
1237
1256
|
}, [onAdd, handleOnChangeInternal]);
|
|
1238
|
-
const handleSearch = async (searchString) => {
|
|
1257
|
+
const handleSearch = useCallback(async (searchString) => {
|
|
1239
1258
|
var _a;
|
|
1240
1259
|
try {
|
|
1241
1260
|
setOptionsLoading(true);
|
|
@@ -1247,11 +1266,11 @@ const SelectBox = forwardRef((props, forwardedRef) => {
|
|
|
1247
1266
|
finally {
|
|
1248
1267
|
setOptionsLoading(false);
|
|
1249
1268
|
}
|
|
1250
|
-
};
|
|
1269
|
+
}, [props.onSearch]);
|
|
1251
1270
|
useEffect(() => {
|
|
1252
1271
|
if (async && debouncedQuery)
|
|
1253
1272
|
handleSearch(debouncedQuery);
|
|
1254
|
-
}, [debouncedQuery, async]);
|
|
1273
|
+
}, [debouncedQuery, async, handleSearch]);
|
|
1255
1274
|
return (jsxs("div", { className: buildClassName('group space-y-2', hasError && 'has-error', containerClass), ref: containerRef, children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, "aria-required": required, children: label }), labelHint] })), jsxs(Combobox, { multiple: multiple, immediate: immediate, name: name, value: selected, onChange: comboboxOnChangeWrapper, onClose: () => setQuery(''), disabled: disabled, children: [multiple ? (jsxs("div", { className: buildClassName(inputClass, 'flex flex-wrap gap-2 peer relative'), ref: forwardedRef, children: [isArray(selected) &&
|
|
1256
1275
|
(selected === null || selected === void 0 ? void 0 : selected.length) > 0 &&
|
|
1257
1276
|
selected.map((option, idx) => (jsx(Badge, { theme: "secondary", removable: !disabled, onRemove: () => removeSelection(idx), children: getDisplayValue(option) }, `${getValue(option)}-${idx}`))), jsx(ComboboxInput, { className: "outline-none flex-1 dark:placeholder-gray-400 placeholder-gray-400", "aria-label": name, value: query, autoComplete: "off", placeholder: (selected === null || selected === void 0 ? void 0 : selected.length) ? '' : placeholder, onChange: (e) => setQuery(e.target.value), id: id, ref: inputRef, onKeyDown: (e) => {
|
|
@@ -1364,7 +1383,11 @@ const ToastProvider = ({ children, placement = 'top-center' }) => {
|
|
|
1364
1383
|
timeoutRefs.current.delete(id);
|
|
1365
1384
|
}
|
|
1366
1385
|
};
|
|
1367
|
-
const
|
|
1386
|
+
const closeToast = useCallback((id) => {
|
|
1387
|
+
clearTimer(id);
|
|
1388
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
1389
|
+
}, []);
|
|
1390
|
+
const scheduleClose = useCallback((toast) => {
|
|
1368
1391
|
if (!toast.autoClose)
|
|
1369
1392
|
return;
|
|
1370
1393
|
clearTimer(toast.id);
|
|
@@ -1372,7 +1395,11 @@ const ToastProvider = ({ children, placement = 'top-center' }) => {
|
|
|
1372
1395
|
closeToast(toast.id);
|
|
1373
1396
|
}, toast.duration);
|
|
1374
1397
|
timeoutRefs.current.set(toast.id, timeout);
|
|
1375
|
-
};
|
|
1398
|
+
}, [closeToast]);
|
|
1399
|
+
useEffect(() => {
|
|
1400
|
+
const refs = timeoutRefs.current;
|
|
1401
|
+
return () => refs.forEach((id) => clearTimeout(id));
|
|
1402
|
+
}, []);
|
|
1376
1403
|
const showToast = useCallback((message, options) => {
|
|
1377
1404
|
var _a, _b, _c, _d;
|
|
1378
1405
|
const id = ++toastCounter;
|
|
@@ -1391,612 +1418,12 @@ const ToastProvider = ({ children, placement = 'top-center' }) => {
|
|
|
1391
1418
|
return updated;
|
|
1392
1419
|
});
|
|
1393
1420
|
scheduleClose(newToast);
|
|
1394
|
-
}, []);
|
|
1395
|
-
const closeToast = useCallback((id) => {
|
|
1396
|
-
clearTimer(id);
|
|
1397
|
-
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
1398
|
-
}, []);
|
|
1421
|
+
}, [scheduleClose]);
|
|
1399
1422
|
return (jsxs(ToastContext.Provider, { value: { showToast, closeToast }, children: [children, jsx("div", { className: buildClassName('fixed z-50 flex flex-col gap-3 pointer-events-none', placementClass[placement]), children: toasts.map((toast, index) => (jsx("div", { className: "pointer-events-auto", onMouseEnter: () => toast.pauseOnHover && clearTimer(toast.id), onMouseLeave: () => toast.pauseOnHover && scheduleClose(toast), children: jsx(Toast, { ...toast, isTop: placement.startsWith('top'), onClose: () => closeToast(toast.id) }) }, toast.id))) })] }));
|
|
1400
1423
|
};
|
|
1401
1424
|
|
|
1402
|
-
const
|
|
1403
|
-
|
|
1404
|
-
if (e !== void 0)
|
|
1405
|
-
switch (typeof e) {
|
|
1406
|
-
case "number":
|
|
1407
|
-
return e;
|
|
1408
|
-
case "string": {
|
|
1409
|
-
if (e.endsWith("px"))
|
|
1410
|
-
return parseFloat(e);
|
|
1411
|
-
break;
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
function Ie({
|
|
1416
|
-
box: e,
|
|
1417
|
-
defaultHeight: t,
|
|
1418
|
-
defaultWidth: s,
|
|
1419
|
-
disabled: r,
|
|
1420
|
-
element: n,
|
|
1421
|
-
mode: o,
|
|
1422
|
-
style: i
|
|
1423
|
-
}) {
|
|
1424
|
-
const { styleHeight: f, styleWidth: l } = useMemo(
|
|
1425
|
-
() => ({
|
|
1426
|
-
styleHeight: oe(i?.height),
|
|
1427
|
-
styleWidth: oe(i?.width)
|
|
1428
|
-
}),
|
|
1429
|
-
[i?.height, i?.width]
|
|
1430
|
-
), [c, d] = useState({
|
|
1431
|
-
height: t,
|
|
1432
|
-
width: s
|
|
1433
|
-
}), a = r || f !== void 0 || o === "only-width" || f !== void 0 && l !== void 0;
|
|
1434
|
-
return q(() => {
|
|
1435
|
-
if (n === null || a)
|
|
1436
|
-
return;
|
|
1437
|
-
const u = new ResizeObserver((I) => {
|
|
1438
|
-
for (const m of I) {
|
|
1439
|
-
const { contentRect: b, target: g } = m;
|
|
1440
|
-
n === g && d((w) => w.height === b.height && w.width === b.width ? w : {
|
|
1441
|
-
height: b.height,
|
|
1442
|
-
width: b.width
|
|
1443
|
-
});
|
|
1444
|
-
}
|
|
1445
|
-
});
|
|
1446
|
-
return u.observe(n, { box: e }), () => {
|
|
1447
|
-
u?.unobserve(n);
|
|
1448
|
-
};
|
|
1449
|
-
}, [e, a, n, f, l]), useMemo(
|
|
1450
|
-
() => ({
|
|
1451
|
-
height: f ?? c.height,
|
|
1452
|
-
width: l ?? c.width
|
|
1453
|
-
}),
|
|
1454
|
-
[c, f, l]
|
|
1455
|
-
);
|
|
1456
|
-
}
|
|
1457
|
-
function ae(e) {
|
|
1458
|
-
const t = useRef(() => {
|
|
1459
|
-
throw new Error("Cannot call during render.");
|
|
1460
|
-
});
|
|
1461
|
-
return q(() => {
|
|
1462
|
-
t.current = e;
|
|
1463
|
-
}, [e]), useCallback((s) => t.current?.(s), [t]);
|
|
1464
|
-
}
|
|
1465
|
-
function Z({
|
|
1466
|
-
containerElement: e,
|
|
1467
|
-
direction: t,
|
|
1468
|
-
isRtl: s,
|
|
1469
|
-
scrollOffset: r
|
|
1470
|
-
}) {
|
|
1471
|
-
return r;
|
|
1472
|
-
}
|
|
1473
|
-
function $(e, t = "Assertion error") {
|
|
1474
|
-
if (!e)
|
|
1475
|
-
throw console.error(t), Error(t);
|
|
1476
|
-
}
|
|
1477
|
-
function Y(e, t) {
|
|
1478
|
-
if (e === t)
|
|
1479
|
-
return true;
|
|
1480
|
-
if (!!e != !!t || ($(e !== void 0), $(t !== void 0), Object.keys(e).length !== Object.keys(t).length))
|
|
1481
|
-
return false;
|
|
1482
|
-
for (const s in e)
|
|
1483
|
-
if (!Object.is(t[s], e[s]))
|
|
1484
|
-
return false;
|
|
1485
|
-
return true;
|
|
1486
|
-
}
|
|
1487
|
-
function fe({
|
|
1488
|
-
cachedBounds: e,
|
|
1489
|
-
itemCount: t,
|
|
1490
|
-
itemSize: s
|
|
1491
|
-
}) {
|
|
1492
|
-
if (t === 0)
|
|
1493
|
-
return 0;
|
|
1494
|
-
if (typeof s == "number")
|
|
1495
|
-
return t * s;
|
|
1496
|
-
{
|
|
1497
|
-
const r = e.get(
|
|
1498
|
-
e.size === 0 ? 0 : e.size - 1
|
|
1499
|
-
);
|
|
1500
|
-
$(r !== void 0, "Unexpected bounds cache miss");
|
|
1501
|
-
const n = (r.scrollOffset + r.size) / e.size;
|
|
1502
|
-
return t * n;
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
function we({
|
|
1506
|
-
align: e,
|
|
1507
|
-
cachedBounds: t,
|
|
1508
|
-
index: s,
|
|
1509
|
-
itemCount: r,
|
|
1510
|
-
itemSize: n,
|
|
1511
|
-
containerScrollOffset: o,
|
|
1512
|
-
containerSize: i
|
|
1513
|
-
}) {
|
|
1514
|
-
if (s < 0 || s >= r)
|
|
1515
|
-
throw RangeError(`Invalid index specified: ${s}`, {
|
|
1516
|
-
cause: `Index ${s} is not within the range of 0 - ${r - 1}`
|
|
1517
|
-
});
|
|
1518
|
-
const f = fe({
|
|
1519
|
-
cachedBounds: t,
|
|
1520
|
-
itemCount: r,
|
|
1521
|
-
itemSize: n
|
|
1522
|
-
}), l = t.get(s), c = Math.max(
|
|
1523
|
-
0,
|
|
1524
|
-
Math.min(f - i, l.scrollOffset)
|
|
1525
|
-
), d = Math.max(
|
|
1526
|
-
0,
|
|
1527
|
-
l.scrollOffset - i + l.size
|
|
1528
|
-
);
|
|
1529
|
-
switch (e === "smart" && (o >= d && o <= c ? e = "auto" : e = "center"), e) {
|
|
1530
|
-
case "start":
|
|
1531
|
-
return c;
|
|
1532
|
-
case "end":
|
|
1533
|
-
return d;
|
|
1534
|
-
case "center":
|
|
1535
|
-
return l.scrollOffset <= i / 2 ? 0 : l.scrollOffset + l.size / 2 >= f - i / 2 ? f - i : l.scrollOffset + l.size / 2 - i / 2;
|
|
1536
|
-
case "auto":
|
|
1537
|
-
default:
|
|
1538
|
-
return o >= d && o <= c ? o : o < d ? d : c;
|
|
1539
|
-
}
|
|
1540
|
-
}
|
|
1541
|
-
function ie({
|
|
1542
|
-
cachedBounds: e,
|
|
1543
|
-
containerScrollOffset: t,
|
|
1544
|
-
containerSize: s,
|
|
1545
|
-
itemCount: r,
|
|
1546
|
-
overscanCount: n
|
|
1547
|
-
}) {
|
|
1548
|
-
const o = r - 1;
|
|
1549
|
-
let i = 0, f = -1, l = 0, c = -1, d = 0;
|
|
1550
|
-
for (; d < o; ) {
|
|
1551
|
-
const a = e.get(d);
|
|
1552
|
-
if (a.scrollOffset + a.size > t)
|
|
1553
|
-
break;
|
|
1554
|
-
d++;
|
|
1555
|
-
}
|
|
1556
|
-
for (i = d, l = Math.max(0, i - n); d < o; ) {
|
|
1557
|
-
const a = e.get(d);
|
|
1558
|
-
if (a.scrollOffset + a.size >= t + s)
|
|
1559
|
-
break;
|
|
1560
|
-
d++;
|
|
1561
|
-
}
|
|
1562
|
-
return f = Math.min(o, d), c = Math.min(r - 1, f + n), i < 0 && (i = 0, f = -1, l = 0, c = -1), {
|
|
1563
|
-
startIndexVisible: i,
|
|
1564
|
-
stopIndexVisible: f,
|
|
1565
|
-
startIndexOverscan: l,
|
|
1566
|
-
stopIndexOverscan: c
|
|
1567
|
-
};
|
|
1568
|
-
}
|
|
1569
|
-
function me({
|
|
1570
|
-
itemCount: e,
|
|
1571
|
-
itemProps: t,
|
|
1572
|
-
itemSize: s
|
|
1573
|
-
}) {
|
|
1574
|
-
const r = /* @__PURE__ */ new Map();
|
|
1575
|
-
return {
|
|
1576
|
-
get(n) {
|
|
1577
|
-
for ($(n < e, `Invalid index ${n}`); r.size - 1 < n; ) {
|
|
1578
|
-
const i = r.size;
|
|
1579
|
-
let f;
|
|
1580
|
-
switch (typeof s) {
|
|
1581
|
-
case "function": {
|
|
1582
|
-
f = s(i, t);
|
|
1583
|
-
break;
|
|
1584
|
-
}
|
|
1585
|
-
case "number": {
|
|
1586
|
-
f = s;
|
|
1587
|
-
break;
|
|
1588
|
-
}
|
|
1589
|
-
}
|
|
1590
|
-
if (i === 0)
|
|
1591
|
-
r.set(i, {
|
|
1592
|
-
size: f,
|
|
1593
|
-
scrollOffset: 0
|
|
1594
|
-
});
|
|
1595
|
-
else {
|
|
1596
|
-
const l = r.get(i - 1);
|
|
1597
|
-
$(
|
|
1598
|
-
l !== void 0,
|
|
1599
|
-
`Unexpected bounds cache miss for index ${n}`
|
|
1600
|
-
), r.set(i, {
|
|
1601
|
-
scrollOffset: l.scrollOffset + l.size,
|
|
1602
|
-
size: f
|
|
1603
|
-
});
|
|
1604
|
-
}
|
|
1605
|
-
}
|
|
1606
|
-
const o = r.get(n);
|
|
1607
|
-
return $(
|
|
1608
|
-
o !== void 0,
|
|
1609
|
-
`Unexpected bounds cache miss for index ${n}`
|
|
1610
|
-
), o;
|
|
1611
|
-
},
|
|
1612
|
-
set(n, o) {
|
|
1613
|
-
r.set(n, o);
|
|
1614
|
-
},
|
|
1615
|
-
get size() {
|
|
1616
|
-
return r.size;
|
|
1617
|
-
}
|
|
1618
|
-
};
|
|
1619
|
-
}
|
|
1620
|
-
function Oe({
|
|
1621
|
-
itemCount: e,
|
|
1622
|
-
itemProps: t,
|
|
1623
|
-
itemSize: s
|
|
1624
|
-
}) {
|
|
1625
|
-
return useMemo(
|
|
1626
|
-
() => me({
|
|
1627
|
-
itemCount: e,
|
|
1628
|
-
itemProps: t,
|
|
1629
|
-
itemSize: s
|
|
1630
|
-
}),
|
|
1631
|
-
[e, t, s]
|
|
1632
|
-
);
|
|
1633
|
-
}
|
|
1634
|
-
function ye({
|
|
1635
|
-
containerSize: e,
|
|
1636
|
-
itemSize: t
|
|
1637
|
-
}) {
|
|
1638
|
-
let s;
|
|
1639
|
-
switch (typeof t) {
|
|
1640
|
-
case "string": {
|
|
1641
|
-
$(
|
|
1642
|
-
t.endsWith("%"),
|
|
1643
|
-
`Invalid item size: "${t}"; string values must be percentages (e.g. "100%")`
|
|
1644
|
-
), $(
|
|
1645
|
-
e !== void 0,
|
|
1646
|
-
"Container size must be defined if a percentage item size is specified"
|
|
1647
|
-
), s = e * parseInt(t) / 100;
|
|
1648
|
-
break;
|
|
1649
|
-
}
|
|
1650
|
-
default: {
|
|
1651
|
-
s = t;
|
|
1652
|
-
break;
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
|
-
return s;
|
|
1656
|
-
}
|
|
1657
|
-
function ee({
|
|
1658
|
-
containerElement: e,
|
|
1659
|
-
containerStyle: t,
|
|
1660
|
-
defaultContainerSize: s = 0,
|
|
1661
|
-
direction: r,
|
|
1662
|
-
isRtl: n = false,
|
|
1663
|
-
itemCount: o,
|
|
1664
|
-
itemProps: i,
|
|
1665
|
-
itemSize: f,
|
|
1666
|
-
onResize: l,
|
|
1667
|
-
overscanCount: c
|
|
1668
|
-
}) {
|
|
1669
|
-
const [d, a] = useState({
|
|
1670
|
-
startIndexVisible: 0,
|
|
1671
|
-
startIndexOverscan: 0,
|
|
1672
|
-
stopIndexVisible: -1,
|
|
1673
|
-
stopIndexOverscan: -1
|
|
1674
|
-
}), {
|
|
1675
|
-
startIndexVisible: u,
|
|
1676
|
-
startIndexOverscan: I,
|
|
1677
|
-
stopIndexVisible: m,
|
|
1678
|
-
stopIndexOverscan: b
|
|
1679
|
-
} = {
|
|
1680
|
-
startIndexVisible: Math.min(o - 1, d.startIndexVisible),
|
|
1681
|
-
startIndexOverscan: Math.min(o - 1, d.startIndexOverscan),
|
|
1682
|
-
stopIndexVisible: Math.min(o - 1, d.stopIndexVisible),
|
|
1683
|
-
stopIndexOverscan: Math.min(o - 1, d.stopIndexOverscan)
|
|
1684
|
-
}, { height: g = s, width: w = s } = Ie({
|
|
1685
|
-
defaultHeight: s ,
|
|
1686
|
-
defaultWidth: void 0,
|
|
1687
|
-
element: e,
|
|
1688
|
-
mode: "only-height" ,
|
|
1689
|
-
style: t
|
|
1690
|
-
}), y = useRef({
|
|
1691
|
-
height: 0,
|
|
1692
|
-
width: 0
|
|
1693
|
-
}), V = g , h = ye({ containerSize: V, itemSize: f });
|
|
1694
|
-
useLayoutEffect(() => {
|
|
1695
|
-
if (typeof l == "function") {
|
|
1696
|
-
const p = y.current;
|
|
1697
|
-
(p.height !== g || p.width !== w) && (l({ height: g, width: w }, { ...p }), p.height = g, p.width = w);
|
|
1698
|
-
}
|
|
1699
|
-
}, [g, l, w]);
|
|
1700
|
-
const z = Oe({
|
|
1701
|
-
itemCount: o,
|
|
1702
|
-
itemProps: i,
|
|
1703
|
-
itemSize: h
|
|
1704
|
-
}), k = useCallback(
|
|
1705
|
-
(p) => z.get(p),
|
|
1706
|
-
[z]
|
|
1707
|
-
), S = useCallback(
|
|
1708
|
-
() => fe({
|
|
1709
|
-
cachedBounds: z,
|
|
1710
|
-
itemCount: o,
|
|
1711
|
-
itemSize: h
|
|
1712
|
-
}),
|
|
1713
|
-
[z, o, h]
|
|
1714
|
-
), W = useCallback(
|
|
1715
|
-
(p) => {
|
|
1716
|
-
const T = Z({
|
|
1717
|
-
containerElement: e,
|
|
1718
|
-
direction: r,
|
|
1719
|
-
isRtl: n,
|
|
1720
|
-
scrollOffset: p
|
|
1721
|
-
});
|
|
1722
|
-
return ie({
|
|
1723
|
-
cachedBounds: z,
|
|
1724
|
-
containerScrollOffset: T,
|
|
1725
|
-
containerSize: V,
|
|
1726
|
-
itemCount: o,
|
|
1727
|
-
overscanCount: c
|
|
1728
|
-
});
|
|
1729
|
-
},
|
|
1730
|
-
[
|
|
1731
|
-
z,
|
|
1732
|
-
e,
|
|
1733
|
-
V,
|
|
1734
|
-
r,
|
|
1735
|
-
n,
|
|
1736
|
-
o,
|
|
1737
|
-
c
|
|
1738
|
-
]
|
|
1739
|
-
);
|
|
1740
|
-
q(() => {
|
|
1741
|
-
const p = (e?.scrollTop ) ?? 0;
|
|
1742
|
-
a(W(p));
|
|
1743
|
-
}, [e, r, W]), q(() => {
|
|
1744
|
-
if (!e)
|
|
1745
|
-
return;
|
|
1746
|
-
const p = () => {
|
|
1747
|
-
a((T) => {
|
|
1748
|
-
const { scrollLeft: R, scrollTop: v } = e, x = Z({
|
|
1749
|
-
containerElement: e,
|
|
1750
|
-
direction: r,
|
|
1751
|
-
isRtl: n,
|
|
1752
|
-
scrollOffset: v
|
|
1753
|
-
}), A = ie({
|
|
1754
|
-
cachedBounds: z,
|
|
1755
|
-
containerScrollOffset: x,
|
|
1756
|
-
containerSize: V,
|
|
1757
|
-
itemCount: o,
|
|
1758
|
-
overscanCount: c
|
|
1759
|
-
});
|
|
1760
|
-
return Y(A, T) ? T : A;
|
|
1761
|
-
});
|
|
1762
|
-
};
|
|
1763
|
-
return e.addEventListener("scroll", p), () => {
|
|
1764
|
-
e.removeEventListener("scroll", p);
|
|
1765
|
-
};
|
|
1766
|
-
}, [
|
|
1767
|
-
z,
|
|
1768
|
-
e,
|
|
1769
|
-
V,
|
|
1770
|
-
r,
|
|
1771
|
-
o,
|
|
1772
|
-
c
|
|
1773
|
-
]);
|
|
1774
|
-
const O = ae(
|
|
1775
|
-
({
|
|
1776
|
-
align: p = "auto",
|
|
1777
|
-
containerScrollOffset: T,
|
|
1778
|
-
index: R
|
|
1779
|
-
}) => {
|
|
1780
|
-
let v = we({
|
|
1781
|
-
align: p,
|
|
1782
|
-
cachedBounds: z,
|
|
1783
|
-
containerScrollOffset: T,
|
|
1784
|
-
containerSize: V,
|
|
1785
|
-
index: R,
|
|
1786
|
-
itemCount: o,
|
|
1787
|
-
itemSize: h
|
|
1788
|
-
});
|
|
1789
|
-
if (e) {
|
|
1790
|
-
if (v = Z({
|
|
1791
|
-
containerElement: e,
|
|
1792
|
-
direction: r,
|
|
1793
|
-
isRtl: n,
|
|
1794
|
-
scrollOffset: v
|
|
1795
|
-
}), typeof e.scrollTo != "function") {
|
|
1796
|
-
const x = W(v);
|
|
1797
|
-
Y(d, x) || a(x);
|
|
1798
|
-
}
|
|
1799
|
-
return v;
|
|
1800
|
-
}
|
|
1801
|
-
}
|
|
1802
|
-
);
|
|
1803
|
-
return {
|
|
1804
|
-
getCellBounds: k,
|
|
1805
|
-
getEstimatedSize: S,
|
|
1806
|
-
scrollToIndex: O,
|
|
1807
|
-
startIndexOverscan: I,
|
|
1808
|
-
startIndexVisible: u,
|
|
1809
|
-
stopIndexOverscan: b,
|
|
1810
|
-
stopIndexVisible: m
|
|
1811
|
-
};
|
|
1812
|
-
}
|
|
1813
|
-
function de(e) {
|
|
1814
|
-
return useMemo(() => e, Object.values(e));
|
|
1815
|
-
}
|
|
1816
|
-
function ue(e, t) {
|
|
1817
|
-
const {
|
|
1818
|
-
ariaAttributes: s,
|
|
1819
|
-
style: r,
|
|
1820
|
-
...n
|
|
1821
|
-
} = e, {
|
|
1822
|
-
ariaAttributes: o,
|
|
1823
|
-
style: i,
|
|
1824
|
-
...f
|
|
1825
|
-
} = t;
|
|
1826
|
-
return Y(s, o) && Y(r, i) && Y(n, f);
|
|
1827
|
-
}
|
|
1828
|
-
function ze(e) {
|
|
1829
|
-
return e != null && typeof e == "object" && "getAverageRowHeight" in e && typeof e.getAverageRowHeight == "function";
|
|
1830
|
-
}
|
|
1831
|
-
const te = "data-react-window-index";
|
|
1832
|
-
function Ae({
|
|
1833
|
-
children: e,
|
|
1834
|
-
className: t,
|
|
1835
|
-
defaultHeight: s = 0,
|
|
1836
|
-
listRef: r,
|
|
1837
|
-
onResize: n,
|
|
1838
|
-
onRowsRendered: o,
|
|
1839
|
-
overscanCount: i = 3,
|
|
1840
|
-
rowComponent: f,
|
|
1841
|
-
rowCount: l,
|
|
1842
|
-
rowHeight: c,
|
|
1843
|
-
rowProps: d,
|
|
1844
|
-
tagName: a = "div",
|
|
1845
|
-
style: u,
|
|
1846
|
-
...I
|
|
1847
|
-
}) {
|
|
1848
|
-
const m = de(d), b = useMemo(
|
|
1849
|
-
() => memo(f, ue),
|
|
1850
|
-
[f]
|
|
1851
|
-
), [g, w] = useState(null), y = ze(c), V = useMemo(() => y ? (v) => c.getRowHeight(v) ?? c.getAverageRowHeight() : c, [y, c]), {
|
|
1852
|
-
getCellBounds: h,
|
|
1853
|
-
getEstimatedSize: z,
|
|
1854
|
-
scrollToIndex: k,
|
|
1855
|
-
startIndexOverscan: S,
|
|
1856
|
-
startIndexVisible: W,
|
|
1857
|
-
stopIndexOverscan: O,
|
|
1858
|
-
stopIndexVisible: p
|
|
1859
|
-
} = ee({
|
|
1860
|
-
containerElement: g,
|
|
1861
|
-
containerStyle: u,
|
|
1862
|
-
defaultContainerSize: s,
|
|
1863
|
-
direction: "vertical",
|
|
1864
|
-
itemCount: l,
|
|
1865
|
-
itemProps: m,
|
|
1866
|
-
itemSize: V,
|
|
1867
|
-
onResize: n,
|
|
1868
|
-
overscanCount: i
|
|
1869
|
-
});
|
|
1870
|
-
useImperativeHandle(
|
|
1871
|
-
r,
|
|
1872
|
-
() => ({
|
|
1873
|
-
get element() {
|
|
1874
|
-
return g;
|
|
1875
|
-
},
|
|
1876
|
-
scrollToRow({
|
|
1877
|
-
align: v = "auto",
|
|
1878
|
-
behavior: x = "auto",
|
|
1879
|
-
index: A
|
|
1880
|
-
}) {
|
|
1881
|
-
const M = k({
|
|
1882
|
-
align: v,
|
|
1883
|
-
containerScrollOffset: g?.scrollTop ?? 0,
|
|
1884
|
-
index: A
|
|
1885
|
-
});
|
|
1886
|
-
typeof g?.scrollTo == "function" && g.scrollTo({
|
|
1887
|
-
behavior: x,
|
|
1888
|
-
top: M
|
|
1889
|
-
});
|
|
1890
|
-
}
|
|
1891
|
-
}),
|
|
1892
|
-
[g, k]
|
|
1893
|
-
), q(() => {
|
|
1894
|
-
if (!g)
|
|
1895
|
-
return;
|
|
1896
|
-
const v = Array.from(g.children).filter((x, A) => {
|
|
1897
|
-
if (x.hasAttribute("aria-hidden"))
|
|
1898
|
-
return false;
|
|
1899
|
-
const M = `${S + A}`;
|
|
1900
|
-
return x.setAttribute(te, M), true;
|
|
1901
|
-
});
|
|
1902
|
-
if (y)
|
|
1903
|
-
return c.observeRowElements(v);
|
|
1904
|
-
}, [
|
|
1905
|
-
g,
|
|
1906
|
-
y,
|
|
1907
|
-
c,
|
|
1908
|
-
S,
|
|
1909
|
-
O
|
|
1910
|
-
]), useEffect(() => {
|
|
1911
|
-
S >= 0 && O >= 0 && o && o(
|
|
1912
|
-
{
|
|
1913
|
-
startIndex: W,
|
|
1914
|
-
stopIndex: p
|
|
1915
|
-
},
|
|
1916
|
-
{
|
|
1917
|
-
startIndex: S,
|
|
1918
|
-
stopIndex: O
|
|
1919
|
-
}
|
|
1920
|
-
);
|
|
1921
|
-
}, [
|
|
1922
|
-
o,
|
|
1923
|
-
S,
|
|
1924
|
-
W,
|
|
1925
|
-
O,
|
|
1926
|
-
p
|
|
1927
|
-
]);
|
|
1928
|
-
const T = useMemo(() => {
|
|
1929
|
-
const v = [];
|
|
1930
|
-
if (l > 0)
|
|
1931
|
-
for (let x = S; x <= O; x++) {
|
|
1932
|
-
const A = h(x);
|
|
1933
|
-
v.push(
|
|
1934
|
-
/* @__PURE__ */ createElement(
|
|
1935
|
-
b,
|
|
1936
|
-
{
|
|
1937
|
-
...m,
|
|
1938
|
-
ariaAttributes: {
|
|
1939
|
-
"aria-posinset": x + 1,
|
|
1940
|
-
"aria-setsize": l,
|
|
1941
|
-
role: "listitem"
|
|
1942
|
-
},
|
|
1943
|
-
key: x,
|
|
1944
|
-
index: x,
|
|
1945
|
-
style: {
|
|
1946
|
-
position: "absolute",
|
|
1947
|
-
left: 0,
|
|
1948
|
-
transform: `translateY(${A.scrollOffset}px)`,
|
|
1949
|
-
// In case of dynamic row heights, don't specify a height style
|
|
1950
|
-
// otherwise a default/estimated height would mask the actual height
|
|
1951
|
-
height: y ? void 0 : A.size,
|
|
1952
|
-
width: "100%"
|
|
1953
|
-
}
|
|
1954
|
-
}
|
|
1955
|
-
)
|
|
1956
|
-
);
|
|
1957
|
-
}
|
|
1958
|
-
return v;
|
|
1959
|
-
}, [
|
|
1960
|
-
b,
|
|
1961
|
-
h,
|
|
1962
|
-
y,
|
|
1963
|
-
l,
|
|
1964
|
-
m,
|
|
1965
|
-
S,
|
|
1966
|
-
O
|
|
1967
|
-
]), R = /* @__PURE__ */ jsx(
|
|
1968
|
-
"div",
|
|
1969
|
-
{
|
|
1970
|
-
"aria-hidden": true,
|
|
1971
|
-
style: {
|
|
1972
|
-
height: z(),
|
|
1973
|
-
width: "100%",
|
|
1974
|
-
zIndex: -1
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
);
|
|
1978
|
-
return createElement(
|
|
1979
|
-
a,
|
|
1980
|
-
{
|
|
1981
|
-
role: "list",
|
|
1982
|
-
...I,
|
|
1983
|
-
className: t,
|
|
1984
|
-
ref: w,
|
|
1985
|
-
style: {
|
|
1986
|
-
position: "relative",
|
|
1987
|
-
maxHeight: "100%",
|
|
1988
|
-
flexGrow: 1,
|
|
1989
|
-
overflowY: "auto",
|
|
1990
|
-
...u
|
|
1991
|
-
}
|
|
1992
|
-
},
|
|
1993
|
-
T,
|
|
1994
|
-
e,
|
|
1995
|
-
R
|
|
1996
|
-
);
|
|
1997
|
-
}
|
|
1998
|
-
|
|
1999
|
-
const VirtualizedRow = ({ index, style, items, columns, gridTemplate, }) => {
|
|
1425
|
+
const VirtualizedRow = ({ index, style, data }) => {
|
|
1426
|
+
const { items, columns, gridTemplate } = data;
|
|
2000
1427
|
const item = items[index];
|
|
2001
1428
|
return (jsx("div", { role: "row", className: "grid border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 group", style: {
|
|
2002
1429
|
...style,
|
|
@@ -2018,14 +1445,21 @@ const VirtualizedRow = ({ index, style, items, columns, gridTemplate, }) => {
|
|
|
2018
1445
|
const useGridTemplate = (columns) => useMemo(() => columns.map((col) => (col.width ? `${col.width}px` : '1fr')).join(' '), [columns]);
|
|
2019
1446
|
const VirtualizedDataTable = ({ items, columns, sorting = {}, onSort, loading = false, emptyMessage = 'No data available', containerClass = '', wrapperClass = '', rowHeight = 48, maxHeight = 400, }) => {
|
|
2020
1447
|
const scrollRef = useRef(null);
|
|
1448
|
+
const outerRef = useRef(null);
|
|
2021
1449
|
const headerRef = useRef(null);
|
|
2022
1450
|
const gridTemplate = useGridTemplate(columns);
|
|
2023
|
-
/** Sync body → header
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
1451
|
+
/** Sync horizontal scroll of the virtualized body → header */
|
|
1452
|
+
useEffect(() => {
|
|
1453
|
+
const el = outerRef.current;
|
|
1454
|
+
if (!el)
|
|
1455
|
+
return;
|
|
1456
|
+
const handler = () => {
|
|
1457
|
+
if (headerRef.current)
|
|
1458
|
+
headerRef.current.scrollLeft = el.scrollLeft;
|
|
1459
|
+
};
|
|
1460
|
+
el.addEventListener('scroll', handler);
|
|
1461
|
+
return () => el.removeEventListener('scroll', handler);
|
|
1462
|
+
}, []);
|
|
2029
1463
|
const handleSort = useCallback((column) => {
|
|
2030
1464
|
if (column.sortable)
|
|
2031
1465
|
onSort === null || onSort === void 0 ? void 0 : onSort(column);
|
|
@@ -2057,11 +1491,7 @@ const VirtualizedDataTable = ({ items, columns, sorting = {}, onSort, loading =
|
|
|
2057
1491
|
/* -------------------------------------------------------
|
|
2058
1492
|
* MAIN (virtualized body)
|
|
2059
1493
|
* ------------------------------------------------------- */
|
|
2060
|
-
return (jsx("div", { className: buildClassName('w-full rounded-lg relative', containerClass), children: jsxs("div", { className: buildClassName('rounded-lg border border-gray-200 dark:border-gray-800 overflow-hidden', wrapperClass), children: [Header, jsx("
|
|
2061
|
-
height: maxHeight,
|
|
2062
|
-
overflowY: 'auto',
|
|
2063
|
-
overflowX: 'auto',
|
|
2064
|
-
}, children: jsx(Ae, { listRef: scrollRef, rowComponent: VirtualizedRow, rowCount: items.length, rowHeight: rowHeight, rowProps: { items, columns, gridTemplate }, onScroll: (e) => handleScrollSync(e.currentTarget.scrollLeft) }) })] }) }));
|
|
1494
|
+
return (jsx("div", { className: buildClassName('w-full rounded-lg relative', containerClass), children: jsxs("div", { className: buildClassName('rounded-lg border border-gray-200 dark:border-gray-800 overflow-hidden', wrapperClass), children: [Header, jsx(FixedSizeList, { ref: scrollRef, outerRef: outerRef, height: maxHeight, width: "100%", itemCount: items.length, itemSize: rowHeight, itemData: { items, columns, gridTemplate }, children: VirtualizedRow })] }) }));
|
|
2065
1495
|
};
|
|
2066
1496
|
|
|
2067
1497
|
const useIsMobile = () => {
|