@ninebone/datagrid 0.1.1 → 0.1.2

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 CHANGED
@@ -25,9 +25,113 @@ Tired of heavy, overly complex JavaScript data grids? **Ninelab HTML Table** pre
25
25
 
26
26
  - [Live Demo](https://ninebone.github.io/datagrid/)
27
27
 
28
- ### Framework Examples & Input Demos
29
- - [Vanilla JS Examples](#)
30
- - [React Examples](#)
28
+ ---
29
+
30
+ ## Quick Start
31
+
32
+ ### 1. Installation
33
+
34
+ ```bash
35
+ npm install @ninebone/datagrid
36
+
37
+
38
+ ### 2. HTML example
39
+
40
+ ```html
41
+ <html>
42
+ <head>
43
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@ninebone/util@latest/dist/nine-util.umd.js"></script>
44
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@ninebone/datagrid@latest/dist/nine-table.umd.js"></script>
45
+ </head>
46
+ <body>
47
+
48
+ <div style="height: 600px;">
49
+ <ninelab-table show-footer="true">
50
+ <table row-indicator="true">
51
+ <colgroup>
52
+ <col width="50" fixed="left"/>
53
+ <col width="130"/>
54
+ <col width="100"/>
55
+ <col width="110"/>
56
+ </colgroup>
57
+ <thead>
58
+ <tr>
59
+ <th cell-type="checkbox"></th>
60
+ <th>Avatar & Name</th>
61
+ <th>Status Badge</th>
62
+ <th>Input Editor</th>
63
+ </tr>
64
+ </thead>
65
+ <tbody>
66
+ <tr>
67
+ <!-- Checkbox Cell -->
68
+ <td data-bind="sel" cell-type="checkbox"></td>
69
+
70
+ <!-- Custom Image Renderer -->
71
+ <td data-bind="NAME" data-expr="host.renderImage(data.PIC)" html="true"></td>
72
+
73
+ <!-- Custom Badge / Chart Renderer -->
74
+ <td data-expr="host.renderBadge(data.REC1, data.REC2)" html="true"></td>
75
+
76
+ <!-- Inline Input Binding -->
77
+ <td data-bind="NAME" cell-type="input" enable="data.REC1 > 30"></td>
78
+ </tr>
79
+ </tbody>
80
+ </table>
81
+ </ninelab-table>
82
+ </div>
83
+
84
+ <script>
85
+ const grd = document.querySelector("nine-table");
86
+
87
+ // Define custom provider helper functions used in data-expr
88
+ grd.provider.add({
89
+ getCommonCode: (group) => exampleData.generateCommonCode(group),
90
+ renderImage: (v) => `<img src="${v}" style="vertical-align:middle; width:58px; height:58px; border-radius:50%;" />`,
91
+ renderBadge: (v1, v2) => `<span>Score: ${Number(v1) + Number(v2)}</span>`,
92
+ });
93
+
94
+ grd.addEventListener("load", () => {
95
+ // Binding Data
96
+ grd.data.set([
97
+ {
98
+ A: "a",
99
+ ...
100
+ },
101
+ ...
102
+ ]);
103
+ });
104
+ </script>
105
+ </body>
106
+ </html>
107
+
108
+ ```
109
+ # Ninelab HTML Table (`@ninebone/datagrid`)
110
+
111
+ > **Blazing-fast performance powered by native HTML tags** — A next-generation table extension supporting 1,000,000+ rows virtual rendering and seamless inline editing out of the box.
112
+
113
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
114
+ [![npm version](https://img.shields.io/badge/npm-v1.0.0-blue.svg)](https://www.npmjs.com/)
115
+
116
+ Tired of heavy, overly complex JavaScript data grids? **Ninelab HTML Table** preserves the familiar structure of native HTML tags while leveraging advanced DOM virtualization to handle massive datasets effortlessly and provide a frictionless inline editing experience.
117
+
118
+ ---
119
+
120
+ ## Key Features
121
+
122
+ - **1M+ DOM Virtualized Rendering:** Scroll and render over a million rows in a fraction of a second without dropping frames.
123
+ - **Seamless Inline Editing & Form Binding:** Native support for Text, Number, Date, Color, Checkbox, Radio, and Combo (Autocomplete) input types.
124
+ - **HTML Tag-Based (Zero Learning Curve):** No complicated JS configuration objects required—build tables using familiar tag structures.
125
+ - **Shadow DOM & CSS Variables:** Perfect style encapsulation with zero CSS pollution, easily customizable via CSS variables.
126
+ - **Framework Agnostic:** Drops seamlessly into React, Vue, Svelte, or Vanilla JS.
127
+
128
+ ---
129
+
130
+ ## Live Demo & Previews
131
+
132
+ ![Ninelab HTML Table Demo](https://raw.githubusercontent.com/ninebone/datagrid/main/assets/demo.gif)
133
+
134
+ - [Live Demo](https://ninebone.github.io/datagrid/)
31
135
 
32
136
  ---
33
137
 
@@ -38,9 +142,10 @@ Tired of heavy, overly complex JavaScript data grids? **Ninelab HTML Table** pre
38
142
  ```bash
39
143
  npm install @ninebone/datagrid
40
144
 
41
- <!-- HTML example -->
42
145
 
43
- ````html
146
+ ### 2. HTML example
147
+
148
+ ```html
44
149
  <html>
45
150
  <head>
46
151
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@ninebone/util@latest/dist/nine-util.umd.js"></script>
@@ -110,5 +215,6 @@ npm install @ninebone/datagrid
110
215
 
111
216
  ```
112
217
 
218
+
113
219
  ## LICENSE
114
220
  MIT © 2026 ninebone
@@ -910,7 +910,6 @@ nine-table-filter-panel.loading::before {
910
910
 
911
911
 
912
912
  :host([theme="simple"]) {
913
- /* 1. 불필요한 패널 및 컴포넌트 숨기기 */
914
913
  .ng-part-header, .ng-part-footer,
915
914
  nine-table-toolbar,
916
915
  nine-table-sheets-footer,
@@ -925,7 +924,7 @@ nine-table-filter-panel.loading::before {
925
924
  }
926
925
 
927
926
  tr {
928
- height: 32px;
927
+ height: 28px;
929
928
  }
930
929
 
931
930
  nine-table-sheet {
@@ -940,15 +939,19 @@ nine-table-filter-panel.loading::before {
940
939
  border: none;
941
940
  padding: 0 8px;
942
941
  }
942
+
943
+ th[data-col="0"] {
944
+ * {
945
+ display: none;
946
+ }
947
+ }
943
948
  }
944
949
 
945
- /* 🎯 Toolbar 숨김 제어 */
946
950
  :host([theme="simple"]) nine-table-toolbar,
947
951
  :host([show-header="false"]) nine-table-toolbar {
948
952
  display: none;
949
953
  }
950
954
 
951
- /* 🎯 Footer(StatusBar) 숨김 제어 (show-statusbar="false") */
952
955
  :host([theme="simple"]) nine-table-sheets-footer,
953
956
  :host([show-footer="false"]) nine-table-sheets-footer,
954
957
  :host([show-statusbar="false"]) nine-table-sheets-footer {
@@ -957,10 +960,10 @@ nine-table-filter-panel.loading::before {
957
960
 
958
961
  :host([theme="simple"]) {
959
962
  col[data-col="0"], th[data-col="0"], td[data-col="0"] {
960
- /**display: none; */
963
+
961
964
  }
962
965
  .ng-container-right {
963
- /**display: none; */
966
+
964
967
  }
965
968
  tr {
966
969
  height: 28px;
@@ -1017,11 +1020,11 @@ nine-table-filter-panel.loading::before {
1017
1020
  max-width: 26px !important;;
1018
1021
  } */
1019
1022
  }
1020
- /**
1023
+
1021
1024
  col[data-col="0"], th[data-col="0"] {
1022
1025
  width: 2px !important;
1023
1026
  max-width: 2px !important;
1024
- } */
1027
+ }
1025
1028
 
1026
1029
  col[data-col="0"], col[data-col="1"] {
1027
1030
  display: table-column;
@@ -1035,11 +1038,7 @@ nine-table-filter-panel.loading::before {
1035
1038
  max-width: 24px;
1036
1039
  }
1037
1040
 
1038
- th[data-col="0"] {
1039
- * {
1040
- display: none;
1041
- }
1042
- }
1041
+
1043
1042
 
1044
1043
  td[data-col="1"] {
1045
1044
  padding: 0;
@@ -1108,20 +1107,19 @@ nine-table-filter-panel.loading::before {
1108
1107
  left: 0;
1109
1108
  right: 0;
1110
1109
  height: 2px;
1111
- background: rgba(255, 255, 255, 0.08); /* 은은한 화이트 트랙 배경 */
1110
+ background: rgba(255, 255, 255, 0.08);
1112
1111
  z-index: 10000;
1113
1112
  display: none;
1114
1113
  overflow: hidden;
1115
1114
  }
1116
1115
 
1117
- /* 🎯 아주 좁고 쨍한 빛 조각 형태로 압축 */
1118
1116
  .ng-loading-bar::after {
1119
1117
  content: '';
1120
1118
  position: absolute;
1121
1119
  top: 0;
1122
1120
  left: 0;
1123
1121
  bottom: 0;
1124
- width: 12%; /* 바의 전체 길이를 12%로 대폭 축소 */
1122
+ width: 12%;
1125
1123
  background: linear-gradient(
1126
1124
  90deg,
1127
1125
  transparent 0%,
@@ -1139,7 +1137,7 @@ nine-table-filter-panel.loading::before {
1139
1137
  transform: translateX(-150%);
1140
1138
  }
1141
1139
  100% {
1142
- transform: translateX(850%); /* 폭이 좁아진 만큼 이동 거리 확장 */
1140
+ transform: translateX(850%);
1143
1141
  }
1144
1142
  }
1145
1143
 
@@ -2993,7 +2993,7 @@ var P = class {
2993
2993
  let e = Array.from(this.#e.children).filter((e) => e.tagName.toUpperCase() === "TABLE"), t = e.length, n = e.map((e, n) => {
2994
2994
  let r = n === 0 ? "active" : "", i = e.id || `sheet${n + 1}`;
2995
2995
  return `<nine-table-sheet class="${r}" data-index="${n}" data-sheet-id="${i}" id="${i}"></nine-table-sheet>` + (n < t - 1 ? `<nine-splitter class="h" data-split-index="${n}"></nine-splitter>` : "");
2996
- }).join(""), r = ["@import \"https://cdn.jsdelivr.net/npm/@ninebone/datagrid@0.1.1/dist/css/nine-table.css\";"];
2996
+ }).join(""), r = ["@import \"https://cdn.jsdelivr.net/npm/@ninebone/datagrid@0.1.2/dist/css/nine-table.css\";"];
2997
2997
  nine["nine-table"] && nine["nine-table"].cssFile && r.push(`@import "${nine["nine-table"].cssFile}";`), this.#e.shadowRoot.innerHTML = `
2998
2998
  <style>
2999
2999
  ${r.join("\n")}
@@ -3130,7 +3130,7 @@ var P = class {
3130
3130
  #i;
3131
3131
  #a = 0;
3132
3132
  constructor() {
3133
- super(), ["NINE-TABLE"].includes(this.tagName) && n.log("Welcome nine-table", "0.1.1"), this.#e = this.attachShadow({ mode: "open" }), this.#t = new o(this), this.#r = new I(this), this.#i = new L(this), this.#c();
3133
+ super(), ["NINE-TABLE"].includes(this.tagName) && n.log("Welcome nine-table", "0.1.2"), this.#e = this.attachShadow({ mode: "open" }), this.#t = new o(this), this.#r = new I(this), this.#i = new L(this), this.#c();
3134
3134
  }
3135
3135
  connectedCallback() {
3136
3136
  setTimeout(() => {
@@ -78,7 +78,7 @@
78
78
 
79
79
  <div class="ng-col-mover-grip"></div>
80
80
  <div class="ng-col-mover-indi"></div>
81
- `,this.#m={mainBody:this.querySelector(`.ng-sheet-body .ng-container-body`),hscrollbar:this.querySelector(`nine-table-hscrollbar`),vscrollbar:this.querySelector(`nine-table-vscrollbar`),content:this.querySelector(`.ng-sheet-body .ng-sheet-body-content`),scrollHolder:this.querySelector(`.ng-sheet-body .ng-virtual-height-holder`)}};#w=()=>{let e=this.querySelector(`.ng-container-left table`),t=this.querySelector(`.ng-container-body table`),n=this.querySelector(`.ng-container-right table`),r=Array.from(e.querySelectorAll(`thead tr:not(.col-indicator-rowgroup)`)),i=Array.from(t.querySelectorAll(`thead tr:not(.col-indicator-rowgroup)`)),a=Array.from(n.querySelectorAll(`thead tr:not(.col-indicator-rowgroup)`));this.#T(r,i,a);let o=Array.from(e.querySelectorAll(`tfoot tr`)),s=Array.from(t.querySelectorAll(`tfoot tr`)),c=Array.from(n.querySelectorAll(`tfoot tr`));this.#T(o,s,c)};#T=(e,t,n)=>{setTimeout(()=>{let r=Math.max(e.length,t.length,n.length);for(let i=0;i<r;i++){let r=[e[i]?.getBoundingClientRect().height||0,t[i]?.getBoundingClientRect().height||0,n[i]?.getBoundingClientRect().height||0],a=Math.max(...r);a>0&&(e[i]&&(e[i].style.height=`${a}px`),t[i]&&(t[i].style.height=`${a}px`),n[i]&&(n[i].style.height=`${a}px`))}})};#E=()=>{let e=this.querySelector(`.ng-sheet-body`);if(!e)return;let t=null;e.addEventListener(`mouseover`,n=>{let r=n.target.closest(`tr`);if(!r||!r.dataset.row&&r.dataset.row!==`0`)return;let i=r.dataset.row;t!==i&&(t=i,e.querySelectorAll(`tr[data-row="${i}"]`).forEach(e=>{e.classList.add(`hover`)}))}),e.addEventListener(`mouseout`,n=>{let r=n.target.closest(`tr`);if(!r)return;let i=n.relatedTarget;r.contains(i)||(e.querySelectorAll(`tr.hover`).forEach(e=>{e.classList.remove(`hover`)}),t=null)})};#D=()=>{[this.#d].forEach(e=>{new Set([...Reflect.ownKeys(e),...Reflect.ownKeys(Object.getPrototypeOf(e))]).forEach(t=>{if(t===`constructor`||String(t).startsWith(`#`))return;let n=e[t];typeof n==`function`?this[t]||(this[t]=(...t)=>n.apply(e,t)):typeof n==`object`&&n&&(this[t]||(this[t]=n))})})};disconnectedCallback(){this.#a?.destroy(),this.#o?.destroy(),this.innerHTML=``}};customElements.get(`nine-table-sheet`)||customElements.define(`nine-table-sheet`,P);var F=class{#e;constructor(e){this.#e=e,this.#t()}#t=()=>{this.#n(),this.#r()};set loading(e){e?this.#e.classList.add(`loading`):this.#e.classList.remove(`loading`)}#n=()=>{let e=Array.from(this.#e.children).filter(e=>e.tagName.toUpperCase()===`TABLE`),t=e.length,n=e.map((e,n)=>{let r=n===0?`active`:``,i=e.id||`sheet${n+1}`;return`<nine-table-sheet class="${r}" data-index="${n}" data-sheet-id="${i}" id="${i}"></nine-table-sheet>`+(n<t-1?`<nine-splitter class="h" data-split-index="${n}"></nine-splitter>`:``)}).join(``),r=[`@import "https://cdn.jsdelivr.net/npm/@ninebone/datagrid@0.1.1/dist/css/nine-table.css";`];nine[`nine-table`]&&nine[`nine-table`].cssFile&&r.push(`@import "${nine[`nine-table`].cssFile}";`),this.#e.shadowRoot.innerHTML=`
81
+ `,this.#m={mainBody:this.querySelector(`.ng-sheet-body .ng-container-body`),hscrollbar:this.querySelector(`nine-table-hscrollbar`),vscrollbar:this.querySelector(`nine-table-vscrollbar`),content:this.querySelector(`.ng-sheet-body .ng-sheet-body-content`),scrollHolder:this.querySelector(`.ng-sheet-body .ng-virtual-height-holder`)}};#w=()=>{let e=this.querySelector(`.ng-container-left table`),t=this.querySelector(`.ng-container-body table`),n=this.querySelector(`.ng-container-right table`),r=Array.from(e.querySelectorAll(`thead tr:not(.col-indicator-rowgroup)`)),i=Array.from(t.querySelectorAll(`thead tr:not(.col-indicator-rowgroup)`)),a=Array.from(n.querySelectorAll(`thead tr:not(.col-indicator-rowgroup)`));this.#T(r,i,a);let o=Array.from(e.querySelectorAll(`tfoot tr`)),s=Array.from(t.querySelectorAll(`tfoot tr`)),c=Array.from(n.querySelectorAll(`tfoot tr`));this.#T(o,s,c)};#T=(e,t,n)=>{setTimeout(()=>{let r=Math.max(e.length,t.length,n.length);for(let i=0;i<r;i++){let r=[e[i]?.getBoundingClientRect().height||0,t[i]?.getBoundingClientRect().height||0,n[i]?.getBoundingClientRect().height||0],a=Math.max(...r);a>0&&(e[i]&&(e[i].style.height=`${a}px`),t[i]&&(t[i].style.height=`${a}px`),n[i]&&(n[i].style.height=`${a}px`))}})};#E=()=>{let e=this.querySelector(`.ng-sheet-body`);if(!e)return;let t=null;e.addEventListener(`mouseover`,n=>{let r=n.target.closest(`tr`);if(!r||!r.dataset.row&&r.dataset.row!==`0`)return;let i=r.dataset.row;t!==i&&(t=i,e.querySelectorAll(`tr[data-row="${i}"]`).forEach(e=>{e.classList.add(`hover`)}))}),e.addEventListener(`mouseout`,n=>{let r=n.target.closest(`tr`);if(!r)return;let i=n.relatedTarget;r.contains(i)||(e.querySelectorAll(`tr.hover`).forEach(e=>{e.classList.remove(`hover`)}),t=null)})};#D=()=>{[this.#d].forEach(e=>{new Set([...Reflect.ownKeys(e),...Reflect.ownKeys(Object.getPrototypeOf(e))]).forEach(t=>{if(t===`constructor`||String(t).startsWith(`#`))return;let n=e[t];typeof n==`function`?this[t]||(this[t]=(...t)=>n.apply(e,t)):typeof n==`object`&&n&&(this[t]||(this[t]=n))})})};disconnectedCallback(){this.#a?.destroy(),this.#o?.destroy(),this.innerHTML=``}};customElements.get(`nine-table-sheet`)||customElements.define(`nine-table-sheet`,P);var F=class{#e;constructor(e){this.#e=e,this.#t()}#t=()=>{this.#n(),this.#r()};set loading(e){e?this.#e.classList.add(`loading`):this.#e.classList.remove(`loading`)}#n=()=>{let e=Array.from(this.#e.children).filter(e=>e.tagName.toUpperCase()===`TABLE`),t=e.length,n=e.map((e,n)=>{let r=n===0?`active`:``,i=e.id||`sheet${n+1}`;return`<nine-table-sheet class="${r}" data-index="${n}" data-sheet-id="${i}" id="${i}"></nine-table-sheet>`+(n<t-1?`<nine-splitter class="h" data-split-index="${n}"></nine-splitter>`:``)}).join(``),r=[`@import "https://cdn.jsdelivr.net/npm/@ninebone/datagrid@0.1.2/dist/css/nine-table.css";`];nine[`nine-table`]&&nine[`nine-table`].cssFile&&r.push(`@import "${nine[`nine-table`].cssFile}";`),this.#e.shadowRoot.innerHTML=`
82
82
  <style>
83
83
  ${r.join(`
84
84
  `)}
@@ -105,7 +105,7 @@
105
105
 
106
106
  if (!data && !host) return "";
107
107
  return ${i};
108
- `),this.#n.set(i,e)),e(t,n,this.#e)}return i}catch{return e}}},L=class{#e;constructor(e){this.#e=e}provider={style:{value:``},add:e=>{if(!e||typeof e!=`object`)return;let{style:t,...n}=e;t&&typeof t==`string`&&(this.provider.style.value=t),Object.keys(n).length>0&&setTimeout(()=>{Object.entries(n).forEach(([e,t])=>{typeof t==`function`&&(this.#e[e]=t)}),this.#e.rerenderer()})}}},R=class{#e;constructor(e){this.#e=e,[`col`,`row`].forEach(e=>{this[e]=new Proxy({},{get:(t,n)=>{let r=this.#t();if(!r||!r[e])return;let i=r[e][n];return typeof i==`function`?(...t)=>i.apply(r[e],t):i}})})}getActiveSheets(){return this.#e.shadow.querySelectorAll(`nine-table-sheet.active`)}#t(){let e=this.getActiveSheets();return e.length>0?e[0]:null}},z=class extends HTMLElement{#e;#t;#n;#r;#i;#a=0;constructor(){super(),[`NINE-TABLE`].includes(this.tagName)&&r.log(`Welcome nine-table`,`0.1.1`),this.#e=this.attachShadow({mode:`open`}),this.#t=new s(this),this.#r=new L(this),this.#i=new R(this),this.#c()}connectedCallback(){setTimeout(()=>{this.#a=this.querySelectorAll(`table`)?.length,this.fields=new c(this),this.exprEngine=new I(this),this.#s(),this.#n=new F(this),this.#o()})}disconnectedCallback(){}#o=()=>{let e=0,t=setInterval(()=>{e++;let n=this.shadow.querySelectorAll(`nine-table-sheet`);if(e>=50&&clearInterval(t),n.length>=this.#a){let e=0;n.forEach(t=>{t.loaded&&e++}),e>=this.#a&&(clearInterval(t),this.loaded=!0,this.dispatchEvent(new CustomEvent(i.EVENT.LOAD,{bubbles:!0,detail:{target:this}})))}},100)};get shadow(){return this.#e}get dataManager(){return this.#t}get data(){return this.#t.data}setData(e){this.#t.data.set(e),this.refresh()}refresh(){this.activeSheet?.invalidate()}set loading(e){this.#n&&(this.#n.loading=e)}rerenderer(){this.activeSheet?.querySelectorAll(`tbody.body th,tbody.body td`).forEach(e=>{Array.from(e.children).find(e=>e.tagName.toLowerCase().startsWith(`cell-`)&&typeof e.rerenderer==`function`)?.rerenderer()})}sheet=e=>{if(e===null||e<0)return this.activeSheet;let t=Array.from(this.shadow.querySelectorAll(`nine-table-sheet`));return typeof e==`number`?t[e]||null:typeof e==`string`?this.shadow.querySelector(`nine-table-sheet#${e}, nine-table-sheet[data-sheet-id="${e}"]`)||null:t[0]||null};get sheets(){return Array.from(this.shadow.querySelectorAll(`nine-table-sheet`))}get activeSheet(){return this.shadow.querySelector(`nine-table-sheet.active`)||null}#s(){let e=new Set;this.querySelectorAll(`[data-source]`).forEach(t=>{let n=t.getAttribute(`data-source`);if(!n)return;let r=n.matchAll(/(?:host\.)?([a-zA-Z0-9_$]+)\s*\(/g);for(let t of r){let n=t[1];n&&n!==`host`&&e.add(n)}}),e.forEach(e=>{let t=null;Object.defineProperty(this,e,{set:e=>{t=e,this.rerenderer()},get:()=>t,configurable:!0,enumerable:!0})})}execute=e=>{setTimeout(()=>{this.loading=!0,setTimeout(()=>{try{e.call(this)}finally{this.loading=!1}})})};#c(){[this.#r,this.#i].forEach(e=>{new Set([...Reflect.ownKeys(e),...Reflect.ownKeys(Object.getPrototypeOf(e))]).forEach(t=>{if(t===`constructor`||String(t).startsWith(`#`))return;let n=e[t];typeof n==`function`?this[t]||(this[t]=(...t)=>n.apply(e,t)):typeof n==`object`&&n&&(this[t]||(this[t]=n))})})}};customElements.get(`nine-table`)||customElements.define(`nine-table`,z),customElements.get(`nine-table-simple`)||customElements.define(`nine-table-simple`,class extends z{connectedCallback(){this.setAttribute(`theme`,`simple`),super.connectedCallback()}});var B=class extends HTMLElement{constructor(){super()}applyBaseStyle(){}connectedCallback(){}},V=new Map,H=class extends B{#e;#t;#n;#r;#i;constructor(){super()}get#a(){return this.#r.getAttribute(`update-row-state`)===`false`}get host(){return this.#e}get sheet(){return this.#t}get cell(){return this.#r}get tr(){return this.#n}get attr(){return this.#i}connectedCallback(){super.connectedCallback(),this.#e=this.getRootNode().host,this.#r=this.closest(`th,td`),this.#n=this.#r.closest(`tr`),this.#t=this.#n.closest(`nine-table-sheet`),this.#r.classList.add(this.tagName),this.#i={};for(let e=0;e<this.#r.attributes.length;e++){let t=this.#r.attributes[e].name;[`text-align`,`class`,`cell-type`,`data-bind`,`data-expr`,`data-col`,`tabindex`].includes(t)||(this.#i[t]=this.#r.attributes[e].value)}if(!this.#r)return;let e=this.shadowRoot||this;e.querySelectorAll(`button, ng-expand-button`).forEach(e=>{e.addEventListener(`click`,()=>{let e=this.getAttribute(`onbuttonclick`)||this.getAttribute(`onButtonClick`)||this.#r?.getAttribute(`onbuttonclick`)||this.#r?.getAttribute(`onButtonClick`),t=this.data,n=parseInt(this.#r.dataset.row,10);if(e&&this.#e){e=e.replace(`()`,``);let r=e.match(/^(\w+)\s*\(/)?.[1]||e;typeof this.#e[r]==`function`?this.#e[r].call(this.#e,t,n,this.#r):typeof this.#e.exprFunction==`function`&&this.#e.exprFunction(e).call(this,t,n)}})});let t=e.querySelector(`.renderer`);t&&this.getAttribute(`link`)===`true`&&(t.classList.add(`link`),t.addEventListener(`click`,()=>{let e=this.getAttribute(`onlinkclick`)||this.getAttribute(`onLinkClick`),t=this.data,n=parseInt(this.#r.dataset.row,10);if(e&&this.#e){e=e.replace(`()`,``);let r=e.match(/^(\w+)\s*\(/)?.[1]||e;typeof this.#e[r]==`function`?this.#e[r].call(this.#e,t,n,this.#r):typeof this.#e.exprFunction==`function`&&this.#e.exprFunction(e).call(this,t,n)}this.#e?.dispatchEvent(new CustomEvent(ninegrid.EVENT.LINK_CLICK,{detail:{target:this.#r,data:t,currow:n},bubbles:!0,composed:!0}))}))}get data(){let e=this.#n?.data;if(!e)return null;if(!e.v)return e;let t=this.#e;return new Proxy(e,{get(e,n){if(n===`__ng`)return e.__ng;if(n===`v`)return e.v;let r=t?.fields?.indexOf?.(n)??-1;return r>=0?e.v[r]:e[n]}})}get value(){if(!this.#r||!this.#n?.data)return``;let e=this.#r.dataset?.bind;if(!e)return``;let t=this.#n.data;if(t.v&&Array.isArray(t.v)){let n=this.#e.fields.get().indexOf(e)??-1;return n>=0?t.v[n]??``:``}return t[e]??``}set value(e){if(!this.#r||!this.#e?.data)return;let t=parseInt(this.#n.dataset.row,10),n=this.#r.dataset.bind;!isNaN(t)&&n&&this.#e.data.setValue(t,n,e,this.#a)}get row(){return parseInt(this.#r?.dataset?.row,10)}get index(){return parseInt(this.#r?.dataset?.index,10)}isValid(){return!this.#r.classList.contains(`invalid`)}isInvalid(){return!this.isValid()}getDisplayText=(e=``)=>{if(!this.#r||!this.#r.closest(`tbody`)||!this.#n.data)return e;let t=this.#r.dataset.expr,n=this.#r.dataset.bind,r=parseInt(this.#r.dataset.row,10);if(t)try{return this.#n.getAttribute(`grouping`)===`true`?this.getGroupExprValue(t,this.#n.data,r,this.#r):this.#e.exprEngine.evaluate(t,this.#n.data,r)}catch{return e}return n?this.value??e:e};refresh(){if(!this.#r||!this.#n)return;let e=this.value;return this.#r.classList.remove(`invalid`),[`color`,`background`,`background-color`,`visible`,`enable`,`validator`].forEach(e=>{let t=this.#i[e];if(t){let n=this.#e.exprEngine.evaluate(t,this.#n.data,parseInt(this.#r.dataset.row,10));e===`validator`?n||this.#r.classList.add(`invalid`):e===`visible`?this.style.display=n?``:`none`:e===`enable`?(this.querySelectorAll(`input, button, textarea, select`).forEach(e=>{e.disabled=!n}),n?this.#r.removeAttribute(`disabled`):this.#r.setAttribute(`disabled`,`true`)):this.#r.style[e]=n}}),e}getExprValue(e,t,n){return!this.#e||!this.#e.exprEngine||e==null||e===``?e:this.#e.exprEngine.evaluate(e,t,n)}getGroupExprValue=(e,t,n,r)=>{if(!e)return``;try{n=parseInt(n,10);let i=e.replace(`()`,``).trim();if(this.#e&&typeof this.#e[i]==`function`)return this.#e[i].call(this,t,n,r);let a=i.match(/^(\w+)\s*\(\s*([\w\-]*)\s*\)/);if(a){let e=t[GROUP_IDX.CHILDREN],n=this.#e?.data?.getArray?this.#e.data.getArray():[],r=e?e.map(e=>n[e]).filter(Boolean):[],[,i,o]=a,s=this.#e;switch(i.toLowerCase()){case`count`:return r.length;case`sum`:{let e=s?.fields?.indexOf?.(o)??-1;return r.reduce((t,n)=>{let r=e>=0?n.v?.[e]:n[o];return t+(Number(r)||0)},0)}case`avg`:{if(r.length===0)return 0;let e=s?.fields?.indexOf?.(o)??-1;return r.reduce((t,n)=>{let r=e>=0?n.v?.[e]:n[o];return t+(Number(r)||0)},0)/r.length}}}if(this.#e&&typeof this.#e.exprFunction==`function`)return this.#e.exprFunction(e).call(this,t,n,this.#e.data);if(e.includes(`data.`)||e.includes(`childRecords`)||e.includes(`groupRecord`)){let i=V.get(`grp_`+e);return i||(i=Function(`groupRecord`,`row`,`cell`,`host`,`
108
+ `),this.#n.set(i,e)),e(t,n,this.#e)}return i}catch{return e}}},L=class{#e;constructor(e){this.#e=e}provider={style:{value:``},add:e=>{if(!e||typeof e!=`object`)return;let{style:t,...n}=e;t&&typeof t==`string`&&(this.provider.style.value=t),Object.keys(n).length>0&&setTimeout(()=>{Object.entries(n).forEach(([e,t])=>{typeof t==`function`&&(this.#e[e]=t)}),this.#e.rerenderer()})}}},R=class{#e;constructor(e){this.#e=e,[`col`,`row`].forEach(e=>{this[e]=new Proxy({},{get:(t,n)=>{let r=this.#t();if(!r||!r[e])return;let i=r[e][n];return typeof i==`function`?(...t)=>i.apply(r[e],t):i}})})}getActiveSheets(){return this.#e.shadow.querySelectorAll(`nine-table-sheet.active`)}#t(){let e=this.getActiveSheets();return e.length>0?e[0]:null}},z=class extends HTMLElement{#e;#t;#n;#r;#i;#a=0;constructor(){super(),[`NINE-TABLE`].includes(this.tagName)&&r.log(`Welcome nine-table`,`0.1.2`),this.#e=this.attachShadow({mode:`open`}),this.#t=new s(this),this.#r=new L(this),this.#i=new R(this),this.#c()}connectedCallback(){setTimeout(()=>{this.#a=this.querySelectorAll(`table`)?.length,this.fields=new c(this),this.exprEngine=new I(this),this.#s(),this.#n=new F(this),this.#o()})}disconnectedCallback(){}#o=()=>{let e=0,t=setInterval(()=>{e++;let n=this.shadow.querySelectorAll(`nine-table-sheet`);if(e>=50&&clearInterval(t),n.length>=this.#a){let e=0;n.forEach(t=>{t.loaded&&e++}),e>=this.#a&&(clearInterval(t),this.loaded=!0,this.dispatchEvent(new CustomEvent(i.EVENT.LOAD,{bubbles:!0,detail:{target:this}})))}},100)};get shadow(){return this.#e}get dataManager(){return this.#t}get data(){return this.#t.data}setData(e){this.#t.data.set(e),this.refresh()}refresh(){this.activeSheet?.invalidate()}set loading(e){this.#n&&(this.#n.loading=e)}rerenderer(){this.activeSheet?.querySelectorAll(`tbody.body th,tbody.body td`).forEach(e=>{Array.from(e.children).find(e=>e.tagName.toLowerCase().startsWith(`cell-`)&&typeof e.rerenderer==`function`)?.rerenderer()})}sheet=e=>{if(e===null||e<0)return this.activeSheet;let t=Array.from(this.shadow.querySelectorAll(`nine-table-sheet`));return typeof e==`number`?t[e]||null:typeof e==`string`?this.shadow.querySelector(`nine-table-sheet#${e}, nine-table-sheet[data-sheet-id="${e}"]`)||null:t[0]||null};get sheets(){return Array.from(this.shadow.querySelectorAll(`nine-table-sheet`))}get activeSheet(){return this.shadow.querySelector(`nine-table-sheet.active`)||null}#s(){let e=new Set;this.querySelectorAll(`[data-source]`).forEach(t=>{let n=t.getAttribute(`data-source`);if(!n)return;let r=n.matchAll(/(?:host\.)?([a-zA-Z0-9_$]+)\s*\(/g);for(let t of r){let n=t[1];n&&n!==`host`&&e.add(n)}}),e.forEach(e=>{let t=null;Object.defineProperty(this,e,{set:e=>{t=e,this.rerenderer()},get:()=>t,configurable:!0,enumerable:!0})})}execute=e=>{setTimeout(()=>{this.loading=!0,setTimeout(()=>{try{e.call(this)}finally{this.loading=!1}})})};#c(){[this.#r,this.#i].forEach(e=>{new Set([...Reflect.ownKeys(e),...Reflect.ownKeys(Object.getPrototypeOf(e))]).forEach(t=>{if(t===`constructor`||String(t).startsWith(`#`))return;let n=e[t];typeof n==`function`?this[t]||(this[t]=(...t)=>n.apply(e,t)):typeof n==`object`&&n&&(this[t]||(this[t]=n))})})}};customElements.get(`nine-table`)||customElements.define(`nine-table`,z),customElements.get(`nine-table-simple`)||customElements.define(`nine-table-simple`,class extends z{connectedCallback(){this.setAttribute(`theme`,`simple`),super.connectedCallback()}});var B=class extends HTMLElement{constructor(){super()}applyBaseStyle(){}connectedCallback(){}},V=new Map,H=class extends B{#e;#t;#n;#r;#i;constructor(){super()}get#a(){return this.#r.getAttribute(`update-row-state`)===`false`}get host(){return this.#e}get sheet(){return this.#t}get cell(){return this.#r}get tr(){return this.#n}get attr(){return this.#i}connectedCallback(){super.connectedCallback(),this.#e=this.getRootNode().host,this.#r=this.closest(`th,td`),this.#n=this.#r.closest(`tr`),this.#t=this.#n.closest(`nine-table-sheet`),this.#r.classList.add(this.tagName),this.#i={};for(let e=0;e<this.#r.attributes.length;e++){let t=this.#r.attributes[e].name;[`text-align`,`class`,`cell-type`,`data-bind`,`data-expr`,`data-col`,`tabindex`].includes(t)||(this.#i[t]=this.#r.attributes[e].value)}if(!this.#r)return;let e=this.shadowRoot||this;e.querySelectorAll(`button, ng-expand-button`).forEach(e=>{e.addEventListener(`click`,()=>{let e=this.getAttribute(`onbuttonclick`)||this.getAttribute(`onButtonClick`)||this.#r?.getAttribute(`onbuttonclick`)||this.#r?.getAttribute(`onButtonClick`),t=this.data,n=parseInt(this.#r.dataset.row,10);if(e&&this.#e){e=e.replace(`()`,``);let r=e.match(/^(\w+)\s*\(/)?.[1]||e;typeof this.#e[r]==`function`?this.#e[r].call(this.#e,t,n,this.#r):typeof this.#e.exprFunction==`function`&&this.#e.exprFunction(e).call(this,t,n)}})});let t=e.querySelector(`.renderer`);t&&this.getAttribute(`link`)===`true`&&(t.classList.add(`link`),t.addEventListener(`click`,()=>{let e=this.getAttribute(`onlinkclick`)||this.getAttribute(`onLinkClick`),t=this.data,n=parseInt(this.#r.dataset.row,10);if(e&&this.#e){e=e.replace(`()`,``);let r=e.match(/^(\w+)\s*\(/)?.[1]||e;typeof this.#e[r]==`function`?this.#e[r].call(this.#e,t,n,this.#r):typeof this.#e.exprFunction==`function`&&this.#e.exprFunction(e).call(this,t,n)}this.#e?.dispatchEvent(new CustomEvent(ninegrid.EVENT.LINK_CLICK,{detail:{target:this.#r,data:t,currow:n},bubbles:!0,composed:!0}))}))}get data(){let e=this.#n?.data;if(!e)return null;if(!e.v)return e;let t=this.#e;return new Proxy(e,{get(e,n){if(n===`__ng`)return e.__ng;if(n===`v`)return e.v;let r=t?.fields?.indexOf?.(n)??-1;return r>=0?e.v[r]:e[n]}})}get value(){if(!this.#r||!this.#n?.data)return``;let e=this.#r.dataset?.bind;if(!e)return``;let t=this.#n.data;if(t.v&&Array.isArray(t.v)){let n=this.#e.fields.get().indexOf(e)??-1;return n>=0?t.v[n]??``:``}return t[e]??``}set value(e){if(!this.#r||!this.#e?.data)return;let t=parseInt(this.#n.dataset.row,10),n=this.#r.dataset.bind;!isNaN(t)&&n&&this.#e.data.setValue(t,n,e,this.#a)}get row(){return parseInt(this.#r?.dataset?.row,10)}get index(){return parseInt(this.#r?.dataset?.index,10)}isValid(){return!this.#r.classList.contains(`invalid`)}isInvalid(){return!this.isValid()}getDisplayText=(e=``)=>{if(!this.#r||!this.#r.closest(`tbody`)||!this.#n.data)return e;let t=this.#r.dataset.expr,n=this.#r.dataset.bind,r=parseInt(this.#r.dataset.row,10);if(t)try{return this.#n.getAttribute(`grouping`)===`true`?this.getGroupExprValue(t,this.#n.data,r,this.#r):this.#e.exprEngine.evaluate(t,this.#n.data,r)}catch{return e}return n?this.value??e:e};refresh(){if(!this.#r||!this.#n)return;let e=this.value;return this.#r.classList.remove(`invalid`),[`color`,`background`,`background-color`,`visible`,`enable`,`validator`].forEach(e=>{let t=this.#i[e];if(t){let n=this.#e.exprEngine.evaluate(t,this.#n.data,parseInt(this.#r.dataset.row,10));e===`validator`?n||this.#r.classList.add(`invalid`):e===`visible`?this.style.display=n?``:`none`:e===`enable`?(this.querySelectorAll(`input, button, textarea, select`).forEach(e=>{e.disabled=!n}),n?this.#r.removeAttribute(`disabled`):this.#r.setAttribute(`disabled`,`true`)):this.#r.style[e]=n}}),e}getExprValue(e,t,n){return!this.#e||!this.#e.exprEngine||e==null||e===``?e:this.#e.exprEngine.evaluate(e,t,n)}getGroupExprValue=(e,t,n,r)=>{if(!e)return``;try{n=parseInt(n,10);let i=e.replace(`()`,``).trim();if(this.#e&&typeof this.#e[i]==`function`)return this.#e[i].call(this,t,n,r);let a=i.match(/^(\w+)\s*\(\s*([\w\-]*)\s*\)/);if(a){let e=t[GROUP_IDX.CHILDREN],n=this.#e?.data?.getArray?this.#e.data.getArray():[],r=e?e.map(e=>n[e]).filter(Boolean):[],[,i,o]=a,s=this.#e;switch(i.toLowerCase()){case`count`:return r.length;case`sum`:{let e=s?.fields?.indexOf?.(o)??-1;return r.reduce((t,n)=>{let r=e>=0?n.v?.[e]:n[o];return t+(Number(r)||0)},0)}case`avg`:{if(r.length===0)return 0;let e=s?.fields?.indexOf?.(o)??-1;return r.reduce((t,n)=>{let r=e>=0?n.v?.[e]:n[o];return t+(Number(r)||0)},0)/r.length}}}if(this.#e&&typeof this.#e.exprFunction==`function`)return this.#e.exprFunction(e).call(this,t,n,this.#e.data);if(e.includes(`data.`)||e.includes(`childRecords`)||e.includes(`groupRecord`)){let i=V.get(`grp_`+e);return i||(i=Function(`groupRecord`,`row`,`cell`,`host`,`
109
109
  const indices = groupRecord[3]; // GROUP_IDX.CHILDREN = 3
110
110
  const allRecords = host?.data?.getArray ? host.data.getArray() : [];
111
111
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ninebone/datagrid",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Blazing-fast virtualized HTML table for massive datasets with inline editing",
5
5
  "keywords": [
6
6
  "datagrid",