@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,1115 @@
1
+ # SplitViewController
2
+
3
+ A powerful split-view navigation component built with Vue 3 Composition API and TypeScript. The SplitViewController provides smooth, animated transitions between different views using GSAP's FLIP (First, Last, Invert, Play) animation technique, creating an intuitive side-by-side interface perfect for desktop applications and complex layouts.
4
+
5
+ ## Installation/Import
6
+
7
+ ```typescript
8
+ import { SplitViewController, useSplitViewController } from "@umbra-ui/core";
9
+ import type { Pane } from "@umbra-ui/core";
10
+ ```
11
+
12
+ **Dependencies:**
13
+
14
+ - Vue 3.x
15
+ - gsap (for animations)
16
+ - gsap/Flip (for FLIP animations)
17
+
18
+ ## Basic Usage
19
+
20
+ ```vue
21
+ <script setup lang="ts">
22
+ import { ref } from "vue";
23
+ import { SplitViewController } from "@umbra-ui/core";
24
+ import SidebarView from "./SidebarView.vue";
25
+ import ContentView from "./ContentView.vue";
26
+ import DetailsView from "./DetailsView.vue";
27
+
28
+ // Define your split-view panes
29
+ const panes = ref([
30
+ {
31
+ name: "Sidebar",
32
+ background: "#ffffff",
33
+ foreground: "#000000",
34
+ component: SidebarView,
35
+ props: { title: "Navigation" },
36
+ },
37
+ {
38
+ name: "Content",
39
+ background: "#f8f9fa",
40
+ foreground: "#212529",
41
+ component: ContentView,
42
+ props: { section: "main" },
43
+ },
44
+ {
45
+ name: "Details",
46
+ background: "#e9ecef",
47
+ foreground: "#495057",
48
+ component: DetailsView,
49
+ props: { item: null },
50
+ },
51
+ ]);
52
+
53
+ const splitviewRef = ref();
54
+
55
+ // Navigate to specific pane
56
+ const goToPane = (index: number) => {
57
+ splitviewRef.value?.navigate(index);
58
+ };
59
+
60
+ // Show all panes
61
+ const showAllPanes = () => {
62
+ splitviewRef.value?.showAll();
63
+ };
64
+
65
+ // Hide all panes except the last one
66
+ const hideAllPanes = () => {
67
+ splitviewRef.value?.hideAll();
68
+ };
69
+
70
+ // Toggle specific pane
71
+ const togglePane = (index: number) => {
72
+ splitviewRef.value?.togglePane(index);
73
+ };
74
+ </script>
75
+
76
+ <template>
77
+ <div class="app">
78
+ <div class="navigation-controls">
79
+ <button @click="goToPane(0)">Sidebar</button>
80
+ <button @click="goToPane(1)">Content</button>
81
+ <button @click="goToPane(2)">Details</button>
82
+ <button @click="showAllPanes">Show All</button>
83
+ <button @click="hideAllPanes">Hide All</button>
84
+ </div>
85
+
86
+ <SplitViewController
87
+ ref="splitviewRef"
88
+ :panes="panes"
89
+ component-id="main-splitview"
90
+ />
91
+ </div>
92
+ </template>
93
+
94
+ <style module>
95
+ .app {
96
+ height: 100vh;
97
+ display: flex;
98
+ flex-direction: column;
99
+ }
100
+
101
+ .navigation-controls {
102
+ display: flex;
103
+ gap: 12px;
104
+ padding: 16px;
105
+ background: var(--background-1);
106
+ border-bottom: 1px solid var(--border-2);
107
+ }
108
+
109
+ .navigation-controls button {
110
+ padding: 8px 16px;
111
+ border: 1px solid var(--border-2);
112
+ background: var(--background-2);
113
+ color: var(--text-1);
114
+ border-radius: 6px;
115
+ cursor: pointer;
116
+ transition: all 0.2s ease;
117
+ }
118
+
119
+ .navigation-controls button:hover {
120
+ background: var(--background-3);
121
+ border-color: var(--border-3);
122
+ }
123
+ </style>
124
+ ```
125
+
126
+ ## Props
127
+
128
+ | Prop Name | Type | Required | Default | Description |
129
+ | ------------- | ------------------------------------------- | -------- | -------------- | -------------------------------------------- |
130
+ | `panes` | `Pane[]` | Yes | - | Array of panes to display in the split-view |
131
+ | `controller` | `ReturnType<typeof useSplitViewController>` | No | - | External controller instance |
132
+ | `componentId` | `string` | No | Auto-generated | Unique identifier for the component instance |
133
+
134
+ ## Pane Interface
135
+
136
+ ```typescript
137
+ interface Pane {
138
+ name: string;
139
+ background: string;
140
+ foreground: string;
141
+ component: any;
142
+ props: Record<string, any>;
143
+ }
144
+ ```
145
+
146
+ ### Pane Properties
147
+
148
+ | Property | Type | Description |
149
+ | ------------ | --------------------- | --------------------------------------- |
150
+ | `name` | `string` | Display name for the pane |
151
+ | `background` | `string` | Background color for the pane container |
152
+ | `foreground` | `string` | Text color for the pane content |
153
+ | `component` | `Component` | Vue component to render in the pane |
154
+ | `props` | `Record<string, any>` | Props to pass to the component |
155
+
156
+ ## Events
157
+
158
+ The SplitViewController component doesn't emit events directly, but you can access navigation methods through template refs.
159
+
160
+ ## Exposed Methods/Refs
161
+
162
+ | Method | Parameters | Description |
163
+ | ------------ | ------------------------------------- | ------------------------------------- |
164
+ | `navigate` | `(index: number, animated?: boolean)` | Navigate to show only a specific pane |
165
+ | `showPane` | `(index: number)` | Show a specific pane |
166
+ | `hidePane` | `(index: number)` | Hide a specific pane |
167
+ | `togglePane` | `(index: number)` | Toggle a pane at a specific index |
168
+ | `showAll` | `()` | Show all panes |
169
+ | `hideAll` | `()` | Hide all panes except the last one |
170
+
171
+ ## useSplitViewController Composable
172
+
173
+ The `useSplitViewController` composable provides the core split-view logic and can be used independently:
174
+
175
+ ```typescript
176
+ import { useSplitViewController } from "@umbra-ui/core";
177
+
178
+ const {
179
+ visiblePanes,
180
+ currentPaneIndex,
181
+ lastVisibilityEvent,
182
+ showPane,
183
+ hidePane,
184
+ togglePane,
185
+ showAll,
186
+ hideAll,
187
+ navigate,
188
+ } = useSplitViewController(panes, componentId);
189
+ ```
190
+
191
+ ### Composable Returns
192
+
193
+ | Property | Type | Description |
194
+ | --------------------- | ------------------------------------------------------ | ------------------------------------------------- |
195
+ | `visiblePanes` | `Ref<boolean[]>` | Reactive array indicating which panes are visible |
196
+ | `currentPaneIndex` | `ComputedRef<number>` | Current active pane index |
197
+ | `lastVisibilityEvent` | `Ref<{type: "show" \| "hide", index: number} \| null>` | Last visibility change event |
198
+ | `showPane` | `(index: number) => void` | Show specific pane |
199
+ | `hidePane` | `(index: number) => void` | Hide specific pane |
200
+ | `togglePane` | `(index: number) => void` | Toggle pane at specific index |
201
+ | `showAll` | `() => void` | Show all panes |
202
+ | `hideAll` | `() => void` | Hide all panes except the last one |
203
+ | `navigate` | `(index: number, animated?: boolean) => void` | Navigate to specific pane |
204
+
205
+ ## CSS Customization
206
+
207
+ ### Layout Variables
208
+
209
+ ```css
210
+ .splitview-controller {
211
+ --splitview-handle-default-width: 4px;
212
+ --splitview-handle-default-height: 24px;
213
+ --splitview-handle-default-opacity: 0.3;
214
+ --splitview-handle-bg: #666;
215
+ --splitview-handle-hover-width: 6px;
216
+ --splitview-handle-hover-height: 32px;
217
+ --splitview-handle-hover-opacity: 0.6;
218
+ }
219
+ ```
220
+
221
+ ### Container Styling
222
+
223
+ ```css
224
+ .splitview-controller {
225
+ position: relative;
226
+ display: grid;
227
+ grid-template-areas: "content";
228
+ height: 100%;
229
+ width: 100%;
230
+ overflow: hidden;
231
+ }
232
+
233
+ .splitview-controller .onscreen {
234
+ grid-area: content;
235
+ display: flex;
236
+ height: 100%;
237
+ }
238
+ ```
239
+
240
+ ### Pane Styling
241
+
242
+ ```css
243
+ .splitview-controller .pane {
244
+ display: grid;
245
+ grid-template-columns: 1fr;
246
+ grid-template-areas: "content";
247
+ height: 100%;
248
+ flex: 0 0 auto;
249
+ }
250
+
251
+ .splitview-controller .pane_full {
252
+ flex: 1 1 auto;
253
+ min-width: 0;
254
+ }
255
+ ```
256
+
257
+ ## Examples
258
+
259
+ ### File Manager Interface
260
+
261
+ ```vue
262
+ <script setup lang="ts">
263
+ import { ref } from "vue";
264
+ import { SplitViewController } from "@umbra-ui/core";
265
+ import FileTree from "./FileTree.vue";
266
+ import FileList from "./FileList.vue";
267
+ import FilePreview from "./FilePreview.vue";
268
+
269
+ const panes = ref([
270
+ {
271
+ name: "Tree",
272
+ background: "#ffffff",
273
+ foreground: "#1a202c",
274
+ component: FileTree,
275
+ props: { rootPath: "/" },
276
+ },
277
+ {
278
+ name: "List",
279
+ background: "#f7fafc",
280
+ foreground: "#2d3748",
281
+ component: FileList,
282
+ props: { currentPath: "/documents" },
283
+ },
284
+ {
285
+ name: "Preview",
286
+ background: "#edf2f7",
287
+ foreground: "#4a5568",
288
+ component: FilePreview,
289
+ props: { selectedFile: null },
290
+ },
291
+ ]);
292
+
293
+ const splitviewRef = ref();
294
+
295
+ const handleFileSelect = (file: any) => {
296
+ // Navigate to preview pane
297
+ splitviewRef.value?.navigate(2);
298
+ };
299
+
300
+ const handleFolderSelect = (folder: any) => {
301
+ // Navigate to file list pane
302
+ splitviewRef.value?.navigate(1);
303
+ };
304
+
305
+ const toggleTree = () => {
306
+ splitviewRef.value?.togglePane(0);
307
+ };
308
+
309
+ const toggleList = () => {
310
+ splitviewRef.value?.togglePane(1);
311
+ };
312
+ </script>
313
+
314
+ <template>
315
+ <div class="file-manager">
316
+ <!-- Toolbar -->
317
+ <div class="file-toolbar">
318
+ <div class="toolbar-section">
319
+ <button @click="splitviewRef?.showAll()" class="toolbar-btn">
320
+ Show All Panes
321
+ </button>
322
+ <button @click="splitviewRef?.hideAll()" class="toolbar-btn">
323
+ Hide All Panes
324
+ </button>
325
+ </div>
326
+
327
+ <div class="toolbar-section">
328
+ <button @click="toggleTree" class="toolbar-btn">Toggle Tree</button>
329
+ <button @click="toggleList" class="toolbar-btn">Toggle List</button>
330
+ <button @click="splitviewRef?.navigate(2)" class="toolbar-btn">
331
+ Preview Only
332
+ </button>
333
+ </div>
334
+ </div>
335
+
336
+ <!-- Split View Controller -->
337
+ <SplitViewController
338
+ ref="splitviewRef"
339
+ :panes="panes"
340
+ component-id="file-manager"
341
+ />
342
+ </div>
343
+ </template>
344
+
345
+ <style module>
346
+ .file-manager {
347
+ height: 100vh;
348
+ display: flex;
349
+ flex-direction: column;
350
+ background: #f8f9fa;
351
+ }
352
+
353
+ .file-toolbar {
354
+ display: flex;
355
+ justify-content: space-between;
356
+ align-items: center;
357
+ padding: 12px 16px;
358
+ background: white;
359
+ border-bottom: 1px solid #e9ecef;
360
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
361
+ }
362
+
363
+ .toolbar-section {
364
+ display: flex;
365
+ gap: 8px;
366
+ }
367
+
368
+ .toolbar-btn {
369
+ padding: 6px 12px;
370
+ border: 1px solid #dee2e6;
371
+ background: white;
372
+ color: #495057;
373
+ border-radius: 4px;
374
+ cursor: pointer;
375
+ font-size: 14px;
376
+ transition: all 0.2s ease;
377
+ }
378
+
379
+ .toolbar-btn:hover {
380
+ background: #f8f9fa;
381
+ border-color: #adb5bd;
382
+ }
383
+ </style>
384
+ ```
385
+
386
+ ### Code Editor Interface
387
+
388
+ ```vue
389
+ <script setup lang="ts">
390
+ import { ref } from "vue";
391
+ import { SplitViewController } from "@umbra-ui/core";
392
+ import FileExplorer from "./FileExplorer.vue";
393
+ import CodeEditor from "./CodeEditor.vue";
394
+ import Terminal from "./Terminal.vue";
395
+
396
+ const panes = ref([
397
+ {
398
+ name: "Explorer",
399
+ background: "#1e1e1e",
400
+ foreground: "#cccccc",
401
+ component: FileExplorer,
402
+ props: { theme: "dark" },
403
+ },
404
+ {
405
+ name: "Editor",
406
+ background: "#2d2d30",
407
+ foreground: "#cccccc",
408
+ component: CodeEditor,
409
+ props: { language: "typescript" },
410
+ },
411
+ {
412
+ name: "Terminal",
413
+ background: "#0c0c0c",
414
+ foreground: "#00ff00",
415
+ component: Terminal,
416
+ props: { shell: "bash" },
417
+ },
418
+ ]);
419
+
420
+ const splitviewRef = ref();
421
+ const currentFile = ref(null);
422
+
423
+ const openFile = (file: any) => {
424
+ currentFile.value = file;
425
+ // Ensure editor is visible
426
+ splitviewRef.value?.navigate(1);
427
+ };
428
+
429
+ const toggleExplorer = () => {
430
+ splitviewRef.value?.togglePane(0);
431
+ };
432
+
433
+ const toggleTerminal = () => {
434
+ splitviewRef.value?.togglePane(2);
435
+ };
436
+
437
+ const focusEditor = () => {
438
+ splitviewRef.value?.navigate(1);
439
+ };
440
+
441
+ const showAllPanels = () => {
442
+ splitviewRef.value?.showAll();
443
+ };
444
+ </script>
445
+
446
+ <template>
447
+ <div class="code-editor">
448
+ <!-- Editor Header -->
449
+ <header class="editor-header">
450
+ <div class="header-left">
451
+ <button @click="toggleExplorer" class="header-btn">📁 Explorer</button>
452
+ <button @click="focusEditor" class="header-btn">✏️ Editor</button>
453
+ <button @click="toggleTerminal" class="header-btn">💻 Terminal</button>
454
+ </div>
455
+
456
+ <div class="header-right">
457
+ <button @click="showAllPanels" class="header-btn">Show All</button>
458
+ <span v-if="currentFile" class="current-file">
459
+ {{ currentFile.name }}
460
+ </span>
461
+ </div>
462
+ </header>
463
+
464
+ <!-- Split View Controller -->
465
+ <SplitViewController
466
+ ref="splitviewRef"
467
+ :panes="panes"
468
+ component-id="code-editor"
469
+ />
470
+ </div>
471
+ </template>
472
+
473
+ <style module>
474
+ .code-editor {
475
+ height: 100vh;
476
+ display: flex;
477
+ flex-direction: column;
478
+ background: #1e1e1e;
479
+ color: #cccccc;
480
+ }
481
+
482
+ .editor-header {
483
+ display: flex;
484
+ justify-content: space-between;
485
+ align-items: center;
486
+ padding: 8px 16px;
487
+ background: #2d2d30;
488
+ border-bottom: 1px solid #3e3e42;
489
+ }
490
+
491
+ .header-left {
492
+ display: flex;
493
+ gap: 8px;
494
+ }
495
+
496
+ .header-right {
497
+ display: flex;
498
+ align-items: center;
499
+ gap: 12px;
500
+ }
501
+
502
+ .header-btn {
503
+ padding: 6px 12px;
504
+ background: transparent;
505
+ border: 1px solid #3e3e42;
506
+ color: #cccccc;
507
+ border-radius: 4px;
508
+ cursor: pointer;
509
+ font-size: 14px;
510
+ transition: all 0.2s ease;
511
+ }
512
+
513
+ .header-btn:hover {
514
+ background: #3e3e42;
515
+ border-color: #007acc;
516
+ }
517
+
518
+ .current-file {
519
+ font-size: 14px;
520
+ color: #007acc;
521
+ font-weight: 500;
522
+ }
523
+ </style>
524
+ ```
525
+
526
+ ### Dashboard Layout
527
+
528
+ ```vue
529
+ <script setup lang="ts">
530
+ import { ref } from "vue";
531
+ import { SplitViewController } from "@umbra-ui/core";
532
+ import Sidebar from "./Sidebar.vue";
533
+ import MainContent from "./MainContent.vue";
534
+ import RightPanel from "./RightPanel.vue";
535
+
536
+ const panes = ref([
537
+ {
538
+ name: "Sidebar",
539
+ background: "#f8f9fa",
540
+ foreground: "#495057",
541
+ component: Sidebar,
542
+ props: { collapsed: false },
543
+ },
544
+ {
545
+ name: "Content",
546
+ background: "#ffffff",
547
+ foreground: "#212529",
548
+ component: MainContent,
549
+ props: { section: "dashboard" },
550
+ },
551
+ {
552
+ name: "Panel",
553
+ background: "#e9ecef",
554
+ foreground: "#495057",
555
+ component: RightPanel,
556
+ props: { type: "info" },
557
+ },
558
+ ]);
559
+
560
+ const splitviewRef = ref();
561
+ const sidebarCollapsed = ref(false);
562
+
563
+ const toggleSidebar = () => {
564
+ sidebarCollapsed.value = !sidebarCollapsed.value;
565
+ if (sidebarCollapsed.value) {
566
+ splitviewRef.value?.hidePane(0);
567
+ } else {
568
+ splitviewRef.value?.showPane(0);
569
+ }
570
+ };
571
+
572
+ const toggleRightPanel = () => {
573
+ splitviewRef.value?.togglePane(2);
574
+ };
575
+
576
+ const showAllPanels = () => {
577
+ splitviewRef.value?.showAll();
578
+ };
579
+
580
+ const focusContent = () => {
581
+ splitviewRef.value?.navigate(1);
582
+ };
583
+ </script>
584
+
585
+ <template>
586
+ <div class="dashboard-layout">
587
+ <!-- Top Navigation -->
588
+ <nav class="top-nav">
589
+ <div class="nav-left">
590
+ <button @click="toggleSidebar" class="nav-btn">
591
+ {{ sidebarCollapsed ? "☰" : "✕" }}
592
+ </button>
593
+ <h1 class="nav-title">Dashboard</h1>
594
+ </div>
595
+
596
+ <div class="nav-center">
597
+ <button @click="focusContent" class="nav-btn">Home</button>
598
+ <button @click="splitviewRef?.navigate(1)" class="nav-btn">
599
+ Analytics
600
+ </button>
601
+ <button @click="splitviewRef?.navigate(1)" class="nav-btn">
602
+ Reports
603
+ </button>
604
+ </div>
605
+
606
+ <div class="nav-right">
607
+ <button @click="toggleRightPanel" class="nav-btn">Panel</button>
608
+ <button @click="showAllPanels" class="nav-btn">Show All</button>
609
+ </div>
610
+ </nav>
611
+
612
+ <!-- Split View Controller -->
613
+ <SplitViewController
614
+ ref="splitviewRef"
615
+ :panes="panes"
616
+ component-id="dashboard-splitview"
617
+ />
618
+ </div>
619
+ </template>
620
+
621
+ <style module>
622
+ .dashboard-layout {
623
+ height: 100vh;
624
+ display: flex;
625
+ flex-direction: column;
626
+ background: #f8f9fa;
627
+ }
628
+
629
+ .top-nav {
630
+ display: flex;
631
+ justify-content: space-between;
632
+ align-items: center;
633
+ padding: 12px 20px;
634
+ background: white;
635
+ border-bottom: 1px solid #dee2e6;
636
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
637
+ }
638
+
639
+ .nav-left {
640
+ display: flex;
641
+ align-items: center;
642
+ gap: 16px;
643
+ }
644
+
645
+ .nav-center {
646
+ display: flex;
647
+ gap: 8px;
648
+ }
649
+
650
+ .nav-right {
651
+ display: flex;
652
+ gap: 8px;
653
+ }
654
+
655
+ .nav-btn {
656
+ padding: 8px 16px;
657
+ background: transparent;
658
+ border: 1px solid #dee2e6;
659
+ color: #495057;
660
+ border-radius: 6px;
661
+ cursor: pointer;
662
+ font-size: 14px;
663
+ transition: all 0.2s ease;
664
+ }
665
+
666
+ .nav-btn:hover {
667
+ background: #f8f9fa;
668
+ border-color: #adb5bd;
669
+ }
670
+
671
+ .nav-title {
672
+ font-size: 20px;
673
+ font-weight: 600;
674
+ color: #212529;
675
+ margin: 0;
676
+ }
677
+ </style>
678
+ ```
679
+
680
+ ### Settings Interface
681
+
682
+ ```vue
683
+ <script setup lang="ts">
684
+ import { ref } from "vue";
685
+ import { SplitViewController } from "@umbra-ui/core";
686
+ import SettingsNav from "./SettingsNav.vue";
687
+ import SettingsContent from "./SettingsContent.vue";
688
+ import SettingsPreview from "./SettingsPreview.vue";
689
+
690
+ const panes = ref([
691
+ {
692
+ name: "Navigation",
693
+ background: "#ffffff",
694
+ foreground: "#1a202c",
695
+ component: SettingsNav,
696
+ props: { currentSection: "general" },
697
+ },
698
+ {
699
+ name: "Content",
700
+ background: "#f7fafc",
701
+ foreground: "#2d3748",
702
+ component: SettingsContent,
703
+ props: { section: "general" },
704
+ },
705
+ {
706
+ name: "Preview",
707
+ background: "#edf2f7",
708
+ foreground: "#4a5568",
709
+ component: SettingsPreview,
710
+ props: { theme: "light" },
711
+ },
712
+ ]);
713
+
714
+ const splitviewRef = ref();
715
+ const currentSection = ref("general");
716
+
717
+ const navigateToSection = (section: string) => {
718
+ currentSection.value = section;
719
+ // Update props for content pane
720
+ panes.value[1].props.section = section;
721
+ panes.value[0].props.currentSection = section;
722
+
723
+ // Ensure content is visible
724
+ splitviewRef.value?.navigate(1);
725
+ };
726
+
727
+ const togglePreview = () => {
728
+ splitviewRef.value?.togglePane(2);
729
+ };
730
+
731
+ const showAllSections = () => {
732
+ splitviewRef.value?.showAll();
733
+ };
734
+
735
+ const hideNavigation = () => {
736
+ splitviewRef.value?.hidePane(0);
737
+ };
738
+ </script>
739
+
740
+ <template>
741
+ <div class="settings-interface">
742
+ <!-- Settings Header -->
743
+ <header class="settings-header">
744
+ <h1 class="settings-title">Settings</h1>
745
+ <div class="settings-actions">
746
+ <button @click="showAllSections" class="action-btn">Show All</button>
747
+ <button @click="hideNavigation" class="action-btn">Hide Nav</button>
748
+ <button @click="togglePreview" class="action-btn">
749
+ Toggle Preview
750
+ </button>
751
+ </div>
752
+ </header>
753
+
754
+ <!-- Quick Navigation -->
755
+ <div class="quick-nav">
756
+ <button
757
+ v-for="section in ['general', 'appearance', 'privacy', 'advanced']"
758
+ :key="section"
759
+ @click="navigateToSection(section)"
760
+ :class="['quick-nav-btn', { active: currentSection === section }]"
761
+ >
762
+ {{ section.charAt(0).toUpperCase() + section.slice(1) }}
763
+ </button>
764
+ </div>
765
+
766
+ <!-- Split View Controller -->
767
+ <SplitViewController
768
+ ref="splitviewRef"
769
+ :panes="panes"
770
+ component-id="settings-splitview"
771
+ />
772
+ </div>
773
+ </template>
774
+
775
+ <style module>
776
+ .settings-interface {
777
+ height: 100vh;
778
+ display: flex;
779
+ flex-direction: column;
780
+ background: #f8f9fa;
781
+ }
782
+
783
+ .settings-header {
784
+ display: flex;
785
+ justify-content: space-between;
786
+ align-items: center;
787
+ padding: 20px 24px;
788
+ background: white;
789
+ border-bottom: 1px solid #e9ecef;
790
+ }
791
+
792
+ .settings-title {
793
+ font-size: 28px;
794
+ font-weight: 700;
795
+ color: #1a202c;
796
+ margin: 0;
797
+ }
798
+
799
+ .settings-actions {
800
+ display: flex;
801
+ gap: 8px;
802
+ }
803
+
804
+ .action-btn {
805
+ padding: 8px 16px;
806
+ background: #f8f9fa;
807
+ border: 1px solid #dee2e6;
808
+ color: #495057;
809
+ border-radius: 6px;
810
+ cursor: pointer;
811
+ font-size: 14px;
812
+ transition: all 0.2s ease;
813
+ }
814
+
815
+ .action-btn:hover {
816
+ background: #e9ecef;
817
+ border-color: #adb5bd;
818
+ }
819
+
820
+ .quick-nav {
821
+ display: flex;
822
+ gap: 4px;
823
+ padding: 12px 24px;
824
+ background: white;
825
+ border-bottom: 1px solid #e9ecef;
826
+ }
827
+
828
+ .quick-nav-btn {
829
+ padding: 8px 16px;
830
+ background: transparent;
831
+ border: 1px solid transparent;
832
+ color: #6c757d;
833
+ border-radius: 6px;
834
+ cursor: pointer;
835
+ font-size: 14px;
836
+ font-weight: 500;
837
+ transition: all 0.2s ease;
838
+ text-transform: capitalize;
839
+ }
840
+
841
+ .quick-nav-btn:hover {
842
+ background: #f8f9fa;
843
+ color: #495057;
844
+ }
845
+
846
+ .quick-nav-btn.active {
847
+ background: #e3f2fd;
848
+ color: #1976d2;
849
+ border-color: #bbdefb;
850
+ }
851
+ </style>
852
+ ```
853
+
854
+ ## Advanced Usage
855
+
856
+ ### Custom Controller Integration
857
+
858
+ ```vue
859
+ <script setup lang="ts">
860
+ import { ref } from "vue";
861
+ import { SplitViewController, useSplitViewController } from "@umbra-ui/core";
862
+
863
+ const panes = ref([
864
+ // ... your panes
865
+ ]);
866
+
867
+ // Create custom controller
868
+ const customController = useSplitViewController(
869
+ panes.value,
870
+ "custom-splitview"
871
+ );
872
+
873
+ // Override methods with custom logic
874
+ const customNavigate = (index: number, animated: boolean = true) => {
875
+ console.log(`Navigating to pane ${index}`);
876
+ customController.navigate(index, animated);
877
+ };
878
+
879
+ const customShowAll = () => {
880
+ console.log("Showing all panes");
881
+ customController.showAll();
882
+ };
883
+ </script>
884
+
885
+ <template>
886
+ <SplitViewController
887
+ :panes="panes"
888
+ :controller="customController"
889
+ component-id="custom-splitview"
890
+ />
891
+ </template>
892
+ ```
893
+
894
+ ### Integration with Router
895
+
896
+ ```vue
897
+ <script setup lang="ts">
898
+ import { ref, watch } from "vue";
899
+ import { useRoute, useRouter } from "vue-router";
900
+ import { SplitViewController } from "@umbra-ui/core";
901
+
902
+ const route = useRoute();
903
+ const router = useRouter();
904
+ const splitviewRef = ref();
905
+
906
+ const panes = ref([
907
+ // ... your panes
908
+ ]);
909
+
910
+ // Sync with router
911
+ watch(
912
+ () => route.params.panel,
913
+ (newPanel) => {
914
+ const index = panes.value.findIndex((pane) => pane.name === newPanel);
915
+ if (index !== -1) {
916
+ splitviewRef.value?.navigate(index);
917
+ }
918
+ }
919
+ );
920
+
921
+ const handleNavigation = (index: number) => {
922
+ const pane = panes.value[index];
923
+ router.push(`/dashboard/${pane.name.toLowerCase()}`);
924
+ };
925
+ </script>
926
+ ```
927
+
928
+ ### Dynamic Pane Management
929
+
930
+ ```vue
931
+ <script setup lang="ts">
932
+ import { ref } from "vue";
933
+ import { SplitViewController } from "@umbra-ui/core";
934
+ import DynamicPane from "./DynamicPane.vue";
935
+
936
+ const panes = ref([
937
+ {
938
+ name: "Main",
939
+ background: "#ffffff",
940
+ foreground: "#000000",
941
+ component: DynamicPane,
942
+ props: { content: "Main Content" },
943
+ },
944
+ ]);
945
+
946
+ const splitviewRef = ref();
947
+ const paneCounter = ref(1);
948
+
949
+ const addPane = () => {
950
+ const newPane = {
951
+ name: `Pane ${paneCounter.value}`,
952
+ background: `hsl(${Math.random() * 360}, 70%, 90%)`,
953
+ foreground: "#000000",
954
+ component: DynamicPane,
955
+ props: { content: `Dynamic Content ${paneCounter.value}` },
956
+ };
957
+
958
+ panes.value.push(newPane);
959
+ paneCounter.value++;
960
+ };
961
+
962
+ const removePane = (index: number) => {
963
+ if (panes.value.length > 1) {
964
+ panes.value.splice(index, 1);
965
+ }
966
+ };
967
+
968
+ const resetPanes = () => {
969
+ panes.value = [
970
+ {
971
+ name: "Main",
972
+ background: "#ffffff",
973
+ foreground: "#000000",
974
+ component: DynamicPane,
975
+ props: { content: "Main Content" },
976
+ },
977
+ ];
978
+ };
979
+ </script>
980
+
981
+ <template>
982
+ <div class="dynamic-splitview">
983
+ <!-- Controls -->
984
+ <div class="controls">
985
+ <button @click="addPane" class="control-btn add">Add Pane</button>
986
+ <button @click="resetPanes" class="control-btn reset">Reset</button>
987
+ </div>
988
+
989
+ <!-- Split View Controller -->
990
+ <SplitViewController
991
+ ref="splitviewRef"
992
+ :panes="panes"
993
+ component-id="dynamic-splitview"
994
+ />
995
+ </div>
996
+ </template>
997
+
998
+ <style module>
999
+ .dynamic-splitview {
1000
+ height: 100vh;
1001
+ display: flex;
1002
+ flex-direction: column;
1003
+ }
1004
+
1005
+ .controls {
1006
+ display: flex;
1007
+ gap: 12px;
1008
+ padding: 16px;
1009
+ background: var(--background-1);
1010
+ border-bottom: 1px solid var(--border-2);
1011
+ }
1012
+
1013
+ .control-btn {
1014
+ padding: 8px 16px;
1015
+ border: none;
1016
+ border-radius: 6px;
1017
+ font-weight: 500;
1018
+ cursor: pointer;
1019
+ transition: all 0.2s ease;
1020
+ }
1021
+
1022
+ .control-btn.add {
1023
+ background: #28a745;
1024
+ color: white;
1025
+ }
1026
+
1027
+ .control-btn.add:hover {
1028
+ background: #218838;
1029
+ }
1030
+
1031
+ .control-btn.reset {
1032
+ background: #6c757d;
1033
+ color: white;
1034
+ }
1035
+
1036
+ .control-btn.reset:hover {
1037
+ background: #5a6268;
1038
+ }
1039
+ </style>
1040
+ ```
1041
+
1042
+ ## Performance Considerations
1043
+
1044
+ - **Component Marking**: Always use `markRaw()` when passing components to prevent Vue's reactivity system from wrapping them
1045
+ - **Animation Performance**: GSAP FLIP animations are optimized for smooth 60fps performance
1046
+ - **Memory Management**: Panes are properly cleaned up when removed from the controller
1047
+ - **DOM Manipulation**: Efficient DOM manipulation using GSAP for optimal performance
1048
+
1049
+ ## Accessibility
1050
+
1051
+ - **Keyboard Navigation**: Support for arrow keys and tab navigation
1052
+ - **Screen Reader Support**: Proper ARIA labels and roles
1053
+ - **Focus Management**: Focus is maintained during transitions
1054
+ - **High Contrast**: Supports high contrast mode
1055
+
1056
+ ## Browser Support
1057
+
1058
+ - **Modern Browsers**: Chrome 88+, Firefox 85+, Safari 14+, Edge 88+
1059
+ - **Mobile Browsers**: iOS Safari 14+, Chrome Mobile 88+
1060
+ - **CSS Features**: Uses CSS Grid and modern layout features
1061
+ - **JavaScript**: Requires ES2020+ support
1062
+
1063
+ ## Troubleshooting
1064
+
1065
+ ### Common Issues
1066
+
1067
+ 1. **Animations not working**: Ensure GSAP and FLIP plugin are properly imported
1068
+ 2. **Panes not displaying**: Check that components are properly marked with `markRaw()`
1069
+ 3. **Navigation not responding**: Verify the `componentId` is unique and consistent
1070
+ 4. **Layout issues**: Ensure the container has a defined height
1071
+
1072
+ ### Debug Mode
1073
+
1074
+ ```vue
1075
+ <script setup lang="ts">
1076
+ import { ref, watch } from "vue";
1077
+ import { SplitViewController } from "@umbra-ui/core";
1078
+
1079
+ const splitviewRef = ref();
1080
+
1081
+ // Watch for navigation changes
1082
+ watch(
1083
+ () => splitviewRef.value?.currentPaneIndex,
1084
+ (newIndex) => {
1085
+ console.log("Current pane index:", newIndex);
1086
+ }
1087
+ );
1088
+
1089
+ // Watch for visibility events
1090
+ watch(
1091
+ () => splitviewRef.value?.lastVisibilityEvent,
1092
+ (event) => {
1093
+ if (event) {
1094
+ console.log("Visibility event:", event);
1095
+ }
1096
+ }
1097
+ );
1098
+ </script>
1099
+ ```
1100
+
1101
+ ## Migration Guide
1102
+
1103
+ ### From v1 to v2
1104
+
1105
+ - `componentId` prop is now optional with auto-generation
1106
+ - Pane interface has been updated with new properties
1107
+ - Animation system has been refactored for better performance
1108
+ - Composable API has been enhanced with new methods
1109
+
1110
+ ### Breaking Changes
1111
+
1112
+ - Removed automatic pane detection
1113
+ - Changed animation timing and easing
1114
+ - Updated CSS class structure
1115
+ - Modified event handling system