@pk-design/react-tailwind 1.1.6 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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, useId, useRef, useState, useEffect, Fragment as Fragment$1, useCallback, useImperativeHandle, createContext, useContext, memo, useLayoutEffect, createElement } from 'react';
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
 
@@ -140,19 +141,19 @@ TextContent.displayName = 'TextContent';
140
141
  */
141
142
  const THEMED_BTN_CLASS = {
142
143
  primary: {
143
- default: 'text-white bg-blue-600 hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-blue-600 disabled:bg-blue-400 dark:disabled:bg-blue-500',
144
- outlined: 'text-blue-600 hover:text-white border border-blue-600 hover:bg-blue-600 dark:border-blue-500 dark:text-blue-500 dark:hover:text-white dark:hover:bg-blue-500 focus:outline-blue-600 disabled:text-blue-400 disabled:border-blue-400',
145
- plain: 'text-blue-600 hover:bg-black/5 dark:text-blue-400 dark:hover:bg-gray-700 focus:outline-blue-600 disabled:text-blue-400',
144
+ default: 'text-white bg-[var(--ui-primary)] hover:bg-[var(--ui-primary-hover)] focus:outline-[var(--ui-primary-ring)] disabled:bg-[var(--ui-primary-disabled)]',
145
+ outlined: 'text-[var(--ui-primary-text)] hover:text-white border border-[var(--ui-primary)] hover:bg-[var(--ui-primary)] focus:outline-[var(--ui-primary-ring)] disabled:text-[var(--ui-primary-disabled)] disabled:border-[var(--ui-primary-disabled)]',
146
+ plain: 'text-[var(--ui-primary-text)] hover:bg-black/5 dark:hover:bg-gray-700 focus:outline-[var(--ui-primary-ring)] disabled:text-[var(--ui-primary-disabled)]',
146
147
  },
147
148
  danger: {
148
- default: 'text-white bg-red-600 hover:bg-red-700 dark:bg-red-600 dark:hover:bg-red-700 focus:outline-red-600 disabled:bg-red-400 dark:disabled:bg-red-500',
149
- outlined: 'text-red-600 hover:text-white border border-red-600 hover:bg-red-600 dark:border-red-500 dark:text-red-500 dark:hover:text-white dark:hover:bg-red-500 focus:outline-red-600 disabled:text-red-400 disabled:border-red-400',
150
- plain: 'text-red-600 hover:bg-black/5 dark:text-red-400 dark:hover:bg-gray-700 focus:outline-red-600 disabled:text-red-400',
149
+ default: 'text-white bg-[var(--ui-danger)] hover:bg-[var(--ui-danger-hover)] focus:outline-[var(--ui-danger-ring)] disabled:bg-[var(--ui-danger-disabled)]',
150
+ outlined: 'text-[var(--ui-danger-text)] hover:text-white border border-[var(--ui-danger)] hover:bg-[var(--ui-danger)] focus:outline-[var(--ui-danger-ring)] disabled:text-[var(--ui-danger-disabled)] disabled:border-[var(--ui-danger-disabled)]',
151
+ plain: 'text-[var(--ui-danger-text)] hover:bg-black/5 dark:hover:bg-gray-700 focus:outline-[var(--ui-danger-ring)] disabled:text-[var(--ui-danger-disabled)]',
151
152
  },
152
153
  secondary: {
153
- default: 'text-gray-700 bg-white border border-gray-300 hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 focus:outline-blue-600 disabled:bg-gray-200 dark:disabled:bg-gray-700',
154
- outlined: 'text-gray-700 hover:text-white border border-gray-500 hover:bg-gray-700 dark:border-gray-500 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-600 focus:outline-blue-600 disabled:text-gray-400 disabled:border-gray-400',
155
- plain: 'text-gray-700 hover:bg-black/5 dark:text-gray-200 dark:hover:bg-gray-700 focus:outline-blue-600 disabled:text-gray-400',
154
+ default: 'text-gray-700 bg-white border border-gray-300 hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 focus:outline-[var(--ui-focus-ring)] disabled:bg-gray-200 dark:disabled:bg-gray-700',
155
+ outlined: 'text-gray-700 hover:text-white border border-gray-500 hover:bg-gray-700 dark:border-gray-500 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-600 focus:outline-[var(--ui-focus-ring)] disabled:text-gray-400 disabled:border-gray-400',
156
+ plain: 'text-gray-700 hover:bg-black/5 dark:text-gray-200 dark:hover:bg-gray-700 focus:outline-[var(--ui-focus-ring)] disabled:text-gray-400',
156
157
  },
157
158
  };
158
159
  /**
@@ -215,10 +216,10 @@ const AlertTypeIconMap = {
215
216
  info: SvgInfo,
216
217
  };
217
218
  const TypeClassMap = {
218
- success: 'bg-green-50 ring-green-600/20 text-green-700',
219
- danger: 'bg-red-50 ring-red-600/20 text-red-700',
220
- warning: 'bg-orange-50 ring-orange-600/20 text-orange-700',
221
- info: 'bg-blue-50 ring-blue-600/20 text-blue-700',
219
+ success: 'bg-[var(--ui-success-light)] ring-[var(--ui-success-ring-subtle)] text-[var(--ui-success-text)]',
220
+ danger: 'bg-[var(--ui-danger-light)] ring-[var(--ui-danger-ring-subtle)] text-[var(--ui-danger-text)]',
221
+ warning: 'bg-[var(--ui-warning-light)] ring-[var(--ui-warning-ring-subtle)] text-[var(--ui-warning-text)]',
222
+ info: 'bg-[var(--ui-info-light)] ring-[var(--ui-info-ring-subtle)] text-[var(--ui-info-text)]',
222
223
  };
223
224
  const Alert = (props) => {
224
225
  const { type = 'info', className = '', message, children, removable = false, onRemove = () => { }, ...restProps } = props;
@@ -228,11 +229,11 @@ const Alert = (props) => {
228
229
  Alert.displayName = 'Alert';
229
230
 
230
231
  const ThemeClassMap = {
231
- success: 'bg-green-50 ring-green-600/20 text-green-700 dark:bg-green-600 dark:text-green-50 dark:ring-green-400/20',
232
- danger: 'bg-red-50 dark:bg-red-600 text-red-700 dark:text-red-50 ring-red-600/20 dark:ring-red-400/20',
233
- warning: 'bg-yellow-50 dark:bg-yellow-600 text-yellow-700 dark:text-yellow-50 ring-yellow-600/20 dark:ring-yellow-400/20',
234
- info: 'bg-blue-50 dark:bg-blue-600 text-blue-700 dark:text-blue-50 ring-blue-600/20 dark:ring-blue-400/20',
235
- secondary: 'bg-gray-50 dark:bg-gray-600 text-gray-700 dark:text-gray-50 ring-gray-600/20 dark:ring-gray-400/20',
232
+ success: 'bg-[var(--ui-success-light)] text-[var(--ui-success-text)] ring-[var(--ui-success-ring-subtle)]',
233
+ danger: 'bg-[var(--ui-danger-light)] text-[var(--ui-danger-text)] ring-[var(--ui-danger-ring-subtle)]',
234
+ warning: 'bg-[var(--ui-warning-light)] text-[var(--ui-warning-text)] ring-[var(--ui-warning-ring-subtle)]',
235
+ info: 'bg-[var(--ui-info-light)] text-[var(--ui-info-text)] ring-[var(--ui-info-ring-subtle)]',
236
+ secondary: 'bg-gray-50 dark:bg-gray-700 text-gray-700 dark:text-gray-200 ring-[var(--ui-secondary-ring-subtle)]',
236
237
  };
237
238
  const Badge = forwardRef((props, ref) => {
238
239
  const { theme = 'info', className = '', children, removable = false, rounded = false, onRemove = () => { }, ...restProps } = props;
@@ -374,7 +375,7 @@ const Checkbox = forwardRef((props, ref) => {
374
375
  ...rest } = props;
375
376
  const generatedId = useId();
376
377
  const checkboxId = (_a = id !== null && id !== void 0 ? id : name) !== null && _a !== void 0 ? _a : generatedId;
377
- 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
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-[var(--ui-primary)] checked:border-[var(--ui-primary)]', 'focus:ring-[var(--ui-focus-ring)] dark:focus:ring-offset-gray-900', disabled
378
379
  ? 'border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-800 pointer-events-none'
379
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
380
381
  ? 'cursor-not-allowed text-gray-400 dark:text-gray-500'
@@ -846,8 +847,8 @@ function buildInputClass(className, { isFocusWithin = false, disabled = false }
846
847
  return buildClassName('transition-all', 'block w-full rounded-lg bg-white px-3.5 py-2 text-base sm:text-sm/6', 'text-gray-900 outline outline-1 -outline-offset-1', 'outline-gray-300 dark:outline-gray-600', 'invalid:group-[.has-error]:outline-red-500', disabled
847
848
  ? 'pointer-events-none bg-gray-100 dark:bg-gray-800 dark:text-gray-600 dark:placeholder-gray-600 placeholder-gray-400 outline-gray-200 dark:outline-gray-700'
848
849
  : 'bg-white dark:bg-gray-700 dark:text-white outline-gray-300 dark:outline-gray-600 dark:placeholder-gray-400 placeholder-gray-400', isFocusWithin
849
- ? 'focus-within:outline-blue-600 dark:focus-within:outline-blue-600 focus-within:outline-2 focus-within:-outline-offset-2'
850
- : 'focus:outline-blue-600 dark:focus:outline-blue-600 focus:outline-2 focus:-outline-offset-2', className);
850
+ ? 'focus-within:outline-[var(--ui-focus-ring)] focus-within:outline-2 focus-within:-outline-offset-2'
851
+ : 'focus:outline-[var(--ui-focus-ring)] focus:outline-2 focus:-outline-offset-2', className);
851
852
  }
852
853
  const Input = forwardRef((props, ref) => {
853
854
  const { name, id = name, type, label, labelHint, className, labelClass, labelWrapperClass, containerClass, error, showErrorMessage = true, rightGroup, leftGroup, ...inputProps } = props;
@@ -873,9 +874,9 @@ const Radio = forwardRef((props, ref) => {
873
874
  ...rest } = props;
874
875
  const generatedId = useId();
875
876
  const radioId = (_a = id !== null && id !== void 0 ? id : name) !== null && _a !== void 0 ? _a : generatedId;
876
- 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
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-[var(--ui-focus-ring)] dark:focus:ring-offset-gray-800', disabled
877
878
  ? 'border-gray-200 dark:border-gray-700 bg-gray-100 dark:bg-gray-800 pointer-events-none'
878
- : 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
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-[var(--ui-primary)] checked:hover:border-[var(--ui-primary)]'), className) }) }), label && (jsx(Label, { htmlFor: radioId, className: buildClassName(disabled
879
880
  ? 'cursor-not-allowed text-gray-400 dark:text-gray-500'
880
881
  : 'cursor-pointer text-gray-600 dark:text-gray-300', labelClass), children: label }))] }), error && (jsx("div", { className: "mt-1", children: jsx(TextContent, { error: true, small: true, children: error }) }))] }));
881
882
  });
@@ -1294,13 +1295,13 @@ function buildTabClass({ selected, variant, }) {
1294
1295
  */
1295
1296
  case 'underline':
1296
1297
  return buildClassName('px-3 py-1.5 text-sm font-medium transition relative', 'text-gray-600 dark:text-gray-300', 'hover:text-gray-900 dark:hover:text-white', selected &&
1297
- 'text-gray-900 dark:text-white after:absolute after:left-0 after:right-0 after:-bottom-1 after:h-0.5 after:bg-blue-600');
1298
+ 'text-gray-900 dark:text-white after:absolute after:left-0 after:right-0 after:-bottom-1 after:h-0.5 after:bg-[var(--ui-primary)]');
1298
1299
  /**
1299
1300
  * SEGMENTED
1300
1301
  */
1301
1302
  case 'segmented':
1302
1303
  return buildClassName('px-3 py-1.5 text-sm font-medium rounded-lg transition', selected
1303
- ? 'bg-blue-600 text-white'
1304
+ ? 'bg-[var(--ui-primary)] text-white'
1304
1305
  : 'text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700');
1305
1306
  /**
1306
1307
  * SOLID
@@ -1324,29 +1325,22 @@ const Textarea = forwardRef((props, ref) => {
1324
1325
  * Icons for each toast type
1325
1326
  */
1326
1327
  const iconMap = {
1327
- success: jsx(SvgCircleCheck, { className: "size-5 text-green-600 dark:text-green-400" }),
1328
- error: jsx(SvgCircleAlert, { className: "size-5 text-red-600 dark:text-red-400" }),
1329
- info: jsx(SvgInfo, { className: "size-5 text-blue-600 dark:text-blue-400" }),
1330
- warning: jsx(SvgTriangleAlert, { className: "size-5 text-yellow-600 dark:text-yellow-400" }),
1328
+ success: jsx(SvgCircleCheck, { className: "size-5 text-[var(--ui-success)]" }),
1329
+ error: jsx(SvgCircleAlert, { className: "size-5 text-[var(--ui-danger)]" }),
1330
+ info: jsx(SvgInfo, { className: "size-5 text-[var(--ui-info)]" }),
1331
+ warning: jsx(SvgTriangleAlert, { className: "size-5 text-[var(--ui-warning)]" }),
1331
1332
  };
1332
- /**
1333
- * Subtle icon + text color adjustments
1334
- */
1335
1333
  const textColorMap = {
1336
- success: 'text-green-900 dark:text-green-200',
1337
- error: 'text-red-900 dark:text-red-200',
1338
- info: 'text-blue-900 dark:text-blue-200',
1339
- warning: 'text-yellow-900 dark:text-yellow-200',
1334
+ success: 'text-[var(--ui-success-text)]',
1335
+ error: 'text-[var(--ui-danger-text)]',
1336
+ info: 'text-[var(--ui-info-text)]',
1337
+ warning: 'text-[var(--ui-warning-text)]',
1340
1338
  };
1341
- /**
1342
- * Pleasant colored *top border only*
1343
- * No background color — soft neutral surface
1344
- */
1345
1339
  const borderStyle = {
1346
- success: 'border-t-4 border-green-600 dark:border-green-400',
1347
- error: 'border-t-4 border-red-600 dark:border-red-400',
1348
- info: 'border-t-4 border-blue-600 dark:border-blue-400',
1349
- warning: 'border-t-4 border-yellow-600 dark:border-yellow-400',
1340
+ success: 'border-t-4 border-[var(--ui-success)]',
1341
+ error: 'border-t-4 border-[var(--ui-danger)]',
1342
+ info: 'border-t-4 border-[var(--ui-info)]',
1343
+ warning: 'border-t-4 border-[var(--ui-warning)]',
1350
1344
  };
1351
1345
  const Toast = ({ message, type, onClose, className, id, isTop = true, }) => {
1352
1346
  const enterFrom = isTop ? 'opacity-0 -translate-y-3 scale-95' : 'opacity-0 translate-y-3 scale-95';
@@ -1421,604 +1415,8 @@ const ToastProvider = ({ children, placement = 'top-center' }) => {
1421
1415
  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))) })] }));
1422
1416
  };
1423
1417
 
1424
- const q = typeof window < "u" ? useLayoutEffect : useEffect;
1425
- function oe(e) {
1426
- if (e !== void 0)
1427
- switch (typeof e) {
1428
- case "number":
1429
- return e;
1430
- case "string": {
1431
- if (e.endsWith("px"))
1432
- return parseFloat(e);
1433
- break;
1434
- }
1435
- }
1436
- }
1437
- function Ie({
1438
- box: e,
1439
- defaultHeight: t,
1440
- defaultWidth: s,
1441
- disabled: r,
1442
- element: n,
1443
- mode: o,
1444
- style: i
1445
- }) {
1446
- const { styleHeight: f, styleWidth: l } = useMemo(
1447
- () => ({
1448
- styleHeight: oe(i?.height),
1449
- styleWidth: oe(i?.width)
1450
- }),
1451
- [i?.height, i?.width]
1452
- ), [c, d] = useState({
1453
- height: t,
1454
- width: s
1455
- }), a = r || f !== void 0 || o === "only-width" || f !== void 0 && l !== void 0;
1456
- return q(() => {
1457
- if (n === null || a)
1458
- return;
1459
- const u = new ResizeObserver((I) => {
1460
- for (const m of I) {
1461
- const { contentRect: b, target: g } = m;
1462
- n === g && d((w) => w.height === b.height && w.width === b.width ? w : {
1463
- height: b.height,
1464
- width: b.width
1465
- });
1466
- }
1467
- });
1468
- return u.observe(n, { box: e }), () => {
1469
- u?.unobserve(n);
1470
- };
1471
- }, [e, a, n, f, l]), useMemo(
1472
- () => ({
1473
- height: f ?? c.height,
1474
- width: l ?? c.width
1475
- }),
1476
- [c, f, l]
1477
- );
1478
- }
1479
- function ae(e) {
1480
- const t = useRef(() => {
1481
- throw new Error("Cannot call during render.");
1482
- });
1483
- return q(() => {
1484
- t.current = e;
1485
- }, [e]), useCallback((s) => t.current?.(s), [t]);
1486
- }
1487
- function Z({
1488
- containerElement: e,
1489
- direction: t,
1490
- isRtl: s,
1491
- scrollOffset: r
1492
- }) {
1493
- return r;
1494
- }
1495
- function $(e, t = "Assertion error") {
1496
- if (!e)
1497
- throw console.error(t), Error(t);
1498
- }
1499
- function Y(e, t) {
1500
- if (e === t)
1501
- return true;
1502
- if (!!e != !!t || ($(e !== void 0), $(t !== void 0), Object.keys(e).length !== Object.keys(t).length))
1503
- return false;
1504
- for (const s in e)
1505
- if (!Object.is(t[s], e[s]))
1506
- return false;
1507
- return true;
1508
- }
1509
- function fe({
1510
- cachedBounds: e,
1511
- itemCount: t,
1512
- itemSize: s
1513
- }) {
1514
- if (t === 0)
1515
- return 0;
1516
- if (typeof s == "number")
1517
- return t * s;
1518
- {
1519
- const r = e.get(
1520
- e.size === 0 ? 0 : e.size - 1
1521
- );
1522
- $(r !== void 0, "Unexpected bounds cache miss");
1523
- const n = (r.scrollOffset + r.size) / e.size;
1524
- return t * n;
1525
- }
1526
- }
1527
- function we({
1528
- align: e,
1529
- cachedBounds: t,
1530
- index: s,
1531
- itemCount: r,
1532
- itemSize: n,
1533
- containerScrollOffset: o,
1534
- containerSize: i
1535
- }) {
1536
- if (s < 0 || s >= r)
1537
- throw RangeError(`Invalid index specified: ${s}`, {
1538
- cause: `Index ${s} is not within the range of 0 - ${r - 1}`
1539
- });
1540
- const f = fe({
1541
- cachedBounds: t,
1542
- itemCount: r,
1543
- itemSize: n
1544
- }), l = t.get(s), c = Math.max(
1545
- 0,
1546
- Math.min(f - i, l.scrollOffset)
1547
- ), d = Math.max(
1548
- 0,
1549
- l.scrollOffset - i + l.size
1550
- );
1551
- switch (e === "smart" && (o >= d && o <= c ? e = "auto" : e = "center"), e) {
1552
- case "start":
1553
- return c;
1554
- case "end":
1555
- return d;
1556
- case "center":
1557
- return l.scrollOffset <= i / 2 ? 0 : l.scrollOffset + l.size / 2 >= f - i / 2 ? f - i : l.scrollOffset + l.size / 2 - i / 2;
1558
- case "auto":
1559
- default:
1560
- return o >= d && o <= c ? o : o < d ? d : c;
1561
- }
1562
- }
1563
- function ie({
1564
- cachedBounds: e,
1565
- containerScrollOffset: t,
1566
- containerSize: s,
1567
- itemCount: r,
1568
- overscanCount: n
1569
- }) {
1570
- const o = r - 1;
1571
- let i = 0, f = -1, l = 0, c = -1, d = 0;
1572
- for (; d < o; ) {
1573
- const a = e.get(d);
1574
- if (a.scrollOffset + a.size > t)
1575
- break;
1576
- d++;
1577
- }
1578
- for (i = d, l = Math.max(0, i - n); d < o; ) {
1579
- const a = e.get(d);
1580
- if (a.scrollOffset + a.size >= t + s)
1581
- break;
1582
- d++;
1583
- }
1584
- return f = Math.min(o, d), c = Math.min(r - 1, f + n), i < 0 && (i = 0, f = -1, l = 0, c = -1), {
1585
- startIndexVisible: i,
1586
- stopIndexVisible: f,
1587
- startIndexOverscan: l,
1588
- stopIndexOverscan: c
1589
- };
1590
- }
1591
- function me({
1592
- itemCount: e,
1593
- itemProps: t,
1594
- itemSize: s
1595
- }) {
1596
- const r = /* @__PURE__ */ new Map();
1597
- return {
1598
- get(n) {
1599
- for ($(n < e, `Invalid index ${n}`); r.size - 1 < n; ) {
1600
- const i = r.size;
1601
- let f;
1602
- switch (typeof s) {
1603
- case "function": {
1604
- f = s(i, t);
1605
- break;
1606
- }
1607
- case "number": {
1608
- f = s;
1609
- break;
1610
- }
1611
- }
1612
- if (i === 0)
1613
- r.set(i, {
1614
- size: f,
1615
- scrollOffset: 0
1616
- });
1617
- else {
1618
- const l = r.get(i - 1);
1619
- $(
1620
- l !== void 0,
1621
- `Unexpected bounds cache miss for index ${n}`
1622
- ), r.set(i, {
1623
- scrollOffset: l.scrollOffset + l.size,
1624
- size: f
1625
- });
1626
- }
1627
- }
1628
- const o = r.get(n);
1629
- return $(
1630
- o !== void 0,
1631
- `Unexpected bounds cache miss for index ${n}`
1632
- ), o;
1633
- },
1634
- set(n, o) {
1635
- r.set(n, o);
1636
- },
1637
- get size() {
1638
- return r.size;
1639
- }
1640
- };
1641
- }
1642
- function Oe({
1643
- itemCount: e,
1644
- itemProps: t,
1645
- itemSize: s
1646
- }) {
1647
- return useMemo(
1648
- () => me({
1649
- itemCount: e,
1650
- itemProps: t,
1651
- itemSize: s
1652
- }),
1653
- [e, t, s]
1654
- );
1655
- }
1656
- function ye({
1657
- containerSize: e,
1658
- itemSize: t
1659
- }) {
1660
- let s;
1661
- switch (typeof t) {
1662
- case "string": {
1663
- $(
1664
- t.endsWith("%"),
1665
- `Invalid item size: "${t}"; string values must be percentages (e.g. "100%")`
1666
- ), $(
1667
- e !== void 0,
1668
- "Container size must be defined if a percentage item size is specified"
1669
- ), s = e * parseInt(t) / 100;
1670
- break;
1671
- }
1672
- default: {
1673
- s = t;
1674
- break;
1675
- }
1676
- }
1677
- return s;
1678
- }
1679
- function ee({
1680
- containerElement: e,
1681
- containerStyle: t,
1682
- defaultContainerSize: s = 0,
1683
- direction: r,
1684
- isRtl: n = false,
1685
- itemCount: o,
1686
- itemProps: i,
1687
- itemSize: f,
1688
- onResize: l,
1689
- overscanCount: c
1690
- }) {
1691
- const [d, a] = useState({
1692
- startIndexVisible: 0,
1693
- startIndexOverscan: 0,
1694
- stopIndexVisible: -1,
1695
- stopIndexOverscan: -1
1696
- }), {
1697
- startIndexVisible: u,
1698
- startIndexOverscan: I,
1699
- stopIndexVisible: m,
1700
- stopIndexOverscan: b
1701
- } = {
1702
- startIndexVisible: Math.min(o - 1, d.startIndexVisible),
1703
- startIndexOverscan: Math.min(o - 1, d.startIndexOverscan),
1704
- stopIndexVisible: Math.min(o - 1, d.stopIndexVisible),
1705
- stopIndexOverscan: Math.min(o - 1, d.stopIndexOverscan)
1706
- }, { height: g = s, width: w = s } = Ie({
1707
- defaultHeight: s ,
1708
- defaultWidth: void 0,
1709
- element: e,
1710
- mode: "only-height" ,
1711
- style: t
1712
- }), y = useRef({
1713
- height: 0,
1714
- width: 0
1715
- }), V = g , h = ye({ containerSize: V, itemSize: f });
1716
- useLayoutEffect(() => {
1717
- if (typeof l == "function") {
1718
- const p = y.current;
1719
- (p.height !== g || p.width !== w) && (l({ height: g, width: w }, { ...p }), p.height = g, p.width = w);
1720
- }
1721
- }, [g, l, w]);
1722
- const z = Oe({
1723
- itemCount: o,
1724
- itemProps: i,
1725
- itemSize: h
1726
- }), k = useCallback(
1727
- (p) => z.get(p),
1728
- [z]
1729
- ), S = useCallback(
1730
- () => fe({
1731
- cachedBounds: z,
1732
- itemCount: o,
1733
- itemSize: h
1734
- }),
1735
- [z, o, h]
1736
- ), W = useCallback(
1737
- (p) => {
1738
- const T = Z({
1739
- containerElement: e,
1740
- direction: r,
1741
- isRtl: n,
1742
- scrollOffset: p
1743
- });
1744
- return ie({
1745
- cachedBounds: z,
1746
- containerScrollOffset: T,
1747
- containerSize: V,
1748
- itemCount: o,
1749
- overscanCount: c
1750
- });
1751
- },
1752
- [
1753
- z,
1754
- e,
1755
- V,
1756
- r,
1757
- n,
1758
- o,
1759
- c
1760
- ]
1761
- );
1762
- q(() => {
1763
- const p = (e?.scrollTop ) ?? 0;
1764
- a(W(p));
1765
- }, [e, r, W]), q(() => {
1766
- if (!e)
1767
- return;
1768
- const p = () => {
1769
- a((T) => {
1770
- const { scrollLeft: R, scrollTop: v } = e, x = Z({
1771
- containerElement: e,
1772
- direction: r,
1773
- isRtl: n,
1774
- scrollOffset: v
1775
- }), A = ie({
1776
- cachedBounds: z,
1777
- containerScrollOffset: x,
1778
- containerSize: V,
1779
- itemCount: o,
1780
- overscanCount: c
1781
- });
1782
- return Y(A, T) ? T : A;
1783
- });
1784
- };
1785
- return e.addEventListener("scroll", p), () => {
1786
- e.removeEventListener("scroll", p);
1787
- };
1788
- }, [
1789
- z,
1790
- e,
1791
- V,
1792
- r,
1793
- o,
1794
- c
1795
- ]);
1796
- const O = ae(
1797
- ({
1798
- align: p = "auto",
1799
- containerScrollOffset: T,
1800
- index: R
1801
- }) => {
1802
- let v = we({
1803
- align: p,
1804
- cachedBounds: z,
1805
- containerScrollOffset: T,
1806
- containerSize: V,
1807
- index: R,
1808
- itemCount: o,
1809
- itemSize: h
1810
- });
1811
- if (e) {
1812
- if (v = Z({
1813
- containerElement: e,
1814
- direction: r,
1815
- isRtl: n,
1816
- scrollOffset: v
1817
- }), typeof e.scrollTo != "function") {
1818
- const x = W(v);
1819
- Y(d, x) || a(x);
1820
- }
1821
- return v;
1822
- }
1823
- }
1824
- );
1825
- return {
1826
- getCellBounds: k,
1827
- getEstimatedSize: S,
1828
- scrollToIndex: O,
1829
- startIndexOverscan: I,
1830
- startIndexVisible: u,
1831
- stopIndexOverscan: b,
1832
- stopIndexVisible: m
1833
- };
1834
- }
1835
- function de(e) {
1836
- return useMemo(() => e, Object.values(e));
1837
- }
1838
- function ue(e, t) {
1839
- const {
1840
- ariaAttributes: s,
1841
- style: r,
1842
- ...n
1843
- } = e, {
1844
- ariaAttributes: o,
1845
- style: i,
1846
- ...f
1847
- } = t;
1848
- return Y(s, o) && Y(r, i) && Y(n, f);
1849
- }
1850
- function ze(e) {
1851
- return e != null && typeof e == "object" && "getAverageRowHeight" in e && typeof e.getAverageRowHeight == "function";
1852
- }
1853
- const te = "data-react-window-index";
1854
- function Ae({
1855
- children: e,
1856
- className: t,
1857
- defaultHeight: s = 0,
1858
- listRef: r,
1859
- onResize: n,
1860
- onRowsRendered: o,
1861
- overscanCount: i = 3,
1862
- rowComponent: f,
1863
- rowCount: l,
1864
- rowHeight: c,
1865
- rowProps: d,
1866
- tagName: a = "div",
1867
- style: u,
1868
- ...I
1869
- }) {
1870
- const m = de(d), b = useMemo(
1871
- () => memo(f, ue),
1872
- [f]
1873
- ), [g, w] = useState(null), y = ze(c), V = useMemo(() => y ? (v) => c.getRowHeight(v) ?? c.getAverageRowHeight() : c, [y, c]), {
1874
- getCellBounds: h,
1875
- getEstimatedSize: z,
1876
- scrollToIndex: k,
1877
- startIndexOverscan: S,
1878
- startIndexVisible: W,
1879
- stopIndexOverscan: O,
1880
- stopIndexVisible: p
1881
- } = ee({
1882
- containerElement: g,
1883
- containerStyle: u,
1884
- defaultContainerSize: s,
1885
- direction: "vertical",
1886
- itemCount: l,
1887
- itemProps: m,
1888
- itemSize: V,
1889
- onResize: n,
1890
- overscanCount: i
1891
- });
1892
- useImperativeHandle(
1893
- r,
1894
- () => ({
1895
- get element() {
1896
- return g;
1897
- },
1898
- scrollToRow({
1899
- align: v = "auto",
1900
- behavior: x = "auto",
1901
- index: A
1902
- }) {
1903
- const M = k({
1904
- align: v,
1905
- containerScrollOffset: g?.scrollTop ?? 0,
1906
- index: A
1907
- });
1908
- typeof g?.scrollTo == "function" && g.scrollTo({
1909
- behavior: x,
1910
- top: M
1911
- });
1912
- }
1913
- }),
1914
- [g, k]
1915
- ), q(() => {
1916
- if (!g)
1917
- return;
1918
- const v = Array.from(g.children).filter((x, A) => {
1919
- if (x.hasAttribute("aria-hidden"))
1920
- return false;
1921
- const M = `${S + A}`;
1922
- return x.setAttribute(te, M), true;
1923
- });
1924
- if (y)
1925
- return c.observeRowElements(v);
1926
- }, [
1927
- g,
1928
- y,
1929
- c,
1930
- S,
1931
- O
1932
- ]), useEffect(() => {
1933
- S >= 0 && O >= 0 && o && o(
1934
- {
1935
- startIndex: W,
1936
- stopIndex: p
1937
- },
1938
- {
1939
- startIndex: S,
1940
- stopIndex: O
1941
- }
1942
- );
1943
- }, [
1944
- o,
1945
- S,
1946
- W,
1947
- O,
1948
- p
1949
- ]);
1950
- const T = useMemo(() => {
1951
- const v = [];
1952
- if (l > 0)
1953
- for (let x = S; x <= O; x++) {
1954
- const A = h(x);
1955
- v.push(
1956
- /* @__PURE__ */ createElement(
1957
- b,
1958
- {
1959
- ...m,
1960
- ariaAttributes: {
1961
- "aria-posinset": x + 1,
1962
- "aria-setsize": l,
1963
- role: "listitem"
1964
- },
1965
- key: x,
1966
- index: x,
1967
- style: {
1968
- position: "absolute",
1969
- left: 0,
1970
- transform: `translateY(${A.scrollOffset}px)`,
1971
- // In case of dynamic row heights, don't specify a height style
1972
- // otherwise a default/estimated height would mask the actual height
1973
- height: y ? void 0 : A.size,
1974
- width: "100%"
1975
- }
1976
- }
1977
- )
1978
- );
1979
- }
1980
- return v;
1981
- }, [
1982
- b,
1983
- h,
1984
- y,
1985
- l,
1986
- m,
1987
- S,
1988
- O
1989
- ]), R = /* @__PURE__ */ jsx(
1990
- "div",
1991
- {
1992
- "aria-hidden": true,
1993
- style: {
1994
- height: z(),
1995
- width: "100%",
1996
- zIndex: -1
1997
- }
1998
- }
1999
- );
2000
- return createElement(
2001
- a,
2002
- {
2003
- role: "list",
2004
- ...I,
2005
- className: t,
2006
- ref: w,
2007
- style: {
2008
- position: "relative",
2009
- maxHeight: "100%",
2010
- flexGrow: 1,
2011
- overflowY: "auto",
2012
- ...u
2013
- }
2014
- },
2015
- T,
2016
- e,
2017
- R
2018
- );
2019
- }
2020
-
2021
- const VirtualizedRow = ({ index, style, items, columns, gridTemplate, }) => {
1418
+ const VirtualizedRow = ({ index, style, data }) => {
1419
+ const { items, columns, gridTemplate } = data;
2022
1420
  const item = items[index];
2023
1421
  return (jsx("div", { role: "row", className: "grid border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 group", style: {
2024
1422
  ...style,
@@ -2040,14 +1438,21 @@ const VirtualizedRow = ({ index, style, items, columns, gridTemplate, }) => {
2040
1438
  const useGridTemplate = (columns) => useMemo(() => columns.map((col) => (col.width ? `${col.width}px` : '1fr')).join(' '), [columns]);
2041
1439
  const VirtualizedDataTable = ({ items, columns, sorting = {}, onSort, loading = false, emptyMessage = 'No data available', containerClass = '', wrapperClass = '', rowHeight = 48, maxHeight = 400, }) => {
2042
1440
  const scrollRef = useRef(null);
1441
+ const outerRef = useRef(null);
2043
1442
  const headerRef = useRef(null);
2044
1443
  const gridTemplate = useGridTemplate(columns);
2045
- /** Sync body → header scroll */
2046
- const handleScrollSync = (scrollOffset) => {
2047
- if (headerRef.current) {
2048
- headerRef.current.scrollLeft = scrollOffset;
2049
- }
2050
- };
1444
+ /** Sync horizontal scroll of the virtualized body → header */
1445
+ useEffect(() => {
1446
+ const el = outerRef.current;
1447
+ if (!el)
1448
+ return;
1449
+ const handler = () => {
1450
+ if (headerRef.current)
1451
+ headerRef.current.scrollLeft = el.scrollLeft;
1452
+ };
1453
+ el.addEventListener('scroll', handler);
1454
+ return () => el.removeEventListener('scroll', handler);
1455
+ }, []);
2051
1456
  const handleSort = useCallback((column) => {
2052
1457
  if (column.sortable)
2053
1458
  onSort === null || onSort === void 0 ? void 0 : onSort(column);
@@ -2079,11 +1484,7 @@ const VirtualizedDataTable = ({ items, columns, sorting = {}, onSort, loading =
2079
1484
  /* -------------------------------------------------------
2080
1485
  * MAIN (virtualized body)
2081
1486
  * ------------------------------------------------------- */
2082
- 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("div", { style: {
2083
- height: maxHeight,
2084
- overflowY: 'auto',
2085
- overflowX: 'auto',
2086
- }, children: jsx(Ae, { listRef: scrollRef, rowComponent: VirtualizedRow, rowCount: items.length, rowHeight: rowHeight, rowProps: { items, columns, gridTemplate }, onScroll: (e) => handleScrollSync(e.currentTarget.scrollLeft) }) })] }) }));
1487
+ 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 })] }) }));
2087
1488
  };
2088
1489
 
2089
1490
  const useIsMobile = () => {