@ryuzaki13/react-foundation-lib 2.21.0 → 2.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/dist/analytical-table/buildAnalyticalTableModel.d.ts +5 -2
  2. package/dist/analytical-table/buildAnalyticalTableModel.d.ts.map +1 -1
  3. package/dist/analytical-table/{calculations.d.ts → definition/calculations.d.ts} +1 -1
  4. package/dist/analytical-table/definition/calculations.d.ts.map +1 -0
  5. package/dist/analytical-table/definition/compileAnalyticalTableDefinition.d.ts +4 -0
  6. package/dist/analytical-table/definition/compileAnalyticalTableDefinition.d.ts.map +1 -0
  7. package/dist/analytical-table/definition/types.d.ts +70 -0
  8. package/dist/analytical-table/definition/types.d.ts.map +1 -0
  9. package/dist/analytical-table/definition/validateAnalyticalView.d.ts +5 -0
  10. package/dist/analytical-table/definition/validateAnalyticalView.d.ts.map +1 -0
  11. package/dist/analytical-table/{dateColumns.d.ts → dynamic-columns/dateColumns.d.ts} +2 -1
  12. package/dist/analytical-table/dynamic-columns/dateColumns.d.ts.map +1 -0
  13. package/dist/analytical-table/dynamic-columns/index.d.ts +3 -0
  14. package/dist/analytical-table/dynamic-columns/index.d.ts.map +1 -0
  15. package/dist/analytical-table/{dateColumnTypes.d.ts → dynamic-columns/types.d.ts} +3 -3
  16. package/dist/analytical-table/dynamic-columns/types.d.ts.map +1 -0
  17. package/dist/analytical-table/index.d.ts +7 -5
  18. package/dist/analytical-table/index.d.ts.map +1 -1
  19. package/dist/analytical-table/index.js +362 -201
  20. package/dist/analytical-table/index.js.map +1 -1
  21. package/dist/analytical-table/projections/expansion.d.ts +4 -0
  22. package/dist/analytical-table/projections/expansion.d.ts.map +1 -0
  23. package/dist/analytical-table/{exportProjection.d.ts → projections/exportProjection.d.ts} +1 -1
  24. package/dist/analytical-table/projections/exportProjection.d.ts.map +1 -0
  25. package/dist/analytical-table/projections/indexAnalyticalRows.d.ts +4 -0
  26. package/dist/analytical-table/projections/indexAnalyticalRows.d.ts.map +1 -0
  27. package/dist/analytical-table/projections/resolveRowsProjection.d.ts +4 -0
  28. package/dist/analytical-table/projections/resolveRowsProjection.d.ts.map +1 -0
  29. package/dist/analytical-table/{exportTypes.d.ts → projections/types.d.ts} +2 -2
  30. package/dist/analytical-table/projections/types.d.ts.map +1 -0
  31. package/dist/analytical-table/{aggregation.d.ts → runtime/aggregation.d.ts} +1 -1
  32. package/dist/analytical-table/runtime/aggregation.d.ts.map +1 -0
  33. package/dist/analytical-table/runtime/buildGroupedModel.d.ts +11 -0
  34. package/dist/analytical-table/runtime/buildGroupedModel.d.ts.map +1 -0
  35. package/dist/analytical-table/runtime/createAnalyticalTableRuntime.d.ts +10 -0
  36. package/dist/analytical-table/runtime/createAnalyticalTableRuntime.d.ts.map +1 -0
  37. package/dist/analytical-table/runtime/filtering.d.ts +7 -0
  38. package/dist/analytical-table/runtime/filtering.d.ts.map +1 -0
  39. package/dist/analytical-table/runtime/grouping.d.ts +10 -0
  40. package/dist/analytical-table/runtime/grouping.d.ts.map +1 -0
  41. package/dist/analytical-table/runtime/hierarchy.d.ts +20 -0
  42. package/dist/analytical-table/runtime/hierarchy.d.ts.map +1 -0
  43. package/dist/analytical-table/runtime/sorting.d.ts +5 -0
  44. package/dist/analytical-table/runtime/sorting.d.ts.map +1 -0
  45. package/dist/analytical-table/runtime/totals.d.ts +12 -0
  46. package/dist/analytical-table/runtime/totals.d.ts.map +1 -0
  47. package/dist/analytical-table/runtime/types.d.ts +71 -0
  48. package/dist/analytical-table/runtime/types.d.ts.map +1 -0
  49. package/dist/analytical-table/{valueComparison.d.ts → runtime/valueComparison.d.ts} +1 -1
  50. package/dist/analytical-table/runtime/valueComparison.d.ts.map +1 -0
  51. package/dist/analytical-table/types.d.ts +4 -7
  52. package/dist/analytical-table/types.d.ts.map +1 -1
  53. package/dist/chunks/{formatters-CEltML3y.js → formatters-D1ob2OkI.js} +501 -451
  54. package/dist/chunks/formatters-D1ob2OkI.js.map +1 -0
  55. package/dist/chunks/{odata-service-CWkHASdw.js → odata-service-tp2U5yIr.js} +415 -415
  56. package/dist/chunks/{odata-service-CWkHASdw.js.map → odata-service-tp2U5yIr.js.map} +1 -1
  57. package/dist/chunks/{validate-M2zPiLXn.js → validate-C8cQm_9m.js} +2 -2
  58. package/dist/chunks/{validate-M2zPiLXn.js.map → validate-C8cQm_9m.js.map} +1 -1
  59. package/dist/error-report/index.js +2 -2
  60. package/dist/excel/index.js +18 -18
  61. package/dist/formatters/formatFileSize.d.ts +7 -0
  62. package/dist/formatters/formatFileSize.d.ts.map +1 -0
  63. package/dist/formatters/index.d.ts +1 -0
  64. package/dist/formatters/index.d.ts.map +1 -1
  65. package/dist/formatters/index.js +5 -5
  66. package/dist/odata-service/formatters.d.ts +2 -2
  67. package/dist/odata-service/index.js +1 -1
  68. package/dist/table/index.js.map +1 -1
  69. package/dist/table/useTableRowSelection.d.ts +1 -1
  70. package/dist/table/useTableRowSelection.d.ts.map +1 -1
  71. package/package.json +1 -1
  72. package/src/analytical-table/README.mdx +232 -143
  73. package/src/formatters/README.mdx +8 -0
  74. package/dist/analytical-table/aggregation.d.ts.map +0 -1
  75. package/dist/analytical-table/calculationTypes.d.ts +0 -11
  76. package/dist/analytical-table/calculationTypes.d.ts.map +0 -1
  77. package/dist/analytical-table/calculations.d.ts.map +0 -1
  78. package/dist/analytical-table/columnTypes.d.ts +0 -30
  79. package/dist/analytical-table/columnTypes.d.ts.map +0 -1
  80. package/dist/analytical-table/dataTypes.d.ts +0 -14
  81. package/dist/analytical-table/dataTypes.d.ts.map +0 -1
  82. package/dist/analytical-table/dateColumnTypes.d.ts.map +0 -1
  83. package/dist/analytical-table/dateColumns.d.ts.map +0 -1
  84. package/dist/analytical-table/expansion.d.ts +0 -4
  85. package/dist/analytical-table/expansion.d.ts.map +0 -1
  86. package/dist/analytical-table/exportProjection.d.ts.map +0 -1
  87. package/dist/analytical-table/exportTypes.d.ts.map +0 -1
  88. package/dist/analytical-table/filtering.d.ts +0 -4
  89. package/dist/analytical-table/filtering.d.ts.map +0 -1
  90. package/dist/analytical-table/indexAnalyticalRows.d.ts +0 -4
  91. package/dist/analytical-table/indexAnalyticalRows.d.ts.map +0 -1
  92. package/dist/analytical-table/modelTypes.d.ts +0 -43
  93. package/dist/analytical-table/modelTypes.d.ts.map +0 -1
  94. package/dist/analytical-table/valueComparison.d.ts.map +0 -1
  95. package/dist/analytical-table/viewTypes.d.ts +0 -24
  96. package/dist/analytical-table/viewTypes.d.ts.map +0 -1
  97. package/dist/chunks/formatters-CEltML3y.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/analytical-table/aggregation.ts","../../src/analytical-table/calculations.ts","../../src/analytical-table/valueComparison.ts","../../src/analytical-table/filtering.ts","../../src/analytical-table/indexAnalyticalRows.ts","../../src/analytical-table/buildAnalyticalTableModel.ts","../../src/analytical-table/dateColumns.ts","../../src/analytical-table/expansion.ts","../../src/analytical-table/exportProjection.ts"],"sourcesContent":["import { type AnalyticalAggregation } from \"./types\";\n\n/** null/пустые/нечисловые значения не превращаются в ноль; count считает непустые факты. */\nexport function aggregateAnalyticalValues(values: readonly unknown[], aggregation: AnalyticalAggregation): number | null {\n\tconst present = values.filter((value) => value !== null && value !== undefined && value !== \"\");\n\tif (aggregation === \"count\") return present.length;\n\tlet count = 0;\n\tlet sum = 0;\n\tlet minimum = Infinity;\n\tlet maximum = -Infinity;\n\tfor (const value of present) {\n\t\tif (typeof value !== \"number\" || !Number.isFinite(value)) continue;\n\t\tcount += 1;\n\t\tsum += value;\n\t\tminimum = Math.min(minimum, value);\n\t\tmaximum = Math.max(maximum, value);\n\t}\n\tif (count === 0) return null;\n\tswitch (aggregation) {\n\t\tcase \"sum\":\n\t\t\treturn sum;\n\t\tcase \"min\":\n\t\t\treturn minimum;\n\t\tcase \"max\":\n\t\t\treturn maximum;\n\t\tcase \"avg\":\n\t\t\treturn sum / count;\n\t}\n}\n","import { arrayDeduplicate } from \"../array\";\nimport { compileTableFormula } from \"../formulas\";\n\nimport { type AnalyticalCalculationPlan, type AnalyticalCalculationStep, type AnalyticalColumn, type AnalyticalValues } from \"./types\";\n\n/** Проверяет граф зависимостей до расчёта строк и компилирует каждую формулу один раз. */\nexport function createAnalyticalCalculationPlan<T>(\n\tcolumns: readonly AnalyticalColumn<T>[],\n\trequiredColumnIds: readonly string[] = columns.map((column) => column.id)\n): AnalyticalCalculationPlan {\n\tconst byId = new Map(columns.map((column) => [column.id, column]));\n\tif (byId.size !== columns.length) throw new Error(\"Идентификаторы аналитических столбцов должны быть уникальны.\");\n\tconst visited = new Set<string>();\n\tconst visiting = new Set<string>();\n\tconst required: string[] = [];\n\tconst steps: AnalyticalCalculationStep[] = [];\n\tconst visit = (id: string): void => {\n\t\tif (visited.has(id)) return;\n\t\tif (visiting.has(id)) throw new Error(`Циклическая зависимость аналитического столбца: ${id}`);\n\t\tconst column = byId.get(id);\n\t\tif (!column) throw new Error(`Неизвестная зависимость аналитического столбца: ${id}`);\n\t\tif (column.formula && column.calculate) throw new Error(`Столбец ${id} содержит два способа вычисления.`);\n\t\tvisiting.add(id);\n\t\tconst dependencies = arrayDeduplicate(column.formula?.dependencies ?? column.calculate?.dependencies ?? []);\n\t\tfor (const dependency of dependencies) visit(dependency);\n\t\tif (column.formula) {\n\t\t\t// Порядок и повторы аргументов формулы сохраняются; уникален лишь граф зависимостей.\n\t\t\tconst compiled = compileTableFormula({ formulaId: column.formula.formulaId, keys: column.formula.dependencies });\n\t\t\tif (!compiled.ok) throw new Error(`Формула столбца ${id} не зарегистрирована: ${column.formula.formulaId}`);\n\t\t\tsteps.push({\n\t\t\t\tcolumnId: id,\n\t\t\t\tdependencies,\n\t\t\t\tcompute: (values) => {\n\t\t\t\t\tconst result = compiled.execute({ ...values });\n\t\t\t\t\tif (!result.ok) throw new Error(`Ошибка формулы столбца ${id}: ${result.reason}`);\n\t\t\t\t\treturn result.value;\n\t\t\t\t}\n\t\t\t});\n\t\t} else if (column.calculate) {\n\t\t\tsteps.push({ columnId: id, dependencies, compute: column.calculate.compute });\n\t\t}\n\t\tvisiting.delete(id);\n\t\tvisited.add(id);\n\t\trequired.push(id);\n\t};\n\tfor (const id of requiredColumnIds) visit(id);\n\treturn { steps, requiredColumnIds: required };\n}\n\n/** Возвращает отдельный набор значений; исходный DTO и значения Query не мутируются. */\nexport function calculateAnalyticalValues(values: AnalyticalValues, plan: AnalyticalCalculationPlan): AnalyticalValues {\n\tconst result: Record<string, unknown> = { ...values };\n\tfor (const step of plan.steps) result[step.columnId] = step.compute(result);\n\treturn result;\n}\n","import { parseDate } from \"../formatters\";\nimport { compareStrings } from \"../string-comparison\";\nimport { stableStringify } from \"../utils\";\n\nimport { type AnalyticalColumn, type AnalyticalValues } from \"./types\";\n\n/** Тип входит в ключ: null, undefined, строка и число не склеивают разные группы. */\nexport function analyticalIdentity(values: AnalyticalValues, ids: readonly string[]): string {\n\treturn stableStringify(\n\t\tids.map((id) => {\n\t\t\tconst value = values[id];\n\t\t\treturn [id, value === null ? \"null\" : typeof value, value];\n\t\t})\n\t);\n}\n\nexport function compareAnalyticalValues<T>(left: unknown, right: unknown, column?: AnalyticalColumn<T>): number {\n\tif (Object.is(left, right)) return 0;\n\tif (left === null || left === undefined) return 1;\n\tif (right === null || right === undefined) return -1;\n\tif (column?.compare) return column.compare(left, right);\n\tif (column?.valueType === \"date\") {\n\t\tconst leftDate = parseDate(left);\n\t\tconst rightDate = parseDate(right);\n\t\tif (leftDate && rightDate) return leftDate.getTime() - rightDate.getTime();\n\t}\n\tif (typeof left === \"number\" && typeof right === \"number\") return left - right;\n\tif (typeof left === \"boolean\" && typeof right === \"boolean\") return Number(left) - Number(right);\n\treturn compareStrings(String(left), String(right));\n}\n","import { normalizeTextToLower } from \"../formatters\";\n\nimport { type AnalyticalColumn, type AnalyticalDataRow, type AnalyticalFilter } from \"./types\";\nimport { compareAnalyticalValues } from \"./valueComparison\";\n\n/** Операции фильтра относятся к данным, поэтому одинаково работают при SSR и в браузере. */\nexport function matchesAnalyticalFilter<T>(row: AnalyticalDataRow<T>, filter: AnalyticalFilter, column?: AnalyticalColumn<T>): boolean {\n\tconst value = row.values[filter.id];\n\tif (column?.filter) return column.filter(value, filter, row);\n\tconst expected = filter.value;\n\tconst compare = (other: unknown) => compareAnalyticalValues(value, other, column);\n\tconst empty = value === null || value === undefined || value === \"\";\n\tswitch (filter.operator ?? \"equals\") {\n\t\tcase \"equals\":\n\t\t\treturn compare(expected) === 0;\n\t\tcase \"notEquals\":\n\t\t\treturn compare(expected) !== 0;\n\t\tcase \"contains\":\n\t\t\treturn normalizeTextToLower(String(value ?? \"\")).includes(normalizeTextToLower(String(expected ?? \"\")));\n\t\tcase \"startsWith\":\n\t\t\treturn normalizeTextToLower(String(value ?? \"\")).startsWith(normalizeTextToLower(String(expected ?? \"\")));\n\t\tcase \"in\":\n\t\t\treturn Array.isArray(expected) && expected.some((item: unknown) => compare(item) === 0);\n\t\tcase \"between\":\n\t\t\treturn Array.isArray(expected) && expected.length === 2 && !empty && compare(expected[0]) >= 0 && compare(expected[1]) <= 0;\n\t\tcase \"gt\":\n\t\t\treturn !empty && compare(expected) > 0;\n\t\tcase \"gte\":\n\t\t\treturn !empty && compare(expected) >= 0;\n\t\tcase \"lt\":\n\t\t\treturn !empty && compare(expected) < 0;\n\t\tcase \"lte\":\n\t\t\treturn !empty && compare(expected) <= 0;\n\t\tcase \"empty\":\n\t\t\treturn empty;\n\t\tcase \"notEmpty\":\n\t\t\treturn !empty;\n\t}\n}\n","import { type AnalyticalModelRow, type AnalyticalTableModel } from \"./types\";\n\n/** Единственный обход индексов полной и видимой проекций дерева. */\nexport function indexAnalyticalRows<T>(\n\trows: readonly AnalyticalModelRow<T>[]\n): Pick<AnalyticalTableModel<T>, \"flatRows\" | \"visibleRows\" | \"rowById\"> {\n\tconst flatRows: AnalyticalModelRow<T>[] = [];\n\tconst visibleRows: AnalyticalModelRow<T>[] = [];\n\tconst rowById = new Map<string, AnalyticalModelRow<T>>();\n\tconst visit = (nodes: readonly AnalyticalModelRow<T>[], visible: boolean): void => {\n\t\tfor (const row of nodes) {\n\t\t\tflatRows.push(row);\n\t\t\trowById.set(row.id, row);\n\t\t\tif (visible) visibleRows.push(row);\n\t\t\tvisit(row.children, visible && row.isExpanded);\n\t\t}\n\t};\n\tvisit(rows, true);\n\treturn { flatRows, visibleRows, rowById };\n}\n","import { arrayDeduplicate } from \"../array\";\nimport { buildTreeTableRows } from \"../tree-table\";\nimport { type TreeTableRowNode } from \"../tree-table\";\nimport { stableStringify } from \"../utils\";\n\nimport { aggregateAnalyticalValues } from \"./aggregation\";\nimport { calculateAnalyticalValues, createAnalyticalCalculationPlan } from \"./calculations\";\nimport { matchesAnalyticalFilter } from \"./filtering\";\nimport { indexAnalyticalRows } from \"./indexAnalyticalRows\";\nimport {\n\ttype AnalyticalDataRow,\n\ttype AnalyticalModelRow,\n\ttype AnalyticalTableModel,\n\ttype AnalyticalValues,\n\ttype BuildAnalyticalTableModelOptions\n} from \"./types\";\nimport { analyticalIdentity, compareAnalyticalValues } from \"./valueComparison\";\n\ntype PreparedNode<T> = Readonly<{\n\tid: string;\n\tkind: \"data\" | \"group\";\n\tsourceRow?: AnalyticalDataRow<T>;\n\tvalues: AnalyticalValues;\n\tchildren: PreparedNode<T>[];\n\tgroupingLevelId?: string;\n}>;\n\n/** Чистая модель полного снимка: не владеет транспортом, кэшем, DOM и жизненным циклом Query. */\nexport function buildAnalyticalTableModel<T>(options: BuildAnalyticalTableModelOptions<T>): AnalyticalTableModel<T> {\n\tconst { snapshot, columns, state = {} } = options;\n\tconst plan = createAnalyticalCalculationPlan(columns);\n\tconst columnsById = new Map(columns.map((column) => [column.id, column]));\n\tconst grouping = state.grouping ?? [];\n\tconst sorting = state.sorting ?? [];\n\tconst filters = state.filters ?? [];\n\tfor (const id of [...sorting.map((sort) => sort.id), ...filters.map((filter) => filter.id)]) {\n\t\tif (!columnsById.has(id)) throw new Error(`Неизвестный аналитический столбец: ${id}`);\n\t}\n\tif (arrayDeduplicate(grouping.map((level) => level.id)).length !== grouping.length)\n\t\tthrow new Error(\"Идентификаторы уровней группировки должны быть уникальны.\");\n\tfor (const level of grouping)\n\t\tif (level.keyColumnIds.length === 0) throw new Error(`Уровень ${level.id} не содержит ключей группировки.`);\n\tconst dataRows = snapshot.rows.map((row) => ({ ...row, values: calculateAnalyticalValues(row.values, plan) }));\n\tif (dataRows.some((row) => row.id.length === 0)) throw new Error(\"Идентификатор аналитической строки не может быть пустым.\");\n\tconst tree = buildTreeTableRows(dataRows, { getRowId: (row) => row.id, getParentRowId: (row) => row.parentId });\n\tconst roots = new Set(tree.rootRowIds);\n\tconst isAggregateRow = options.isAggregateRow ?? ((row: AnalyticalDataRow<T>) => roots.has(row.id));\n\tconst prepare = (node: TreeTableRowNode<AnalyticalDataRow<T>>): PreparedNode<T> => ({\n\t\tid: node.id,\n\t\tkind: \"data\",\n\t\tsourceRow: tree.rowById.get(node.id),\n\t\tvalues: node.values,\n\t\tchildren: (node.children ?? []).map(prepare)\n\t});\n\tconst sourceRoots = tree.rows.map(prepare);\n\tconst collectRows = (nodes: readonly PreparedNode<T>[]): AnalyticalDataRow<T>[] => {\n\t\tconst rows: AnalyticalDataRow<T>[] = [];\n\t\tconst visit = (node: PreparedNode<T>): void => {\n\t\t\tif (node.sourceRow && isAggregateRow(node.sourceRow)) rows.push(node.sourceRow);\n\t\t\tfor (const child of node.children) visit(child);\n\t\t};\n\t\tfor (const node of nodes) visit(node);\n\t\treturn rows;\n\t};\n\tconst aggregate = (nodes: readonly PreparedNode<T>[], scope: \"group\" | \"grand\", path: AnalyticalValues): AnalyticalValues => {\n\t\tconst context = { scope, rows: collectRows(nodes), groupingPath: path };\n\t\tconst values: Record<string, unknown> = { ...path };\n\t\tfor (const column of columns) {\n\t\t\tif (!column.aggregate) continue;\n\t\t\tvalues[column.id] =\n\t\t\t\ttypeof column.aggregate === \"function\"\n\t\t\t\t\t? column.aggregate(context)\n\t\t\t\t\t: aggregateAnalyticalValues(\n\t\t\t\t\t\t\tcontext.rows.map((row) => row.values[column.id]),\n\t\t\t\t\t\t\tcolumn.aggregate\n\t\t\t\t\t\t);\n\t\t}\n\t\tObject.assign(values, options.aggregate?.(context));\n\t\t// Готовый итог колонки и значения пути имеют приоритет над её построчной\n\t\t// формулой. Зависимые формулы при этом читают уже выбранный итог: например,\n\t\t// сумма произведений не превращается в произведение сумм, а ratio без\n\t\t// собственного aggregate по-прежнему вычисляется из сумм числителя и знаменателя.\n\t\tconst totalsPlan = { ...plan, steps: plan.steps.filter((step) => !Object.hasOwn(values, step.columnId)) };\n\t\treturn calculateAnalyticalValues(values, totalsPlan);\n\t};\n\t// Совпадение родителя сохраняет его ветвь целиком; совпадение ребёнка сохраняет путь к нему.\n\tconst filterNodes = (nodes: readonly PreparedNode<T>[]): PreparedNode<T>[] =>\n\t\tnodes.flatMap((node) => {\n\t\t\tconst sourceRow = node.sourceRow;\n\t\t\tif (sourceRow && filters.every((filter) => matchesAnalyticalFilter(sourceRow, filter, columnsById.get(filter.id))))\n\t\t\t\treturn [node];\n\t\t\tconst children = filterNodes(node.children);\n\t\t\treturn children.length > 0 ? [{ ...node, children }] : [];\n\t\t});\n\tconst filteredRoots = filters.length > 0 ? filterNodes(sourceRoots) : sourceRoots;\n\tconst groupNodes = (\n\t\tnodes: PreparedNode<T>[],\n\t\tlevelIndex: number,\n\t\tpath: AnalyticalValues,\n\t\tidentityPath: readonly string[]\n\t): PreparedNode<T>[] => {\n\t\tconst level = grouping[levelIndex];\n\t\tif (!level) return nodes;\n\t\tconst buckets = new Map<string, PreparedNode<T>[]>();\n\t\tfor (const node of nodes) {\n\t\t\tconst key = analyticalIdentity(node.values, level.keyColumnIds);\n\t\t\tconst bucket = buckets.get(key);\n\t\t\tif (bucket) bucket.push(node);\n\t\t\telse buckets.set(key, [node]);\n\t\t}\n\t\treturn Array.from(buckets, ([key, members]) => {\n\t\t\tconst identity = [...identityPath, level.id, key];\n\t\t\tconst id = `analytical-group:${stableStringify(identity)}`;\n\t\t\tif (tree.rowById.has(id)) throw new Error(`Идентификатор исходной строки совпал с группой: ${id}`);\n\t\t\tconst nextPath: Record<string, unknown> = { ...path };\n\t\t\tfor (const columnId of [...level.keyColumnIds, ...(level.displayColumnIds ?? [])])\n\t\t\t\tnextPath[columnId] = members[0].values[columnId];\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\tkind: \"group\",\n\t\t\t\tgroupingLevelId: level.id,\n\t\t\t\tvalues: aggregate(members, \"group\", nextPath),\n\t\t\t\tchildren: groupNodes(members, levelIndex + 1, nextPath, identity)\n\t\t\t};\n\t\t});\n\t};\n\tconst prepared = groupNodes(filteredRoots, 0, {}, []);\n\tconst expanded = new Set(state.expandedRowIds === \"all\" ? [] : (state.expandedRowIds ?? []));\n\tconst sortNodes = (nodes: readonly PreparedNode<T>[]): PreparedNode<T>[] =>\n\t\t[...nodes].sort((left, right) => {\n\t\t\tfor (const sort of sorting) {\n\t\t\t\tconst comparison = compareAnalyticalValues(left.values[sort.id], right.values[sort.id], columnsById.get(sort.id));\n\t\t\t\tif (comparison !== 0) return sort.desc ? -comparison : comparison;\n\t\t\t}\n\t\t\treturn 0;\n\t\t});\n\tconst materialize = (nodes: readonly PreparedNode<T>[], parentId: string | null, level: number): AnalyticalModelRow<T>[] =>\n\t\tsortNodes(nodes).map((node) => ({\n\t\t\tid: node.id,\n\t\t\tparentId,\n\t\t\tkind: node.kind,\n\t\t\tsourceRow: node.sourceRow,\n\t\t\toriginal: node.sourceRow?.original,\n\t\t\tvalues: node.values,\n\t\t\tlevel,\n\t\t\tchildren: materialize(node.children, node.id, level + 1),\n\t\t\tisExpandable: node.children.length > 0,\n\t\t\tisExpanded: node.children.length > 0 && (state.expandedRowIds === \"all\" || expanded.has(node.id)),\n\t\t\tgroupingLevelId: node.groupingLevelId\n\t\t}));\n\tconst rows = materialize(prepared, null, 0);\n\treturn {\n\t\tcolumns,\n\t\trows,\n\t\t...indexAnalyticalRows(rows),\n\t\tgrandTotals:\n\t\t\toptions.grandTotals === false ? null : aggregate(options.grandTotalsScope === \"all\" ? sourceRoots : filteredRoots, \"grand\", {}),\n\t\tdiagnostics: { orphanRowIds: tree.orphanRowIds, duplicateRowIds: tree.duplicateRowIds, cyclicRowIds: tree.cyclicRowIds }\n\t};\n}\n","import {\n\taddCalendarDays,\n\taddCalendarMonths,\n\taddCalendarYears,\n\tcreateCalendarDate,\n\tformatDate,\n\tgetStartOfDay,\n\tgetStartOfMonth,\n\tgetStartOfWeek,\n\tgetStartOfYear,\n\tparseDateByPattern,\n\tresolveDateFormatPreset\n} from \"../formatters\";\n\nimport { aggregateAnalyticalValues } from \"./aggregation\";\nimport {\n\ttype AnalyticalDataRow,\n\ttype AnalyticalDateColumn,\n\ttype AnalyticalDateColumnsOptions,\n\ttype AnalyticalDateColumnsPlan,\n\ttype AnalyticalValues,\n\ttype ProjectAnalyticalDateFactsOptions\n} from \"./types\";\nimport { analyticalIdentity } from \"./valueComparison\";\n\nconst CALENDAR_FORMAT = resolveDateFormatPreset(\"yyyy-MM-dd\");\nconst DATE_LABEL_FORMAT = resolveDateFormatPreset(\"dd.MM.yyyy\");\n\n/** Принимает только календарный контракт; преобразование timestamp принадлежит transport/domain адаптеру. */\nfunction readCalendarDate(value: unknown): Date | null {\n\tif (typeof value !== \"string\" || value.length !== 10) return null;\n\tconst parsed = parseDateByPattern(value, \"yyyy-MM-dd\");\n\treturn parsed?.kind === \"date-time\" ? parsed.date : null;\n}\n\nfunction calendarString(date: Date): string {\n\treturn formatDate(date, CALENDAR_FORMAT);\n}\n\nfunction bucketStart(date: Date, granularity: AnalyticalDateColumnsOptions[\"granularity\"]): Date {\n\tswitch (granularity) {\n\t\tcase \"day\":\n\t\t\treturn getStartOfDay(date);\n\t\tcase \"week\":\n\t\t\treturn getStartOfWeek(date, 1);\n\t\tcase \"month\":\n\t\t\treturn getStartOfMonth(date);\n\t\tcase \"quarter\":\n\t\t\treturn createCalendarDate(date.getFullYear(), Math.floor(date.getMonth() / 3) * 3, 1);\n\t\tcase \"year\":\n\t\t\treturn getStartOfYear(date);\n\t}\n}\n\nfunction nextBucket(date: Date, granularity: AnalyticalDateColumnsOptions[\"granularity\"]): Date {\n\tswitch (granularity) {\n\t\tcase \"day\":\n\t\t\treturn addCalendarDays(date, 1);\n\t\tcase \"week\":\n\t\t\treturn addCalendarDays(date, 7);\n\t\tcase \"month\":\n\t\t\treturn addCalendarMonths(date, 1);\n\t\tcase \"quarter\":\n\t\t\treturn addCalendarMonths(date, 3);\n\t\tcase \"year\":\n\t\t\treturn addCalendarYears(date, 1);\n\t}\n}\n\n/** Строит ограниченный календарный план; ISO-моменты времени сюда не передаются. */\nexport function createAnalyticalDateColumnsPlan(options: AnalyticalDateColumnsOptions): AnalyticalDateColumnsPlan {\n\tconst from = readCalendarDate(options.from);\n\tconst to = readCalendarDate(options.to);\n\tif (!from || !to || calendarString(from) !== options.from || calendarString(to) !== options.to || options.from > options.to)\n\t\tthrow new Error(\"Некорректный календарный диапазон аналитических столбцов.\");\n\tconst maxColumns = options.maxColumns ?? 366;\n\tif (!Number.isSafeInteger(maxColumns) || maxColumns < 1)\n\t\tthrow new Error(\"Лимит динамических столбцов должен быть положительным целым числом.\");\n\tif (!options.id || options.identityColumnIds.length === 0)\n\t\tthrow new Error(\"Динамическим столбцам нужны идентификатор и ключи сопоставления фактов.\");\n\tconst columns: AnalyticalDateColumn[] = [];\n\tfor (let start = bucketStart(from, options.granularity); start <= to; start = nextBucket(start, options.granularity)) {\n\t\tif (columns.length >= maxColumns) throw new Error(`Превышен лимит динамических столбцов: ${maxColumns}`);\n\t\tconst key = calendarString(start);\n\t\tconst end = calendarString(addCalendarDays(nextBucket(start, options.granularity), -1));\n\t\tcolumns.push({\n\t\t\tid: `${options.id}:${options.granularity}:${key}`,\n\t\t\tlabel: options.granularity === \"day\" ? formatDate(start, DATE_LABEL_FORMAT) : `${key} — ${end}`,\n\t\t\tfrom: key < options.from ? options.from : key,\n\t\t\tto: end > options.to ? options.to : end\n\t\t});\n\t}\n\treturn { options: { ...options, identityColumnIds: [...options.identityColumnIds] }, columns };\n}\n\nfunction factColumnId(fact: AnalyticalValues, plan: AnalyticalDateColumnsPlan): string | undefined {\n\t// Факт без полного ключа нельзя сопоставить строке; общий итог использует ту же область допустимых фактов.\n\tif (plan.options.identityColumnIds.some((id) => fact[id] === undefined || fact[id] === null)) return undefined;\n\tconst date = readCalendarDate(fact[plan.options.dateColumnId]);\n\tif (!date) return undefined;\n\tconst day = calendarString(date);\n\tif (day < plan.options.from || day > plan.options.to) return undefined;\n\treturn `${plan.options.id}:${plan.options.granularity}:${calendarString(bucketStart(date, plan.options.granularity))}`;\n}\n\n/** Сопоставляет отдельные facts составному ключу строки; порядок и количество base rows неизменны. */\nexport function projectAnalyticalDateFacts<T>(args: ProjectAnalyticalDateFactsOptions<T>): readonly AnalyticalDataRow<T>[] {\n\tconst { rows, facts, plan } = args;\n\tconst byIdentity = new Map<string, Map<string, unknown[]>>();\n\tfor (const fact of facts) {\n\t\tconst columnId = factColumnId(fact, plan);\n\t\tif (!columnId) continue;\n\t\tconst identity = analyticalIdentity(fact, plan.options.identityColumnIds);\n\t\tlet buckets = byIdentity.get(identity);\n\t\tif (!buckets) {\n\t\t\tbuckets = new Map();\n\t\t\tbyIdentity.set(identity, buckets);\n\t\t}\n\t\tconst bucket = buckets.get(columnId);\n\t\tif (bucket) bucket.push(fact[plan.options.measureColumnId]);\n\t\telse buckets.set(columnId, [fact[plan.options.measureColumnId]]);\n\t}\n\treturn rows.map((row) => {\n\t\tconst buckets = byIdentity.get(analyticalIdentity(row.values, plan.options.identityColumnIds));\n\t\tconst values: Record<string, unknown> = { ...row.values };\n\t\tfor (const column of plan.columns) {\n\t\t\tif (Object.hasOwn(values, column.id)) throw new Error(`Динамический столбец перезаписывает исходное поле: ${column.id}`);\n\t\t\tconst bucket = buckets?.get(column.id);\n\t\t\tvalues[column.id] = bucket ? aggregateAnalyticalValues(bucket, plan.options.aggregation) : null;\n\t\t}\n\t\treturn { ...row, values };\n\t});\n}\n\n/**\n * Общие итоги считаются по исходным facts с полным ключом: среднее от средних не подменяет взвешенный результат.\n * Отбор допустимых непустых identities по области доступа и фильтрам выполняет вызывающий адаптер.\n */\nexport function aggregateAnalyticalDateFacts(facts: readonly AnalyticalValues[], plan: AnalyticalDateColumnsPlan): AnalyticalValues {\n\tconst buckets = new Map<string, unknown[]>();\n\tfor (const fact of facts) {\n\t\tconst id = factColumnId(fact, plan);\n\t\tif (!id) continue;\n\t\tconst bucket = buckets.get(id);\n\t\tif (bucket) bucket.push(fact[plan.options.measureColumnId]);\n\t\telse buckets.set(id, [fact[plan.options.measureColumnId]]);\n\t}\n\treturn Object.fromEntries(\n\t\tplan.columns.map((column) => [\n\t\t\tcolumn.id,\n\t\t\tbuckets.has(column.id) ? aggregateAnalyticalValues(buckets.get(column.id) ?? [], plan.options.aggregation) : null\n\t\t])\n\t);\n}\n","import { indexAnalyticalRows } from \"./indexAnalyticalRows\";\nimport { type AnalyticalModelRow, type AnalyticalTableModel } from \"./types\";\n\n/** Раскрытие не меняет группировки, формулы и итоги; UI мемоизирует базовую модель отдельно. */\nexport function projectAnalyticalTableExpansion<T>(\n\tmodel: AnalyticalTableModel<T>,\n\texpandedRowIds: readonly string[] | \"all\"\n): AnalyticalTableModel<T> {\n\tconst expanded = new Set(expandedRowIds === \"all\" ? [] : expandedRowIds);\n\tconst project = (nodes: readonly AnalyticalModelRow<T>[]): AnalyticalModelRow<T>[] =>\n\t\tnodes.map((node) => ({\n\t\t\t...node,\n\t\t\tisExpanded: node.isExpandable && (expandedRowIds === \"all\" || expanded.has(node.id)),\n\t\t\tchildren: project(node.children)\n\t\t}));\n\tconst rows = project(model.rows);\n\treturn { ...model, rows, ...indexAnalyticalRows(rows) };\n}\n","import { type AnalyticalExportColumn, type AnalyticalExportProjection, type ProjectAnalyticalTableExportOptions } from \"./types\";\n\n/** Проекция для /excel или /table-document; сам runtime не скачивает файлы и не читает DOM. */\nexport function projectAnalyticalTableExport<T>(args: ProjectAnalyticalTableExportOptions<T>): AnalyticalExportProjection {\n\tconst { model } = args;\n\tconst columns: readonly AnalyticalExportColumn<T>[] = args.columns ?? model.columns;\n\tconst selected = new Set(args.selectedRowIds ?? []);\n\tconst source = args.scope === \"visible\" ? model.visibleRows : model.flatRows;\n\tconst rows: AnalyticalExportProjection[\"rows\"][number][] = source\n\t\t.filter((row) => (args.includeGroups !== false || row.kind !== \"group\") && (args.scope !== \"selected\" || selected.has(row.id)))\n\t\t.map((row) => ({\n\t\t\tid: row.id,\n\t\t\tlevel: row.level,\n\t\t\tkind: row.kind,\n\t\t\tvalues: columns.map((column) => (column.format ? column.format(row.values[column.id], row) : row.values[column.id]))\n\t\t}));\n\tif (args.includeGrandTotals && model.grandTotals)\n\t\trows.push({\n\t\t\tid: \"analytical-grand-total\",\n\t\t\tlevel: 0,\n\t\t\tkind: \"grand\",\n\t\t\tvalues: columns.map((column) => {\n\t\t\t\tconst value = model.grandTotals?.[column.id];\n\t\t\t\treturn column.formatTotal ? column.formatTotal(value) : value;\n\t\t\t})\n\t\t});\n\treturn { columns: columns.map((column) => ({ id: column.id, label: column.label ?? column.id })), rows };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/analytical-table/runtime/aggregation.ts","../../src/analytical-table/definition/calculations.ts","../../src/analytical-table/definition/compileAnalyticalTableDefinition.ts","../../src/analytical-table/definition/validateAnalyticalView.ts","../../src/analytical-table/projections/indexAnalyticalRows.ts","../../src/analytical-table/projections/resolveRowsProjection.ts","../../src/analytical-table/projections/expansion.ts","../../src/analytical-table/runtime/totals.ts","../../src/analytical-table/runtime/valueComparison.ts","../../src/analytical-table/runtime/grouping.ts","../../src/analytical-table/runtime/buildGroupedModel.ts","../../src/analytical-table/runtime/filtering.ts","../../src/analytical-table/runtime/hierarchy.ts","../../src/analytical-table/runtime/sorting.ts","../../src/analytical-table/runtime/createAnalyticalTableRuntime.ts","../../src/analytical-table/buildAnalyticalTableModel.ts","../../src/analytical-table/dynamic-columns/dateColumns.ts","../../src/analytical-table/projections/exportProjection.ts"],"sourcesContent":["import { type AnalyticalAggregation } from \"../types\";\n\n/** null/пустые/нечисловые значения не превращаются в ноль; count считает непустые факты. */\nexport function aggregateAnalyticalValues(values: readonly unknown[], aggregation: AnalyticalAggregation): number | null {\n\tconst present = values.filter((value) => value !== null && value !== undefined && value !== \"\");\n\tif (aggregation === \"count\") return present.length;\n\n\tlet count = 0;\n\tlet sum = 0;\n\tlet minimum = Infinity;\n\tlet maximum = -Infinity;\n\n\tfor (const value of present) {\n\t\tif (typeof value !== \"number\" || !Number.isFinite(value)) continue;\n\t\tcount += 1;\n\t\tsum += value;\n\t\tminimum = Math.min(minimum, value);\n\t\tmaximum = Math.max(maximum, value);\n\t}\n\n\tif (count === 0) return null;\n\n\tswitch (aggregation) {\n\t\tcase \"sum\":\n\t\t\treturn sum;\n\t\tcase \"min\":\n\t\t\treturn minimum;\n\t\tcase \"max\":\n\t\t\treturn maximum;\n\t\tcase \"avg\":\n\t\t\treturn sum / count;\n\t}\n}\n","import { arrayDeduplicate } from \"../../array\";\nimport { compileTableFormula } from \"../../formulas\";\nimport { type AnalyticalCalculationPlan, type AnalyticalCalculationStep, type AnalyticalColumn, type AnalyticalValues } from \"../types\";\n\n/** Проверяет граф зависимостей до расчёта строк и компилирует каждую формулу один раз. */\nexport function createAnalyticalCalculationPlan<T>(\n\tcolumns: readonly AnalyticalColumn<T>[],\n\trequiredColumnIds: readonly string[] = columns.map((column) => column.id)\n): AnalyticalCalculationPlan {\n\tconst byId = new Map(columns.map((column) => [column.id, column]));\n\tif (byId.size !== columns.length) throw new Error(\"Идентификаторы аналитических столбцов должны быть уникальны.\");\n\tconst visited = new Set<string>();\n\tconst visiting = new Set<string>();\n\tconst required: string[] = [];\n\tconst steps: AnalyticalCalculationStep[] = [];\n\tconst visit = (id: string): void => {\n\t\tif (visited.has(id)) return;\n\t\tif (visiting.has(id)) throw new Error(`Циклическая зависимость аналитического столбца: ${id}`);\n\t\tconst column = byId.get(id);\n\t\tif (!column) throw new Error(`Неизвестная зависимость аналитического столбца: ${id}`);\n\t\tif (column.formula && column.calculate) throw new Error(`Столбец ${id} содержит два способа вычисления.`);\n\t\tvisiting.add(id);\n\t\tconst dependencies = arrayDeduplicate(column.formula?.dependencies ?? column.calculate?.dependencies ?? []);\n\t\tfor (const dependency of dependencies) visit(dependency);\n\t\tif (column.formula) {\n\t\t\t// Порядок и повторы аргументов формулы сохраняются; уникален лишь граф зависимостей.\n\t\t\tconst compiled = compileTableFormula({ formulaId: column.formula.formulaId, keys: column.formula.dependencies });\n\t\t\tif (!compiled.ok) throw new Error(`Формула столбца ${id} не зарегистрирована: ${column.formula.formulaId}`);\n\t\t\tsteps.push({\n\t\t\t\tcolumnId: id,\n\t\t\t\tdependencies,\n\t\t\t\tcompute: (values) => {\n\t\t\t\t\tconst result = compiled.execute(values);\n\t\t\t\t\tif (!result.ok) throw new Error(`Ошибка формулы столбца ${id}: ${result.reason}`);\n\t\t\t\t\treturn result.value;\n\t\t\t\t}\n\t\t\t});\n\t\t} else if (column.calculate) {\n\t\t\tsteps.push({ columnId: id, dependencies, compute: column.calculate.compute });\n\t\t}\n\t\tvisiting.delete(id);\n\t\tvisited.add(id);\n\t\trequired.push(id);\n\t};\n\tfor (const id of requiredColumnIds) visit(id);\n\treturn { steps, requiredColumnIds: required };\n}\n\n/** Возвращает отдельный набор значений; исходный DTO и значения Query не мутируются. */\nexport function calculateAnalyticalValues(values: AnalyticalValues, plan: AnalyticalCalculationPlan): AnalyticalValues {\n\tconst result: Record<string, unknown> = { ...values };\n\tfor (const step of plan.steps) result[step.columnId] = step.compute(result);\n\treturn result;\n}\n","import { createAnalyticalCalculationPlan } from \"./calculations\";\nimport { type AnalyticalTableDefinition, type CompiledAnalyticalTableDefinition } from \"./types\";\n\n/** Проверяет единый каталог полей, включая служебные зависимости невидимых вычислений. */\nexport function compileAnalyticalTableDefinition<T>(definition: AnalyticalTableDefinition<T>): CompiledAnalyticalTableDefinition<T> {\n\tconst fields = [...definition.columns, ...(definition.dataFields ?? [])];\n\tconst calculations = createAnalyticalCalculationPlan(fields);\n\n\treturn {\n\t\tcolumns: definition.columns,\n\t\tfieldsById: new Map(fields.map((field) => [field.id, field])),\n\t\tcalculations,\n\t\taggregateFields: fields.filter((field) => field.aggregate !== undefined),\n\t\tisAggregateRow: definition.isAggregateRow,\n\t\taggregate: definition.aggregate,\n\t\tgrandTotals: definition.grandTotals !== false,\n\t\tgrandTotalsScope: definition.grandTotalsScope ?? \"filtered\"\n\t};\n}\n","import { type AnalyticalViewState } from \"../runtime/types\";\n\nimport { type CompiledAnalyticalTableDefinition } from \"./types\";\n\n/** Состояние ссылается на проверенное описание; grouping keys могут быть служебными полями values. */\nexport function validateAnalyticalView<T>(definition: CompiledAnalyticalTableDefinition<T>, state: AnalyticalViewState): void {\n\tfor (const entry of [...(state.sorting ?? []), ...(state.filters ?? [])]) {\n\t\tif (!definition.fieldsById.has(entry.id)) {\n\t\t\tthrow new Error(`Неизвестный аналитический столбец: ${entry.id}`);\n\t\t}\n\t}\n\n\tconst levelIds = new Set<string>();\n\tfor (const level of state.grouping ?? []) {\n\t\tif (levelIds.has(level.id)) {\n\t\t\tthrow new Error(\"Идентификаторы уровней группировки должны быть уникальны.\");\n\t\t}\n\t\tif (level.keyColumnIds.length === 0) {\n\t\t\tthrow new Error(`Уровень ${level.id} не содержит ключей группировки.`);\n\t\t}\n\t\tlevelIds.add(level.id);\n\t}\n}\n","import { type AnalyticalModelRow, type AnalyticalTableModel } from \"../types\";\n\ntype RowTraversalFrame<T> = {\n\treadonly rows: readonly AnalyticalModelRow<T>[];\n\treadonly visible: boolean;\n\tnextIndex: number;\n};\n\n/** Строит согласованные индексы за один проход, не расходуя стек вызовов на глубину дерева. */\nexport function indexAnalyticalRows<T>(\n\trows: readonly AnalyticalModelRow<T>[]\n): Pick<AnalyticalTableModel<T>, \"flatRows\" | \"visibleRows\" | \"rowById\"> {\n\tconst flatRows: AnalyticalModelRow<T>[] = [];\n\tconst visibleRows: AnalyticalModelRow<T>[] = [];\n\tconst rowById = new Map<string, AnalyticalModelRow<T>>();\n\tconst stack: RowTraversalFrame<T>[] = [{ rows, visible: true, nextIndex: 0 }];\n\n\twhile (stack.length > 0) {\n\t\tconst frame = stack[stack.length - 1];\n\t\tif (frame.nextIndex === frame.rows.length) {\n\t\t\tstack.pop();\n\t\t\tcontinue;\n\t\t}\n\t\tconst row = frame.rows[frame.nextIndex++];\n\t\tflatRows.push(row);\n\t\trowById.set(row.id, row);\n\t\tif (frame.visible) visibleRows.push(row);\n\t\tif (row.children.length > 0) {\n\t\t\tstack.push({ rows: row.children, visible: frame.visible && row.isExpanded, nextIndex: 0 });\n\t\t}\n\t}\n\treturn { flatRows, visibleRows, rowById };\n}\n","import { type AnalyticalModelRow, type AnalyticalTableModel } from \"../types\";\n\nimport { indexAnalyticalRows } from \"./indexAnalyticalRows\";\n\n/** Любая проекция дерева заменяет индексы вместе с узлами, сохраняя уже рассчитанные итоги. */\nexport function resolveRowsProjection<T>(model: AnalyticalTableModel<T>, rows: readonly AnalyticalModelRow<T>[]): AnalyticalTableModel<T> {\n\tif (rows === model.rows) return model;\n\treturn { ...model, rows, ...indexAnalyticalRows(rows) };\n}\n","import { type AnalyticalModelRow, type AnalyticalTableModel } from \"../types\";\n\nimport { resolveRowsProjection } from \"./resolveRowsProjection\";\n\n/** Копирует массив только при замене его непосредственного ребёнка. */\nfunction replaceExpandedRows<T>(\n\trows: readonly AnalyticalModelRow<T>[],\n\treplacements: ReadonlyMap<AnalyticalModelRow<T>, AnalyticalModelRow<T>>\n): readonly AnalyticalModelRow<T>[] {\n\tlet projected: AnalyticalModelRow<T>[] | undefined;\n\tfor (let index = 0; index < rows.length; index++) {\n\t\tconst replacement = replacements.get(rows[index]);\n\t\tif (!replacement) continue;\n\t\tprojected ??= rows.slice();\n\t\tprojected[index] = replacement;\n\t}\n\treturn projected ?? rows;\n}\n\n/** Раскрытие меняет только затронутые ветви; формулы и итоги остаются результатом базовой модели. */\nexport function projectAnalyticalTableExpansion<T>(\n\tmodel: AnalyticalTableModel<T>,\n\texpandedRowIds: readonly string[] | \"all\"\n): AnalyticalTableModel<T> {\n\tconst expandAll = expandedRowIds === \"all\";\n\tconst expanded = new Set(expandAll ? [] : expandedRowIds);\n\tconst replacements = new Map<AnalyticalModelRow<T>, AnalyticalModelRow<T>>();\n\n\t// flatRows уже содержит обход родитель → дети. Обратный проход позволяет\n\t// заменить ребёнка до родителя без рекурсии и сохранить ссылки остальных ветвей.\n\tfor (let index = model.flatRows.length - 1; index >= 0; index--) {\n\t\tconst row = model.flatRows[index];\n\t\tconst children = replaceExpandedRows(row.children, replacements);\n\t\tconst isExpanded = row.isExpandable && (expandAll || expanded.has(row.id));\n\t\tif (isExpanded !== row.isExpanded || children !== row.children) {\n\t\t\treplacements.set(row, { ...row, isExpanded, children });\n\t\t}\n\t}\n\n\t// Неизвестные ID и листья не меняют эффективное раскрытие и не сбрасывают memo потребителей.\n\tif (replacements.size === 0) return model;\n\treturn resolveRowsProjection(model, replaceExpandedRows(model.rows, replacements));\n}\n","import { calculateAnalyticalValues } from \"../definition/calculations\";\nimport { type AnalyticalAggregateContext, type CompiledAnalyticalTableDefinition } from \"../definition/types\";\n\nimport { aggregateAnalyticalValues } from \"./aggregation\";\nimport { type AnalyticalHierarchyNode } from \"./hierarchy\";\nimport { type AnalyticalDataRow, type AnalyticalValues } from \"./types\";\n\n/** Отбирает исходные строки выбранной зернистости; синтетические группы в итоги не попадают. */\nfunction collectAggregateRows<T>(\n\tnodes: readonly AnalyticalHierarchyNode<T>[],\n\taggregateRowIds: ReadonlySet<string>\n): AnalyticalDataRow<T>[] {\n\tconst rows: AnalyticalDataRow<T>[] = [];\n\tconst visit = (node: AnalyticalHierarchyNode<T>): void => {\n\t\tif (node.sourceRow && aggregateRowIds.has(node.id)) {\n\t\t\trows.push(node.sourceRow);\n\t\t}\n\n\t\tfor (const child of node.children) {\n\t\t\tvisit(child);\n\t\t}\n\t};\n\n\tfor (const node of nodes) {\n\t\tvisit(node);\n\t}\n\n\treturn rows;\n}\n\n/** Один порядок для групповых и общих итогов: агрегации → callback → зависимые формулы. */\nexport function calculateAnalyticalTotals<T>(args: {\n\tdefinition: CompiledAnalyticalTableDefinition<T>;\n\tnodes: readonly AnalyticalHierarchyNode<T>[];\n\taggregateRowIds: ReadonlySet<string>;\n\tscope: \"group\" | \"grand\";\n\tgroupingPath?: AnalyticalValues;\n}): AnalyticalValues {\n\tconst { definition, nodes, aggregateRowIds, scope, groupingPath = {} } = args;\n\tconst context: AnalyticalAggregateContext<T> = {\n\t\tscope,\n\t\trows: collectAggregateRows(nodes, aggregateRowIds),\n\t\tgroupingPath\n\t};\n\tconst values: Record<string, unknown> = { ...groupingPath };\n\n\tfor (const field of definition.aggregateFields) {\n\t\tconst aggregate = field.aggregate;\n\t\tif (aggregate === undefined) continue;\n\n\t\tvalues[field.id] =\n\t\t\ttypeof aggregate === \"function\"\n\t\t\t\t? aggregate(context)\n\t\t\t\t: aggregateAnalyticalValues(\n\t\t\t\t\t\tcontext.rows.map((row) => row.values[field.id]),\n\t\t\t\t\t\taggregate\n\t\t\t\t\t);\n\t}\n\n\tObject.assign(values, definition.aggregate?.(context));\n\n\t// Явные итоги и ключи пути сохраняются. Остальные формулы читают уже готовые\n\t// суммы: процент считается из сумм, а сумма произведений не заменяется произведением сумм.\n\tconst calculations = {\n\t\t...definition.calculations,\n\t\tsteps: definition.calculations.steps.filter((step) => !Object.hasOwn(values, step.columnId))\n\t};\n\n\treturn calculateAnalyticalValues(values, calculations);\n}\n","import { parseDate } from \"../../formatters\";\nimport { compareStrings } from \"../../string-comparison\";\nimport { stableStringify } from \"../../utils\";\nimport { type AnalyticalColumn, type AnalyticalValues } from \"../types\";\n\n/** Тип входит в ключ: null, undefined, строка и число не склеивают разные группы. */\nexport function analyticalIdentity(values: AnalyticalValues, ids: readonly string[]): string {\n\treturn stableStringify(\n\t\tids.map((id) => {\n\t\t\tconst value = values[id];\n\t\t\treturn [id, value === null ? \"null\" : typeof value, value];\n\t\t})\n\t);\n}\n\nexport function compareAnalyticalValues<T>(left: unknown, right: unknown, column?: AnalyticalColumn<T>): number {\n\tif (Object.is(left, right)) return 0;\n\tif (left === null || left === undefined) return 1;\n\tif (right === null || right === undefined) return -1;\n\tif (column?.compare) return column.compare(left, right);\n\tif (column?.valueType === \"date\") {\n\t\tconst leftDate = parseDate(left);\n\t\tconst rightDate = parseDate(right);\n\t\tif (leftDate && rightDate) return leftDate.getTime() - rightDate.getTime();\n\t}\n\tif (typeof left === \"number\" && typeof right === \"number\") return left - right;\n\tif (typeof left === \"boolean\" && typeof right === \"boolean\") return Number(left) - Number(right);\n\treturn compareStrings(String(left), String(right));\n}\n","import { stableStringify } from \"../../utils\";\nimport { type AnalyticalGroupingLevel, type CompiledAnalyticalTableDefinition } from \"../definition/types\";\n\nimport { type AnalyticalHierarchyNode, type AnalyticalSourceHierarchy } from \"./hierarchy\";\nimport { calculateAnalyticalTotals } from \"./totals\";\nimport { type AnalyticalValues } from \"./types\";\nimport { analyticalIdentity } from \"./valueComparison\";\n\n/** Группировка добавляет уровни над предметными корнями и сохраняет их дочернюю детализацию. */\nexport function groupAnalyticalHierarchy<T>(args: {\n\trows: readonly AnalyticalHierarchyNode<T>[];\n\tgrouping: readonly AnalyticalGroupingLevel[];\n\tdefinition: CompiledAnalyticalTableDefinition<T>;\n\tsource: AnalyticalSourceHierarchy<T>;\n}): readonly AnalyticalHierarchyNode<T>[] {\n\tconst { grouping, definition, source } = args;\n\tconst groupLevel = (\n\t\trows: readonly AnalyticalHierarchyNode<T>[],\n\t\tlevelIndex: number,\n\t\tpath: AnalyticalValues,\n\t\tidentityPath: readonly string[]\n\t): readonly AnalyticalHierarchyNode<T>[] => {\n\t\tconst level = grouping[levelIndex];\n\t\tif (!level) return rows;\n\n\t\tconst buckets = new Map<string, AnalyticalHierarchyNode<T>[]>();\n\t\tfor (const row of rows) {\n\t\t\tconst key = analyticalIdentity(row.values, level.keyColumnIds);\n\t\t\tconst bucket = buckets.get(key);\n\t\t\tif (bucket) bucket.push(row);\n\t\t\telse buckets.set(key, [row]);\n\t\t}\n\n\t\treturn Array.from(buckets, ([key, members]) => {\n\t\t\tconst identity = [...identityPath, level.id, key];\n\t\t\tconst id = `analytical-group:${stableStringify(identity)}`;\n\t\t\tif (source.sourceRowIds.has(id)) {\n\t\t\t\tthrow new Error(`Идентификатор исходной строки совпал с группой: ${id}`);\n\t\t\t}\n\n\t\t\tconst groupingPath: Record<string, unknown> = { ...path };\n\t\t\tfor (const fieldId of [...level.keyColumnIds, ...(level.displayColumnIds ?? [])]) {\n\t\t\t\tgroupingPath[fieldId] = members[0].values[fieldId];\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\tkind: \"group\",\n\t\t\t\tgroupingLevelId: level.id,\n\t\t\t\tvalues: calculateAnalyticalTotals({\n\t\t\t\t\tdefinition,\n\t\t\t\t\tnodes: members,\n\t\t\t\t\taggregateRowIds: source.aggregateRowIds,\n\t\t\t\t\tscope: \"group\",\n\t\t\t\t\tgroupingPath\n\t\t\t\t}),\n\t\t\t\tchildren: groupLevel(members, levelIndex + 1, groupingPath, identity)\n\t\t\t};\n\t\t});\n\t};\n\n\treturn groupLevel(args.rows, 0, {}, []);\n}\n","import { type AnalyticalGroupingLevel, type CompiledAnalyticalTableDefinition } from \"../definition/types\";\nimport { indexAnalyticalRows } from \"../projections/indexAnalyticalRows\";\n\nimport { groupAnalyticalHierarchy } from \"./grouping\";\nimport { type AnalyticalHierarchyNode, type AnalyticalSourceHierarchy } from \"./hierarchy\";\nimport { calculateAnalyticalTotals } from \"./totals\";\nimport { type AnalyticalModelRow, type AnalyticalTableModel } from \"./types\";\n\n/** Назначает конечные уровни и родителей после добавления всех группировок. */\nfunction materializeRows<T>(\n\tnodes: readonly AnalyticalHierarchyNode<T>[],\n\tparentId: string | null = null,\n\tlevel = 0\n): AnalyticalModelRow<T>[] {\n\treturn nodes.map((node) => ({\n\t\tid: node.id,\n\t\tparentId,\n\t\tkind: node.kind,\n\t\tsourceRow: node.sourceRow,\n\t\toriginal: node.sourceRow?.original,\n\t\tvalues: node.values,\n\t\tlevel,\n\t\tchildren: materializeRows(node.children, node.id, level + 1),\n\t\tisExpandable: node.children.length > 0,\n\t\tisExpanded: false,\n\t\tgroupingLevelId: node.groupingLevelId\n\t}));\n}\n\n/** Базовая модель содержит все отобранные строки и итоги; порядок и раскрытие задаются позже. */\nexport function buildGroupedAnalyticalModel<T>(args: {\n\tdefinition: CompiledAnalyticalTableDefinition<T>;\n\tsource: AnalyticalSourceHierarchy<T>;\n\tfilteredRows: readonly AnalyticalHierarchyNode<T>[];\n\tgrouping: readonly AnalyticalGroupingLevel[];\n}): AnalyticalTableModel<T> {\n\tconst { definition, source, filteredRows, grouping } = args;\n\tconst hierarchy = groupAnalyticalHierarchy({ rows: filteredRows, grouping, definition, source });\n\tconst rows = materializeRows(hierarchy);\n\tconst grandTotals = definition.grandTotals\n\t\t? calculateAnalyticalTotals({\n\t\t\t\tdefinition,\n\t\t\t\tnodes: definition.grandTotalsScope === \"all\" ? source.rows : filteredRows,\n\t\t\t\taggregateRowIds: source.aggregateRowIds,\n\t\t\t\tscope: \"grand\"\n\t\t\t})\n\t\t: null;\n\n\treturn {\n\t\tcolumns: definition.columns,\n\t\trows,\n\t\t...indexAnalyticalRows(rows),\n\t\tgrandTotals,\n\t\tdiagnostics: source.diagnostics\n\t};\n}\n","import { normalizeTextToLower } from \"../../formatters\";\nimport { type AnalyticalColumn, type AnalyticalDataRow, type AnalyticalFilter } from \"../types\";\n\nimport { type AnalyticalHierarchyNode } from \"./hierarchy\";\nimport { compareAnalyticalValues } from \"./valueComparison\";\n\n/** Операции фильтра относятся к данным, поэтому одинаково работают при SSR и в браузере. */\nexport function matchesAnalyticalFilter<T>(row: AnalyticalDataRow<T>, filter: AnalyticalFilter, column?: AnalyticalColumn<T>): boolean {\n\tconst value = row.values[filter.id];\n\tif (column?.filter) return column.filter(value, filter, row);\n\tconst expected = filter.value;\n\tconst compare = (other: unknown) => compareAnalyticalValues(value, other, column);\n\tconst empty = value === null || value === undefined || value === \"\";\n\tswitch (filter.operator ?? \"equals\") {\n\t\tcase \"equals\":\n\t\t\treturn compare(expected) === 0;\n\t\tcase \"notEquals\":\n\t\t\treturn compare(expected) !== 0;\n\t\tcase \"contains\":\n\t\t\treturn normalizeTextToLower(String(value ?? \"\")).includes(normalizeTextToLower(String(expected ?? \"\")));\n\t\tcase \"startsWith\":\n\t\t\treturn normalizeTextToLower(String(value ?? \"\")).startsWith(normalizeTextToLower(String(expected ?? \"\")));\n\t\tcase \"in\":\n\t\t\treturn Array.isArray(expected) && expected.some((item: unknown) => compare(item) === 0);\n\t\tcase \"between\":\n\t\t\treturn Array.isArray(expected) && expected.length === 2 && !empty && compare(expected[0]) >= 0 && compare(expected[1]) <= 0;\n\t\tcase \"gt\":\n\t\t\treturn !empty && compare(expected) > 0;\n\t\tcase \"gte\":\n\t\t\treturn !empty && compare(expected) >= 0;\n\t\tcase \"lt\":\n\t\t\treturn !empty && compare(expected) < 0;\n\t\tcase \"lte\":\n\t\t\treturn !empty && compare(expected) <= 0;\n\t\tcase \"empty\":\n\t\t\treturn empty;\n\t\tcase \"notEmpty\":\n\t\t\treturn !empty;\n\t}\n}\n\n/** Совпавший родитель оставляет всю ветвь; совпавший ребёнок сохраняет путь к нему. */\nexport function filterAnalyticalHierarchy<T>(\n\trows: readonly AnalyticalHierarchyNode<T>[],\n\tfilters: readonly AnalyticalFilter[],\n\tfieldsById: ReadonlyMap<string, AnalyticalColumn<T>>\n): readonly AnalyticalHierarchyNode<T>[] {\n\tif (filters.length === 0) return rows;\n\n\tconst filtered: AnalyticalHierarchyNode<T>[] = [];\n\tfor (const row of rows) {\n\t\tconst sourceRow = row.sourceRow;\n\t\tconst matches = sourceRow && filters.every((filter) => matchesAnalyticalFilter(sourceRow, filter, fieldsById.get(filter.id)));\n\t\tif (matches) {\n\t\t\tfiltered.push(row);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst children = filterAnalyticalHierarchy(row.children, filters, fieldsById);\n\t\tif (children.length > 0) {\n\t\t\tfiltered.push({ ...row, children });\n\t\t}\n\t}\n\n\treturn filtered;\n}\n","import { buildTreeTableRows, type TreeTableRowNode } from \"../../tree-table\";\nimport { calculateAnalyticalValues } from \"../definition/calculations\";\nimport { type CompiledAnalyticalTableDefinition } from \"../definition/types\";\n\nimport { type AnalyticalDataRow, type AnalyticalDiagnostics, type AnalyticalSnapshot, type AnalyticalValues } from \"./types\";\n\n/** Узел до назначения итогового parentId/level: группировка ещё может добавить предков. */\nexport type AnalyticalHierarchyNode<T> = Readonly<{\n\tid: string;\n\tkind: \"data\" | \"group\";\n\tsourceRow?: AnalyticalDataRow<T>;\n\tvalues: AnalyticalValues;\n\tchildren: readonly AnalyticalHierarchyNode<T>[];\n\tgroupingLevelId?: string;\n}>;\n\nexport type AnalyticalSourceHierarchy<T> = Readonly<{\n\trows: readonly AnalyticalHierarchyNode<T>[];\n\tsourceRowIds: ReadonlySet<string>;\n\taggregateRowIds: ReadonlySet<string>;\n\tdiagnostics: AnalyticalDiagnostics;\n}>;\n\n/** Формулы исходных строк и предметная иерархия зависят только от определения и снимка. */\nexport function prepareAnalyticalHierarchy<T>(\n\tsnapshot: AnalyticalSnapshot<T>,\n\tdefinition: CompiledAnalyticalTableDefinition<T>\n): AnalyticalSourceHierarchy<T> {\n\tif (snapshot.rows.some((row) => row.id.length === 0)) {\n\t\tthrow new Error(\"Идентификатор аналитической строки не может быть пустым.\");\n\t}\n\n\tconst calculatedRows = snapshot.rows.map((row) => ({\n\t\t...row,\n\t\tvalues: calculateAnalyticalValues(row.values, definition.calculations)\n\t}));\n\tconst tree = buildTreeTableRows(calculatedRows, {\n\t\tgetRowId: (row) => row.id,\n\t\tgetParentRowId: (row) => row.parentId\n\t});\n\n\tconst prepareNode = (node: TreeTableRowNode<AnalyticalDataRow<T>>): AnalyticalHierarchyNode<T> => ({\n\t\tid: node.id,\n\t\tkind: \"data\",\n\t\tsourceRow: tree.rowById.get(node.id),\n\t\tvalues: node.values,\n\t\tchildren: (node.children ?? []).map(prepareNode)\n\t});\n\tconst aggregateRowIds = definition.isAggregateRow\n\t\t? Array.from(tree.rowById.values())\n\t\t\t\t.filter(definition.isAggregateRow)\n\t\t\t\t.map((row) => row.id)\n\t\t: tree.rootRowIds;\n\n\treturn {\n\t\trows: tree.rows.map(prepareNode),\n\t\tsourceRowIds: new Set(tree.allRowIds),\n\t\taggregateRowIds: new Set(aggregateRowIds),\n\t\tdiagnostics: {\n\t\t\torphanRowIds: tree.orphanRowIds,\n\t\t\tduplicateRowIds: tree.duplicateRowIds,\n\t\t\tcyclicRowIds: tree.cyclicRowIds\n\t\t}\n\t};\n}\n","import { type AnalyticalColumn } from \"../definition/types\";\nimport { resolveRowsProjection } from \"../projections/resolveRowsProjection\";\n\nimport { type AnalyticalModelRow, type AnalyticalSorting, type AnalyticalTableModel } from \"./types\";\nimport { compareAnalyticalValues } from \"./valueComparison\";\n\n/** Меняет только порядок соседей: вычисленные значения, итоги и связи parent/child сохраняются. */\nexport function sortAnalyticalModel<T>(\n\tmodel: AnalyticalTableModel<T>,\n\tsorting: readonly AnalyticalSorting[],\n\tfieldsById: ReadonlyMap<string, AnalyticalColumn<T>>\n): AnalyticalTableModel<T> {\n\tif (sorting.length === 0) return model;\n\n\tconst compareRows = (left: AnalyticalModelRow<T>, right: AnalyticalModelRow<T>): number => {\n\t\tfor (const sort of sorting) {\n\t\t\tconst comparison = compareAnalyticalValues(left.values[sort.id], right.values[sort.id], fieldsById.get(sort.id));\n\t\t\tif (comparison !== 0) return sort.desc ? -comparison : comparison;\n\t\t}\n\t\treturn 0;\n\t};\n\tconst sortBranch = (rows: readonly AnalyticalModelRow<T>[]): readonly AnalyticalModelRow<T>[] => {\n\t\tif (rows.length === 0) return rows;\n\n\t\tconst projected = rows.map((row) => {\n\t\t\tconst children = sortBranch(row.children);\n\t\t\treturn children === row.children ? row : { ...row, children };\n\t\t});\n\t\tprojected.sort(compareRows);\n\n\t\treturn projected.every((row, index) => row === rows[index]) ? rows : projected;\n\t};\n\n\treturn resolveRowsProjection(model, sortBranch(model.rows));\n}\n","import { validateAnalyticalView } from \"../definition/validateAnalyticalView\";\nimport { projectAnalyticalTableExpansion } from \"../projections/expansion\";\n\nimport { buildGroupedAnalyticalModel } from \"./buildGroupedModel\";\nimport { filterAnalyticalHierarchy } from \"./filtering\";\nimport { prepareAnalyticalHierarchy } from \"./hierarchy\";\nimport { sortAnalyticalModel } from \"./sorting\";\nimport {\n\ttype AnalyticalTableModel,\n\ttype AnalyticalTableRuntime,\n\ttype AnalyticalViewState,\n\ttype CreateAnalyticalTableRuntimeOptions\n} from \"./types\";\n\nconst EMPTY_STATE: AnalyticalViewState = {};\nconst EMPTY_ITEMS = Object.freeze([]);\n\n/**\n * Создаёт вычислительный runtime для одного снимка.\n *\n * Хранится только последний результат каждого этапа. Исходные строки рассчитываются\n * один раз; фильтры/группировки меняют итоги, сортировка — порядок, раскрытие — видимость.\n * Входные определения, снимки и массивы состояния должны оставаться неизменяемыми.\n */\nexport function createAnalyticalTableRuntime<T>(options: CreateAnalyticalTableRuntimeOptions<T>): AnalyticalTableRuntime<T> {\n\tconst { definition, snapshot } = options;\n\tconst source = prepareAnalyticalHierarchy(snapshot, definition);\n\tlet previousState: AnalyticalViewState = EMPTY_STATE;\n\tlet filteredRows = source.rows;\n\tlet groupedModel: AnalyticalTableModel<T> | undefined;\n\tlet sortedModel: AnalyticalTableModel<T> | undefined;\n\tlet expandedModel: AnalyticalTableModel<T> | undefined;\n\n\treturn {\n\t\tgetModel(state = EMPTY_STATE) {\n\t\t\tvalidateAnalyticalView(definition, state);\n\t\t\tconst filters = state.filters ?? EMPTY_ITEMS;\n\t\t\tconst grouping = state.grouping ?? EMPTY_ITEMS;\n\t\t\tconst sorting = state.sorting ?? EMPTY_ITEMS;\n\t\t\tconst expandedRowIds = state.expandedRowIds ?? EMPTY_ITEMS;\n\t\t\tconst filtersChanged = !groupedModel || filters !== (previousState.filters ?? EMPTY_ITEMS);\n\t\t\tconst groupingChanged = !groupedModel || grouping !== (previousState.grouping ?? EMPTY_ITEMS);\n\t\t\tconst sortingChanged = sorting !== (previousState.sorting ?? EMPTY_ITEMS);\n\t\t\tconst expansionChanged = expandedRowIds !== (previousState.expandedRowIds ?? EMPTY_ITEMS);\n\n\t\t\tconst nextFilteredRows = filtersChanged ? filterAnalyticalHierarchy(source.rows, filters, definition.fieldsById) : filteredRows;\n\n\t\t\tconst rebuildGroups = !groupedModel || filtersChanged || groupingChanged;\n\t\t\tconst nextGroupedModel = rebuildGroups\n\t\t\t\t? buildGroupedAnalyticalModel({ definition, source, filteredRows: nextFilteredRows, grouping })\n\t\t\t\t: groupedModel!;\n\n\t\t\tconst rebuildSorting = !sortedModel || rebuildGroups || sortingChanged;\n\t\t\tconst nextSortedModel = rebuildSorting ? sortAnalyticalModel(nextGroupedModel, sorting, definition.fieldsById) : sortedModel!;\n\n\t\t\tconst nextExpandedModel =\n\t\t\t\t!expandedModel || rebuildSorting || expansionChanged\n\t\t\t\t\t? projectAnalyticalTableExpansion(rebuildSorting ? nextSortedModel : (expandedModel ?? nextSortedModel), expandedRowIds)\n\t\t\t\t\t: expandedModel;\n\n\t\t\t// Ошибка callback не должна оставлять стадии от разных состояний в одном runtime.\n\t\t\tfilteredRows = nextFilteredRows;\n\t\t\tgroupedModel = nextGroupedModel;\n\t\t\tsortedModel = nextSortedModel;\n\t\t\texpandedModel = nextExpandedModel;\n\t\t\tpreviousState = { filters, grouping, sorting, expandedRowIds };\n\t\t\treturn expandedModel;\n\t\t}\n\t};\n}\n","import { compileAnalyticalTableDefinition } from \"./definition/compileAnalyticalTableDefinition\";\nimport { createAnalyticalTableRuntime } from \"./runtime/createAnalyticalTableRuntime\";\nimport { type AnalyticalTableModel, type BuildAnalyticalTableModelOptions } from \"./runtime/types\";\n\n/**\n * Строит таблицу за один вызов: описание → runtime снимка → модель представления.\n * Для последовательных изменений состояния сохраняйте определение и runtime отдельно.\n */\nexport function buildAnalyticalTableModel<T>(options: BuildAnalyticalTableModelOptions<T>): AnalyticalTableModel<T> {\n\tconst definition = compileAnalyticalTableDefinition(options);\n\tconst runtime = createAnalyticalTableRuntime({ definition, snapshot: options.snapshot });\n\n\treturn runtime.getModel(options.state);\n}\n","import {\n\taddCalendarDays,\n\taddCalendarMonths,\n\taddCalendarYears,\n\tcreateCalendarDate,\n\tformatDateAsDate,\n\tformatDateAsODataDate,\n\tgetStartOfDay,\n\tgetStartOfMonth,\n\tgetStartOfWeek,\n\tgetStartOfYear,\n\tparseDateByPattern\n} from \"../../formatters\";\nimport { aggregateAnalyticalValues } from \"../runtime/aggregation\";\nimport { type AnalyticalDataRow, type AnalyticalValues } from \"../runtime/types\";\nimport { analyticalIdentity } from \"../runtime/valueComparison\";\n\nimport {\n\ttype AnalyticalDateColumn,\n\ttype AnalyticalDateColumnsOptions,\n\ttype AnalyticalDateColumnsPlan,\n\ttype ProjectAnalyticalDateFactsOptions\n} from \"./types\";\n\n/** Принимает только календарный контракт; преобразование timestamp принадлежит transport/domain адаптеру. */\nfunction readCalendarDate(value: unknown): Date | null {\n\tif (typeof value !== \"string\" || value.length !== 10) return null;\n\tconst parsed = parseDateByPattern(value, \"yyyy-MM-dd\");\n\treturn parsed?.kind === \"date-time\" ? parsed.date : null;\n}\n\nfunction getDateBucketStart(date: Date, granularity: AnalyticalDateColumnsOptions[\"granularity\"]): Date {\n\tswitch (granularity) {\n\t\tcase \"day\":\n\t\t\treturn getStartOfDay(date);\n\t\tcase \"week\":\n\t\t\treturn getStartOfWeek(date, 1);\n\t\tcase \"month\":\n\t\t\treturn getStartOfMonth(date);\n\t\tcase \"quarter\":\n\t\t\treturn createCalendarDate(date.getFullYear(), Math.floor(date.getMonth() / 3) * 3, 1);\n\t\tcase \"year\":\n\t\t\treturn getStartOfYear(date);\n\t}\n}\n\nfunction getNextDateBucketStart(date: Date, granularity: AnalyticalDateColumnsOptions[\"granularity\"]): Date {\n\tswitch (granularity) {\n\t\tcase \"day\":\n\t\t\treturn addCalendarDays(date, 1);\n\t\tcase \"week\":\n\t\t\treturn addCalendarDays(date, 7);\n\t\tcase \"month\":\n\t\t\treturn addCalendarMonths(date, 1);\n\t\tcase \"quarter\":\n\t\t\treturn addCalendarMonths(date, 3);\n\t\tcase \"year\":\n\t\t\treturn addCalendarYears(date, 1);\n\t}\n}\n\n/** Строит ограниченный календарный план; ISO-моменты времени сюда не передаются. */\nexport function createAnalyticalDateColumnsPlan(options: AnalyticalDateColumnsOptions): AnalyticalDateColumnsPlan {\n\tconst from = readCalendarDate(options.from);\n\tconst to = readCalendarDate(options.to);\n\tif (\n\t\t!from ||\n\t\t!to ||\n\t\tformatDateAsODataDate(from) !== options.from ||\n\t\tformatDateAsODataDate(to) !== options.to ||\n\t\toptions.from > options.to\n\t)\n\t\tthrow new Error(\"Некорректный календарный диапазон аналитических столбцов.\");\n\tconst maxColumns = options.maxColumns ?? 366;\n\tif (!Number.isSafeInteger(maxColumns) || maxColumns < 1)\n\t\tthrow new Error(\"Лимит динамических столбцов должен быть положительным целым числом.\");\n\tif (!options.id || options.identityColumnIds.length === 0)\n\t\tthrow new Error(\"Динамическим столбцам нужны идентификатор и ключи сопоставления фактов.\");\n\n\t// Идентификатор относится ко всему календарному периоду, границы отбора — только к запрошенной части периода.\n\tconst columns: AnalyticalDateColumn[] = [];\n\tlet start = getDateBucketStart(from, options.granularity);\n\twhile (start <= to) {\n\t\tif (columns.length >= maxColumns) throw new Error(`Превышен лимит динамических столбцов: ${maxColumns}`);\n\t\tconst nextStart = getNextDateBucketStart(start, options.granularity);\n\t\tconst key = formatDateAsODataDate(start);\n\t\tconst end = formatDateAsODataDate(addCalendarDays(nextStart, -1));\n\t\tcolumns.push({\n\t\t\tid: `${options.id}:${options.granularity}:${key}`,\n\t\t\t// Подпись дня следует общей настройке date; машинные даты используют штатный odata-date.\n\t\t\tlabel: options.granularity === \"day\" ? formatDateAsDate(start) : `${key} — ${end}`,\n\t\t\tfrom: key < options.from ? options.from : key,\n\t\t\tto: end > options.to ? options.to : end\n\t\t});\n\t\tstart = nextStart;\n\t}\n\treturn { options: { ...options, identityColumnIds: [...options.identityColumnIds] }, columns };\n}\n\nfunction resolveFactColumnId(fact: AnalyticalValues, plan: AnalyticalDateColumnsPlan): string | undefined {\n\t// Факт без полного ключа нельзя сопоставить строке; общий итог использует ту же область допустимых фактов.\n\tif (plan.options.identityColumnIds.some((id) => fact[id] === undefined || fact[id] === null)) return undefined;\n\tconst date = readCalendarDate(fact[plan.options.dateColumnId]);\n\tif (!date) return undefined;\n\tconst day = formatDateAsODataDate(date);\n\tif (day < plan.options.from || day > plan.options.to) return undefined;\n\treturn `${plan.options.id}:${plan.options.granularity}:${formatDateAsODataDate(getDateBucketStart(date, plan.options.granularity))}`;\n}\n\n/** Индекс содержит исходные значения мер: выбор способа агрегации происходит после сопоставления фактов. */\nfunction indexFactMeasuresByIdentity(\n\tfacts: readonly AnalyticalValues[],\n\tplan: AnalyticalDateColumnsPlan\n): ReadonlyMap<string, ReadonlyMap<string, readonly unknown[]>> {\n\tconst byIdentity = new Map<string, Map<string, unknown[]>>();\n\tfor (const fact of facts) {\n\t\tconst columnId = resolveFactColumnId(fact, plan);\n\t\tif (!columnId) continue;\n\t\tconst identity = analyticalIdentity(fact, plan.options.identityColumnIds);\n\t\tlet buckets = byIdentity.get(identity);\n\t\tif (!buckets) {\n\t\t\tbuckets = new Map();\n\t\t\tbyIdentity.set(identity, buckets);\n\t\t}\n\t\tconst bucket = buckets.get(columnId);\n\t\tif (bucket) bucket.push(fact[plan.options.measureColumnId]);\n\t\telse buckets.set(columnId, [fact[plan.options.measureColumnId]]);\n\t}\n\treturn byIdentity;\n}\n\n/** Сопоставляет отдельные facts составному ключу строки; порядок и количество base rows неизменны. */\nexport function projectAnalyticalDateFacts<T>(args: ProjectAnalyticalDateFactsOptions<T>): readonly AnalyticalDataRow<T>[] {\n\tconst { rows, facts, plan } = args;\n\tconst byIdentity = indexFactMeasuresByIdentity(facts, plan);\n\treturn rows.map((row) => {\n\t\tconst buckets = byIdentity.get(analyticalIdentity(row.values, plan.options.identityColumnIds));\n\t\tconst values: Record<string, unknown> = { ...row.values };\n\t\tfor (const column of plan.columns) {\n\t\t\tif (Object.hasOwn(values, column.id)) throw new Error(`Динамический столбец перезаписывает исходное поле: ${column.id}`);\n\t\t\tconst bucket = buckets?.get(column.id);\n\t\t\tvalues[column.id] = bucket ? aggregateAnalyticalValues(bucket, plan.options.aggregation) : null;\n\t\t}\n\t\treturn { ...row, values };\n\t});\n}\n\n/**\n * Общие итоги считаются по исходным facts с полным ключом: среднее от средних не подменяет взвешенный результат.\n * Отбор допустимых непустых identities по области доступа и фильтрам выполняет вызывающий адаптер.\n */\nexport function aggregateAnalyticalDateFacts(facts: readonly AnalyticalValues[], plan: AnalyticalDateColumnsPlan): AnalyticalValues {\n\tconst buckets = new Map<string, unknown[]>();\n\tfor (const fact of facts) {\n\t\tconst id = resolveFactColumnId(fact, plan);\n\t\tif (!id) continue;\n\t\tconst bucket = buckets.get(id);\n\t\tif (bucket) bucket.push(fact[plan.options.measureColumnId]);\n\t\telse buckets.set(id, [fact[plan.options.measureColumnId]]);\n\t}\n\treturn Object.fromEntries(\n\t\tplan.columns.map((column) => {\n\t\t\tconst bucket = buckets.get(column.id);\n\t\t\treturn [column.id, bucket ? aggregateAnalyticalValues(bucket, plan.options.aggregation) : null];\n\t\t})\n\t);\n}\n","import {\n\ttype AnalyticalExportColumn,\n\ttype AnalyticalExportProjection,\n\ttype AnalyticalTableModel,\n\ttype ProjectAnalyticalTableExportOptions\n} from \"../types\";\n\n/** ID итога устойчив между областями экспорта и не конфликтует даже со скрытой строкой модели. */\nfunction resolveGrandTotalId<T>(model: AnalyticalTableModel<T>): string {\n\tconst baseId = \"analytical-grand-total\";\n\tlet id = baseId;\n\tlet suffix = 1;\n\twhile (model.rowById.has(id)) id = `${baseId}:${suffix++}`;\n\treturn id;\n}\n\n/** Проекция для /excel или /table-document; сам runtime не скачивает файлы и не читает DOM. */\nexport function projectAnalyticalTableExport<T>(args: ProjectAnalyticalTableExportOptions<T>): AnalyticalExportProjection {\n\tconst { model, scope = \"all\", includeGroups = true, includeGrandTotals = false } = args;\n\tconst columns: readonly AnalyticalExportColumn<T>[] = args.columns ?? model.columns;\n\tconst selected = new Set(args.selectedRowIds ?? []);\n\tconst source = scope === \"visible\" ? model.visibleRows : model.flatRows;\n\tconst rows: AnalyticalExportProjection[\"rows\"][number][] = [];\n\n\tfor (const row of source) {\n\t\tif (!includeGroups && row.kind === \"group\") continue;\n\t\tif (scope === \"selected\" && !selected.has(row.id)) continue;\n\t\trows.push({\n\t\t\tid: row.id,\n\t\t\tlevel: row.level,\n\t\t\tkind: row.kind,\n\t\t\tvalues: columns.map((column) => (column.format ? column.format(row.values[column.id], row) : row.values[column.id]))\n\t\t});\n\t}\n\n\tif (includeGrandTotals && model.grandTotals) {\n\t\tconst totals = model.grandTotals;\n\t\trows.push({\n\t\t\tid: resolveGrandTotalId(model),\n\t\t\tlevel: 0,\n\t\t\tkind: \"grand\",\n\t\t\tvalues: columns.map((column) => (column.formatTotal ? column.formatTotal(totals[column.id]) : totals[column.id]))\n\t\t});\n\t}\n\treturn { columns: columns.map((column) => ({ id: column.id, label: column.label ?? column.id })), rows };\n}\n"],"mappings":";;;;;;;;AAGA,SAAgB,EAA0B,GAA4B,GAAmD;CACxH,IAAM,IAAU,EAAO,QAAQ,MAAU,KAAU,QAA+B,MAAU,EAAE;CAC9F,IAAI,MAAgB,SAAS,OAAO,EAAQ;CAE5C,IAAI,IAAQ,GACR,IAAM,GACN,IAAU,UACV,IAAU;CAEd,KAAK,IAAM,KAAS,GACf,OAAO,KAAU,YAAY,CAAC,OAAO,SAAS,CAAK,MACvD,KAAS,GACT,KAAO,GACP,IAAU,KAAK,IAAI,GAAS,CAAK,GACjC,IAAU,KAAK,IAAI,GAAS,CAAK;CAGlC,IAAI,MAAU,GAAG,OAAO;CAExB,QAAQ,GAAR;EACC,KAAK,OACJ,OAAO;EACR,KAAK,OACJ,OAAO;EACR,KAAK,OACJ,OAAO;EACR,KAAK,OACJ,OAAO,IAAM;CACf;AACD;;;AC3BA,SAAgB,EACf,GACA,IAAuC,EAAQ,KAAK,MAAW,EAAO,EAAE,GAC5C;CAC5B,IAAM,IAAO,IAAI,IAAI,EAAQ,KAAK,MAAW,CAAC,EAAO,IAAI,CAAM,CAAC,CAAC;CACjE,IAAI,EAAK,SAAS,EAAQ,QAAQ,MAAU,MAAM,8DAA8D;CAChH,IAAM,oBAAU,IAAI,IAAY,GAC1B,oBAAW,IAAI,IAAY,GAC3B,IAAqB,CAAC,GACtB,IAAqC,CAAC,GACtC,KAAS,MAAqB;EACnC,IAAI,EAAQ,IAAI,CAAE,GAAG;EACrB,IAAI,EAAS,IAAI,CAAE,GAAG,MAAU,MAAM,mDAAmD,GAAI;EAC7F,IAAM,IAAS,EAAK,IAAI,CAAE;EAC1B,IAAI,CAAC,GAAQ,MAAU,MAAM,mDAAmD,GAAI;EACpF,IAAI,EAAO,WAAW,EAAO,WAAW,MAAU,MAAM,WAAW,EAAG,kCAAkC;EACxG,EAAS,IAAI,CAAE;EACf,IAAM,IAAe,EAAiB,EAAO,SAAS,gBAAgB,EAAO,WAAW,gBAAgB,CAAC,CAAC;EAC1G,KAAK,IAAM,KAAc,GAAc,EAAM,CAAU;EACvD,IAAI,EAAO,SAAS;GAEnB,IAAM,IAAW,EAAoB;IAAE,WAAW,EAAO,QAAQ;IAAW,MAAM,EAAO,QAAQ;GAAa,CAAC;GAC/G,IAAI,CAAC,EAAS,IAAI,MAAU,MAAM,mBAAmB,EAAG,wBAAwB,EAAO,QAAQ,WAAW;GAC1G,EAAM,KAAK;IACV,UAAU;IACV;IACA,UAAU,MAAW;KACpB,IAAM,IAAS,EAAS,QAAQ,CAAM;KACtC,IAAI,CAAC,EAAO,IAAI,MAAU,MAAM,0BAA0B,EAAG,IAAI,EAAO,QAAQ;KAChF,OAAO,EAAO;IACf;GACD,CAAC;EACF,OAAO,AAAI,EAAO,aACjB,EAAM,KAAK;GAAE,UAAU;GAAI;GAAc,SAAS,EAAO,UAAU;EAAQ,CAAC;EAI7E,AAFA,EAAS,OAAO,CAAE,GAClB,EAAQ,IAAI,CAAE,GACd,EAAS,KAAK,CAAE;CACjB;CACA,KAAK,IAAM,KAAM,GAAmB,EAAM,CAAE;CAC5C,OAAO;EAAE;EAAO,mBAAmB;CAAS;AAC7C;AAGA,SAAgB,EAA0B,GAA0B,GAAmD;CACtH,IAAM,IAAkC,EAAE,GAAG,EAAO;CACpD,KAAK,IAAM,KAAQ,EAAK,OAAO,EAAO,EAAK,YAAY,EAAK,QAAQ,CAAM;CAC1E,OAAO;AACR;;;ACjDA,SAAgB,EAAoC,GAAgF;CACnI,IAAM,IAAS,CAAC,GAAG,EAAW,SAAS,GAAI,EAAW,cAAc,CAAC,CAAE,GACjE,IAAe,EAAgC,CAAM;CAE3D,OAAO;EACN,SAAS,EAAW;EACpB,YAAY,IAAI,IAAI,EAAO,KAAK,MAAU,CAAC,EAAM,IAAI,CAAK,CAAC,CAAC;EAC5D;EACA,iBAAiB,EAAO,QAAQ,MAAU,EAAM,cAAc,KAAA,CAAS;EACvE,gBAAgB,EAAW;EAC3B,WAAW,EAAW;EACtB,aAAa,EAAW,gBAAgB;EACxC,kBAAkB,EAAW,oBAAoB;CAClD;AACD;;;ACbA,SAAgB,EAA0B,GAAkD,GAAkC;CAC7H,KAAK,IAAM,KAAS,CAAC,GAAI,EAAM,WAAW,CAAC,GAAI,GAAI,EAAM,WAAW,CAAC,CAAE,GACtE,IAAI,CAAC,EAAW,WAAW,IAAI,EAAM,EAAE,GACtC,MAAU,MAAM,sCAAsC,EAAM,IAAI;CAIlE,IAAM,oBAAW,IAAI,IAAY;CACjC,KAAK,IAAM,KAAS,EAAM,YAAY,CAAC,GAAG;EACzC,IAAI,EAAS,IAAI,EAAM,EAAE,GACxB,MAAU,MAAM,2DAA2D;EAE5E,IAAI,EAAM,aAAa,WAAW,GACjC,MAAU,MAAM,WAAW,EAAM,GAAG,iCAAiC;EAEtE,EAAS,IAAI,EAAM,EAAE;CACtB;AACD;;;ACbA,SAAgB,EACf,GACwE;CACxE,IAAM,IAAoC,CAAC,GACrC,IAAuC,CAAC,GACxC,oBAAU,IAAI,IAAmC,GACjD,IAAgC,CAAC;EAAE;EAAM,SAAS;EAAM,WAAW;CAAE,CAAC;CAE5E,OAAO,EAAM,SAAS,IAAG;EACxB,IAAM,IAAQ,EAAM,EAAM,SAAS;EACnC,IAAI,EAAM,cAAc,EAAM,KAAK,QAAQ;GAC1C,EAAM,IAAI;GACV;EACD;EACA,IAAM,IAAM,EAAM,KAAK,EAAM;EAI7B,AAHA,EAAS,KAAK,CAAG,GACjB,EAAQ,IAAI,EAAI,IAAI,CAAG,GACnB,EAAM,WAAS,EAAY,KAAK,CAAG,GACnC,EAAI,SAAS,SAAS,KACzB,EAAM,KAAK;GAAE,MAAM,EAAI;GAAU,SAAS,EAAM,WAAW,EAAI;GAAY,WAAW;EAAE,CAAC;CAE3F;CACA,OAAO;EAAE;EAAU;EAAa;CAAQ;AACzC;;;AC3BA,SAAgB,EAAyB,GAAgC,GAAiE;CAEzI,OADI,MAAS,EAAM,OAAa,IACzB;EAAE,GAAG;EAAO;EAAM,GAAG,EAAoB,CAAI;CAAE;AACvD;;;ACHA,SAAS,EACR,GACA,GACmC;CACnC,IAAI;CACJ,KAAK,IAAI,IAAQ,GAAG,IAAQ,EAAK,QAAQ,KAAS;EACjD,IAAM,IAAc,EAAa,IAAI,EAAK,EAAM;EAC3C,MACL,MAAc,EAAK,MAAM,GACzB,EAAU,KAAS;CACpB;CACA,OAAO,KAAa;AACrB;AAGA,SAAgB,EACf,GACA,GAC0B;CAC1B,IAAM,IAAY,MAAmB,OAC/B,IAAW,IAAI,IAAI,IAAY,CAAC,IAAI,CAAc,GAClD,oBAAe,IAAI,IAAkD;CAI3E,KAAK,IAAI,IAAQ,EAAM,SAAS,SAAS,GAAG,KAAS,GAAG,KAAS;EAChE,IAAM,IAAM,EAAM,SAAS,IACrB,IAAW,EAAoB,EAAI,UAAU,CAAY,GACzD,IAAa,EAAI,iBAAiB,KAAa,EAAS,IAAI,EAAI,EAAE;EACxE,CAAI,MAAe,EAAI,cAAc,MAAa,EAAI,aACrD,EAAa,IAAI,GAAK;GAAE,GAAG;GAAK;GAAY;EAAS,CAAC;CAExD;CAIA,OADI,EAAa,SAAS,IAAU,IAC7B,EAAsB,GAAO,EAAoB,EAAM,MAAM,CAAY,CAAC;AAClF;;;AClCA,SAAS,EACR,GACA,GACyB;CACzB,IAAM,IAA+B,CAAC,GAChC,KAAS,MAA2C;EACzD,AAAI,EAAK,aAAa,EAAgB,IAAI,EAAK,EAAE,KAChD,EAAK,KAAK,EAAK,SAAS;EAGzB,KAAK,IAAM,KAAS,EAAK,UACxB,EAAM,CAAK;CAEb;CAEA,KAAK,IAAM,KAAQ,GAClB,EAAM,CAAI;CAGX,OAAO;AACR;AAGA,SAAgB,EAA6B,GAMxB;CACpB,IAAM,EAAE,eAAY,UAAO,oBAAiB,UAAO,kBAAe,CAAC,MAAM,GACnE,IAAyC;EAC9C;EACA,MAAM,EAAqB,GAAO,CAAe;EACjD;CACD,GACM,IAAkC,EAAE,GAAG,EAAa;CAE1D,KAAK,IAAM,KAAS,EAAW,iBAAiB;EAC/C,IAAM,IAAY,EAAM;EACpB,MAAc,KAAA,MAElB,EAAO,EAAM,MACZ,OAAO,KAAc,aAClB,EAAU,CAAO,IACjB,EACA,EAAQ,KAAK,KAAK,MAAQ,EAAI,OAAO,EAAM,GAAG,GAC9C,CACD;CACJ;CAWA,OATA,OAAO,OAAO,GAAQ,EAAW,YAAY,CAAO,CAAC,GAS9C,EAA0B,GAAQ;EAJxC,GAAG,EAAW;EACd,OAAO,EAAW,aAAa,MAAM,QAAQ,MAAS,CAAC,OAAO,OAAO,GAAQ,EAAK,QAAQ,CAAC;CAGnD,CAAY;AACtD;;;AC/DA,SAAgB,EAAmB,GAA0B,GAAgC;CAC5F,OAAO,EACN,EAAI,KAAK,MAAO;EACf,IAAM,IAAQ,EAAO;EACrB,OAAO;GAAC;GAAI,MAAU,OAAO,SAAS,OAAO;GAAO;EAAK;CAC1D,CAAC,CACF;AACD;AAEA,SAAgB,EAA2B,GAAe,GAAgB,GAAsC;CAC/G,IAAI,OAAO,GAAG,GAAM,CAAK,GAAG,OAAO;CACnC,IAAI,KAAS,MAA4B,OAAO;CAChD,IAAI,KAAU,MAA6B,OAAO;CAClD,IAAI,GAAQ,SAAS,OAAO,EAAO,QAAQ,GAAM,CAAK;CACtD,IAAI,GAAQ,cAAc,QAAQ;EACjC,IAAM,IAAW,EAAU,CAAI,GACzB,IAAY,EAAU,CAAK;EACjC,IAAI,KAAY,GAAW,OAAO,EAAS,QAAQ,IAAI,EAAU,QAAQ;CAC1E;CAGA,OAFI,OAAO,KAAS,YAAY,OAAO,KAAU,WAAiB,IAAO,IACrE,OAAO,KAAS,aAAa,OAAO,KAAU,YAAkB,OAAO,CAAI,IAAI,OAAO,CAAK,IACxF,EAAe,OAAO,CAAI,GAAG,OAAO,CAAK,CAAC;AAClD;;;ACnBA,SAAgB,EAA4B,GAKF;CACzC,IAAM,EAAE,aAAU,eAAY,cAAW,GACnC,KACL,GACA,GACA,GACA,MAC2C;EAC3C,IAAM,IAAQ,EAAS;EACvB,IAAI,CAAC,GAAO,OAAO;EAEnB,IAAM,oBAAU,IAAI,IAA0C;EAC9D,KAAK,IAAM,KAAO,GAAM;GACvB,IAAM,IAAM,EAAmB,EAAI,QAAQ,EAAM,YAAY,GACvD,IAAS,EAAQ,IAAI,CAAG;GAC9B,AAAI,IAAQ,EAAO,KAAK,CAAG,IACtB,EAAQ,IAAI,GAAK,CAAC,CAAG,CAAC;EAC5B;EAEA,OAAO,MAAM,KAAK,IAAU,CAAC,GAAK,OAAa;GAC9C,IAAM,IAAW;IAAC,GAAG;IAAc,EAAM;IAAI;GAAG,GAC1C,IAAK,oBAAoB,EAAgB,CAAQ;GACvD,IAAI,EAAO,aAAa,IAAI,CAAE,GAC7B,MAAU,MAAM,mDAAmD,GAAI;GAGxE,IAAM,IAAwC,EAAE,GAAG,EAAK;GACxD,KAAK,IAAM,KAAW,CAAC,GAAG,EAAM,cAAc,GAAI,EAAM,oBAAoB,CAAC,CAAE,GAC9E,EAAa,KAAW,EAAQ,EAAE,CAAC,OAAO;GAG3C,OAAO;IACN;IACA,MAAM;IACN,iBAAiB,EAAM;IACvB,QAAQ,EAA0B;KACjC;KACA,OAAO;KACP,iBAAiB,EAAO;KACxB,OAAO;KACP;IACD,CAAC;IACD,UAAU,EAAW,GAAS,IAAa,GAAG,GAAc,CAAQ;GACrE;EACD,CAAC;CACF;CAEA,OAAO,EAAW,EAAK,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC;AACvC;;;ACrDA,SAAS,EACR,GACA,IAA0B,MAC1B,IAAQ,GACkB;CAC1B,OAAO,EAAM,KAAK,OAAU;EAC3B,IAAI,EAAK;EACT;EACA,MAAM,EAAK;EACX,WAAW,EAAK;EAChB,UAAU,EAAK,WAAW;EAC1B,QAAQ,EAAK;EACb;EACA,UAAU,EAAgB,EAAK,UAAU,EAAK,IAAI,IAAQ,CAAC;EAC3D,cAAc,EAAK,SAAS,SAAS;EACrC,YAAY;EACZ,iBAAiB,EAAK;CACvB,EAAE;AACH;AAGA,SAAgB,EAA+B,GAKnB;CAC3B,IAAM,EAAE,eAAY,WAAQ,iBAAc,gBAAa,GAEjD,IAAO,EADK,EAAyB;EAAE,MAAM;EAAc;EAAU;EAAY;CAAO,CACjE,CAAS,GAChC,IAAc,EAAW,cAC5B,EAA0B;EAC1B;EACA,OAAO,EAAW,qBAAqB,QAAQ,EAAO,OAAO;EAC7D,iBAAiB,EAAO;EACxB,OAAO;CACR,CAAC,IACA;CAEH,OAAO;EACN,SAAS,EAAW;EACpB;EACA,GAAG,EAAoB,CAAI;EAC3B;EACA,aAAa,EAAO;CACrB;AACD;;;AChDA,SAAgB,EAA2B,GAA2B,GAA0B,GAAuC;CACtI,IAAM,IAAQ,EAAI,OAAO,EAAO;CAChC,IAAI,GAAQ,QAAQ,OAAO,EAAO,OAAO,GAAO,GAAQ,CAAG;CAC3D,IAAM,IAAW,EAAO,OAClB,KAAW,MAAmB,EAAwB,GAAO,GAAO,CAAM,GAC1E,IAAQ,KAAU,QAA+B,MAAU;CACjE,QAAQ,EAAO,YAAY,UAA3B;EACC,KAAK,UACJ,OAAO,EAAQ,CAAQ,MAAM;EAC9B,KAAK,aACJ,OAAO,EAAQ,CAAQ,MAAM;EAC9B,KAAK,YACJ,OAAO,EAAqB,OAAO,KAAS,EAAE,CAAC,CAAC,CAAC,SAAS,EAAqB,OAAO,KAAY,EAAE,CAAC,CAAC;EACvG,KAAK,cACJ,OAAO,EAAqB,OAAO,KAAS,EAAE,CAAC,CAAC,CAAC,WAAW,EAAqB,OAAO,KAAY,EAAE,CAAC,CAAC;EACzG,KAAK,MACJ,OAAO,MAAM,QAAQ,CAAQ,KAAK,EAAS,MAAM,MAAkB,EAAQ,CAAI,MAAM,CAAC;EACvF,KAAK,WACJ,OAAO,MAAM,QAAQ,CAAQ,KAAK,EAAS,WAAW,KAAK,CAAC,KAAS,EAAQ,EAAS,EAAE,KAAK,KAAK,EAAQ,EAAS,EAAE,KAAK;EAC3H,KAAK,MACJ,OAAO,CAAC,KAAS,EAAQ,CAAQ,IAAI;EACtC,KAAK,OACJ,OAAO,CAAC,KAAS,EAAQ,CAAQ,KAAK;EACvC,KAAK,MACJ,OAAO,CAAC,KAAS,EAAQ,CAAQ,IAAI;EACtC,KAAK,OACJ,OAAO,CAAC,KAAS,EAAQ,CAAQ,KAAK;EACvC,KAAK,SACJ,OAAO;EACR,KAAK,YACJ,OAAO,CAAC;CACV;AACD;AAGA,SAAgB,EACf,GACA,GACA,GACwC;CACxC,IAAI,EAAQ,WAAW,GAAG,OAAO;CAEjC,IAAM,IAAyC,CAAC;CAChD,KAAK,IAAM,KAAO,GAAM;EACvB,IAAM,IAAY,EAAI;EAEtB,IADgB,KAAa,EAAQ,OAAO,MAAW,EAAwB,GAAW,GAAQ,EAAW,IAAI,EAAO,EAAE,CAAC,CAAC,GAC/G;GACZ,EAAS,KAAK,CAAG;GACjB;EACD;EAEA,IAAM,IAAW,EAA0B,EAAI,UAAU,GAAS,CAAU;EAC5E,AAAI,EAAS,SAAS,KACrB,EAAS,KAAK;GAAE,GAAG;GAAK;EAAS,CAAC;CAEpC;CAEA,OAAO;AACR;;;ACzCA,SAAgB,EACf,GACA,GAC+B;CAC/B,IAAI,EAAS,KAAK,MAAM,MAAQ,EAAI,GAAG,WAAW,CAAC,GAClD,MAAU,MAAM,0DAA0D;CAG3E,IAAM,IAAiB,EAAS,KAAK,KAAK,OAAS;EAClD,GAAG;EACH,QAAQ,EAA0B,EAAI,QAAQ,EAAW,YAAY;CACtE,EAAE,GACI,IAAO,EAAmB,GAAgB;EAC/C,WAAW,MAAQ,EAAI;EACvB,iBAAiB,MAAQ,EAAI;CAC9B,CAAC,GAEK,KAAe,OAA8E;EAClG,IAAI,EAAK;EACT,MAAM;EACN,WAAW,EAAK,QAAQ,IAAI,EAAK,EAAE;EACnC,QAAQ,EAAK;EACb,WAAW,EAAK,YAAY,CAAC,EAAA,CAAG,IAAI,CAAW;CAChD,IACM,IAAkB,EAAW,iBAChC,MAAM,KAAK,EAAK,QAAQ,OAAO,CAAC,CAAC,CAChC,OAAO,EAAW,cAAc,CAAC,CACjC,KAAK,MAAQ,EAAI,EAAE,IACpB,EAAK;CAER,OAAO;EACN,MAAM,EAAK,KAAK,IAAI,CAAW;EAC/B,cAAc,IAAI,IAAI,EAAK,SAAS;EACpC,iBAAiB,IAAI,IAAI,CAAe;EACxC,aAAa;GACZ,cAAc,EAAK;GACnB,iBAAiB,EAAK;GACtB,cAAc,EAAK;EACpB;CACD;AACD;;;ACzDA,SAAgB,EACf,GACA,GACA,GAC0B;CAC1B,IAAI,EAAQ,WAAW,GAAG,OAAO;CAEjC,IAAM,KAAe,GAA6B,MAAyC;EAC1F,KAAK,IAAM,KAAQ,GAAS;GAC3B,IAAM,IAAa,EAAwB,EAAK,OAAO,EAAK,KAAK,EAAM,OAAO,EAAK,KAAK,EAAW,IAAI,EAAK,EAAE,CAAC;GAC/G,IAAI,MAAe,GAAG,OAAO,EAAK,OAAO,CAAC,IAAa;EACxD;EACA,OAAO;CACR,GACM,KAAc,MAA6E;EAChG,IAAI,EAAK,WAAW,GAAG,OAAO;EAE9B,IAAM,IAAY,EAAK,KAAK,MAAQ;GACnC,IAAM,IAAW,EAAW,EAAI,QAAQ;GACxC,OAAO,MAAa,EAAI,WAAW,IAAM;IAAE,GAAG;IAAK;GAAS;EAC7D,CAAC;EAGD,OAFA,EAAU,KAAK,CAAW,GAEnB,EAAU,OAAO,GAAK,MAAU,MAAQ,EAAK,EAAM,IAAI,IAAO;CACtE;CAEA,OAAO,EAAsB,GAAO,EAAW,EAAM,IAAI,CAAC;AAC3D;;;ACpBA,IAAM,IAAmC,CAAC,GACpC,IAAc,OAAO,OAAO,CAAC,CAAC;AASpC,SAAgB,EAAgC,GAA4E;CAC3H,IAAM,EAAE,eAAY,gBAAa,GAC3B,IAAS,EAA2B,GAAU,CAAU,GAC1D,IAAqC,GACrC,IAAe,EAAO,MACtB,GACA,GACA;CAEJ,OAAO,EACN,SAAS,IAAQ,GAAa;EAC7B,EAAuB,GAAY,CAAK;EACxC,IAAM,IAAU,EAAM,WAAW,GAC3B,IAAW,EAAM,YAAY,GAC7B,IAAU,EAAM,WAAW,GAC3B,IAAiB,EAAM,kBAAkB,GACzC,IAAiB,CAAC,KAAgB,OAAa,EAAc,WAAW,IACxE,IAAkB,CAAC,KAAgB,OAAc,EAAc,YAAY,IAC3E,IAAiB,OAAa,EAAc,WAAW,IACvD,IAAmB,OAAoB,EAAc,kBAAkB,IAEvE,IAAmB,IAAiB,EAA0B,EAAO,MAAM,GAAS,EAAW,UAAU,IAAI,GAE7G,IAAgB,CAAC,KAAgB,KAAkB,GACnD,IAAmB,IACtB,EAA4B;GAAE;GAAY;GAAQ,cAAc;GAAkB;EAAS,CAAC,IAC5F,GAEG,IAAiB,CAAC,KAAe,KAAiB,GAClD,IAAkB,IAAiB,EAAoB,GAAkB,GAAS,EAAW,UAAU,IAAI,GAE3G,IACL,CAAC,KAAiB,KAAkB,IACjC,EAAgC,IAAiB,IAAmB,KAAiB,GAAkB,CAAc,IACrH;EAQJ,OALA,IAAe,GACf,IAAe,GACf,IAAc,GACd,IAAgB,GAChB,IAAgB;GAAE;GAAS;GAAU;GAAS;EAAe,GACtD;CACR,EACD;AACD;;;AC7DA,SAAgB,EAA6B,GAAuE;CAInH,OAFgB,EAA6B;EAAE,YAD5B,EAAiC,CACL;EAAY,UAAU,EAAQ;CAAS,CAE/E,CAAA,CAAQ,SAAS,EAAQ,KAAK;AACtC;;;ACYA,SAAS,EAAiB,GAA6B;CACtD,IAAI,OAAO,KAAU,YAAY,EAAM,WAAW,IAAI,OAAO;CAC7D,IAAM,IAAS,EAAmB,GAAO,YAAY;CACrD,OAAO,GAAQ,SAAS,cAAc,EAAO,OAAO;AACrD;AAEA,SAAS,EAAmB,GAAY,GAAgE;CACvG,QAAQ,GAAR;EACC,KAAK,OACJ,OAAO,EAAc,CAAI;EAC1B,KAAK,QACJ,OAAO,EAAe,GAAM,CAAC;EAC9B,KAAK,SACJ,OAAO,EAAgB,CAAI;EAC5B,KAAK,WACJ,OAAO,EAAmB,EAAK,YAAY,GAAG,KAAK,MAAM,EAAK,SAAS,IAAI,CAAC,IAAI,GAAG,CAAC;EACrF,KAAK,QACJ,OAAO,EAAe,CAAI;CAC5B;AACD;AAEA,SAAS,EAAuB,GAAY,GAAgE;CAC3G,QAAQ,GAAR;EACC,KAAK,OACJ,OAAO,EAAgB,GAAM,CAAC;EAC/B,KAAK,QACJ,OAAO,EAAgB,GAAM,CAAC;EAC/B,KAAK,SACJ,OAAO,EAAkB,GAAM,CAAC;EACjC,KAAK,WACJ,OAAO,EAAkB,GAAM,CAAC;EACjC,KAAK,QACJ,OAAO,EAAiB,GAAM,CAAC;CACjC;AACD;AAGA,SAAgB,EAAgC,GAAkE;CACjH,IAAM,IAAO,EAAiB,EAAQ,IAAI,GACpC,IAAK,EAAiB,EAAQ,EAAE;CACtC,IACC,CAAC,KACD,CAAC,KACD,EAAsB,CAAI,MAAM,EAAQ,QACxC,EAAsB,CAAE,MAAM,EAAQ,MACtC,EAAQ,OAAO,EAAQ,IAEvB,MAAU,MAAM,2DAA2D;CAC5E,IAAM,IAAa,EAAQ,cAAc;CACzC,IAAI,CAAC,OAAO,cAAc,CAAU,KAAK,IAAa,GACrD,MAAU,MAAM,qEAAqE;CACtF,IAAI,CAAC,EAAQ,MAAM,EAAQ,kBAAkB,WAAW,GACvD,MAAU,MAAM,yEAAyE;CAG1F,IAAM,IAAkC,CAAC,GACrC,IAAQ,EAAmB,GAAM,EAAQ,WAAW;CACxD,OAAO,KAAS,IAAI;EACnB,IAAI,EAAQ,UAAU,GAAY,MAAU,MAAM,yCAAyC,GAAY;EACvG,IAAM,IAAY,EAAuB,GAAO,EAAQ,WAAW,GAC7D,IAAM,EAAsB,CAAK,GACjC,IAAM,EAAsB,EAAgB,GAAW,EAAE,CAAC;EAQhE,AAPA,EAAQ,KAAK;GACZ,IAAI,GAAG,EAAQ,GAAG,GAAG,EAAQ,YAAY,GAAG;GAE5C,OAAO,EAAQ,gBAAgB,QAAQ,EAAiB,CAAK,IAAI,GAAG,EAAI,KAAK;GAC7E,MAAM,IAAM,EAAQ,OAAO,EAAQ,OAAO;GAC1C,IAAI,IAAM,EAAQ,KAAK,EAAQ,KAAK;EACrC,CAAC,GACD,IAAQ;CACT;CACA,OAAO;EAAE,SAAS;GAAE,GAAG;GAAS,mBAAmB,CAAC,GAAG,EAAQ,iBAAiB;EAAE;EAAG;CAAQ;AAC9F;AAEA,SAAS,EAAoB,GAAwB,GAAqD;CAEzG,IAAI,EAAK,QAAQ,kBAAkB,MAAM,MAAO,EAAK,OAAQ,KAAA,KAAa,EAAK,OAAQ,IAAI,GAAG;CAC9F,IAAM,IAAO,EAAiB,EAAK,EAAK,QAAQ,aAAa;CAC7D,IAAI,CAAC,GAAM;CACX,IAAM,IAAM,EAAsB,CAAI;CAClC,UAAM,EAAK,QAAQ,QAAQ,IAAM,EAAK,QAAQ,KAClD,OAAO,GAAG,EAAK,QAAQ,GAAG,GAAG,EAAK,QAAQ,YAAY,GAAG,EAAsB,EAAmB,GAAM,EAAK,QAAQ,WAAW,CAAC;AAClI;AAGA,SAAS,EACR,GACA,GAC+D;CAC/D,IAAM,oBAAa,IAAI,IAAoC;CAC3D,KAAK,IAAM,KAAQ,GAAO;EACzB,IAAM,IAAW,EAAoB,GAAM,CAAI;EAC/C,IAAI,CAAC,GAAU;EACf,IAAM,IAAW,EAAmB,GAAM,EAAK,QAAQ,iBAAiB,GACpE,IAAU,EAAW,IAAI,CAAQ;EACrC,AAAK,MACJ,oBAAU,IAAI,IAAI,GAClB,EAAW,IAAI,GAAU,CAAO;EAEjC,IAAM,IAAS,EAAQ,IAAI,CAAQ;EACnC,AAAI,IAAQ,EAAO,KAAK,EAAK,EAAK,QAAQ,gBAAgB,IACrD,EAAQ,IAAI,GAAU,CAAC,EAAK,EAAK,QAAQ,gBAAgB,CAAC;CAChE;CACA,OAAO;AACR;AAGA,SAAgB,EAA8B,GAA6E;CAC1H,IAAM,EAAE,SAAM,UAAO,YAAS,GACxB,IAAa,EAA4B,GAAO,CAAI;CAC1D,OAAO,EAAK,KAAK,MAAQ;EACxB,IAAM,IAAU,EAAW,IAAI,EAAmB,EAAI,QAAQ,EAAK,QAAQ,iBAAiB,CAAC,GACvF,IAAkC,EAAE,GAAG,EAAI,OAAO;EACxD,KAAK,IAAM,KAAU,EAAK,SAAS;GAClC,IAAI,OAAO,OAAO,GAAQ,EAAO,EAAE,GAAG,MAAU,MAAM,sDAAsD,EAAO,IAAI;GACvH,IAAM,IAAS,GAAS,IAAI,EAAO,EAAE;GACrC,EAAO,EAAO,MAAM,IAAS,EAA0B,GAAQ,EAAK,QAAQ,WAAW,IAAI;EAC5F;EACA,OAAO;GAAE,GAAG;GAAK;EAAO;CACzB,CAAC;AACF;AAMA,SAAgB,EAA6B,GAAoC,GAAmD;CACnI,IAAM,oBAAU,IAAI,IAAuB;CAC3C,KAAK,IAAM,KAAQ,GAAO;EACzB,IAAM,IAAK,EAAoB,GAAM,CAAI;EACzC,IAAI,CAAC,GAAI;EACT,IAAM,IAAS,EAAQ,IAAI,CAAE;EAC7B,AAAI,IAAQ,EAAO,KAAK,EAAK,EAAK,QAAQ,gBAAgB,IACrD,EAAQ,IAAI,GAAI,CAAC,EAAK,EAAK,QAAQ,gBAAgB,CAAC;CAC1D;CACA,OAAO,OAAO,YACb,EAAK,QAAQ,KAAK,MAAW;EAC5B,IAAM,IAAS,EAAQ,IAAI,EAAO,EAAE;EACpC,OAAO,CAAC,EAAO,IAAI,IAAS,EAA0B,GAAQ,EAAK,QAAQ,WAAW,IAAI,IAAI;CAC/F,CAAC,CACF;AACD;;;AC9JA,SAAS,EAAuB,GAAwC;CACvE,IAAM,IAAS,0BACX,IAAK,GACL,IAAS;CACb,OAAO,EAAM,QAAQ,IAAI,CAAE,IAAG,IAAK,GAAG,EAAO,GAAG;CAChD,OAAO;AACR;AAGA,SAAgB,EAAgC,GAA0E;CACzH,IAAM,EAAE,UAAO,WAAQ,OAAO,mBAAgB,IAAM,wBAAqB,OAAU,GAC7E,IAAgD,EAAK,WAAW,EAAM,SACtE,IAAW,IAAI,IAAI,EAAK,kBAAkB,CAAC,CAAC,GAC5C,IAAS,MAAU,YAAY,EAAM,cAAc,EAAM,UACzD,IAAqD,CAAC;CAE5D,KAAK,IAAM,KAAO,GACb,CAAC,KAAiB,EAAI,SAAS,WAC/B,MAAU,cAAc,CAAC,EAAS,IAAI,EAAI,EAAE,KAChD,EAAK,KAAK;EACT,IAAI,EAAI;EACR,OAAO,EAAI;EACX,MAAM,EAAI;EACV,QAAQ,EAAQ,KAAK,MAAY,EAAO,SAAS,EAAO,OAAO,EAAI,OAAO,EAAO,KAAK,CAAG,IAAI,EAAI,OAAO,EAAO,GAAI;CACpH,CAAC;CAGF,IAAI,KAAsB,EAAM,aAAa;EAC5C,IAAM,IAAS,EAAM;EACrB,EAAK,KAAK;GACT,IAAI,EAAoB,CAAK;GAC7B,OAAO;GACP,MAAM;GACN,QAAQ,EAAQ,KAAK,MAAY,EAAO,cAAc,EAAO,YAAY,EAAO,EAAO,GAAG,IAAI,EAAO,EAAO,GAAI;EACjH,CAAC;CACF;CACA,OAAO;EAAE,SAAS,EAAQ,KAAK,OAAY;GAAE,IAAI,EAAO;GAAI,OAAO,EAAO,SAAS,EAAO;EAAG,EAAE;EAAG;CAAK;AACxG"}
@@ -0,0 +1,4 @@
1
+ import { type AnalyticalTableModel } from "../types";
2
+ /** Раскрытие меняет только затронутые ветви; формулы и итоги остаются результатом базовой модели. */
3
+ export declare function projectAnalyticalTableExpansion<T>(model: AnalyticalTableModel<T>, expandedRowIds: readonly string[] | "all"): AnalyticalTableModel<T>;
4
+ //# sourceMappingURL=expansion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expansion.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/projections/expansion.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAmB9E,qGAAqG;AACrG,wBAAgB,+BAA+B,CAAC,CAAC,EAChD,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAC9B,cAAc,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,GACvC,oBAAoB,CAAC,CAAC,CAAC,CAmBzB"}
@@ -1,4 +1,4 @@
1
- import { type AnalyticalExportProjection, type ProjectAnalyticalTableExportOptions } from "./types";
1
+ import { type AnalyticalExportProjection, type ProjectAnalyticalTableExportOptions } from "../types";
2
2
  /** Проекция для /excel или /table-document; сам runtime не скачивает файлы и не читает DOM. */
3
3
  export declare function projectAnalyticalTableExport<T>(args: ProjectAnalyticalTableExportOptions<T>): AnalyticalExportProjection;
4
4
  //# sourceMappingURL=exportProjection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exportProjection.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/projections/exportProjection.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,0BAA0B,EAE/B,KAAK,mCAAmC,EACxC,MAAM,UAAU,CAAC;AAWlB,+FAA+F;AAC/F,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,IAAI,EAAE,mCAAmC,CAAC,CAAC,CAAC,GAAG,0BAA0B,CA4BxH"}
@@ -0,0 +1,4 @@
1
+ import { type AnalyticalModelRow, type AnalyticalTableModel } from "../types";
2
+ /** Строит согласованные индексы за один проход, не расходуя стек вызовов на глубину дерева. */
3
+ export declare function indexAnalyticalRows<T>(rows: readonly AnalyticalModelRow<T>[]): Pick<AnalyticalTableModel<T>, "flatRows" | "visibleRows" | "rowById">;
4
+ //# sourceMappingURL=indexAnalyticalRows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexAnalyticalRows.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/projections/indexAnalyticalRows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAQ9E,+FAA+F;AAC/F,wBAAgB,mBAAmB,CAAC,CAAC,EACpC,IAAI,EAAE,SAAS,kBAAkB,CAAC,CAAC,CAAC,EAAE,GACpC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC,CAqBvE"}
@@ -0,0 +1,4 @@
1
+ import { type AnalyticalModelRow, type AnalyticalTableModel } from "../types";
2
+ /** Любая проекция дерева заменяет индексы вместе с узлами, сохраняя уже рассчитанные итоги. */
3
+ export declare function resolveRowsProjection<T>(model: AnalyticalTableModel<T>, rows: readonly AnalyticalModelRow<T>[]): AnalyticalTableModel<T>;
4
+ //# sourceMappingURL=resolveRowsProjection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveRowsProjection.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/projections/resolveRowsProjection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAI9E,+FAA+F;AAC/F,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,kBAAkB,CAAC,CAAC,CAAC,EAAE,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAGxI"}
@@ -1,4 +1,4 @@
1
- import { type AnalyticalModelRow, type AnalyticalTableModel } from "./modelTypes";
1
+ import { type AnalyticalModelRow, type AnalyticalTableModel } from "../types";
2
2
  export type AnalyticalExportColumn<TOriginal = unknown> = Readonly<{
3
3
  id: string;
4
4
  label?: string;
@@ -28,4 +28,4 @@ export type ProjectAnalyticalTableExportOptions<TOriginal = unknown> = Readonly<
28
28
  includeGroups?: boolean;
29
29
  includeGrandTotals?: boolean;
30
30
  }>;
31
- //# sourceMappingURL=exportTypes.d.ts.map
31
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/projections/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAE9E,MAAM,MAAM,sBAAsB,CAAC,SAAS,GAAG,OAAO,IAAI,QAAQ,CAAC;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC;IACzE,oFAAoF;IACpF,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CAC1C,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE7E,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE,CAAC,CAAC;AAExI,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IACjD,OAAO,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC3C,IAAI,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACrC,CAAC,CAAC;AAEH,MAAM,MAAM,mCAAmC,CAAC,SAAS,GAAG,OAAO,IAAI,QAAQ,CAAC;IAC/E,KAAK,EAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,SAAS,sBAAsB,CAAC,SAAS,CAAC,EAAE,CAAC;IACvD,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,UAAU,CAAC;IACvC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC,CAAC"}
@@ -1,4 +1,4 @@
1
- import { type AnalyticalAggregation } from "./types";
1
+ import { type AnalyticalAggregation } from "../types";
2
2
  /** null/пустые/нечисловые значения не превращаются в ноль; count считает непустые факты. */
3
3
  export declare function aggregateAnalyticalValues(values: readonly unknown[], aggregation: AnalyticalAggregation): number | null;
4
4
  //# sourceMappingURL=aggregation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregation.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/runtime/aggregation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEtD,4FAA4F;AAC5F,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,EAAE,WAAW,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CA6BvH"}
@@ -0,0 +1,11 @@
1
+ import { type AnalyticalGroupingLevel, type CompiledAnalyticalTableDefinition } from "../definition/types";
2
+ import { type AnalyticalHierarchyNode, type AnalyticalSourceHierarchy } from "./hierarchy";
3
+ import { type AnalyticalTableModel } from "./types";
4
+ /** Базовая модель содержит все отобранные строки и итоги; порядок и раскрытие задаются позже. */
5
+ export declare function buildGroupedAnalyticalModel<T>(args: {
6
+ definition: CompiledAnalyticalTableDefinition<T>;
7
+ source: AnalyticalSourceHierarchy<T>;
8
+ filteredRows: readonly AnalyticalHierarchyNode<T>[];
9
+ grouping: readonly AnalyticalGroupingLevel[];
10
+ }): AnalyticalTableModel<T>;
11
+ //# sourceMappingURL=buildGroupedModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildGroupedModel.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/runtime/buildGroupedModel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,iCAAiC,EAAE,MAAM,qBAAqB,CAAC;AAI3G,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAE3F,OAAO,EAA2B,KAAK,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAuB7E,iGAAiG;AACjG,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,IAAI,EAAE;IACpD,UAAU,EAAE,iCAAiC,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC,CAAC;IACrC,YAAY,EAAE,SAAS,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,QAAQ,EAAE,SAAS,uBAAuB,EAAE,CAAC;CAC7C,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAoB1B"}
@@ -0,0 +1,10 @@
1
+ import { type AnalyticalTableRuntime, type CreateAnalyticalTableRuntimeOptions } from "./types";
2
+ /**
3
+ * Создаёт вычислительный runtime для одного снимка.
4
+ *
5
+ * Хранится только последний результат каждого этапа. Исходные строки рассчитываются
6
+ * один раз; фильтры/группировки меняют итоги, сортировка — порядок, раскрытие — видимость.
7
+ * Входные определения, снимки и массивы состояния должны оставаться неизменяемыми.
8
+ */
9
+ export declare function createAnalyticalTableRuntime<T>(options: CreateAnalyticalTableRuntimeOptions<T>): AnalyticalTableRuntime<T>;
10
+ //# sourceMappingURL=createAnalyticalTableRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAnalyticalTableRuntime.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/runtime/createAnalyticalTableRuntime.ts"],"names":[],"mappings":"AAOA,OAAO,EAEN,KAAK,sBAAsB,EAE3B,KAAK,mCAAmC,EACxC,MAAM,SAAS,CAAC;AAKjB;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,OAAO,EAAE,mCAAmC,CAAC,CAAC,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC,CA6C1H"}
@@ -0,0 +1,7 @@
1
+ import { type AnalyticalColumn, type AnalyticalDataRow, type AnalyticalFilter } from "../types";
2
+ import { type AnalyticalHierarchyNode } from "./hierarchy";
3
+ /** Операции фильтра относятся к данным, поэтому одинаково работают при SSR и в браузере. */
4
+ export declare function matchesAnalyticalFilter<T>(row: AnalyticalDataRow<T>, filter: AnalyticalFilter, column?: AnalyticalColumn<T>): boolean;
5
+ /** Совпавший родитель оставляет всю ветвь; совпавший ребёнок сохраняет путь к нему. */
6
+ export declare function filterAnalyticalHierarchy<T>(rows: readonly AnalyticalHierarchyNode<T>[], filters: readonly AnalyticalFilter[], fieldsById: ReadonlyMap<string, AnalyticalColumn<T>>): readonly AnalyticalHierarchyNode<T>[];
7
+ //# sourceMappingURL=filtering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filtering.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/runtime/filtering.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEhG,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAG3D,4FAA4F;AAC5F,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAgCrI;AAED,uFAAuF;AACvF,wBAAgB,yBAAyB,CAAC,CAAC,EAC1C,IAAI,EAAE,SAAS,uBAAuB,CAAC,CAAC,CAAC,EAAE,EAC3C,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAClD,SAAS,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAmBvC"}
@@ -0,0 +1,10 @@
1
+ import { type AnalyticalGroupingLevel, type CompiledAnalyticalTableDefinition } from "../definition/types";
2
+ import { type AnalyticalHierarchyNode, type AnalyticalSourceHierarchy } from "./hierarchy";
3
+ /** Группировка добавляет уровни над предметными корнями и сохраняет их дочернюю детализацию. */
4
+ export declare function groupAnalyticalHierarchy<T>(args: {
5
+ rows: readonly AnalyticalHierarchyNode<T>[];
6
+ grouping: readonly AnalyticalGroupingLevel[];
7
+ definition: CompiledAnalyticalTableDefinition<T>;
8
+ source: AnalyticalSourceHierarchy<T>;
9
+ }): readonly AnalyticalHierarchyNode<T>[];
10
+ //# sourceMappingURL=grouping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grouping.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/runtime/grouping.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,iCAAiC,EAAE,MAAM,qBAAqB,CAAC;AAE3G,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAK3F,gGAAgG;AAChG,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,IAAI,EAAE;IACjD,IAAI,EAAE,SAAS,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5C,QAAQ,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAC7C,UAAU,EAAE,iCAAiC,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC,CAAC;CACrC,GAAG,SAAS,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAgDxC"}
@@ -0,0 +1,20 @@
1
+ import { type CompiledAnalyticalTableDefinition } from "../definition/types";
2
+ import { type AnalyticalDataRow, type AnalyticalDiagnostics, type AnalyticalSnapshot, type AnalyticalValues } from "./types";
3
+ /** Узел до назначения итогового parentId/level: группировка ещё может добавить предков. */
4
+ export type AnalyticalHierarchyNode<T> = Readonly<{
5
+ id: string;
6
+ kind: "data" | "group";
7
+ sourceRow?: AnalyticalDataRow<T>;
8
+ values: AnalyticalValues;
9
+ children: readonly AnalyticalHierarchyNode<T>[];
10
+ groupingLevelId?: string;
11
+ }>;
12
+ export type AnalyticalSourceHierarchy<T> = Readonly<{
13
+ rows: readonly AnalyticalHierarchyNode<T>[];
14
+ sourceRowIds: ReadonlySet<string>;
15
+ aggregateRowIds: ReadonlySet<string>;
16
+ diagnostics: AnalyticalDiagnostics;
17
+ }>;
18
+ /** Формулы исходных строк и предметная иерархия зависят только от определения и снимка. */
19
+ export declare function prepareAnalyticalHierarchy<T>(snapshot: AnalyticalSnapshot<T>, definition: CompiledAnalyticalTableDefinition<T>): AnalyticalSourceHierarchy<T>;
20
+ //# sourceMappingURL=hierarchy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hierarchy.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/runtime/hierarchy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,iCAAiC,EAAE,MAAM,qBAAqB,CAAC;AAE7E,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE7H,2FAA2F;AAC3F,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI,QAAQ,CAAC;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,EAAE,SAAS,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,MAAM,yBAAyB,CAAC,CAAC,IAAI,QAAQ,CAAC;IACnD,IAAI,EAAE,SAAS,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5C,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,WAAW,EAAE,qBAAqB,CAAC;CACnC,CAAC,CAAC;AAEH,2FAA2F;AAC3F,wBAAgB,0BAA0B,CAAC,CAAC,EAC3C,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAC/B,UAAU,EAAE,iCAAiC,CAAC,CAAC,CAAC,GAC9C,yBAAyB,CAAC,CAAC,CAAC,CAqC9B"}
@@ -0,0 +1,5 @@
1
+ import { type AnalyticalColumn } from "../definition/types";
2
+ import { type AnalyticalSorting, type AnalyticalTableModel } from "./types";
3
+ /** Меняет только порядок соседей: вычисленные значения, итоги и связи parent/child сохраняются. */
4
+ export declare function sortAnalyticalModel<T>(model: AnalyticalTableModel<T>, sorting: readonly AnalyticalSorting[], fieldsById: ReadonlyMap<string, AnalyticalColumn<T>>): AnalyticalTableModel<T>;
5
+ //# sourceMappingURL=sorting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sorting.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/runtime/sorting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,OAAO,EAA2B,KAAK,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGrG,mGAAmG;AACnG,wBAAgB,mBAAmB,CAAC,CAAC,EACpC,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAC9B,OAAO,EAAE,SAAS,iBAAiB,EAAE,EACrC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAClD,oBAAoB,CAAC,CAAC,CAAC,CAuBzB"}
@@ -0,0 +1,12 @@
1
+ import { type CompiledAnalyticalTableDefinition } from "../definition/types";
2
+ import { type AnalyticalHierarchyNode } from "./hierarchy";
3
+ import { type AnalyticalValues } from "./types";
4
+ /** Один порядок для групповых и общих итогов: агрегации → callback → зависимые формулы. */
5
+ export declare function calculateAnalyticalTotals<T>(args: {
6
+ definition: CompiledAnalyticalTableDefinition<T>;
7
+ nodes: readonly AnalyticalHierarchyNode<T>[];
8
+ aggregateRowIds: ReadonlySet<string>;
9
+ scope: "group" | "grand";
10
+ groupingPath?: AnalyticalValues;
11
+ }): AnalyticalValues;
12
+ //# sourceMappingURL=totals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"totals.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/runtime/totals.ts"],"names":[],"mappings":"AACA,OAAO,EAAmC,KAAK,iCAAiC,EAAE,MAAM,qBAAqB,CAAC;AAG9G,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAyBxE,2FAA2F;AAC3F,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,IAAI,EAAE;IAClD,UAAU,EAAE,iCAAiC,CAAC,CAAC,CAAC,CAAC;IACjD,KAAK,EAAE,SAAS,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,gBAAgB,CAAC;CAChC,GAAG,gBAAgB,CAgCnB"}
@@ -0,0 +1,71 @@
1
+ import { type AnalyticalColumn, type AnalyticalGroupingLevel, type AnalyticalTableDefinition, type CompiledAnalyticalTableDefinition } from "../definition/types";
2
+ /** Значения таблицы отделены от исходного DTO: runtime не изменяет снимок Query. */
3
+ export type AnalyticalValues = Readonly<Record<string, unknown>>;
4
+ export type AnalyticalDataRow<TOriginal = unknown> = Readonly<{
5
+ id: string;
6
+ parentId?: string | null;
7
+ kind?: string;
8
+ original?: TOriginal;
9
+ values: AnalyticalValues;
10
+ }>;
11
+ /** Готовый полный снимок. Его загрузкой и отменой владеет транспорт потребителя. */
12
+ export type AnalyticalSnapshot<TOriginal = unknown> = Readonly<{
13
+ rows: readonly AnalyticalDataRow<TOriginal>[];
14
+ }>;
15
+ export type AnalyticalSorting = Readonly<{
16
+ id: string;
17
+ desc?: boolean;
18
+ }>;
19
+ export type AnalyticalFilter = Readonly<{
20
+ id: string;
21
+ operator?: "equals" | "notEquals" | "contains" | "startsWith" | "in" | "between" | "gt" | "gte" | "lt" | "lte" | "empty" | "notEmpty";
22
+ value?: unknown;
23
+ }>;
24
+ /** Состояние сериализуется для SSR/URL; Map и Set появляются только в результате. */
25
+ export type AnalyticalViewState = Readonly<{
26
+ grouping?: readonly AnalyticalGroupingLevel[];
27
+ sorting?: readonly AnalyticalSorting[];
28
+ filters?: readonly AnalyticalFilter[];
29
+ expandedRowIds?: readonly string[] | "all";
30
+ }>;
31
+ export type AnalyticalModelRow<TOriginal = unknown> = Readonly<{
32
+ id: string;
33
+ parentId: string | null;
34
+ kind: "data" | "group";
35
+ sourceRow?: AnalyticalDataRow<TOriginal>;
36
+ original?: TOriginal;
37
+ values: AnalyticalValues;
38
+ level: number;
39
+ children: readonly AnalyticalModelRow<TOriginal>[];
40
+ isExpandable: boolean;
41
+ isExpanded: boolean;
42
+ groupingLevelId?: string;
43
+ }>;
44
+ export type AnalyticalDiagnostics = Readonly<{
45
+ orphanRowIds: readonly string[];
46
+ duplicateRowIds: readonly string[];
47
+ cyclicRowIds: readonly string[];
48
+ }>;
49
+ export type AnalyticalTableModel<TOriginal = unknown> = Readonly<{
50
+ columns: readonly AnalyticalColumn<TOriginal>[];
51
+ rows: readonly AnalyticalModelRow<TOriginal>[];
52
+ /** Все строки результата в обходе дерева; раскрытие влияет только на visibleRows. */
53
+ flatRows: readonly AnalyticalModelRow<TOriginal>[];
54
+ visibleRows: readonly AnalyticalModelRow<TOriginal>[];
55
+ rowById: ReadonlyMap<string, AnalyticalModelRow<TOriginal>>;
56
+ grandTotals: AnalyticalValues | null;
57
+ diagnostics: AnalyticalDiagnostics;
58
+ }>;
59
+ export type BuildAnalyticalTableModelOptions<TOriginal = unknown> = AnalyticalTableDefinition<TOriginal> & Readonly<{
60
+ snapshot: AnalyticalSnapshot<TOriginal>;
61
+ state?: AnalyticalViewState;
62
+ }>;
63
+ export type CreateAnalyticalTableRuntimeOptions<TOriginal = unknown> = Readonly<{
64
+ definition: CompiledAnalyticalTableDefinition<TOriginal>;
65
+ snapshot: AnalyticalSnapshot<TOriginal>;
66
+ }>;
67
+ /** Runtime принадлежит одному неизменяемому снимку; новый снимок создаёт новый runtime. */
68
+ export type AnalyticalTableRuntime<TOriginal = unknown> = Readonly<{
69
+ getModel: (state?: AnalyticalViewState) => AnalyticalTableModel<TOriginal>;
70
+ }>;
71
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/runtime/types.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type AnalyticalColumn, type AnalyticalValues } from "./types";
1
+ import { type AnalyticalColumn, type AnalyticalValues } from "../types";
2
2
  /** Тип входит в ключ: null, undefined, строка и число не склеивают разные группы. */
3
3
  export declare function analyticalIdentity(values: AnalyticalValues, ids: readonly string[]): string;
4
4
  export declare function compareAnalyticalValues<T>(left: unknown, right: unknown, column?: AnalyticalColumn<T>): number;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"valueComparison.d.ts","sourceRoot":"","sources":["../../../src/analytical-table/runtime/valueComparison.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAExE,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAO3F;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,CAa9G"}
@@ -1,8 +1,5 @@
1
- export type * from "./dataTypes";
2
- export type * from "./columnTypes";
3
- export type * from "./viewTypes";
4
- export type * from "./modelTypes";
5
- export type * from "./calculationTypes";
6
- export type * from "./dateColumnTypes";
7
- export type * from "./exportTypes";
1
+ export type * from "./definition/types";
2
+ export type * from "./runtime/types";
3
+ export type * from "./dynamic-columns/types";
4
+ export type * from "./projections/types";
8
5
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/analytical-table/types.ts"],"names":[],"mappings":"AAAA,mBAAmB,aAAa,CAAC;AACjC,mBAAmB,eAAe,CAAC;AACnC,mBAAmB,aAAa,CAAC;AACjC,mBAAmB,cAAc,CAAC;AAClC,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,mBAAmB,CAAC;AACvC,mBAAmB,eAAe,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/analytical-table/types.ts"],"names":[],"mappings":"AAAA,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,iBAAiB,CAAC;AACrC,mBAAmB,yBAAyB,CAAC;AAC7C,mBAAmB,qBAAqB,CAAC"}