@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.
- package/dist/components/controls/Dropdown/types.d.ts +5 -0
- package/dist/components/controls/Dropdown/types.d.ts.map +1 -0
- package/dist/components/controls/Dropdown/types.js +1 -0
- package/dist/components/controls/SegmentedControl/types.d.ts +6 -0
- package/dist/components/controls/SegmentedControl/types.d.ts.map +1 -0
- package/dist/components/controls/SegmentedControl/types.js +1 -0
- package/dist/components/dialogs/Alert/types.d.ts +7 -0
- package/dist/components/dialogs/Alert/types.d.ts.map +1 -0
- package/dist/components/dialogs/Alert/types.js +1 -0
- package/dist/components/dialogs/Toast/types.d.ts +34 -0
- package/dist/components/dialogs/Toast/types.d.ts.map +1 -0
- package/dist/components/dialogs/Toast/types.js +10 -0
- package/dist/components/dialogs/Toast/useToast.d.ts +36 -0
- package/dist/components/dialogs/Toast/useToast.d.ts.map +1 -0
- package/dist/components/dialogs/Toast/useToast.js +90 -0
- package/dist/components/indicators/Tooltip/tooltip.d.ts +3 -0
- package/dist/components/indicators/Tooltip/tooltip.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/tooltip.js +33 -0
- package/dist/components/indicators/Tooltip/types.d.ts +14 -0
- package/dist/components/indicators/Tooltip/types.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/types.js +1 -0
- package/dist/components/indicators/Tooltip/useTooltip.d.ts +18 -0
- package/dist/components/indicators/Tooltip/useTooltip.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/useTooltip.js +57 -0
- package/dist/components/inputs/Tags/tag-bar-styles.d.ts +14 -0
- package/dist/components/inputs/Tags/tag-bar-styles.d.ts.map +1 -0
- package/dist/components/inputs/Tags/tag-bar-styles.js +313 -0
- package/dist/components/inputs/Tags/types.d.ts +93 -0
- package/dist/components/inputs/Tags/types.d.ts.map +1 -0
- package/dist/components/inputs/Tags/types.js +216 -0
- package/dist/components/inputs/search/types.d.ts +9 -0
- package/dist/components/inputs/search/types.d.ts.map +1 -0
- package/dist/components/inputs/search/types.js +1 -0
- package/dist/components/navigation/adaptive/types.d.ts +16 -0
- package/dist/components/navigation/adaptive/types.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/types.js +1 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts +27 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.js +40 -0
- package/dist/components/navigation/adaptive/useBreakpoints.d.ts +6 -0
- package/dist/components/navigation/adaptive/useBreakpoints.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useBreakpoints.js +37 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.d.ts +93 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.js +145 -0
- package/dist/components/navigation/adaptive/useViewAnimation.d.ts +31 -0
- package/dist/components/navigation/adaptive/useViewAnimation.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useViewAnimation.js +591 -0
- package/dist/components/navigation/adaptive/useViewResize.d.ts +52 -0
- package/dist/components/navigation/adaptive/useViewResize.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useViewResize.js +146 -0
- package/dist/components/navigation/navstack/useNavigationStack.d.ts +25 -0
- package/dist/components/navigation/navstack/useNavigationStack.d.ts.map +1 -0
- package/dist/components/navigation/navstack/useNavigationStack.js +133 -0
- package/dist/components/navigation/slideover/useSlideoverController.d.ts +20 -0
- package/dist/components/navigation/slideover/useSlideoverController.d.ts.map +1 -0
- package/dist/components/navigation/slideover/useSlideoverController.js +267 -0
- package/dist/components/navigation/splitview/useSplitViewController.d.ts +20 -0
- package/dist/components/navigation/splitview/useSplitViewController.d.ts.map +1 -0
- package/dist/components/navigation/splitview/useSplitViewController.js +325 -0
- package/dist/components/navigation/tabcontroller/types.d.ts +21 -0
- package/dist/components/navigation/tabcontroller/types.d.ts.map +1 -0
- package/dist/components/navigation/tabcontroller/types.js +1 -0
- package/dist/components/navigation/tabcontroller/useTabController.d.ts +5 -0
- package/dist/components/navigation/tabcontroller/useTabController.d.ts.map +1 -0
- package/dist/components/navigation/tabcontroller/useTabController.js +10 -0
- package/dist/components/navigation/types.d.ts +8 -0
- package/dist/components/navigation/types.d.ts.map +1 -0
- package/dist/components/navigation/types.js +1 -0
- package/dist/components/pickers/CollectionPicker/types.d.ts +11 -0
- package/dist/components/pickers/CollectionPicker/types.d.ts.map +1 -0
- package/dist/components/pickers/CollectionPicker/types.js +1 -0
- package/dist/components/pickers/ColorPicker/colors.d.ts +13 -0
- package/dist/components/pickers/ColorPicker/colors.d.ts.map +1 -0
- package/dist/components/pickers/ColorPicker/colors.js +266 -0
- package/dist/components/pickers/FilePicker/types.d.ts +10 -0
- package/dist/components/pickers/FilePicker/types.d.ts.map +1 -0
- package/dist/components/pickers/FilePicker/types.js +1 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +196 -0
- package/dist/theme.d.ts +73 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +279 -0
- package/dist/themes/blank.d.ts +7 -0
- package/dist/themes/blank.d.ts.map +1 -0
- package/dist/themes/blank.js +543 -0
- package/dist/themes/crimson-dark.d.ts +4 -0
- package/dist/themes/crimson-dark.d.ts.map +1 -0
- package/dist/themes/crimson-dark.js +552 -0
- package/dist/themes/cyan-light.d.ts +4 -0
- package/dist/themes/cyan-light.d.ts.map +1 -0
- package/dist/themes/cyan-light.js +552 -0
- package/dist/themes/dark.d.ts +4 -0
- package/dist/themes/dark.d.ts.map +1 -0
- package/dist/themes/dark.js +551 -0
- package/dist/themes/gold-dark.d.ts +4 -0
- package/dist/themes/gold-dark.d.ts.map +1 -0
- package/dist/themes/gold-dark.js +552 -0
- package/dist/themes/grass-dark.d.ts +4 -0
- package/dist/themes/grass-dark.d.ts.map +1 -0
- package/dist/themes/grass-dark.js +552 -0
- package/dist/themes/indigo.d.ts +4 -0
- package/dist/themes/indigo.d.ts.map +1 -0
- package/dist/themes/indigo.js +552 -0
- package/dist/themes/light.d.ts +4 -0
- package/dist/themes/light.d.ts.map +1 -0
- package/dist/themes/light.js +551 -0
- package/dist/themes/orange-dark.d.ts +4 -0
- package/dist/themes/orange-dark.d.ts.map +1 -0
- package/dist/themes/orange-dark.js +551 -0
- package/dist/themes/orange-light.d.ts +4 -0
- package/dist/themes/orange-light.d.ts.map +1 -0
- package/dist/themes/orange-light.js +551 -0
- package/package.json +62 -0
- package/src/components/controls/Button/Button.vue +417 -0
- package/src/components/controls/Button/README.md +348 -0
- package/src/components/controls/Button/theme.css +200 -0
- package/src/components/controls/Checkbox/Checkbox.vue +164 -0
- package/src/components/controls/Checkbox/README.md +441 -0
- package/src/components/controls/Checkbox/theme.css +36 -0
- package/src/components/controls/Dropdown/Dropdown.vue +476 -0
- package/src/components/controls/Dropdown/README.md +370 -0
- package/src/components/controls/Dropdown/theme.css +50 -0
- package/src/components/controls/Dropdown/types.ts +6 -0
- package/src/components/controls/IconButton/IconButton.vue +267 -0
- package/src/components/controls/IconButton/README.md +502 -0
- package/src/components/controls/IconButton/theme.css +89 -0
- package/src/components/controls/Radio/README.md +591 -0
- package/src/components/controls/Radio/Radio.vue +89 -0
- package/src/components/controls/Radio/theme.css +14 -0
- package/src/components/controls/RangeSlider/README.md +608 -0
- package/src/components/controls/RangeSlider/RangeSlider.vue +535 -0
- package/src/components/controls/RangeSlider/theme.css +80 -0
- package/src/components/controls/SegmentedControl/README.md +587 -0
- package/src/components/controls/SegmentedControl/SegmentedControl.vue +284 -0
- package/src/components/controls/SegmentedControl/theme.css +60 -0
- package/src/components/controls/SegmentedControl/types.ts +5 -0
- package/src/components/controls/Slider/README.md +627 -0
- package/src/components/controls/Slider/Slider.vue +260 -0
- package/src/components/controls/Slider/theme.css +74 -0
- package/src/components/controls/Stepper/README.md +601 -0
- package/src/components/controls/Stepper/Stepper.vue +103 -0
- package/src/components/controls/Stepper/theme.css +53 -0
- package/src/components/controls/Switch/README.md +667 -0
- package/src/components/controls/Switch/Switch.vue +127 -0
- package/src/components/controls/Switch/theme.css +42 -0
- package/src/components/dialogs/Alert/Alert.vue +218 -0
- package/src/components/dialogs/Alert/README.md +450 -0
- package/src/components/dialogs/Alert/theme.css +44 -0
- package/src/components/dialogs/Alert/types.ts +11 -0
- package/src/components/dialogs/Toast/README.md +522 -0
- package/src/components/dialogs/Toast/Toast.vue +296 -0
- package/src/components/dialogs/Toast/ToastContainer.vue +330 -0
- package/src/components/dialogs/Toast/theme.css +44 -0
- package/src/components/dialogs/Toast/types.ts +46 -0
- package/src/components/dialogs/Toast/useToast.ts +127 -0
- package/src/components/indicators/ProgressBar/ProgressBar.vue +98 -0
- package/src/components/indicators/ProgressBar/README.md +744 -0
- package/src/components/indicators/ProgressBar/theme.css +36 -0
- package/src/components/indicators/Tooltip/README.md +723 -0
- package/src/components/indicators/Tooltip/TooltipProvider.vue +142 -0
- package/src/components/indicators/Tooltip/theme.css +18 -0
- package/src/components/indicators/Tooltip/tooltip.ts +48 -0
- package/src/components/indicators/Tooltip/types.ts +15 -0
- package/src/components/indicators/Tooltip/useTooltip.ts +71 -0
- package/src/components/inputs/AutogrowTextView/AutogrowTextView.vue +110 -0
- package/src/components/inputs/AutogrowTextView/README.md +643 -0
- package/src/components/inputs/AutogrowTextView/theme.css +28 -0
- package/src/components/inputs/InputCard/InputCard.vue +600 -0
- package/src/components/inputs/InputCard/README.md +636 -0
- package/src/components/inputs/InputEmail/InputEmail.vue +698 -0
- package/src/components/inputs/InputEmail/README.md +764 -0
- package/src/components/inputs/InputNumber/InputNumber.vue +300 -0
- package/src/components/inputs/InputNumber/README.md +749 -0
- package/src/components/inputs/InputPhone/InputPhone.vue +645 -0
- package/src/components/inputs/InputPhone/README.md +636 -0
- package/src/components/inputs/InputSecure/InputSecure.vue +646 -0
- package/src/components/inputs/InputSecure/README.md +771 -0
- package/src/components/inputs/InputText/InputText.vue +225 -0
- package/src/components/inputs/InputText/README.md +844 -0
- package/src/components/inputs/OTP/OTP.vue +349 -0
- package/src/components/inputs/OTP/README.md +736 -0
- package/src/components/inputs/OTP/theme.css +50 -0
- package/src/components/inputs/StringCapture/README.md +718 -0
- package/src/components/inputs/StringCapture/StringCapture.vue +315 -0
- package/src/components/inputs/StringCapture/theme.css +86 -0
- package/src/components/inputs/Tags/README.md +897 -0
- package/src/components/inputs/Tags/TagBar.vue +793 -0
- package/src/components/inputs/Tags/TagCreation.vue +219 -0
- package/src/components/inputs/Tags/TagPicker.vue +380 -0
- package/src/components/inputs/Tags/tag-bar-styles.ts +354 -0
- package/src/components/inputs/Tags/theme.css +121 -0
- package/src/components/inputs/Tags/types.ts +346 -0
- package/src/components/inputs/search/README.md +759 -0
- package/src/components/inputs/search/SearchBar.vue +394 -0
- package/src/components/inputs/search/SearchResults.vue +310 -0
- package/src/components/inputs/search/theme.css +187 -0
- package/src/components/inputs/search/types.ts +8 -0
- package/src/components/inputs/theme.css +102 -0
- package/src/components/menus/ActionMenu/ActionMenu.vue +383 -0
- package/src/components/menus/ActionMenu/README.md +825 -0
- package/src/components/menus/ActionMenu/theme.css +93 -0
- package/src/components/models/Popover/Popover.vue +551 -0
- package/src/components/models/Popover/README.md +885 -0
- package/src/components/models/Popover/theme.css +52 -0
- package/src/components/models/Sheet/README.md +1159 -0
- package/src/components/models/Sheet/Sheet.vue +465 -0
- package/src/components/models/Sheet/theme.css +72 -0
- package/src/components/models/Sidebar/README.md +1228 -0
- package/src/components/models/Sidebar/Sidebar.vue +480 -0
- package/src/components/models/Sidebar/theme.css +90 -0
- package/src/components/navigation/adaptive/AdaptiveLayout.vue +779 -0
- package/src/components/navigation/adaptive/AdaptiveLayoutBreadcrumbs.vue +192 -0
- package/src/components/navigation/adaptive/AdaptiveLayoutMenuButton.vue +149 -0
- package/src/components/navigation/adaptive/README.md +768 -0
- package/src/components/navigation/adaptive/types.ts +19 -0
- package/src/components/navigation/adaptive/useAdaptiveLayout.ts +89 -0
- package/src/components/navigation/adaptive/useBreakpoints.ts +41 -0
- package/src/components/navigation/adaptive/useContainerMonitor.ts +214 -0
- package/src/components/navigation/adaptive/useViewAnimation.ts +721 -0
- package/src/components/navigation/adaptive/useViewResize.ts +211 -0
- package/src/components/navigation/navstack/NavigationStack.vue +180 -0
- package/src/components/navigation/navstack/README.md +994 -0
- package/src/components/navigation/navstack/useNavigationStack.ts +164 -0
- package/src/components/navigation/slideover/README.md +1275 -0
- package/src/components/navigation/slideover/SlideoverController.vue +287 -0
- package/src/components/navigation/slideover/useSlideoverController.ts +320 -0
- package/src/components/navigation/splitview/README.md +1115 -0
- package/src/components/navigation/splitview/SplitViewController.vue +176 -0
- package/src/components/navigation/splitview/useSplitViewController.ts +388 -0
- package/src/components/navigation/tabcontroller/README.md +919 -0
- package/src/components/navigation/tabcontroller/TabController.vue +307 -0
- package/src/components/navigation/tabcontroller/TabItem.vue +57 -0
- package/src/components/navigation/tabcontroller/types.ts +24 -0
- package/src/components/navigation/tabcontroller/useTabController.ts +18 -0
- package/src/components/navigation/theme.css +91 -0
- package/src/components/navigation/types.ts +7 -0
- package/src/components/pickers/CollectionPicker/CollectionPicker.vue +398 -0
- package/src/components/pickers/CollectionPicker/README.md +1115 -0
- package/src/components/pickers/CollectionPicker/theme.css +14 -0
- package/src/components/pickers/CollectionPicker/types.ts +11 -0
- package/src/components/pickers/ColorPicker/ColorPicker.vue +376 -0
- package/src/components/pickers/ColorPicker/README.md +1439 -0
- package/src/components/pickers/ColorPicker/colors.ts +299 -0
- package/src/components/pickers/ColorPicker/theme.css +32 -0
- package/src/components/pickers/DatePicker/DatePicker.vue +660 -0
- package/src/components/pickers/DatePicker/README.md +1195 -0
- package/src/components/pickers/DatePicker/theme.css +22 -0
- package/src/components/pickers/FilePicker/FilePicker.vue +534 -0
- package/src/components/pickers/FilePicker/README.md +1542 -0
- package/src/components/pickers/FilePicker/theme.css +48 -0
- package/src/components/pickers/FilePicker/types.ts +10 -0
- package/src/components/pickers/IconPicker/IconPicker.vue +327 -0
- package/src/components/pickers/IconPicker/README.md +1161 -0
- package/src/components/pickers/IconPicker/theme.css +28 -0
- package/src/components/pickers/theme.css +82 -0
- package/src/components/views/MarkdownViewer/MarkdownViewer.vue +442 -0
- package/src/components/views/MarkdownViewer/README.md +833 -0
- package/src/components/views/MarkdownViewer/theme.css +130 -0
- package/src/index.ts +263 -0
- package/src/theme.ts +378 -0
- package/src/themes/crimson-dark.ts +556 -0
- package/src/themes/cyan-light.ts +556 -0
- package/src/themes/dark.ts +557 -0
- package/src/themes/gold-dark.ts +556 -0
- package/src/themes/grass-dark.ts +556 -0
- package/src/themes/indigo.ts +556 -0
- package/src/themes/light.ts +557 -0
- package/src/themes/orange-dark.ts +557 -0
- package/src/themes/orange-light.ts +557 -0
- package/src/vue.d.ts +45 -0
|
@@ -0,0 +1,768 @@
|
|
|
1
|
+
# Adaptive Layout
|
|
2
|
+
|
|
3
|
+
A comprehensive adaptive navigation system built with Vue 3 Composition API and TypeScript. The Adaptive Layout system provides intelligent, responsive layouts that automatically adapt to different screen sizes and breakpoints, offering split-view, slideover, and navigation stack patterns.
|
|
4
|
+
|
|
5
|
+
## Installation/Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import {
|
|
9
|
+
AdaptiveLayout,
|
|
10
|
+
AdaptiveLayoutBreadcrumbs,
|
|
11
|
+
AdaptiveLayoutMenuButton,
|
|
12
|
+
} from "@umbra-ui/core";
|
|
13
|
+
import type { View, ViewLayout, ViewLocation } from "@umbra-ui/core";
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Dependencies:**
|
|
17
|
+
|
|
18
|
+
- Vue 3.x
|
|
19
|
+
- @umbra-ui/core (for IconButton)
|
|
20
|
+
- @umbra-ui/icons (for MenuIcon)
|
|
21
|
+
|
|
22
|
+
## Basic Usage
|
|
23
|
+
|
|
24
|
+
```vue
|
|
25
|
+
<script setup lang="ts">
|
|
26
|
+
import { ref } from "vue";
|
|
27
|
+
import {
|
|
28
|
+
AdaptiveLayout,
|
|
29
|
+
AdaptiveLayoutBreadcrumbs,
|
|
30
|
+
AdaptiveLayoutMenuButton,
|
|
31
|
+
} from "@umbra-ui/core";
|
|
32
|
+
import MySidebar from "./MySidebar.vue";
|
|
33
|
+
import MyContent from "./MyContent.vue";
|
|
34
|
+
import MyDetails from "./MyDetails.vue";
|
|
35
|
+
|
|
36
|
+
// Define your views
|
|
37
|
+
const initialViews = [
|
|
38
|
+
{
|
|
39
|
+
id: "sidebar",
|
|
40
|
+
component: MySidebar,
|
|
41
|
+
label: "Navigation",
|
|
42
|
+
minWidth: 200,
|
|
43
|
+
maxWidth: 300,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "content",
|
|
47
|
+
component: MyContent,
|
|
48
|
+
label: "Content",
|
|
49
|
+
minWidth: 300,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "details",
|
|
53
|
+
component: MyDetails,
|
|
54
|
+
label: "Details",
|
|
55
|
+
minWidth: 250,
|
|
56
|
+
maxWidth: 400,
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const layoutRef = ref();
|
|
61
|
+
|
|
62
|
+
// Access layout methods
|
|
63
|
+
const showView = (id: string) => {
|
|
64
|
+
layoutRef.value?.show(id);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const hideView = (id: string) => {
|
|
68
|
+
layoutRef.value?.hide(id);
|
|
69
|
+
};
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<template>
|
|
73
|
+
<div class="app-layout">
|
|
74
|
+
<!-- Navigation controls -->
|
|
75
|
+
<div class="layout-controls">
|
|
76
|
+
<AdaptiveLayoutMenuButton />
|
|
77
|
+
<AdaptiveLayoutBreadcrumbs />
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<!-- Main layout -->
|
|
81
|
+
<AdaptiveLayout
|
|
82
|
+
ref="layoutRef"
|
|
83
|
+
:initial-views="initialViews"
|
|
84
|
+
layout="adaptive"
|
|
85
|
+
padding="16px"
|
|
86
|
+
gap="8px"
|
|
87
|
+
:can-hide-views="true"
|
|
88
|
+
:can-resize-views="true"
|
|
89
|
+
/>
|
|
90
|
+
</div>
|
|
91
|
+
</template>
|
|
92
|
+
|
|
93
|
+
<style module>
|
|
94
|
+
.app-layout {
|
|
95
|
+
height: 100vh;
|
|
96
|
+
display: flex;
|
|
97
|
+
flex-direction: column;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.layout-controls {
|
|
101
|
+
display: flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
gap: 16px;
|
|
104
|
+
padding: 12px 16px;
|
|
105
|
+
border-bottom: 1px solid var(--border-2);
|
|
106
|
+
background: var(--background-1);
|
|
107
|
+
}
|
|
108
|
+
</style>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Components
|
|
112
|
+
|
|
113
|
+
### AdaptiveLayout
|
|
114
|
+
|
|
115
|
+
The main layout component that manages view positioning and responsive behavior.
|
|
116
|
+
|
|
117
|
+
#### Props
|
|
118
|
+
|
|
119
|
+
| Prop Name | Type | Required | Default | Description |
|
|
120
|
+
| ---------------- | ------------ | -------- | ------------------- | ---------------------------------------------------------------- |
|
|
121
|
+
| `initialViews` | `View[]` | Yes | - | Array of views to display in the layout |
|
|
122
|
+
| `instanceKey` | `string` | No | `"adaptive-layout"` | Unique key for shared state management |
|
|
123
|
+
| `padding` | `string` | No | `"0"` | CSS padding value for the layout container |
|
|
124
|
+
| `gap` | `string` | No | `"0"` | CSS gap value between views |
|
|
125
|
+
| `canHideViews` | `boolean` | No | `true` | Whether views can be hidden/shown |
|
|
126
|
+
| `canResizeViews` | `boolean` | No | `true` | Whether views can be resized |
|
|
127
|
+
| `layout` | `ViewLayout` | No | `"adaptive"` | Layout mode: "adaptive", "splitview", "slideover", or "navstack" |
|
|
128
|
+
|
|
129
|
+
#### View Interface
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
interface View {
|
|
133
|
+
id: string;
|
|
134
|
+
component: Component | ReturnType<typeof markRaw<Component>>;
|
|
135
|
+
props?: Record<string, unknown>;
|
|
136
|
+
minWidth?: number;
|
|
137
|
+
maxWidth?: number;
|
|
138
|
+
currentWidth?: number;
|
|
139
|
+
label?: string;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### ViewLayout Types
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
type ViewLayout = "splitview" | "slideover" | "navstack" | "adaptive";
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### Events
|
|
150
|
+
|
|
151
|
+
| Event Name | Payload Type | Description |
|
|
152
|
+
| ----------- | ---------------- | ------------------------------------------ |
|
|
153
|
+
| `view-show` | `{ id: string }` | Emitted when a view is shown |
|
|
154
|
+
| `view-hide` | `{ id: string }` | Emitted when a view is hidden |
|
|
155
|
+
| `view-push` | `{ id: string }` | Emitted when a view is pushed to overlay |
|
|
156
|
+
| `view-pop` | `{ id: string }` | Emitted when a view is popped from overlay |
|
|
157
|
+
|
|
158
|
+
#### Exposed Methods/Refs
|
|
159
|
+
|
|
160
|
+
| Method | Parameters | Description |
|
|
161
|
+
| --------- | ---------------------------------------------- | -------------------------------- |
|
|
162
|
+
| `show` | `(id: string, animated?: boolean)` | Show a specific view |
|
|
163
|
+
| `hide` | `(id: string, animated?: boolean)` | Hide a specific view |
|
|
164
|
+
| `push` | `(id: string, animated?: boolean)` | Push a view to overlay |
|
|
165
|
+
| `pop` | `(id: string, animated?: boolean)` | Pop a view from overlay |
|
|
166
|
+
| `toggle` | `(id: string, animated?: boolean)` | Toggle view visibility |
|
|
167
|
+
| `add` | `(view: View, animated?: boolean)` | Add a new view (not implemented) |
|
|
168
|
+
| `remove` | `(id: string, animated?: boolean)` | Remove a view (not implemented) |
|
|
169
|
+
| `replace` | `(id: string, view: View, animated?: boolean)` | Replace a view (not implemented) |
|
|
170
|
+
|
|
171
|
+
### AdaptiveLayoutBreadcrumbs
|
|
172
|
+
|
|
173
|
+
Navigation breadcrumbs that show the current view hierarchy and allow navigation between views.
|
|
174
|
+
|
|
175
|
+
#### Props
|
|
176
|
+
|
|
177
|
+
| Prop Name | Type | Required | Default | Description |
|
|
178
|
+
| ---------------- | ------------------ | -------- | --------------------------- | ----------------------------------------- |
|
|
179
|
+
| `instanceKey` | `string \| symbol` | No | `Symbol("adaptive-layout")` | Key to match with AdaptiveLayout instance |
|
|
180
|
+
| `separator` | `string` | No | `"/"` | Separator character between breadcrumbs |
|
|
181
|
+
| `showTooltip` | `boolean` | No | `true` | Whether to show tooltips on hover |
|
|
182
|
+
| `maxLabelLength` | `number` | No | `20` | Maximum length for breadcrumb labels |
|
|
183
|
+
|
|
184
|
+
#### Events
|
|
185
|
+
|
|
186
|
+
| Event Name | Payload Type | Description |
|
|
187
|
+
| ------------------ | -------------------------------------------------- | ------------------------------------ |
|
|
188
|
+
| `breadcrumb-click` | `{ id: string, label: string, isActive: boolean }` | Emitted when a breadcrumb is clicked |
|
|
189
|
+
|
|
190
|
+
### AdaptiveLayoutMenuButton
|
|
191
|
+
|
|
192
|
+
A menu button that shows/hides offscreen views in an overlay, with an optional count badge.
|
|
193
|
+
|
|
194
|
+
#### Props
|
|
195
|
+
|
|
196
|
+
| Prop Name | Type | Required | Default | Description |
|
|
197
|
+
| ------------- | ------------------------------------ | -------- | --------------------------- | ----------------------------------------- |
|
|
198
|
+
| `instanceKey` | `string \| symbol` | No | `Symbol("adaptive-layout")` | Key to match with AdaptiveLayout instance |
|
|
199
|
+
| `isolated` | `boolean` | No | `false` | Use completely isolated instance |
|
|
200
|
+
| `showCount` | `boolean` | No | `true` | Whether to show the count badge |
|
|
201
|
+
| `customIcon` | `{ open?: string, closed?: string }` | No | - | Custom icons for open/closed states |
|
|
202
|
+
|
|
203
|
+
#### Events
|
|
204
|
+
|
|
205
|
+
| Event Name | Payload Type | Description |
|
|
206
|
+
| ---------------- | --------------------- | ------------------------------- |
|
|
207
|
+
| `toggle-overlay` | `{ isOpen: boolean }` | Emitted when overlay is toggled |
|
|
208
|
+
|
|
209
|
+
## Layout Modes
|
|
210
|
+
|
|
211
|
+
### Adaptive Mode
|
|
212
|
+
|
|
213
|
+
**Default mode** - Automatically switches between layout patterns based on screen size:
|
|
214
|
+
|
|
215
|
+
- **Desktop**: Split-view layout with all views visible
|
|
216
|
+
- **Tablet**: Slideover layout with overlay for hidden views
|
|
217
|
+
- **Mobile**: Navigation stack with full-screen views
|
|
218
|
+
|
|
219
|
+
### Split-View Mode
|
|
220
|
+
|
|
221
|
+
- All views displayed side-by-side
|
|
222
|
+
- Resizable panels with drag handles
|
|
223
|
+
- Ideal for desktop applications
|
|
224
|
+
- Supports minimum and maximum width constraints
|
|
225
|
+
|
|
226
|
+
### Slideover Mode
|
|
227
|
+
|
|
228
|
+
- Primary view always visible
|
|
229
|
+
- Secondary views appear as overlays
|
|
230
|
+
- Semi-transparent backdrop with blur effect
|
|
231
|
+
- Touch-friendly for tablet interfaces
|
|
232
|
+
|
|
233
|
+
### Navigation Stack Mode
|
|
234
|
+
|
|
235
|
+
- Full-screen views with stack navigation
|
|
236
|
+
- Push/pop navigation pattern
|
|
237
|
+
- Mobile-optimized interface
|
|
238
|
+
- Breadcrumb navigation support
|
|
239
|
+
|
|
240
|
+
## Responsive Breakpoints
|
|
241
|
+
|
|
242
|
+
The system automatically adapts based on container width:
|
|
243
|
+
|
|
244
|
+
- **Mobile**: < 768px - Navigation stack layout
|
|
245
|
+
- **Tablet**: 768px - 1024px - Slideover layout
|
|
246
|
+
- **Desktop**: > 1024px - Split-view layout
|
|
247
|
+
|
|
248
|
+
## CSS Customization
|
|
249
|
+
|
|
250
|
+
### Layout Variables
|
|
251
|
+
|
|
252
|
+
```css
|
|
253
|
+
.adaptive-layout {
|
|
254
|
+
--padding: 16px;
|
|
255
|
+
--gap: 8px;
|
|
256
|
+
--width: 100%;
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Handle Styling
|
|
261
|
+
|
|
262
|
+
```css
|
|
263
|
+
.adaptive-layout {
|
|
264
|
+
--slideover-handle-default-width: 4px;
|
|
265
|
+
--slideover-handle-default-height: 24px;
|
|
266
|
+
--slideover-handle-default-opacity: 0.3;
|
|
267
|
+
--slideover-handle-bg: #666;
|
|
268
|
+
--slideover-handle-hover-width: 6px;
|
|
269
|
+
--slideover-handle-hover-height: 32px;
|
|
270
|
+
--slideover-handle-hover-opacity: 0.6;
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Breadcrumb Styling
|
|
275
|
+
|
|
276
|
+
```css
|
|
277
|
+
.adaptive-layout {
|
|
278
|
+
--slideover-breadcrumb-hover-opacity: 0.8;
|
|
279
|
+
--background-1: #ffffff;
|
|
280
|
+
--border-2: #e2e8f0;
|
|
281
|
+
--text-1: #1a202c;
|
|
282
|
+
--font-weight-regular: 400;
|
|
283
|
+
--font-weight-medium: 500;
|
|
284
|
+
--control-2: #f7fafc;
|
|
285
|
+
--border-1: #cbd5e0;
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Examples
|
|
290
|
+
|
|
291
|
+
### Basic Three-Panel Layout
|
|
292
|
+
|
|
293
|
+
```vue
|
|
294
|
+
<script setup lang="ts">
|
|
295
|
+
import { ref } from "vue";
|
|
296
|
+
import { AdaptiveLayout } from "@umbra-ui/core";
|
|
297
|
+
import Sidebar from "./Sidebar.vue";
|
|
298
|
+
import Content from "./Content.vue";
|
|
299
|
+
import Details from "./Details.vue";
|
|
300
|
+
|
|
301
|
+
const views = [
|
|
302
|
+
{
|
|
303
|
+
id: "sidebar",
|
|
304
|
+
component: Sidebar,
|
|
305
|
+
label: "Sidebar",
|
|
306
|
+
minWidth: 200,
|
|
307
|
+
maxWidth: 300,
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
id: "content",
|
|
311
|
+
component: Content,
|
|
312
|
+
label: "Content",
|
|
313
|
+
minWidth: 400,
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
id: "details",
|
|
317
|
+
component: Details,
|
|
318
|
+
label: "Details",
|
|
319
|
+
minWidth: 250,
|
|
320
|
+
maxWidth: 400,
|
|
321
|
+
},
|
|
322
|
+
];
|
|
323
|
+
</script>
|
|
324
|
+
|
|
325
|
+
<template>
|
|
326
|
+
<AdaptiveLayout
|
|
327
|
+
:initial-views="views"
|
|
328
|
+
padding="16px"
|
|
329
|
+
gap="12px"
|
|
330
|
+
:can-hide-views="true"
|
|
331
|
+
:can-resize-views="true"
|
|
332
|
+
/>
|
|
333
|
+
</template>
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### File Explorer Layout
|
|
337
|
+
|
|
338
|
+
```vue
|
|
339
|
+
<script setup lang="ts">
|
|
340
|
+
import { ref } from "vue";
|
|
341
|
+
import {
|
|
342
|
+
AdaptiveLayout,
|
|
343
|
+
AdaptiveLayoutBreadcrumbs,
|
|
344
|
+
AdaptiveLayoutMenuButton,
|
|
345
|
+
} from "@umbra-ui/core";
|
|
346
|
+
import FileTree from "./FileTree.vue";
|
|
347
|
+
import FileList from "./FileList.vue";
|
|
348
|
+
import FilePreview from "./FilePreview.vue";
|
|
349
|
+
|
|
350
|
+
const views = [
|
|
351
|
+
{
|
|
352
|
+
id: "tree",
|
|
353
|
+
component: FileTree,
|
|
354
|
+
label: "Folders",
|
|
355
|
+
minWidth: 200,
|
|
356
|
+
maxWidth: 350,
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
id: "list",
|
|
360
|
+
component: FileList,
|
|
361
|
+
label: "Files",
|
|
362
|
+
minWidth: 300,
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
id: "preview",
|
|
366
|
+
component: FilePreview,
|
|
367
|
+
label: "Preview",
|
|
368
|
+
minWidth: 300,
|
|
369
|
+
maxWidth: 500,
|
|
370
|
+
},
|
|
371
|
+
];
|
|
372
|
+
|
|
373
|
+
const layoutRef = ref();
|
|
374
|
+
|
|
375
|
+
const handleFileSelect = (file: any) => {
|
|
376
|
+
// Show preview when file is selected
|
|
377
|
+
layoutRef.value?.show("preview");
|
|
378
|
+
};
|
|
379
|
+
</script>
|
|
380
|
+
|
|
381
|
+
<template>
|
|
382
|
+
<div class="file-explorer">
|
|
383
|
+
<header class="explorer-header">
|
|
384
|
+
<AdaptiveLayoutMenuButton />
|
|
385
|
+
<AdaptiveLayoutBreadcrumbs />
|
|
386
|
+
</header>
|
|
387
|
+
|
|
388
|
+
<AdaptiveLayout
|
|
389
|
+
ref="layoutRef"
|
|
390
|
+
:initial-views="views"
|
|
391
|
+
layout="adaptive"
|
|
392
|
+
padding="0"
|
|
393
|
+
gap="1px"
|
|
394
|
+
:can-hide-views="true"
|
|
395
|
+
:can-resize-views="true"
|
|
396
|
+
/>
|
|
397
|
+
</div>
|
|
398
|
+
</template>
|
|
399
|
+
|
|
400
|
+
<style module>
|
|
401
|
+
.file-explorer {
|
|
402
|
+
height: 100vh;
|
|
403
|
+
display: flex;
|
|
404
|
+
flex-direction: column;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.explorer-header {
|
|
408
|
+
display: flex;
|
|
409
|
+
align-items: center;
|
|
410
|
+
gap: 16px;
|
|
411
|
+
padding: 12px 16px;
|
|
412
|
+
background: var(--background-1);
|
|
413
|
+
border-bottom: 1px solid var(--border-2);
|
|
414
|
+
}
|
|
415
|
+
</style>
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Settings Panel Layout
|
|
419
|
+
|
|
420
|
+
```vue
|
|
421
|
+
<script setup lang="ts">
|
|
422
|
+
import { ref } from "vue";
|
|
423
|
+
import { AdaptiveLayout } from "@umbra-ui/core";
|
|
424
|
+
import SettingsNav from "./SettingsNav.vue";
|
|
425
|
+
import SettingsContent from "./SettingsContent.vue";
|
|
426
|
+
|
|
427
|
+
const views = [
|
|
428
|
+
{
|
|
429
|
+
id: "nav",
|
|
430
|
+
component: SettingsNav,
|
|
431
|
+
label: "Categories",
|
|
432
|
+
minWidth: 200,
|
|
433
|
+
maxWidth: 250,
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
id: "content",
|
|
437
|
+
component: SettingsContent,
|
|
438
|
+
label: "Settings",
|
|
439
|
+
minWidth: 400,
|
|
440
|
+
},
|
|
441
|
+
];
|
|
442
|
+
|
|
443
|
+
const layoutRef = ref();
|
|
444
|
+
|
|
445
|
+
const showCategory = (categoryId: string) => {
|
|
446
|
+
// Show specific settings category
|
|
447
|
+
layoutRef.value?.show("content");
|
|
448
|
+
};
|
|
449
|
+
</script>
|
|
450
|
+
|
|
451
|
+
<template>
|
|
452
|
+
<div class="settings-layout">
|
|
453
|
+
<AdaptiveLayout
|
|
454
|
+
ref="layoutRef"
|
|
455
|
+
:initial-views="views"
|
|
456
|
+
layout="adaptive"
|
|
457
|
+
padding="24px"
|
|
458
|
+
gap="16px"
|
|
459
|
+
:can-hide-views="true"
|
|
460
|
+
:can-resize-views="false"
|
|
461
|
+
/>
|
|
462
|
+
</div>
|
|
463
|
+
</template>
|
|
464
|
+
|
|
465
|
+
<style module>
|
|
466
|
+
.settings-layout {
|
|
467
|
+
height: 100vh;
|
|
468
|
+
background: var(--background-1);
|
|
469
|
+
}
|
|
470
|
+
</style>
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Mobile-First Navigation
|
|
474
|
+
|
|
475
|
+
```vue
|
|
476
|
+
<script setup lang="ts">
|
|
477
|
+
import { ref } from "vue";
|
|
478
|
+
import { AdaptiveLayout, AdaptiveLayoutBreadcrumbs } from "@umbra-ui/core";
|
|
479
|
+
import HomeView from "./HomeView.vue";
|
|
480
|
+
import ProfileView from "./ProfileView.vue";
|
|
481
|
+
import SettingsView from "./SettingsView.vue";
|
|
482
|
+
|
|
483
|
+
const views = [
|
|
484
|
+
{
|
|
485
|
+
id: "home",
|
|
486
|
+
component: HomeView,
|
|
487
|
+
label: "Home",
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
id: "profile",
|
|
491
|
+
component: ProfileView,
|
|
492
|
+
label: "Profile",
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
id: "settings",
|
|
496
|
+
component: SettingsView,
|
|
497
|
+
label: "Settings",
|
|
498
|
+
},
|
|
499
|
+
];
|
|
500
|
+
|
|
501
|
+
const layoutRef = ref();
|
|
502
|
+
|
|
503
|
+
const navigateTo = (viewId: string) => {
|
|
504
|
+
layoutRef.value?.show(viewId);
|
|
505
|
+
};
|
|
506
|
+
</script>
|
|
507
|
+
|
|
508
|
+
<template>
|
|
509
|
+
<div class="mobile-app">
|
|
510
|
+
<nav class="app-nav">
|
|
511
|
+
<AdaptiveLayoutBreadcrumbs />
|
|
512
|
+
</nav>
|
|
513
|
+
|
|
514
|
+
<AdaptiveLayout
|
|
515
|
+
ref="layoutRef"
|
|
516
|
+
:initial-views="views"
|
|
517
|
+
layout="navstack"
|
|
518
|
+
padding="16px"
|
|
519
|
+
gap="0"
|
|
520
|
+
:can-hide-views="true"
|
|
521
|
+
:can-resize-views="false"
|
|
522
|
+
/>
|
|
523
|
+
</div>
|
|
524
|
+
</template>
|
|
525
|
+
|
|
526
|
+
<style module>
|
|
527
|
+
.mobile-app {
|
|
528
|
+
height: 100vh;
|
|
529
|
+
display: flex;
|
|
530
|
+
flex-direction: column;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.app-nav {
|
|
534
|
+
padding: 12px 16px;
|
|
535
|
+
background: var(--background-1);
|
|
536
|
+
border-bottom: 1px solid var(--border-2);
|
|
537
|
+
}
|
|
538
|
+
</style>
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### Custom Layout with Resize Handles
|
|
542
|
+
|
|
543
|
+
```vue
|
|
544
|
+
<script setup lang="ts">
|
|
545
|
+
import { ref } from "vue";
|
|
546
|
+
import { AdaptiveLayout } from "@umbra-ui/core";
|
|
547
|
+
import CodeEditor from "./CodeEditor.vue";
|
|
548
|
+
import FileExplorer from "./FileExplorer.vue";
|
|
549
|
+
import Terminal from "./Terminal.vue";
|
|
550
|
+
|
|
551
|
+
const views = [
|
|
552
|
+
{
|
|
553
|
+
id: "explorer",
|
|
554
|
+
component: FileExplorer,
|
|
555
|
+
label: "Explorer",
|
|
556
|
+
minWidth: 200,
|
|
557
|
+
maxWidth: 400,
|
|
558
|
+
currentWidth: 250,
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
id: "editor",
|
|
562
|
+
component: CodeEditor,
|
|
563
|
+
label: "Editor",
|
|
564
|
+
minWidth: 300,
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
id: "terminal",
|
|
568
|
+
component: Terminal,
|
|
569
|
+
label: "Terminal",
|
|
570
|
+
minWidth: 200,
|
|
571
|
+
maxWidth: 500,
|
|
572
|
+
currentWidth: 300,
|
|
573
|
+
},
|
|
574
|
+
];
|
|
575
|
+
|
|
576
|
+
const layoutRef = ref();
|
|
577
|
+
|
|
578
|
+
const handleResize = (viewId: string, newWidth: number) => {
|
|
579
|
+
console.log(`${viewId} resized to ${newWidth}px`);
|
|
580
|
+
};
|
|
581
|
+
</script>
|
|
582
|
+
|
|
583
|
+
<template>
|
|
584
|
+
<div class="ide-layout">
|
|
585
|
+
<AdaptiveLayout
|
|
586
|
+
ref="layoutRef"
|
|
587
|
+
:initial-views="views"
|
|
588
|
+
layout="splitview"
|
|
589
|
+
padding="0"
|
|
590
|
+
gap="1px"
|
|
591
|
+
:can-hide-views="true"
|
|
592
|
+
:can-resize-views="true"
|
|
593
|
+
/>
|
|
594
|
+
</div>
|
|
595
|
+
</template>
|
|
596
|
+
|
|
597
|
+
<style module>
|
|
598
|
+
.ide-layout {
|
|
599
|
+
height: 100vh;
|
|
600
|
+
background: var(--background-1);
|
|
601
|
+
}
|
|
602
|
+
</style>
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
## Advanced Usage
|
|
606
|
+
|
|
607
|
+
### Shared State Management
|
|
608
|
+
|
|
609
|
+
```vue
|
|
610
|
+
<script setup lang="ts">
|
|
611
|
+
import { ref } from "vue";
|
|
612
|
+
import {
|
|
613
|
+
AdaptiveLayout,
|
|
614
|
+
AdaptiveLayoutBreadcrumbs,
|
|
615
|
+
AdaptiveLayoutMenuButton,
|
|
616
|
+
} from "@umbra-ui/core";
|
|
617
|
+
|
|
618
|
+
// Use the same instance key for shared state
|
|
619
|
+
const LAYOUT_KEY = "main-layout";
|
|
620
|
+
|
|
621
|
+
const views = [
|
|
622
|
+
// ... your views
|
|
623
|
+
];
|
|
624
|
+
|
|
625
|
+
const layoutRef = ref();
|
|
626
|
+
</script>
|
|
627
|
+
|
|
628
|
+
<template>
|
|
629
|
+
<div class="app">
|
|
630
|
+
<!-- These components share the same layout state -->
|
|
631
|
+
<AdaptiveLayoutMenuButton :instance-key="LAYOUT_KEY" />
|
|
632
|
+
<AdaptiveLayoutBreadcrumbs :instance-key="LAYOUT_KEY" />
|
|
633
|
+
|
|
634
|
+
<AdaptiveLayout
|
|
635
|
+
ref="layoutRef"
|
|
636
|
+
:instance-key="LAYOUT_KEY"
|
|
637
|
+
:initial-views="views"
|
|
638
|
+
/>
|
|
639
|
+
</div>
|
|
640
|
+
</template>
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### Dynamic View Management
|
|
644
|
+
|
|
645
|
+
```vue
|
|
646
|
+
<script setup lang="ts">
|
|
647
|
+
import { ref, markRaw } from "vue";
|
|
648
|
+
import { AdaptiveLayout } from "@umbra-ui/core";
|
|
649
|
+
import DynamicView from "./DynamicView.vue";
|
|
650
|
+
|
|
651
|
+
const views = ref([
|
|
652
|
+
{
|
|
653
|
+
id: "main",
|
|
654
|
+
component: markRaw(DynamicView),
|
|
655
|
+
label: "Main View",
|
|
656
|
+
minWidth: 300,
|
|
657
|
+
},
|
|
658
|
+
]);
|
|
659
|
+
|
|
660
|
+
const layoutRef = ref();
|
|
661
|
+
|
|
662
|
+
const addView = (id: string, component: any, props: any = {}) => {
|
|
663
|
+
const newView = {
|
|
664
|
+
id,
|
|
665
|
+
component: markRaw(component),
|
|
666
|
+
label: id,
|
|
667
|
+
minWidth: 200,
|
|
668
|
+
props,
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
// Note: add method is not yet implemented
|
|
672
|
+
// layoutRef.value?.add(newView);
|
|
673
|
+
console.log("Add view:", newView);
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
const removeView = (id: string) => {
|
|
677
|
+
// Note: remove method is not yet implemented
|
|
678
|
+
// layoutRef.value?.remove(id);
|
|
679
|
+
console.log("Remove view:", id);
|
|
680
|
+
};
|
|
681
|
+
</script>
|
|
682
|
+
|
|
683
|
+
<template>
|
|
684
|
+
<div class="dynamic-layout">
|
|
685
|
+
<div class="controls">
|
|
686
|
+
<button @click="addView('new', DynamicView)">Add View</button>
|
|
687
|
+
<button @click="removeView('new')">Remove View</button>
|
|
688
|
+
</div>
|
|
689
|
+
|
|
690
|
+
<AdaptiveLayout
|
|
691
|
+
ref="layoutRef"
|
|
692
|
+
:initial-views="views"
|
|
693
|
+
:can-hide-views="true"
|
|
694
|
+
:can-resize-views="true"
|
|
695
|
+
/>
|
|
696
|
+
</div>
|
|
697
|
+
</template>
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
## Performance Considerations
|
|
701
|
+
|
|
702
|
+
- **Component Marking**: Always use `markRaw()` when passing components to prevent Vue's reactivity system from wrapping them
|
|
703
|
+
- **View Limits**: Consider limiting the number of views to prevent performance issues
|
|
704
|
+
- **Resize Debouncing**: Resize operations are automatically debounced for smooth performance
|
|
705
|
+
- **Memory Management**: Views are properly cleaned up when removed from the layout
|
|
706
|
+
|
|
707
|
+
## Accessibility
|
|
708
|
+
|
|
709
|
+
- **Keyboard Navigation**: All interactive elements support keyboard navigation
|
|
710
|
+
- **Screen Reader Support**: Proper ARIA labels and roles for screen readers
|
|
711
|
+
- **Focus Management**: Focus is properly managed during view transitions
|
|
712
|
+
- **High Contrast**: Supports high contrast mode and custom color schemes
|
|
713
|
+
|
|
714
|
+
## Browser Support
|
|
715
|
+
|
|
716
|
+
- **Modern Browsers**: Chrome 88+, Firefox 85+, Safari 14+, Edge 88+
|
|
717
|
+
- **Mobile Browsers**: iOS Safari 14+, Chrome Mobile 88+
|
|
718
|
+
- **CSS Features**: Uses CSS Grid, Flexbox, and modern CSS features
|
|
719
|
+
- **JavaScript**: Requires ES2020+ support for optional chaining and nullish coalescing
|
|
720
|
+
|
|
721
|
+
## Troubleshooting
|
|
722
|
+
|
|
723
|
+
### Common Issues
|
|
724
|
+
|
|
725
|
+
1. **Views not showing**: Ensure components are properly marked with `markRaw()`
|
|
726
|
+
2. **Layout not responsive**: Check that the container has a defined height
|
|
727
|
+
3. **Resize not working**: Verify `canResizeViews` is set to `true`
|
|
728
|
+
4. **State not shared**: Ensure all components use the same `instanceKey`
|
|
729
|
+
|
|
730
|
+
### Debug Mode
|
|
731
|
+
|
|
732
|
+
```vue
|
|
733
|
+
<script setup lang="ts">
|
|
734
|
+
import { ref, watch } from "vue";
|
|
735
|
+
import { AdaptiveLayout } from "@umbra-ui/core";
|
|
736
|
+
|
|
737
|
+
const layoutRef = ref();
|
|
738
|
+
const debugInfo = ref({});
|
|
739
|
+
|
|
740
|
+
// Watch for layout changes
|
|
741
|
+
watch(
|
|
742
|
+
() => layoutRef.value,
|
|
743
|
+
(layout) => {
|
|
744
|
+
if (layout) {
|
|
745
|
+
// Access internal state for debugging
|
|
746
|
+
console.log("Layout state:", layout);
|
|
747
|
+
}
|
|
748
|
+
},
|
|
749
|
+
{ immediate: true }
|
|
750
|
+
);
|
|
751
|
+
</script>
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
## Migration Guide
|
|
755
|
+
|
|
756
|
+
### From v1 to v2
|
|
757
|
+
|
|
758
|
+
- `instanceKey` prop is now required for shared state
|
|
759
|
+
- `layout` prop replaces individual layout components
|
|
760
|
+
- View interface has been updated with new properties
|
|
761
|
+
- Animation system has been refactored for better performance
|
|
762
|
+
|
|
763
|
+
### Breaking Changes
|
|
764
|
+
|
|
765
|
+
- Removed individual layout components (SplitView, Slideover, NavStack)
|
|
766
|
+
- Changed view management API
|
|
767
|
+
- Updated CSS class names and structure
|
|
768
|
+
- Modified event payload structure
|