@ornery/ui-grid-react 0.1.6 → 0.1.7
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/demo/main.tsx +1 -1
- package/demo/vite.config.ts +1 -1
- package/dist/UiGrid.d.ts +1 -1
- package/dist/UiGrid.d.ts.map +1 -1
- package/dist/gridStateMath.d.ts +1 -1
- package/dist/gridStateMath.d.ts.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +388 -239
- package/dist/index.mjs +245 -96
- package/dist/rustWasmGridEngine.d.ts +1 -1
- package/dist/rustWasmGridEngine.d.ts.map +1 -1
- package/dist/useGridState.d.ts +3 -2
- package/dist/useGridState.d.ts.map +1 -1
- package/dist/vanillaAdapter.d.ts +14 -0
- package/dist/vanillaAdapter.d.ts.map +1 -0
- package/package.json +11 -11
- package/src/UiGrid.test.tsx +61 -24
- package/src/UiGrid.tsx +320 -198
- package/src/gridStateMath.test.ts +10 -8
- package/src/gridStateMath.ts +20 -7
- package/src/index.ts +20 -5
- package/src/rustWasmGridEngine.test.ts +4 -4
- package/src/rustWasmGridEngine.ts +4 -4
- package/src/ui-grid.css +56 -17
- package/src/useGridState.ts +20 -6
- package/src/vanillaAdapter.test.ts +33 -0
- package/src/vanillaAdapter.ts +36 -0
- package/tsconfig.dts.json +1 -1
- package/tsconfig.json +1 -1
- package/vitest.config.ts +1 -1
|
@@ -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(
|
|
22
|
-
'customer',
|
|
23
|
-
|
|
24
|
-
|
|
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(
|
|
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
|
+
});
|
package/src/gridStateMath.ts
CHANGED
|
@@ -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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 {
|
|
9
|
-
|
|
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(
|
|
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(
|
|
32
|
-
|
|
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)
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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)
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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(
|
|
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);
|
package/src/useGridState.ts
CHANGED
|
@@ -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(
|
|
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
package/tsconfig.json
CHANGED
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/
|
|
7
|
+
'@ornery/ui-grid-core': path.resolve(__dirname, '../ui-grid-core/src/index.ts'),
|
|
8
8
|
},
|
|
9
9
|
},
|
|
10
10
|
test: {
|