@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,19 @@
1
+ import { Component, markRaw } from "vue";
2
+
3
+ export interface View {
4
+ id: string;
5
+ component: Component | ReturnType<typeof markRaw<Component>>;
6
+ props?: Record<string, unknown>;
7
+ minWidth?: number;
8
+ maxWidth?: number;
9
+ currentWidth?: number;
10
+ label?: string;
11
+ }
12
+
13
+ export type ViewLayout = "splitview" | "slideover" | "navstack" | "adaptive";
14
+
15
+ export type ViewLocation = "leading" | "trailing" | "onscreen" | "overlay";
16
+
17
+ export interface InternalView extends View {
18
+ location: ViewLocation;
19
+ }
@@ -0,0 +1,89 @@
1
+ import {
2
+ ref,
3
+ computed,
4
+ reactive,
5
+ shallowRef,
6
+ type Ref,
7
+ type ComputedRef,
8
+ } from "vue";
9
+ import type { View, InternalView } from "./types";
10
+ import type { useResponsiveContainer } from "./useContainerMonitor";
11
+
12
+ type ResponsiveMonitor = ReturnType<typeof useResponsiveContainer>;
13
+
14
+ interface AdaptiveLayoutState {
15
+ views: Ref<InternalView[]>;
16
+ offScreenViewsLeading: ComputedRef<InternalView[]>;
17
+ offScreenViewsTrailing: ComputedRef<InternalView[]>;
18
+ onScreenViews: ComputedRef<InternalView[]>;
19
+ overlayViews: ComputedRef<InternalView[]>;
20
+ monitor: Ref<ResponsiveMonitor | null>;
21
+ methods: {
22
+ add: (view: View, animated?: boolean) => void;
23
+ remove: (id: string, animated?: boolean) => void;
24
+ replace: (id: string, view: View, animated?: boolean) => void;
25
+ show: (id: string, animated?: boolean) => void;
26
+ hide: (id: string, animated?: boolean) => void;
27
+ push: (id: string, animated?: boolean) => void;
28
+ pop: (id: string, animated?: boolean) => void;
29
+ setMethods: (methods: any) => void;
30
+ setMonitor: (monitor: ResponsiveMonitor) => void;
31
+ };
32
+ initialized: Ref<boolean>;
33
+ }
34
+
35
+ const layoutStates = new Map<string | symbol, AdaptiveLayoutState>();
36
+
37
+ export const useAdaptiveLayoutState = (key: string | symbol = Symbol()) => {
38
+ if (!layoutStates.has(key)) {
39
+ const views = ref<InternalView[]>([]);
40
+ const initialized = ref(false);
41
+ const monitor = shallowRef<ResponsiveMonitor | null>(null);
42
+
43
+ const offScreenViewsLeading = computed(() =>
44
+ views.value.filter((view) => view.location === "leading")
45
+ );
46
+
47
+ const offScreenViewsTrailing = computed(() =>
48
+ views.value.filter((view) => view.location === "trailing")
49
+ );
50
+
51
+ const onScreenViews = computed(() =>
52
+ views.value.filter((view) => view.location === "onscreen")
53
+ );
54
+
55
+ const overlayViews = computed(() =>
56
+ views.value.filter((view) => view.location === "overlay")
57
+ );
58
+
59
+ const methods = reactive({
60
+ add: () => console.warn("Layout not initialized"),
61
+ remove: () => console.warn("Layout not initialized"),
62
+ replace: () => console.warn("Layout not initialized"),
63
+ show: () => console.warn("Layout not initialized"),
64
+ hide: () => console.warn("Layout not initialized"),
65
+ push: () => console.warn("Layout not initialized"),
66
+ pop: () => console.warn("Layout not initialized"),
67
+ setMethods: (newMethods: any) => {
68
+ Object.assign(methods, newMethods);
69
+ initialized.value = true;
70
+ },
71
+ setMonitor: (newMonitor: ResponsiveMonitor) => {
72
+ monitor.value = newMonitor;
73
+ },
74
+ });
75
+
76
+ layoutStates.set(key, {
77
+ views,
78
+ offScreenViewsLeading,
79
+ offScreenViewsTrailing,
80
+ onScreenViews,
81
+ overlayViews,
82
+ monitor,
83
+ methods,
84
+ initialized,
85
+ });
86
+ }
87
+
88
+ return layoutStates.get(key)!;
89
+ };
@@ -0,0 +1,41 @@
1
+ import { Ref } from "vue";
2
+ import { InternalView } from "./types";
3
+
4
+ export const useBreakpoints = (views: Ref<InternalView[]>) => {
5
+ const setupForBreakpoint = (
6
+ oldBreakpoint: string | null,
7
+ currentBreakpoint: string | null
8
+ ) => {
9
+ switch (currentBreakpoint) {
10
+ case "mobile":
11
+ // Mark all views except the 1st one in location 'trailing'
12
+ views.value.forEach((view, index) => {
13
+ if (index === 0) {
14
+ view.location = "onscreen";
15
+ } else {
16
+ view.location = "trailing";
17
+ }
18
+ });
19
+ break;
20
+ case "tablet":
21
+ // Mark all views except the last one in location 'leading'
22
+ views.value.forEach((view, index) => {
23
+ if (index === views.value.length - 1) {
24
+ view.location = "onscreen";
25
+ } else {
26
+ view.location = "leading";
27
+ }
28
+ });
29
+ break;
30
+ case "desktop":
31
+ // Mark all views for location 'onscreen'
32
+ views.value.forEach((view) => {
33
+ view.location = "onscreen";
34
+ });
35
+ break;
36
+ }
37
+ };
38
+ return {
39
+ setupForBreakpoint,
40
+ };
41
+ };
@@ -0,0 +1,214 @@
1
+ import { ref, computed, onMounted, onUnmounted, type Ref } from "vue";
2
+
3
+ // Default breakpoint configuration
4
+ export const DEFAULT_BREAKPOINTS = {
5
+ mobile: { min: 0, max: 639 },
6
+ tablet: { min: 640, max: 1023 },
7
+ desktop: { min: 1024, max: Infinity },
8
+ } as const;
9
+
10
+ // Types
11
+ export type BreakpointName = string;
12
+
13
+ export interface BreakpointRange {
14
+ min: number;
15
+ max: number;
16
+ }
17
+
18
+ export interface BreakpointConfig {
19
+ [key: BreakpointName]: BreakpointRange;
20
+ }
21
+
22
+ export interface ContainerMonitorOptions {
23
+ breakpoints?: BreakpointConfig;
24
+ debounceMs?: number;
25
+ }
26
+
27
+ export interface ContainerDimensions {
28
+ width: number;
29
+ height: number;
30
+ }
31
+
32
+ // Utility function to find the current breakpoint
33
+ const findCurrentBreakpoint = (
34
+ width: number,
35
+ breakpoints: BreakpointConfig
36
+ ): BreakpointName | null => {
37
+ for (const [name, range] of Object.entries(breakpoints)) {
38
+ if (width >= range.min && width <= range.max) {
39
+ return name;
40
+ }
41
+ }
42
+ return null;
43
+ };
44
+
45
+ // Main composable
46
+ export const useContainerMonitor = (
47
+ elementRef: Ref<HTMLElement | undefined>,
48
+ options: ContainerMonitorOptions = {}
49
+ ) => {
50
+ const {
51
+ breakpoints = DEFAULT_BREAKPOINTS,
52
+ debounceMs = 16, // ~60fps
53
+ } = options;
54
+
55
+ // Reactive state
56
+ const dimensions = ref<ContainerDimensions>({ width: 0, height: 0 });
57
+ const currentBreakpoint = ref<BreakpointName | null>(null);
58
+ const previousBreakpoint = ref<BreakpointName | null>(null);
59
+
60
+ // Computed properties for easy breakpoint checking
61
+ const breakpointQueries = computed(() => {
62
+ const queries: Record<string, boolean> = {};
63
+
64
+ Object.keys(breakpoints).forEach((name) => {
65
+ queries[`is${name.charAt(0).toUpperCase() + name.slice(1)}`] =
66
+ currentBreakpoint.value === name;
67
+ });
68
+
69
+ return queries;
70
+ });
71
+
72
+ // Utility functions for responsive checks
73
+ const isBreakpoint = (name: BreakpointName): boolean => {
74
+ return currentBreakpoint.value === name;
75
+ };
76
+
77
+ const isBreakpointOrAbove = (name: BreakpointName): boolean => {
78
+ if (!currentBreakpoint.value) return false;
79
+
80
+ const currentWidth = dimensions.value.width;
81
+ const targetRange = breakpoints[name as keyof typeof breakpoints];
82
+ if (!targetRange) return false;
83
+
84
+ return currentWidth >= targetRange.min;
85
+ };
86
+
87
+ const isBreakpointOrBelow = (name: BreakpointName): boolean => {
88
+ if (!currentBreakpoint.value) return false;
89
+
90
+ const currentWidth = dimensions.value.width;
91
+ const targetRange = breakpoints[name as keyof typeof breakpoints];
92
+ if (!targetRange) return false;
93
+
94
+ return currentWidth <= targetRange.max;
95
+ };
96
+
97
+ const isBetweenBreakpoints = (
98
+ min: BreakpointName,
99
+ max: BreakpointName
100
+ ): boolean => {
101
+ const currentWidth = dimensions.value.width;
102
+ const minRange = breakpoints[min as keyof typeof breakpoints];
103
+ const maxRange = breakpoints[max as keyof typeof breakpoints];
104
+
105
+ if (!minRange || !maxRange) return false;
106
+
107
+ return currentWidth >= minRange.min && currentWidth <= maxRange.max;
108
+ };
109
+
110
+ // Resize observer and debouncing
111
+ let resizeObserver: ResizeObserver | null = null;
112
+ let debounceTimer: number | null = null;
113
+
114
+ const updateDimensions = (entries: ResizeObserverEntry[]) => {
115
+ if (debounceTimer) {
116
+ clearTimeout(debounceTimer);
117
+ }
118
+
119
+ debounceTimer = window.setTimeout(() => {
120
+ const entry = entries[0];
121
+ if (!entry) return;
122
+
123
+ const { width, height } = entry.contentRect;
124
+
125
+ // Update dimensions
126
+ dimensions.value = { width, height };
127
+
128
+ // Update breakpoint
129
+ const newBreakpoint = findCurrentBreakpoint(width, breakpoints);
130
+
131
+ if (newBreakpoint !== currentBreakpoint.value) {
132
+ previousBreakpoint.value = currentBreakpoint.value;
133
+ currentBreakpoint.value = newBreakpoint;
134
+ }
135
+ }, debounceMs);
136
+ };
137
+
138
+ // Initialize observer
139
+ const startObserver = () => {
140
+ if (!elementRef.value || resizeObserver) return;
141
+
142
+ resizeObserver = new ResizeObserver(updateDimensions);
143
+ resizeObserver.observe(elementRef.value);
144
+
145
+ // Get initial dimensions
146
+ const rect = elementRef.value.getBoundingClientRect();
147
+ dimensions.value = { width: rect.width, height: rect.height };
148
+ currentBreakpoint.value = findCurrentBreakpoint(rect.width, breakpoints);
149
+ };
150
+
151
+ const stopObserver = () => {
152
+ if (resizeObserver) {
153
+ resizeObserver.disconnect();
154
+ resizeObserver = null;
155
+ }
156
+
157
+ if (debounceTimer) {
158
+ clearTimeout(debounceTimer);
159
+ debounceTimer = null;
160
+ }
161
+ };
162
+
163
+ // Lifecycle hooks
164
+ onMounted(() => {
165
+ startObserver();
166
+ });
167
+
168
+ onUnmounted(() => {
169
+ stopObserver();
170
+ });
171
+
172
+ // Watch for element ref changes
173
+ const restart = () => {
174
+ stopObserver();
175
+ startObserver();
176
+ };
177
+
178
+ return {
179
+ // Reactive state
180
+ dimensions,
181
+ currentBreakpoint,
182
+ previousBreakpoint,
183
+
184
+ // Computed breakpoint queries (isTablet, isMobile, etc.)
185
+ ...breakpointQueries.value,
186
+
187
+ // Utility functions
188
+ isBreakpoint,
189
+ isBreakpointOrAbove,
190
+ isBreakpointOrBelow,
191
+ isBetweenBreakpoints,
192
+
193
+ // Control functions
194
+ restart,
195
+
196
+ // Configuration
197
+ breakpoints,
198
+ };
199
+ };
200
+
201
+ // Convenience composable for common use cases
202
+ export const useResponsiveContainer = (
203
+ elementRef: Ref<HTMLElement | undefined>,
204
+ customBreakpoints?: Partial<BreakpointConfig>
205
+ ) => {
206
+ const breakpoints = customBreakpoints
207
+ ? { ...DEFAULT_BREAKPOINTS, ...customBreakpoints }
208
+ : DEFAULT_BREAKPOINTS;
209
+
210
+ return useContainerMonitor(elementRef, { breakpoints });
211
+ };
212
+
213
+ // Export default breakpoints for convenience
214
+ export { DEFAULT_BREAKPOINTS as breakpoints };