@warkypublic/svelix 0.1.43 → 0.1.44

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.
@@ -1137,6 +1137,7 @@
1137
1137
  style:--gridler-bg-header-focus={mergedTheme.bgHeaderHasFocus}
1138
1138
  style:--gridler-bg-search-result={mergedTheme.bgSearchResult}
1139
1139
  style:--gridler-header-height={`${headerHeight}px`}
1140
+ style:--gridler-row-marker-width={`${rowMarkerWidth}px`}
1140
1141
  onfocusin={handleFocusIn}
1141
1142
  onfocusout={handleFocusOut}
1142
1143
  onmouseenter={onGridEnter}
@@ -970,7 +970,10 @@
970
970
  .gf-loading,
971
971
  .gf-error {
972
972
  position: absolute;
973
- inset: 0;
973
+ top: var(--gridler-header-height, 36px);
974
+ left: var(--gridler-row-marker-width, 0px);
975
+ right: 0;
976
+ bottom: 0;
974
977
  display: flex;
975
978
  align-items: center;
976
979
  justify-content: center;
@@ -9,11 +9,11 @@
9
9
 
10
10
  const { value, onValueChange, onClose }: Props = $props();
11
11
 
12
- let inputRef: HTMLInputElement | undefined = $state();
12
+ let inputRef: HTMLInputElement | undefined;
13
13
 
14
- $effect(() => {
14
+ export function focus() {
15
15
  inputRef?.focus();
16
- });
16
+ }
17
17
  </script>
18
18
 
19
19
  <div class="gridler-search" role="search">
@@ -3,6 +3,8 @@ interface Props {
3
3
  onValueChange: (v: string) => void;
4
4
  onClose?: () => void;
5
5
  }
6
- declare const GridlerSearch: import("svelte").Component<Props, {}, "">;
6
+ declare const GridlerSearch: import("svelte").Component<Props, {
7
+ focus: () => void;
8
+ }, "">;
7
9
  type GridlerSearch = ReturnType<typeof GridlerSearch>;
8
10
  export default GridlerSearch;
@@ -11,6 +11,12 @@
11
11
  }
12
12
 
13
13
  const { show, value, onToggle, onValueChange, onClose }: Props = $props();
14
+
15
+ let search: GridlerSearch | undefined = $state();
16
+
17
+ $effect(() => {
18
+ if (show) search?.focus();
19
+ });
14
20
  </script>
15
21
 
16
22
  <button
@@ -25,6 +31,7 @@
25
31
 
26
32
  {#if show}
27
33
  <GridlerSearch
34
+ bind:this={search}
28
35
  {value}
29
36
  {onValueChange}
30
37
  {onClose}
@@ -1,4 +1,4 @@
1
- import type { GridColumn, GridCommonProps, GridColumnSortOrder, GridColumnFilters } from '../Types/generic_grid';
1
+ import type { GridColumn, GridCommonProps, GridColumnSortOrder, GridColumnFilters, GridContextMenuItem } from '../Types/generic_grid';
2
2
  import type { Options } from '@warkypublic/resolvespec-js';
3
3
  export type { GridColumnSortOrder, GridColumnFilters };
4
4
  export type Item = [col: number, row: number];
@@ -60,8 +60,6 @@ export interface GridlerColumn extends GridColumn<Record<string, unknown>> {
60
60
  width: number;
61
61
  /** Per-column theme overrides applied during canvas rendering. */
62
62
  themeOverride?: Partial<GridlerTheme>;
63
- /** Show a context-menu trigger button on this column's header. */
64
- hasMenu?: boolean;
65
63
  }
66
64
  export interface GridlerCellFormatOptions {
67
65
  /** Currency code for 'currency' cells (default: 'ZAR'). */
@@ -166,14 +164,6 @@ export interface GridlerProps extends GridCommonProps<Record<string, unknown>> {
166
164
  /** Show the built-in search bar. Also settable via settings.showSearch. */
167
165
  showSearch?: boolean;
168
166
  }
169
- export interface GridlerContextMenuItem {
170
- id: string;
171
- label: string;
172
- disabled?: boolean;
173
- icon?: string;
174
- /** Use 'separator' to render a divider line. */
175
- kind?: 'item' | 'separator';
176
- onselect?: (rowData?: Record<string, unknown>) => void;
177
- }
167
+ export type GridlerContextMenuItem = GridContextMenuItem<Record<string, unknown>>;
178
168
  export declare const DEFAULT_THEME: GridlerTheme;
179
169
  export declare const DEFAULT_THEME_DARK: GridlerTheme;
@@ -1,8 +1,9 @@
1
+ import { getNestedValue } from "@warkypublic/artemis-kit/object";
1
2
  export function rowToCell(row, key) {
2
3
  if (row === undefined) {
3
4
  return { kind: "text", data: null, displayData: "", allowOverlay: false, allowEditing: false };
4
5
  }
5
- const raw = key ? row[key] : undefined;
6
+ const raw = key ? getNestedValue(key, row) : undefined;
6
7
  const display = raw == null ? "" : String(raw);
7
8
  if (typeof raw === "number") {
8
9
  return { kind: "number", data: raw, displayData: display, allowOverlay: true, allowEditing: true };
@@ -1,3 +1,4 @@
1
+ import { getNestedValue } from "@warkypublic/artemis-kit/object";
1
2
  export function gridColumnFiltersToFilterOptions(f) {
2
3
  return Object.entries(f).map(([id, filter]) => ({
3
4
  column: filter.dataKey ?? id,
@@ -15,8 +16,7 @@ export function applyLocalFilter(data, filters, columns) {
15
16
  for (const [colId, filter] of entries) {
16
17
  const colDef = columns.find((c) => c.id === colId);
17
18
  const key = colDef?.dataKey ?? colId;
18
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
- const rawVal = row[key];
19
+ const rawVal = getNestedValue(key, row);
20
20
  const cellStr = rawVal == null ? "" : String(rawVal).toLowerCase();
21
21
  const filterVal = filter.value?.toLowerCase() ?? "";
22
22
  const op = filter.op ?? "contains";
@@ -1,3 +1,4 @@
1
+ import { getNestedValue } from "@warkypublic/artemis-kit/object";
1
2
  export function compareValues(a, b) {
2
3
  if (a == null && b == null)
3
4
  return 0;
@@ -27,7 +28,7 @@ export function applyLocalSort(data, sortOptions, columns) {
27
28
  for (const { column, direction } of sortOptions) {
28
29
  const colDef = columns.find((c) => c.id === column);
29
30
  const key = colDef?.dataKey ?? column;
30
- const cmp = compareValues(a[key], b[key]);
31
+ const cmp = compareValues(getNestedValue(key, a), getNestedValue(key, b));
31
32
  if (cmp !== 0)
32
33
  return direction === "asc" ? cmp : -cmp;
33
34
  }
@@ -25,6 +25,8 @@ export interface GridColumn<RowDataType = unknown, CellType = unknown> {
25
25
  disableSearch?: boolean | ((item: RowDataType) => boolean);
26
26
  span?: [startRow: number, endRow: number];
27
27
  renderCell?: (item: RowDataType) => CellType;
28
+ /** Show a context-menu trigger button on this column's header. */
29
+ hasMenu?: boolean;
28
30
  }
29
31
  export interface GridColumnSortOrder {
30
32
  [id: string]: "asc" | "desc" | "none";
@@ -44,34 +46,74 @@ export interface GridEventCoords {
44
46
  code?: string;
45
47
  }
46
48
  export type GridEventDetail = Record<string, unknown>;
49
+ /** Generic context-menu item. Implementations (e.g. GridlerContextMenuItem) extend this. */
50
+ export interface GridContextMenuItem<RowDataType = unknown> {
51
+ id: string;
52
+ label: string;
53
+ disabled?: boolean;
54
+ icon?: string;
55
+ /** Use 'separator' to render a divider line. */
56
+ kind?: 'item' | 'separator';
57
+ onselect?: (rowData?: RowDataType) => void;
58
+ }
47
59
  export interface GridCommonProps<RowDataType = unknown, CellType = unknown> {
48
60
  columns: Array<GridColumn<RowDataType, CellType>>;
49
61
  width?: string | number;
50
62
  height?: string | number;
51
63
  rowHeight?: number;
52
64
  headerHeight?: number;
53
- onCellEvent?: (type: GridCellEventType, item: RowDataType, column: GridColumn<RowDataType, CellType>, coords?: GridEventCoords, // For keyboard/mouse events, code represents the key code of the pressed key
54
- detail?: GridEventDetail) => void;
55
- onGridEvent?: (type: GridEventType, item?: RowDataType, column?: GridColumn<RowDataType, CellType>, coords?: GridEventCoords, // For keyboard/mouse events, code represents the key code of the pressed key
56
- detail?: GridEventDetail) => void;
65
+ /** Number of columns pinned to the left. */
66
+ fixedColumns?: number;
67
+ /** When true, the grid manages column reordering internally on drag. */
68
+ manageColumns?: boolean;
69
+ /** Called when the internal column order changes (only fires when manageColumns is true). */
70
+ onColumnsChange?: (columns: GridColumn<RowDataType, CellType>[]) => void;
71
+ onCellEvent?: (type: GridCellEventType, item: RowDataType, column: GridColumn<RowDataType, CellType>, coords?: GridEventCoords, detail?: GridEventDetail) => void;
72
+ onGridEvent?: (type: GridEventType, item?: RowDataType, column?: GridColumn<RowDataType, CellType>, coords?: GridEventCoords, detail?: GridEventDetail) => void;
57
73
  onMenuClick?: (item?: RowDataType, column?: GridColumn<RowDataType, CellType>, coords?: GridEventCoords) => Promise<void>;
74
+ /** Called when a body row is clicked. */
75
+ onRowClick?: (row: number, rowData?: RowDataType) => void;
76
+ /** Called when a body row is double-clicked. */
77
+ onRowDblClick?: (row: number, rowData?: RowDataType) => void;
78
+ /** Called when a body row receives a context-menu event. */
79
+ onRowContextMenu?: (row: number, rowData?: RowDataType, x?: number, y?: number) => void;
80
+ /** Called when a cell is double-clicked. */
81
+ onCellDblClick?: (row: number, column: GridColumn<RowDataType, CellType>, rowData?: RowDataType) => void;
58
82
  onColumnMoved?: (startIndex: number, endIndex: number) => void;
59
83
  onSortOrderChange?: (sortOrder: GridColumnSortOrder) => void;
60
84
  sortOrder?: GridColumnSortOrder;
61
85
  onFilterChange?: (filters: GridColumnFilters) => void;
62
86
  filters?: GridColumnFilters;
63
- onSearchValueChange?: (value: string) => void;
64
87
  searchValue?: string;
88
+ /** Uncontrolled initial search value (only used when searchValue is undefined). */
89
+ defaultSearchValue?: string;
90
+ onSearchValueChange?: (value: string) => void;
91
+ /**
92
+ * When true, the search input value is translated into server-side filters
93
+ * instead of only being used for client-side highlighting.
94
+ */
95
+ serverSideSearch?: boolean;
96
+ /** Columns searched when serverSideSearch is true. Defaults to all columns. */
97
+ searchColumns?: string[];
65
98
  selectedItems?: RowDataType[];
66
99
  onSelectedItemsChange?: (items: RowDataType[]) => void;
100
+ /** Extra items appended to the built-in context menu. */
101
+ menuItems?: GridContextMenuItem<RowDataType>[];
102
+ /** Called when any context menu item is selected (built-in or custom). */
103
+ onMenuItemSelect?: (item: GridContextMenuItem<RowDataType>, rowData?: RowDataType) => void;
67
104
  dataSource?: "local" | "resolvespec" | "headerspec" | "websockspec" | "custom";
68
105
  dataSourceOptions?: {
69
106
  url?: string;
70
107
  authToken?: string;
71
108
  schema?: string;
72
109
  entity?: string;
110
+ /**
111
+ * Row field whose value is used as the cursor for subsequent page requests.
112
+ * Defaults to 'id'. Can also be set via the top-level uniqueID shorthand.
113
+ */
73
114
  uniqueID?: string;
74
115
  headers?: Record<string, string>;
116
+ /** Fields to fetch in addition to column fields (for filters, sort, relations). */
75
117
  hotfields?: string[];
76
118
  /**
77
119
  * Default ResolveSpec options sent with every request. Grid-controlled sort, filters, limit,
@@ -93,6 +135,32 @@ export interface GridCommonProps<RowDataType = unknown, CellType = unknown> {
93
135
  };
94
136
  data?: RowDataType[] | (() => Promise<RowDataType[]>);
95
137
  onDataChange?: (data: RowDataType[]) => Promise<void>;
138
+ /** Rows per cursor-forward page. Defaults to 200. */
139
+ pageSize?: number;
140
+ /**
141
+ * Shorthand for dataSourceOptions.uniqueID.
142
+ * Row field whose value is passed as cursor_forward on subsequent requests.
143
+ */
144
+ uniqueID?: string;
145
+ /** Called when a server fetch fails. */
146
+ onLoadError?: (error: string) => void;
147
+ /**
148
+ * Bindable. Reflects the server-reported total row count.
149
+ * Updated after every successful page fetch; 0 until the first response.
150
+ */
151
+ total?: number;
152
+ /**
153
+ * Bindable. true while any server fetch is in flight.
154
+ */
155
+ loading?: boolean;
156
+ /** When true, all cells are read-only. Also settable via settings.readonly. */
157
+ readonly?: boolean;
158
+ /** Allow users to drag column edges to resize. Also settable via settings.resizableColumns. */
159
+ resizableColumns?: boolean;
160
+ /** Show the built-in search bar. Also settable via settings.showSearch. */
161
+ showSearch?: boolean;
162
+ /** Row-marker style shown in the leading column. Also settable via settings.rowMarkerType. */
163
+ rowMarkers?: "checkbox" | "number" | "none";
96
164
  settings?: {
97
165
  hideHeader?: boolean;
98
166
  showRowMarkers?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warkypublic/svelix",
3
- "version": "0.1.43",
3
+ "version": "0.1.44",
4
4
  "description": "Svelte 5 component library with Skeleton UI and Tailwind CSS",
5
5
  "license": "Apache-2.0",
6
6
  "exports": {