@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
@@ -38,6 +38,10 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
38
38
  const mirroring = ref(false);
39
39
  let mirrorAddr = null;
40
40
  const fxDraft = ref("");
41
+ /** 鼠标是否悬停在公式栏输入区 */
42
+ const fxHovered = ref(false);
43
+ /** 输入框是否处于 focus 状态 */
44
+ const fxFocused = ref(false);
41
45
  /** 输入面板是否因内容增高而浮出(文档流仍保持单行) */
42
46
  const fxExpanded = ref(false);
43
47
  /** textarea 光标(selectionStart);输入/点击/方向键后同步 */
@@ -76,7 +80,13 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
76
80
  }
77
81
  function nameText(state) {
78
82
  const range = state.ranges[0];
79
- if (range) return formatRange(range);
83
+ if (range) {
84
+ if (state.activeCell) {
85
+ const merge = props.sheet.merges.getMergeAt(state.activeCell);
86
+ if (merge && range.start.row === merge.start.row && range.start.col === merge.start.col && range.end.row === merge.end.row && range.end.col === merge.end.col) return formatAddress(state.activeCell);
87
+ }
88
+ return formatRange(range);
89
+ }
80
90
  return state.activeCell ? formatAddress(state.activeCell) : "";
81
91
  }
82
92
  function cellText(addr) {
@@ -93,7 +103,16 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
93
103
  fxDraft.value = active ? cellText(active) : "";
94
104
  fxCursor.value = fxDraft.value.length;
95
105
  closeSuggest();
96
- scheduleAutosize();
106
+ if (fxHovered.value || fxFocused.value || editing.value) scheduleAutosize();
107
+ else collapseFx();
108
+ }
109
+ /** 恢复单行高度并重置展开状态 */
110
+ function collapseFx() {
111
+ const el = fxRef.value;
112
+ if (!el) return;
113
+ el.style.height = "";
114
+ el.scrollTop = 0;
115
+ fxExpanded.value = false;
97
116
  }
98
117
  /** 每帧合并一次的 autosizeFx(批量 cell-change 同帧 N 次 nextTick → 1 次强制布局) */
99
118
  let autosizePending = false;
@@ -106,20 +125,33 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
106
125
  });
107
126
  }
108
127
  /**
109
- * 按内容增高浮出面板,不超过 CSS max-height。
128
+ * 仅在鼠标悬停、获得焦点或编辑时按内容增高浮出面板,不超过 CSS max-height。
110
129
  * 增高走绝对定位,公式栏文档流高度始终单行。
111
130
  */
112
131
  function autosizeFx() {
113
132
  const el = fxRef.value;
114
133
  if (!el) return;
134
+ if (!fxHovered.value && !fxFocused.value && !editing.value) {
135
+ collapseFx();
136
+ return;
137
+ }
115
138
  el.style.height = "0px";
116
139
  const styles = getComputedStyle(el);
117
140
  const max = Number.parseFloat(styles.maxHeight);
118
141
  const min = Number.parseFloat(styles.minHeight);
142
+ const hasMultipleLines = fxDraft.value.includes("\n");
119
143
  const content = el.scrollHeight;
120
144
  const next = Number.isFinite(max) && max > 0 ? Math.min(content, max) : content;
121
145
  el.style.height = `${next}px`;
122
- fxExpanded.value = Number.isFinite(min) ? next > min + 1 : next > 1;
146
+ fxExpanded.value = (Number.isFinite(min) ? next > min + 1 : next > 1) || hasMultipleLines;
147
+ }
148
+ function handleFxMouseEnter() {
149
+ fxHovered.value = true;
150
+ if (fxDraft.value) autosizeFx();
151
+ }
152
+ function handleFxMouseLeave() {
153
+ fxHovered.value = false;
154
+ if (!fxFocused.value && !editing.value) collapseFx();
123
155
  }
124
156
  function syncFxCursor() {
125
157
  const el = fxRef.value;
@@ -193,23 +225,30 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
193
225
  }
194
226
  function handleFxFocus() {
195
227
  if (fxDisabled.value) return;
228
+ fxFocused.value = true;
196
229
  mirroring.value = false;
197
230
  mirrorAddr = null;
198
231
  editing.value = true;
199
232
  editAddr = selection.value.activeCell;
200
233
  syncFxCursor();
234
+ scheduleAutosize();
201
235
  }
202
236
  /**
203
237
  * 失焦提交;引用选择期间(画布 pointerdown 已挂起)跳过。
204
238
  * ✓/✗ / 候选列表用 mousedown.prevent 拦截失焦。
205
239
  */
206
240
  function handleFxBlur() {
207
- if (!editing.value) return;
241
+ fxFocused.value = false;
242
+ if (!editing.value) {
243
+ if (!fxHovered.value) collapseFx();
244
+ return;
245
+ }
208
246
  if (suppressBlurCommit) {
209
247
  suppressBlurCommit = false;
210
248
  return;
211
249
  }
212
250
  commitEdit();
251
+ if (!fxHovered.value) collapseFx();
213
252
  }
214
253
  function handleFxKeydown(event) {
215
254
  if (suggestOpen.value) {
@@ -345,7 +384,11 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
345
384
  onKeydown: handleNameKeydown
346
385
  }, null, 34), [[vModelText, nameDraft.value]]),
347
386
  createElementVNode("span", { class: normalizeClass(unref(cls).e("fx-label")) }, "fx", 2),
348
- createElementVNode("div", { class: normalizeClass(unref(cls).e("fx-editor")) }, [createCommentVNode(" 文档流只占单行;面板绝对定位向下浮起,不撑开公式栏 "), createElementVNode("div", { class: normalizeClass([unref(cls).e("fx-input-panel"), unref(bem).is("expanded", fxExpanded.value)]) }, [withDirectives(createElementVNode("textarea", {
387
+ createElementVNode("div", {
388
+ class: normalizeClass(unref(cls).e("fx-editor")),
389
+ onMouseenter: handleFxMouseEnter,
390
+ onMouseleave: handleFxMouseLeave
391
+ }, [createCommentVNode(" 文档流只占单行;面板绝对定位向下浮起,不撑开公式栏 "), createElementVNode("div", { class: normalizeClass([unref(cls).e("fx-input-panel"), unref(bem).is("expanded", fxExpanded.value)]) }, [withDirectives(createElementVNode("textarea", {
349
392
  ref_key: "fxRef",
350
393
  ref: fxRef,
351
394
  "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => fxDraft.value = $event),
@@ -368,7 +411,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
368
411
  "active-index": suggestIndex.value,
369
412
  onSelect: confirmSuggest,
370
413
  onHover: _cache[3] || (_cache[3] = (i) => suggestIndex.value = i)
371
- }, null, 8, ["items", "active-index"])], 2)], 2),
414
+ }, null, 8, ["items", "active-index"])], 2)], 34),
372
415
  editing.value ? (openBlock(), createElementBlock("button", {
373
416
  key: 0,
374
417
  type: "button",
@@ -14,7 +14,7 @@
14
14
  * --u-height-default: 32px;
15
15
  * --u-height-small: 24px;
16
16
  */
17
- /** 暗色:data-theme 与系统偏好,与 UITheme.injectBuiltInThemes 选择器策略一致 */
17
+ /** 暗色:`UITheme.render()` 按主题系列写入 html[data-theme] */
18
18
  .u-sheet {
19
19
  position: relative;
20
20
  display: flex;
@@ -246,7 +246,7 @@
246
246
  line-height: 1.4;
247
247
  resize: none;
248
248
  overflow-x: hidden;
249
- overflow-y: auto;
249
+ overflow-y: hidden;
250
250
  outline: none;
251
251
  }
252
252
  .u-sheet__fx-input:focus {
package/dist/index.d.ts CHANGED
@@ -1,23 +1,6 @@
1
- import _sfc_main$2 from "./components/sheet/sheet.js";
2
- import _sfc_main$1 from "./components/report/report-viewer.js";
3
- import _sfc_main from "./components/report/report-designer.js";
1
+ import _sfc_main from "./components/sheet/sheet.js";
4
2
  import { SheetContext, createSheetContext } from "./tools/context.js";
5
3
  import { SheetTool, SheetToolGroup, SheetToolPopupType, defaultToolRegistry, registerTool, unregisterTool } from "./tools/registry.js";
6
4
  import { SheetEmits, SheetExposed, SheetProps, _SheetExposed } from "./types/sheet.js";
7
- import { ConditionalOperator, ConditionalRule, DatasetCatalogItem, DatasetField, DatasetRecords, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, ReportAggregate, ReportBinding, ReportDrillConfig, ReportExpand, ReportPreset, ReportSort, ReportTemplateListItem } from "./report/types.js";
8
- import { InferParentOptions, ListParentCandidateOptions, REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, prefersGroupParent, presetBindingPatch, presetStillApplies, setBindingCatalog } from "./report/binding.js";
9
- import { ConditionalEvalContext, evaluateCondition, evaluateConditionalStyle, resolveRuleCompareValue, toComparableNumber } from "./report/rules/evaluate.js";
10
- import { buildParamDefs, extractParamIds, resolveBoundDatasetParams } from "./report/params.js";
11
- import { ReportColWidthEntry, exportFilledReportXlsx } from "./report/export-xlsx.js";
12
- import { mapFilledColWidths } from "./report/render/builder.js";
13
- import { renderReport, resolveFilledColWidths } from "./report/render/index.js";
14
- import { ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, QueryResult, Result, createHttpConnector, resolvePortOnTypeChange } from "./report/connector.js";
15
- import { IncompatibleTemplateVersionError, REPORT_TEMPLATE_VERSION, ReportDatasetDef, ReportTemplate, assertCompatibleTemplateVersion, createReportTemplate, fetchTemplateRecords, getBoundDatasetIds, getTemplateDatasets, resolveParamDefaults, resolveTemplateParams } from "./report/template.js";
16
- import { parseDateRangeValue, patchParamValues, resolveNumberParamValue } from "./report/filter-bar.js";
17
- import { DrillHit, DrillStack, DrillStackLayer, ResolveReportTemplate, buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams } from "./report/drill.js";
18
- import { ReportPrintOptions, buildFilledReportPrintHtml } from "./report/print.js";
19
- import "./report/index.js";
20
- import { ReportViewerExposed, ReportViewerProps, _ReportViewerExposed } from "./types/report-viewer.js";
21
- import { ReportDesignerEmits, ReportDesignerExposed, ReportDesignerProps, _ReportDesignerExposed } from "./types/report-designer.js";
22
5
  import "./types/index.js";
23
- export { type ConditionalEvalContext, ConditionalOperator, ConditionalRule, ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, DatasetCatalogItem, DatasetField, DatasetRecords, DrillHit, DrillStack, DrillStackLayer, IncompatibleTemplateVersionError, InferParentOptions, ListParentCandidateOptions, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, QueryResult, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, ReportAggregate, ReportBinding, ReportColWidthEntry, ReportDatasetDef, type ReportDesignerEmits, type ReportDesignerExposed, type ReportDesignerProps, ReportDrillConfig, ReportExpand, ReportPreset, ReportPrintOptions, ReportSort, ReportTemplate, ReportTemplateListItem, type ReportViewerExposed, type ReportViewerProps, ResolveReportTemplate, Result, type SheetContext, type SheetEmits, type SheetExposed, type SheetProps, type SheetTool, type SheetToolGroup, type SheetToolPopupType, _sfc_main as UReportDesigner, _sfc_main$1 as UReportViewer, _sfc_main$2 as USheet, type _ReportDesignerExposed, type _ReportViewerExposed, type _SheetExposed, applyReportPreset, assertCompatibleTemplateVersion, buildDrillHitMap, buildFilledReportPrintHtml, buildParamDefs, createDrillStack, createHttpConnector, createReportBinding, createReportTemplate, createSheetContext, currentDrillLayer, defaultToolRegistry, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, popDrillLayer, prefersGroupParent, presetBindingPatch, presetStillApplies, pushDrillLayer, registerTool, renderReport, resolveBoundDatasetParams, resolveDrillParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber, unregisterTool };
6
+ export { type SheetContext, type SheetEmits, type SheetExposed, type SheetProps, type SheetTool, type SheetToolGroup, type SheetToolPopupType, _sfc_main as USheet, type _SheetExposed, createSheetContext, defaultToolRegistry, registerTool, unregisterTool };
package/dist/index.js CHANGED
@@ -1,18 +1,5 @@
1
1
  import { defaultToolRegistry, registerTool, unregisterTool } from "./tools/registry.js";
2
2
  import "./tools/builtin.js";
3
3
  import { createSheetContext } from "./tools/context.js";
4
- import _sfc_main$2 from "./components/sheet/sheet.js";
5
- import { exportFilledReportXlsx } from "./report/export-xlsx.js";
6
- import { buildFilledReportPrintHtml } from "./report/print.js";
7
- import { parseDateRangeValue, patchParamValues, resolveNumberParamValue } from "./report/filter-bar.js";
8
- import { REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, prefersGroupParent, presetBindingPatch, presetStillApplies, setBindingCatalog } from "./report/binding.js";
9
- import { buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams } from "./report/drill.js";
10
- import { evaluateCondition, evaluateConditionalStyle, resolveRuleCompareValue, toComparableNumber } from "./report/rules/evaluate.js";
11
- import { mapFilledColWidths } from "./report/render/builder.js";
12
- import { renderReport, resolveFilledColWidths } from "./report/render/index.js";
13
- import { buildParamDefs, extractParamIds, resolveBoundDatasetParams } from "./report/params.js";
14
- import { IncompatibleTemplateVersionError, REPORT_TEMPLATE_VERSION, assertCompatibleTemplateVersion, createReportTemplate, fetchTemplateRecords, getBoundDatasetIds, getTemplateDatasets, resolveParamDefaults, resolveTemplateParams } from "./report/template.js";
15
- import _sfc_main$1 from "./components/report/report-viewer.js";
16
- import { DEFAULT_CONNECTION_PORTS, createHttpConnector, resolvePortOnTypeChange } from "./report/connector.js";
17
- import _sfc_main from "./components/report/report-designer.js";
18
- export { DEFAULT_CONNECTION_PORTS, IncompatibleTemplateVersionError, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, _sfc_main as UReportDesigner, _sfc_main$1 as UReportViewer, _sfc_main$2 as USheet, applyReportPreset, assertCompatibleTemplateVersion, buildDrillHitMap, buildFilledReportPrintHtml, buildParamDefs, createDrillStack, createHttpConnector, createReportBinding, createReportTemplate, createSheetContext, currentDrillLayer, defaultToolRegistry, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, popDrillLayer, prefersGroupParent, presetBindingPatch, presetStillApplies, pushDrillLayer, registerTool, renderReport, resolveBoundDatasetParams, resolveDrillParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber, unregisterTool };
4
+ import _sfc_main from "./components/sheet/sheet.js";
5
+ export { _sfc_main as USheet, createSheetContext, defaultToolRegistry, registerTool, unregisterTool };
@@ -1,4 +1,2 @@
1
1
  import { SheetEmits, SheetExposed, SheetProps, _SheetExposed } from "./sheet.js";
2
- import { ReportViewerExposed, ReportViewerProps, _ReportViewerExposed } from "./report-viewer.js";
3
- import { ReportDesignerEmits, ReportDesignerExposed, ReportDesignerProps, _ReportDesignerExposed } from "./report-designer.js";
4
- export { ReportDesignerEmits, ReportDesignerExposed, ReportDesignerProps, ReportViewerExposed, ReportViewerProps, SheetEmits, SheetExposed, SheetProps, _ReportDesignerExposed, _ReportViewerExposed, _SheetExposed };
2
+ export { SheetEmits, SheetExposed, SheetProps, _SheetExposed };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veltra/sheet",
3
- "version": "2.4.0",
3
+ "version": "2.5.1",
4
4
  "homepage": "https://github.com/cabinet-fe/ultra-ui#readme",
5
5
  "bugs": {
6
6
  "url": "https://github.com/cabinet-fe/ultra-ui/issues"
@@ -36,12 +36,11 @@
36
36
  "peerDependencies": {
37
37
  "@cat-kit/core": ">=1.1.8",
38
38
  "@cat-kit/fe": ">=1.1.8",
39
- "@veltra/compositions": "^1.6.5",
40
- "@veltra/desktop": "^1.6.5",
39
+ "@veltra/desktop": "^1.7.0",
41
40
  "@veltra/icons": "^1.5.0",
42
- "@veltra/sheet-core": "^2.4.0",
43
- "@veltra/styles": "^1.6.5",
44
- "@veltra/utils": "^1.6.5",
41
+ "@veltra/sheet-core": "^2.5.1",
42
+ "@veltra/styles": "^1.7.0",
43
+ "@veltra/utils": "^1.7.0",
45
44
  "vue": ">=3.5.41"
46
45
  }
47
46
  }
@@ -471,4 +471,33 @@ describe('USheet 公式栏:函数补全与引用选择', () => {
471
471
  await nextTick()
472
472
  expect(fxInput(el).value).toBe('=A1+B1')
473
473
  })
474
+
475
+ it('多行文本:默认保持单行高度,鼠标进入展开,移出后收起', async () => {
476
+ const workbook = new Workbook()
477
+ const sheet = workbook.activeSheet
478
+ sheet.setCellValue({ row: 0, col: 0 }, 'Line1\nLine2\nLine3\nLine4\nLine5')
479
+ const { el } = mount(() => ({ workbook, rows: 20, cols: 8 }))
480
+ await nextTick()
481
+ sheet.selectCell({ row: 0, col: 0 })
482
+ await nextTick()
483
+
484
+ const input = fxInput(el)
485
+ const panel = el.querySelector('.u-sheet__fx-input-panel')!
486
+ const editor = el.querySelector('.u-sheet__fx-editor')!
487
+
488
+ // 默认单行未展开,无 is-expanded 类,height 为空(由 CSS min-height 承载)
489
+ expect(panel.classList.contains('is-expanded')).toBe(false)
490
+ expect(input.style.height).toBe('')
491
+
492
+ // 鼠标移入公式栏编辑区:触发展开
493
+ editor.dispatchEvent(new MouseEvent('mouseenter'))
494
+ await nextTick()
495
+ expect(panel.classList.contains('is-expanded')).toBe(true)
496
+
497
+ // 鼠标移出公式栏编辑区:收起为单行
498
+ editor.dispatchEvent(new MouseEvent('mouseleave'))
499
+ await nextTick()
500
+ expect(panel.classList.contains('is-expanded')).toBe(false)
501
+ expect(input.style.height).toBe('')
502
+ })
474
503
  })
@@ -11,7 +11,11 @@
11
11
  @keydown="handleNameKeydown"
12
12
  />
13
13
  <span :class="cls.e('fx-label')">fx</span>
14
- <div :class="cls.e('fx-editor')">
14
+ <div
15
+ :class="cls.e('fx-editor')"
16
+ @mouseenter="handleFxMouseEnter"
17
+ @mouseleave="handleFxMouseLeave"
18
+ >
15
19
  <!-- 文档流只占单行;面板绝对定位向下浮起,不撑开公式栏 -->
16
20
  <div :class="[cls.e('fx-input-panel'), bem.is('expanded', fxExpanded)]">
17
21
  <textarea
@@ -122,6 +126,10 @@ let editAddr: CellAddress | null = null
122
126
  const mirroring = ref(false)
123
127
  let mirrorAddr: CellAddress | null = null
124
128
  const fxDraft = ref('')
129
+ /** 鼠标是否悬停在公式栏输入区 */
130
+ const fxHovered = ref(false)
131
+ /** 输入框是否处于 focus 状态 */
132
+ const fxFocused = ref(false)
125
133
  /** 输入面板是否因内容增高而浮出(文档流仍保持单行) */
126
134
  const fxExpanded = ref(false)
127
135
  /** textarea 光标(selectionStart);输入/点击/方向键后同步 */
@@ -170,7 +178,21 @@ function handleRefSelect(range: CellRange): void {
170
178
 
171
179
  function nameText(state: SelectionState): string {
172
180
  const range = state.ranges[0]
173
- if (range) return formatRange(range)
181
+ if (range) {
182
+ if (state.activeCell) {
183
+ const merge = props.sheet.merges.getMergeAt(state.activeCell)
184
+ if (
185
+ merge &&
186
+ range.start.row === merge.start.row &&
187
+ range.start.col === merge.start.col &&
188
+ range.end.row === merge.end.row &&
189
+ range.end.col === merge.end.col
190
+ ) {
191
+ return formatAddress(state.activeCell)
192
+ }
193
+ }
194
+ return formatRange(range)
195
+ }
174
196
  return state.activeCell ? formatAddress(state.activeCell) : ''
175
197
  }
176
198
 
@@ -190,7 +212,20 @@ function refreshFx(): void {
190
212
  fxDraft.value = active ? cellText(active) : ''
191
213
  fxCursor.value = fxDraft.value.length
192
214
  closeSuggest()
193
- scheduleAutosize()
215
+ if (fxHovered.value || fxFocused.value || editing.value) {
216
+ scheduleAutosize()
217
+ } else {
218
+ collapseFx()
219
+ }
220
+ }
221
+
222
+ /** 恢复单行高度并重置展开状态 */
223
+ function collapseFx(): void {
224
+ const el = fxRef.value
225
+ if (!el) return
226
+ el.style.height = ''
227
+ el.scrollTop = 0
228
+ fxExpanded.value = false
194
229
  }
195
230
 
196
231
  /** 每帧合并一次的 autosizeFx(批量 cell-change 同帧 N 次 nextTick → 1 次强制布局) */
@@ -205,20 +240,39 @@ function scheduleAutosize(): void {
205
240
  }
206
241
 
207
242
  /**
208
- * 按内容增高浮出面板,不超过 CSS max-height。
243
+ * 仅在鼠标悬停、获得焦点或编辑时按内容增高浮出面板,不超过 CSS max-height。
209
244
  * 增高走绝对定位,公式栏文档流高度始终单行。
210
245
  */
211
246
  function autosizeFx(): void {
212
247
  const el = fxRef.value
213
248
  if (!el) return
249
+ if (!fxHovered.value && !fxFocused.value && !editing.value) {
250
+ collapseFx()
251
+ return
252
+ }
214
253
  el.style.height = '0px'
215
254
  const styles = getComputedStyle(el)
216
255
  const max = Number.parseFloat(styles.maxHeight)
217
256
  const min = Number.parseFloat(styles.minHeight)
257
+ const hasMultipleLines = fxDraft.value.includes('\n')
218
258
  const content = el.scrollHeight
219
259
  const next = Number.isFinite(max) && max > 0 ? Math.min(content, max) : content
220
260
  el.style.height = `${next}px`
221
- fxExpanded.value = Number.isFinite(min) ? next > min + 1 : next > 1
261
+ fxExpanded.value = (Number.isFinite(min) ? next > min + 1 : next > 1) || hasMultipleLines
262
+ }
263
+
264
+ function handleFxMouseEnter(): void {
265
+ fxHovered.value = true
266
+ if (fxDraft.value) {
267
+ autosizeFx()
268
+ }
269
+ }
270
+
271
+ function handleFxMouseLeave(): void {
272
+ fxHovered.value = false
273
+ if (!fxFocused.value && !editing.value) {
274
+ collapseFx()
275
+ }
222
276
  }
223
277
 
224
278
  function syncFxCursor(): void {
@@ -311,11 +365,13 @@ function commitName(): void {
311
365
 
312
366
  function handleFxFocus(): void {
313
367
  if (fxDisabled.value) return
368
+ fxFocused.value = true
314
369
  mirroring.value = false
315
370
  mirrorAddr = null
316
371
  editing.value = true
317
372
  editAddr = selection.value.activeCell
318
373
  syncFxCursor()
374
+ scheduleAutosize()
319
375
  }
320
376
 
321
377
  /**
@@ -323,12 +379,17 @@ function handleFxFocus(): void {
323
379
  * ✓/✗ / 候选列表用 mousedown.prevent 拦截失焦。
324
380
  */
325
381
  function handleFxBlur(): void {
326
- if (!editing.value) return
382
+ fxFocused.value = false
383
+ if (!editing.value) {
384
+ if (!fxHovered.value) collapseFx()
385
+ return
386
+ }
327
387
  if (suppressBlurCommit) {
328
388
  suppressBlurCommit = false
329
389
  return
330
390
  }
331
391
  commitEdit()
392
+ if (!fxHovered.value) collapseFx()
332
393
  }
333
394
 
334
395
  function handleFxKeydown(event: KeyboardEvent): void {
@@ -269,7 +269,7 @@
269
269
  line-height: 1.4;
270
270
  resize: none;
271
271
  overflow-x: hidden;
272
- overflow-y: auto;
272
+ overflow-y: hidden;
273
273
  outline: none;
274
274
 
275
275
  &:focus {
package/src/index.ts CHANGED
@@ -1,13 +1,5 @@
1
- // 内置工具注册(undo/redo/合并/取消合并):随包入口完成,
2
- // 与 sheet-core command 的 default-registry 同构;深导入 sheet-core 子路径的
3
- // 无头场景不涉及
4
1
  import './tools/builtin'
5
2
 
6
- // 数据模型 / 渲染内核在 @veltra/sheet-core(独立发包)。本包**不做** re-export:
7
- // core API(Workbook / Sheet / 公式 / IO 等)一律 `from '@veltra/sheet-core'` 直导;
8
- // SheetGrid 走 `@veltra/sheet-core/grid`;白名单外符号深导入其子路径。
9
- // 本入口只导出 sheet 自有能力:组件、tools、组件类型。
10
-
11
3
  export { createSheetContext, type SheetContext } from './tools/context'
12
4
 
13
5
  export {
@@ -19,24 +11,6 @@ export {
19
11
  type SheetToolGroup
20
12
  } from './tools/registry'
21
13
 
22
- export {
23
- type SheetProps,
24
- type SheetEmits,
25
- type _SheetExposed,
26
- type SheetExposed,
27
- type ReportViewerProps,
28
- type _ReportViewerExposed,
29
- type ReportViewerExposed,
30
- type ReportDesignerProps,
31
- type ReportDesignerEmits,
32
- type _ReportDesignerExposed,
33
- type ReportDesignerExposed
34
- } from './types'
14
+ export { type SheetProps, type SheetEmits, type _SheetExposed, type SheetExposed } from './types'
35
15
 
36
16
  export { USheet } from './components/sheet'
37
-
38
- export { UReportViewer, UReportDesigner } from './components/report'
39
-
40
- // 报表纯 TS 内核:renderReport / binding / rules / params / DataConnector / Report Template /
41
- // Filter Bar 值规范化(结构见 packages/sheet/AGENTS.md)
42
- export * from './report'
@@ -1,3 +1 @@
1
1
  export * from './sheet'
2
- export * from './report-viewer'
3
- export * from './report-designer'
@@ -1,118 +0,0 @@
1
- import { formatBindingPlaceholderParts, inferReportPreset } from "../../report/binding.js";
2
- import { CustomLayout } from "@veltra/sheet-core/grid";
3
- //#region src/components/report/binding-badge.ts
4
- const REPORT_PRESET_BADGE_COLORS = {
5
- groupHeader: {
6
- cell: "#eef4ff",
7
- fg: "#2f54eb"
8
- },
9
- detail: {
10
- cell: "#effaf3",
11
- fg: "#1f9254"
12
- },
13
- subtotal: {
14
- cell: "#fff7e6",
15
- fg: "#d46b08"
16
- },
17
- grandTotal: {
18
- cell: "#fff1f0",
19
- fg: "#cf1322"
20
- },
21
- cross: {
22
- cell: "#f8f5ff",
23
- fg: "#5f3dc4"
24
- }
25
- };
26
- const CUSTOM_PRESET_BADGE_COLOR = {
27
- cell: "#f7f8fa",
28
- fg: "#495057"
29
- };
30
- /** 徽章字段标签文字色(中性深灰,与强调色形成层次) */
31
- const BADGE_LABEL_COLOR = "#343a40";
32
- function resolveBadgeColor(binding) {
33
- const preset = inferReportPreset(binding);
34
- return preset ? REPORT_PRESET_BADGE_COLORS[preset] : CUSTOM_PRESET_BADGE_COLOR;
35
- }
36
- /** 绑定格角色底色(走 resolveCellStyle,保留 VTable 默认边框绘制) */
37
- function createBindingBadgeStyleResolver(getBindingAt) {
38
- return (addr, base) => {
39
- const binding = getBindingAt(addr);
40
- if (!binding) return base;
41
- const { cell } = resolveBadgeColor(binding);
42
- return {
43
- ...base,
44
- fill: { color: cell }
45
- };
46
- };
47
- }
48
- /**
49
- * 单元格对齐 → 徽章容器 flex 布局映射(纯函数,便于单测):
50
- * `horizontal` left / 缺省 → 主轴起点;`vertical` middle / 缺省 → 交叉轴居中。
51
- */
52
- function badgeLayoutProps(align) {
53
- return {
54
- justifyContent: align?.horizontal === "center" ? "center" : align?.horizontal === "right" ? "flex-end" : "flex-start",
55
- alignItems: align?.vertical === "top" ? "flex-start" : align?.vertical === "bottom" ? "flex-end" : "center"
56
- };
57
- }
58
- /**
59
- * 绑定格富渲染徽章(ADR-0004 `resolveCellRenderer` 首个消费者):
60
- * 绑定单元格渲染为徽章布局(强调色聚合标签 + 中性色字段标签),
61
- * 布局跟随单元格水平 / 垂直对齐(经 `resolveAlign` 读有效样式);
62
- * 未绑定格返回 `undefined` 回落默认渲染。
63
- */
64
- function createBindingBadgeRenderer(getBindingAt, resolveLabel, resolveAlign) {
65
- return (addr) => {
66
- const binding = getBindingAt(addr);
67
- if (!binding) return void 0;
68
- const { fg } = resolveBadgeColor(binding);
69
- const { tag, label } = formatBindingPlaceholderParts(binding, resolveLabel);
70
- const { justifyContent, alignItems } = badgeLayoutProps(resolveAlign?.(addr));
71
- const rootContainer = new CustomLayout.Container({
72
- display: "flex",
73
- flexDirection: "row",
74
- justifyContent,
75
- alignItems
76
- });
77
- const tagEl = new CustomLayout.Tag({
78
- text: tag,
79
- textStyle: {
80
- fontSize: 10,
81
- fontWeight: 600,
82
- fill: "#ffffff"
83
- },
84
- panel: {
85
- visible: true,
86
- fill: fg,
87
- cornerRadius: 3
88
- },
89
- padding: [
90
- 1,
91
- 4,
92
- 1,
93
- 4
94
- ],
95
- marginLeft: 6,
96
- marginRight: 5
97
- });
98
- rootContainer.add(tagEl);
99
- rootContainer.add(new CustomLayout.Text({
100
- text: label,
101
- fontSize: 11,
102
- fontWeight: 500,
103
- fill: BADGE_LABEL_COLOR
104
- }));
105
- if (binding.drill) rootContainer.add(new CustomLayout.Text({
106
- text: " ↗",
107
- fontSize: 11,
108
- fontWeight: 700,
109
- fill: fg
110
- }));
111
- return {
112
- rootContainer,
113
- renderDefault: false
114
- };
115
- };
116
- }
117
- //#endregion
118
- export { REPORT_PRESET_BADGE_COLORS, badgeLayoutProps, createBindingBadgeRenderer, createBindingBadgeStyleResolver };
@@ -1,46 +0,0 @@
1
- function resolveGridOverlayLayout(host) {
2
- const gridEl = host.querySelector(".u-sheet__grid-instance");
3
- if (!gridEl) return null;
4
- const hostBox = host.getBoundingClientRect();
5
- const gridBox = gridEl.getBoundingClientRect();
6
- return {
7
- gridEl,
8
- layout: {
9
- offsetX: gridBox.left - hostBox.left,
10
- offsetY: gridBox.top - hostBox.top,
11
- viewW: gridEl.clientWidth,
12
- viewH: gridEl.clientHeight
13
- }
14
- };
15
- }
16
- /** 将屏幕坐标换算为网格落点地址(用于字段拖拽 bind) */
17
- function resolveGridDropAddress(grid, gridEl, clientX, clientY) {
18
- const rect = gridEl.getBoundingClientRect();
19
- return grid.hitTestSheetAddr(clientX - rect.left, clientY - rect.top) ?? null;
20
- }
21
- function getCellOverlayRect(grid, cell, layout) {
22
- const table = grid.getTable();
23
- let cellRect;
24
- try {
25
- cellRect = table.getCellRelativeRect(cell.col + 1, cell.row + 1);
26
- } catch {
27
- return null;
28
- }
29
- const left = layout.offsetX + cellRect.left;
30
- const top = layout.offsetY + cellRect.top;
31
- const right = layout.offsetX + cellRect.right;
32
- const bottom = layout.offsetY + cellRect.bottom;
33
- if (cellRect.bottom < 0 || cellRect.right < 0 || cellRect.top > layout.viewH || cellRect.left > layout.viewW) return null;
34
- return {
35
- left,
36
- top,
37
- right,
38
- bottom,
39
- width: right - left,
40
- height: bottom - top,
41
- centerX: (left + right) / 2,
42
- centerY: (top + bottom) / 2
43
- };
44
- }
45
- //#endregion
46
- export { getCellOverlayRect, resolveGridDropAddress, resolveGridOverlayLayout };
@@ -1,29 +0,0 @@
1
- //#region src/components/report/designer/col-widths.ts
2
- /** 行号列数(隐藏行头时为 0;与 GridCoords 探测一致) */
3
- function seriesNumberColCount(table) {
4
- const rowOffset = table.columnHeaderLevelCount;
5
- let col = 0;
6
- while (col < table.colCount && table.isSeriesNumber(col, rowOffset)) col++;
7
- return col;
8
- }
9
- /** 将模型列宽写入 VTable(模型 → grid 同步辅助) */
10
- function applyGridColWidths(grid, widths) {
11
- if (!grid) return;
12
- const table = grid.getTable();
13
- const colOffset = seriesNumberColCount(table);
14
- for (const [sheetCol, width] of widths) table.setColWidth(sheetCol + colOffset, width);
15
- }
16
- /** 把列宽条目写入 Sheet 模型(不进 undo,对称 setColWidth) */
17
- function applySheetColWidths(sheet, widths) {
18
- if (!sheet) return;
19
- for (const [col, width] of widths) sheet.setColWidth(col, width);
20
- }
21
- /** 从当前网格读取指定模型列宽度;网格未就绪时返回 null */
22
- function readGridColWidths(grid, cols) {
23
- if (!grid) return null;
24
- const table = grid.getTable();
25
- const colOffset = seriesNumberColCount(table);
26
- return cols.map((sheetCol) => [sheetCol, table.getColWidth(sheetCol + colOffset)]);
27
- }
28
- //#endregion
29
- export { applyGridColWidths, applySheetColWidths, readGridColWidths };