@skewedaspect/sleekspace-ui 0.7.1 → 0.8.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/sleekspace-ui.css +984 -291
- package/dist/sleekspace-ui.es.js +31559 -29868
- package/dist/sleekspace-ui.umd.js +32210 -30438
- package/dist/{components → src/components}/Accordion/SkAccordion.vue.d.ts +1 -1
- package/dist/{components → src/components}/Accordion/types.d.ts +1 -1
- package/dist/{components → src/components}/Alert/SkAlert.vue.d.ts +1 -1
- package/dist/{components → src/components}/Alert/types.d.ts +1 -1
- package/dist/{components → src/components}/Avatar/SkAvatar.vue.d.ts +1 -1
- package/dist/{components → src/components}/Avatar/types.d.ts +1 -1
- package/dist/{components → src/components}/Breadcrumbs/SkBreadcrumbs.vue.d.ts +2 -2
- package/dist/{components → src/components}/Breadcrumbs/types.d.ts +1 -1
- package/dist/{components → src/components}/Button/SkButton.vue.d.ts +9 -1
- package/dist/{components → src/components}/Button/types.d.ts +1 -1
- package/dist/{components → src/components}/Card/SkCard.vue.d.ts +1 -1
- package/dist/src/components/Card/types.d.ts +2 -0
- package/dist/{components → src/components}/Checkbox/SkCheckbox.vue.d.ts +1 -1
- package/dist/{components → src/components}/Checkbox/types.d.ts +1 -1
- package/dist/{components → src/components}/Collapsible/SkCollapsible.vue.d.ts +1 -1
- package/dist/src/components/Collapsible/types.d.ts +2 -0
- package/dist/{components → src/components}/ColorPicker/SkColorPicker.vue.d.ts +1 -1
- package/dist/{components → src/components}/ColorPicker/types.d.ts +1 -1
- package/dist/{components → src/components}/ContextMenu/SkContextMenu.vue.d.ts +1 -1
- package/dist/src/components/ContextMenu/types.d.ts +2 -0
- package/dist/{components → src/components}/Divider/SkDivider.vue.d.ts +1 -1
- package/dist/{components → src/components}/Dropdown/SkDropdown.vue.d.ts +1 -1
- package/dist/{components → src/components}/Dropdown/types.d.ts +1 -1
- package/dist/{components → src/components}/Input/SkInput.vue.d.ts +1 -1
- package/dist/{components → src/components}/Input/types.d.ts +1 -1
- package/dist/{components → src/components}/Listbox/SkListbox.vue.d.ts +1 -1
- package/dist/{components → src/components}/Listbox/types.d.ts +1 -1
- package/dist/{components → src/components}/Modal/SkModal.vue.d.ts +1 -1
- package/dist/{components → src/components}/Modal/types.d.ts +1 -1
- package/dist/{components → src/components}/NavBar/SkNavBar.vue.d.ts +2 -1
- package/dist/src/components/NavBar/context.d.ts +3 -0
- package/dist/{components → src/components}/NavBar/types.d.ts +1 -1
- package/dist/{components → src/components}/NumberInput/SkNumberInput.vue.d.ts +1 -1
- package/dist/{components → src/components}/NumberInput/types.d.ts +1 -1
- package/dist/src/components/Page/SkPage.vue.d.ts +161 -0
- package/dist/src/components/Page/SkPageSidebarToggle.vue.d.ts +41 -0
- package/dist/src/components/Page/index.d.ts +3 -0
- package/dist/src/components/Page/types.d.ts +39 -0
- package/dist/{components → src/components}/Pagination/SkPagination.vue.d.ts +3 -3
- package/dist/{components → src/components}/Pagination/types.d.ts +1 -1
- package/dist/{components → src/components}/Panel/SkPanel.vue.d.ts +1 -1
- package/dist/{components → src/components}/Panel/types.d.ts +1 -1
- package/dist/{components → src/components}/Popover/SkPopover.vue.d.ts +1 -1
- package/dist/{components → src/components}/Progress/SkProgress.vue.d.ts +1 -1
- package/dist/{components → src/components}/Progress/types.d.ts +1 -1
- package/dist/{components → src/components}/Radio/SkRadio.vue.d.ts +1 -1
- package/dist/{components → src/components}/Radio/types.d.ts +1 -1
- package/dist/{components → src/components}/ScrollArea/SkScrollArea.vue.d.ts +9 -0
- package/dist/{components → src/components}/ScrollArea/types.d.ts +1 -1
- package/dist/{components → src/components}/Select/SkSelect.vue.d.ts +1 -1
- package/dist/{components → src/components}/Select/SkSelectItem.vue.d.ts +6 -18
- package/dist/{components → src/components}/Select/types.d.ts +1 -1
- package/dist/{components → src/components}/Sidebar/SkSidebar.vue.d.ts +10 -2
- package/dist/{components → src/components}/Sidebar/types.d.ts +1 -1
- package/dist/{components → src/components}/Slider/SkSlider.vue.d.ts +1 -1
- package/dist/{components → src/components}/Slider/types.d.ts +1 -1
- package/dist/{components → src/components}/Spinner/SkSpinner.vue.d.ts +1 -1
- package/dist/{components → src/components}/Spinner/types.d.ts +1 -1
- package/dist/{components → src/components}/Splitter/types.d.ts +1 -1
- package/dist/{components → src/components}/Switch/SkSwitch.vue.d.ts +1 -1
- package/dist/{components → src/components}/Switch/types.d.ts +1 -1
- package/dist/{components → src/components}/Table/SkTable.vue.d.ts +1 -1
- package/dist/{components → src/components}/Table/types.d.ts +1 -1
- package/dist/{components → src/components}/Tabs/SkTab.vue.d.ts +1 -1
- package/dist/{components → src/components}/Tabs/SkTabs.vue.d.ts +2 -2
- package/dist/{components → src/components}/Tag/SkTag.vue.d.ts +1 -1
- package/dist/{components → src/components}/TagsInput/SkTagsInput.vue.d.ts +1 -1
- package/dist/{components → src/components}/TagsInput/types.d.ts +1 -1
- package/dist/{components → src/components}/Textarea/SkTextarea.vue.d.ts +1 -1
- package/dist/{components → src/components}/Textarea/types.d.ts +1 -1
- package/dist/{components → src/components}/Toolbar/types.d.ts +1 -1
- package/dist/{components → src/components}/Tooltip/SkTooltip.vue.d.ts +1 -1
- package/dist/{components → src/components}/Tooltip/types.d.ts +1 -1
- package/dist/{components → src/components}/TreeView/SkTreeView.vue.d.ts +5 -5
- package/dist/{components → src/components}/TreeView/types.d.ts +1 -1
- package/dist/src/composables/useFocusTrap.d.ts +17 -0
- package/dist/src/composables/usePageDrawer.d.ts +35 -0
- package/dist/src/composables/usePortalContext.test.d.ts +1 -0
- package/dist/{index.d.ts → src/index.d.ts} +2 -0
- package/dist/src/styles/mixins/fluidSize.test.d.ts +1 -0
- package/dist/tokens.css +60 -0
- package/llms-full.txt +6349 -0
- package/llms.txt +46 -0
- package/package.json +16 -11
- package/src/components/Button/SkButton.vue +25 -13
- package/src/components/NavBar/SkNavBar.vue +12 -1
- package/src/components/NavBar/context.ts +16 -0
- package/src/components/Page/SkPage.vue +460 -72
- package/src/components/Page/SkPageSidebarToggle.vue +148 -0
- package/src/components/Page/index.ts +1 -0
- package/src/components/Page/types.ts +30 -5
- package/src/components/ScrollArea/SkScrollArea.vue +12 -0
- package/src/components/Select/SkSelectItem.vue +2 -2
- package/src/components/Sidebar/SkSidebar.vue +10 -0
- package/src/components/TreeView/SkTreeView.vue +6 -6
- package/src/composables/useFocusTrap.test.ts +184 -0
- package/src/composables/useFocusTrap.ts +141 -0
- package/src/composables/usePageDrawer.ts +96 -0
- package/src/global.d.ts +1 -0
- package/src/index.ts +5 -0
- package/src/styles/components/_accordion.scss +15 -0
- package/src/styles/components/_alert.scss +1 -0
- package/src/styles/components/_avatar.scss +1 -0
- package/src/styles/components/_breadcrumbs.scss +7 -0
- package/src/styles/components/_button.scss +291 -214
- package/src/styles/components/_checkbox.scss +9 -1
- package/src/styles/components/_collapsible.scss +15 -0
- package/src/styles/components/_color-picker.scss +4 -1
- package/src/styles/components/_input.scss +1 -0
- package/src/styles/components/_listbox.scss +8 -2
- package/src/styles/components/_menu.scss +9 -2
- package/src/styles/components/_modal.scss +18 -2
- package/src/styles/components/_navbar.scss +22 -6
- package/src/styles/components/_number-input.scss +1 -0
- package/src/styles/components/_page.scss +220 -12
- package/src/styles/components/_pagination.scss +10 -1
- package/src/styles/components/_panel.scss +8 -3
- package/src/styles/components/_popover.scss +15 -2
- package/src/styles/components/_progress.scss +14 -0
- package/src/styles/components/_radio.scss +8 -1
- package/src/styles/components/_scroll-area.scss +56 -0
- package/src/styles/components/_select.scss +3 -1
- package/src/styles/components/_sidebar.scss +78 -38
- package/src/styles/components/_skeleton.scss +18 -0
- package/src/styles/components/_slider.scss +1 -0
- package/src/styles/components/_spinner.scss +15 -0
- package/src/styles/components/_switch.scss +5 -0
- package/src/styles/components/_table.scss +1 -0
- package/src/styles/components/_tabs.scss +6 -0
- package/src/styles/components/_tag.scss +2 -0
- package/src/styles/components/_tags-input.scss +1 -0
- package/src/styles/components/_textarea.scss +1 -0
- package/src/styles/components/_toast.scss +16 -1
- package/src/styles/components/_toolbar.scss +2 -0
- package/src/styles/components/_tooltip.scss +14 -1
- package/src/styles/components/_tree-view.scss +6 -1
- package/src/styles/mixins/_index.scss +1 -0
- package/src/styles/mixins/_responsive.scss +184 -0
- package/src/styles/mixins/fluidSize.test.ts +149 -0
- package/src/styles/tokens/_foundation-breakpoints.scss +26 -0
- package/src/styles/tokens/_foundation-z-index.scss +38 -0
- package/src/styles/tokens/index.scss +2 -0
- package/web-types.json +194 -14
- package/dist/components/Card/types.d.ts +0 -2
- package/dist/components/Collapsible/types.d.ts +0 -2
- package/dist/components/ContextMenu/types.d.ts +0 -2
- package/dist/components/Page/SkPage.vue.d.ts +0 -64
- package/dist/components/Page/index.d.ts +0 -2
- package/dist/components/Page/types.d.ts +0 -16
- package/dist/{components → src/components}/Accordion/SkAccordionItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/Accordion/index.d.ts +0 -0
- package/dist/{components → src/components}/Avatar/index.d.ts +0 -0
- package/dist/{components → src/components}/Breadcrumbs/SkBreadcrumbItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/Breadcrumbs/SkBreadcrumbSeparator.vue.d.ts +0 -0
- package/dist/{components → src/components}/Breadcrumbs/index.d.ts +0 -0
- package/dist/{components → src/components}/Checkbox/index.d.ts +0 -0
- package/dist/{components → src/components}/Collapsible/index.d.ts +0 -0
- package/dist/{components → src/components}/ColorPicker/index.d.ts +0 -0
- package/dist/{components → src/components}/ContextMenu/SkContextMenuCheckboxItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/ContextMenu/SkContextMenuItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/ContextMenu/SkContextMenuLabel.vue.d.ts +0 -0
- package/dist/{components → src/components}/ContextMenu/SkContextMenuRadioGroup.vue.d.ts +0 -0
- package/dist/{components → src/components}/ContextMenu/SkContextMenuRadioItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/ContextMenu/SkContextMenuSeparator.vue.d.ts +0 -0
- package/dist/{components → src/components}/ContextMenu/SkContextMenuSubmenu.vue.d.ts +0 -0
- package/dist/{components → src/components}/ContextMenu/index.d.ts +0 -0
- package/dist/{components → src/components}/Divider/types.d.ts +0 -0
- package/dist/{components → src/components}/Dropdown/SkDropdownCheckboxItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/Dropdown/SkDropdownMenuItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/Dropdown/SkDropdownMenuLabel.vue.d.ts +0 -0
- package/dist/{components → src/components}/Dropdown/SkDropdownMenuSeparator.vue.d.ts +0 -0
- package/dist/{components → src/components}/Dropdown/SkDropdownRadioGroup.vue.d.ts +0 -0
- package/dist/{components → src/components}/Dropdown/SkDropdownRadioItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/Dropdown/SkDropdownSubmenu.vue.d.ts +0 -0
- package/dist/{components → src/components}/Dropdown/index.d.ts +0 -0
- package/dist/{components → src/components}/Field/SkField.vue.d.ts +0 -0
- package/dist/{components → src/components}/Field/index.d.ts +0 -0
- package/dist/{components → src/components}/Field/types.d.ts +0 -0
- package/dist/{components → src/components}/Group/SkGroup.vue.d.ts +0 -0
- package/dist/{components → src/components}/Group/types.d.ts +0 -0
- package/dist/{components → src/components}/Input/index.d.ts +0 -0
- package/dist/{components → src/components}/Listbox/SkListboxItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/Listbox/SkListboxSeparator.vue.d.ts +0 -0
- package/dist/{components → src/components}/Listbox/index.d.ts +0 -0
- package/dist/{components → src/components}/Modal/index.d.ts +0 -0
- package/dist/{components → src/components}/NavBar/index.d.ts +0 -0
- package/dist/{components → src/components}/NumberInput/index.d.ts +0 -0
- package/dist/{components → src/components}/Pagination/SkPaginationItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/Pagination/index.d.ts +0 -0
- package/dist/{components → src/components}/Popover/index.d.ts +0 -0
- package/dist/{components → src/components}/Popover/types.d.ts +0 -0
- package/dist/{components → src/components}/Progress/index.d.ts +0 -0
- package/dist/{components → src/components}/Radio/SkRadioGroup.vue.d.ts +0 -0
- package/dist/{components → src/components}/Radio/index.d.ts +0 -0
- package/dist/{components → src/components}/ScrollArea/index.d.ts +0 -0
- package/dist/{components → src/components}/Select/SkSelectSeparator.vue.d.ts +0 -0
- package/dist/{components → src/components}/Select/index.d.ts +0 -0
- package/dist/{components → src/components}/Sidebar/SkSidebarItem.vue.d.ts +0 -0
- package/dist/{components → src/components}/Sidebar/SkSidebarSection.vue.d.ts +0 -0
- package/dist/{components → src/components}/Skeleton/SkSkeleton.vue.d.ts +2 -2
- /package/dist/{components → src/components}/Skeleton/index.d.ts +0 -0
- /package/dist/{components → src/components}/Skeleton/types.d.ts +0 -0
- /package/dist/{components → src/components}/Slider/index.d.ts +0 -0
- /package/dist/{components → src/components}/Spinner/index.d.ts +0 -0
- /package/dist/{components → src/components}/Splitter/SkSplitter.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Splitter/SkSplitterHandle.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Splitter/SkSplitterPanel.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Splitter/index.d.ts +0 -0
- /package/dist/{components → src/components}/Switch/index.d.ts +0 -0
- /package/dist/{components → src/components}/Table/index.d.ts +0 -0
- /package/dist/{components → src/components}/Tabs/SkTabList.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Tabs/SkTabPanel.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Tabs/SkTabPanels.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Tabs/types.d.ts +0 -0
- /package/dist/{components → src/components}/Tag/types.d.ts +0 -0
- /package/dist/{components → src/components}/TagsInput/index.d.ts +0 -0
- /package/dist/{components → src/components}/Textarea/index.d.ts +0 -0
- /package/dist/{components → src/components}/Theme/SkTheme.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Theme/types.d.ts +0 -0
- /package/dist/{components → src/components}/Theme/useTheme.d.ts +0 -0
- /package/dist/{components → src/components}/Toast/SkToast.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Toast/SkToastProvider.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Toast/index.d.ts +0 -0
- /package/dist/{components → src/components}/Toast/types.d.ts +0 -0
- /package/dist/{components → src/components}/Toast/useToast.d.ts +0 -0
- /package/dist/{components → src/components}/Toolbar/SkToolbar.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Toolbar/SkToolbarButton.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Toolbar/SkToolbarSeparator.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Toolbar/SkToolbarToggleGroup.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Toolbar/SkToolbarToggleItem.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Toolbar/index.d.ts +0 -0
- /package/dist/{components → src/components}/Tooltip/SkTooltipProvider.vue.d.ts +0 -0
- /package/dist/{components → src/components}/Tooltip/index.d.ts +0 -0
- /package/dist/{components → src/components}/TreeView/SkTreeItem.vue.d.ts +0 -0
- /package/dist/{components → src/components}/TreeView/index.d.ts +0 -0
- /package/dist/{composables → src/composables}/useCustomColors.d.ts +0 -0
- /package/dist/{composables → src/composables}/useCustomColors.test.d.ts +0 -0
- /package/dist/{composables/usePortalContext.test.d.ts → src/composables/useFocusTrap.test.d.ts} +0 -0
- /package/dist/{composables → src/composables}/usePortalContext.d.ts +0 -0
- /package/dist/{types.d.ts → src/types.d.ts} +0 -0
|
@@ -1,22 +1,136 @@
|
|
|
1
|
+
<!----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
- Page Component
|
|
3
|
+
--------------------------------------------------------------------------------------------------------------------->
|
|
4
|
+
|
|
1
5
|
<template>
|
|
2
|
-
<div :class="classes" :style="customStyles" :data-scheme="theme">
|
|
6
|
+
<div ref="rootRef" :class="classes" :style="customStyles" :data-scheme="theme">
|
|
3
7
|
<header v-if="$slots.header" class="sk-page-header">
|
|
4
8
|
<slot name="header" />
|
|
5
9
|
</header>
|
|
6
10
|
|
|
11
|
+
<div v-if="$slots.subheader" class="sk-page-subheader">
|
|
12
|
+
<slot name="subheader" />
|
|
13
|
+
</div>
|
|
14
|
+
|
|
7
15
|
<div class="sk-page-main">
|
|
8
|
-
|
|
9
|
-
|
|
16
|
+
<!-- Persistent (inline) sidebar on the left -->
|
|
17
|
+
<aside
|
|
18
|
+
v-if="hasSidebar && !isSidebarDrawerActive"
|
|
19
|
+
class="sk-page-sidebar"
|
|
20
|
+
>
|
|
21
|
+
<div v-if="$slots['sidebar-header']" class="sk-page-sidebar-header">
|
|
22
|
+
<slot name="sidebar-header" :is-drawer="false" />
|
|
23
|
+
</div>
|
|
24
|
+
<div class="sk-page-sidebar-body">
|
|
25
|
+
<slot name="sidebar" :is-drawer="false" />
|
|
26
|
+
</div>
|
|
27
|
+
<div v-if="$slots['sidebar-footer']" class="sk-page-sidebar-footer">
|
|
28
|
+
<slot name="sidebar-footer" :is-drawer="false" />
|
|
29
|
+
</div>
|
|
10
30
|
</aside>
|
|
11
31
|
|
|
12
|
-
<
|
|
13
|
-
<
|
|
14
|
-
|
|
32
|
+
<div class="sk-page-center">
|
|
33
|
+
<div v-if="$slots['main-header']" class="sk-page-main-header">
|
|
34
|
+
<slot name="main-header" />
|
|
35
|
+
</div>
|
|
36
|
+
<main class="sk-page-content">
|
|
37
|
+
<slot />
|
|
38
|
+
</main>
|
|
39
|
+
<div v-if="$slots['main-footer']" class="sk-page-main-footer">
|
|
40
|
+
<slot name="main-footer" />
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<!-- Persistent (inline) aside on the right -->
|
|
45
|
+
<aside
|
|
46
|
+
v-if="hasAside && !isAsideDrawerActive"
|
|
47
|
+
class="sk-page-aside"
|
|
48
|
+
>
|
|
49
|
+
<div v-if="$slots['aside-header']" class="sk-page-aside-header">
|
|
50
|
+
<slot name="aside-header" :is-drawer="false" />
|
|
51
|
+
</div>
|
|
52
|
+
<div class="sk-page-aside-body">
|
|
53
|
+
<slot name="aside" :is-drawer="false" />
|
|
54
|
+
</div>
|
|
55
|
+
<div v-if="$slots['aside-footer']" class="sk-page-aside-footer">
|
|
56
|
+
<slot name="aside-footer" :is-drawer="false" />
|
|
57
|
+
</div>
|
|
58
|
+
</aside>
|
|
15
59
|
</div>
|
|
16
60
|
|
|
17
61
|
<footer v-if="$slots.footer" class="sk-page-footer">
|
|
18
62
|
<slot name="footer" />
|
|
19
63
|
</footer>
|
|
64
|
+
|
|
65
|
+
<!-- Sidebar drawer (off-canvas, slides in from the left) -->
|
|
66
|
+
<template v-if="hasSidebar && isSidebarDrawerActive">
|
|
67
|
+
<Transition name="sk-page-drawer-backdrop">
|
|
68
|
+
<div
|
|
69
|
+
v-if="sidebarDrawerOpen"
|
|
70
|
+
class="sk-page-drawer-backdrop"
|
|
71
|
+
:data-scheme="theme"
|
|
72
|
+
@click="closeSidebarDrawer"
|
|
73
|
+
/>
|
|
74
|
+
</Transition>
|
|
75
|
+
|
|
76
|
+
<Transition name="sk-page-drawer-left">
|
|
77
|
+
<aside
|
|
78
|
+
v-if="sidebarDrawerOpen"
|
|
79
|
+
ref="sidebarDrawerRef"
|
|
80
|
+
class="sk-page-drawer sk-page-drawer-left"
|
|
81
|
+
:data-scheme="theme"
|
|
82
|
+
role="dialog"
|
|
83
|
+
aria-modal="true"
|
|
84
|
+
tabindex="-1"
|
|
85
|
+
@click="onSidebarDrawerClick"
|
|
86
|
+
>
|
|
87
|
+
<div v-if="$slots['sidebar-header']" class="sk-page-sidebar-header">
|
|
88
|
+
<slot name="sidebar-header" :is-drawer="true" />
|
|
89
|
+
</div>
|
|
90
|
+
<div class="sk-page-sidebar-body">
|
|
91
|
+
<slot name="sidebar" :is-drawer="true" />
|
|
92
|
+
</div>
|
|
93
|
+
<div v-if="$slots['sidebar-footer']" class="sk-page-sidebar-footer">
|
|
94
|
+
<slot name="sidebar-footer" :is-drawer="true" />
|
|
95
|
+
</div>
|
|
96
|
+
</aside>
|
|
97
|
+
</Transition>
|
|
98
|
+
</template>
|
|
99
|
+
|
|
100
|
+
<!-- Aside drawer (off-canvas, slides in from the right) -->
|
|
101
|
+
<template v-if="hasAside && isAsideDrawerActive">
|
|
102
|
+
<Transition name="sk-page-drawer-backdrop">
|
|
103
|
+
<div
|
|
104
|
+
v-if="asideDrawerOpen"
|
|
105
|
+
class="sk-page-drawer-backdrop"
|
|
106
|
+
:data-scheme="theme"
|
|
107
|
+
@click="closeAsideDrawer"
|
|
108
|
+
/>
|
|
109
|
+
</Transition>
|
|
110
|
+
|
|
111
|
+
<Transition name="sk-page-drawer-right">
|
|
112
|
+
<aside
|
|
113
|
+
v-if="asideDrawerOpen"
|
|
114
|
+
ref="asideDrawerRef"
|
|
115
|
+
class="sk-page-drawer sk-page-drawer-right"
|
|
116
|
+
:data-scheme="theme"
|
|
117
|
+
role="dialog"
|
|
118
|
+
aria-modal="true"
|
|
119
|
+
tabindex="-1"
|
|
120
|
+
@click="onAsideDrawerClick"
|
|
121
|
+
>
|
|
122
|
+
<div v-if="$slots['aside-header']" class="sk-page-aside-header">
|
|
123
|
+
<slot name="aside-header" :is-drawer="true" />
|
|
124
|
+
</div>
|
|
125
|
+
<div class="sk-page-aside-body">
|
|
126
|
+
<slot name="aside" :is-drawer="true" />
|
|
127
|
+
</div>
|
|
128
|
+
<div v-if="$slots['aside-footer']" class="sk-page-aside-footer">
|
|
129
|
+
<slot name="aside-footer" :is-drawer="true" />
|
|
130
|
+
</div>
|
|
131
|
+
</aside>
|
|
132
|
+
</Transition>
|
|
133
|
+
</template>
|
|
20
134
|
</div>
|
|
21
135
|
</template>
|
|
22
136
|
|
|
@@ -31,125 +145,404 @@
|
|
|
31
145
|
<script setup lang="ts">
|
|
32
146
|
/**
|
|
33
147
|
* @component SkPage
|
|
34
|
-
* @description
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
148
|
+
* @description Full-page layout shell with symmetric panels: a left sidebar and a right aside, each with
|
|
149
|
+
* its own header/body/footer slot trio, and each independently persistent, drawer-based, or responsive.
|
|
150
|
+
* Wraps header / subheader / main content (with optional `main-header` and `main-footer` strips) / footer.
|
|
151
|
+
* Sidebar slides in from the left; aside slides in from the right, with backdrop, focus trap, and
|
|
152
|
+
* ESC-to-close. Drop `<SkPageSidebarToggle />` into the navbar's `#leading` for the sidebar and
|
|
153
|
+
* `<SkPageSidebarToggle side="aside" />` into `#actions` for the aside.
|
|
38
154
|
*
|
|
39
|
-
* @example
|
|
155
|
+
* @example App shell with both panels
|
|
40
156
|
* ```vue
|
|
41
|
-
* <SkPage fixed-header
|
|
157
|
+
* <SkPage fixed-header>
|
|
42
158
|
* <template #header>
|
|
43
|
-
* <
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
159
|
+
* <SkNavBar>
|
|
160
|
+
* <template #leading><SkPageSidebarToggle /></template>
|
|
161
|
+
* <template #brand>AppName</template>
|
|
162
|
+
* <template #actions><SkPageSidebarToggle side="aside" /></template>
|
|
163
|
+
* </SkNavBar>
|
|
47
164
|
* </template>
|
|
165
|
+
* <template #sidebar><SkSidebar>...</SkSidebar></template>
|
|
166
|
+
* <template #aside>...</template>
|
|
48
167
|
* <MainContent />
|
|
49
|
-
* <template #footer>
|
|
50
|
-
* <AppFooter />
|
|
51
|
-
* </template>
|
|
52
168
|
* </SkPage>
|
|
53
169
|
* ```
|
|
54
170
|
*
|
|
55
|
-
* @slot default -
|
|
56
|
-
*
|
|
57
|
-
* @slot
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
171
|
+
* @slot default - Main content. Scrolls inside the content area and receives the default content padding.
|
|
172
|
+
* @slot header - Top-of-page header. Typically a SkNavBar.
|
|
173
|
+
* @slot subheader - Full-width strip between the header and the main row. Good for breadcrumbs or sub-tabs.
|
|
174
|
+
* @slot sidebar - Left sidebar body. Renders inline when persistent, inside a drawer when in drawer mode.
|
|
175
|
+
* Slot props: `{ isDrawer: boolean }` — true when this invocation is the off-canvas drawer.
|
|
176
|
+
* @slot sidebar-header - Pinned top of the sidebar (e.g. logo, search). Renders in the drawer too.
|
|
177
|
+
* Slot props: `{ isDrawer: boolean }`.
|
|
178
|
+
* @slot sidebar-footer - Pinned bottom of the sidebar (e.g. user menu). Renders in the drawer too.
|
|
179
|
+
* Slot props: `{ isDrawer: boolean }`.
|
|
180
|
+
* @slot main-header - Pinned top of the center column (e.g. breadcrumbs, sub-tabs). Does not scroll.
|
|
181
|
+
* @slot main-footer - Pinned bottom of the center column (e.g. status bar). Does not scroll.
|
|
182
|
+
* @slot aside - Right aside body. Persistent or drawer, mirror of the sidebar on the opposite side.
|
|
183
|
+
* Slot props: `{ isDrawer: boolean }` — use to add chrome only when rendering in the drawer.
|
|
184
|
+
* @slot aside-header - Pinned top of the aside (e.g. panel title). Renders in the drawer too.
|
|
185
|
+
* Slot props: `{ isDrawer: boolean }`.
|
|
186
|
+
* @slot aside-footer - Pinned bottom of the aside (e.g. action buttons). Renders in the drawer too.
|
|
187
|
+
* Slot props: `{ isDrawer: boolean }`.
|
|
188
|
+
* @slot footer - Bottom-of-page footer.
|
|
63
189
|
*/
|
|
64
190
|
|
|
65
|
-
import { computed, provide, watch } from 'vue';
|
|
191
|
+
import { type Ref, computed, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue';
|
|
66
192
|
|
|
67
193
|
// Types
|
|
68
194
|
import type { SkThemeName } from '../Theme/types';
|
|
69
|
-
import type {
|
|
195
|
+
import type { SkPagePanelMode } from './types';
|
|
70
196
|
|
|
71
197
|
// Composables
|
|
72
198
|
import { provideTheme } from '../Theme/useTheme';
|
|
199
|
+
import { useFocusTrap } from '@/composables/useFocusTrap';
|
|
200
|
+
import { providePageDrawers } from '@/composables/usePageDrawer';
|
|
73
201
|
|
|
74
202
|
//------------------------------------------------------------------------------------------------------------------
|
|
75
203
|
|
|
76
204
|
export interface SkPageComponentProps
|
|
77
205
|
{
|
|
78
206
|
/**
|
|
79
|
-
*
|
|
80
|
-
* will be positioned on the specified side, with the main content area filling the
|
|
81
|
-
* remaining space. Has no effect if the sidebar slot is not provided.
|
|
82
|
-
* @default 'left'
|
|
83
|
-
*/
|
|
84
|
-
sidebarPosition ?: SkPageSidebarPosition;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* When true, the header remains fixed at the top of the viewport while the main
|
|
88
|
-
* content scrolls beneath it. Useful for keeping navigation always accessible.
|
|
89
|
-
* The content area adjusts its top padding to prevent overlap with the fixed header.
|
|
207
|
+
* When true, the header remains sticky at the top of the viewport while the main content scrolls.
|
|
90
208
|
* @default false
|
|
91
209
|
*/
|
|
92
210
|
fixedHeader ?: boolean;
|
|
93
211
|
|
|
94
212
|
/**
|
|
95
|
-
* When true, the footer remains
|
|
96
|
-
* content scrolls above it. Useful for persistent action bars or important links.
|
|
97
|
-
* The content area adjusts its bottom padding to prevent overlap with the fixed footer.
|
|
213
|
+
* When true, the footer remains sticky at the bottom of the viewport while the main content scrolls.
|
|
98
214
|
* @default false
|
|
99
215
|
*/
|
|
100
216
|
fixedFooter ?: boolean;
|
|
101
217
|
|
|
102
218
|
/**
|
|
103
|
-
* Custom width for the sidebar
|
|
104
|
-
*
|
|
105
|
-
* Only applies when the sidebar slot is provided.
|
|
219
|
+
* Custom width for the sidebar (persistent and drawer). Accepts any CSS length. When not specified,
|
|
220
|
+
* uses the `--sk-page-sidebar-width` token default (16rem).
|
|
106
221
|
*/
|
|
107
222
|
sidebarWidth ?: string;
|
|
108
223
|
|
|
109
224
|
/**
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
|
|
113
|
-
|
|
225
|
+
* Custom width for the aside (persistent and drawer). Accepts any CSS length. When not specified,
|
|
226
|
+
* uses the `--sk-page-aside-width` token default (16rem).
|
|
227
|
+
*/
|
|
228
|
+
asideWidth ?: string;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Sidebar rendering mode.
|
|
232
|
+
* - `auto`: persistent above `sidebarBreakpoint`, drawer below. Default.
|
|
233
|
+
* - `persistent`: always inline.
|
|
234
|
+
* - `drawer`: always off-canvas.
|
|
235
|
+
* @default 'auto'
|
|
236
|
+
*/
|
|
237
|
+
sidebarMode ?: SkPagePanelMode;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Aside rendering mode. Mirror of `sidebarMode` for the right-side panel.
|
|
241
|
+
* @default 'auto'
|
|
242
|
+
*/
|
|
243
|
+
asideMode ?: SkPagePanelMode;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Viewport width below which the sidebar's `auto` mode switches to drawer. Accepts any CSS length.
|
|
247
|
+
* @default '1024px'
|
|
248
|
+
*/
|
|
249
|
+
sidebarBreakpoint ?: string;
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Viewport width below which the aside's `auto` mode switches to drawer. Accepts any CSS length.
|
|
253
|
+
* @default '1024px'
|
|
254
|
+
*/
|
|
255
|
+
asideBreakpoint ?: string;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Controlled sidebar drawer open state. Bind via `v-model:sidebarOpen` to control programmatically.
|
|
259
|
+
* When omitted, SkPage manages state internally.
|
|
260
|
+
*/
|
|
261
|
+
sidebarOpen ?: boolean;
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Controlled aside drawer open state. Bind via `v-model:asideOpen` to control programmatically.
|
|
265
|
+
* When omitted, SkPage manages state internally.
|
|
266
|
+
*/
|
|
267
|
+
asideOpen ?: boolean;
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Optional theme name. When provided, SkPage acts as a theme provider -- setting `data-scheme`
|
|
271
|
+
* on the root element and providing theme context for descendant components (including portal
|
|
272
|
+
* components like dropdowns and modals).
|
|
114
273
|
*/
|
|
115
274
|
theme ?: SkThemeName;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* When true, zeroes out `--sk-page-gap` and `--sk-page-content-padding` so panels and content
|
|
278
|
+
* sit flush against the header, footer, edges, and each other.
|
|
279
|
+
* @default false
|
|
280
|
+
*/
|
|
281
|
+
flush ?: boolean;
|
|
116
282
|
}
|
|
117
283
|
|
|
118
284
|
//------------------------------------------------------------------------------------------------------------------
|
|
119
285
|
|
|
120
286
|
const props = withDefaults(defineProps<SkPageComponentProps>(), {
|
|
121
|
-
sidebarPosition: 'left',
|
|
122
287
|
fixedHeader: false,
|
|
123
288
|
fixedFooter: false,
|
|
124
289
|
sidebarWidth: undefined,
|
|
290
|
+
asideWidth: undefined,
|
|
291
|
+
sidebarMode: 'auto',
|
|
292
|
+
asideMode: 'auto',
|
|
293
|
+
sidebarBreakpoint: '1024px',
|
|
294
|
+
asideBreakpoint: '1024px',
|
|
295
|
+
sidebarOpen: undefined,
|
|
296
|
+
asideOpen: undefined,
|
|
125
297
|
theme: undefined,
|
|
298
|
+
flush: false,
|
|
126
299
|
});
|
|
127
300
|
|
|
301
|
+
const emit = defineEmits<{
|
|
302
|
+
'update:sidebarOpen' : [ value : boolean ];
|
|
303
|
+
'update:asideOpen' : [ value : boolean ];
|
|
304
|
+
}>();
|
|
305
|
+
|
|
306
|
+
const slots = defineSlots<{
|
|
307
|
+
'default' ?: () => unknown;
|
|
308
|
+
'header' ?: () => unknown;
|
|
309
|
+
'subheader' ?: () => unknown;
|
|
310
|
+
'sidebar' ?: (props : { isDrawer : boolean }) => unknown;
|
|
311
|
+
'sidebar-header' ?: (props : { isDrawer : boolean }) => unknown;
|
|
312
|
+
'sidebar-footer' ?: (props : { isDrawer : boolean }) => unknown;
|
|
313
|
+
'main-header' ?: () => unknown;
|
|
314
|
+
'main-footer' ?: () => unknown;
|
|
315
|
+
'aside' ?: (props : { isDrawer : boolean }) => unknown;
|
|
316
|
+
'aside-header' ?: (props : { isDrawer : boolean }) => unknown;
|
|
317
|
+
'aside-footer' ?: (props : { isDrawer : boolean }) => unknown;
|
|
318
|
+
'footer' ?: () => unknown;
|
|
319
|
+
}>();
|
|
320
|
+
|
|
128
321
|
//------------------------------------------------------------------------------------------------------------------
|
|
129
|
-
//
|
|
322
|
+
// Slot-derived state
|
|
130
323
|
//------------------------------------------------------------------------------------------------------------------
|
|
131
324
|
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
[`sk-sidebar-${ props.sidebarPosition }`]: true,
|
|
135
|
-
'sk-fixed-header': props.fixedHeader,
|
|
136
|
-
'sk-fixed-footer': props.fixedFooter,
|
|
137
|
-
}));
|
|
325
|
+
const hasSidebar = computed<boolean>(() => Boolean(slots.sidebar));
|
|
326
|
+
const hasAside = computed<boolean>(() => Boolean(slots.aside));
|
|
138
327
|
|
|
139
328
|
//------------------------------------------------------------------------------------------------------------------
|
|
140
|
-
//
|
|
329
|
+
// Responsive mode detection — driven by SkPage's own width, not the viewport, so embedded
|
|
330
|
+
// demos, split panes, and modal shells collapse based on the space they're actually given.
|
|
141
331
|
//------------------------------------------------------------------------------------------------------------------
|
|
142
332
|
|
|
143
|
-
const
|
|
333
|
+
const rootRef = ref<HTMLElement | null>(null);
|
|
334
|
+
const rootWidth = ref<number>(Number.POSITIVE_INFINITY);
|
|
335
|
+
|
|
336
|
+
function resolvePx(value : string, context : HTMLElement | null) : number
|
|
337
|
+
{
|
|
338
|
+
// Fast path for plain pixel values.
|
|
339
|
+
if(/^\d+(\.\d+)?px$/.test(value)) { return parseFloat(value); }
|
|
340
|
+
|
|
341
|
+
if(typeof document === 'undefined') { return parseFloat(value) || 1024; }
|
|
342
|
+
|
|
343
|
+
// Measure by writing the length into a detached element and reading its computed width.
|
|
344
|
+
// Handles rem, em, vw, ch, etc. in a single mechanism.
|
|
345
|
+
const probe = document.createElement('div');
|
|
346
|
+
probe.style.position = 'absolute';
|
|
347
|
+
probe.style.visibility = 'hidden';
|
|
348
|
+
probe.style.pointerEvents = 'none';
|
|
349
|
+
probe.style.width = value;
|
|
350
|
+
(context ?? document.body).appendChild(probe);
|
|
351
|
+
const px = probe.offsetWidth;
|
|
352
|
+
probe.remove();
|
|
353
|
+
return px;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const sidebarBreakpointPx = computed<number>(() => resolvePx(props.sidebarBreakpoint, rootRef.value));
|
|
357
|
+
const asideBreakpointPx = computed<number>(() => resolvePx(props.asideBreakpoint, rootRef.value));
|
|
358
|
+
|
|
359
|
+
const sidebarBelowBreakpoint = computed<boolean>(() => rootWidth.value < sidebarBreakpointPx.value);
|
|
360
|
+
const asideBelowBreakpoint = computed<boolean>(() => rootWidth.value < asideBreakpointPx.value);
|
|
361
|
+
|
|
362
|
+
let observer : ResizeObserver | null = null;
|
|
363
|
+
|
|
364
|
+
onMounted(() =>
|
|
365
|
+
{
|
|
366
|
+
if(!rootRef.value || typeof ResizeObserver === 'undefined') { return; }
|
|
367
|
+
|
|
368
|
+
rootWidth.value = rootRef.value.clientWidth;
|
|
369
|
+
|
|
370
|
+
observer = new ResizeObserver((entries) =>
|
|
371
|
+
{
|
|
372
|
+
for(const entry of entries)
|
|
373
|
+
{
|
|
374
|
+
// borderBoxSize is the standards-aligned readout; fall back to contentRect for older engines.
|
|
375
|
+
const size = entry.borderBoxSize?.[0];
|
|
376
|
+
rootWidth.value = size ? size.inlineSize : entry.contentRect.width;
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
observer.observe(rootRef.value);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
onBeforeUnmount(() =>
|
|
383
|
+
{
|
|
384
|
+
observer?.disconnect();
|
|
385
|
+
observer = null;
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const isSidebarDrawerActive = computed<boolean>(() =>
|
|
389
|
+
{
|
|
390
|
+
if(!hasSidebar.value) { return false; }
|
|
391
|
+
if(props.sidebarMode === 'drawer') { return true; }
|
|
392
|
+
if(props.sidebarMode === 'persistent') { return false; }
|
|
393
|
+
return sidebarBelowBreakpoint.value;
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
const isAsideDrawerActive = computed<boolean>(() =>
|
|
397
|
+
{
|
|
398
|
+
if(!hasAside.value) { return false; }
|
|
399
|
+
if(props.asideMode === 'drawer') { return true; }
|
|
400
|
+
if(props.asideMode === 'persistent') { return false; }
|
|
401
|
+
return asideBelowBreakpoint.value;
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
405
|
+
// Drawer open state (uncontrolled by default, controlled when the corresponding v-model is bound)
|
|
406
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
407
|
+
|
|
408
|
+
interface DrawerState
|
|
409
|
+
{
|
|
410
|
+
open : Ref<boolean>;
|
|
411
|
+
setOpen : (value : boolean) => void;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function useDrawerState(
|
|
415
|
+
controlledProp : () => boolean | undefined,
|
|
416
|
+
setControlled : (value : boolean) => void,
|
|
417
|
+
isActive : Ref<boolean>
|
|
418
|
+
) : DrawerState
|
|
144
419
|
{
|
|
145
|
-
|
|
420
|
+
const internal = ref<boolean>(false);
|
|
421
|
+
const isControlled = computed<boolean>(() => controlledProp() !== undefined);
|
|
422
|
+
|
|
423
|
+
const open = computed<boolean>(() =>
|
|
146
424
|
{
|
|
147
|
-
return
|
|
148
|
-
|
|
425
|
+
if(!isActive.value) { return false; }
|
|
426
|
+
if(isControlled.value) { return controlledProp() === true; }
|
|
427
|
+
return internal.value;
|
|
428
|
+
});
|
|
149
429
|
|
|
150
|
-
|
|
151
|
-
|
|
430
|
+
const setOpen = (value : boolean) : void =>
|
|
431
|
+
{
|
|
432
|
+
if(!isControlled.value) { internal.value = value; }
|
|
433
|
+
setControlled(value);
|
|
152
434
|
};
|
|
435
|
+
|
|
436
|
+
// Collapse open state if layout becomes persistent (e.g. user widens the viewport).
|
|
437
|
+
watch(isActive, (active) =>
|
|
438
|
+
{
|
|
439
|
+
if(!active && open.value) { setOpen(false); }
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
return { open, setOpen };
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const sidebar = useDrawerState(
|
|
446
|
+
() => props.sidebarOpen,
|
|
447
|
+
(value) => emit('update:sidebarOpen', value),
|
|
448
|
+
isSidebarDrawerActive
|
|
449
|
+
);
|
|
450
|
+
const aside = useDrawerState(
|
|
451
|
+
() => props.asideOpen,
|
|
452
|
+
(value) => emit('update:asideOpen', value),
|
|
453
|
+
isAsideDrawerActive
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
const sidebarDrawerOpen = sidebar.open;
|
|
457
|
+
const asideDrawerOpen = aside.open;
|
|
458
|
+
|
|
459
|
+
const closeSidebarDrawer = () : void => sidebar.setOpen(false);
|
|
460
|
+
const closeAsideDrawer = () : void => aside.setOpen(false);
|
|
461
|
+
|
|
462
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
463
|
+
// Click-to-dismiss on empty drawer chrome. We don't use `pointer-events: none` for this
|
|
464
|
+
// because that also blocks wheel/touch scrolling inside the drawer body. Instead we listen
|
|
465
|
+
// for clicks on the drawer and close when the target wasn't something interactive.
|
|
466
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
467
|
+
|
|
468
|
+
const INTERACTIVE_SELECTOR = [
|
|
469
|
+
'a[href]',
|
|
470
|
+
'button:not([disabled])',
|
|
471
|
+
'input:not([disabled]):not([type="hidden"])',
|
|
472
|
+
'select:not([disabled])',
|
|
473
|
+
'textarea:not([disabled])',
|
|
474
|
+
'label',
|
|
475
|
+
'summary',
|
|
476
|
+
'[role="button"]',
|
|
477
|
+
'[role="link"]',
|
|
478
|
+
'[role="menuitem"]',
|
|
479
|
+
'[role="option"]',
|
|
480
|
+
'[role="tab"]',
|
|
481
|
+
'[role="checkbox"]',
|
|
482
|
+
'[role="radio"]',
|
|
483
|
+
'[role="switch"]',
|
|
484
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
485
|
+
'.sk-sidebar-item',
|
|
486
|
+
].join(',');
|
|
487
|
+
|
|
488
|
+
function onSidebarDrawerClick(event : MouseEvent) : void
|
|
489
|
+
{
|
|
490
|
+
const target = event.target as HTMLElement | null;
|
|
491
|
+
if(!target || !target.closest(INTERACTIVE_SELECTOR)) { closeSidebarDrawer(); }
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function onAsideDrawerClick(event : MouseEvent) : void
|
|
495
|
+
{
|
|
496
|
+
const target = event.target as HTMLElement | null;
|
|
497
|
+
if(!target || !target.closest(INTERACTIVE_SELECTOR)) { closeAsideDrawer(); }
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
501
|
+
// Provide drawer context for toggle components
|
|
502
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
503
|
+
|
|
504
|
+
providePageDrawers(
|
|
505
|
+
{ isOpen: sidebarDrawerOpen, isAvailable: isSidebarDrawerActive, setOpen: sidebar.setOpen },
|
|
506
|
+
{ isOpen: asideDrawerOpen, isAvailable: isAsideDrawerActive, setOpen: aside.setOpen }
|
|
507
|
+
);
|
|
508
|
+
|
|
509
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
510
|
+
// Focus trap
|
|
511
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
512
|
+
|
|
513
|
+
const sidebarDrawerRef = ref<HTMLElement | null>(null);
|
|
514
|
+
const asideDrawerRef = ref<HTMLElement | null>(null);
|
|
515
|
+
|
|
516
|
+
useFocusTrap({
|
|
517
|
+
active: sidebarDrawerOpen,
|
|
518
|
+
container: sidebarDrawerRef,
|
|
519
|
+
onEscape: closeSidebarDrawer,
|
|
520
|
+
});
|
|
521
|
+
useFocusTrap({
|
|
522
|
+
active: asideDrawerOpen,
|
|
523
|
+
container: asideDrawerRef,
|
|
524
|
+
onEscape: closeAsideDrawer,
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
528
|
+
// Classes & styles
|
|
529
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
530
|
+
|
|
531
|
+
const classes = computed(() => ({
|
|
532
|
+
'sk-page': true,
|
|
533
|
+
'sk-fixed-header': props.fixedHeader,
|
|
534
|
+
'sk-fixed-footer': props.fixedFooter,
|
|
535
|
+
'sk-sidebar-drawer-active': isSidebarDrawerActive.value,
|
|
536
|
+
'sk-aside-drawer-active': isAsideDrawerActive.value,
|
|
537
|
+
'sk-flush': props.flush,
|
|
538
|
+
}));
|
|
539
|
+
|
|
540
|
+
const customStyles = computed(() =>
|
|
541
|
+
{
|
|
542
|
+
const styles : Record<string, string> = {};
|
|
543
|
+
if(props.sidebarWidth) { styles['--sk-page-sidebar-width'] = props.sidebarWidth; }
|
|
544
|
+
if(props.asideWidth) { styles['--sk-page-aside-width'] = props.asideWidth; }
|
|
545
|
+
return styles;
|
|
153
546
|
});
|
|
154
547
|
|
|
155
548
|
//------------------------------------------------------------------------------------------------------------------
|
|
@@ -159,19 +552,14 @@
|
|
|
159
552
|
if(props.theme)
|
|
160
553
|
{
|
|
161
554
|
const { currentTheme, setTheme } = provideTheme(props.theme);
|
|
162
|
-
|
|
163
|
-
// Provide theme for portal components (dropdown, modal, tooltip, etc.)
|
|
164
555
|
provide('sk-theme', currentTheme);
|
|
165
556
|
|
|
166
|
-
// Watch for external theme prop changes
|
|
167
557
|
watch(() => props.theme, (newTheme) =>
|
|
168
558
|
{
|
|
169
|
-
if(newTheme)
|
|
170
|
-
{
|
|
171
|
-
setTheme(newTheme);
|
|
172
|
-
}
|
|
559
|
+
if(newTheme) { setTheme(newTheme); }
|
|
173
560
|
});
|
|
174
561
|
}
|
|
562
|
+
|
|
175
563
|
</script>
|
|
176
564
|
|
|
177
565
|
<!--------------------------------------------------------------------------------------------------------------------->
|