bge-ui 1.2.0 → 1.2.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,51 @@
1
+ declare const _default: import("vue").DefineComponent<{
2
+ marks: {
3
+ type: ObjectConstructor;
4
+ default: () => void;
5
+ };
6
+ modelValue: {
7
+ type: NumberConstructor;
8
+ default: number;
9
+ };
10
+ showToolTip: {
11
+ type: BooleanConstructor;
12
+ default: boolean;
13
+ };
14
+ formatTooltip: {
15
+ type: FunctionConstructor;
16
+ default: undefined;
17
+ };
18
+ }, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
+ input: (...args: any[]) => void;
20
+ "update:modelValue": (...args: any[]) => void;
21
+ blur: (...args: any[]) => void;
22
+ focus: (...args: any[]) => void;
23
+ }, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
24
+ marks: {
25
+ type: ObjectConstructor;
26
+ default: () => void;
27
+ };
28
+ modelValue: {
29
+ type: NumberConstructor;
30
+ default: number;
31
+ };
32
+ showToolTip: {
33
+ type: BooleanConstructor;
34
+ default: boolean;
35
+ };
36
+ formatTooltip: {
37
+ type: FunctionConstructor;
38
+ default: undefined;
39
+ };
40
+ }>> & {
41
+ onFocus?: ((...args: any[]) => any) | undefined;
42
+ onBlur?: ((...args: any[]) => any) | undefined;
43
+ onInput?: ((...args: any[]) => any) | undefined;
44
+ "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
45
+ }, {
46
+ modelValue: number;
47
+ showToolTip: boolean;
48
+ marks: Record<string, any>;
49
+ formatTooltip: Function;
50
+ }, {}>;
51
+ export default _default;
package/dist/style.css CHANGED
@@ -764,6 +764,8 @@ to {
764
764
  margin-top: 4px;
765
765
  }.bge-input {
766
766
  position: relative;
767
+ --bg-input: var(--bg-opacity);
768
+ --bg-input-hover: var(--bg-opacity-hover);
767
769
  }
768
770
  .bge-input .bge-input__wrapper {
769
771
  height: 40px;
@@ -1428,4 +1430,110 @@ to {
1428
1430
  }
1429
1431
  .bge-radio__inner:hover .border {
1430
1432
  fill: var(--tc-theme);
1433
+ }.bge-slider {
1434
+ width: 100%;
1435
+ height: 32px;
1436
+ display: flex;
1437
+ align-items: center;
1438
+ cursor: pointer;
1439
+ }
1440
+ .bge-slider .bge-slider__runway {
1441
+ background: var(--bg-slider, #2E3842);
1442
+ height: 2px;
1443
+ width: 100%;
1444
+ border-radius: var(--radius-small);
1445
+ position: relative;
1446
+ vertical-align: middle;
1447
+ }
1448
+ .bge-slider .bge-slider__runway .ui-slider__bar {
1449
+ height: 2px;
1450
+ background: var(--bg-slider-selected, #4F5C71);
1451
+ border-top-left-radius: 3px;
1452
+ border-bottom-left-radius: 3px;
1453
+ position: absolute;
1454
+ }
1455
+ .bge-slider .bge-slider__runway .slider-button-wrapper {
1456
+ height: 16px;
1457
+ width: 16px;
1458
+ position: absolute;
1459
+ z-index: 100;
1460
+ top: -15px;
1461
+ transform: translateX(-50%);
1462
+ background-color: transparent;
1463
+ text-align: center;
1464
+ -webkit-user-select: none;
1465
+ -moz-user-select: none;
1466
+ -ms-user-select: none;
1467
+ user-select: none;
1468
+ line-height: normal;
1469
+ }
1470
+ .bge-slider .bge-slider__runway .slider-button-wrapper .slider-button {
1471
+ background: var(--bg-slider-selected, #4F5C71);
1472
+ position: relative;
1473
+ top: 6px;
1474
+ width: 14px;
1475
+ height: 14px;
1476
+ border-radius: 50%;
1477
+ transition: 0.2s;
1478
+ user-select: none;
1479
+ vertical-align: middle;
1480
+ display: inline-block;
1481
+ }
1482
+ .bge-slider .bge-slider__runway .slider-button-wrapper .slider-button:hover {
1483
+ transform: scale(1.2);
1484
+ cursor: grab;
1485
+ }
1486
+ .bge-slider .bge-slider__runway .slider-button-wrapper .slider-button::before {
1487
+ content: "";
1488
+ position: absolute;
1489
+ left: 0;
1490
+ top: 0;
1491
+ transform: translate(3px, 3px);
1492
+ display: inline-block;
1493
+ width: 8px;
1494
+ height: 8px;
1495
+ border-radius: 50%;
1496
+ background-color: var(--bg-secondary);
1497
+ }
1498
+ .bge-slider .bge-slider__runway .bge-slider__stop {
1499
+ background: var(--bg-slider, #2E3842);
1500
+ height: 8px;
1501
+ width: 8px;
1502
+ top: -3px;
1503
+ position: absolute;
1504
+ border-radius: 100%;
1505
+ transform: translateX(-50%);
1506
+ }
1507
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-0 .bge-slider__stop:nth-child(-n+1) {
1508
+ background: var(--bg-slider-selected, #4F5C71);
1509
+ }
1510
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-1 .bge-slider__stop:nth-child(-n+2) {
1511
+ background: var(--bg-slider-selected, #4F5C71);
1512
+ }
1513
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-2 .bge-slider__stop:nth-child(-n+3) {
1514
+ background: var(--bg-slider-selected, #4F5C71);
1515
+ }
1516
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-3 .bge-slider__stop:nth-child(-n+4) {
1517
+ background: var(--bg-slider-selected, #4F5C71);
1518
+ }
1519
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-4 .bge-slider__stop:nth-child(-n+5) {
1520
+ background: var(--bg-slider-selected, #4F5C71);
1521
+ }
1522
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-5 .bge-slider__stop:nth-child(-n+6) {
1523
+ background: var(--bg-slider-selected, #4F5C71);
1524
+ }
1525
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-6 .bge-slider__stop:nth-child(-n+7) {
1526
+ background: var(--bg-slider-selected, #4F5C71);
1527
+ }
1528
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-7 .bge-slider__stop:nth-child(-n+8) {
1529
+ background: var(--bg-slider-selected, #4F5C71);
1530
+ }
1531
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-8 .bge-slider__stop:nth-child(-n+9) {
1532
+ background: var(--bg-slider-selected, #4F5C71);
1533
+ }
1534
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-9 .bge-slider__stop:nth-child(-n+10) {
1535
+ background: var(--bg-slider-selected, #4F5C71);
1536
+ }
1537
+ .bge-slider .bge-slider__runway .bge-slider__stops.bge-slider__stop-10 .bge-slider__stop:nth-child(-n+11) {
1538
+ background: var(--bg-slider-selected, #4F5C71);
1431
1539
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bge-ui",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -26,7 +26,8 @@
26
26
  "sass": "^1.69.5",
27
27
  "tsx": "^4.6.2",
28
28
  "vite-plugin-dts": "^3.6.4",
29
- "vue": "^3.3.9"
29
+ "vue": "^3.3.9",
30
+ "bignumber.js": "^9.1.2"
30
31
  },
31
32
  "devDependencies": {
32
33
  "@types/node": "^20.10.1"
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ import UiMessage from "./message/method.ts"
12
12
  import UiDialog from "./dialog/index.vue"
13
13
  import UiCheckbox from "./checkBox/index.vue"
14
14
  import UiRadio from "./radio/index.vue"
15
+ import UiSlider from "./slider/index.vue"
15
16
 
16
17
  const components: any = {
17
18
  UiButton,
@@ -24,7 +25,8 @@ const components: any = {
24
25
  UiTooltip,
25
26
  UiDialog,
26
27
  UiCheckbox,
27
- UiRadio
28
+ UiRadio,
29
+ UiSlider
28
30
  }
29
31
 
30
32
  export * from './icons/index.ts'
@@ -41,7 +43,8 @@ export {
41
43
  UiDialog,
42
44
  UiMessage,
43
45
  UiCheckbox,
44
- UiRadio
46
+ UiRadio,
47
+ UiSlider
45
48
  }
46
49
 
47
50
  export default {
@@ -113,6 +113,9 @@ function handelClear() {
113
113
  .bge-input {
114
114
  position: relative;
115
115
 
116
+ --bg-input: var(--bg-opacity);
117
+ --bg-input-hover: var(--bg-opacity-hover);
118
+
116
119
  .bge-input__wrapper {
117
120
  height: 40px;
118
121
  padding: var(--layout-x-0, 0px) var(--layout-x-4, 16px);
@@ -0,0 +1,262 @@
1
+ <template>
2
+ <div class="bge-slider" @mouseleave="onDragEnd" @click="onSliderClick">
3
+ <div ref="slider" class="bge-slider__runway" >
4
+ <div class="ui-slider__bar" :style="state.sliderBarStyle"></div>
5
+ <div class="slider-button-wrapper" :style="state.sliderButtonStyle"
6
+ @touchstart="onButtonDown"
7
+ @mousedown="onButtonDown"
8
+ >
9
+ <ui-tooltip v-if="showToolTip" ref="tooltip" placement="top" size="mini" >
10
+ <template #content>
11
+ {{ formatTooltip ? formatTooltip(modelValue) : `${modelValue}%` }}
12
+ </template>
13
+ <div class="slider-button" @mouseover="state.hovering = true" @mouseleave="state.hovering = false"></div>
14
+ </ui-tooltip>
15
+
16
+ <div v-else class="slider-button" @mouseover="state.hovering = true" @mouseleave="state.hovering = false"></div>
17
+ </div>
18
+ <div :class="`bge-slider__stops bge-slider__stop-${state.stopValue}`">
19
+ <div v-for="(mark, key) in marks" :key="key" class="bge-slider__stop" :style="`left: ${key}%;`"></div>
20
+ </div>
21
+ </div>
22
+ </div>
23
+ </template>
24
+ <script lang="ts" setup>
25
+ import { ref, reactive, watch } from 'vue'
26
+ import UiTooltip from '../tooltip/index.vue'
27
+ import BigNumber from 'bignumber.js'
28
+
29
+ const props = defineProps({
30
+ marks: {
31
+ type: Object,
32
+ default: () => {}
33
+ },
34
+ modelValue: {
35
+ type: Number,
36
+ default: 0
37
+ },
38
+ showToolTip: {
39
+ type: Boolean,
40
+ default: true
41
+ },
42
+ formatTooltip: {
43
+ type: Function,
44
+ default: undefined
45
+ }
46
+ })
47
+ const emit = defineEmits(['input', 'focus', 'blur', 'update:modelValue'])
48
+ const state = reactive({
49
+ hovering: false,
50
+ dragging: false,
51
+ isClick: false,
52
+ sliderOffsetLeft: 0,
53
+ sliderSize: 0,
54
+ sliderBarStyle: '',
55
+ sliderButtonStyle: '',
56
+ currentX: 0,
57
+ currentY: 0,
58
+ startPosition: 0,
59
+ newPosition: 0,
60
+ stopValue: 0,
61
+ newValue: 0
62
+ })
63
+
64
+ function onDragStart (event: any) {
65
+ emit('focus')
66
+ state.dragging = true
67
+ state.hovering = true
68
+ state.isClick = true
69
+ if (event.type === 'touchstart') {
70
+ event.clientY = event.touches[0].clientY
71
+ event.clientX = event.touches[0].clientX
72
+ }
73
+ state.sliderSize = slider.value.clientWidth
74
+ state.sliderOffsetLeft = slider.value.getBoundingClientRect().left
75
+ state.newPosition = state.startPosition
76
+ }
77
+
78
+ function onButtonDown (event: any) {
79
+ event.preventDefault()
80
+ onDragStart(event)
81
+ window.addEventListener('mousemove', onDragging)
82
+ window.addEventListener('touchmove', onDragging)
83
+ window.addEventListener('mouseup', onDragEnd)
84
+ window.addEventListener('touchend', onDragEnd)
85
+ window.addEventListener('contextmenu', onDragEnd)
86
+ }
87
+
88
+ function onDragEnd() {
89
+ if (state.dragging) {
90
+ /*
91
+ * 防止在 mouseup 后立即触发 click,导致滑块有几率产生一小段位移
92
+ * 不使用 preventDefault 是因为 mouseup 和 click 没有注册在同一个 DOM 上
93
+ */
94
+ setTimeout(() => {
95
+ state.dragging = false
96
+ state.hovering = false
97
+ }, 0)
98
+ window.removeEventListener('mousemove', onDragging)
99
+ window.removeEventListener('touchmove', onDragging)
100
+ window.removeEventListener('mouseup', onDragEnd)
101
+ window.removeEventListener('touchend', onDragEnd)
102
+ window.removeEventListener('contextmenu', onDragEnd)
103
+ emit('blur')
104
+ }
105
+ }
106
+
107
+ function onDragging(event: any) {
108
+ if (state.dragging) {
109
+ state.isClick = false
110
+ if (event.type === 'touchmove') {
111
+ event.clientY = event.touches[0].clientY
112
+ event.clientX = event.touches[0].clientX
113
+ }
114
+ let percent = ((event.clientX - state.sliderOffsetLeft) / state.sliderSize * 100)
115
+ percent = percent > 100 ? 100 : percent
116
+ percent = percent < 0 ? 0 : percent
117
+ setPosition(percent)
118
+ }
119
+ }
120
+
121
+ const slider = ref()
122
+
123
+ function onSliderClick (event: any) {
124
+ if (state.dragging) {
125
+ return false
126
+ }
127
+ emit('focus')
128
+ state.sliderSize = slider.value.clientWidth
129
+ state.sliderOffsetLeft = slider.value.getBoundingClientRect().left
130
+ let percent = ((event.clientX - state.sliderOffsetLeft) / state.sliderSize * 100)
131
+
132
+ percent = percent > 100 ? 100 : percent
133
+ percent = percent < 0 ? 0 : percent
134
+ // 下边五行代码 要改到业务代码中
135
+ percent = new BigNumber(new BigNumber(percent).toFixed(0)).toNumber()
136
+ const maybePercent = new BigNumber(new BigNumber(percent).div(25).toFixed(0)).multipliedBy(25).toNumber()
137
+ const diffPercent = new BigNumber(maybePercent).minus(percent).abs().div(100).toNumber()
138
+ const isChange = diffPercent <= 0.03
139
+ percent = isChange ? maybePercent : percent
140
+ setPosition(percent)
141
+ setTimeout(() => emit('blur'))
142
+ }
143
+
144
+ const tooltip = ref()
145
+
146
+ function setPosition (percent: any) {
147
+ state.sliderBarStyle = `width: ${percent}%`
148
+ state.sliderButtonStyle = `left: ${percent}%`
149
+ state.stopValue = Number((percent / 100 * (Object.values(props.marks).length - 1)).toFixed())
150
+ state.newValue = Number(percent.toFixed())
151
+ emit('input', state.newValue)
152
+ emit('update:modelValue', state.newValue)
153
+ setTimeout(() => {
154
+ tooltip.value && tooltip.value.popper.value.update()
155
+ }, 50)
156
+ }
157
+
158
+ watch(() => props.modelValue, (val: number) => {
159
+ let percent = val
160
+ percent = percent > 100 ? 100 : percent
161
+ percent = percent < 0 ? 0 : percent
162
+ setPosition(percent)
163
+ }, {
164
+ immediate: true
165
+ })
166
+ </script>
167
+ <style lang="scss">
168
+ .bge-slider {
169
+ width: 100%;
170
+ height: 32px;
171
+ display: flex;
172
+ align-items: center;
173
+ cursor: pointer;
174
+
175
+ .bge-slider__runway {
176
+ background: var(--bg-slider, #2E3842);
177
+ height: 2px;
178
+ width: 100%;
179
+ border-radius: var(--radius-small);
180
+ position: relative;
181
+ vertical-align: middle;
182
+
183
+ .ui-slider__bar {
184
+ height: 2px;
185
+ background: var(--bg-slider-selected, #4F5C71);
186
+ border-top-left-radius: 3px;
187
+ border-bottom-left-radius: 3px;
188
+ position: absolute;
189
+ }
190
+
191
+ .slider-button-wrapper {
192
+ height: 16px;
193
+ width: 16px;
194
+ position: absolute;
195
+ z-index: 100;
196
+ top: -15px;
197
+ transform: translateX(-50%);
198
+ background-color: transparent;
199
+ text-align: center;
200
+ -webkit-user-select: none;
201
+ -moz-user-select: none;
202
+ -ms-user-select: none;
203
+ user-select: none;
204
+ line-height: normal;
205
+
206
+ .slider-button {
207
+ // border: solid 4px rgba(255, 214, 51, 0.16);
208
+ background: var(--bg-slider-selected, #4F5C71);
209
+ position: relative;
210
+ top: 6px;
211
+ width: 14px;
212
+ height: 14px;
213
+ border-radius: 50%;
214
+ transition: 0.2s;
215
+ user-select: none;
216
+ vertical-align: middle;
217
+ display: inline-block;
218
+
219
+ &:hover {
220
+ transform: scale(1.2);
221
+ cursor: grab;
222
+ }
223
+
224
+ &::before {
225
+ content: "";
226
+ position: absolute;
227
+ left: 0;
228
+ top: 0;
229
+ transform: translate(3px, 3px);
230
+ display: inline-block;
231
+ width: 8px;
232
+ height: 8px;
233
+ border-radius: 50%;
234
+ background-color: var(--bg-secondary);
235
+ }
236
+ }
237
+ }
238
+
239
+ .bge-slider__stop {
240
+ background: var(--bg-slider, #2E3842);
241
+ height: 8px;
242
+ width: 8px;
243
+ top: -3px;
244
+ position: absolute;
245
+ border-radius: 100%;
246
+ transform: translateX(-50%);
247
+ }
248
+
249
+ .bge-slider__stops {
250
+ @for $i from 0 through 10 {
251
+ &.bge-slider__stop-#{$i} {
252
+ .bge-slider__stop {
253
+ &:nth-child(-n + #{$i+1}) {
254
+ background: var(--bg-slider-selected, #4F5C71);
255
+ }
256
+ }
257
+ }
258
+ }
259
+ }
260
+ }
261
+ }
262
+ </style>