@dreamtree-org/twreact-ui 1.3.2 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/DESIGN.md +2 -2
  2. package/README.md +14 -6
  3. package/ai-skills/dreamtree-ui.md +3 -1
  4. package/bin/cli.mjs +72 -4
  5. package/dist/ai-schema.json +3 -2
  6. package/dist/charts/index.js +75 -47
  7. package/dist/components/charts/CartesianChart.d.ts.map +1 -1
  8. package/dist/components/charts/DonutChart.d.ts.map +1 -1
  9. package/dist/components/charts/Sparkline.d.ts.map +1 -1
  10. package/dist/components/charts/chartTheme.d.ts +13 -3
  11. package/dist/components/charts/chartTheme.d.ts.map +1 -1
  12. package/dist/components/core/Table/MobileCard.d.ts.map +1 -1
  13. package/dist/components/core/Table/MobileFilters.d.ts.map +1 -1
  14. package/dist/components/core/Table/Table.d.ts.map +1 -1
  15. package/dist/components/core/Table/TableRow.d.ts.map +1 -1
  16. package/dist/components/core/Table/helpers.d.ts +12 -0
  17. package/dist/components/core/Table/helpers.d.ts.map +1 -1
  18. package/dist/components/utility/Stepper.d.ts.map +1 -1
  19. package/dist/esm/components/blocks/StatCard.js +1 -1
  20. package/dist/esm/components/charts/CartesianChart.js +7 -2
  21. package/dist/esm/components/charts/DonutChart.js +4 -1
  22. package/dist/esm/components/charts/Sparkline.js +4 -1
  23. package/dist/esm/components/charts/chartTheme.js +65 -48
  24. package/dist/esm/components/core/Select.js +2 -2
  25. package/dist/esm/components/core/Table/ActionMenu.js +5 -5
  26. package/dist/esm/components/core/Table/ColumnMenu.js +1 -1
  27. package/dist/esm/components/core/Table/FieldInput.js +5 -5
  28. package/dist/esm/components/core/Table/MobileCard.js +14 -12
  29. package/dist/esm/components/core/Table/MobileFilters.js +11 -4
  30. package/dist/esm/components/core/Table/Pagination.js +1 -1
  31. package/dist/esm/components/core/Table/Table.js +22 -19
  32. package/dist/esm/components/core/Table/TableRow.js +10 -11
  33. package/dist/esm/components/core/Table/helpers.js +16 -1
  34. package/dist/esm/components/navigation/Dropdown.js +1 -1
  35. package/dist/esm/components/navigation/Navbar.js +21 -21
  36. package/dist/esm/components/navigation/Sidebar.js +12 -12
  37. package/dist/esm/components/utility/Card.js +5 -5
  38. package/dist/esm/components/utility/Stepper.js +6 -4
  39. package/dist/index.css +1 -1
  40. package/dist/index.esm.css +1 -1
  41. package/dist/index.esm.js +129 -101
  42. package/dist/index.js +129 -101
  43. package/dist/tokens/brands/practicepro.json +1 -0
  44. package/dist/tokens/brands/studio.json +1 -0
  45. package/dist/types/index.d.ts +1 -0
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/mcp/catalog.snapshot.json +21 -21
  48. package/package.json +2 -1
  49. package/tokens/brand.schema.json +612 -0
  50. package/tokens/brands/practicepro.json +1 -0
  51. package/tokens/brands/studio.json +1 -0
  52. package/tokens/lib.cjs +131 -7
@@ -4,7 +4,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
4
4
  import React from 'react';
5
5
  import { ResponsiveContainer, PieChart, Tooltip, Pie } from 'recharts';
6
6
  import { ChartFrame, ChartTooltipContent } from './ChartFrame.js';
7
- import { useChartTheme, useReducedMotion, defaultValueFormatter } from './chartTheme.js';
7
+ import { useChartTheme, useReducedMotion, useChartId, defaultValueFormatter } from './chartTheme.js';
8
8
 
9
9
  var _excluded = ["data", "index", "category", "colors", "valueFormatter", "variant", "innerRadius", "outerRadius", "centerLabel", "height", "showLegend", "showTooltip", "animate", "title", "description", "emptyState", "accessibleTable", "className"];
10
10
  var DonutChart = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
@@ -46,6 +46,7 @@ var DonutChart = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
46
46
  chrome = _useChartTheme.chrome,
47
47
  series = _useChartTheme.series;
48
48
  var reducedMotion = useReducedMotion();
49
+ var chartId = useChartId();
49
50
  var slices = rows.map(function (row, i) {
50
51
  return _objectSpread2(_objectSpread2({}, row), {}, {
51
52
  fill: series[i]
@@ -87,6 +88,7 @@ var DonutChart = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
87
88
  height: "100%",
88
89
  minWidth: 0,
89
90
  children: jsxs(PieChart, {
91
+ id: chartId,
90
92
  accessibilityLayer: false,
91
93
  children: [showTooltip && jsx(Tooltip, {
92
94
  isAnimationActive: false,
@@ -95,6 +97,7 @@ var DonutChart = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
95
97
  hideLabel: true
96
98
  })
97
99
  }), jsx(Pie, {
100
+ id: "".concat(chartId, "-0"),
98
101
  data: slices,
99
102
  dataKey: category,
100
103
  nameKey: index,
@@ -4,7 +4,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
4
4
  import React from 'react';
5
5
  import { ResponsiveContainer, AreaChart, LineChart, YAxis, Tooltip, Area, Line } from 'recharts';
6
6
  import { ChartFrame, ChartTooltipContent } from './ChartFrame.js';
7
- import { useChartTheme, useReducedMotion, defaultValueFormatter } from './chartTheme.js';
7
+ import { useChartTheme, useReducedMotion, useChartId, defaultValueFormatter } from './chartTheme.js';
8
8
 
9
9
  var _excluded = ["data", "category", "index", "color", "type", "valueFormatter", "height", "showTooltip", "animate", "title", "description", "emptyState", "accessibleTable", "className"];
10
10
  /** A word-sized trend line: no axes, grid or legend — just the shape of the data. */
@@ -36,9 +36,11 @@ var Sparkline = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
36
36
  var _useChartTheme = useChartTheme([category], [color]),
37
37
  series = _useChartTheme.series;
38
38
  var reducedMotion = useReducedMotion();
39
+ var chartId = useChartId();
39
40
  var stroke = series[0];
40
41
  var Root = type === "area" ? AreaChart : LineChart;
41
42
  var common = {
43
+ id: "".concat(chartId, "-0"),
42
44
  dataKey: category,
43
45
  name: category,
44
46
  type: "monotone",
@@ -79,6 +81,7 @@ var Sparkline = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
79
81
  height: "100%",
80
82
  minWidth: 0,
81
83
  children: jsxs(Root, {
84
+ id: chartId,
82
85
  data: data,
83
86
  margin: {
84
87
  top: 2,
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { slicedToArray as _slicedToArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
- import { useState, useEffect } from 'react';
3
+ import { useSyncExternalStore, useId } from 'react';
4
4
  import { prefersReducedMotion } from '../../utils/position.js';
5
5
 
6
6
  var CHART_PALETTES = ["primary", "secondary", "success", "warning", "error", "info", "gray"];
@@ -23,9 +23,11 @@ function readVar(name) {
23
23
  }
24
24
  // SVG presentation attributes do not resolve var() in every engine, so a token is
25
25
  // turned into a concrete rgb() string when the browser can tell us its value. The
26
- // var() form is the SSR / jsdom fallback.
26
+ // var() form is the SSR / jsdom fallback, and what the first (hydrating) client
27
+ // render uses so it matches the server's HTML (`live` = false).
27
28
  function resolveVar(name) {
28
- var value = readVar(name);
29
+ var live = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
30
+ var value = live ? readVar(name) : "";
29
31
  return value ? "rgb(".concat(value.split(/[\s,]+/).join(" "), ")") : "rgb(var(".concat(name, "))");
30
32
  }
31
33
  /**
@@ -34,76 +36,91 @@ function resolveVar(name) {
34
36
  * by the consumer (e.g. a colour stored with the data).
35
37
  */
36
38
  function resolveColor(color) {
39
+ var live = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
37
40
  var name = tokenVar(color);
38
- return name ? resolveVar(name) : color;
41
+ return name ? resolveVar(name, live) : color;
39
42
  }
40
43
  function seriesColors(categories, colors) {
44
+ var live = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
41
45
  var palette = colors && colors.length ? colors : DEFAULT_CHART_COLORS;
42
46
  return categories.map(function (_, i) {
43
- return resolveColor(palette[i % palette.length]);
47
+ return resolveColor(palette[i % palette.length], live);
44
48
  });
45
49
  }
46
- function readChrome() {
50
+ function readChrome(live) {
47
51
  return Object.fromEntries(Object.entries(CHROME_VARS).map(function (_ref) {
48
52
  var _ref2 = _slicedToArray(_ref, 2),
49
53
  k = _ref2[0],
50
54
  v = _ref2[1];
51
- return [k, resolveVar(v)];
55
+ return [k, resolveVar(v, live)];
52
56
  }));
53
57
  }
58
+ // The theme is an external store: the attributes on <html> that flip it. The
59
+ // server snapshot is null, so a hydrating render keeps the var() fallback the
60
+ // server rendered and React re-renders with live colours right after (#130).
61
+ function subscribeTheme(onChange) {
62
+ if (typeof document === "undefined" || typeof MutationObserver !== "function") return function () {};
63
+ var observer = new MutationObserver(onChange);
64
+ observer.observe(document.documentElement, {
65
+ attributes: true,
66
+ attributeFilter: ["class", "data-theme", "style"]
67
+ });
68
+ return function () {
69
+ return observer.disconnect();
70
+ };
71
+ }
72
+ function themeSnapshot() {
73
+ if (typeof document === "undefined") return null;
74
+ var el = document.documentElement;
75
+ return "".concat(el.className, "|").concat(el.getAttribute("data-theme") || "", "|").concat(el.getAttribute("style") || "");
76
+ }
77
+ var serverThemeSnapshot = function serverThemeSnapshot() {
78
+ return null;
79
+ };
54
80
  /**
55
81
  * Chart chrome + series colours, re-read whenever the theme flips (the `dark`
56
82
  * class or `data-theme` on <html>) so axes and series follow dark mode without
57
83
  * a remount.
58
84
  */
59
85
  function useChartTheme(categories, colors) {
60
- var _useState = useState(0),
61
- _useState2 = _slicedToArray(_useState, 2);
62
- _useState2[0];
63
- var setVersion = _useState2[1];
64
- useEffect(function () {
65
- if (typeof MutationObserver !== "function") return undefined;
66
- var observer = new MutationObserver(function () {
67
- return setVersion(function (v) {
68
- return v + 1;
69
- });
70
- });
71
- observer.observe(document.documentElement, {
72
- attributes: true,
73
- attributeFilter: ["class", "data-theme", "style"]
74
- });
75
- return function () {
76
- return observer.disconnect();
77
- };
78
- }, []);
86
+ // The snapshot only signals a change; the values come from the live document.
87
+ var live = useSyncExternalStore(subscribeTheme, themeSnapshot, serverThemeSnapshot) !== null;
79
88
  return {
80
- chrome: readChrome(),
81
- series: seriesColors(categories, colors)
89
+ chrome: readChrome(live),
90
+ series: seriesColors(categories, colors, live)
91
+ };
92
+ }
93
+ function subscribeReducedMotion(onChange) {
94
+ var _query$addEventListen;
95
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return function () {};
96
+ var query = window.matchMedia("(prefers-reduced-motion: reduce)");
97
+ (_query$addEventListen = query.addEventListener) === null || _query$addEventListen === void 0 || _query$addEventListen.call(query, "change", onChange);
98
+ return function () {
99
+ var _query$removeEventLis;
100
+ return (_query$removeEventLis = query.removeEventListener) === null || _query$removeEventLis === void 0 ? void 0 : _query$removeEventLis.call(query, "change", onChange);
82
101
  };
83
102
  }
84
- /** `true` while the user asks the OS for reduced motion; follows changes live. */
103
+ var serverReducedMotion = function serverReducedMotion() {
104
+ return false;
105
+ };
106
+ /**
107
+ * `true` while the user asks the OS for reduced motion; follows changes live.
108
+ * `false` on the server and while hydrating, so the first render matches.
109
+ */
85
110
  function useReducedMotion() {
86
- var _useState3 = useState(prefersReducedMotion),
87
- _useState4 = _slicedToArray(_useState3, 2),
88
- reduced = _useState4[0],
89
- setReduced = _useState4[1];
90
- useEffect(function () {
91
- var _query$addEventListen;
92
- if (typeof window === "undefined" || typeof window.matchMedia !== "function") return undefined;
93
- var query = window.matchMedia("(prefers-reduced-motion: reduce)");
94
- var update = function update() {
95
- return setReduced(query.matches);
96
- };
97
- (_query$addEventListen = query.addEventListener) === null || _query$addEventListen === void 0 || _query$addEventListen.call(query, "change", update);
98
- return function () {
99
- var _query$removeEventLis;
100
- return (_query$removeEventLis = query.removeEventListener) === null || _query$removeEventLis === void 0 ? void 0 : _query$removeEventLis.call(query, "change", update);
101
- };
102
- }, []);
103
- return reduced;
111
+ return useSyncExternalStore(subscribeReducedMotion, prefersReducedMotion, serverReducedMotion);
104
112
  }
105
113
  var defaultValueFormatter = function defaultValueFormatter(value) {
106
114
  return typeof value === "number" ? value.toLocaleString() : value == null ? "" : String(value);
107
115
  };
116
+ /**
117
+ * A per-instance id for the SVG defs recharts draws (clip paths). recharts 2
118
+ * falls back to a module-level counter, which differs between the server and the
119
+ * client; an id from React.useId() is the same on both. Only [A-Za-z0-9_-] so it
120
+ * is safe inside `url(#…)`.
121
+ */
122
+ function useChartId() {
123
+ return "dt-chart-".concat(useId().replace(/[^A-Za-z0-9_-]/g, ""));
124
+ }
108
125
 
109
- export { CHART_PALETTES, DEFAULT_CHART_COLORS, defaultValueFormatter, resolveColor, seriesColors, tokenVar, useChartTheme, useReducedMotion };
126
+ export { CHART_PALETTES, DEFAULT_CHART_COLORS, defaultValueFormatter, resolveColor, seriesColors, tokenVar, useChartId, useChartTheme, useReducedMotion };
@@ -127,7 +127,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
127
127
  onMenuItemRender = _ref.onMenuItemRender,
128
128
  className = _ref.className,
129
129
  _ref$allowClear = _ref.allowClear,
130
- allowClear = _ref$allowClear === void 0 ? true : _ref$allowClear,
130
+ allowClear = _ref$allowClear === void 0 ? false : _ref$allowClear,
131
131
  _ref$creatable = _ref.creatable,
132
132
  creatable = _ref$creatable === void 0 ? false : _ref$creatable,
133
133
  onCreateOption = _ref.onCreateOption,
@@ -564,7 +564,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
564
564
  }, opt.value);
565
565
  })
566
566
  }), jsxs("div", {
567
- className: "text-xs text-primary-500",
567
+ className: "text-xs text-primary-700",
568
568
  children: ["+", rest]
569
569
  })]
570
570
  });
@@ -6,8 +6,8 @@ import { createPortal } from 'react-dom';
6
6
  import { cn } from '../../../utils/cn.js';
7
7
  import { useLatestRef } from '../../../hooks/useLatestRef.js';
8
8
 
9
- var DEFAULT_MENU_BG = "bg-white border border-gray-100 shadow-xl";
10
- var DEFAULT_MENU_ITEM_HOVER = "opacity-75 hover:opacity-100 hover:bg-gray-100/80 active:bg-gray-200/80";
9
+ var DEFAULT_MENU_BG = "bg-surface border border-line shadow-xl";
10
+ var DEFAULT_MENU_ITEM_HOVER = "opacity-75 hover:opacity-100 hover:bg-gray-100/80 active:bg-gray-200/80 dark:hover:bg-gray-800 dark:active:bg-gray-700";
11
11
  function ActionMenu(_ref) {
12
12
  var _theme$menuBg, _theme$menuItemHover;
13
13
  var _ref$actions = _ref.actions,
@@ -211,7 +211,7 @@ function ActionMenu(_ref) {
211
211
  children: jsx("div", {
212
212
  className: "p-1.5 space-y-0.5",
213
213
  children: !Array.isArray(actions) || actions.length === 0 ? jsx("div", {
214
- className: "px-3 py-2 text-sm text-gray-400 italic",
214
+ className: "px-3 py-2 text-sm text-muted italic",
215
215
  children: "No actions"
216
216
  }) : actions.map(function (action, idx) {
217
217
  var _action$name;
@@ -222,7 +222,7 @@ function ActionMenu(_ref) {
222
222
  type: "button",
223
223
  disabled: isDisabled,
224
224
  "aria-disabled": isDisabled || undefined,
225
- className: cn("w-full text-left px-3 py-2 text-sm flex items-center gap-2.5 rounded-lg transition-colors font-medium", isDisabled ? "opacity-50 cursor-not-allowed text-gray-400" : ["text-gray-700 hover:text-gray-900", menuItemHover, isFocused ? "bg-gray-100 text-gray-900 ring-1 ring-gray-300" : ""]),
225
+ className: cn("w-full text-left px-3 py-2 text-sm flex items-center gap-2.5 rounded-lg transition-colors font-medium", isDisabled ? "opacity-50 cursor-not-allowed text-muted" : ["text-foreground", menuItemHover, isFocused ? "bg-gray-100 text-gray-900 ring-1 ring-gray-300 dark:bg-gray-800 dark:text-foreground dark:ring-gray-600" : ""]),
226
226
  onMouseEnter: function onMouseEnter() {
227
227
  return !isDisabled && setFocusedIndex(idx);
228
228
  },
@@ -234,7 +234,7 @@ function ActionMenu(_ref) {
234
234
  },
235
235
  children: action.render ? action.render(row) : jsxs(Fragment, {
236
236
  children: [action.icon && jsx("span", {
237
- className: "inline-flex text-gray-500 flex-shrink-0",
237
+ className: "inline-flex text-muted flex-shrink-0",
238
238
  children: action.icon
239
239
  }), jsx("span", {
240
240
  className: "truncate",
@@ -4,7 +4,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import 'react';
5
5
  import { cn } from '../../../utils/cn.js';
6
6
 
7
- var DEFAULT_ROW_HOVER = "bg-gray-50";
7
+ var DEFAULT_ROW_HOVER = "bg-background";
8
8
  /**
9
9
  * Column visibility toggle menu
10
10
  */
@@ -56,7 +56,7 @@ function FieldInput(_ref) {
56
56
  onClick: stopProp,
57
57
  onMouseDown: stopProp,
58
58
  placeholder: "Enter ".concat(column.label || column.key, "..."),
59
- className: cn("w-full px-2 py-1 text-sm border rounded outline-none transition-all focus:ring-2 focus:ring-primary-500 bg-white resize-y min-h-[2.5rem]", className)
59
+ className: cn("w-full px-2 py-1 text-sm border rounded outline-none transition-all focus:ring-2 focus:ring-primary-500 bg-surface text-foreground resize-y min-h-[2.5rem]", className)
60
60
  });
61
61
  }
62
62
  // Select / Dropdown
@@ -76,7 +76,7 @@ function FieldInput(_ref) {
76
76
  onKeyDown: onKeyDown,
77
77
  onClick: stopProp,
78
78
  onMouseDown: stopProp,
79
- className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-white", className),
79
+ className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-surface text-foreground", className),
80
80
  children: [jsxs("option", {
81
81
  value: "",
82
82
  children: ["Select ", column.label || column.key]
@@ -119,7 +119,7 @@ function FieldInput(_ref) {
119
119
  onKeyDown: onKeyDown,
120
120
  onClick: stopProp,
121
121
  onMouseDown: stopProp,
122
- className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-white", className)
122
+ className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-surface text-foreground", className)
123
123
  });
124
124
  }
125
125
  // Number
@@ -135,7 +135,7 @@ function FieldInput(_ref) {
135
135
  onClick: stopProp,
136
136
  onMouseDown: stopProp,
137
137
  placeholder: "Enter ".concat(column.label || column.key, "..."),
138
- className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-white", className)
138
+ className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-surface text-foreground", className)
139
139
  });
140
140
  }
141
141
  // Default: Text
@@ -150,7 +150,7 @@ function FieldInput(_ref) {
150
150
  onClick: stopProp,
151
151
  onMouseDown: stopProp,
152
152
  placeholder: "Enter ".concat(column.label || column.key, "..."),
153
- className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-white", className)
153
+ className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-surface text-foreground", className)
154
154
  });
155
155
  }
156
156
 
@@ -4,7 +4,7 @@ import React from 'react';
4
4
  import { cn } from '../../../utils/cn.js';
5
5
  import { MoreVertical } from 'lucide-react';
6
6
  import ActionMenu from './ActionMenu.js';
7
- import { getRowKey, resolveActions, rowHasDetails, getActionLabelText } from './helpers.js';
7
+ import { getRowKey, resolveActions, rowHasDetails, getActionLabelText, getStripeProps } from './helpers.js';
8
8
 
9
9
  /**
10
10
  * Mobile card view for a single table row
@@ -61,11 +61,10 @@ function MobileCard(_ref) {
61
61
  var hasActions = withAction && (inlineActions.length > 0 || menuActions.length > 0);
62
62
  var showHeader = showDetailsToggle || selectable || showSerial || hasActions;
63
63
  var stripeBg = stripedRows && !isSelected && Array.isArray(stripedColors) && stripedColors.length > 0 ? stripedColors[globalIndex % stripedColors.length] : undefined;
64
+ var stripeProps = getStripeProps(stripeBg);
64
65
  return jsxs("div", {
65
- style: stripeBg ? {
66
- backgroundColor: stripeBg
67
- } : undefined,
68
- className: cn("border rounded-lg mb-3 shadow-sm overflow-hidden transition-all duration-200", {
66
+ style: stripeProps.style,
67
+ className: cn(stripeProps.className, "border border-line rounded-lg mb-3 shadow-sm overflow-hidden transition-all duration-200", {
69
68
  "cursor-pointer": !!onRowClick,
70
69
  "bg-primary-50 border-primary-200": isSelected,
71
70
  "hover:shadow-md": !isSelected
@@ -74,7 +73,7 @@ function MobileCard(_ref) {
74
73
  return onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(row, globalIndex);
75
74
  },
76
75
  children: [showHeader && jsxs("div", {
77
- className: "flex items-center justify-between p-4 border-b bg-gray-50",
76
+ className: "flex items-center justify-between p-4 border-b border-line bg-background",
78
77
  children: [jsxs("div", {
79
78
  className: "flex items-center gap-3",
80
79
  children: [showDetailsToggle && jsx("button", {
@@ -85,7 +84,7 @@ function MobileCard(_ref) {
85
84
  },
86
85
  "aria-expanded": isExpanded,
87
86
  "aria-label": isExpanded ? "Collapse row details" : "Expand row details",
88
- className: "p-1 rounded hover:bg-gray-200",
87
+ className: "p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700",
89
88
  children: isExpanded ? "▾" : "▸"
90
89
  }), selectable && jsx("input", {
91
90
  type: "checkbox",
@@ -119,7 +118,7 @@ function MobileCard(_ref) {
119
118
  if (action.disabled) return;
120
119
  handleOnAction(action, row);
121
120
  },
122
- className: cn("p-1.5 rounded", action.disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-gray-200"),
121
+ className: cn("p-1.5 rounded", action.disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-gray-200 dark:hover:bg-gray-700"),
123
122
  children: action.render ? action.render(row) : (_action$icon = action.icon) !== null && _action$icon !== void 0 ? _action$icon : jsx("span", {
124
123
  className: "text-xs",
125
124
  children: actionLabel
@@ -128,6 +127,7 @@ function MobileCard(_ref) {
128
127
  }), menuActions.length > 0 && jsxs("div", {
129
128
  className: "relative",
130
129
  children: [jsx("button", {
130
+ type: "button",
131
131
  ref: function ref(el) {
132
132
  return registerActionButton === null || registerActionButton === void 0 ? void 0 : registerActionButton(actionCellKey, el);
133
133
  },
@@ -135,10 +135,12 @@ function MobileCard(_ref) {
135
135
  return toggleActions(e, actionCellKey, row);
136
136
  },
137
137
  "aria-expanded": activeActionRowKey === actionCellKey,
138
- className: "p-1.5 rounded hover:bg-gray-200",
138
+ className: "p-1.5 rounded hover:bg-gray-200 dark:hover:bg-gray-700",
139
139
  title: "Actions",
140
+ "aria-label": "Actions",
140
141
  children: jsx(MoreVertical, {
141
- className: "h-4 w-4"
142
+ className: "h-4 w-4",
143
+ "aria-hidden": "true"
142
144
  })
143
145
  }), activeActionRowKey === actionCellKey && jsx(ActionMenu, {
144
146
  actions: menuActions,
@@ -166,7 +168,7 @@ function MobileCard(_ref) {
166
168
  return jsxs("div", {
167
169
  className: cn("flex justify-between items-center flex-row py-2 border-b last:border-b-0", safeExtraCellClass),
168
170
  children: [jsx("div", {
169
- className: "text-xs font-medium text-primary-500 uppercase tracking-wide mb-1 sm:mb-0 sm:w-1/3 sm:pr-2",
171
+ className: "text-xs font-medium text-primary-700 uppercase tracking-wide mb-1 sm:mb-0 sm:w-1/3 sm:pr-2",
170
172
  children: column.label
171
173
  }), jsx("div", {
172
174
  className: "text-sm text-primary-900 sm:w-2/3 sm:pl-2 break-words",
@@ -175,7 +177,7 @@ function MobileCard(_ref) {
175
177
  }, column.key);
176
178
  })
177
179
  }), showDetailsToggle && isExpanded && DetailsComponent && jsx("div", {
178
- className: "border-t bg-gray-50 p-4",
180
+ className: "border-t border-line bg-background p-4",
179
181
  children: jsx(DetailsComponent, {
180
182
  row: row,
181
183
  index: globalIndex
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
- import 'react';
3
+ import React from 'react';
4
4
  import { Search } from 'lucide-react';
5
5
 
6
6
  /**
@@ -17,20 +17,23 @@ function MobileFilters(_ref) {
17
17
  visibleColumns = _ref.visibleColumns,
18
18
  filters = _ref.filters,
19
19
  handleFilter = _ref.handleFilter;
20
+ var idPrefix = React.useId();
20
21
  return jsxs("div", {
21
- className: "mb-4 p-3 bg-gray-50 rounded-lg",
22
+ className: "mb-4 p-3 bg-background rounded-lg",
22
23
  children: [jsxs("div", {
23
24
  className: "flex items-center justify-between mb-3",
24
25
  children: [jsx("h3", {
25
26
  className: "text-sm font-medium",
26
27
  children: "Filters"
27
28
  }), jsx("button", {
29
+ type: "button",
28
30
  onClick: function onClick() {
29
31
  return setShowMobileFilters(function (s) {
30
32
  return !s;
31
33
  });
32
34
  },
33
- className: "text-xs text-primary-500",
35
+ "aria-expanded": !!showMobileFilters,
36
+ className: "text-xs font-medium text-primary-700",
34
37
  children: showMobileFilters ? "Hide" : "Show"
35
38
  })]
36
39
  }), showMobileFilters && jsxs("div", {
@@ -40,6 +43,7 @@ function MobileFilters(_ref) {
40
43
  children: [jsx("input", {
41
44
  type: "text",
42
45
  placeholder: "Search...",
46
+ "aria-label": "Search",
43
47
  className: "w-full rounded-md border border-gray-300 px-4 py-2 text-sm",
44
48
  value: searchInput,
45
49
  onChange: function onChange(e) {
@@ -47,14 +51,17 @@ function MobileFilters(_ref) {
47
51
  },
48
52
  onKeyDown: onGlobalKeyDown
49
53
  }), jsx(Search, {
50
- className: "absolute right-3 top-2.5 h-4 w-4 text-primary-400"
54
+ className: "absolute right-3 top-2.5 h-4 w-4 text-primary-400",
55
+ "aria-hidden": "true"
51
56
  })]
52
57
  }), filterable && visibleColumns.map(function (column) {
53
58
  return jsxs("div", {
54
59
  children: [jsx("label", {
60
+ htmlFor: "".concat(idPrefix, "-filter-").concat(column.key),
55
61
  className: "block text-xs font-medium mb-1",
56
62
  children: column.label
57
63
  }), jsx("input", {
64
+ id: "".concat(idPrefix, "-filter-").concat(column.key),
58
65
  type: "text",
59
66
  placeholder: "Filter ".concat(column.label),
60
67
  className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm",
@@ -9,7 +9,7 @@ import { ChevronsLeft, ChevronLeft, ChevronRight, ChevronsRight } from 'lucide-r
9
9
  * Pagination controls component for the table
10
10
  * Supports both header (icon-only) and footer (with page numbers) variants
11
11
  */
12
- var DEFAULT_ROW_HOVER = "bg-gray-50";
12
+ var DEFAULT_ROW_HOVER = "bg-background";
13
13
  // Header pagination (compact, icon-based)
14
14
  function PaginationHeader(_ref) {
15
15
  var _theme$rowHover;
@@ -21,11 +21,11 @@ var _excluded = ["data", "columns", "sortable", "filterable", "selectable", "pag
21
21
  var DEFAULT_DATA = [];
22
22
  var DEFAULT_COLUMNS = [];
23
23
  var DEFAULT_THEME = {
24
- stripedColors: ["bg-[#ffffff]", "bg-[#f7fafc]"],
25
- rowHover: "bg-gray-50",
26
- accentColor: "bg-gray-50",
27
- menuBg: "bg-white",
28
- menuItemHover: "hover:bg-gray-50"
24
+ stripedColors: ["bg-surface", "bg-background"],
25
+ rowHover: "bg-background",
26
+ accentColor: "bg-background",
27
+ menuBg: "bg-surface",
28
+ menuItemHover: "hover:bg-background"
29
29
  };
30
30
  var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
31
31
  var _validationErrors$;
@@ -1179,10 +1179,13 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1179
1179
  children: [showReloadButton && jsx(Fragment, {
1180
1180
  children: renderReloadButton ? typeof renderReloadButton === "function" ? renderReloadButton() : renderReloadButton : jsxs("button", {
1181
1181
  type: "button",
1182
+ "aria-label": "Reload",
1183
+ title: "Reload",
1182
1184
  className: "px-4 py-2 bg-primary-100 flex items-center gap-2 rounded-lg md:rounded text-primary-700 hover:bg-primary-200 transition-colors",
1183
1185
  onClick: onReload,
1184
1186
  children: [jsx(RefreshCcw, {
1185
- className: "size-4"
1187
+ className: "size-4",
1188
+ "aria-hidden": "true"
1186
1189
  }), jsx("span", {
1187
1190
  className: "hidden sm:inline",
1188
1191
  children: "Reload"
@@ -1236,7 +1239,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1236
1239
  onClick: handleClearChanges,
1237
1240
  disabled: isSaving,
1238
1241
  title: "Discard all pending modifications",
1239
- className: "px-4 py-2 font-medium rounded-lg text-sm flex items-center gap-2 transition-all border border-primary-300 text-primary-700 bg-white hover:bg-primary-50 active:bg-primary-100 cursor-pointer shadow-sm disabled:opacity-50",
1242
+ className: "px-4 py-2 font-medium rounded-lg text-sm flex items-center gap-2 transition-all border border-primary-300 text-primary-700 bg-surface hover:bg-primary-50 dark:text-primary-300 dark:border-primary-700 dark:hover:bg-primary-900/40 active:bg-primary-100 cursor-pointer shadow-sm disabled:opacity-50",
1240
1243
  children: [jsx(X, {
1241
1244
  className: "w-4 h-4 text-primary-600"
1242
1245
  }), jsx("span", {
@@ -1280,7 +1283,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1280
1283
  onKeyDown: onGlobalKeyDown
1281
1284
  }), jsx("button", {
1282
1285
  onClick: applyGlobalSearch,
1283
- className: "absolute right-2 top-1/2 transform -translate-y-1/2 p-2 rounded-lg hover:bg-gray-100",
1286
+ className: "absolute right-2 top-1/2 transform -translate-y-1/2 p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800",
1284
1287
  title: "Search",
1285
1288
  children: jsx(Search, {
1286
1289
  className: "h-4 w-4 text-primary-400"
@@ -1291,7 +1294,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1291
1294
  setSearchInput("");
1292
1295
  handleFilter("global", "");
1293
1296
  },
1294
- className: "whitespace-nowrap rounded-lg md:rounded-md border border-gray-300 px-4 py-3 md:py-2 text-sm hover:bg-gray-100 w-full sm:w-auto",
1297
+ className: "whitespace-nowrap rounded-lg md:rounded-md border border-gray-300 px-4 py-3 md:py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-800 w-full sm:w-auto",
1295
1298
  children: "Clear"
1296
1299
  })]
1297
1300
  })
@@ -1315,7 +1318,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1315
1318
  }), !isMobileView && jsx("div", {
1316
1319
  className: "overflow-x-auto overflow-y-visible",
1317
1320
  children: jsxs("table", _objectSpread2(_objectSpread2({
1318
- className: cn("min-w-full divide-y divide-gray-200", className)
1321
+ className: cn("min-w-full divide-y divide-line", className)
1319
1322
  }, props), {}, {
1320
1323
  children: [jsxs("thead", {
1321
1324
  className: safeTheme.accentColor,
@@ -1323,7 +1326,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1323
1326
  children: [hasDetailsColumn && jsx("th", {
1324
1327
  className: "w-8 px-4 py-3"
1325
1328
  }), showSerial && jsx("th", {
1326
- className: "w-8 px-4 py-3 text-left text-xs font-medium text-primary-500 uppercase tracking-wider",
1329
+ className: "w-8 px-4 py-3 text-left text-xs font-medium text-primary-700 uppercase tracking-wider",
1327
1330
  children: "#"
1328
1331
  }), selectable && jsx("th", {
1329
1332
  className: "w-12 px-6 py-3",
@@ -1336,8 +1339,8 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1336
1339
  }), visibleColumns.map(function (column) {
1337
1340
  var _column$rules;
1338
1341
  return jsx("th", {
1339
- className: cn("px-6 py-3 text-left text-xs font-medium text-primary-500 uppercase tracking-wider", {
1340
- "cursor-pointer hover:bg-gray-100": sortable && column.sortable !== false
1342
+ className: cn("px-6 py-3 text-left text-xs font-medium text-primary-700 uppercase tracking-wider", {
1343
+ "cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800": sortable && column.sortable !== false
1341
1344
  }),
1342
1345
  onClick: function onClick() {
1343
1346
  return column.sortable !== false && handleSort(column.key);
@@ -1381,7 +1384,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1381
1384
  return !s;
1382
1385
  });
1383
1386
  },
1384
- className: "p-1 rounded hover:bg-gray-100",
1387
+ className: "p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-800",
1385
1388
  children: jsx(MoreVertical, {
1386
1389
  className: "h-4 w-4"
1387
1390
  })
@@ -1417,7 +1420,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1417
1420
  })]
1418
1421
  })]
1419
1422
  }), jsx("tbody", {
1420
- className: "divide-y divide-gray-200",
1423
+ className: "divide-y divide-line",
1421
1424
  children: loading ? jsx("tr", {
1422
1425
  children: jsx("td", {
1423
1426
  colSpan: visibleCount,
@@ -1427,7 +1430,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1427
1430
  children: [jsx("div", {
1428
1431
  className: "h-6 w-6 animate-spin rounded-full border-2 border-primary-600 border-t-transparent"
1429
1432
  }), jsx("span", {
1430
- className: "text-sm text-primary-500",
1433
+ className: "text-sm text-muted",
1431
1434
  children: "Loading..."
1432
1435
  })]
1433
1436
  })
@@ -1445,7 +1448,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1445
1448
  className: "h-8 w-8"
1446
1449
  })
1447
1450
  }), jsx("span", {
1448
- className: "text-sm text-primary-500",
1451
+ className: "text-sm text-muted",
1449
1452
  children: "No results found."
1450
1453
  })]
1451
1454
  })
@@ -1490,7 +1493,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1490
1493
  children: [jsx("div", {
1491
1494
  className: "h-6 w-6 animate-spin rounded-full border-2 border-primary-600 border-t-transparent"
1492
1495
  }), jsx("span", {
1493
- className: "text-sm text-primary-500",
1496
+ className: "text-sm text-muted",
1494
1497
  children: "Loading..."
1495
1498
  })]
1496
1499
  })
@@ -1504,7 +1507,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1504
1507
  className: "h-8 w-8"
1505
1508
  })
1506
1509
  }), jsx("span", {
1507
- className: "text-sm text-primary-500",
1510
+ className: "text-sm text-muted",
1508
1511
  children: "No results found."
1509
1512
  })]
1510
1513
  })