@una-ui/nuxt 0.40.0-beta.1 → 0.41.0-beta.1

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 (52) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +10 -4
  3. package/dist/runtime/components/data/table/Table.vue +1 -0
  4. package/dist/runtime/components/elements/Button.vue +1 -0
  5. package/dist/runtime/components/elements/Link.vue +53 -18
  6. package/dist/runtime/components/elements/Link.vue.d.ts +1 -0
  7. package/dist/runtime/components/forms/select/SelectTrigger.vue +2 -1
  8. package/dist/runtime/components/misc/ThemeSwitcher.vue +5 -3
  9. package/dist/runtime/components/navigation/breadcrumb/BreadcrumbPage.vue +19 -0
  10. package/dist/runtime/components/overlays/toast/Toast.vue +3 -3
  11. package/dist/runtime/components/overlays/toast/ToastClose.vue +1 -1
  12. package/dist/runtime/components/overlays/toast/ToastDescription.vue +1 -1
  13. package/dist/runtime/components/overlays/toast/ToastInfo.vue +1 -1
  14. package/dist/runtime/components/overlays/toast/ToastTitle.vue +1 -1
  15. package/dist/runtime/components/overlays/toast/ToastViewport.vue +1 -1
  16. package/dist/runtime/components/sheet/Sheet.vue +64 -62
  17. package/dist/runtime/components/sidebar/Sidebar.vue +115 -0
  18. package/dist/runtime/components/sidebar/SidebarContent.vue +22 -0
  19. package/dist/runtime/components/sidebar/SidebarFooter.vue +19 -0
  20. package/dist/runtime/components/sidebar/SidebarGroup.vue +28 -0
  21. package/dist/runtime/components/sidebar/SidebarGroupAction.vue +25 -0
  22. package/dist/runtime/components/sidebar/SidebarGroupContent.vue +19 -0
  23. package/dist/runtime/components/sidebar/SidebarGroupLabel.vue +25 -0
  24. package/dist/runtime/components/sidebar/SidebarHeader.vue +19 -0
  25. package/dist/runtime/components/sidebar/SidebarInput.vue +20 -0
  26. package/dist/runtime/components/sidebar/SidebarInset.vue +18 -0
  27. package/dist/runtime/components/sidebar/SidebarMenu.vue +30 -0
  28. package/dist/runtime/components/sidebar/SidebarMenuAction.vue +25 -0
  29. package/dist/runtime/components/sidebar/SidebarMenuBadge.vue +19 -0
  30. package/dist/runtime/components/sidebar/SidebarMenuButton.vue +59 -0
  31. package/dist/runtime/components/sidebar/SidebarMenuButtonChild.vue +64 -0
  32. package/dist/runtime/components/sidebar/SidebarMenuItem.vue +19 -0
  33. package/dist/runtime/components/sidebar/SidebarMenuSkeleton.vue +37 -0
  34. package/dist/runtime/components/sidebar/SidebarMenuSub.vue +19 -0
  35. package/dist/runtime/components/sidebar/SidebarMenuSubButton.vue +31 -0
  36. package/dist/runtime/components/sidebar/SidebarMenuSubItem.vue +18 -0
  37. package/dist/runtime/components/sidebar/SidebarProvider.vue +82 -0
  38. package/dist/runtime/components/sidebar/SidebarRail.vue +26 -0
  39. package/dist/runtime/components/sidebar/SidebarSeparator.vue +20 -0
  40. package/dist/runtime/components/sidebar/SidebarTrigger.vue +28 -0
  41. package/dist/runtime/composables/useSidebar.d.ts +56 -0
  42. package/dist/runtime/composables/useSidebar.js +8 -0
  43. package/dist/runtime/types/index.d.ts +1 -0
  44. package/dist/runtime/types/index.js +1 -0
  45. package/dist/runtime/types/link.d.ts +1 -1
  46. package/dist/runtime/types/sheet.d.ts +53 -0
  47. package/dist/runtime/types/sidebar.d.ts +545 -0
  48. package/dist/runtime/types/sidebar.js +0 -0
  49. package/dist/una.config.d.mts +5 -2
  50. package/dist/una.config.d.ts +5 -2
  51. package/dist/una.config.mjs +44 -31
  52. package/package.json +13 -12
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@una-ui/nuxt",
3
3
  "configKey": "una",
4
- "version": "0.40.0-beta.1",
4
+ "version": "0.41.0-beta.1",
5
5
  "compatibility": {
6
6
  "nuxt": ">=3.0.0"
7
7
  },
package/dist/module.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { defineNuxtModule, createResolver, addComponentsDir, addPlugin, addImportsDir, installModule } from '@nuxt/kit';
2
2
  import extendUnocssOptions from './una.config.mjs';
3
+ import '@iconify/utils/lib/loader/external-pkg';
3
4
  import '@una-ui/extractor-vue-script';
4
5
  import '@una-ui/preset';
5
6
  import '@una-ui/preset/prefixes';
@@ -7,7 +8,7 @@ import 'unocss';
7
8
  import 'unocss-preset-animations';
8
9
 
9
10
  const name = "@una-ui/nuxt";
10
- const version = "0.40.0-beta.1";
11
+ const version = "0.41.0-beta.1";
11
12
 
12
13
  const module = defineNuxtModule({
13
14
  meta: {
@@ -169,6 +170,13 @@ const module = defineNuxtModule({
169
170
  watch: nuxt.options.dev,
170
171
  priority: 10
171
172
  });
173
+ addComponentsDir({
174
+ path: resolve(runtimeDir, "components", "sidebar"),
175
+ prefix: options.prefix,
176
+ global: options.global,
177
+ watch: nuxt.options.dev,
178
+ priority: 10
179
+ });
172
180
  addComponentsDir({
173
181
  path: resolve(runtimeDir, "components", "scroll-area"),
174
182
  prefix: options.prefix,
@@ -180,10 +188,8 @@ const module = defineNuxtModule({
180
188
  addPlugin(resolve(runtimeDir, "plugins", "theme.client"));
181
189
  addPlugin(resolve(runtimeDir, "plugins", "theme.server"));
182
190
  }
183
- if (!options.dev)
184
- nuxt.options.unocss = extendUnocssOptions(nuxt.options.unocss);
185
191
  addImportsDir(resolve(runtimeDir, "utils", "cn"));
186
- await installModule("@unocss/nuxt");
192
+ await installModule("@unocss/nuxt", extendUnocssOptions(nuxt.options.unocss));
187
193
  await installModule("@nuxtjs/color-mode", {
188
194
  classSuffix: ""
189
195
  });
@@ -296,6 +296,7 @@ defineExpose({
296
296
  :key="header.id"
297
297
  :una
298
298
  :colspan="header.colSpan"
299
+ class="font-normal"
299
300
  :data-pinned="header.column.getIsPinned()"
300
301
  v-bind="{ ...props._tableHead, ...header.column.columnDef.meta }"
301
302
  >
@@ -8,6 +8,7 @@ import NLink from '../elements/Link.vue'
8
8
 
9
9
  const props = withDefaults(defineProps<NButtonProps>(), {
10
10
  type: 'button',
11
+ size: 'sm',
11
12
  loadingPlacement: 'leading',
12
13
  square: false,
13
14
  una: () => ({
@@ -1,6 +1,7 @@
1
1
  <script>
2
2
  import { NuxtLink } from "#components";
3
- import { isEqual } from "ohash";
3
+ import { useRoute } from "#imports";
4
+ import { diff, isEqual } from "ohash/utils";
4
5
  import { defineComponent } from "vue";
5
6
  export default defineComponent({
6
7
  inheritAttrs: false,
@@ -24,7 +25,7 @@ export default defineComponent({
24
25
  type: String,
25
26
  default: void 0
26
27
  },
27
- // preset
28
+ // TODO: convert to sidebar preset
28
29
  navLinkActive: {
29
30
  type: String,
30
31
  default: void 0
@@ -35,10 +36,11 @@ export default defineComponent({
35
36
  }
36
37
  },
37
38
  setup(props) {
38
- function resolveLinkClass(route, $route, { isActive, isExactActive }) {
39
- if (props.exactQuery && !isEqual(route.query, $route.query))
39
+ const route = useRoute();
40
+ function resolveLinkClass(route2, $route, { isActive, isExactActive }) {
41
+ if (props.exactQuery && !isEqual(route2.query, $route.query))
40
42
  return props.inactiveClass;
41
- if (props.exactHash && !isEqual(route.hash, $route.hash))
43
+ if (props.exactHash && !isEqual(route2.hash, $route.hash))
42
44
  return props.inactiveClass;
43
45
  if (props.exact && isExactActive)
44
46
  return props.exactActiveClass;
@@ -46,10 +48,10 @@ export default defineComponent({
46
48
  return props.activeClass;
47
49
  return props.inactiveClass;
48
50
  }
49
- function resolveNavLinkActive(route, $route, { isActive, isExactActive }) {
50
- if (props.exactQuery && !isEqual(route.query, $route.query))
51
+ function resolveNavLinkActive(route2, $route, { isActive, isExactActive }) {
52
+ if (props.exactQuery && !isEqual(route2.query, $route.query))
51
53
  return null;
52
- if (props.exactHash && !isEqual(route.hash, $route.hash))
54
+ if (props.exactHash && !isEqual(route2.hash, $route.hash))
53
55
  return null;
54
56
  if (props.exact && isExactActive)
55
57
  return props.navLinkActive;
@@ -57,42 +59,75 @@ export default defineComponent({
57
59
  return props.navLinkActive;
58
60
  return null;
59
61
  }
60
- function resolveNavLinkInactive(route, $route, { isActive, isExactActive }) {
61
- if (props.exactQuery && !isEqual(route.query, $route.query))
62
+ function resolveNavLinkInactive(route2, $route, { isActive, isExactActive }) {
63
+ if (props.exactQuery && !isEqual(route2.query, $route.query))
62
64
  return props.navLinkInactive;
63
- if (props.exactHash && !isEqual(route.hash, $route.hash))
65
+ if (props.exactHash && !isEqual(route2.hash, $route.hash))
64
66
  return props.navLinkInactive;
65
67
  if (!props.exact && isActive || props.exact && isExactActive)
66
68
  return null;
67
69
  return props.navLinkInactive;
68
70
  }
71
+ function isPartiallyEqual(item1, item2) {
72
+ const diffedKeys = diff(item1, item2).reduce((filtered, q) => {
73
+ if (q.type === "added") {
74
+ filtered.add(q.key);
75
+ }
76
+ return filtered;
77
+ }, /* @__PURE__ */ new Set());
78
+ const item1Filtered = Object.fromEntries(Object.entries(item1).filter(([key]) => !diffedKeys.has(key)));
79
+ const item2Filtered = Object.fromEntries(Object.entries(item2).filter(([key]) => !diffedKeys.has(key)));
80
+ return isEqual(item1Filtered, item2Filtered);
81
+ }
82
+ function isLinkActive({ route: linkRoute, isActive, isExactActive }) {
83
+ if (props.active !== void 0) {
84
+ return props.active;
85
+ }
86
+ if (props.exactQuery === "partial") {
87
+ if (!isPartiallyEqual(linkRoute.query, route.query))
88
+ return false;
89
+ } else if (props.exactQuery === true) {
90
+ if (!isEqual(linkRoute.query, route.query))
91
+ return false;
92
+ }
93
+ if (props.exactHash && linkRoute.hash !== route.hash) {
94
+ return false;
95
+ }
96
+ if (props.exact && isExactActive) {
97
+ return true;
98
+ }
99
+ if (!props.exact && isActive) {
100
+ return true;
101
+ }
102
+ return false;
103
+ }
69
104
  return {
70
105
  resolveLinkClass,
71
106
  resolveNavLinkActive,
72
- resolveNavLinkInactive
107
+ resolveNavLinkInactive,
108
+ isLinkActive
73
109
  };
74
110
  }
75
111
  });
76
112
  </script>
77
113
 
78
114
  <template>
79
- <!-- eslint-disable vue/no-template-shadow -->
80
115
  <NuxtLink
81
- v-slot="{ route, href, target, rel, navigate, isActive, isExactActive, isExternal, exact }"
116
+ v-slot="{ route, href, target, rel, navigate, isActive, isExactActive, isExternal }"
82
117
  v-bind="$props"
83
118
  custom
84
119
  >
85
120
  <a
86
121
  v-bind="$attrs"
87
- :href="href"
88
- :rel="rel"
89
- :target="target"
122
+ :href
123
+ :rel="rel ?? undefined"
124
+ :target="target ?? undefined"
90
125
  :class="resolveLinkClass(route, $route, { isActive, isExactActive })"
91
126
  :nav-link-active="resolveNavLinkActive(route, $route, { isActive, isExactActive })"
92
127
  :nav-link-inactive="resolveNavLinkInactive(route, $route, { isActive, isExactActive })"
93
128
  @click="(e) => !isExternal && navigate(e)"
94
129
  >
95
- <slot v-bind="{ isActive: exact ? isExactActive : isActive }" />
130
+ <slot :active="isLinkActive({ route, isActive, isExactActive })" />
96
131
  </a>
97
132
  </NuxtLink>
98
133
  </template>
@@ -11,6 +11,7 @@ declare const _default: import("vue").DefineComponent<{}, {
11
11
  isActive: boolean;
12
12
  isExactActive: boolean;
13
13
  }) => string | null;
14
+ isLinkActive: ({ route: linkRoute, isActive, isExactActive }: any) => any;
14
15
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {} | {
15
16
  [x: string]: any;
16
17
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -25,7 +25,7 @@ const statusClassVariants = computed(() => {
25
25
  success: props.una?.selectTriggerSuccessIcon ?? 'select-trigger-success-icon',
26
26
  warning: props.una?.selectTriggerWarningIcon ?? 'select-trigger-warning-icon',
27
27
  error: props.una?.selectTriggerErrorIcon ?? 'select-trigger-error-icon',
28
- default: props.una?.selectTriggerTrailingIcon ?? 'select-trigger-trailing-icon',
28
+ default: props?.trailing ?? props.una?.selectTriggerTrailingIcon ?? 'select-trigger-trailing-icon',
29
29
  }
30
30
 
31
31
  return {
@@ -35,6 +35,7 @@ const statusClassVariants = computed(() => {
35
35
  })
36
36
 
37
37
  const id = computed(() => props.id ?? randomId('select-trigger'))
38
+ const status = computed(() => props.status ?? 'default')
38
39
  </script>
39
40
 
40
41
  <template>
@@ -48,9 +48,11 @@ function shuffleTheme(): void {
48
48
  </script>
49
49
 
50
50
  <template>
51
- <Popover :_popover-content="{ align: 'end', class: 'w-73 bg-muted' }">
52
- <template #trigger>
53
- <slot name="trigger">
51
+ <Popover
52
+ :_popover-content="{ align: 'end', class: 'w-73 bg-muted' }"
53
+ >
54
+ <template #trigger="{ open }">
55
+ <slot name="trigger" :open="open">
54
56
  <Button
55
57
  btn="soft"
56
58
  square
@@ -0,0 +1,19 @@
1
+ <script lang="ts" setup>
2
+ import type { HTMLAttributes } from 'vue'
3
+ import { cn } from '../../../utils'
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes['class']
7
+ }>()
8
+ </script>
9
+
10
+ <template>
11
+ <span
12
+ role="link"
13
+ aria-disabled="true"
14
+ aria-current="page"
15
+ :class="cn('font-normal text-base', props.class)"
16
+ >
17
+ <slot />
18
+ </span>
19
+ </template>
@@ -23,7 +23,7 @@ const props = withDefaults(defineProps<NToastProps>(), {
23
23
  })
24
24
 
25
25
  const emits = defineEmits<ToastRootEmits>()
26
- const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultOpen', 'open', 'duration', 'type'), emits)
26
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'asChild', 'defaultOpen', 'open', 'duration', 'type', 'forceMount'), emits)
27
27
  </script>
28
28
 
29
29
  <template>
@@ -31,10 +31,10 @@ const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultOpen',
31
31
  v-slot="{ remaining, duration }"
32
32
  :class="cn(
33
33
  'group toast data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--reka-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--reka-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',
34
- props.class,
35
34
  props.una?.toast,
35
+ props.class,
36
36
  )"
37
- v-bind="rootProps"
37
+ v-bind="{ ...rootProps, ...$attrs }"
38
38
  :toast
39
39
  @update:open="onOpenChange"
40
40
  >
@@ -19,8 +19,8 @@ const delegatedProps = computed(() => {
19
19
  v-bind="delegatedProps"
20
20
  :class="cn(
21
21
  'toast-close',
22
- props.class,
23
22
  props.una?.toastClose,
23
+ props.class,
24
24
  )"
25
25
  >
26
26
  <Icon
@@ -18,8 +18,8 @@ const delegatedProps = computed(() => {
18
18
  v-bind="delegatedProps"
19
19
  :class="cn(
20
20
  'toast-description',
21
- props.class,
22
21
  props.una?.toastDescription,
22
+ props.class,
23
23
  )"
24
24
  >
25
25
  <slot />
@@ -9,8 +9,8 @@ const props = defineProps<NToastInfoProps>()
9
9
  <div
10
10
  :class="cn(
11
11
  'toast-info',
12
- props.class,
13
12
  props.una?.toastInfo,
13
+ props.class,
14
14
  )"
15
15
  >
16
16
  <slot />
@@ -18,8 +18,8 @@ const delegatedProps = computed(() => {
18
18
  v-bind="delegatedProps"
19
19
  :class="cn(
20
20
  'toast-title',
21
- props.class,
22
21
  props.una?.toastTitle,
22
+ props.class,
23
23
  )"
24
24
  >
25
25
  <slot />
@@ -18,8 +18,8 @@ const delegatedProps = computed(() => {
18
18
  v-bind="delegatedProps"
19
19
  :class="cn(
20
20
  'toast-viewport',
21
- props.class,
22
21
  props.una?.toastViewport,
22
+ props.class,
23
23
  )"
24
24
  />
25
25
  </template>
@@ -30,73 +30,75 @@ const forwarded = useForwardPropsEmits(rootProps, emits)
30
30
 
31
31
  <template>
32
32
  <DialogRoot v-slot="{ open }" v-bind="forwarded">
33
- <SheetTrigger
34
- v-if="$slots.trigger"
35
- v-bind="_sheetTrigger"
36
- >
37
- <slot name="trigger" :open />
38
- </SheetTrigger>
33
+ <slot name="root">
34
+ <SheetTrigger
35
+ v-if="$slots.trigger"
36
+ v-bind="_sheetTrigger"
37
+ >
38
+ <slot name="trigger" :open />
39
+ </SheetTrigger>
39
40
 
40
- <SheetContent
41
- :_sheet-close
42
- :_sheet-overlay
43
- :_sheet-portal
44
- :sheet
45
- :prevent-close
46
- :show-close
47
- :overlay
48
- v-bind="_sheetContent"
49
- :una
50
- >
51
- <VisuallyHidden v-if="(title === DEFAULT_TITLE || !!$slots.title) || (description === DEFAULT_DESCRIPTION || !!$slots.description)">
52
- <SheetTitle v-if="title === DEFAULT_TITLE || !!$slots.title">
53
- {{ title }}
54
- </SheetTitle>
41
+ <SheetContent
42
+ :_sheet-close
43
+ :_sheet-overlay
44
+ :_sheet-portal
45
+ :sheet
46
+ :prevent-close
47
+ :show-close
48
+ :overlay
49
+ v-bind="_sheetContent"
50
+ :una
51
+ >
52
+ <VisuallyHidden v-if="(title === DEFAULT_TITLE || !!$slots.title) || (description === DEFAULT_DESCRIPTION || !!$slots.description)">
53
+ <SheetTitle v-if="title === DEFAULT_TITLE || !!$slots.title">
54
+ {{ title }}
55
+ </SheetTitle>
55
56
 
56
- <SheetDescription v-if="description === DEFAULT_DESCRIPTION || !!$slots.description">
57
- {{ description }}
58
- </SheetDescription>
59
- </VisuallyHidden>
57
+ <SheetDescription v-if="description === DEFAULT_DESCRIPTION || !!$slots.description">
58
+ {{ description }}
59
+ </SheetDescription>
60
+ </VisuallyHidden>
60
61
 
61
- <slot name="content">
62
- <SheetHeader
63
- v-if="!!$slots.header || (title !== DEFAULT_TITLE || !!$slots.title) || (description !== DEFAULT_DESCRIPTION || !!$slots.description)"
64
- v-bind="_sheetHeader"
65
- :una
66
- >
67
- <slot name="header">
68
- <SheetTitle
69
- v-if="$slots.title || title !== DEFAULT_TITLE"
70
- v-bind="_sheetTitle"
71
- :una
72
- >
73
- <slot name="title">
74
- {{ title }}
75
- </slot>
76
- </SheetTitle>
62
+ <slot name="content">
63
+ <SheetHeader
64
+ v-if="!!$slots.header || (title !== DEFAULT_TITLE || !!$slots.title) || (description !== DEFAULT_DESCRIPTION || !!$slots.description)"
65
+ v-bind="_sheetHeader"
66
+ :una
67
+ >
68
+ <slot name="header">
69
+ <SheetTitle
70
+ v-if="$slots.title || title !== DEFAULT_TITLE"
71
+ v-bind="_sheetTitle"
72
+ :una
73
+ >
74
+ <slot name="title">
75
+ {{ title }}
76
+ </slot>
77
+ </SheetTitle>
77
78
 
78
- <SheetDescription
79
- v-if="$slots.description || description !== DEFAULT_DESCRIPTION"
80
- v-bind="_sheetDescription"
81
- :una
82
- >
83
- <slot name="description">
84
- {{ description }}
85
- </slot>
86
- </SheetDescription>
87
- </slot>
88
- </SheetHeader>
79
+ <SheetDescription
80
+ v-if="$slots.description || description !== DEFAULT_DESCRIPTION"
81
+ v-bind="_sheetDescription"
82
+ :una
83
+ >
84
+ <slot name="description">
85
+ {{ description }}
86
+ </slot>
87
+ </SheetDescription>
88
+ </slot>
89
+ </SheetHeader>
89
90
 
90
- <slot />
91
+ <slot />
91
92
 
92
- <SheetFooter
93
- v-if="$slots.footer"
94
- v-bind="_sheetFooter"
95
- :una
96
- >
97
- <slot name="footer" />
98
- </SheetFooter>
99
- </slot>
100
- </SheetContent>
93
+ <SheetFooter
94
+ v-if="$slots.footer"
95
+ v-bind="_sheetFooter"
96
+ :una
97
+ >
98
+ <slot name="footer" />
99
+ </SheetFooter>
100
+ </slot>
101
+ </SheetContent>
102
+ </slot>
101
103
  </DialogRoot>
102
104
  </template>
@@ -0,0 +1,115 @@
1
+ <script setup lang="ts">
2
+ import type { NSidebarProps } from '../../types'
3
+ import { createReusableTemplate } from '@vueuse/core'
4
+ import { SIDEBAR_WIDTH_MOBILE, useSidebar } from '../../composables/useSidebar'
5
+ import { cn } from '../../utils'
6
+ import Sheet from '../sheet/Sheet.vue'
7
+ import SidebarContent from './SidebarContent.vue'
8
+ import SidebarFooter from './SidebarFooter.vue'
9
+ import SidebarHeader from './SidebarHeader.vue'
10
+
11
+ defineOptions({
12
+ inheritAttrs: false,
13
+ })
14
+
15
+ const props = withDefaults(defineProps<NSidebarProps>(), {
16
+ sheet: 'left',
17
+ sidebar: 'sidebar',
18
+ collapsible: 'offcanvas',
19
+ rail: true,
20
+ })
21
+
22
+ const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
23
+
24
+ const [DefineSlot, ReuseSlot] = createReusableTemplate()
25
+ </script>
26
+
27
+ <template>
28
+ <DefineSlot>
29
+ <slot>
30
+ <SidebarHeader v-bind="props._sidebarHeader">
31
+ <slot name="header" />
32
+ </SidebarHeader>
33
+ <SidebarContent v-bind="props._sidebarContent">
34
+ <slot name="content" />
35
+ </SidebarContent>
36
+ <SidebarFooter v-bind="props._sidebarFooter">
37
+ <slot name="footer" />
38
+ </SidebarFooter>
39
+ <NSidebarRail v-if="rail" v-bind="props._sidebarRail" />
40
+ </slot>
41
+ </DefineSlot>
42
+
43
+ <div
44
+ v-if="collapsible === 'none'"
45
+ :class="cn(
46
+ 'sidebar-collapsible-none',
47
+ props.una?.sidebar,
48
+ props.class,
49
+ )"
50
+ v-bind="$attrs"
51
+ >
52
+ <ReuseSlot />
53
+ </div>
54
+
55
+ <Sheet
56
+ v-else-if="isMobile"
57
+ :open="openMobile"
58
+ v-bind="$attrs"
59
+ :_sheet-content="{
60
+ dataSidebar: 'sidebar',
61
+ dataMobile: true,
62
+ sheet,
63
+ class: 'sidebar-mobile',
64
+ style: {
65
+ '--sidebar-width': SIDEBAR_WIDTH_MOBILE,
66
+ },
67
+ ...props._sheetContent,
68
+ }"
69
+ @update:open="setOpenMobile"
70
+ >
71
+ <div class="sidebar-mobile-inner">
72
+ <ReuseSlot />
73
+ </div>
74
+ </Sheet>
75
+
76
+ <div
77
+ v-else :class="cn('group peer sidebar-desktop')"
78
+ :data-state="state"
79
+ :data-collapsible="state === 'collapsed' ? collapsible : ''"
80
+ :data-variant="sidebar"
81
+ :data-side="sheet"
82
+ >
83
+ <!-- This is what handles the sidebar gap on desktop -->
84
+ <div
85
+ :class="cn(
86
+ 'sidebar-desktop-gap',
87
+ sidebar === 'floating' || sidebar === 'inset'
88
+ ? 'sidebar-desktop-gap-floating'
89
+ : 'sidebar-desktop-gap-default',
90
+ )"
91
+ />
92
+ <div
93
+ :class="cn(
94
+ 'sidebar-desktop-position',
95
+ sheet === 'left'
96
+ ? 'sidebar-desktop-position-left'
97
+ : 'sidebar-desktop-position-right',
98
+ // Adjust the padding for floating and inset variants.
99
+ sidebar === 'floating' || sidebar === 'inset'
100
+ ? 'sidebar-desktop-padding-floating'
101
+ : 'sidebar-desktop-padding-default',
102
+ props.una?.sidebar,
103
+ props.class,
104
+ )"
105
+ v-bind="$attrs"
106
+ >
107
+ <div
108
+ data-sidebar="sidebar"
109
+ class="sidebar-desktop-inner"
110
+ >
111
+ <ReuseSlot />
112
+ </div>
113
+ </div>
114
+ </div>
115
+ </template>
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ import type { NSidebarContentProps } from '../../types'
3
+ import { cn } from '../../utils'
4
+ import ScrollArea from '../scroll-area/ScrollArea.vue'
5
+
6
+ const props = defineProps<NSidebarContentProps>()
7
+ </script>
8
+
9
+ <template>
10
+ <div
11
+ data-sidebar="content"
12
+ :class="cn(
13
+ 'sidebar-content',
14
+ props.una?.sidebarContent,
15
+ props.class,
16
+ )"
17
+ >
18
+ <ScrollArea>
19
+ <slot />
20
+ </ScrollArea>
21
+ </div>
22
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import type { NSidebarFooterProps } from '../../types'
3
+ import { cn } from '../../utils'
4
+
5
+ const props = defineProps<NSidebarFooterProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <div
10
+ data-sidebar="footer"
11
+ :class="cn(
12
+ 'sidebar-footer',
13
+ props.una?.sidebarFooter,
14
+ props.class,
15
+ )"
16
+ >
17
+ <slot />
18
+ </div>
19
+ </template>
@@ -0,0 +1,28 @@
1
+ <script setup lang="ts">
2
+ import type { NSidebarGroupProps } from '../../types'
3
+ import { cn } from '../../utils'
4
+ import SidebarGroupLabel from './SidebarGroupLabel.vue'
5
+
6
+ const props = defineProps<NSidebarGroupProps>()
7
+ </script>
8
+
9
+ <template>
10
+ <div
11
+ data-sidebar="group"
12
+ :class="cn(
13
+ 'sidebar-group',
14
+ props.una?.sidebarGroup,
15
+ props.class,
16
+ )"
17
+ >
18
+ <slot name="root">
19
+ <SidebarGroupLabel v-if="props.label">
20
+ <slot name="label">
21
+ {{ props.label }}
22
+ </slot>
23
+ </SidebarGroupLabel>
24
+
25
+ <slot />
26
+ </slot>
27
+ </div>
28
+ </template>