@ornery/ui-grid-react 0.1.6 → 0.1.7-hotfix-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import type { GridColumnDef } from '@ornery/ui-grid';
2
+ import type { GridColumnDef } from '@ornery/ui-grid-core';
3
3
  import {
4
4
  buildGridTemplateColumns,
5
5
  computeViewportHeightPx,
@@ -18,15 +18,17 @@ describe('gridStateMath', () => {
18
18
  ];
19
19
 
20
20
  it('orders only visible columns by the provided column order', () => {
21
- expect(orderVisibleColumns(columns, ['customer', 'revenue', 'status', 'owner']).map((column) => column.name)).toEqual([
22
- 'customer',
23
- 'revenue',
24
- 'status',
25
- ]);
21
+ expect(
22
+ orderVisibleColumns(columns, ['customer', 'revenue', 'status', 'owner']).map(
23
+ (column) => column.name,
24
+ ),
25
+ ).toEqual(['customer', 'revenue', 'status']);
26
26
  });
27
27
 
28
28
  it('builds grid template columns deterministically', () => {
29
- expect(buildGridTemplateColumns(orderVisibleColumns(columns, ['status', 'revenue', 'customer']))).toBe('2fr 120px minmax(11rem, max-content)');
29
+ expect(
30
+ buildGridTemplateColumns(orderVisibleColumns(columns, ['status', 'revenue', 'customer'])),
31
+ ).toBe('2fr 120px minmax(11rem, max-content)');
30
32
  });
31
33
 
32
34
  it('resolves benchmark iterations with a minimum of one', () => {
@@ -46,4 +48,4 @@ describe('gridStateMath', () => {
46
48
  expect(computeViewportRows(undefined, undefined)).toBe(13);
47
49
  expect(computeViewportRows(220, 44)).toBe(5);
48
50
  });
49
- });
51
+ });
@@ -1,7 +1,10 @@
1
- import type { GridColumnDef } from '@ornery/ui-grid';
2
- import { gridColumnWidth } from '@ornery/ui-grid';
1
+ import type { GridColumnDef } from '@ornery/ui-grid-core';
2
+ import { gridColumnWidth } from '@ornery/ui-grid-core';
3
3
 
4
- export function orderVisibleColumns(columns: readonly GridColumnDef[], order: readonly string[]): GridColumnDef[] {
4
+ export function orderVisibleColumns(
5
+ columns: readonly GridColumnDef[],
6
+ order: readonly string[],
7
+ ): GridColumnDef[] {
5
8
  return [...columns]
6
9
  .filter((column) => column.visible !== false)
7
10
  .sort((left, right) => order.indexOf(left.name) - order.indexOf(right.name));
@@ -11,11 +14,18 @@ export function buildGridTemplateColumns(columns: readonly GridColumnDef[]): str
11
14
  return columns.map((column) => gridColumnWidth(column)).join(' ');
12
15
  }
13
16
 
14
- export function resolveBenchmarkIterations(iterations?: number, configuredIterations?: number): number {
17
+ export function resolveBenchmarkIterations(
18
+ iterations?: number,
19
+ configuredIterations?: number,
20
+ ): number {
15
21
  return Math.max(1, iterations ?? configuredIterations ?? 25);
16
22
  }
17
23
 
18
- export function formatPaginationSummary(totalItems: number, firstRowIndex: number, lastRowIndex: number): string {
24
+ export function formatPaginationSummary(
25
+ totalItems: number,
26
+ firstRowIndex: number,
27
+ lastRowIndex: number,
28
+ ): string {
19
29
  if (totalItems === 0) {
20
30
  return '0-0 of 0';
21
31
  }
@@ -23,10 +33,13 @@ export function formatPaginationSummary(totalItems: number, firstRowIndex: numbe
23
33
  return `${firstRowIndex + 1}-${lastRowIndex + 1} of ${totalItems}`;
24
34
  }
25
35
 
26
- export function computeViewportHeightPx(viewportHeight?: number, autoViewportHeight?: number | null): string {
36
+ export function computeViewportHeightPx(
37
+ viewportHeight?: number,
38
+ autoViewportHeight?: number | null,
39
+ ): string {
27
40
  return `${viewportHeight ?? autoViewportHeight ?? 560}px`;
28
41
  }
29
42
 
30
43
  export function computeViewportRows(viewportHeight?: number, rowHeight?: number): number {
31
44
  return Math.max(1, Math.ceil((viewportHeight ?? 560) / (rowHeight ?? 44)));
32
- }
45
+ }
package/src/index.ts CHANGED
@@ -1,12 +1,27 @@
1
1
  export { UiGrid } from './UiGrid';
2
2
  export type { UiGridProps } from './UiGrid';
3
3
  export { mountUiGrid } from './mountUiGrid';
4
+ export {
5
+ mountUiGridCustomElement,
6
+ type MountUiGridCustomElementOptions,
7
+ type MountedUiGridCustomElement,
8
+ } from './vanillaAdapter';
4
9
  export { useGridState } from './useGridState';
5
10
  export type { UseGridStateResult } from './useGridState';
6
11
  export { useVirtualScroll } from './useVirtualScroll';
7
12
  export type { UseVirtualScrollOptions, UseVirtualScrollResult } from './useVirtualScroll';
8
- export { orderVisibleColumns, buildGridTemplateColumns, resolveBenchmarkIterations, formatPaginationSummary, computeViewportHeightPx, computeViewportRows } from './gridStateMath';
9
- export { enableReactUiGridWasmEngine, registerReactUiGridWasmEngineFromModule } from './rustWasmGridEngine';
13
+ export {
14
+ orderVisibleColumns,
15
+ buildGridTemplateColumns,
16
+ resolveBenchmarkIterations,
17
+ formatPaginationSummary,
18
+ computeViewportHeightPx,
19
+ computeViewportRows,
20
+ } from './gridStateMath';
21
+ export {
22
+ enableReactUiGridWasmEngine,
23
+ registerReactUiGridWasmEngineFromModule,
24
+ } from './rustWasmGridEngine';
10
25
 
11
26
  export type {
12
27
  GridOptions,
@@ -20,7 +35,7 @@ export type {
20
35
  GridBenchmarkResult,
21
36
  GridSavedState,
22
37
  SortState,
23
- } from '@ornery/ui-grid';
38
+ } from '@ornery/ui-grid-core';
24
39
 
25
- export type { UiGridApi } from '@ornery/ui-grid';
26
- export { DEFAULT_GRID_LABELS } from '@ornery/ui-grid';
40
+ export type { UiGridApi } from '@ornery/ui-grid-core';
41
+ export { DEFAULT_GRID_LABELS } from '@ornery/ui-grid-core';
@@ -3,10 +3,10 @@ import {
3
3
  activeGridEngineBackend,
4
4
  clearRustWasmGridEngine,
5
5
  defaultGridEngine,
6
- } from '@ornery/ui-grid';
6
+ } from '@ornery/ui-grid-core';
7
7
  import { registerReactUiGridWasmEngineFromModule } from './rustWasmGridEngine';
8
- import { SORT_DIRECTIONS } from '@ornery/ui-grid';
9
- import type { BuildGridPipelineContext, PipelineResult } from '@ornery/ui-grid';
8
+ import { SORT_DIRECTIONS } from '@ornery/ui-grid-core';
9
+ import type { BuildGridPipelineContext, PipelineResult } from '@ornery/ui-grid-core';
10
10
 
11
11
  function createContext(): BuildGridPipelineContext {
12
12
  return {
@@ -53,4 +53,4 @@ describe('rustWasmGridEngine', () => {
53
53
  expect(defaultGridEngine.buildPipeline(createContext())).toBe(sentinel);
54
54
  expect(activeGridEngineBackend()).toBe('rust-wasm');
55
55
  });
56
- });
56
+ });
@@ -1,5 +1,5 @@
1
- import type { BuildGridPipelineContext, PipelineResult } from '@ornery/ui-grid';
2
- import { registerRustWasmGridEngine } from '@ornery/ui-grid';
1
+ import type { BuildGridPipelineContext, PipelineResult } from '@ornery/ui-grid-core';
2
+ import { registerRustWasmGridEngine } from '@ornery/ui-grid-core';
3
3
 
4
4
  const uiGridWasmModulePath = '../../../dist/ui-grid-wasm-web/ui_grid_wasm.js';
5
5
  const uiGridWasmBinaryPath = '/dist/ui-grid-wasm-web/ui_grid_wasm_bg.wasm';
@@ -12,7 +12,7 @@ export function registerReactUiGridWasmEngineFromModule(module: UiGridWasmModule
12
12
  registerRustWasmGridEngine({
13
13
  buildPipeline(context: BuildGridPipelineContext): PipelineResult {
14
14
  return module.build_pipeline_js(context);
15
- }
15
+ },
16
16
  });
17
17
  }
18
18
 
@@ -20,4 +20,4 @@ export async function enableReactUiGridWasmEngine(): Promise<void> {
20
20
  const module = await import(/* @vite-ignore */ uiGridWasmModulePath);
21
21
  await module.default(uiGridWasmBinaryPath);
22
22
  registerReactUiGridWasmEngineFromModule(module);
23
- }
23
+ }
package/src/ui-grid.css CHANGED
@@ -25,11 +25,20 @@
25
25
  --ui-grid-pin-menu-gap: var(--app-ui-grid-pin-menu-gap, 0.25rem);
26
26
  --ui-grid-pin-menu-padding: var(--app-ui-grid-pin-menu-padding, 0.25rem);
27
27
  --ui-grid-pin-menu-radius: var(--app-ui-grid-pin-menu-radius, 999px);
28
- --ui-grid-pin-menu-shadow: var(--app-ui-grid-pin-menu-shadow, 0 10px 24px color-mix(in srgb, var(--ui-grid-cell-color) 10%, transparent));
28
+ --ui-grid-pin-menu-shadow: var(
29
+ --app-ui-grid-pin-menu-shadow,
30
+ 0 10px 24px color-mix(in srgb, var(--ui-grid-cell-color) 10%, transparent)
31
+ );
29
32
  --ui-grid-pin-menu-action-size: var(--app-ui-grid-pin-menu-action-size, 1.75rem);
30
33
  --ui-grid-pin-control-collapsed-size: var(--app-ui-grid-pin-control-collapsed-size, 1px);
31
- --ui-grid-pin-control-transition-duration: var(--app-ui-grid-pin-control-transition-duration, 160ms);
32
- --ui-grid-pin-control-transition-easing: var(--app-ui-grid-pin-control-transition-easing, cubic-bezier(0.22, 1, 0.36, 1));
34
+ --ui-grid-pin-control-transition-duration: var(
35
+ --app-ui-grid-pin-control-transition-duration,
36
+ 160ms
37
+ );
38
+ --ui-grid-pin-control-transition-easing: var(
39
+ --app-ui-grid-pin-control-transition-easing,
40
+ cubic-bezier(0.22, 1, 0.36, 1)
41
+ );
33
42
  --ui-grid-pin-menu-scale-closed: var(--app-ui-grid-pin-menu-scale-closed, 0.72);
34
43
  display: block;
35
44
  color: var(--ui-grid-cell-color);
@@ -224,6 +233,20 @@
224
233
  align-items: center;
225
234
  }
226
235
 
236
+ .header-cell[draggable='true'] {
237
+ cursor: grab;
238
+ }
239
+
240
+ .header-cell.is-dragging {
241
+ opacity: 0.6;
242
+ }
243
+
244
+ .header-cell.is-drag-target {
245
+ background: color-mix(in srgb, var(--ui-grid-accent) 9%, var(--ui-grid-header-background));
246
+ border: 1px dashed color-mix(in srgb, var(--ui-grid-accent) 45%, var(--ui-grid-border-color));
247
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ui-grid-accent) 18%, transparent);
248
+ }
249
+
227
250
  .header-cell.is-active {
228
251
  background: color-mix(in srgb, var(--ui-grid-accent) 8%, var(--ui-grid-header-background));
229
252
  }
@@ -311,13 +334,20 @@
311
334
  grid-area: 1 / 1;
312
335
  transform-origin: center;
313
336
  transition:
314
- width var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
315
- height var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
316
- opacity var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
317
- transform var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
318
- border-color var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
319
- background-color var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
320
- color var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing);
337
+ width var(--ui-grid-pin-control-transition-duration)
338
+ var(--ui-grid-pin-control-transition-easing),
339
+ height var(--ui-grid-pin-control-transition-duration)
340
+ var(--ui-grid-pin-control-transition-easing),
341
+ opacity var(--ui-grid-pin-control-transition-duration)
342
+ var(--ui-grid-pin-control-transition-easing),
343
+ transform var(--ui-grid-pin-control-transition-duration)
344
+ var(--ui-grid-pin-control-transition-easing),
345
+ border-color var(--ui-grid-pin-control-transition-duration)
346
+ var(--ui-grid-pin-control-transition-easing),
347
+ background-color var(--ui-grid-pin-control-transition-duration)
348
+ var(--ui-grid-pin-control-transition-easing),
349
+ color var(--ui-grid-pin-control-transition-duration)
350
+ var(--ui-grid-pin-control-transition-easing);
321
351
  }
322
352
 
323
353
  .pin-menu {
@@ -340,12 +370,18 @@
340
370
  transform: scale(var(--ui-grid-pin-menu-scale-closed));
341
371
  transform-origin: center;
342
372
  transition:
343
- max-height var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
344
- opacity var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
345
- transform var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
346
- padding var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
347
- border-color var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing),
348
- box-shadow var(--ui-grid-pin-control-transition-duration) var(--ui-grid-pin-control-transition-easing);
373
+ max-height var(--ui-grid-pin-control-transition-duration)
374
+ var(--ui-grid-pin-control-transition-easing),
375
+ opacity var(--ui-grid-pin-control-transition-duration)
376
+ var(--ui-grid-pin-control-transition-easing),
377
+ transform var(--ui-grid-pin-control-transition-duration)
378
+ var(--ui-grid-pin-control-transition-easing),
379
+ padding var(--ui-grid-pin-control-transition-duration)
380
+ var(--ui-grid-pin-control-transition-easing),
381
+ border-color var(--ui-grid-pin-control-transition-duration)
382
+ var(--ui-grid-pin-control-transition-easing),
383
+ box-shadow var(--ui-grid-pin-control-transition-duration)
384
+ var(--ui-grid-pin-control-transition-easing);
349
385
  }
350
386
 
351
387
  .pin-control-open {
@@ -361,7 +397,10 @@
361
397
  }
362
398
 
363
399
  .pin-control-open .pin-menu {
364
- max-height: calc((var(--ui-grid-pin-menu-action-size) * 2) + var(--ui-grid-pin-menu-gap) + (var(--ui-grid-pin-menu-padding) * 2));
400
+ max-height: calc(
401
+ (var(--ui-grid-pin-menu-action-size) * 2) + var(--ui-grid-pin-menu-gap) +
402
+ (var(--ui-grid-pin-menu-padding) * 2)
403
+ );
365
404
  opacity: 1;
366
405
  pointer-events: auto;
367
406
  transform: scale(1);
@@ -128,7 +128,7 @@ import {
128
128
  raiseGridBenchmarkComplete,
129
129
  downloadGridCsvFile,
130
130
  observeGridHostSize,
131
- } from '@ornery/ui-grid';
131
+ } from '@ornery/ui-grid-core';
132
132
  import type {
133
133
  DisplayItem,
134
134
  GroupItem,
@@ -141,7 +141,7 @@ import type {
141
141
  GridExpandableTemplateContext,
142
142
  PinDirection,
143
143
  PinnedColumnState,
144
- } from '@ornery/ui-grid';
144
+ } from '@ornery/ui-grid-core';
145
145
 
146
146
  function escapeCssSelectorValue(value: string): string {
147
147
  const nativeEscape = globalThis.CSS?.escape;
@@ -162,9 +162,7 @@ function escapeCssSelectorValue(value: string): string {
162
162
  const isControlCharacter = (codePoint >= 0x0001 && codePoint <= 0x001f) || codePoint === 0x007f;
163
163
  const startsWithDigit = index === 0 && codePoint >= 0x0030 && codePoint <= 0x0039;
164
164
  const secondCharDigitAfterHyphen =
165
- index === 1 &&
166
- codePoint >= 0x0030 && codePoint <= 0x0039 &&
167
- value.charCodeAt(0) === 0x002d;
165
+ index === 1 && codePoint >= 0x0030 && codePoint <= 0x0039 && value.charCodeAt(0) === 0x002d;
168
166
 
169
167
  if (isControlCharacter || startsWithDigit || secondCharDigitAfterHyphen) {
170
168
  output += `\\${codePoint.toString(16)} `;
@@ -308,6 +306,7 @@ export interface UseGridStateResult {
308
306
  toggleRowExpansion: (row: GridRow, event?: React.MouseEvent) => void;
309
307
  toggleTreeRow: (row: GridRow, event?: React.MouseEvent) => void;
310
308
  moveColumn: (fromIndex: number, toIndex: number) => void;
309
+ moveVisibleColumn: (columnName: string, targetColumnName: string) => void;
311
310
  nextPage: () => void;
312
311
  previousPage: () => void;
313
312
  onPageSizeChange: (value: string) => void;
@@ -408,7 +407,9 @@ export function useGridState(
408
407
  .filter(([, direction]) => direction === 'right')
409
408
  .map(([columnName]) => columnByName.get(columnName))
410
409
  .filter((column): column is GridColumnDef => column !== undefined);
411
- const centerColumns = orderedColumns.filter((column) => pinnedColumns[column.name] === undefined);
410
+ const centerColumns = orderedColumns.filter(
411
+ (column) => pinnedColumns[column.name] === undefined,
412
+ );
412
413
 
413
414
  return [...pinnedLeft, ...centerColumns, ...pinnedRight];
414
415
  }, [options.columnDefs, columnOrder, pinnedColumns]);
@@ -1571,6 +1572,18 @@ export function useGridState(
1571
1572
  );
1572
1573
  }, []);
1573
1574
 
1575
+ const moveVisibleColumnFn = useCallback((columnName: string, targetColumnName: string): void => {
1576
+ moveGridVisibleColumnCommand(
1577
+ gridApiRef.current!,
1578
+ FEATURE_COLUMN_MOVING && optionsRef.current.enableColumnMoving === true,
1579
+ columnOrderRef.current,
1580
+ visibleColumnsRef.current.map((column) => column.name),
1581
+ columnName,
1582
+ targetColumnName,
1583
+ (order) => setColumnOrder(order),
1584
+ );
1585
+ }, []);
1586
+
1574
1587
  const nextPageFn = useCallback((): void => {
1575
1588
  seekPageFn(getCurrentPageValueFn() + 1);
1576
1589
  }, [seekPageFn, getCurrentPageValueFn]);
@@ -1718,6 +1731,7 @@ export function useGridState(
1718
1731
  toggleRowExpansion: toggleRowExpansionFn,
1719
1732
  toggleTreeRow: toggleTreeRowFn,
1720
1733
  moveColumn: moveColumnFn,
1734
+ moveVisibleColumn: moveVisibleColumnFn,
1721
1735
  nextPage: nextPageFn,
1722
1736
  previousPage: previousPageFn,
1723
1737
  onPageSizeChange: onPageSizeChangeFn,
@@ -0,0 +1,33 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+
3
+ import { mountUiGridCustomElement } from './vanillaAdapter';
4
+
5
+ describe('mountUiGridCustomElement', () => {
6
+ it('mounts a custom element and applies grid options', async () => {
7
+ const host = document.createElement('div');
8
+ const ensureDefined = vi.fn(async (tagName: string) => {
9
+ if (!customElements.get(tagName)) {
10
+ customElements.define(tagName, class extends HTMLElement {});
11
+ }
12
+ });
13
+
14
+ const options = {
15
+ id: 'react-adapter-grid',
16
+ data: [{ name: 'Alice' }],
17
+ columnDefs: [{ name: 'name' }],
18
+ };
19
+
20
+ const mounted = await mountUiGridCustomElement(host, {
21
+ options,
22
+ tagName: 'ui-grid-react-adapter-test',
23
+ ensureDefined,
24
+ });
25
+
26
+ expect(ensureDefined).toHaveBeenCalledWith('ui-grid-react-adapter-test');
27
+ expect(host.firstElementChild).toBe(mounted.element);
28
+ expect(mounted.element.options).toBe(options);
29
+
30
+ mounted.unmount();
31
+ expect(host.childElementCount).toBe(0);
32
+ });
33
+ });
@@ -0,0 +1,36 @@
1
+ import type { GridOptions } from '@ornery/ui-grid-core';
2
+
3
+ export interface MountUiGridCustomElementOptions {
4
+ options: GridOptions;
5
+ tagName?: string;
6
+ ensureDefined?: (tagName: string) => Promise<void> | void;
7
+ }
8
+
9
+ export interface MountedUiGridCustomElement {
10
+ element: HTMLElement & { options: GridOptions };
11
+ unmount: () => void;
12
+ }
13
+
14
+ export async function mountUiGridCustomElement(
15
+ container: Element,
16
+ mountOptions: MountUiGridCustomElementOptions,
17
+ ): Promise<MountedUiGridCustomElement> {
18
+ const tagName = mountOptions.tagName ?? 'ui-grid-element';
19
+
20
+ if (mountOptions.ensureDefined) {
21
+ await mountOptions.ensureDefined(tagName);
22
+ }
23
+
24
+ const element = document.createElement(tagName) as HTMLElement & { options: GridOptions };
25
+ element.options = mountOptions.options;
26
+ container.replaceChildren(element);
27
+
28
+ return {
29
+ element,
30
+ unmount: () => {
31
+ if (container.firstElementChild === element) {
32
+ container.replaceChildren();
33
+ }
34
+ },
35
+ };
36
+ }
package/tsconfig.dts.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "outDir": "./dist",
8
8
  "rootDir": "./src",
9
9
  "paths": {
10
- "@ornery/ui-grid": ["../../dist/ui-grid"]
10
+ "@ornery/ui-grid-core": ["../ui-grid-core/dist/index.d.ts"]
11
11
  }
12
12
  },
13
13
  "include": ["src/**/*.ts", "src/**/*.tsx"],
package/tsconfig.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "declarationMap": true,
8
8
  "baseUrl": ".",
9
9
  "paths": {
10
- "@ornery/ui-grid": ["../ui-grid/src/public-api.react.ts"]
10
+ "@ornery/ui-grid-core": ["../ui-grid-core/src/index.ts"]
11
11
  }
12
12
  },
13
13
  "include": ["src"]
package/vitest.config.ts CHANGED
@@ -4,7 +4,7 @@ import path from 'path';
4
4
  export default defineConfig({
5
5
  resolve: {
6
6
  alias: {
7
- '@ornery/ui-grid': path.resolve(__dirname, '../ui-grid/src/public-api.react.ts'),
7
+ '@ornery/ui-grid-core': path.resolve(__dirname, '../ui-grid-core/src/index.ts'),
8
8
  },
9
9
  },
10
10
  test: {