@toolbox-web/grid 0.4.1 → 0.5.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 +9 -13
- package/all.js +1678 -1588
- package/all.js.map +1 -1
- package/index.js +762 -568
- package/index.js.map +1 -1
- package/lib/core/grid.d.ts +21 -0
- package/lib/core/grid.d.ts.map +1 -1
- package/lib/core/internal/config-manager.d.ts +1 -0
- package/lib/core/internal/config-manager.d.ts.map +1 -1
- package/lib/core/internal/dom-builder.d.ts +2 -0
- package/lib/core/internal/dom-builder.d.ts.map +1 -1
- package/lib/core/internal/header.d.ts.map +1 -1
- package/lib/core/internal/keyboard.d.ts.map +1 -1
- package/lib/core/internal/resize.d.ts.map +1 -1
- package/lib/core/internal/rows.d.ts.map +1 -1
- package/lib/core/internal/shell.d.ts +19 -13
- package/lib/core/internal/shell.d.ts.map +1 -1
- package/lib/core/internal/utils.d.ts +1 -0
- package/lib/core/internal/utils.d.ts.map +1 -1
- package/lib/core/plugin/base-plugin.d.ts +70 -3
- package/lib/core/plugin/base-plugin.d.ts.map +1 -1
- package/lib/core/plugin/expander-column.d.ts +51 -0
- package/lib/core/plugin/expander-column.d.ts.map +1 -0
- package/lib/core/plugin/plugin-manager.d.ts +6 -2
- package/lib/core/plugin/plugin-manager.d.ts.map +1 -1
- package/lib/core/plugin/types.d.ts +117 -1
- package/lib/core/plugin/types.d.ts.map +1 -1
- package/lib/core/types.d.ts +10 -5
- package/lib/core/types.d.ts.map +1 -1
- package/lib/plugins/clipboard/ClipboardPlugin.d.ts +5 -4
- package/lib/plugins/clipboard/ClipboardPlugin.d.ts.map +1 -1
- package/lib/plugins/clipboard/index.d.ts +1 -1
- package/lib/plugins/clipboard/index.d.ts.map +1 -1
- package/lib/plugins/clipboard/index.js +295 -190
- package/lib/plugins/clipboard/index.js.map +1 -1
- package/lib/plugins/clipboard/types.d.ts +72 -2
- package/lib/plugins/clipboard/types.d.ts.map +1 -1
- package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts +0 -1
- package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -1
- package/lib/plugins/column-virtualization/index.js +143 -56
- package/lib/plugins/column-virtualization/index.js.map +1 -1
- package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +0 -1
- package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
- package/lib/plugins/context-menu/index.js +189 -102
- package/lib/plugins/context-menu/index.js.map +1 -1
- package/lib/plugins/editing/EditingPlugin.d.ts +2 -7
- package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
- package/lib/plugins/editing/index.js +227 -150
- package/lib/plugins/editing/index.js.map +1 -1
- package/lib/plugins/export/ExportPlugin.d.ts +0 -1
- package/lib/plugins/export/ExportPlugin.d.ts.map +1 -1
- package/lib/plugins/export/index.js +184 -97
- package/lib/plugins/export/index.js.map +1 -1
- package/lib/plugins/filtering/FilteringPlugin.d.ts +14 -3
- package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
- package/lib/plugins/filtering/index.js +296 -176
- package/lib/plugins/filtering/index.js.map +1 -1
- package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +2 -2
- package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
- package/lib/plugins/grouping-columns/grouping-columns.d.ts +1 -1
- package/lib/plugins/grouping-columns/grouping-columns.d.ts.map +1 -1
- package/lib/plugins/grouping-columns/index.js +169 -61
- package/lib/plugins/grouping-columns/index.js.map +1 -1
- package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts +14 -2
- package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts.map +1 -1
- package/lib/plugins/grouping-rows/index.js +243 -140
- package/lib/plugins/grouping-rows/index.js.map +1 -1
- package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +13 -11
- package/lib/plugins/master-detail/MasterDetailPlugin.d.ts.map +1 -1
- package/lib/plugins/master-detail/index.js +278 -196
- package/lib/plugins/master-detail/index.js.map +1 -1
- package/lib/plugins/master-detail/types.d.ts +0 -10
- package/lib/plugins/master-detail/types.d.ts.map +1 -1
- package/lib/plugins/multi-sort/MultiSortPlugin.d.ts +1 -2
- package/lib/plugins/multi-sort/MultiSortPlugin.d.ts.map +1 -1
- package/lib/plugins/multi-sort/index.js +125 -40
- package/lib/plugins/multi-sort/index.js.map +1 -1
- package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +0 -1
- package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -1
- package/lib/plugins/pinned-columns/index.js +156 -75
- package/lib/plugins/pinned-columns/index.js.map +1 -1
- package/lib/plugins/pinned-columns/pinned-columns.d.ts +2 -2
- package/lib/plugins/pinned-columns/pinned-columns.d.ts.map +1 -1
- package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts +1 -2
- package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -1
- package/lib/plugins/pinned-rows/index.js +202 -117
- package/lib/plugins/pinned-rows/index.js.map +1 -1
- package/lib/plugins/pivot/PivotPlugin.d.ts +26 -4
- package/lib/plugins/pivot/PivotPlugin.d.ts.map +1 -1
- package/lib/plugins/pivot/index.js +413 -314
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/pivot/pivot-rows.d.ts +2 -1
- package/lib/plugins/pivot/pivot-rows.d.ts.map +1 -1
- package/lib/plugins/reorder/ReorderPlugin.d.ts +13 -10
- package/lib/plugins/reorder/ReorderPlugin.d.ts.map +1 -1
- package/lib/plugins/reorder/index.d.ts +1 -1
- package/lib/plugins/reorder/index.d.ts.map +1 -1
- package/lib/plugins/reorder/index.js +296 -223
- package/lib/plugins/reorder/index.js.map +1 -1
- package/lib/plugins/selection/SelectionPlugin.d.ts +21 -3
- package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
- package/lib/plugins/selection/index.d.ts +2 -2
- package/lib/plugins/selection/index.d.ts.map +1 -1
- package/lib/plugins/selection/index.js +282 -141
- package/lib/plugins/selection/index.js.map +1 -1
- package/lib/plugins/selection/types.d.ts +24 -0
- package/lib/plugins/selection/types.d.ts.map +1 -1
- package/lib/plugins/server-side/ServerSidePlugin.d.ts +0 -1
- package/lib/plugins/server-side/ServerSidePlugin.d.ts.map +1 -1
- package/lib/plugins/server-side/index.js +96 -9
- package/lib/plugins/server-side/index.js.map +1 -1
- package/lib/plugins/tree/TreePlugin.d.ts +5 -1
- package/lib/plugins/tree/TreePlugin.d.ts.map +1 -1
- package/lib/plugins/tree/index.js +209 -113
- package/lib/plugins/tree/index.js.map +1 -1
- package/lib/plugins/tree/types.d.ts +0 -10
- package/lib/plugins/tree/types.d.ts.map +1 -1
- package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +0 -1
- package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts.map +1 -1
- package/lib/plugins/undo-redo/index.js +98 -11
- package/lib/plugins/undo-redo/index.js.map +1 -1
- package/lib/plugins/visibility/VisibilityPlugin.d.ts +7 -4
- package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -1
- package/lib/plugins/visibility/index.js +155 -64
- package/lib/plugins/visibility/index.js.map +1 -1
- package/package.json +1 -1
- package/themes/dg-theme-bootstrap.css +55 -53
- package/themes/dg-theme-contrast.css +42 -40
- package/themes/dg-theme-large.css +38 -37
- package/themes/dg-theme-material.css +54 -52
- package/themes/dg-theme-standard.css +19 -17
- package/themes/dg-theme-vibrant.css +16 -14
- package/umd/grid.all.umd.js +23 -24
- package/umd/grid.all.umd.js.map +1 -1
- package/umd/grid.umd.js +12 -11
- package/umd/grid.umd.js.map +1 -1
- package/umd/plugins/clipboard.umd.js +5 -7
- package/umd/plugins/clipboard.umd.js.map +1 -1
- package/umd/plugins/column-virtualization.umd.js +1 -1
- package/umd/plugins/column-virtualization.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/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/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/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/pivot.umd.js +1 -1
- package/umd/plugins/pivot.umd.js.map +1 -1
- package/umd/plugins/reorder.umd.js +1 -1
- package/umd/plugins/reorder.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/tree.umd.js +1 -1
- package/umd/plugins/tree.umd.js.map +1 -1
- package/umd/plugins/undo-redo.umd.js +1 -1
- package/umd/plugins/undo-redo.umd.js.map +1 -1
- package/umd/plugins/visibility.umd.js +1 -1
- package/umd/plugins/visibility.umd.js.map +1 -1
- package/lib/core/internal/editing.d.ts +0 -76
- package/lib/core/internal/editing.d.ts.map +0 -1
|
@@ -25,8 +25,11 @@ class I {
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
static dependencies;
|
|
28
|
-
/**
|
|
29
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Plugin version - defaults to grid version for built-in plugins.
|
|
30
|
+
* Third-party plugins can override with their own semver.
|
|
31
|
+
*/
|
|
32
|
+
version = typeof __GRID_VERSION__ < "u" ? __GRID_VERSION__ : "dev";
|
|
30
33
|
/** CSS styles to inject into the grid's shadow DOM */
|
|
31
34
|
styles;
|
|
32
35
|
/** Custom cell renderers keyed by type name */
|
|
@@ -110,8 +113,16 @@ class I {
|
|
|
110
113
|
/**
|
|
111
114
|
* Emit a custom event from the grid.
|
|
112
115
|
*/
|
|
113
|
-
emit(e,
|
|
114
|
-
this.grid?.dispatchEvent?.(new CustomEvent(e, { detail:
|
|
116
|
+
emit(e, t) {
|
|
117
|
+
this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Emit a cancelable custom event from the grid.
|
|
121
|
+
* @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
|
|
122
|
+
*/
|
|
123
|
+
emitCancelable(e, t) {
|
|
124
|
+
const n = new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 });
|
|
125
|
+
return this.grid?.dispatchEvent?.(n), n.defaultPrevented;
|
|
115
126
|
}
|
|
116
127
|
/**
|
|
117
128
|
* Request a re-render of the grid.
|
|
@@ -119,6 +130,14 @@ class I {
|
|
|
119
130
|
requestRender() {
|
|
120
131
|
this.grid?.requestRender?.();
|
|
121
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Request a re-render and restore focus styling afterward.
|
|
135
|
+
* Use this when a plugin action (like expand/collapse) triggers a render
|
|
136
|
+
* but needs to maintain keyboard navigation focus.
|
|
137
|
+
*/
|
|
138
|
+
requestRenderWithFocus() {
|
|
139
|
+
this.grid?.requestRenderWithFocus?.();
|
|
140
|
+
}
|
|
122
141
|
/**
|
|
123
142
|
* Request a lightweight style update without rebuilding DOM.
|
|
124
143
|
* Use this instead of requestRender() when only CSS classes need updating.
|
|
@@ -153,10 +172,34 @@ class I {
|
|
|
153
172
|
return this.grid?._visibleColumns ?? [];
|
|
154
173
|
}
|
|
155
174
|
/**
|
|
156
|
-
* Get the
|
|
175
|
+
* Get the grid as an HTMLElement for direct DOM operations.
|
|
176
|
+
* Use sparingly - prefer the typed GridElementRef API when possible.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* const width = this.gridElement.clientWidth;
|
|
181
|
+
* this.gridElement.classList.add('my-plugin-active');
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
get gridElement() {
|
|
185
|
+
return this.grid;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get the render root of the grid for DOM queries.
|
|
189
|
+
* @deprecated Use `gridElement` instead. This getter exists only for backward compatibility.
|
|
190
|
+
*
|
|
191
|
+
* With Shadow DOM removed, the grid element itself is the render root.
|
|
192
|
+
* All new code should use `this.gridElement` for DOM queries.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* // OLD (deprecated)
|
|
196
|
+
* const rows = this.shadowRoot?.querySelector('.rows');
|
|
197
|
+
*
|
|
198
|
+
* // NEW (preferred)
|
|
199
|
+
* const rows = this.gridElement.querySelector('.rows');
|
|
157
200
|
*/
|
|
158
201
|
get shadowRoot() {
|
|
159
|
-
return this.
|
|
202
|
+
return this.gridElement;
|
|
160
203
|
}
|
|
161
204
|
/**
|
|
162
205
|
* Get the disconnect signal for event listener cleanup.
|
|
@@ -186,6 +229,51 @@ class I {
|
|
|
186
229
|
const e = this.grid?.gridConfig?.icons ?? {};
|
|
187
230
|
return { ...C, ...e };
|
|
188
231
|
}
|
|
232
|
+
// #region Animation Helpers
|
|
233
|
+
/**
|
|
234
|
+
* Check if animations are enabled at the grid level.
|
|
235
|
+
* Respects gridConfig.animation.mode and the CSS variable set by the grid.
|
|
236
|
+
*
|
|
237
|
+
* Plugins should use this to skip animations when:
|
|
238
|
+
* - Animation mode is 'off' or `false`
|
|
239
|
+
* - User prefers reduced motion and mode is 'reduced-motion' (default)
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```ts
|
|
243
|
+
* private get animationStyle(): 'slide' | 'fade' | false {
|
|
244
|
+
* if (!this.isAnimationEnabled) return false;
|
|
245
|
+
* return this.config.animation ?? 'slide';
|
|
246
|
+
* }
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
get isAnimationEnabled() {
|
|
250
|
+
const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
|
|
251
|
+
if (e === !1 || e === "off") return !1;
|
|
252
|
+
if (e === !0 || e === "on") return !0;
|
|
253
|
+
const t = this.gridElement;
|
|
254
|
+
return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get the animation duration in milliseconds from CSS variable.
|
|
258
|
+
* Falls back to 200ms if not set.
|
|
259
|
+
*
|
|
260
|
+
* Plugins can use this for their animation timing to stay consistent
|
|
261
|
+
* with the grid-level animation.duration setting.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```ts
|
|
265
|
+
* element.animate(keyframes, { duration: this.animationDuration });
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
get animationDuration() {
|
|
269
|
+
const e = this.gridElement;
|
|
270
|
+
if (e) {
|
|
271
|
+
const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), n = parseInt(t, 10);
|
|
272
|
+
if (!isNaN(n)) return n;
|
|
273
|
+
}
|
|
274
|
+
return 200;
|
|
275
|
+
}
|
|
276
|
+
// #endregion
|
|
189
277
|
/**
|
|
190
278
|
* Resolve an icon value to string or HTMLElement.
|
|
191
279
|
* Checks plugin config first, then grid-level icons, then defaults.
|
|
@@ -194,8 +282,8 @@ class I {
|
|
|
194
282
|
* @param pluginOverride - Optional plugin-level override
|
|
195
283
|
* @returns The resolved icon value
|
|
196
284
|
*/
|
|
197
|
-
resolveIcon(e,
|
|
198
|
-
return
|
|
285
|
+
resolveIcon(e, t) {
|
|
286
|
+
return t !== void 0 ? t : this.gridIcons[e];
|
|
199
287
|
}
|
|
200
288
|
/**
|
|
201
289
|
* Set an icon value on an element.
|
|
@@ -204,8 +292,8 @@ class I {
|
|
|
204
292
|
* @param element - The element to set the icon on
|
|
205
293
|
* @param icon - The icon value (string or HTMLElement)
|
|
206
294
|
*/
|
|
207
|
-
setIcon(e,
|
|
208
|
-
typeof
|
|
295
|
+
setIcon(e, t) {
|
|
296
|
+
typeof t == "string" ? e.innerHTML = t : t instanceof HTMLElement && (e.innerHTML = "", e.appendChild(t.cloneNode(!0)));
|
|
209
297
|
}
|
|
210
298
|
/**
|
|
211
299
|
* Log a warning message.
|
|
@@ -215,82 +303,81 @@ class I {
|
|
|
215
303
|
}
|
|
216
304
|
// #endregion
|
|
217
305
|
}
|
|
218
|
-
const g = ".tbw-context-menu{position:fixed;background:light-dark(#f5f5f5
|
|
219
|
-
function
|
|
220
|
-
return (typeof
|
|
306
|
+
const g = "@layer tbw-plugins{.tbw-context-menu{position:fixed;background:var(--tbw-context-menu-bg, var(--tbw-color-panel-bg, light-dark(#f5f5f5, #2a2a2a)));color:var(--tbw-context-menu-fg, var(--tbw-color-fg, light-dark(#222, #eee)));border:1px solid var(--tbw-context-menu-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-border-radius, .25rem);box-shadow:0 2px 10px var(--tbw-color-shadow, rgba(0, 0, 0, .15));min-width:var(--tbw-menu-min-width, 10rem);padding:var(--tbw-spacing-xs, .25rem) 0;z-index:10000;font-size:var(--tbw-font-size-sm, .8125rem);font-family:var(--tbw-font-family, system-ui, sans-serif)}.tbw-context-menu-item{display:flex;align-items:center;padding:var(--tbw-menu-item-padding, .375rem .75rem);cursor:pointer;gap:var(--tbw-menu-item-gap, .5rem)}.tbw-context-menu-item:hover:not(.disabled){background:var(--tbw-context-menu-hover, var(--tbw-color-row-hover, light-dark(#e8e8e8, #3a3a3a)))}.tbw-context-menu-item.disabled{opacity:.5;cursor:default}.tbw-context-menu-item.danger{color:light-dark(#c00,#f66)}.tbw-context-menu-icon{width:var(--tbw-icon-size, 1rem);text-align:center}.tbw-context-menu-label{flex:1}.tbw-context-menu-shortcut{color:var(--tbw-color-fg-muted, light-dark(#888, #888));font-size:var(--tbw-font-size-xs, .6875rem)}.tbw-context-menu-arrow{font-size:var(--tbw-font-size-2xs, .625rem);color:var(--tbw-color-fg-muted, light-dark(#888, #888))}.tbw-context-menu-separator{height:1px;background:var(--tbw-context-menu-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));margin:var(--tbw-spacing-xs, .25rem) 0}}";
|
|
307
|
+
function v(r, e) {
|
|
308
|
+
return (typeof r == "function" ? r(e) : r).filter((n) => !(n.hidden === !0 || typeof n.hidden == "function" && n.hidden(e)));
|
|
221
309
|
}
|
|
222
|
-
function M(
|
|
223
|
-
return
|
|
310
|
+
function M(r, e) {
|
|
311
|
+
return r.disabled === !0 ? !0 : typeof r.disabled == "function" ? r.disabled(e) : !1;
|
|
224
312
|
}
|
|
225
|
-
function
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
for (const o of
|
|
313
|
+
function x(r, e, t, n = C.submenuArrow) {
|
|
314
|
+
const l = document.createElement("div");
|
|
315
|
+
l.className = "tbw-context-menu", l.setAttribute("role", "menu");
|
|
316
|
+
for (const o of r) {
|
|
229
317
|
if (o.separator) {
|
|
230
|
-
const
|
|
231
|
-
|
|
318
|
+
const s = document.createElement("div");
|
|
319
|
+
s.className = "tbw-context-menu-separator", s.setAttribute("role", "separator"), l.appendChild(s);
|
|
232
320
|
continue;
|
|
233
321
|
}
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
if (
|
|
238
|
-
const
|
|
239
|
-
|
|
322
|
+
const i = document.createElement("div");
|
|
323
|
+
i.className = "tbw-context-menu-item", o.cssClass && i.classList.add(o.cssClass), i.setAttribute("role", "menuitem"), i.setAttribute("data-id", o.id);
|
|
324
|
+
const d = M(o, e);
|
|
325
|
+
if (d && (i.classList.add("disabled"), i.setAttribute("aria-disabled", "true")), o.icon) {
|
|
326
|
+
const s = document.createElement("span");
|
|
327
|
+
s.className = "tbw-context-menu-icon", s.innerHTML = o.icon, i.appendChild(s);
|
|
240
328
|
}
|
|
241
|
-
const
|
|
242
|
-
if (
|
|
243
|
-
const
|
|
244
|
-
|
|
329
|
+
const a = document.createElement("span");
|
|
330
|
+
if (a.className = "tbw-context-menu-label", a.textContent = o.name, i.appendChild(a), o.shortcut) {
|
|
331
|
+
const s = document.createElement("span");
|
|
332
|
+
s.className = "tbw-context-menu-shortcut", s.textContent = o.shortcut, i.appendChild(s);
|
|
245
333
|
}
|
|
246
334
|
if (o.subMenu?.length) {
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
if (
|
|
250
|
-
const h =
|
|
251
|
-
|
|
252
|
-
}),
|
|
253
|
-
const u =
|
|
335
|
+
const s = document.createElement("span");
|
|
336
|
+
s.className = "tbw-context-menu-arrow", typeof n == "string" ? s.innerHTML = n : n instanceof HTMLElement && s.appendChild(n.cloneNode(!0)), i.appendChild(s), i.addEventListener("mouseenter", () => {
|
|
337
|
+
if (i.querySelector(".tbw-context-menu") || !o.subMenu) return;
|
|
338
|
+
const h = v(o.subMenu, e), c = x(h, e, t, n);
|
|
339
|
+
c.classList.add("tbw-context-submenu"), c.style.position = "absolute", c.style.left = "100%", c.style.top = "0", i.style.position = "relative", i.appendChild(c);
|
|
340
|
+
}), i.addEventListener("mouseleave", () => {
|
|
341
|
+
const u = i.querySelector(".tbw-context-menu");
|
|
254
342
|
u && u.remove();
|
|
255
343
|
});
|
|
256
344
|
}
|
|
257
|
-
!
|
|
258
|
-
|
|
259
|
-
}),
|
|
345
|
+
!d && o.action && !o.subMenu && i.addEventListener("click", (s) => {
|
|
346
|
+
s.stopPropagation(), t(o);
|
|
347
|
+
}), l.appendChild(i);
|
|
260
348
|
}
|
|
261
|
-
return
|
|
349
|
+
return l;
|
|
262
350
|
}
|
|
263
|
-
function y(
|
|
264
|
-
|
|
265
|
-
const
|
|
266
|
-
let
|
|
267
|
-
e +
|
|
351
|
+
function y(r, e, t) {
|
|
352
|
+
r.style.position = "fixed", r.style.left = `${e}px`, r.style.top = `${t}px`, r.style.visibility = "hidden", r.style.zIndex = "10000";
|
|
353
|
+
const n = r.getBoundingClientRect(), l = window.innerWidth, o = window.innerHeight;
|
|
354
|
+
let i = e, d = t;
|
|
355
|
+
e + n.width > l && (i = e - n.width), t + n.height > o && (d = t - n.height), i = Math.max(0, i), d = Math.max(0, d), r.style.left = `${i}px`, r.style.top = `${d}px`, r.style.visibility = "visible";
|
|
268
356
|
}
|
|
269
|
-
let f = null,
|
|
270
|
-
const
|
|
357
|
+
let f = null, b = null, m = null, p = 0;
|
|
358
|
+
const w = [
|
|
271
359
|
{
|
|
272
360
|
id: "copy",
|
|
273
361
|
name: "Copy",
|
|
274
362
|
shortcut: "Ctrl+C",
|
|
275
|
-
action: (
|
|
276
|
-
|
|
363
|
+
action: (r) => {
|
|
364
|
+
r.grid?.plugins?.clipboard?.copy?.();
|
|
277
365
|
}
|
|
278
366
|
},
|
|
279
367
|
{ separator: !0, id: "sep1", name: "" },
|
|
280
368
|
{
|
|
281
369
|
id: "export-csv",
|
|
282
370
|
name: "Export CSV",
|
|
283
|
-
action: (
|
|
284
|
-
|
|
371
|
+
action: (r) => {
|
|
372
|
+
r.grid?.plugins?.export?.exportCsv?.();
|
|
285
373
|
}
|
|
286
374
|
}
|
|
287
375
|
];
|
|
288
376
|
class H extends I {
|
|
289
377
|
name = "contextMenu";
|
|
290
|
-
version = "1.0.0";
|
|
291
378
|
get defaultConfig() {
|
|
292
379
|
return {
|
|
293
|
-
items:
|
|
380
|
+
items: w
|
|
294
381
|
};
|
|
295
382
|
}
|
|
296
383
|
// #region Internal State
|
|
@@ -301,7 +388,7 @@ class H extends I {
|
|
|
301
388
|
// #endregion
|
|
302
389
|
// #region Lifecycle
|
|
303
390
|
attach(e) {
|
|
304
|
-
super.attach(e), this.installGlobalHandlers(),
|
|
391
|
+
super.attach(e), this.installGlobalHandlers(), p++;
|
|
305
392
|
}
|
|
306
393
|
detach() {
|
|
307
394
|
this.menuElement && (this.menuElement.remove(), this.menuElement = null), this.isOpen = !1, this.params = null, this.uninstallGlobalHandlers();
|
|
@@ -310,44 +397,44 @@ class H extends I {
|
|
|
310
397
|
// #region Private Methods
|
|
311
398
|
installGlobalHandlers() {
|
|
312
399
|
!m && typeof document < "u" && typeof g == "string" && g && (m = document.createElement("style"), m.id = "tbw-context-menu-styles", m.textContent = g, document.head.appendChild(m)), f || (f = () => {
|
|
313
|
-
document.querySelectorAll(".tbw-context-menu").forEach((
|
|
314
|
-
}, document.addEventListener("click", f)),
|
|
315
|
-
e.key === "Escape" && document.querySelectorAll(".tbw-context-menu").forEach((
|
|
316
|
-
}, document.addEventListener("keydown",
|
|
400
|
+
document.querySelectorAll(".tbw-context-menu").forEach((t) => t.remove());
|
|
401
|
+
}, document.addEventListener("click", f)), b || (b = (e) => {
|
|
402
|
+
e.key === "Escape" && document.querySelectorAll(".tbw-context-menu").forEach((n) => n.remove());
|
|
403
|
+
}, document.addEventListener("keydown", b));
|
|
317
404
|
}
|
|
318
405
|
/**
|
|
319
406
|
* Clean up global handlers when the last instance detaches.
|
|
320
407
|
* Uses reference counting to ensure handlers persist while any grid uses the plugin.
|
|
321
408
|
*/
|
|
322
409
|
uninstallGlobalHandlers() {
|
|
323
|
-
|
|
410
|
+
p--, !(p > 0) && (f && (document.removeEventListener("click", f), f = null), b && (document.removeEventListener("keydown", b), b = null), m && (m.remove(), m = null));
|
|
324
411
|
}
|
|
325
412
|
// #endregion
|
|
326
413
|
// #region Hooks
|
|
327
414
|
afterRender() {
|
|
328
|
-
const e = this.
|
|
415
|
+
const e = this.gridElement;
|
|
329
416
|
if (!e) return;
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
const o =
|
|
335
|
-
let
|
|
336
|
-
if (
|
|
337
|
-
const u = parseInt(
|
|
338
|
-
|
|
417
|
+
const t = e.children[0];
|
|
418
|
+
t && t.getAttribute("data-context-menu-bound") !== "true" && (t.setAttribute("data-context-menu-bound", "true"), t.addEventListener("contextmenu", (n) => {
|
|
419
|
+
const l = n;
|
|
420
|
+
l.preventDefault();
|
|
421
|
+
const o = l.target, i = o.closest("[data-row][data-col]"), d = o.closest(".header-cell");
|
|
422
|
+
let a;
|
|
423
|
+
if (i) {
|
|
424
|
+
const u = parseInt(i.getAttribute("data-row") ?? "-1", 10), h = parseInt(i.getAttribute("data-col") ?? "-1", 10), c = this.columns[h], E = this.rows[u];
|
|
425
|
+
a = {
|
|
339
426
|
row: E,
|
|
340
427
|
rowIndex: u,
|
|
341
|
-
column:
|
|
428
|
+
column: c,
|
|
342
429
|
columnIndex: h,
|
|
343
|
-
field:
|
|
344
|
-
value: E?.[
|
|
430
|
+
field: c?.field ?? "",
|
|
431
|
+
value: E?.[c?.field] ?? null,
|
|
345
432
|
isHeader: !1,
|
|
346
|
-
event:
|
|
433
|
+
event: l
|
|
347
434
|
};
|
|
348
|
-
} else if (
|
|
349
|
-
const u = parseInt(
|
|
350
|
-
|
|
435
|
+
} else if (d) {
|
|
436
|
+
const u = parseInt(d.getAttribute("data-col") ?? "-1", 10), h = this.columns[u];
|
|
437
|
+
a = {
|
|
351
438
|
row: null,
|
|
352
439
|
rowIndex: -1,
|
|
353
440
|
column: h,
|
|
@@ -355,20 +442,20 @@ class H extends I {
|
|
|
355
442
|
field: h?.field ?? "",
|
|
356
443
|
value: null,
|
|
357
444
|
isHeader: !0,
|
|
358
|
-
event:
|
|
445
|
+
event: l
|
|
359
446
|
};
|
|
360
447
|
} else
|
|
361
448
|
return;
|
|
362
|
-
this.params =
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
449
|
+
this.params = a, this.position = { x: l.clientX, y: l.clientY };
|
|
450
|
+
const s = v(this.config.items ?? w, a);
|
|
451
|
+
s.length && (this.menuElement && this.menuElement.remove(), this.menuElement = x(
|
|
452
|
+
s,
|
|
453
|
+
a,
|
|
367
454
|
(u) => {
|
|
368
|
-
u.action && u.action(
|
|
455
|
+
u.action && u.action(a), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
|
|
369
456
|
},
|
|
370
457
|
this.gridIcons.submenuArrow
|
|
371
|
-
), document.body.appendChild(this.menuElement), y(this.menuElement,
|
|
458
|
+
), document.body.appendChild(this.menuElement), y(this.menuElement, l.clientX, l.clientY), this.isOpen = !0, this.emit("context-menu-open", { params: a, items: s }));
|
|
372
459
|
}));
|
|
373
460
|
}
|
|
374
461
|
// #endregion
|
|
@@ -379,25 +466,25 @@ class H extends I {
|
|
|
379
466
|
* @param y - Y coordinate
|
|
380
467
|
* @param params - Partial context menu parameters
|
|
381
468
|
*/
|
|
382
|
-
showMenu(e,
|
|
383
|
-
const
|
|
384
|
-
row:
|
|
385
|
-
rowIndex:
|
|
386
|
-
column:
|
|
387
|
-
columnIndex:
|
|
388
|
-
field:
|
|
389
|
-
value:
|
|
390
|
-
isHeader:
|
|
391
|
-
event:
|
|
392
|
-
}, o =
|
|
393
|
-
this.menuElement && this.menuElement.remove(), this.menuElement =
|
|
469
|
+
showMenu(e, t, n) {
|
|
470
|
+
const l = {
|
|
471
|
+
row: n.row ?? null,
|
|
472
|
+
rowIndex: n.rowIndex ?? -1,
|
|
473
|
+
column: n.column ?? null,
|
|
474
|
+
columnIndex: n.columnIndex ?? -1,
|
|
475
|
+
field: n.field ?? "",
|
|
476
|
+
value: n.value ?? null,
|
|
477
|
+
isHeader: n.isHeader ?? !1,
|
|
478
|
+
event: n.event ?? new MouseEvent("contextmenu")
|
|
479
|
+
}, o = v(this.config.items ?? w, l);
|
|
480
|
+
this.menuElement && this.menuElement.remove(), this.menuElement = x(
|
|
394
481
|
o,
|
|
395
|
-
|
|
396
|
-
(
|
|
397
|
-
|
|
482
|
+
l,
|
|
483
|
+
(i) => {
|
|
484
|
+
i.action && i.action(l), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
|
|
398
485
|
},
|
|
399
486
|
this.gridIcons.submenuArrow
|
|
400
|
-
), document.body.appendChild(this.menuElement), y(this.menuElement, e,
|
|
487
|
+
), document.body.appendChild(this.menuElement), y(this.menuElement, e, t), this.isOpen = !0;
|
|
401
488
|
}
|
|
402
489
|
/**
|
|
403
490
|
* Hide the context menu.
|