jvs-ppt-ui 0.0.14 → 0.0.16

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 (67) hide show
  1. package/dist/lib/check_imgs.html +18 -0
  2. package/dist/lib/jvs-ppt-ui/iconfont/iconfont.css +187 -27
  3. package/dist/lib/jvs-ppt-ui/iconfont/iconfont.js +1 -1
  4. package/dist/lib/jvs-ppt-ui/iconfont/iconfont.json +345 -65
  5. package/dist/lib/jvs-ppt-ui/iconfont/iconfont.ttf +0 -0
  6. package/dist/lib/jvs-ppt-ui/iconfont/iconfont.woff +0 -0
  7. package/dist/lib/jvs-ppt-ui/iconfont/iconfont.woff2 +0 -0
  8. package/dist/lib/jvs-ppt-ui/img/al.png +0 -0
  9. package/dist/lib/jvs-ppt-ui/img/d.png +0 -0
  10. package/dist/lib/jvs-ppt-ui/img/dl.png +0 -0
  11. package/dist/lib/jvs-ppt-ui/img/l.png +0 -0
  12. package/dist/lib/jvs-ppt-ui.es.js +44973 -43349
  13. package/dist/lib/jvs-ppt-ui.umd.js +102 -102
  14. package/dist/lib/style.css +1 -1
  15. package/package.json +1 -1
  16. package/scripts/check-icons.mjs +22 -0
  17. package/scripts/patch-anim-icons.mjs +45 -0
  18. package/src/assets/iconfont/iconfont.css +187 -27
  19. package/src/assets/iconfont/iconfont.js +1 -1
  20. package/src/assets/iconfont/iconfont.json +345 -65
  21. package/src/assets/iconfont/iconfont.ttf +0 -0
  22. package/src/assets/iconfont/iconfont.woff +0 -0
  23. package/src/assets/iconfont/iconfont.woff2 +0 -0
  24. package/src/components/CanvasArea.vue +218 -193
  25. package/src/components/ChartTypeSelector.vue +509 -148
  26. package/src/components/Header.vue +327 -44
  27. package/src/components/PresentationGroupChild.vue +44 -13
  28. package/src/components/PresentationMode.vue +84 -33
  29. package/src/components/QuickBorderPopover.vue +51 -11
  30. package/src/components/QuickColorPopover.vue +65 -21
  31. package/src/components/SidebarLeft.vue +286 -107
  32. package/src/components/SidebarRight.vue +45 -38
  33. package/src/components/TemplateGallery.vue +1110 -1237
  34. package/src/components/ToastNotification.vue +2 -2
  35. package/src/components/Toolbar.vue +825 -733
  36. package/src/components/canvas/CanvasQuickToolbar.vue +17 -30
  37. package/src/components/canvas/elements/CanvasGroupElement.vue +6 -0
  38. package/src/components/canvas/elements/CanvasShapeElement.vue +198 -38
  39. package/src/components/canvas/elements/CanvasTextElement.vue +4 -3
  40. package/src/components/sidebar/common/SidebarAlignGroup.vue +104 -50
  41. package/src/components/sidebar/common/SidebarBorderAccordion.vue +375 -148
  42. package/src/components/sidebar/common/SidebarPositionGroup.vue +358 -149
  43. package/src/components/sidebar/common/SidebarReflectionAccordion.vue +429 -203
  44. package/src/components/sidebar/common/SidebarShadowAccordion.vue +844 -416
  45. package/src/components/sidebar/panels/GradientEditor.vue +671 -316
  46. package/src/components/sidebar/panels/LayoutThumbSvg.vue +33 -16
  47. package/src/components/sidebar/panels/SidebarAnimationPanel.vue +701 -138
  48. package/src/components/sidebar/panels/SidebarChartFormatPanel.vue +3 -3
  49. package/src/components/sidebar/panels/SidebarDesignPanel.vue +1754 -416
  50. package/src/components/sidebar/panels/SidebarMediaFormatPanel.vue +12 -0
  51. package/src/components/sidebar/panels/SidebarShapeFormatPanel.vue +813 -174
  52. package/src/components/sidebar/panels/SidebarTableFormatPanel.vue +2 -2
  53. package/src/components/sidebar/panels/SidebarTextFormatPanel.vue +1938 -1427
  54. package/src/components/sidebar/panels/SidebarTransitionPanel.vue +791 -210
  55. package/src/composables/canvas/useCanvasShortcuts.ts +20 -6
  56. package/src/composables/canvas/useCanvasText.ts +1 -1
  57. package/src/composables/canvas/useCanvasTransform.ts +44 -0
  58. package/src/composables/presetThemes.ts +43 -44
  59. package/src/composables/sidebar/useSidebarAnimation.ts +101 -25
  60. package/src/composables/sidebar/useSidebarDesign.ts +30 -11
  61. package/src/composables/sidebar/useSidebarElementTransform.ts +10 -1
  62. package/src/composables/sidebar/useSidebarImage.ts +10 -2
  63. package/src/composables/sidebar/useSidebarShapeFormat.ts +562 -107
  64. package/src/composables/useSlides.ts +331 -153
  65. package/src/main.ts +2 -0
  66. package/src/style.css +926 -359
  67. package/src/utils/canvas/elementStyles.ts +42 -1
@@ -16,7 +16,9 @@ import {
16
16
  hasElementBorderGradient,
17
17
  getElementBorderGradientCss,
18
18
  getGradientAngleDeg,
19
- getSvgGradientCoords
19
+ getSvgGradientCoords,
20
+ isElementPatternTile,
21
+ getElementPatternTileSize
20
22
  } from '../utils/canvas/elementStyles'
21
23
  import {
22
24
  getLineElementPath, getLineElementRenderPath, getLineDashArray, getSvgWidth, getSvgHeight, isEllipseShape
@@ -532,6 +534,22 @@ function getElementWidthHeight(el: any) {
532
534
  return { width, height }
533
535
  }
534
536
 
537
+ function getShapePatternTransform(el: any, isTriangle = false): string | undefined {
538
+ if (!isElementPatternTile(el)) return undefined
539
+ const dim = getElementWidthHeight(el)
540
+ const w = Math.max(1, dim.width || 100)
541
+ const h = Math.max(1, dim.height || 100)
542
+ if (isTriangle) {
543
+ return `scale(${+(100 / w).toFixed(4)}, ${+(100 / h).toFixed(4)})`
544
+ }
545
+ const vbW = el.viewBox ? el.viewBox[0] : 200
546
+ const vbH = el.viewBox ? el.viewBox[1] : 200
547
+ const bw = el.shapType === 'arc' ? 0 : (el.style?.borderWidth ? parseFloat(el.style.borderWidth) : 2)
548
+ const effW = Math.max(1, w - bw)
549
+ const effH = Math.max(1, h - bw)
550
+ return `scale(${+(vbW / effW).toFixed(4)}, ${+(vbH / effH).toFixed(4)})`
551
+ }
552
+
535
553
  function parseColorString(fill: any, fallback = 'none'): string {
536
554
  if (!fill) return fallback
537
555
  if (typeof fill === 'string') return fill
@@ -1120,14 +1138,17 @@ function getSafeShapeText(el: any): string {
1120
1138
  <svg v-if="el.path || (el.content && (el.content.trim().startsWith('M') || el.content.trim().startsWith('m')))"
1121
1139
  :viewBox="`0 0 ${el.viewBox ? el.viewBox[0] : (el.width || 200)} ${el.viewBox ? el.viewBox[1] : (el.height || 200)}`"
1122
1140
  preserveAspectRatio="none" style="width: 100%; height: 100%; display: block; overflow: visible;">
1123
- <defs v-if="getElementPattern(el)">
1124
- <pattern :id="`pres-master-pat-${slide.id || activeIndex}-${el.id}`" width="100%" height="100%" patternContentUnits="objectBoundingBox">
1125
- <image :href="getElementPattern(el)" width="1" height="1" preserveAspectRatio="none" />
1126
- </pattern>
1127
- </defs>
1128
1141
  <defs>
1129
- <pattern v-if="getElementPattern(el)" :id="`pres-master-pat-${slide.id || activeIndex}-${el.id}`" width="100%" height="100%" patternContentUnits="objectBoundingBox">
1130
- <image :href="getElementPattern(el)" width="1" height="1" preserveAspectRatio="none" />
1142
+ <pattern v-if="getElementPattern(el)" :id="`pres-master-pat-${slide.id || activeIndex}-${el.id}`"
1143
+ :width="isElementPatternTile(el) ? getElementPatternTileSize(el).w : '100%'"
1144
+ :height="isElementPatternTile(el) ? getElementPatternTileSize(el).h : '100%'"
1145
+ :patternUnits="isElementPatternTile(el) ? 'userSpaceOnUse' : 'objectBoundingBox'"
1146
+ :patternContentUnits="isElementPatternTile(el) ? 'userSpaceOnUse' : 'objectBoundingBox'"
1147
+ :patternTransform="getShapePatternTransform(el, false)">
1148
+ <image :href="getElementPattern(el)"
1149
+ :width="isElementPatternTile(el) ? getElementPatternTileSize(el).w : 1"
1150
+ :height="isElementPatternTile(el) ? getElementPatternTileSize(el).h : 1"
1151
+ preserveAspectRatio="none" />
1131
1152
  </pattern>
1132
1153
  <template v-if="getElementGradientConfig(el)">
1133
1154
  <radialGradient v-if="getElementGradientConfig(el)!.path && getElementGradientConfig(el)!.path !== 'line'"
@@ -1169,7 +1190,9 @@ function getSafeShapeText(el: any): string {
1169
1190
  <div v-else :style="{
1170
1191
  backgroundColor: getElementPattern(el) ? 'transparent' : ((getElementGradientCss(el) || (getElementFill(el) !== undefined && getElementFill(el) !== 'none')) ? (getElementGradientCss(el) ? 'transparent' : getElementFill(el)) : (getElementFill(el) === 'none' ? 'transparent' : '#3b82f6')),
1171
1192
  backgroundImage: getElementPattern(el) ? `url('${getElementPattern(el)}')` : (getElementGradientCss(el) || 'none'),
1172
- backgroundSize: getElementPattern(el) ? 'cover' : undefined,
1193
+ backgroundSize: getElementPattern(el) ? (isElementPatternTile(el) ? `${getElementPatternTileSize(el).w}px ${getElementPatternTileSize(el).h}px` : 'cover') : undefined,
1194
+ backgroundPosition: getElementPattern(el) ? (isElementPatternTile(el) ? '0 0' : 'center center') : undefined,
1195
+ backgroundRepeat: getElementPattern(el) ? (isElementPatternTile(el) ? 'repeat' : 'no-repeat') : undefined,
1173
1196
  width: '100%',
1174
1197
  height: '100%',
1175
1198
  borderRadius: el.style?.borderRadius || '0px',
@@ -1321,9 +1344,9 @@ function getSafeShapeText(el: any): string {
1321
1344
  height: '100%',
1322
1345
  backgroundColor: getElementPattern(el) ? 'transparent' : ((getElementGradientCss(el) || (getElementFill(el) !== undefined && getElementFill(el) !== 'none')) ? (getElementGradientCss(el) ? 'transparent' : getElementFill(el)) : (getElementFill(el) === 'none' ? 'transparent' : '#3b82f6')),
1323
1346
  backgroundImage: getElementPattern(el) ? `url('${getElementPattern(el)}')` : (getElementGradientCss(el) || 'none'),
1324
- backgroundSize: getElementPattern(el) ? 'cover' : undefined,
1325
- backgroundPosition: getElementPattern(el) ? 'center center' : undefined,
1326
- backgroundRepeat: getElementPattern(el) ? 'no-repeat' : undefined,
1347
+ backgroundSize: getElementPattern(el) ? (isElementPatternTile(el) ? `${getElementPatternTileSize(el).w}px ${getElementPatternTileSize(el).h}px` : 'cover') : undefined,
1348
+ backgroundPosition: getElementPattern(el) ? (isElementPatternTile(el) ? '0 0' : 'center center') : undefined,
1349
+ backgroundRepeat: getElementPattern(el) ? (isElementPatternTile(el) ? 'repeat' : 'no-repeat') : undefined,
1327
1350
  borderRadius: '50%',
1328
1351
  borderWidth: `${getElementBorderWidth(el)}px`,
1329
1352
  borderStyle: el.style?.borderStyle || (el as any).borderType || 'solid',
@@ -1337,9 +1360,16 @@ function getSafeShapeText(el: any): string {
1337
1360
  style="width: 100%; height: 100%; display: block; overflow: visible;"
1338
1361
  :style="{ filter: (el.shadow && el.shadow.type === 'inner') ? `url(#pres-shape-inner-shadow-${el.id})` : '' }">
1339
1362
  <defs>
1340
- <pattern v-if="getElementPattern(el)" :id="`pres-main-shape-pattern-${el.id}`" width="100%" height="100%"
1341
- patternContentUnits="objectBoundingBox">
1342
- <image :href="getElementPattern(el)" width="1" height="1" preserveAspectRatio="none" />
1363
+ <pattern v-if="getElementPattern(el)" :id="`pres-main-shape-pattern-${el.id}`"
1364
+ :width="isElementPatternTile(el) ? getElementPatternTileSize(el).w : '100%'"
1365
+ :height="isElementPatternTile(el) ? getElementPatternTileSize(el).h : '100%'"
1366
+ :patternUnits="isElementPatternTile(el) ? 'userSpaceOnUse' : 'objectBoundingBox'"
1367
+ :patternContentUnits="isElementPatternTile(el) ? 'userSpaceOnUse' : 'objectBoundingBox'"
1368
+ :patternTransform="getShapePatternTransform(el, true)">
1369
+ <image :href="getElementPattern(el)"
1370
+ :width="isElementPatternTile(el) ? getElementPatternTileSize(el).w : 1"
1371
+ :height="isElementPatternTile(el) ? getElementPatternTileSize(el).h : 1"
1372
+ preserveAspectRatio="none" />
1343
1373
  </pattern>
1344
1374
  <template v-if="getElementGradientConfig(el)">
1345
1375
  <radialGradient
@@ -1394,9 +1424,16 @@ function getSafeShapeText(el: any): string {
1394
1424
  <svg overflow="visible" style="width: 100%; height: 100%; display: block; overflow: visible;"
1395
1425
  :style="{ filter: (el.shadow && el.shadow.type === 'inner') ? `url(#pres-shape-inner-shadow-${el.id})` : '' }">
1396
1426
  <defs>
1397
- <pattern v-if="getElementPattern(el)" :id="`pres-main-shape-pattern-${el.id}`" width="100%" height="100%"
1398
- patternContentUnits="objectBoundingBox">
1399
- <image :href="getElementPattern(el)" width="1" height="1" preserveAspectRatio="none" />
1427
+ <pattern v-if="getElementPattern(el)" :id="`pres-main-shape-pattern-${el.id}`"
1428
+ :width="isElementPatternTile(el) ? getElementPatternTileSize(el).w : '100%'"
1429
+ :height="isElementPatternTile(el) ? getElementPatternTileSize(el).h : '100%'"
1430
+ :patternUnits="isElementPatternTile(el) ? 'userSpaceOnUse' : 'objectBoundingBox'"
1431
+ :patternContentUnits="isElementPatternTile(el) ? 'userSpaceOnUse' : 'objectBoundingBox'"
1432
+ :patternTransform="getShapePatternTransform(el, false)">
1433
+ <image :href="getElementPattern(el)"
1434
+ :width="isElementPatternTile(el) ? getElementPatternTileSize(el).w : 1"
1435
+ :height="isElementPatternTile(el) ? getElementPatternTileSize(el).h : 1"
1436
+ preserveAspectRatio="none" />
1400
1437
  </pattern>
1401
1438
  <template v-if="getElementGradientConfig(el)">
1402
1439
  <radialGradient
@@ -1453,9 +1490,9 @@ function getSafeShapeText(el: any): string {
1453
1490
  height: '100%',
1454
1491
  backgroundColor: getElementPattern(el) ? 'transparent' : ((getElementGradientCss(el) || (getElementFill(el) !== undefined && getElementFill(el) !== 'none')) ? (getElementGradientCss(el) ? 'transparent' : getElementFill(el)) : (getElementFill(el) === 'none' ? 'transparent' : '#10b981')),
1455
1492
  backgroundImage: getElementPattern(el) ? `url('${getElementPattern(el)}')` : (getElementGradientCss(el) || 'none'),
1456
- backgroundSize: getElementPattern(el) ? 'cover' : undefined,
1457
- backgroundPosition: getElementPattern(el) ? 'center center' : undefined,
1458
- backgroundRepeat: getElementPattern(el) ? 'no-repeat' : undefined,
1493
+ backgroundSize: getElementPattern(el) ? (isElementPatternTile(el) ? `${getElementPatternTileSize(el).w}px ${getElementPatternTileSize(el).h}px` : 'cover') : undefined,
1494
+ backgroundPosition: getElementPattern(el) ? (isElementPatternTile(el) ? '0 0' : 'center center') : undefined,
1495
+ backgroundRepeat: getElementPattern(el) ? (isElementPatternTile(el) ? 'repeat' : 'no-repeat') : undefined,
1459
1496
  borderRadius: el.style?.borderRadius !== undefined ? el.style.borderRadius : '0px',
1460
1497
  borderWidth: `${getElementBorderWidth(el)}px`,
1461
1498
  borderStyle: el.style?.borderStyle || (el as any).borderType || 'solid',
@@ -1765,9 +1802,9 @@ function getSafeShapeText(el: any): string {
1765
1802
  height: '100%',
1766
1803
  backgroundColor: getElementPattern(el) ? 'transparent' : ((getElementGradientCss(el) || (getElementFill(el) !== undefined && getElementFill(el) !== 'none')) ? (getElementGradientCss(el) ? 'transparent' : getElementFill(el)) : (getElementFill(el) === 'none' ? 'transparent' : '#3b82f6')),
1767
1804
  backgroundImage: getElementPattern(el) ? `url('${getElementPattern(el)}')` : (getElementGradientCss(el) || 'none'),
1768
- backgroundSize: getElementPattern(el) ? 'cover' : undefined,
1769
- backgroundPosition: getElementPattern(el) ? 'center center' : undefined,
1770
- backgroundRepeat: getElementPattern(el) ? 'no-repeat' : undefined,
1805
+ backgroundSize: getElementPattern(el) ? (isElementPatternTile(el) ? `${getElementPatternTileSize(el).w}px ${getElementPatternTileSize(el).h}px` : 'cover') : undefined,
1806
+ backgroundPosition: getElementPattern(el) ? (isElementPatternTile(el) ? '0 0' : 'center center') : undefined,
1807
+ backgroundRepeat: getElementPattern(el) ? (isElementPatternTile(el) ? 'repeat' : 'no-repeat') : undefined,
1771
1808
  borderRadius: '50%',
1772
1809
  borderWidth: `${getElementBorderWidth(el)}px`,
1773
1810
  borderStyle: el.style?.borderStyle || (el as any).borderType || 'solid',
@@ -1781,9 +1818,16 @@ function getSafeShapeText(el: any): string {
1781
1818
  style="width: 100%; height: 100%; display: block; overflow: visible;"
1782
1819
  :style="{ filter: (el.shadow && el.shadow.type === 'inner') ? `url(#pres-shape-inner-shadow-${el.id})` : '' }">
1783
1820
  <defs>
1784
- <pattern v-if="getElementPattern(el)" :id="`pres-shape-pattern-${el.id}`" width="100%" height="100%"
1785
- patternContentUnits="objectBoundingBox">
1786
- <image :href="getElementPattern(el)" width="1" height="1" preserveAspectRatio="none" />
1821
+ <pattern v-if="getElementPattern(el)" :id="`pres-shape-pattern-${el.id}`"
1822
+ :width="isElementPatternTile(el) ? getElementPatternTileSize(el).w : '100%'"
1823
+ :height="isElementPatternTile(el) ? getElementPatternTileSize(el).h : '100%'"
1824
+ :patternUnits="isElementPatternTile(el) ? 'userSpaceOnUse' : 'objectBoundingBox'"
1825
+ :patternContentUnits="isElementPatternTile(el) ? 'userSpaceOnUse' : 'objectBoundingBox'"
1826
+ :patternTransform="getShapePatternTransform(el, true)">
1827
+ <image :href="getElementPattern(el)"
1828
+ :width="isElementPatternTile(el) ? getElementPatternTileSize(el).w : 1"
1829
+ :height="isElementPatternTile(el) ? getElementPatternTileSize(el).h : 1"
1830
+ preserveAspectRatio="none" />
1787
1831
  </pattern>
1788
1832
  <template v-if="getElementGradientConfig(el)">
1789
1833
  <radialGradient
@@ -1838,9 +1882,16 @@ function getSafeShapeText(el: any): string {
1838
1882
  <svg overflow="visible" style="width: 100%; height: 100%; display: block; overflow: visible;"
1839
1883
  :style="{ filter: (el.shadow && el.shadow.type === 'inner') ? `url(#pres-shape-inner-shadow-${el.id})` : '' }">
1840
1884
  <defs>
1841
- <pattern v-if="getElementPattern(el)" :id="`pres-shape-pattern-${el.id}`" width="100%" height="100%"
1842
- patternContentUnits="objectBoundingBox">
1843
- <image :href="getElementPattern(el)" width="1" height="1" preserveAspectRatio="none" />
1885
+ <pattern v-if="getElementPattern(el)" :id="`pres-shape-pattern-${el.id}`"
1886
+ :width="isElementPatternTile(el) ? getElementPatternTileSize(el).w : '100%'"
1887
+ :height="isElementPatternTile(el) ? getElementPatternTileSize(el).h : '100%'"
1888
+ :patternUnits="isElementPatternTile(el) ? 'userSpaceOnUse' : 'objectBoundingBox'"
1889
+ :patternContentUnits="isElementPatternTile(el) ? 'userSpaceOnUse' : 'objectBoundingBox'"
1890
+ :patternTransform="getShapePatternTransform(el, false)">
1891
+ <image :href="getElementPattern(el)"
1892
+ :width="isElementPatternTile(el) ? getElementPatternTileSize(el).w : 1"
1893
+ :height="isElementPatternTile(el) ? getElementPatternTileSize(el).h : 1"
1894
+ preserveAspectRatio="none" />
1844
1895
  </pattern>
1845
1896
  <template v-if="getElementGradientConfig(el)">
1846
1897
  <radialGradient
@@ -1897,9 +1948,9 @@ function getSafeShapeText(el: any): string {
1897
1948
  height: '100%',
1898
1949
  backgroundColor: getElementPattern(el) ? 'transparent' : ((getElementGradientCss(el) || getElementFill(el) !== undefined) ? (getElementGradientCss(el) ? 'transparent' : getElementFill(el)) : (getElementFill(el) === 'none' ? 'transparent' : '#10b981')),
1899
1950
  backgroundImage: getElementPattern(el) ? `url('${getElementPattern(el)}')` : (getElementGradientCss(el) || 'none'),
1900
- backgroundSize: getElementPattern(el) ? 'cover' : undefined,
1901
- backgroundPosition: getElementPattern(el) ? 'center center' : undefined,
1902
- backgroundRepeat: getElementPattern(el) ? 'no-repeat' : undefined,
1951
+ backgroundSize: getElementPattern(el) ? (isElementPatternTile(el) ? `${getElementPatternTileSize(el).w}px ${getElementPatternTileSize(el).h}px` : 'cover') : undefined,
1952
+ backgroundPosition: getElementPattern(el) ? (isElementPatternTile(el) ? '0 0' : 'center center') : undefined,
1953
+ backgroundRepeat: getElementPattern(el) ? (isElementPatternTile(el) ? 'repeat' : 'no-repeat') : undefined,
1903
1954
  borderRadius: '4px',
1904
1955
  borderWidth: `${getElementBorderWidth(el)}px`,
1905
1956
  borderStyle: el.style?.borderStyle || (el as any).borderType || 'solid',
@@ -5,15 +5,18 @@ import { useSlides } from '../composables/useSlides'
5
5
  interface Props {
6
6
  visible: boolean
7
7
  color: string
8
+ alpha?: number
8
9
  borderStyle: string
9
10
  borderWidth: number
10
11
  recentColors?: string[]
11
12
  hideHeaderSettings?: boolean
13
+ offset?: number
12
14
  }
13
15
 
14
16
  const props = withDefaults(defineProps<Props>(), {
15
17
  recentColors: () => [],
16
- hideHeaderSettings: false
18
+ hideHeaderSettings: false,
19
+ offset: 4
17
20
  })
18
21
 
19
22
  const emit = defineEmits<{
@@ -150,17 +153,38 @@ async function triggerQuickEyeDropper() {
150
153
  const customColorBtnRef = ref()
151
154
  const customColorPickerRef = ref()
152
155
 
156
+ function getCurrentColor(): string {
157
+ const col = props.color || '#000000'
158
+ if (!col || col === 'transparent' || col === 'none') {
159
+ return 'rgba(0, 0, 0, 0)'
160
+ }
161
+ if (props.alpha !== undefined && props.alpha >= 0 && props.alpha <= 100) {
162
+ const cleanHex = col.trim().replace('#', '')
163
+ if (cleanHex.length === 6) {
164
+ const r = parseInt(cleanHex.substring(0, 2), 16) || 0
165
+ const g = parseInt(cleanHex.substring(2, 4), 16) || 0
166
+ const b = parseInt(cleanHex.substring(4, 6), 16) || 0
167
+ return `rgba(${r}, ${g}, ${b}, ${props.alpha / 100})`
168
+ }
169
+ }
170
+ return col
171
+ }
172
+
153
173
  function openCustomColor() {
154
174
  customColorBtnRef.value = document.querySelector('.custom-color-trigger-btn')
175
+ const curColor = getCurrentColor()
155
176
  nextTick(() => {
156
177
  if (customColorPickerRef.value) {
178
+ const pickerInstance = customColorPickerRef.value.$el || customColorPickerRef.value
179
+ if (typeof customColorPickerRef.value.initPickerColor === 'function') {
180
+ customColorPickerRef.value.initPickerColor(curColor)
181
+ } else if (pickerInstance && typeof pickerInstance.initPickerColor === 'function') {
182
+ pickerInstance.initPickerColor(curColor)
183
+ }
157
184
  if (typeof customColorPickerRef.value.openColorPicker === 'function') {
158
- customColorPickerRef.value.openColorPicker()
159
- } else {
160
- const pickerInstance = customColorPickerRef.value.$el || customColorPickerRef.value
161
- if (pickerInstance && typeof pickerInstance.openColorPicker === 'function') {
162
- pickerInstance.openColorPicker()
163
- }
185
+ customColorPickerRef.value.openColorPicker(curColor)
186
+ } else if (pickerInstance && typeof pickerInstance.openColorPicker === 'function') {
187
+ pickerInstance.openColorPicker(curColor)
164
188
  }
165
189
  }
166
190
  })
@@ -185,7 +209,7 @@ defineExpose({
185
209
  </script>
186
210
 
187
211
  <template>
188
- <el-popover v-model:visible="popoverVisible" placement="bottom" :width="260" trigger="click"
212
+ <el-popover v-model:visible="popoverVisible" placement="bottom" :offset="props.offset" :width="260" trigger="click"
189
213
  popper-class="quick-color-popover" :show-arrow="false">
190
214
  <template #reference>
191
215
  <slot name="reference"></slot>
@@ -284,12 +308,13 @@ defineExpose({
284
308
 
285
309
  <div style="padding: 0px 16px 6px;">
286
310
  <!-- Custom Colors -->
287
- <jvs-picker-color-v3 ref="customColorPickerRef" :color="props.color" :options="{
311
+ <jvs-picker-color-v3 ref="customColorPickerRef" :color="getCurrentColor()" :options="{
288
312
  openGradual: false,
289
313
  pickerButtonRef: customColorBtnRef,
290
314
  showFooterBtn: false,
291
- popoverWidth: 260,
292
- selectorWidth: 260,
315
+ popoverWidth: 290,
316
+ selectorWidth: 290,
317
+ popoverPadding: '12px 16px',
293
318
  showHistory: false,
294
319
  showCommonColor: false
295
320
  }" @change="(val: any) => selectCustomColor(val.hex || val)" @colorShow="emit('color-picker-show')"
@@ -342,6 +367,21 @@ defineExpose({
342
367
  border-radius: 8px !important;
343
368
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08) !important;
344
369
  border: 1px solid #E2E8F0 !important;
370
+ background: #ffffff !important;
371
+ z-index: 3000 !important;
372
+ }
373
+
374
+ :global(.color-picker-popover-box) {
375
+ z-index: 3100 !important;
376
+ }
377
+
378
+ :global(.color-picker-popover-box .rgb-color-input) {
379
+ padding: 0 6px !important;
380
+ }
381
+
382
+ :global(.color-picker-popover-box .rgb-color-input .el-input__inner) {
383
+ font-size: 12px !important;
384
+ padding: 0 2px !important;
345
385
  }
346
386
 
347
387
  .quick-color-square {
@@ -1,22 +1,25 @@
1
1
  <script setup lang="ts">
2
- import { ref, computed, nextTick, watch, onMounted, onUnmounted } from 'vue'
2
+ import { ref, computed, nextTick, watch, onMounted, onUnmounted, getCurrentInstance } from 'vue'
3
3
  import { useSlides } from '../composables/useSlides'
4
4
 
5
5
  interface Props {
6
6
  visible?: boolean
7
7
  color?: string
8
+ alpha?: number
8
9
  textBackground?: string
9
10
  showTabs?: boolean
10
11
  recentColors?: string[]
11
12
  themeColors?: string[]
12
13
  placement?: string
14
+ offset?: number
13
15
  }
14
16
 
15
17
  const props = withDefaults(defineProps<Props>(), {
16
18
  textBackground: 'transparent',
17
19
  showTabs: false,
18
20
  recentColors: () => [],
19
- placement: 'bottom'
21
+ placement: 'bottom',
22
+ offset: 4
20
23
  })
21
24
 
22
25
  const emit = defineEmits<{
@@ -69,14 +72,21 @@ onUnmounted(() => {
69
72
  document.body.removeEventListener('pointerup', handleBodyBubble)
70
73
  })
71
74
 
75
+ const internalVisible = ref(false)
76
+ const instance = getCurrentInstance()
77
+ const isControlled = computed(() => {
78
+ return !!(instance?.vnode.props && ('visible' in instance.vnode.props || 'onUpdate:visible' in instance.vnode.props))
79
+ })
80
+
72
81
  const popoverVisible = computed({
73
82
  get() {
74
- return props.visible
83
+ return isControlled.value ? !!props.visible : internalVisible.value
75
84
  },
76
85
  set(val) {
77
86
  if (!val && isCustomColorPickerShow.value) {
78
87
  return
79
88
  }
89
+ internalVisible.value = val
80
90
  emit('update:visible', val)
81
91
  }
82
92
  })
@@ -97,7 +107,7 @@ function addColorToRecent(color: string) {
97
107
  emit('update:recentColors', list)
98
108
  }
99
109
 
100
- watch(() => props.visible, (newVal) => {
110
+ watch(popoverVisible, (newVal) => {
101
111
  if (newVal) {
102
112
  if (props.showTabs) {
103
113
  activeQuickColorTab.value = 'color'
@@ -129,12 +139,26 @@ function getQuickColorActive(color: string): boolean {
129
139
  }
130
140
  }
131
141
 
132
- function getCurrentColorHex(): string {
142
+ function getCurrentColor(): string {
143
+ let col = '#000000'
133
144
  if (props.showTabs && activeQuickColorTab.value === 'background') {
134
- return props.textBackground || '#FFFFFF'
145
+ col = props.textBackground || '#FFFFFF'
135
146
  } else {
136
- return props.color || '#000000'
147
+ col = props.color || '#000000'
148
+ }
149
+ if (!col || col === 'transparent' || col === 'none') {
150
+ return 'rgba(0, 0, 0, 0)'
151
+ }
152
+ if (props.alpha !== undefined && props.alpha >= 0 && props.alpha <= 100) {
153
+ const cleanHex = col.trim().replace('#', '')
154
+ if (cleanHex.length === 6) {
155
+ const r = parseInt(cleanHex.substring(0, 2), 16) || 0
156
+ const g = parseInt(cleanHex.substring(2, 4), 16) || 0
157
+ const b = parseInt(cleanHex.substring(4, 6), 16) || 0
158
+ return `rgba(${r}, ${g}, ${b}, ${props.alpha / 100})`
159
+ }
137
160
  }
161
+ return col
138
162
  }
139
163
 
140
164
  function selectQuickColor(color: string) {
@@ -203,15 +227,19 @@ const customColorPickerRef = ref()
203
227
 
204
228
  function openCustomColor() {
205
229
  customColorBtnRef.value = document.querySelector('.custom-color-trigger-btn')
230
+ const curColor = getCurrentColor()
206
231
  nextTick(() => {
207
232
  if (customColorPickerRef.value) {
233
+ const pickerInstance = customColorPickerRef.value.$el || customColorPickerRef.value
234
+ if (typeof customColorPickerRef.value.initPickerColor === 'function') {
235
+ customColorPickerRef.value.initPickerColor(curColor)
236
+ } else if (pickerInstance && typeof pickerInstance.initPickerColor === 'function') {
237
+ pickerInstance.initPickerColor(curColor)
238
+ }
208
239
  if (typeof customColorPickerRef.value.openColorPicker === 'function') {
209
- customColorPickerRef.value.openColorPicker()
210
- } else {
211
- const pickerInstance = customColorPickerRef.value.$el || customColorPickerRef.value
212
- if (pickerInstance && typeof pickerInstance.openColorPicker === 'function') {
213
- pickerInstance.openColorPicker()
214
- }
240
+ customColorPickerRef.value.openColorPicker(curColor)
241
+ } else if (pickerInstance && typeof pickerInstance.openColorPicker === 'function') {
242
+ pickerInstance.openColorPicker(curColor)
215
243
  }
216
244
  }
217
245
  })
@@ -236,7 +264,7 @@ defineExpose({
236
264
  </script>
237
265
 
238
266
  <template>
239
- <el-popover v-model:visible="popoverVisible" :placement="props.placement" :width="260" trigger="click"
267
+ <el-popover v-model:visible="popoverVisible" :placement="props.placement" :offset="props.offset" :width="260" trigger="click"
240
268
  popper-class="quick-color-popover" :show-arrow="false">
241
269
  <template #reference>
242
270
  <span ref="referenceWrapperRef" style="display: inline-block; vertical-align: middle;" class="color-span-box">
@@ -270,9 +298,8 @@ defineExpose({
270
298
  }" :class="{
271
299
  'is-active': getQuickColorActive(tCol)
272
300
  }" @click="selectQuickColor(tCol)" :title="`主题颜色 ${tIdx + 1}: ${tCol}`">
273
- <svg v-if="getQuickColorActive(tCol)" viewBox="0 0 24 24" width="10"
274
- height="10" fill="none" stroke="currentColor" stroke-width="3.5"
275
- style="color: #ffffff; z-index: 2;">
301
+ <svg v-if="getQuickColorActive(tCol)" viewBox="0 0 24 24" width="10" height="10" fill="none"
302
+ stroke="currentColor" stroke-width="3.5" style="color: #ffffff; z-index: 2;">
276
303
  <polyline points="20 6 9 17 4 12" />
277
304
  </svg>
278
305
  </div>
@@ -324,15 +351,15 @@ defineExpose({
324
351
  </div>
325
352
 
326
353
  <div class="quick-color-popover-divider"></div>
327
-
328
354
  <div style="padding: 0px 16px 6px;">
329
355
  <!-- Custom Colors -->
330
- <jvs-picker-color-v3 ref="customColorPickerRef" :color="getCurrentColorHex()" :options="{
356
+ <jvs-picker-color-v3 ref="customColorPickerRef" :color="getCurrentColor()" :options="{
331
357
  openGradual: false,
332
358
  pickerButtonRef: customColorBtnRef,
333
359
  showFooterBtn: false,
334
- popoverWidth: 260,
335
- selectorWidth: 260,
360
+ popoverWidth: 290,
361
+ selectorWidth: 290,
362
+ popoverPadding: '12px 16px',
336
363
  showHistory: false,
337
364
  showCommonColor: false
338
365
  }" @change="(val: any) => selectCustomColor(val.hex || val)"
@@ -386,6 +413,21 @@ defineExpose({
386
413
  border-radius: 8px !important;
387
414
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08) !important;
388
415
  border: 1px solid #E2E8F0 !important;
416
+ background: #ffffff !important;
417
+ z-index: 3000 !important;
418
+ }
419
+
420
+ :global(.color-picker-popover-box) {
421
+ z-index: 3100 !important;
422
+ }
423
+
424
+ :global(.color-picker-popover-box .rgb-color-input) {
425
+ padding: 0 6px !important;
426
+ }
427
+
428
+ :global(.color-picker-popover-box .rgb-color-input .el-input__inner) {
429
+ font-size: 12px !important;
430
+ padding: 0 2px !important;
389
431
  }
390
432
 
391
433
  .quick-color-square {
@@ -445,6 +487,8 @@ defineExpose({
445
487
  .quick-color-popover-container {
446
488
  display: flex;
447
489
  flex-direction: column;
490
+ background: #ffffff;
491
+ border-radius: 8px;
448
492
  }
449
493
 
450
494
  .quick-color-tabs-header {