@dou-ui/pivot 0.0.0-stage → 0.1.0-alpha.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 +10 -2
- package/dist/assets/default-PXde2wzm.js.map +1 -0
- package/dist/core/format.js +116 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/labels.js +28 -0
- package/dist/core/labels.js.map +1 -0
- package/dist/core/layout.js +190 -0
- package/dist/core/layout.js.map +1 -0
- package/dist/core/source.js +46 -0
- package/dist/core/source.js.map +1 -0
- package/dist/core/table.js +154 -0
- package/dist/core/table.js.map +1 -0
- package/dist/engine/aggregate.js +51 -0
- package/dist/engine/aggregate.js.map +1 -0
- package/dist/engine/compute.js +735 -0
- package/dist/engine/compute.js.map +1 -0
- package/dist/engine/engine.js +46 -0
- package/dist/engine/engine.js.map +1 -0
- package/dist/engine/formula.js +225 -0
- package/dist/engine/formula.js.map +1 -0
- package/dist/engine/group.js +107 -0
- package/dist/engine/group.js.map +1 -0
- package/dist/engine/hash.js +108 -0
- package/dist/engine/hash.js.map +1 -0
- package/dist/engine/index.js +8 -0
- package/dist/engine/show.js +132 -0
- package/dist/engine/show.js.map +1 -0
- package/dist/engine/source.js +339 -0
- package/dist/engine/source.js.map +1 -0
- package/dist/engine/tree.js +226 -0
- package/dist/engine/tree.js.map +1 -0
- package/dist/fields/fields.js +6 -0
- package/dist/fields/fields.js.map +1 -0
- package/dist/fields/fields.vue_vue_type_script_setup_true_lang.js +881 -0
- package/dist/fields/fields.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/fields/filter-list.js +6 -0
- package/dist/fields/filter-list.js.map +1 -0
- package/dist/fields/filter-list.vue_vue_type_script_setup_true_lang.js +184 -0
- package/dist/fields/filter-list.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/fields/formula-dialog.js +6 -0
- package/dist/fields/formula-dialog.js.map +1 -0
- package/dist/fields/formula-dialog.vue_vue_type_script_setup_true_lang.js +165 -0
- package/dist/fields/formula-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/fields/model.js +200 -0
- package/dist/fields/model.js.map +1 -0
- package/dist/fields/top-dialog.js +6 -0
- package/dist/fields/top-dialog.js.map +1 -0
- package/dist/fields/top-dialog.vue_vue_type_script_setup_true_lang.js +174 -0
- package/dist/fields/top-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/locale.js +508 -0
- package/dist/locale.js.map +1 -0
- package/dist/pivot.js +6 -0
- package/dist/pivot.js.map +1 -0
- package/dist/pivot.vue_vue_type_script_setup_true_lang.js +1711 -0
- package/dist/pivot.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/style.d.ts +1 -0
- package/dist/style.js +13 -0
- package/dist/types/core/format.d.ts +26 -0
- package/dist/types/core/labels.d.ts +14 -0
- package/dist/types/core/layout.d.ts +72 -0
- package/dist/types/core/source.d.ts +7 -0
- package/dist/types/core/table.d.ts +73 -0
- package/dist/types/engine/aggregate.d.ts +35 -0
- package/dist/types/engine/compute.d.ts +173 -0
- package/dist/types/engine/engine.d.ts +29 -0
- package/dist/types/engine/formula.d.ts +44 -0
- package/dist/types/engine/group.d.ts +34 -0
- package/dist/types/engine/hash.d.ts +36 -0
- package/dist/types/engine/index.d.ts +15 -0
- package/dist/types/engine/show.d.ts +27 -0
- package/dist/types/engine/source.d.ts +108 -0
- package/dist/types/engine/tree.d.ts +87 -0
- package/dist/types/engine/types.d.ts +148 -0
- package/dist/types/fields/fields.vue.d.ts +26 -0
- package/dist/types/fields/filter-list.vue.d.ts +20 -0
- package/dist/types/fields/formula-dialog.vue.d.ts +30 -0
- package/dist/types/fields/model.d.ts +52 -0
- package/dist/types/fields/top-dialog.vue.d.ts +25 -0
- package/dist/types/index.d.ts +458 -0
- package/dist/types/locale.d.ts +184 -0
- package/dist/types/pivot.vue.d.ts +29 -0
- package/dist/types/types.d.ts +199 -0
- package/dist/types/worker/client.d.ts +19 -0
- package/dist/types/worker/default.d.ts +1 -0
- package/dist/types/worker/index.d.ts +5 -0
- package/dist/types/worker/protocol.d.ts +60 -0
- package/dist/types/worker/serve.d.ts +22 -0
- package/dist/worker/client.js +191 -0
- package/dist/worker/client.js.map +1 -0
- package/dist/worker/default.js +20 -0
- package/dist/worker/default.js.map +1 -0
- package/dist/worker/index.js +3 -0
- package/dist/worker/serve.js +101 -0
- package/dist/worker/serve.js.map +1 -0
- package/package.json +64 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 daidr
|
|
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 deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @dou-ui/pivot
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[DouUI](https://github.com/daidr/dou-ui) 的数据透视表:按行列字段分组汇总明细记录,百万条记录可以放进 worker 汇总。
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
bun add @dou-ui/pivot dou-ui
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
用法见 [文档](https://ui.daidr.me/pivot/)。
|
|
10
|
+
|
|
11
|
+
许可证:MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-PXde2wzm.js","names":[],"sources":["../../src/engine/aggregate.ts","../../src/engine/formula.ts","../../src/engine/hash.ts","../../src/engine/show.ts","../../src/engine/group.ts","../../src/engine/source.ts","../../src/engine/tree.ts","../../src/engine/compute.ts","../../src/engine/engine.ts","../../src/worker/serve.ts","../../src/worker/default.ts"],"sourcesContent":["/**\n * A way to sum up a field. A state is built per group of records: `add`\n * takes each record's value, `merge` joins two groups' states (subtotals and\n * totals are merged from the groups inside them, never re-read from the\n * records), and `result` turns a state into the number shown.\n */\n// oxlint-disable-next-line typescript/no-explicit-any\nexport interface PivotAggregator<State = any> {\n name: string\n /** The header word, as in \"金额 · 求和\"; the name when left out. */\n label?: string\n /**\n * What `add` gets: `'number'` the field as a number (records without one\n * are skipped), `'value'` the field's value as it is (empty ones skipped).\n */\n input: 'number' | 'value'\n init: () => State\n add: (state: State, value: never) => State\n merge: (into: State, from: State) => State\n /** `null` or `NaN` for an empty cell. */\n result: (state: State) => number | null\n /** Whether a value is an integer count (written without decimals); `false` by default. */\n integer?: boolean\n}\n\n/** Declares a way to sum up a field, for `aggregators` and the config's `aggregate`. */\nexport function defineAggregator<State, Input extends 'number' | 'value' = 'number'>(\n aggregator: Omit<PivotAggregator<State>, 'add' | 'input'> & {\n input?: Input\n add: (state: State, value: Input extends 'number' ? number : unknown) => State\n },\n): PivotAggregator<State> {\n return { input: 'number', ...aggregator } as PivotAggregator<State>\n}\n\n/** The built-in ways with a typed-array fast path: one number (or two, for `avg`) per group. */\nexport type PivotFastAggregate = 'sum' | 'count' | 'avg' | 'min' | 'max'\n\nexport const FAST_AGGREGATES: ReadonlySet<string> = new Set(['sum', 'count', 'avg', 'min', 'max'])\n\n/** Counts each value once; the state holds group numbers, so it never compares values. */\nexport const distinctAggregator: PivotAggregator<Set<number>> = {\n name: 'distinct',\n input: 'value',\n integer: true,\n init: () => new Set(),\n add: (state, code: never) => state.add(code),\n merge: (into, from) => {\n for (const code of from) into.add(code)\n return into\n },\n result: (state) => state.size,\n}\n\nexport const medianAggregator: PivotAggregator<number[]> = {\n name: 'median',\n input: 'number',\n init: () => [],\n add: (state, value: never) => (state.push(value), state),\n merge: (into, from) => {\n for (let i = 0; i < from.length; i++) into.push(from[i]!)\n return into\n },\n result: (state) => {\n if (state.length === 0) return null\n // oxlint-disable-next-line unicorn/no-array-sort -- sorts its own copy\n const sorted = Float64Array.from(state).sort()\n const mid = sorted.length >> 1\n return sorted.length % 2 ? sorted[mid]! : (sorted[mid - 1]! + sorted[mid]!) / 2\n },\n}\n\nexport const BUILTIN_AGGREGATORS: Readonly<Record<string, PivotAggregator>> = {\n distinct: distinctAggregator as PivotAggregator,\n median: medianAggregator as PivotAggregator,\n}\n","/**\n * Calculated values: a small expression language over the fields, read\n * without `eval`. `profit / amount` divides the sum of `profit` by the sum\n * of `amount` in each cell, so totals are ratios of totals, not sums of ratios.\n *\n * - numbers: `12`, `0.5`, `1e3`\n * - fields: a name (`amount`, `销售额`), or any name in brackets (`[unit price]`)\n * - `+ - * /`, parentheses and a leading minus\n * - `sum(f)`, `avg(f)`, `min(f)`, `max(f)`, `count(f)` (records where f is not empty) and `count()`\n *\n * A bare field name stands for `sum(name)`. Dividing by zero leaves the cell empty.\n */\n\n/** The ways a formula can sum up a field. */\nexport type PivotFormulaAggregate = 'sum' | 'avg' | 'min' | 'max' | 'count'\n\n/** A field a formula reads, and how. `field` is null for `count()`. */\nexport interface PivotFormulaTerm {\n aggregate: PivotFormulaAggregate\n field: string | null\n}\n\ntype Node =\n | { kind: 'number'; value: number }\n | { kind: 'term'; index: number }\n | { kind: 'negate'; operand: Node }\n | { kind: 'binary'; op: '+' | '-' | '*' | '/'; left: Node; right: Node }\n\n/** A formula read into its terms and a function of their values. */\nexport interface PivotFormula {\n source: string\n /** Each distinct field-and-aggregate the formula reads, in the order of `evaluate`'s input. */\n terms: PivotFormulaTerm[]\n /** The formula's value from its terms' values; `NaN` for an empty cell. */\n evaluate(values: ArrayLike<number>): number\n}\n\n/** Why a formula could not be read. */\nexport type PivotFormulaErrorCode =\n | 'empty'\n | 'incomplete'\n | 'unknownChar'\n | 'unexpected'\n | 'expected'\n | 'unclosedBracket'\n | 'emptyName'\n | 'unknownFunction'\n | 'needsField'\n | 'needsName'\n | 'unknownField'\n | 'notNumber'\n\nconst MESSAGES: Record<PivotFormulaErrorCode, string> = {\n empty: '公式是空的',\n incomplete: '公式不完整',\n unknownChar: '无法识别“{detail}”',\n unexpected: '这里不应出现“{detail}”',\n expected: '这里应当是“{detail}”',\n unclosedBracket: '缺少“]”',\n emptyName: '方括号里没有字段名',\n unknownFunction: '没有名为“{detail}”的函数',\n needsField: '{detail}() 需要一个字段',\n needsName: '这里应当是字段名',\n unknownField: '没有名为“{detail}”的字段',\n notNumber: '“{detail}”不是数字字段',\n}\n\n/**\n * Why a formula could not be read, and where: `at` is a character offset,\n * `detail` the text the message is about. `code` lets a page word it its own way.\n */\nexport class PivotFormulaError extends Error {\n constructor(\n readonly code: PivotFormulaErrorCode,\n readonly at: number,\n readonly detail = '',\n ) {\n super(`[@dou-ui/pivot] 计算值:${MESSAGES[code].replace('{detail}', detail)}`)\n this.name = 'PivotFormulaError'\n }\n}\n\nconst FUNCTIONS = new Set<PivotFormulaAggregate>(['sum', 'avg', 'min', 'max', 'count'])\n\ninterface Token {\n type: 'number' | 'name' | 'op' | 'end'\n text: string\n at: number\n /** A name written in brackets, so never a function. */\n quoted?: boolean\n}\n\nconst NAME_START = /[\\p{L}_$]/u\nconst NAME_PART = /[\\p{L}\\p{N}_$.]/u\n\nfunction tokenize(text: string): Token[] {\n const out: Token[] = []\n let i = 0\n while (i < text.length) {\n const ch = text[i]!\n if (/\\s/.test(ch)) {\n i++\n continue\n }\n const at = i\n if (/[0-9.]/.test(ch)) {\n const match = /^(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\\d+)?/.exec(text.slice(i))\n if (!match) throw new PivotFormulaError('unknownChar', at, ch)\n out.push({ type: 'number', text: match[0], at })\n i += match[0].length\n } else if (ch === '[') {\n const end = text.indexOf(']', i + 1)\n if (end < 0) throw new PivotFormulaError('unclosedBracket', at)\n const name = text.slice(i + 1, end).trim()\n if (!name) throw new PivotFormulaError('emptyName', at)\n out.push({ type: 'name', text: name, at, quoted: true })\n i = end + 1\n } else if (NAME_START.test(ch)) {\n let j = i + 1\n while (j < text.length && NAME_PART.test(text[j]!)) j++\n out.push({ type: 'name', text: text.slice(i, j), at })\n i = j\n } else if ('+-*/(),'.includes(ch)) {\n out.push({ type: 'op', text: ch, at })\n i++\n } else {\n throw new PivotFormulaError('unknownChar', at, ch)\n }\n }\n out.push({ type: 'end', text: '', at: text.length })\n return out\n}\n\n/**\n * Reads a formula. Throws a `PivotFormulaError` when it is not well formed.\n * Field names are not checked here (see `computePivot`).\n */\nexport function parsePivotFormula(text: string): PivotFormula {\n const tokens = tokenize(text)\n const terms: PivotFormulaTerm[] = []\n let pos = 0\n const peek = () => tokens[pos]!\n const next = () => tokens[pos++]!\n const expect = (op: string) => {\n const t = next()\n if (t.type !== 'op' || t.text !== op) throw new PivotFormulaError('expected', t.at, op)\n }\n const term = (aggregate: PivotFormulaAggregate, field: string | null): Node => {\n let index = terms.findIndex((t) => t.aggregate === aggregate && t.field === field)\n if (index < 0) index = terms.push({ aggregate, field }) - 1\n return { kind: 'term', index }\n }\n\n // expression := product (('+' | '-') product)*\n function expression(): Node {\n let left = product()\n for (let t = peek(); t.type === 'op' && (t.text === '+' || t.text === '-'); t = peek()) {\n next()\n left = { kind: 'binary', op: t.text as '+' | '-', left, right: product() }\n }\n return left\n }\n // product := unary (('*' | '/') unary)*\n function product(): Node {\n let left = unary()\n for (let t = peek(); t.type === 'op' && (t.text === '*' || t.text === '/'); t = peek()) {\n next()\n left = { kind: 'binary', op: t.text as '*' | '/', left, right: unary() }\n }\n return left\n }\n function unary(): Node {\n const t = peek()\n if (t.type === 'op' && (t.text === '-' || t.text === '+')) {\n next()\n const operand = unary()\n return t.text === '-' ? { kind: 'negate', operand } : operand\n }\n return primary()\n }\n function primary(): Node {\n const t = next()\n if (t.type === 'number') return { kind: 'number', value: Number(t.text) }\n if (t.type === 'op' && t.text === '(') {\n const inner = expression()\n expect(')')\n return inner\n }\n if (t.type === 'name') {\n const after = peek()\n if (!t.quoted && after.type === 'op' && after.text === '(') {\n const name = t.text.toLowerCase() as PivotFormulaAggregate\n if (!FUNCTIONS.has(name)) throw new PivotFormulaError('unknownFunction', t.at, t.text)\n next()\n const close = peek()\n if (close.type === 'op' && close.text === ')') {\n if (name !== 'count') throw new PivotFormulaError('needsField', close.at, t.text)\n next()\n return term('count', null)\n }\n const arg = next()\n if (arg.type !== 'name') throw new PivotFormulaError('needsName', arg.at)\n expect(')')\n return term(name, arg.text)\n }\n return term('sum', t.text)\n }\n if (t.type === 'end') throw new PivotFormulaError('incomplete', t.at)\n throw new PivotFormulaError('unexpected', t.at, t.text)\n }\n\n if (peek().type === 'end') throw new PivotFormulaError('empty', 0)\n const root = expression()\n const rest = peek()\n if (rest.type !== 'end') throw new PivotFormulaError('unexpected', rest.at, rest.text)\n\n const run = (node: Node, values: ArrayLike<number>): number => {\n switch (node.kind) {\n case 'number':\n return node.value\n case 'term':\n return values[node.index]!\n case 'negate':\n return -run(node.operand, values)\n case 'binary': {\n const a = run(node.left, values)\n const b = run(node.right, values)\n switch (node.op) {\n case '+':\n return a + b\n case '-':\n return a - b\n case '*':\n return a * b\n case '/':\n return b === 0 ? Number.NaN : a / b\n }\n }\n }\n }\n return {\n source: text,\n terms,\n evaluate: (values) => {\n const v = run(root, values)\n return Number.isFinite(v) ? v : Number.NaN\n },\n }\n}\n","/**\n * A table from whole numbers (0 to 2^53) to the order they were first seen\n * in: open addressing over typed arrays, so millions of lookups allocate\n * nothing and never touch a `Map`.\n */\nexport class IntIndex {\n /** The keys by slot; `-1` marks a free slot. */\n private table: Float64Array\n /** What each slot's key maps to. */\n private ids: Int32Array\n private mask: number\n /** The keys in the order they were added. */\n keys: Float64Array\n size = 0\n\n constructor(expected = 16) {\n let capacity = 16\n while (capacity < expected * 2) capacity *= 2\n this.table = new Float64Array(capacity).fill(-1)\n this.ids = new Int32Array(capacity)\n this.mask = capacity - 1\n this.keys = new Float64Array(Math.max(8, expected))\n }\n\n /** The id of `key`, or -1. */\n get(key: number) {\n const { table, mask } = this\n let slot = hash(key) & mask\n for (;;) {\n const at = table[slot]!\n if (at === key) return this.ids[slot]!\n if (at === -1) return -1\n slot = (slot + 1) & mask\n }\n }\n\n /** The id of `key`, adding it with the next id when it is new. */\n add(key: number) {\n const { table, mask } = this\n let slot = hash(key) & mask\n for (;;) {\n const at = table[slot]!\n if (at === key) return this.ids[slot]!\n if (at === -1) break\n slot = (slot + 1) & mask\n }\n const id = this.size++\n table[slot] = key\n this.ids[slot] = id\n if (id >= this.keys.length) {\n const keys = new Float64Array(this.keys.length * 2 || 8)\n keys.set(this.keys)\n this.keys = keys\n }\n this.keys[id] = key\n if (this.size * 2 > table.length) this.grow()\n return id\n }\n\n /** Its arrays, to send to another thread (moved, not copied) or save. */\n pack(): PivotIndexPacket {\n return { table: this.table, ids: this.ids, keys: this.keys, size: this.size }\n }\n\n /** An index made from `pack()`'s output; plain arrays (from JSON) work too. */\n static unpack(packet: PivotIndexPacket): IntIndex {\n const index = new IntIndex(0)\n index.table = typed(Float64Array, packet.table)\n index.ids = typed(Int32Array, packet.ids)\n index.keys = typed(Float64Array, packet.keys)\n index.mask = index.table.length - 1\n index.size = packet.size\n return index\n }\n\n private grow() {\n const capacity = this.table.length * 2\n const table = new Float64Array(capacity).fill(-1)\n const ids = new Int32Array(capacity)\n const mask = capacity - 1\n const { keys, size } = this\n for (let id = 0; id < size; id++) {\n const key = keys[id]!\n let slot = hash(key) & mask\n while (table[slot] !== -1) slot = (slot + 1) & mask\n table[slot] = key\n ids[slot] = id\n }\n this.table = table\n this.ids = ids\n this.mask = mask\n }\n}\n\ntype TypedArrayOf =\n Float64ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Uint8ArrayConstructor\n\n/** The array as it is when it is already of that type (moved from a worker), else a typed copy (from JSON). */\nexport function typed<T extends TypedArrayOf>(Type: T, array: ArrayLike<number>): InstanceType<T> {\n return (array instanceof Type ? array : Type.from(array)) as InstanceType<T>\n}\n\n/** An `IntIndex` as data. */\nexport interface PivotIndexPacket {\n table: ArrayLike<number>\n ids: ArrayLike<number>\n keys: ArrayLike<number>\n size: number\n}\n\nconst HIGH = 4294967296\n\n/** Mixes both halves of a key up to 2^53 into 32 bits. */\nfunction hash(key: number) {\n let h = Math.imul((key >>> 0) ^ Math.imul((key / HIGH) | 0, 0x9e3779b1), 0x85ebca6b)\n h ^= h >>> 13\n h = Math.imul(h, 0xc2b2ae35)\n return h ^ (h >>> 16)\n}\n","import type { PivotTree } from './tree'\nimport type { PivotShow, PivotShowAs } from './types'\n\n/** A way of showing a value with its axis worked out. */\nexport interface PivotResolvedShow {\n as: PivotShowAs\n axis: 'rows' | 'columns'\n}\n\nconst ON_COLUMNS: ReadonlySet<PivotShowAs> = new Set([\n 'difference',\n 'percentDifference',\n 'runningTotal',\n])\n\n/** The axis a way of showing works along: as given, or the default when that axis has fields. */\nexport function resolveShow(\n show: PivotShow,\n rows: PivotTree,\n columns: PivotTree,\n): PivotResolvedShow {\n let axis = show.axis ?? (ON_COLUMNS.has(show.as) ? 'columns' : 'rows')\n const has = (on: 'rows' | 'columns') => (on === 'rows' ? rows : columns).levels.length > 0\n if (!show.axis && !has(axis) && has(axis === 'rows' ? 'columns' : 'rows')) {\n axis = axis === 'rows' ? 'columns' : 'rows'\n }\n return { as: show.as, axis }\n}\n\n/** Where each group sits among all the children (its index in `children`). */\nconst places = new WeakMap<PivotTree, Int32Array>()\nfunction placeOf(tree: PivotTree) {\n let place = places.get(tree)\n if (!place) {\n place = new Int32Array(tree.size)\n tree.children.forEach((node, at) => (place![node] = at))\n places.set(tree, place)\n }\n return place\n}\n\n/**\n * Works out a value as it is shown, from the summed-up values (`get`).\n * Groups come in their label order, whatever order the rows are shown in.\n */\nexport class PivotShown {\n private running = new Map<number, number>()\n private sorted = new Map<number, Float64Array>()\n\n constructor(\n readonly show: PivotResolvedShow,\n private rows: PivotTree,\n private columns: PivotTree,\n private get: (row: number, column: number) => number,\n ) {}\n\n value(row: number, column: number): number {\n const { get, show } = this\n const v = get(row, column)\n switch (show.as) {\n case 'percentOfTotal':\n return ratio(v, get(0, 0))\n case 'percentOfRow':\n return ratio(v, get(row, 0))\n case 'percentOfColumn':\n return ratio(v, get(0, column))\n case 'percentOfParent': {\n if (show.axis === 'rows') return ratio(v, get(row > 0 ? this.rows.parent[row]! : 0, column))\n return ratio(v, get(row, column > 0 ? this.columns.parent[column]! : 0))\n }\n case 'difference':\n case 'percentDifference': {\n const prev = this.previous(row, column)\n if (prev === null) return Number.NaN\n const p = show.axis === 'rows' ? get(prev, column) : get(row, prev)\n if (show.as === 'difference') return v - p\n return p === 0 ? Number.NaN : (v - p) / Math.abs(p)\n }\n case 'runningTotal':\n return this.runningTotal(row, column)\n case 'rank':\n return this.rank(row, column, v)\n }\n }\n\n /** The group before this one on the axis, or null for the first and for totals. */\n private previous(row: number, column: number): number | null {\n const tree = this.show.axis === 'rows' ? this.rows : this.columns\n const node = this.show.axis === 'rows' ? row : column\n if (node <= 0) return null\n const at = placeOf(tree)[node]!\n return at > tree.childStart[tree.parent[node]!]! ? tree.children[at - 1]! : null\n }\n\n private runningTotal(row: number, column: number) {\n const onRows = this.show.axis === 'rows'\n const tree = onRows ? this.rows : this.columns\n const node = onRows ? row : column\n const other = onRows ? column : row\n const read = (n: number) => (onRows ? this.get(n, other) : this.get(other, n))\n if (node <= 0) return read(node)\n const key = (n: number) => n * (onRows ? this.columns.size : this.rows.size) + other\n const cached = this.running.get(key(node))\n if (cached !== undefined) return cached\n // add up from the first group (or the last one worked out) to this one\n const place = placeOf(tree)\n const first = tree.childStart[tree.parent[node]!]!\n let at = place[node]!\n while (at > first && !this.running.has(key(tree.children[at - 1]!))) at--\n let total = at > first ? this.running.get(key(tree.children[at - 1]!))! : Number.NaN\n for (; at <= place[node]!; at++) {\n const n = tree.children[at]!\n const v = read(n)\n if (v === v) total = total === total ? total + v : v\n this.running.set(key(n), total)\n }\n return total\n }\n\n private rank(row: number, column: number, v: number) {\n if (v !== v) return Number.NaN\n const onRows = this.show.axis === 'rows'\n const tree = onRows ? this.rows : this.columns\n const node = onRows ? row : column\n if (node <= 0) return Number.NaN\n const other = onRows ? column : row\n const parent = tree.parent[node]!\n const key = parent * (onRows ? this.columns.size : this.rows.size) + other\n let values = this.sorted.get(key)\n if (!values) {\n const list: number[] = []\n for (let k = tree.childStart[parent]!; k < tree.childStart[parent + 1]!; k++) {\n const n = tree.children[k]!\n const x = onRows ? this.get(n, other) : this.get(other, n)\n if (x === x) list.push(x)\n }\n values = Float64Array.from(list)\n // oxlint-disable-next-line unicorn/no-array-sort -- sorts a fresh array\n values.sort()\n this.sorted.set(key, values)\n }\n // how many are larger: those after the last one not larger, found by bisection\n let lo = 0\n let hi = values.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (values[mid]! <= v) lo = mid + 1\n else hi = mid\n }\n return values.length - lo + 1\n }\n}\n\nconst ratio = (a: number, b: number) => (b === 0 || b !== b || a !== a ? Number.NaN : a / b)\n","/**\n * How a field's values are put in groups: dates by a period, numbers in\n * ranges of `step` (starting at `start`, 0 by default).\n */\nexport type PivotGroupBy =\n 'year' | 'quarter' | 'month' | 'week' | 'day' | { step: number; start?: number }\n\n/** The periods a date can be grouped by. */\nexport const DATE_PERIODS = ['year', 'quarter', 'month', 'week', 'day'] as const\nexport type PivotDatePeriod = (typeof DATE_PERIODS)[number]\n\n/** A name for a grouping, to cache the grouped field under. */\nexport function groupKey(by: PivotGroupBy | undefined): string {\n if (by === undefined) return ''\n if (typeof by === 'string') return by\n return `step:${by.step}:${by.start ?? 0}`\n}\n\nconst pad = (n: number, width = 2) => String(n).padStart(width, '0')\n\n/**\n * A date out of a value: a `Date`, a time in ms, or text such as\n * `'2026-03-15'` (read in local time, like the other parts of a day).\n */\nexport function toDate(value: unknown): Date | null {\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value\n if (typeof value === 'number') return Number.isFinite(value) ? new Date(value) : null\n if (typeof value === 'string') {\n const day = /^(\\d{4})-(\\d{1,2})-(\\d{1,2})$/.exec(value.trim())\n // a bare date is midnight here, not in UTC\n const date = day ? new Date(+day[1]!, +day[2]! - 1, +day[3]!) : new Date(value)\n return Number.isNaN(date.getTime()) ? null : date\n }\n return null\n}\n\n/** The ISO week a day is in, and the year that week belongs to. */\nexport function isoWeek(date: Date): [year: number, week: number] {\n const day = new Date(date.getFullYear(), date.getMonth(), date.getDate())\n // the Thursday of the same week decides the year\n const weekday = (day.getDay() + 6) % 7\n day.setDate(day.getDate() - weekday + 3)\n const year = day.getFullYear()\n const first = new Date(year, 0, 4)\n const firstThursday = new Date(year, 0, 4 - ((first.getDay() + 6) % 7) + 3)\n const week = 1 + Math.round((day.getTime() - firstThursday.getTime()) / 604_800_000)\n return [year, week]\n}\n\n/**\n * The group a value falls in: plain data that sorts in order and can be\n * saved in the config (filters, collapsed groups): a year is a number\n * (`2026`); a quarter, month, week or day is text (`'2026-Q1'`,\n * `'2026-03'`, `'2026-W12'`, `'2026-03-15'`); a range is its lowest\n * number. `null` when the value has no group (empty, or not a date / number).\n */\nexport function bucketer(by: PivotGroupBy): (value: unknown) => number | string | null {\n if (typeof by === 'object') {\n const step = by.step > 0 ? by.step : 1\n const start = by.start ?? 0\n return (value) => {\n const n = typeof value === 'number' ? value : value instanceof Date ? value.getTime() : NaN\n if (!Number.isFinite(n)) return null\n // rounded so 0.1 steps do not come out as 0.30000000000000004\n return +(Math.floor((n - start) / step) * step + start).toPrecision(12)\n }\n }\n return (value) => {\n const date = toDate(value)\n if (!date) return null\n const year = date.getFullYear()\n switch (by) {\n case 'year':\n return year\n case 'quarter':\n return `${year}-Q${Math.floor(date.getMonth() / 3) + 1}`\n case 'month':\n return `${year}-${pad(date.getMonth() + 1)}`\n case 'week': {\n const [y, w] = isoWeek(date)\n return `${y}-W${pad(w)}`\n }\n default:\n return `${year}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`\n }\n }\n}\n\n/** The parts of a period's group, read back from its text. */\nexport function readBucket(\n by: PivotDatePeriod,\n bucket: unknown,\n): { year: number; part: number; date: Date } | null {\n if (by === 'year') {\n const year = Number(bucket)\n return Number.isFinite(year) ? { year, part: 0, date: new Date(year, 0, 1) } : null\n }\n if (typeof bucket !== 'string') return null\n const m = /^(\\d{4})-(Q|W)?(\\d{1,2})(?:-(\\d{1,2}))?$/.exec(bucket)\n if (!m) return null\n const year = +m[1]!\n const part = +m[3]!\n if (m[2] === 'Q') return { year, part, date: new Date(year, (part - 1) * 3, 1) }\n if (m[2] === 'W') return { year, part, date: new Date(year, 0, 4 + (part - 1) * 7) }\n return { year, part, date: new Date(year, part - 1, m[4] ? +m[4] : 1) }\n}\n","import { bucketer, groupKey, type PivotGroupBy } from './group'\nimport type { PivotField, PivotFieldType } from './types'\n\n/** A field's groups: each record's group number, and each group's value. */\nexport interface PivotDimensionColumn {\n /** Each record's group. */\n codes: Uint32Array\n /** Each group's value; `null` for the empty group. */\n labels: unknown[]\n /** The empty group's number, or -1 when every record has a value. */\n empty: number\n /** Each group's place in the field's natural order (its `order`, then sorted, empty last). */\n rank: Uint32Array\n /** The group of `value`, or -1 when no record has it. */\n find: (value: unknown) => number\n}\n\n/** A field with its type worked out. */\nexport interface PivotResolvedField<Row = unknown> extends PivotField<Row> {\n label: string\n type: PivotFieldType\n}\n\nexport interface PivotSourceOptions<Row> {\n fields?: readonly PivotField<Row>[]\n /** For sorting group labels; the runtime's locale when left out. */\n locale?: string\n}\n\n/**\n * Records given column by column: each field's values in one array (or\n * typed array), all of the same length. A million records take far less\n * memory this way than as a million objects.\n */\nexport type PivotColumns = Readonly<Record<string, ArrayLike<unknown>>>\n\n/** The records: an array of objects, or their columns. */\nexport type PivotData<Row = Record<string, unknown>> = readonly Row[] | PivotColumns\n\n/** A field's groups before they are put in order: what a worker is sent. */\nexport interface PivotEncodedColumn {\n codes: Uint32Array\n labels: unknown[]\n empty: number\n}\n\nconst SAMPLE = 100\n/** Records read between looks at the clock while reading in slices. */\nconst STEP = 4096\n\nexport const isColumns = (data: unknown): data is PivotColumns =>\n !!data && typeof data === 'object' && !Array.isArray(data)\n\n/**\n * The records, read field by field into typed arrays the first time each\n * field is used, and kept until the records change.\n */\nexport class PivotSource<Row = Record<string, unknown>> {\n /** The records as given: objects, or columns. */\n readonly data: PivotData<Row>\n readonly length: number\n readonly fields: Map<string, PivotResolvedField<Row>>\n readonly locale: string | undefined\n private collator: Intl.Collator\n private dimensions = new Map<string, PivotDimensionColumn>()\n private measures = new Map<string, Float64Array>()\n /** Groups read elsewhere (in the page, for a worker), waiting to be put in order. */\n private given = new Map<string, PivotEncodedColumn>()\n\n constructor(data: PivotData<Row>, options: PivotSourceOptions<Row> & { length?: number } = {}) {\n this.data = data\n this.length = isColumns(data)\n ? (options.length ?? Math.max(0, ...Object.values(data).map((c) => c.length)))\n : data.length\n this.locale = options.locale\n this.collator = new Intl.Collator(options.locale, { numeric: true })\n this.fields = new Map()\n for (const field of options.fields ?? inferFields(data)) {\n this.fields.set(field.name, this.resolve(field))\n }\n }\n\n /** The record at `index`: the object given, or one made from the columns. */\n record(index: number): Row {\n const { data } = this\n if (!isColumns(data)) return data[index]!\n const row: Record<string, unknown> = {}\n for (const name in data) row[name] = data[name]![index]\n return row as Row\n }\n\n /** How to read a field from record `i`. */\n private reader(field: PivotField<Row>): (i: number) => unknown {\n const { data } = this\n const read = field.value\n if (read) {\n if (!isColumns(data)) return (i) => read(data[i]!, i)\n return (i) => read(this.record(i), i)\n }\n if (isColumns(data)) {\n const column = data[field.name]\n return column ? (i) => column[i] : () => undefined\n }\n const name = field.name\n return (i) => (data[i] as Record<string, unknown> | undefined)?.[name]\n }\n\n /** Describes a field (or describes it again), as `fields` would have. */\n define(field: PivotField<Row>) {\n this.fields.set(field.name, this.resolve(field))\n }\n\n /** Hands over groups read elsewhere, such as in the page for a worker. */\n provide(name: string, column: PivotEncodedColumn) {\n this.given.set(name, column)\n for (const key of this.dimensions.keys())\n if (key === name || key.startsWith(`${name}\\u0000`)) this.dimensions.delete(key)\n }\n\n /** Hands over a field's numbers read elsewhere. */\n provideMeasure(name: string, values: Float64Array) {\n this.measures.set(name, values)\n }\n\n /** The field called `name`; one is made up for keys the fields do not list. */\n field(name: string): PivotResolvedField<Row> {\n let field = this.fields.get(name)\n if (!field) {\n field = this.resolve({ name })\n this.fields.set(name, field)\n }\n return field\n }\n\n /** The field's values, one per record. */\n values(name: string): unknown[] {\n const read = this.reader(this.field(name))\n const out: unknown[] = Array.from({ length: this.length })\n for (let i = 0; i < this.length; i++) out[i] = read(i)\n return out\n }\n\n /**\n * The field grouped by value, or by `by`: dates by a period, numbers in\n * ranges. A grouping is worked out from the field's groups, not from the\n * records, so it costs one pass over the group numbers.\n */\n dimension(name: string, by?: PivotGroupBy): PivotDimensionColumn {\n const key = by === undefined ? name : `${name}\\u0000${groupKey(by)}`\n let column = this.dimensions.get(key)\n if (!column) {\n column = by === undefined ? this.encode(name) : this.group(name, by)\n this.dimensions.set(key, column)\n }\n return column\n }\n\n private group(name: string, by: PivotGroupBy): PivotDimensionColumn {\n const base = this.dimension(name)\n const bucketOf = bucketer(by)\n const labels: unknown[] = []\n const byValue = new Map<unknown, number>()\n let empty = -1\n // each of the field's groups goes in one bucket\n const map = new Uint32Array(base.labels.length)\n base.labels.forEach((label, code) => {\n const bucket = code === base.empty ? null : bucketOf(label)\n let to: number | undefined\n if (bucket === null) {\n if (empty < 0) {\n empty = labels.length\n labels.push(null)\n }\n to = empty\n } else {\n to = byValue.get(bucket)\n if (to === undefined) {\n to = labels.length\n labels.push(bucket)\n byValue.set(bucket, to)\n }\n }\n map[code] = to\n })\n const from = base.codes\n const codes = new Uint32Array(from.length)\n for (let i = 0; i < from.length; i++) codes[i] = map[from[i]!]!\n const find = (value: unknown) => (isEmpty(value) ? empty : (byValue.get(value) ?? -1))\n // buckets sort by themselves; the field's `order` is for its own values\n return { codes, labels, empty, rank: this.rank(labels, { name }, find), find }\n }\n\n /** The field as numbers, `NaN` where a record has none. */\n measure(name: string): Float64Array {\n let column = this.measures.get(name)\n if (!column) {\n column = run(this.measureSteps(name))\n this.measures.set(name, column)\n }\n return column\n }\n\n /**\n * Reads a field's numbers a slice at a time, for reading a large field\n * without holding up the page. The array is new: the source keeps none.\n */\n *measureSteps(name: string, copy = false): Generator<void, Float64Array> {\n const field = this.field(name)\n const given = isColumns(this.data) && !field.value ? this.data[name] : undefined\n // a column of numbers is used as it is (or copied, to be sent away)\n if (given instanceof Float64Array && given.length === this.length)\n return copy ? given.slice() : given\n const read = this.reader(field)\n const column = new Float64Array(this.length)\n for (let i = 0; i < this.length; i++) {\n if (i % STEP === 0 && i) yield\n column[i] = toNumber(read(i))\n }\n return column\n }\n\n private resolve(field: PivotField<Row>): PivotResolvedField<Row> {\n return {\n ...field,\n label: field.label ?? field.name,\n type: field.type ?? this.guess(field),\n }\n }\n\n private guess(field: PivotField<Row>): PivotFieldType {\n const read = this.reader(field)\n let seen = 0\n let type: PivotFieldType | undefined\n for (let i = 0; i < this.length && seen < SAMPLE; i++) {\n const value = read(i)\n if (isEmpty(value)) continue\n seen++\n const kind = typeOf(value)\n if (type && type !== kind) return 'string'\n type = kind\n }\n return type ?? 'string'\n }\n\n private encode(name: string): PivotDimensionColumn {\n const field = this.field(name)\n const given = this.given.get(name)\n const { codes, labels, empty } = given ?? run(this.encodeSteps(name))\n const find = finder(labels, empty)\n return { codes, labels, empty, rank: this.rank(labels, field, find), find }\n }\n\n /**\n * Reads a field's groups a slice at a time, for reading a large field\n * without holding up the page: each record's group number and each\n * group's value, not yet in order.\n */\n *encodeSteps(name: string): Generator<void, PivotEncodedColumn> {\n const read = this.reader(this.field(name))\n const n = this.length\n const codes = new Uint32Array(n)\n const labels: unknown[] = []\n const byValue = new Map<unknown, number>()\n const byTime = new Map<number, number>()\n let empty = -1\n let last: unknown = undefined\n let lastCode = -1\n const codeOf = (value: unknown) => {\n if (isEmpty(value)) {\n if (empty < 0) {\n empty = labels.length\n labels.push(null)\n }\n return empty\n }\n if (value instanceof Date) {\n const time = value.getTime()\n let code = byTime.get(time)\n if (code === undefined) {\n code = labels.length\n labels.push(value)\n byTime.set(time, code)\n }\n return code\n }\n let code = byValue.get(value)\n if (code === undefined) {\n code = labels.length\n labels.push(value)\n byValue.set(value, code)\n }\n return code\n }\n for (let i = 0; i < n; i++) {\n if (i % STEP === 0 && i) yield\n const value = read(i)\n // sorted data repeats itself, so the last lookup is often the answer\n if (value === last && lastCode >= 0) {\n codes[i] = lastCode\n continue\n }\n lastCode = codeOf(value)\n last = value\n codes[i] = lastCode\n }\n return { codes, labels, empty }\n }\n\n /** Each group's place: the field's `order` first, then by value, the empty group last. */\n private rank(labels: unknown[], field: PivotField<Row>, find: (value: unknown) => number) {\n const order = new Int32Array(labels.length).fill(-1)\n field.order?.forEach((value, at) => {\n const code = find(value)\n if (code >= 0 && order[code] === -1) order[code] = at\n })\n const codes = Array.from(labels.keys())\n const { collator } = this\n codes.sort((a, b) => {\n const oa = order[a]!\n const ob = order[b]!\n if (oa >= 0 || ob >= 0) {\n if (oa < 0) return 1\n if (ob < 0) return -1\n return oa - ob\n }\n return compareValues(labels[a], labels[b], collator)\n })\n const rank = new Uint32Array(labels.length)\n codes.forEach((code, at) => (rank[code] = at))\n return rank\n }\n}\n\n/** Empty: `null`, `undefined`, `''`, `NaN` and invalid dates all go in the empty group. */\nexport const isEmpty = (value: unknown) =>\n value === null ||\n value === undefined ||\n value === '' ||\n (typeof value === 'number' && Number.isNaN(value)) ||\n (value instanceof Date && Number.isNaN(value.getTime()))\n\nconst typeOf = (value: unknown): PivotFieldType =>\n typeof value === 'number'\n ? 'number'\n : typeof value === 'boolean'\n ? 'boolean'\n : value instanceof Date\n ? 'date'\n : 'string'\n\nconst KIND: Record<PivotFieldType, number> = { number: 0, date: 1, string: 2, boolean: 3 }\n\n/** Natural order: numbers and dates by size, text by the locale (digits as numbers), empty last. */\nexport function compareValues(a: unknown, b: unknown, collator: Intl.Collator) {\n const ea = isEmpty(a)\n const eb = isEmpty(b)\n if (ea || eb) return ea === eb ? 0 : ea ? 1 : -1\n const ka = KIND[typeOf(a)]\n const kb = KIND[typeOf(b)]\n if (ka !== kb) return ka - kb\n if (ka === 2) return collator.compare(a as string, b as string)\n return Number(a) - Number(b)\n}\n\n/** A value as a number: numbers, dates and numeric text; `NaN` for anything else. */\nexport function toNumber(value: unknown) {\n if (typeof value === 'number') return value\n if (value instanceof Date) return value.getTime()\n if (typeof value === 'string') {\n const text = value.trim()\n return text === '' ? Number.NaN : Number(text)\n }\n return Number.NaN\n}\n\n/** Runs reading in slices to the end, at once. */\nexport function run<T>(steps: Generator<void, T>): T {\n for (;;) {\n const step = steps.next()\n if (step.done) return step.value\n }\n}\n\n/** Finds a group by its value; dates by their time. */\nexport function finder(labels: readonly unknown[], empty: number) {\n const byValue = new Map<unknown, number>()\n const byTime = new Map<number, number>()\n labels.forEach((label, code) => {\n if (code === empty) return\n if (label instanceof Date) byTime.set(label.getTime(), code)\n else byValue.set(label, code)\n })\n return (value: unknown) => {\n if (isEmpty(value)) return empty\n if (value instanceof Date) return byTime.get(value.getTime()) ?? -1\n return byValue.get(value) ?? -1\n }\n}\n\n/** The fields of records nobody described: every key of the first records, or every column. */\nfunction inferFields<Row>(data: PivotData<Row>): PivotField<Row>[] {\n if (isColumns(data)) return Object.keys(data).map((name) => ({ name }))\n const rows = data\n const names = new Set<string>()\n for (let i = 0; i < Math.min(rows.length, SAMPLE); i++) {\n const row = rows[i]\n if (row && typeof row === 'object') for (const key of Object.keys(row)) names.add(key)\n }\n return [...names].map((name) => ({ name }))\n}\n","import type { PivotGroupBy } from './group'\nimport { IntIndex, typed, type PivotIndexPacket } from './hash'\nimport { finder, type PivotDimensionColumn, type PivotResolvedField } from './source'\n\n/** A field on an axis, with what the config asked of it. */\nexport interface PivotLevel {\n field: PivotResolvedField<unknown>\n column: PivotDimensionColumn\n sort: 'asc' | 'desc'\n subtotal: boolean\n /** How the field's values are grouped, when not by each value. */\n by?: PivotGroupBy\n}\n\n/**\n * The groups along one axis. Node 0 is the whole axis (the grand total);\n * a node at depth `d` is a group of the `d`-th field inside its parent.\n * Children are kept in label order, as compressed lists: the children of\n * `node` are `children[childStart[node]]` up to `children[childStart[node + 1]]`.\n */\nexport class PivotTree {\n /** The root: the grand total, as a row or column group. */\n readonly total = 0\n readonly size: number\n readonly levels: readonly PivotLevel[]\n readonly parent: Int32Array\n readonly depth: Uint8Array\n /** The group number within its field (`-1` for the root). */\n readonly code: Int32Array\n readonly childStart: Int32Array\n readonly children: Int32Array\n /** Where each node starts and ends in a walk of the tree, to tell descendants apart. */\n readonly enter: Int32Array\n readonly exit: Int32Array\n private index: IntIndex\n private stride: number\n\n constructor(builder: PivotTreeBuilder, levels: readonly PivotLevel[]) {\n const size = builder.size\n this.size = size\n this.levels = levels\n this.parent = builder.parent.slice(0, size)\n this.depth = builder.depth.slice(0, size)\n this.code = builder.code.slice(0, size)\n this.index = builder.index\n this.stride = builder.stride\n // children by parent, in the order they were made, then sorted by label\n const childStart = new Int32Array(size + 1)\n for (let node = 1; node < size; node++) childStart[this.parent[node]! + 1]!++\n for (let node = 0; node < size; node++) childStart[node + 1]! += childStart[node]!\n const fill = childStart.slice(0, size)\n const children = new Int32Array(Math.max(0, size - 1))\n for (let node = 1; node < size; node++) children[fill[this.parent[node]!]!++] = node\n this.childStart = childStart\n this.children = children\n for (let node = 0; node < size; node++) {\n const from = childStart[node]!\n const to = childStart[node + 1]!\n if (to - from < 2) continue\n const level = levels[this.depth[node]!]!\n const { rank } = level.column\n const sign = level.sort === 'desc' ? -1 : 1\n const code = this.code\n children.subarray(from, to).sort((a, b) => {\n const ra = rank[code[a]!]!\n const rb = rank[code[b]!]!\n // the empty group stays last either way\n if (level.column.empty >= 0) {\n if (code[a] === level.column.empty) return 1\n if (code[b] === level.column.empty) return -1\n }\n return sign * (ra - rb)\n })\n }\n this.enter = new Int32Array(size)\n this.exit = new Int32Array(size)\n this.walk()\n }\n\n /** The tree as data: typed arrays to move to another thread, or to write as JSON. */\n pack(): PivotTreePacket {\n return {\n size: this.size,\n stride: this.stride,\n parent: this.parent,\n depth: this.depth,\n code: this.code,\n childStart: this.childStart,\n children: this.children,\n enter: this.enter,\n exit: this.exit,\n index: this.index.pack(),\n levels: this.levels.map((l) => ({\n field: l.field.name,\n sort: l.sort,\n subtotal: l.subtotal,\n ...(l.by === undefined ? {} : { by: l.by }),\n labels: l.column.labels,\n empty: l.column.empty,\n rank: l.column.rank,\n })),\n }\n }\n\n /** A tree made from `pack()`'s output, with fields described by `field`. */\n static unpack(\n packet: PivotTreePacket,\n field: (name: string) => PivotResolvedField<unknown>,\n ): PivotTree {\n const tree = Object.create(PivotTree.prototype) as PivotTree\n const levels: PivotLevel[] = packet.levels.map((l) => {\n const f = field(l.field)\n // JSON writes dates as text\n const labels =\n f.type === 'date' && l.by === undefined\n ? l.labels.map((v) => (typeof v === 'string' ? new Date(v) : v))\n : l.labels\n return {\n field: f,\n sort: l.sort,\n subtotal: l.subtotal,\n by: l.by,\n column: {\n codes: new Uint32Array(0),\n labels,\n empty: l.empty,\n rank: typed(Uint32Array, l.rank),\n find: finder(labels, l.empty),\n },\n }\n })\n Object.assign(tree, {\n total: 0,\n size: packet.size,\n levels,\n parent: typed(Int32Array, packet.parent),\n depth: typed(Uint8Array, packet.depth),\n code: typed(Int32Array, packet.code),\n childStart: typed(Int32Array, packet.childStart),\n children: typed(Int32Array, packet.children),\n enter: typed(Int32Array, packet.enter),\n exit: typed(Int32Array, packet.exit),\n index: IntIndex.unpack(packet.index),\n stride: packet.stride,\n })\n return tree\n }\n\n /** The node's own value (its group label); `undefined` for the root. */\n label(node: number): unknown {\n if (node <= 0) return undefined\n return this.levels[this.depth[node]! - 1]!.column.labels[this.code[node]!]\n }\n\n /** The labels from the outermost group down to `node`. */\n path(node: number): unknown[] {\n const path: unknown[] = []\n for (let at = node; at > 0; at = this.parent[at]!) path.push(this.label(at))\n // oxlint-disable-next-line unicorn/no-array-reverse -- reverses its own array\n return path.reverse()\n }\n\n /** The node with these labels, or -1. */\n find(path: readonly unknown[]): number {\n let node = 0\n for (let d = 0; d < path.length; d++) {\n const level = this.levels[d]\n if (!level) return -1\n const code = level.column.find(path[d])\n if (code < 0) return -1\n const id = this.index.get(node * this.stride + code)\n if (id < 0) return -1\n node = id + 1\n }\n return node\n }\n\n /** Whether `node` has groups inside it. */\n isGroup(node: number) {\n return this.childStart[node + 1]! > this.childStart[node]!\n }\n\n /** Whether `node` is `ancestor` or inside it. */\n within(node: number, ancestor: number) {\n return this.enter[node]! >= this.enter[ancestor]! && this.enter[node]! < this.exit[ancestor]!\n }\n\n private walk() {\n const { childStart, children, enter, exit } = this\n const stack = new Int32Array(this.levels.length + 2)\n const next = new Int32Array(this.levels.length + 2)\n let top = 0\n let clock = 0\n stack[0] = 0\n next[0] = childStart[0]!\n enter[0] = clock++\n while (top >= 0) {\n const node = stack[top]!\n if (next[top]! < childStart[node + 1]!) {\n const child = children[next[top]!++]!\n top++\n stack[top] = child\n next[top] = childStart[child]!\n enter[child] = clock++\n } else {\n exit[node] = clock\n top--\n }\n }\n }\n}\n\n/** A `PivotTree` as data. */\nexport interface PivotTreePacket {\n size: number\n stride: number\n parent: ArrayLike<number>\n depth: ArrayLike<number>\n code: ArrayLike<number>\n childStart: ArrayLike<number>\n children: ArrayLike<number>\n enter: ArrayLike<number>\n exit: ArrayLike<number>\n index: PivotIndexPacket\n levels: {\n field: string\n sort: 'asc' | 'desc'\n subtotal: boolean\n by?: PivotGroupBy\n labels: unknown[]\n empty: number\n rank: ArrayLike<number>\n }[]\n}\n\n/** Grows a tree one record at a time: each record walks down its groups. */\nexport class PivotTreeBuilder {\n parent = new Int32Array(64)\n depth = new Uint8Array(64)\n code = new Int32Array(64)\n size = 1\n readonly index: IntIndex\n\n /** `stride` is more than any group number, so (parent, group) makes a unique key. */\n constructor(readonly stride: number) {\n this.parent[0] = -1\n this.code[0] = -1\n this.index = new IntIndex(256)\n }\n\n /** The child of `node` for group `code`, made when new. */\n child(node: number, code: number) {\n const index = this.index\n const before = index.size\n const id = index.add(node * this.stride + code)\n const child = id + 1\n if (index.size !== before) {\n if (child >= this.parent.length) this.grow()\n this.parent[child] = node\n this.depth[child] = this.depth[node]! + 1\n this.code[child] = code\n this.size = child + 1\n }\n return child\n }\n\n private grow() {\n const capacity = this.parent.length * 2\n const parent = new Int32Array(capacity)\n parent.set(this.parent)\n const depth = new Uint8Array(capacity)\n depth.set(this.depth)\n const code = new Int32Array(capacity)\n code.set(this.code)\n this.parent = parent\n this.depth = depth\n this.code = code\n }\n}\n","import {\n BUILTIN_AGGREGATORS,\n distinctAggregator,\n FAST_AGGREGATES,\n type PivotAggregator,\n} from './aggregate'\nimport { parsePivotFormula, PivotFormulaError, type PivotFormula } from './formula'\nimport { IntIndex, typed, type PivotIndexPacket } from './hash'\nimport { PivotShown, resolveShow, type PivotResolvedShow } from './show'\n\nexport type { PivotResolvedShow }\nimport type { PivotResolvedField, PivotSource } from './source'\nimport { PivotTree, PivotTreeBuilder, type PivotLevel, type PivotTreePacket } from './tree'\nimport type {\n PivotConfig,\n PivotDimension,\n PivotFilter,\n PivotFormat,\n PivotMark,\n PivotShow,\n PivotShowAs,\n PivotValueSort,\n} from './types'\n\n/** A value of the config with everything filled in. */\nexport interface PivotResolvedValue {\n field: PivotResolvedField<unknown> | null\n aggregate: string\n /** The custom aggregator, for names that are not built in. */\n aggregator?: PivotAggregator\n /** As given; the component works out a header when there is none. */\n label?: string\n format?: PivotFormat\n /** Whether the value is a count, written without decimals. */\n integer: boolean\n /** Whether it stands in for an empty `values` (a count of records). */\n implicit?: boolean\n /** A calculated value's formula, as written (`aggregate` is then `'formula'`). */\n formula?: string\n /** How it is shown, as given (the axis is worked out by the result). */\n show?: PivotShow\n mark?: Required<PivotMark>\n}\n\n/** The ways of showing a value that write it as a percentage. */\nexport const PERCENT_SHOWS: ReadonlySet<PivotShowAs> = new Set([\n 'percentOfTotal',\n 'percentOfRow',\n 'percentOfColumn',\n 'percentOfParent',\n 'percentDifference',\n])\n\n/** A `show` as an object. */\nexport const showOf = (show: PivotShowAs | PivotShow | undefined): PivotShow | undefined =>\n show === undefined ? undefined : typeof show === 'string' ? { as: show } : show\n\n/** A `mark` with its tone filled in. */\nexport const markOf = (\n mark: 'bar' | 'scale' | PivotMark | undefined,\n): Required<PivotMark> | undefined =>\n mark === undefined\n ? undefined\n : typeof mark === 'string'\n ? { type: mark, tone: 'neutral' as const }\n : { type: mark.type, tone: mark.tone ?? 'neutral' }\n\n/**\n * Reads a calculated value's formula and finds its fields by name (or by\n * label). Throws a `PivotFormulaError` when it is not well formed, names a\n * field that is not there, or sums up one that is not a number.\n */\nexport function checkPivotFormula<Row>(source: PivotSource<Row>, text: string): PivotFormula {\n const formula = parsePivotFormula(text)\n const byLabel = new Map<string, string>()\n for (const f of source.fields.values()) if (!byLabel.has(f.label)) byLabel.set(f.label, f.name)\n for (const term of formula.terms) {\n if (term.field === null) continue\n const name = source.fields.has(term.field) ? term.field : byLabel.get(term.field)\n if (name === undefined) {\n const at = text.indexOf(term.field)\n throw new PivotFormulaError('unknownField', Math.max(0, at), term.field)\n }\n if (term.aggregate !== 'count' && source.field(name).type !== 'number') {\n throw new PivotFormulaError('notNumber', Math.max(0, text.indexOf(term.field)), term.field)\n }\n term.field = name\n }\n return formula\n}\n\nexport interface PivotComputeOptions {\n /** Aggregators by name, beside the built-in ones. */\n aggregators?: Readonly<Record<string, PivotAggregator>>\n}\n\n/** The fields of the config resolved against a source, without reading any records. */\nexport function resolveConfig(\n source: PivotSource<unknown>,\n config: PivotConfig,\n options: PivotComputeOptions = {},\n) {\n const level = (item: PivotDimension) => {\n const spec = typeof item === 'string' ? { field: item } : item\n return {\n field: source.field(spec.field),\n sort: spec.sort ?? 'asc',\n subtotal: spec.subtotal ?? true,\n by: spec.by,\n }\n }\n const formulas: (PivotFormula | null)[] = []\n const values: PivotResolvedValue[] = (config.values ?? []).map((item) => {\n const spec = typeof item === 'string' ? { field: item } : item\n const show = showOf(spec.show)\n const mark = markOf(spec.mark)\n // a share or a rank is not in the field's units\n const ownFormat = show && (PERCENT_SHOWS.has(show.as) || show.as === 'rank')\n if (spec.formula !== undefined) {\n formulas.push(checkPivotFormula(source, spec.formula))\n return {\n field: null,\n aggregate: 'formula',\n label: spec.label,\n format: spec.format,\n integer: false,\n formula: spec.formula,\n ...(show ? { show } : {}),\n ...(mark ? { mark } : {}),\n }\n }\n formulas.push(null)\n const field = spec.field === undefined ? null : source.field(spec.field)\n let name = spec.aggregate ?? (field?.type === 'number' ? 'sum' : 'count')\n if (!field && name !== 'count') name = 'count'\n const aggregator = FAST_AGGREGATES.has(name)\n ? undefined\n : (options.aggregators?.[name] ?? BUILTIN_AGGREGATORS[name])\n if (!FAST_AGGREGATES.has(name) && !aggregator) {\n throw new Error(`[@dou-ui/pivot] there is no aggregate named \"${name}\"`)\n }\n return {\n field,\n aggregate: name,\n aggregator,\n label: spec.label,\n format: spec.format ?? (ownFormat ? undefined : field?.format),\n integer: name === 'count' || !!aggregator?.integer,\n ...(show ? { show } : {}),\n ...(mark ? { mark } : {}),\n }\n })\n if (values.length === 0) {\n values.push({ field: null, aggregate: 'count', integer: true, implicit: true })\n formulas.push(null)\n }\n return {\n rows: (config.rows ?? []).map(level),\n columns: (config.columns ?? []).map(level),\n values,\n formulas,\n }\n}\n\n/**\n * Groups the records by the config's row and column fields and sums up\n * its values for every group, subtotal and total.\n *\n * Each record is placed once, in its innermost row group and innermost\n * column group; the values are summed per such pair, and every subtotal\n * is then merged from those pairs, never from the records again.\n */\nexport function computePivot<Row>(\n source: PivotSource<Row>,\n config: PivotConfig,\n options: PivotComputeOptions = {},\n): PivotResult {\n const src = source as PivotSource<unknown>\n if (Object.values(config.filters ?? {}).some((f) => f.top || f.between)) {\n return computePivot(\n source,\n { ...config, filters: rankedFilters(src, config, options) },\n options,\n )\n }\n const resolved = resolveConfig(src, config, options)\n const rowLevels: PivotLevel[] = resolved.rows.map((l) => ({\n ...l,\n column: src.dimension(l.field.name, l.by),\n }))\n const colLevels: PivotLevel[] = resolved.columns.map((l) => ({\n ...l,\n column: src.dimension(l.field.name, l.by),\n }))\n const n = source.length\n const rowTree = new PivotTreeBuilder(stride(rowLevels))\n const colTree = new PivotTreeBuilder(stride(colLevels))\n const rowCodes = rowLevels.map((l) => l.column.codes)\n const colCodes = colLevels.map((l) => l.column.codes)\n // more than any column node can be, so (row, column) makes a unique key\n const width = n * Math.max(1, colLevels.length) + 2\n\n const filters = Object.entries(config.filters ?? {}).flatMap(([name, filter]) => {\n if (!filter.include && !filter.exclude) return []\n // without its own grouping, a filter takes the one the field has on an axis\n const by =\n filter.by ?? [...resolved.rows, ...resolved.columns].find((l) => l.field.name === name)?.by\n const column = src.dimension(name, by)\n const allow = new Uint8Array(column.labels.length).fill(filter.include ? 0 : 1)\n for (const value of filter.include ?? []) {\n const code = column.find(value)\n if (code >= 0) allow[code] = 1\n }\n for (const value of filter.exclude ?? []) {\n const code = column.find(value)\n if (code >= 0) allow[code] = 0\n }\n return [{ codes: column.codes, allow }]\n })\n\n const slotOf = new Int32Array(n)\n const cells = new IntIndex(1024)\n let matched = 0\n const rowCards = rowLevels.map((l) => l.column.labels.length)\n const colCards = colLevels.map((l) => l.column.labels.length)\n const rowSpace = rowCards.reduce((a, b) => a * b, 1)\n const colSpace = colCards.reduce((a, b) => a * b, 1)\n const skip = (i: number) => {\n for (let f = 0; f < filters.length; f++) {\n const filter = filters[f]!\n if (filter.allow[filter.codes[i]!] === 0) return true\n }\n return false\n }\n\n if (rowSpace * colSpace <= Number.MAX_SAFE_INTEGER) {\n // Each record's innermost groups, written as one number per axis (the group\n // numbers as digits). A pair of them is looked up once per record, in a\n // plain array when every pair fits in one; the trees are grown once per pair.\n const space = rowSpace * colSpace\n const dense = space <= DENSE_PAIRS ? new Int32Array(space).fill(-1) : null\n const index = dense ? null : new IntIndex(1024)\n let pairRow = new Float64Array(1024)\n let pairCol = new Float64Array(1024)\n let pairs = 0\n for (let i = 0; i < n; i++) {\n if (filters.length && skip(i)) {\n slotOf[i] = -1\n continue\n }\n let rk = 0\n for (let d = 0; d < rowCodes.length; d++) rk = rk * rowCards[d]! + rowCodes[d]![i]!\n let ck = 0\n for (let d = 0; d < colCodes.length; d++) ck = ck * colCards[d]! + colCodes[d]![i]!\n const key = rk * colSpace + ck\n let slot: number\n if (dense) {\n slot = dense[key]!\n if (slot < 0) slot = dense[key] = pairs\n } else slot = index!.add(key)\n if (slot === pairs) {\n if (pairs === pairRow.length) {\n const grownRow = new Float64Array(pairs * 2)\n grownRow.set(pairRow)\n pairRow = grownRow\n const grownCol = new Float64Array(pairs * 2)\n grownCol.set(pairCol)\n pairCol = grownCol\n }\n pairRow[pairs] = rk\n pairCol[pairs] = ck\n pairs++\n }\n slotOf[i] = slot\n matched++\n }\n const rowLeaf = new Map<number, number>()\n const colLeaf = new Map<number, number>()\n const rowDigits = new Int32Array(rowCards.length)\n const colDigits = new Int32Array(colCards.length)\n for (let p = 0; p < pairs; p++) {\n const row = leaf(pairRow[p]!, rowLeaf, rowTree, rowCards, rowDigits)\n const col = leaf(pairCol[p]!, colLeaf, colTree, colCards, colDigits)\n // pairs are distinct, so the cell made here is cell number p\n cells.add(row * width + col)\n }\n } else {\n // too many combinations to number: walk down the trees record by record\n for (let i = 0; i < n; i++) {\n if (filters.length && skip(i)) {\n slotOf[i] = -1\n continue\n }\n let row = 0\n for (let d = 0; d < rowCodes.length; d++) row = rowTree.child(row, rowCodes[d]![i]!)\n let col = 0\n for (let d = 0; d < colCodes.length; d++) col = colTree.child(col, colCodes[d]![i]!)\n slotOf[i] = cells.add(row * width + col)\n matched++\n }\n }\n\n // every (ancestor row, ancestor column) pair that each innermost pair adds into\n const leaves = cells.size\n const rowDepth = rowLevels.length\n const colDepth = colLevels.length\n const fan = (rowDepth + 1) * (colDepth + 1) - 1\n const targets = new Int32Array(leaves * fan)\n const rowUp = new Int32Array(rowDepth + 1)\n const colUp = new Int32Array(colDepth + 1)\n const leafRow = new Int32Array(leaves)\n const leafCol = new Int32Array(leaves)\n for (let s = 0; s < leaves; s++) {\n const key = cells.keys[s]!\n const row = Math.floor(key / width)\n const col = key - row * width\n leafRow[s] = row\n leafCol[s] = col\n for (let d = 0, at = row; d <= rowDepth; d++, at = rowTree.parent[at]!) rowUp[d] = at\n for (let d = 0, at = col; d <= colDepth; d++, at = colTree.parent[at]!) colUp[d] = at\n let k = s * fan\n for (let a = 0; a <= rowDepth; a++) {\n for (let b = 0; b <= colDepth; b++) {\n if (a === 0 && b === 0) continue\n targets[k++] = cells.add(rowUp[a]! * width + colUp[b]!)\n }\n }\n }\n\n const size = cells.size\n const sum = (value: PivotResolvedValue) =>\n aggregate(src, value, slotOf, leaves, size, targets, fan)\n const data = resolved.values.map((value, i) => {\n const formula = resolved.formulas[i]\n return formula ? calculate(src, formula, sum, size) : sum(value)\n })\n return new PivotResult({\n rows: new PivotTree(rowTree, rowLevels),\n columns: new PivotTree(colTree, colLevels),\n values: resolved.values,\n matched,\n cells,\n width,\n data,\n slotOf,\n leafRow,\n leafCol,\n })\n}\n\n/**\n * The filters with `top` and `between` turned into lists of the groups they\n * keep: each field's groups are summed up once on their own, over the\n * records that the `include` and `exclude` lists keep.\n */\nfunction rankedFilters(\n source: PivotSource<unknown>,\n config: PivotConfig,\n options: PivotComputeOptions,\n): Record<string, PivotFilter> {\n const given = config.filters ?? {}\n const plain: Record<string, PivotFilter> = {}\n for (const [name, f] of Object.entries(given)) {\n if (f.include || f.exclude) plain[name] = { include: f.include, exclude: f.exclude, by: f.by }\n }\n const out: Record<string, PivotFilter> = { ...plain }\n const axes = [...(config.rows ?? []), ...(config.columns ?? [])]\n for (const [name, f] of Object.entries(given)) {\n if (!f.top && !f.between) continue\n const onAxis = axes.find((d) => typeof d === 'object' && d.field === name)\n const by = f.by ?? (typeof onAxis === 'object' ? onAxis.by : undefined)\n const index = f.top?.valueIndex ?? f.between?.valueIndex ?? 0\n const value = config.values?.[index]\n const plainValue =\n value === undefined ? [] : [typeof value === 'string' ? value : { ...value, show: undefined }]\n const totals = computePivot(\n source,\n { rows: [{ field: name, by, subtotal: false }], values: plainValue, filters: plain },\n options,\n )\n const tree = totals.rows\n let groups: { label: unknown; total: number }[] = []\n for (let k = tree.childStart[0]!; k < tree.childStart[1]!; k++) {\n const node = tree.children[k]!\n groups.push({ label: tree.label(node), total: totals.get(node, 0) })\n }\n if (f.between) {\n const { min = -Infinity, max = Infinity } = f.between\n groups = groups.filter((g) => g.total >= min && g.total <= max)\n }\n if (f.top) {\n const sign = f.top.order === 'asc' ? 1 : -1\n const ranked = groups.filter((g) => g.total === g.total)\n // oxlint-disable-next-line unicorn/no-array-sort -- sorts a fresh array\n ranked.sort((a, b) => sign * (a.total - b.total))\n groups = ranked.slice(0, Math.max(0, f.top.count))\n }\n out[name] = { include: groups.map((g) => g.label), by }\n }\n return out\n}\n\n/** A calculated value: each term summed up as usual, then the formula per cell. */\nfunction calculate(\n source: PivotSource<unknown>,\n formula: PivotFormula,\n sum: (value: PivotResolvedValue) => Float64Array,\n size: number,\n) {\n const columns = formula.terms.map((term) =>\n sum({\n field: term.field === null ? null : source.field(term.field),\n aggregate: term.aggregate,\n integer: term.aggregate === 'count',\n }),\n )\n const out = new Float64Array(size)\n const values = new Float64Array(columns.length)\n for (let s = 0; s < size; s++) {\n for (let t = 0; t < columns.length; t++) values[t] = columns[t]![s]!\n out[s] = formula.evaluate(values)\n }\n return out\n}\n\n/** More than any group number of the axis, so (parent, group) makes a unique key. */\nconst stride = (levels: PivotLevel[]) =>\n Math.max(1, ...levels.map((l) => l.column.labels.length)) + 1\n\n/** The innermost group whose group numbers are the digits of `key`, made when new. */\nfunction leaf(\n key: number,\n memo: Map<number, number>,\n tree: PivotTreeBuilder,\n cards: number[],\n digits: Int32Array,\n) {\n let node = memo.get(key)\n if (node !== undefined) return node\n for (let d = cards.length - 1, rest = key; d >= 0; d--) {\n const card = cards[d]!\n const digit = rest % card\n digits[d] = digit\n rest = (rest - digit) / card\n }\n node = 0\n for (let d = 0; d < cards.length; d++) node = tree.child(node, digits[d]!)\n memo.set(key, node)\n return node\n}\n\n/** Pairs of innermost groups up to this many are found in a plain array instead of a hash. */\nconst DENSE_PAIRS = 1 << 22\n\n/** One value for every cell: summed per innermost pair, then merged up into the totals. */\nfunction aggregate(\n source: PivotSource<unknown>,\n value: PivotResolvedValue,\n slotOf: Int32Array,\n leaves: number,\n size: number,\n targets: Int32Array,\n fan: number,\n) {\n const n = slotOf.length\n const out = new Float64Array(size)\n const kind = value.aggregate\n const roll = (fn: (into: number, from: number) => void) => {\n for (let s = 0; s < leaves; s++) {\n const base = s * fan\n for (let k = 0; k < fan; k++) fn(targets[base + k]!, s)\n }\n }\n\n if (kind === 'count') {\n if (value.field) {\n const { codes, empty } = source.dimension(value.field.name)\n for (let i = 0; i < n; i++) {\n const s = slotOf[i]!\n if (s >= 0 && codes[i] !== empty) out[s]!++\n }\n } else {\n for (let i = 0; i < n; i++) {\n const s = slotOf[i]!\n if (s >= 0) out[s]!++\n }\n }\n roll((t, s) => (out[t]! += out[s]!))\n return out\n }\n\n if (FAST_AGGREGATES.has(kind)) {\n const values = source.measure(value.field!.name)\n if (kind === 'min' || kind === 'max') {\n out.fill(Number.NaN)\n const max = kind === 'max'\n for (let i = 0; i < n; i++) {\n const s = slotOf[i]!\n const v = values[i]!\n if (s < 0 || v !== v) continue\n const at = out[s]!\n // NaN compares false, so an empty cell takes the first value\n if (max ? !(at >= v) : !(at <= v)) out[s] = v\n }\n roll((t, s) => {\n const v = out[s]!\n if (v !== v) return\n const at = out[t]!\n if (max ? !(at >= v) : !(at <= v)) out[t] = v\n })\n return out\n }\n // sum and avg: a total and how many records went into it\n const count = new Float64Array(size)\n for (let i = 0; i < n; i++) {\n const s = slotOf[i]!\n const v = values[i]!\n if (s < 0 || v !== v) continue\n out[s]! += v\n count[s]!++\n }\n roll((t, s) => {\n out[t]! += out[s]!\n count[t]! += count[s]!\n })\n for (let s = 0; s < size; s++) {\n const c = count[s]!\n out[s] = c === 0 ? Number.NaN : kind === 'avg' ? out[s]! / c : out[s]!\n }\n return out\n }\n\n const aggregator = value.aggregator!\n const field = value.field!\n const states: unknown[] = Array.from({ length: size })\n const { init, merge } = aggregator\n const add = aggregator.add as (state: unknown, value: unknown) => unknown\n if (aggregator.input === 'number') {\n const values = source.measure(field.name)\n for (let i = 0; i < n; i++) {\n const s = slotOf[i]!\n const v = values[i]!\n if (s < 0 || v !== v) continue\n states[s] = add(states[s] ?? init(), v)\n }\n } else {\n const { codes, labels, empty } = source.dimension(field.name)\n const byCode = aggregator === distinctAggregator\n for (let i = 0; i < n; i++) {\n const s = slotOf[i]!\n const code = codes[i]!\n if (s < 0 || code === empty) continue\n states[s] = add(states[s] ?? init(), byCode ? code : labels[code])\n }\n }\n roll((t, s) => {\n const from = states[s]\n if (from !== undefined) states[t] = merge(states[t] ?? init(), from)\n })\n const { result } = aggregator\n for (let s = 0; s < size; s++) {\n const state = states[s]\n out[s] = state === undefined ? Number.NaN : (result(state) ?? Number.NaN)\n }\n return out\n}\n\ninterface PivotResultInit {\n rows: PivotTree\n columns: PivotTree\n values: PivotResolvedValue[]\n matched: number\n cells: IntIndex\n width: number\n data: Float64Array[]\n slotOf: Int32Array\n leafRow: Int32Array\n leafCol: Int32Array\n}\n\n/**\n * A `PivotResult` as data: typed arrays a worker moves to the page without\n * copying, or plain arrays from JSON (a result summed up on a server).\n */\nexport interface PivotPacket {\n rows: PivotTreePacket\n columns: PivotTreePacket\n values: {\n field: string | null\n aggregate: string\n integer: boolean\n implicit?: boolean\n label?: string\n formula?: string\n show?: PivotShow\n mark?: Required<PivotMark>\n }[]\n matched: number\n cells: PivotIndexPacket\n width: number\n data: ArrayLike<number>[]\n slotOf: ArrayLike<number>\n leafRow: ArrayLike<number>\n leafCol: ArrayLike<number>\n}\n\nconst plainArray = (a: ArrayLike<number>) => Array.from(a)\n\n/** A packet with plain arrays in place of typed ones, ready for JSON. */\nfunction toPlain(packet: PivotPacket): PivotPacket {\n const tree = (t: PivotTreePacket): PivotTreePacket => ({\n ...t,\n parent: plainArray(t.parent),\n depth: plainArray(t.depth),\n code: plainArray(t.code),\n childStart: plainArray(t.childStart),\n children: plainArray(t.children),\n enter: plainArray(t.enter),\n exit: plainArray(t.exit),\n index: index(t.index),\n levels: t.levels.map((l) => ({ ...l, rank: plainArray(l.rank) })),\n })\n const index = (i: PivotIndexPacket): PivotIndexPacket => ({\n size: i.size,\n table: plainArray(i.table),\n ids: plainArray(i.ids),\n keys: plainArray(i.keys).slice(0, i.size),\n })\n return {\n ...packet,\n rows: tree(packet.rows),\n columns: tree(packet.columns),\n cells: index(packet.cells),\n data: packet.data.map((d) => Array.from(d, (v) => (v === v ? v : (null as never)))),\n slotOf: plainArray(packet.slotOf),\n leafRow: plainArray(packet.leafRow),\n leafCol: plainArray(packet.leafCol),\n }\n}\n\n/** The groups on both axes and every cell's values. */\nexport class PivotResult {\n readonly rows: PivotTree\n readonly columns: PivotTree\n readonly values: readonly PivotResolvedValue[]\n /** How many records passed the filters. */\n readonly matched: number\n private cells: IntIndex\n private width: number\n private data: Float64Array[]\n /** Each record's innermost cell, -1 when filtered out; and each such cell's groups. */\n private slotOf: Int32Array\n private leafRow: Int32Array\n private leafCol: Int32Array\n\n constructor(init: PivotResultInit) {\n this.rows = init.rows\n this.columns = init.columns\n this.values = init.values\n this.matched = init.matched\n this.cells = init.cells\n this.width = init.width\n this.data = init.data\n this.slotOf = init.slotOf\n this.leafRow = init.leafRow\n this.leafCol = init.leafCol\n }\n\n /**\n * The result as data, to send from a worker or a server. With `plain`,\n * plain arrays for `JSON.stringify` (typed arrays do not survive it);\n * empty cells go as `null`.\n */\n pack({ plain = false }: { plain?: boolean } = {}): PivotPacket {\n const packet = this.packTyped()\n return plain ? toPlain(packet) : packet\n }\n\n private packTyped(): PivotPacket {\n return {\n rows: this.rows.pack(),\n columns: this.columns.pack(),\n values: this.values.map((v) => ({\n field: v.field?.name ?? null,\n aggregate: v.aggregate,\n integer: v.integer,\n ...(v.implicit ? { implicit: true } : {}),\n ...(v.label === undefined ? {} : { label: v.label }),\n ...(v.formula === undefined ? {} : { formula: v.formula }),\n ...(v.show ? { show: v.show } : {}),\n ...(v.mark ? { mark: v.mark } : {}),\n })),\n matched: this.matched,\n cells: this.cells.pack(),\n width: this.width,\n data: this.data,\n slotOf: this.slotOf,\n leafRow: this.leafRow,\n leafCol: this.leafCol,\n }\n }\n\n /** The typed arrays in a packet, to move them instead of copying (`postMessage`'s transfer list). */\n static transferables(packet: PivotPacket): ArrayBuffer[] {\n const out = new Set<ArrayBuffer>()\n const add = (a: ArrayLike<number>) => {\n if (ArrayBuffer.isView(a) && a.buffer instanceof ArrayBuffer) out.add(a.buffer)\n }\n for (const tree of [packet.rows, packet.columns]) {\n for (const a of [tree.parent, tree.depth, tree.code, tree.childStart, tree.children]) add(a)\n for (const a of [tree.enter, tree.exit, tree.index.table, tree.index.ids, tree.index.keys])\n add(a)\n // a level's order belongs to the source, which keeps it for the next result\n }\n for (const a of [packet.cells.table, packet.cells.ids, packet.cells.keys]) add(a)\n for (const a of [...packet.data, packet.slotOf, packet.leafRow, packet.leafCol]) add(a)\n return [...out]\n }\n\n /**\n * A result made from `pack()`'s output. Fields are described by\n * `source` (no record is read), formats come from `config`.\n */\n static unpack<Row>(packet: PivotPacket, source: PivotSource<Row>, config?: PivotConfig) {\n const field = (name: string) => source.field(name) as PivotResolvedField<unknown>\n const given = config?.values ?? []\n return new PivotResult({\n rows: PivotTree.unpack(packet.rows, field),\n columns: PivotTree.unpack(packet.columns, field),\n values: packet.values.map((v, i) => {\n const f = v.field === null ? null : field(v.field)\n const spec = v.implicit ? undefined : given[i]\n const format = typeof spec === 'object' ? spec.format : undefined\n const own =\n v.formula !== undefined ||\n (v.show && (PERCENT_SHOWS.has(v.show.as) || v.show.as === 'rank'))\n return { ...v, field: f, format: format ?? (own ? undefined : f?.format) }\n }),\n matched: packet.matched,\n cells: IntIndex.unpack(packet.cells),\n width: packet.width,\n // JSON wrote NaN (an empty cell) as null\n data: packet.data.map((d) =>\n d instanceof Float64Array ? d : Float64Array.from(d, (v) => v ?? Number.NaN),\n ),\n slotOf: typed(Int32Array, packet.slotOf),\n leafRow: typed(Int32Array, packet.leafRow),\n leafCol: typed(Int32Array, packet.leafCol),\n })\n }\n\n private showing = new Map<string, PivotShown | null>()\n private ranges = new Map<string, { min: number; max: number }>()\n\n private shownBy(valueIndex: number, show: PivotShow | null | undefined) {\n const spec = show === undefined ? this.values[valueIndex]?.show : show\n const key = `${valueIndex}|${spec ? `${spec.as}|${spec.axis ?? ''}` : ''}`\n let shown = this.showing.get(key)\n if (shown === undefined) {\n shown = spec\n ? new PivotShown(\n resolveShow(spec, this.rows, this.columns),\n this.rows,\n this.columns,\n (r, c) => this.get(r, c, valueIndex),\n )\n : null\n this.showing.set(key, shown)\n }\n return shown\n }\n\n /**\n * How a value is shown, its `show` with the axis worked out; null when as\n * it is. `show` stands in for the value's own (`null` for none).\n */\n show(valueIndex = 0, show?: PivotShow | null): PivotResolvedShow | null {\n return this.shownBy(valueIndex, show)?.show ?? null\n }\n\n /**\n * The value as it is shown: a share, a difference, a running total or a\n * rank when the value has a `show` (or one is given), the summed-up value\n * otherwise. Nothing is summed up again.\n */\n shown(row: number, column: number, valueIndex = 0, show?: PivotShow | null): number {\n const shown = this.shownBy(valueIndex, show)\n return shown ? shown.value(row, column) : this.get(row, column, valueIndex)\n }\n\n /**\n * The smallest and largest shown values of the innermost cells (those\n * under no subtotal or total), which marks are drawn against.\n */\n range(valueIndex = 0, show?: PivotShow | null): { min: number; max: number } {\n const spec = show === undefined ? this.values[valueIndex]?.show : show\n const key = `${valueIndex}|${spec ? `${spec.as}|${spec.axis ?? ''}` : ''}`\n let range = this.ranges.get(key)\n if (!range) {\n const { rows, columns, cells, width } = this\n const rowDepth = rows.levels.length\n const colDepth = columns.levels.length\n let min = Infinity\n let max = -Infinity\n for (let s = 0; s < cells.size; s++) {\n const cell = cells.keys[s]!\n const row = Math.floor(cell / width)\n const col = cell - row * width\n if (rows.depth[row] !== rowDepth || columns.depth[col] !== colDepth) continue\n const v = this.shown(row, col, valueIndex, spec ?? null)\n if (v !== v) continue\n if (v < min) min = v\n if (v > max) max = v\n }\n range = min > max ? { min: Number.NaN, max: Number.NaN } : { min, max }\n this.ranges.set(key, range)\n }\n return range\n }\n\n /**\n * The value at `valueIndex` (its place in `values`) of a row group and a\n * column group; `NaN` when no record falls in both. The trees' `total`\n * is the grand total.\n */\n get(row: number, column: number, valueIndex = 0): number {\n const slot = this.cells.get(row * this.width + column)\n return slot < 0 ? Number.NaN : this.data[valueIndex]![slot]!\n }\n\n /** The indexes of the records in a row group and a column group, for showing the details. */\n indices(row: number, column: number): number[] {\n const { slotOf, leafRow, leafCol, rows, columns } = this\n // which innermost cells fall in the cell, then which records fall in those\n const inside = new Uint8Array(leafRow.length)\n for (let s = 0; s < leafRow.length; s++)\n inside[s] = rows.within(leafRow[s]!, row) && columns.within(leafCol[s]!, column) ? 1 : 0\n const out: number[] = []\n for (let i = 0; i < slotOf.length; i++) {\n const s = slotOf[i]!\n if (s >= 0 && inside[s]) out.push(i)\n }\n return out\n }\n\n /**\n * The children of every row group, reordered by a column's values (or as\n * they are when `sort` is empty). Nothing is summed up again.\n */\n rowOrder(sort: PivotValueSort | null | undefined): Int32Array {\n const { rows } = this\n if (!sort || !this.data[sort.valueIndex]) return rows.children\n const column = this.columns.find(sort.column ?? [])\n if (column < 0) return rows.children\n const children = rows.children.slice()\n const keys = new Float64Array(rows.size)\n for (let node = 0; node < rows.size; node++)\n keys[node] = this.get(node, column, sort.valueIndex)\n const sign = sort.order === 'desc' ? -1 : 1\n const place = new Int32Array(rows.size)\n rows.children.forEach((node, at) => (place[node] = at))\n for (let node = 0; node < rows.size; node++) {\n const from = rows.childStart[node]!\n const to = rows.childStart[node + 1]!\n if (to - from < 2) continue\n children.subarray(from, to).sort((a, b) => {\n const ka = keys[a]!\n const kb = keys[b]!\n // empty cells last, ties in label order\n if (ka !== ka || kb !== kb) return ka !== ka ? (kb !== kb ? place[a]! - place[b]! : 1) : -1\n return ka === kb ? place[a]! - place[b]! : sign * (ka - kb)\n })\n }\n return children\n }\n}\n","import { BUILTIN_AGGREGATORS, type PivotAggregator } from './aggregate'\nimport { checkPivotFormula, type PivotResult } from './compute'\nimport type { PivotConfig } from './types'\nimport type { PivotSource } from './source'\n\nexport interface PivotComputeRequest {\n /** Aggregators by name, beside the built-in ones. */\n aggregators?: Readonly<Record<string, PivotAggregator>>\n /** Aborted when a newer config makes this one stale. */\n signal?: AbortSignal\n}\n\n/**\n * Sums up the records somewhere else than in the page: in a worker\n * (`createPivotWorker`), or on a server. `DouPivot` asks it for a result\n * whenever the fields to sum up change, and shows only the newest one.\n */\nexport interface PivotEngine {\n compute<Row>(\n source: PivotSource<Row>,\n config: PivotConfig,\n request?: PivotComputeRequest,\n ): Promise<PivotResult>\n /** Lets go of what it holds (a worker, a connection) when the table goes away. */\n dispose?(): void\n}\n\n/**\n * The fields a config reads, and how: grouped (`dimensions`: on an axis,\n * filtered, counted) or as numbers (`measures`: summed and the like).\n * No record is read.\n */\nexport function neededColumns<Row>(\n source: PivotSource<Row>,\n config: PivotConfig,\n aggregators: Readonly<Record<string, PivotAggregator>> = {},\n) {\n const src = source as PivotSource<unknown>\n const dimensions = new Set<string>()\n const measures = new Set<string>()\n for (const d of [...(config.rows ?? []), ...(config.columns ?? [])])\n dimensions.add(typeof d === 'string' ? d : d.field)\n for (const name of Object.keys(config.filters ?? {})) {\n const f = config.filters![name]!\n if (f.include || f.exclude || f.top || f.between) dimensions.add(name)\n }\n for (const v of config.values ?? []) {\n const spec = typeof v === 'string' ? { field: v } : v\n if (spec.formula !== undefined) {\n let formula\n try {\n formula = checkPivotFormula(src, spec.formula)\n } catch {\n // computing it says what is wrong\n continue\n }\n for (const term of formula.terms) {\n if (term.field === null) continue\n if (term.aggregate === 'count') dimensions.add(term.field)\n else measures.add(term.field)\n }\n continue\n }\n if (spec.field === undefined) continue\n const name = spec.aggregate ?? (src.field(spec.field).type === 'number' ? 'sum' : 'count')\n const input =\n name === 'count'\n ? 'value'\n : (aggregators[name]?.input ?? BUILTIN_AGGREGATORS[name]?.input ?? 'number')\n if (input === 'value') dimensions.add(spec.field)\n else measures.add(spec.field)\n }\n return { dimensions: [...dimensions], measures: [...measures] }\n}\n","import type { PivotAggregator } from '../engine/aggregate'\nimport { computePivot, PivotResult } from '../engine/compute'\nimport { neededColumns } from '../engine/engine'\nimport { PivotSource } from '../engine/source'\nimport type { PivotFromWorker, PivotToWorker } from './protocol'\n\nexport interface ServePivotOptions {\n /** Custom aggregators (`defineAggregator`) the configs may name; functions cannot be sent, so they live here. */\n aggregators?: readonly PivotAggregator[]\n}\n\n/** The worker's side of the messages: anything with `postMessage` and `onmessage`. */\nexport interface PivotWorkerScope {\n postMessage(message: unknown, transfer?: Transferable[]): void\n addEventListener(type: 'message', listener: (event: MessageEvent) => void): void\n}\n\n/**\n * Sums up for the page in a worker. Call it in your own worker file when\n * configs use custom aggregators; `DouPivot`'s built-in worker calls it\n * with none.\n *\n * ```ts\n * // pivot.worker.ts\n * import { servePivot } from '@dou-ui/pivot/worker'\n * servePivot({ aggregators: [weightedAverage] })\n * ```\n */\nexport function servePivot(\n options: ServePivotOptions = {},\n scope: PivotWorkerScope = globalThis as unknown as PivotWorkerScope,\n) {\n const aggregators: Record<string, PivotAggregator> = {}\n for (const a of options.aggregators ?? []) aggregators[a.name] = a\n let source: PivotSource<unknown> | null = null\n let sourceId = -1\n const have = { dimensions: new Set<string>(), measures: new Set<string>() }\n // only the newest compute is worth doing: the ones that queued up behind it are skipped\n let pending: Extract<PivotToWorker, { type: 'compute' }> | null = null\n let scheduled = false\n const send = (message: PivotFromWorker, transfer?: Transferable[]) =>\n scope.postMessage(message, transfer)\n\n const run = () => {\n scheduled = false\n const job = pending\n pending = null\n if (!job || !source || job.source !== sourceId) return\n const s = source\n const need = neededColumns(s, job.config, aggregators)\n const dimensions = need.dimensions.filter((n) => !have.dimensions.has(n))\n const measures = need.measures.filter((n) => !have.measures.has(n))\n if (dimensions.length || measures.length) {\n send({ type: 'need', id: job.id, dimensions, measures })\n return\n }\n try {\n const packet = computePivot(s, job.config, { aggregators }).pack()\n send({ type: 'result', id: job.id, packet }, PivotResult.transferables(packet))\n } catch (error) {\n send({ type: 'error', id: job.id, message: (error as Error).message })\n }\n }\n\n scope.addEventListener('message', (event) => {\n const m = event.data as PivotToWorker\n if (m.type === 'source') {\n sourceId = m.source\n source = new PivotSource({}, { fields: m.fields, locale: m.locale, length: m.length })\n have.dimensions.clear()\n have.measures.clear()\n return\n }\n if (m.source !== sourceId || !source) return\n if (m.type === 'fields') {\n for (const f of m.fields) source.define(f)\n } else if (m.type === 'dimension') {\n source.provide(m.name, { codes: m.codes, labels: m.labels, empty: m.empty })\n have.dimensions.add(m.name)\n } else if (m.type === 'measure') {\n source.provideMeasure(m.name, m.values)\n have.measures.add(m.name)\n } else {\n if (pending) send({ type: 'skipped', id: pending.id })\n pending = m\n if (!scheduled) {\n scheduled = true\n setTimeout(run)\n }\n }\n })\n}\n","// The worker DouPivot starts on its own: built-in aggregators only.\nimport { servePivot } from './serve'\n\nservePivot()\n"],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { readBucket } from "../engine/group.js";
|
|
2
|
+
import { isEmpty } from "../engine/source.js";
|
|
3
|
+
import { PERCENT_SHOWS } from "../engine/compute.js";
|
|
4
|
+
// src/core/format.ts
|
|
5
|
+
var fill = (text, params) => text.replace(/\{(\w+)\}/g, (m, k) => String(params[k] ?? m));
|
|
6
|
+
var DATE = {
|
|
7
|
+
year: "numeric",
|
|
8
|
+
month: "2-digit",
|
|
9
|
+
day: "2-digit"
|
|
10
|
+
};
|
|
11
|
+
/** Writes a group label: the field's `format`, or a plain form of the value. */
|
|
12
|
+
function labelFormatter(field, locale, texts, by) {
|
|
13
|
+
if (by !== void 0) return groupFormatter(field, locale, texts, by);
|
|
14
|
+
const format = field.format;
|
|
15
|
+
const custom = typeof format === "function" ? format : format && field.type === "date" ? dateFormat(locale, format) : format && field.type === "number" ? numberFormat(locale, format) : null;
|
|
16
|
+
const dates = dateFormat(locale, DATE);
|
|
17
|
+
return (value) => {
|
|
18
|
+
if (isEmpty(value)) return texts.empty;
|
|
19
|
+
if (custom) return custom(value);
|
|
20
|
+
if (value instanceof Date) return dates(value);
|
|
21
|
+
if (typeof value === "boolean") return value ? texts.yes : texts.no;
|
|
22
|
+
return String(value);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Writes the groups of a grouping: periods in the locale's words, ranges by the field's format. */
|
|
26
|
+
function groupFormatter(field, locale, texts, by) {
|
|
27
|
+
if (typeof by === "object") {
|
|
28
|
+
const format = field.format;
|
|
29
|
+
const write = typeof format === "function" ? format : numberFormat(locale, format ?? { maximumFractionDigits: 6 });
|
|
30
|
+
return (value) => isEmpty(value) ? texts.empty : fill(texts.range, {
|
|
31
|
+
from: write(value),
|
|
32
|
+
to: write(+(value + by.step).toPrecision(12))
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const month = dateFormat(locale, {
|
|
36
|
+
year: "numeric",
|
|
37
|
+
month: "long"
|
|
38
|
+
});
|
|
39
|
+
const day = dateFormat(locale, DATE);
|
|
40
|
+
return (value) => {
|
|
41
|
+
if (isEmpty(value)) return texts.empty;
|
|
42
|
+
const parts = readBucket(by, value);
|
|
43
|
+
if (!parts) return String(value);
|
|
44
|
+
switch (by) {
|
|
45
|
+
case "year": return fill(texts.year, { year: parts.year });
|
|
46
|
+
case "quarter": return fill(texts.quarter, {
|
|
47
|
+
year: parts.year,
|
|
48
|
+
quarter: parts.part
|
|
49
|
+
});
|
|
50
|
+
case "month": return month(parts.date);
|
|
51
|
+
case "week": return fill(texts.week, {
|
|
52
|
+
year: parts.year,
|
|
53
|
+
week: parts.part
|
|
54
|
+
});
|
|
55
|
+
default: return day(parts.date);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The number format a value is written with: the share, sign and rank
|
|
61
|
+
* defaults, or its own `format`. `null` for a format function and for
|
|
62
|
+
* dates (a `min` or `max` of a date field).
|
|
63
|
+
*/
|
|
64
|
+
function valueNumberOptions(value) {
|
|
65
|
+
const format = value.format;
|
|
66
|
+
if (typeof format === "function") return null;
|
|
67
|
+
const show = value.show?.as;
|
|
68
|
+
const signed = show === "difference" || show === "percentDifference";
|
|
69
|
+
if (show && PERCENT_SHOWS.has(show)) return format ?? {
|
|
70
|
+
style: "percent",
|
|
71
|
+
minimumFractionDigits: 1,
|
|
72
|
+
maximumFractionDigits: 1,
|
|
73
|
+
...signed ? { signDisplay: "exceptZero" } : {}
|
|
74
|
+
};
|
|
75
|
+
if (show === "rank") return format ?? { maximumFractionDigits: 0 };
|
|
76
|
+
if (value.field?.type === "date" && !show && (value.aggregate === "min" || value.aggregate === "max")) return null;
|
|
77
|
+
const options = format ?? (value.integer ? { maximumFractionDigits: 0 } : { maximumFractionDigits: 2 });
|
|
78
|
+
return signed && !options.signDisplay ? {
|
|
79
|
+
...options,
|
|
80
|
+
signDisplay: "exceptZero"
|
|
81
|
+
} : options;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Writes a value; an empty cell is blank. A value shown as a share is a
|
|
85
|
+
* percentage, a difference has its sign, a rank is a whole number; a
|
|
86
|
+
* `format` of its own is used as given.
|
|
87
|
+
*/
|
|
88
|
+
function valueFormatter(value, locale) {
|
|
89
|
+
const format = value.format;
|
|
90
|
+
let fn;
|
|
91
|
+
const options = valueNumberOptions(value);
|
|
92
|
+
if (typeof format === "function") fn = format;
|
|
93
|
+
else if (options) fn = numberFormat(locale, options);
|
|
94
|
+
else {
|
|
95
|
+
const write = dateFormat(locale, format ?? DATE);
|
|
96
|
+
fn = (n) => write(new Date(n));
|
|
97
|
+
}
|
|
98
|
+
return (n) => n !== n ? "" : fn(n);
|
|
99
|
+
}
|
|
100
|
+
var numbers = /* @__PURE__ */ new Map();
|
|
101
|
+
var dates = /* @__PURE__ */ new Map();
|
|
102
|
+
function numberFormat(locale, options) {
|
|
103
|
+
const key = `${locale}|${JSON.stringify(options)}`;
|
|
104
|
+
let format = numbers.get(key);
|
|
105
|
+
if (!format) numbers.set(key, format = new Intl.NumberFormat(locale, options));
|
|
106
|
+
return (n) => format.format(n);
|
|
107
|
+
}
|
|
108
|
+
function dateFormat(locale, options) {
|
|
109
|
+
const key = `${locale}|${JSON.stringify(options)}`;
|
|
110
|
+
let format = dates.get(key);
|
|
111
|
+
if (!format) dates.set(key, format = new Intl.DateTimeFormat(locale, options));
|
|
112
|
+
return (d) => format.format(d);
|
|
113
|
+
}
|
|
114
|
+
export { labelFormatter, valueFormatter, valueNumberOptions };
|
|
115
|
+
|
|
116
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","names":[],"sources":["../../src/core/format.ts"],"sourcesContent":["import type { PivotResolvedField, PivotResolvedValue } from '../engine'\nimport { isEmpty, PERCENT_SHOWS } from '../engine'\nimport { readBucket, type PivotGroupBy } from '../engine/group'\nimport type { PivotFormat } from '../engine/types'\n\nexport interface PivotLabelTexts {\n empty: string\n yes: string\n no: string\n /** Group labels of a grouping: `{year}`, `{quarter}`, `{week}`, `{from}`, `{to}`. */\n year: string\n quarter: string\n week: string\n range: string\n}\n\nconst fill = (text: string, params: Record<string, string | number>) =>\n text.replace(/\\{(\\w+)\\}/g, (m, k: string) => String(params[k] ?? m))\n\nconst DATE: Intl.DateTimeFormatOptions = { year: 'numeric', month: '2-digit', day: '2-digit' }\n\n/** Writes a group label: the field's `format`, or a plain form of the value. */\nexport function labelFormatter(\n field: PivotResolvedField<unknown>,\n locale: string,\n texts: PivotLabelTexts,\n by?: PivotGroupBy,\n): (value: unknown) => string {\n if (by !== undefined) return groupFormatter(field, locale, texts, by)\n const format = field.format\n const custom =\n typeof format === 'function'\n ? format\n : format && field.type === 'date'\n ? dateFormat(locale, format as Intl.DateTimeFormatOptions)\n : format && field.type === 'number'\n ? numberFormat(locale, format as Intl.NumberFormatOptions)\n : null\n const dates = dateFormat(locale, DATE)\n return (value) => {\n if (isEmpty(value)) return texts.empty\n if (custom) return custom(value)\n if (value instanceof Date) return dates(value)\n if (typeof value === 'boolean') return value ? texts.yes : texts.no\n return String(value)\n }\n}\n\n/** Writes the groups of a grouping: periods in the locale's words, ranges by the field's format. */\nfunction groupFormatter(\n field: PivotResolvedField<unknown>,\n locale: string,\n texts: PivotLabelTexts,\n by: PivotGroupBy,\n): (value: unknown) => string {\n if (typeof by === 'object') {\n const format = field.format\n const write =\n typeof format === 'function'\n ? (format as (n: number) => string)\n : numberFormat(locale, (format as Intl.NumberFormatOptions) ?? { maximumFractionDigits: 6 })\n return (value) =>\n isEmpty(value)\n ? texts.empty\n : fill(texts.range, {\n from: write(value as number),\n to: write(+((value as number) + by.step).toPrecision(12)),\n })\n }\n const month = dateFormat(locale, { year: 'numeric', month: 'long' })\n const day = dateFormat(locale, DATE)\n return (value) => {\n if (isEmpty(value)) return texts.empty\n const parts = readBucket(by, value)\n if (!parts) return String(value)\n switch (by) {\n case 'year':\n return fill(texts.year, { year: parts.year })\n case 'quarter':\n return fill(texts.quarter, { year: parts.year, quarter: parts.part })\n case 'month':\n return month(parts.date)\n case 'week':\n return fill(texts.week, { year: parts.year, week: parts.part })\n default:\n return day(parts.date)\n }\n }\n}\n\n/**\n * The number format a value is written with: the share, sign and rank\n * defaults, or its own `format`. `null` for a format function and for\n * dates (a `min` or `max` of a date field).\n */\nexport function valueNumberOptions(value: PivotResolvedValue): Intl.NumberFormatOptions | null {\n const format: PivotFormat | undefined = value.format\n if (typeof format === 'function') return null\n const show = value.show?.as\n const signed = show === 'difference' || show === 'percentDifference'\n if (show && PERCENT_SHOWS.has(show)) {\n return (\n (format as Intl.NumberFormatOptions) ?? {\n style: 'percent',\n minimumFractionDigits: 1,\n maximumFractionDigits: 1,\n ...(signed ? { signDisplay: 'exceptZero' } : {}),\n }\n )\n }\n if (show === 'rank') return (format as Intl.NumberFormatOptions) ?? { maximumFractionDigits: 0 }\n if (\n value.field?.type === 'date' &&\n !show &&\n (value.aggregate === 'min' || value.aggregate === 'max')\n )\n return null\n const options =\n (format as Intl.NumberFormatOptions) ??\n (value.integer ? { maximumFractionDigits: 0 } : { maximumFractionDigits: 2 })\n return signed && !options.signDisplay ? { ...options, signDisplay: 'exceptZero' } : options\n}\n\n/**\n * Writes a value; an empty cell is blank. A value shown as a share is a\n * percentage, a difference has its sign, a rank is a whole number; a\n * `format` of its own is used as given.\n */\nexport function valueFormatter(value: PivotResolvedValue, locale: string): (n: number) => string {\n const format: PivotFormat | undefined = value.format\n let fn: (n: number) => string\n const options = valueNumberOptions(value)\n if (typeof format === 'function') fn = format as (n: number) => string\n else if (options) fn = numberFormat(locale, options)\n else {\n const write = dateFormat(locale, (format as Intl.DateTimeFormatOptions) ?? DATE)\n fn = (n) => write(new Date(n))\n }\n return (n) => (n !== n ? '' : fn(n))\n}\n\nconst numbers = new Map<string, Intl.NumberFormat>()\nconst dates = new Map<string, Intl.DateTimeFormat>()\n\nfunction numberFormat(locale: string, options: Intl.NumberFormatOptions) {\n const key = `${locale}|${JSON.stringify(options)}`\n let format = numbers.get(key)\n if (!format) numbers.set(key, (format = new Intl.NumberFormat(locale, options)))\n return (n: unknown) => format!.format(n as number)\n}\n\nfunction dateFormat(locale: string, options: Intl.DateTimeFormatOptions) {\n const key = `${locale}|${JSON.stringify(options)}`\n let format = dates.get(key)\n if (!format) dates.set(key, (format = new Intl.DateTimeFormat(locale, options)))\n return (d: unknown) => format!.format(d as Date)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { format } from "../locale.js";
|
|
2
|
+
// src/core/labels.ts
|
|
3
|
+
/**
|
|
4
|
+
* A value's header: its `label`, the field's name for a sum, or the field
|
|
5
|
+
* and the way it is summed up ("销售额 · 平均值"); a plain count is "计数";
|
|
6
|
+
* a calculated value's formula. A value with a `show` adds it ("销售额 · 占总计").
|
|
7
|
+
*/
|
|
8
|
+
function valueLabel(value, label, m) {
|
|
9
|
+
if (label ?? value.label) return label ?? value.label;
|
|
10
|
+
const base = plainLabel(value, m);
|
|
11
|
+
return value.show ? format(m.shownValue, {
|
|
12
|
+
value: base,
|
|
13
|
+
show: m.shows[value.show.as]
|
|
14
|
+
}) : base;
|
|
15
|
+
}
|
|
16
|
+
/** The header of a value without its `show`. */
|
|
17
|
+
function plainLabel(value, m) {
|
|
18
|
+
if (value.formula !== void 0) return value.formula;
|
|
19
|
+
if (value.implicit || !value.field) return m.aggregates.count;
|
|
20
|
+
if (value.aggregate === "sum") return value.field.label;
|
|
21
|
+
return format(m.value, {
|
|
22
|
+
field: value.field.label,
|
|
23
|
+
aggregate: m.aggregates[value.aggregate] ?? value.aggregator?.label ?? value.aggregate
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export { valueLabel };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.js","names":[],"sources":["../../src/core/labels.ts"],"sourcesContent":["import type { PivotResolvedValue } from '../engine'\nimport { format } from '../locale'\n\ninterface ValueTexts {\n value: string\n aggregates: Record<string, string>\n shows: Record<string, string>\n shownValue: string\n}\n\n/**\n * A value's header: its `label`, the field's name for a sum, or the field\n * and the way it is summed up (\"销售额 · 平均值\"); a plain count is \"计数\";\n * a calculated value's formula. A value with a `show` adds it (\"销售额 · 占总计\").\n */\nexport function valueLabel(value: PivotResolvedValue, label: string | undefined, m: ValueTexts) {\n if (label ?? value.label) return (label ?? value.label)!\n const base = plainLabel(value, m)\n return value.show ? format(m.shownValue, { value: base, show: m.shows[value.show.as]! }) : base\n}\n\n/** The header of a value without its `show`. */\nfunction plainLabel(value: PivotResolvedValue, m: ValueTexts) {\n if (value.formula !== undefined) return value.formula\n if (value.implicit || !value.field) return m.aggregates.count!\n if (value.aggregate === 'sum') return value.field.label\n return format(m.value, {\n field: value.field.label,\n aggregate: m.aggregates[value.aggregate] ?? value.aggregator?.label ?? value.aggregate,\n })\n}\n"],"mappings":";;;;;;;AAeA,SAAgB,WAAW,OAA2B,OAA2B,GAAe;CAC9F,IAAI,SAAS,MAAM,OAAO,OAAQ,SAAS,MAAM;CACjD,MAAM,OAAO,WAAW,OAAO,CAAC;CAChC,OAAO,MAAM,OAAO,OAAO,EAAE,YAAY;EAAE,OAAO;EAAM,MAAM,EAAE,MAAM,MAAM,KAAK;CAAK,CAAC,IAAI;AAC7F;;AAGA,SAAS,WAAW,OAA2B,GAAe;CAC5D,IAAI,MAAM,YAAY,KAAA,GAAW,OAAO,MAAM;CAC9C,IAAI,MAAM,YAAY,CAAC,MAAM,OAAO,OAAO,EAAE,WAAW;CACxD,IAAI,MAAM,cAAc,OAAO,OAAO,MAAM,MAAM;CAClD,OAAO,OAAO,EAAE,OAAO;EACrB,OAAO,MAAM,MAAM;EACnB,WAAW,EAAE,WAAW,MAAM,cAAc,MAAM,YAAY,SAAS,MAAM;CAC/E,CAAC;AACH"}
|