@toolbox-web/grid 2.1.0 → 2.2.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/index.js +1 -1
- package/index.js.map +1 -1
- package/lib/core/constants.d.ts +18 -0
- package/lib/core/internal/value-accessor.d.ts +33 -0
- package/lib/core/types.d.ts +114 -0
- 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 +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.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/index.js.map +1 -1
- 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 +1 -1
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/print/index.js.map +1 -1
- package/lib/plugins/reorder-columns/index.js.map +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.map +1 -1
- 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/index.js.map +1 -1
- package/package.json +1 -1
- package/public.d.ts +4 -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/grouping-columns.umd.js +1 -1
- package/umd/plugins/grouping-columns.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-rows.umd.js +1 -1
- package/umd/plugins/pinned-rows.umd.js.map +1 -1
- package/umd/plugins/pivot.umd.js +1 -1
- package/umd/plugins/pivot.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/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];
|
|
@@ -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
|
@@ -465,6 +465,8 @@ export interface InternalGrid<T = any> extends PublicGrid<T>, GridConfig<T> {
|
|
|
465
465
|
/** @internal Access the plugin manager's cached state. */
|
|
466
466
|
_pluginManager?: {
|
|
467
467
|
_hasRowStructurePlugins: boolean;
|
|
468
|
+
/** Emit an event on the plugin event bus (does not dispatch a DOM event). */
|
|
469
|
+
emitPluginEvent?: <D>(eventType: string, detail: D) => void;
|
|
468
470
|
};
|
|
469
471
|
_gridTemplate: string;
|
|
470
472
|
_virtualization: VirtualState;
|
|
@@ -792,6 +794,50 @@ export interface BaseColumnConfig<TRow = any, TValue = any> {
|
|
|
792
794
|
resizable?: boolean;
|
|
793
795
|
/** Optional custom comparator for sorting (a,b) -> number */
|
|
794
796
|
sortComparator?: (a: TValue, b: TValue, rowA: TRow, rowB: TRow) => number;
|
|
797
|
+
/**
|
|
798
|
+
* Compute the cell's value from the row. When defined, this is the single
|
|
799
|
+
* source of truth used by sorting, filtering, formatting, cell rendering,
|
|
800
|
+
* export, and clipboard — eliminating the need to duplicate value-extraction
|
|
801
|
+
* logic across `sortComparator`, `filterValue`, and per-renderer code.
|
|
802
|
+
*
|
|
803
|
+
* **Resolution precedence**:
|
|
804
|
+
* - **Sort**: `sortComparator` → `valueAccessor` → `row[field]`
|
|
805
|
+
* - **Filter**: `filterValue` → `valueAccessor` → `row[field]`
|
|
806
|
+
* - **Render / format / export / copy**: `valueAccessor` → `row[field]`
|
|
807
|
+
*
|
|
808
|
+
* The accessor is the *default* value source — per-column escape hatches
|
|
809
|
+
* (`sortComparator`, `filterValue`) still take precedence when set.
|
|
810
|
+
*
|
|
811
|
+
* Results are memoized per `(row identity, column field)` so accessors are
|
|
812
|
+
* free to be "slow but correct" (e.g. `array.find(...)`). Immutable row
|
|
813
|
+
* updates auto-invalidate; in-place mutations are invalidated by the grid's
|
|
814
|
+
* edit / transaction paths.
|
|
815
|
+
*
|
|
816
|
+
* Note: a `valueAccessor` without a paired `valueSetter` (planned API)
|
|
817
|
+
* implies the column is read-only — editors will not commit through it.
|
|
818
|
+
*
|
|
819
|
+
* @example
|
|
820
|
+
* ```typescript
|
|
821
|
+
* // Computed value from nested data
|
|
822
|
+
* {
|
|
823
|
+
* field: 'bolDate',
|
|
824
|
+
* header: 'BL date',
|
|
825
|
+
* valueAccessor: ({ row }) => {
|
|
826
|
+
* if (isCargo(row)) {
|
|
827
|
+
* return row.movements.find(m => m.operationType === 'LOAD')?.movementDate ?? null;
|
|
828
|
+
* }
|
|
829
|
+
* return row.movementDate ?? null;
|
|
830
|
+
* },
|
|
831
|
+
* filterType: 'date',
|
|
832
|
+
* // No need for sortComparator or filterValue — they fall back to the accessor.
|
|
833
|
+
* }
|
|
834
|
+
* ```
|
|
835
|
+
*/
|
|
836
|
+
valueAccessor?: (ctx: {
|
|
837
|
+
row: TRow;
|
|
838
|
+
column: ColumnConfig<TRow>;
|
|
839
|
+
rowIndex: number;
|
|
840
|
+
}) => TValue;
|
|
795
841
|
/** For select type - available options */
|
|
796
842
|
options?: Array<{
|
|
797
843
|
label: string;
|
|
@@ -1883,6 +1929,10 @@ export declare const FitModeEnum: {
|
|
|
1883
1929
|
readonly STRETCH: "stretch";
|
|
1884
1930
|
readonly FIXED: "fixed";
|
|
1885
1931
|
};
|
|
1932
|
+
/**
|
|
1933
|
+
* Column sizing mode — determines how columns fill the available grid width.
|
|
1934
|
+
* Use `FitModeEnum` to access individual values by key.
|
|
1935
|
+
*/
|
|
1886
1936
|
export type FitMode = (typeof FitModeEnum)[keyof typeof FitModeEnum];
|
|
1887
1937
|
/**
|
|
1888
1938
|
* Minimal plugin interface for type-checking.
|
|
@@ -2615,6 +2665,42 @@ export interface DataChangeDetail {
|
|
|
2615
2665
|
/** Total number of source rows (before filtering/grouping) */
|
|
2616
2666
|
sourceRowCount: number;
|
|
2617
2667
|
}
|
|
2668
|
+
/**
|
|
2669
|
+
* Detail payload for the `tbw-scroll` event.
|
|
2670
|
+
*
|
|
2671
|
+
* Dispatched on the grid host whenever the vertical viewport scrolls
|
|
2672
|
+
* (rAF-batched — at most one per frame). Use to trigger pagination,
|
|
2673
|
+
* defer heavy cell content rendering, dismiss overlays, or sync a
|
|
2674
|
+
* scroll-tracking UI outside the grid.
|
|
2675
|
+
*
|
|
2676
|
+
* For server-side pagination of large datasets, prefer
|
|
2677
|
+
* `ServerSidePlugin` which handles block fetching out of the box.
|
|
2678
|
+
*
|
|
2679
|
+
* @example
|
|
2680
|
+
* ```typescript
|
|
2681
|
+
* grid.addEventListener('tbw-scroll', (e) => {
|
|
2682
|
+
* const { scrollTop, scrollHeight, clientHeight } = e.detail;
|
|
2683
|
+
* if (scrollTop + clientHeight >= scrollHeight - 200) loadMore();
|
|
2684
|
+
* });
|
|
2685
|
+
* ```
|
|
2686
|
+
*
|
|
2687
|
+
* @see {@link DataGridEventMap} for all event types
|
|
2688
|
+
* @category Events
|
|
2689
|
+
*/
|
|
2690
|
+
export interface TbwScrollDetail {
|
|
2691
|
+
/** Current vertical scroll offset in pixels (faux scrollbar). */
|
|
2692
|
+
scrollTop: number;
|
|
2693
|
+
/** Total scrollable height in pixels (faux scrollbar). */
|
|
2694
|
+
scrollHeight: number;
|
|
2695
|
+
/** Visible viewport height in pixels (faux scrollbar). */
|
|
2696
|
+
clientHeight: number;
|
|
2697
|
+
/**
|
|
2698
|
+
* Axis that triggered this dispatch. Currently always `'vertical'`;
|
|
2699
|
+
* `'horizontal'` is reserved for a future opt-in dispatch and is
|
|
2700
|
+
* declared up-front so consumer narrowing remains source-compatible.
|
|
2701
|
+
*/
|
|
2702
|
+
direction: 'vertical' | 'horizontal';
|
|
2703
|
+
}
|
|
2618
2704
|
/**
|
|
2619
2705
|
* Indicates the origin of a data change.
|
|
2620
2706
|
* Used to prevent infinite loops in cascade update handlers.
|
|
@@ -3625,6 +3711,34 @@ export interface DataGridEventMap<TRow = unknown> {
|
|
|
3625
3711
|
* @group Core Events
|
|
3626
3712
|
*/
|
|
3627
3713
|
'data-change': DataChangeDetail;
|
|
3714
|
+
/**
|
|
3715
|
+
* Fired when the grid's viewport is scrolled vertically (rAF-batched).
|
|
3716
|
+
* Use to trigger pagination, defer heavy cell content, dismiss overlays,
|
|
3717
|
+
* or sync external UI to the grid's scroll position.
|
|
3718
|
+
*
|
|
3719
|
+
* For server-side pagination of large datasets, prefer the
|
|
3720
|
+
* `ServerSidePlugin` — it handles block fetching out of the box.
|
|
3721
|
+
*
|
|
3722
|
+
* @example
|
|
3723
|
+
* ```typescript
|
|
3724
|
+
* // Infinite scroll
|
|
3725
|
+
* grid.on('tbw-scroll', ({ scrollTop, scrollHeight, clientHeight }) => {
|
|
3726
|
+
* if (scrollTop + clientHeight >= scrollHeight - 200) loadMore();
|
|
3727
|
+
* });
|
|
3728
|
+
*
|
|
3729
|
+
* // Defer heavy cell content (Angular @defer style)
|
|
3730
|
+
* grid.on('tbw-scroll', ({ scrollTop }) => {
|
|
3731
|
+
* updateVisibleHeavyCells(scrollTop);
|
|
3732
|
+
* });
|
|
3733
|
+
*
|
|
3734
|
+
* // Dismiss tooltip/popover on scroll
|
|
3735
|
+
* grid.on('tbw-scroll', () => closeOpenOverlays());
|
|
3736
|
+
* ```
|
|
3737
|
+
*
|
|
3738
|
+
* @see {@link TbwScrollDetail}
|
|
3739
|
+
* @group Core Events
|
|
3740
|
+
*/
|
|
3741
|
+
'tbw-scroll': TbwScrollDetail;
|
|
3628
3742
|
/**
|
|
3629
3743
|
* Emitted when a cell with an external view renderer (React, Angular, Vue component)
|
|
3630
3744
|
* needs to be mounted. Framework adapters listen for this event internally.
|
|
@@ -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.meta?.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
|