@vue-pivottable/multi-value-renderer 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 +21 -0
- package/README.md +167 -0
- package/dist/MultiValuePivotData.js +81 -0
- package/dist/MultiValueTableRenderer.js +364 -0
- package/dist/core.js +92 -0
- package/dist/core.mjs +92 -0
- package/dist/index.js +12 -0
- package/dist/index.mjs +12 -0
- package/dist/styles.css +119 -0
- package/dist/vue2.js +399 -0
- package/dist/vue2.mjs +399 -0
- package/dist/vue3.js +5 -0
- package/dist/vue3.mjs +5 -0
- package/package.json +81 -0
- package/types/index.d.ts +170 -0
package/dist/vue2.mjs
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { PivotUtilities } from "vue-pivottable";
|
|
2
|
+
import { c as createMultiValueAggregator } from "./MultiValuePivotData.js";
|
|
3
|
+
const { PivotData } = PivotUtilities;
|
|
4
|
+
function redColorScaleGenerator(values) {
|
|
5
|
+
const numericValues = values.filter((v) => typeof v === "number" && !isNaN(v));
|
|
6
|
+
if (numericValues.length === 0) {
|
|
7
|
+
return () => ({});
|
|
8
|
+
}
|
|
9
|
+
const min = Math.min(...numericValues);
|
|
10
|
+
const max = Math.max(...numericValues);
|
|
11
|
+
return (x) => {
|
|
12
|
+
if (typeof x !== "number" || isNaN(x) || max === min) {
|
|
13
|
+
return {};
|
|
14
|
+
}
|
|
15
|
+
const nonRed = 255 - Math.round(255 * (x - min) / (max - min));
|
|
16
|
+
return { backgroundColor: `rgb(255,${nonRed},${nonRed})` };
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function makeMultiValueRenderer(opts = {}) {
|
|
20
|
+
return {
|
|
21
|
+
name: opts.name || "vue2-multi-value-table",
|
|
22
|
+
props: {
|
|
23
|
+
// Data props
|
|
24
|
+
data: {
|
|
25
|
+
type: [Array, Object, Function],
|
|
26
|
+
required: true
|
|
27
|
+
},
|
|
28
|
+
rows: {
|
|
29
|
+
type: Array,
|
|
30
|
+
default: () => []
|
|
31
|
+
},
|
|
32
|
+
cols: {
|
|
33
|
+
type: Array,
|
|
34
|
+
default: () => []
|
|
35
|
+
},
|
|
36
|
+
vals: {
|
|
37
|
+
type: Array,
|
|
38
|
+
default: () => []
|
|
39
|
+
},
|
|
40
|
+
// Multi-value specific props
|
|
41
|
+
aggregatorMap: {
|
|
42
|
+
type: Object,
|
|
43
|
+
default: () => ({})
|
|
44
|
+
},
|
|
45
|
+
aggregators: {
|
|
46
|
+
type: Object,
|
|
47
|
+
required: true
|
|
48
|
+
},
|
|
49
|
+
// Filter and sort props
|
|
50
|
+
valueFilter: {
|
|
51
|
+
type: Object,
|
|
52
|
+
default: () => ({})
|
|
53
|
+
},
|
|
54
|
+
sorters: {
|
|
55
|
+
type: [Object, Function],
|
|
56
|
+
default: () => ({})
|
|
57
|
+
},
|
|
58
|
+
derivedAttributes: {
|
|
59
|
+
type: [Object, Function],
|
|
60
|
+
default: () => ({})
|
|
61
|
+
},
|
|
62
|
+
rowOrder: {
|
|
63
|
+
type: String,
|
|
64
|
+
default: "key_a_to_z"
|
|
65
|
+
},
|
|
66
|
+
colOrder: {
|
|
67
|
+
type: String,
|
|
68
|
+
default: "key_a_to_z"
|
|
69
|
+
},
|
|
70
|
+
// Display props
|
|
71
|
+
rowTotal: {
|
|
72
|
+
type: Boolean,
|
|
73
|
+
default: true
|
|
74
|
+
},
|
|
75
|
+
colTotal: {
|
|
76
|
+
type: Boolean,
|
|
77
|
+
default: true
|
|
78
|
+
},
|
|
79
|
+
tableColorScaleGenerator: {
|
|
80
|
+
type: Function,
|
|
81
|
+
default: () => redColorScaleGenerator
|
|
82
|
+
},
|
|
83
|
+
tableOptions: {
|
|
84
|
+
type: Object,
|
|
85
|
+
default: () => ({})
|
|
86
|
+
},
|
|
87
|
+
localeStrings: {
|
|
88
|
+
type: Object,
|
|
89
|
+
default: () => ({ totals: "Totals" })
|
|
90
|
+
},
|
|
91
|
+
labels: {
|
|
92
|
+
type: Object,
|
|
93
|
+
default: () => ({})
|
|
94
|
+
},
|
|
95
|
+
// Multi-value display options
|
|
96
|
+
cellLayout: {
|
|
97
|
+
type: String,
|
|
98
|
+
default: "vertical",
|
|
99
|
+
validator: (v) => ["vertical", "horizontal", "compact"].includes(v)
|
|
100
|
+
},
|
|
101
|
+
showValueLabels: {
|
|
102
|
+
type: Boolean,
|
|
103
|
+
default: true
|
|
104
|
+
},
|
|
105
|
+
valueLabels: {
|
|
106
|
+
type: Object,
|
|
107
|
+
default: () => ({})
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
methods: {
|
|
111
|
+
/**
|
|
112
|
+
* Apply label transformation to a value
|
|
113
|
+
*/
|
|
114
|
+
applyLabel(attr, value) {
|
|
115
|
+
if (this.labels && typeof this.labels[attr] === "function") {
|
|
116
|
+
return this.labels[attr](value);
|
|
117
|
+
}
|
|
118
|
+
return value;
|
|
119
|
+
},
|
|
120
|
+
/**
|
|
121
|
+
* Get display label for a value column
|
|
122
|
+
*/
|
|
123
|
+
getValueLabel(valName) {
|
|
124
|
+
if (this.valueLabels && this.valueLabels[valName]) {
|
|
125
|
+
return this.valueLabels[valName];
|
|
126
|
+
}
|
|
127
|
+
return valName;
|
|
128
|
+
},
|
|
129
|
+
/**
|
|
130
|
+
* Calculate row/col span for merged cells
|
|
131
|
+
*/
|
|
132
|
+
spanSize(arr, i, j) {
|
|
133
|
+
let x;
|
|
134
|
+
if (i !== 0) {
|
|
135
|
+
let noDraw = true;
|
|
136
|
+
for (x = 0; x <= j; x++) {
|
|
137
|
+
if (arr[i - 1][x] !== arr[i][x]) {
|
|
138
|
+
noDraw = false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (noDraw) return -1;
|
|
142
|
+
}
|
|
143
|
+
let len = 0;
|
|
144
|
+
while (i + len < arr.length) {
|
|
145
|
+
let stop = false;
|
|
146
|
+
for (x = 0; x <= j; x++) {
|
|
147
|
+
if (arr[i][x] !== arr[i + len][x]) {
|
|
148
|
+
stop = true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (stop) break;
|
|
152
|
+
len++;
|
|
153
|
+
}
|
|
154
|
+
return len;
|
|
155
|
+
},
|
|
156
|
+
/**
|
|
157
|
+
* Format a single value using the appropriate aggregator
|
|
158
|
+
*/
|
|
159
|
+
formatValue(valName, value) {
|
|
160
|
+
const aggName = this.aggregatorMap[valName] || "Sum";
|
|
161
|
+
const agg = this.aggregators[aggName];
|
|
162
|
+
if (agg) {
|
|
163
|
+
try {
|
|
164
|
+
const instance = agg([valName])();
|
|
165
|
+
if (instance && instance.format) {
|
|
166
|
+
return instance.format(value);
|
|
167
|
+
}
|
|
168
|
+
} catch (e) {
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (value === null || value === void 0) return "";
|
|
172
|
+
if (typeof value === "number") {
|
|
173
|
+
return value.toLocaleString();
|
|
174
|
+
}
|
|
175
|
+
return String(value);
|
|
176
|
+
},
|
|
177
|
+
/**
|
|
178
|
+
* Render multi-value cell content
|
|
179
|
+
*/
|
|
180
|
+
renderMultiValueCell(h, values, rowKey, colKey) {
|
|
181
|
+
if (!values || typeof values !== "object") {
|
|
182
|
+
return String(values || "");
|
|
183
|
+
}
|
|
184
|
+
const items = this.vals.map((val) => {
|
|
185
|
+
const value = values[val];
|
|
186
|
+
const formatted = this.formatValue(val, value);
|
|
187
|
+
const label = this.getValueLabel(val);
|
|
188
|
+
const aggName = this.aggregatorMap[val] || "Sum";
|
|
189
|
+
if (this.cellLayout === "compact") {
|
|
190
|
+
return formatted;
|
|
191
|
+
}
|
|
192
|
+
return h("div", {
|
|
193
|
+
staticClass: "multi-value-item",
|
|
194
|
+
key: val,
|
|
195
|
+
attrs: {
|
|
196
|
+
"data-value": val,
|
|
197
|
+
"data-aggregator": aggName
|
|
198
|
+
}
|
|
199
|
+
}, [
|
|
200
|
+
this.showValueLabels ? h("span", {
|
|
201
|
+
staticClass: "multi-value-label"
|
|
202
|
+
}, `${label}: `) : null,
|
|
203
|
+
h("span", {
|
|
204
|
+
staticClass: ["multi-value-value"]
|
|
205
|
+
}, formatted)
|
|
206
|
+
]);
|
|
207
|
+
});
|
|
208
|
+
if (this.cellLayout === "compact") {
|
|
209
|
+
return items.join(" / ");
|
|
210
|
+
}
|
|
211
|
+
return h("div", {
|
|
212
|
+
staticClass: ["multi-value-cell", `layout-${this.cellLayout}`]
|
|
213
|
+
}, items);
|
|
214
|
+
},
|
|
215
|
+
/**
|
|
216
|
+
* Create PivotData-like structure with multi-value aggregation
|
|
217
|
+
*/
|
|
218
|
+
createPivotData() {
|
|
219
|
+
const multiValueAgg = createMultiValueAggregator(
|
|
220
|
+
this.aggregatorMap,
|
|
221
|
+
this.aggregators,
|
|
222
|
+
this.vals
|
|
223
|
+
);
|
|
224
|
+
const modifiedAggregators = {
|
|
225
|
+
...this.aggregators,
|
|
226
|
+
"Multi-Value": () => multiValueAgg
|
|
227
|
+
};
|
|
228
|
+
return new PivotData({
|
|
229
|
+
data: this.data,
|
|
230
|
+
rows: this.rows,
|
|
231
|
+
cols: this.cols,
|
|
232
|
+
vals: this.vals,
|
|
233
|
+
aggregators: modifiedAggregators,
|
|
234
|
+
aggregatorName: "Multi-Value",
|
|
235
|
+
valueFilter: this.valueFilter,
|
|
236
|
+
sorters: this.sorters,
|
|
237
|
+
derivedAttributes: this.derivedAttributes,
|
|
238
|
+
rowOrder: this.rowOrder,
|
|
239
|
+
colOrder: this.colOrder
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
render(h) {
|
|
244
|
+
let pivotData;
|
|
245
|
+
try {
|
|
246
|
+
pivotData = this.createPivotData();
|
|
247
|
+
} catch (error) {
|
|
248
|
+
console.error("Multi-Value Renderer Error:", error);
|
|
249
|
+
return h("div", {
|
|
250
|
+
staticClass: ["pvtError"]
|
|
251
|
+
}, `Error: ${error.message}`);
|
|
252
|
+
}
|
|
253
|
+
const colAttrs = pivotData.props.cols;
|
|
254
|
+
const rowAttrs = pivotData.props.rows;
|
|
255
|
+
const rowKeys = pivotData.getRowKeys();
|
|
256
|
+
const colKeys = pivotData.getColKeys();
|
|
257
|
+
const grandTotalAggregator = pivotData.getAggregator([], []);
|
|
258
|
+
const getClickHandler = (value, rowValues, colValues) => {
|
|
259
|
+
if (this.tableOptions && this.tableOptions.clickCallback) {
|
|
260
|
+
const filters = {};
|
|
261
|
+
colAttrs.forEach((attr, i) => {
|
|
262
|
+
if (colValues[i] !== null) {
|
|
263
|
+
filters[attr] = colValues[i];
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
rowAttrs.forEach((attr, i) => {
|
|
267
|
+
if (rowValues[i] !== null) {
|
|
268
|
+
filters[attr] = rowValues[i];
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
return (e) => this.tableOptions.clickCallback(e, value, filters, pivotData);
|
|
272
|
+
}
|
|
273
|
+
return null;
|
|
274
|
+
};
|
|
275
|
+
return h("table", {
|
|
276
|
+
staticClass: ["pvtTable", "pvtMultiValueTable"]
|
|
277
|
+
}, [
|
|
278
|
+
// THEAD
|
|
279
|
+
h("thead", [
|
|
280
|
+
// Column attribute headers
|
|
281
|
+
colAttrs.map((c, j) => {
|
|
282
|
+
return h("tr", { key: `colAttrs${j}` }, [
|
|
283
|
+
// Top-left corner cell
|
|
284
|
+
j === 0 && rowAttrs.length !== 0 ? h("th", {
|
|
285
|
+
attrs: {
|
|
286
|
+
colSpan: rowAttrs.length,
|
|
287
|
+
rowSpan: colAttrs.length
|
|
288
|
+
}
|
|
289
|
+
}) : void 0,
|
|
290
|
+
// Column attribute label
|
|
291
|
+
h("th", { staticClass: ["pvtAxisLabel"] }, c),
|
|
292
|
+
// Column keys
|
|
293
|
+
colKeys.map((colKey, i) => {
|
|
294
|
+
const x = this.spanSize(colKeys, i, j);
|
|
295
|
+
if (x === -1) return null;
|
|
296
|
+
return h("th", {
|
|
297
|
+
staticClass: ["pvtColLabel"],
|
|
298
|
+
attrs: {
|
|
299
|
+
key: `colKey${i}`,
|
|
300
|
+
colSpan: x,
|
|
301
|
+
rowSpan: j === colAttrs.length - 1 && rowAttrs.length !== 0 ? 2 : 1
|
|
302
|
+
}
|
|
303
|
+
}, this.applyLabel(colAttrs[j], colKey[j]));
|
|
304
|
+
}),
|
|
305
|
+
// Totals header
|
|
306
|
+
j === 0 && this.rowTotal ? h("th", {
|
|
307
|
+
staticClass: ["pvtTotalLabel"],
|
|
308
|
+
attrs: {
|
|
309
|
+
rowSpan: colAttrs.length + (rowAttrs.length === 0 ? 0 : 1)
|
|
310
|
+
}
|
|
311
|
+
}, this.localeStrings.totals) : void 0
|
|
312
|
+
]);
|
|
313
|
+
}),
|
|
314
|
+
// Row attribute labels row
|
|
315
|
+
rowAttrs.length !== 0 ? h("tr", [
|
|
316
|
+
rowAttrs.map((r, i) => {
|
|
317
|
+
return h("th", {
|
|
318
|
+
staticClass: ["pvtAxisLabel"],
|
|
319
|
+
key: `rowAttr${i}`
|
|
320
|
+
}, r);
|
|
321
|
+
}),
|
|
322
|
+
this.rowTotal ? h(
|
|
323
|
+
"th",
|
|
324
|
+
{ staticClass: ["pvtTotalLabel"] },
|
|
325
|
+
colAttrs.length === 0 ? this.localeStrings.totals : null
|
|
326
|
+
) : colAttrs.length === 0 ? void 0 : h("th")
|
|
327
|
+
]) : void 0
|
|
328
|
+
]),
|
|
329
|
+
// TBODY
|
|
330
|
+
h("tbody", [
|
|
331
|
+
// Data rows
|
|
332
|
+
rowKeys.map((rowKey, i) => {
|
|
333
|
+
const totalAggregator = pivotData.getAggregator(rowKey, []);
|
|
334
|
+
return h("tr", { key: `rowKeyRow${i}` }, [
|
|
335
|
+
// Row labels
|
|
336
|
+
rowKey.map((text, j) => {
|
|
337
|
+
const x = this.spanSize(rowKeys, i, j);
|
|
338
|
+
if (x === -1) return null;
|
|
339
|
+
return h("th", {
|
|
340
|
+
staticClass: ["pvtRowLabel"],
|
|
341
|
+
attrs: {
|
|
342
|
+
key: `rowKeyLabel${i}-${j}`,
|
|
343
|
+
rowSpan: x,
|
|
344
|
+
colSpan: j === rowAttrs.length - 1 && colAttrs.length !== 0 ? 2 : 1
|
|
345
|
+
}
|
|
346
|
+
}, this.applyLabel(rowAttrs[j], text));
|
|
347
|
+
}),
|
|
348
|
+
// Data cells
|
|
349
|
+
colKeys.map((colKey, j) => {
|
|
350
|
+
const aggregator = pivotData.getAggregator(rowKey, colKey);
|
|
351
|
+
const value = aggregator.value();
|
|
352
|
+
const clickHandler = getClickHandler(value, rowKey, colKey);
|
|
353
|
+
return h("td", {
|
|
354
|
+
staticClass: ["pvVal", "pvtMultiVal"],
|
|
355
|
+
attrs: { key: `pvtVal${i}-${j}` },
|
|
356
|
+
on: clickHandler ? { click: clickHandler } : {}
|
|
357
|
+
}, [this.renderMultiValueCell(h, value, rowKey, colKey)]);
|
|
358
|
+
}),
|
|
359
|
+
// Row total
|
|
360
|
+
this.rowTotal ? h("td", {
|
|
361
|
+
staticClass: ["pvtTotal", "pvtMultiVal"],
|
|
362
|
+
on: getClickHandler(totalAggregator.value(), rowKey, []) ? { click: getClickHandler(totalAggregator.value(), rowKey, []) } : {}
|
|
363
|
+
}, [this.renderMultiValueCell(h, totalAggregator.value(), rowKey, [])]) : void 0
|
|
364
|
+
]);
|
|
365
|
+
}),
|
|
366
|
+
// Column totals row
|
|
367
|
+
h("tr", [
|
|
368
|
+
this.colTotal ? h("th", {
|
|
369
|
+
staticClass: ["pvtTotalLabel"],
|
|
370
|
+
attrs: {
|
|
371
|
+
colSpan: rowAttrs.length + (colAttrs.length === 0 ? 0 : 1)
|
|
372
|
+
}
|
|
373
|
+
}, this.localeStrings.totals) : void 0,
|
|
374
|
+
this.colTotal ? colKeys.map((colKey, i) => {
|
|
375
|
+
const totalAggregator = pivotData.getAggregator([], colKey);
|
|
376
|
+
const clickHandler = getClickHandler(totalAggregator.value(), [], colKey);
|
|
377
|
+
return h("td", {
|
|
378
|
+
staticClass: ["pvtTotal", "pvtMultiVal"],
|
|
379
|
+
attrs: { key: `total${i}` },
|
|
380
|
+
on: clickHandler ? { click: clickHandler } : {}
|
|
381
|
+
}, [this.renderMultiValueCell(h, totalAggregator.value(), [], colKey)]);
|
|
382
|
+
}) : void 0,
|
|
383
|
+
this.colTotal && this.rowTotal ? h("td", {
|
|
384
|
+
staticClass: ["pvtGrandTotal", "pvtMultiVal"],
|
|
385
|
+
on: getClickHandler(grandTotalAggregator.value(), [], []) ? { click: getClickHandler(grandTotalAggregator.value(), [], []) } : {}
|
|
386
|
+
}, [this.renderMultiValueCell(h, grandTotalAggregator.value(), [], [])]) : void 0
|
|
387
|
+
])
|
|
388
|
+
])
|
|
389
|
+
]);
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
const MultiValueTableRenderer = {
|
|
394
|
+
"Multi-Value Table": makeMultiValueRenderer({ name: "vue2-multi-value-table" })
|
|
395
|
+
};
|
|
396
|
+
export {
|
|
397
|
+
MultiValueTableRenderer as MultiValueRenderers,
|
|
398
|
+
makeMultiValueRenderer
|
|
399
|
+
};
|
package/dist/vue3.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const MultiValueTableRenderer = require("./MultiValueTableRenderer.js");
|
|
4
|
+
exports.MultiValueRenderers = MultiValueTableRenderer.MultiValueTableRenderer;
|
|
5
|
+
exports.makeMultiValueRenderer = MultiValueTableRenderer.makeMultiValueRenderer;
|
package/dist/vue3.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vue-pivottable/multi-value-renderer",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Multi-value aggregator renderer for vue-pivottable (Vue 2/3 compatible)",
|
|
5
|
+
"author": "Seungwoo321",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.mjs",
|
|
10
|
+
"types": "./types/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./types/index.d.ts",
|
|
14
|
+
"import": "./dist/index.mjs",
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./vue2": {
|
|
18
|
+
"types": "./types/index.d.ts",
|
|
19
|
+
"import": "./dist/vue2.mjs",
|
|
20
|
+
"require": "./dist/vue2.js"
|
|
21
|
+
},
|
|
22
|
+
"./vue3": {
|
|
23
|
+
"types": "./types/index.d.ts",
|
|
24
|
+
"import": "./dist/vue3.mjs",
|
|
25
|
+
"require": "./dist/vue3.js"
|
|
26
|
+
},
|
|
27
|
+
"./dist/styles.css": "./dist/styles.css",
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"types",
|
|
33
|
+
"LICENSE",
|
|
34
|
+
"README.md"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"clean": "rimraf dist",
|
|
38
|
+
"build": "vite build && cp src/styles.css dist/styles.css",
|
|
39
|
+
"build:all": "npm run clean && npm run build",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"typecheck": "tsc --noEmit"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"vue": "^2.7.0 || ^3.0.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependenciesMeta": {
|
|
47
|
+
"vue": {
|
|
48
|
+
"optional": false
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
53
|
+
"release-it": "^17.0.0",
|
|
54
|
+
"rimraf": "^5.0.0",
|
|
55
|
+
"typescript": "^5.0.0",
|
|
56
|
+
"vite": "^5.0.0",
|
|
57
|
+
"vitest": "^1.0.0"
|
|
58
|
+
},
|
|
59
|
+
"keywords": [
|
|
60
|
+
"vue",
|
|
61
|
+
"vue2",
|
|
62
|
+
"vue3",
|
|
63
|
+
"pivot",
|
|
64
|
+
"pivottable",
|
|
65
|
+
"vue-pivottable",
|
|
66
|
+
"aggregator",
|
|
67
|
+
"multi-value",
|
|
68
|
+
"renderer"
|
|
69
|
+
],
|
|
70
|
+
"repository": {
|
|
71
|
+
"type": "git",
|
|
72
|
+
"url": "git+https://github.com/vue-pivottable/multi-value-renderer.git"
|
|
73
|
+
},
|
|
74
|
+
"bugs": {
|
|
75
|
+
"url": "https://github.com/vue-pivottable/multi-value-renderer/issues"
|
|
76
|
+
},
|
|
77
|
+
"homepage": "https://github.com/vue-pivottable/multi-value-renderer#readme",
|
|
78
|
+
"publishConfig": {
|
|
79
|
+
"access": "public"
|
|
80
|
+
}
|
|
81
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type { Component, DefineComponent } from 'vue'
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Core Types
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Map of value column names to aggregator names
|
|
9
|
+
* @example { sales: 'Sum', quantity: 'Average' }
|
|
10
|
+
*/
|
|
11
|
+
export type AggregatorMap = Record<string, string>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Aggregator result interface
|
|
15
|
+
*/
|
|
16
|
+
export interface AggregatorResult {
|
|
17
|
+
push(record: Record<string, any>): void
|
|
18
|
+
value(): any
|
|
19
|
+
format(value: any): string
|
|
20
|
+
numInputs?: number
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Aggregator factory function
|
|
25
|
+
*/
|
|
26
|
+
export type AggregatorFactory = (
|
|
27
|
+
data?: any,
|
|
28
|
+
rowKey?: string[],
|
|
29
|
+
colKey?: string[]
|
|
30
|
+
) => AggregatorResult
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Aggregator definition
|
|
34
|
+
*/
|
|
35
|
+
export type Aggregator = (attributes: string[]) => AggregatorFactory
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Collection of aggregators
|
|
39
|
+
*/
|
|
40
|
+
export type Aggregators = Record<string, Aggregator>
|
|
41
|
+
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// Multi-Value Aggregator
|
|
44
|
+
// ============================================================================
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Multi-value aggregator result with per-value access
|
|
48
|
+
*/
|
|
49
|
+
export interface MultiValueAggregatorResult extends AggregatorResult {
|
|
50
|
+
valueOf(valName: string): any
|
|
51
|
+
formatOf(valName: string, value: any): string
|
|
52
|
+
getSubAggregator(valName: string): AggregatorResult | null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Creates a multi-value aggregator factory
|
|
57
|
+
*/
|
|
58
|
+
export function createMultiValueAggregator(
|
|
59
|
+
aggregatorMap: AggregatorMap,
|
|
60
|
+
aggregators: Aggregators,
|
|
61
|
+
vals: string[]
|
|
62
|
+
): AggregatorFactory
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Legacy alias for createMultiValueAggregator
|
|
66
|
+
*/
|
|
67
|
+
export function createMultiAggregator(
|
|
68
|
+
aggregatorMap: AggregatorMap,
|
|
69
|
+
aggregators: Aggregators
|
|
70
|
+
): (vals: string[]) => AggregatorFactory
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Default color scale generator for heatmaps
|
|
74
|
+
*/
|
|
75
|
+
export function defaultColorScaleGenerator(
|
|
76
|
+
values: number[]
|
|
77
|
+
): (value: number) => { backgroundColor: string }
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Validates an aggregator map configuration
|
|
81
|
+
*/
|
|
82
|
+
export function validateAggregatorMap(
|
|
83
|
+
aggregatorMap: AggregatorMap,
|
|
84
|
+
aggregators: Aggregators
|
|
85
|
+
): {
|
|
86
|
+
valid: boolean
|
|
87
|
+
errors: string[]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// Renderer Props
|
|
92
|
+
// ============================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Cell layout options for multi-value display
|
|
96
|
+
*/
|
|
97
|
+
export type CellLayout = 'vertical' | 'horizontal' | 'compact'
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Props for the multi-value renderer
|
|
101
|
+
*/
|
|
102
|
+
export interface MultiValueRendererProps {
|
|
103
|
+
// Data props
|
|
104
|
+
data: any[] | Record<string, any>[] | ((callback: (record: Record<string, any>) => void) => void)
|
|
105
|
+
rows?: string[]
|
|
106
|
+
cols?: string[]
|
|
107
|
+
vals?: string[]
|
|
108
|
+
|
|
109
|
+
// Multi-value specific
|
|
110
|
+
aggregatorMap?: AggregatorMap
|
|
111
|
+
aggregators: Aggregators
|
|
112
|
+
|
|
113
|
+
// Filter and sort
|
|
114
|
+
valueFilter?: Record<string, Record<string, boolean>>
|
|
115
|
+
sorters?: Record<string, (a: any, b: any) => number> | ((attr: string) => (a: any, b: any) => number)
|
|
116
|
+
derivedAttributes?: Record<string, (record: Record<string, any>) => any>
|
|
117
|
+
rowOrder?: 'key_a_to_z' | 'value_a_to_z' | 'value_z_to_a'
|
|
118
|
+
colOrder?: 'key_a_to_z' | 'value_a_to_z' | 'value_z_to_a'
|
|
119
|
+
|
|
120
|
+
// Display options
|
|
121
|
+
rowTotal?: boolean
|
|
122
|
+
colTotal?: boolean
|
|
123
|
+
tableColorScaleGenerator?: (values: number[]) => (value: number) => { backgroundColor: string }
|
|
124
|
+
tableOptions?: {
|
|
125
|
+
clickCallback?: (
|
|
126
|
+
event: MouseEvent,
|
|
127
|
+
value: any,
|
|
128
|
+
filters: Record<string, any>,
|
|
129
|
+
pivotData: any
|
|
130
|
+
) => void
|
|
131
|
+
}
|
|
132
|
+
localeStrings?: {
|
|
133
|
+
totals?: string
|
|
134
|
+
}
|
|
135
|
+
labels?: Record<string, (value: any) => any>
|
|
136
|
+
|
|
137
|
+
// Multi-value display options
|
|
138
|
+
cellLayout?: CellLayout
|
|
139
|
+
showValueLabels?: boolean
|
|
140
|
+
valueLabels?: Record<string, string>
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ============================================================================
|
|
144
|
+
// Renderer Factory
|
|
145
|
+
// ============================================================================
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Options for creating a multi-value renderer
|
|
149
|
+
*/
|
|
150
|
+
export interface MultiValueRendererOptions {
|
|
151
|
+
name?: string
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Creates a multi-value table renderer component
|
|
156
|
+
*/
|
|
157
|
+
export function makeMultiValueRenderer(
|
|
158
|
+
opts?: MultiValueRendererOptions
|
|
159
|
+
): DefineComponent<MultiValueRendererProps>
|
|
160
|
+
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// Exports
|
|
163
|
+
// ============================================================================
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Pre-configured multi-value renderers
|
|
167
|
+
*/
|
|
168
|
+
export const MultiValueRenderers: Record<string, Component>
|
|
169
|
+
|
|
170
|
+
export default MultiValueRenderers
|