@veltra/sheet 2.4.0 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/dist/components/sheet/formula-bar.js +50 -7
  2. package/dist/components/sheet/style2.css +2 -2
  3. package/dist/index.d.ts +2 -19
  4. package/dist/index.js +2 -15
  5. package/dist/types/index.d.ts +1 -3
  6. package/package.json +5 -6
  7. package/src/components/sheet/__test__/formula-bar.test.ts +29 -0
  8. package/src/components/sheet/formula-bar.vue +67 -6
  9. package/src/components/sheet/style.scss +1 -1
  10. package/src/index.ts +1 -27
  11. package/src/types/index.ts +0 -2
  12. package/dist/components/report/binding-badge.js +0 -118
  13. package/dist/components/report/designer/cell-coords.js +0 -46
  14. package/dist/components/report/designer/col-widths.js +0 -29
  15. package/dist/components/report/designer/conditional-rules/helpers.js +0 -139
  16. package/dist/components/report/designer/drill-dialog.js +0 -258
  17. package/dist/components/report/designer/drop-highlight-overlay.js +0 -76
  18. package/dist/components/report/designer/float-panel.js +0 -434
  19. package/dist/components/report/designer/role.js +0 -17
  20. package/dist/components/report/designer/rule-preview.js +0 -33
  21. package/dist/components/report/designer/rule-row.js +0 -253
  22. package/dist/components/report/designer/rules-dialog.js +0 -118
  23. package/dist/components/report/designer/topology-overlay.js +0 -122
  24. package/dist/components/report/designer/topology.js +0 -64
  25. package/dist/components/report/designer/use-grid-overlay.js +0 -75
  26. package/dist/components/report/designer-hub.js +0 -177
  27. package/dist/components/report/field-panel-helpers.js +0 -33
  28. package/dist/components/report/field-panel.js +0 -132
  29. package/dist/components/report/filter-bar.js +0 -74
  30. package/dist/components/report/hub-connection-form.js +0 -145
  31. package/dist/components/report/hub-dataset-editor.js +0 -409
  32. package/dist/components/report/preview-grid-size.js +0 -32
  33. package/dist/components/report/print.js +0 -39
  34. package/dist/components/report/report-designer.js +0 -428
  35. package/dist/components/report/report-viewer.js +0 -253
  36. package/dist/components/report/style.d.ts +0 -17
  37. package/dist/components/report/style.js +0 -18
  38. package/dist/components/report/style2.css +0 -965
  39. package/dist/components/report/use-report-designer.js +0 -387
  40. package/dist/components/report/use-report-viewer.js +0 -140
  41. package/dist/report/binding.d.ts +0 -83
  42. package/dist/report/binding.js +0 -334
  43. package/dist/report/connector.d.ts +0 -66
  44. package/dist/report/connector.js +0 -159
  45. package/dist/report/drill.d.ts +0 -48
  46. package/dist/report/drill.js +0 -78
  47. package/dist/report/export-xlsx.d.ts +0 -13
  48. package/dist/report/export-xlsx.js +0 -13
  49. package/dist/report/filter-bar.d.ts +0 -10
  50. package/dist/report/filter-bar.js +0 -31
  51. package/dist/report/index.d.ts +0 -14
  52. package/dist/report/params.d.ts +0 -13
  53. package/dist/report/params.js +0 -61
  54. package/dist/report/print.d.ts +0 -23
  55. package/dist/report/print.js +0 -197
  56. package/dist/report/render/aggregate.js +0 -193
  57. package/dist/report/render/builder.d.ts +0 -12
  58. package/dist/report/render/builder.js +0 -139
  59. package/dist/report/render/coordinate.d.ts +0 -25
  60. package/dist/report/render/coordinate.js +0 -733
  61. package/dist/report/render/index.d.ts +0 -14
  62. package/dist/report/render/index.js +0 -21
  63. package/dist/report/render/style-resolver.js +0 -50
  64. package/dist/report/render/template-index.d.ts +0 -24
  65. package/dist/report/render/template-index.js +0 -137
  66. package/dist/report/rules/evaluate.d.ts +0 -25
  67. package/dist/report/rules/evaluate.js +0 -82
  68. package/dist/report/rules/index.d.ts +0 -2
  69. package/dist/report/template.d.ts +0 -63
  70. package/dist/report/template.js +0 -83
  71. package/dist/report/types.d.ts +0 -103
  72. package/dist/types/report-designer.d.ts +0 -51
  73. package/dist/types/report-viewer.d.ts +0 -57
  74. package/src/components/report/__test__/binding-badge.test.ts +0 -92
  75. package/src/components/report/__test__/conditional-rules-helpers.test.ts +0 -88
  76. package/src/components/report/__test__/field-panel-helpers.test.ts +0 -65
  77. package/src/components/report/__test__/float-panel-position.test.ts +0 -45
  78. package/src/components/report/__test__/preview-grid-size.test.ts +0 -63
  79. package/src/components/report/__test__/report-designer.test.ts +0 -559
  80. package/src/components/report/__test__/report-drill.test.ts +0 -692
  81. package/src/components/report/__test__/report-viewer.test.ts +0 -400
  82. package/src/components/report/__test__/topology.test.ts +0 -143
  83. package/src/components/report/__test__/use-report-designer.test.ts +0 -804
  84. package/src/components/report/binding-badge.ts +0 -122
  85. package/src/components/report/designer/cell-coords.ts +0 -95
  86. package/src/components/report/designer/col-widths.ts +0 -56
  87. package/src/components/report/designer/conditional-rules/helpers.ts +0 -189
  88. package/src/components/report/designer/drill-dialog.vue +0 -245
  89. package/src/components/report/designer/drop-highlight-overlay.vue +0 -75
  90. package/src/components/report/designer/float-panel.vue +0 -444
  91. package/src/components/report/designer/role.ts +0 -32
  92. package/src/components/report/designer/rule-preview.vue +0 -40
  93. package/src/components/report/designer/rule-row.vue +0 -252
  94. package/src/components/report/designer/rules-dialog.vue +0 -110
  95. package/src/components/report/designer/topology-overlay.vue +0 -128
  96. package/src/components/report/designer/topology.ts +0 -124
  97. package/src/components/report/designer/use-grid-overlay.ts +0 -114
  98. package/src/components/report/designer-hub.vue +0 -198
  99. package/src/components/report/field-panel-helpers.ts +0 -44
  100. package/src/components/report/field-panel.vue +0 -136
  101. package/src/components/report/filter-bar.vue +0 -77
  102. package/src/components/report/hub-connection-form.vue +0 -124
  103. package/src/components/report/hub-dataset-editor.vue +0 -387
  104. package/src/components/report/index.ts +0 -2
  105. package/src/components/report/preview-grid-size.ts +0 -33
  106. package/src/components/report/print.ts +0 -44
  107. package/src/components/report/report-designer.vue +0 -454
  108. package/src/components/report/report-viewer.vue +0 -289
  109. package/src/components/report/style-designer.scss +0 -653
  110. package/src/components/report/style-hub.scss +0 -292
  111. package/src/components/report/style-viewer.scss +0 -144
  112. package/src/components/report/style.scss +0 -3
  113. package/src/components/report/style.ts +0 -20
  114. package/src/components/report/use-report-designer.ts +0 -603
  115. package/src/components/report/use-report-viewer.ts +0 -227
  116. package/src/report/__test__/binding.test.ts +0 -320
  117. package/src/report/__test__/connector.test.ts +0 -239
  118. package/src/report/__test__/drill.test.ts +0 -194
  119. package/src/report/__test__/export-xlsx.test.ts +0 -96
  120. package/src/report/__test__/filter-bar.test.ts +0 -58
  121. package/src/report/__test__/params.test.ts +0 -156
  122. package/src/report/__test__/print.test.ts +0 -170
  123. package/src/report/__test__/render.test.ts +0 -856
  124. package/src/report/__test__/rules.test.ts +0 -131
  125. package/src/report/__test__/template.test.ts +0 -366
  126. package/src/report/binding.ts +0 -474
  127. package/src/report/connector.ts +0 -206
  128. package/src/report/drill.ts +0 -112
  129. package/src/report/export-xlsx.ts +0 -15
  130. package/src/report/filter-bar.ts +0 -36
  131. package/src/report/index.ts +0 -16
  132. package/src/report/params.ts +0 -96
  133. package/src/report/print.ts +0 -234
  134. package/src/report/render/__test__/aggregate.test.ts +0 -16
  135. package/src/report/render/__test__/coordinate.test.ts +0 -405
  136. package/src/report/render/aggregate.ts +0 -289
  137. package/src/report/render/builder.ts +0 -211
  138. package/src/report/render/coordinate.ts +0 -1239
  139. package/src/report/render/index.ts +0 -30
  140. package/src/report/render/style-resolver.ts +0 -68
  141. package/src/report/render/template-index.ts +0 -200
  142. package/src/report/rules/evaluate.ts +0 -113
  143. package/src/report/rules/index.ts +0 -7
  144. package/src/report/template.ts +0 -145
  145. package/src/report/types.ts +0 -116
  146. package/src/types/report-designer.ts +0 -55
  147. package/src/types/report-viewer.ts +0 -54
@@ -1,57 +0,0 @@
1
- import { ParamValues } from "../report/types.js";
2
- import { ReportColWidthEntry } from "../report/export-xlsx.js";
3
- import { DataConnector } from "../report/connector.js";
4
- import { ReportTemplate } from "../report/template.js";
5
- import { ResolveReportTemplate } from "../report/drill.js";
6
- import { ReportPrintOptions } from "../report/print.js";
7
- import "../report/index.js";
8
- import { DeconstructValue } from "@veltra/utils";
9
- import { Workbook } from "@veltra/sheet-core/core/workbook";
10
- //#region src/types/report-viewer.d.ts
11
- /** 报表查看器组件属性(ADR-0003 决策 2) */
12
- interface ReportViewerProps {
13
- /** 数据连接器(如 `createHttpConnector({ endpoint })`) */
14
- connector: DataConnector;
15
- /**
16
- * 自包含 Report Template(SheetSnapshot + 内嵌数据集定义,见 `ReportTemplate`):
17
- * 查看器据此提取实际绑定数据集的查询参数并集生成 Filter Bar,并经连接器取数展开渲染
18
- */
19
- template: ReportTemplate;
20
- /** 承载填充报表的工作簿(USheet 先例:缺省内部自建单 sheet 工作簿) */
21
- workbook?: Workbook;
22
- /**
23
- * 列宽显式覆盖(可选):优先于模板 `colWidths` / 展开映射结果写入模型与网格。
24
- * 列宽已进 `SheetSnapshot.colWidths`,通常无需再传。
25
- */
26
- colWidths?: ReadonlyArray<ReportColWidthEntry>;
27
- /**
28
- * 下钻目标模板解析契约(可选,内核共享类型):单击配了下钻的绑定格时按 `target` 引用取目标模板。
29
- * 解析失败(抛错 / reject,或宿主实现返回空值)时查看器给出可读提示并停留当前报。
30
- * 缺省时下钻不生效(无点击行为与可点视觉提示)。
31
- */
32
- resolveTemplate?: ResolveReportTemplate;
33
- /**
34
- * Filter Bar 初值(可选):与当前模板参数默认值合并,显式键覆盖默认值。
35
- * 仅在根模板载入时播种(下钻弹框传入映射参数);缺省则只用参数默认值。
36
- */
37
- initialValues?: ParamValues;
38
- }
39
- /** 在组件内部引用 */
40
- interface _ReportViewerExposed {
41
- /** 重新取数并展开渲染(外部状态变化后主动刷新报表) */
42
- refresh: () => Promise<void>;
43
- /**
44
- * 导出填充报表为 XLSX(取数完成前拒绝;内部读取填充 sheet 与运行时列宽)。
45
- * 不内置导出按钮,工具栏由下游决定。
46
- */
47
- exportXlsx: () => Promise<void>;
48
- /**
49
- * 打印填充报表(纯前端:模型 → 打印 HTML → 隐藏 iframe 调起浏览器打印;
50
- * 取数完成前拒绝)。不内置打印按钮,工具栏由下游决定。
51
- */
52
- print: (options?: ReportPrintOptions) => void;
53
- }
54
- /** 报表查看器组件暴露的方法 */
55
- type ReportViewerExposed = DeconstructValue<_ReportViewerExposed>;
56
- //#endregion
57
- export { ReportViewerExposed, ReportViewerProps, _ReportViewerExposed };
@@ -1,92 +0,0 @@
1
- import { Sheet } from '@veltra/sheet-core'
2
- import type { CellAddress } from '@veltra/sheet-core'
3
- import { describe, expect, it } from 'vitest'
4
-
5
- import { REPORT_META_NAMESPACE, createReportBinding } from '../../../report/binding'
6
- import type { DatasetCatalogItem, ReportBinding } from '../../../report/types'
7
- import { badgeLayoutProps, createBindingBadgeRenderer } from '../binding-badge'
8
-
9
- // ---- 内联 fixtures ----
10
-
11
- const ORDERS_DATASET: DatasetCatalogItem = {
12
- id: 'orders',
13
- label: '销售明细',
14
- fields: [
15
- { name: 'customer', label: '客户', type: 'string' },
16
- { name: 'amount', label: '金额', type: 'number' }
17
- ]
18
- }
19
-
20
- const ADDR = { row: 1, col: 3 }
21
-
22
- function bindingMap(entries: Array<{ addr: CellAddress; binding: ReportBinding }>) {
23
- const map = new Map<string, ReportBinding>()
24
- for (const { addr, binding } of entries) map.set(`${addr.row},${addr.col}`, binding)
25
- return (addr: CellAddress) => map.get(`${addr.row},${addr.col}`)
26
- }
27
-
28
- describe('badgeLayoutProps(单元格对齐 → 徽章容器 flex 映射)', () => {
29
- it('缺省对齐 → 主轴起点 + 交叉轴居中(向后兼容)', () => {
30
- expect(badgeLayoutProps(undefined)).toEqual({
31
- justifyContent: 'flex-start',
32
- alignItems: 'center'
33
- })
34
- expect(badgeLayoutProps({})).toEqual({ justifyContent: 'flex-start', alignItems: 'center' })
35
- })
36
-
37
- it('horizontal center / right / left → justifyContent', () => {
38
- expect(badgeLayoutProps({ horizontal: 'center' }).justifyContent).toBe('center')
39
- expect(badgeLayoutProps({ horizontal: 'right' }).justifyContent).toBe('flex-end')
40
- expect(badgeLayoutProps({ horizontal: 'left' }).justifyContent).toBe('flex-start')
41
- })
42
-
43
- it('vertical bottom / top / middle → alignItems', () => {
44
- expect(badgeLayoutProps({ vertical: 'bottom' }).alignItems).toBe('flex-end')
45
- expect(badgeLayoutProps({ vertical: 'top' }).alignItems).toBe('flex-start')
46
- expect(badgeLayoutProps({ vertical: 'middle' }).alignItems).toBe('center')
47
- })
48
- })
49
-
50
- describe('createBindingBadgeRenderer', () => {
51
- it('未绑定格返回 undefined 回落默认渲染', () => {
52
- const renderer = createBindingBadgeRenderer(bindingMap([]))
53
- expect(renderer(ADDR, undefined)).toBeUndefined()
54
- })
55
-
56
- it('绑定格不传 resolveAlign 保持左对齐徽章(向后兼容)', () => {
57
- const binding = createReportBinding(ORDERS_DATASET, 'amount')
58
- const renderer = createBindingBadgeRenderer(bindingMap([{ addr: ADDR, binding }]))
59
- const layout = renderer(ADDR, undefined)
60
- expect(layout?.renderDefault).toBe(false)
61
- expect(layout?.rootContainer.attribute.justifyContent).toBe('flex-start')
62
- expect(layout?.rootContainer.attribute.alignItems).toBe('center')
63
- })
64
-
65
- it('绑定格容器跟随 resolveAlign 的水平 / 垂直对齐', () => {
66
- const binding = createReportBinding(ORDERS_DATASET, 'amount')
67
- const renderer = createBindingBadgeRenderer(
68
- bindingMap([{ addr: ADDR, binding }]),
69
- undefined,
70
- () => ({ horizontal: 'center', vertical: 'bottom' })
71
- )
72
- const layout = renderer(ADDR, undefined)
73
- expect(layout?.rootContainer.attribute.justifyContent).toBe('center')
74
- expect(layout?.rootContainer.attribute.alignItems).toBe('flex-end')
75
- })
76
-
77
- it('接线冒烟:经 Sheet.getEffectiveStyle 读取有效样式对齐(含行默认样式叠加)', () => {
78
- const sheet = new Sheet()
79
- sheet.setCellMeta(ADDR, REPORT_META_NAMESPACE, createReportBinding(ORDERS_DATASET, 'amount'))
80
- sheet.setCellStyle({ start: ADDR, end: ADDR }, { align: { horizontal: 'center' } })
81
- sheet.setRowStyle(ADDR.row, { align: { vertical: 'bottom' } })
82
-
83
- const renderer = createBindingBadgeRenderer(
84
- (addr) => sheet.getCellMeta<ReportBinding>(addr, REPORT_META_NAMESPACE),
85
- undefined,
86
- (addr) => sheet.getEffectiveStyle(addr)?.align
87
- )
88
- const layout = renderer(ADDR, undefined)
89
- expect(layout?.rootContainer.attribute.justifyContent).toBe('center')
90
- expect(layout?.rootContainer.attribute.alignItems).toBe('flex-end')
91
- })
92
- })
@@ -1,88 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
-
3
- import type { ConditionalRule } from '../../../report/types'
4
- import {
5
- cloneRulesFromDraft,
6
- coerceValueForOperator,
7
- createDraftItem,
8
- defaultRuleValue,
9
- initDraftFromRules,
10
- operatorsForFieldType,
11
- readBetweenValue,
12
- resolveEvalFieldType,
13
- ruleEvalFieldOptions,
14
- RULE_SCOPE_OPTIONS,
15
- writeBetweenValue
16
- } from '../designer/conditional-rules/helpers'
17
-
18
- describe('conditional-rules helpers', () => {
19
- it('按字段类型返回运算符列表', () => {
20
- expect(operatorsForFieldType('number').map((o) => o.value)).toEqual([
21
- 'gt',
22
- 'gte',
23
- 'lt',
24
- 'lte',
25
- 'eq',
26
- 'between'
27
- ])
28
- expect(operatorsForFieldType('string').map((o) => o.value)).toEqual(['eq', 'contains'])
29
- })
30
-
31
- it('运算符切换时重置比较值', () => {
32
- expect(coerceValueForOperator('between', 'number', 42)).toEqual([0, 100])
33
- expect(coerceValueForOperator('contains', 'string', 42)).toBe('')
34
- expect(coerceValueForOperator('gt', 'number', '12')).toBe(12)
35
- })
36
-
37
- it('between 读写辅助', () => {
38
- const value = defaultRuleValue('between', 'number')
39
- expect(readBetweenValue(value, 0, 'number')).toBe(0)
40
- expect(readBetweenValue(value, 1, 'number')).toBe(100)
41
- expect(writeBetweenValue(value, 1, 250, 'number')).toEqual([0, 250])
42
- })
43
-
44
- it('草稿与规则互转保持深拷贝', () => {
45
- const rules: ConditionalRule[] = [
46
- { operator: 'gt', value: 10, style: { fill: { color: '#FFCCCC' }, font: { bold: true } } }
47
- ]
48
- const draft = initDraftFromRules(rules, 'number')
49
- expect(draft).toHaveLength(1)
50
-
51
- const cloned = cloneRulesFromDraft(draft)
52
- expect(cloned[0]).toEqual(rules[0])
53
- expect(cloned[0]).not.toBe(rules[0])
54
-
55
- draft[0]!.rule.style.fill!.color = '#000000'
56
- expect(rules[0]!.style.fill!.color).toBe('#FFCCCC')
57
- })
58
-
59
- it('新建草稿项带默认样式', () => {
60
- const item = createDraftItem(undefined, 'string')
61
- expect(item.rule.operator).toBe('eq')
62
- expect(item.rule.value).toBe('')
63
- expect(item.rule.style.fill?.color).toBeTruthy()
64
- })
65
-
66
- it('求值字段与作用范围选项', () => {
67
- const fields = [
68
- { name: 'amount', label: '金额', type: 'number' as const },
69
- { name: 'region', label: '地区', type: 'string' as const }
70
- ]
71
- expect(ruleEvalFieldOptions('amount', fields).map((item) => item.label)).toEqual([
72
- '本格字段',
73
- '地区'
74
- ])
75
- expect(ruleEvalFieldOptions('amount', fields).map((item) => item.value)).toEqual(['', 'region'])
76
- expect(RULE_SCOPE_OPTIONS.map((item) => item.label)).toEqual(['本格', '整行'])
77
- expect(resolveEvalFieldType({ operator: 'eq', value: '', style: {} }, 'amount', fields)).toBe(
78
- 'number'
79
- )
80
- expect(
81
- resolveEvalFieldType(
82
- { operator: 'eq', value: '', style: {}, field: 'region' },
83
- 'amount',
84
- fields
85
- )
86
- ).toBe('string')
87
- })
88
- })
@@ -1,65 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
-
3
- import type { DatasetCatalogItem } from '../../../report/types'
4
- import {
5
- fieldTypeGlyph,
6
- filterDatasetsByQuery,
7
- formatFieldDragPayload,
8
- parseFieldDragPayload
9
- } from '../field-panel-helpers'
10
-
11
- // ---- 内联 fixtures ----
12
-
13
- const ORDERS: DatasetCatalogItem = {
14
- id: 'orders',
15
- label: '销售明细',
16
- fields: [
17
- { name: 'customer', label: '客户', type: 'string' },
18
- { name: 'amount', label: '金额', type: 'number' }
19
- ]
20
- }
21
-
22
- const INVENTORY: DatasetCatalogItem = {
23
- id: 'inventory',
24
- label: '库存',
25
- fields: [
26
- { name: 'sku', label: 'SKU', type: 'string' },
27
- { name: 'qty', label: '数量', type: 'number' }
28
- ]
29
- }
30
-
31
- describe('field-panel helpers', () => {
32
- it('fieldTypeGlyph 按字段类型返回短标识', () => {
33
- expect(fieldTypeGlyph('string')).toBe('文')
34
- expect(fieldTypeGlyph('number')).toBe('#')
35
- expect(fieldTypeGlyph('date')).toBe('日')
36
- })
37
-
38
- it('filterDatasetsByQuery 按中文名或英文字段名过滤', () => {
39
- const datasets = [ORDERS, INVENTORY]
40
-
41
- expect(filterDatasetsByQuery(datasets, '客户')).toEqual([
42
- { ...ORDERS, fields: [ORDERS.fields[0]!] }
43
- ])
44
-
45
- expect(filterDatasetsByQuery(datasets, 'qty')).toEqual([
46
- { ...INVENTORY, fields: [INVENTORY.fields[1]!] }
47
- ])
48
-
49
- expect(filterDatasetsByQuery(datasets, ' ')).toEqual(datasets)
50
- expect(filterDatasetsByQuery(datasets, '不存在')).toEqual([])
51
- })
52
-
53
- it('字段拖拽负载编解码往返;非法负载返回 null', () => {
54
- const payload = formatFieldDragPayload('orders', 'customer')
55
- expect(payload).toBe('orders:customer')
56
- expect(parseFieldDragPayload(payload)).toEqual({ datasetId: 'orders', fieldName: 'customer' })
57
-
58
- // 字段名含冒号时按首个分隔符切分
59
- expect(parseFieldDragPayload('orders:a:b')).toEqual({ datasetId: 'orders', fieldName: 'a:b' })
60
-
61
- expect(parseFieldDragPayload('')).toBeNull()
62
- expect(parseFieldDragPayload(':customer')).toBeNull()
63
- expect(parseFieldDragPayload('orders:')).toBeNull()
64
- })
65
- })
@@ -1,45 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
-
3
- import type { CellOverlayRect, GridOverlayLayout } from '../designer/cell-coords'
4
- import { resolveBindingFloatPanelPosition } from '../designer/use-grid-overlay'
5
-
6
- function cellRect(top: number, height = 24): CellOverlayRect {
7
- const bottom = top + height
8
- return {
9
- left: 100,
10
- top,
11
- right: 180,
12
- bottom,
13
- width: 80,
14
- height,
15
- centerX: 140,
16
- centerY: top + height / 2
17
- }
18
- }
19
-
20
- const layout: GridOverlayLayout = { offsetX: 0, offsetY: 77, viewW: 640, viewH: 400 }
21
-
22
- describe('resolveBindingFloatPanelPosition', () => {
23
- it('顶行格空间不足时改在单元格下方', () => {
24
- const rect = cellRect(101)
25
- const position = resolveBindingFloatPanelPosition(rect, layout, 320, 68, 640)
26
-
27
- expect(position.placement).toBe('below')
28
- expect(position.top).toBe(rect.bottom + 8)
29
- })
30
-
31
- it('中部格优先在单元格上方', () => {
32
- const rect = cellRect(200)
33
- const position = resolveBindingFloatPanelPosition(rect, layout, 320, 68, 640)
34
-
35
- expect(position.placement).toBe('above')
36
- expect(position.top).toBe(rect.top - 8)
37
- })
38
-
39
- it('水平居中并限制在宿主宽度内', () => {
40
- const rect = cellRect(200)
41
- const position = resolveBindingFloatPanelPosition(rect, layout, 320, 68, 340)
42
-
43
- expect(position.left).toBe(170)
44
- })
45
- })
@@ -1,63 +0,0 @@
1
- import type { SheetSnapshot } from '@veltra/sheet-core'
2
- import { describe, expect, it } from 'vitest'
3
-
4
- import { previewGridSize } from '../preview-grid-size'
5
-
6
- function snap(
7
- partial: Partial<SheetSnapshot> & Pick<SheetSnapshot, 'cells'>
8
- ): Pick<SheetSnapshot, 'cells' | 'merges' | 'meta' | 'rows'> {
9
- return { merges: [], rows: 0, ...partial }
10
- }
11
-
12
- describe('previewGridSize', () => {
13
- it('template 模式用内容包围盒,忽略设计态 canvas 尺寸', () => {
14
- expect(
15
- previewGridSize(
16
- snap({
17
- cells: [
18
- { row: 0, col: 0, v: '客户' },
19
- { row: 0, col: 1, v: '金额' }
20
- ],
21
- rows: 24,
22
- cols: 10
23
- }),
24
- 'template'
25
- )
26
- ).toEqual({ rows: 1, cols: 2 })
27
- })
28
-
29
- it('filled 模式行保留展开布局尺寸,列按包围盒收敛(去掉设计态撑大的列)', () => {
30
- expect(
31
- previewGridSize(
32
- snap({
33
- cells: [
34
- { row: 0, col: 0, v: '客户' },
35
- { row: 3, col: 1, v: 300 }
36
- ],
37
- rows: 4,
38
- cols: 10
39
- }),
40
- 'filled'
41
- )
42
- ).toEqual({ rows: 4, cols: 2 })
43
- })
44
-
45
- it('空快照至少 1×1(VTable 需要非零网格)', () => {
46
- expect(previewGridSize(snap({ cells: [] }), 'template')).toEqual({ rows: 1, cols: 1 })
47
- })
48
-
49
- it('包围盒计入合并区终点与 meta 绑定格', () => {
50
- expect(
51
- previewGridSize(
52
- snap({
53
- cells: [{ row: 0, col: 0, v: '标题' }],
54
- merges: [{ start: { row: 0, col: 0 }, end: { row: 0, col: 2 } }],
55
- meta: [{ row: 2, col: 1, namespace: 'report', payload: {} }],
56
- rows: 24,
57
- cols: 10
58
- }),
59
- 'template'
60
- )
61
- ).toEqual({ rows: 3, cols: 3 })
62
- })
63
- })