vue-editify 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,440 @@
1
+ <template>
2
+ <div class="editify-button">
3
+ <div class="editify-button-wrap" :class="{ 'right-border': rightBorder, 'left-border': leftBorder }">
4
+ <Tooltip :content="title" :disabled="!tooltip">
5
+ <div ref="btn" :style="btnStyle" class="editify-button-el" :class="{ disabled: disabled, active: active }" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" @mousedown="handleMouseDown" @mouseup="handleMouseUp" @click="handleClick">
6
+ <div v-if="type == 'default' || type == 'select'" class="editify-button-slot">
7
+ <slot></slot>
8
+ </div>
9
+ <div v-else-if="type == 'display'">{{ displayLabel }}</div>
10
+ <Icon v-if="type == 'select' || type == 'display'" value="caret-down" class="editify-button-caret" :class="{ rotate: layerConfig.show }"></Icon>
11
+ </div>
12
+ </Tooltip>
13
+ <Layer ref="layer" v-model="layerConfig.show" :node="layerConfig.node" border fade placement="bottom-start" :z-index="20" animation="translate" @show="layerShow" @shown="layerShown" @hidden="layerHidden">
14
+ <div class="editify-button-layer" :style="{ width: (type == 'select' ? parseSelectConfig.width : parseDisplayConfig.width) + 'px', maxHeight: (type == 'select' ? parseSelectConfig.maxHeight : parseDisplayConfig.maxHeight) + 'px', overflow: hideScroll ? 'visible' : '' }">
15
+ <slot v-if="$slots.layer" name="layer" :options="cmpOptions"></slot>
16
+ <div v-else class="editify-button-options">
17
+ <div @click="select(item)" class="editify-button-option" :class="{ active: type == 'display' ? item.value == parseDisplayConfig.value : false }" :style="item.style || ''" v-for="item in cmpOptions">
18
+ <slot v-if="$slots.option" name="option" :item="item"></slot>
19
+ <div class="editify-button-option-flex" v-else>
20
+ <Icon v-if="item.icon" :value="item.icon"></Icon>
21
+ <span>{{ item.label }}</span>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </Layer>
27
+ </div>
28
+ </div>
29
+ </template>
30
+ <script>
31
+ import Tooltip from './Tooltip'
32
+ import Layer from './Layer'
33
+ import Icon from './Icon'
34
+ import Dap from 'dap-util'
35
+ export default {
36
+ name: 'Button',
37
+ emits: ['operate', 'layerShow', 'layerShown', 'layerHidden'],
38
+ props: {
39
+ //按钮类型
40
+ type: {
41
+ type: String,
42
+ default: 'default',
43
+ validator(value) {
44
+ //default表示默认的点击按钮
45
+ //select表示下拉列表的按钮
46
+ //display表示显示值的下拉列表按钮
47
+ return ['default', 'select', 'display'].includes(value)
48
+ }
49
+ },
50
+ //按钮名称,唯一值
51
+ name: {
52
+ type: String,
53
+ default: ''
54
+ },
55
+ //按钮提示内容
56
+ title: {
57
+ type: String,
58
+ default: ''
59
+ },
60
+ //是否显示工具提示
61
+ tooltip: {
62
+ type: Boolean,
63
+ default: false
64
+ },
65
+ //是否显示右侧边框
66
+ rightBorder: {
67
+ type: Boolean,
68
+ default: false
69
+ },
70
+ //是否显示左侧边框
71
+ leftBorder: {
72
+ type: Boolean,
73
+ default: false
74
+ },
75
+ //主题色,用于按钮悬浮颜色变化使用,仅支持十六进制
76
+ color: {
77
+ type: String,
78
+ default: ''
79
+ },
80
+ //是否禁用
81
+ disabled: {
82
+ type: Boolean,
83
+ default: false
84
+ },
85
+ //是否激活
86
+ active: {
87
+ type: Boolean,
88
+ default: false
89
+ },
90
+ //type=select时的配置
91
+ selectConfig: {
92
+ type: Object,
93
+ default: null
94
+ },
95
+ //type=display时的配置
96
+ displayConfig: {
97
+ type: Object,
98
+ default: null
99
+ },
100
+ //浮层隐藏滚动条
101
+ hideScroll: {
102
+ type: Boolean,
103
+ default: false
104
+ }
105
+ },
106
+ data() {
107
+ return {
108
+ //选择列表的浮层配置
109
+ layerConfig: {
110
+ show: false,
111
+ node: null
112
+ },
113
+ //按钮状态
114
+ status: null //hover表示悬浮,down表示按下
115
+ }
116
+ },
117
+ computed: {
118
+ //显示在页面的value值对应的label
119
+ displayLabel() {
120
+ const val = this.parseDisplayConfig.options.find(item => {
121
+ return item.value == this.parseDisplayConfig.value
122
+ })
123
+ return val ? val.label : ''
124
+ },
125
+ //渲染的浮层列表数据
126
+ cmpOptions() {
127
+ return this.type == 'select' ? this.parseSelectConfig.options : this.parseDisplayConfig.options
128
+ },
129
+ //处理后的select配置
130
+ parseSelectConfig() {
131
+ let options = []
132
+ let width = ''
133
+ let maxHeight = ''
134
+ if (Dap.common.isObject(this.selectConfig)) {
135
+ if (Array.isArray(this.selectConfig.options)) {
136
+ options = this.selectConfig.options.map(item => {
137
+ if (Dap.common.isObject(item)) {
138
+ return {
139
+ label: item.label,
140
+ value: item.value,
141
+ icon: item.icon,
142
+ style: item.style
143
+ }
144
+ }
145
+ return {
146
+ label: item,
147
+ value: item
148
+ }
149
+ })
150
+ }
151
+ if (typeof this.selectConfig.width == 'number') {
152
+ width = this.selectConfig.width
153
+ }
154
+ if (typeof this.selectConfig.maxHeight == 'number') {
155
+ maxHeight = this.selectConfig.maxHeight
156
+ }
157
+ }
158
+ return {
159
+ options,
160
+ width,
161
+ maxHeight
162
+ }
163
+ },
164
+ //处理后的display配置
165
+ parseDisplayConfig() {
166
+ let options = []
167
+ let width = ''
168
+ let maxHeight = ''
169
+ let value = ''
170
+ if (Dap.common.isObject(this.displayConfig)) {
171
+ if (typeof this.displayConfig.value == 'string' || typeof this.displayConfig.value == 'number') {
172
+ value = this.displayConfig.value
173
+ }
174
+ if (Array.isArray(this.displayConfig.options)) {
175
+ options = this.displayConfig.options.map(item => {
176
+ if (Dap.common.isObject(item)) {
177
+ return {
178
+ label: item.label,
179
+ value: item.value,
180
+ icon: item.icon,
181
+ style: item.style
182
+ }
183
+ }
184
+ return {
185
+ label: item,
186
+ value: item
187
+ }
188
+ })
189
+ let optItem = options.find(item => {
190
+ return item.value == value
191
+ })
192
+ if (!optItem && options[0]) {
193
+ value = options[0].value
194
+ }
195
+ }
196
+ if (typeof this.displayConfig.width == 'number') {
197
+ width = this.displayConfig.width
198
+ }
199
+ if (typeof this.displayConfig.maxHeight == 'number') {
200
+ maxHeight = this.displayConfig.maxHeight
201
+ }
202
+ }
203
+ return {
204
+ options,
205
+ width,
206
+ maxHeight,
207
+ value
208
+ }
209
+ },
210
+ //十六进制颜色转换的rgb颜色数组
211
+ parseColor() {
212
+ return Dap.color.hex2rgb(this.color)
213
+ },
214
+ //按钮样式
215
+ btnStyle() {
216
+ if (this.disabled) {
217
+ return {}
218
+ }
219
+ if (this.color) {
220
+ //激活情况下和鼠标按下状态
221
+ if (this.active || this.status == 'down') {
222
+ return {
223
+ color: this.color,
224
+ backgroundColor: `rgba(${this.parseColor[0]},${this.parseColor[1]},${this.parseColor[2]},0.15)`
225
+ }
226
+ }
227
+ //鼠标悬浮状态
228
+ if (this.status == 'hover') {
229
+ return {
230
+ color: `rgba(${this.parseColor[0]},${this.parseColor[1]},${this.parseColor[2]},0.9)`,
231
+ backgroundColor: `rgba(${this.parseColor[0]},${this.parseColor[1]},${this.parseColor[2]},0.05)`
232
+ }
233
+ }
234
+ }
235
+ return {}
236
+ }
237
+ },
238
+ components: {
239
+ Tooltip,
240
+ Layer,
241
+ Icon
242
+ },
243
+ methods: {
244
+ //主动关闭浮层
245
+ hideLayer() {
246
+ this.layerConfig.show = false
247
+ this.layerConfig.node = null
248
+ },
249
+ //浮层显示时
250
+ layerShow() {
251
+ this.$emit('layerShow')
252
+ },
253
+ //浮层显示后
254
+ layerShown() {
255
+ this.$emit('layerShown')
256
+ },
257
+ //浮层隐藏后
258
+ layerHidden() {
259
+ this.$emit('layerHidden')
260
+ },
261
+ //列表选择
262
+ select(item) {
263
+ if (this.disabled) {
264
+ return
265
+ }
266
+ this.$emit('operate', this.name, item.value)
267
+ this.hideLayer()
268
+ },
269
+ //按钮点击处理
270
+ handleClick() {
271
+ if (this.disabled) {
272
+ return
273
+ }
274
+ if (this.type == 'default') {
275
+ this.$emit('operate', this.name)
276
+ } else {
277
+ if (this.layerConfig.show) {
278
+ this.hideLayer()
279
+ } else {
280
+ this.layerConfig.node = this.$refs.btn
281
+ this.layerConfig.show = true
282
+ }
283
+ }
284
+ },
285
+ //鼠标移入处理
286
+ handleMouseEnter() {
287
+ this.status = 'hover'
288
+ },
289
+ //鼠标移出处理
290
+ handleMouseLeave() {
291
+ this.status = null
292
+ },
293
+ //鼠标按下处理
294
+ handleMouseDown() {
295
+ this.status = 'down'
296
+ },
297
+ //鼠标松开处理
298
+ handleMouseUp() {
299
+ this.status = 'hover'
300
+ }
301
+ }
302
+ }
303
+ </script>
304
+ <style lang="less" scoped>
305
+ .editify-button {
306
+ display: inline-flex;
307
+ justify-content: center;
308
+ align-items: center;
309
+ position: relative;
310
+ color: @font-color;
311
+ font-size: @font-size;
312
+
313
+ .editify-button-wrap {
314
+ padding: 0 4px;
315
+ position: relative;
316
+
317
+ &.right-border::after {
318
+ position: absolute;
319
+ right: 0;
320
+ top: 50%;
321
+ content: '';
322
+ transform: translateY(-50%);
323
+ height: 18px;
324
+ width: 1px;
325
+ background-color: @border-color;
326
+ }
327
+
328
+ &.left-border::before {
329
+ position: absolute;
330
+ left: 0;
331
+ top: 50%;
332
+ content: '';
333
+ transform: translateY(-50%);
334
+ height: 18px;
335
+ width: 1px;
336
+ background-color: @border-color;
337
+ }
338
+
339
+ .editify-button-el {
340
+ display: inline-flex;
341
+ justify-content: flex-start;
342
+ align-items: center;
343
+ white-space: nowrap;
344
+ height: 28px;
345
+ line-height: 1;
346
+ transition: all 200ms;
347
+ background-color: @background;
348
+ padding: 0 8px;
349
+ border-radius: 2px;
350
+
351
+ .editify-button-slot {
352
+ display: inline-flex;
353
+ justify-content: flex-start;
354
+ align-items: center;
355
+ }
356
+
357
+ .editify-button-caret {
358
+ margin-left: 2px;
359
+ transform: scale(0.6);
360
+ transition: transform 200ms;
361
+ font-size: 14px;
362
+
363
+ &.rotate {
364
+ transform: scale(0.6) rotate(180deg);
365
+ }
366
+ }
367
+
368
+ &:hover {
369
+ cursor: pointer;
370
+ background-color: @background-dark;
371
+ }
372
+
373
+ &:active,
374
+ &.active {
375
+ background-color: @background-darker;
376
+ }
377
+
378
+ &.disabled {
379
+ color: @font-color-disabled;
380
+ cursor: not-allowed;
381
+ background-color: @background;
382
+ }
383
+ }
384
+ }
385
+
386
+ .editify-button-layer {
387
+ display: block;
388
+ position: relative;
389
+ overflow-x: hidden;
390
+ overflow-y: auto;
391
+
392
+ .editify-button-options {
393
+ display: block;
394
+ width: 100%;
395
+ padding: 4px 0;
396
+
397
+ .editify-button-option {
398
+ display: flex;
399
+ justify-content: flex-start;
400
+ align-items: center;
401
+ width: 100%;
402
+ padding: 6px 12px;
403
+ transition: all 200ms;
404
+ opacity: 0.8;
405
+ white-space: nowrap;
406
+ text-overflow: ellipsis;
407
+ overflow: hidden;
408
+ box-sizing: border-box;
409
+
410
+ &:hover {
411
+ opacity: 1;
412
+ cursor: pointer;
413
+ background-color: @background-dark;
414
+ }
415
+
416
+ &:active {
417
+ opacity: 1;
418
+ background-color: @background-darker;
419
+ }
420
+
421
+ &.active {
422
+ opacity: 1;
423
+ background-color: @background-darker;
424
+ }
425
+
426
+ .editify-button-option-flex {
427
+ display: flex;
428
+ justify-content: flex-start;
429
+ align-items: center;
430
+ width: 100%;
431
+
432
+ :deep(.editify-icon) {
433
+ margin-right: 10px;
434
+ }
435
+ }
436
+ }
437
+ }
438
+ }
439
+ }
440
+ </style>
@@ -0,0 +1,196 @@
1
+ <template>
2
+ <label class="editify-checkbox" :class="{ disabled: disabled }">
3
+ <span v-if="placement == 'left' && label" class="editify-checkbox-label" :data-editify-placement="placement" v-text="label"></span>
4
+ <input @change="change" :value="value" :disabled="disabled" :checked="check" type="checkbox" />
5
+ <span class="editify-checkbox-item" :class="{ reverse: !color, round: round, checked: check && !disabled }" :style="itemStyle">
6
+ <Icon value="check" :style="{ opacity: check ? '' : 0 }" />
7
+ </span>
8
+ <span v-if="placement == 'right' && label" class="editify-checkbox-label" :data-editify-placement="placement" v-text="label"></span>
9
+ </label>
10
+ </template>
11
+
12
+ <script>
13
+ import Dap from 'dap-util'
14
+ import Icon from './Icon'
15
+ export default {
16
+ name: 'Checkbox',
17
+ emits: ['update:modelValue', 'change'],
18
+ props: {
19
+ //是否禁用
20
+ disabled: {
21
+ type: Boolean,
22
+ default: false
23
+ },
24
+ //是否选中
25
+ modelValue: {
26
+ type: [Boolean, Array],
27
+ default: false
28
+ },
29
+ //label文字
30
+ label: {
31
+ type: String,
32
+ default: null
33
+ },
34
+ //值
35
+ value: {
36
+ type: [Object, Number, String, Array],
37
+ default: ''
38
+ },
39
+ //是否圆形
40
+ round: {
41
+ type: Boolean,
42
+ default: false
43
+ },
44
+ //文字位置
45
+ placement: {
46
+ type: String,
47
+ default: 'right',
48
+ validator(value) {
49
+ return ['left', 'right'].includes(value)
50
+ }
51
+ },
52
+ //主题颜色
53
+ color: {
54
+ type: String,
55
+ default: '',
56
+ validator(value) {
57
+ return Dap.common.matchingText(value, 'hex')
58
+ }
59
+ }
60
+ },
61
+ computed: {
62
+ check() {
63
+ if (typeof this.modelValue == 'boolean') {
64
+ return this.modelValue
65
+ }
66
+ if (Array.isArray(this.modelValue)) {
67
+ //数组中是否已包含此复选框的值
68
+ return this.modelValue.some(item => {
69
+ return Dap.common.equal(item, this.value)
70
+ })
71
+ }
72
+ return false
73
+ },
74
+ itemStyle() {
75
+ let style = {}
76
+ if (this.color && this.check && !this.disabled) {
77
+ style.backgroundColor = this.color
78
+ style.borderColor = this.color
79
+ }
80
+ return style
81
+ }
82
+ },
83
+ components: {
84
+ Icon
85
+ },
86
+ methods: {
87
+ change(event) {
88
+ if (Array.isArray(this.modelValue)) {
89
+ let arr = [...this.modelValue]
90
+ //勾选且不包含
91
+ if (event.target.checked && !this.check) {
92
+ arr.push(this.value)
93
+ }
94
+ //取消且包含
95
+ else if (this.check) {
96
+ arr = arr.filter(item => {
97
+ return !Dap.common.equal(item, this.value)
98
+ })
99
+ }
100
+ this.$emit('update:modelValue', arr)
101
+ this.$emit('change', arr)
102
+ } else if (typeof this.modelValue == 'boolean') {
103
+ this.$emit('update:modelValue', event.target.checked)
104
+ this.$emit('change', event.target.checked)
105
+ }
106
+ }
107
+ }
108
+ }
109
+ </script>
110
+
111
+ <style scoped lang="less">
112
+ .editify-checkbox {
113
+ display: inline-flex;
114
+ margin: 0;
115
+ padding: 0;
116
+ position: relative;
117
+ vertical-align: middle;
118
+ justify-content: flex-start;
119
+ align-items: center;
120
+ cursor: pointer;
121
+ user-select: none;
122
+ font-size: @font-size;
123
+
124
+ input[type='checkbox'] {
125
+ width: 0;
126
+ height: 0;
127
+ opacity: 0;
128
+ border: none;
129
+ display: none;
130
+ }
131
+
132
+ .editify-checkbox-item {
133
+ display: inline-flex;
134
+ display: -webkit-inline-flex;
135
+ justify-content: center;
136
+ align-items: center;
137
+ position: relative;
138
+ margin: 0;
139
+ padding: 1px;
140
+ border: 1px solid @border-color;
141
+ background-color: @background;
142
+ border-radius: 2px;
143
+ color: @background;
144
+ transition: border-color 0.1s cubic-bezier(0.71, -0.46, 0.29, 1.46), background-color 0.1s cubic-bezier(0.71, -0.46, 0.29, 1.46), color 0.1s cubic-bezier(0.71, -0.46, 0.29, 1.46);
145
+
146
+ &.round {
147
+ border-radius: 50%;
148
+ }
149
+
150
+ &.checked {
151
+ background-color: @font-color;
152
+ border-color: @font-color;
153
+
154
+ &.reverse {
155
+ background-color: @background;
156
+ color: @font-color-light;
157
+ border-color: @border-color;
158
+ }
159
+ }
160
+
161
+ :deep(.editify-icon) {
162
+ font-size: 18px;
163
+ zoom: 50%;
164
+ }
165
+ }
166
+
167
+ .editify-checkbox-label {
168
+ vertical-align: middle;
169
+ color: @font-color;
170
+ user-select: none;
171
+ line-height: 1;
172
+
173
+ &[data-editify-placement='left'] {
174
+ margin-right: 6px;
175
+ }
176
+
177
+ &[data-editify-placement='right'] {
178
+ margin-left: 6px;
179
+ }
180
+ }
181
+
182
+ &.disabled {
183
+ cursor: not-allowed;
184
+ .editify-checkbox-item,
185
+ .editify-checkbox-item.check {
186
+ background-color: @background-darker;
187
+ border-color: @border-color;
188
+ color: @font-color-disabled;
189
+ }
190
+
191
+ .editify-checkbox-label {
192
+ color: @font-color-disabled;
193
+ }
194
+ }
195
+ }
196
+ </style>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <i class="editify-icon" :class="'editify-icon-' + value"></i>
3
+ </template>
4
+ <script>
5
+ export default {
6
+ name: 'Icon',
7
+ props: {
8
+ //图标值
9
+ value: {
10
+ type: String,
11
+ default: ''
12
+ }
13
+ }
14
+ }
15
+ </script>
16
+ <style lang="less" scoped>
17
+ @font-face {
18
+ font-family: 'editify-icon';
19
+ src: url('../../icon/iconfont.woff?t=1699274556400') format('woff'), url('../../icon/iconfont.ttf?t=1699274556400') format('truetype');
20
+ }
21
+
22
+ .editify-icon {
23
+ font-family: 'editify-icon' !important;
24
+ font-size: inherit;
25
+ font-style: normal;
26
+ -webkit-font-smoothing: antialiased;
27
+ -moz-osx-font-smoothing: grayscale;
28
+ line-height: 1;
29
+ vertical-align: middle;
30
+ }
31
+ </style>