daisy-ui-kit 5.0.0-pre.27 → 5.0.0-pre.29
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/app/components/Range.vue +183 -43
- package/app/components/TextArea.vue +43 -1
- package/package.json +1 -1
package/app/components/Range.vue
CHANGED
|
@@ -1,61 +1,201 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
|
|
4
|
-
const props =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
4
|
+
const props = withDefaults(
|
|
5
|
+
defineProps<{
|
|
6
|
+
modelValue?: number | [number, number]
|
|
7
|
+
min?: number
|
|
8
|
+
max?: number
|
|
9
|
+
step?: number
|
|
10
|
+
disabled?: boolean
|
|
11
|
+
|
|
12
|
+
color?: string
|
|
13
|
+
neutral?: boolean
|
|
14
|
+
primary?: boolean
|
|
15
|
+
secondary?: boolean
|
|
16
|
+
accent?: boolean
|
|
17
|
+
success?: boolean
|
|
18
|
+
warning?: boolean
|
|
19
|
+
info?: boolean
|
|
20
|
+
error?: boolean
|
|
21
|
+
|
|
22
|
+
size?: 'xl' | 'lg' | 'md' | 'sm' | 'xs'
|
|
23
|
+
xl?: boolean
|
|
24
|
+
lg?: boolean
|
|
25
|
+
md?: boolean
|
|
26
|
+
sm?: boolean
|
|
27
|
+
xs?: boolean
|
|
28
|
+
}>(),
|
|
29
|
+
{
|
|
30
|
+
min: 0,
|
|
31
|
+
max: 100,
|
|
32
|
+
step: 1,
|
|
33
|
+
},
|
|
34
|
+
)
|
|
28
35
|
const emit = defineEmits(['update:modelValue'])
|
|
29
36
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
const isRange = computed(() => {
|
|
38
|
+
return Array.isArray(props.modelValue)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const singleValue = computed({
|
|
42
|
+
get: () => (isRange.value ? 0 : (props.modelValue as number)),
|
|
43
|
+
set: val => emit('update:modelValue', Number(val)),
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const lowValue = computed({
|
|
47
|
+
get: () => (isRange.value ? (props.modelValue as [number, number])[0] : 0),
|
|
48
|
+
set: val => {
|
|
49
|
+
const v = Number(val)
|
|
50
|
+
const high = (props.modelValue as [number, number])[1]
|
|
51
|
+
emit('update:modelValue', [Math.min(v, high), high])
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const highValue = computed({
|
|
56
|
+
get: () => (isRange.value ? (props.modelValue as [number, number])[1] : 100),
|
|
57
|
+
set: val => {
|
|
58
|
+
const v = Number(val)
|
|
59
|
+
const low = (props.modelValue as [number, number])[0]
|
|
60
|
+
emit('update:modelValue', [low, Math.max(v, low)])
|
|
61
|
+
},
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const rangeClasses = computed(() => ({
|
|
65
|
+
'range-neutral': props.neutral || props.color === 'neutral',
|
|
66
|
+
'range-primary': props.primary || props.color === 'primary',
|
|
67
|
+
'range-secondary': props.secondary || props.color === 'secondary',
|
|
68
|
+
'range-accent': props.accent || props.color === 'accent',
|
|
69
|
+
'range-success': props.success || props.color === 'success',
|
|
70
|
+
'range-info': props.info || props.color === 'info',
|
|
71
|
+
'range-warning': props.warning || props.color === 'warning',
|
|
72
|
+
'range-error': props.error || props.color === 'error',
|
|
73
|
+
'range-xl': props.xl || props.size === 'xl',
|
|
74
|
+
'range-lg': props.lg || props.size === 'lg',
|
|
75
|
+
'range-md': props.md || props.size === 'md',
|
|
76
|
+
'range-sm': props.sm || props.size === 'sm',
|
|
77
|
+
'range-xs': props.xs || props.size === 'xs',
|
|
78
|
+
}))
|
|
79
|
+
|
|
80
|
+
// Calculate percentage positions for the filled track
|
|
81
|
+
const lowPercent = computed(() => {
|
|
82
|
+
const range = props.max - props.min
|
|
83
|
+
return ((lowValue.value - props.min) / range) * 100
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const highPercent = computed(() => {
|
|
87
|
+
const range = props.max - props.min
|
|
88
|
+
return ((highValue.value - props.min) / range) * 100
|
|
33
89
|
})
|
|
34
90
|
</script>
|
|
35
91
|
|
|
36
92
|
<template>
|
|
93
|
+
<!-- Single value mode -->
|
|
37
94
|
<input
|
|
38
|
-
v-
|
|
95
|
+
v-if="!isRange"
|
|
96
|
+
v-model="singleValue"
|
|
39
97
|
type="range"
|
|
40
98
|
class="range"
|
|
41
|
-
:class="
|
|
42
|
-
'range-neutral': neutral || color === 'neutral',
|
|
43
|
-
'range-primary': primary || color === 'primary',
|
|
44
|
-
'range-secondary': secondary || color === 'secondary',
|
|
45
|
-
'range-accent': accent || color === 'accent',
|
|
46
|
-
'range-success': success || color === 'success',
|
|
47
|
-
'range-info': info || color === 'info',
|
|
48
|
-
'range-warning': warning || color === 'warning',
|
|
49
|
-
'range-error': error || color === 'error',
|
|
50
|
-
'range-xl': xl || size === 'xl',
|
|
51
|
-
'range-lg': lg || size === 'lg',
|
|
52
|
-
'range-md': md || size === 'md',
|
|
53
|
-
'range-sm': sm || size === 'sm',
|
|
54
|
-
'range-xs': xs || size === 'xs',
|
|
55
|
-
}"
|
|
99
|
+
:class="rangeClasses"
|
|
56
100
|
:min="min"
|
|
57
101
|
:max="max"
|
|
58
102
|
:step="step"
|
|
59
103
|
:disabled="disabled"
|
|
60
104
|
/>
|
|
105
|
+
|
|
106
|
+
<!-- Dual handle range mode -->
|
|
107
|
+
<div v-else class="range range-slider-wrapper" :class="rangeClasses">
|
|
108
|
+
<div class="range-slider-track" />
|
|
109
|
+
<div
|
|
110
|
+
class="range-slider-fill"
|
|
111
|
+
:style="{
|
|
112
|
+
left: `calc(${lowPercent}% + (var(--range-thumb-size, 1.5rem) / 2) - (${lowPercent} * var(--range-thumb-size, 1.5rem) / 100))`,
|
|
113
|
+
width: `calc(${highPercent - lowPercent}% - (${highPercent - lowPercent} * var(--range-thumb-size, 1.5rem) / 100))`,
|
|
114
|
+
}"
|
|
115
|
+
/>
|
|
116
|
+
<input
|
|
117
|
+
v-model="lowValue"
|
|
118
|
+
type="range"
|
|
119
|
+
class="range range-slider-input"
|
|
120
|
+
:class="rangeClasses"
|
|
121
|
+
:min="min"
|
|
122
|
+
:max="max"
|
|
123
|
+
:step="step"
|
|
124
|
+
:disabled="disabled"
|
|
125
|
+
/>
|
|
126
|
+
<input
|
|
127
|
+
v-model="highValue"
|
|
128
|
+
type="range"
|
|
129
|
+
class="range range-slider-input"
|
|
130
|
+
:class="rangeClasses"
|
|
131
|
+
:min="min"
|
|
132
|
+
:max="max"
|
|
133
|
+
:step="step"
|
|
134
|
+
:disabled="disabled"
|
|
135
|
+
/>
|
|
136
|
+
</div>
|
|
61
137
|
</template>
|
|
138
|
+
|
|
139
|
+
<style>
|
|
140
|
+
.range-slider-wrapper {
|
|
141
|
+
position: relative;
|
|
142
|
+
width: 100%;
|
|
143
|
+
height: var(--range-thumb-size, 1.5rem);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.range-slider-track {
|
|
147
|
+
position: absolute;
|
|
148
|
+
top: 50%;
|
|
149
|
+
left: 0;
|
|
150
|
+
right: 0;
|
|
151
|
+
height: calc(var(--range-thumb-size, 1.5rem) / 3);
|
|
152
|
+
transform: translateY(-50%);
|
|
153
|
+
background: color-mix(in oklab, currentColor 10%, transparent);
|
|
154
|
+
border-radius: var(--radius-selector, 1rem);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.range-slider-fill {
|
|
158
|
+
position: absolute;
|
|
159
|
+
top: 50%;
|
|
160
|
+
height: var(--range-thumb-size, 1.5rem);
|
|
161
|
+
transform: translateY(-50%);
|
|
162
|
+
background: currentColor;
|
|
163
|
+
border-radius: 0;
|
|
164
|
+
z-index: 1;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.range-slider-input {
|
|
168
|
+
position: absolute;
|
|
169
|
+
top: 0;
|
|
170
|
+
left: 0;
|
|
171
|
+
width: 100%;
|
|
172
|
+
height: 100%;
|
|
173
|
+
pointer-events: none;
|
|
174
|
+
background: transparent;
|
|
175
|
+
--range-fill: 0 !important;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* Hide both tracks - we draw our own */
|
|
179
|
+
.range-slider-input::-webkit-slider-runnable-track {
|
|
180
|
+
background: transparent !important;
|
|
181
|
+
box-shadow: none !important;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.range-slider-input::-moz-range-track {
|
|
185
|
+
background: transparent !important;
|
|
186
|
+
box-shadow: none !important;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* Enable pointer events only on thumbs */
|
|
190
|
+
.range-slider-input::-webkit-slider-thumb {
|
|
191
|
+
pointer-events: auto;
|
|
192
|
+
position: relative;
|
|
193
|
+
z-index: 3;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.range-slider-input::-moz-range-thumb {
|
|
197
|
+
pointer-events: auto;
|
|
198
|
+
position: relative;
|
|
199
|
+
z-index: 3;
|
|
200
|
+
}
|
|
201
|
+
</style>
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { nextTick, onMounted, ref, watch } from 'vue'
|
|
3
|
+
|
|
2
4
|
const props = withDefaults(
|
|
3
5
|
defineProps<{
|
|
4
6
|
modelValue?: string
|
|
5
7
|
placeholder?: string
|
|
6
8
|
type?: 'text' | 'phone' | 'email' | 'search'
|
|
9
|
+
rows?: number
|
|
10
|
+
autoExpand?: boolean
|
|
7
11
|
|
|
8
12
|
color?: string
|
|
9
13
|
neutral?: boolean
|
|
@@ -28,15 +32,48 @@ const props = withDefaults(
|
|
|
28
32
|
}>(),
|
|
29
33
|
{
|
|
30
34
|
type: 'text',
|
|
35
|
+
rows: 2,
|
|
31
36
|
},
|
|
32
37
|
)
|
|
33
38
|
defineEmits(['update:modelValue'])
|
|
39
|
+
|
|
40
|
+
const textareaRef = ref<HTMLTextAreaElement | null>(null)
|
|
41
|
+
|
|
42
|
+
let minHeight = 0
|
|
43
|
+
|
|
44
|
+
function adjustHeight() {
|
|
45
|
+
if (!props.autoExpand || !textareaRef.value) return
|
|
46
|
+
const el = textareaRef.value
|
|
47
|
+
|
|
48
|
+
// Capture the initial rendered height as minimum (respects rows attribute)
|
|
49
|
+
if (minHeight === 0) {
|
|
50
|
+
minHeight = el.offsetHeight
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
el.style.height = 'auto'
|
|
54
|
+
el.style.height = `${Math.max(el.scrollHeight, minHeight)}px`
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
watch(
|
|
58
|
+
() => props.modelValue,
|
|
59
|
+
() => {
|
|
60
|
+
nextTick(adjustHeight)
|
|
61
|
+
},
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
onMounted(() => {
|
|
65
|
+
if (props.autoExpand) {
|
|
66
|
+
nextTick(adjustHeight)
|
|
67
|
+
}
|
|
68
|
+
})
|
|
34
69
|
</script>
|
|
35
70
|
|
|
36
71
|
<template>
|
|
37
72
|
<textarea
|
|
73
|
+
ref="textareaRef"
|
|
38
74
|
:value="modelValue"
|
|
39
75
|
:type="type"
|
|
76
|
+
:rows="rows"
|
|
40
77
|
:placeholder="placeholder"
|
|
41
78
|
:disabled="disabled"
|
|
42
79
|
class="textarea"
|
|
@@ -59,6 +96,11 @@ defineEmits(['update:modelValue'])
|
|
|
59
96
|
'textarea-sm': props.sm || props.size === 'sm',
|
|
60
97
|
'textarea-xs': props.xs || props.size === 'xs',
|
|
61
98
|
}"
|
|
62
|
-
@input="
|
|
99
|
+
@input="
|
|
100
|
+
event => {
|
|
101
|
+
$emit('update:modelValue', (event.target as HTMLTextAreaElement).value)
|
|
102
|
+
adjustHeight()
|
|
103
|
+
}
|
|
104
|
+
"
|
|
63
105
|
/>
|
|
64
106
|
</template>
|