jvs-ppt-ui 0.0.8 → 0.0.10

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 (34) hide show
  1. package/README.md +60 -2
  2. package/dist/lib/jvs-ppt-ui.es.js +22404 -21454
  3. package/dist/lib/jvs-ppt-ui.umd.js +102 -101
  4. package/dist/lib/style.css +1 -1
  5. package/package.json +1 -1
  6. package/src/App.vue +53 -53
  7. package/src/components/AIPptDialog.vue +2 -0
  8. package/src/components/CanvasArea.vue +164 -72
  9. package/src/components/Header.vue +374 -144
  10. package/src/components/PptEditor.vue +33 -15
  11. package/src/components/PresentationMode.vue +24 -4
  12. package/src/components/SidebarRight.vue +8 -1
  13. package/src/components/SvgChart.vue +5 -2
  14. package/src/components/TemplateGallery.vue +1321 -866
  15. package/src/components/Toolbar.vue +244 -22
  16. package/src/components/canvas/CanvasTransformHandles.vue +5 -1
  17. package/src/components/canvas/elements/CanvasShapeElement.vue +98 -19
  18. package/src/components/canvas/elements/CanvasTextElement.vue +39 -9
  19. package/src/components/canvas/textSelectionOverlay.ts +305 -0
  20. package/src/composables/canvas/useCanvasAlignment.ts +286 -238
  21. package/src/composables/canvas/useCanvasContextMenu.ts +53 -22
  22. package/src/composables/canvas/useCanvasFormatting.ts +35 -12
  23. package/src/composables/canvas/useCanvasTable.ts +52 -24
  24. package/src/composables/canvas/useCanvasText.ts +12 -0
  25. package/src/composables/canvas/useCanvasTransform.ts +15 -2
  26. package/src/composables/sidebar/useSidebarElementTransform.ts +5 -5
  27. package/src/composables/sidebar/useSidebarShapeFormat.ts +2 -2
  28. package/src/composables/useSlides.ts +495 -132
  29. package/src/style.css +88 -0
  30. package/src/types/index.ts +8 -0
  31. package/src/utils/line.ts +274 -312
  32. package/src/utils/pptxShapes.ts +1 -1
  33. package/src/utils/pptxShapesLazy.ts +39 -0
  34. package/src/utils/svgPathParser.ts +12 -1
@@ -1,5 +1,5 @@
1
1
  import { ref, computed, nextTick, type Ref } from 'vue'
2
- import { SHAPE_PATH_FORMULAS } from '../../utils/pptxShapes'
2
+ import { shapeFormulas } from '../../utils/pptxShapesLazy'
3
3
 
4
4
  export interface FormattingOptions {
5
5
  activeSlide: Ref<any>
@@ -45,6 +45,29 @@ export function useCanvasFormatting(options: FormattingOptions) {
45
45
 
46
46
  const quickRecentColors = ref<string[]>([])
47
47
 
48
+ // 组合内子元素感知:按选中 id 递归解析(含嵌套组),不能只查顶层 elements,
49
+ // 否则选中组合内子元素时字号/颜色/填充/边框等设置全部静默失效
50
+ function findElementNested(id: string | null | undefined, elements: any[] = activeSlide.value?.elements || []): any {
51
+ if (!id) return null
52
+ for (const el of elements) {
53
+ if (el.id === id) return el
54
+ if (Array.isArray(el.elements) && el.elements.length) {
55
+ const found = findElementNested(id, el.elements)
56
+ if (found) return found
57
+ }
58
+ }
59
+ return null
60
+ }
61
+
62
+ function resolveSelectedElements(typeFilter?: string): any[] {
63
+ const out: any[] = []
64
+ for (const id of selectedElementIds.value || []) {
65
+ const el = findElementNested(id)
66
+ if (el && (!typeFilter || el.type === typeFilter)) out.push(el)
67
+ }
68
+ return out
69
+ }
70
+
48
71
  function rgbToHex(rgbStr: string | undefined): string {
49
72
  if (!rgbStr || rgbStr === 'transparent') return 'transparent'
50
73
  if (rgbStr.startsWith('#')) return rgbStr
@@ -147,7 +170,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
147
170
  const quickBorderStyle = computed({
148
171
  get() {
149
172
  if (!selectedElementId.value || !activeSlide.value) return 'solid'
150
- const el = activeSlide.value.elements.find((e: any) => e.id === selectedElementId.value)
173
+ const el = findElementNested(selectedElementId.value)
151
174
  if (!el) return 'solid'
152
175
  if (el.type === 'line') {
153
176
  return el.lineStyle || 'solid'
@@ -156,7 +179,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
156
179
  },
157
180
  set(val) {
158
181
  if (selectedElementIds.value.length === 0 || !activeSlide.value) return
159
- const els = activeSlide.value.elements.filter((e: any) => selectedElementIds.value.includes(e.id))
182
+ const els = resolveSelectedElements()
160
183
  if (els.length === 0) return
161
184
  els.forEach((el: any) => {
162
185
  if (el.type === 'line') {
@@ -171,7 +194,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
171
194
 
172
195
  const quickBorderWidth = computed({
173
196
  get() {
174
- const el = (selectedElement && selectedElement.value) || (activeSlide.value && selectedElementId.value ? activeSlide.value.elements.find((e: any) => e.id === selectedElementId.value) : null)
197
+ const el = (selectedElement && selectedElement.value) || findElementNested(selectedElementId.value)
175
198
  if (!el) return 1
176
199
  if (el.type === 'line') {
177
200
  return el.style?.strokeWidth !== undefined ? el.style.strokeWidth : 1
@@ -181,7 +204,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
181
204
  },
182
205
  set(val) {
183
206
  if (selectedElementIds.value.length === 0 || !activeSlide.value) return
184
- const els = activeSlide.value.elements.filter((e: any) => selectedElementIds.value.includes(e.id))
207
+ const els = resolveSelectedElements()
185
208
  if (els.length === 0) return
186
209
  els.forEach((el: any) => {
187
210
  let num = val
@@ -324,7 +347,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
324
347
 
325
348
  function selectQuickTextColor(color: string, type: 'color' | 'background') {
326
349
  if (selectedElementIds.value.length === 0 || !activeSlide.value) return
327
- const els = activeSlide.value.elements.filter((e: any) => selectedElementIds.value.includes(e.id))
350
+ const els = resolveSelectedElements()
328
351
  if (els.length === 0) return
329
352
 
330
353
  // 0. Synchronize DOM contents to reactive state first for non-table elements
@@ -581,7 +604,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
581
604
 
582
605
  function selectQuickFillColor(color: string) {
583
606
  if (selectedElementIds.value.length === 0 || !activeSlide.value) return
584
- const els = activeSlide.value.elements.filter((e: any) => selectedElementIds.value.includes(e.id))
607
+ const els = resolveSelectedElements()
585
608
  if (els.length === 0) return
586
609
 
587
610
  let hasAppliedToCells = false
@@ -649,7 +672,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
649
672
 
650
673
  function changeQuickBorderColor(color: string) {
651
674
  if (selectedElementIds.value.length === 0 || !activeSlide.value) return
652
- const els = activeSlide.value.elements.filter((e: any) => selectedElementIds.value.includes(e.id))
675
+ const els = resolveSelectedElements()
653
676
  if (els.length === 0) return
654
677
 
655
678
  els.forEach((el: any) => {
@@ -697,7 +720,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
697
720
  if (!el) return
698
721
  const isEllipse = shape.title === '椭圆' || shape.pathFormula === 'ellipse' || shape.pptxShapeType === 'ellipse'
699
722
  if (selectedElementIds.value.length > 1 && activeSlide.value) {
700
- const els = activeSlide.value.elements.filter((e: any) => selectedElementIds.value.includes(e.id) && e.type === 'shape')
723
+ const els = resolveSelectedElements('shape')
701
724
  els.forEach((item: any) => {
702
725
  item.content = shape.path
703
726
  item.viewBox = shape.viewBox
@@ -712,7 +735,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
712
735
 
713
736
  if (shape.pathFormula) {
714
737
  item.pathFormula = shape.pathFormula
715
- const formulaObj = SHAPE_PATH_FORMULAS[shape.pathFormula]
738
+ const formulaObj = shapeFormulas()[shape.pathFormula]
716
739
  if (formulaObj) {
717
740
  if (shape.keypoints) {
718
741
  item.keypoints = [...shape.keypoints]
@@ -745,7 +768,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
745
768
 
746
769
  if (shape.pathFormula) {
747
770
  el.pathFormula = shape.pathFormula
748
- const formulaObj = SHAPE_PATH_FORMULAS[shape.pathFormula]
771
+ const formulaObj = shapeFormulas()[shape.pathFormula]
749
772
  if (formulaObj) {
750
773
  if (shape.keypoints) {
751
774
  el.keypoints = [...shape.keypoints]
@@ -786,7 +809,7 @@ export function useCanvasFormatting(options: FormattingOptions) {
786
809
  }
787
810
 
788
811
  if (selectedElementIds.value.length > 1 && activeSlide.value) {
789
- const els = activeSlide.value.elements.filter((e: any) => selectedElementIds.value.includes(e.id) && e.type === 'line')
812
+ const els = resolveSelectedElements('line')
790
813
  els.forEach(updateItem)
791
814
  } else {
792
815
  updateItem(el)
@@ -24,6 +24,27 @@ interface TableMeasure {
24
24
  rowDots: number[]
25
25
  }
26
26
 
27
+ // 剥离表格编辑态的运行时属性(contenteditable/selected-cell/选区边框/索引),
28
+ // 存入 el.content 前必须清理,否则编辑态样式会被烙进内容(退出编辑后蓝边框残留)
29
+ export function cleanTableDOMForSaving(tableEl: HTMLTableElement) {
30
+ tableEl.querySelectorAll('td').forEach(td => {
31
+ td.removeAttribute('contenteditable')
32
+ td.classList.remove('selected-cell')
33
+ td.classList.remove('focused-cell')
34
+ td.removeAttribute('data-row')
35
+ td.removeAttribute('data-col')
36
+ td.removeAttribute('data-sel-top')
37
+ td.removeAttribute('data-sel-bottom')
38
+ td.removeAttribute('data-sel-left')
39
+ td.removeAttribute('data-sel-right')
40
+ td.style.boxShadow = ''
41
+ if (td.style.cursor === 'default') {
42
+ td.style.removeProperty('cursor')
43
+ }
44
+ })
45
+ tableEl.style.removeProperty('cursor')
46
+ }
47
+
27
48
  export function useCanvasTable(options: TableOptions) {
28
49
  const {
29
50
  activeSlide,
@@ -97,6 +118,15 @@ export function useCanvasTable(options: TableOptions) {
97
118
  targetEl.content = html
98
119
  bumpTableMeasure()
99
120
  addHistorySnapshot()
121
+ // CanvasTextElement 的 syncContentToDom 在焦点位于单元格内时不再回写 DOM(保光标),
122
+ // 结构/样式操作随后的恢复代码(重设 contenteditable、重新绑定、重新聚焦)依赖新
123
+ // DOM,这里在 nextTick 强制同步一次;焦点不在表格内时组件 watch 已写过,此处幂等
124
+ nextTick(() => {
125
+ const container = document.getElementById(`editable-${targetEl.id}`)
126
+ if (container && container.innerHTML !== html) {
127
+ container.innerHTML = html
128
+ }
129
+ })
100
130
  }
101
131
 
102
132
  function getTableMeasure(el: any): TableMeasure | null {
@@ -359,6 +389,7 @@ export function useCanvasTable(options: TableOptions) {
359
389
 
360
390
  tableEl.querySelectorAll('td').forEach(td => {
361
391
  td.style.boxShadow = ''
392
+ td.classList.remove('focused-cell')
362
393
  td.removeAttribute('data-sel-top')
363
394
  td.removeAttribute('data-sel-bottom')
364
395
  td.removeAttribute('data-sel-left')
@@ -393,31 +424,16 @@ export function useCanvasTable(options: TableOptions) {
393
424
  if (isRight) shadows.push('inset -1.5px 0 0 0 #2563eb')
394
425
 
395
426
  if (selectedTds.length === 1 && activeEl === td) {
427
+ // 焦点(光标)落在唯一选中格上:既不要描边也不要 selected-cell 蒙层,
428
+ // 否则出现"光标在单元格里还显示选中效果";focused-cell 类供 CSS 压掉蒙层
396
429
  td.style.boxShadow = 'none'
430
+ td.classList.add('focused-cell')
397
431
  } else {
398
432
  td.style.boxShadow = shadows.length > 0 ? shadows.join(', ') : 'none'
399
433
  }
400
434
  })
401
435
  }
402
436
 
403
- function cleanTableDOMForSaving(tableEl: HTMLTableElement) {
404
- tableEl.querySelectorAll('td').forEach(td => {
405
- td.removeAttribute('contenteditable')
406
- td.classList.remove('selected-cell')
407
- td.removeAttribute('data-row')
408
- td.removeAttribute('data-col')
409
- td.removeAttribute('data-sel-top')
410
- td.removeAttribute('data-sel-bottom')
411
- td.removeAttribute('data-sel-left')
412
- td.removeAttribute('data-sel-right')
413
- td.style.boxShadow = ''
414
- if (td.style.cursor === 'default') {
415
- td.style.removeProperty('cursor')
416
- }
417
- })
418
- tableEl.style.removeProperty('cursor')
419
- }
420
-
421
437
  function doSelectColumn(tableEl: HTMLTableElement, el: any, colIdx: number) {
422
438
  tableEl.querySelectorAll('td').forEach(td => td.setAttribute('contenteditable', 'true'))
423
439
  bindTableSelectionEvents(el)
@@ -836,8 +852,10 @@ export function useCanvasTable(options: TableOptions) {
836
852
  const freshTd = freshTable.querySelector(`td[data-row="${newSelectR}"][data-col="${newSelectC}"]`) as HTMLTableCellElement
837
853
  if (freshTd) {
838
854
  freshTd.classList.add('selected-cell')
839
- updateSelectionBorders(freshTable)
855
+ // 先 focus 再算边框:focus() 同步设置 activeElement,这样 updateSelectionBorders
856
+ // 里"唯一选中格=焦点格"的抑制分支才生效,结构操作后不会边描边边留蒙层
840
857
  freshTd.focus()
858
+ updateSelectionBorders(freshTable)
841
859
  }
842
860
  }
843
861
  }
@@ -962,8 +980,10 @@ export function useCanvasTable(options: TableOptions) {
962
980
  const freshTd = freshTable.querySelector(`td[data-row="${newSelectR}"][data-col="${newSelectC}"]`) as HTMLTableCellElement
963
981
  if (freshTd) {
964
982
  freshTd.classList.add('selected-cell')
965
- updateSelectionBorders(freshTable)
983
+ // 先 focus 再算边框:focus() 同步设置 activeElement,这样 updateSelectionBorders
984
+ // 里"唯一选中格=焦点格"的抑制分支才生效,结构操作后不会边描边边留蒙层
966
985
  freshTd.focus()
986
+ updateSelectionBorders(freshTable)
967
987
  }
968
988
  }
969
989
  }
@@ -1024,8 +1044,10 @@ export function useCanvasTable(options: TableOptions) {
1024
1044
  const freshTd = freshTable.querySelector(`td[data-row="${newSelectR}"][data-col="${newSelectC}"]`) as HTMLTableCellElement
1025
1045
  if (freshTd) {
1026
1046
  freshTd.classList.add('selected-cell')
1027
- updateSelectionBorders(freshTable)
1047
+ // 先 focus 再算边框:focus() 同步设置 activeElement,这样 updateSelectionBorders
1048
+ // 里"唯一选中格=焦点格"的抑制分支才生效,结构操作后不会边描边边留蒙层
1028
1049
  freshTd.focus()
1050
+ updateSelectionBorders(freshTable)
1029
1051
  }
1030
1052
  }
1031
1053
  }
@@ -1092,8 +1114,10 @@ export function useCanvasTable(options: TableOptions) {
1092
1114
  const freshTd = freshTable.querySelector(`td[data-row="${newSelectR}"][data-col="${newSelectC}"]`) as HTMLTableCellElement
1093
1115
  if (freshTd) {
1094
1116
  freshTd.classList.add('selected-cell')
1095
- updateSelectionBorders(freshTable)
1117
+ // 先 focus 再算边框:focus() 同步设置 activeElement,这样 updateSelectionBorders
1118
+ // 里"唯一选中格=焦点格"的抑制分支才生效,结构操作后不会边描边边留蒙层
1096
1119
  freshTd.focus()
1120
+ updateSelectionBorders(freshTable)
1097
1121
  }
1098
1122
  }
1099
1123
  }
@@ -1158,8 +1182,10 @@ export function useCanvasTable(options: TableOptions) {
1158
1182
  const freshTd = freshTable.querySelector(`td[data-row="${bounds.minRow}"][data-col="${bounds.minCol}"]`) as HTMLTableCellElement
1159
1183
  if (freshTd) {
1160
1184
  freshTd.classList.add('selected-cell')
1161
- updateSelectionBorders(freshTable)
1185
+ // 先 focus 再算边框:focus() 同步设置 activeElement,这样 updateSelectionBorders
1186
+ // 里"唯一选中格=焦点格"的抑制分支才生效,结构操作后不会边描边边留蒙层
1162
1187
  freshTd.focus()
1188
+ updateSelectionBorders(freshTable)
1163
1189
  }
1164
1190
  }
1165
1191
  }
@@ -1260,8 +1286,10 @@ export function useCanvasTable(options: TableOptions) {
1260
1286
  const freshTd = freshTable.querySelector(`td[data-row="${rStart}"][data-col="${cStart}"]`) as HTMLTableCellElement
1261
1287
  if (freshTd) {
1262
1288
  freshTd.classList.add('selected-cell')
1263
- updateSelectionBorders(freshTable)
1289
+ // 先 focus 再算边框:focus() 同步设置 activeElement,这样 updateSelectionBorders
1290
+ // 里"唯一选中格=焦点格"的抑制分支才生效,结构操作后不会边描边边留蒙层
1264
1291
  freshTd.focus()
1292
+ updateSelectionBorders(freshTable)
1265
1293
  }
1266
1294
  }
1267
1295
  }
@@ -2,6 +2,7 @@ import { ref, nextTick, type Ref } from 'vue'
2
2
  import { normalizeHtmlFontFamily } from '../useSlides'
3
3
  import { getDefaultPlaceholderContent, isSvgPathString } from '../../utils/canvas/elementStyles'
4
4
  import { isEllipseShape } from '../../utils/line'
5
+ import { cleanTableDOMForSaving } from './useCanvasTable'
5
6
 
6
7
  export interface TextOptions {
7
8
  activeSlide: Ref<any>
@@ -514,6 +515,17 @@ export function useCanvasText(options: TextOptions) {
514
515
  htmlVal = htmlVal.replace(/style="\s*;\s*"/gi, '')
515
516
  htmlVal = htmlVal.replace(/style="\s*"/gi, '')
516
517
  }
518
+ // 表格:活 DOM 带编辑态运行时属性(contenteditable/selected-cell/选区边框),
519
+ // 存档前克隆清理,避免烙进 content(退出编辑后蓝边框残留)
520
+ if (htmlVal.includes('<table')) {
521
+ const div = document.createElement('div')
522
+ div.innerHTML = htmlVal
523
+ const tableEl = div.querySelector('table')
524
+ if (tableEl) {
525
+ cleanTableDOMForSaving(tableEl)
526
+ htmlVal = div.innerHTML
527
+ }
528
+ }
517
529
  el.content = htmlVal
518
530
 
519
531
  if (el.content && el.content.includes('<table')) {
@@ -1,5 +1,6 @@
1
1
  import { ref, nextTick, type Ref } from 'vue'
2
- import { SHAPE_PATH_FORMULAS } from '../../utils/pptxShapes'
2
+ import { shapeFormulas } from '../../utils/pptxShapesLazy'
3
+ import { syncSlideConnections } from '../../utils/line'
3
4
 
4
5
  export interface ResizeState {
5
6
  el: any
@@ -412,6 +413,9 @@ export function useCanvasTransform(options: CanvasTransformOptions) {
412
413
  }
413
414
  }
414
415
  }
416
+ if (activeSlide.value && activeSlide.value.elements) {
417
+ syncSlideConnections(activeSlide.value, logicalWidth.value, logicalHeight.value, selectedElementIds.value)
418
+ }
415
419
  }
416
420
 
417
421
  function stopResize() {
@@ -539,6 +543,9 @@ export function useCanvasTransform(options: CanvasTransformOptions) {
539
543
  newAngle = (newAngle % 360 + 360) % 360
540
544
  state.el.style.rotate = Math.round(newAngle)
541
545
  }
546
+ if (activeSlide.value && activeSlide.value.elements) {
547
+ syncSlideConnections(activeSlide.value, logicalWidth.value, logicalHeight.value, selectedElementIds.value)
548
+ }
542
549
  }
543
550
 
544
551
  function stopRotate() {
@@ -598,7 +605,7 @@ export function useCanvasTransform(options: CanvasTransformOptions) {
598
605
  if (!isDraggingKeypoint || !currentElement.value) return
599
606
 
600
607
  const curEl = currentElement.value
601
- const formulaObj = SHAPE_PATH_FORMULAS[curEl.pathFormula as string]
608
+ const formulaObj = shapeFormulas()[curEl.pathFormula as string]
602
609
  if (!formulaObj) return
603
610
 
604
611
  const dx = e.clientX - dragKeypointStartX
@@ -1031,6 +1038,9 @@ export function useCanvasTransform(options: CanvasTransformOptions) {
1031
1038
  parentGroup.elements[idx] = { ...curEl, path: newPath, content: newPath }
1032
1039
  }
1033
1040
  }
1041
+ if (activeSlide.value && activeSlide.value.elements) {
1042
+ syncSlideConnections(activeSlide.value, logicalWidth.value, logicalHeight.value, selectedElementIds.value)
1043
+ }
1034
1044
  }
1035
1045
 
1036
1046
  function stopDragKeypoint() {
@@ -1249,6 +1259,9 @@ export function useCanvasTransform(options: CanvasTransformOptions) {
1249
1259
  currentElement.value = null
1250
1260
  window.removeEventListener('mousemove', handleDragLinePoint)
1251
1261
  window.removeEventListener('mouseup', stopDragLinePoint)
1262
+ if (activeSlide.value && activeSlide.value.elements) {
1263
+ syncSlideConnections(activeSlide.value, logicalWidth.value, logicalHeight.value, selectedElementIds.value)
1264
+ }
1252
1265
  pauseHistory.value = false
1253
1266
  addHistorySnapshot()
1254
1267
  }
@@ -1,5 +1,5 @@
1
1
  import { computed, type Ref, type ComputedRef } from 'vue'
2
- import { SHAPE_PATH_FORMULAS } from '../../utils/pptxShapes'
2
+ import { shapeFormulas } from '../../utils/pptxShapesLazy'
3
3
  import { useSlides } from '../useSlides'
4
4
 
5
5
  export function useSidebarElementTransform(
@@ -277,7 +277,7 @@ export function useSidebarElementTransform(
277
277
  if (typeof el.height === 'number') el.height = newH
278
278
  }
279
279
  if (el.type === 'shape' && el.pathFormula) {
280
- const formulaObj = SHAPE_PATH_FORMULAS[el.pathFormula]
280
+ const formulaObj = shapeFormulas()[el.pathFormula]
281
281
  if (formulaObj) {
282
282
  const logicalW = parseFloat(el.style.width) || val
283
283
  const logicalH = parseFloat(el.style.height) || 120
@@ -333,7 +333,7 @@ export function useSidebarElementTransform(
333
333
  })
334
334
  }
335
335
  if (selectedElement.value.type === 'shape' && selectedElement.value.pathFormula) {
336
- const formulaObj = SHAPE_PATH_FORMULAS[selectedElement.value.pathFormula]
336
+ const formulaObj = shapeFormulas()[selectedElement.value.pathFormula]
337
337
  if (formulaObj) {
338
338
  const logicalW = parseFloat(selectedElement.value.style.width) || val
339
339
  const logicalH = parseFloat(selectedElement.value.style.height) || 120
@@ -408,7 +408,7 @@ export function useSidebarElementTransform(
408
408
  if (typeof el.width === 'number') el.width = newW
409
409
  }
410
410
  if (el.type === 'shape' && el.pathFormula) {
411
- const formulaObj = SHAPE_PATH_FORMULAS[el.pathFormula]
411
+ const formulaObj = shapeFormulas()[el.pathFormula]
412
412
  if (formulaObj) {
413
413
  const logicalW = parseFloat(el.style.width) || 120
414
414
  const logicalH = parseFloat(el.style.height) || val
@@ -464,7 +464,7 @@ export function useSidebarElementTransform(
464
464
  })
465
465
  }
466
466
  if (selectedElement.value.type === 'shape' && selectedElement.value.pathFormula) {
467
- const formulaObj = SHAPE_PATH_FORMULAS[selectedElement.value.pathFormula]
467
+ const formulaObj = shapeFormulas()[selectedElement.value.pathFormula]
468
468
  if (formulaObj) {
469
469
  const logicalW = parseFloat(selectedElement.value.style.width) || 120
470
470
  const logicalH = parseFloat(selectedElement.value.style.height) || val
@@ -1,5 +1,5 @@
1
1
  import { ref, computed, watch, nextTick, type Ref, type ComputedRef } from 'vue'
2
- import { SHAPE_PATH_FORMULAS } from '../../utils/pptxShapes'
2
+ import { shapeFormulas } from '../../utils/pptxShapesLazy'
3
3
  import {
4
4
  isImagePlaceholder,
5
5
  normalizeGradientConfig,
@@ -1253,7 +1253,7 @@ export function useSidebarShapeFormat(
1253
1253
 
1254
1254
  if (shape.pathFormula) {
1255
1255
  item.pathFormula = shape.pathFormula
1256
- const formulaObj = SHAPE_PATH_FORMULAS[shape.pathFormula]
1256
+ const formulaObj = shapeFormulas()[shape.pathFormula]
1257
1257
  if (formulaObj) {
1258
1258
  if (shape.keypoints) {
1259
1259
  item.keypoints = [...shape.keypoints]