ketekny-ui-kit 1.0.137 → 1.0.138
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/README.md +46 -1
- package/index.js +2 -1
- package/package.json +1 -1
- package/src/ui/kRange.vue +130 -0
package/README.md
CHANGED
|
@@ -42,6 +42,7 @@ import "ketekny-ui-kit/styles.css";
|
|
|
42
42
|
import {
|
|
43
43
|
kButton,
|
|
44
44
|
kInput,
|
|
45
|
+
kRange,
|
|
45
46
|
kSelect,
|
|
46
47
|
kDateSelector,
|
|
47
48
|
kToggle,
|
|
@@ -58,6 +59,7 @@ const app = createApp(App);
|
|
|
58
59
|
|
|
59
60
|
app.component("kButton", kButton);
|
|
60
61
|
app.component("kInput", kInput);
|
|
62
|
+
app.component("kRange", kRange);
|
|
61
63
|
app.component("kSelect", kSelect);
|
|
62
64
|
app.component("kDateSelector", kDateSelector);
|
|
63
65
|
app.component("kToggle", kToggle);
|
|
@@ -194,6 +196,49 @@ module.exports = {
|
|
|
194
196
|
|
|
195
197
|
Note: exact option keys may vary by component/plugin implementation version.
|
|
196
198
|
|
|
199
|
+
## Integer Range
|
|
200
|
+
|
|
201
|
+
`kRange` is a dual-handle slider that selects two integers. Its `v-model` is a
|
|
202
|
+
two-item array in `[from, to]` order.
|
|
203
|
+
|
|
204
|
+
```vue
|
|
205
|
+
<template>
|
|
206
|
+
<kRange
|
|
207
|
+
v-model="range"
|
|
208
|
+
label="Allowed age"
|
|
209
|
+
:min="18"
|
|
210
|
+
:max="80"
|
|
211
|
+
:step="1"
|
|
212
|
+
/>
|
|
213
|
+
</template>
|
|
214
|
+
|
|
215
|
+
<script setup>
|
|
216
|
+
import { ref } from "vue";
|
|
217
|
+
import { kRange } from "ketekny-ui-kit";
|
|
218
|
+
|
|
219
|
+
const range = ref([25, 65]);
|
|
220
|
+
</script>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
The configured minimum and maximum appear at the slider ends. Selected values
|
|
224
|
+
appear below their handles.
|
|
225
|
+
|
|
226
|
+
Props:
|
|
227
|
+
|
|
228
|
+
- `modelValue` (`Number[]`, default `[0, 100]`): selected `[from, to]` integers.
|
|
229
|
+
- `min` (`Number`, default `0`): minimum selectable value.
|
|
230
|
+
- `max` (`Number`, default `100`): maximum selectable value.
|
|
231
|
+
- `step` (`Number`, default `1`): positive integer increment.
|
|
232
|
+
- `label`, `info`, `error`, `id`: standard field metadata.
|
|
233
|
+
- `disabled`: disables the slider.
|
|
234
|
+
- `showStops`: shows every step along the slider.
|
|
235
|
+
- `showTooltip`: shows handle tooltips while dragging.
|
|
236
|
+
|
|
237
|
+
Events:
|
|
238
|
+
|
|
239
|
+
- `update:modelValue`: emitted while either handle moves.
|
|
240
|
+
- `change`: emitted when the selected range changes.
|
|
241
|
+
|
|
197
242
|
## Exports
|
|
198
243
|
|
|
199
244
|
Components:
|
|
@@ -201,7 +246,7 @@ Components:
|
|
|
201
246
|
- `kMessage`, `kCode`, `kToolbar`, `kTable`, `kTabs`, `kChip`
|
|
202
247
|
- `kSpinner`, `kDatatable`, `kIcon`, `kMenu`, `kSkeleton`
|
|
203
248
|
- `kProgressBar`, `kPagination`, `kTree`, `kButton`, `kSelect`, `kUploader`
|
|
204
|
-
- `kToggle`, `kCheckbox`, `kInput`, `kDateSelector`, `kEditor`
|
|
249
|
+
- `kToggle`, `kCheckbox`, `kInput`, `kRange`, `kDateSelector`, `kEditor`
|
|
205
250
|
- `kSelectButton`, `kTags`, `kSearch`, `kArrayList`, `kList`, `kTextArea`
|
|
206
251
|
- `kDialog`, `kDrawer`
|
|
207
252
|
- `kAppHeader`, `kAppFooter`, `kAppMain`, `kHero`
|
package/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import kCode from './src/ui/kCode.vue'
|
|
|
9
9
|
import kDialog from './src/ui/kDialog.vue'
|
|
10
10
|
import kDrawer from './src/ui/kDrawer.vue'
|
|
11
11
|
import kInput from './src/ui/kInput.vue'
|
|
12
|
+
import kRange from './src/ui/kRange.vue'
|
|
12
13
|
import kDateSelector from './src/ui/kDateSelector.vue'
|
|
13
14
|
import kToolbar from './src/ui/kToolbar.vue'
|
|
14
15
|
import kTooltip from './src/ui/kTooltip.vue'
|
|
@@ -63,7 +64,7 @@ export {
|
|
|
63
64
|
kMessage, kCode, kToolbar, kTooltip, kTable, kTabs, kCard, kChip, kClipboard, kSpinner, kDatatable, kIcon, kMenu, kSkeleton, kProgressBar, kPagination, kTree,
|
|
64
65
|
|
|
65
66
|
// Form Components
|
|
66
|
-
kButton, kCheckbox, kSelect, kUploader, kToggle, kInput, kDateSelector, kEditor, kSelectButton, kTags, kSearch, kArrayList, kList, kTextArea, kForm, kOptionGroup,
|
|
67
|
+
kButton, kCheckbox, kSelect, kUploader, kToggle, kInput, kRange, kDateSelector, kEditor, kSelectButton, kTags, kSearch, kArrayList, kList, kTextArea, kForm, kOptionGroup,
|
|
67
68
|
|
|
68
69
|
// Dialogs
|
|
69
70
|
kDialog, kDrawer,
|
package/package.json
CHANGED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="w-full text-primary/90">
|
|
3
|
+
<label v-if="label != null" :for="rangeId" class="inputLabel" :class="labelClass">
|
|
4
|
+
{{ label }}
|
|
5
|
+
</label>
|
|
6
|
+
|
|
7
|
+
<div class="flex items-start gap-4">
|
|
8
|
+
<span class="min-w-8 pt-2 text-right text-sm tabular-nums">{{ min }}</span>
|
|
9
|
+
<div class="relative min-w-0 flex-1 pb-7">
|
|
10
|
+
<el-slider
|
|
11
|
+
:id="rangeId"
|
|
12
|
+
:model-value="rangeValue"
|
|
13
|
+
:min="min"
|
|
14
|
+
:max="max"
|
|
15
|
+
:step="step"
|
|
16
|
+
:disabled="disabled"
|
|
17
|
+
:show-stops="showStops"
|
|
18
|
+
:show-tooltip="showTooltip"
|
|
19
|
+
range
|
|
20
|
+
@update:model-value="updateValue"
|
|
21
|
+
@change="$emit('change', $event)"
|
|
22
|
+
/>
|
|
23
|
+
<span
|
|
24
|
+
v-for="marker in selectedMarkers"
|
|
25
|
+
:key="marker.key"
|
|
26
|
+
class="absolute top-8 text-sm tabular-nums"
|
|
27
|
+
:class="marker.alignment"
|
|
28
|
+
:style="{ left: `${marker.position}%` }"
|
|
29
|
+
>
|
|
30
|
+
{{ marker.label }}
|
|
31
|
+
</span>
|
|
32
|
+
</div>
|
|
33
|
+
<span class="min-w-8 pt-2 text-sm tabular-nums">{{ max }}</span>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div :id="errorId" :class="theme.errorText" v-if="hasError && error !== true && error !== ''">
|
|
37
|
+
{{ error }}
|
|
38
|
+
</div>
|
|
39
|
+
<div :id="infoId" :class="theme.infoText" v-else-if="info != null">
|
|
40
|
+
{{ info }}
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</template>
|
|
44
|
+
|
|
45
|
+
<script>
|
|
46
|
+
import { ElSlider } from "element-plus";
|
|
47
|
+
import { K_INPUT_THEME } from "./themes/kInput.theme";
|
|
48
|
+
|
|
49
|
+
export default {
|
|
50
|
+
name: "kRange",
|
|
51
|
+
components: { ElSlider },
|
|
52
|
+
props: {
|
|
53
|
+
modelValue: {
|
|
54
|
+
type: Array,
|
|
55
|
+
default: () => [0, 100],
|
|
56
|
+
validator: (value) => value.length === 2,
|
|
57
|
+
},
|
|
58
|
+
min: { type: Number, default: 0 },
|
|
59
|
+
max: { type: Number, default: 100 },
|
|
60
|
+
step: {
|
|
61
|
+
type: Number,
|
|
62
|
+
default: 1,
|
|
63
|
+
validator: (value) => Number.isInteger(value) && value > 0,
|
|
64
|
+
},
|
|
65
|
+
label: { type: String, default: null },
|
|
66
|
+
info: { type: String, default: null },
|
|
67
|
+
error: { type: [String, Boolean], default: null },
|
|
68
|
+
disabled: { type: Boolean, default: false },
|
|
69
|
+
showStops: { type: Boolean, default: false },
|
|
70
|
+
showTooltip: { type: Boolean, default: true },
|
|
71
|
+
id: { type: String, default: null },
|
|
72
|
+
},
|
|
73
|
+
emits: ["update:modelValue", "change"],
|
|
74
|
+
data() {
|
|
75
|
+
return {
|
|
76
|
+
theme: K_INPUT_THEME,
|
|
77
|
+
generatedId: `range-${Math.random().toString(36).slice(2, 11)}`,
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
computed: {
|
|
81
|
+
rangeId() {
|
|
82
|
+
return this.id || this.generatedId;
|
|
83
|
+
},
|
|
84
|
+
errorId() {
|
|
85
|
+
return `${this.rangeId}-error`;
|
|
86
|
+
},
|
|
87
|
+
infoId() {
|
|
88
|
+
return `${this.rangeId}-info`;
|
|
89
|
+
},
|
|
90
|
+
rangeValue() {
|
|
91
|
+
const values = this.modelValue?.length === 2 ? this.modelValue : [this.min, this.max];
|
|
92
|
+
return values.map((value, index) => {
|
|
93
|
+
const fallback = index === 0 ? this.min : this.max;
|
|
94
|
+
const integer = Number.isFinite(Number(value)) ? Math.round(Number(value)) : fallback;
|
|
95
|
+
return Math.min(this.max, Math.max(this.min, integer));
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
selectedMarkers() {
|
|
99
|
+
if (this.rangeValue[0] === this.rangeValue[1]) {
|
|
100
|
+
return [this.createMarker(this.rangeValue[0], `${this.rangeValue[0]} – ${this.rangeValue[1]}`, "range")];
|
|
101
|
+
}
|
|
102
|
+
return [
|
|
103
|
+
this.createMarker(this.rangeValue[0], this.rangeValue[0], "from"),
|
|
104
|
+
this.createMarker(this.rangeValue[1], this.rangeValue[1], "to"),
|
|
105
|
+
];
|
|
106
|
+
},
|
|
107
|
+
hasError() {
|
|
108
|
+
return this.error != null && this.error !== false;
|
|
109
|
+
},
|
|
110
|
+
labelClass() {
|
|
111
|
+
if (this.hasError) return this.theme.labelError;
|
|
112
|
+
if (this.disabled) return this.theme.labelDisabled;
|
|
113
|
+
return this.theme.label;
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
methods: {
|
|
117
|
+
createMarker(value, label, key) {
|
|
118
|
+
const span = this.max - this.min;
|
|
119
|
+
const position = span === 0 ? 0 : ((value - this.min) / span) * 100;
|
|
120
|
+
let alignment = "-translate-x-1/2";
|
|
121
|
+
if (position <= 0) alignment = "translate-x-0";
|
|
122
|
+
if (position >= 100) alignment = "-translate-x-full";
|
|
123
|
+
return { key, label, position, alignment };
|
|
124
|
+
},
|
|
125
|
+
updateValue(value) {
|
|
126
|
+
this.$emit("update:modelValue", value.map((item) => Math.round(item)));
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
</script>
|