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
@@ -1,203 +1,429 @@
1
- <script setup lang="ts">
2
- const props = withDefaults(defineProps<{
3
- enableReflection?: boolean
4
- isReflectionExpanded?: boolean
5
- reflectionDistance?: number
6
- reflectionSize?: number
7
- reflectionOpacity?: number
8
- reflectionBlur?: number
9
- }>(), {
10
- enableReflection: false,
11
- isReflectionExpanded: false,
12
- reflectionDistance: 0,
13
- reflectionSize: 100,
14
- reflectionOpacity: 30,
15
- reflectionBlur: 0
16
- })
17
-
18
- const emit = defineEmits<{
19
- (e: 'update:enableReflection', val: boolean): void
20
- (e: 'update:isReflectionExpanded', val: boolean): void
21
- (e: 'update:reflectionDistance', val: number): void
22
- (e: 'update:reflectionSize', val: number): void
23
- (e: 'update:reflectionOpacity', val: number): void
24
- (e: 'update:reflectionBlur', val: number): void
25
- }>()
26
-
27
- function toggleHeader() {
28
- if (!props.enableReflection) return
29
- emit('update:isReflectionExpanded', !props.isReflectionExpanded)
30
- }
31
-
32
- function toggleExpand() {
33
- if (!props.enableReflection) return
34
- emit('update:isReflectionExpanded', !props.isReflectionExpanded)
35
- }
36
-
37
- function toggleSwitch(val: any) {
38
- const boolVal = !!val
39
- emit('update:enableReflection', boolVal)
40
- emit('update:isReflectionExpanded', boolVal)
41
- }
42
- </script>
43
-
44
- <template>
45
- <div class="control-group shape-accordion-group">
46
- <div class="shape-accordion-header" @click="toggleHeader">
47
- <span class="control-label shape-accordion-header-label">
48
- <span class="accordion-arrow" @click.stop="toggleExpand"
49
- :style="{ transform: (enableReflection && isReflectionExpanded) ? 'rotate(90deg)' : 'rotate(0deg)' }">▶</span>倒影
50
- </span>
51
- <el-switch :model-value="enableReflection" size="small" @click.stop @change="toggleSwitch" />
52
- </div>
53
-
54
- <div v-show="isReflectionExpanded && enableReflection" class="shape-accordion-content">
55
- <!-- Distance Slider -->
56
- <div class="shape-property-row">
57
- <span class="shape-property-label">距离</span>
58
- <div class="shape-slider-wrapper">
59
- <el-slider :model-value="reflectionDistance || 0"
60
- @update:model-value="emit('update:reflectionDistance', $event as number)" :min="0" :max="100" :step="0.1"
61
- size="small" style="flex: 1;" class="custom-slider" :show-tooltip="false" show-input
62
- :show-input-controls="false" />
63
- </div>
64
- </div>
65
-
66
- <!-- Size Slider -->
67
- <div class="shape-property-row">
68
- <span class="shape-property-label">大小</span>
69
- <div class="shape-slider-wrapper">
70
- <el-slider :model-value="reflectionSize || 0"
71
- @update:model-value="emit('update:reflectionSize', $event as number)" :min="0" :max="100" :step="0.1"
72
- size="small" style="flex: 1;" class="custom-slider" :show-tooltip="false" show-input
73
- :show-input-controls="false" />
74
- </div>
75
- </div>
76
-
77
- <!-- Opacity Slider -->
78
- <div class="shape-property-row">
79
- <span class="shape-property-label">透明度</span>
80
- <div class="shape-slider-wrapper">
81
- <el-slider :model-value="reflectionOpacity || 0"
82
- @update:model-value="emit('update:reflectionOpacity', $event as number)" :min="0" :max="100" :step="1"
83
- size="small" style="flex: 1;" class="custom-slider" :show-tooltip="false" show-input
84
- :show-input-controls="false" />
85
- </div>
86
- </div>
87
-
88
- <!-- Blur Slider -->
89
- <div class="shape-property-row">
90
- <span class="shape-property-label">模糊</span>
91
- <div class="shape-slider-wrapper">
92
- <el-slider :model-value="reflectionBlur || 0"
93
- @update:model-value="emit('update:reflectionBlur', $event as number)" :min="0" :max="100" :step="0.1"
94
- size="small" style="flex: 1;" class="custom-slider" :show-tooltip="false" show-input
95
- :show-input-controls="false" />
96
- </div>
97
- </div>
98
- </div>
99
- </div>
100
- </template>
101
-
102
- <style scoped lang="scss">
103
- .shape-accordion-group {
104
- border-bottom: 1px solid #EEEFF0;
105
- padding-bottom: 12px;
106
- margin-bottom: 8px;
107
- }
108
-
109
- .shape-accordion-header {
110
- display: flex;
111
- align-items: center;
112
- padding: 0 16px;
113
- height: 32px;
114
- cursor: pointer;
115
- }
116
-
117
- .shape-accordion-header-label {
118
- font-size: 13px;
119
- font-weight: 600;
120
- color: var(--text-primary);
121
- display: flex;
122
- align-items: center;
123
- gap: 6px;
124
- width: 80px;
125
- flex-shrink: 0;
126
- text-align: left;
127
- }
128
-
129
- .accordion-arrow {
130
- font-size: 9px;
131
- transition: transform 0.2s;
132
- display: inline-block;
133
- color: #475569;
134
- }
135
-
136
- .shape-accordion-content {
137
- padding: 12px 16px 0 16px;
138
- display: flex;
139
- flex-direction: column;
140
- gap: 12px;
141
- }
142
-
143
- .shape-property-row {
144
- display: flex;
145
- align-items: center;
146
- justify-content: space-between;
147
- height: 32px;
148
- padding: 0;
149
- gap: 8px;
150
- }
151
-
152
- .shape-property-label {
153
- font-size: 12px;
154
- color: var(--text-secondary, #64748b);
155
- width: 80px;
156
- flex-shrink: 0;
157
- text-align: left;
158
- }
159
-
160
- .shape-slider-wrapper {
161
- display: flex;
162
- align-items: center;
163
- gap: 10px;
164
- flex: 1;
165
- }
166
-
167
- .custom-slider {
168
- --el-slider-height: 4px !important;
169
- --el-slider-button-size: 16px !important;
170
- --el-slider-button-wrapper-offset: -16px !important;
171
-
172
- :deep(.show-input) {
173
- margin-right: 16px;
174
- }
175
-
176
- :deep(.el-input-number) {
177
- width: 48px;
178
- height: 30px;
179
-
180
- .el-input__wrapper {
181
- padding: 4px;
182
- background: #F5F6F7;
183
- border: none;
184
- border-radius: 4px;
185
- box-shadow: none;
186
- }
187
-
188
- .el-input__inner {
189
- text-align: center;
190
- font-size: 12px;
191
- color: var(--text-primary);
192
- }
193
- }
194
- }
195
-
196
- :deep(.el-switch__core) {
197
- border-radius: 4px !important;
198
- }
199
-
200
- :deep(.el-switch__action) {
201
- border-radius: 3px !important;
202
- }
203
- </style>
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+
4
+ const props = withDefaults(defineProps<{
5
+ enableReflection?: boolean
6
+ isReflectionExpanded?: boolean
7
+ reflectionDistance?: number
8
+ reflectionSize?: number
9
+ reflectionOpacity?: number
10
+ reflectionBlur?: number
11
+ }>(), {
12
+ enableReflection: false,
13
+ isReflectionExpanded: false,
14
+ reflectionDistance: 0,
15
+ reflectionSize: 100,
16
+ reflectionOpacity: 30,
17
+ reflectionBlur: 0
18
+ })
19
+
20
+ const emit = defineEmits<{
21
+ (e: 'update:enableReflection', val: boolean): void
22
+ (e: 'update:isReflectionExpanded', val: boolean): void
23
+ (e: 'update:reflectionDistance', val: number): void
24
+ (e: 'update:reflectionSize', val: number): void
25
+ (e: 'update:reflectionOpacity', val: number): void
26
+ (e: 'update:reflectionBlur', val: number): void
27
+ }>()
28
+
29
+ function toggleHeader() {
30
+ if (!props.enableReflection) return
31
+ emit('update:isReflectionExpanded', !props.isReflectionExpanded)
32
+ }
33
+
34
+ function toggleSwitch(val: any) {
35
+ const boolVal = !!val
36
+ emit('update:enableReflection', boolVal)
37
+ emit('update:isReflectionExpanded', boolVal)
38
+ }
39
+
40
+ // Distance input
41
+ const distanceInputRef = ref<HTMLInputElement | null>(null)
42
+ function focusDistanceInput(e: MouseEvent) {
43
+ if (e.target !== distanceInputRef.value) {
44
+ distanceInputRef.value?.focus()
45
+ distanceInputRef.value?.select()
46
+ }
47
+ }
48
+ function onDistanceInput(e: Event) {
49
+ const target = e.target as HTMLInputElement
50
+ if (target.value === '') return
51
+ const val = Number(target.value)
52
+ if (isNaN(val)) return
53
+ emit('update:reflectionDistance', Math.max(0, Math.min(100, val)))
54
+ }
55
+ function onDistanceBlur(e: Event) {
56
+ const target = e.target as HTMLInputElement
57
+ if (target.value === '' || isNaN(Number(target.value))) {
58
+ target.value = String(props.reflectionDistance || 0)
59
+ } else {
60
+ const val = Math.max(0, Math.min(100, Number(target.value)))
61
+ target.value = String(val)
62
+ emit('update:reflectionDistance', val)
63
+ }
64
+ }
65
+
66
+ // Size input
67
+ const sizeInputRef = ref<HTMLInputElement | null>(null)
68
+ function focusSizeInput(e: MouseEvent) {
69
+ if (e.target !== sizeInputRef.value) {
70
+ sizeInputRef.value?.focus()
71
+ sizeInputRef.value?.select()
72
+ }
73
+ }
74
+ function onSizeInput(e: Event) {
75
+ const target = e.target as HTMLInputElement
76
+ if (target.value === '') return
77
+ const val = Number(target.value)
78
+ if (isNaN(val)) return
79
+ emit('update:reflectionSize', Math.max(0, Math.min(100, val)))
80
+ }
81
+ function onSizeBlur(e: Event) {
82
+ const target = e.target as HTMLInputElement
83
+ if (target.value === '' || isNaN(Number(target.value))) {
84
+ target.value = String(props.reflectionSize || 0)
85
+ } else {
86
+ const val = Math.max(0, Math.min(100, Number(target.value)))
87
+ target.value = String(val)
88
+ emit('update:reflectionSize', val)
89
+ }
90
+ }
91
+
92
+ // Blur input
93
+ const blurInputRef = ref<HTMLInputElement | null>(null)
94
+ function focusBlurInput(e: MouseEvent) {
95
+ if (e.target !== blurInputRef.value) {
96
+ blurInputRef.value?.focus()
97
+ blurInputRef.value?.select()
98
+ }
99
+ }
100
+ function onBlurInput(e: Event) {
101
+ const target = e.target as HTMLInputElement
102
+ if (target.value === '') return
103
+ const val = Number(target.value)
104
+ if (isNaN(val)) return
105
+ emit('update:reflectionBlur', Math.max(0, Math.min(100, val)))
106
+ }
107
+ function onBlurBlur(e: Event) {
108
+ const target = e.target as HTMLInputElement
109
+ if (target.value === '' || isNaN(Number(target.value))) {
110
+ target.value = String(props.reflectionBlur || 0)
111
+ } else {
112
+ const val = Math.max(0, Math.min(100, Number(target.value)))
113
+ target.value = String(val)
114
+ emit('update:reflectionBlur', val)
115
+ }
116
+ }
117
+
118
+ // Opacity input
119
+ const opacityInputRef = ref<HTMLInputElement | null>(null)
120
+ function focusOpacityInput(e: MouseEvent) {
121
+ if (e.target !== opacityInputRef.value) {
122
+ opacityInputRef.value?.focus()
123
+ opacityInputRef.value?.select()
124
+ }
125
+ }
126
+ function onOpacityInput(e: Event) {
127
+ const target = e.target as HTMLInputElement
128
+ if (target.value === '') return
129
+ const val = Number(target.value)
130
+ if (isNaN(val)) return
131
+ emit('update:reflectionOpacity', Math.max(0, Math.min(100, val)))
132
+ }
133
+ function onOpacityBlur(e: Event) {
134
+ const target = e.target as HTMLInputElement
135
+ if (target.value === '' || isNaN(Number(target.value))) {
136
+ target.value = String(props.reflectionOpacity || 0)
137
+ } else {
138
+ const val = Math.max(0, Math.min(100, Number(target.value)))
139
+ target.value = String(val)
140
+ emit('update:reflectionOpacity', val)
141
+ }
142
+ }
143
+ </script>
144
+
145
+ <template>
146
+ <div class="control-group shape-accordion-group">
147
+ <!-- Header -->
148
+ <div class="shape-accordion-header" @click="toggleHeader">
149
+ <span class="control-label shape-accordion-header-label">
150
+ <span>倒影</span>
151
+ <span class="accordion-arrow">
152
+ <svg class="icon" style="width: 14px; height: 14px;">
153
+ <use :href="(enableReflection && isReflectionExpanded) ? '#icon-xiala-zhankai' : '#icon-xiala-shouqi'"
154
+ :xlink:href="(enableReflection && isReflectionExpanded) ? '#icon-xiala-zhankai' : '#icon-xiala-shouqi'"></use>
155
+ </svg>
156
+ </span>
157
+ </span>
158
+ <el-switch :model-value="enableReflection" size="small" @click.stop @change="toggleSwitch" />
159
+ </div>
160
+
161
+ <!-- Content (order: 距离, 大小, 模糊度, 透明度 matching Image 2) -->
162
+ <div v-show="isReflectionExpanded && enableReflection" class="shape-accordion-content">
163
+ <!-- 1. 距离 (Distance) -->
164
+ <div class="prop-item">
165
+ <div class="prop-label">距离</div>
166
+ <div class="slider-control-row">
167
+ <el-slider
168
+ :model-value="reflectionDistance || 0"
169
+ @update:model-value="emit('update:reflectionDistance', Math.round(($event as number) * 10) / 10)"
170
+ :min="0"
171
+ :max="100"
172
+ :step="0.5"
173
+ size="small"
174
+ class="custom-slider"
175
+ :show-tooltip="false"
176
+ />
177
+ <div class="slider-num-pill" @click="focusDistanceInput">
178
+ <input
179
+ ref="distanceInputRef"
180
+ type="text"
181
+ inputmode="numeric"
182
+ :value="reflectionDistance || 0"
183
+ @input="onDistanceInput"
184
+ @blur="onDistanceBlur"
185
+ @keydown.enter="($event.target as HTMLElement).blur()"
186
+ class="num-field-center"
187
+ />
188
+ </div>
189
+ </div>
190
+ </div>
191
+
192
+ <!-- 2. 大小 (Size) -->
193
+ <div class="prop-item">
194
+ <div class="prop-label">大小</div>
195
+ <div class="slider-control-row">
196
+ <el-slider
197
+ :model-value="reflectionSize || 0"
198
+ @update:model-value="emit('update:reflectionSize', Math.round(($event as number) * 10) / 10)"
199
+ :min="0"
200
+ :max="100"
201
+ :step="0.5"
202
+ size="small"
203
+ class="custom-slider"
204
+ :show-tooltip="false"
205
+ />
206
+ <div class="slider-num-pill" @click="focusSizeInput">
207
+ <input
208
+ ref="sizeInputRef"
209
+ type="text"
210
+ inputmode="numeric"
211
+ :value="reflectionSize || 0"
212
+ @input="onSizeInput"
213
+ @blur="onSizeBlur"
214
+ @keydown.enter="($event.target as HTMLElement).blur()"
215
+ class="num-field-center"
216
+ />
217
+ </div>
218
+ </div>
219
+ </div>
220
+
221
+ <!-- 3. 模糊度 (Blur) -->
222
+ <div class="prop-item">
223
+ <div class="prop-label">模糊度</div>
224
+ <div class="slider-control-row">
225
+ <el-slider
226
+ :model-value="reflectionBlur || 0"
227
+ @update:model-value="emit('update:reflectionBlur', Math.round(($event as number) * 10) / 10)"
228
+ :min="0"
229
+ :max="100"
230
+ :step="0.5"
231
+ size="small"
232
+ class="custom-slider"
233
+ :show-tooltip="false"
234
+ />
235
+ <div class="slider-num-pill" @click="focusBlurInput">
236
+ <input
237
+ ref="blurInputRef"
238
+ type="text"
239
+ inputmode="numeric"
240
+ :value="reflectionBlur || 0"
241
+ @input="onBlurInput"
242
+ @blur="onBlurBlur"
243
+ @keydown.enter="($event.target as HTMLElement).blur()"
244
+ class="num-field-center"
245
+ />
246
+ </div>
247
+ </div>
248
+ </div>
249
+
250
+ <!-- 4. 透明度 (Opacity) -->
251
+ <div class="prop-item">
252
+ <div class="prop-label">透明度</div>
253
+ <div class="slider-control-row">
254
+ <el-slider
255
+ :model-value="reflectionOpacity || 0"
256
+ @update:model-value="emit('update:reflectionOpacity', Math.round(($event as number) * 10) / 10)"
257
+ :min="0"
258
+ :max="100"
259
+ :step="1"
260
+ size="small"
261
+ class="custom-slider"
262
+ :show-tooltip="false"
263
+ />
264
+ <div class="slider-num-pill" @click="focusOpacityInput">
265
+ <input
266
+ ref="opacityInputRef"
267
+ type="text"
268
+ inputmode="numeric"
269
+ :value="reflectionOpacity || 0"
270
+ @input="onOpacityInput"
271
+ @blur="onOpacityBlur"
272
+ @keydown.enter="($event.target as HTMLElement).blur()"
273
+ class="num-field-center"
274
+ />
275
+ </div>
276
+ </div>
277
+ </div>
278
+ </div>
279
+ </div>
280
+ </template>
281
+
282
+ <style scoped lang="scss">
283
+ .shape-accordion-group {
284
+ border-bottom: 1px solid #f1f5f9;
285
+ padding-bottom: 12px;
286
+ margin-bottom: 12px;
287
+ }
288
+
289
+ .shape-accordion-header {
290
+ display: flex;
291
+ align-items: center;
292
+ justify-content: space-between;
293
+ padding: 0 16px;
294
+ height: 34px;
295
+ cursor: pointer;
296
+ user-select: none;
297
+ }
298
+
299
+ .shape-accordion-header-label {
300
+ font-size: 14px;
301
+ font-weight: 400;
302
+ color: #1e293b;
303
+ display: flex;
304
+ align-items: center;
305
+ gap: 6px;
306
+ flex-shrink: 0;
307
+ }
308
+
309
+ .accordion-arrow {
310
+ display: flex;
311
+ align-items: center;
312
+ justify-content: center;
313
+ color: #64748b;
314
+ }
315
+
316
+ :deep(.el-switch) {
317
+ --el-switch-on-color: #2563eb;
318
+ --el-switch-off-color: #cbd5e1;
319
+ }
320
+
321
+ .shape-accordion-content {
322
+ padding: 8px 16px 0 16px;
323
+ display: flex;
324
+ flex-direction: column;
325
+ gap: 12px;
326
+ }
327
+
328
+ .prop-item {
329
+ display: flex;
330
+ flex-direction: column;
331
+ gap: 6px;
332
+ width: 100%;
333
+ }
334
+
335
+ .prop-label {
336
+ font-size: 13px;
337
+ font-weight: 500;
338
+ color: #1e293b;
339
+ user-select: none;
340
+ text-align: left;
341
+ }
342
+
343
+ .slider-control-row {
344
+ display: flex;
345
+ align-items: center;
346
+ width: 100%;
347
+ }
348
+
349
+ .custom-slider {
350
+ --el-slider-main-bg-color: #1e293b;
351
+ --el-slider-runway-bg-color: #E5E7EB;
352
+ --el-slider-height: 4px !important;
353
+ --el-slider-button-size: 14px !important;
354
+ --el-slider-button-wrapper-offset: -15px !important;
355
+ flex: 1;
356
+ margin-right: 12px;
357
+
358
+ :deep(.el-slider__runway) {
359
+ background-color: #E5E7EB !important;
360
+ height: 4px !important;
361
+ border-radius: 2px !important;
362
+ }
363
+
364
+ :deep(.el-slider__bar) {
365
+ background-color: #1e293b !important;
366
+ height: 4px !important;
367
+ border-radius: 2px !important;
368
+ }
369
+
370
+ :deep(.el-slider__button) {
371
+ width: 14px !important;
372
+ height: 14px !important;
373
+ border: 1px solid #d1d5db !important;
374
+ background-color: #ffffff !important;
375
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12) !important;
376
+ transition: transform 0.15s ease !important;
377
+
378
+ &:hover {
379
+ transform: scale(1.15);
380
+ }
381
+ }
382
+ }
383
+
384
+ .slider-num-pill {
385
+ width: 52px;
386
+ height: 32px;
387
+ background: #FAFAFA;
388
+ border: 1px solid #edf0f3;
389
+ border-radius: 8px;
390
+ box-sizing: border-box;
391
+ display: flex;
392
+ align-items: center;
393
+ justify-content: center;
394
+ flex-shrink: 0;
395
+ cursor: text;
396
+ transition: all 0.15s ease;
397
+
398
+ &:hover {
399
+ border-color: #cbd5e1;
400
+ }
401
+
402
+ &:focus-within {
403
+ border-color: #2563eb;
404
+ box-shadow: 0 0 0 1px #2563eb;
405
+ }
406
+ }
407
+
408
+ .num-field-center {
409
+ width: 100%;
410
+ border: none;
411
+ background: transparent;
412
+ outline: none;
413
+ font-size: 13px;
414
+ font-weight: 500;
415
+ color: #1e293b;
416
+ text-align: center;
417
+ padding: 0;
418
+ margin: 0;
419
+ font-variant-numeric: tabular-nums;
420
+ box-sizing: border-box;
421
+
422
+ &::-webkit-outer-spin-button,
423
+ &::-webkit-inner-spin-button {
424
+ -webkit-appearance: none;
425
+ display: none !important;
426
+ margin: 0;
427
+ }
428
+ }
429
+ </style>