@rufous/ui 0.1.65 → 0.1.67

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.
@@ -191,53 +191,55 @@ var APP_THEMES = {
191
191
  // lib/Contexts/rufousThemeProvider.tsx
192
192
  var RufousThemeContext = (0, import_react.createContext)(null);
193
193
  var RufousThemeProvider = ({ children }) => {
194
- const [colorScheme, setColorScheme] = (0, import_react.useState)("rufous");
195
- const [mode, setMode] = (0, import_react.useState)("light");
194
+ const [committedThemeKey, setCommittedThemeKey] = (0, import_react.useState)("default");
195
+ const [previewThemeKey, setPreviewThemeKey] = (0, import_react.useState)("default");
196
+ const [settings, setSettings] = (0, import_react.useState)(null);
197
+ const getGeneralSettings = async () => {
198
+ try {
199
+ const theme = localStorage.getItem("theme") || "default";
200
+ setCommittedThemeKey(theme);
201
+ setPreviewThemeKey(theme);
202
+ } catch (err) {
203
+ console.error("Error fetching general settings:", err);
204
+ }
205
+ };
196
206
  (0, import_react.useEffect)(() => {
197
- const savedScheme = localStorage.getItem("colorScheme") || "rufous";
198
- const savedMode = localStorage.getItem("themeMode") || "light";
199
- setColorScheme(savedScheme);
200
- setMode(savedMode);
207
+ getGeneralSettings();
201
208
  }, []);
202
- const toggleMode = () => {
203
- const newMode = mode === "light" ? "dark" : "light";
204
- setMode(newMode);
205
- localStorage.setItem("themeMode", newMode);
206
- };
207
- const changeScheme = (scheme) => {
208
- setColorScheme(scheme);
209
- localStorage.setItem("colorScheme", scheme);
210
- };
211
- const saveTheme = () => {
212
- localStorage.setItem("themeMode", mode);
213
- localStorage.setItem("colorScheme", colorScheme);
214
- };
215
- const updateSettings = (settings) => {
216
- if (settings.theme) setColorScheme(settings.theme);
217
- if (settings.mode) setMode(settings.mode);
218
- };
219
209
  const fullTheme = (0, import_react.useMemo)(() => {
220
210
  return {
221
- themeKey: colorScheme,
222
- customStyles: APP_THEMES[colorScheme][mode]
211
+ themeKey: previewThemeKey || settings.theme,
212
+ customStyles: APP_THEMES[previewThemeKey || settings.theme]
223
213
  };
224
- }, [colorScheme, mode]);
214
+ }, [previewThemeKey, settings]);
215
+ const previewTheme = (key) => setPreviewThemeKey(key);
216
+ const saveTheme = (inputKey) => {
217
+ const key = inputKey || previewThemeKey || settings.theme;
218
+ localStorage.setItem("theme", key);
219
+ setCommittedThemeKey(key);
220
+ };
221
+ const cancelTheme = () => setPreviewThemeKey(committedThemeKey);
225
222
  return /* @__PURE__ */ import_react.default.createElement(
226
223
  RufousThemeContext.Provider,
227
224
  {
228
225
  value: {
229
- colorScheme,
230
- mode,
231
- toggleMode,
232
- changeScheme,
233
- previewTheme: fullTheme,
226
+ theme: fullTheme,
227
+ previewTheme,
234
228
  saveTheme,
235
- updateSettings,
236
- theme: APP_THEMES[colorScheme][mode],
237
- themeConfig: APP_THEMES[colorScheme][mode]
229
+ cancelTheme,
230
+ currentThemeKey: previewThemeKey,
231
+ committedThemeKey,
232
+ settings,
233
+ updateSettings: (v) => setSettings(v)
238
234
  }
239
235
  },
240
- /* @__PURE__ */ import_react.default.createElement("div", { className: `rufous-theme-root scheme-${colorScheme} mode-${mode}` }, children)
236
+ /* @__PURE__ */ import_react.default.createElement(
237
+ "div",
238
+ {
239
+ className: `theme-${previewThemeKey || committedThemeKey || "default"}`
240
+ },
241
+ children
242
+ )
241
243
  );
242
244
  };
243
245
  var useRufousTheme = () => (0, import_react.useContext)(RufousThemeContext);
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  RufousThemeProvider,
3
3
  useRufousTheme
4
- } from "../chunk-NNKORPBI.js";
4
+ } from "../chunk-BOE27BFQ.js";
5
5
  import "../chunk-S7BNFVQO.js";
6
6
  import "../chunk-LI4N7JWK.js";
7
7
  export {
@@ -47,7 +47,8 @@ function DataGrid({
47
47
  const [columnWidths, setColumnWidths] = (0, import_react.useState)(() => {
48
48
  const widths = {};
49
49
  initialColumns.forEach((col) => {
50
- widths[String(col.key)] = parseInt(col.width || "200");
50
+ const w = col.width || 200;
51
+ widths[String(col.key)] = typeof w === "number" ? w : parseInt(w);
51
52
  });
52
53
  return widths;
53
54
  });
@@ -74,8 +75,8 @@ function DataGrid({
74
75
  if (!resizingColumn) return;
75
76
  const col = columns.find((c) => String(c.key) === resizingColumn);
76
77
  const diff = e.clientX - startX;
77
- const minW = col?.minWidth ? parseInt(col.minWidth) : 80;
78
- const maxW = col?.maxWidth ? parseInt(col.maxWidth) : Infinity;
78
+ const minW = col?.minWidth ? typeof col.minWidth === "number" ? col.minWidth : parseInt(col.minWidth) : 80;
79
+ const maxW = col?.maxWidth ? typeof col.maxWidth === "number" ? col.maxWidth : parseInt(col.maxWidth) : Infinity;
79
80
  const newWidth = Math.min(maxW, Math.max(minW, startWidth + diff));
80
81
  setColumnWidths((prev) => ({ ...prev, [resizingColumn]: newWidth }));
81
82
  };
@@ -166,14 +167,19 @@ function DataGrid({
166
167
  }, [data, filterText, advancedFilters]);
167
168
  const sortedData = (0, import_react.useMemo)(() => {
168
169
  if (!sortKey || !sortDirection) return filteredData;
170
+ const col = columns.find((c) => c.key === sortKey);
169
171
  return [...filteredData].sort((a, b) => {
170
- const aVal = a[sortKey];
171
- const bVal = b[sortKey];
172
+ let aVal = a[sortKey];
173
+ let bVal = b[sortKey];
174
+ if (col?.valueGetter) {
175
+ aVal = col.valueGetter({ value: aVal, row: a, field: String(sortKey) });
176
+ bVal = col.valueGetter({ value: bVal, row: b, field: String(sortKey) });
177
+ }
172
178
  if (aVal < bVal) return sortDirection === "asc" ? -1 : 1;
173
179
  if (aVal > bVal) return sortDirection === "asc" ? 1 : -1;
174
180
  return 0;
175
181
  });
176
- }, [filteredData, sortKey, sortDirection]);
182
+ }, [filteredData, sortKey, sortDirection, columns]);
177
183
  const totalPages = Math.max(1, Math.ceil(sortedData.length / pageSize));
178
184
  const paginatedData = (0, import_react.useMemo)(() => {
179
185
  const start = (currentPage - 1) * pageSize;
@@ -253,8 +259,8 @@ function DataGrid({
253
259
  "th",
254
260
  {
255
261
  key: colKey,
256
- className: `dg-thead-cell${col.pinned === "left" ? " pinned-left" : col.pinned === "right" ? " pinned-right" : ""}`,
257
- style: { width, minWidth: width, left: leftOffset }
262
+ className: `dg-thead-cell${col.pinned === "left" ? " pinned-left" : col.pinned === "right" ? " pinned-right" : ""} ${col.headerClassName || ""}`,
263
+ style: { width, minWidth: width, left: leftOffset, flex: col.flex }
258
264
  },
259
265
  /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-th-inner" }, /* @__PURE__ */ import_react.default.createElement(
260
266
  "div",
@@ -265,7 +271,7 @@ function DataGrid({
265
271
  col.header,
266
272
  isSorted && sortDirection === "asc" && /* @__PURE__ */ import_react.default.createElement(import_lucide_react.ChevronUp, { size: 12 }),
267
273
  isSorted && sortDirection === "desc" && /* @__PURE__ */ import_react.default.createElement(import_lucide_react.ChevronDown, { size: 12 })
268
- ), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-th-actions" }, /* @__PURE__ */ import_react.default.createElement(
274
+ ), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-th-actions" }, !col.disableColumnMenu && /* @__PURE__ */ import_react.default.createElement(
269
275
  "button",
270
276
  {
271
277
  className: "dg-th-menu-btn",
@@ -293,22 +299,39 @@ function DataGrid({
293
299
  "td",
294
300
  {
295
301
  key: `${item.id}-${colKey}`,
296
- className: `dg-td${col.pinned === "left" ? " pinned-left" : ""}`,
297
- style: { width, minWidth: width, maxWidth: width, left: leftOffset }
302
+ className: `dg-td${col.pinned === "left" ? " pinned-left" : ""} ${col.cellClassName || ""}`,
303
+ style: { width, minWidth: width, maxWidth: width, left: leftOffset, flex: col.flex }
298
304
  },
299
- col.render ? col.render(item[col.key], item) : String(item[col.key] ?? "")
305
+ (() => {
306
+ const field = String(col.key);
307
+ const rawValue = item[col.key];
308
+ let value = col.valueGetter ? col.valueGetter({ value: rawValue, row: item, field }) : rawValue;
309
+ const formattedValue = col.valueFormatter ? col.valueFormatter({ value, row: item, field }) : value;
310
+ if (col.renderCell) {
311
+ return col.renderCell({ value, row: item, field });
312
+ }
313
+ if (col.render) {
314
+ return col.render(value, item);
315
+ }
316
+ return String(formattedValue ?? "");
317
+ })()
300
318
  );
301
- }), actions && /* @__PURE__ */ import_react.default.createElement("td", { className: "dg-row-actions-cell" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-row-actions" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-action-group" }, actions.map((action, i) => /* @__PURE__ */ import_react.default.createElement(
302
- "button",
303
- {
304
- key: i,
305
- className: "dg-row-action-btn",
306
- style: { color: action.color || "var(--text-secondary)" },
307
- onClick: () => action.onClick(item),
308
- title: action.label
309
- },
310
- action.icon
311
- )))))))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ import_react.default.createElement("span", null, "Rows per page:"), /* @__PURE__ */ import_react.default.createElement(
319
+ }), actions && /* @__PURE__ */ import_react.default.createElement("td", { className: "dg-row-actions-cell" }, (() => {
320
+ const resolvedActions = typeof actions === "function" ? actions(item) : actions;
321
+ const visibleActions = resolvedActions.filter((a) => !a.show || a.show(item));
322
+ if (visibleActions.length === 0) return null;
323
+ return /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-row-actions" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-action-group" }, visibleActions.map((action, i) => /* @__PURE__ */ import_react.default.createElement(
324
+ "button",
325
+ {
326
+ key: i,
327
+ className: "dg-row-action-btn",
328
+ style: { color: action.color || "var(--text-secondary)" },
329
+ onClick: () => action.onClick(item),
330
+ title: action.label
331
+ },
332
+ action.icon
333
+ ))));
334
+ })())))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ import_react.default.createElement("span", null, "Rows per page:"), /* @__PURE__ */ import_react.default.createElement(
312
335
  "select",
313
336
  {
314
337
  value: pageSize,
@@ -349,7 +372,7 @@ function DataGrid({
349
372
  value: colSearch,
350
373
  onChange: (e) => setColSearch(e.target.value)
351
374
  }
352
- )), columns.filter((c) => c.header.toLowerCase().includes(colSearch.toLowerCase())).map((col) => /* @__PURE__ */ import_react.default.createElement("div", { key: String(col.key), className: "dg-col-row" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-col-label" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-col-dot", style: { background: col.hidden ? "var(--border-color)" : "var(--primary-color)" } }), col.header), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-icon-btn", onClick: () => toggleHide(String(col.key)) }, col.hidden ? /* @__PURE__ */ import_react.default.createElement(import_lucide_react.EyeOff, { size: 14 }) : /* @__PURE__ */ import_react.default.createElement(import_lucide_react.EyeOff, { size: 14, style: { opacity: 0.4 } }))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-footer" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: false }))) }, "Show All"), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: true }))) }, "Hide All")))), showAdvancedFilter && /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-overlay", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal dg-modal-wide", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-header" }, /* @__PURE__ */ import_react.default.createElement("h3", null, "Filters"), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-icon-btn", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react.default.createElement(import_lucide_react.X, { size: 18 }))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-body" }, advancedFilters.map((f, idx) => /* @__PURE__ */ import_react.default.createElement("div", { key: idx }, idx > 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-filter-logic" }, /* @__PURE__ */ import_react.default.createElement(
375
+ )), columns.filter((c) => c.header.toLowerCase().includes(colSearch.toLowerCase()) && c.hideable !== false).map((col) => /* @__PURE__ */ import_react.default.createElement("div", { key: String(col.key), className: "dg-col-row" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-col-label" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-col-dot", style: { background: col.hidden ? "var(--border-color)" : "var(--primary-color)" } }), col.header), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-icon-btn", onClick: () => toggleHide(String(col.key)) }, col.hidden ? /* @__PURE__ */ import_react.default.createElement(import_lucide_react.EyeOff, { size: 14 }) : /* @__PURE__ */ import_react.default.createElement(import_lucide_react.EyeOff, { size: 14, style: { opacity: 0.4 } }))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-footer" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: false }))) }, "Show All"), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => c.hideable !== false ? { ...c, hidden: true } : c)) }, "Hide All")))), showAdvancedFilter && /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-overlay", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal dg-modal-wide", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-header" }, /* @__PURE__ */ import_react.default.createElement("h3", null, "Filters"), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-icon-btn", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react.default.createElement(import_lucide_react.X, { size: 18 }))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-body" }, advancedFilters.map((f, idx) => /* @__PURE__ */ import_react.default.createElement("div", { key: idx }, idx > 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-filter-logic" }, /* @__PURE__ */ import_react.default.createElement(
353
376
  "button",
354
377
  {
355
378
  className: `dg-logic-btn${f.logic === "AND" ? " active" : ""}`,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DataGrid,
3
3
  DataGrid_default
4
- } from "../chunk-J6E3UO2W.js";
4
+ } from "../chunk-IKG2B6JQ.js";
5
5
  import "../chunk-LI4N7JWK.js";
6
6
  export {
7
7
  DataGrid,
@@ -48,7 +48,8 @@ function DataGrid({
48
48
  const [columnWidths, setColumnWidths] = (0, import_react.useState)(() => {
49
49
  const widths = {};
50
50
  initialColumns.forEach((col) => {
51
- widths[String(col.key)] = parseInt(col.width || "200");
51
+ const w = col.width || 200;
52
+ widths[String(col.key)] = typeof w === "number" ? w : parseInt(w);
52
53
  });
53
54
  return widths;
54
55
  });
@@ -75,8 +76,8 @@ function DataGrid({
75
76
  if (!resizingColumn) return;
76
77
  const col = columns.find((c) => String(c.key) === resizingColumn);
77
78
  const diff = e.clientX - startX;
78
- const minW = col?.minWidth ? parseInt(col.minWidth) : 80;
79
- const maxW = col?.maxWidth ? parseInt(col.maxWidth) : Infinity;
79
+ const minW = col?.minWidth ? typeof col.minWidth === "number" ? col.minWidth : parseInt(col.minWidth) : 80;
80
+ const maxW = col?.maxWidth ? typeof col.maxWidth === "number" ? col.maxWidth : parseInt(col.maxWidth) : Infinity;
80
81
  const newWidth = Math.min(maxW, Math.max(minW, startWidth + diff));
81
82
  setColumnWidths((prev) => ({ ...prev, [resizingColumn]: newWidth }));
82
83
  };
@@ -167,14 +168,19 @@ function DataGrid({
167
168
  }, [data, filterText, advancedFilters]);
168
169
  const sortedData = (0, import_react.useMemo)(() => {
169
170
  if (!sortKey || !sortDirection) return filteredData;
171
+ const col = columns.find((c) => c.key === sortKey);
170
172
  return [...filteredData].sort((a, b) => {
171
- const aVal = a[sortKey];
172
- const bVal = b[sortKey];
173
+ let aVal = a[sortKey];
174
+ let bVal = b[sortKey];
175
+ if (col?.valueGetter) {
176
+ aVal = col.valueGetter({ value: aVal, row: a, field: String(sortKey) });
177
+ bVal = col.valueGetter({ value: bVal, row: b, field: String(sortKey) });
178
+ }
173
179
  if (aVal < bVal) return sortDirection === "asc" ? -1 : 1;
174
180
  if (aVal > bVal) return sortDirection === "asc" ? 1 : -1;
175
181
  return 0;
176
182
  });
177
- }, [filteredData, sortKey, sortDirection]);
183
+ }, [filteredData, sortKey, sortDirection, columns]);
178
184
  const totalPages = Math.max(1, Math.ceil(sortedData.length / pageSize));
179
185
  const paginatedData = (0, import_react.useMemo)(() => {
180
186
  const start = (currentPage - 1) * pageSize;
@@ -254,8 +260,8 @@ function DataGrid({
254
260
  "th",
255
261
  {
256
262
  key: colKey,
257
- className: `dg-thead-cell${col.pinned === "left" ? " pinned-left" : col.pinned === "right" ? " pinned-right" : ""}`,
258
- style: { width, minWidth: width, left: leftOffset }
263
+ className: `dg-thead-cell${col.pinned === "left" ? " pinned-left" : col.pinned === "right" ? " pinned-right" : ""} ${col.headerClassName || ""}`,
264
+ style: { width, minWidth: width, left: leftOffset, flex: col.flex }
259
265
  },
260
266
  /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-th-inner" }, /* @__PURE__ */ import_react.default.createElement(
261
267
  "div",
@@ -266,7 +272,7 @@ function DataGrid({
266
272
  col.header,
267
273
  isSorted && sortDirection === "asc" && /* @__PURE__ */ import_react.default.createElement(import_lucide_react.ChevronUp, { size: 12 }),
268
274
  isSorted && sortDirection === "desc" && /* @__PURE__ */ import_react.default.createElement(import_lucide_react.ChevronDown, { size: 12 })
269
- ), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-th-actions" }, /* @__PURE__ */ import_react.default.createElement(
275
+ ), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-th-actions" }, !col.disableColumnMenu && /* @__PURE__ */ import_react.default.createElement(
270
276
  "button",
271
277
  {
272
278
  className: "dg-th-menu-btn",
@@ -294,22 +300,39 @@ function DataGrid({
294
300
  "td",
295
301
  {
296
302
  key: `${item.id}-${colKey}`,
297
- className: `dg-td${col.pinned === "left" ? " pinned-left" : ""}`,
298
- style: { width, minWidth: width, maxWidth: width, left: leftOffset }
303
+ className: `dg-td${col.pinned === "left" ? " pinned-left" : ""} ${col.cellClassName || ""}`,
304
+ style: { width, minWidth: width, maxWidth: width, left: leftOffset, flex: col.flex }
299
305
  },
300
- col.render ? col.render(item[col.key], item) : String(item[col.key] ?? "")
306
+ (() => {
307
+ const field = String(col.key);
308
+ const rawValue = item[col.key];
309
+ let value = col.valueGetter ? col.valueGetter({ value: rawValue, row: item, field }) : rawValue;
310
+ const formattedValue = col.valueFormatter ? col.valueFormatter({ value, row: item, field }) : value;
311
+ if (col.renderCell) {
312
+ return col.renderCell({ value, row: item, field });
313
+ }
314
+ if (col.render) {
315
+ return col.render(value, item);
316
+ }
317
+ return String(formattedValue ?? "");
318
+ })()
301
319
  );
302
- }), actions && /* @__PURE__ */ import_react.default.createElement("td", { className: "dg-row-actions-cell" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-row-actions" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-action-group" }, actions.map((action, i) => /* @__PURE__ */ import_react.default.createElement(
303
- "button",
304
- {
305
- key: i,
306
- className: "dg-row-action-btn",
307
- style: { color: action.color || "var(--text-secondary)" },
308
- onClick: () => action.onClick(item),
309
- title: action.label
310
- },
311
- action.icon
312
- )))))))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ import_react.default.createElement("span", null, "Rows per page:"), /* @__PURE__ */ import_react.default.createElement(
320
+ }), actions && /* @__PURE__ */ import_react.default.createElement("td", { className: "dg-row-actions-cell" }, (() => {
321
+ const resolvedActions = typeof actions === "function" ? actions(item) : actions;
322
+ const visibleActions = resolvedActions.filter((a) => !a.show || a.show(item));
323
+ if (visibleActions.length === 0) return null;
324
+ return /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-row-actions" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-action-group" }, visibleActions.map((action, i) => /* @__PURE__ */ import_react.default.createElement(
325
+ "button",
326
+ {
327
+ key: i,
328
+ className: "dg-row-action-btn",
329
+ style: { color: action.color || "var(--text-secondary)" },
330
+ onClick: () => action.onClick(item),
331
+ title: action.label
332
+ },
333
+ action.icon
334
+ ))));
335
+ })())))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ import_react.default.createElement("span", null, "Rows per page:"), /* @__PURE__ */ import_react.default.createElement(
313
336
  "select",
314
337
  {
315
338
  value: pageSize,
@@ -350,7 +373,7 @@ function DataGrid({
350
373
  value: colSearch,
351
374
  onChange: (e) => setColSearch(e.target.value)
352
375
  }
353
- )), columns.filter((c) => c.header.toLowerCase().includes(colSearch.toLowerCase())).map((col) => /* @__PURE__ */ import_react.default.createElement("div", { key: String(col.key), className: "dg-col-row" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-col-label" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-col-dot", style: { background: col.hidden ? "var(--border-color)" : "var(--primary-color)" } }), col.header), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-icon-btn", onClick: () => toggleHide(String(col.key)) }, col.hidden ? /* @__PURE__ */ import_react.default.createElement(import_lucide_react.EyeOff, { size: 14 }) : /* @__PURE__ */ import_react.default.createElement(import_lucide_react.EyeOff, { size: 14, style: { opacity: 0.4 } }))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-footer" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: false }))) }, "Show All"), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: true }))) }, "Hide All")))), showAdvancedFilter && /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-overlay", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal dg-modal-wide", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-header" }, /* @__PURE__ */ import_react.default.createElement("h3", null, "Filters"), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-icon-btn", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react.default.createElement(import_lucide_react.X, { size: 18 }))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-body" }, advancedFilters.map((f, idx) => /* @__PURE__ */ import_react.default.createElement("div", { key: idx }, idx > 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-filter-logic" }, /* @__PURE__ */ import_react.default.createElement(
376
+ )), columns.filter((c) => c.header.toLowerCase().includes(colSearch.toLowerCase()) && c.hideable !== false).map((col) => /* @__PURE__ */ import_react.default.createElement("div", { key: String(col.key), className: "dg-col-row" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-col-label" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-col-dot", style: { background: col.hidden ? "var(--border-color)" : "var(--primary-color)" } }), col.header), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-icon-btn", onClick: () => toggleHide(String(col.key)) }, col.hidden ? /* @__PURE__ */ import_react.default.createElement(import_lucide_react.EyeOff, { size: 14 }) : /* @__PURE__ */ import_react.default.createElement(import_lucide_react.EyeOff, { size: 14, style: { opacity: 0.4 } }))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-footer" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: false }))) }, "Show All"), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => c.hideable !== false ? { ...c, hidden: true } : c)) }, "Hide All")))), showAdvancedFilter && /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-overlay", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal dg-modal-wide", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-header" }, /* @__PURE__ */ import_react.default.createElement("h3", null, "Filters"), /* @__PURE__ */ import_react.default.createElement("button", { className: "dg-icon-btn", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react.default.createElement(import_lucide_react.X, { size: 18 }))), /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-modal-body" }, advancedFilters.map((f, idx) => /* @__PURE__ */ import_react.default.createElement("div", { key: idx }, idx > 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: "dg-filter-logic" }, /* @__PURE__ */ import_react.default.createElement(
354
377
  "button",
355
378
  {
356
379
  className: `dg-logic-btn${f.logic === "AND" ? " active" : ""}`,
@@ -1,7 +1,7 @@
1
1
  import "../chunk-7KRG7VNW.js";
2
2
  import {
3
3
  DataGrid
4
- } from "../chunk-J6E3UO2W.js";
4
+ } from "../chunk-IKG2B6JQ.js";
5
5
  import "../chunk-LI4N7JWK.js";
6
6
  export {
7
7
  DataGrid
@@ -7,22 +7,45 @@ interface Column<T> {
7
7
  sortable?: boolean;
8
8
  filterable?: boolean;
9
9
  render?: (value: any, item: T) => React__default.ReactNode;
10
- width?: string;
11
- minWidth?: string;
12
- maxWidth?: string;
10
+ renderCell?: (params: {
11
+ value: any;
12
+ row: T;
13
+ field: string;
14
+ }) => React__default.ReactNode;
15
+ valueGetter?: (params: {
16
+ value: any;
17
+ row: T;
18
+ field: string;
19
+ }) => any;
20
+ valueFormatter?: (params: {
21
+ value: any;
22
+ row: T;
23
+ field: string;
24
+ }) => string;
25
+ width?: string | number;
26
+ minWidth?: string | number;
27
+ maxWidth?: string | number;
28
+ flex?: number;
13
29
  pinned?: 'left' | 'right';
14
30
  hidden?: boolean;
31
+ type?: 'string' | 'number' | 'date' | 'boolean' | 'actions';
32
+ editable?: boolean;
33
+ headerClassName?: string;
34
+ cellClassName?: string;
35
+ hideable?: boolean;
36
+ disableColumnMenu?: boolean;
15
37
  }
16
38
  interface Action<T> {
17
39
  label: string;
18
40
  icon: React__default.ReactNode;
19
41
  onClick: (item: T) => void;
20
42
  color?: string;
43
+ show?: (item: T) => boolean;
21
44
  }
22
45
  interface DataGridProps<T> {
23
46
  columns: Column<T>[];
24
47
  data: T[];
25
- actions?: Action<T>[];
48
+ actions?: Action<T>[] | ((item: T) => Action<T>[]);
26
49
  pageSize?: number;
27
50
  pageSizeOptions?: number[];
28
51
  title?: string;
@@ -7,22 +7,45 @@ interface Column<T> {
7
7
  sortable?: boolean;
8
8
  filterable?: boolean;
9
9
  render?: (value: any, item: T) => React__default.ReactNode;
10
- width?: string;
11
- minWidth?: string;
12
- maxWidth?: string;
10
+ renderCell?: (params: {
11
+ value: any;
12
+ row: T;
13
+ field: string;
14
+ }) => React__default.ReactNode;
15
+ valueGetter?: (params: {
16
+ value: any;
17
+ row: T;
18
+ field: string;
19
+ }) => any;
20
+ valueFormatter?: (params: {
21
+ value: any;
22
+ row: T;
23
+ field: string;
24
+ }) => string;
25
+ width?: string | number;
26
+ minWidth?: string | number;
27
+ maxWidth?: string | number;
28
+ flex?: number;
13
29
  pinned?: 'left' | 'right';
14
30
  hidden?: boolean;
31
+ type?: 'string' | 'number' | 'date' | 'boolean' | 'actions';
32
+ editable?: boolean;
33
+ headerClassName?: string;
34
+ cellClassName?: string;
35
+ hideable?: boolean;
36
+ disableColumnMenu?: boolean;
15
37
  }
16
38
  interface Action<T> {
17
39
  label: string;
18
40
  icon: React__default.ReactNode;
19
41
  onClick: (item: T) => void;
20
42
  color?: string;
43
+ show?: (item: T) => boolean;
21
44
  }
22
45
  interface DataGridProps<T> {
23
46
  columns: Column<T>[];
24
47
  data: T[];
25
- actions?: Action<T>[];
48
+ actions?: Action<T>[] | ((item: T) => Action<T>[]);
26
49
  pageSize?: number;
27
50
  pageSizeOptions?: number[];
28
51
  title?: string;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BaseDialog_default
3
- } from "../chunk-EZ7WAUAG.js";
3
+ } from "../chunk-4GPYGFPP.js";
4
4
  import "../chunk-E5RTHYCU.js";
5
5
  import "../chunk-EZI3QGYJ.js";
6
6
  import "../chunk-QTGVW36I.js";
@@ -58,14 +58,13 @@ import "../chunk-AH6RCYDL.js";
58
58
  import "../chunk-3IBCGGN3.js";
59
59
  import "../chunk-MNPAE2ZF.js";
60
60
  import "../chunk-Q5XKCUE3.js";
61
- import "../chunk-3MC7I6L2.js";
61
+ import "../chunk-GJGRMMAQ.js";
62
+ import "../chunk-GHCM2AWR.js";
62
63
  import "../chunk-UPCMMCPQ.js";
63
- import "../chunk-X357WQOT.js";
64
- import "../chunk-NNKORPBI.js";
65
- import "../chunk-S7BNFVQO.js";
66
64
  import "../chunk-7KRG7VNW.js";
67
- import "../chunk-J6E3UO2W.js";
68
- import "../chunk-GJGRMMAQ.js";
65
+ import "../chunk-BOE27BFQ.js";
66
+ import "../chunk-S7BNFVQO.js";
67
+ import "../chunk-X357WQOT.js";
69
68
  import "../chunk-66HHM7VI.js";
70
69
  import "../chunk-QPGJCRBS.js";
71
70
  import "../chunk-U7SARO5B.js";
@@ -73,6 +72,7 @@ import "../chunk-BMMDUQDJ.js";
73
72
  import "../chunk-R3GARAVJ.js";
74
73
  import "../chunk-YRLN3TBF.js";
75
74
  import "../chunk-CTBYVXFP.js";
75
+ import "../chunk-IKG2B6JQ.js";
76
76
  import "../chunk-LI4N7JWK.js";
77
77
  export {
78
78
  BaseDialog_default as default
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BaseDialog_default
3
- } from "../chunk-EZ7WAUAG.js";
3
+ } from "../chunk-4GPYGFPP.js";
4
4
  import "../chunk-E5RTHYCU.js";
5
5
  import "../chunk-EZI3QGYJ.js";
6
6
  import "../chunk-QTGVW36I.js";
@@ -58,14 +58,13 @@ import "../chunk-AH6RCYDL.js";
58
58
  import "../chunk-3IBCGGN3.js";
59
59
  import "../chunk-MNPAE2ZF.js";
60
60
  import "../chunk-Q5XKCUE3.js";
61
- import "../chunk-3MC7I6L2.js";
61
+ import "../chunk-GJGRMMAQ.js";
62
+ import "../chunk-GHCM2AWR.js";
62
63
  import "../chunk-UPCMMCPQ.js";
63
- import "../chunk-X357WQOT.js";
64
- import "../chunk-NNKORPBI.js";
65
- import "../chunk-S7BNFVQO.js";
66
64
  import "../chunk-7KRG7VNW.js";
67
- import "../chunk-J6E3UO2W.js";
68
- import "../chunk-GJGRMMAQ.js";
65
+ import "../chunk-BOE27BFQ.js";
66
+ import "../chunk-S7BNFVQO.js";
67
+ import "../chunk-X357WQOT.js";
69
68
  import "../chunk-66HHM7VI.js";
70
69
  import "../chunk-QPGJCRBS.js";
71
70
  import "../chunk-U7SARO5B.js";
@@ -73,6 +72,7 @@ import "../chunk-BMMDUQDJ.js";
73
72
  import "../chunk-R3GARAVJ.js";
74
73
  import "../chunk-YRLN3TBF.js";
75
74
  import "../chunk-CTBYVXFP.js";
75
+ import "../chunk-IKG2B6JQ.js";
76
76
  import "../chunk-LI4N7JWK.js";
77
77
  export {
78
78
  BaseDialog_default as BaseDialog
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  AddressLookup_default
3
- } from "../chunk-3MC7I6L2.js";
3
+ } from "../chunk-GHCM2AWR.js";
4
4
  import "../chunk-UPCMMCPQ.js";
5
- import "../chunk-NNKORPBI.js";
5
+ import "../chunk-BOE27BFQ.js";
6
6
  import "../chunk-S7BNFVQO.js";
7
7
  import "../chunk-CTBYVXFP.js";
8
8
  import "../chunk-LI4N7JWK.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-Q5XKCUE3.js";
4
4
  import {
5
5
  useRufousTheme
6
- } from "./chunk-NNKORPBI.js";
6
+ } from "./chunk-BOE27BFQ.js";
7
7
 
8
8
  // lib/Dialogs/BaseDialog.tsx
9
9
  import * as React from "react";
@@ -0,0 +1,71 @@
1
+ import {
2
+ APP_THEMES
3
+ } from "./chunk-S7BNFVQO.js";
4
+
5
+ // lib/Contexts/rufousThemeProvider.tsx
6
+ import React, {
7
+ createContext,
8
+ useContext,
9
+ useEffect,
10
+ useMemo,
11
+ useState
12
+ } from "react";
13
+ var RufousThemeContext = createContext(null);
14
+ var RufousThemeProvider = ({ children }) => {
15
+ const [committedThemeKey, setCommittedThemeKey] = useState("default");
16
+ const [previewThemeKey, setPreviewThemeKey] = useState("default");
17
+ const [settings, setSettings] = useState(null);
18
+ const getGeneralSettings = async () => {
19
+ try {
20
+ const theme = localStorage.getItem("theme") || "default";
21
+ setCommittedThemeKey(theme);
22
+ setPreviewThemeKey(theme);
23
+ } catch (err) {
24
+ console.error("Error fetching general settings:", err);
25
+ }
26
+ };
27
+ useEffect(() => {
28
+ getGeneralSettings();
29
+ }, []);
30
+ const fullTheme = useMemo(() => {
31
+ return {
32
+ themeKey: previewThemeKey || settings.theme,
33
+ customStyles: APP_THEMES[previewThemeKey || settings.theme]
34
+ };
35
+ }, [previewThemeKey, settings]);
36
+ const previewTheme = (key) => setPreviewThemeKey(key);
37
+ const saveTheme = (inputKey) => {
38
+ const key = inputKey || previewThemeKey || settings.theme;
39
+ localStorage.setItem("theme", key);
40
+ setCommittedThemeKey(key);
41
+ };
42
+ const cancelTheme = () => setPreviewThemeKey(committedThemeKey);
43
+ return /* @__PURE__ */ React.createElement(
44
+ RufousThemeContext.Provider,
45
+ {
46
+ value: {
47
+ theme: fullTheme,
48
+ previewTheme,
49
+ saveTheme,
50
+ cancelTheme,
51
+ currentThemeKey: previewThemeKey,
52
+ committedThemeKey,
53
+ settings,
54
+ updateSettings: (v) => setSettings(v)
55
+ }
56
+ },
57
+ /* @__PURE__ */ React.createElement(
58
+ "div",
59
+ {
60
+ className: `theme-${previewThemeKey || committedThemeKey || "default"}`
61
+ },
62
+ children
63
+ )
64
+ );
65
+ };
66
+ var useRufousTheme = () => useContext(RufousThemeContext);
67
+
68
+ export {
69
+ RufousThemeProvider,
70
+ useRufousTheme
71
+ };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-UPCMMCPQ.js";
4
4
  import {
5
5
  useRufousTheme
6
- } from "./chunk-NNKORPBI.js";
6
+ } from "./chunk-BOE27BFQ.js";
7
7
  import {
8
8
  circularProgress_default
9
9
  } from "./chunk-CTBYVXFP.js";
@@ -30,7 +30,8 @@ function DataGrid({
30
30
  const [columnWidths, setColumnWidths] = useState(() => {
31
31
  const widths = {};
32
32
  initialColumns.forEach((col) => {
33
- widths[String(col.key)] = parseInt(col.width || "200");
33
+ const w = col.width || 200;
34
+ widths[String(col.key)] = typeof w === "number" ? w : parseInt(w);
34
35
  });
35
36
  return widths;
36
37
  });
@@ -57,8 +58,8 @@ function DataGrid({
57
58
  if (!resizingColumn) return;
58
59
  const col = columns.find((c) => String(c.key) === resizingColumn);
59
60
  const diff = e.clientX - startX;
60
- const minW = col?.minWidth ? parseInt(col.minWidth) : 80;
61
- const maxW = col?.maxWidth ? parseInt(col.maxWidth) : Infinity;
61
+ const minW = col?.minWidth ? typeof col.minWidth === "number" ? col.minWidth : parseInt(col.minWidth) : 80;
62
+ const maxW = col?.maxWidth ? typeof col.maxWidth === "number" ? col.maxWidth : parseInt(col.maxWidth) : Infinity;
62
63
  const newWidth = Math.min(maxW, Math.max(minW, startWidth + diff));
63
64
  setColumnWidths((prev) => ({ ...prev, [resizingColumn]: newWidth }));
64
65
  };
@@ -149,14 +150,19 @@ function DataGrid({
149
150
  }, [data, filterText, advancedFilters]);
150
151
  const sortedData = useMemo(() => {
151
152
  if (!sortKey || !sortDirection) return filteredData;
153
+ const col = columns.find((c) => c.key === sortKey);
152
154
  return [...filteredData].sort((a, b) => {
153
- const aVal = a[sortKey];
154
- const bVal = b[sortKey];
155
+ let aVal = a[sortKey];
156
+ let bVal = b[sortKey];
157
+ if (col?.valueGetter) {
158
+ aVal = col.valueGetter({ value: aVal, row: a, field: String(sortKey) });
159
+ bVal = col.valueGetter({ value: bVal, row: b, field: String(sortKey) });
160
+ }
155
161
  if (aVal < bVal) return sortDirection === "asc" ? -1 : 1;
156
162
  if (aVal > bVal) return sortDirection === "asc" ? 1 : -1;
157
163
  return 0;
158
164
  });
159
- }, [filteredData, sortKey, sortDirection]);
165
+ }, [filteredData, sortKey, sortDirection, columns]);
160
166
  const totalPages = Math.max(1, Math.ceil(sortedData.length / pageSize));
161
167
  const paginatedData = useMemo(() => {
162
168
  const start = (currentPage - 1) * pageSize;
@@ -236,8 +242,8 @@ function DataGrid({
236
242
  "th",
237
243
  {
238
244
  key: colKey,
239
- className: `dg-thead-cell${col.pinned === "left" ? " pinned-left" : col.pinned === "right" ? " pinned-right" : ""}`,
240
- style: { width, minWidth: width, left: leftOffset }
245
+ className: `dg-thead-cell${col.pinned === "left" ? " pinned-left" : col.pinned === "right" ? " pinned-right" : ""} ${col.headerClassName || ""}`,
246
+ style: { width, minWidth: width, left: leftOffset, flex: col.flex }
241
247
  },
242
248
  /* @__PURE__ */ React.createElement("div", { className: "dg-th-inner" }, /* @__PURE__ */ React.createElement(
243
249
  "div",
@@ -248,7 +254,7 @@ function DataGrid({
248
254
  col.header,
249
255
  isSorted && sortDirection === "asc" && /* @__PURE__ */ React.createElement(ChevronUp, { size: 12 }),
250
256
  isSorted && sortDirection === "desc" && /* @__PURE__ */ React.createElement(ChevronDown, { size: 12 })
251
- ), /* @__PURE__ */ React.createElement("div", { className: "dg-th-actions" }, /* @__PURE__ */ React.createElement(
257
+ ), /* @__PURE__ */ React.createElement("div", { className: "dg-th-actions" }, !col.disableColumnMenu && /* @__PURE__ */ React.createElement(
252
258
  "button",
253
259
  {
254
260
  className: "dg-th-menu-btn",
@@ -276,22 +282,39 @@ function DataGrid({
276
282
  "td",
277
283
  {
278
284
  key: `${item.id}-${colKey}`,
279
- className: `dg-td${col.pinned === "left" ? " pinned-left" : ""}`,
280
- style: { width, minWidth: width, maxWidth: width, left: leftOffset }
285
+ className: `dg-td${col.pinned === "left" ? " pinned-left" : ""} ${col.cellClassName || ""}`,
286
+ style: { width, minWidth: width, maxWidth: width, left: leftOffset, flex: col.flex }
281
287
  },
282
- col.render ? col.render(item[col.key], item) : String(item[col.key] ?? "")
288
+ (() => {
289
+ const field = String(col.key);
290
+ const rawValue = item[col.key];
291
+ let value = col.valueGetter ? col.valueGetter({ value: rawValue, row: item, field }) : rawValue;
292
+ const formattedValue = col.valueFormatter ? col.valueFormatter({ value, row: item, field }) : value;
293
+ if (col.renderCell) {
294
+ return col.renderCell({ value, row: item, field });
295
+ }
296
+ if (col.render) {
297
+ return col.render(value, item);
298
+ }
299
+ return String(formattedValue ?? "");
300
+ })()
283
301
  );
284
- }), actions && /* @__PURE__ */ React.createElement("td", { className: "dg-row-actions-cell" }, /* @__PURE__ */ React.createElement("div", { className: "dg-row-actions" }, /* @__PURE__ */ React.createElement("div", { className: "dg-action-group" }, actions.map((action, i) => /* @__PURE__ */ React.createElement(
285
- "button",
286
- {
287
- key: i,
288
- className: "dg-row-action-btn",
289
- style: { color: action.color || "var(--text-secondary)" },
290
- onClick: () => action.onClick(item),
291
- title: action.label
292
- },
293
- action.icon
294
- )))))))))), /* @__PURE__ */ React.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ React.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ React.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ React.createElement("span", null, "Rows per page:"), /* @__PURE__ */ React.createElement(
302
+ }), actions && /* @__PURE__ */ React.createElement("td", { className: "dg-row-actions-cell" }, (() => {
303
+ const resolvedActions = typeof actions === "function" ? actions(item) : actions;
304
+ const visibleActions = resolvedActions.filter((a) => !a.show || a.show(item));
305
+ if (visibleActions.length === 0) return null;
306
+ return /* @__PURE__ */ React.createElement("div", { className: "dg-row-actions" }, /* @__PURE__ */ React.createElement("div", { className: "dg-action-group" }, visibleActions.map((action, i) => /* @__PURE__ */ React.createElement(
307
+ "button",
308
+ {
309
+ key: i,
310
+ className: "dg-row-action-btn",
311
+ style: { color: action.color || "var(--text-secondary)" },
312
+ onClick: () => action.onClick(item),
313
+ title: action.label
314
+ },
315
+ action.icon
316
+ ))));
317
+ })())))))), /* @__PURE__ */ React.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ React.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ React.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ React.createElement("span", null, "Rows per page:"), /* @__PURE__ */ React.createElement(
295
318
  "select",
296
319
  {
297
320
  value: pageSize,
@@ -332,7 +355,7 @@ function DataGrid({
332
355
  value: colSearch,
333
356
  onChange: (e) => setColSearch(e.target.value)
334
357
  }
335
- )), columns.filter((c) => c.header.toLowerCase().includes(colSearch.toLowerCase())).map((col) => /* @__PURE__ */ React.createElement("div", { key: String(col.key), className: "dg-col-row" }, /* @__PURE__ */ React.createElement("div", { className: "dg-col-label" }, /* @__PURE__ */ React.createElement("div", { className: "dg-col-dot", style: { background: col.hidden ? "var(--border-color)" : "var(--primary-color)" } }), col.header), /* @__PURE__ */ React.createElement("button", { className: "dg-icon-btn", onClick: () => toggleHide(String(col.key)) }, col.hidden ? /* @__PURE__ */ React.createElement(EyeOff, { size: 14 }) : /* @__PURE__ */ React.createElement(EyeOff, { size: 14, style: { opacity: 0.4 } }))))), /* @__PURE__ */ React.createElement("div", { className: "dg-modal-footer" }, /* @__PURE__ */ React.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: false }))) }, "Show All"), /* @__PURE__ */ React.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: true }))) }, "Hide All")))), showAdvancedFilter && /* @__PURE__ */ React.createElement("div", { className: "dg-modal-overlay", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ React.createElement("div", { className: "dg-modal dg-modal-wide", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React.createElement("div", { className: "dg-modal-header" }, /* @__PURE__ */ React.createElement("h3", null, "Filters"), /* @__PURE__ */ React.createElement("button", { className: "dg-icon-btn", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ React.createElement(X, { size: 18 }))), /* @__PURE__ */ React.createElement("div", { className: "dg-modal-body" }, advancedFilters.map((f, idx) => /* @__PURE__ */ React.createElement("div", { key: idx }, idx > 0 && /* @__PURE__ */ React.createElement("div", { className: "dg-filter-logic" }, /* @__PURE__ */ React.createElement(
358
+ )), columns.filter((c) => c.header.toLowerCase().includes(colSearch.toLowerCase()) && c.hideable !== false).map((col) => /* @__PURE__ */ React.createElement("div", { key: String(col.key), className: "dg-col-row" }, /* @__PURE__ */ React.createElement("div", { className: "dg-col-label" }, /* @__PURE__ */ React.createElement("div", { className: "dg-col-dot", style: { background: col.hidden ? "var(--border-color)" : "var(--primary-color)" } }), col.header), /* @__PURE__ */ React.createElement("button", { className: "dg-icon-btn", onClick: () => toggleHide(String(col.key)) }, col.hidden ? /* @__PURE__ */ React.createElement(EyeOff, { size: 14 }) : /* @__PURE__ */ React.createElement(EyeOff, { size: 14, style: { opacity: 0.4 } }))))), /* @__PURE__ */ React.createElement("div", { className: "dg-modal-footer" }, /* @__PURE__ */ React.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: false }))) }, "Show All"), /* @__PURE__ */ React.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => c.hideable !== false ? { ...c, hidden: true } : c)) }, "Hide All")))), showAdvancedFilter && /* @__PURE__ */ React.createElement("div", { className: "dg-modal-overlay", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ React.createElement("div", { className: "dg-modal dg-modal-wide", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React.createElement("div", { className: "dg-modal-header" }, /* @__PURE__ */ React.createElement("h3", null, "Filters"), /* @__PURE__ */ React.createElement("button", { className: "dg-icon-btn", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ React.createElement(X, { size: 18 }))), /* @__PURE__ */ React.createElement("div", { className: "dg-modal-body" }, advancedFilters.map((f, idx) => /* @__PURE__ */ React.createElement("div", { key: idx }, idx > 0 && /* @__PURE__ */ React.createElement("div", { className: "dg-filter-logic" }, /* @__PURE__ */ React.createElement(
336
359
  "button",
337
360
  {
338
361
  className: `dg-logic-btn${f.logic === "AND" ? " active" : ""}`,
package/dist/main.cjs CHANGED
@@ -29973,53 +29973,55 @@ var BaseDialog_default = BaseDialog;
29973
29973
  var import_react14 = __toESM(require("react"), 1);
29974
29974
  var RufousThemeContext = (0, import_react14.createContext)(null);
29975
29975
  var RufousThemeProvider = ({ children }) => {
29976
- const [colorScheme, setColorScheme] = (0, import_react14.useState)("rufous");
29977
- const [mode, setMode] = (0, import_react14.useState)("light");
29976
+ const [committedThemeKey, setCommittedThemeKey] = (0, import_react14.useState)("default");
29977
+ const [previewThemeKey, setPreviewThemeKey] = (0, import_react14.useState)("default");
29978
+ const [settings, setSettings] = (0, import_react14.useState)(null);
29979
+ const getGeneralSettings = async () => {
29980
+ try {
29981
+ const theme = localStorage.getItem("theme") || "default";
29982
+ setCommittedThemeKey(theme);
29983
+ setPreviewThemeKey(theme);
29984
+ } catch (err) {
29985
+ console.error("Error fetching general settings:", err);
29986
+ }
29987
+ };
29978
29988
  (0, import_react14.useEffect)(() => {
29979
- const savedScheme = localStorage.getItem("colorScheme") || "rufous";
29980
- const savedMode = localStorage.getItem("themeMode") || "light";
29981
- setColorScheme(savedScheme);
29982
- setMode(savedMode);
29989
+ getGeneralSettings();
29983
29990
  }, []);
29984
- const toggleMode = () => {
29985
- const newMode = mode === "light" ? "dark" : "light";
29986
- setMode(newMode);
29987
- localStorage.setItem("themeMode", newMode);
29988
- };
29989
- const changeScheme = (scheme) => {
29990
- setColorScheme(scheme);
29991
- localStorage.setItem("colorScheme", scheme);
29992
- };
29993
- const saveTheme = () => {
29994
- localStorage.setItem("themeMode", mode);
29995
- localStorage.setItem("colorScheme", colorScheme);
29996
- };
29997
- const updateSettings = (settings) => {
29998
- if (settings.theme) setColorScheme(settings.theme);
29999
- if (settings.mode) setMode(settings.mode);
30000
- };
30001
29991
  const fullTheme = (0, import_react14.useMemo)(() => {
30002
29992
  return {
30003
- themeKey: colorScheme,
30004
- customStyles: APP_THEMES[colorScheme][mode]
30005
- };
30006
- }, [colorScheme, mode]);
29993
+ themeKey: previewThemeKey || settings.theme,
29994
+ customStyles: APP_THEMES[previewThemeKey || settings.theme]
29995
+ };
29996
+ }, [previewThemeKey, settings]);
29997
+ const previewTheme = (key) => setPreviewThemeKey(key);
29998
+ const saveTheme = (inputKey) => {
29999
+ const key = inputKey || previewThemeKey || settings.theme;
30000
+ localStorage.setItem("theme", key);
30001
+ setCommittedThemeKey(key);
30002
+ };
30003
+ const cancelTheme = () => setPreviewThemeKey(committedThemeKey);
30007
30004
  return /* @__PURE__ */ import_react14.default.createElement(
30008
30005
  RufousThemeContext.Provider,
30009
30006
  {
30010
30007
  value: {
30011
- colorScheme,
30012
- mode,
30013
- toggleMode,
30014
- changeScheme,
30015
- previewTheme: fullTheme,
30008
+ theme: fullTheme,
30009
+ previewTheme,
30016
30010
  saveTheme,
30017
- updateSettings,
30018
- theme: APP_THEMES[colorScheme][mode],
30019
- themeConfig: APP_THEMES[colorScheme][mode]
30011
+ cancelTheme,
30012
+ currentThemeKey: previewThemeKey,
30013
+ committedThemeKey,
30014
+ settings,
30015
+ updateSettings: (v) => setSettings(v)
30020
30016
  }
30021
30017
  },
30022
- /* @__PURE__ */ import_react14.default.createElement("div", { className: `rufous-theme-root scheme-${colorScheme} mode-${mode}` }, children)
30018
+ /* @__PURE__ */ import_react14.default.createElement(
30019
+ "div",
30020
+ {
30021
+ className: `theme-${previewThemeKey || committedThemeKey || "default"}`
30022
+ },
30023
+ children
30024
+ )
30023
30025
  );
30024
30026
  };
30025
30027
  var useRufousTheme = () => (0, import_react14.useContext)(RufousThemeContext);
@@ -30386,7 +30388,8 @@ function DataGrid({
30386
30388
  const [columnWidths, setColumnWidths] = (0, import_react18.useState)(() => {
30387
30389
  const widths = {};
30388
30390
  initialColumns.forEach((col) => {
30389
- widths[String(col.key)] = parseInt(col.width || "200");
30391
+ const w = col.width || 200;
30392
+ widths[String(col.key)] = typeof w === "number" ? w : parseInt(w);
30390
30393
  });
30391
30394
  return widths;
30392
30395
  });
@@ -30413,8 +30416,8 @@ function DataGrid({
30413
30416
  if (!resizingColumn) return;
30414
30417
  const col = columns.find((c) => String(c.key) === resizingColumn);
30415
30418
  const diff = e.clientX - startX;
30416
- const minW = col?.minWidth ? parseInt(col.minWidth) : 80;
30417
- const maxW = col?.maxWidth ? parseInt(col.maxWidth) : Infinity;
30419
+ const minW = col?.minWidth ? typeof col.minWidth === "number" ? col.minWidth : parseInt(col.minWidth) : 80;
30420
+ const maxW = col?.maxWidth ? typeof col.maxWidth === "number" ? col.maxWidth : parseInt(col.maxWidth) : Infinity;
30418
30421
  const newWidth = Math.min(maxW, Math.max(minW, startWidth + diff));
30419
30422
  setColumnWidths((prev) => ({ ...prev, [resizingColumn]: newWidth }));
30420
30423
  };
@@ -30505,14 +30508,19 @@ function DataGrid({
30505
30508
  }, [data, filterText, advancedFilters]);
30506
30509
  const sortedData = (0, import_react18.useMemo)(() => {
30507
30510
  if (!sortKey || !sortDirection) return filteredData;
30511
+ const col = columns.find((c) => c.key === sortKey);
30508
30512
  return [...filteredData].sort((a, b) => {
30509
- const aVal = a[sortKey];
30510
- const bVal = b[sortKey];
30513
+ let aVal = a[sortKey];
30514
+ let bVal = b[sortKey];
30515
+ if (col?.valueGetter) {
30516
+ aVal = col.valueGetter({ value: aVal, row: a, field: String(sortKey) });
30517
+ bVal = col.valueGetter({ value: bVal, row: b, field: String(sortKey) });
30518
+ }
30511
30519
  if (aVal < bVal) return sortDirection === "asc" ? -1 : 1;
30512
30520
  if (aVal > bVal) return sortDirection === "asc" ? 1 : -1;
30513
30521
  return 0;
30514
30522
  });
30515
- }, [filteredData, sortKey, sortDirection]);
30523
+ }, [filteredData, sortKey, sortDirection, columns]);
30516
30524
  const totalPages = Math.max(1, Math.ceil(sortedData.length / pageSize));
30517
30525
  const paginatedData = (0, import_react18.useMemo)(() => {
30518
30526
  const start = (currentPage - 1) * pageSize;
@@ -30592,8 +30600,8 @@ function DataGrid({
30592
30600
  "th",
30593
30601
  {
30594
30602
  key: colKey,
30595
- className: `dg-thead-cell${col.pinned === "left" ? " pinned-left" : col.pinned === "right" ? " pinned-right" : ""}`,
30596
- style: { width, minWidth: width, left: leftOffset }
30603
+ className: `dg-thead-cell${col.pinned === "left" ? " pinned-left" : col.pinned === "right" ? " pinned-right" : ""} ${col.headerClassName || ""}`,
30604
+ style: { width, minWidth: width, left: leftOffset, flex: col.flex }
30597
30605
  },
30598
30606
  /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-th-inner" }, /* @__PURE__ */ import_react18.default.createElement(
30599
30607
  "div",
@@ -30604,7 +30612,7 @@ function DataGrid({
30604
30612
  col.header,
30605
30613
  isSorted && sortDirection === "asc" && /* @__PURE__ */ import_react18.default.createElement(import_lucide_react.ChevronUp, { size: 12 }),
30606
30614
  isSorted && sortDirection === "desc" && /* @__PURE__ */ import_react18.default.createElement(import_lucide_react.ChevronDown, { size: 12 })
30607
- ), /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-th-actions" }, /* @__PURE__ */ import_react18.default.createElement(
30615
+ ), /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-th-actions" }, !col.disableColumnMenu && /* @__PURE__ */ import_react18.default.createElement(
30608
30616
  "button",
30609
30617
  {
30610
30618
  className: "dg-th-menu-btn",
@@ -30632,22 +30640,39 @@ function DataGrid({
30632
30640
  "td",
30633
30641
  {
30634
30642
  key: `${item.id}-${colKey}`,
30635
- className: `dg-td${col.pinned === "left" ? " pinned-left" : ""}`,
30636
- style: { width, minWidth: width, maxWidth: width, left: leftOffset }
30643
+ className: `dg-td${col.pinned === "left" ? " pinned-left" : ""} ${col.cellClassName || ""}`,
30644
+ style: { width, minWidth: width, maxWidth: width, left: leftOffset, flex: col.flex }
30637
30645
  },
30638
- col.render ? col.render(item[col.key], item) : String(item[col.key] ?? "")
30646
+ (() => {
30647
+ const field = String(col.key);
30648
+ const rawValue = item[col.key];
30649
+ let value = col.valueGetter ? col.valueGetter({ value: rawValue, row: item, field }) : rawValue;
30650
+ const formattedValue = col.valueFormatter ? col.valueFormatter({ value, row: item, field }) : value;
30651
+ if (col.renderCell) {
30652
+ return col.renderCell({ value, row: item, field });
30653
+ }
30654
+ if (col.render) {
30655
+ return col.render(value, item);
30656
+ }
30657
+ return String(formattedValue ?? "");
30658
+ })()
30639
30659
  );
30640
- }), actions && /* @__PURE__ */ import_react18.default.createElement("td", { className: "dg-row-actions-cell" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-row-actions" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-action-group" }, actions.map((action, i) => /* @__PURE__ */ import_react18.default.createElement(
30641
- "button",
30642
- {
30643
- key: i,
30644
- className: "dg-row-action-btn",
30645
- style: { color: action.color || "var(--text-secondary)" },
30646
- onClick: () => action.onClick(item),
30647
- title: action.label
30648
- },
30649
- action.icon
30650
- )))))))))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ import_react18.default.createElement("span", null, "Rows per page:"), /* @__PURE__ */ import_react18.default.createElement(
30660
+ }), actions && /* @__PURE__ */ import_react18.default.createElement("td", { className: "dg-row-actions-cell" }, (() => {
30661
+ const resolvedActions = typeof actions === "function" ? actions(item) : actions;
30662
+ const visibleActions = resolvedActions.filter((a) => !a.show || a.show(item));
30663
+ if (visibleActions.length === 0) return null;
30664
+ return /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-row-actions" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-action-group" }, visibleActions.map((action, i) => /* @__PURE__ */ import_react18.default.createElement(
30665
+ "button",
30666
+ {
30667
+ key: i,
30668
+ className: "dg-row-action-btn",
30669
+ style: { color: action.color || "var(--text-secondary)" },
30670
+ onClick: () => action.onClick(item),
30671
+ title: action.label
30672
+ },
30673
+ action.icon
30674
+ ))));
30675
+ })())))))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-pagination" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-page-info" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-per-page" }, /* @__PURE__ */ import_react18.default.createElement("span", null, "Rows per page:"), /* @__PURE__ */ import_react18.default.createElement(
30651
30676
  "select",
30652
30677
  {
30653
30678
  value: pageSize,
@@ -30688,7 +30713,7 @@ function DataGrid({
30688
30713
  value: colSearch,
30689
30714
  onChange: (e) => setColSearch(e.target.value)
30690
30715
  }
30691
- )), columns.filter((c) => c.header.toLowerCase().includes(colSearch.toLowerCase())).map((col) => /* @__PURE__ */ import_react18.default.createElement("div", { key: String(col.key), className: "dg-col-row" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-col-label" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-col-dot", style: { background: col.hidden ? "var(--border-color)" : "var(--primary-color)" } }), col.header), /* @__PURE__ */ import_react18.default.createElement("button", { className: "dg-icon-btn", onClick: () => toggleHide(String(col.key)) }, col.hidden ? /* @__PURE__ */ import_react18.default.createElement(import_lucide_react.EyeOff, { size: 14 }) : /* @__PURE__ */ import_react18.default.createElement(import_lucide_react.EyeOff, { size: 14, style: { opacity: 0.4 } }))))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-modal-footer" }, /* @__PURE__ */ import_react18.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: false }))) }, "Show All"), /* @__PURE__ */ import_react18.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: true }))) }, "Hide All")))), showAdvancedFilter && /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-modal-overlay", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-modal dg-modal-wide", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-modal-header" }, /* @__PURE__ */ import_react18.default.createElement("h3", null, "Filters"), /* @__PURE__ */ import_react18.default.createElement("button", { className: "dg-icon-btn", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react18.default.createElement(import_lucide_react.X, { size: 18 }))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-modal-body" }, advancedFilters.map((f, idx) => /* @__PURE__ */ import_react18.default.createElement("div", { key: idx }, idx > 0 && /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-filter-logic" }, /* @__PURE__ */ import_react18.default.createElement(
30716
+ )), columns.filter((c) => c.header.toLowerCase().includes(colSearch.toLowerCase()) && c.hideable !== false).map((col) => /* @__PURE__ */ import_react18.default.createElement("div", { key: String(col.key), className: "dg-col-row" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-col-label" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-col-dot", style: { background: col.hidden ? "var(--border-color)" : "var(--primary-color)" } }), col.header), /* @__PURE__ */ import_react18.default.createElement("button", { className: "dg-icon-btn", onClick: () => toggleHide(String(col.key)) }, col.hidden ? /* @__PURE__ */ import_react18.default.createElement(import_lucide_react.EyeOff, { size: 14 }) : /* @__PURE__ */ import_react18.default.createElement(import_lucide_react.EyeOff, { size: 14, style: { opacity: 0.4 } }))))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-modal-footer" }, /* @__PURE__ */ import_react18.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => ({ ...c, hidden: false }))) }, "Show All"), /* @__PURE__ */ import_react18.default.createElement("button", { className: "dg-action-btn", onClick: () => setColumns((p) => p.map((c) => c.hideable !== false ? { ...c, hidden: true } : c)) }, "Hide All")))), showAdvancedFilter && /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-modal-overlay", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-modal dg-modal-wide", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-modal-header" }, /* @__PURE__ */ import_react18.default.createElement("h3", null, "Filters"), /* @__PURE__ */ import_react18.default.createElement("button", { className: "dg-icon-btn", onClick: () => setShowAdvancedFilter(false) }, /* @__PURE__ */ import_react18.default.createElement(import_lucide_react.X, { size: 18 }))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-modal-body" }, advancedFilters.map((f, idx) => /* @__PURE__ */ import_react18.default.createElement("div", { key: idx }, idx > 0 && /* @__PURE__ */ import_react18.default.createElement("div", { className: "dg-filter-logic" }, /* @__PURE__ */ import_react18.default.createElement(
30692
30717
  "button",
30693
30718
  {
30694
30719
  className: `dg-logic-btn${f.logic === "AND" ? " active" : ""}`,
package/dist/main.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BaseDialog_default
3
- } from "./chunk-EZ7WAUAG.js";
3
+ } from "./chunk-4GPYGFPP.js";
4
4
  import "./chunk-E5RTHYCU.js";
5
5
  import {
6
6
  unsubscribeIcon_default
@@ -170,27 +170,24 @@ import {
170
170
  import {
171
171
  closeIcon_default
172
172
  } from "./chunk-Q5XKCUE3.js";
173
+ import "./chunk-GJGRMMAQ.js";
173
174
  import {
174
175
  AddressLookup_default
175
- } from "./chunk-3MC7I6L2.js";
176
+ } from "./chunk-GHCM2AWR.js";
176
177
  import {
177
178
  FloatingInput
178
179
  } from "./chunk-UPCMMCPQ.js";
179
- import {
180
- Checkbox
181
- } from "./chunk-X357WQOT.js";
180
+ import "./chunk-7KRG7VNW.js";
182
181
  import {
183
182
  RufousThemeProvider,
184
183
  useRufousTheme
185
- } from "./chunk-NNKORPBI.js";
184
+ } from "./chunk-BOE27BFQ.js";
186
185
  import {
187
186
  APP_THEMES
188
187
  } from "./chunk-S7BNFVQO.js";
189
- import "./chunk-7KRG7VNW.js";
190
188
  import {
191
- DataGrid
192
- } from "./chunk-J6E3UO2W.js";
193
- import "./chunk-GJGRMMAQ.js";
189
+ Checkbox
190
+ } from "./chunk-X357WQOT.js";
194
191
  import {
195
192
  RichTextEditor
196
193
  } from "./chunk-66HHM7VI.js";
@@ -210,6 +207,9 @@ import {
210
207
  import {
211
208
  circularProgress_default
212
209
  } from "./chunk-CTBYVXFP.js";
210
+ import {
211
+ DataGrid
212
+ } from "./chunk-IKG2B6JQ.js";
213
213
  import "./chunk-LI4N7JWK.js";
214
214
  export {
215
215
  APP_THEMES,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rufous/ui",
3
3
  "private": false,
4
- "version": "0.1.65",
4
+ "version": "0.1.67",
5
5
  "type": "module",
6
6
  "description": "Experimental: A lightweight React UI component library (Beta)",
7
7
  "style": "./dist/style.css",
@@ -67,4 +67,4 @@
67
67
  "react": "^18.0.0 || ^19.0.0",
68
68
  "react-dom": "^18.0.0 || ^19.0.0"
69
69
  }
70
- }
70
+ }
@@ -1,69 +0,0 @@
1
- import {
2
- APP_THEMES
3
- } from "./chunk-S7BNFVQO.js";
4
-
5
- // lib/Contexts/rufousThemeProvider.tsx
6
- import React, {
7
- createContext,
8
- useContext,
9
- useEffect,
10
- useMemo,
11
- useState
12
- } from "react";
13
- var RufousThemeContext = createContext(null);
14
- var RufousThemeProvider = ({ children }) => {
15
- const [colorScheme, setColorScheme] = useState("rufous");
16
- const [mode, setMode] = useState("light");
17
- useEffect(() => {
18
- const savedScheme = localStorage.getItem("colorScheme") || "rufous";
19
- const savedMode = localStorage.getItem("themeMode") || "light";
20
- setColorScheme(savedScheme);
21
- setMode(savedMode);
22
- }, []);
23
- const toggleMode = () => {
24
- const newMode = mode === "light" ? "dark" : "light";
25
- setMode(newMode);
26
- localStorage.setItem("themeMode", newMode);
27
- };
28
- const changeScheme = (scheme) => {
29
- setColorScheme(scheme);
30
- localStorage.setItem("colorScheme", scheme);
31
- };
32
- const saveTheme = () => {
33
- localStorage.setItem("themeMode", mode);
34
- localStorage.setItem("colorScheme", colorScheme);
35
- };
36
- const updateSettings = (settings) => {
37
- if (settings.theme) setColorScheme(settings.theme);
38
- if (settings.mode) setMode(settings.mode);
39
- };
40
- const fullTheme = useMemo(() => {
41
- return {
42
- themeKey: colorScheme,
43
- customStyles: APP_THEMES[colorScheme][mode]
44
- };
45
- }, [colorScheme, mode]);
46
- return /* @__PURE__ */ React.createElement(
47
- RufousThemeContext.Provider,
48
- {
49
- value: {
50
- colorScheme,
51
- mode,
52
- toggleMode,
53
- changeScheme,
54
- previewTheme: fullTheme,
55
- saveTheme,
56
- updateSettings,
57
- theme: APP_THEMES[colorScheme][mode],
58
- themeConfig: APP_THEMES[colorScheme][mode]
59
- }
60
- },
61
- /* @__PURE__ */ React.createElement("div", { className: `rufous-theme-root scheme-${colorScheme} mode-${mode}` }, children)
62
- );
63
- };
64
- var useRufousTheme = () => useContext(RufousThemeContext);
65
-
66
- export {
67
- RufousThemeProvider,
68
- useRufousTheme
69
- };