@rufous/ui 0.2.90 → 0.2.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.cjs CHANGED
@@ -1925,6 +1925,15 @@ function defaultGetLabel(option) {
1925
1925
  return String(option.label);
1926
1926
  return String(option);
1927
1927
  }
1928
+ function defaultIsEqual(a, b) {
1929
+ if (a === b) return true;
1930
+ if (a !== null && b !== null && typeof a === "object" && typeof b === "object") {
1931
+ const aVal = a.value;
1932
+ const bVal = b.value;
1933
+ if (aVal !== void 0 && bVal !== void 0) return aVal === bVal;
1934
+ }
1935
+ return false;
1936
+ }
1928
1937
  function defaultFilter(options, inputValue, getLabel) {
1929
1938
  if (!inputValue) return options;
1930
1939
  const q = inputValue.toLowerCase();
@@ -2007,7 +2016,7 @@ function AutocompleteInner(props, _ref) {
2007
2016
  const activeInput = controlledInput !== void 0 ? controlledInput : inputStr;
2008
2017
  const selectedValues = multiple ? Array.isArray(value) ? value : [] : value != null ? [value] : [];
2009
2018
  const isEqual = (0, import_react18.useCallback)(
2010
- (a, b) => isOptionEqualToValue ? isOptionEqualToValue(a, b) : a === b,
2019
+ (a, b) => isOptionEqualToValue ? isOptionEqualToValue(a, b) : defaultIsEqual(a, b),
2011
2020
  [isOptionEqualToValue]
2012
2021
  );
2013
2022
  const isSelected = (0, import_react18.useCallback)(
@@ -4305,7 +4314,9 @@ function DataGrid({
4305
4314
  className,
4306
4315
  sx,
4307
4316
  onRowDoubleClick,
4308
- onCellDoubleClick
4317
+ onCellDoubleClick,
4318
+ headerActions,
4319
+ toolbarContent
4309
4320
  }) {
4310
4321
  const sxClass = useSx(sx);
4311
4322
  const [editingCell, setEditingCell] = (0, import_react23.useState)(null);
@@ -4626,6 +4637,7 @@ function DataGrid({
4626
4637
  };
4627
4638
  const hasActiveFilters = advancedFilters.some((f) => f.value);
4628
4639
  const activeMenuCol = activeMenu ? resolvedColumns.find((c) => String(c.field) === activeMenu) : null;
4640
+ const alignClass = (align) => align === "center" ? "dg-slot--center" : align === "right" ? "dg-slot--right" : "dg-slot--left";
4629
4641
  return /* @__PURE__ */ import_react23.default.createElement("div", { className: ["dg-root", sxClass, className].filter(Boolean).join(" ") }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-header" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-header-info" }, /* @__PURE__ */ import_react23.default.createElement("h2", null, title), /* @__PURE__ */ import_react23.default.createElement("p", null, filteredData.length, " total records")), /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-header-actions" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "dg-search-wrap" }, /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.Search, { size: 15 }), /* @__PURE__ */ import_react23.default.createElement(
4630
4642
  "input",
4631
4643
  {
@@ -4651,7 +4663,7 @@ function DataGrid({
4651
4663
  onClick: () => setShowManageColumns(true)
4652
4664
  },
4653
4665
  /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.Columns, { size: 16 })
4654
- )), /* @__PURE__ */ import_react23.default.createElement("button", { className: "dg-action-btn", onClick: handleExport }, /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.Download, { size: 14 }), " Export CSV"))), /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-table-wrap${paginatedData.length === 0 ? " dg-table-wrap--empty" : ""}` }, /* @__PURE__ */ import_react23.default.createElement("table", { className: "dg-table" }, /* @__PURE__ */ import_react23.default.createElement("thead", null, /* @__PURE__ */ import_react23.default.createElement("tr", null, visibleColumns.map((col, idx) => {
4666
+ )), /* @__PURE__ */ import_react23.default.createElement("button", { className: "dg-action-btn", onClick: handleExport }, /* @__PURE__ */ import_react23.default.createElement(import_lucide_react2.Download, { size: 14 }), " Export CSV"), headerActions && /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-header-slot ${alignClass(headerActions.align)}` }, headerActions.content))), /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-toolbar ${alignClass(toolbarContent?.align)}` }, toolbarContent?.content || ""), /* @__PURE__ */ import_react23.default.createElement("div", { className: `dg-table-wrap${paginatedData.length === 0 ? " dg-table-wrap--empty" : ""}` }, /* @__PURE__ */ import_react23.default.createElement("table", { className: "dg-table" }, /* @__PURE__ */ import_react23.default.createElement("thead", null, /* @__PURE__ */ import_react23.default.createElement("tr", null, visibleColumns.map((col, idx) => {
4655
4667
  const colField = String(col.field);
4656
4668
  const width = columnWidths[colField] || 200;
4657
4669
  const leftOffset = getLeftOffset(col, idx);
package/dist/main.css CHANGED
@@ -326,8 +326,7 @@
326
326
  color: var(--text-color);
327
327
  }
328
328
  .dg-header {
329
- padding: 20px 24px;
330
- border-bottom: 1px solid var(--border-color);
329
+ padding: 20px 24px 0 24px;
331
330
  display: flex;
332
331
  align-items: center;
333
332
  justify-content: space-between;
@@ -351,6 +350,32 @@
351
350
  gap: 10px;
352
351
  flex-wrap: wrap;
353
352
  }
353
+ .dg-header-slot {
354
+ display: flex;
355
+ align-items: center;
356
+ gap: 8px;
357
+ }
358
+ .dg-toolbar {
359
+ padding: 10px 24px;
360
+ display: flex;
361
+ align-items: center;
362
+ gap: 10px;
363
+ flex-wrap: wrap;
364
+ }
365
+ .dg-slot--left,
366
+ .dg-toolbar.dg-slot--left {
367
+ justify-content: flex-start;
368
+ }
369
+ .dg-slot--center,
370
+ .dg-toolbar.dg-slot--center {
371
+ justify-content: center;
372
+ flex: 1;
373
+ }
374
+ .dg-slot--right,
375
+ .dg-toolbar.dg-slot--right {
376
+ justify-content: flex-end;
377
+ margin-left: auto;
378
+ }
354
379
  .dg-search-wrap {
355
380
  position: relative;
356
381
  }
@@ -413,6 +438,8 @@
413
438
  background: var(--hover-color);
414
439
  }
415
440
  .dg-table-wrap {
441
+ border-top: 2px solid var(--border-color);
442
+ border-bottom: 1px solid var(--border-color);
416
443
  overflow-x: auto;
417
444
  flex: 1;
418
445
  }
package/dist/main.d.cts CHANGED
@@ -819,6 +819,10 @@ interface Action<T> {
819
819
  color?: string;
820
820
  show?: (item: T) => boolean;
821
821
  }
822
+ interface DataGridToolbarSlot {
823
+ content: React__default.ReactNode;
824
+ align?: 'left' | 'center' | 'right';
825
+ }
822
826
  interface DataGridProps<T> {
823
827
  columns: Column<T>[];
824
828
  data: T[];
@@ -834,11 +838,15 @@ interface DataGridProps<T> {
834
838
  field: string;
835
839
  value: any;
836
840
  }) => void;
841
+ /** Extra buttons/components rendered beside the Export button in the header row */
842
+ headerActions?: DataGridToolbarSlot;
843
+ /** Extra content rendered in a second row below the header */
844
+ toolbarContent?: DataGridToolbarSlot;
837
845
  }
838
846
 
839
847
  declare function DataGrid<T extends {
840
848
  id: string | number;
841
- }>({ columns: initialColumnsProp, data, actions, pageSize: initialPageSize, pageSizeOptions, title, className, sx, onRowDoubleClick, onCellDoubleClick, }: DataGridProps<T>): React__default.JSX.Element;
849
+ }>({ columns: initialColumnsProp, data, actions, pageSize: initialPageSize, pageSizeOptions, title, className, sx, onRowDoubleClick, onCellDoubleClick, headerActions, toolbarContent, }: DataGridProps<T>): React__default.JSX.Element;
842
850
 
843
851
  type SelectOption = {
844
852
  value: string | number;
package/dist/main.d.ts CHANGED
@@ -819,6 +819,10 @@ interface Action<T> {
819
819
  color?: string;
820
820
  show?: (item: T) => boolean;
821
821
  }
822
+ interface DataGridToolbarSlot {
823
+ content: React__default.ReactNode;
824
+ align?: 'left' | 'center' | 'right';
825
+ }
822
826
  interface DataGridProps<T> {
823
827
  columns: Column<T>[];
824
828
  data: T[];
@@ -834,11 +838,15 @@ interface DataGridProps<T> {
834
838
  field: string;
835
839
  value: any;
836
840
  }) => void;
841
+ /** Extra buttons/components rendered beside the Export button in the header row */
842
+ headerActions?: DataGridToolbarSlot;
843
+ /** Extra content rendered in a second row below the header */
844
+ toolbarContent?: DataGridToolbarSlot;
837
845
  }
838
846
 
839
847
  declare function DataGrid<T extends {
840
848
  id: string | number;
841
- }>({ columns: initialColumnsProp, data, actions, pageSize: initialPageSize, pageSizeOptions, title, className, sx, onRowDoubleClick, onCellDoubleClick, }: DataGridProps<T>): React__default.JSX.Element;
849
+ }>({ columns: initialColumnsProp, data, actions, pageSize: initialPageSize, pageSizeOptions, title, className, sx, onRowDoubleClick, onCellDoubleClick, headerActions, toolbarContent, }: DataGridProps<T>): React__default.JSX.Element;
842
850
 
843
851
  type SelectOption = {
844
852
  value: string | number;
package/dist/main.js CHANGED
@@ -1764,6 +1764,15 @@ function defaultGetLabel(option) {
1764
1764
  return String(option.label);
1765
1765
  return String(option);
1766
1766
  }
1767
+ function defaultIsEqual(a, b) {
1768
+ if (a === b) return true;
1769
+ if (a !== null && b !== null && typeof a === "object" && typeof b === "object") {
1770
+ const aVal = a.value;
1771
+ const bVal = b.value;
1772
+ if (aVal !== void 0 && bVal !== void 0) return aVal === bVal;
1773
+ }
1774
+ return false;
1775
+ }
1767
1776
  function defaultFilter(options, inputValue, getLabel) {
1768
1777
  if (!inputValue) return options;
1769
1778
  const q = inputValue.toLowerCase();
@@ -1846,7 +1855,7 @@ function AutocompleteInner(props, _ref) {
1846
1855
  const activeInput = controlledInput !== void 0 ? controlledInput : inputStr;
1847
1856
  const selectedValues = multiple ? Array.isArray(value) ? value : [] : value != null ? [value] : [];
1848
1857
  const isEqual = useCallback(
1849
- (a, b) => isOptionEqualToValue ? isOptionEqualToValue(a, b) : a === b,
1858
+ (a, b) => isOptionEqualToValue ? isOptionEqualToValue(a, b) : defaultIsEqual(a, b),
1850
1859
  [isOptionEqualToValue]
1851
1860
  );
1852
1861
  const isSelected = useCallback(
@@ -4175,7 +4184,9 @@ function DataGrid({
4175
4184
  className,
4176
4185
  sx,
4177
4186
  onRowDoubleClick,
4178
- onCellDoubleClick
4187
+ onCellDoubleClick,
4188
+ headerActions,
4189
+ toolbarContent
4179
4190
  }) {
4180
4191
  const sxClass = useSx(sx);
4181
4192
  const [editingCell, setEditingCell] = useState9(null);
@@ -4496,6 +4507,7 @@ function DataGrid({
4496
4507
  };
4497
4508
  const hasActiveFilters = advancedFilters.some((f) => f.value);
4498
4509
  const activeMenuCol = activeMenu ? resolvedColumns.find((c) => String(c.field) === activeMenu) : null;
4510
+ const alignClass = (align) => align === "center" ? "dg-slot--center" : align === "right" ? "dg-slot--right" : "dg-slot--left";
4499
4511
  return /* @__PURE__ */ React75.createElement("div", { className: ["dg-root", sxClass, className].filter(Boolean).join(" ") }, /* @__PURE__ */ React75.createElement("div", { className: "dg-header" }, /* @__PURE__ */ React75.createElement("div", { className: "dg-header-info" }, /* @__PURE__ */ React75.createElement("h2", null, title), /* @__PURE__ */ React75.createElement("p", null, filteredData.length, " total records")), /* @__PURE__ */ React75.createElement("div", { className: "dg-header-actions" }, /* @__PURE__ */ React75.createElement("div", { className: "dg-search-wrap" }, /* @__PURE__ */ React75.createElement(Search, { size: 15 }), /* @__PURE__ */ React75.createElement(
4500
4512
  "input",
4501
4513
  {
@@ -4521,7 +4533,7 @@ function DataGrid({
4521
4533
  onClick: () => setShowManageColumns(true)
4522
4534
  },
4523
4535
  /* @__PURE__ */ React75.createElement(Columns, { size: 16 })
4524
- )), /* @__PURE__ */ React75.createElement("button", { className: "dg-action-btn", onClick: handleExport }, /* @__PURE__ */ React75.createElement(Download, { size: 14 }), " Export CSV"))), /* @__PURE__ */ React75.createElement("div", { className: `dg-table-wrap${paginatedData.length === 0 ? " dg-table-wrap--empty" : ""}` }, /* @__PURE__ */ React75.createElement("table", { className: "dg-table" }, /* @__PURE__ */ React75.createElement("thead", null, /* @__PURE__ */ React75.createElement("tr", null, visibleColumns.map((col, idx) => {
4536
+ )), /* @__PURE__ */ React75.createElement("button", { className: "dg-action-btn", onClick: handleExport }, /* @__PURE__ */ React75.createElement(Download, { size: 14 }), " Export CSV"), headerActions && /* @__PURE__ */ React75.createElement("div", { className: `dg-header-slot ${alignClass(headerActions.align)}` }, headerActions.content))), /* @__PURE__ */ React75.createElement("div", { className: `dg-toolbar ${alignClass(toolbarContent?.align)}` }, toolbarContent?.content || ""), /* @__PURE__ */ React75.createElement("div", { className: `dg-table-wrap${paginatedData.length === 0 ? " dg-table-wrap--empty" : ""}` }, /* @__PURE__ */ React75.createElement("table", { className: "dg-table" }, /* @__PURE__ */ React75.createElement("thead", null, /* @__PURE__ */ React75.createElement("tr", null, visibleColumns.map((col, idx) => {
4525
4537
  const colField = String(col.field);
4526
4538
  const width = columnWidths[colField] || 200;
4527
4539
  const leftOffset = getLeftOffset(col, idx);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rufous/ui",
3
3
  "private": false,
4
- "version": "0.2.90",
4
+ "version": "0.2.92",
5
5
  "type": "module",
6
6
  "description": "Experimental: A lightweight React UI component library (Beta)",
7
7
  "style": "./dist/main.css",