@dou-ui/pivot 0.0.0-stage → 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/dist/assets/default-PXde2wzm.js.map +1 -0
  4. package/dist/core/format.js +116 -0
  5. package/dist/core/format.js.map +1 -0
  6. package/dist/core/labels.js +28 -0
  7. package/dist/core/labels.js.map +1 -0
  8. package/dist/core/layout.js +190 -0
  9. package/dist/core/layout.js.map +1 -0
  10. package/dist/core/source.js +46 -0
  11. package/dist/core/source.js.map +1 -0
  12. package/dist/core/table.js +154 -0
  13. package/dist/core/table.js.map +1 -0
  14. package/dist/engine/aggregate.js +51 -0
  15. package/dist/engine/aggregate.js.map +1 -0
  16. package/dist/engine/compute.js +735 -0
  17. package/dist/engine/compute.js.map +1 -0
  18. package/dist/engine/engine.js +46 -0
  19. package/dist/engine/engine.js.map +1 -0
  20. package/dist/engine/formula.js +225 -0
  21. package/dist/engine/formula.js.map +1 -0
  22. package/dist/engine/group.js +107 -0
  23. package/dist/engine/group.js.map +1 -0
  24. package/dist/engine/hash.js +108 -0
  25. package/dist/engine/hash.js.map +1 -0
  26. package/dist/engine/index.js +8 -0
  27. package/dist/engine/show.js +132 -0
  28. package/dist/engine/show.js.map +1 -0
  29. package/dist/engine/source.js +339 -0
  30. package/dist/engine/source.js.map +1 -0
  31. package/dist/engine/tree.js +226 -0
  32. package/dist/engine/tree.js.map +1 -0
  33. package/dist/fields/fields.js +6 -0
  34. package/dist/fields/fields.js.map +1 -0
  35. package/dist/fields/fields.vue_vue_type_script_setup_true_lang.js +881 -0
  36. package/dist/fields/fields.vue_vue_type_script_setup_true_lang.js.map +1 -0
  37. package/dist/fields/filter-list.js +6 -0
  38. package/dist/fields/filter-list.js.map +1 -0
  39. package/dist/fields/filter-list.vue_vue_type_script_setup_true_lang.js +184 -0
  40. package/dist/fields/filter-list.vue_vue_type_script_setup_true_lang.js.map +1 -0
  41. package/dist/fields/formula-dialog.js +6 -0
  42. package/dist/fields/formula-dialog.js.map +1 -0
  43. package/dist/fields/formula-dialog.vue_vue_type_script_setup_true_lang.js +165 -0
  44. package/dist/fields/formula-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  45. package/dist/fields/model.js +200 -0
  46. package/dist/fields/model.js.map +1 -0
  47. package/dist/fields/top-dialog.js +6 -0
  48. package/dist/fields/top-dialog.js.map +1 -0
  49. package/dist/fields/top-dialog.vue_vue_type_script_setup_true_lang.js +174 -0
  50. package/dist/fields/top-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  51. package/dist/index.js +16 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/locale.js +508 -0
  54. package/dist/locale.js.map +1 -0
  55. package/dist/pivot.js +6 -0
  56. package/dist/pivot.js.map +1 -0
  57. package/dist/pivot.vue_vue_type_script_setup_true_lang.js +1711 -0
  58. package/dist/pivot.vue_vue_type_script_setup_true_lang.js.map +1 -0
  59. package/dist/style.css +1 -0
  60. package/dist/style.d.ts +1 -0
  61. package/dist/style.js +13 -0
  62. package/dist/types/core/format.d.ts +26 -0
  63. package/dist/types/core/labels.d.ts +14 -0
  64. package/dist/types/core/layout.d.ts +72 -0
  65. package/dist/types/core/source.d.ts +7 -0
  66. package/dist/types/core/table.d.ts +73 -0
  67. package/dist/types/engine/aggregate.d.ts +35 -0
  68. package/dist/types/engine/compute.d.ts +173 -0
  69. package/dist/types/engine/engine.d.ts +29 -0
  70. package/dist/types/engine/formula.d.ts +44 -0
  71. package/dist/types/engine/group.d.ts +34 -0
  72. package/dist/types/engine/hash.d.ts +36 -0
  73. package/dist/types/engine/index.d.ts +15 -0
  74. package/dist/types/engine/show.d.ts +27 -0
  75. package/dist/types/engine/source.d.ts +108 -0
  76. package/dist/types/engine/tree.d.ts +87 -0
  77. package/dist/types/engine/types.d.ts +148 -0
  78. package/dist/types/fields/fields.vue.d.ts +26 -0
  79. package/dist/types/fields/filter-list.vue.d.ts +20 -0
  80. package/dist/types/fields/formula-dialog.vue.d.ts +30 -0
  81. package/dist/types/fields/model.d.ts +52 -0
  82. package/dist/types/fields/top-dialog.vue.d.ts +25 -0
  83. package/dist/types/index.d.ts +458 -0
  84. package/dist/types/locale.d.ts +184 -0
  85. package/dist/types/pivot.vue.d.ts +29 -0
  86. package/dist/types/types.d.ts +199 -0
  87. package/dist/types/worker/client.d.ts +19 -0
  88. package/dist/types/worker/default.d.ts +1 -0
  89. package/dist/types/worker/index.d.ts +5 -0
  90. package/dist/types/worker/protocol.d.ts +60 -0
  91. package/dist/types/worker/serve.d.ts +22 -0
  92. package/dist/worker/client.js +191 -0
  93. package/dist/worker/client.js.map +1 -0
  94. package/dist/worker/default.js +20 -0
  95. package/dist/worker/default.js.map +1 -0
  96. package/dist/worker/index.js +3 -0
  97. package/dist/worker/serve.js +101 -0
  98. package/dist/worker/serve.js.map +1 -0
  99. package/package.json +64 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pivot.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_normalizeClass","_normalizeStyle","_createElementVNode","_Fragment","_renderList","_toDisplayString","_createCommentVNode","_unref","_createTextVNode","_createBlock","_createVNode","_isMemoSame"],"sources":["../src/pivot.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"Row = Record<string, unknown>\">\nimport type { HTMLAttributes } from 'vue'\nimport type { ForwardedAttributes } from 'dou-ui'\nimport { useElementSize, useLocale } from 'dou-ui'\nimport { ArrowDownIcon, ArrowUpIcon, ChevronRightIcon } from '@dou-ui/icons'\nimport {\n computed,\n markRaw,\n nextTick,\n onBeforeUnmount,\n ref,\n shallowRef,\n toRaw,\n useId,\n watch,\n} from 'vue'\nimport {\n computePivot,\n PivotSource,\n type PivotAggregator,\n type PivotResult,\n type PivotTree,\n} from './engine'\nimport { BUILTIN_AGGREGATORS, FAST_AGGREGATES } from './engine/aggregate'\nimport { markOf, PERCENT_SHOWS, showOf } from './engine/compute'\nimport type { PivotEngine } from './engine/engine'\nimport type {\n PivotCollapsed,\n PivotConfig,\n PivotDimension,\n PivotField,\n PivotPath,\n} from './engine/types'\nimport {\n collapsedNodes,\n columnLines,\n groupPaths,\n headerSpans,\n rowLines,\n samePath,\n spansIn,\n totalLines,\n type PivotAxis,\n type PivotHeaderSpan,\n type PivotLine,\n} from './core/layout'\nimport { labelFormatter, valueFormatter, valueNumberOptions } from './core/format'\nimport { valueLabel } from './core/labels'\nimport { usePivotSource } from './core/source'\nimport {\n gridMerges,\n gridToCSV,\n gridToHTML,\n gridToSheetCells,\n gridToTSV,\n sheetFormat,\n SHEET_STYLES,\n type PivotCSVOptions,\n type PivotGrid,\n type PivotGridCell,\n} from './core/table'\nimport { format, usePivotMessages } from './locale'\nimport type {\n PivotCellEvent,\n PivotChartRows,\n PivotChartRowsOptions,\n PivotCopyOptions,\n PivotEmits,\n PivotExpose,\n PivotPrintOptions,\n PivotProps,\n PivotSheetWorkbook,\n} from './types'\n\ndefineOptions({ name: 'DouPivot' })\n\nconst props = withDefaults(\n defineProps<\n PivotProps<Row> &\n /* @vue-ignore */ ForwardedAttributes<\n HTMLAttributes,\n PivotProps<Row>,\n keyof PivotEmits & string\n >\n >(),\n {\n layout: 'compact',\n resizable: true,\n worker: 'auto',\n maxHeight: 480,\n size: 'md',\n rowHeaderWidth: 200,\n columnWidth: 120,\n },\n)\nconst config = defineModel<PivotConfig>('config', { default: () => ({}) })\nconst collapsed = defineModel<PivotCollapsed>('collapsed', { default: () => ({}) })\nconst emit = defineEmits<{ cellClick: [cell: PivotCellEvent<Row>] }>()\n\nconst { locale } = useLocale()\nconst messages = usePivotMessages(() => props.messages)\nconst uid = useId()\n\nconst ROW_HEIGHT: Record<string, number> = { sm: 28, md: 32, lg: 40 }\nconst VALUE_HEADER_WIDTH = 120\n\n// ---- the records, read once per array ----\n\nconst source = usePivotSource(\n () => props.data,\n () => props.fields,\n)\n\n/** Stays the same object while the aggregators do, even when the array is written inline. */\nlet lastAggregators: Record<string, PivotAggregator> = {}\nconst aggregatorMap = computed(() => {\n const list = props.aggregators ?? []\n const last = Object.values(lastAggregators)\n if (list.length === last.length && list.every((a) => lastAggregators[a.name] === toRaw(a)))\n return lastAggregators\n const map: Record<string, PivotAggregator> = {}\n for (const aggregator of list) map[aggregator.name] = toRaw(aggregator)\n return (lastAggregators = map)\n})\n\nconst keyReplacer = (_key: string, value: unknown) =>\n typeof value === 'function' ? undefined : value\n\nconst dimensionKey = (d: PivotDimension) =>\n typeof d === 'string'\n ? { field: d }\n : { field: d.field, sort: d.sort, subtotal: d.subtotal, by: d.by }\n\n/**\n * The part of the config that changes what is summed up. Sorting, totals,\n * labels and formats leave it as it is, so they never sum up again.\n */\nlet engineCache: { key: string; config: PivotConfig } | null = null\nconst engineConfig = computed<PivotConfig>(() => {\n const c = config.value\n const custom = aggregatorMap.value\n const values = (c.values ?? []).filter((v) => {\n const name = typeof v === 'string' ? undefined : v.aggregate\n if (!name || FAST_AGGREGATES.has(name) || BUILTIN_AGGREGATORS[name] || custom[name]) return true\n if (import.meta.env?.DEV)\n console.warn(\n `[@dou-ui/pivot] there is no aggregate named \"${name}\", so this value is left out; register it in the aggregators prop`,\n )\n return false\n })\n const next: PivotConfig = {\n rows: (c.rows ?? []).map(dimensionKey),\n columns: (c.columns ?? []).map(dimensionKey),\n // how values are shown, marked, headed and written changes nothing to sum up\n values: values.map((v) =>\n typeof v === 'string'\n ? { field: v }\n : v.formula !== undefined\n ? { formula: v.formula }\n : { field: v.field, aggregate: v.aggregate },\n ),\n filters: c.filters,\n }\n const key = JSON.stringify(next, keyReplacer)\n if (engineCache?.key === key) return engineCache.config\n engineCache = { key, config: next }\n return next\n})\n\n// ---- summing up: here, or in a worker ----\n\n/** Records from which `'auto'` sums up in a worker. */\nconst WORKER_FROM = 100_000\n/** How long a worker may take before the table says it is busy, in ms. */\nconst BUSY_AFTER = 120\n\n/** Set when the table's own worker cannot start (under a strict CSP, say); it then sums up here. */\nconst ownFailed = ref(false)\nconst away = computed(\n () =>\n !!props.engine ||\n (!ownFailed.value &&\n (props.worker === true ||\n (props.worker === 'auto' &&\n source.value.length > WORKER_FROM &&\n typeof Worker !== 'undefined'))),\n)\n\n/** The last result summed up here, shown while a worker sums up the first time. */\nlet lastHere: PivotResult | null = null\nconst here = computed(() => {\n if (away.value) return null\n const next = computePivot(source.value, engineConfig.value, { aggregators: aggregatorMap.value })\n return (lastHere = markRaw(next))\n})\n\n/** What a worker last sent, and whether a newer one is on its way. */\nconst fromAway = shallowRef<PivotResult | null>(null)\nconst busy = ref(false)\n/** Groups with no records yet: the shape of the table while the first result is on its way. */\nconst shapeOnly = computed(() =>\n markRaw(computePivot(new PivotSource([], { fields: [...source.value.fields.values()] }), {})),\n)\nconst result = computed<PivotResult>(() => here.value ?? fromAway.value ?? shapeOnly.value)\n\nlet ownEngine: PivotEngine | null = null\nasync function startOwnEngine() {\n const [{ createPivotWorker }, { default: PivotWorker }] = await Promise.all([\n import('./worker/client'),\n import('./worker/default?worker&inline'),\n ])\n return createPivotWorker(() => new PivotWorker())\n}\nlet ownEngineReady: Promise<PivotEngine> | null = null\nconst engineFor = () =>\n props.engine\n ? Promise.resolve(props.engine)\n : (ownEngineReady ??= startOwnEngine().then((engine) => (ownEngine = engine)))\n\nlet job = 0\nlet stop: AbortController | null = null\nwatch(\n [away, source, engineConfig, () => props.engine],\n async ([isAway, src, cfg]) => {\n stop?.abort()\n stop = null\n const id = ++job\n if (!isAway) {\n busy.value = false\n fromAway.value = null\n return\n }\n // keep what is on screen until the worker's first result comes\n if (!fromAway.value && lastHere) fromAway.value = lastHere\n lastHere = null\n const controller = (stop = new AbortController())\n const slow = setTimeout(() => id === job && (busy.value = true), BUSY_AFTER)\n try {\n const engine = await engineFor()\n const next = await engine.compute(src, cfg, {\n aggregators: aggregatorMap.value,\n signal: controller.signal,\n })\n if (id !== job) return\n fromAway.value = markRaw(next)\n } catch (error) {\n if (id !== job || (error as Error).name === 'AbortError') return\n if (props.engine)\n console.error(\n '[@dou-ui/pivot] the engine passed to DouPivot failed in compute(); the table keeps the last result',\n error,\n )\n else {\n // the own worker failed: sum up on the page from now on\n console.warn(\n '[@dou-ui/pivot] the worker is not available, so the table sums up on the page from now on',\n error,\n )\n ownEngine?.dispose?.()\n ownEngine = null\n ownEngineReady = null\n ownFailed.value = true\n }\n } finally {\n clearTimeout(slow)\n if (id === job) busy.value = false\n }\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n stop?.abort()\n job++\n ownEngine?.dispose?.()\n})\n\n// ---- what is shown ----\n\nconst valueCount = computed(() => result.value.values.length)\nconst valuesOnRows = computed(() => config.value.valuesOn === 'rows' && valueCount.value > 1)\nconst showRowTotal = computed(() => config.value.totals?.rows !== false)\nconst showColumnTotal = computed(() => config.value.totals?.columns !== false)\n\nconst rowCollapsed = computed(() => collapsedNodes(result.value.rows, collapsed.value.rows))\nconst columnCollapsed = computed(() =>\n collapsedNodes(result.value.columns, collapsed.value.columns),\n)\nconst rowOrder = computed(() => result.value.rowOrder(config.value.sort))\n/** Each row field in a column of its own, open groups' totals on a line after their children. */\nconst tabular = computed(() => props.layout === 'tabular' && result.value.rows.levels.length > 0)\n\nconst bodyLines = computed(() =>\n rowLines(result.value.rows, rowOrder.value, rowCollapsed.value, {\n values: valueCount.value,\n valuesHere: valuesOnRows.value,\n total: showRowTotal.value,\n totalsAfter: tabular.value,\n }),\n)\nconst footLines = computed(() =>\n totalLines(result.value.rows, {\n values: valueCount.value,\n valuesHere: valuesOnRows.value,\n total: showRowTotal.value,\n }),\n)\nconst colLines = computed(() =>\n columnLines(result.value.columns, columnCollapsed.value, {\n values: valueCount.value,\n valuesHere: !valuesOnRows.value,\n total: showColumnTotal.value,\n }),\n)\n/**\n * The row naming each column's value: left out when the values run along the\n * rows, and when one value sits under column groups (each would repeat it).\n */\nconst valueRow = computed(\n () => result.value.columns.levels.length === 0 || (!valuesOnRows.value && valueCount.value > 1),\n)\nconst spans = computed(() => headerSpans(result.value.columns, colLines.value, valueRow.value))\n\n/** How each value is headed, shown, marked and written: the config's, on what was summed up. */\nconst valueDisplay = computed(() => {\n const m = messages.value\n return result.value.values.map((value, i) => {\n const given = config.value.values?.[i]\n const spec = typeof given === 'object' ? given : undefined\n const show = showOf(spec?.show)\n // a share or a rank is not in the field's units\n const own = show && (PERCENT_SHOWS.has(show.as) || show.as === 'rank')\n const shownValue = {\n ...value,\n show,\n format: spec?.format ?? (own ? undefined : value.format),\n }\n const options = valueNumberOptions(shownValue)\n return {\n label: valueLabel(shownValue, spec?.label, m),\n write: valueFormatter(shownValue, locale.value.name),\n /** The same format for a sheet, when there is one. */\n sheetFormat: options ? sheetFormat(options, locale.value.name) : undefined,\n show: show ?? null,\n mark: markOf(spec?.mark),\n }\n })\n})\n\nconst labelWriters = (tree: PivotTree) => {\n const m = messages.value\n const texts = {\n empty: m.empty,\n yes: m.yes,\n no: m.no,\n year: m.yearLabel,\n quarter: m.quarterLabel,\n week: m.weekLabel,\n range: m.rangeLabel,\n }\n return tree.levels.map((level) => labelFormatter(level.field, locale.value.name, texts, level.by))\n}\nconst rowWriters = computed(() => labelWriters(result.value.rows))\nconst colWriters = computed(() => labelWriters(result.value.columns))\n\nconst nodeText = (tree: PivotTree, writers: ((v: unknown) => string)[], node: number) =>\n node <= 0 ? messages.value.total : writers[tree.depth[node]! - 1]!(tree.label(node))\n\n// ---- sizes and the window in view ----\n\nconst rowHeight = computed(() => ROW_HEIGHT[props.size] ?? 32)\n/** A row per column field, and one more for the row fields (and the values, when shown). */\nconst headRows = computed(() => result.value.columns.levels.length + 1)\nconst headHeight = computed(() => headRows.value * rowHeight.value)\n/** Set by dragging the edge of the corner; `0` for the width worked out from the props. */\nconst rowHeadDragged = ref(0)\nconst rowLevelCount = computed(() => (tabular.value ? result.value.rows.levels.length : 1))\n/**\n * The row headers' width. A tabular layout gives each row field a column of\n * 60% of `rowHeaderWidth`. On a narrow screen the row headers give up some\n * width so the numbers still show.\n */\nconst rowHeadWidth = computed(() => {\n if (rowHeadDragged.value) return rowHeadDragged.value\n const want = tabular.value\n ? rowLevelCount.value * Math.round(props.rowHeaderWidth * 0.6)\n : props.rowHeaderWidth\n return Math.min(want, Math.max(120, Math.floor(viewWidth.value * (tabular.value ? 0.5 : 0.4))))\n})\n/** The width of each row field's column in the tabular layout. */\nconst levelWidth = computed(() => Math.floor(rowHeadWidth.value / rowLevelCount.value))\nconst headWidth = computed(() => rowHeadWidth.value + (valuesOnRows.value ? VALUE_HEADER_WIDTH : 0))\n/** Columns widen to fill a wide table, up to twice their width; past that the bands run on alone. */\nconst colWidth = computed(() => {\n const count = colLines.value.length\n const fill = count ? Math.floor((viewWidth.value - headWidth.value) / count) : 0\n return Math.max(props.columnWidth, Math.min(fill, props.columnWidth * 2))\n})\n/** Widths set by dragging a column's edge, by the column's groups, kind and value. */\nconst dragged = shallowRef(new Map<string, number>())\nconst colKey = (line: PivotLine) =>\n `${line.kind}|${line.value}|${line.kind === 'total' ? '' : JSON.stringify(result.value.columns.path(line.node))}`\n/** Where each column starts; the last entry is where the last one ends. */\nconst colStarts = computed(() => {\n const lines = colLines.value\n const starts = new Float64Array(lines.length + 1)\n const base = colWidth.value\n const map = dragged.value\n for (let i = 0; i < lines.length; i++)\n starts[i + 1] = starts[i]! + (map.size ? (map.get(colKey(lines[i]!)) ?? base) : base)\n return starts\n})\n/** The column at `x` px from the left of the columns. */\nfunction columnAt(x: number) {\n const starts = colStarts.value\n let low = 0\n let high = starts.length - 2\n while (low < high) {\n const mid = (low + high + 1) >> 1\n if (starts[mid]! <= x) low = mid\n else high = mid - 1\n }\n return Math.max(0, low)\n}\nconst columnsWidth = computed(() => colStarts.value[colLines.value.length]!)\nconst totalWidth = computed(() => headWidth.value + columnsWidth.value)\nconst bodyHeight = computed(() => bodyLines.value.length * rowHeight.value)\nconst footHeight = computed(() => footLines.value.length * rowHeight.value)\n\nconst root = ref<HTMLElement>()\nconst viewport = ref<HTMLElement>()\nconst { width: viewWidth, height: viewHeight } = useElementSize(viewport, {\n initial: { width: 960, height: 480 },\n})\nconst scroll = shallowRef({ top: 0, left: 0 })\n/** The height of the horizontal scrollbar, when there is one that takes room. */\nconst gutter = ref(0)\nwatch(\n [viewWidth, viewHeight, () => totalWidth.value],\n () =>\n nextTick(() => {\n const el = viewport.value\n if (el) gutter.value = el.offsetHeight - el.clientHeight\n }),\n { flush: 'post' },\n)\n\nfunction onScroll() {\n const el = viewport.value\n if (!el) return\n if (el.scrollTop !== scroll.value.top || el.scrollLeft !== scroll.value.left)\n scroll.value = { top: el.scrollTop, left: el.scrollLeft }\n}\n\nconst OVERSCAN_ROWS = 6\nconst OVERSCAN_COLS = 2\n\nconst rowWindow = computed(() => {\n const h = rowHeight.value\n const space = Math.max(h, viewHeight.value - headHeight.value - footHeight.value)\n const from = Math.max(0, Math.floor(scroll.value.top / h) - OVERSCAN_ROWS)\n const to = Math.min(\n bodyLines.value.length,\n Math.ceil((scroll.value.top + space) / h) + OVERSCAN_ROWS,\n )\n return { from, to }\n})\n\nconst colWindow = computed(() => {\n const space = Math.max(colWidth.value, viewWidth.value - headWidth.value)\n const count = colLines.value.length\n const from = Math.max(0, columnAt(scroll.value.left) - OVERSCAN_COLS)\n const to = count ? Math.min(count, columnAt(scroll.value.left + space) + 1 + OVERSCAN_COLS) : 0\n // a stable object while the window stays put, so rows can skip re-rendering\n const last = lastColWindow\n if (last && last.from === from && last.to === to) return last\n return (lastColWindow = { from, to })\n})\nlet lastColWindow: { from: number; to: number } | null = null\n\nconst visibleRows = computed(() => {\n const { from, to } = rowWindow.value\n const out: { line: PivotLine; index: number }[] = []\n for (let i = from; i < to; i++) out.push({ line: bodyLines.value[i]!, index: i })\n return out\n})\nconst visibleFoot = computed(() =>\n footLines.value.map((line, i) => ({ line, index: bodyLines.value.length + i })),\n)\nconst visibleCols = computed(() => {\n const { from, to } = colWindow.value\n return colLines.value.slice(from, to).map((line, i) => ({ line, index: from + i }))\n})\nconst visibleSpans = computed(() => {\n const { from, to } = colWindow.value\n return spans.value.map((list) => spansIn(list, from, to))\n})\n\n// ---- rows ----\n\nconst rowTree = computed(() => result.value.rows)\n\n/** Whether a group's own row is blank because its field has no subtotals and it is open. */\nconst rowBlank = (line: PivotLine) => {\n if (line.kind !== 'group') return false\n const tree = rowTree.value\n if (!tree.isGroup(line.node) || rowCollapsed.value.has(line.node)) return false\n return !tree.levels[tree.depth[line.node]! - 1]!.subtotal\n}\n\nconst isFirstOfNode = (line: PivotLine) => line.value <= 0\n\n/** A group whose label shows on a line: in the tabular layout, one per row field. */\ninterface RowHeadPart {\n text: string\n /** The group a click on the arrow opens or closes, or -1. */\n toggle: number\n open: boolean\n}\n\ninterface RowHead {\n text: string\n depth: number\n group: boolean\n open: boolean\n valueText: string\n firstOfNode: boolean\n /** The tabular layout's labels, by row field; empty in the compact layout. */\n parts: (RowHeadPart | null)[]\n}\n\n/** Whether a line opens or closes a group from its row header: a group's line, or its total's. */\n/** Whether a line opens and closes its group; a subtotal after the children (tabular) does not. */\nconst lineToggles = (line: PivotLine) =>\n (line.kind === 'group' || (line.kind === 'subtotal' && !tabular.value)) &&\n rowTree.value.isGroup(line.node)\n\nfunction rowHead(line: PivotLine, index: number): RowHead {\n const tree = rowTree.value\n const group = lineToggles(line)\n const head: RowHead = {\n text:\n line.kind === 'total'\n ? messages.value.total\n : line.kind === 'subtotal'\n ? format(messages.value.subtotalRow, {\n label: nodeText(tree, rowWriters.value, line.node),\n })\n : nodeText(tree, rowWriters.value, line.node),\n depth: line.kind === 'total' ? 0 : tree.depth[line.node]! - 1,\n group,\n open: group && !rowCollapsed.value.has(line.node),\n valueText: line.value >= 0 ? valueDisplay.value[line.value]!.label : '',\n firstOfNode: isFirstOfNode(line),\n parts: [],\n }\n if (!tabular.value || !head.firstOfNode) return head\n const parts: (RowHeadPart | null)[] = Array.from({ length: tree.levels.length }, () => null)\n if (line.kind === 'total' || line.kind === 'subtotal') {\n parts[head.depth] = { text: head.text, toggle: group ? line.node : -1, open: head.open }\n } else {\n // a group's label shows on the first line inside it\n const before = index > 0 ? bodyLines.value[index - 1] : undefined\n for (let at = line.node; at > 0; at = tree.parent[at]!) {\n const level = tree.depth[at]! - 1\n if (at !== line.node && before && before.kind !== 'total' && tree.within(before.node, at))\n break\n const isGroup = tree.isGroup(at)\n parts[level] = {\n text: nodeText(tree, rowWriters.value, at),\n toggle: isGroup ? at : -1,\n open: isGroup && !rowCollapsed.value.has(at),\n }\n }\n }\n head.parts = parts\n return head\n}\n\ninterface Cell {\n key: number\n /** In the selected range. */\n selected: boolean\n text: string\n cls: string\n col: number\n style: string\n}\n\n/** Where a mark puts a value: a bar's start and size, or a tint's depth, from 0 to 1. */\nfunction markStyle(value: number, valueIndex: number) {\n const { mark, show } = valueDisplay.value[valueIndex]!\n if (!mark) return ''\n const { min, max } = result.value.range(valueIndex, show)\n if (min !== min) return ''\n const tone = `--dou-pivot-tone:var(--dou-color-${mark.tone})`\n if (mark.type === 'scale') {\n const depth = max === min ? 1 : (value - min) / (max - min)\n return `;${tone};--dou-pivot-mark:${depth.toFixed(3)}`\n }\n // bars grow from zero, to the left for values below it\n const lo = Math.min(0, min)\n const span = Math.max(0, max) - lo || 1\n const start = (Math.min(value, 0) - lo) / span\n return `;${tone};--dou-pivot-bar-start:${start.toFixed(3)};--dou-pivot-bar-size:${(Math.abs(value) / span).toFixed(3)}`\n}\n\nfunction rowCells(line: PivotLine, row: number): Cell[] {\n const res = result.value\n const sel = selection.value\n const picked = sel && row >= sel.top && row <= sel.bottom ? sel : null\n const blank = rowBlank(line)\n const display = valueDisplay.value\n const starts = colStarts.value\n // marks go on the innermost cells, never on subtotals and totals\n // (without fields on an axis, its grand total is its innermost group)\n const innerRow = res.rows.depth[line.node] === res.rows.levels.length && !blank\n return visibleCols.value.map(({ line: col, index }) => {\n const v = line.value >= 0 ? line.value : Math.max(0, col.value)\n const n = blank ? Number.NaN : res.shown(line.node, col.node, v, display[v]!.show)\n let cls = 'dou-pivot__cell'\n if (col.kind !== 'group') cls += ' is-total'\n if (col.kind === 'group' && col.node > 0 && res.columns.isGroup(col.node)) cls += ' is-closed'\n const selected = !!picked && index >= picked.left && index <= picked.right\n if (selected) cls += ' is-selected'\n if (col.node === highlightCol.value) cls += ' is-highlighted'\n let style = `width:${starts[index + 1]! - starts[index]!}px`\n const mark = display[v]!.mark\n if (mark && innerRow && n === n && res.columns.depth[col.node] === res.columns.levels.length) {\n cls += mark.type === 'bar' ? ' has-bar' : ' has-scale'\n style += markStyle(n, v)\n }\n return { key: index, col: index, text: display[v]!.write(n), cls, style, selected }\n })\n}\n\n// ---- header ----\n\ninterface HeadCell {\n key: string\n span: PivotHeaderSpan\n text: string\n style: string\n toggle: boolean\n open: boolean\n sortable: boolean\n sorted: 'asc' | 'desc' | null\n cls: string\n /** The column whose width its edge sets, or -1. */\n resize: number\n}\n\n/** What a header cell says: a group, a subtotal, the grand total or a value. */\nfunction spanText(span: PivotHeaderSpan) {\n const tree = result.value.columns\n if (span.kind === 'value')\n return span.value >= 0 ? valueDisplay.value[span.value]!.label : messages.value.total\n if (span.kind === 'total') return messages.value.total\n if (span.kind === 'subtotal')\n return format(messages.value.subtotal, { label: nodeText(tree, colWriters.value, span.node) })\n return nodeText(tree, colWriters.value, span.node)\n}\n\nconst columnPath = (line: { kind: string; node: number }) =>\n line.kind === 'total' ? [] : result.value.columns.path(line.node)\n\nconst headCells = computed<HeadCell[]>(() => {\n const tree = result.value.columns\n const starts = colStarts.value\n const h = rowHeight.value\n const sort = config.value.sort\n const out: HeadCell[] = []\n const rows = headRows.value\n visibleSpans.value.forEach((list) => {\n for (const span of list) {\n const reachesBottom = span.level + span.rows === rows\n const single = span.to - span.from === 1\n const line = colLines.value[span.from]!\n const sortable = span.kind === 'value' || (reachesBottom && single && !valueRow.value)\n const value = span.kind === 'value' ? Math.max(0, span.value) : Math.max(0, line.value)\n const sorted =\n sortable &&\n sort &&\n sort.valueIndex === value &&\n samePath(sort.column ?? [], columnPath(line))\n ? sort.order\n : null\n const canToggle = span.kind === 'group' && tree.isGroup(span.node)\n const text = spanText(span)\n let cls = `dou-pivot__col-head is-${span.kind}`\n // over the numbers, names sit right like them; a group with a toggle reads from the left\n if (span.kind !== 'group' || (!canToggle && single)) cls += ' is-end'\n if (span.kind === 'value' && line.kind !== 'group') cls += ' is-total'\n if (sorted) cls += ' is-sorted'\n out.push({\n key: `${span.level}:${span.from}:${span.kind}`,\n span,\n text,\n style: `left:${starts[span.from]}px;top:${span.level * h}px;width:${starts[span.to]! - starts[span.from]!}px;height:${span.rows * h}px`,\n resize: reachesBottom && single && props.resizable ? span.from : -1,\n toggle: canToggle,\n open: canToggle && !columnCollapsed.value.has(span.node),\n sortable,\n sorted,\n cls,\n })\n }\n })\n return out\n})\n\nconst rowFieldNames = computed(() => rowFields.value.map((f) => f.label).join(' / '))\nconst rowFields = computed(() =>\n result.value.rows.levels.map((level, i) => ({\n index: i,\n label: level.field.label,\n sort: level.sort,\n })),\n)\nconst columnFields = computed(() => result.value.columns.levels.map((level) => level.field.label))\n\n// ---- changing the config and the collapsed groups ----\n\nfunction sortByColumn(span: PivotHeaderSpan) {\n const line = colLines.value[span.from]!\n const value = span.kind === 'value' ? Math.max(0, span.value) : Math.max(0, line.value)\n const column = columnPath(line)\n const current = config.value.sort\n const same = current && current.valueIndex === value && samePath(current.column ?? [], column)\n // descending first (largest on top), then ascending, then back to the labels\n const order = !same ? 'desc' : current!.order === 'desc' ? 'asc' : null\n config.value = { ...config.value, sort: order ? { valueIndex: value, column, order } : null }\n}\n\nfunction sortByField(index: number) {\n const rows = (config.value.rows ?? []).map((d, i) => {\n const spec = typeof d === 'string' ? { field: d } : { ...d }\n if (i !== index) return d\n const wasValueSorted = !!config.value.sort\n spec.sort = wasValueSorted ? (spec.sort ?? 'asc') : spec.sort === 'desc' ? 'asc' : 'desc'\n return spec\n })\n config.value = { ...config.value, rows, sort: null }\n}\n\nfunction setCollapsed(axis: PivotAxis, paths: PivotPath[]) {\n collapsed.value = { ...collapsed.value, [axis]: paths }\n}\n\nfunction toggle(axis: PivotAxis, path: PivotPath, open?: boolean) {\n const list = collapsed.value[axis] ?? []\n const at = list.findIndex((p) => samePath(p, path))\n const isOpen = at < 0\n const next = open ?? !isOpen\n if (next === isOpen) return\n setCollapsed(axis, next ? list.filter((_, i) => i !== at) : [...list, path])\n}\n\nfunction toggleNode(axis: PivotAxis, node: number, all = false) {\n const tree = axis === 'rows' ? result.value.rows : result.value.columns\n const nodes = axis === 'rows' ? rowCollapsed.value : columnCollapsed.value\n const open = nodes.has(node)\n const label = nodeText(tree, axis === 'rows' ? rowWriters.value : colWriters.value, node)\n announce(format(open ? messages.value.expanded : messages.value.collapsed, { label }))\n if (!all) return toggle(axis, tree.path(node), open)\n // Alt: every group at the same depth goes the same way\n const depth = tree.depth[node]!\n const same: PivotPath[] = []\n for (let at = 1; at < tree.size; at++)\n if (tree.depth[at] === depth && tree.isGroup(at)) same.push(tree.path(at))\n const rest = (collapsed.value[axis] ?? []).filter((p) => !same.some((q) => samePath(p, q)))\n setCollapsed(axis, open ? rest : [...rest, ...same])\n}\n\nfunction expandAll({ axis }: { axis?: PivotAxis } = {}) {\n const next = { ...collapsed.value }\n for (const a of axis ? [axis] : (['rows', 'columns'] as const)) next[a] = []\n collapsed.value = next\n}\n\nfunction collapseAll({ axis, depth = 1 }: { axis?: PivotAxis; depth?: number } = {}) {\n const next = { ...collapsed.value }\n for (const a of axis ? [axis] : (['rows', 'columns'] as const))\n next[a] = groupPaths(a === 'rows' ? result.value.rows : result.value.columns, depth)\n collapsed.value = next\n}\n\n// ---- column widths ----\n\nlet justResized = false\nconst MIN_COLUMN = 56\nconst MAX_COLUMN = 640\n\n/** A column's width, or the row headers' for `-1`. */\nconst widthOf = (col: number) =>\n col < 0 ? rowHeadWidth.value : colStarts.value[col + 1]! - colStarts.value[col]!\nconst minWidthOf = (col: number) => (col < 0 ? 80 * rowLevelCount.value : MIN_COLUMN)\nconst maxWidthOf = (col: number) => (col < 0 ? 480 * rowLevelCount.value : MAX_COLUMN)\n\nfunction setWidth(col: number, width: number) {\n const w = Math.round(Math.min(Math.max(width, minWidthOf(col)), maxWidthOf(col)))\n if (col < 0) {\n rowHeadDragged.value = w\n return\n }\n const next = new Map(dragged.value)\n next.set(colKey(colLines.value[col]!), w)\n dragged.value = next\n}\n\n/** Dragging the edge of a column header (or of the corner, for the row headers). */\nfunction onResizeDown(event: PointerEvent) {\n const handle = (event.target as HTMLElement).closest<HTMLElement>('[data-resize]')\n if (!handle || event.button !== 0) return\n event.preventDefault()\n event.stopPropagation()\n const col = Number(handle.dataset.resize)\n const startX = event.clientX\n const from = widthOf(col)\n let moved = false\n handle.setPointerCapture?.(event.pointerId)\n const onMove = (e: PointerEvent) => {\n const dx = e.clientX - startX\n if (!moved && Math.abs(dx) < 2) return\n moved = true\n setWidth(col, from + dx)\n }\n const onUp = () => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n window.removeEventListener('pointercancel', onUp)\n if (moved) {\n // the click that follows the drag is not a sort\n justResized = true\n setTimeout(() => (justResized = false))\n }\n }\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n window.addEventListener('pointercancel', onUp)\n}\n\nconst measurer = ref<HTMLElement>()\n/** The widest of some texts in the table's font, measured once by the browser. */\nfunction widest(texts: string[]) {\n const el = measurer.value\n if (!el) return 0\n // the longest few by length; measuring every text would cost a layout each\n // oxlint-disable-next-line unicorn/no-array-sort -- sorts a fresh array\n const top = [...new Set(texts)].sort((a, b) => b.length - a.length).slice(0, 12)\n let max = 0\n for (const text of top) {\n el.textContent = text\n max = Math.max(max, el.getBoundingClientRect().width)\n }\n el.textContent = ''\n return Math.ceil(max)\n}\n\n/** Double-clicking a column's edge fits it to its numbers and its header; the corner's goes back to its width. */\nfunction onResizeFit(event: MouseEvent) {\n const handle = (event.target as HTMLElement).closest<HTMLElement>('[data-resize]')\n if (!handle) return\n event.stopPropagation()\n fitWidth(Number(handle.dataset.resize))\n}\n\nfunction fitWidth(col: number) {\n if (col < 0) {\n rowHeadDragged.value = 0\n return\n }\n const column = colLines.value[col]!\n const display = valueDisplay.value\n const res = result.value\n const lines = allLines.value\n const texts: string[] = []\n const limit = Math.min(lines.length, 5000)\n for (let i = 0; i < limit; i++) {\n const line = lines[i]!\n const v = line.value >= 0 ? line.value : Math.max(0, column.value)\n texts.push(display[v]!.write(rowBlank(line) ? Number.NaN : res.get(line.node, column.node, v)))\n }\n const head = headCells.value.find((c) => c.resize === col)\n const textWidth = widest(texts)\n const headWidthNeeded = head ? widest([head.text]) + (head.sorted ? 16 : 0) : 0\n const next = new Map(dragged.value)\n next.set(\n colKey(column),\n Math.min(MAX_COLUMN, Math.max(MIN_COLUMN, Math.max(textWidth, headWidthNeeded) + 26)),\n )\n dragged.value = next\n}\n\n/** The keys on a focused edge: the arrows resize it (Shift for bigger steps), Enter fits it. */\nfunction onResizeKeydown(event: KeyboardEvent) {\n const handle = (event.target as HTMLElement).closest<HTMLElement>('[data-resize]')\n if (!handle || event.key === 'Tab') return\n // the table's own keys stay off while an edge has the focus\n event.stopPropagation()\n const col = Number(handle.dataset.resize)\n const step = event.shiftKey ? 32 : 8\n if (event.key === 'ArrowLeft') setWidth(col, widthOf(col) - step)\n else if (event.key === 'ArrowRight') setWidth(col, widthOf(col) + step)\n else if (event.key === 'Enter') fitWidth(col)\n else return\n event.preventDefault()\n}\n\n/** One edge takes Tab: that of the active cell's column, or the row headers'. */\nconst resizeStop = computed(() => {\n const col = active.value?.col ?? -1\n return col >= 0 && col < colLines.value.length ? col : -1\n})\n\n// ---- pointer and keys ----\n\nconst active = shallowRef<{ row: number; col: number } | null>(null)\nconst focused = ref(false)\n/** Where a range of cells starts; the active cell is its other corner. */\nconst anchor = shallowRef<{ row: number; col: number } | null>(null)\n/** The selected range, rows and columns from first to last (column -1 is the row headers); null for one cell. */\nconst selection = computed(() => {\n const a = anchor.value\n const b = active.value\n if (!a || !b || (a.row === b.row && a.col === b.col)) return null\n return {\n top: Math.min(a.row, b.row),\n bottom: Math.max(a.row, b.row),\n left: Math.min(a.col, b.col),\n right: Math.max(a.col, b.col),\n }\n})\n/** What a screen reader reads out: a range picked, cells copied, a group opened. */\nconst announcement = ref('')\nlet announceTimer: ReturnType<typeof setTimeout> | undefined\nfunction announce(text: string, delay = 0) {\n clearTimeout(announceTimer)\n // cleared first, so the same words twice are read twice\n announcement.value = ''\n announceTimer = setTimeout(() => (announcement.value = text), delay || 50)\n}\n// read out once the range stops growing, not on every step\nwatch(selection, (sel) => {\n if (!sel) return\n announce(\n format(messages.value.selected, {\n rows: sel.bottom - sel.top + 1,\n columns: sel.right - sel.left + 1,\n }),\n 400,\n )\n})\nonBeforeUnmount(() => clearTimeout(announceTimer))\n\n/** The selected columns of a row, as `left:right`; empty when the row is not in the range. */\nconst selectedIn = (row: number) => {\n const sel = selection.value\n return sel && row >= sel.top && row <= sel.bottom ? `${sel.left}:${sel.right}` : ''\n}\nconst allLines = computed(() => [...bodyLines.value, ...footLines.value])\n\n/** The highlighted groups' nodes, -1 when there is none (or its path matches no group). */\nconst highlightRow = computed(() => {\n const path = props.highlight?.row\n return path?.length ? result.value.rows.find(path) || -1 : -1\n})\nconst highlightCol = computed(() => {\n const path = props.highlight?.column\n return path?.length ? result.value.columns.find(path) || -1 : -1\n})\n\nconst cellId = (row: number, col: number) => `${uid}-${row}-${col}`\nconst activeId = computed(() => {\n const a = active.value\n if (!a || !focused.value) return undefined\n return cellId(a.row, a.col)\n})\n\nfunction cellEvent(row: PivotLine, col: PivotLine): PivotCellEvent<Row> {\n const res = result.value\n const src = source.value\n const valueIndex = row.value >= 0 ? row.value : Math.max(0, col.value)\n const indices = () => res.indices(row.node, col.node)\n return {\n row: row.kind === 'total' ? [] : res.rows.path(row.node),\n column: col.kind === 'total' ? [] : res.columns.path(col.node),\n labels: {\n row: row.kind === 'total' ? [] : pathTexts(res.rows, rowWriters.value, row.node),\n column: col.kind === 'total' ? [] : pathTexts(res.columns, colWriters.value, col.node),\n },\n valueIndex,\n value: rowBlank(row)\n ? Number.NaN\n : res.shown(row.node, col.node, valueIndex, valueDisplay.value[valueIndex]?.show ?? null),\n records: () => indices().map((i) => src.record(i) as Row),\n indices,\n }\n}\n\n/** Set while a drag (or a Shift+click) picks a range, so the click that ends it opens nothing. */\nlet swept = false\n\n/** Pressing on a cell and dragging picks a range; Shift+click grows it. Touch scrolls instead. */\nfunction onPointerDown(event: PointerEvent) {\n if (event.button !== 0 || event.pointerType === 'touch') return\n const target = event.target as HTMLElement\n if (target.closest('[data-resize], [data-head], [data-toggle-node], [data-sort-field]')) return\n const el = target.closest<HTMLElement>('[data-row]')\n const view = viewport.value\n if (!el || !view) return\n // no text selection while dragging; the table takes the focus itself\n event.preventDefault()\n view.focus({ preventScroll: true })\n const start = { row: Number(el.dataset.row), col: Number(el.dataset.col) }\n if (event.shiftKey) {\n anchor.value ??= active.value ?? start\n active.value = start\n swept = true\n setTimeout(() => (swept = false))\n return\n }\n anchor.value = null\n const onMove = (e: PointerEvent) => {\n // near an edge the table scrolls on\n const box = view.getBoundingClientRect()\n if (e.clientY > box.bottom - 24) view.scrollTop += 16\n else if (e.clientY < box.top + headHeight.value + 8) view.scrollTop -= 16\n if (e.clientX > box.right - 24) view.scrollLeft += 16\n else if (e.clientX < box.left + headWidth.value + 8 && start.col >= 0) view.scrollLeft -= 16\n const hit = document.elementFromPoint(e.clientX, e.clientY)?.closest<HTMLElement>('[data-row]')\n if (!hit || !view.contains(hit)) return\n const at = { row: Number(hit.dataset.row), col: Number(hit.dataset.col) }\n if (!swept && at.row === start.row && at.col === start.col) return\n swept = true\n anchor.value = start\n if (active.value?.row !== at.row || active.value?.col !== at.col) active.value = at\n }\n const onUp = () => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n window.removeEventListener('pointercancel', onUp)\n setTimeout(() => (swept = false))\n }\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n window.addEventListener('pointercancel', onUp)\n}\n\nfunction onClick(event: MouseEvent) {\n const target = event.target as HTMLElement\n if (target.closest('[data-resize]') || justResized || swept) return\n const sortField = target.closest<HTMLElement>('[data-sort-field]')\n if (sortField) return sortByField(Number(sortField.dataset.sortField))\n const head = target.closest<HTMLElement>('[data-head]')\n if (head) {\n const cell = headCells.value.find((c) => c.key === head.dataset.head)\n if (!cell) return\n if (cell.toggle && (target.closest('[data-toggle]') || !cell.sortable))\n return toggleNode('columns', cell.span.node, event.altKey)\n if (cell.sortable) sortByColumn(cell.span)\n return\n }\n const el = target.closest<HTMLElement>('[data-row]')\n if (!el) return\n const row = Number(el.dataset.row)\n const col = Number(el.dataset.col)\n active.value = { row, col }\n anchor.value = null\n const line = allLines.value[row]\n if (!line) return\n if (col < 0) {\n const part = target.closest<HTMLElement>('[data-toggle-node]')\n if (part) toggleNode('rows', Number(part.dataset.toggleNode), event.altKey)\n else if (lineToggles(line)) toggleNode('rows', line.node, event.altKey)\n return\n }\n const column = colLines.value[col]\n if (column) emit('cellClick', cellEvent(line, column))\n}\n\nfunction ensureVisible(row: number, col: number) {\n const el = viewport.value\n if (!el) return\n const h = rowHeight.value\n if (row < bodyLines.value.length) {\n const space = viewHeight.value - headHeight.value - footHeight.value\n if (row * h < el.scrollTop) el.scrollTop = row * h\n else if ((row + 1) * h > el.scrollTop + space) el.scrollTop = (row + 1) * h - space\n }\n if (col >= 0) {\n const starts = colStarts.value\n const space = viewWidth.value - headWidth.value\n if (starts[col]! < el.scrollLeft) el.scrollLeft = starts[col]!\n else if (starts[col + 1]! > el.scrollLeft + space) el.scrollLeft = starts[col + 1]! - space\n }\n onScroll()\n}\n\n/** Moves the active cell; `extend` (Shift) grows the range from where it started instead. */\nfunction moveTo(row: number, col: number, extend = false) {\n const rows = allLines.value.length\n const cols = colLines.value.length\n if (rows === 0) return\n const next = {\n row: Math.max(0, Math.min(rows - 1, row)),\n col: Math.max(-1, Math.min(cols - 1, col)),\n }\n if (extend) anchor.value ??= active.value ?? next\n else anchor.value = null\n active.value = next\n ensureVisible(next.row, next.col)\n}\n\n/** The index of the first line of `node`'s parent above `row`. */\nfunction parentRow(row: number) {\n const lines = allLines.value\n const tree = rowTree.value\n const parent = tree.parent[lines[row]!.node]!\n if (parent <= 0) return row\n for (let i = row - 1; i >= 0; i--) {\n if (lines[i]!.node === parent) {\n let first = i\n while (first > 0 && lines[first - 1]!.node === parent) first--\n return first\n }\n }\n // in the tabular layout a group's own line is its total, after its children\n for (let i = row + 1; i < lines.length; i++) if (lines[i]!.node === parent) return i\n return row\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.isComposing) return\n const a = active.value ?? { row: 0, col: -1 }\n const line = allLines.value[a.row]\n const isGroup = !!line && lineToggles(line)\n const open = isGroup && !rowCollapsed.value.has(line!.node)\n const page = Math.max(1, Math.floor((viewHeight.value - headHeight.value) / rowHeight.value) - 1)\n const mod = event.ctrlKey || event.metaKey\n const shift = event.shiftKey\n if (mod && !shift && !event.altKey && event.key.toLowerCase() === 'a') {\n selectAll()\n event.preventDefault()\n return\n }\n switch (event.key) {\n case 'ArrowDown':\n moveTo(a.row + 1, a.col, shift)\n break\n case 'ArrowUp':\n moveTo(a.row - 1, a.col, shift)\n break\n case 'ArrowRight':\n if (a.col < 0 && isGroup && !open && !shift) toggleNode('rows', line!.node)\n else moveTo(a.row, a.col + 1, shift)\n break\n case 'ArrowLeft':\n if (shift) moveTo(a.row, a.col - 1, true)\n else if (a.col < 0 && open) toggleNode('rows', line!.node)\n else if (a.col < 0 && line) moveTo(parentRow(a.row), -1)\n else moveTo(a.row, a.col - 1)\n break\n case 'PageDown':\n moveTo(a.row + page, a.col, shift)\n break\n case 'PageUp':\n moveTo(a.row - page, a.col, shift)\n break\n case 'Home':\n moveTo(mod ? 0 : a.row, -1, shift)\n break\n case 'End':\n moveTo(mod ? allLines.value.length - 1 : a.row, colLines.value.length - 1, shift)\n break\n case 'Escape':\n if (!anchor.value) return\n anchor.value = null\n break\n case 'Enter':\n case ' ':\n if (!line) return\n if (a.col < 0) {\n if (isGroup) toggleNode('rows', line.node, event.altKey)\n } else if (event.key === 'Enter') {\n const column = colLines.value[a.col]\n if (column) emit('cellClick', cellEvent(line, column))\n }\n break\n default:\n return\n }\n event.preventDefault()\n}\n\nfunction onFocus() {\n focused.value = true\n if (!active.value && allLines.value.length) active.value = { row: 0, col: -1 }\n}\n\n// The active cell's row and column by their groups, so that it stays on the\n// same groups when the data changes and lines come and go.\nconst rowKey = (line: PivotLine | undefined) =>\n line\n ? `${line.kind}|${line.value}|${line.kind === 'total' ? '' : JSON.stringify(result.value.rows.path(line.node))}`\n : ''\nlet activeKeys: { row: string; col: string } | null = null\nwatch(\n active,\n (a) => {\n activeKeys = a\n ? { row: rowKey(allLines.value[a.row]), col: a.col < 0 ? '' : colKey(colLines.value[a.col]!) }\n : null\n },\n { flush: 'sync' },\n)\nwatch([allLines, colLines], ([rows, cols]) => {\n const a = active.value\n const keys = activeKeys\n if (!a || !keys) return\n // most changes leave it where it was; look further only when they don't\n let row =\n rowKey(rows[a.row]) === keys.row ? a.row : rows.findIndex((line) => rowKey(line) === keys.row)\n if (row < 0) row = Math.min(a.row, rows.length - 1)\n let col = !keys.col\n ? -1\n : a.col >= 0 && cols[a.col] && colKey(cols[a.col]!) === keys.col\n ? a.col\n : cols.findIndex((line) => colKey(line) === keys.col)\n if (col < 0 && keys.col) col = Math.min(a.col, cols.length - 1)\n if (row < 0) active.value = null\n else if (row !== a.row || col !== a.col) {\n active.value = { row, col }\n anchor.value = null\n // it moved with its groups: bring it into view where the lines now put it\n nextTick(() => ensureVisible(row, col))\n }\n})\n\n// back to the top left when the layout changes\nwatch(engineConfig, () => {\n nextTick(() => {\n const el = viewport.value\n if (!el) return\n el.scrollTop = 0\n el.scrollLeft = 0\n onScroll()\n })\n})\n\n// ---- the table as cells: copying, CSV, a sheet, a chart and printing ----\n\n/** The column headers for export, which always name the values when they run along the columns. */\nconst exportSpans = computed(() =>\n headerSpans(\n result.value.columns,\n colLines.value,\n result.value.columns.levels.length === 0 || !valuesOnRows.value,\n ),\n)\n\ninterface GridRange {\n top: number\n bottom: number\n left: number\n right: number\n}\n\n/** A row's labels, one per row field: the group on its own line, as the table shows it. */\nfunction rowLabels(line: PivotLine, index: number, count: number) {\n const texts: string[] = Array.from({ length: count }, () => '')\n if (line.kind === 'total') texts[0] = messages.value.total\n else if (isFirstOfNode(line)) {\n const head = rowHead(line, index)\n if (tabular.value) head.parts.forEach((part, level) => part && (texts[level] = part.text))\n else texts[head.depth] = head.text\n }\n return texts\n}\n\n/**\n * Cells of the table: rows `top` to `bottom`, columns `left` to `right`\n * (`-1` takes the row headers), with the column headers when `heads`.\n */\nfunction gridOf(range: GridRange, heads: boolean): PivotGrid {\n const res = result.value\n const display = valueDisplay.value\n const levels = Math.max(1, res.rows.levels.length)\n const withLeft = range.left < 0\n const headCols = withLeft ? levels + (valuesOnRows.value ? 1 : 0) : 0\n const from = Math.max(0, range.left)\n const to = range.right\n const width = headCols + Math.max(0, to - from + 1)\n const cells: (PivotGridCell | null)[][] = []\n const headRowCount = heads ? res.columns.levels.length + 1 : 0\n for (let r = 0; r < headRowCount; r++)\n cells.push(Array.from({ length: width }, (): PivotGridCell => ({ text: '', kind: 'head' })))\n if (heads && withLeft) {\n columnFields.value.forEach((label, level) => (cells[level]![0] = { text: label, kind: 'head' }))\n const last = cells[headRowCount - 1]!\n for (const field of rowFields.value) last[field.index] = { text: field.label, kind: 'head' }\n if (valuesOnRows.value) last[levels] = { text: messages.value.values, kind: 'head' }\n }\n if (heads) {\n for (const list of exportSpans.value) {\n for (const span of list) {\n const a = Math.max(span.from, from)\n const b = Math.min(span.to - 1, to)\n if (a > b) continue\n const col = headCols + a - from\n const cell: PivotGridCell = { text: spanText(span), kind: 'head' }\n const line = colLines.value[span.from]!\n if (span.kind === 'total' || span.kind === 'subtotal' || line.kind !== 'group')\n cell.total = true\n if (b > a) cell.colSpan = b - a + 1\n if (span.rows > 1) cell.rowSpan = span.rows\n for (let r = span.level; r < span.level + span.rows; r++)\n for (let c = col; c <= col + b - a; c++) cells[r]![c] = null\n cells[span.level]![col] = cell\n }\n }\n }\n const lines = allLines.value\n for (let i = range.top; i <= range.bottom; i++) {\n const line = lines[i]\n if (!line) continue\n const out: (PivotGridCell | null)[] = []\n // a group's own line holds its total\n const lineTotal = line.kind !== 'group' || (line.node > 0 && res.rows.isGroup(line.node))\n const mark = lineTotal ? { total: true } : {}\n if (withLeft) {\n for (const text of rowLabels(line, i, levels)) out.push({ text, kind: 'label', ...mark })\n if (valuesOnRows.value)\n out.push({\n text: line.value >= 0 ? display[line.value]!.label : '',\n kind: 'label',\n ...mark,\n })\n }\n const blank = rowBlank(line)\n for (let c = from; c <= to; c++) {\n const col = colLines.value[c]!\n const v = line.value >= 0 ? line.value : Math.max(0, col.value)\n const n = blank ? Number.NaN : res.shown(line.node, col.node, v, display[v]!.show)\n const total =\n lineTotal || col.kind !== 'group' || (col.node > 0 && res.columns.isGroup(col.node))\n out.push({\n text: display[v]!.write(n),\n kind: 'value',\n value: n,\n valueIndex: v,\n ...(total ? { total: true } : {}),\n })\n }\n cells.push(out)\n }\n const widths: number[] = []\n if (withLeft) {\n const own = tabular.value\n ? levelWidth.value\n : levels === 1\n ? rowHeadWidth.value\n : Math.max(80, Math.round(props.rowHeaderWidth * 0.6))\n for (let l = 0; l < levels; l++) widths.push(own)\n if (valuesOnRows.value) widths.push(VALUE_HEADER_WIDTH)\n }\n const starts = colStarts.value\n for (let c = from; c <= to; c++) widths.push(starts[c + 1]! - starts[c]!)\n return {\n cells,\n headRows: headRowCount,\n headCols,\n formats: display.map((d) => d.sheetFormat),\n widths,\n }\n}\n\nconst wholeRange = (): GridRange => ({\n top: 0,\n bottom: allLines.value.length - 1,\n left: -1,\n right: colLines.value.length - 1,\n})\n\n/** The whole table, headers and all, as cells. */\nconst toGrid = () => gridOf(wholeRange(), true)\n\n/**\n * What copying takes: the selected range, or the active cell. A range over\n * the whole table brings the column headers along.\n */\nfunction copyGrid(all = false): PivotGrid | null {\n if (all) return toGrid()\n const range: GridRange | null =\n selection.value ??\n (active.value\n ? {\n top: active.value.row,\n bottom: active.value.row,\n left: active.value.col,\n right: active.value.col,\n }\n : null)\n if (!range) return null\n const whole = wholeRange()\n const isWhole =\n range.top === 0 &&\n range.bottom === whole.bottom &&\n range.left === -1 &&\n range.right === whole.right\n return gridOf(range, isWhole)\n}\n\n/** Selects every cell, the row headers too (Ctrl / ⌘ + A). */\nfunction selectAll() {\n const whole = wholeRange()\n if (whole.bottom < 0) return\n anchor.value = { row: 0, col: -1 }\n active.value = { row: whole.bottom, col: whole.right }\n}\n\n/** Copying puts tab-separated text and a table on the clipboard; pasted into DouSheet, numbers keep their formats. */\nfunction onCopy(event: ClipboardEvent) {\n const grid = copyGrid()\n if (!grid || !event.clipboardData) return\n event.preventDefault()\n event.clipboardData.setData('text/plain', gridToTSV(grid))\n event.clipboardData.setData('text/html', gridToHTML(grid, { sheet: true }))\n announceCopied(grid)\n}\n\nfunction announceCopied(grid: PivotGrid) {\n let cells = 0\n for (const row of grid.cells) for (const cell of row) if (cell) cells++\n announce(format(messages.value.copied, { cells }))\n}\n\nasync function copy(options: PivotCopyOptions = {}) {\n const grid = copyGrid(options.all)\n if (!grid) return\n const text = gridToTSV(grid)\n const html = gridToHTML(grid, { sheet: true })\n const clipboard = navigator.clipboard\n if (typeof ClipboardItem !== 'undefined' && clipboard?.write) {\n await clipboard.write([\n new ClipboardItem({\n 'text/plain': new Blob([text], { type: 'text/plain' }),\n 'text/html': new Blob([html], { type: 'text/html' }),\n }),\n ])\n } else await clipboard.writeText(text)\n announceCopied(grid)\n}\n\nconst toCSV = (options?: PivotCSVOptions) => gridToCSV(toGrid(), options)\n\nfunction toSheet(options: { name?: string } = {}): PivotSheetWorkbook {\n const grid = toGrid()\n const colSizes: Record<number, number> = {}\n grid.widths.forEach((w, i) => (colSizes[i] = w))\n return {\n version: 1,\n sheets: [\n {\n name: options.name ?? messages.value.pivot,\n cells: gridToSheetCells(grid),\n merges: gridMerges(grid),\n freeze: { rows: grid.headRows, cols: grid.headCols },\n colSizes,\n },\n ],\n styles: structuredClone(SHEET_STYLES),\n }\n}\n\n/**\n * Rows for a chart: a row per group on show that is not open (its children\n * would be the rows instead), a series per column the same way; the\n * subtotals and totals are left out.\n */\nfunction toChartRows(options: PivotChartRowsOptions = {}): PivotChartRows {\n const res = result.value\n const display = valueDisplay.value\n const { valueIndex } = options\n const many = display.length > 1\n const series = colLines.value\n .map((line, col) => ({ line, col }))\n .filter(({ line }) =>\n res.columns.levels.length === 0 ? line.kind === 'total' : line.kind === 'group',\n )\n .filter(({ line }) => valueIndex === undefined || line.value < 0 || line.value === valueIndex)\n .map(({ line }, i) => {\n const v = line.value >= 0 ? line.value : (valueIndex ?? 0)\n const group = line.kind === 'total' ? '' : pathText(res.columns, colWriters.value, line.node)\n const value = display[v]!.label\n const name = group ? (many && !valuesOnRows.value ? join([group, value]) : group) : value\n return { key: `s${i}`, name, valueIndex: v, node: line.node, format: display[v]!.write }\n })\n const lines = res.rows.levels.length === 0 ? footLines.value : bodyLines.value\n const rows: Record<string, string | number | null>[] = []\n for (const line of lines) {\n if (res.rows.levels.length > 0) {\n if (line.kind !== 'group') continue\n if (res.rows.isGroup(line.node) && !rowCollapsed.value.has(line.node)) continue\n }\n if (valuesOnRows.value && line.value !== (valueIndex ?? 0)) continue\n const row: Record<string, string | number | null> = {\n label:\n line.kind === 'total'\n ? messages.value.total\n : pathText(res.rows, rowWriters.value, line.node),\n }\n for (const s of series) {\n const v = valuesOnRows.value ? line.value : s.valueIndex\n const n = res.shown(line.node, s.node, v, display[v]!.show)\n row[s.key] = n === n ? n : null\n }\n rows.push(row)\n }\n return {\n x: 'label',\n rows,\n series: series.map(({ key, name, valueIndex: v, format: write }) => {\n const at = valuesOnRows.value ? (valueIndex ?? 0) : v\n return { key, name, valueIndex: at, format: valuesOnRows.value ? display[at]!.write : write }\n }),\n }\n}\n\nconst join = (texts: string[]) => texts.join(' · ')\n/** A group's labels from the outermost in, as one text. */\nfunction pathTexts(tree: PivotTree, writers: ((v: unknown) => string)[], node: number) {\n const texts: string[] = []\n for (let at = node; at > 0; at = tree.parent[at]!) texts.unshift(nodeText(tree, writers, at))\n return texts\n}\nconst pathText = (tree: PivotTree, writers: ((v: unknown) => string)[], node: number) =>\n join(pathTexts(tree, writers, node))\nconst escape = (text: string) =>\n text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n\n/** A4 less 10mm margins, in px at 96 per inch. */\nconst PAGE_WIDTH = { portrait: 718, landscape: 1047 }\n\nfunction print(options: PivotPrintOptions = {}) {\n const grid = toGrid()\n const orientation =\n options.orientation ??\n (grid.widths.reduce((a, b) => a + b, 0) > PAGE_WIDTH.portrait ? 'landscape' : 'portrait')\n const title = options.title ?? ariaLabel.value\n const iframe = document.createElement('iframe')\n iframe.setAttribute('aria-hidden', 'true')\n iframe.style.cssText = 'position:fixed;width:0;height:0;border:0;visibility:hidden'\n document.body.append(iframe)\n const doc = iframe.contentDocument!\n const font = root.value ? getComputedStyle(root.value).fontFamily : 'sans-serif'\n doc.open()\n doc.write(\n `<!doctype html><html><head><meta charset=\"utf-8\"><title>${escape(title || document.title)}</title><style>` +\n `@page{size:A4 ${orientation};margin:10mm}` +\n `html,body{margin:0;color:#1f1f1f;font:10px/1.4 ${font};font-variant-numeric:tabular-nums}` +\n `h1{margin:0 0 8px;font-size:13px;font-weight:600}` +\n `table{border-collapse:collapse;width:100%}` +\n `thead{display:table-header-group}tr{break-inside:avoid}` +\n `th,td{border:1px solid #d6d6d6;padding:3px 6px;white-space:nowrap}` +\n `th{background:#f5f5f5;font-weight:500;text-align:left}` +\n `tbody th{background:none}.is-total{font-weight:600}` +\n `thead th.is-end{text-align:right}` +\n `*{print-color-adjust:exact;-webkit-print-color-adjust:exact}` +\n `</style></head><body>${title ? `<h1>${escape(title)}</h1>` : ''}${gridToHTML(grid)}</body></html>`,\n )\n doc.close()\n const win = iframe.contentWindow!\n const done = () => iframe.remove()\n win.addEventListener('afterprint', done)\n // browsers that print without a dialog, or never send afterprint\n setTimeout(done, 60_000)\n win.focus()\n win.print()\n}\n\nconst ariaLabel = computed(() => props.ariaLabel ?? messages.value.pivot)\nconst rootStyle = computed(() => {\n const height = typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight\n // a short table ends with its last row instead of leaving blank space under it\n const content = headHeight.value + bodyHeight.value + footHeight.value + gutter.value + 2\n return `height:min(${height}, ${content}px);--dou-pivot-row-height:${rowHeight.value}px;--dou-pivot-head-width:${headWidth.value}px`\n})\n\ndefineExpose<PivotExpose>({\n get result() {\n return result.value\n },\n expandAll,\n collapseAll,\n toggle,\n toGrid,\n toCSV,\n toSheet,\n toChartRows,\n copy,\n print,\n selectAll,\n})\n</script>\n\n<template>\n <div\n ref=\"root\"\n class=\"dou-pivot\"\n :class=\"[\n `dou-pivot--${size}`,\n {\n 'is-focused': focused,\n 'is-scrolled-x': scroll.left > 0,\n 'is-scrolled-y': scroll.top > 0,\n 'has-values-column': valuesOnRows,\n 'is-tabular': tabular,\n 'is-busy': busy,\n },\n ]\"\n :style=\"rootStyle\"\n >\n <div\n ref=\"viewport\"\n class=\"dou-pivot__viewport\"\n role=\"treegrid\"\n tabindex=\"0\"\n :aria-label=\"ariaLabel\"\n :aria-rowcount=\"headRows + allLines.length\"\n :aria-colcount=\"colLines.length + (valuesOnRows ? 2 : 1)\"\n aria-multiselectable=\"true\"\n :aria-activedescendant=\"activeId\"\n :aria-busy=\"busy || undefined\"\n @scroll=\"onScroll\"\n @pointerdown=\"onPointerDown\"\n @click=\"onClick\"\n @copy=\"onCopy\"\n @keydown=\"onKeydown\"\n @focus=\"onFocus\"\n @blur=\"focused = false\"\n >\n <div class=\"dou-pivot__sheet\" :style=\"`width:${totalWidth}px`\">\n <div class=\"dou-pivot__head\" role=\"rowgroup\" :style=\"`height:${headHeight}px`\">\n <div class=\"dou-pivot__corner\" :style=\"`width:${headWidth}px;height:${headHeight}px`\">\n <div\n v-for=\"(label, level) in columnFields\"\n :key=\"`c${level}`\"\n class=\"dou-pivot__corner-line is-column\"\n :style=\"`top:${level * rowHeight}px`\"\n >\n <span class=\"dou-pivot__corner-label\">{{ label }}</span>\n </div>\n <div\n class=\"dou-pivot__corner-line is-rows\"\n :style=\"`top:${(headRows - 1) * rowHeight}px`\"\n >\n <template v-for=\"field in rowFields\" :key=\"field.index\">\n <span\n v-if=\"field.index > 0 && !tabular\"\n class=\"dou-pivot__corner-sep\"\n aria-hidden=\"true\"\n >/</span\n >\n <span\n :class=\"\n tabular\n ? [\n 'dou-pivot__corner-field',\n { 'is-last': field.index === rowFields.length - 1 },\n ]\n : 'dou-pivot__corner-inline'\n \"\n :style=\"tabular ? `width:${levelWidth}px` : undefined\"\n >\n <button\n type=\"button\"\n class=\"dou-pivot__field\"\n :class=\"{ 'is-sorted': !config.sort && field.sort === 'desc' }\"\n tabindex=\"-1\"\n :data-sort-field=\"field.index\"\n :aria-label=\"format(messages.sortField, { field: field.label })\"\n >\n {{ field.label }}\n <ArrowDownIcon\n v-if=\"!config.sort && field.sort === 'desc'\"\n aria-hidden=\"true\"\n />\n </button>\n </span>\n </template>\n <span v-if=\"valuesOnRows\" class=\"dou-pivot__corner-values\">{{\n messages.values\n }}</span>\n <span v-else-if=\"!valueRow\" class=\"dou-pivot__corner-values\">{{\n valueDisplay[0]!.label\n }}</span>\n </div>\n <span\n v-if=\"resizable\"\n class=\"dou-pivot__resize\"\n data-resize=\"-1\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n :aria-label=\"format(messages.columnWidth, { column: rowFieldNames })\"\n :aria-valuenow=\"widthOf(-1)\"\n :aria-valuemin=\"minWidthOf(-1)\"\n :aria-valuemax=\"maxWidthOf(-1)\"\n :tabindex=\"resizeStop === -1 ? 0 : -1\"\n :title=\"messages.resizeColumn\"\n @pointerdown=\"onResizeDown\"\n @dblclick=\"onResizeFit\"\n @keydown=\"onResizeKeydown\"\n />\n </div>\n <div\n class=\"dou-pivot__col-heads\"\n :style=\"`width:${columnsWidth}px;height:${headHeight}px`\"\n >\n <div\n v-for=\"cell in headCells\"\n :key=\"cell.key\"\n :class=\"cell.cls\"\n role=\"columnheader\"\n :aria-sort=\"\n cell.sorted ? (cell.sorted === 'asc' ? 'ascending' : 'descending') : undefined\n \"\n :aria-expanded=\"cell.toggle ? cell.open : undefined\"\n :data-head=\"cell.key\"\n :title=\"cell.sortable ? messages.sortValue : undefined\"\n :style=\"cell.style\"\n >\n <span class=\"dou-pivot__col-label\">\n <span\n v-if=\"cell.toggle\"\n class=\"dou-pivot__toggle\"\n :class=\"{ 'is-open': cell.open }\"\n data-toggle\n :aria-label=\"cell.open ? messages.collapse : messages.expand\"\n >\n <ChevronRightIcon aria-hidden=\"true\" />\n </span>\n <span class=\"dou-pivot__text\">{{ cell.text }}</span>\n <ArrowUpIcon\n v-if=\"cell.sorted === 'asc'\"\n class=\"dou-pivot__sort\"\n aria-hidden=\"true\"\n />\n <ArrowDownIcon\n v-else-if=\"cell.sorted === 'desc'\"\n class=\"dou-pivot__sort\"\n aria-hidden=\"true\"\n />\n </span>\n <span\n v-if=\"cell.resize >= 0\"\n class=\"dou-pivot__resize\"\n :data-resize=\"cell.resize\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n :aria-label=\"format(messages.columnWidth, { column: cell.text })\"\n :aria-valuenow=\"widthOf(cell.resize)\"\n :aria-valuemin=\"MIN_COLUMN\"\n :aria-valuemax=\"MAX_COLUMN\"\n :tabindex=\"resizeStop === cell.resize ? 0 : -1\"\n :title=\"messages.resizeColumn\"\n @pointerdown=\"onResizeDown\"\n @dblclick=\"onResizeFit\"\n @keydown=\"onResizeKeydown\"\n />\n </div>\n </div>\n </div>\n\n <div class=\"dou-pivot__body\" role=\"rowgroup\" :style=\"`height:${bodyHeight}px`\">\n <div\n v-for=\"{ line, index } in visibleRows\"\n :key=\"index\"\n v-memo=\"[\n line,\n colWindow,\n colLines,\n colStarts,\n rowHeadWidth,\n tabular,\n valueDisplay,\n rowWriters,\n active?.row === index ? active.col : -9,\n selectedIn(index),\n highlightCol,\n line.node === highlightRow,\n ]\"\n class=\"dou-pivot__row\"\n :class=\"{\n 'is-group': lineToggles(line),\n 'is-subtotal': line.kind === 'subtotal',\n 'is-node-start': line.value <= 0,\n 'is-highlighted': line.node === highlightRow,\n }\"\n role=\"row\"\n :aria-rowindex=\"headRows + index + 1\"\n :aria-level=\"rowTree.depth[line.node]\"\n :aria-expanded=\"lineToggles(line) ? !rowCollapsed.has(line.node) : undefined\"\n :style=\"`top:${index * rowHeight}px;width:${totalWidth}px`\"\n >\n <template v-for=\"head in [rowHead(line, index)]\" :key=\"0\">\n <div\n :id=\"cellId(index, -1)\"\n class=\"dou-pivot__row-head\"\n :class=\"{\n 'is-active': active?.row === index && active.col === -1,\n 'is-clickable': head.group,\n 'is-selected': selectedIn(index).startsWith('-1:'),\n }\"\n role=\"rowheader\"\n :aria-selected=\"selectedIn(index).startsWith('-1:') || undefined\"\n :data-row=\"index\"\n data-col=\"-1\"\n :style=\"\n tabular\n ? `width:${rowHeadWidth}px;padding-left:0`\n : `width:${rowHeadWidth}px;padding-left:${12 + head.depth * 16}px`\n \"\n >\n <template v-if=\"tabular\">\n <span\n v-for=\"(part, level) in head.parts\"\n :key=\"level\"\n class=\"dou-pivot__level\"\n :style=\"`width:${levelWidth}px`\"\n >\n <template v-if=\"part\">\n <span\n v-if=\"part.toggle > 0\"\n class=\"dou-pivot__toggle\"\n :class=\"{ 'is-open': part.open }\"\n :data-toggle-node=\"part.toggle\"\n aria-hidden=\"true\"\n >\n <ChevronRightIcon />\n </span>\n <span\n v-else-if=\"level < head.parts.length - 1\"\n class=\"dou-pivot__toggle-space\"\n />\n <span class=\"dou-pivot__text\">{{ part.text }}</span>\n </template>\n </span>\n </template>\n <template v-else-if=\"head.firstOfNode\">\n <span\n v-if=\"head.group\"\n class=\"dou-pivot__toggle\"\n :class=\"{ 'is-open': head.open }\"\n aria-hidden=\"true\"\n >\n <ChevronRightIcon />\n </span>\n <span v-else-if=\"rowTree.levels.length > 1\" class=\"dou-pivot__toggle-space\" />\n <span class=\"dou-pivot__text\">{{ head.text }}</span>\n </template>\n </div>\n <div\n v-if=\"valuesOnRows\"\n class=\"dou-pivot__value-head\"\n role=\"rowheader\"\n :style=\"`width:${VALUE_HEADER_WIDTH}px;left:${rowHeadWidth}px`\"\n >\n <span class=\"dou-pivot__text\">{{ head.valueText }}</span>\n </div>\n </template>\n <div class=\"dou-pivot__spacer\" :style=\"`width:${colStarts[colWindow.from]}px`\" />\n <div\n v-for=\"cell in rowCells(line, index)\"\n :id=\"cellId(index, cell.col)\"\n :key=\"cell.key\"\n :class=\"[cell.cls, { 'is-active': active?.row === index && active.col === cell.col }]\"\n role=\"gridcell\"\n :aria-selected=\"cell.selected || undefined\"\n :aria-colindex=\"cell.col + (valuesOnRows ? 3 : 2)\"\n :data-row=\"index\"\n :data-col=\"cell.col\"\n :style=\"cell.style\"\n >\n <span class=\"dou-pivot__text\">{{ cell.text }}</span>\n </div>\n </div>\n </div>\n\n <div\n v-if=\"footLines.length\"\n class=\"dou-pivot__foot\"\n role=\"rowgroup\"\n :style=\"`height:${footHeight}px`\"\n >\n <div\n v-for=\"({ line, index }, i) in visibleFoot\"\n :key=\"index\"\n class=\"dou-pivot__row is-total\"\n role=\"row\"\n :aria-rowindex=\"headRows + index + 1\"\n :style=\"`top:${i * rowHeight}px;width:${totalWidth}px`\"\n >\n <div\n :id=\"cellId(index, -1)\"\n class=\"dou-pivot__row-head\"\n :class=\"{\n 'is-active': active?.row === index && active.col === -1,\n 'is-selected': selectedIn(index).startsWith('-1:'),\n }\"\n role=\"rowheader\"\n :aria-selected=\"selectedIn(index).startsWith('-1:') || undefined\"\n :data-row=\"index\"\n data-col=\"-1\"\n :style=\"`width:${rowHeadWidth}px`\"\n >\n <span v-if=\"line.value <= 0\" class=\"dou-pivot__text\">{{ messages.total }}</span>\n </div>\n <div\n v-if=\"valuesOnRows\"\n class=\"dou-pivot__value-head\"\n role=\"rowheader\"\n :style=\"`width:${VALUE_HEADER_WIDTH}px;left:${rowHeadWidth}px`\"\n >\n <span class=\"dou-pivot__text\">{{ valueDisplay[line.value]?.label }}</span>\n </div>\n <div class=\"dou-pivot__spacer\" :style=\"`width:${colStarts[colWindow.from]}px`\" />\n <div\n v-for=\"cell in rowCells(line, index)\"\n :id=\"cellId(index, cell.col)\"\n :key=\"cell.key\"\n :class=\"[cell.cls, { 'is-active': active?.row === index && active.col === cell.col }]\"\n role=\"gridcell\"\n :aria-selected=\"cell.selected || undefined\"\n :aria-colindex=\"cell.col + (valuesOnRows ? 3 : 2)\"\n :data-row=\"index\"\n :data-col=\"cell.col\"\n :style=\"cell.style\"\n >\n <span class=\"dou-pivot__text\">{{ cell.text }}</span>\n </div>\n </div>\n </div>\n </div>\n <span ref=\"measurer\" class=\"dou-pivot__measure\" aria-hidden=\"true\" />\n <div\n v-if=\"result.matched === 0 && !busy && result !== shapeOnly\"\n class=\"dou-pivot__empty\"\n role=\"status\"\n >\n {{ messages.noData }}\n </div>\n </div>\n <span class=\"dou-pivot__live\" role=\"status\" aria-live=\"polite\">{{ announcement }}</span>\n <!-- the last result stays under a veil while the next one is summed up -->\n <div v-if=\"busy\" class=\"dou-pivot__veil\" role=\"status\">\n <span class=\"dou-pivot__busy\">{{ messages.busy }}</span>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ @layer dou.components{.dou-pivot-fields{--dou-pivot-fields-well:color-mix(in oklab,var(--dou-color-text)3%,var(--dou-color-bg-surface));box-sizing:border-box;border:1px solid var(--dou-color-border);border-radius:var(--dou-radius-container);background-color:var(--dou-color-bg-surface);color:var(--dou-color-text);font-family:var(--dou-font-family);font-size:var(--dou-font-size-sm);line-height:var(--dou-font-line-height);min-width:0}.dou-pivot-fields.is-in-drawer{background:0 0;border:0;border-radius:0}.dou-pivot-fields__list-part{display:flex;flex-direction:column;gap:6px;padding:8px}.dou-pivot-fields__list.dou-sortable{overflow:auto;overscroll-behavior:contain;scrollbar-width:thin;gap:0;min-height:0;max-height:288px}.dou-pivot-fields__field{display:flex;box-sizing:border-box;border-radius:var(--dou-radius-control);cursor:grab;user-select:none;-webkit-tap-highlight-color:transparent;align-items: center;gap:8px;height:32px;padding:0 8px}.dou-pivot-fields__field:hover{background-color:color-mix(in oklab,var(--dou-color-text)5%,transparent)}.dou-pivot-fields__type{color:var(--dou-color-text-tertiary);flex:none;width:14px;height:14px}.dou-pivot-fields__name,.dou-pivot-fields__chip-text{display:flex;flex-direction:column;flex:1;align-items: flex-start;gap:6px;min-width:0}.dou-pivot-fields__chip-name,.dou-pivot-fields__chip-group{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-box:trim-both cap alphabetic;max-width:100%;margin-block-start:-4px;margin-block-end:-4px;padding-block-start:4px;padding-block-end:4px}.dou-pivot-fields__chip-group{color:var(--dou-color-text-tertiary);font-size:12px}.dou-pivot-fields__none,.dou-pivot-fields__drop{color:var(--dou-color-text-tertiary);text-align:center;margin:0;padding:8px;font-size:12px}.dou-pivot-fields__drop{display:flex;justify-content:center;align-items: center;min-height:28px;padding:4px}.dou-pivot-fields__areas{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));border-top:1px solid var(--dou-color-border-subtle);gap:8px;padding:8px}.is-in-drawer .dou-pivot-fields__areas{padding-inline-start:0;padding-inline-end:0}.dou-pivot-fields__area{display:flex;flex-direction:column;gap:6px;min-width:0}.dou-pivot-fields__area-title{display:flex;color:var(--dou-color-text-secondary);align-items: center;gap:6px;margin:0;padding-inline-start:2px;padding-inline-end:2px;font-size:12px;font-weight:500;line-height:16px}.dou-pivot-fields__area-title svg{color:var(--dou-color-text-tertiary);width:14px;height:14px}.dou-pivot-fields__chips.dou-sortable{display:flex;box-sizing:border-box;border-radius:var(--dou-radius-control);background-color:var(--dou-pivot-fields-well);flex-direction:column;flex:1;gap:4px;min-height:84px;padding:4px}.dou-pivot-fields__chips.dou-sortable>.dou-sortable__empty{border:0;min-height:0}.dou-pivot-fields__chip{display:flex;box-sizing:border-box;border:1px solid var(--dou-color-border);border-radius:var(--dou-radius-control);background-color:var(--dou-color-bg-surface);color:var(--dou-color-text);font-family:var(--dou-font-family);font-size:var(--dou-font-size-sm);cursor:grab;user-select:none;-webkit-tap-highlight-color:transparent;align-items: center;gap:2px;min-height:28px;padding:6px 2px 6px 8px}.dou-pivot-fields__chip-button{display:inline-flex;border-radius:calc(var(--dou-radius-control) - 2px);color:var(--dou-color-text-tertiary);cursor:pointer;background:0 0;border:0;flex:none;justify-content:center;align-items: center;width:22px;height:22px;margin-block-start:-4px;margin-block-end:-4px;padding:0}.dou-pivot-fields__chip-button svg{width:14px;height:14px}.dou-pivot-fields__chip-button:hover{background-color:color-mix(in oklab,var(--dou-color-text)7%,transparent);color:var(--dou-color-text)}.dou-pivot-fields__chip-button[aria-expanded=true]{background-color:color-mix(in oklab,var(--dou-color-text)7%,transparent);color:var(--dou-color-text)}.dou-pivot-fields__chip-button.is-on{color:var(--dou-color-primary-text);background:color-mix(in srgb,var(--dou-color-primary)12%,transparent)}.dou-pivot-fields__chip-button:focus-visible{outline:2px solid var(--dou-color-focus);outline-offset:-2px}@media (pointer:coarse){.dou-pivot-fields__chip{min-height:40px}.dou-pivot-fields__chip-button{width:36px;height:36px;margin-block-start:-10px;margin-block-end:-10px}.dou-pivot-fields__chip-button svg{width:16px;height:16px}}.dou-pivot-fields-trigger{display:flex}.dou-pivot-filter{display:flex;flex-direction:column;gap:6px;margin:-4px}.dou-pivot-filter__all{border-bottom:1px solid var(--dou-color-border-subtle);padding:2px 8px 6px}.dou-pivot-filter__item{display:flex;box-sizing:border-box;align-items: center;gap:8px;height:32px;padding:0 8px}.dou-pivot-filter__item .dou-checkbox{flex:1;min-width:0}.dou-pivot-filter__text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dou-pivot-filter__count{color:var(--dou-color-text-tertiary);font-variant-numeric:tabular-nums;flex:none;font-size:12px}.dou-pivot-filter__none{color:var(--dou-color-text-tertiary);text-align:center;margin:0;padding:16px 8px}.dou-pivot-filter__foot{display:flex;border-top:1px solid var(--dou-color-border-subtle);align-items: center;gap:6px;padding-top:8px}.dou-pivot-filter__picked{color:var(--dou-color-text-tertiary);flex:1;font-size:12px}.dou-pivot-fields__add.dou-button{align-self: flex-start;margin-top:4px}.dou-pivot-formula__fields{display:flex;flex-wrap:wrap;align-items: center;gap:6px}.dou-pivot-formula__fields-title{color:var(--dou-color-text-secondary);font-size:var(--dou-font-size-sm);margin-right:4px}.dou-pivot-top__range{display:grid;grid-template-columns:1fr 1fr;gap:12px}.dou-pivot-top__help{color:var(--dou-color-text-secondary);font-size:var(--dou-font-size-sm);margin:0}.dou-pivot-top__clear.dou-button{margin-right:auto}}@layer dou.components{.dou-pivot{--dou-pivot-line:var(--dou-color-border-subtle);--dou-pivot-line-strong:var(--dou-color-border);--dou-pivot-bg:var(--dou-color-bg-surface);--dou-pivot-head-bg:color-mix(in oklab,var(--dou-color-text)2.5%,var(--dou-pivot-bg));--dou-pivot-total-bg:color-mix(in oklab,var(--dou-color-text)2%,var(--dou-pivot-bg));--dou-pivot-hover-bg:color-mix(in oklab,var(--dou-color-text)3.5%,var(--dou-pivot-bg));--dou-pivot-hover-total-bg:color-mix(in oklab,var(--dou-color-text)5.5%,var(--dou-pivot-bg));--dou-pivot-scroll-shadow:color-mix(in oklab,var(--dou-color-text)14%,transparent);--dou-pivot-ring:var(--dou-color-primary);--dou-pivot-selected:color-mix(in oklab,var(--dou-color-text)6%,transparent);--dou-pivot-highlight:color-mix(in oklab,var(--dou-color-text)4%,transparent);--dou-pivot-scale-strength:28%;--dou-pivot-bar-strength:12%;--dou-pivot-bar-strength-dark:24%;position:relative;box-sizing:border-box;overflow:hidden;border:1px solid var(--dou-pivot-line-strong);border-radius:var(--dou-radius-container);background-color:var(--dou-pivot-bg);color:var(--dou-color-text);font-family:var(--dou-font-family);font-size:var(--dou-font-size-sm);line-height:var(--dou-font-line-height);width:100%;min-width:0}.dou-pivot.is-focused{--dou-pivot-selected:color-mix(in oklab,var(--dou-color-primary)10%,transparent)}.dou-pivot:has(.dou-pivot__viewport:focus-visible){outline:2px solid var(--dou-color-focus);outline-offset:2px}.dou-pivot__viewport{position:absolute;overflow:auto;overscroll-behavior-x:contain;outline:none;scrollbar-width:thin;scrollbar-color:color-mix(in oklab,var(--dou-color-text)22%,transparent)transparent;-webkit-tap-highlight-color:transparent;inset:0}.dou-pivot__sheet{position:relative;min-width:100%}.dou-pivot__text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-box:trim-both cap alphabetic;min-width:0;margin-block-start:-4px;margin-block-end:-4px;padding-block-start:4px;padding-block-end:4px}.dou-pivot__head{position:sticky;z-index:3;display:flex;background-color:var(--dou-pivot-head-bg);box-shadow:inset 0 -1px 0 var(--dou-pivot-line-strong);transition:box-shadow var(--dou-motion-duration-fast)var(--dou-motion-easing);top:0}.is-scrolled-y .dou-pivot__head{box-shadow:inset 0 -1px 0 var(--dou-pivot-line-strong),0 4px 6px -4px var(--dou-pivot-scroll-shadow)}.dou-pivot__corner{position:sticky;z-index:2;box-sizing:border-box;border-right:1px solid var(--dou-pivot-line-strong);border-bottom:1px solid var(--dou-pivot-line-strong);background-color:var(--dou-pivot-head-bg);transition:box-shadow var(--dou-motion-duration-fast)var(--dou-motion-easing);flex:none;left:0}.is-scrolled-x .dou-pivot__corner{box-shadow:4px 0 6px -4px var(--dou-pivot-scroll-shadow)}.dou-pivot__corner-line{position:absolute;display:flex;box-sizing:border-box;height:var(--dou-pivot-row-height);align-items: center;gap:2px;padding:0 8px;left:0;right:0}.dou-pivot__corner-line.is-column{color:var(--dou-color-text-tertiary);justify-content:flex-end;padding-right:12px;font-size:12px}.dou-pivot__corner-line.is-rows{padding-right:12px}.dou-pivot__corner-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-box:trim-both cap alphabetic;margin-block-start:-4px;margin-block-end:-4px;padding-block-start:4px;padding-block-end:4px}.dou-pivot__corner-sep{color:var(--dou-color-text-disabled);font-size:12px}.dou-pivot__corner-values{overflow:hidden;color:var(--dou-color-text-tertiary);text-overflow:ellipsis;white-space:nowrap;min-width:0;margin-left:auto;font-size:12px}.dou-pivot__field{display:inline-flex;border-radius:calc(var(--dou-radius-control) - 2px);color:var(--dou-color-text-secondary);font:inherit;font-weight:var(--dou-font-weight-medium);text-box:trim-both cap alphabetic;cursor:pointer;transition-property:background-color,color;transition-duration:var(--dou-motion-duration-fast);transition-timing-function:var(--dou-motion-easing);background:0 0;border:0;flex:none;align-items: center;gap:2px;height:20px;padding:0 4px}.dou-pivot__field>svg{width:12px;height:12px}.dou-pivot__field:hover{background-color:color-mix(in oklab,var(--dou-color-text)6%,transparent);color:var(--dou-color-text)}.dou-pivot__col-heads{position:relative;flex:none}.dou-pivot__col-head{position:absolute;display:flex;box-sizing:border-box;border-right:1px solid var(--dou-pivot-line);border-bottom:1px solid var(--dou-pivot-line);background-color:var(--dou-pivot-head-bg);color:var(--dou-color-text-secondary);font-weight:var(--dou-font-weight-medium);white-space:nowrap;user-select:none;-webkit-user-select:none;align-items: center;padding:0 12px}.dou-pivot__col-head.is-end{border-bottom-color:var(--dou-pivot-line-strong);justify-content:flex-end}.dou-pivot__col-head.is-value{color:var(--dou-color-text-tertiary);font-size:12px}.dou-pivot__col-head.is-total{background-color:color-mix(in oklab,var(--dou-color-text)2%,var(--dou-pivot-head-bg))}.dou-pivot__col-head.is-subtotal{background-color:color-mix(in oklab,var(--dou-color-text)2%,var(--dou-pivot-head-bg))}.dou-pivot__col-head[title]{cursor:pointer}.dou-pivot__col-head[title]:hover{color:var(--dou-color-text)}.dou-pivot__col-head.is-sorted{color:var(--dou-color-text)}.dou-pivot__col-label{position:sticky;left:calc(var(--dou-pivot-head-width) + 12px);display:inline-flex;align-items: center;gap:4px;min-width:0;max-width:100%}.is-end>.dou-pivot__col-label{left:auto}.dou-pivot__sort{flex:none;width:12px;height:12px}.dou-pivot__toggle,.dou-pivot__toggle-space{display:inline-flex;flex:none;justify-content:center;align-items: center;width:20px;height:20px}.dou-pivot__toggle{border-radius:calc(var(--dou-radius-control) - 2px);color:var(--dou-color-text-tertiary);cursor:pointer;transition-property:background-color,color;transition-duration:var(--dou-motion-duration-fast);transition-timing-function:var(--dou-motion-easing);margin-left:-4px}.dou-pivot__toggle>svg{transition:transform var(--dou-motion-duration-fast)var(--dou-motion-easing);width:14px;height:14px}.dou-pivot__toggle.is-open>svg{transform:rotate(90deg)}.dou-pivot__toggle:hover{background-color:color-mix(in oklab,var(--dou-color-text)6%,transparent);color:var(--dou-color-text)}.is-clickable:hover>.dou-pivot__toggle{background-color:color-mix(in oklab,var(--dou-color-text)6%,transparent);color:var(--dou-color-text)}.dou-pivot__toggle-space{margin-left:-4px}.dou-pivot__body{position:relative}.dou-pivot__row{position:absolute;display:flex;box-sizing:border-box;height:var(--dou-pivot-row-height);border-bottom:1px solid var(--dou-pivot-line);min-width:100%;left:0}.dou-pivot__row:hover{background-color:var(--dou-pivot-hover-bg)}.dou-pivot__row.is-group{font-weight:var(--dou-font-weight-medium)}.dou-pivot__row-head,.dou-pivot__value-head{position:sticky;z-index:1;display:flex;box-sizing:border-box;background-color:var(--dou-pivot-bg);transition:box-shadow var(--dou-motion-duration-fast)var(--dou-motion-easing);flex:none;align-items: center;gap:4px;height:100%;padding-right:12px;left:0}.dou-pivot__row:hover>:is(.dou-pivot__row-head,.dou-pivot__value-head){background-color:var(--dou-pivot-hover-bg)}.dou-pivot__row-head{border-right:1px solid var(--dou-pivot-line-strong)}.dou-pivot__row-head.is-clickable{cursor:pointer}.has-values-column .dou-pivot__row-head{border-right-color:var(--dou-pivot-line)}.dou-pivot__value-head{border-right:1px solid var(--dou-pivot-line-strong);color:var(--dou-color-text-secondary);font-weight:var(--dou-font-weight-regular);padding-left:12px}.is-scrolled-x .dou-pivot__row-head,.is-scrolled-x .dou-pivot__value-head{box-shadow:4px 0 6px -4px var(--dou-pivot-scroll-shadow)}.is-scrolled-x.has-values-column .dou-pivot__row-head{box-shadow:none}.dou-pivot__spacer{flex:none}.dou-pivot__cell{display:flex;box-sizing:border-box;border-right:1px solid var(--dou-pivot-line);font-variant-numeric:tabular-nums;white-space:nowrap;background-image:var(--dou-pivot-highlight-layer,none);flex:none;justify-content:flex-end;align-items: center;height:100%;padding:0 12px}.dou-pivot__cell.is-total{background-color:var(--dou-pivot-total-bg)}.dou-pivot__cell.has-scale{--dou-pivot-tint:color-mix(in oklab,var(--dou-pivot-tone)calc(var(--dou-pivot-mark)*var(--dou-pivot-scale-strength)),transparent);background-image:var(--dou-pivot-highlight-layer,linear-gradient(transparent,transparent)),linear-gradient(var(--dou-pivot-tint),var(--dou-pivot-tint))}.dou-pivot__cell.has-bar{position:relative}.dou-pivot__cell.has-bar:before{position:absolute;top:6px;bottom:6px;left:calc(4px + (100% - 8px)*var(--dou-pivot-bar-start));width:calc((100% - 8px)*var(--dou-pivot-bar-size));background-color:color-mix(in oklab,var(--dou-pivot-tone)calc(var(--dou-pivot-bar-strength) + (var(--dou-pivot-bar-strength-dark) - var(--dou-pivot-bar-strength))*var(--dou-scheme-dark)),transparent);content:"";border-radius:3px}.dou-pivot__cell.has-bar>.dou-pivot__text{position:relative}.dou-pivot__row:hover>.dou-pivot__cell{background-color:var(--dou-pivot-hover-bg)}.dou-pivot__row:hover>.dou-pivot__cell.is-total{background-color:var(--dou-pivot-hover-total-bg)}.dou-pivot__row.is-highlighted .dou-pivot__row-head{background-image:linear-gradient(to right,var(--dou-color-text)2px,transparent 2px);font-weight:var(--dou-font-weight-medium)}.dou-pivot__row.is-highlighted .dou-pivot__cell,.dou-pivot__cell.is-highlighted{--dou-pivot-highlight-layer:linear-gradient(var(--dou-pivot-highlight),var(--dou-pivot-highlight))}.dou-pivot__row.is-highlighted .dou-pivot__cell.is-highlighted{font-weight:var(--dou-font-weight-medium)}.dou-pivot__cell.is-selected{position:relative}:is(.dou-pivot__cell.is-selected,.dou-pivot__row-head.is-selected):after{position:absolute;background-color:var(--dou-pivot-selected);content:"";pointer-events:none;inset:0}.dou-pivot.is-focused .dou-pivot__cell.is-active,.dou-pivot.is-focused .dou-pivot__row-head.is-active{box-shadow:inset 0 0 0 2px var(--dou-pivot-ring)}.dou-pivot.is-focused.is-scrolled-x .dou-pivot__row-head.is-active{box-shadow:inset 0 0 0 2px var(--dou-pivot-ring),4px 0 6px -4px var(--dou-pivot-scroll-shadow)}.dou-pivot__foot{position:sticky;z-index:2;background-color:var(--dou-pivot-head-bg);box-shadow:0 -1px 0 var(--dou-pivot-line-strong);bottom:0}.dou-pivot__foot .dou-pivot__row{font-weight:var(--dou-font-weight-medium);border-bottom:0}.dou-pivot__foot .dou-pivot__row-head{background-color:var(--dou-pivot-head-bg)}.dou-pivot__foot .dou-pivot__value-head{background-color:var(--dou-pivot-head-bg)}.dou-pivot__foot .dou-pivot__cell{background-color:var(--dou-pivot-head-bg)}.dou-pivot__foot .dou-pivot__row-head{padding-left:12px}.dou-pivot__empty{position:absolute;display:flex;color:var(--dou-color-text-tertiary);pointer-events:none;justify-content:center;align-items: center;inset:0}.dou-pivot__veil{position:absolute;z-index:5;display:flex;background-color:color-mix(in srgb,var(--dou-pivot-bg)60%,transparent);pointer-events:none;animation:dou-pivot-veil var(--dou-motion-duration-fast)var(--dou-motion-easing);justify-content:center;align-items: center;inset:0}.dou-pivot__busy{border:1px solid var(--dou-color-border);border-radius:var(--dou-radius-control);background-color:var(--dou-color-bg-surface);box-shadow:var(--dou-shadow-sm);color:var(--dou-color-text-secondary);font-size:var(--dou-font-size-sm);padding:6px 12px}@keyframes dou-pivot-veil{0%{opacity:0}}}@layer dou.components{.dou-pivot.is-tabular .dou-pivot__row-head{padding-right:0}.dou-pivot.is-tabular .dou-pivot__corner-line.is-rows{padding-left:0}.dou-pivot.is-tabular .dou-pivot__row.is-group:not(.is-subtotal){font-weight:inherit}.dou-pivot__row.is-subtotal{background-color:var(--dou-pivot-total-bg);font-weight:var(--dou-font-weight-medium)}.dou-pivot__row.is-subtotal>.dou-pivot__row-head{background-color:var(--dou-pivot-total-bg)}.dou-pivot__row.is-subtotal>.dou-pivot__value-head{background-color:var(--dou-pivot-total-bg)}.dou-pivot__level{display:flex;box-sizing:border-box;overflow:hidden;flex:none;align-items: center;gap:4px;min-width:0;height:100%;padding:0 8px 0 12px}.dou-pivot__level+.dou-pivot__level{border-left:1px solid var(--dou-pivot-line)}.dou-pivot__corner-inline{display:contents}.dou-pivot__corner-field{display:flex;box-sizing:border-box;overflow:hidden;flex:none;align-items: center;min-width:0;padding-left:8px}.dou-pivot__corner-field.is-last{flex-shrink:1}.dou-pivot.is-tabular .dou-pivot__corner-values{flex:none;padding-right:8px}.dou-pivot__resize{position:absolute;z-index:3;cursor:col-resize;touch-action:none;width:8px;height:100%;top:0;right:-4px}.dou-pivot__resize:after{position:absolute;background-color:var(--dou-pivot-ring);opacity:0;transition:opacity var(--dou-motion-duration-fast)var(--dou-motion-easing);content:"";border-radius:1px;width:2px;top:6px;bottom:6px;left:3px}.dou-pivot__resize:focus-visible{outline:none}.dou-pivot__resize:hover:after{opacity:1}.dou-pivot__resize:active:after{opacity:1}.dou-pivot__resize:focus-visible:after{opacity:1}.dou-pivot__live{position:absolute;overflow:hidden;clip-path:inset(50%);white-space:nowrap;width:1px;height:1px}.dou-pivot__measure{position:absolute;font-variant-numeric:tabular-nums;white-space:nowrap;visibility:hidden;pointer-events:none;top:0;left:0}}
@@ -0,0 +1 @@
1
+ export {}
package/dist/style.js ADDED
@@ -0,0 +1,13 @@
1
+ import 'dou-ui/components/checkbox/style'
2
+ import 'dou-ui/components/dialog/style'
3
+ import 'dou-ui/components/drawer/style'
4
+ import 'dou-ui/components/dropdown/style'
5
+ import 'dou-ui/components/form/style'
6
+ import 'dou-ui/components/input-number/style'
7
+ import 'dou-ui/components/popover/style'
8
+ import 'dou-ui/components/segmented-control/style'
9
+ import 'dou-ui/components/select/style'
10
+ import 'dou-ui/components/sortable/style'
11
+ import 'dou-ui/components/textarea/style'
12
+ import 'dou-ui/components/virtual-list/style'
13
+ import './style.css'
@@ -0,0 +1,26 @@
1
+ import type { PivotResolvedField, PivotResolvedValue } from '../engine';
2
+ import { type PivotGroupBy } from '../engine/group';
3
+ export interface PivotLabelTexts {
4
+ empty: string;
5
+ yes: string;
6
+ no: string;
7
+ /** Group labels of a grouping: `{year}`, `{quarter}`, `{week}`, `{from}`, `{to}`. */
8
+ year: string;
9
+ quarter: string;
10
+ week: string;
11
+ range: string;
12
+ }
13
+ /** Writes a group label: the field's `format`, or a plain form of the value. */
14
+ export declare function labelFormatter(field: PivotResolvedField<unknown>, locale: string, texts: PivotLabelTexts, by?: PivotGroupBy): (value: unknown) => string;
15
+ /**
16
+ * The number format a value is written with: the share, sign and rank
17
+ * defaults, or its own `format`. `null` for a format function and for
18
+ * dates (a `min` or `max` of a date field).
19
+ */
20
+ export declare function valueNumberOptions(value: PivotResolvedValue): Intl.NumberFormatOptions | null;
21
+ /**
22
+ * Writes a value; an empty cell is blank. A value shown as a share is a
23
+ * percentage, a difference has its sign, a rank is a whole number; a
24
+ * `format` of its own is used as given.
25
+ */
26
+ export declare function valueFormatter(value: PivotResolvedValue, locale: string): (n: number) => string;
@@ -0,0 +1,14 @@
1
+ import type { PivotResolvedValue } from '../engine';
2
+ interface ValueTexts {
3
+ value: string;
4
+ aggregates: Record<string, string>;
5
+ shows: Record<string, string>;
6
+ shownValue: string;
7
+ }
8
+ /**
9
+ * A value's header: its `label`, the field's name for a sum, or the field
10
+ * and the way it is summed up ("销售额 · 平均值"); a plain count is "计数";
11
+ * a calculated value's formula. A value with a `show` adds it ("销售额 · 占总计").
12
+ */
13
+ export declare function valueLabel(value: PivotResolvedValue, label: string | undefined, m: ValueTexts): string;
14
+ export {};
@@ -0,0 +1,72 @@
1
+ import type { PivotTree } from '../engine';
2
+ import type { PivotCollapsed, PivotPath } from '../engine/types';
3
+ /**
4
+ * One row, or one column, of the table: a group (or the grand total), and
5
+ * which value it shows when the values run along this axis.
6
+ */
7
+ export interface PivotLine {
8
+ node: number;
9
+ /**
10
+ * `group`: a group's own line (its cells hold its total); `subtotal`: the
11
+ * column after an open column group that holds its total; `total`: the
12
+ * grand total.
13
+ */
14
+ kind: 'group' | 'subtotal' | 'total';
15
+ /** The value's place in `values`, or -1 when the values run along the other axis. */
16
+ value: number;
17
+ }
18
+ /** A header cell over the columns `from` up to (not including) `to`. */
19
+ export interface PivotHeaderSpan {
20
+ from: number;
21
+ to: number;
22
+ /** The header row it starts in, and how many it covers. */
23
+ level: number;
24
+ rows: number;
25
+ node: number;
26
+ kind: PivotLine['kind'] | 'value';
27
+ value: number;
28
+ }
29
+ /** The nodes of collapsed paths; paths that no longer match a group are skipped. */
30
+ export declare function collapsedNodes(tree: PivotTree, paths: readonly PivotPath[] | undefined): Set<number>;
31
+ export interface PivotLinesOptions {
32
+ /** How many values run along this axis (1 when they run along the other one). */
33
+ values: number;
34
+ /** Whether the values run along this axis. */
35
+ valuesHere: boolean;
36
+ /** Whether the grand total gets a line. */
37
+ total: boolean;
38
+ /**
39
+ * Rows only: an open group's total goes on a line of its own after its
40
+ * children (the tabular layout), instead of on the group's own line.
41
+ */
42
+ totalsAfter?: boolean;
43
+ }
44
+ /**
45
+ * The rows of the table, top to bottom, without the grand total: each open
46
+ * group is followed by its children; a group's own row holds its total
47
+ * (or, with `totalsAfter`, a row after its children does).
48
+ */
49
+ export declare function rowLines(tree: PivotTree, order: Int32Array, collapsed: ReadonlySet<number>, options: PivotLinesOptions): PivotLine[];
50
+ /** The grand total row(s), kept apart so they can stay at the bottom. */
51
+ export declare function totalLines(tree: PivotTree, options: PivotLinesOptions): PivotLine[];
52
+ /**
53
+ * The columns of the table, left to right: an open group's children and
54
+ * then, when its field has subtotals, a column with its total; a closed
55
+ * group is one column; the grand total comes last.
56
+ */
57
+ export declare function columnLines(tree: PivotTree, collapsed: ReadonlySet<number>, options: PivotLinesOptions): PivotLine[];
58
+ /**
59
+ * The header cells over the columns, one list per header row. Each field
60
+ * of the columns is a row; a group spans its children; a closed group, a
61
+ * subtotal and the grand total reach down to the values row. The values
62
+ * row names each column's value; without it, the cells reach one row
63
+ * further down instead (the header keeps a row for the row fields).
64
+ */
65
+ export declare function headerSpans(tree: PivotTree, lines: readonly PivotLine[], valueRow: boolean): PivotHeaderSpan[][];
66
+ /** The spans that reach into the columns `from` to `to`. */
67
+ export declare function spansIn(list: readonly PivotHeaderSpan[], from: number, to: number): PivotHeaderSpan[];
68
+ /** Paths of every group at `depth` and deeper (to collapse a level), or of every group. */
69
+ export declare function groupPaths(tree: PivotTree, depth?: number): PivotPath[];
70
+ /** Whether two paths are the same groups; dates match by time. */
71
+ export declare function samePath(a: PivotPath, b: PivotPath): boolean;
72
+ export type PivotAxis = keyof PivotCollapsed;
@@ -0,0 +1,7 @@
1
+ import { type MaybeRefOrGetter } from 'vue';
2
+ import { PivotSource, type PivotData } from '../engine';
3
+ import type { PivotField } from '../engine/types';
4
+ /** Whether two field lists describe the fields the same way (inline arrays are new each render). */
5
+ export declare function sameFields(a?: readonly PivotField<never>[], b?: readonly PivotField<never>[]): boolean;
6
+ /** The records as a `PivotSource`, read again only when the array, the fields or the locale change. */
7
+ export declare function usePivotSource<Row>(data: MaybeRefOrGetter<PivotData<Row>>, fields: MaybeRefOrGetter<readonly PivotField<Row>[] | undefined>): import("vue").ComputedRef<PivotSource<Row>>;
@@ -0,0 +1,73 @@
1
+ import type { PivotSheetCell } from '../types';
2
+ /** A cell of the table as it is copied or exported. */
3
+ export interface PivotGridCell {
4
+ /** What the cell shows. */
5
+ text: string;
6
+ /** `head`: a column header or the corner; `label`: a row's group; `value`: a number. */
7
+ kind: 'head' | 'label' | 'value';
8
+ /** For `value`: the number as shown (a share, when the value has `show`); `NaN` when empty. */
9
+ value?: number;
10
+ /** For `value`: the value's place in `config.values`. */
11
+ valueIndex?: number;
12
+ /** A subtotal or a total: a line, a column or both. */
13
+ total?: boolean;
14
+ /** A header over several columns or rows; the cells it covers are `null`. */
15
+ colSpan?: number;
16
+ rowSpan?: number;
17
+ }
18
+ /** The table, or part of it, row by row. */
19
+ export interface PivotGrid {
20
+ cells: (PivotGridCell | null)[][];
21
+ /** How many rows at the top are column headers, and how many columns at the left are row headers. */
22
+ headRows: number;
23
+ headCols: number;
24
+ /** Each value's number format for a sheet (`#,##0.00`, `0.0%`), by its place in `config.values`. */
25
+ formats: (string | undefined)[];
26
+ /** The width of each column on screen, in px. */
27
+ widths: number[];
28
+ }
29
+ /** A number without the float noise of adding up (`1592.0200000000002` is `1592.02`). */
30
+ export declare const tidyNumber: (n: number) => number;
31
+ export interface PivotCSVOptions {
32
+ /**
33
+ * Write the numbers as the table shows them (`¥1,280.00`, `21.3%`)
34
+ * instead of values a spreadsheet can add up (`1280`, `0.213`).
35
+ * Defaults to `false`.
36
+ */
37
+ text?: boolean;
38
+ /** Start with a byte order mark, so spreadsheets read the file as UTF-8. Defaults to `true`. */
39
+ bom?: boolean;
40
+ /**
41
+ * Put a `'` before labels a spreadsheet program would run as a formula
42
+ * (starting with `=`, `+`, `-`, `@`, a tab or a carriage return). Defaults to
43
+ * `true`; `false` writes them as they are.
44
+ */
45
+ escapeFormulas?: boolean;
46
+ }
47
+ /** The grid as CSV. Labels that a spreadsheet would read as a formula get a `'` in front. */
48
+ export declare function gridToCSV(grid: PivotGrid, options?: PivotCSVOptions): string;
49
+ export declare function gridToTSV(grid: PivotGrid): string;
50
+ /** The styles the sheet cells refer to. */
51
+ export declare const SHEET_STYLES: {
52
+ 'pivot-head': {
53
+ bold: boolean;
54
+ };
55
+ 'pivot-total': {
56
+ bold: boolean;
57
+ };
58
+ };
59
+ /** The cells as `DouSheet` takes them, row by row. */
60
+ export declare function gridToSheetCells(grid: PivotGrid): PivotSheetCell[][];
61
+ /** The merged header cells, as ranges such as `'B1:D1'`. */
62
+ export declare function gridMerges(grid: PivotGrid): string[];
63
+ /**
64
+ * The grid as an HTML table, for the clipboard and for printing: headers in
65
+ * `<thead>` (repeated on each printed page), spans kept. With `sheet`, the
66
+ * table also carries the cells for `DouSheet`, so pasting there keeps the
67
+ * numbers and their formats.
68
+ */
69
+ export declare function gridToHTML(grid: PivotGrid, { sheet }?: {
70
+ sheet?: boolean;
71
+ }): string;
72
+ /** A sheet number format that writes numbers like these `Intl.NumberFormat` options. */
73
+ export declare function sheetFormat(options: Intl.NumberFormatOptions, locale: string): string | undefined;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * A way to sum up a field. A state is built per group of records: `add`
3
+ * takes each record's value, `merge` joins two groups' states (subtotals and
4
+ * totals are merged from the groups inside them, never re-read from the
5
+ * records), and `result` turns a state into the number shown.
6
+ */
7
+ export interface PivotAggregator<State = any> {
8
+ name: string;
9
+ /** The header word, as in "金额 · 求和"; the name when left out. */
10
+ label?: string;
11
+ /**
12
+ * What `add` gets: `'number'` the field as a number (records without one
13
+ * are skipped), `'value'` the field's value as it is (empty ones skipped).
14
+ */
15
+ input: 'number' | 'value';
16
+ init: () => State;
17
+ add: (state: State, value: never) => State;
18
+ merge: (into: State, from: State) => State;
19
+ /** `null` or `NaN` for an empty cell. */
20
+ result: (state: State) => number | null;
21
+ /** Whether a value is an integer count (written without decimals); `false` by default. */
22
+ integer?: boolean;
23
+ }
24
+ /** Declares a way to sum up a field, for `aggregators` and the config's `aggregate`. */
25
+ export declare function defineAggregator<State, Input extends 'number' | 'value' = 'number'>(aggregator: Omit<PivotAggregator<State>, 'add' | 'input'> & {
26
+ input?: Input;
27
+ add: (state: State, value: Input extends 'number' ? number : unknown) => State;
28
+ }): PivotAggregator<State>;
29
+ /** The built-in ways with a typed-array fast path: one number (or two, for `avg`) per group. */
30
+ export type PivotFastAggregate = 'sum' | 'count' | 'avg' | 'min' | 'max';
31
+ export declare const FAST_AGGREGATES: ReadonlySet<string>;
32
+ /** Counts each value once; the state holds group numbers, so it never compares values. */
33
+ export declare const distinctAggregator: PivotAggregator<Set<number>>;
34
+ export declare const medianAggregator: PivotAggregator<number[]>;
35
+ export declare const BUILTIN_AGGREGATORS: Readonly<Record<string, PivotAggregator>>;