@toolbox-web/grid 1.30.2 → 1.31.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/README.md +1 -1
- 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/internal/dom-builder.d.ts +3 -3
- package/lib/core/plugin/base-plugin.d.ts +31 -8
- package/lib/core/plugin/plugin-manager.d.ts +2 -2
- package/lib/core/types.d.ts +16 -1
- package/lib/plugins/clipboard/index.js +1 -1
- package/lib/plugins/clipboard/index.js.map +1 -1
- package/lib/plugins/column-virtualization/index.js +1 -1
- package/lib/plugins/column-virtualization/index.js.map +1 -1
- package/lib/plugins/context-menu/index.js +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/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 +1 -1
- package/lib/plugins/master-detail/index.js.map +1 -1
- package/lib/plugins/multi-sort/MultiSortPlugin.d.ts +8 -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 +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/PivotPlugin.d.ts +43 -1
- package/lib/plugins/pivot/index.d.ts +1 -1
- package/lib/plugins/pivot/index.js +1 -1
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/pivot/pivot-engine.d.ts +21 -2
- package/lib/plugins/pivot/pivot-model.d.ts +6 -3
- package/lib/plugins/pivot/pivot-panel.d.ts +8 -3
- package/lib/plugins/pivot/pivot-rows.d.ts +3 -3
- package/lib/plugins/pivot/types.d.ts +121 -8
- package/lib/plugins/print/index.js +1 -1
- package/lib/plugins/print/index.js.map +1 -1
- package/lib/plugins/reorder-columns/index.js +1 -1
- package/lib/plugins/reorder-columns/index.js.map +1 -1
- 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 +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/server-side/index.js +1 -1
- package/lib/plugins/server-side/index.js.map +1 -1
- package/lib/plugins/tooltip/index.js +1 -1
- package/lib/plugins/tooltip/index.js.map +1 -1
- package/lib/plugins/tree/index.js +1 -1
- package/lib/plugins/tree/index.js.map +1 -1
- package/lib/plugins/undo-redo/index.js +1 -1
- package/lib/plugins/undo-redo/index.js.map +1 -1
- package/lib/plugins/visibility/index.js +1 -1
- package/lib/plugins/visibility/index.js.map +1 -1
- package/package.json +1 -1
- package/themes/dg-theme-bootstrap.css +8 -1
- package/themes/dg-theme-large.css +3 -1
- package/themes/dg-theme-material.css +3 -1
- package/themes/dg-theme-standard.css +5 -0
- package/themes/dg-theme-vibrant.css +5 -0
- 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/context-menu.umd.js +1 -1
- package/umd/plugins/context-menu.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/filtering.umd.js +1 -1
- package/umd/plugins/filtering.umd.js.map +1 -1
- package/umd/plugins/grouping-rows.umd.js +1 -1
- package/umd/plugins/grouping-rows.umd.js.map +1 -1
- package/umd/plugins/master-detail.umd.js +1 -1
- package/umd/plugins/master-detail.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/pivot.umd.js +1 -1
- package/umd/plugins/pivot.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-rows.umd.js +1 -1
- package/umd/plugins/reorder-rows.umd.js.map +1 -1
- package/umd/plugins/tree.umd.js +1 -1
- package/umd/plugins/tree.umd.js.map +1 -1
- package/umd/plugins/visibility.umd.js +1 -1
- package/umd/plugins/visibility.umd.js.map +1 -1
|
@@ -66,7 +66,7 @@ export interface ShellHeaderOptions {
|
|
|
66
66
|
title?: string;
|
|
67
67
|
hasPanels: boolean;
|
|
68
68
|
isPanelOpen: boolean;
|
|
69
|
-
toolPanelIcon
|
|
69
|
+
toolPanelIcon?: string;
|
|
70
70
|
/** Config toolbar contents with render function (pre-sorted by order) */
|
|
71
71
|
configButtons: Array<{
|
|
72
72
|
id: string;
|
|
@@ -88,8 +88,8 @@ export declare function buildShellHeader(options: ShellHeaderOptions): HTMLDivEl
|
|
|
88
88
|
export interface ShellBodyOptions {
|
|
89
89
|
position: 'left' | 'right';
|
|
90
90
|
isPanelOpen: boolean;
|
|
91
|
-
expandIcon
|
|
92
|
-
collapseIcon
|
|
91
|
+
expandIcon?: string;
|
|
92
|
+
collapseIcon?: string;
|
|
93
93
|
/** Sorted panels for accordion */
|
|
94
94
|
panels: Array<{
|
|
95
95
|
id: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DiagnosticCode } from '../internal/diagnostics';
|
|
2
|
-
import { ColumnConfig, ColumnState, GridPlugin, HeaderContentDefinition, IconValue, PluginNameMap, ToolPanelDefinition
|
|
2
|
+
import { ColumnConfig, ColumnState, GridIcons, GridPlugin, HeaderContentDefinition, IconValue, PluginNameMap, ToolPanelDefinition } from '../types';
|
|
3
3
|
import { AfterCellRenderContext, AfterRowRenderContext, CellClickEvent, CellEditor, CellMouseEvent, CellRenderer, GridElementRef, HeaderClickEvent, HeaderRenderer, PluginQuery, RowClickEvent, ScrollEvent } from './types';
|
|
4
4
|
export { PLUGIN_QUERIES } from './types';
|
|
5
5
|
export type { AfterCellRenderContext, AfterRowRenderContext, CellClickEvent, CellCoords, CellEditor, CellMouseEvent, CellRenderer, ContextMenuItem, ContextMenuParams, GridElementRef, HeaderClickEvent, HeaderRenderer, KeyboardModifiers, PluginCellRenderContext, PluginQuery, RowClickEvent, ScrollEvent, } from './types';
|
|
@@ -199,7 +199,7 @@ export interface PluginConfigRule<TConfig = unknown> {
|
|
|
199
199
|
*
|
|
200
200
|
* @category Plugin Development
|
|
201
201
|
*/
|
|
202
|
-
export type HookName = 'processColumns' | 'processRows' | 'afterRender' | 'afterCellRender' | 'afterRowRender' | 'onCellClick' | 'onCellMouseDown' | 'onCellMouseMove' | 'onCellMouseUp' | 'onKeyDown' | 'onScroll' | 'onScrollRender';
|
|
202
|
+
export type HookName = 'processColumns' | 'processRows' | 'afterRender' | 'afterCellRender' | 'afterRowRender' | 'onCellClick' | 'onCellMouseDown' | 'onCellMouseMove' | 'onCellMouseUp' | 'onHeaderClick' | 'onKeyDown' | 'onRowClick' | 'onScroll' | 'onScrollRender';
|
|
203
203
|
/**
|
|
204
204
|
* Static metadata about a plugin's capabilities and requirements.
|
|
205
205
|
* Declared as a static property on plugin classes.
|
|
@@ -276,6 +276,8 @@ export interface PluginManifest<TConfig = unknown> {
|
|
|
276
276
|
*/
|
|
277
277
|
events?: EventDefinition[];
|
|
278
278
|
}
|
|
279
|
+
/** Convert camelCase icon key to kebab-case data-icon attribute value. */
|
|
280
|
+
export declare function toIconAttr(key: string): string;
|
|
279
281
|
/**
|
|
280
282
|
* Abstract base class for all grid plugins.
|
|
281
283
|
*
|
|
@@ -574,7 +576,7 @@ export declare abstract class BaseGridPlugin<TConfig = unknown> implements GridP
|
|
|
574
576
|
* Get the grid-level icons configuration.
|
|
575
577
|
* Returns merged icons (user config + defaults).
|
|
576
578
|
*/
|
|
577
|
-
protected get gridIcons():
|
|
579
|
+
protected get gridIcons(): Required<GridIcons>;
|
|
578
580
|
/**
|
|
579
581
|
* Check if animations are enabled at the grid level.
|
|
580
582
|
* Respects gridConfig.animation.mode and the CSS variable set by the grid.
|
|
@@ -609,19 +611,40 @@ export declare abstract class BaseGridPlugin<TConfig = unknown> implements GridP
|
|
|
609
611
|
* Resolve an icon value to string or HTMLElement.
|
|
610
612
|
* Checks plugin config first, then grid-level icons, then defaults.
|
|
611
613
|
*
|
|
614
|
+
* @deprecated Use `setIcon(element, iconKey)` instead. Will be removed in v2.0.0.
|
|
612
615
|
* @param iconKey - The icon key in GridIcons (e.g., 'expand', 'collapse')
|
|
613
616
|
* @param pluginOverride - Optional plugin-level override
|
|
614
617
|
* @returns The resolved icon value
|
|
615
618
|
*/
|
|
616
|
-
protected resolveIcon(iconKey: keyof
|
|
619
|
+
protected resolveIcon(iconKey: keyof GridIcons, pluginOverride?: IconValue): IconValue;
|
|
617
620
|
/**
|
|
618
|
-
* Set an icon
|
|
619
|
-
*
|
|
621
|
+
* Set an icon on an element using the CSS-first hybrid approach.
|
|
622
|
+
*
|
|
623
|
+
* Sets `data-icon` for CSS pseudo-element rendering and `data-expanded` for
|
|
624
|
+
* expand/collapse toggle elements. Only injects DOM content when a JS override
|
|
625
|
+
* is present (via `gridConfig.icons` or `pluginOverride`), which naturally
|
|
626
|
+
* suppresses the CSS `::before` via the `:empty` selector.
|
|
620
627
|
*
|
|
621
628
|
* @param element - The element to set the icon on
|
|
622
|
-
* @param
|
|
629
|
+
* @param iconKey - The icon key in GridIcons (e.g., 'expand', 'collapse')
|
|
630
|
+
* @param pluginOverride - Optional plugin-level override (string or HTMLElement)
|
|
631
|
+
*/
|
|
632
|
+
protected setIcon(element: HTMLElement, iconKey: keyof GridIcons, pluginOverride?: IconValue): void;
|
|
633
|
+
/**
|
|
634
|
+
* Create or replace a sort indicator on a header cell.
|
|
635
|
+
*
|
|
636
|
+
* Handles the full lifecycle: removes any existing indicator, creates a new
|
|
637
|
+
* `<span part="sort-indicator" class="sort-indicator">` with the appropriate
|
|
638
|
+
* icon, sets `aria-sort` / `data-sort` attributes, and inserts it before the
|
|
639
|
+
* filter button or resize handle.
|
|
640
|
+
*
|
|
641
|
+
* Plugins decide **which** cells and **when** — this method handles **how**.
|
|
642
|
+
*
|
|
643
|
+
* @param cell - The header cell element
|
|
644
|
+
* @param direction - `'asc'` | `'desc'` for sorted, `null` for unsorted idle state
|
|
645
|
+
* @returns The created indicator element (useful for appending badges, etc.)
|
|
623
646
|
*/
|
|
624
|
-
protected
|
|
647
|
+
protected updateSortIndicator(cell: Element, direction: 'asc' | 'desc' | null): HTMLElement;
|
|
625
648
|
/**
|
|
626
649
|
* Log a warning with an optional diagnostic code.
|
|
627
650
|
*
|
|
@@ -3,8 +3,8 @@ import { AfterCellRenderContext, AfterRowRenderContext, BaseGridPlugin, CellClic
|
|
|
3
3
|
/**
|
|
4
4
|
* Manages plugins for a single grid instance.
|
|
5
5
|
*
|
|
6
|
-
* Plugins are executed in array order
|
|
7
|
-
*
|
|
6
|
+
* Plugins are executed in array order by default. Use `manifest.hookPriority`
|
|
7
|
+
* to override execution order for specific hooks.
|
|
8
8
|
*/
|
|
9
9
|
export declare class PluginManager {
|
|
10
10
|
#private;
|
package/lib/core/types.d.ts
CHANGED
|
@@ -2155,7 +2155,14 @@ export interface GridConfig<TRow = any> {
|
|
|
2155
2155
|
shell?: ShellConfig;
|
|
2156
2156
|
/**
|
|
2157
2157
|
* Grid-wide icon configuration.
|
|
2158
|
-
*
|
|
2158
|
+
*
|
|
2159
|
+
* The grid uses a **CSS-first hybrid icon system**:
|
|
2160
|
+
* - **Default (CSS):** Icons render via `--tbw-icon-*` CSS custom properties on `tbw-grid`.
|
|
2161
|
+
* Override them in your theme CSS — no JavaScript needed.
|
|
2162
|
+
* - **JS override:** Setting `gridConfig.icons` takes precedence over CSS for any key provided.
|
|
2163
|
+
* Use this for dynamic icons, icon libraries, or `HTMLElement` instances.
|
|
2164
|
+
*
|
|
2165
|
+
* All icons are optional — sensible defaults are used when not specified.
|
|
2159
2166
|
* Plugins will use these by default but can override with their own config.
|
|
2160
2167
|
*/
|
|
2161
2168
|
icons?: GridIcons;
|
|
@@ -2801,6 +2808,14 @@ export type IconValue = string | HTMLElement;
|
|
|
2801
2808
|
* Grid-wide icon configuration.
|
|
2802
2809
|
* All icons are optional - sensible defaults are used when not specified.
|
|
2803
2810
|
*
|
|
2811
|
+
* The grid uses a **CSS-first hybrid approach**: icons render via `--tbw-icon-*` CSS
|
|
2812
|
+
* custom properties by default. Setting `gridConfig.icons` provides JS overrides that
|
|
2813
|
+
* take precedence over CSS (the JS icon injects DOM content, suppressing the CSS
|
|
2814
|
+
* `::before` pseudo-element via the `:empty` selector).
|
|
2815
|
+
*
|
|
2816
|
+
* **Use CSS** for static theming (text, emoji, SVG masks via `--tbw-icon-*-mask`).
|
|
2817
|
+
* **Use JS** for dynamic icons, icon libraries, or `HTMLElement` instances.
|
|
2818
|
+
*
|
|
2804
2819
|
* Icons can be text (including emoji), HTML strings (for SVG), or HTMLElement instances.
|
|
2805
2820
|
*
|
|
2806
2821
|
* @example
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function e(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function t(t,n,r,i){return`${e(r,i)} ${t}: ${n}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(t)}`}const n=/* @__PURE__ */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"]),r=/^on\w+$/i,i=/* @__PURE__ */new Set(["href","src","action","formaction","data","srcdoc","xlink:href","poster","srcset"]),o=/^\s*(javascript|vbscript|data|blob):/i;function s(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=[],s=e.querySelectorAll("*");for(const l of s){const e=l.tagName.toLowerCase();if(n.has(e)){t.push(l);continue}if("svg"===e||"http://www.w3.org/2000/svg"===l.namespaceURI){if(Array.from(l.attributes).some(e=>r.test(e.name)||"href"===e.name||"xlink:href"===e.name)){t.push(l);continue}}const s=[];for(const t of l.attributes){const e=t.name.toLowerCase();r.test(e)?s.push(t.name):(i.has(e)&&o.test(t.value)||"style"===e&&/expression\s*\(|javascript:|behavior\s*:/i.test(t.value))&&s.push(t.name)}s.forEach(e=>l.removeAttribute(e))}t.forEach(e=>e.remove())}(t.content),t.innerHTML}const l='<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>',a={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:l,filterActive:l,print:"🖨️"};class c{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)}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{...a,...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}resolveIcon(e,t){return void 0!==t?t:this.gridIcons[e]}setIcon(e,t){"string"==typeof t?e.innerHTML=s(t):t instanceof HTMLElement&&(e.innerHTML="",e.appendChild(t.cloneNode(!0)))}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 d(e){try{return await navigator.clipboard.writeText(e),!0}catch(s){n="TBW100",r=`Clipboard API failed: ${s}`,console.warn(t(n,r,i,o));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,i,o}function h(e,t){const n=t.delimiter??"\t",r=t.newline??"\n",i=e.replace(/\r\n/g,"\n").replace(/\r/g,"\n"),o=[];let s=[],l="",a=!1;for(let c=0;c<i.length;c++){const e=i[c];'"'!==e||a?'"'===e&&a?'"'===i[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()))&&o.push(s),s=[]):(s.push(l),l=""):a=!0}return s.push(l),(s.length>1||s.some(e=>""!==e.trim()))&&o.push(s),o}function f(e,t){const{rows:n,target:r,fields:i}=e;if(!r)return;const o=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=[...o],u=r.bounds?r.bounds.endRow:1/0;n.forEach((e,t)=>{const n=r.row+t;if(!(n>u)){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=i[t];r&&a.get(r)&&(c[n][r]=e)})}}),t.rows=c}class g extends c{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.#t(e),{signal:this.disconnectSignal})}detach(){this.lastCopied=null}onKeyDown(e){return!(!e.ctrlKey&&!e.metaKey||"c"!==e.key)&&(e.preventDefault(),this.#n(e.target),!0)}#n(e){const t=this.#r();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()}#t(e){const t=e.clipboardData?.getData("text/plain");if(!t)return;e.preventDefault();const n=h(t,this.config),r=this.#r(),i=r?.ranges?.[0],o=i?.from.row??0,s=i?.from.col??0,l=i&&("range"===r?.mode||"row"===r?.mode)&&(i.from.row!==i.to.row||i.from.col!==i.to.col)?{endRow:i.to.row,endCol:i.to.col}:null,a=l?.endCol??this.visibleColumns.length-1,c=this.visibleColumns[s],u=c?{row:o,col:s,field:c.field,bounds:l}:null,d=[],f=n[0]?.length??0;for(let h=0;h<f&&s+h<=a;h++){const e=this.visibleColumns[s+h];e&&d.push(e.field)}const g={rows:n,text:t,target:u,fields:d};this.emit("paste",g),this.#o(g)}#o(e){if(!this.grid)return;const{pasteHandler:t}=this.config;if(null===t)return;(t??f)(e,this.grid)}#r(){const e=this.grid?.query("getSelection");return e?.[0]}#s(e){const t=this.#r();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),i=Math.max(e.from.col,e.to.col);n=u(this.visibleColumns.slice(r,i+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),i=Math.max(e.from.row,e.to.row);r=[];for(let t=n;t<=i;t++){const e=this.rows[t];e&&r.push(e)}}else r=this.rows;return{columns:n,rows:r}}#l(e,t,n){const r=n?.delimiter??this.config.delimiter??"\t",i=n?.newline??this.config.newline??"\n",o=n?.includeHeaders??this.config.includeHeaders??!1,s=n?.processCell??this.config.processCell,l=[];o&&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.#a(e,t,a)});l.push(t.join(r))}return l.join(i)}#a(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.#c(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)}#c(e,t){const n=this.gridElement;if(!n)return null;const r=this.rows.indexOf(t);if(-1===r)return null;const i=n.querySelector(`.cell[data-row="${r}"][data-field="${e}"]`);return i?i.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 i=parseInt(r,10);if(isNaN(i))return null;const o=this.columns.findIndex(e=>e.field===n);return-1===o?null:{row:i,col:o}}getSelectionAsText(e){const{columns:t,rows:n}=this.#s(e);return 0===t.length||0===n.length?"":this.#l(t,n,e)}async copy(e){const{columns:t,rows:n}=this.#s(e);if(0===t.length||0===n.length)return"";const r=this.#l(t,n,e);return await d(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?h(e,this.config):null}getLastCopied(){return this.lastCopied}}export{g as ClipboardPlugin,f as defaultPasteHandler};
|
|
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)}`}["__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"].map(e=>e.split("").reverse().join(""));const n=/* @__PURE__ */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"]),r=/^on\w+$/i,o=/* @__PURE__ */new Set(["href","src","action","formaction","data","srcdoc","xlink:href","poster","srcset"]),i=/^\s*(javascript|vbscript|data|blob):/i;function s(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=[],s=e.querySelectorAll("*");for(const l of s){const e=l.tagName.toLowerCase();if(n.has(e)){t.push(l);continue}if("svg"===e||"http://www.w3.org/2000/svg"===l.namespaceURI){if(Array.from(l.attributes).some(e=>r.test(e.name)||"href"===e.name||"xlink:href"===e.name)){t.push(l);continue}}const s=[];for(const t of l.attributes){const e=t.name.toLowerCase();r.test(e)?s.push(t.name):(o.has(e)&&i.test(t.value)||"style"===e&&/expression\s*\(|javascript:|behavior\s*:/i.test(t.value))&&s.push(t.name)}s.forEach(e=>l.removeAttribute(e))}t.forEach(e=>e.remove())}(t.content),t.innerHTML}const l='<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>',a={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:l,filterActive:l,print:"🖨️"};class c{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)}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{...a,...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}resolveIcon(e,t){return void 0!==t?t:this.gridIcons[e]}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=s(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 d(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 u(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 h(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 f(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 g extends c{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}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=h(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=[],f=n[0]?.length??0;for(let h=0;h<f&&s+h<=a;h++){const e=this.visibleColumns[s+h];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??f)(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=d(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=d(this.visibleColumns.slice(r,o+1))}else n=d(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 u(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?h(e,this.config):null}getLastCopied(){return this.lastCopied}}export{g as ClipboardPlugin,f as defaultPasteHandler};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|