@toolbox-web/grid 2.1.1 → 2.3.0
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/all.js +2 -2
- package/all.js.map +1 -1
- package/custom-elements.json +21 -2
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/lib/core/adapter-conformance.d.ts +23 -0
- package/lib/core/constants.d.ts +18 -0
- package/lib/core/grid.d.ts +13 -15
- package/lib/core/internal/value-accessor.d.ts +33 -0
- package/lib/core/types.d.ts +186 -12
- package/lib/plugins/clipboard/index.js +1 -1
- package/lib/plugins/clipboard/index.js.map +1 -1
- package/lib/plugins/column-virtualization/index.js.map +1 -1
- package/lib/plugins/context-menu/index.js.map +1 -1
- package/lib/plugins/editing/index.js +1 -1
- package/lib/plugins/editing/index.js.map +1 -1
- package/lib/plugins/export/index.js +1 -1
- package/lib/plugins/export/index.js.map +1 -1
- package/lib/plugins/filtering/FilteringPlugin.d.ts +19 -1
- package/lib/plugins/filtering/index.js +1 -1
- package/lib/plugins/filtering/index.js.map +1 -1
- package/lib/plugins/grouping-columns/index.js.map +1 -1
- package/lib/plugins/grouping-rows/index.js +2 -2
- package/lib/plugins/grouping-rows/index.js.map +1 -1
- package/lib/plugins/master-detail/index.js +1 -1
- package/lib/plugins/master-detail/index.js.map +1 -1
- package/lib/plugins/multi-sort/index.js +1 -1
- package/lib/plugins/multi-sort/index.js.map +1 -1
- package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +1 -1
- package/lib/plugins/pinned-columns/index.js +1 -1
- package/lib/plugins/pinned-columns/index.js.map +1 -1
- package/lib/plugins/pinned-columns/types.d.ts +7 -0
- package/lib/plugins/pinned-rows/index.js +1 -1
- package/lib/plugins/pinned-rows/index.js.map +1 -1
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/print/index.js +1 -1
- package/lib/plugins/print/index.js.map +1 -1
- package/lib/plugins/reorder-columns/ReorderPlugin.d.ts +13 -1
- package/lib/plugins/reorder-columns/column-drag.d.ts +7 -1
- package/lib/plugins/reorder-columns/index.js +1 -1
- package/lib/plugins/reorder-columns/index.js.map +1 -1
- package/lib/plugins/reorder-columns/types.d.ts +12 -0
- package/lib/plugins/reorder-rows/index.js +1 -1
- package/lib/plugins/reorder-rows/index.js.map +1 -1
- package/lib/plugins/responsive/index.js.map +1 -1
- package/lib/plugins/selection/index.js +1 -1
- package/lib/plugins/selection/index.js.map +1 -1
- package/lib/plugins/selection/types.d.ts +8 -0
- package/lib/plugins/server-side/ServerSidePlugin.d.ts +4 -0
- package/lib/plugins/server-side/index.js +1 -1
- package/lib/plugins/server-side/index.js.map +1 -1
- package/lib/plugins/server-side/types.d.ts +48 -0
- package/lib/plugins/tooltip/index.js.map +1 -1
- package/lib/plugins/tree/index.js.map +1 -1
- package/lib/plugins/undo-redo/index.js.map +1 -1
- package/lib/plugins/visibility/VisibilityPlugin.d.ts +11 -1
- package/lib/plugins/visibility/index.js +1 -1
- package/lib/plugins/visibility/index.js.map +1 -1
- package/package.json +1 -1
- package/public.d.ts +5 -1
- package/umd/grid.all.umd.js +1 -1
- package/umd/grid.all.umd.js.map +1 -1
- package/umd/grid.umd.js +1 -1
- package/umd/grid.umd.js.map +1 -1
- package/umd/plugins/clipboard.umd.js +1 -1
- package/umd/plugins/clipboard.umd.js.map +1 -1
- package/umd/plugins/editing.umd.js +1 -1
- package/umd/plugins/editing.umd.js.map +1 -1
- package/umd/plugins/export.umd.js +1 -1
- package/umd/plugins/export.umd.js.map +1 -1
- package/umd/plugins/filtering.umd.js +1 -1
- package/umd/plugins/filtering.umd.js.map +1 -1
- package/umd/plugins/multi-sort.umd.js +1 -1
- package/umd/plugins/multi-sort.umd.js.map +1 -1
- package/umd/plugins/pinned-columns.umd.js +1 -1
- package/umd/plugins/pinned-columns.umd.js.map +1 -1
- package/umd/plugins/pinned-rows.umd.js +1 -1
- package/umd/plugins/pinned-rows.umd.js.map +1 -1
- package/umd/plugins/print.umd.js +1 -1
- package/umd/plugins/print.umd.js.map +1 -1
- package/umd/plugins/reorder-columns.umd.js +1 -1
- package/umd/plugins/reorder-columns.umd.js.map +1 -1
- package/umd/plugins/reorder-rows.umd.js +1 -1
- package/umd/plugins/reorder-rows.umd.js.map +1 -1
- package/umd/plugins/selection.umd.js +1 -1
- package/umd/plugins/selection.umd.js.map +1 -1
- package/umd/plugins/server-side.umd.js +1 -1
- package/umd/plugins/server-side.umd.js.map +1 -1
- package/umd/plugins/visibility.umd.js +1 -1
- package/umd/plugins/visibility.umd.js.map +1 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FrameworkAdapter } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Method names that are technically optional on {@link FrameworkAdapter}
|
|
4
|
+
* but are actually consumed by the grid core. An adapter that skips any
|
|
5
|
+
* of these silently drops the matching feature for its framework users.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CORE_CONSUMED_ADAPTER_METHODS: ReadonlyArray<keyof FrameworkAdapter>;
|
|
8
|
+
export interface AdapterConformanceReport {
|
|
9
|
+
name: string;
|
|
10
|
+
implemented: (keyof FrameworkAdapter)[];
|
|
11
|
+
missing: (keyof FrameworkAdapter)[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Inspect an adapter and report which core-consumed hooks are implemented
|
|
15
|
+
* vs. missing. Performs a shallow `typeof adapter[name] === 'function'`
|
|
16
|
+
* check — works for class instances, prototypes, and plain objects.
|
|
17
|
+
*/
|
|
18
|
+
export declare function reportAdapterConformance(adapter: FrameworkAdapter): AdapterConformanceReport;
|
|
19
|
+
/**
|
|
20
|
+
* Assert that an adapter implements every core-consumed hook.
|
|
21
|
+
* Throws listing the missing method names. Intended for unit tests.
|
|
22
|
+
*/
|
|
23
|
+
export declare function assertAdapterConformance(adapter: FrameworkAdapter): void;
|
package/lib/core/constants.d.ts
CHANGED
|
@@ -110,6 +110,24 @@ export declare const GridCSSVars: {
|
|
|
110
110
|
readonly BORDER_RADIUS: "--tbw-border-radius";
|
|
111
111
|
readonly FOCUS_OUTLINE: "--tbw-focus-outline";
|
|
112
112
|
};
|
|
113
|
+
/**
|
|
114
|
+
* Union of all CSS class names used in the grid's DOM.
|
|
115
|
+
* Use `GridClasses` to access individual values by key.
|
|
116
|
+
*
|
|
117
|
+
* @category Plugin Development
|
|
118
|
+
*/
|
|
113
119
|
export type GridClassName = (typeof GridClasses)[keyof typeof GridClasses];
|
|
120
|
+
/**
|
|
121
|
+
* Union of all `data-*` attribute names used on grid elements.
|
|
122
|
+
* Use `GridDataAttrs` to access individual values by key.
|
|
123
|
+
*
|
|
124
|
+
* @category Plugin Development
|
|
125
|
+
*/
|
|
114
126
|
export type GridDataAttr = (typeof GridDataAttrs)[keyof typeof GridDataAttrs];
|
|
127
|
+
/**
|
|
128
|
+
* Union of all CSS custom property names (`--tbw-*`) available for theming.
|
|
129
|
+
* Use `GridCSSVars` to access individual values by key.
|
|
130
|
+
*
|
|
131
|
+
* @category Plugin Development
|
|
132
|
+
*/
|
|
115
133
|
export type GridCSSVar = (typeof GridCSSVars)[keyof typeof GridCSSVars];
|
package/lib/core/grid.d.ts
CHANGED
|
@@ -1222,15 +1222,21 @@ export declare class DataGridElement<T = any> extends HTMLElement implements Int
|
|
|
1222
1222
|
*
|
|
1223
1223
|
* // Later, restore the state
|
|
1224
1224
|
* const saved = localStorage.getItem('gridState');
|
|
1225
|
-
* if (saved)
|
|
1226
|
-
* grid.columnState = JSON.parse(saved);
|
|
1227
|
-
* }
|
|
1225
|
+
* if (saved) grid.applyColumnState(JSON.parse(saved));
|
|
1228
1226
|
* ```
|
|
1229
1227
|
*/
|
|
1230
1228
|
getColumnState(): GridColumnState;
|
|
1231
1229
|
/**
|
|
1232
|
-
*
|
|
1233
|
-
*
|
|
1230
|
+
* Get the current column state.
|
|
1231
|
+
* Alias for `getColumnState()` for property-style read access.
|
|
1232
|
+
* @group State Persistence
|
|
1233
|
+
*/
|
|
1234
|
+
get columnState(): GridColumnState | undefined;
|
|
1235
|
+
/**
|
|
1236
|
+
* Apply a previously saved column state, restoring column order, widths,
|
|
1237
|
+
* visibility, sort, and any plugin-contributed state. Can be called
|
|
1238
|
+
* before or after grid initialization — pre-init calls are deferred and
|
|
1239
|
+
* applied during setup.
|
|
1234
1240
|
*
|
|
1235
1241
|
* @group State Persistence
|
|
1236
1242
|
* @fires column-state-change - Emitted after state is applied (if grid is initialized)
|
|
@@ -1239,18 +1245,10 @@ export declare class DataGridElement<T = any> extends HTMLElement implements Int
|
|
|
1239
1245
|
* // Restore saved state on page load
|
|
1240
1246
|
* const grid = queryGrid('tbw-grid');
|
|
1241
1247
|
* const saved = localStorage.getItem('myGridState');
|
|
1242
|
-
* if (saved)
|
|
1243
|
-
* grid.columnState = JSON.parse(saved);
|
|
1244
|
-
* }
|
|
1248
|
+
* if (saved) grid.applyColumnState(JSON.parse(saved));
|
|
1245
1249
|
* ```
|
|
1246
1250
|
*/
|
|
1247
|
-
|
|
1248
|
-
/**
|
|
1249
|
-
* Get the current column state.
|
|
1250
|
-
* Alias for `getColumnState()` for property-style access.
|
|
1251
|
-
* @group State Persistence
|
|
1252
|
-
*/
|
|
1253
|
-
get columnState(): GridColumnState | undefined;
|
|
1251
|
+
applyColumnState(state: GridColumnState | undefined): void;
|
|
1254
1252
|
/**
|
|
1255
1253
|
* Get the current single-column sort state.
|
|
1256
1254
|
*
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ColumnConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the cell value for a column, honoring `valueAccessor` if defined,
|
|
4
|
+
* otherwise reading `row[column.field]`.
|
|
5
|
+
*
|
|
6
|
+
* @param row - The row object
|
|
7
|
+
* @param column - The column definition
|
|
8
|
+
* @param rowIndex - The visible row index (passed to accessor; defaults to -1)
|
|
9
|
+
* @returns The resolved cell value
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const value = resolveCellValue(row, column);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveCellValue<TRow>(row: TRow, column: ColumnConfig<TRow>, rowIndex?: number): unknown;
|
|
17
|
+
/**
|
|
18
|
+
* Invalidate cached accessor values for a row (after in-place mutation),
|
|
19
|
+
* a single (row, field) pair, or — when called with no argument — clear
|
|
20
|
+
* the entire cache. Immutable updates auto-invalidate via row identity.
|
|
21
|
+
*
|
|
22
|
+
* Edit/transaction paths that mutate row objects in-place must call this.
|
|
23
|
+
*/
|
|
24
|
+
export declare function invalidateAccessorCache(row?: object, field?: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Build a `(value, row) => unknown` extractor compatible with
|
|
27
|
+
* `filterValue`-style APIs from a column's `valueAccessor`. Returns `undefined`
|
|
28
|
+
* when the column has no accessor.
|
|
29
|
+
*
|
|
30
|
+
* Used by FilteringPlugin to bridge the two API shapes without duplicating
|
|
31
|
+
* cache lookups.
|
|
32
|
+
*/
|
|
33
|
+
export declare function accessorAsFilterValue<TRow>(column: ColumnConfig<TRow>): ((value: unknown, row: TRow) => unknown) | undefined;
|
package/lib/core/types.d.ts
CHANGED
|
@@ -219,18 +219,29 @@ export interface PublicGrid<T = any> {
|
|
|
219
219
|
*/
|
|
220
220
|
getColumnState?(): GridColumnState;
|
|
221
221
|
/**
|
|
222
|
-
*
|
|
223
|
-
*
|
|
222
|
+
* Read the current column state. Property-style accessor that mirrors
|
|
223
|
+
* {@link PublicGrid.getColumnState}. To restore state, use
|
|
224
|
+
* {@link PublicGrid.applyColumnState}.
|
|
224
225
|
*
|
|
225
226
|
* @example
|
|
226
227
|
* ```typescript
|
|
227
|
-
* const
|
|
228
|
-
* if (saved) {
|
|
229
|
-
* grid.columnState = JSON.parse(saved);
|
|
230
|
-
* }
|
|
228
|
+
* const snapshot = grid.columnState;
|
|
231
229
|
* ```
|
|
232
230
|
*/
|
|
233
231
|
columnState?: GridColumnState;
|
|
232
|
+
/**
|
|
233
|
+
* Apply a previously saved column state, restoring column order, widths,
|
|
234
|
+
* visibility, sort, and any plugin-contributed state. Can be called before
|
|
235
|
+
* or after grid initialization — pre-init calls are deferred and applied
|
|
236
|
+
* during setup.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```typescript
|
|
240
|
+
* const saved = localStorage.getItem('gridState');
|
|
241
|
+
* if (saved) grid.applyColumnState(JSON.parse(saved));
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
applyColumnState?(state: GridColumnState | undefined): void;
|
|
234
245
|
/**
|
|
235
246
|
* Get the current sort state.
|
|
236
247
|
*
|
|
@@ -465,6 +476,8 @@ export interface InternalGrid<T = any> extends PublicGrid<T>, GridConfig<T> {
|
|
|
465
476
|
/** @internal Access the plugin manager's cached state. */
|
|
466
477
|
_pluginManager?: {
|
|
467
478
|
_hasRowStructurePlugins: boolean;
|
|
479
|
+
/** Emit an event on the plugin event bus (does not dispatch a DOM event). */
|
|
480
|
+
emitPluginEvent?: <D>(eventType: string, detail: D) => void;
|
|
468
481
|
};
|
|
469
482
|
_gridTemplate: string;
|
|
470
483
|
_virtualization: VirtualState;
|
|
@@ -792,6 +805,50 @@ export interface BaseColumnConfig<TRow = any, TValue = any> {
|
|
|
792
805
|
resizable?: boolean;
|
|
793
806
|
/** Optional custom comparator for sorting (a,b) -> number */
|
|
794
807
|
sortComparator?: (a: TValue, b: TValue, rowA: TRow, rowB: TRow) => number;
|
|
808
|
+
/**
|
|
809
|
+
* Compute the cell's value from the row. When defined, this is the single
|
|
810
|
+
* source of truth used by sorting, filtering, formatting, cell rendering,
|
|
811
|
+
* export, and clipboard — eliminating the need to duplicate value-extraction
|
|
812
|
+
* logic across `sortComparator`, `filterValue`, and per-renderer code.
|
|
813
|
+
*
|
|
814
|
+
* **Resolution precedence**:
|
|
815
|
+
* - **Sort**: `sortComparator` → `valueAccessor` → `row[field]`
|
|
816
|
+
* - **Filter**: `filterValue` → `valueAccessor` → `row[field]`
|
|
817
|
+
* - **Render / format / export / copy**: `valueAccessor` → `row[field]`
|
|
818
|
+
*
|
|
819
|
+
* The accessor is the *default* value source — per-column escape hatches
|
|
820
|
+
* (`sortComparator`, `filterValue`) still take precedence when set.
|
|
821
|
+
*
|
|
822
|
+
* Results are memoized per `(row identity, column field)` so accessors are
|
|
823
|
+
* free to be "slow but correct" (e.g. `array.find(...)`). Immutable row
|
|
824
|
+
* updates auto-invalidate; in-place mutations are invalidated by the grid's
|
|
825
|
+
* edit / transaction paths.
|
|
826
|
+
*
|
|
827
|
+
* Note: a `valueAccessor` without a paired `valueSetter` (planned API)
|
|
828
|
+
* implies the column is read-only — editors will not commit through it.
|
|
829
|
+
*
|
|
830
|
+
* @example
|
|
831
|
+
* ```typescript
|
|
832
|
+
* // Computed value from nested data
|
|
833
|
+
* {
|
|
834
|
+
* field: 'bolDate',
|
|
835
|
+
* header: 'BL date',
|
|
836
|
+
* valueAccessor: ({ row }) => {
|
|
837
|
+
* if (isCargo(row)) {
|
|
838
|
+
* return row.movements.find(m => m.operationType === 'LOAD')?.movementDate ?? null;
|
|
839
|
+
* }
|
|
840
|
+
* return row.movementDate ?? null;
|
|
841
|
+
* },
|
|
842
|
+
* filterType: 'date',
|
|
843
|
+
* // No need for sortComparator or filterValue — they fall back to the accessor.
|
|
844
|
+
* }
|
|
845
|
+
* ```
|
|
846
|
+
*/
|
|
847
|
+
valueAccessor?: (ctx: {
|
|
848
|
+
row: TRow;
|
|
849
|
+
column: ColumnConfig<TRow>;
|
|
850
|
+
rowIndex: number;
|
|
851
|
+
}) => TValue;
|
|
795
852
|
/** For select type - available options */
|
|
796
853
|
options?: Array<{
|
|
797
854
|
label: string;
|
|
@@ -828,7 +885,58 @@ export interface BaseColumnConfig<TRow = any, TValue = any> {
|
|
|
828
885
|
* ```
|
|
829
886
|
*/
|
|
830
887
|
format?: (value: TValue, row: TRow) => string;
|
|
831
|
-
/**
|
|
888
|
+
/**
|
|
889
|
+
* Marks this column as a **system / utility column** — a column that exists to
|
|
890
|
+
* support grid behaviour rather than to display user data.
|
|
891
|
+
*
|
|
892
|
+
* Built-in plugins set this on the columns they synthesize (selection checkbox,
|
|
893
|
+
* row-reorder drag handle, master-detail / tree / row-grouping expander). You can
|
|
894
|
+
* also set it on columns you author yourself when you want them to behave the same
|
|
895
|
+
* way — for example, a row-action menu column, a status indicator, or any
|
|
896
|
+
* developer-defined "system" column that should be visible in the grid only.
|
|
897
|
+
*
|
|
898
|
+
* Setting `utility: true` excludes the column from:
|
|
899
|
+
*
|
|
900
|
+
* - **Visibility panel** — not listed in the show/hide UI
|
|
901
|
+
* - **Column reorder** — header drag-drop and visibility-panel drag treat it as locked
|
|
902
|
+
* (equivalent to `lockPosition: true`)
|
|
903
|
+
* - **Print** — hidden by `PrintPlugin` during print
|
|
904
|
+
* - **Clipboard copy** — skipped by `ClipboardPlugin`
|
|
905
|
+
* - **Export** (CSV / JSON / Excel) — skipped by `ExportPlugin`
|
|
906
|
+
* - **Range / row selection** — clicks land on the column but selection ignores it
|
|
907
|
+
* - **Filter UI** — no filter button rendered, no filter model entry
|
|
908
|
+
*
|
|
909
|
+
* The column is still rendered in the grid and still receives `cellRenderer` /
|
|
910
|
+
* `viewRenderer` / `headerRenderer` callbacks — it is "hidden from the system,
|
|
911
|
+
* visible in the grid".
|
|
912
|
+
*
|
|
913
|
+
* Convention: name the field with a `__`-prefix (e.g. `__actions`) so it cannot
|
|
914
|
+
* collide with a real data field.
|
|
915
|
+
*
|
|
916
|
+
* @example A custom row-actions column
|
|
917
|
+
* ```ts
|
|
918
|
+
* {
|
|
919
|
+
* field: '__actions',
|
|
920
|
+
* header: '',
|
|
921
|
+
* width: 80,
|
|
922
|
+
* utility: true, // excluded from print, export, reorder, visibility, etc.
|
|
923
|
+
* resizable: false,
|
|
924
|
+
* sortable: false,
|
|
925
|
+
* filterable: false,
|
|
926
|
+
* viewRenderer: ({ row }) => createActionsButton(row),
|
|
927
|
+
* }
|
|
928
|
+
* ```
|
|
929
|
+
*/
|
|
930
|
+
utility?: boolean;
|
|
931
|
+
/**
|
|
932
|
+
* Arbitrary extra metadata for application use.
|
|
933
|
+
*
|
|
934
|
+
* @remarks
|
|
935
|
+
* **Do not use `meta` for grid-recognized flags.** Properties like `lockPosition`,
|
|
936
|
+
* `lockVisible`, `lockPinning`, `pinned`, `utility`, and `checkboxColumn` are first-class
|
|
937
|
+
* augmented properties on `ColumnConfig` itself. Using `meta.<flag>` for any of them is
|
|
938
|
+
* deprecated and only kept as a runtime fallback for back-compat.
|
|
939
|
+
*/
|
|
832
940
|
meta?: Record<string, unknown>;
|
|
833
941
|
}
|
|
834
942
|
/**
|
|
@@ -1883,6 +1991,10 @@ export declare const FitModeEnum: {
|
|
|
1883
1991
|
readonly STRETCH: "stretch";
|
|
1884
1992
|
readonly FIXED: "fixed";
|
|
1885
1993
|
};
|
|
1994
|
+
/**
|
|
1995
|
+
* Column sizing mode — determines how columns fill the available grid width.
|
|
1996
|
+
* Use `FitModeEnum` to access individual values by key.
|
|
1997
|
+
*/
|
|
1886
1998
|
export type FitMode = (typeof FitModeEnum)[keyof typeof FitModeEnum];
|
|
1887
1999
|
/**
|
|
1888
2000
|
* Minimal plugin interface for type-checking.
|
|
@@ -2615,6 +2727,42 @@ export interface DataChangeDetail {
|
|
|
2615
2727
|
/** Total number of source rows (before filtering/grouping) */
|
|
2616
2728
|
sourceRowCount: number;
|
|
2617
2729
|
}
|
|
2730
|
+
/**
|
|
2731
|
+
* Detail payload for the `tbw-scroll` event.
|
|
2732
|
+
*
|
|
2733
|
+
* Dispatched on the grid host whenever the vertical viewport scrolls
|
|
2734
|
+
* (rAF-batched — at most one per frame). Use to trigger pagination,
|
|
2735
|
+
* defer heavy cell content rendering, dismiss overlays, or sync a
|
|
2736
|
+
* scroll-tracking UI outside the grid.
|
|
2737
|
+
*
|
|
2738
|
+
* For server-side pagination of large datasets, prefer
|
|
2739
|
+
* `ServerSidePlugin` which handles block fetching out of the box.
|
|
2740
|
+
*
|
|
2741
|
+
* @example
|
|
2742
|
+
* ```typescript
|
|
2743
|
+
* grid.addEventListener('tbw-scroll', (e) => {
|
|
2744
|
+
* const { scrollTop, scrollHeight, clientHeight } = e.detail;
|
|
2745
|
+
* if (scrollTop + clientHeight >= scrollHeight - 200) loadMore();
|
|
2746
|
+
* });
|
|
2747
|
+
* ```
|
|
2748
|
+
*
|
|
2749
|
+
* @see {@link DataGridEventMap} for all event types
|
|
2750
|
+
* @category Events
|
|
2751
|
+
*/
|
|
2752
|
+
export interface TbwScrollDetail {
|
|
2753
|
+
/** Current vertical scroll offset in pixels (faux scrollbar). */
|
|
2754
|
+
scrollTop: number;
|
|
2755
|
+
/** Total scrollable height in pixels (faux scrollbar). */
|
|
2756
|
+
scrollHeight: number;
|
|
2757
|
+
/** Visible viewport height in pixels (faux scrollbar). */
|
|
2758
|
+
clientHeight: number;
|
|
2759
|
+
/**
|
|
2760
|
+
* Axis that triggered this dispatch. Currently always `'vertical'`;
|
|
2761
|
+
* `'horizontal'` is reserved for a future opt-in dispatch and is
|
|
2762
|
+
* declared up-front so consumer narrowing remains source-compatible.
|
|
2763
|
+
*/
|
|
2764
|
+
direction: 'vertical' | 'horizontal';
|
|
2765
|
+
}
|
|
2618
2766
|
/**
|
|
2619
2767
|
* Indicates the origin of a data change.
|
|
2620
2768
|
* Used to prevent infinite loops in cascade update handlers.
|
|
@@ -3194,9 +3342,7 @@ export interface HeaderContentDefinition {
|
|
|
3194
3342
|
*
|
|
3195
3343
|
* // Restore on page load
|
|
3196
3344
|
* const saved = localStorage.getItem('gridState');
|
|
3197
|
-
* if (saved)
|
|
3198
|
-
* grid.columnState = JSON.parse(saved);
|
|
3199
|
-
* }
|
|
3345
|
+
* if (saved) grid.applyColumnState(JSON.parse(saved));
|
|
3200
3346
|
*
|
|
3201
3347
|
* // Example column state structure
|
|
3202
3348
|
* const state: GridColumnState = {
|
|
@@ -3257,7 +3403,7 @@ export interface ColumnSortState {
|
|
|
3257
3403
|
* localStorage.setItem('grid-state', JSON.stringify(state));
|
|
3258
3404
|
*
|
|
3259
3405
|
* // Restore state
|
|
3260
|
-
* grid.
|
|
3406
|
+
* grid.applyColumnState(JSON.parse(localStorage.getItem('grid-state')));
|
|
3261
3407
|
* ```
|
|
3262
3408
|
*
|
|
3263
3409
|
* @see {@link ColumnState} for individual column state
|
|
@@ -3625,6 +3771,34 @@ export interface DataGridEventMap<TRow = unknown> {
|
|
|
3625
3771
|
* @group Core Events
|
|
3626
3772
|
*/
|
|
3627
3773
|
'data-change': DataChangeDetail;
|
|
3774
|
+
/**
|
|
3775
|
+
* Fired when the grid's viewport is scrolled vertically (rAF-batched).
|
|
3776
|
+
* Use to trigger pagination, defer heavy cell content, dismiss overlays,
|
|
3777
|
+
* or sync external UI to the grid's scroll position.
|
|
3778
|
+
*
|
|
3779
|
+
* For server-side pagination of large datasets, prefer the
|
|
3780
|
+
* `ServerSidePlugin` — it handles block fetching out of the box.
|
|
3781
|
+
*
|
|
3782
|
+
* @example
|
|
3783
|
+
* ```typescript
|
|
3784
|
+
* // Infinite scroll
|
|
3785
|
+
* grid.on('tbw-scroll', ({ scrollTop, scrollHeight, clientHeight }) => {
|
|
3786
|
+
* if (scrollTop + clientHeight >= scrollHeight - 200) loadMore();
|
|
3787
|
+
* });
|
|
3788
|
+
*
|
|
3789
|
+
* // Defer heavy cell content (Angular @defer style)
|
|
3790
|
+
* grid.on('tbw-scroll', ({ scrollTop }) => {
|
|
3791
|
+
* updateVisibleHeavyCells(scrollTop);
|
|
3792
|
+
* });
|
|
3793
|
+
*
|
|
3794
|
+
* // Dismiss tooltip/popover on scroll
|
|
3795
|
+
* grid.on('tbw-scroll', () => closeOpenOverlays());
|
|
3796
|
+
* ```
|
|
3797
|
+
*
|
|
3798
|
+
* @see {@link TbwScrollDetail}
|
|
3799
|
+
* @group Core Events
|
|
3800
|
+
*/
|
|
3801
|
+
'tbw-scroll': TbwScrollDetail;
|
|
3628
3802
|
/**
|
|
3629
3803
|
* Emitted when a cell with an external view renderer (React, Angular, Vue component)
|
|
3630
3804
|
* needs to be mounted. Framework adapters listen for this event internally.
|
|
@@ -3724,7 +3898,7 @@ export interface DataGridEventMap<TRow = unknown> {
|
|
|
3724
3898
|
*
|
|
3725
3899
|
* // Restore on load
|
|
3726
3900
|
* const saved = localStorage.getItem('grid-state');
|
|
3727
|
-
* if (saved) grid.
|
|
3901
|
+
* if (saved) grid.applyColumnState(JSON.parse(saved));
|
|
3728
3902
|
* ```
|
|
3729
3903
|
*
|
|
3730
3904
|
* @see {@link GridColumnState}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function e(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function t(t,n,r,o){return`${e(r,o)} ${t}: ${n}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(t)}`}const n="__otorp__|__retteGenifed__|__retteSenifed__|rotcurtsnoc|wodniw|sihTlabolg|labolg|ssecorp|noitcnuF|tropmi|lave|tcelfeR|yxorP|rorrE|stnemugra|tnemucod|noitacol|eikooc|egarotSlacol|egarotSnoisses|BDdexedni|hctef|tseuqeRpttHLMX|tekcoSbeW|rekroW|rekroWderahS|rekroWecivreS|renepo|tnerap|pot|semarf|fles".split("|").map(e=>e.split("").reverse().join(""));new RegExp(`__(proto|defineGetter|defineSetter)|${n.slice(3).join("|")}|this\\b`);const r=new Set("script|iframe|object|embed|form|input|button|textarea|select|link|meta|base|style|template|slot|portal|frame|frameset|applet|noscript|noembed|plaintext|xmp|listing".split("|")),o=/^on\w+$/i,i=new Set("href|src|action|formaction|data|srcdoc|xlink:href|poster|srcset".split("|")),s=/^\s*(javascript|vbscript|data|blob):/i;function l(e){if(!e||"string"!=typeof e)return"";if(-1===e.indexOf("<"))return e;const t=document.createElement("template");return t.innerHTML=e,function(e){const t=[],n=e.querySelectorAll("*");for(const l of n){const e=l.tagName.toLowerCase();if(r.has(e)){t.push(l);continue}if("svg"===e||"http://www.w3.org/2000/svg"===l.namespaceURI){if(Array.from(l.attributes).some(e=>o.test(e.name)||"href"===e.name||"xlink:href"===e.name)){t.push(l);continue}}const n=[];for(const t of l.attributes){const e=t.name.toLowerCase();o.test(e)?n.push(t.name):(i.has(e)&&s.test(t.value)||"style"===e&&/expression\s*\(|javascript:|behavior\s*:/i.test(t.value))&&n.push(t.name)}n.forEach(e=>l.removeAttribute(e))}t.forEach(e=>e.remove())}(t.content),t.innerHTML}const a='<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>',c={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:a,filterActive:a,print:"🖨️"};class d{static dependencies;static manifest;aliases;version="undefined"!=typeof __GRID_VERSION__?__GRID_VERSION__:"dev";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}attach(e){this.#e?.abort(),this.#e=new AbortController,this.grid=e,this.config={...this.defaultConfig,...this.userConfig}}detach(){this.#e?.abort(),this.#e=void 0}getPlugin(e){return this.grid?.getPlugin(e)}emit(e,t){this.grid?.dispatchEvent?.(new CustomEvent(e,{detail:t,bubbles:!0}))}emitCancelable(e,t){const n=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return this.grid?.dispatchEvent?.(n),n.defaultPrevented}on(e,t){this.grid?._pluginManager?.subscribe(this,e,t)}off(e){this.grid?._pluginManager?.unsubscribe(this,e)}emitPluginEvent(e,t){this.grid?._pluginManager?.emitPluginEvent(e,t)}broadcast(e,t){this.emitPluginEvent(e,t),this.emit(e,t)}requestRender(){this.grid?.requestRender?.()}requestColumnsRender(){this.grid?.requestColumnsRender?.()}requestRenderWithFocus(){this.grid?.requestRenderWithFocus?.()}requestAfterRender(){this.grid?.requestAfterRender?.()}requestVirtualRefresh(){this.grid?.requestVirtualRefresh?.()}get rows(){return this.grid?.rows??[]}get sourceRows(){return this.grid?.sourceRows??[]}get columns(){return this.grid?.columns??[]}get visibleColumns(){return this.grid?._visibleColumns??[]}get gridElement(){return this.grid?._hostElement}get disconnectSignal(){return this.#e?.signal??this.grid?.disconnectSignal}get gridIcons(){const e=this.grid?.gridConfig?.icons??{};return{...c,...e}}get isAnimationEnabled(){const e=this.grid?.effectiveConfig?.animation?.mode??"reduced-motion";if(!1===e||"off"===e)return!1;if(!0===e||"on"===e)return!0;const t=this.gridElement;if(t){return"0"!==getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim()}return!0}get animationDuration(){const e=this.gridElement;if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(),n=parseInt(t,10);if(!isNaN(n))return n}return 200}setIcon(e,t,n){e.dataset.icon=t.replace(/([A-Z])/g,"-$1").toLowerCase(),"collapse"===t?e.dataset.expanded="":"expand"===t&&delete e.dataset.expanded;const r=this.#t(t,n);void 0!==r?"string"==typeof r?e.innerHTML=l(r):r instanceof HTMLElement&&(e.innerHTML="",e.appendChild(r.cloneNode(!0))):e.innerHTML=""}#t(e,t){return void 0!==t?t:this.grid?.gridConfig?.icons?.[e]}updateSortIndicator(e,t){e.querySelector('[part~="sort-indicator"], .sort-indicator')?.remove();const n=document.createElement("span");n.setAttribute("part","sort-indicator"),n.className="sort-indicator",t?(e.setAttribute("aria-sort","asc"===t?"ascending":"descending"),e.setAttribute("data-sort",t),this.setIcon(n,"asc"===t?"sortAsc":"sortDesc")):(e.setAttribute("aria-sort","none"),e.removeAttribute("data-sort"),this.setIcon(n,"sortNone"));const r=e.querySelector(".tbw-filter-btn")??e.querySelector(".resize-handle");return r?e.insertBefore(n,r):e.appendChild(n),n}warn(n,r){void 0!==r?console.warn(t(n,r,this.gridElement.id,this.name)):console.warn(`${e(this.gridElement.id,this.name)} ${n}`)}throwDiagnostic(e,n){throw new Error(t(e,n,this.gridElement.id,this.name))}}function u(e,t,n=!0){let r=e;if(n&&(r=r.filter(e=>!e.hidden&&!e.field.startsWith("__")&&!0!==e.meta?.utility)),t?.length){const e=new Set(t);r=r.filter(t=>e.has(t.field))}return r}async function h(e){try{return await navigator.clipboard.writeText(e),!0}catch(s){n="TBW100",r=`Clipboard API failed: ${s}`,console.warn(t(n,r,o,i));const l=document.createElement("textarea");l.value=e,l.style.position="fixed",l.style.opacity="0",l.style.pointerEvents="none",document.body.appendChild(l),l.select();const a=document.execCommand("copy");return document.body.removeChild(l),a}var n,r,o,i}function f(e,t){const n=t.delimiter??"\t",r=t.newline??"\n",o=e.replace(/\r\n/g,"\n").replace(/\r/g,"\n"),i=[];let s=[],l="",a=!1;for(let c=0;c<o.length;c++){const e=o[c];'"'!==e||a?'"'===e&&a?'"'===o[c+1]?(l+='"',c++):a=!1:e!==n||a?e!==r||a?l+=e:(s.push(l),l="",(s.length>1||s.some(e=>""!==e.trim()))&&i.push(s),s=[]):(s.push(l),l=""):a=!0}return s.push(l),(s.length>1||s.some(e=>""!==e.trim()))&&i.push(s),i}function g(e,t){const{rows:n,target:r,fields:o}=e;if(!r)return;const i=t.rows,s=t.effectiveConfig.columns??[],l=s.map(e=>e.field),a=/* @__PURE__ */new Map;s.forEach(e=>{a.set(e.field,!0===e.editable)});const c=[...i],d=r.bounds?r.bounds.endRow:1/0;n.forEach((e,t)=>{const n=r.row+t;if(!(n>d)){if(r.bounds){if(n>=c.length)return}else for(;n>=c.length;){const e={};l.forEach(t=>e[t]=""),c.push(e)}c[n]={...c[n]},e.forEach((e,t)=>{const r=o[t];r&&a.get(r)&&(c[n][r]=e)})}}),t.rows=c}class m extends d{static manifest={queries:[{type:"clipboard:copy",description:"Triggers a copy operation and returns the copied text"}]};static dependencies=[{name:"selection",required:!1,reason:"Enables copy/paste of selected cells instead of entire grid"}];name="clipboard";get defaultConfig(){return{includeHeaders:!1,delimiter:"\t",newline:"\n",quoteStrings:!1}}lastCopied=null;attach(e){super.attach(e),e.addEventListener("paste",e=>this.#n(e),{signal:this.disconnectSignal})}detach(){this.lastCopied=null}handleQuery(e){if("clipboard:copy"===e.type)return this.copy(),!0}onKeyDown(e){return!(!e.ctrlKey&&!e.metaKey||"c"!==e.key)&&(e.preventDefault(),this.#r(e.target),!0)}#r(e){const t=this.#o();if(t&&0===t.ranges.length){const t=this.#i(e);if(!t)return;const n=this.columns[t.col];if(!n)return;return void this.copy({rowIndices:[t.row],columns:[n.field]})}this.copy()}#n(e){const t=e.clipboardData?.getData("text/plain");if(!t)return;e.preventDefault();const n=f(t,this.config),r=this.#o(),o=r?.ranges?.[0],i=o?.from.row??0,s=o?.from.col??0,l=o&&("range"===r?.mode||"row"===r?.mode)&&(o.from.row!==o.to.row||o.from.col!==o.to.col)?{endRow:o.to.row,endCol:o.to.col}:null,a=l?.endCol??this.visibleColumns.length-1,c=this.visibleColumns[s],d=c?{row:i,col:s,field:c.field,bounds:l}:null,u=[],h=n[0]?.length??0;for(let f=0;f<h&&s+f<=a;f++){const e=this.visibleColumns[s+f];e&&u.push(e.field)}const g={rows:n,text:t,target:d,fields:u};this.emit("paste",g),this.#s(g)}#s(e){if(!this.grid)return;const{pasteHandler:t}=this.config;if(null===t)return;(t??g)(e,this.grid)}#o(){const e=this.grid?.query("getSelection");return e?.[0]}#l(e){const t=this.#o();let n,r;if(e?.columns)n=u(this.columns,e.columns);else if(t?.ranges.length&&"row"!==t.mode){const e=t.ranges[t.ranges.length-1],r=Math.min(e.from.col,e.to.col),o=Math.max(e.from.col,e.to.col);n=u(this.visibleColumns.slice(r,o+1))}else n=u(this.columns);if(e?.rowIndices)r=function(e,t){return t?.length?[...t].sort((e,t)=>e-t).map(t=>e[t]).filter(e=>null!=e):e}(this.rows,e.rowIndices);else if(t?.ranges.length){const e=t.ranges[t.ranges.length-1],n=Math.min(e.from.row,e.to.row),o=Math.max(e.from.row,e.to.row);r=[];for(let t=n;t<=o;t++){const e=this.rows[t];e&&r.push(e)}}else r=this.rows;return{columns:n,rows:r}}#a(e,t,n){const r=n?.delimiter??this.config.delimiter??"\t",o=n?.newline??this.config.newline??"\n",i=n?.includeHeaders??this.config.includeHeaders??!1,s=n?.processCell??this.config.processCell,l=[];i&&l.push(e.map(e=>e.header||e.field).join(r));for(const a of t){const t=e.map(e=>{const t=a[e.field];return s?s(t,e.field,a):this.#c(e,t,a)});l.push(t.join(r))}return l.join(o)}#c(e,t,n){if(e.format)try{const r=e.format(t,n);return null==r?"":String(r)}catch{}if(e.renderer||e.viewRenderer){const t=this.#d(e.field,n);if(null!=t)return t}return function(e){return null==e?"":e instanceof Date?e.toISOString():"object"==typeof e?JSON.stringify(e):String(e)}(t)}#d(e,t){const n=this.gridElement;if(!n)return null;const r=this.rows.indexOf(t);if(-1===r)return null;const o=n.querySelector(`.cell[data-row="${r}"][data-field="${e}"]`);return o?o.textContent?.trim()??null:null}#i(e){const t=e.closest("[data-field-cache]");if(!t)return null;const n=t.dataset.fieldCache,r=t.dataset.row;if(!n||!r)return null;const o=parseInt(r,10);if(isNaN(o))return null;const i=this.columns.findIndex(e=>e.field===n);return-1===i?null:{row:o,col:i}}getSelectionAsText(e){const{columns:t,rows:n}=this.#l(e);return 0===t.length||0===n.length?"":this.#a(t,n,e)}async copy(e){const{columns:t,rows:n}=this.#l(e);if(0===t.length||0===n.length)return"";const r=this.#a(t,n,e);return await h(r),this.lastCopied={text:r,timestamp:Date.now()},this.emit("copy",{text:r,rowCount:n.length,columnCount:t.length}),r}async copyRows(e,t){return 0===e.length?"":this.copy({...t,rowIndices:e})}async paste(){const e=await async function(){try{return await navigator.clipboard.readText()}catch{return""}}();return e?f(e,this.config):null}getLastCopied(){return this.lastCopied}}export{m as ClipboardPlugin,g as defaultPasteHandler};
|
|
1
|
+
const e=/* @__PURE__ */new WeakMap;function t(t,n,r=-1){if(!n.valueAccessor)return t?.[n.field];if("object"!=typeof t||null===t)return n.valueAccessor({row:t,column:n,rowIndex:r});const o=n.field;let i=e.get(t);if(i){if(i.has(o))return i.get(o)}else i=/* @__PURE__ */new Map,e.set(t,i);const s=n.valueAccessor({row:t,column:n,rowIndex:r});return i.set(o,s),s}function n(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function r(e,t,r,o){return`${n(r,o)} ${e}: ${t}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(e)}`}const o="__otorp__|__retteGenifed__|__retteSenifed__|rotcurtsnoc|wodniw|sihTlabolg|labolg|ssecorp|noitcnuF|tropmi|lave|tcelfeR|yxorP|rorrE|stnemugra|tnemucod|noitacol|eikooc|egarotSlacol|egarotSnoisses|BDdexedni|hctef|tseuqeRpttHLMX|tekcoSbeW|rekroW|rekroWderahS|rekroWecivreS|renepo|tnerap|pot|semarf|fles".split("|").map(e=>e.split("").reverse().join(""));new RegExp(`__(proto|defineGetter|defineSetter)|${o.slice(3).join("|")}|this\\b`);const i=new Set("script|iframe|object|embed|form|input|button|textarea|select|link|meta|base|style|template|slot|portal|frame|frameset|applet|noscript|noembed|plaintext|xmp|listing".split("|")),s=/^on\w+$/i,l=new Set("href|src|action|formaction|data|srcdoc|xlink:href|poster|srcset".split("|")),a=/^\s*(javascript|vbscript|data|blob):/i;function c(e){if(!e||"string"!=typeof e)return"";if(-1===e.indexOf("<"))return e;const t=document.createElement("template");return t.innerHTML=e,function(e){const t=[],n=e.querySelectorAll("*");for(const r of n){const e=r.tagName.toLowerCase();if(i.has(e)){t.push(r);continue}if("svg"===e||"http://www.w3.org/2000/svg"===r.namespaceURI){if(Array.from(r.attributes).some(e=>s.test(e.name)||"href"===e.name||"xlink:href"===e.name)){t.push(r);continue}}const n=[];for(const t of r.attributes){const e=t.name.toLowerCase();s.test(e)?n.push(t.name):(l.has(e)&&a.test(t.value)||"style"===e&&/expression\s*\(|javascript:|behavior\s*:/i.test(t.value))&&n.push(t.name)}n.forEach(e=>r.removeAttribute(e))}t.forEach(e=>e.remove())}(t.content),t.innerHTML}const d='<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>',u={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:d,filterActive:d,print:"🖨️"};class h{static dependencies;static manifest;aliases;version="undefined"!=typeof __GRID_VERSION__?__GRID_VERSION__:"dev";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}attach(e){this.#e?.abort(),this.#e=new AbortController,this.grid=e,this.config={...this.defaultConfig,...this.userConfig}}detach(){this.#e?.abort(),this.#e=void 0}getPlugin(e){return this.grid?.getPlugin(e)}emit(e,t){this.grid?.dispatchEvent?.(new CustomEvent(e,{detail:t,bubbles:!0}))}emitCancelable(e,t){const n=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return this.grid?.dispatchEvent?.(n),n.defaultPrevented}on(e,t){this.grid?._pluginManager?.subscribe(this,e,t)}off(e){this.grid?._pluginManager?.unsubscribe(this,e)}emitPluginEvent(e,t){this.grid?._pluginManager?.emitPluginEvent(e,t)}broadcast(e,t){this.emitPluginEvent(e,t),this.emit(e,t)}requestRender(){this.grid?.requestRender?.()}requestColumnsRender(){this.grid?.requestColumnsRender?.()}requestRenderWithFocus(){this.grid?.requestRenderWithFocus?.()}requestAfterRender(){this.grid?.requestAfterRender?.()}requestVirtualRefresh(){this.grid?.requestVirtualRefresh?.()}get rows(){return this.grid?.rows??[]}get sourceRows(){return this.grid?.sourceRows??[]}get columns(){return this.grid?.columns??[]}get visibleColumns(){return this.grid?._visibleColumns??[]}get gridElement(){return this.grid?._hostElement}get disconnectSignal(){return this.#e?.signal??this.grid?.disconnectSignal}get gridIcons(){const e=this.grid?.gridConfig?.icons??{};return{...u,...e}}get isAnimationEnabled(){const e=this.grid?.effectiveConfig?.animation?.mode??"reduced-motion";if(!1===e||"off"===e)return!1;if(!0===e||"on"===e)return!0;const t=this.gridElement;if(t){return"0"!==getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim()}return!0}get animationDuration(){const e=this.gridElement;if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(),n=parseInt(t,10);if(!isNaN(n))return n}return 200}setIcon(e,t,n){e.dataset.icon=t.replace(/([A-Z])/g,"-$1").toLowerCase(),"collapse"===t?e.dataset.expanded="":"expand"===t&&delete e.dataset.expanded;const r=this.#t(t,n);void 0!==r?"string"==typeof r?e.innerHTML=c(r):r instanceof HTMLElement&&(e.innerHTML="",e.appendChild(r.cloneNode(!0))):e.innerHTML=""}#t(e,t){return void 0!==t?t:this.grid?.gridConfig?.icons?.[e]}updateSortIndicator(e,t){e.querySelector('[part~="sort-indicator"], .sort-indicator')?.remove();const n=document.createElement("span");n.setAttribute("part","sort-indicator"),n.className="sort-indicator",t?(e.setAttribute("aria-sort","asc"===t?"ascending":"descending"),e.setAttribute("data-sort",t),this.setIcon(n,"asc"===t?"sortAsc":"sortDesc")):(e.setAttribute("aria-sort","none"),e.removeAttribute("data-sort"),this.setIcon(n,"sortNone"));const r=e.querySelector(".tbw-filter-btn")??e.querySelector(".resize-handle");return r?e.insertBefore(n,r):e.appendChild(n),n}warn(e,t){void 0!==t?console.warn(r(e,t,this.gridElement.id,this.name)):console.warn(`${n(this.gridElement.id,this.name)} ${e}`)}throwDiagnostic(e,t){throw new Error(r(e,t,this.gridElement.id,this.name))}}function f(e,t,n=!0){let r=e;if(n&&(r=r.filter(e=>!e.hidden&&!e.field.startsWith("__")&&!0!==e.utility)),t?.length){const e=new Set(t);r=r.filter(t=>e.has(t.field))}return r}async function g(e){try{return await navigator.clipboard.writeText(e),!0}catch(s){t="TBW100",n=`Clipboard API failed: ${s}`,console.warn(r(t,n,o,i));const l=document.createElement("textarea");l.value=e,l.style.position="fixed",l.style.opacity="0",l.style.pointerEvents="none",document.body.appendChild(l),l.select();const a=document.execCommand("copy");return document.body.removeChild(l),a}var t,n,o,i}function m(e,t){const n=t.delimiter??"\t",r=t.newline??"\n",o=e.replace(/\r\n/g,"\n").replace(/\r/g,"\n"),i=[];let s=[],l="",a=!1;for(let c=0;c<o.length;c++){const e=o[c];'"'!==e||a?'"'===e&&a?'"'===o[c+1]?(l+='"',c++):a=!1:e!==n||a?e!==r||a?l+=e:(s.push(l),l="",(s.length>1||s.some(e=>""!==e.trim()))&&i.push(s),s=[]):(s.push(l),l=""):a=!0}return s.push(l),(s.length>1||s.some(e=>""!==e.trim()))&&i.push(s),i}function p(e,t){const{rows:n,target:r,fields:o}=e;if(!r)return;const i=t.rows,s=t.effectiveConfig.columns??[],l=s.map(e=>e.field),a=/* @__PURE__ */new Map;s.forEach(e=>{a.set(e.field,!0===e.editable)});const c=[...i],d=r.bounds?r.bounds.endRow:1/0;n.forEach((e,t)=>{const n=r.row+t;if(!(n>d)){if(r.bounds){if(n>=c.length)return}else for(;n>=c.length;){const e={};l.forEach(t=>e[t]=""),c.push(e)}c[n]={...c[n]},e.forEach((e,t)=>{const r=o[t];r&&a.get(r)&&(c[n][r]=e)})}}),t.rows=c}class w extends h{static manifest={queries:[{type:"clipboard:copy",description:"Triggers a copy operation and returns the copied text"}]};static dependencies=[{name:"selection",required:!1,reason:"Enables copy/paste of selected cells instead of entire grid"}];name="clipboard";get defaultConfig(){return{includeHeaders:!1,delimiter:"\t",newline:"\n",quoteStrings:!1}}lastCopied=null;attach(e){super.attach(e),e.addEventListener("paste",e=>this.#n(e),{signal:this.disconnectSignal})}detach(){this.lastCopied=null}handleQuery(e){if("clipboard:copy"===e.type)return this.copy(),!0}onKeyDown(e){return!(!e.ctrlKey&&!e.metaKey||"c"!==e.key)&&(e.preventDefault(),this.#r(e.target),!0)}#r(e){const t=this.#o();if(t&&0===t.ranges.length){const t=this.#i(e);if(!t)return;const n=this.columns[t.col];if(!n)return;return void this.copy({rowIndices:[t.row],columns:[n.field]})}this.copy()}#n(e){const t=e.clipboardData?.getData("text/plain");if(!t)return;e.preventDefault();const n=m(t,this.config),r=this.#o(),o=r?.ranges?.[0],i=o?.from.row??0,s=o?.from.col??0,l=o&&("range"===r?.mode||"row"===r?.mode)&&(o.from.row!==o.to.row||o.from.col!==o.to.col)?{endRow:o.to.row,endCol:o.to.col}:null,a=l?.endCol??this.visibleColumns.length-1,c=this.visibleColumns[s],d=c?{row:i,col:s,field:c.field,bounds:l}:null,u=[],h=n[0]?.length??0;for(let g=0;g<h&&s+g<=a;g++){const e=this.visibleColumns[s+g];e&&u.push(e.field)}const f={rows:n,text:t,target:d,fields:u};this.emit("paste",f),this.#s(f)}#s(e){if(!this.grid)return;const{pasteHandler:t}=this.config;if(null===t)return;(t??p)(e,this.grid)}#o(){const e=this.grid?.query("getSelection");return e?.[0]}#l(e){const t=this.#o();let n,r;if(e?.columns)n=f(this.columns,e.columns);else if(t?.ranges.length&&"row"!==t.mode){const e=t.ranges[t.ranges.length-1],r=Math.min(e.from.col,e.to.col),o=Math.max(e.from.col,e.to.col);n=f(this.visibleColumns.slice(r,o+1))}else n=f(this.columns);if(e?.rowIndices)r=function(e,t){return t?.length?[...t].sort((e,t)=>e-t).map(t=>e[t]).filter(e=>null!=e):e}(this.rows,e.rowIndices);else if(t?.ranges.length){const e=t.ranges[t.ranges.length-1],n=Math.min(e.from.row,e.to.row),o=Math.max(e.from.row,e.to.row);r=[];for(let t=n;t<=o;t++){const e=this.rows[t];e&&r.push(e)}}else r=this.rows;return{columns:n,rows:r}}#a(e,n,r){const o=r?.delimiter??this.config.delimiter??"\t",i=r?.newline??this.config.newline??"\n",s=r?.includeHeaders??this.config.includeHeaders??!1,l=r?.processCell??this.config.processCell,a=[];s&&a.push(e.map(e=>e.header||e.field).join(o));for(const c of n){const n=e.map(e=>{const n=t(c,e);return l?l(n,e.field,c):this.#c(e,n,c)});a.push(n.join(o))}return a.join(i)}#c(e,t,n){if(e.format)try{const r=e.format(t,n);return null==r?"":String(r)}catch{}if(e.renderer||e.viewRenderer){const t=this.#d(e.field,n);if(null!=t)return t}return function(e){return null==e?"":e instanceof Date?e.toISOString():"object"==typeof e?JSON.stringify(e):String(e)}(t)}#d(e,t){const n=this.gridElement;if(!n)return null;const r=this.rows.indexOf(t);if(-1===r)return null;const o=n.querySelector(`.cell[data-row="${r}"][data-field="${e}"]`);return o?o.textContent?.trim()??null:null}#i(e){const t=e.closest("[data-field-cache]");if(!t)return null;const n=t.dataset.fieldCache,r=t.dataset.row;if(!n||!r)return null;const o=parseInt(r,10);if(isNaN(o))return null;const i=this.columns.findIndex(e=>e.field===n);return-1===i?null:{row:o,col:i}}getSelectionAsText(e){const{columns:t,rows:n}=this.#l(e);return 0===t.length||0===n.length?"":this.#a(t,n,e)}async copy(e){const{columns:t,rows:n}=this.#l(e);if(0===t.length||0===n.length)return"";const r=this.#a(t,n,e);return await g(r),this.lastCopied={text:r,timestamp:Date.now()},this.emit("copy",{text:r,rowCount:n.length,columnCount:t.length}),r}async copyRows(e,t){return 0===e.length?"":this.copy({...t,rowIndices:e})}async paste(){const e=await async function(){try{return await navigator.clipboard.readText()}catch{return""}}();return e?m(e,this.config):null}getLastCopied(){return this.lastCopied}}export{w as ClipboardPlugin,p as defaultPasteHandler};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|