@toolbox-web/grid 3.0.0-beta.2 → 3.0.0-beta.3

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.
Files changed (39) hide show
  1. package/all.js +2 -2
  2. package/all.js.map +1 -1
  3. package/index.js +1 -1
  4. package/lib/features/registry.js +1 -1
  5. package/lib/plugins/clipboard/clipboard-payload.d.ts +47 -0
  6. package/lib/plugins/clipboard/copy.d.ts +9 -2
  7. package/lib/plugins/clipboard/index.js +1 -1
  8. package/lib/plugins/clipboard/index.js.map +1 -1
  9. package/lib/plugins/clipboard/types.d.ts +18 -0
  10. package/lib/plugins/column-virtualization/index.js +1 -1
  11. package/lib/plugins/context-menu/index.js +1 -1
  12. package/lib/plugins/editing/index.js +1 -1
  13. package/lib/plugins/export/index.js +1 -1
  14. package/lib/plugins/filtering/index.js +1 -1
  15. package/lib/plugins/grouping-columns/index.js +1 -1
  16. package/lib/plugins/grouping-rows/index.js +1 -1
  17. package/lib/plugins/master-detail/index.js +1 -1
  18. package/lib/plugins/multi-sort/index.js +1 -1
  19. package/lib/plugins/pinned-columns/index.js +1 -1
  20. package/lib/plugins/pinned-rows/index.js +1 -1
  21. package/lib/plugins/pivot/index.js +1 -1
  22. package/lib/plugins/print/index.js +1 -1
  23. package/lib/plugins/reorder-columns/index.js +1 -1
  24. package/lib/plugins/responsive/index.js +1 -1
  25. package/lib/plugins/row-drag-drop/index.js +1 -1
  26. package/lib/plugins/selection/index.js +1 -1
  27. package/lib/plugins/server-side/index.js +1 -1
  28. package/lib/plugins/shell/index.js +1 -1
  29. package/lib/plugins/sticky-rows/index.js +1 -1
  30. package/lib/plugins/tooltip/index.js +1 -1
  31. package/lib/plugins/tree/index.js +1 -1
  32. package/lib/plugins/undo-redo/index.js +1 -1
  33. package/lib/plugins/visibility/index.js +1 -1
  34. package/package.json +1 -1
  35. package/umd/grid.all.umd.js +1 -1
  36. package/umd/grid.all.umd.js.map +1 -1
  37. package/umd/grid.umd.js +1 -1
  38. package/umd/plugins/clipboard.umd.js +1 -1
  39. package/umd/plugins/clipboard.umd.js.map +1 -1
@@ -1,2 +1,2 @@
1
- import{setFeatureResolver as o}from"@toolbox-web/grid";function t(o,t,e,n){console.warn(function(o,t){return`[tbw-grid] ${o}: ${t}\n\n → More info: ${function(o){return`https://toolboxjs.com/grid/errors#${o.toLowerCase()}`}(o)}`}(o,t))}const e="3.0.0-beta.2",n=/* @__PURE__ */Symbol.for(`@toolbox-web/grid:feature-registry@${e}/v1`),r=/* @__PURE__ */Symbol.for(`@toolbox-web/grid:feature-registry-warned@${e}/v1`);function s(o,t){let e=Reflect.get(globalThis,o);return void 0===e&&(e=t(),Reflect.set(globalThis,o,e)),e}const i=s(n,()=>/* @__PURE__ */new Map),c=s(r,()=>/* @__PURE__ */new Set),f=()=>"undefined"!=typeof window&&("localhost"===window.location?.hostname||"127.0.0.1"===window.location?.hostname);function a(o,e,n){f()&&i.has(o)&&!n?.override&&t("TBW030",`Feature "${o}" was re-registered. Previous registration overwritten.`),i.set(o,{factory:e,name:o})}function u(o){return i.has(o)}function d(o){return i.get(o)?.factory}function l(){return Array.from(i.keys())}const w={undoRedo:["editing"],clipboard:["selection"]};function g(o,e){const n=i.get(o);if(n)return n.factory(e);if(f()&&!c.has(o)){c.add(o);const e=o.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();t("TBW031",`Feature "${o}" is configured but not registered.\nAdd this import to enable it:\n\n import '@toolbox-web/grid/features/${e}';\n`)}}function b(o){const e=[];for(const[t,r]of Object.entries(o))void 0!==r&&!1!==r&&e.push(t);!function(o){const e=new Set(o);for(const n of o){const o=w[n];if(o)for(const r of o)e.has(r)||f()&&t("TBW032",`Feature "${n}" requires "${r}" to be enabled. Add "${r}" to your features configuration.`)}}(e);const n=[];for(const t of e){const e=g(t,o[t]);e&&n.push(e)}return function(o){if(o.length<2)return o;const t=/* @__PURE__ */new Map;for(const i of o)t.set(i.name,i);const e=[],n=/* @__PURE__ */new Set,r=/* @__PURE__ */new Set,s=o=>{if(n.has(o)||r.has(o))return;r.add(o);const i=o.constructor.dependencies??[];for(const e of i){const o=t.get(e.name);o&&s(o)}r.delete(o),n.add(o),e.push(o)};for(const i of o)s(i);return e}(n)}function h(){i.clear(),c.clear()}o(b);export{h as clearFeatureRegistry,g as createPluginFromFeature,b as createPluginsFromFeatures,d as getFeatureFactory,l as getRegisteredFeatures,u as isFeatureRegistered,a as registerFeature};
1
+ import{setFeatureResolver as o}from"@toolbox-web/grid";function t(o,t,e,n){console.warn(function(o,t){return`[tbw-grid] ${o}: ${t}\n\n → More info: ${function(o){return`https://toolboxjs.com/grid/errors#${o.toLowerCase()}`}(o)}`}(o,t))}const e="3.0.0-beta.3",n=/* @__PURE__ */Symbol.for(`@toolbox-web/grid:feature-registry@${e}/v1`),r=/* @__PURE__ */Symbol.for(`@toolbox-web/grid:feature-registry-warned@${e}/v1`);function s(o,t){let e=Reflect.get(globalThis,o);return void 0===e&&(e=t(),Reflect.set(globalThis,o,e)),e}const i=s(n,()=>/* @__PURE__ */new Map),c=s(r,()=>/* @__PURE__ */new Set),f=()=>"undefined"!=typeof window&&("localhost"===window.location?.hostname||"127.0.0.1"===window.location?.hostname);function a(o,e,n){f()&&i.has(o)&&!n?.override&&t("TBW030",`Feature "${o}" was re-registered. Previous registration overwritten.`),i.set(o,{factory:e,name:o})}function u(o){return i.has(o)}function d(o){return i.get(o)?.factory}function l(){return Array.from(i.keys())}const w={undoRedo:["editing"],clipboard:["selection"]};function g(o,e){const n=i.get(o);if(n)return n.factory(e);if(f()&&!c.has(o)){c.add(o);const e=o.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();t("TBW031",`Feature "${o}" is configured but not registered.\nAdd this import to enable it:\n\n import '@toolbox-web/grid/features/${e}';\n`)}}function b(o){const e=[];for(const[t,r]of Object.entries(o))void 0!==r&&!1!==r&&e.push(t);!function(o){const e=new Set(o);for(const n of o){const o=w[n];if(o)for(const r of o)e.has(r)||f()&&t("TBW032",`Feature "${n}" requires "${r}" to be enabled. Add "${r}" to your features configuration.`)}}(e);const n=[];for(const t of e){const e=g(t,o[t]);e&&n.push(e)}return function(o){if(o.length<2)return o;const t=/* @__PURE__ */new Map;for(const i of o)t.set(i.name,i);const e=[],n=/* @__PURE__ */new Set,r=/* @__PURE__ */new Set,s=o=>{if(n.has(o)||r.has(o))return;r.add(o);const i=o.constructor.dependencies??[];for(const e of i){const o=t.get(e.name);o&&s(o)}r.delete(o),n.add(o),e.push(o)};for(const i of o)s(i);return e}(n)}function h(){i.clear(),c.clear()}o(b);export{h as clearFeatureRegistry,g as createPluginFromFeature,b as createPluginsFromFeatures,d as getFeatureFactory,l as getRegisteredFeatures,u as isFeatureRegistered,a as registerFeature};
2
2
  //# sourceMappingURL=registry.js.map
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Structured clipboard payload codec.
3
+ *
4
+ * Copy writes both `text/plain` (WYSIWYG for external targets) and `text/html`.
5
+ * The HTML is a real `<table>` of the display text whose root element also
6
+ * carries a base64-encoded structured payload in a `data-tbw-clip` attribute.
7
+ * A same-app paste — even **cross-grid or cross-window** — can then recover the
8
+ * raw cell values losslessly, while external targets just see the table/text.
9
+ *
10
+ * Kept in its own module so `copy.ts` and `paste.ts` share the format without
11
+ * importing each other.
12
+ */
13
+ /**
14
+ * Structured clipboard payload carried in `text/html`. `rows` are the RAW cell
15
+ * values (data rows only), `fields` the source column fields in the same order.
16
+ * @internal
17
+ */
18
+ export interface ClipboardPayload {
19
+ /** Payload schema version. */
20
+ v: 1;
21
+ /** Source column fields, in column order. */
22
+ fields: string[];
23
+ /** Raw cell values, one inner array per data row (no header). */
24
+ rows: unknown[][];
25
+ }
26
+ /** Attribute (on the payload table) that marks our structured HTML clipboard. */
27
+ export declare const CLIPBOARD_PAYLOAD_ATTR = "data-tbw-clip";
28
+ /**
29
+ * Build the `text/html` clipboard representation: a real `<table>` of the
30
+ * DISPLAY text (so external targets like Excel get a proper table) whose root
31
+ * element carries the base64-encoded structured {@link ClipboardPayload} in a
32
+ * `data-tbw-clip` attribute for lossless same-app paste.
33
+ */
34
+ export declare function buildClipboardHtml(header: string[] | null, displayRows: string[][], payload: ClipboardPayload): string;
35
+ /**
36
+ * Extract the structured {@link ClipboardPayload} embedded in a `text/html`
37
+ * clipboard representation written by {@link buildClipboardHtml}. Enables a
38
+ * lossless **cross-grid / cross-window** paste of object-valued cells (the
39
+ * in-memory buffer only covers the same grid instance).
40
+ *
41
+ * Returns `null` when the HTML has no `data-tbw-clip` marker (e.g. an external
42
+ * paste from Excel) or the payload can't be decoded. Parsing is defensive —
43
+ * malformed input never throws.
44
+ *
45
+ * @param html - Raw `text/html` from `clipboardData.getData('text/html')`
46
+ */
47
+ export declare function parseClipboardHtmlPayload(html: string | undefined | null): ClipboardPayload | null;
@@ -44,7 +44,14 @@ export declare function buildClipboardText(params: CopyParams): string;
44
44
  * Uses the modern Clipboard API when available, with fallback
45
45
  * to execCommand for older browsers.
46
46
  *
47
- * @param text - The text to copy
47
+ * When `html` is supplied, writes BOTH `text/plain` and `text/html` via
48
+ * `ClipboardItem` so a same-app paste (even cross-grid or cross-window) can
49
+ * recover a structured payload embedded in the HTML, while external targets
50
+ * (Excel, editors) still get the plain text. Silently falls back to text-only
51
+ * when `ClipboardItem` / `clipboard.write` is unavailable or rejects.
52
+ *
53
+ * @param text - The text to copy (`text/plain`)
54
+ * @param html - Optional rich `text/html` representation (may embed a payload)
48
55
  * @returns Promise resolving to true if successful, false otherwise
49
56
  */
50
- export declare function copyToClipboard(text: string): Promise<boolean>;
57
+ export declare function copyToClipboard(text: string, html?: string): Promise<boolean>;
@@ -1,2 +1,2 @@
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=t,i=n.field;let s=e.get(o);if(s){const e=s.get(i);if(void 0!==e)return e.v}else s=/* @__PURE__ */new Map,e.set(o,s);const l=n.valueAccessor({row:t,column:n,rowIndex:r});return s.set(i,{v:l}),l}function n(t,n){t&&(n?e.get(t)?.delete(n):e.delete(t))}function r(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function o(e,t,n,o){return`${r(n,o)} ${e}: ${t}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(e)}`}const i="__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)|${i.slice(3).join("|")}|this\\b`);const s=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("|")),l=/^on\w+$/i,a=new Set("href|src|action|formaction|data|srcdoc|xlink:href|poster|srcset".split("|")),c=/^\s*(javascript|vbscript|data|blob):/i;function u(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(s.has(e)){t.push(r);continue}if("svg"===e||"http://www.w3.org/2000/svg"===r.namespaceURI){if(Array.from(r.attributes).some(e=>l.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();l.test(e)?n.push(t.name):(a.has(e)&&c.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={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:"",filterActive:"",print:"🖨️"};class f{static dependencies;static manifest;aliases;version="3.0.0-beta.2";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}get resolvedConfig(){return this.#e?this.config:{...this.defaultConfig,...this.userConfig}}mergeConfigsFrom(e){if(0===e.length)return;const t={...this.userConfig},n={};for(const r of Object.keys(t))n[r]=this;for(const r of e){const e=r.userConfig;for(const[i,s]of Object.entries(e)){if(void 0===s)continue;if(!(i in t)){t[i]=s,n[i]=r;continue}if(t[i]===s)continue;const e=n[i]?.constructor.name??this.constructor.name,l=r.constructor.name,a=o("TBW025",`Cannot merge plugin configs for "${this.name}": conflicting value for "${i}" supplied by both ${e} and ${l}. Pass the option on a single instance, or remove the duplicate.`,void 0,this.name);throw new Error(a)}}Object.assign(this.userConfig,t)}refreshUserConfigFrom(e){const t=this.userConfig,n={...e.userConfig};for(const r of Object.keys(t))delete t[r];Object.assign(t,n)}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{...d,...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=u(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(o(e,t,this.gridElement.id,this.name)):console.warn(`${r(this.gridElement.id,this.name)} ${e}`)}throwDiagnostic(e,t){throw new Error(o(e,t,this.gridElement.id,this.name))}}function h(e,t,n=!0){let r=e;if(n&&(r=r.filter(e=>!e.hidden&&!e.field.startsWith("__")&&!0!==e.utility)),t?.length){const e=new Set(t);r=r.filter(t=>e.has(t.field))}return r}async function g(e){try{return await navigator.clipboard.writeText(e),!0}catch(s){t="TBW100",n=`Clipboard API failed: ${s}`,console.warn(o(t,n,r,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,r,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=o.length,s=[];let l=[],a=0,c=!1,u=!1;const d=e=>{const t=o.slice(a,e);return u?function(e){let t="",n=!1;for(let r=0;r<e.length;r++){const o=e[r];'"'===o?n?'"'===e[r+1]?(t+='"',r++):n=!1:n=!0:t+=o}return t}(t):t},f=()=>{(l.length>1||l.some(e=>""!==e.trim()))&&s.push(l),l=[]};for(let h=0;h<i;h++){const e=o[h];'"'===e?(u=!0,c?'"'===o[h+1]?h++:c=!1:c=!0):e!==n||c?e!==r||c||(l.push(d(h)),a=h+1,u=!1,f()):(l.push(d(h)),a=h+1,u=!1)}return l.push(d(i)),f(),s}function p(e,t){const{rows:r,target:o,fields:i,fillSelection:s}=e;if(!o||0===r.length)return;const l=t.rows,a=(t.effectiveConfig.columns??[]).map(e=>e.field),[c=()=>!1]=t.query("getCellEditableResolver"),u=/* @__PURE__ */new Map;let d=l.length;const f=(e,t,n,r)=>{if(!t||!c(t,r))return;let o=u.get(e);o||(o={},u.set(e,o)),o[t]=n};if(s&&o.bounds){const e=r.length;for(let t=o.row;t<=o.bounds.endRow&&!(t>=l.length);t++){const n=r[(t-o.row)%e],s=n.length;if(0===s)continue;const a=l[t];i.forEach((e,r)=>f(t,e,n[r%s],a))}}else{const e=o.bounds?o.bounds.endRow:1/0;r.forEach((t,n)=>{const r=o.row+n;if(r>e)return;if(o.bounds&&r>=l.length)return;!o.bounds&&r>=d&&(d=r+1);const s=l[r]??{};t.forEach((e,t)=>f(r,i[t],e,s))})}if(0===u.size&&d===l.length)return;if(d>l.length){const e=[...l];for(;e.length<d;){const t={};a.forEach(e=>t[e]=""),e.push(t)}t.rows=e}const h=t.rows,g=[];let m=!1;for(const[p,w]of u){const e=h[p];if(!e)continue;let r;try{r=t.getRowId(e)}catch{r=void 0}if(null==r){for(const[t,r]of Object.entries(w))e[t]=r,n(e,t);m=!0}else g.push({id:r,changes:w})}g.length>0?t.updateRows(g,"api"):m&&d===l.length&&(t.rows=[...h])}class w extends f{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){if(this.#s(e.target))return;const t=e.clipboardData?.getData("text/plain");if(!t)return;e.preventDefault();const n=m(t,this.config),r=this.#o(),o=r?.ranges??[],i=o[0];let s=1/0,l=1/0,a=-1/0,c=-1/0;for(const m of o)s=Math.min(s,m.from.row,m.to.row),a=Math.max(a,m.from.row,m.to.row),l=Math.min(l,m.from.col,m.to.col),c=Math.max(c,m.from.col,m.to.col);const u=i?s:0,d=i?l:0,f=!(!i||"range"!==r?.mode&&"row"!==r?.mode||s===a&&l===c)?{endRow:a,endCol:c}:null,h=f?.endCol??this.visibleColumns.length-1;this.#l(n,d,h);const g=this.visibleColumns[d],p=g?{row:u,col:d,field:g.field,bounds:f}:null,w=!0===this.config.fillSelection&&null!==f,b=[],C=n[0]?.length??0,v=w?h-d+1:C;for(let m=0;m<v&&d+m<=h;m++){const e=this.visibleColumns[d+m];e&&b.push(e.field)}const y={rows:n,text:t,target:p,fields:b,fillSelection:w};this.emit("paste",y),this.#a(y)}#a(e){if(!this.grid)return;const{pasteHandler:t}=this.config;if(null===t)return;(t??p)(e,this.grid)}#l(e,t,n){if(!this.config.includeHeaders)return;if(e.length<=1)return;const r=e[0];if(0!==r.length){for(let e=0;e<r.length&&t+e<=n;e++){const n=this.visibleColumns[t+e];if(!n||r[e]!==(n.header||n.field))return}e.shift()}}#s(e){return e instanceof Element&&!!e.closest('input, textarea, select, [contenteditable=""], [contenteditable="true"]')}#o(){const e=this.grid?.query("getSelection");return e?.[0]}#c(e){const t=this.#o();let n,r;if(e?.columns)n=h(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=h(this.visibleColumns.slice(r,o+1))}else n=h(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}}#u(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.#d(e,n,c)});a.push(n.join(o))}return a.join(i)}#d(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.#f(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)}#f(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.#c(e);return 0===t.length||0===n.length?"":this.#u(t,n,e)}async copy(e){const{columns:t,rows:n}=this.#c(e);if(0===t.length||0===n.length)return"";const r=this.#u(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};
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=t,i=n.field;let s=e.get(o);if(s){const e=s.get(i);if(void 0!==e)return e.v}else s=/* @__PURE__ */new Map,e.set(o,s);const l=n.valueAccessor({row:t,column:n,rowIndex:r});return s.set(i,{v:l}),l}function n(t,n){t&&(n?e.get(t)?.delete(n):e.delete(t))}function r(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function o(e,t,n,o){return`${r(n,o)} ${e}: ${t}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(e)}`}const i="__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)|${i.slice(3).join("|")}|this\\b`);const s=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("|")),l=/^on\w+$/i,a=new Set("href|src|action|formaction|data|srcdoc|xlink:href|poster|srcset".split("|")),c=/^\s*(javascript|vbscript|data|blob):/i;function u(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(s.has(e)){t.push(r);continue}if("svg"===e||"http://www.w3.org/2000/svg"===r.namespaceURI){if(Array.from(r.attributes).some(e=>l.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();l.test(e)?n.push(t.name):(a.has(e)&&c.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={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:"",filterActive:"",print:"🖨️"};class h{static dependencies;static manifest;aliases;version="3.0.0-beta.3";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}get resolvedConfig(){return this.#e?this.config:{...this.defaultConfig,...this.userConfig}}mergeConfigsFrom(e){if(0===e.length)return;const t={...this.userConfig},n={};for(const r of Object.keys(t))n[r]=this;for(const r of e){const e=r.userConfig;for(const[i,s]of Object.entries(e)){if(void 0===s)continue;if(!(i in t)){t[i]=s,n[i]=r;continue}if(t[i]===s)continue;const e=n[i]?.constructor.name??this.constructor.name,l=r.constructor.name,a=o("TBW025",`Cannot merge plugin configs for "${this.name}": conflicting value for "${i}" supplied by both ${e} and ${l}. Pass the option on a single instance, or remove the duplicate.`,void 0,this.name);throw new Error(a)}}Object.assign(this.userConfig,t)}refreshUserConfigFrom(e){const t=this.userConfig,n={...e.userConfig};for(const r of Object.keys(t))delete t[r];Object.assign(t,n)}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{...d,...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=u(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(o(e,t,this.gridElement.id,this.name)):console.warn(`${r(this.gridElement.id,this.name)} ${e}`)}throwDiagnostic(e,t){throw new Error(o(e,t,this.gridElement.id,this.name))}}function f(e,t,n=!0){let r=e;if(n&&(r=r.filter(e=>!e.hidden&&!e.field.startsWith("__")&&!0!==e.utility)),t?.length){const e=new Set(t);r=r.filter(t=>e.has(t.field))}return r}const g="data-tbw-clip";const p=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");function m(e,t,n){const r=e?`<thead><tr>${e.map(e=>`<th>${p(e)}</th>`).join("")}</tr></thead>`:"",o=`<tbody>${t.map(e=>`<tr>${e.map(e=>`<td>${p(e)}</td>`).join("")}</tr>`).join("")}</tbody>`;return`<table ${g}="${function(e){return btoa(encodeURIComponent(JSON.stringify(e)))}(n)}">${r}${o}</table>`}async function w(e,t){if(t&&"undefined"!=typeof ClipboardItem&&navigator.clipboard?.write)try{return await navigator.clipboard.write([new ClipboardItem({"text/plain":new Blob([e],{type:"text/plain"}),"text/html":new Blob([t],{type:"text/html"})})]),!0}catch{}try{return await navigator.clipboard.writeText(e),!0}catch(l){n="TBW100",r=`Clipboard API failed: ${l}`,console.warn(o(n,r,i,s));const t=document.createElement("textarea");t.value=e,t.style.position="fixed",t.style.opacity="0",t.style.pointerEvents="none",document.body.appendChild(t),t.select();const a=document.execCommand("copy");return document.body.removeChild(t),a}var n,r,i,s}function b(e,t){const n=t.delimiter??"\t",r=t.newline??"\n",o=e.replace(/\r\n/g,"\n").replace(/\r/g,"\n"),i=o.length,s=[];let l=[],a=0,c=!1,u=!1;const d=e=>{const t=o.slice(a,e);return u?function(e){let t="",n=!1;for(let r=0;r<e.length;r++){const o=e[r];'"'===o?n?'"'===e[r+1]?(t+='"',r++):n=!1:n=!0:t+=o}return t}(t):t},h=()=>{(l.length>1||l.some(e=>""!==e.trim()))&&s.push(l),l=[]};for(let f=0;f<i;f++){const e=o[f];'"'===e?(u=!0,c?'"'===o[f+1]?f++:c=!1:c=!0):e!==n||c?e!==r||c||(l.push(d(f)),a=f+1,u=!1,h()):(l.push(d(f)),a=f+1,u=!1)}return l.push(d(i)),h(),s}function C(e,t){const{rows:r,rawRows:o,target:i,fields:s,fillSelection:l}=e;if(!i||0===r.length)return;const a=o??r,c=t.rows,u=(t.effectiveConfig.columns??[]).map(e=>e.field),[d=()=>!1]=t.query("getCellEditableResolver"),h=/* @__PURE__ */new Map;let f=c.length;const g=(e,t,n,r)=>{if(!t||!d(t,r))return;let o=h.get(e);o||(o={},h.set(e,o)),o[t]=y(n)};if(l&&i.bounds){const e=a.length;for(let t=i.row;t<=i.bounds.endRow&&!(t>=c.length);t++){const n=a[(t-i.row)%e],r=n.length;if(0===r)continue;const o=c[t];s.forEach((e,i)=>g(t,e,n[i%r],o))}}else{const e=i.bounds?i.bounds.endRow:1/0;a.forEach((t,n)=>{const r=i.row+n;if(r>e)return;if(i.bounds&&r>=c.length)return;!i.bounds&&r>=f&&(f=r+1);const o=c[r]??{};t.forEach((e,t)=>g(r,s[t],e,o))})}if(0===h.size&&f===c.length)return;if(f>c.length){const e=[...c];for(;e.length<f;){const t={};u.forEach(e=>t[e]=""),e.push(t)}t.rows=e}const p=t.rows,m=[];let w=!1;for(const[b,C]of h){const e=p[b];if(!e)continue;let r;try{r=t.getRowId(e)}catch{r=void 0}if(null==r){for(const[t,r]of Object.entries(C))e[t]=r,n(e,t);w=!0}else m.push({id:r,changes:C})}m.length>0?t.updateRows(m,"api"):w&&f===c.length&&(t.rows=[...p])}function y(e){if(null===e||"object"!=typeof e)return e;try{return structuredClone(e)}catch{return e}}class v 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;#n=null;attach(e){super.attach(e),e.addEventListener("paste",e=>this.#r(e),{signal:this.disconnectSignal})}detach(){this.lastCopied=null,this.#n=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.#o(e.target),!0)}#o(e){const t=this.#i();if(t&&0===t.ranges.length){let n,r;if(t.anchor)n=t.anchor.row,r=this.visibleColumns[t.anchor.col]?.field;else{const t=this.#s(e);t&&(n=t.row,r=this.columns[t.col]?.field)}if(null==n||null==r)return;return void this.copy({rowIndices:[n],columns:[r]})}this.copy()}#r(e){if(this.#l(e.target))return;const t=e.clipboardData?.getData("text/plain");if(!t)return;e.preventDefault();const n=b(t,this.config),r=this.#i(),o=r?.ranges??[],i=o[0];let s=1/0,l=1/0,a=-1/0,c=-1/0;for(const g of o)s=Math.min(s,g.from.row,g.to.row),a=Math.max(a,g.from.row,g.to.row),l=Math.min(l,g.from.col,g.to.col),c=Math.max(c,g.from.col,g.to.col);const u=r?.anchor??null,d=i?s:u?.row??0,h=i?l:u?.col??0,f=!(!i||"range"!==r?.mode&&"row"!==r?.mode||s===a&&l===c)?{endRow:a,endCol:c}:null,p=f?.endCol??this.visibleColumns.length-1;let m;if(this.#a(n),this.#n&&this.#n.text===t&&this.#n.rawRows.length===n.length)m=this.#n.rawRows;else{const t=function(e){if(!e||-1===e.indexOf(g))return null;try{const t=(new DOMParser).parseFromString(e,"text/html"),n=t.querySelector(`[${g}]`)?.getAttribute(g);if(!n)return null;const r=JSON.parse(decodeURIComponent(atob(n)));return r&&Array.isArray(r.rows)&&Array.isArray(r.fields)?r:null}catch{return null}}(e.clipboardData?.getData("text/html"));t&&t.rows.length===n.length&&(m=t.rows)}const w=this.visibleColumns[h],C=w?{row:d,col:h,field:w.field,bounds:f}:null,y=!0===this.config.fillSelection&&null!==f,v=[],x=n[0]?.length??0,S=y?p-h+1:x;for(let g=0;g<S&&h+g<=p;g++){const e=this.visibleColumns[h+g];e&&v.push(e.field)}const E={rows:n,text:t,target:C,fields:v,fillSelection:y,rawRows:m};this.emit("paste",E),this.#c(E)}#c(e){if(!this.grid)return;const{pasteHandler:t}=this.config;if(null===t)return;(t??C)(e,this.grid)}#a(e){if(!this.config.includeHeaders)return;if(e.length<=1)return;const t=e[0];if(0===t.length)return;const n=this.#u();for(const r of t)if(!n.has(r))return;e.shift()}#u(){const e=/* @__PURE__ */new Set;for(const t of this.columns){const n=t.header||t.field;n&&e.add(n)}return e}#l(e){return e instanceof Element&&!!e.closest('input, textarea, select, [contenteditable=""], [contenteditable="true"]')}#i(){const e=this.grid?.query("getSelection");return e?.[0]}#d(e){const t=this.#i();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}}#h(e,t,n){return this.#f(this.#g(e,t,n),n)}#g(e,n,r){const o=r?.includeHeaders??this.config.includeHeaders??!1,i=r?.processCell??this.config.processCell;return{header:o?e.map(e=>e.header||e.field):null,rows:n.map(n=>e.map(e=>{const r=t(n,e);return i?i(r,e.field,n):this.#p(e,r,n)}))}}#f(e,t){const n=t?.delimiter??this.config.delimiter??"\t",r=t?.newline??this.config.newline??"\n",o=[];e.header&&o.push(e.header.join(n));for(const i of e.rows)o.push(i.join(n));return o.join(r)}#p(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.#m(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)}#m(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}#s(e){const t=e.closest(".cell[data-field]");if(!t)return null;const n=t.dataset.field,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.#d(e);return 0===t.length||0===n.length?"":this.#h(t,n,e)}async copy(e){const{columns:n,rows:r}=this.#d(e);if(0===n.length||0===r.length)return"";const o=this.#g(n,r,e),i=this.#f(o,e),s=r.map(e=>n.map(n=>y(t(e,n)))),l=n.map(e=>e.field);return await w(i,m(o.header,o.rows,{v:1,fields:l,rows:s})),this.lastCopied={text:i,timestamp:Date.now()},this.#n={text:i,rawRows:s},this.emit("copy",{text:i,rowCount:r.length,columnCount:n.length}),i}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?b(e,this.config):null}getLastCopied(){return this.lastCopied}}export{v as ClipboardPlugin,C as defaultPasteHandler};
2
2
  //# sourceMappingURL=index.js.map