@umbra.ui/core 0.1.17 → 0.1.19
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/components/controls/Button/Button.vue +417 -0
- package/dist/components/controls/Button/README.md +348 -0
- package/dist/components/controls/Button/theme.css +200 -0
- package/dist/components/controls/Checkbox/Checkbox.vue +164 -0
- package/dist/components/controls/Checkbox/README.md +441 -0
- package/dist/components/controls/Checkbox/theme.css +36 -0
- package/dist/components/controls/Dropdown/Dropdown.vue +476 -0
- package/dist/components/controls/Dropdown/README.md +370 -0
- package/dist/components/controls/Dropdown/theme.css +50 -0
- package/dist/components/controls/Dropdown/types.ts +6 -0
- package/dist/components/controls/IconButton/IconButton.vue +267 -0
- package/dist/components/controls/IconButton/README.md +502 -0
- package/dist/components/controls/IconButton/theme.css +89 -0
- package/dist/components/controls/Radio/README.md +591 -0
- package/dist/components/controls/Radio/Radio.vue +89 -0
- package/dist/components/controls/Radio/theme.css +14 -0
- package/dist/components/controls/RangeSlider/README.md +608 -0
- package/dist/components/controls/RangeSlider/RangeSlider.vue +535 -0
- package/dist/components/controls/RangeSlider/theme.css +80 -0
- package/dist/components/controls/SegmentedControl/README.md +587 -0
- package/dist/components/controls/SegmentedControl/SegmentedControl.vue +284 -0
- package/dist/components/controls/SegmentedControl/theme.css +60 -0
- package/dist/components/controls/SegmentedControl/types.ts +5 -0
- package/dist/components/controls/Slider/README.md +627 -0
- package/dist/components/controls/Slider/Slider.vue +260 -0
- package/dist/components/controls/Slider/theme.css +74 -0
- package/dist/components/controls/Stepper/README.md +601 -0
- package/dist/components/controls/Stepper/Stepper.vue +103 -0
- package/dist/components/controls/Stepper/theme.css +53 -0
- package/dist/components/controls/Switch/README.md +667 -0
- package/dist/components/controls/Switch/Switch.vue +127 -0
- package/dist/components/controls/Switch/theme.css +42 -0
- package/dist/components/dialogs/Alert/Alert.vue +218 -0
- package/dist/components/dialogs/Alert/README.md +450 -0
- package/dist/components/dialogs/Alert/theme.css +44 -0
- package/dist/components/dialogs/Alert/types.ts +11 -0
- package/dist/components/dialogs/Toast/README.md +522 -0
- package/dist/components/dialogs/Toast/Toast.vue +296 -0
- package/dist/components/dialogs/Toast/ToastContainer.vue +330 -0
- package/dist/components/dialogs/Toast/theme.css +44 -0
- package/dist/components/dialogs/Toast/types.ts +46 -0
- package/dist/components/dialogs/Toast/useToast.ts +127 -0
- package/dist/components/indicators/ProgressBar/ProgressBar.vue +98 -0
- package/dist/components/indicators/ProgressBar/README.md +744 -0
- package/dist/components/indicators/ProgressBar/theme.css +36 -0
- package/dist/components/indicators/Tooltip/README.md +723 -0
- package/dist/components/indicators/Tooltip/TooltipProvider.vue +142 -0
- package/dist/components/indicators/Tooltip/theme.css +18 -0
- package/dist/components/indicators/Tooltip/tooltip.ts +48 -0
- package/dist/components/indicators/Tooltip/types.ts +15 -0
- package/dist/components/indicators/Tooltip/useTooltip.ts +71 -0
- package/dist/components/inputs/AutogrowTextView/AutogrowTextView.vue +110 -0
- package/dist/components/inputs/AutogrowTextView/README.md +643 -0
- package/dist/components/inputs/AutogrowTextView/theme.css +28 -0
- package/dist/components/inputs/InputCard/InputCard.vue +600 -0
- package/dist/components/inputs/InputCard/README.md +636 -0
- package/dist/components/inputs/InputEmail/InputEmail.vue +698 -0
- package/dist/components/inputs/InputEmail/README.md +764 -0
- package/dist/components/inputs/InputNumber/InputNumber.vue +300 -0
- package/dist/components/inputs/InputNumber/README.md +749 -0
- package/dist/components/inputs/InputPhone/InputPhone.vue +645 -0
- package/dist/components/inputs/InputPhone/README.md +636 -0
- package/dist/components/inputs/InputSecure/InputSecure.vue +646 -0
- package/dist/components/inputs/InputSecure/README.md +771 -0
- package/dist/components/inputs/InputText/InputText.vue +225 -0
- package/dist/components/inputs/InputText/README.md +844 -0
- package/dist/components/inputs/OTP/OTP.vue +349 -0
- package/dist/components/inputs/OTP/README.md +736 -0
- package/dist/components/inputs/OTP/theme.css +50 -0
- package/dist/components/inputs/StringCapture/README.md +718 -0
- package/dist/components/inputs/StringCapture/StringCapture.vue +315 -0
- package/dist/components/inputs/StringCapture/theme.css +86 -0
- package/dist/components/inputs/Tags/README.md +897 -0
- package/dist/components/inputs/Tags/TagBar.vue +793 -0
- package/dist/components/inputs/Tags/TagCreation.vue +219 -0
- package/dist/components/inputs/Tags/TagPicker.vue +380 -0
- package/dist/components/inputs/Tags/tag-bar-styles.ts +354 -0
- package/dist/components/inputs/Tags/theme.css +121 -0
- package/dist/components/inputs/Tags/types.ts +346 -0
- package/dist/components/inputs/search/README.md +759 -0
- package/dist/components/inputs/search/SearchBar.vue +394 -0
- package/dist/components/inputs/search/SearchResults.vue +310 -0
- package/dist/components/inputs/search/theme.css +187 -0
- package/dist/components/inputs/search/types.ts +8 -0
- package/dist/components/inputs/theme.css +102 -0
- package/dist/components/menus/ActionMenu/ActionMenu.vue +383 -0
- package/dist/components/menus/ActionMenu/README.md +825 -0
- package/dist/components/menus/ActionMenu/theme.css +93 -0
- package/dist/components/models/Popover/Popover.vue +551 -0
- package/dist/components/models/Popover/README.md +885 -0
- package/dist/components/models/Popover/theme.css +52 -0
- package/dist/components/models/Sheet/README.md +1159 -0
- package/dist/components/models/Sheet/Sheet.vue +465 -0
- package/dist/components/models/Sheet/theme.css +72 -0
- package/dist/components/models/Sidebar/README.md +1228 -0
- package/dist/components/models/Sidebar/Sidebar.vue +480 -0
- package/dist/components/models/Sidebar/theme.css +90 -0
- package/dist/components/navigation/adaptive/AdaptiveLayout.vue +779 -0
- package/dist/components/navigation/adaptive/AdaptiveLayoutBreadcrumbs.vue +192 -0
- package/dist/components/navigation/adaptive/AdaptiveLayoutMenuButton.vue +149 -0
- package/dist/components/navigation/adaptive/README.md +768 -0
- package/dist/components/navigation/adaptive/types.ts +19 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.ts +89 -0
- package/dist/components/navigation/adaptive/useBreakpoints.ts +41 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.ts +214 -0
- package/dist/components/navigation/adaptive/useViewAnimation.ts +721 -0
- package/dist/components/navigation/adaptive/useViewResize.ts +211 -0
- package/dist/components/navigation/navstack/NavigationStack.vue +180 -0
- package/dist/components/navigation/navstack/README.md +994 -0
- package/dist/components/navigation/navstack/useNavigationStack.ts +164 -0
- package/dist/components/navigation/slideover/README.md +1275 -0
- package/dist/components/navigation/slideover/SlideoverController.vue +287 -0
- package/dist/components/navigation/slideover/useSlideoverController.ts +320 -0
- package/dist/components/navigation/splitview/README.md +1115 -0
- package/dist/components/navigation/splitview/SplitViewController.vue +176 -0
- package/dist/components/navigation/splitview/useSplitViewController.ts +388 -0
- package/dist/components/navigation/tabcontroller/README.md +919 -0
- package/dist/components/navigation/tabcontroller/TabController.vue +307 -0
- package/dist/components/navigation/tabcontroller/TabItem.vue +57 -0
- package/dist/components/navigation/tabcontroller/types.ts +24 -0
- package/dist/components/navigation/tabcontroller/useTabController.ts +18 -0
- package/dist/components/navigation/theme.css +91 -0
- package/dist/components/navigation/types.ts +7 -0
- package/dist/components/pickers/CollectionPicker/CollectionPicker.vue +398 -0
- package/dist/components/pickers/CollectionPicker/README.md +1115 -0
- package/dist/components/pickers/CollectionPicker/theme.css +14 -0
- package/dist/components/pickers/CollectionPicker/types.ts +11 -0
- package/dist/components/pickers/ColorPicker/ColorPicker.vue +376 -0
- package/dist/components/pickers/ColorPicker/README.md +1439 -0
- package/dist/components/pickers/ColorPicker/colors.ts +299 -0
- package/dist/components/pickers/ColorPicker/theme.css +32 -0
- package/dist/components/pickers/DatePicker/DatePicker.vue +660 -0
- package/dist/components/pickers/DatePicker/README.md +1195 -0
- package/dist/components/pickers/DatePicker/theme.css +22 -0
- package/dist/components/pickers/FilePicker/FilePicker.vue +534 -0
- package/dist/components/pickers/FilePicker/README.md +1542 -0
- package/dist/components/pickers/FilePicker/theme.css +48 -0
- package/dist/components/pickers/FilePicker/types.ts +10 -0
- package/dist/components/pickers/IconPicker/IconPicker.vue +327 -0
- package/dist/components/pickers/IconPicker/README.md +1161 -0
- package/dist/components/pickers/IconPicker/theme.css +28 -0
- package/dist/components/pickers/theme.css +82 -0
- package/dist/components/views/MarkdownViewer/MarkdownViewer.vue +442 -0
- package/dist/components/views/MarkdownViewer/README.md +833 -0
- package/dist/components/views/MarkdownViewer/theme.css +130 -0
- package/package.json +4 -3
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, computed, watch } from "vue";
|
|
3
|
+
import "./theme.css";
|
|
4
|
+
|
|
5
|
+
export interface Props {
|
|
6
|
+
sliderStyle?: "default" | "capline" | "capsule";
|
|
7
|
+
min?: number;
|
|
8
|
+
max?: number;
|
|
9
|
+
minValue: number;
|
|
10
|
+
maxValue: number;
|
|
11
|
+
tickInterval?: number;
|
|
12
|
+
showTickLabels?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
16
|
+
sliderStyle: "default",
|
|
17
|
+
min: 0,
|
|
18
|
+
max: 100,
|
|
19
|
+
minValue: 25,
|
|
20
|
+
maxValue: 75,
|
|
21
|
+
tickInterval: 10,
|
|
22
|
+
showTickLabels: false,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const emit = defineEmits<{
|
|
26
|
+
"update:minValue": [value: number];
|
|
27
|
+
"update:maxValue": [value: number];
|
|
28
|
+
}>();
|
|
29
|
+
|
|
30
|
+
const minProgress = ref(props.minValue);
|
|
31
|
+
const maxProgress = ref(props.maxValue);
|
|
32
|
+
const activeThumb = ref<"min" | "max" | null>(null);
|
|
33
|
+
const showMinHud = ref(false);
|
|
34
|
+
const showMaxHud = ref(false);
|
|
35
|
+
const trackRef = ref<HTMLDivElement>();
|
|
36
|
+
let hideMinTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
37
|
+
let hideMaxTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
38
|
+
|
|
39
|
+
// Computed properties for thumb positions
|
|
40
|
+
const minThumbPosition = computed(() => `${minProgress.value}%`);
|
|
41
|
+
const maxThumbPosition = computed(() => `${maxProgress.value}%`);
|
|
42
|
+
|
|
43
|
+
// Computed property for the range track
|
|
44
|
+
const rangeStyle = computed(() => ({
|
|
45
|
+
left: `${minProgress.value}%`,
|
|
46
|
+
width: `${maxProgress.value - minProgress.value}%`,
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
// Convert percentage to actual value
|
|
50
|
+
const percentageToValue = (percentage: number) => {
|
|
51
|
+
const range = props.max - props.min;
|
|
52
|
+
return props.min + (percentage / 100) * range;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Convert value to percentage
|
|
56
|
+
const valueToPercentage = (value: number) => {
|
|
57
|
+
const range = props.max - props.min;
|
|
58
|
+
return ((value - props.min) / range) * 100;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Initialize progress from props
|
|
62
|
+
minProgress.value = valueToPercentage(props.minValue);
|
|
63
|
+
maxProgress.value = valueToPercentage(props.maxValue);
|
|
64
|
+
|
|
65
|
+
// Watch for changes to minValue and maxValue props
|
|
66
|
+
watch(
|
|
67
|
+
() => [props.minValue, props.maxValue],
|
|
68
|
+
([newMinValue, newMaxValue]) => {
|
|
69
|
+
minProgress.value = valueToPercentage(newMinValue);
|
|
70
|
+
maxProgress.value = valueToPercentage(newMaxValue);
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const updateProgress = (
|
|
75
|
+
event: MouseEvent | TouchEvent,
|
|
76
|
+
thumbType: "min" | "max"
|
|
77
|
+
) => {
|
|
78
|
+
if (!trackRef.value) return;
|
|
79
|
+
|
|
80
|
+
const rect = trackRef.value.getBoundingClientRect();
|
|
81
|
+
const clientX = "touches" in event ? event.touches[0].clientX : event.clientX;
|
|
82
|
+
const x = clientX - rect.left;
|
|
83
|
+
const percentage = (x / rect.width) * 100;
|
|
84
|
+
const clampedPercentage = Math.max(0, Math.min(100, percentage));
|
|
85
|
+
|
|
86
|
+
if (thumbType === "min") {
|
|
87
|
+
// Ensure min doesn't exceed max
|
|
88
|
+
minProgress.value = Math.min(clampedPercentage, maxProgress.value);
|
|
89
|
+
emit("update:minValue", percentageToValue(minProgress.value));
|
|
90
|
+
} else {
|
|
91
|
+
// Ensure max doesn't go below min
|
|
92
|
+
maxProgress.value = Math.max(clampedPercentage, minProgress.value);
|
|
93
|
+
emit("update:maxValue", percentageToValue(maxProgress.value));
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const getClosestThumb = (event: MouseEvent | TouchEvent): "min" | "max" => {
|
|
98
|
+
if (!trackRef.value) return "min";
|
|
99
|
+
|
|
100
|
+
const rect = trackRef.value.getBoundingClientRect();
|
|
101
|
+
const clientX = "touches" in event ? event.touches[0].clientX : event.clientX;
|
|
102
|
+
const x = clientX - rect.left;
|
|
103
|
+
const percentage = (x / rect.width) * 100;
|
|
104
|
+
|
|
105
|
+
// Calculate distances to each thumb
|
|
106
|
+
const distToMin = Math.abs(percentage - minProgress.value);
|
|
107
|
+
const distToMax = Math.abs(percentage - maxProgress.value);
|
|
108
|
+
|
|
109
|
+
// If thumbs are overlapping, prefer the one that would increase the range
|
|
110
|
+
if (Math.abs(minProgress.value - maxProgress.value) < 5) {
|
|
111
|
+
return percentage < minProgress.value ? "min" : "max";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return distToMin < distToMax ? "min" : "max";
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const handleMouseDown = (
|
|
118
|
+
event: MouseEvent | TouchEvent,
|
|
119
|
+
thumbType?: "min" | "max"
|
|
120
|
+
) => {
|
|
121
|
+
event.preventDefault();
|
|
122
|
+
event.stopPropagation();
|
|
123
|
+
|
|
124
|
+
// Determine which thumb to move
|
|
125
|
+
const thumb = thumbType || getClosestThumb(event);
|
|
126
|
+
activeThumb.value = thumb;
|
|
127
|
+
|
|
128
|
+
// Show appropriate HUD
|
|
129
|
+
if (thumb === "min") {
|
|
130
|
+
showMinHud.value = true;
|
|
131
|
+
if (hideMinTimeout) clearTimeout(hideMinTimeout);
|
|
132
|
+
} else {
|
|
133
|
+
showMaxHud.value = true;
|
|
134
|
+
if (hideMaxTimeout) clearTimeout(hideMaxTimeout);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
updateProgress(event, thumb);
|
|
138
|
+
|
|
139
|
+
const handleMove = (e: MouseEvent | TouchEvent) => {
|
|
140
|
+
if (activeThumb.value) {
|
|
141
|
+
updateProgress(e, activeThumb.value);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const handleUp = () => {
|
|
146
|
+
const wasActiveThumb = activeThumb.value;
|
|
147
|
+
activeThumb.value = null;
|
|
148
|
+
|
|
149
|
+
// Hide appropriate HUD after delay
|
|
150
|
+
if (wasActiveThumb === "min") {
|
|
151
|
+
hideMinTimeout = setTimeout(() => {
|
|
152
|
+
showMinHud.value = false;
|
|
153
|
+
}, 500);
|
|
154
|
+
} else if (wasActiveThumb === "max") {
|
|
155
|
+
hideMaxTimeout = setTimeout(() => {
|
|
156
|
+
showMaxHud.value = false;
|
|
157
|
+
}, 500);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
document.removeEventListener("mousemove", handleMove);
|
|
161
|
+
document.removeEventListener("touchmove", handleMove);
|
|
162
|
+
document.removeEventListener("mouseup", handleUp);
|
|
163
|
+
document.removeEventListener("touchend", handleUp);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
document.addEventListener("mousemove", handleMove);
|
|
167
|
+
document.addEventListener("touchmove", handleMove);
|
|
168
|
+
document.addEventListener("mouseup", handleUp);
|
|
169
|
+
document.addEventListener("touchend", handleUp);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Computed values for display
|
|
173
|
+
const minDisplayValue = computed(() =>
|
|
174
|
+
Math.round(percentageToValue(minProgress.value))
|
|
175
|
+
);
|
|
176
|
+
const maxDisplayValue = computed(() =>
|
|
177
|
+
Math.round(percentageToValue(maxProgress.value))
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
// Generate tick marks
|
|
181
|
+
const ticks = computed(() => {
|
|
182
|
+
if (!props.tickInterval || props.tickInterval <= 0) return [];
|
|
183
|
+
|
|
184
|
+
const ticksArray = [];
|
|
185
|
+
const range = props.max - props.min;
|
|
186
|
+
|
|
187
|
+
// Start from min and add ticks at intervals
|
|
188
|
+
for (let value = props.min; value <= props.max; value += props.tickInterval) {
|
|
189
|
+
const percentage = ((value - props.min) / range) * 100;
|
|
190
|
+
ticksArray.push({
|
|
191
|
+
value,
|
|
192
|
+
percentage,
|
|
193
|
+
position: `${percentage}%`,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Ensure the max value is included if it's not already
|
|
198
|
+
const lastTick = ticksArray[ticksArray.length - 1];
|
|
199
|
+
if (lastTick && lastTick.value < props.max) {
|
|
200
|
+
ticksArray.push({
|
|
201
|
+
value: props.max,
|
|
202
|
+
percentage: 100,
|
|
203
|
+
position: "100%",
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return ticksArray;
|
|
208
|
+
});
|
|
209
|
+
</script>
|
|
210
|
+
|
|
211
|
+
<template>
|
|
212
|
+
<div :class="[$style.container, $style[sliderStyle]]">
|
|
213
|
+
<p :class="[$style.label, 'footnote']">{{ min }}</p>
|
|
214
|
+
<div :class="$style.sliderWrapper">
|
|
215
|
+
<div
|
|
216
|
+
ref="trackRef"
|
|
217
|
+
:class="$style.track"
|
|
218
|
+
@mousedown="handleMouseDown"
|
|
219
|
+
@touchstart="handleMouseDown"
|
|
220
|
+
>
|
|
221
|
+
<!-- Tick marks -->
|
|
222
|
+
<div v-if="tickInterval > 0" :class="$style.ticks">
|
|
223
|
+
<div
|
|
224
|
+
v-for="tick in ticks"
|
|
225
|
+
:key="tick.value"
|
|
226
|
+
:class="$style.tick"
|
|
227
|
+
:style="{ left: tick.position }"
|
|
228
|
+
/>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<!-- Range highlight (render before thumbs so thumbs appear above without z-index) -->
|
|
232
|
+
<div :class="$style.progress" :style="rangeStyle"></div>
|
|
233
|
+
|
|
234
|
+
<!-- Thumbs: render active thumb last so it appears on top without z-index -->
|
|
235
|
+
<template v-if="activeThumb === 'min'">
|
|
236
|
+
<!-- Max then Min (Min on top) -->
|
|
237
|
+
<div
|
|
238
|
+
:class="[$style.thumb]"
|
|
239
|
+
:style="{ '--progress': maxProgress + '%' }"
|
|
240
|
+
@mousedown.stop="(e) => handleMouseDown(e, 'max')"
|
|
241
|
+
@touchstart.stop="(e) => handleMouseDown(e, 'max')"
|
|
242
|
+
>
|
|
243
|
+
<div :class="[$style.hud, { [$style.visible]: showMaxHud }]">
|
|
244
|
+
<p class="footnote">{{ maxDisplayValue }}</p>
|
|
245
|
+
</div>
|
|
246
|
+
</div>
|
|
247
|
+
<div
|
|
248
|
+
:class="[$style.thumb, $style.active]"
|
|
249
|
+
:style="{ '--progress': minProgress + '%' }"
|
|
250
|
+
@mousedown.stop="(e) => handleMouseDown(e, 'min')"
|
|
251
|
+
@touchstart.stop="(e) => handleMouseDown(e, 'min')"
|
|
252
|
+
>
|
|
253
|
+
<div :class="[$style.hud, { [$style.visible]: showMinHud }]">
|
|
254
|
+
<p class="footnote">{{ minDisplayValue }}</p>
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
</template>
|
|
258
|
+
<template v-else-if="activeThumb === 'max'">
|
|
259
|
+
<!-- Min then Max (Max on top) -->
|
|
260
|
+
<div
|
|
261
|
+
:class="[$style.thumb]"
|
|
262
|
+
:style="{ '--progress': minProgress + '%' }"
|
|
263
|
+
@mousedown.stop="(e) => handleMouseDown(e, 'min')"
|
|
264
|
+
@touchstart.stop="(e) => handleMouseDown(e, 'min')"
|
|
265
|
+
>
|
|
266
|
+
<div :class="[$style.hud, { [$style.visible]: showMinHud }]">
|
|
267
|
+
<p class="footnote">{{ minDisplayValue }}</p>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
<div
|
|
271
|
+
:class="[$style.thumb, $style.active]"
|
|
272
|
+
:style="{ '--progress': maxProgress + '%' }"
|
|
273
|
+
@mousedown.stop="(e) => handleMouseDown(e, 'max')"
|
|
274
|
+
@touchstart.stop="(e) => handleMouseDown(e, 'max')"
|
|
275
|
+
>
|
|
276
|
+
<div :class="[$style.hud, { [$style.visible]: showMaxHud }]">
|
|
277
|
+
<p class="footnote">{{ maxDisplayValue }}</p>
|
|
278
|
+
</div>
|
|
279
|
+
</div>
|
|
280
|
+
</template>
|
|
281
|
+
<template v-else>
|
|
282
|
+
<!-- Default order: Min then Max; neither active -->
|
|
283
|
+
<div
|
|
284
|
+
:class="[$style.thumb]"
|
|
285
|
+
:style="{ '--progress': minProgress + '%' }"
|
|
286
|
+
@mousedown.stop="(e) => handleMouseDown(e, 'min')"
|
|
287
|
+
@touchstart.stop="(e) => handleMouseDown(e, 'min')"
|
|
288
|
+
>
|
|
289
|
+
<div :class="[$style.hud, { [$style.visible]: showMinHud }]">
|
|
290
|
+
<p class="footnote">{{ minDisplayValue }}</p>
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
<div
|
|
294
|
+
:class="[$style.thumb]"
|
|
295
|
+
:style="{ '--progress': maxProgress + '%' }"
|
|
296
|
+
@mousedown.stop="(e) => handleMouseDown(e, 'max')"
|
|
297
|
+
@touchstart.stop="(e) => handleMouseDown(e, 'max')"
|
|
298
|
+
>
|
|
299
|
+
<div :class="[$style.hud, { [$style.visible]: showMaxHud }]">
|
|
300
|
+
<p class="footnote">{{ maxDisplayValue }}</p>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
</template>
|
|
304
|
+
</div>
|
|
305
|
+
|
|
306
|
+
<!-- Tick labels -->
|
|
307
|
+
<div v-if="showTickLabels && tickInterval > 0" :class="$style.tickLabels">
|
|
308
|
+
<span
|
|
309
|
+
v-for="tick in ticks"
|
|
310
|
+
:key="`label-${tick.value}`"
|
|
311
|
+
:class="$style.tickLabel"
|
|
312
|
+
:style="{ left: tick.position }"
|
|
313
|
+
>
|
|
314
|
+
{{ tick.value }}
|
|
315
|
+
</span>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
<p :class="[$style.label, 'footnote']">{{ max }}</p>
|
|
319
|
+
</div>
|
|
320
|
+
</template>
|
|
321
|
+
|
|
322
|
+
<style module>
|
|
323
|
+
.container {
|
|
324
|
+
display: flex;
|
|
325
|
+
align-items: center;
|
|
326
|
+
gap: 0.47rem;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.label {
|
|
330
|
+
color: var(--rangeslider-label-color);
|
|
331
|
+
opacity: 1;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.track {
|
|
335
|
+
position: relative;
|
|
336
|
+
top: 0.59rem;
|
|
337
|
+
min-width: 11.76rem;
|
|
338
|
+
width: 100%;
|
|
339
|
+
border-radius: 999px;
|
|
340
|
+
cursor: default;
|
|
341
|
+
user-select: none;
|
|
342
|
+
}
|
|
343
|
+
.container.default .track {
|
|
344
|
+
height: 0.24rem;
|
|
345
|
+
background-color: var(--rangeslider-track-default-bg);
|
|
346
|
+
}
|
|
347
|
+
.container.capsule .track {
|
|
348
|
+
background-color: transparent;
|
|
349
|
+
height: 1.18rem;
|
|
350
|
+
border: 0.12rem solid var(--rangeslider-track-capsule-border);
|
|
351
|
+
}
|
|
352
|
+
.container.capline .track {
|
|
353
|
+
height: 0.88rem;
|
|
354
|
+
background-color: var(--rangeslider-track-capline-bg);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.thumb {
|
|
358
|
+
position: absolute;
|
|
359
|
+
top: 50%;
|
|
360
|
+
transform: translate(-50%, -50%);
|
|
361
|
+
cursor: grab;
|
|
362
|
+
transition: transform 0.1s ease;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.thumb.active {
|
|
366
|
+
cursor: grabbing;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.container.default .thumb {
|
|
370
|
+
background-color: var(--rangeslider-thumb-default-bg);
|
|
371
|
+
width: 0.82rem;
|
|
372
|
+
height: 0.82rem;
|
|
373
|
+
border-radius: 50%;
|
|
374
|
+
left: var(--progress);
|
|
375
|
+
}
|
|
376
|
+
.container.default .thumb.active {
|
|
377
|
+
transform: translate(-50%, -50%) scale(1.2);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.container.capsule .thumb {
|
|
381
|
+
background-color: var(--rangeslider-thumb-capsule-bg);
|
|
382
|
+
width: 1rem;
|
|
383
|
+
height: 1rem;
|
|
384
|
+
border-radius: 50%;
|
|
385
|
+
border: 0.12rem solid var(--rangeslider-thumb-capsule-border);
|
|
386
|
+
left: var(--progress);
|
|
387
|
+
}
|
|
388
|
+
.container.capsule .thumb.active {
|
|
389
|
+
transform: translate(-50%, -50%) scale(1.15);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.container.capline .thumb {
|
|
393
|
+
background-color: var(--rangeslider-thumb-capline-bg);
|
|
394
|
+
width: 0.29rem;
|
|
395
|
+
height: 1.35rem;
|
|
396
|
+
border-radius: 999px;
|
|
397
|
+
left: var(--progress);
|
|
398
|
+
}
|
|
399
|
+
.container.capline .thumb.active {
|
|
400
|
+
transform: translate(-50%, -50%) scale(1.1, 1.05);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.progress {
|
|
404
|
+
height: 100%;
|
|
405
|
+
border-radius: 999px;
|
|
406
|
+
position: absolute;
|
|
407
|
+
top: 0;
|
|
408
|
+
}
|
|
409
|
+
.container.default .progress {
|
|
410
|
+
background-color: var(--rangeslider-progress-default-bg);
|
|
411
|
+
}
|
|
412
|
+
.container.capsule .progress {
|
|
413
|
+
background-color: var(--rangeslider-progress-capsule-bg);
|
|
414
|
+
border-top: 0.24rem solid var(--rangeslider-progress-capsule-border-top);
|
|
415
|
+
border-bottom: 0.24rem solid var(--rangeslider-progress-capsule-border-bottom);
|
|
416
|
+
}
|
|
417
|
+
.container.capline .progress {
|
|
418
|
+
background-color: var(--rangeslider-progress-capline-bg);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.hud {
|
|
422
|
+
position: absolute;
|
|
423
|
+
padding: 0.24rem;
|
|
424
|
+
border-radius: 0.24rem;
|
|
425
|
+
left: 50%;
|
|
426
|
+
transform: translateX(-50%);
|
|
427
|
+
white-space: nowrap;
|
|
428
|
+
opacity: 0;
|
|
429
|
+
transition: opacity 0.2s ease;
|
|
430
|
+
display: flex;
|
|
431
|
+
align-items: center;
|
|
432
|
+
justify-content: center;
|
|
433
|
+
pointer-events: none;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.container.default .hud {
|
|
437
|
+
bottom: calc(100% + 0.29rem);
|
|
438
|
+
background-color: var(--rangeslider-hud-default-bg);
|
|
439
|
+
}
|
|
440
|
+
.container.capsule .hud {
|
|
441
|
+
bottom: calc(100% + 0.59rem);
|
|
442
|
+
background-color: var(--rangeslider-hud-capsule-bg);
|
|
443
|
+
border-radius: 999px;
|
|
444
|
+
min-width: 2rem;
|
|
445
|
+
}
|
|
446
|
+
.container.capline .hud {
|
|
447
|
+
bottom: calc(100% + 0.59rem);
|
|
448
|
+
background-color: var(--rangeslider-hud-capline-bg);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.hud.visible {
|
|
452
|
+
opacity: 1;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
.hud p {
|
|
456
|
+
margin: 0;
|
|
457
|
+
}
|
|
458
|
+
.container.default .hud p {
|
|
459
|
+
color: var(--rangeslider-hud-default-text);
|
|
460
|
+
}
|
|
461
|
+
.container.capsule .hud p {
|
|
462
|
+
color: var(--rangeslider-hud-capsule-text);
|
|
463
|
+
}
|
|
464
|
+
.container.capline .hud p {
|
|
465
|
+
color: var(--rangeslider-hud-capline-text);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/* Slider wrapper to contain track and labels */
|
|
469
|
+
.sliderWrapper {
|
|
470
|
+
position: relative;
|
|
471
|
+
flex: 1;
|
|
472
|
+
padding-bottom: 1.18rem; /* Space for tick labels if shown */
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/* Tick marks container */
|
|
476
|
+
.ticks {
|
|
477
|
+
position: absolute;
|
|
478
|
+
top: 0;
|
|
479
|
+
left: 0;
|
|
480
|
+
right: 0;
|
|
481
|
+
height: 100%;
|
|
482
|
+
pointer-events: none;
|
|
483
|
+
}
|
|
484
|
+
.ticks > :first-child {
|
|
485
|
+
opacity: 0;
|
|
486
|
+
}
|
|
487
|
+
.ticks > :last-child {
|
|
488
|
+
opacity: 0;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/* Individual tick mark */
|
|
492
|
+
.tick {
|
|
493
|
+
position: absolute;
|
|
494
|
+
top: 50%;
|
|
495
|
+
transform: translate(-50%, -50%);
|
|
496
|
+
background-color: var(--rangeslider-tick-color);
|
|
497
|
+
opacity: 1;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.container.default .tick {
|
|
501
|
+
width: 0.5px;
|
|
502
|
+
height: 0.47rem;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.container.capsule .tick {
|
|
506
|
+
width: 0.5px;
|
|
507
|
+
height: 0.71rem;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
.container.capline .tick {
|
|
511
|
+
width: 0.5px;
|
|
512
|
+
height: 1.18rem;
|
|
513
|
+
border-radius: 999px;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/* Tick labels container */
|
|
517
|
+
.tickLabels {
|
|
518
|
+
position: absolute;
|
|
519
|
+
top: 100%;
|
|
520
|
+
left: 0;
|
|
521
|
+
right: 0;
|
|
522
|
+
margin-top: 0.47rem;
|
|
523
|
+
height: 1.18rem;
|
|
524
|
+
font-size: 0.59rem;
|
|
525
|
+
color: var(--rangeslider-tick-label-color);
|
|
526
|
+
opacity: var(--rangeslider-tick-label-opacity);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/* Individual tick label */
|
|
530
|
+
.tickLabel {
|
|
531
|
+
position: absolute;
|
|
532
|
+
transform: translateX(-50%);
|
|
533
|
+
white-space: nowrap;
|
|
534
|
+
}
|
|
535
|
+
</style>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* Light theme using Colors */
|
|
2
|
+
:root {
|
|
3
|
+
/* RangeSlider label colors */
|
|
4
|
+
--rangeslider-label-color: #1a1d23; /* gray12 - dark text for light mode */
|
|
5
|
+
|
|
6
|
+
/* RangeSlider track colors */
|
|
7
|
+
--rangeslider-track-default-bg: #cecece; /* gray5 - light background for light mode */
|
|
8
|
+
--rangeslider-track-capsule-border: #0090ff; /* blue9 - same as button primary */
|
|
9
|
+
--rangeslider-track-capline-bg: #e3e5e8; /* gray5 - light background for light mode */
|
|
10
|
+
|
|
11
|
+
/* RangeSlider thumb colors */
|
|
12
|
+
--rangeslider-thumb-default-bg: #838383;
|
|
13
|
+
--rangeslider-thumb-capsule-bg: #838383;
|
|
14
|
+
--rangeslider-thumb-capsule-border: white;
|
|
15
|
+
--rangeslider-thumb-capline-bg: #838383;
|
|
16
|
+
|
|
17
|
+
/* RangeSlider progress colors */
|
|
18
|
+
--rangeslider-progress-default-bg: #0090ff; /* blue9 - same as button primary */
|
|
19
|
+
--rangeslider-progress-capsule-bg: #acd8fc; /* light blue background for light mode */
|
|
20
|
+
--rangeslider-progress-capsule-border-top: white;
|
|
21
|
+
--rangeslider-progress-capsule-border-bottom: white;
|
|
22
|
+
--rangeslider-progress-capsule-border-left: white;
|
|
23
|
+
--rangeslider-progress-capline-bg: #0090ff; /* blue9 - same as button primary */
|
|
24
|
+
|
|
25
|
+
/* RangeSlider HUD colors */
|
|
26
|
+
--rangeslider-hud-default-bg: #8b8d98; /* gray9 - muted background for light mode */
|
|
27
|
+
--rangeslider-hud-default-text: #ffffff; /* white text for contrast */
|
|
28
|
+
--rangeslider-hud-capsule-bg: #0090ff; /* blue9 - same as button primary */
|
|
29
|
+
--rangeslider-hud-capsule-text: #ffffff; /* white text for contrast */
|
|
30
|
+
--rangeslider-hud-capline-bg: #8b8d98; /* white background for light mode */
|
|
31
|
+
--rangeslider-hud-capline-text: #ffffff; /* gray12 - dark text for light mode */
|
|
32
|
+
|
|
33
|
+
/* RangeSlider tick colors */
|
|
34
|
+
--rangeslider-tick-color: #bbbbbb; /* gray8 - muted color for light mode */
|
|
35
|
+
|
|
36
|
+
/* RangeSlider tick label colors */
|
|
37
|
+
--rangeslider-tick-label-color: #8b8d98; /* gray9 - muted text for light mode */
|
|
38
|
+
--rangeslider-tick-label-opacity: 0.8; /* slightly more visible in light mode */
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Dark theme */
|
|
42
|
+
.dark,
|
|
43
|
+
.dark-theme {
|
|
44
|
+
/* RangeSlider label colors */
|
|
45
|
+
--rangeslider-label-color: #eeeeee; /* Original dark mode value */
|
|
46
|
+
|
|
47
|
+
/* RangeSlider track colors */
|
|
48
|
+
--rangeslider-track-default-bg: #484848; /* Original dark mode value */
|
|
49
|
+
--rangeslider-track-capsule-border: #0090ff; /* blue9 - same as button primary */
|
|
50
|
+
--rangeslider-track-capline-bg: #484848; /* Original dark mode value */
|
|
51
|
+
|
|
52
|
+
/* RangeSlider thumb colors */
|
|
53
|
+
--rangeslider-thumb-default-bg: #b4b4b4; /* Original dark mode value */
|
|
54
|
+
--rangeslider-thumb-capsule-bg: #eeeeee; /* Original dark mode value */
|
|
55
|
+
--rangeslider-thumb-capsule-border: #000000; /* Original dark mode value */
|
|
56
|
+
--rangeslider-thumb-capline-bg: #b4b4b4; /* Original dark mode value */
|
|
57
|
+
|
|
58
|
+
/* RangeSlider progress colors */
|
|
59
|
+
--rangeslider-progress-default-bg: #0090ff; /* blue9 - same as button primary */
|
|
60
|
+
--rangeslider-progress-capsule-bg: #0d2847; /* Original dark mode value */
|
|
61
|
+
--rangeslider-progress-capsule-border-top: #000000; /* Original dark mode value */
|
|
62
|
+
--rangeslider-progress-capsule-border-bottom: #000000; /* Original dark mode value */
|
|
63
|
+
--rangeslider-progress-capsule-border-left: #000000;
|
|
64
|
+
--rangeslider-progress-capline-bg: #0090ff; /* blue9 - same as button primary */
|
|
65
|
+
|
|
66
|
+
/* RangeSlider HUD colors */
|
|
67
|
+
--rangeslider-hud-default-bg: #b4b4b4; /* Original dark mode value */
|
|
68
|
+
--rangeslider-hud-default-text: #000000; /* Original dark mode value */
|
|
69
|
+
--rangeslider-hud-capsule-bg: #0090ff; /* blue9 - same as button primary */
|
|
70
|
+
--rangeslider-hud-capsule-text: #eeeeee; /* Original dark mode value */
|
|
71
|
+
--rangeslider-hud-capline-bg: #eeeeee; /* Original dark mode value */
|
|
72
|
+
--rangeslider-hud-capline-text: #000000; /* Original dark mode value */
|
|
73
|
+
|
|
74
|
+
/* RangeSlider tick colors */
|
|
75
|
+
--rangeslider-tick-color: #7b7b7b; /* Original dark mode value */
|
|
76
|
+
|
|
77
|
+
/* RangeSlider tick label colors */
|
|
78
|
+
--rangeslider-tick-label-color: #b4b4b4; /* Original dark mode value */
|
|
79
|
+
--rangeslider-tick-label-opacity: 0.6; /* Original dark mode value */
|
|
80
|
+
}
|