@bitrix24/b24ui-nuxt 0.4.9 → 0.4.11
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/.nuxt/b24ui/collapsible.ts +6 -0
- package/.nuxt/b24ui/index.ts +15 -0
- package/.nuxt/b24ui/navbar-divider.ts +5 -0
- package/.nuxt/b24ui/navbar-section.ts +5 -0
- package/.nuxt/b24ui/navbar-spacer.ts +5 -0
- package/.nuxt/b24ui/navbar.ts +5 -0
- package/.nuxt/b24ui/navigation-menu.ts +299 -0
- package/.nuxt/b24ui/sidebar-body.ts +15 -0
- package/.nuxt/b24ui/sidebar-footer.ts +5 -0
- package/.nuxt/b24ui/sidebar-header.ts +5 -0
- package/.nuxt/b24ui/sidebar-heading.ts +5 -0
- package/.nuxt/b24ui/sidebar-layout.ts +38 -0
- package/.nuxt/b24ui/sidebar-section.ts +5 -0
- package/.nuxt/b24ui/sidebar-spacer.ts +5 -0
- package/.nuxt/b24ui/sidebar.ts +5 -0
- package/.nuxt/b24ui/stacked-layout.ts +9 -0
- package/cli/package.json +1 -1
- package/dist/meta.cjs +10969 -846
- package/dist/meta.d.cts +10969 -846
- package/dist/meta.d.mts +10969 -846
- package/dist/meta.d.ts +10969 -846
- package/dist/meta.mjs +10969 -846
- package/dist/module.cjs +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/components/Collapsible.vue +56 -0
- package/dist/runtime/components/DropdownMenu.vue +2 -0
- package/dist/runtime/components/Navbar.vue +43 -0
- package/dist/runtime/components/NavbarDivider.vue +42 -0
- package/dist/runtime/components/NavbarSection.vue +46 -0
- package/dist/runtime/components/NavbarSpacer.vue +42 -0
- package/dist/runtime/components/NavigationMenu.vue +340 -0
- package/dist/runtime/components/Sidebar.vue +43 -0
- package/dist/runtime/components/SidebarBody.vue +49 -0
- package/dist/runtime/components/SidebarFooter.vue +42 -0
- package/dist/runtime/components/SidebarHeader.vue +42 -0
- package/dist/runtime/components/SidebarHeading.vue +42 -0
- package/dist/runtime/components/SidebarLayout.vue +157 -0
- package/dist/runtime/components/SidebarSection.vue +46 -0
- package/dist/runtime/components/SidebarSpacer.vue +42 -0
- package/dist/runtime/components/StackedLayout.vue +49 -0
- package/dist/runtime/composables/defineLocale.js +1 -0
- package/dist/runtime/composables/defineShortcuts.js +1 -0
- package/dist/runtime/composables/useComponentIcons.d.ts +2 -2
- package/dist/runtime/composables/useKbd.js +1 -1
- package/dist/runtime/composables/useLocale.js +2 -2
- package/dist/runtime/composables/useOverlay.js +1 -1
- package/dist/runtime/index.css +1 -1
- package/dist/runtime/plugins/colors.js +2 -5
- package/dist/runtime/types/index.d.ts +15 -0
- package/dist/runtime/types/index.js +15 -0
- package/dist/runtime/utils/link.d.ts +7 -7
- package/dist/runtime/utils/tv.js +1 -1
- package/dist/runtime/vue/plugins/head.js +3 -0
- package/dist/runtime/vue/stubs.d.ts +1 -2
- package/dist/runtime/vue/stubs.js +1 -2
- package/dist/shared/{b24ui-nuxt.D6rkGFKm.mjs → b24ui-nuxt.CJqO7fYv.mjs} +495 -0
- package/dist/shared/{b24ui-nuxt.CH0xlXgy.cjs → b24ui-nuxt.CltBJi1M.cjs} +495 -0
- package/dist/unplugin.cjs +6 -2
- package/dist/unplugin.mjs +6 -2
- package/dist/vite.cjs +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +5 -5
package/dist/module.cjs
CHANGED
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defu } from 'defu';
|
|
2
2
|
import { defineNuxtModule, createResolver, addVitePlugin, addPlugin, addComponentsDir, addImportsDir, hasNuxtModule, installModule } from '@nuxt/kit';
|
|
3
|
-
import { d as defaultOptions, a as getDefaultUiConfig, b as addTemplates } from './shared/b24ui-nuxt.
|
|
3
|
+
import { d as defaultOptions, a as getDefaultUiConfig, b as addTemplates } from './shared/b24ui-nuxt.CJqO7fYv.mjs';
|
|
4
4
|
import 'node:url';
|
|
5
5
|
import 'scule';
|
|
6
6
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { CollapsibleRootProps, CollapsibleRootEmits } from 'reka-ui'
|
|
3
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
4
|
+
import _appConfig from '#build/app.config'
|
|
5
|
+
import theme from '#build/b24ui/collapsible'
|
|
6
|
+
import { tv } from '../utils/tv'
|
|
7
|
+
|
|
8
|
+
const appConfigCollapsible = _appConfig as AppConfig & { b24ui: { collapsible: Partial<typeof theme> } }
|
|
9
|
+
|
|
10
|
+
const collapsible = tv({ extend: tv(theme), ...(appConfigCollapsible.b24ui?.collapsible || {}) })
|
|
11
|
+
|
|
12
|
+
export interface CollapsibleProps extends Pick<CollapsibleRootProps, 'defaultOpen' | 'open' | 'disabled' | 'unmountOnHide'> {
|
|
13
|
+
/**
|
|
14
|
+
* The element or component this component should render as.
|
|
15
|
+
* @defaultValue 'div'
|
|
16
|
+
*/
|
|
17
|
+
as?: any
|
|
18
|
+
class?: any
|
|
19
|
+
b24ui?: Partial<typeof collapsible.slots>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface CollapsibleEmits extends CollapsibleRootEmits {}
|
|
23
|
+
|
|
24
|
+
export interface CollapsibleSlots {
|
|
25
|
+
default(props: { open: boolean }): any
|
|
26
|
+
content(props?: {}): any
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<script setup lang="ts">
|
|
31
|
+
import { CollapsibleRoot, CollapsibleTrigger, CollapsibleContent, useForwardPropsEmits } from 'reka-ui'
|
|
32
|
+
import { reactivePick } from '@vueuse/core'
|
|
33
|
+
|
|
34
|
+
const props = withDefaults(defineProps<CollapsibleProps>(), {
|
|
35
|
+
unmountOnHide: true
|
|
36
|
+
})
|
|
37
|
+
const emits = defineEmits<CollapsibleEmits>()
|
|
38
|
+
const slots = defineSlots<CollapsibleSlots>()
|
|
39
|
+
|
|
40
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultOpen', 'open', 'disabled', 'unmountOnHide'), emits)
|
|
41
|
+
|
|
42
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
43
|
+
const b24ui = collapsible()
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<template>
|
|
47
|
+
<CollapsibleRoot v-slot="{ open }" v-bind="rootProps" :class="b24ui.root({ class: [props.class, props.b24ui?.root] })">
|
|
48
|
+
<CollapsibleTrigger v-if="!!slots.default" as-child>
|
|
49
|
+
<slot :open="open" />
|
|
50
|
+
</CollapsibleTrigger>
|
|
51
|
+
|
|
52
|
+
<CollapsibleContent :class="b24ui.content({ class: props.b24ui?.content })">
|
|
53
|
+
<slot name="content" />
|
|
54
|
+
</CollapsibleContent>
|
|
55
|
+
</CollapsibleRoot>
|
|
56
|
+
</template>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- eslint-disable vue/block-tag-newline -->
|
|
1
2
|
<script lang="ts">
|
|
2
3
|
import type { VariantProps } from 'tailwind-variants'
|
|
3
4
|
import type { DropdownMenuRootProps, DropdownMenuRootEmits, DropdownMenuContentProps, DropdownMenuArrowProps } from 'reka-ui'
|
|
@@ -99,6 +100,7 @@ export type DropdownMenuSlots<T extends { slot?: string }> = {
|
|
|
99
100
|
'item-label': SlotProps<T>
|
|
100
101
|
'item-trailing': SlotProps<T>
|
|
101
102
|
} & DynamicSlots<T, SlotProps<T>>
|
|
103
|
+
|
|
102
104
|
</script>
|
|
103
105
|
|
|
104
106
|
<script setup lang="ts" generic="T extends DropdownMenuItem">
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
3
|
+
import _appConfig from '#build/app.config'
|
|
4
|
+
import theme from '#build/b24ui/navbar'
|
|
5
|
+
import { tv } from '../utils/tv'
|
|
6
|
+
|
|
7
|
+
const appConfigNavbar = _appConfig as AppConfig & { b24ui: { navbar: Partial<typeof theme> } }
|
|
8
|
+
|
|
9
|
+
const navbar = tv({ extend: tv(theme), ...(appConfigNavbar.b24ui?.navbar || {}) })
|
|
10
|
+
|
|
11
|
+
export interface NavbarProps {
|
|
12
|
+
/**
|
|
13
|
+
* The element or component this component should render as.
|
|
14
|
+
* @defaultValue 'nav'
|
|
15
|
+
*/
|
|
16
|
+
as?: any
|
|
17
|
+
class?: any
|
|
18
|
+
b24ui?: Partial<typeof navbar.slots>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface NavbarSlots {
|
|
22
|
+
default(props?: {}): any
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
import { Primitive } from 'reka-ui'
|
|
28
|
+
|
|
29
|
+
const props = withDefaults(defineProps<NavbarProps>(), {
|
|
30
|
+
as: 'nav'
|
|
31
|
+
})
|
|
32
|
+
defineSlots<NavbarSlots>()
|
|
33
|
+
|
|
34
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
35
|
+
const b24ui = navbar()
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<!-- Navbar -->
|
|
40
|
+
<Primitive :as="as" :class="b24ui.root({ class: [props.class, props.b24ui?.root] })">
|
|
41
|
+
<slot />
|
|
42
|
+
</Primitive>
|
|
43
|
+
</template>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
3
|
+
import _appConfig from '#build/app.config'
|
|
4
|
+
import theme from '#build/b24ui/navbar-divider'
|
|
5
|
+
import { tv } from '../utils/tv'
|
|
6
|
+
|
|
7
|
+
const appConfigNavbarDivider = _appConfig as AppConfig & { b24ui: { navbarDivider: Partial<typeof theme> } }
|
|
8
|
+
|
|
9
|
+
const navbarDivider = tv({ extend: tv(theme), ...(appConfigNavbarDivider.b24ui?.navbarDivider || {}) })
|
|
10
|
+
|
|
11
|
+
export interface NavbarDividerProps {
|
|
12
|
+
/**
|
|
13
|
+
* The element or component this component should render as.
|
|
14
|
+
* @defaultValue 'div'
|
|
15
|
+
*/
|
|
16
|
+
as?: any
|
|
17
|
+
class?: any
|
|
18
|
+
b24ui?: Partial<typeof navbarDivider.slots>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface NavbarDividerSlots {
|
|
22
|
+
default(props?: {}): any
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
import { Primitive } from 'reka-ui'
|
|
28
|
+
|
|
29
|
+
const props = withDefaults(defineProps<NavbarDividerProps>(), {
|
|
30
|
+
as: 'div'
|
|
31
|
+
})
|
|
32
|
+
defineSlots<NavbarDividerSlots>()
|
|
33
|
+
|
|
34
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
35
|
+
const b24ui = navbarDivider()
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<Primitive :as="as" aria-hidden="true" :class="b24ui.root({ class: [props.class, props.b24ui?.root] })">
|
|
40
|
+
<slot />
|
|
41
|
+
</Primitive>
|
|
42
|
+
</template>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
3
|
+
import _appConfig from '#build/app.config'
|
|
4
|
+
import theme from '#build/b24ui/navbar-section'
|
|
5
|
+
import { tv } from '../utils/tv'
|
|
6
|
+
|
|
7
|
+
const appConfigNavSection = _appConfig as AppConfig & { b24ui: { navbarSection: Partial<typeof theme> } }
|
|
8
|
+
|
|
9
|
+
const navbarSection = tv({ extend: tv(theme), ...(appConfigNavSection.b24ui?.navbarSection || {}) })
|
|
10
|
+
|
|
11
|
+
export interface NavbarSectionProps {
|
|
12
|
+
/**
|
|
13
|
+
* The element or component this component should render as.
|
|
14
|
+
* @defaultValue 'div'
|
|
15
|
+
*/
|
|
16
|
+
as?: any
|
|
17
|
+
class?: any
|
|
18
|
+
b24ui?: Partial<typeof navbarSection.slots>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface NavbarSectionSlots {
|
|
22
|
+
default(props?: {}): any
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
import { Primitive } from 'reka-ui'
|
|
28
|
+
|
|
29
|
+
const props = withDefaults(defineProps<NavbarSectionProps>(), {
|
|
30
|
+
as: 'div'
|
|
31
|
+
})
|
|
32
|
+
defineSlots<NavbarSectionSlots>()
|
|
33
|
+
|
|
34
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
35
|
+
const b24ui = navbarSection()
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<Primitive
|
|
40
|
+
:as="as"
|
|
41
|
+
:class="b24ui.root({ class: [props.class, props.b24ui?.root] })"
|
|
42
|
+
data-slot="section"
|
|
43
|
+
>
|
|
44
|
+
<slot />
|
|
45
|
+
</Primitive>
|
|
46
|
+
</template>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
3
|
+
import _appConfig from '#build/app.config'
|
|
4
|
+
import theme from '#build/b24ui/navbar-spacer'
|
|
5
|
+
import { tv } from '../utils/tv'
|
|
6
|
+
|
|
7
|
+
const appConfigNavbarSpacer = _appConfig as AppConfig & { b24ui: { navbarSpacer: Partial<typeof theme> } }
|
|
8
|
+
|
|
9
|
+
const navbarSpacer = tv({ extend: tv(theme), ...(appConfigNavbarSpacer.b24ui?.navbarSpacer || {}) })
|
|
10
|
+
|
|
11
|
+
export interface NavbarSpacerProps {
|
|
12
|
+
/**
|
|
13
|
+
* The element or component this component should render as.
|
|
14
|
+
* @defaultValue 'div'
|
|
15
|
+
*/
|
|
16
|
+
as?: any
|
|
17
|
+
class?: any
|
|
18
|
+
b24ui?: Partial<typeof navbarSpacer.slots>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface NavbarSpacerSlots {
|
|
22
|
+
default(props?: {}): any
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
import { Primitive } from 'reka-ui'
|
|
28
|
+
|
|
29
|
+
const props = withDefaults(defineProps<NavbarSpacerProps>(), {
|
|
30
|
+
as: 'div'
|
|
31
|
+
})
|
|
32
|
+
defineSlots<NavbarSpacerSlots>()
|
|
33
|
+
|
|
34
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
35
|
+
const b24ui = navbarSpacer()
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<Primitive :as="as" aria-hidden="true" :class="b24ui.root({ class: [props.class, props.b24ui?.root] })">
|
|
40
|
+
<slot />
|
|
41
|
+
</Primitive>
|
|
42
|
+
</template>
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
<!-- eslint-disable vue/block-tag-newline -->
|
|
2
|
+
<script lang="ts">
|
|
3
|
+
import type { VariantProps } from 'tailwind-variants'
|
|
4
|
+
import type { NavigationMenuRootProps, NavigationMenuRootEmits, NavigationMenuContentProps, CollapsibleRootProps } from 'reka-ui'
|
|
5
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
6
|
+
import _appConfig from '#build/app.config'
|
|
7
|
+
import theme from '#build/b24ui/navigation-menu'
|
|
8
|
+
import { tv } from '../utils/tv'
|
|
9
|
+
import type { AvatarProps, BadgeProps, LinkProps, IconComponent } from '../types'
|
|
10
|
+
import type { DynamicSlots, MaybeArrayOfArray, MaybeArrayOfArrayItem, PartialString } from '../types/utils'
|
|
11
|
+
|
|
12
|
+
const appConfigNavigationMenu = _appConfig as AppConfig & { b24ui: { navigationMenu: Partial<typeof theme> } }
|
|
13
|
+
|
|
14
|
+
const navigationMenu = tv({ extend: tv(theme), ...(appConfigNavigationMenu.b24ui?.navigationMenu || {}) })
|
|
15
|
+
|
|
16
|
+
export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, 'children' | 'type'> {
|
|
17
|
+
/** Description is only used when `orientation` is `horizontal`. */
|
|
18
|
+
description?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'>, Pick<CollapsibleRootProps, 'defaultOpen' | 'open'> {
|
|
22
|
+
label?: string
|
|
23
|
+
/**
|
|
24
|
+
* @IconComponent
|
|
25
|
+
*/
|
|
26
|
+
icon?: IconComponent
|
|
27
|
+
avatar?: AvatarProps
|
|
28
|
+
/**
|
|
29
|
+
* Display a badge on the item.
|
|
30
|
+
* `{ size: 'sm', color: 'neutral', variant: 'outline' }`{lang="ts-type"}
|
|
31
|
+
*/
|
|
32
|
+
badge?: string | number | BadgeProps
|
|
33
|
+
/**
|
|
34
|
+
* @IconComponent
|
|
35
|
+
*/
|
|
36
|
+
trailingIcon?: IconComponent
|
|
37
|
+
/**
|
|
38
|
+
* The type of the item.
|
|
39
|
+
* The `label` type only works on `vertical` orientation.
|
|
40
|
+
* @defaultValue 'link'
|
|
41
|
+
*/
|
|
42
|
+
type?: 'label' | 'link'
|
|
43
|
+
slot?: string
|
|
44
|
+
value?: string
|
|
45
|
+
children?: NavigationMenuChildItem[]
|
|
46
|
+
onSelect?(e: Event): void
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type NavigationMenuVariants = VariantProps<typeof navigationMenu>
|
|
50
|
+
|
|
51
|
+
export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'modelValue' | 'defaultValue' | 'delayDuration' | 'disableClickTrigger' | 'disableHoverTrigger' | 'skipDelayDuration' | 'disablePointerLeaveClose' | 'unmountOnHide'> {
|
|
52
|
+
/**
|
|
53
|
+
* The element or component this component should render as.
|
|
54
|
+
* @defaultValue 'div'
|
|
55
|
+
*/
|
|
56
|
+
as?: any
|
|
57
|
+
/**
|
|
58
|
+
* The icon displayed to open the menu.
|
|
59
|
+
* @defaultValue icons.chevronDown
|
|
60
|
+
* @IconComponent
|
|
61
|
+
*/
|
|
62
|
+
trailingIcon?: IconComponent
|
|
63
|
+
/**
|
|
64
|
+
* The icon displayed when the item is an external link.
|
|
65
|
+
* Set to `false` to hide the external icon.
|
|
66
|
+
* @defaultValue icons.external
|
|
67
|
+
* @IconComponent
|
|
68
|
+
*/
|
|
69
|
+
externalIcon?: boolean | IconComponent
|
|
70
|
+
items?: T
|
|
71
|
+
/**
|
|
72
|
+
* @defaultValue 'primary'
|
|
73
|
+
*/
|
|
74
|
+
color?: NavigationMenuVariants['color']
|
|
75
|
+
/**
|
|
76
|
+
* @defaultValue 'pill'
|
|
77
|
+
*/
|
|
78
|
+
variant?: NavigationMenuVariants['variant']
|
|
79
|
+
/**
|
|
80
|
+
* The orientation of the menu.
|
|
81
|
+
* @defaultValue 'horizontal'
|
|
82
|
+
*/
|
|
83
|
+
orientation?: NavigationMenuRootProps['orientation']
|
|
84
|
+
/**
|
|
85
|
+
* Collapse the navigation menu to only show icons.
|
|
86
|
+
* Only works when `orientation` is `vertical`.
|
|
87
|
+
* @defaultValue false
|
|
88
|
+
*/
|
|
89
|
+
collapsed?: boolean
|
|
90
|
+
/** Display a line next to the active item. */
|
|
91
|
+
highlight?: boolean
|
|
92
|
+
/**
|
|
93
|
+
* @defaultValue 'primary'
|
|
94
|
+
*/
|
|
95
|
+
highlightColor?: NavigationMenuVariants['highlightColor']
|
|
96
|
+
/** The content of the menu. */
|
|
97
|
+
content?: Omit<NavigationMenuContentProps, 'as' | 'asChild' | 'forceMount'>
|
|
98
|
+
/**
|
|
99
|
+
* The orientation of the content.
|
|
100
|
+
* Only works when `orientation` is `horizontal`.
|
|
101
|
+
* @defaultValue 'horizontal'
|
|
102
|
+
*/
|
|
103
|
+
contentOrientation?: NavigationMenuVariants['contentOrientation']
|
|
104
|
+
/**
|
|
105
|
+
* Display an arrow alongside the menu.
|
|
106
|
+
* @defaultValue false
|
|
107
|
+
*/
|
|
108
|
+
arrow?: boolean
|
|
109
|
+
/**
|
|
110
|
+
* The key used to get the label from the item.
|
|
111
|
+
* @defaultValue 'label'
|
|
112
|
+
*/
|
|
113
|
+
labelKey?: string
|
|
114
|
+
class?: any
|
|
115
|
+
b24ui?: PartialString<typeof navigationMenu.slots>
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface NavigationMenuEmits extends NavigationMenuRootEmits {}
|
|
119
|
+
|
|
120
|
+
type SlotProps<T> = (props: { item: T, index: number, active?: boolean }) => any
|
|
121
|
+
|
|
122
|
+
export type NavigationMenuSlots<T extends { slot?: string }> = {
|
|
123
|
+
'item': SlotProps<T>
|
|
124
|
+
'item-leading': SlotProps<T>
|
|
125
|
+
'item-label': SlotProps<T>
|
|
126
|
+
'item-trailing': SlotProps<T>
|
|
127
|
+
'item-content': SlotProps<T>
|
|
128
|
+
} & DynamicSlots<T, SlotProps<T>>
|
|
129
|
+
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<NavigationMenuItem>">
|
|
133
|
+
import { computed, toRef } from 'vue'
|
|
134
|
+
import { NavigationMenuRoot, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport, useForwardPropsEmits } from 'reka-ui'
|
|
135
|
+
import { createReusableTemplate } from '@vueuse/core'
|
|
136
|
+
import { get } from '../utils'
|
|
137
|
+
import { pickLinkProps } from '../utils/link'
|
|
138
|
+
import icons from '../dictionary/icons'
|
|
139
|
+
import B24LinkBase from './LinkBase.vue'
|
|
140
|
+
import B24Link from './Link.vue'
|
|
141
|
+
import B24Avatar from './Avatar.vue'
|
|
142
|
+
import B24Badge from './Badge.vue'
|
|
143
|
+
import B24Collapsible from './Collapsible.vue'
|
|
144
|
+
|
|
145
|
+
const props = withDefaults(defineProps<NavigationMenuProps<I>>(), {
|
|
146
|
+
orientation: 'horizontal',
|
|
147
|
+
contentOrientation: 'horizontal',
|
|
148
|
+
externalIcon: true,
|
|
149
|
+
delayDuration: 0,
|
|
150
|
+
unmountOnHide: true,
|
|
151
|
+
labelKey: 'label'
|
|
152
|
+
})
|
|
153
|
+
const emits = defineEmits<NavigationMenuEmits>()
|
|
154
|
+
const slots = defineSlots<NavigationMenuSlots<T>>()
|
|
155
|
+
|
|
156
|
+
const rootProps = useForwardPropsEmits(computed(() => ({
|
|
157
|
+
as: props.as,
|
|
158
|
+
modelValue: props.modelValue,
|
|
159
|
+
defaultValue: props.defaultValue,
|
|
160
|
+
delayDuration: props.delayDuration,
|
|
161
|
+
skipDelayDuration: props.skipDelayDuration,
|
|
162
|
+
orientation: props.orientation,
|
|
163
|
+
disableClickTrigger: props.disableClickTrigger,
|
|
164
|
+
disableHoverTrigger: props.disableHoverTrigger,
|
|
165
|
+
disablePointerLeaveClose: props.disablePointerLeaveClose,
|
|
166
|
+
unmountOnHide: props.unmountOnHide
|
|
167
|
+
})), emits)
|
|
168
|
+
|
|
169
|
+
const contentProps = toRef(() => props.content)
|
|
170
|
+
|
|
171
|
+
const [DefineLinkTemplate, ReuseLinkTemplate] = createReusableTemplate<{ item: NavigationMenuItem, index: number, active?: boolean }>()
|
|
172
|
+
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: NavigationMenuItem, index: number, level?: number }>({
|
|
173
|
+
props: {
|
|
174
|
+
item: Object,
|
|
175
|
+
index: Number,
|
|
176
|
+
level: Number
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
const b24ui = computed(() => navigationMenu({
|
|
181
|
+
orientation: props.orientation,
|
|
182
|
+
contentOrientation: props.contentOrientation,
|
|
183
|
+
collapsed: props.collapsed,
|
|
184
|
+
color: props.color,
|
|
185
|
+
variant: props.variant,
|
|
186
|
+
highlight: props.highlight,
|
|
187
|
+
highlightColor: props.highlightColor || props.color
|
|
188
|
+
}))
|
|
189
|
+
|
|
190
|
+
const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]) ? props.items : [props.items]) as T[][] : [])
|
|
191
|
+
</script>
|
|
192
|
+
|
|
193
|
+
<template>
|
|
194
|
+
<DefineLinkTemplate v-slot="{ item, active, index }">
|
|
195
|
+
<slot :name="item.slot || 'item'" :item="(item as T)" :index="index">
|
|
196
|
+
<slot :name="item.slot ? `${item.slot}-leading` : 'item-leading'" :item="(item as T)" :active="active" :index="index">
|
|
197
|
+
<Component
|
|
198
|
+
:is="item.icon"
|
|
199
|
+
v-if="item.icon"
|
|
200
|
+
:class="b24ui.linkLeadingIcon({ class: props.b24ui?.linkLeadingIcon, active, disabled: !!item.disabled })"
|
|
201
|
+
/>
|
|
202
|
+
<B24Avatar v-else-if="item.avatar" :size="((props.b24ui?.linkLeadingAvatarSize || b24ui.linkLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="b24ui.linkLeadingAvatar({ class: props.b24ui?.linkLeadingAvatar, active, disabled: !!item.disabled })" />
|
|
203
|
+
</slot>
|
|
204
|
+
|
|
205
|
+
<span
|
|
206
|
+
v-if="(!collapsed || orientation !== 'vertical') && (get(item, props.labelKey as string) || !!slots[item.slot ? `${item.slot}-label` : 'item-label'])"
|
|
207
|
+
:class="b24ui.linkLabel({ class: props.b24ui?.linkLabel })"
|
|
208
|
+
>
|
|
209
|
+
<slot :name="item.slot ? `${item.slot}-label` : 'item-label'" :item="(item as T)" :active="active" :index="index">
|
|
210
|
+
{{ get(item, props.labelKey as string) }}
|
|
211
|
+
</slot>
|
|
212
|
+
|
|
213
|
+
<Component
|
|
214
|
+
:is="typeof externalIcon !== 'boolean' ? externalIcon : icons.external"
|
|
215
|
+
v-if="item.target === '_blank' && externalIcon !== false"
|
|
216
|
+
:class="b24ui.linkLabelExternalIcon({ class: props.b24ui?.linkLabelExternalIcon, active })"
|
|
217
|
+
/>
|
|
218
|
+
</span>
|
|
219
|
+
|
|
220
|
+
<span v-if="(!collapsed || orientation !== 'vertical') && (item.badge || (orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) || (orientation === 'vertical' && item.children?.length) || item.trailingIcon || !!slots[item.slot ? `${item.slot}-trailing` : 'item-trailing'])" :class="b24ui.linkTrailing({ class: props.b24ui?.linkTrailing })">
|
|
221
|
+
<slot :name="item.slot ? `${item.slot}-trailing` : 'item-trailing'" :item="(item as T)" :active="active" :index="index">
|
|
222
|
+
<B24Badge
|
|
223
|
+
v-if="item.badge"
|
|
224
|
+
color="default"
|
|
225
|
+
depth="normal"
|
|
226
|
+
:use-fill="false"
|
|
227
|
+
:size="((props.b24ui?.linkTrailingBadgeSize || b24ui.linkTrailingBadgeSize()) as BadgeProps['size'])"
|
|
228
|
+
v-bind="(typeof item.badge === 'string' || typeof item.badge === 'number') ? { label: item.badge } : item.badge"
|
|
229
|
+
:class="b24ui.linkTrailingBadge({ class: props.b24ui?.linkTrailingBadge })"
|
|
230
|
+
/>
|
|
231
|
+
|
|
232
|
+
<Component
|
|
233
|
+
:is="item.trailingIcon || trailingIcon || icons.chevronDown"
|
|
234
|
+
v-if="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) || (orientation === 'vertical' && item.children?.length)"
|
|
235
|
+
:class="b24ui.linkTrailingIcon({ class: props.b24ui?.linkTrailingIcon, active })"
|
|
236
|
+
/>
|
|
237
|
+
<Component
|
|
238
|
+
:is="item.trailingIcon"
|
|
239
|
+
v-else-if="item.trailingIcon"
|
|
240
|
+
:class="b24ui.linkTrailingIcon({ class: props.b24ui?.linkTrailingIcon, active })"
|
|
241
|
+
/>
|
|
242
|
+
</slot>
|
|
243
|
+
</span>
|
|
244
|
+
</slot>
|
|
245
|
+
</DefineLinkTemplate>
|
|
246
|
+
|
|
247
|
+
<DefineItemTemplate v-slot="{ item, index, level = 0 }">
|
|
248
|
+
<component
|
|
249
|
+
:is="(orientation === 'vertical' && item.children?.length && !collapsed) ? B24Collapsible : NavigationMenuItem"
|
|
250
|
+
as="li"
|
|
251
|
+
:value="item.value || String(index)"
|
|
252
|
+
:default-open="item.defaultOpen"
|
|
253
|
+
:unmount-on-hide="(orientation === 'vertical' && item.children?.length && !collapsed) ? unmountOnHide : undefined"
|
|
254
|
+
:open="item.open"
|
|
255
|
+
>
|
|
256
|
+
<div v-if="orientation === 'vertical' && item.type === 'label'" :class="b24ui.label({ class: props.b24ui?.label })">
|
|
257
|
+
<ReuseLinkTemplate :item="(item as T)" :index="index" />
|
|
258
|
+
</div>
|
|
259
|
+
<B24Link v-else-if="item.type !== 'label'" v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length && !collapsed) ? {} : pickLinkProps(item as Omit<NavigationMenuItem, 'type'>)" custom>
|
|
260
|
+
<component
|
|
261
|
+
:is="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) ? NavigationMenuTrigger : NavigationMenuLink"
|
|
262
|
+
as-child
|
|
263
|
+
:active="active || item.active"
|
|
264
|
+
:disabled="item.disabled"
|
|
265
|
+
@select="item.onSelect"
|
|
266
|
+
>
|
|
267
|
+
<B24LinkBase v-bind="slotProps" :class="b24ui.link({ class: [props.b24ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
|
|
268
|
+
<ReuseLinkTemplate :item="(item as T)" :active="active || item.active" :index="index" />
|
|
269
|
+
</B24LinkBase>
|
|
270
|
+
</component>
|
|
271
|
+
|
|
272
|
+
<NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])" v-bind="contentProps" :class="b24ui.content({ class: props.b24ui?.content })">
|
|
273
|
+
<slot :name="item.slot ? `${item.slot}-content` : 'item-content'" :item="(item as T)" :active="active" :index="index">
|
|
274
|
+
<ul :class="b24ui.childList({ class: props.b24ui?.childList })">
|
|
275
|
+
<li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="b24ui.childItem({ class: props.b24ui?.childItem })">
|
|
276
|
+
<B24Link v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
|
|
277
|
+
<NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
|
|
278
|
+
<B24LinkBase v-bind="childSlotProps" :class="b24ui.childLink({ class: [props.b24ui?.childLink, childItem.class], active: childActive })">
|
|
279
|
+
<Component
|
|
280
|
+
:is="childItem.icon"
|
|
281
|
+
v-if="childItem.icon"
|
|
282
|
+
:class="b24ui.childLinkIcon({ class: props.b24ui?.childLinkIcon, active: childActive })"
|
|
283
|
+
/>
|
|
284
|
+
|
|
285
|
+
<div :class="b24ui.childLinkWrapper({ class: props.b24ui?.childLinkWrapper })">
|
|
286
|
+
<p :class="b24ui.childLinkLabel({ class: props.b24ui?.childLinkLabel, active: childActive })">
|
|
287
|
+
{{ get(childItem, props.labelKey as string) }}
|
|
288
|
+
|
|
289
|
+
<Component
|
|
290
|
+
:is="typeof externalIcon === 'string' ? externalIcon : icons.external"
|
|
291
|
+
v-if="childItem.target === '_blank' && externalIcon !== false"
|
|
292
|
+
:class="b24ui.childLinkLabelExternalIcon({ class: props.b24ui?.childLinkLabelExternalIcon, active: childActive })"
|
|
293
|
+
/>
|
|
294
|
+
</p>
|
|
295
|
+
<p v-if="childItem.description" :class="b24ui.childLinkDescription({ class: props.b24ui?.childLinkDescription, active: childActive })">
|
|
296
|
+
{{ childItem.description }}
|
|
297
|
+
</p>
|
|
298
|
+
</div>
|
|
299
|
+
</B24LinkBase>
|
|
300
|
+
</NavigationMenuLink>
|
|
301
|
+
</B24Link>
|
|
302
|
+
</li>
|
|
303
|
+
</ul>
|
|
304
|
+
</slot>
|
|
305
|
+
</NavigationMenuContent>
|
|
306
|
+
</B24Link>
|
|
307
|
+
|
|
308
|
+
<template v-if="orientation === 'vertical' && item.children?.length && !collapsed" #content>
|
|
309
|
+
<ul :class="b24ui.childList({ class: props.b24ui?.childList })">
|
|
310
|
+
<ReuseItemTemplate
|
|
311
|
+
v-for="(childItem, childIndex) in item.children"
|
|
312
|
+
:key="childIndex"
|
|
313
|
+
:item="childItem"
|
|
314
|
+
:index="childIndex"
|
|
315
|
+
:level="level + 1"
|
|
316
|
+
:class="b24ui.childItem({ class: props.b24ui?.childItem })"
|
|
317
|
+
/>
|
|
318
|
+
</ul>
|
|
319
|
+
</template>
|
|
320
|
+
</component>
|
|
321
|
+
</DefineItemTemplate>
|
|
322
|
+
|
|
323
|
+
<NavigationMenuRoot v-bind="rootProps" :data-collapsed="collapsed" :class="b24ui.root({ class: [props.class, props.b24ui?.root] })">
|
|
324
|
+
<template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
|
|
325
|
+
<NavigationMenuList :class="b24ui.list({ class: props.b24ui?.list })">
|
|
326
|
+
<ReuseItemTemplate v-for="(item, index) in list" :key="`list-${listIndex}-${index}`" :item="item" :index="index" :class="b24ui.item({ class: props.b24ui?.item })" />
|
|
327
|
+
</NavigationMenuList>
|
|
328
|
+
|
|
329
|
+
<div v-if="orientation === 'vertical' && listIndex < lists.length - 1" :class="b24ui.separator({ class: props.b24ui?.separator })" />
|
|
330
|
+
</template>
|
|
331
|
+
|
|
332
|
+
<div v-if="orientation === 'horizontal'" :class="b24ui.viewportWrapper({ class: props.b24ui?.viewportWrapper })">
|
|
333
|
+
<NavigationMenuIndicator v-if="arrow" :class="b24ui.indicator({ class: props.b24ui?.indicator })">
|
|
334
|
+
<div :class="b24ui.arrow({ class: props.b24ui?.arrow })" />
|
|
335
|
+
</NavigationMenuIndicator>
|
|
336
|
+
|
|
337
|
+
<NavigationMenuViewport :class="b24ui.viewport({ class: props.b24ui?.viewport })" />
|
|
338
|
+
</div>
|
|
339
|
+
</NavigationMenuRoot>
|
|
340
|
+
</template>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
3
|
+
import _appConfig from '#build/app.config'
|
|
4
|
+
import theme from '#build/b24ui/sidebar'
|
|
5
|
+
import { tv } from '../utils/tv'
|
|
6
|
+
|
|
7
|
+
const appConfigSidebar = _appConfig as AppConfig & { b24ui: { sidebar: Partial<typeof theme> } }
|
|
8
|
+
|
|
9
|
+
const sidebar = tv({ extend: tv(theme), ...(appConfigSidebar.b24ui?.sidebar || {}) })
|
|
10
|
+
|
|
11
|
+
export interface SidebarProps {
|
|
12
|
+
/**
|
|
13
|
+
* The element or component this component should render as.
|
|
14
|
+
* @defaultValue 'div'
|
|
15
|
+
*/
|
|
16
|
+
as?: any
|
|
17
|
+
class?: any
|
|
18
|
+
b24ui?: Partial<typeof sidebar.slots>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SidebarSlots {
|
|
22
|
+
default(props?: {}): any
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
import { Primitive } from 'reka-ui'
|
|
28
|
+
|
|
29
|
+
const props = withDefaults(defineProps<SidebarProps>(), {
|
|
30
|
+
as: 'div'
|
|
31
|
+
})
|
|
32
|
+
defineSlots<SidebarSlots>()
|
|
33
|
+
|
|
34
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
35
|
+
const b24ui = sidebar()
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<!-- Sidebar -->
|
|
40
|
+
<Primitive :as="as" :class="b24ui.root({ class: [props.class, props.b24ui?.root] })">
|
|
41
|
+
<slot />
|
|
42
|
+
</Primitive>
|
|
43
|
+
</template>
|