@umbra.ui/core 0.1.0

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.
Files changed (272) hide show
  1. package/dist/components/controls/Dropdown/types.d.ts +5 -0
  2. package/dist/components/controls/Dropdown/types.d.ts.map +1 -0
  3. package/dist/components/controls/Dropdown/types.js +1 -0
  4. package/dist/components/controls/SegmentedControl/types.d.ts +6 -0
  5. package/dist/components/controls/SegmentedControl/types.d.ts.map +1 -0
  6. package/dist/components/controls/SegmentedControl/types.js +1 -0
  7. package/dist/components/dialogs/Alert/types.d.ts +7 -0
  8. package/dist/components/dialogs/Alert/types.d.ts.map +1 -0
  9. package/dist/components/dialogs/Alert/types.js +1 -0
  10. package/dist/components/dialogs/Toast/types.d.ts +34 -0
  11. package/dist/components/dialogs/Toast/types.d.ts.map +1 -0
  12. package/dist/components/dialogs/Toast/types.js +10 -0
  13. package/dist/components/dialogs/Toast/useToast.d.ts +36 -0
  14. package/dist/components/dialogs/Toast/useToast.d.ts.map +1 -0
  15. package/dist/components/dialogs/Toast/useToast.js +90 -0
  16. package/dist/components/indicators/Tooltip/tooltip.d.ts +3 -0
  17. package/dist/components/indicators/Tooltip/tooltip.d.ts.map +1 -0
  18. package/dist/components/indicators/Tooltip/tooltip.js +33 -0
  19. package/dist/components/indicators/Tooltip/types.d.ts +14 -0
  20. package/dist/components/indicators/Tooltip/types.d.ts.map +1 -0
  21. package/dist/components/indicators/Tooltip/types.js +1 -0
  22. package/dist/components/indicators/Tooltip/useTooltip.d.ts +18 -0
  23. package/dist/components/indicators/Tooltip/useTooltip.d.ts.map +1 -0
  24. package/dist/components/indicators/Tooltip/useTooltip.js +57 -0
  25. package/dist/components/inputs/Tags/tag-bar-styles.d.ts +14 -0
  26. package/dist/components/inputs/Tags/tag-bar-styles.d.ts.map +1 -0
  27. package/dist/components/inputs/Tags/tag-bar-styles.js +313 -0
  28. package/dist/components/inputs/Tags/types.d.ts +93 -0
  29. package/dist/components/inputs/Tags/types.d.ts.map +1 -0
  30. package/dist/components/inputs/Tags/types.js +216 -0
  31. package/dist/components/inputs/search/types.d.ts +9 -0
  32. package/dist/components/inputs/search/types.d.ts.map +1 -0
  33. package/dist/components/inputs/search/types.js +1 -0
  34. package/dist/components/navigation/adaptive/types.d.ts +16 -0
  35. package/dist/components/navigation/adaptive/types.d.ts.map +1 -0
  36. package/dist/components/navigation/adaptive/types.js +1 -0
  37. package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts +27 -0
  38. package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts.map +1 -0
  39. package/dist/components/navigation/adaptive/useAdaptiveLayout.js +40 -0
  40. package/dist/components/navigation/adaptive/useBreakpoints.d.ts +6 -0
  41. package/dist/components/navigation/adaptive/useBreakpoints.d.ts.map +1 -0
  42. package/dist/components/navigation/adaptive/useBreakpoints.js +37 -0
  43. package/dist/components/navigation/adaptive/useContainerMonitor.d.ts +93 -0
  44. package/dist/components/navigation/adaptive/useContainerMonitor.d.ts.map +1 -0
  45. package/dist/components/navigation/adaptive/useContainerMonitor.js +145 -0
  46. package/dist/components/navigation/adaptive/useViewAnimation.d.ts +31 -0
  47. package/dist/components/navigation/adaptive/useViewAnimation.d.ts.map +1 -0
  48. package/dist/components/navigation/adaptive/useViewAnimation.js +591 -0
  49. package/dist/components/navigation/adaptive/useViewResize.d.ts +52 -0
  50. package/dist/components/navigation/adaptive/useViewResize.d.ts.map +1 -0
  51. package/dist/components/navigation/adaptive/useViewResize.js +146 -0
  52. package/dist/components/navigation/navstack/useNavigationStack.d.ts +25 -0
  53. package/dist/components/navigation/navstack/useNavigationStack.d.ts.map +1 -0
  54. package/dist/components/navigation/navstack/useNavigationStack.js +133 -0
  55. package/dist/components/navigation/slideover/useSlideoverController.d.ts +20 -0
  56. package/dist/components/navigation/slideover/useSlideoverController.d.ts.map +1 -0
  57. package/dist/components/navigation/slideover/useSlideoverController.js +267 -0
  58. package/dist/components/navigation/splitview/useSplitViewController.d.ts +20 -0
  59. package/dist/components/navigation/splitview/useSplitViewController.d.ts.map +1 -0
  60. package/dist/components/navigation/splitview/useSplitViewController.js +325 -0
  61. package/dist/components/navigation/tabcontroller/types.d.ts +21 -0
  62. package/dist/components/navigation/tabcontroller/types.d.ts.map +1 -0
  63. package/dist/components/navigation/tabcontroller/types.js +1 -0
  64. package/dist/components/navigation/tabcontroller/useTabController.d.ts +5 -0
  65. package/dist/components/navigation/tabcontroller/useTabController.d.ts.map +1 -0
  66. package/dist/components/navigation/tabcontroller/useTabController.js +10 -0
  67. package/dist/components/navigation/types.d.ts +8 -0
  68. package/dist/components/navigation/types.d.ts.map +1 -0
  69. package/dist/components/navigation/types.js +1 -0
  70. package/dist/components/pickers/CollectionPicker/types.d.ts +11 -0
  71. package/dist/components/pickers/CollectionPicker/types.d.ts.map +1 -0
  72. package/dist/components/pickers/CollectionPicker/types.js +1 -0
  73. package/dist/components/pickers/ColorPicker/colors.d.ts +13 -0
  74. package/dist/components/pickers/ColorPicker/colors.d.ts.map +1 -0
  75. package/dist/components/pickers/ColorPicker/colors.js +266 -0
  76. package/dist/components/pickers/FilePicker/types.d.ts +10 -0
  77. package/dist/components/pickers/FilePicker/types.d.ts.map +1 -0
  78. package/dist/components/pickers/FilePicker/types.js +1 -0
  79. package/dist/index.d.ts +91 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +196 -0
  82. package/dist/theme.d.ts +73 -0
  83. package/dist/theme.d.ts.map +1 -0
  84. package/dist/theme.js +279 -0
  85. package/dist/themes/blank.d.ts +7 -0
  86. package/dist/themes/blank.d.ts.map +1 -0
  87. package/dist/themes/blank.js +543 -0
  88. package/dist/themes/crimson-dark.d.ts +4 -0
  89. package/dist/themes/crimson-dark.d.ts.map +1 -0
  90. package/dist/themes/crimson-dark.js +552 -0
  91. package/dist/themes/cyan-light.d.ts +4 -0
  92. package/dist/themes/cyan-light.d.ts.map +1 -0
  93. package/dist/themes/cyan-light.js +552 -0
  94. package/dist/themes/dark.d.ts +4 -0
  95. package/dist/themes/dark.d.ts.map +1 -0
  96. package/dist/themes/dark.js +551 -0
  97. package/dist/themes/gold-dark.d.ts +4 -0
  98. package/dist/themes/gold-dark.d.ts.map +1 -0
  99. package/dist/themes/gold-dark.js +552 -0
  100. package/dist/themes/grass-dark.d.ts +4 -0
  101. package/dist/themes/grass-dark.d.ts.map +1 -0
  102. package/dist/themes/grass-dark.js +552 -0
  103. package/dist/themes/indigo.d.ts +4 -0
  104. package/dist/themes/indigo.d.ts.map +1 -0
  105. package/dist/themes/indigo.js +552 -0
  106. package/dist/themes/light.d.ts +4 -0
  107. package/dist/themes/light.d.ts.map +1 -0
  108. package/dist/themes/light.js +551 -0
  109. package/dist/themes/orange-dark.d.ts +4 -0
  110. package/dist/themes/orange-dark.d.ts.map +1 -0
  111. package/dist/themes/orange-dark.js +551 -0
  112. package/dist/themes/orange-light.d.ts +4 -0
  113. package/dist/themes/orange-light.d.ts.map +1 -0
  114. package/dist/themes/orange-light.js +551 -0
  115. package/package.json +62 -0
  116. package/src/components/controls/Button/Button.vue +417 -0
  117. package/src/components/controls/Button/README.md +348 -0
  118. package/src/components/controls/Button/theme.css +200 -0
  119. package/src/components/controls/Checkbox/Checkbox.vue +164 -0
  120. package/src/components/controls/Checkbox/README.md +441 -0
  121. package/src/components/controls/Checkbox/theme.css +36 -0
  122. package/src/components/controls/Dropdown/Dropdown.vue +476 -0
  123. package/src/components/controls/Dropdown/README.md +370 -0
  124. package/src/components/controls/Dropdown/theme.css +50 -0
  125. package/src/components/controls/Dropdown/types.ts +6 -0
  126. package/src/components/controls/IconButton/IconButton.vue +267 -0
  127. package/src/components/controls/IconButton/README.md +502 -0
  128. package/src/components/controls/IconButton/theme.css +89 -0
  129. package/src/components/controls/Radio/README.md +591 -0
  130. package/src/components/controls/Radio/Radio.vue +89 -0
  131. package/src/components/controls/Radio/theme.css +14 -0
  132. package/src/components/controls/RangeSlider/README.md +608 -0
  133. package/src/components/controls/RangeSlider/RangeSlider.vue +535 -0
  134. package/src/components/controls/RangeSlider/theme.css +80 -0
  135. package/src/components/controls/SegmentedControl/README.md +587 -0
  136. package/src/components/controls/SegmentedControl/SegmentedControl.vue +284 -0
  137. package/src/components/controls/SegmentedControl/theme.css +60 -0
  138. package/src/components/controls/SegmentedControl/types.ts +5 -0
  139. package/src/components/controls/Slider/README.md +627 -0
  140. package/src/components/controls/Slider/Slider.vue +260 -0
  141. package/src/components/controls/Slider/theme.css +74 -0
  142. package/src/components/controls/Stepper/README.md +601 -0
  143. package/src/components/controls/Stepper/Stepper.vue +103 -0
  144. package/src/components/controls/Stepper/theme.css +53 -0
  145. package/src/components/controls/Switch/README.md +667 -0
  146. package/src/components/controls/Switch/Switch.vue +127 -0
  147. package/src/components/controls/Switch/theme.css +42 -0
  148. package/src/components/dialogs/Alert/Alert.vue +218 -0
  149. package/src/components/dialogs/Alert/README.md +450 -0
  150. package/src/components/dialogs/Alert/theme.css +44 -0
  151. package/src/components/dialogs/Alert/types.ts +11 -0
  152. package/src/components/dialogs/Toast/README.md +522 -0
  153. package/src/components/dialogs/Toast/Toast.vue +296 -0
  154. package/src/components/dialogs/Toast/ToastContainer.vue +330 -0
  155. package/src/components/dialogs/Toast/theme.css +44 -0
  156. package/src/components/dialogs/Toast/types.ts +46 -0
  157. package/src/components/dialogs/Toast/useToast.ts +127 -0
  158. package/src/components/indicators/ProgressBar/ProgressBar.vue +98 -0
  159. package/src/components/indicators/ProgressBar/README.md +744 -0
  160. package/src/components/indicators/ProgressBar/theme.css +36 -0
  161. package/src/components/indicators/Tooltip/README.md +723 -0
  162. package/src/components/indicators/Tooltip/TooltipProvider.vue +142 -0
  163. package/src/components/indicators/Tooltip/theme.css +18 -0
  164. package/src/components/indicators/Tooltip/tooltip.ts +48 -0
  165. package/src/components/indicators/Tooltip/types.ts +15 -0
  166. package/src/components/indicators/Tooltip/useTooltip.ts +71 -0
  167. package/src/components/inputs/AutogrowTextView/AutogrowTextView.vue +110 -0
  168. package/src/components/inputs/AutogrowTextView/README.md +643 -0
  169. package/src/components/inputs/AutogrowTextView/theme.css +28 -0
  170. package/src/components/inputs/InputCard/InputCard.vue +600 -0
  171. package/src/components/inputs/InputCard/README.md +636 -0
  172. package/src/components/inputs/InputEmail/InputEmail.vue +698 -0
  173. package/src/components/inputs/InputEmail/README.md +764 -0
  174. package/src/components/inputs/InputNumber/InputNumber.vue +300 -0
  175. package/src/components/inputs/InputNumber/README.md +749 -0
  176. package/src/components/inputs/InputPhone/InputPhone.vue +645 -0
  177. package/src/components/inputs/InputPhone/README.md +636 -0
  178. package/src/components/inputs/InputSecure/InputSecure.vue +646 -0
  179. package/src/components/inputs/InputSecure/README.md +771 -0
  180. package/src/components/inputs/InputText/InputText.vue +225 -0
  181. package/src/components/inputs/InputText/README.md +844 -0
  182. package/src/components/inputs/OTP/OTP.vue +349 -0
  183. package/src/components/inputs/OTP/README.md +736 -0
  184. package/src/components/inputs/OTP/theme.css +50 -0
  185. package/src/components/inputs/StringCapture/README.md +718 -0
  186. package/src/components/inputs/StringCapture/StringCapture.vue +315 -0
  187. package/src/components/inputs/StringCapture/theme.css +86 -0
  188. package/src/components/inputs/Tags/README.md +897 -0
  189. package/src/components/inputs/Tags/TagBar.vue +793 -0
  190. package/src/components/inputs/Tags/TagCreation.vue +219 -0
  191. package/src/components/inputs/Tags/TagPicker.vue +380 -0
  192. package/src/components/inputs/Tags/tag-bar-styles.ts +354 -0
  193. package/src/components/inputs/Tags/theme.css +121 -0
  194. package/src/components/inputs/Tags/types.ts +346 -0
  195. package/src/components/inputs/search/README.md +759 -0
  196. package/src/components/inputs/search/SearchBar.vue +394 -0
  197. package/src/components/inputs/search/SearchResults.vue +310 -0
  198. package/src/components/inputs/search/theme.css +187 -0
  199. package/src/components/inputs/search/types.ts +8 -0
  200. package/src/components/inputs/theme.css +102 -0
  201. package/src/components/menus/ActionMenu/ActionMenu.vue +383 -0
  202. package/src/components/menus/ActionMenu/README.md +825 -0
  203. package/src/components/menus/ActionMenu/theme.css +93 -0
  204. package/src/components/models/Popover/Popover.vue +551 -0
  205. package/src/components/models/Popover/README.md +885 -0
  206. package/src/components/models/Popover/theme.css +52 -0
  207. package/src/components/models/Sheet/README.md +1159 -0
  208. package/src/components/models/Sheet/Sheet.vue +465 -0
  209. package/src/components/models/Sheet/theme.css +72 -0
  210. package/src/components/models/Sidebar/README.md +1228 -0
  211. package/src/components/models/Sidebar/Sidebar.vue +480 -0
  212. package/src/components/models/Sidebar/theme.css +90 -0
  213. package/src/components/navigation/adaptive/AdaptiveLayout.vue +779 -0
  214. package/src/components/navigation/adaptive/AdaptiveLayoutBreadcrumbs.vue +192 -0
  215. package/src/components/navigation/adaptive/AdaptiveLayoutMenuButton.vue +149 -0
  216. package/src/components/navigation/adaptive/README.md +768 -0
  217. package/src/components/navigation/adaptive/types.ts +19 -0
  218. package/src/components/navigation/adaptive/useAdaptiveLayout.ts +89 -0
  219. package/src/components/navigation/adaptive/useBreakpoints.ts +41 -0
  220. package/src/components/navigation/adaptive/useContainerMonitor.ts +214 -0
  221. package/src/components/navigation/adaptive/useViewAnimation.ts +721 -0
  222. package/src/components/navigation/adaptive/useViewResize.ts +211 -0
  223. package/src/components/navigation/navstack/NavigationStack.vue +180 -0
  224. package/src/components/navigation/navstack/README.md +994 -0
  225. package/src/components/navigation/navstack/useNavigationStack.ts +164 -0
  226. package/src/components/navigation/slideover/README.md +1275 -0
  227. package/src/components/navigation/slideover/SlideoverController.vue +287 -0
  228. package/src/components/navigation/slideover/useSlideoverController.ts +320 -0
  229. package/src/components/navigation/splitview/README.md +1115 -0
  230. package/src/components/navigation/splitview/SplitViewController.vue +176 -0
  231. package/src/components/navigation/splitview/useSplitViewController.ts +388 -0
  232. package/src/components/navigation/tabcontroller/README.md +919 -0
  233. package/src/components/navigation/tabcontroller/TabController.vue +307 -0
  234. package/src/components/navigation/tabcontroller/TabItem.vue +57 -0
  235. package/src/components/navigation/tabcontroller/types.ts +24 -0
  236. package/src/components/navigation/tabcontroller/useTabController.ts +18 -0
  237. package/src/components/navigation/theme.css +91 -0
  238. package/src/components/navigation/types.ts +7 -0
  239. package/src/components/pickers/CollectionPicker/CollectionPicker.vue +398 -0
  240. package/src/components/pickers/CollectionPicker/README.md +1115 -0
  241. package/src/components/pickers/CollectionPicker/theme.css +14 -0
  242. package/src/components/pickers/CollectionPicker/types.ts +11 -0
  243. package/src/components/pickers/ColorPicker/ColorPicker.vue +376 -0
  244. package/src/components/pickers/ColorPicker/README.md +1439 -0
  245. package/src/components/pickers/ColorPicker/colors.ts +299 -0
  246. package/src/components/pickers/ColorPicker/theme.css +32 -0
  247. package/src/components/pickers/DatePicker/DatePicker.vue +660 -0
  248. package/src/components/pickers/DatePicker/README.md +1195 -0
  249. package/src/components/pickers/DatePicker/theme.css +22 -0
  250. package/src/components/pickers/FilePicker/FilePicker.vue +534 -0
  251. package/src/components/pickers/FilePicker/README.md +1542 -0
  252. package/src/components/pickers/FilePicker/theme.css +48 -0
  253. package/src/components/pickers/FilePicker/types.ts +10 -0
  254. package/src/components/pickers/IconPicker/IconPicker.vue +327 -0
  255. package/src/components/pickers/IconPicker/README.md +1161 -0
  256. package/src/components/pickers/IconPicker/theme.css +28 -0
  257. package/src/components/pickers/theme.css +82 -0
  258. package/src/components/views/MarkdownViewer/MarkdownViewer.vue +442 -0
  259. package/src/components/views/MarkdownViewer/README.md +833 -0
  260. package/src/components/views/MarkdownViewer/theme.css +130 -0
  261. package/src/index.ts +263 -0
  262. package/src/theme.ts +378 -0
  263. package/src/themes/crimson-dark.ts +556 -0
  264. package/src/themes/cyan-light.ts +556 -0
  265. package/src/themes/dark.ts +557 -0
  266. package/src/themes/gold-dark.ts +556 -0
  267. package/src/themes/grass-dark.ts +556 -0
  268. package/src/themes/indigo.ts +556 -0
  269. package/src/themes/light.ts +557 -0
  270. package/src/themes/orange-dark.ts +557 -0
  271. package/src/themes/orange-light.ts +557 -0
  272. package/src/vue.d.ts +45 -0
@@ -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
+ }