pivotgrid-js 0.1.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/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ Copyright (c) 2026 Aleksandr Korolev
2
+
3
+ Non-Commercial License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to use,
7
+ copy, modify, and distribute the Software for personal, educational, or
8
+ non-commercial purposes, subject to the following conditions:
9
+
10
+ 1. The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ 2. The Software may not be used, in whole or in part, for commercial purposes
14
+ without a separate commercial license obtained from the author.
15
+
16
+ 3. "Commercial use" means any use of the Software intended for or directed
17
+ toward commercial advantage or monetary compensation, including but not
18
+ limited to: use in a commercial product or service, use by a for-profit
19
+ organization, or use in a client project for payment.
20
+
21
+ For commercial licensing, contact: korolevalexa@gmail.com
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
@@ -0,0 +1,60 @@
1
+ PIVOTGRID COMMERCIAL LICENSE AGREEMENT
2
+
3
+ This Commercial License Agreement ("Agreement") is entered into as of [DATE]
4
+ between Aleksandr Korolev ("Licensor") and [COMPANY/INDIVIDUAL NAME] ("Licensee").
5
+
6
+ 1. GRANT OF LICENSE
7
+
8
+ Licensor grants Licensee a non-exclusive, non-transferable, worldwide license
9
+ to use, integrate, and deploy the PivotGrid software ("Software") in commercial
10
+ products and services, subject to the terms of this Agreement.
11
+
12
+ 2. PERMITTED USES
13
+
14
+ Licensee may:
15
+ - Use the Software in commercial products or services
16
+ - Integrate the Software into client projects
17
+ - Modify the Software for internal use
18
+ - Deploy the Software on any number of servers owned or operated by Licensee
19
+
20
+ 3. RESTRICTIONS
21
+
22
+ Licensee may not:
23
+ - Resell, sublicense, or redistribute the Software as a standalone product
24
+ - Remove or alter copyright notices in the Software
25
+ - Use the Software to create a competing product
26
+
27
+ 4. LICENSE SCOPE
28
+
29
+ This license covers: [DESCRIPTION — e.g. "single commercial product",
30
+ "unlimited internal projects", "single client project"]
31
+
32
+ 5. PAYMENT
33
+
34
+ License fee: [AMOUNT AND CURRENCY]
35
+ Payment date: [DATE]
36
+
37
+ 6. TERM
38
+
39
+ This Agreement is effective from the date of payment and remains in force
40
+ indefinitely unless terminated due to breach of its terms.
41
+
42
+ 7. TERMINATION
43
+
44
+ This Agreement terminates automatically if Licensee breaches any of its terms.
45
+ Upon termination, Licensee must cease all use of the Software.
46
+
47
+ 8. WARRANTY DISCLAIMER
48
+
49
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. LICENSOR SHALL
50
+ NOT BE LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF THE SOFTWARE.
51
+
52
+ 9. CONTACT
53
+
54
+ Aleksandr Korolev
55
+ korolevalexa@gmail.com
56
+
57
+
58
+ ___________________________ ___________________________
59
+ Aleksandr Korolev (Licensor) [NAME] (Licensee)
60
+ Date: ___________________ Date: ___________________
package/README.dev.md ADDED
@@ -0,0 +1,247 @@
1
+ # PivotGrid
2
+
3
+ Vanilla JS pivot table — no dependencies, no frameworks.
4
+
5
+ - **Fast** — virtual scroll, columnar storage on TypedArrays, in-memory cache
6
+ - **Flexible** — drag-and-drop dimensions, filters, hierarchical rows and columns
7
+ - **Simple** — one `<div>` and two attributes, nothing else needed
8
+
9
+ ## Concept
10
+
11
+ All configuration is done through a config file. The grid API is intentionally minimal:
12
+ just create a container with `data-config` and the widget does the rest.
13
+
14
+ The config is stored on the server and loaded at startup —
15
+ no need to change application code to modify the grid structure.
16
+
17
+ ## Quick Start
18
+
19
+ ```html
20
+ <!-- Styles -->
21
+ <link rel="stylesheet" href="src/pivot.css">
22
+ <link rel="stylesheet" href="src/field-zones.css">
23
+ <link rel="stylesheet" href="widget/widget.css">
24
+
25
+ <!-- Engine -->
26
+ <script src="engine/dictionary-encoder.js"></script>
27
+ <script src="engine/aggregator.js"></script>
28
+ <script src="engine/column-store.js"></script>
29
+
30
+ <!-- Providers -->
31
+ <script src="providers/rest-provider.js"></script>
32
+ <script src="providers/array-provider.js"></script>
33
+
34
+ <!-- Component -->
35
+ <script src="src/pivot.js"></script>
36
+ <script src="src/field-zones.js"></script>
37
+ <script src="src/filter-manager.js"></script>
38
+
39
+ <!-- Widget -->
40
+ <script src="widget/i18n.js"></script>
41
+ <script src="widget/cache-manager.js"></script>
42
+ <script src="widget/pivot-widget.js"></script>
43
+
44
+ <!-- Grid -->
45
+ <div id="my-pivot"
46
+ data-config="sales"
47
+ data-server="http://localhost:8000">
48
+ </div>
49
+ ```
50
+
51
+ The widget builds the entire UI structure inside the container automatically.
52
+
53
+ ## Demo Without a Server
54
+
55
+ ```html
56
+ <!-- Demo data and config -->
57
+ <script src="demo/demo-data.js"></script>
58
+ <script src="demo/demo-config.js"></script>
59
+
60
+ <div id="my-pivot" data-demo="true"></div>
61
+ ```
62
+
63
+ ## Container Attributes
64
+
65
+ | Attribute | Description | Example |
66
+ |-----------|-------------|---------|
67
+ | `data-config` | Config name on the server | `"sales"` |
68
+ | `data-server` | Server URL | `"http://localhost:8000"` |
69
+ | `data-demo` | Demo mode without a server | `"true"` |
70
+ | `data-lang` | Interface language | `"ru"` / `"en"` |
71
+ | `data-standalone` | Use an existing HTML structure | `"true"` |
72
+
73
+ ## Config
74
+
75
+ Configs are stored on the server at `configs/{name}.json`:
76
+
77
+ ```json
78
+ {
79
+ "query": "SELECT * FROM sales_data",
80
+
81
+ "dimensions": ["region", "category", "channel"],
82
+ "measures": ["revenue", "units"],
83
+ "funcs": ["sum", "avg", "count", "min", "max"],
84
+
85
+ "fields": {
86
+ "region": { "label": "region", "title": "Region" },
87
+ "category": { "label": "category", "title": "Category" },
88
+ "channel": { "label": "channel", "title": "Channel" },
89
+ "revenue": { "label": "revenue", "title": "Revenue" },
90
+ "units": { "label": "units", "title": "Units" }
91
+ },
92
+
93
+ "cachedDimensions": ["region", "category"],
94
+
95
+ "rows": ["region"],
96
+ "columns": [],
97
+ "measure": "revenue",
98
+ "func": "sum",
99
+
100
+ "maxCachedRows": 500000,
101
+ "filterCheckboxLimit": 5
102
+ }
103
+ ```
104
+
105
+ ## Server
106
+
107
+ `server/server.py` — a lightweight Python proxy to the database.
108
+
109
+ ```bash
110
+ pip install psycopg2-binary
111
+ python server/server.py
112
+ ```
113
+
114
+ ### Endpoints
115
+
116
+ | Method | Path | Description |
117
+ |--------|------|-------------|
118
+ | `POST` | `/query` | Execute a SQL query |
119
+ | `GET` | `/configs` | List all configs |
120
+ | `GET` | `/configs/{name}` | Get a config |
121
+ | `POST` | `/configs/{name}` | Save a config |
122
+ | `GET` | `/server-config` | DB settings (password excluded) |
123
+ | `POST` | `/server-config` | Save DB settings |
124
+
125
+ ### DB Connectors
126
+
127
+ PostgreSQL is included by default. To add a custom database, create a file in `server/connectors/`:
128
+
129
+ ```python
130
+ # server/connectors/mydb.py
131
+ NAME = "My Database"
132
+
133
+ def execute_query(query):
134
+ # your implementation
135
+ return [{"col": "val"}, ...]
136
+ ```
137
+
138
+ The server picks up the new connector on next startup.
139
+
140
+ ## Config Editor
141
+
142
+ A visual config editor — `config/config-editor.html`.
143
+
144
+ - Fetch columns from the database with one click
145
+ - Configure dimensions, measures, sortKey
146
+ - Drag-and-drop initial state (rows / columns / cache)
147
+ - Save config to the server
148
+ - Preview changes without saving
149
+
150
+ ## Grid API
151
+
152
+ ```js
153
+ // Expand / collapse rows
154
+ grid.expandAll()
155
+ grid.collapseAll()
156
+ grid.expandToDepth(depth)
157
+
158
+ // Expand / collapse columns
159
+ grid.expandAllCols()
160
+ grid.collapseAllCols()
161
+
162
+ // Subtotals
163
+ grid.toggleSubtotals(visible)
164
+
165
+ // Update data
166
+ grid.setResult(result, { rows, columns, measure, fieldDefs })
167
+ ```
168
+
169
+ ## Drillthrough
170
+
171
+ Clicking a cell dispatches a `drillthrough` event:
172
+
173
+ ```js
174
+ container.addEventListener('drillthrough', (e) => {
175
+ const { context, value } = e.detail;
176
+ // context = { region: 'North', channel: 'Online' }
177
+ // value = aggregated cell value
178
+ });
179
+ ```
180
+
181
+ Click behaviour is configured in the config:
182
+
183
+ ```json
184
+ "drillthroughQuery": "SELECT * FROM sales WHERE {filters} LIMIT 200"
185
+ ```
186
+
187
+ or
188
+
189
+ ```json
190
+ "drillthroughUrl": "https://myapp.com/details"
191
+ ```
192
+
193
+ ## Internationalization
194
+
195
+ ```html
196
+ <div data-config="sales" data-lang="en"></div>
197
+ ```
198
+
199
+ `ru` and `en` are supported. To add a language, extend the `I18N` object in `widget/i18n.js`.
200
+
201
+ ## Project Structure
202
+
203
+ ```
204
+ ├── src/ # Component
205
+ │ ├── pivot.js
206
+ │ ├── pivot.css
207
+ │ ├── field-zones.js
208
+ │ ├── field-zones.css
209
+ │ └── filter-manager.js
210
+
211
+ ├── engine/ # Aggregation engine
212
+ │ ├── aggregator.js
213
+ │ ├── column-store.js
214
+ │ └── dictionary-encoder.js
215
+
216
+ ├── providers/ # Data providers
217
+ │ ├── rest-provider.js
218
+ │ └── array-provider.js
219
+
220
+ ├── widget/ # Widget (UI + init)
221
+ │ ├── pivot-widget.js
222
+ │ ├── cache-manager.js
223
+ │ ├── i18n.js
224
+ │ └── widget.css
225
+
226
+ ├── config/ # Config editor
227
+ │ ├── config-editor.html
228
+ │ ├── config-editor.css
229
+ │ └── config-editor.js
230
+
231
+ ├── server/ # Python server
232
+ │ ├── server.py
233
+ │ └── connectors/
234
+ │ └── postgresql.py
235
+
236
+ └── demo/ # Demo
237
+ ├── index.html
238
+ ├── example.html
239
+ ├── demo-example.html
240
+ ├── demo-data.js
241
+ └── demo-config.js
242
+ ```
243
+
244
+ ## License
245
+
246
+ Free for personal and non-commercial use.
247
+ For commercial use, a license is required — contact [korolevalexa@gmail.com](mailto:korolevalexa@gmail.com).
package/README.md ADDED
@@ -0,0 +1,253 @@
1
+ # PivotGrid JS
2
+
3
+ Vanilla JS pivot table — no dependencies, no frameworks.
4
+
5
+ - **Fast** — virtual scroll, columnar storage on TypedArrays, in-memory cache
6
+ - **Flexible** — drag-and-drop dimensions, filters, hierarchical rows and columns
7
+ - **Simple** — one `<div>` and few attributes, nothing else needed
8
+
9
+ **[Live Demo](https://windowrepino.ru/pivot/demo/demo-example.html)**
10
+
11
+ ![PivotGrid](https://raw.githubusercontent.com/AlexKorole/pivotgrid/main/assets/screenshot.png)
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install pivotgrid-js
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```html
22
+ <!DOCTYPE html>
23
+ <html>
24
+ <head>
25
+ <link rel="stylesheet" href="node_modules/pivotgrid-js/dist/pivotgrid.css">
26
+ </head>
27
+ <body>
28
+
29
+ <div id="my-pivot"
30
+ data-config="sales"
31
+ data-server="http://localhost:8000"
32
+ data-lang="en">
33
+ </div>
34
+
35
+ <script src="node_modules/pivotgrid-js/dist/pivotgrid.js"></script>
36
+ <script src="node_modules/pivotgrid-js/widget/pivot-widget.js"></script>
37
+
38
+ </body>
39
+ </html>
40
+ ```
41
+
42
+ ## Demo Mode (no server)
43
+
44
+ ```html
45
+ <!DOCTYPE html>
46
+ <html>
47
+ <head>
48
+ <link rel="stylesheet" href="node_modules/pivotgrid-js/dist/pivotgrid.css">
49
+ </head>
50
+ <body>
51
+ <div id="my-pivot" data-demo="true" data-lang="en"></div>
52
+
53
+ <script src="node_modules/pivotgrid-js/dist/pivotgrid.js"></script>
54
+ <script src="node_modules/pivotgrid-js/demo_data/demo-data.js"></script>
55
+ <script src="node_modules/pivotgrid-js/demo_data/demo-config.js"></script>
56
+ <script src="node_modules/pivotgrid-js/widget/pivot-widget.js"></script>
57
+ </body>
58
+ </html>
59
+ ```
60
+
61
+ ## Container Attributes
62
+
63
+ | Attribute | Description | Example |
64
+ |-----------|-------------|---------|
65
+ | `data-config` | Config name on the server | `"sales"` |
66
+ | `data-server` | Server URL | `"http://localhost:8000"` |
67
+ | `data-demo` | Demo mode without a server | `"true"` |
68
+ | `data-lang` | Interface language | `"ru"` / `"en"` |
69
+ | `data-standalone` | Use an existing HTML structure | `"true"` |
70
+
71
+ ## Config
72
+
73
+ Configs are stored on the server at `server/configs/{name}.json`:
74
+
75
+ ```json
76
+ {
77
+ "query": "SELECT * FROM sales_data",
78
+
79
+ "dimensions": ["region", "category", "channel"],
80
+ "measures": ["revenue", "units"],
81
+ "funcs": ["sum", "avg", "count", "min", "max"],
82
+
83
+ "fields": {
84
+ "region": { "label": "region", "title": "Region" },
85
+ "category": { "label": "category", "title": "Category" },
86
+ "channel": { "label": "channel", "title": "Channel" },
87
+ "revenue": { "label": "revenue", "title": "Revenue" },
88
+ "units": { "label": "units", "title": "Units" }
89
+ },
90
+
91
+ "cachedDimensions": ["region", "category"],
92
+
93
+ "rows": ["region"],
94
+ "columns": [],
95
+ "measure": "revenue",
96
+ "func": "sum",
97
+
98
+ "maxCachedRows": 500000,
99
+ "filterCheckboxLimit": 5,
100
+
101
+ "drillthroughQuery": "SELECT * FROM sales_data WHERE {filters} LIMIT 200"
102
+ }
103
+ ```
104
+
105
+ ### Config Fields
106
+
107
+ | Field | Type | Description |
108
+ |-------|------|-------------|
109
+ | `query` | `string` | Base SQL query |
110
+ | `dimensions` | `string[]` | List of dimension field names |
111
+ | `measures` | `string[]` | List of measure field names |
112
+ | `funcs` | `string[]` | Aggregation functions: `sum`, `avg`, `count`, `min`, `max`, `stddev`, `variance` |
113
+ | `fields` | `object` | Field definitions — see below |
114
+ | `cachedDimensions` | `string[]` | Dimensions to pre-aggregate and cache on startup |
115
+ | `rows` | `string[]` | Initial row dimensions |
116
+ | `columns` | `string[]` | Initial column dimensions |
117
+ | `measure` | `string` | Initial active measure |
118
+ | `func` | `string` | Initial aggregation function |
119
+ | `maxCachedRows` | `number` | Maximum rows in cache (default: `500000`) |
120
+ | `filterCheckboxLimit` | `number` | Max distinct values to show as checkboxes in filter popup (default: `30`) |
121
+ | `drillthroughQuery` | `string` | SQL for drillthrough panel. Use `{filters}` as placeholder |
122
+ | `drillthroughUrl` | `string` | External URL for drillthrough. Filters are appended as query params |
123
+
124
+ ### Field Definition
125
+
126
+ Each entry in `fields` can have:
127
+
128
+ | Property | Type | Description |
129
+ |----------|------|-------------|
130
+ | `label` | `string` | Actual column name in the database |
131
+ | `title` | `string` | Display name shown in the UI |
132
+ | `sortKey` | `string` | Column to sort by instead of the label (useful for month names etc.) |
133
+
134
+ Example — month sorted by number:
135
+ ```json
136
+ "sale_month": {
137
+ "label": "sale_month_name",
138
+ "title": "Month",
139
+ "sortKey": "sale_month_num"
140
+ }
141
+ ```
142
+
143
+ ## Server
144
+
145
+ A lightweight Python proxy to your database is included:
146
+
147
+ ```bash
148
+ pip install psycopg2-binary
149
+ python node_modules/pivotgrid-js/server/server.py
150
+ ```
151
+
152
+ See `node_modules/pivotgrid-js/server/README.md` for full server documentation.
153
+
154
+ ## Config Editor
155
+
156
+ A visual config editor is included. Open it locally:
157
+
158
+ ```
159
+ node_modules/pivotgrid-js/config/config-editor.html
160
+ ```
161
+
162
+ ![Config Editor](https://raw.githubusercontent.com/AlexKorole/pivotgrid/main/assets/config-editor.png)
163
+
164
+ Features:
165
+ - Fetch columns from the database with one click
166
+ - Configure dimensions, measures, sortKey
167
+ - Drag-and-drop initial state (rows / columns / cache)
168
+ - Save config to the server
169
+ - Preview changes without saving
170
+
171
+ ## Grid API
172
+
173
+ ```js
174
+ // Expand / collapse rows
175
+ grid.expandAll()
176
+ grid.collapseAll()
177
+ grid.expandToDepth(depth) // e.g. expandToDepth(1) — first level only
178
+
179
+ // Expand / collapse columns
180
+ grid.expandAllCols()
181
+ grid.collapseAllCols()
182
+
183
+ // Subtotals
184
+ grid.toggleSubtotals(visible)
185
+
186
+ // Update data
187
+ grid.setResult(result, { rows, columns, measure, fieldDefs })
188
+ ```
189
+
190
+ ## Drillthrough
191
+
192
+ Three ways to handle cell clicks:
193
+
194
+ ### 1. Built-in panel (SQL query)
195
+
196
+ Add `drillthroughQuery` to your config:
197
+
198
+ ```json
199
+ "drillthroughQuery": "SELECT * FROM sales_data WHERE {filters} LIMIT 200"
200
+ ```
201
+
202
+ A detail panel slides up at the bottom of the page showing the raw rows.
203
+
204
+ ### 2. External URL
205
+
206
+ Add `drillthroughUrl` to your config:
207
+
208
+ ```json
209
+ "drillthroughUrl": "https://myapp.com/details"
210
+ ```
211
+
212
+ Opens the URL in a new tab with filters appended as query parameters:
213
+ `https://myapp.com/details?region=North&channel=Online`
214
+
215
+ ### 3. Custom handler
216
+
217
+ Listen for the `drillthrough` event on the container:
218
+
219
+ ```js
220
+ document.getElementById('my-pivot').addEventListener('drillthrough', (e) => {
221
+ const { context, value } = e.detail;
222
+ // context = { region: 'North', channel: 'Online' }
223
+ // value = aggregated cell value
224
+ // your custom logic here
225
+ });
226
+ ```
227
+
228
+ If neither `drillthroughQuery` nor `drillthroughUrl` is set in the config,
229
+ only your custom handler fires.
230
+
231
+ ## Internationalization
232
+
233
+ `ru` and `en` are supported out of the box:
234
+
235
+ ```html
236
+ <div data-config="sales" data-lang="en"></div>
237
+ ```
238
+
239
+ To add a language, extend the `I18N` object in `widget/i18n.js`.
240
+
241
+ ## Using with a Bundler
242
+
243
+ ```js
244
+ import { PivotGrid, Aggregator, RestProvider, ArrayProvider } from 'pivotgrid-js';
245
+ ```
246
+
247
+ Available exports: `PivotGrid`, `Aggregator`, `ColumnStore`, `DictionaryEncoder`,
248
+ `RestProvider`, `ArrayProvider`, `FieldZones`, `FilterManager`, `CacheManager`, `I18N`.
249
+
250
+ ## License
251
+
252
+ Free for personal and non-commercial use.
253
+ For commercial use, a license is required — contact [korolevalexa@gmail.com](mailto:korolevalexa@gmail.com).