@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,779 @@
1
+ <!-- AdaptiveLayout2.vue -->
2
+ <script setup lang="ts">
3
+ import {
4
+ markRaw,
5
+ type Component,
6
+ defineExpose,
7
+ ref,
8
+ computed,
9
+ onMounted,
10
+ onUnmounted,
11
+ watch,
12
+ nextTick,
13
+ watchEffect,
14
+ } from "vue";
15
+ import { useAdaptiveLayoutState } from "./useAdaptiveLayout";
16
+ import { useResponsiveContainer } from "./useContainerMonitor";
17
+ import { View, InternalView, ViewLayout } from "./types";
18
+ import { useViewAnimation } from "./useViewAnimation";
19
+ import { useBreakpoints } from "./useBreakpoints";
20
+ import {
21
+ useViewResize,
22
+ type ResizeConfig,
23
+ type ResizableView,
24
+ } from "./useViewResize";
25
+
26
+ export interface Props {
27
+ initialViews: View[];
28
+ instanceKey?: string;
29
+ padding?: string;
30
+ gap?: string;
31
+ canHideViews?: boolean;
32
+ canResizeViews?: boolean;
33
+ layout?: ViewLayout;
34
+ }
35
+
36
+ const props = withDefaults(defineProps<Props>(), {
37
+ initialViews: () => [],
38
+ instanceKey: () => "adaptive-layout",
39
+ padding: "0",
40
+ gap: "0",
41
+ canHideViews: true,
42
+ canResizeViews: true,
43
+ layout: "adaptive",
44
+ });
45
+
46
+ // View state management
47
+ const layoutState = useAdaptiveLayoutState(props.instanceKey);
48
+ const views = layoutState.views;
49
+
50
+ // Initialize views with the initial data
51
+ views.value = props.initialViews.map((view) => ({
52
+ ...view,
53
+ location: "onscreen",
54
+ }));
55
+
56
+ const offScreenViewsLeading = layoutState.offScreenViewsLeading;
57
+ const offScreenViewsTrailing = layoutState.offScreenViewsTrailing;
58
+ const onScreenViews = layoutState.onScreenViews;
59
+ const overlayViews = layoutState.overlayViews;
60
+
61
+ onMounted(() => {
62
+ layoutState.methods.setMethods({
63
+ add,
64
+ remove,
65
+ replace,
66
+ show,
67
+ hide,
68
+ push,
69
+ pop,
70
+ });
71
+ });
72
+
73
+ // Container ref and monitoring
74
+ const containerRef = ref<HTMLElement>();
75
+ const monitor = useResponsiveContainer(containerRef);
76
+
77
+ // Share the monitor with the state whenever it's available
78
+ watchEffect(() => {
79
+ if (monitor && containerRef.value) {
80
+ layoutState.methods.setMonitor(monitor);
81
+ }
82
+ });
83
+
84
+ // Extract view animation functionality
85
+ const {
86
+ getOnscreenId,
87
+ getViewId,
88
+ getOffscreenLeadingId,
89
+ getOffscreenTrailingId,
90
+ getDarkenId,
91
+ getOverlayId,
92
+ splitViewShow,
93
+ splitViewHide,
94
+ splitViewPush,
95
+ splitViewPop,
96
+ slideoverShow,
97
+ slideoverHide,
98
+ slideoverPush,
99
+ slideoverPop,
100
+ navstackShow,
101
+ navstackPush,
102
+ navstackPop,
103
+ hasPrecedingViews,
104
+ getSingleViewBefore,
105
+ getSingleViewAfter,
106
+ isOverlayOpen,
107
+ } = useViewAnimation(
108
+ views,
109
+ props.instanceKey,
110
+ monitor.dimensions,
111
+ props.padding,
112
+ props.gap
113
+ );
114
+
115
+ // Extract breakpoint handling
116
+ const { setupForBreakpoint } = useBreakpoints(views);
117
+
118
+ const getViewIdForResize = (view: ResizableView) => {
119
+ return `${props.instanceKey}-view-${view.id}`;
120
+ };
121
+
122
+ // Resize configuration
123
+ const resizeConfig: ResizeConfig = {
124
+ defaultMinWidth: 150,
125
+ gap: Number(props.gap) || 0,
126
+ padding: Number(props.padding) || 0,
127
+ };
128
+
129
+ // Extract resize functionality with the updated signature
130
+ const { resizeTooltip, startResize } = useViewResize(
131
+ onScreenViews,
132
+ resizeConfig,
133
+ props,
134
+ getViewIdForResize, // Now passes the correct signature
135
+ getOnscreenId
136
+ );
137
+
138
+ // Public methods
139
+
140
+ const add = (view: View, animated: boolean = true) => {
141
+ console.error("add not implemented");
142
+ };
143
+
144
+ const remove = (id: string, animated: boolean = true) => {
145
+ console.error("remove not implemented");
146
+ };
147
+
148
+ const replace = (id: string, view: View, animated: boolean = true) => {
149
+ console.error("replace not implemented");
150
+ };
151
+
152
+ const show = (id: string, animated: boolean = true) => {
153
+ switch (props.layout) {
154
+ case "splitview":
155
+ splitViewShow(id);
156
+ return;
157
+ case "slideover":
158
+ slideoverShow(id);
159
+ return;
160
+ case "navstack":
161
+ navstackShow(id);
162
+ return;
163
+ }
164
+ switch (monitor.currentBreakpoint.value) {
165
+ case "desktop":
166
+ splitViewShow(id);
167
+ return;
168
+ case "tablet":
169
+ slideoverShow(id);
170
+ return;
171
+ case "mobile":
172
+ navstackShow(id);
173
+ return;
174
+ }
175
+ };
176
+
177
+ const hide = (id: string, animated: boolean = true) => {
178
+ switch (props.layout) {
179
+ case "splitview":
180
+ splitViewHide(id);
181
+ return;
182
+ case "slideover":
183
+ slideoverHide();
184
+ return;
185
+ case "navstack":
186
+ navstackShow(views.value[0].id);
187
+ return;
188
+ }
189
+ switch (monitor.currentBreakpoint.value) {
190
+ case "desktop":
191
+ splitViewHide(id);
192
+ return;
193
+ case "tablet":
194
+ slideoverHide();
195
+ return;
196
+ case "mobile":
197
+ navstackShow(views.value[0].id);
198
+ return;
199
+ }
200
+ };
201
+
202
+ const push = (id: string, animated: boolean = true) => {
203
+ switch (props.layout) {
204
+ case "splitview":
205
+ splitViewPush(id);
206
+ return;
207
+ case "slideover":
208
+ slideoverPush(id);
209
+ return;
210
+ case "navstack":
211
+ navstackPush();
212
+ return;
213
+ }
214
+ switch (monitor.currentBreakpoint.value) {
215
+ case "desktop":
216
+ splitViewPush(id);
217
+ return;
218
+ case "tablet":
219
+ slideoverPush(id);
220
+ return;
221
+ case "mobile":
222
+ navstackPush();
223
+ return;
224
+ }
225
+ };
226
+
227
+ const pop = (id: string, animated: boolean = true) => {
228
+ switch (props.layout) {
229
+ case "splitview":
230
+ splitViewPop(id);
231
+ return;
232
+ case "slideover":
233
+ slideoverPop(id);
234
+ return;
235
+ case "navstack":
236
+ navstackPop(id);
237
+ return;
238
+ }
239
+ switch (monitor.currentBreakpoint.value) {
240
+ case "desktop":
241
+ splitViewPop(id);
242
+ return;
243
+ case "tablet":
244
+ slideoverPop(id);
245
+ return;
246
+ case "mobile":
247
+ navstackPop(id);
248
+ return;
249
+ }
250
+ };
251
+
252
+ const toggle = (id: string, animated: boolean = true) => {
253
+ const view = views.value.find((view) => view.id === id);
254
+ if (!view) return;
255
+ if (view.location === "onscreen") {
256
+ hide(view.id);
257
+ } else {
258
+ show(view.id);
259
+ }
260
+ // const next = getSingleViewAfter(view.id);
261
+ // if (!next) return;
262
+ // handleClicked(next);
263
+ };
264
+
265
+ defineExpose({
266
+ add,
267
+ remove,
268
+ replace,
269
+ show,
270
+ hide,
271
+ push,
272
+ pop,
273
+ toggle,
274
+ });
275
+
276
+ // Watch for breakpoint changes
277
+ watch(
278
+ () => monitor.currentBreakpoint.value,
279
+ (newBreakpoint, oldBreakpoint) => {
280
+ if (props.layout !== "adaptive") {
281
+ return;
282
+ }
283
+ // ensure the overlay is hidden if showing
284
+ if (isOverlayOpen.value) {
285
+ slideoverHide();
286
+ }
287
+ setupForBreakpoint(oldBreakpoint, newBreakpoint);
288
+ }
289
+ );
290
+
291
+ /*
292
+ * Internal Functions
293
+ */
294
+
295
+ const darkenClicked = async () => {
296
+ slideoverHide();
297
+ };
298
+
299
+ const handleClicked = async (view: InternalView) => {
300
+ switch (props.layout) {
301
+ case "splitview":
302
+ toggleSplitView(view);
303
+ return;
304
+ case "slideover":
305
+ toggleSlideover(view);
306
+ return;
307
+ case "navstack":
308
+ toggleNavstack(view);
309
+ return;
310
+ }
311
+ switch (monitor.currentBreakpoint.value) {
312
+ case "desktop":
313
+ toggleSplitView(view);
314
+ return;
315
+ case "tablet":
316
+ toggleSlideover(view);
317
+ return;
318
+ case "mobile":
319
+ toggleNavstack(view);
320
+ return;
321
+ }
322
+ };
323
+
324
+ const toggleSplitView = async (view: InternalView) => {
325
+ // If there are any preceding views that are onscreen, hide this view (and they will be hidden too)
326
+ if (hasPrecedingViews(view.id, "onscreen")) {
327
+ pop(view.id);
328
+ } else {
329
+ // All preceding views are offscreen (or there are no preceding views), so show the preceding view
330
+ push(view.id);
331
+ }
332
+ };
333
+ const toggleSlideover = async (view: InternalView) => {
334
+ switch (view.location) {
335
+ case "onscreen":
336
+ const previous = getSingleViewBefore(view.id);
337
+ if (previous) {
338
+ slideoverShow(previous.id);
339
+ }
340
+ break;
341
+ case "overlay":
342
+ if (hasPrecedingViews(view.id, "leading")) {
343
+ slideoverPush(view.id);
344
+ } else {
345
+ slideoverPop(view.id);
346
+ }
347
+ break;
348
+ }
349
+ };
350
+ const toggleNavstack = async (view: InternalView) => {
351
+ popNavstack(view);
352
+ };
353
+ const pushNavstack = async (view: InternalView) => {
354
+ navstackPush();
355
+ };
356
+ const popNavstack = async (view: InternalView) => {
357
+ navstackPop(view.id);
358
+ };
359
+
360
+ const shouldShowLeftHandle = (index: number): boolean => {
361
+ return (
362
+ props.canHideViews &&
363
+ (index > 0 || (index === 0 && offScreenViewsLeading.value.length > 0))
364
+ );
365
+ };
366
+ const shouldShowRightHandle = (index: number): boolean => {
367
+ if (props.layout === "navstack" && props.canHideViews) {
368
+ return offScreenViewsTrailing.value.length > 0;
369
+ }
370
+ if (
371
+ props.layout === "adaptive" &&
372
+ props.canHideViews &&
373
+ monitor.currentBreakpoint.value === "mobile"
374
+ ) {
375
+ return offScreenViewsTrailing.value.length > 0;
376
+ }
377
+ return false;
378
+ };
379
+
380
+ const getViewMinWidthOnscreen = (view: InternalView): string => {
381
+ if (props.layout === "navstack") {
382
+ return "";
383
+ }
384
+ if (
385
+ props.layout === "adaptive" &&
386
+ monitor.currentBreakpoint.value === "mobile"
387
+ ) {
388
+ return "";
389
+ }
390
+ return `${view.minWidth || 100}px`;
391
+ };
392
+ const getViewMaxWidthOnscreen = (view: InternalView): string => {
393
+ if (props.layout === "navstack") {
394
+ return "";
395
+ }
396
+ if (
397
+ props.layout === "adaptive" &&
398
+ monitor.currentBreakpoint.value === "mobile"
399
+ ) {
400
+ return "";
401
+ }
402
+ return `${view.maxWidth || Infinity}px`;
403
+ };
404
+ </script>
405
+
406
+ <template>
407
+ <div
408
+ ref="containerRef"
409
+ :class="$style.container"
410
+ :style="{
411
+ '--padding': props.padding,
412
+ '--gap': props.gap,
413
+ '--width': `${monitor.dimensions.value.width}px`,
414
+ }"
415
+ >
416
+ <div :id="getOnscreenId()" :class="$style.onscreen">
417
+ <div
418
+ v-for="(view, index) in onScreenViews"
419
+ :key="view.id"
420
+ :class="[
421
+ $style.viewWrapper,
422
+ {
423
+ [$style.lastView]: index === onScreenViews.length - 1,
424
+ },
425
+ ]"
426
+ :style="{
427
+ order: index,
428
+ minWidth: getViewMinWidthOnscreen(view),
429
+ maxWidth: getViewMaxWidthOnscreen(view),
430
+ width:
431
+ view.currentWidth && index < onScreenViews.length - 1
432
+ ? `${view.currentWidth}px`
433
+ : undefined,
434
+ flexShrink: index === onScreenViews.length - 1 ? 1 : 0,
435
+ }"
436
+ :id="getViewId(view)"
437
+ >
438
+ <!-- Toggle Button: Left -->
439
+ <div
440
+ v-if="shouldShowLeftHandle(index)"
441
+ :class="[$style.handle_container, $style.handle_container_left]"
442
+ @click="handleClicked(view)"
443
+ >
444
+ <div :class="$style.handle"></div>
445
+ </div>
446
+
447
+ <!-- Toggle Button: Right (Only for navstack layout) -->
448
+ <div
449
+ v-if="shouldShowRightHandle(index)"
450
+ :class="[$style.handle_container, $style.handle_container_right]"
451
+ @click="pushNavstack(view)"
452
+ >
453
+ <div :class="$style.handle"></div>
454
+ </div>
455
+
456
+ <!-- Component-->
457
+ <component :is="view.component" v-bind="view.props || {}" />
458
+
459
+ <!-- Resize handle (not on last element) -->
460
+ <div
461
+ v-if="props.canResizeViews && index < onScreenViews.length - 1"
462
+ :class="$style.resizeHandle"
463
+ @mousedown="startResize(view.id, $event)"
464
+ >
465
+ <div :class="$style.resizeHandleBar" />
466
+ </div>
467
+ </div>
468
+ </div>
469
+
470
+ <!-- Resize tooltip -->
471
+ <div
472
+ v-if="resizeTooltip.visible"
473
+ :class="$style.resizeTooltip"
474
+ :style="{
475
+ left: `${resizeTooltip.x}px`,
476
+ top: `${resizeTooltip.y}px`,
477
+ }"
478
+ >
479
+ {{ resizeTooltip.width }}px
480
+ </div>
481
+
482
+ <!-- Offscreen Leading -->
483
+ <div :id="getOffscreenLeadingId()" :class="$style.offscreenLeading">
484
+ <div
485
+ v-for="(view, index) in offScreenViewsLeading"
486
+ :key="view.id"
487
+ :class="$style.viewWrapper"
488
+ :style="{
489
+ order: index,
490
+ minWidth: `${view.minWidth || 100}px`,
491
+ maxWidth: view.maxWidth ? `${view.maxWidth}px` : undefined,
492
+ width: view.currentWidth ? `${view.currentWidth}px` : undefined,
493
+ flexShrink: 0,
494
+ }"
495
+ :id="getViewId(view)"
496
+ >
497
+ <component :is="view.component" v-bind="view.props || {}" />
498
+ </div>
499
+ </div>
500
+
501
+ <!-- Offscreen Trailing -->
502
+ <div :id="getOffscreenTrailingId()" :class="$style.offscreenTrailing">
503
+ <div
504
+ v-for="(view, index) in offScreenViewsTrailing"
505
+ :key="view.id"
506
+ :class="$style.viewWrapper"
507
+ :style="{
508
+ order: index,
509
+ minWidth: `${view.minWidth || 100}px`,
510
+ maxWidth: view.maxWidth ? `${view.maxWidth}px` : undefined,
511
+ width: view.currentWidth ? `${view.currentWidth}px` : undefined,
512
+ flexShrink: 0,
513
+ }"
514
+ :id="getViewId(view)"
515
+ >
516
+ <component :is="view.component" v-bind="view.props || {}" />
517
+ </div>
518
+ </div>
519
+
520
+ <!-- Darken -->
521
+ <div
522
+ :id="getDarkenId()"
523
+ :class="[$style.darken, { [$style.darkenVisible]: isOverlayOpen }]"
524
+ @click="darkenClicked"
525
+ ></div>
526
+
527
+ <!-- Overlay -->
528
+ <div :id="getOverlayId()" :class="$style.overlay">
529
+ <div
530
+ v-for="(view, index) in overlayViews"
531
+ :key="view.id"
532
+ :class="$style.viewWrapper"
533
+ :style="{
534
+ order: index,
535
+ minWidth: `${view.minWidth || 100}px`,
536
+ maxWidth: view.maxWidth ? `${view.maxWidth}px` : undefined,
537
+ width: view.currentWidth ? `${view.currentWidth}px` : undefined,
538
+ flexShrink: 0,
539
+ }"
540
+ :id="getViewId(view)"
541
+ >
542
+ <!-- Close/toggle button (not on first view unless there are offscreen views) -->
543
+ <div
544
+ v-if="
545
+ props.canHideViews &&
546
+ (index > 0 ||
547
+ (index === 0 &&
548
+ (offScreenViewsLeading.length > 0 ||
549
+ offScreenViewsTrailing.length > 0)))
550
+ "
551
+ :class="$style.handle_container"
552
+ @click="handleClicked(view)"
553
+ >
554
+ <div :class="$style.handle"></div>
555
+ </div>
556
+
557
+ <component :is="view.component" v-bind="view.props || {}" />
558
+ </div>
559
+ </div>
560
+ </div>
561
+ </template>
562
+
563
+ <style module>
564
+ .container {
565
+ width: 100%;
566
+ height: 100%;
567
+ position: relative;
568
+ overflow: hidden;
569
+ }
570
+
571
+ .offscreenLeading {
572
+ width: var(--width);
573
+ position: absolute;
574
+ top: 0;
575
+ left: calc(var(--width) * -1);
576
+ bottom: 0;
577
+
578
+ margin-top: var(--padding);
579
+ margin-bottom: var(--padding);
580
+
581
+ display: grid;
582
+ grid-template-columns: 1fr;
583
+ grid-template-rows: 1fr;
584
+ grid-template-areas: "content";
585
+ justify-items: end;
586
+ }
587
+
588
+ .offscreenLeading > * {
589
+ grid-area: content;
590
+ }
591
+
592
+ .offscreenTrailing {
593
+ width: var(--width);
594
+ position: absolute;
595
+ top: 0;
596
+ right: calc(var(--width) * -1);
597
+ bottom: 0;
598
+
599
+ margin-top: var(--padding);
600
+ margin-bottom: var(--padding);
601
+
602
+ display: grid;
603
+ grid-template-columns: 1fr;
604
+ grid-template-rows: 1fr;
605
+ grid-template-areas: "content";
606
+ justify-items: start;
607
+ }
608
+
609
+ .offscreenTrailing > * {
610
+ grid-area: content;
611
+ }
612
+
613
+ .onscreen {
614
+ position: absolute;
615
+ top: 0;
616
+ left: 0;
617
+ right: 0;
618
+ bottom: 0;
619
+ padding: var(--padding);
620
+ display: flex;
621
+ flex-direction: row;
622
+ gap: var(--gap);
623
+ height: 100%;
624
+ width: 100%;
625
+ box-sizing: border-box;
626
+ transition: filter 0.3s ease;
627
+ /*
628
+ overflow: hidden;
629
+ */
630
+ overflow: scroll;
631
+ max-width: 100%;
632
+ }
633
+ .overlay {
634
+ position: absolute;
635
+ top: 0;
636
+ left: 0;
637
+ bottom: 0;
638
+ pointer-events: none;
639
+ width: auto;
640
+ transition: opacity 3.3s ease;
641
+ transform: translateX(calc((110% + 10px) * -1));
642
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease;
643
+ z-index: 3;
644
+ display: flex;
645
+ flex-direction: row;
646
+ gap: var(--gap);
647
+ padding: var(--padding);
648
+ }
649
+ .darken {
650
+ position: absolute;
651
+ top: 0;
652
+ left: 0;
653
+ right: 0;
654
+ bottom: 0;
655
+ background-color: black;
656
+ background: rgba(0, 0, 0, 0.7);
657
+ backdrop-filter: blur(4px);
658
+ z-index: 2;
659
+ pointer-events: none;
660
+ opacity: 0;
661
+ transition: opacity 0.3s ease;
662
+ }
663
+
664
+ .darkenVisible {
665
+ opacity: 1;
666
+ pointer-events: auto;
667
+ }
668
+
669
+ .viewWrapper {
670
+ flex: 0 0 auto;
671
+ height: 100%;
672
+ box-sizing: border-box;
673
+ display: flex;
674
+ align-items: stretch;
675
+ position: relative;
676
+ overflow: hidden;
677
+ max-width: 100%;
678
+ }
679
+ .viewWrapper > *:not(.handle_container):not(.resizeHandle) {
680
+ width: 100%;
681
+ height: 100%;
682
+ }
683
+ .lastView {
684
+ flex: 1 1 auto;
685
+ /*min-width: 0; Allow the last view to shrink below its content size */
686
+ }
687
+
688
+ .handle_container {
689
+ width: 15px;
690
+ display: flex;
691
+ align-items: center;
692
+ justify-content: center;
693
+ height: 100%;
694
+ position: absolute;
695
+ top: 0;
696
+ bottom: 0;
697
+ z-index: 2;
698
+ }
699
+ .handle_container_left {
700
+ left: 0;
701
+ }
702
+ .handle_container_right {
703
+ right: 0;
704
+ }
705
+ .handle {
706
+ width: var(--slideover-handle-default-width, 4px);
707
+ height: var(--slideover-handle-default-height, 24px);
708
+ opacity: var(--slideover-handle-default-opacity, 0.3);
709
+ background-color: var(--slideover-handle-bg, #666);
710
+ border-radius: 999px;
711
+ transition: width 0.5s ease, height 0.5s ease, opacity 0.5s ease;
712
+ }
713
+
714
+ .handle_container:hover .handle {
715
+ width: var(--slideover-handle-hover-width, 6px);
716
+ height: var(--slideover-handle-hover-height, 32px);
717
+ opacity: var(--slideover-handle-hover-opacity, 0.6);
718
+ }
719
+
720
+ .resizeHandle {
721
+ position: absolute;
722
+ right: -5px;
723
+ top: 0;
724
+ bottom: 0;
725
+ width: 10px;
726
+ cursor: col-resize;
727
+ display: flex;
728
+ align-items: center;
729
+ justify-content: center;
730
+ z-index: 2;
731
+ }
732
+
733
+ .resizeHandle:hover .resizeHandleBar {
734
+ background: #4a5568;
735
+ opacity: 0.5;
736
+ }
737
+
738
+ .resizeHandleBar {
739
+ width: 2px;
740
+ height: 30%;
741
+ background: transparent;
742
+ border-radius: 999px;
743
+ transition: all 0.2s ease;
744
+ }
745
+
746
+ .resizeHandle:active .resizeHandleBar {
747
+ background: var(--accent);
748
+ opacity: 0.8;
749
+ height: 100%;
750
+ }
751
+
752
+ .resizeTooltip {
753
+ position: fixed;
754
+ background: #2d3748;
755
+ color: white;
756
+ padding: 4px 8px;
757
+ border-radius: 4px;
758
+ font-size: 12px;
759
+ font-weight: 500;
760
+ pointer-events: none;
761
+ z-index: 1000;
762
+ transform: translateX(-50%);
763
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
764
+ white-space: nowrap;
765
+ }
766
+
767
+ .resizeTooltip::after {
768
+ content: "";
769
+ position: absolute;
770
+ top: 100%;
771
+ left: 50%;
772
+ transform: translateX(-50%);
773
+ width: 0;
774
+ height: 0;
775
+ border-left: 4px solid transparent;
776
+ border-right: 4px solid transparent;
777
+ border-top: 4px solid #2d3748;
778
+ }
779
+ </style>