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.
- package/dist/lib/check_imgs.html +18 -0
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.css +187 -27
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.js +1 -1
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.json +345 -65
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.ttf +0 -0
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.woff +0 -0
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.woff2 +0 -0
- package/dist/lib/jvs-ppt-ui/img/al.png +0 -0
- package/dist/lib/jvs-ppt-ui/img/d.png +0 -0
- package/dist/lib/jvs-ppt-ui/img/dl.png +0 -0
- package/dist/lib/jvs-ppt-ui/img/l.png +0 -0
- package/dist/lib/jvs-ppt-ui.es.js +44973 -43349
- package/dist/lib/jvs-ppt-ui.umd.js +102 -102
- package/dist/lib/style.css +1 -1
- package/package.json +1 -1
- package/scripts/check-icons.mjs +22 -0
- package/scripts/patch-anim-icons.mjs +45 -0
- package/src/assets/iconfont/iconfont.css +187 -27
- package/src/assets/iconfont/iconfont.js +1 -1
- package/src/assets/iconfont/iconfont.json +345 -65
- package/src/assets/iconfont/iconfont.ttf +0 -0
- package/src/assets/iconfont/iconfont.woff +0 -0
- package/src/assets/iconfont/iconfont.woff2 +0 -0
- package/src/components/CanvasArea.vue +218 -193
- package/src/components/ChartTypeSelector.vue +509 -148
- package/src/components/Header.vue +327 -44
- package/src/components/PresentationGroupChild.vue +44 -13
- package/src/components/PresentationMode.vue +84 -33
- package/src/components/QuickBorderPopover.vue +51 -11
- package/src/components/QuickColorPopover.vue +65 -21
- package/src/components/SidebarLeft.vue +286 -107
- package/src/components/SidebarRight.vue +45 -38
- package/src/components/TemplateGallery.vue +1110 -1237
- package/src/components/ToastNotification.vue +2 -2
- package/src/components/Toolbar.vue +825 -733
- package/src/components/canvas/CanvasQuickToolbar.vue +17 -30
- package/src/components/canvas/elements/CanvasGroupElement.vue +6 -0
- package/src/components/canvas/elements/CanvasShapeElement.vue +198 -38
- package/src/components/canvas/elements/CanvasTextElement.vue +4 -3
- package/src/components/sidebar/common/SidebarAlignGroup.vue +104 -50
- package/src/components/sidebar/common/SidebarBorderAccordion.vue +375 -148
- package/src/components/sidebar/common/SidebarPositionGroup.vue +358 -149
- package/src/components/sidebar/common/SidebarReflectionAccordion.vue +429 -203
- package/src/components/sidebar/common/SidebarShadowAccordion.vue +844 -416
- package/src/components/sidebar/panels/GradientEditor.vue +671 -316
- package/src/components/sidebar/panels/LayoutThumbSvg.vue +33 -16
- package/src/components/sidebar/panels/SidebarAnimationPanel.vue +701 -138
- package/src/components/sidebar/panels/SidebarChartFormatPanel.vue +3 -3
- package/src/components/sidebar/panels/SidebarDesignPanel.vue +1754 -416
- package/src/components/sidebar/panels/SidebarMediaFormatPanel.vue +12 -0
- package/src/components/sidebar/panels/SidebarShapeFormatPanel.vue +813 -174
- package/src/components/sidebar/panels/SidebarTableFormatPanel.vue +2 -2
- package/src/components/sidebar/panels/SidebarTextFormatPanel.vue +1938 -1427
- package/src/components/sidebar/panels/SidebarTransitionPanel.vue +791 -210
- package/src/composables/canvas/useCanvasShortcuts.ts +20 -6
- package/src/composables/canvas/useCanvasText.ts +1 -1
- package/src/composables/canvas/useCanvasTransform.ts +44 -0
- package/src/composables/presetThemes.ts +43 -44
- package/src/composables/sidebar/useSidebarAnimation.ts +101 -25
- package/src/composables/sidebar/useSidebarDesign.ts +30 -11
- package/src/composables/sidebar/useSidebarElementTransform.ts +10 -1
- package/src/composables/sidebar/useSidebarImage.ts +10 -2
- package/src/composables/sidebar/useSidebarShapeFormat.ts +562 -107
- package/src/composables/useSlides.ts +331 -153
- package/src/main.ts +2 -0
- package/src/style.css +926 -359
- package/src/utils/canvas/elementStyles.ts +42 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
2
|
+
import { ref, computed } from 'vue'
|
|
3
|
+
import { useSlides } from '../../../composables/useSlides'
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<{
|
|
3
6
|
elementX: number
|
|
4
7
|
elementY: number
|
|
5
8
|
elementW: number
|
|
@@ -32,191 +35,342 @@ const emit = defineEmits<{
|
|
|
32
35
|
(e: 'toggleFlipV'): void
|
|
33
36
|
(e: 'adjustZIndex', command: any): void
|
|
34
37
|
}>()
|
|
38
|
+
|
|
39
|
+
const { activeSlide, selectedElementId, selectedElementIds } = useSlides()
|
|
40
|
+
|
|
41
|
+
const selectedIds = computed(() => {
|
|
42
|
+
if (selectedElementIds.value && selectedElementIds.value.length > 0) {
|
|
43
|
+
return selectedElementIds.value
|
|
44
|
+
}
|
|
45
|
+
if (selectedElementId.value) {
|
|
46
|
+
return [selectedElementId.value]
|
|
47
|
+
}
|
|
48
|
+
return []
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const slideElements = computed(() => activeSlide.value?.elements || [])
|
|
52
|
+
|
|
53
|
+
const selectedIndices = computed(() => {
|
|
54
|
+
const ids = selectedIds.value
|
|
55
|
+
if (!ids.length) return []
|
|
56
|
+
return slideElements.value
|
|
57
|
+
.map((el: any, index: number) => (ids.includes(el.id) ? index : -1))
|
|
58
|
+
.filter((idx: number) => idx !== -1)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const canMoveUp = computed(() => {
|
|
62
|
+
if (selectedIndices.value.length === 0 || slideElements.value.length <= 1) return false
|
|
63
|
+
const total = slideElements.value.length
|
|
64
|
+
const allAtTop = selectedIndices.value.every((idx: number) => idx >= total - selectedIndices.value.length)
|
|
65
|
+
return !allAtTop
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const canMoveDown = computed(() => {
|
|
69
|
+
if (selectedIndices.value.length === 0 || slideElements.value.length <= 1) return false
|
|
70
|
+
const allAtBottom = selectedIndices.value.every((idx: number) => idx < selectedIndices.value.length)
|
|
71
|
+
return !allAtBottom
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const canMoveTop = computed(() => canMoveUp.value)
|
|
75
|
+
const canMoveBottom = computed(() => canMoveDown.value)
|
|
76
|
+
|
|
77
|
+
const rotateInputRef = ref<HTMLInputElement | null>(null)
|
|
78
|
+
const rotateDisplayLen = computed(() => Math.max(1, String(props.elementRotate ?? 0).length))
|
|
79
|
+
|
|
80
|
+
function focusRotateInput(e: MouseEvent) {
|
|
81
|
+
if (e.target !== rotateInputRef.value) {
|
|
82
|
+
rotateInputRef.value?.focus()
|
|
83
|
+
rotateInputRef.value?.select()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function onRotateInput(e: Event) {
|
|
88
|
+
const target = e.target as HTMLInputElement
|
|
89
|
+
const raw = target.value
|
|
90
|
+
if (raw === '' || raw === '-') return
|
|
91
|
+
const val = Number(raw)
|
|
92
|
+
if (isNaN(val)) return
|
|
93
|
+
let deg = Math.round(val) % 360
|
|
94
|
+
if (deg < 0) deg += 360
|
|
95
|
+
emit('update:elementRotate', deg)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function onRotateBlur(e: Event) {
|
|
99
|
+
const target = e.target as HTMLInputElement
|
|
100
|
+
if (target.value === '' || target.value === '-' || isNaN(Number(target.value))) {
|
|
101
|
+
target.value = String(props.elementRotate ?? 0)
|
|
102
|
+
} else {
|
|
103
|
+
let val = Math.round(Number(target.value)) % 360
|
|
104
|
+
if (val < 0) val += 360
|
|
105
|
+
target.value = String(val)
|
|
106
|
+
emit('update:elementRotate', val)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
35
109
|
</script>
|
|
36
110
|
|
|
37
111
|
<template>
|
|
38
|
-
<div class="control-group sidebar-position-group"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
112
|
+
<div class="control-group sidebar-position-group">
|
|
113
|
+
<!-- Row 1: X & Y -->
|
|
114
|
+
<div v-if="!hidePosition" class="pos-row">
|
|
115
|
+
<div class="pos-main-cols">
|
|
116
|
+
<div class="custom-num-input">
|
|
117
|
+
<span class="custom-num-prefix">X</span>
|
|
118
|
+
<input type="number" step="any" :value="elementX"
|
|
119
|
+
@input="emit('update:elementX', Number(($event.target as HTMLInputElement).value))"
|
|
120
|
+
class="custom-num-field" />
|
|
121
|
+
</div>
|
|
122
|
+
<div class="custom-num-input">
|
|
123
|
+
<span class="custom-num-prefix">Y</span>
|
|
124
|
+
<input type="number" step="any" :value="elementY"
|
|
125
|
+
@input="emit('update:elementY', Number(($event.target as HTMLInputElement).value))"
|
|
126
|
+
class="custom-num-field" />
|
|
127
|
+
</div>
|
|
53
128
|
</div>
|
|
129
|
+
<div class="pos-side-placeholder"></div>
|
|
54
130
|
</div>
|
|
55
131
|
|
|
56
|
-
<!-- W & H & Lock aspect ratio -->
|
|
57
|
-
<div v-if="!hideDimensions"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
132
|
+
<!-- Row 2: W & H & Lock aspect ratio -->
|
|
133
|
+
<div v-if="!hideDimensions" class="pos-row">
|
|
134
|
+
<div class="pos-main-cols">
|
|
135
|
+
<div class="custom-num-input">
|
|
136
|
+
<span class="custom-num-prefix">W</span>
|
|
137
|
+
<input type="number" step="any" :value="elementW"
|
|
138
|
+
@input="emit('update:elementW', Number(($event.target as HTMLInputElement).value))"
|
|
139
|
+
class="custom-num-field" />
|
|
140
|
+
</div>
|
|
141
|
+
<div class="custom-num-input" :class="{ 'is-disabled': disableHeight }">
|
|
142
|
+
<span class="custom-num-prefix">H</span>
|
|
143
|
+
<input type="number" step="any" :value="elementH" :disabled="disableHeight" :readonly="disableHeight"
|
|
144
|
+
@input="!disableHeight && emit('update:elementH', Number(($event.target as HTMLInputElement).value))"
|
|
145
|
+
class="custom-num-field" />
|
|
146
|
+
</div>
|
|
70
147
|
</div>
|
|
71
|
-
<!--
|
|
72
|
-
<
|
|
148
|
+
<!-- Aspect lock button -->
|
|
149
|
+
<button type="button" class="aspect-lock-btn" :class="{ 'is-active': isFixedRatio }"
|
|
150
|
+
:title="isFixedRatio ? '取消锁定宽高比' : '锁定宽高比'"
|
|
73
151
|
@click="emit('update:isFixedRatio', !isFixedRatio)">
|
|
74
|
-
<svg class="icon" style="width: 16px; height: 16px;">
|
|
152
|
+
<svg class="icon" style="width: 16px; height: 16px; fill: currentColor;">
|
|
75
153
|
<use :xlink:href="isFixedRatio ? '#icon-suoding1' : '#icon-quxiaosuoding'"></use>
|
|
76
154
|
</svg>
|
|
77
|
-
</
|
|
155
|
+
</button>
|
|
78
156
|
</div>
|
|
79
157
|
|
|
80
|
-
<!--
|
|
81
|
-
<div v-if="showRotate || showFlips"
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
<
|
|
102
|
-
<use xlink:href="#icon-shuipingfanzhuan"></use>
|
|
103
|
-
</svg>
|
|
158
|
+
<!-- Row 3: Rotate & Flips -->
|
|
159
|
+
<div v-if="showRotate || showFlips" class="pos-row">
|
|
160
|
+
<div class="pos-main-cols">
|
|
161
|
+
<!-- Rotate in Col 1 (matches width of X and W exactly) -->
|
|
162
|
+
<div v-if="showRotate" class="custom-num-input rotate-input-wrapper" @click="focusRotateInput">
|
|
163
|
+
<span class="custom-num-prefix angle-prefix-icon">
|
|
164
|
+
<svg class="icon" style="width: 14px; height: 14px; fill: currentColor;">
|
|
165
|
+
<use xlink:href="#icon-jiaodu"></use>
|
|
166
|
+
</svg>
|
|
167
|
+
</span>
|
|
168
|
+
<input
|
|
169
|
+
ref="rotateInputRef"
|
|
170
|
+
type="text"
|
|
171
|
+
inputmode="numeric"
|
|
172
|
+
:value="elementRotate ?? 0"
|
|
173
|
+
@input="onRotateInput"
|
|
174
|
+
@blur="onRotateBlur"
|
|
175
|
+
@keydown.enter="($event.target as HTMLElement).blur()"
|
|
176
|
+
class="custom-num-field rotate-num-field"
|
|
177
|
+
:style="{ width: `calc(${rotateDisplayLen}ch + 6px)` }"
|
|
178
|
+
/>
|
|
179
|
+
<span class="angle-deg-symbol">°</span>
|
|
104
180
|
</div>
|
|
105
|
-
<div class="
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
181
|
+
<div v-else class="empty-col-placeholder"></div>
|
|
182
|
+
|
|
183
|
+
<!-- Flips in Col 2 (matches boundaries of Y and H exactly) -->
|
|
184
|
+
<div v-if="showFlips" class="flips-pair">
|
|
185
|
+
<button type="button" class="pos-action-btn" title="水平翻转"
|
|
186
|
+
@click="emit('toggleFlipH')">
|
|
187
|
+
<svg viewBox="0 0 16 16" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.4">
|
|
188
|
+
<polygon points="8,2 2,14 8,14" fill="none" stroke="currentColor" />
|
|
189
|
+
<polygon points="8,2 14,14 8,14" fill="currentColor" stroke="currentColor" />
|
|
190
|
+
<line x1="8" y1="1" x2="8" y2="15" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" />
|
|
191
|
+
</svg>
|
|
192
|
+
</button>
|
|
193
|
+
<button type="button" class="pos-action-btn" title="垂直翻转"
|
|
194
|
+
@click="emit('toggleFlipV')">
|
|
195
|
+
<svg viewBox="0 0 16 16" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.4">
|
|
196
|
+
<polygon points="14,8 2,2 2,8" fill="none" stroke="currentColor" />
|
|
197
|
+
<polygon points="14,8 2,14 2,8" fill="currentColor" stroke="currentColor" />
|
|
198
|
+
<line x1="1" y1="8" x2="15" y2="8" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" />
|
|
199
|
+
</svg>
|
|
200
|
+
</button>
|
|
111
201
|
</div>
|
|
112
202
|
</div>
|
|
203
|
+
<div class="pos-side-placeholder"></div>
|
|
113
204
|
</div>
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
205
|
+
|
|
206
|
+
<!-- Row 4: Layer ordering buttons (上移一层, 下移一层, 置于顶层, 置于底层) -->
|
|
207
|
+
<div class="pos-row">
|
|
208
|
+
<div class="pos-main-cols">
|
|
209
|
+
<div class="layer-buttons-quad">
|
|
210
|
+
<!-- 上移一层 -->
|
|
211
|
+
<button type="button" class="pos-action-btn" :class="{ 'is-disabled': !canMoveUp }"
|
|
212
|
+
:disabled="!canMoveUp" title="上移一层" @click="canMoveUp && emit('adjustZIndex', 'forward')">
|
|
213
|
+
<svg class="icon" style="width: 16px; height: 16px;">
|
|
214
|
+
<use :xlink:href="canMoveUp ? '#icon-shangyiyiceng' : '#icon-shangyiyiceng1'"></use>
|
|
215
|
+
</svg>
|
|
216
|
+
</button>
|
|
217
|
+
|
|
218
|
+
<!-- 下移一层 -->
|
|
219
|
+
<button type="button" class="pos-action-btn" :class="{ 'is-disabled': !canMoveDown }"
|
|
220
|
+
:disabled="!canMoveDown" title="下移一层" @click="canMoveDown && emit('adjustZIndex', 'backward')">
|
|
221
|
+
<svg class="icon" style="width: 16px; height: 16px;">
|
|
222
|
+
<use :xlink:href="canMoveDown ? '#icon-xiayiyiceng' : '#icon-xiayiyiceng1'"></use>
|
|
223
|
+
</svg>
|
|
224
|
+
</button>
|
|
225
|
+
|
|
226
|
+
<!-- 置于顶层 -->
|
|
227
|
+
<button type="button" class="pos-action-btn" :class="{ 'is-disabled': !canMoveTop }"
|
|
228
|
+
:disabled="!canMoveTop" title="置于顶层" @click="canMoveTop && emit('adjustZIndex', 'front')">
|
|
229
|
+
<svg class="icon" style="width: 16px; height: 16px;">
|
|
230
|
+
<use :xlink:href="canMoveTop ? '#icon-zhiyudingceng' : '#icon-zhiyudingceng1'"></use>
|
|
231
|
+
</svg>
|
|
232
|
+
</button>
|
|
233
|
+
|
|
234
|
+
<!-- 置于底层 -->
|
|
235
|
+
<button type="button" class="pos-action-btn" :class="{ 'is-disabled': !canMoveBottom }"
|
|
236
|
+
:disabled="!canMoveBottom" title="置于底层" @click="canMoveBottom && emit('adjustZIndex', 'back')">
|
|
237
|
+
<svg class="icon" style="width: 16px; height: 16px;">
|
|
238
|
+
<use :xlink:href="canMoveBottom ? '#icon-zhiyudiceng' : '#icon-zhiyudiceng1'"></use>
|
|
239
|
+
</svg>
|
|
240
|
+
</button>
|
|
241
|
+
</div>
|
|
135
242
|
</div>
|
|
243
|
+
<div class="pos-side-placeholder"></div>
|
|
136
244
|
</div>
|
|
137
245
|
<slot />
|
|
138
246
|
</div>
|
|
139
247
|
</template>
|
|
140
248
|
|
|
141
249
|
<style scoped>
|
|
142
|
-
.
|
|
250
|
+
.sidebar-position-group {
|
|
251
|
+
padding: 0 16px;
|
|
252
|
+
margin-top: 4px;
|
|
253
|
+
margin-bottom: 12px;
|
|
254
|
+
border-bottom: 1px solid #edf0f3;
|
|
255
|
+
padding-bottom: 12px;
|
|
143
256
|
display: flex;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
border: 1px solid #F5F6F7;
|
|
147
|
-
border-radius: 4px;
|
|
148
|
-
padding: 0 8px;
|
|
149
|
-
height: 32px;
|
|
150
|
-
box-sizing: border-box;
|
|
151
|
-
transition: border-color 0.15s ease;
|
|
257
|
+
flex-direction: column;
|
|
258
|
+
gap: 8px;
|
|
152
259
|
}
|
|
153
260
|
|
|
154
|
-
.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
background: #f8fafc;
|
|
160
|
-
cursor: not-allowed;
|
|
161
|
-
opacity: 0.85;
|
|
261
|
+
.pos-row {
|
|
262
|
+
display: flex;
|
|
263
|
+
align-items: center;
|
|
264
|
+
gap: 8px;
|
|
265
|
+
width: 100%;
|
|
162
266
|
}
|
|
163
267
|
|
|
164
|
-
.
|
|
165
|
-
|
|
268
|
+
.pos-main-cols {
|
|
269
|
+
flex: 1;
|
|
270
|
+
display: grid;
|
|
271
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
272
|
+
gap: 8px;
|
|
273
|
+
align-items: center;
|
|
274
|
+
min-width: 0;
|
|
166
275
|
}
|
|
167
276
|
|
|
168
|
-
.
|
|
169
|
-
|
|
170
|
-
|
|
277
|
+
.pos-side-placeholder {
|
|
278
|
+
width: 34px;
|
|
279
|
+
height: 34px;
|
|
280
|
+
flex-shrink: 0;
|
|
281
|
+
visibility: hidden;
|
|
171
282
|
pointer-events: none;
|
|
172
|
-
user-select: none;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
.custom-num-input.is-disabled:hover,
|
|
176
|
-
.custom-num-input.is-disabled:focus-within {
|
|
177
|
-
border-color: #F5F6F7;
|
|
178
283
|
}
|
|
179
284
|
|
|
180
285
|
.aspect-lock-btn {
|
|
181
|
-
width:
|
|
182
|
-
height:
|
|
183
|
-
border-radius:
|
|
286
|
+
width: 34px;
|
|
287
|
+
height: 34px;
|
|
288
|
+
border-radius: 8px;
|
|
184
289
|
display: flex;
|
|
185
290
|
align-items: center;
|
|
186
291
|
justify-content: center;
|
|
187
292
|
cursor: pointer;
|
|
188
|
-
transition: all 0.
|
|
293
|
+
transition: all 0.15s ease;
|
|
189
294
|
box-sizing: border-box;
|
|
190
295
|
flex-shrink: 0;
|
|
191
|
-
background: #
|
|
192
|
-
color:
|
|
193
|
-
border:
|
|
296
|
+
background: #f8f9fa;
|
|
297
|
+
color: #64748b;
|
|
298
|
+
border: 1px solid #edf0f3;
|
|
299
|
+
padding: 0;
|
|
194
300
|
}
|
|
195
301
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
302
|
+
/* 仅在未选中状态下应用鼠标移入浅蓝背景 */
|
|
303
|
+
.aspect-lock-btn:not(.is-active):hover {
|
|
304
|
+
background: rgba(30, 111, 255, 0.12);
|
|
305
|
+
color: #1E6FFF;
|
|
306
|
+
border-color: rgba(30, 111, 255, 0.4);
|
|
199
307
|
}
|
|
200
308
|
|
|
201
|
-
|
|
202
|
-
|
|
309
|
+
/* 选中状态:以选中的 #1E6FFF 为主,鼠标移入时不覆盖背景色 */
|
|
310
|
+
.aspect-lock-btn.is-active,
|
|
311
|
+
.aspect-lock-btn.is-active:hover {
|
|
312
|
+
background: #1E6FFF !important;
|
|
203
313
|
color: #ffffff !important;
|
|
314
|
+
border-color: #1E6FFF !important;
|
|
204
315
|
}
|
|
205
316
|
|
|
206
|
-
.
|
|
207
|
-
|
|
317
|
+
.flips-pair {
|
|
318
|
+
display: grid;
|
|
319
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
320
|
+
gap: 8px;
|
|
321
|
+
width: 100%;
|
|
322
|
+
min-width: 0;
|
|
208
323
|
}
|
|
209
324
|
|
|
210
|
-
.
|
|
211
|
-
|
|
212
|
-
|
|
325
|
+
.layer-buttons-quad {
|
|
326
|
+
grid-column: 1 / -1;
|
|
327
|
+
display: grid;
|
|
328
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
329
|
+
gap: 8px;
|
|
330
|
+
width: 100%;
|
|
331
|
+
min-width: 0;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.empty-col-placeholder {
|
|
335
|
+
height: 34px;
|
|
336
|
+
visibility: hidden;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.custom-num-input {
|
|
340
|
+
display: flex;
|
|
341
|
+
align-items: center;
|
|
342
|
+
background: #f8f9fa;
|
|
343
|
+
border: 1px solid #edf0f3;
|
|
344
|
+
border-radius: 8px;
|
|
345
|
+
padding: 0 10px;
|
|
346
|
+
height: 34px;
|
|
347
|
+
box-sizing: border-box;
|
|
348
|
+
transition: all 0.15s ease;
|
|
349
|
+
position: relative;
|
|
350
|
+
min-width: 0;
|
|
351
|
+
width: 100%;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.custom-num-input:hover {
|
|
355
|
+
border-color: #e2e8f0;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.custom-num-input:focus-within {
|
|
359
|
+
background: #ffffff;
|
|
360
|
+
border-color: #1E6FFF;
|
|
361
|
+
box-shadow: 0 0 0 2px rgba(30, 111, 255, 0.12);
|
|
213
362
|
}
|
|
214
363
|
|
|
215
364
|
.custom-num-prefix {
|
|
216
365
|
font-size: 12px;
|
|
217
|
-
|
|
366
|
+
font-weight: 500;
|
|
367
|
+
color: #94a3b8;
|
|
218
368
|
white-space: nowrap;
|
|
219
369
|
user-select: none;
|
|
370
|
+
margin-right: 6px;
|
|
371
|
+
display: flex;
|
|
372
|
+
align-items: center;
|
|
373
|
+
flex-shrink: 0;
|
|
220
374
|
}
|
|
221
375
|
|
|
222
376
|
.custom-num-field {
|
|
@@ -224,9 +378,11 @@ const emit = defineEmits<{
|
|
|
224
378
|
border: none;
|
|
225
379
|
background: transparent;
|
|
226
380
|
outline: none;
|
|
227
|
-
font-size:
|
|
228
|
-
|
|
229
|
-
|
|
381
|
+
font-size: 13px;
|
|
382
|
+
font-weight: 500;
|
|
383
|
+
color: #1e293b;
|
|
384
|
+
padding: 0;
|
|
385
|
+
min-width: 0;
|
|
230
386
|
}
|
|
231
387
|
|
|
232
388
|
.custom-num-field::-webkit-outer-spin-button,
|
|
@@ -235,32 +391,85 @@ const emit = defineEmits<{
|
|
|
235
391
|
margin: 0;
|
|
236
392
|
}
|
|
237
393
|
|
|
238
|
-
.
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
394
|
+
.rotate-input-wrapper {
|
|
395
|
+
cursor: text;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.rotate-num-field {
|
|
399
|
+
width: auto;
|
|
400
|
+
min-width: 1ch;
|
|
401
|
+
flex: none;
|
|
402
|
+
font-variant-numeric: tabular-nums;
|
|
403
|
+
box-sizing: content-box;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.angle-prefix-icon {
|
|
407
|
+
color: #64748b;
|
|
408
|
+
margin-right: 6px;
|
|
409
|
+
flex-shrink: 0;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.angle-deg-symbol {
|
|
243
413
|
font-size: 12px;
|
|
244
|
-
|
|
414
|
+
font-weight: 500;
|
|
415
|
+
color: #64748b;
|
|
245
416
|
margin-left: 2px;
|
|
417
|
+
line-height: 1;
|
|
418
|
+
user-select: none;
|
|
419
|
+
pointer-events: none;
|
|
420
|
+
flex-shrink: 0;
|
|
246
421
|
}
|
|
247
422
|
|
|
248
|
-
.
|
|
249
|
-
height:
|
|
250
|
-
border-radius:
|
|
423
|
+
.pos-action-btn {
|
|
424
|
+
height: 34px;
|
|
425
|
+
border-radius: 8px;
|
|
251
426
|
display: flex;
|
|
252
427
|
align-items: center;
|
|
253
428
|
justify-content: center;
|
|
254
429
|
cursor: pointer;
|
|
255
|
-
background: #
|
|
256
|
-
color:
|
|
257
|
-
border:
|
|
430
|
+
background: #f8f9fa;
|
|
431
|
+
color: #64748b;
|
|
432
|
+
border: 1px solid #edf0f3;
|
|
258
433
|
box-sizing: border-box;
|
|
259
434
|
transition: all 0.15s ease;
|
|
435
|
+
padding: 0;
|
|
436
|
+
width: 100%;
|
|
437
|
+
min-width: 0;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/* 仅在未选中且未禁用状态下应用鼠标移入浅蓝背景 */
|
|
441
|
+
.pos-action-btn:not(.is-active):not(:disabled):not(.is-disabled):hover {
|
|
442
|
+
background: rgba(30, 111, 255, 0.12);
|
|
443
|
+
color: #1E6FFF;
|
|
444
|
+
border-color: rgba(30, 111, 255, 0.4);
|
|
260
445
|
}
|
|
261
446
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
447
|
+
/* 禁用状态 */
|
|
448
|
+
.pos-action-btn:disabled,
|
|
449
|
+
.pos-action-btn.is-disabled {
|
|
450
|
+
cursor: not-allowed;
|
|
451
|
+
opacity: 0.85;
|
|
452
|
+
background: #f8f9fa;
|
|
453
|
+
border-color: #edf0f3;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/* 选中状态:以选中的 #1E6FFF 为主,鼠标移入时不覆盖背景色 */
|
|
457
|
+
.pos-action-btn.is-active,
|
|
458
|
+
.pos-action-btn.is-active:hover {
|
|
459
|
+
background: #1E6FFF !important;
|
|
460
|
+
color: #ffffff !important;
|
|
461
|
+
border-color: #1E6FFF !important;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.custom-num-input.is-disabled {
|
|
465
|
+
background: #f8fafc;
|
|
466
|
+
cursor: not-allowed;
|
|
467
|
+
opacity: 0.7;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.custom-num-input.is-disabled .custom-num-prefix,
|
|
471
|
+
.custom-num-input.is-disabled .custom-num-field {
|
|
472
|
+
color: #94a3b8;
|
|
473
|
+
cursor: not-allowed;
|
|
265
474
|
}
|
|
266
475
|
</style>
|