@wordup-md/nuxt-layer-shadcn-unocss 0.2.2 → 0.2.4

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 (34) hide show
  1. package/.playground/app.config.ts +3 -3
  2. package/.playground/content/1.getting-started/1.introduction.md +7 -1
  3. package/.playground/content/2.content-elements/11.tables.md +17 -1
  4. package/.playground/content/3.components/2.docs/badge.md +18 -39
  5. package/.playground/content/3.components/2.docs/button-link.md +12 -12
  6. package/.playground/content/3.components/3.page/accordion.md +1 -1
  7. package/.playground/content/3.components/3.page/file-download.md +6 -0
  8. package/.playground/content/3.components/3.page/hero.md +1 -1
  9. package/.playground/content/3.components/3.page/list.md +42 -0
  10. package/.playground/content/index.md +1 -0
  11. package/.playground/content/layout.md +1 -1
  12. package/.playground/content/test.md +24 -1
  13. package/README.md +2 -2
  14. package/components/content/Badge.vue +7 -0
  15. package/components/content/ButtonLink.vue +11 -8
  16. package/components/content/ButtonLogin.vue +19 -0
  17. package/components/content/FileDownload.vue +103 -0
  18. package/components/content/List.vue +26 -7
  19. package/components/content/Menu.vue +43 -0
  20. package/components/content/MenuItem.vue +22 -0
  21. package/components/content/global/CardGroupEditor.vue +1 -1
  22. package/components/content/global/ListEditor.vue +11 -0
  23. package/components/layout/Block404.vue +24 -0
  24. package/components/layout/Footer.vue +2 -11
  25. package/i18n/i18n.config.ts +180 -2
  26. package/index.d.ts +1 -1
  27. package/middleware/admin.global.ts +12 -0
  28. package/package.json +1 -1
  29. package/pages/[...slug].vue +47 -12
  30. package/pages/admin/[...slug].vue +17 -38
  31. package/pages/admin/login.vue +51 -0
  32. package/public/content-doc.json +56 -14
  33. package/scripts/buildContentDoc.ts +5 -3
  34. package/.playground/content/_menu-footer.md +0 -12
@@ -78,7 +78,7 @@ export default defineAppConfig({
78
78
  }],
79
79
  links: [{
80
80
  icon: 'lucide:twitter',
81
- to: 'https://x.com/unpress_dev',
81
+ to: 'https://x.com/wordup_md',
82
82
  target: '_blank',
83
83
  }],
84
84
  },
@@ -97,7 +97,7 @@ export default defineAppConfig({
97
97
  codeCopyToast: true,
98
98
  editLink: {
99
99
  enable: true,
100
- pattern: 'https://github.com/wordup-md/nuxt-layer-shadcn-unocss/edit/main/content/:path',
100
+ pattern: 'https://github.com/wordup-md/nuxt-layer-shadcn-unocss/edit/main/.playground/content/:path',
101
101
  text: 'Edit this page',
102
102
  icon: 'lucide:square-pen',
103
103
  placement: ['pageFooter', 'toc'],
@@ -147,7 +147,7 @@ export default defineAppConfig({
147
147
  },
148
148
  },
149
149
  footer: {
150
- credits: 'Made with ❤️ by [**Emmanuel Salomon**](https://github.com/ManUtopiK/) with [Unpress](https://unpress.dev)',
150
+ credits: 'Made with ❤️ by [**Emmanuel Salomon**](https://github.com/ManUtopiK/) with [WordUp](https://wordup.md)',
151
151
  links: [
152
152
  {
153
153
  title: 'shadcn-vue',
@@ -5,4 +5,10 @@ icon: lucide:info
5
5
  toc: false
6
6
  ---
7
7
 
8
- :card-group{data="/getting-started/writing"}
8
+ ::list
9
+ ---
10
+ class: group grid gap-4 md:grid-cols-2 [&:not(:first-child)]:mt-4
11
+ component: card
12
+ path: /getting-started/writing
13
+ ---
14
+ ::
@@ -22,4 +22,20 @@ icon: lucide:table
22
22
  | 2 | Wonderful | Data |
23
23
  | 3 | Wonderful | Website |
24
24
  ```
25
- ::
25
+ ::
26
+
27
+ ## Alignment
28
+
29
+ ::stack
30
+ :::div{.p-4}
31
+ | Default (left) | Left | Center | Right |
32
+ | -------------- | :---------------- | :-----------------: | -----------------: |
33
+ | default text | left aligned text | center aligned text | right aligned text |
34
+ :::
35
+
36
+ ```md
37
+ | Default (left) | Left | Center | Right |
38
+ | -------------- | :---------------- | :-----------------: | -----------------: |
39
+ | default text | left aligned text | center aligned text | right aligned text |
40
+ ```
41
+ ::
@@ -40,7 +40,7 @@ badges:
40
40
 
41
41
  ### Types
42
42
 
43
- ::stack{label="default"}
43
+ ::stack
44
44
  ::div{class="p-3"}
45
45
  :badge[Default]
46
46
  :badge[Primary]{type="primary"}
@@ -64,46 +64,24 @@ badges:
64
64
 
65
65
  ### Variants
66
66
 
67
- ::stack{label="default"}
68
- ::div{class="p-3"}
69
- :badge[Default]{variant="fill"}
70
- :badge[Primary]{type="primary" variant="fill"}
71
- :badge[Secondary]{type="secondary" variant="fill"}
72
- :badge[Info]{type="info" variant="fill"}
73
- :badge[Warning]{type="warning" variant="fill"}
74
- :badge[Success]{type="success" variant="fill"}
75
- :badge[Danger]{type="danger" variant="fill"}
76
- :badge[New]{type="new" variant="fill"}
77
- ::
67
+ |Default|Fill|Outline|Text|
68
+ |---|---|---|---|
69
+ |:badge[Default]|:badge[Default]{variant="fill"}|:badge[Default]{variant="outline"}|:badge[Default]{variant="text"}|
70
+ |:badge[Primary]{type="primary"}|:badge[Primary]{type="primary" variant="fill"}|:badge[Primary]{type="primary" variant="outline"}|:badge[Primary]{type="primary" variant="text"}|
71
+ |:badge[Secondary]{type="secondary"}|:badge[Secondary]{type="secondary" variant="fill"}|:badge[Secondary]{type="secondary" variant="outline"}|:badge[Secondary]{type="secondary" variant="text"}|
72
+ |:badge[Info]{type="info"}|:badge[Info]{type="info" variant="fill"}|:badge[Info]{type="info" variant="outline"}|:badge[Info]{type="info" variant="text"}|
73
+ |:badge[Warning]{type="warning"}|:badge[Warning]{type="warning" variant="fill"}|:badge[Warning]{type="warning" variant="outline"}|:badge[Warning]{type="warning" variant="text"}|
74
+ |:badge[Success]{type="success"}|:badge[Success]{type="success" variant="fill"}|:badge[Success]{type="success" variant="outline"}|:badge[Success]{type="success" variant="text"}|
75
+ |:badge[Danger]{type="danger"}|:badge[Danger]{type="danger" variant="fill"}|:badge[Danger]{type="danger" variant="outline"}|:badge[Danger]{type="danger" variant="text"}|
76
+ |:badge[New]{type="new"}|:badge[New]{type="new" variant="fill"}|:badge[New]{type="new" variant="outline"}|:badge[New]{type="new" variant="text"}|
78
77
 
79
- ::div{class="p-3"}
80
- :badge[Default]{variant="outline"}
81
- :badge[Primary]{type="primary" variant="outline"}
82
- :badge[Secondary]{type="secondary" variant="outline"}
83
- :badge[Info]{type="info" variant="outline"}
84
- :badge[Warning]{type="warning" variant="outline"}
85
- :badge[Success]{type="success" variant="outline"}
86
- :badge[Danger]{type="danger" variant="outline"}
87
- :badge[New]{type="new" variant="outline"}
88
- ::
78
+ **Examples:**
89
79
 
90
- ::div{class="p-3"}
91
- :badge[Default]{variant="text"}
92
- :badge[Primary]{type="primary" variant="text"}
93
- :badge[Secondary]{type="secondary" variant="text"}
94
- :badge[Info]{type="info" variant="text"}
95
- :badge[Warning]{type="warning" variant="text"}
96
- :badge[Success]{type="success" variant="text"}
97
- :badge[Danger]{type="danger" variant="text"}
98
- :badge[New]{type="new" variant="text"}
99
- ::
100
-
101
- ```mdc
102
- :badge[...]{type="..." variant="fill"}
103
- :badge[...]{type="..." variant="outline"}
104
- :badge[...]{type="..." variant="text"}
105
- ```
106
- ::
80
+ ```mdc
81
+ :badge[Some text]{type="info" variant="fill"}
82
+ :badge[Some text]{type="danger" variant="outline"}
83
+ :badge[Some text]{type="new" variant="text"}
84
+ ```
107
85
 
108
86
  ### Link
109
87
 
@@ -123,6 +101,7 @@ badges:
123
101
  ## Props
124
102
 
125
103
  ::field-group
104
+ :field{name="title" type="string"}[Can be used to set the label of the badge instead of the content]
126
105
  :field{name="type" type="'default' | 'info' | 'warning' | 'success' | 'danger' | 'lime'" default-value="'default'"}
127
106
  :field{name="variant" type="'default' | 'secondary' | 'destructive' | 'outline'" default-value="'default'"}
128
107
  :field{name="size" type="'md' | 'sm'" default-value="'md'"}
@@ -16,26 +16,26 @@ badges:
16
16
 
17
17
  ::stack
18
18
  ::div{class="p-3 flex gap-4"}
19
- ::button-link{right-icon="lucide:arrow-up-right" to="/getting-started" target="_blank"}
20
- Get Started
21
- ::
22
- ::button-link{left-icon="lucide:github" variant="outline" to="https://github.com/wordup-md/nuxt-layer-shadcn-unocss" target="_blank"}
19
+ ::button-link{icon="lucide:github" variant="outline" to="https://github.com/wordup-md/nuxt-layer-shadcn-unocss" target="_blank"}
23
20
  GitHub
24
21
  ::
25
- ::button-link{left-icon="lucide:ghost" variant="ghost" href="https://github.com/wordup-md/nuxt-layer-shadcn-unocss" blank}
22
+ ::button-link{icon="lucide:ghost" variant="ghost" href="https://github.com/wordup-md/nuxt-layer-shadcn-unocss" blank}
26
23
  Ghost
27
24
  ::
28
- ::
29
- ```mdc
30
- ::button-link{right-icon="lucide:arrow-up-right" to="/getting-started" target="_blank"}
25
+ ::button-link{trailing-icon="lucide:arrow-up-right" to="/getting-started" target="_blank"}
31
26
  Get Started
32
27
  ::
33
- ::button-link{left-icon="lucide:github" variant="outline" to="https://github.com/wordup-md/nuxt-layer-shadcn-unocss" target="_blank"}
28
+ ::
29
+ ```mdc
30
+ ::button-link{icon="lucide:github" variant="outline" to="https://github.com/wordup-md/nuxt-layer-shadcn-unocss" target="_blank"}
34
31
  GitHub
35
32
  ::
36
- ::button-link{left-icon="lucide:ghost" variant="ghost" href="https://github.com/wordup-md/nuxt-layer-shadcn-unocss" blank}
33
+ ::button-link{icon="lucide:ghost" variant="ghost" href="https://github.com/wordup-md/nuxt-layer-shadcn-unocss" blank}
37
34
  Ghost
38
35
  ::
36
+ ::button-link{trailing-icon="lucide:arrow-up-right" to="/getting-started" target="_blank"}
37
+ Get Started
38
+ ::
39
39
  ```
40
40
  ::
41
41
 
@@ -44,8 +44,8 @@ badges:
44
44
  ::field-group
45
45
  :field{name="variant" type="'default' | 'secondary' | 'link' | 'destructive' | 'outline' | 'ghost'" default-value="'default'"}
46
46
  :field{name="size" type="'default' | 'icon' | 'sm' | 'xs' | 'lg'" default-value="'default'"}
47
- :field{name="leftIcon" type="string"}[Icon on the left]
48
- :field{name="rightIcon" type="string"}[Icon on the right]
47
+ :field{name="icon" type="string"}[Icon on the left]
48
+ :field{name="trailingIcon" type="string"}[Icon on the right]
49
49
  :field{name="to" type="string"}[Link URL]
50
50
  :field{name="href" type="string"}[Alias to `to`]
51
51
  :field{name="target" type="Target"}[A `target` attribute value to apply on the link]
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Accordion
3
- icon: lucide:layout-list
3
+ icon: i-mingcute:list-expansion-line
4
4
  badges:
5
5
  - value: Source
6
6
  icon: lucide:code
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: File Download
3
+ icon: i-mdi-file
4
+ ---
5
+
6
+ :file-download{path="/logo.svg"}
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Hero
3
- icon: lucide:align-center
3
+ icon: i-lucide:layout-panel-top
4
4
  badges:
5
5
  - value: Source
6
6
  icon: lucide:code
@@ -0,0 +1,42 @@
1
+ ---
2
+ title: Dynamic List
3
+ icon: i-lucide:layout-list
4
+ badges:
5
+ - value: Source
6
+ icon: lucide:code
7
+ to: https://github.com/wordup-md/nuxt-layer-shadcn-unocss/blob/main/components/content/List.vue
8
+ target: _blank
9
+ ---
10
+
11
+ ## Usage
12
+
13
+ ::stack
14
+ ::div{class="p-4"}
15
+ ::list
16
+ ---
17
+ path: /components/
18
+ query:
19
+ limit: 3
20
+ component: card
21
+ ---
22
+ ::
23
+ ::
24
+ ```mdc
25
+ ::list
26
+ ---
27
+ path: /components/
28
+ query:
29
+ limit: 3
30
+ component: card
31
+ ---
32
+ ::
33
+ ```
34
+ ::
35
+
36
+ ## Props
37
+
38
+ ::field-group
39
+ :field{name="path" type="string"}[Path to the list]
40
+ :field{name="query" type="object"}[Query parameters]
41
+ :field{name="component" type="string"}[Component to use for each item]
42
+ ::
@@ -2,6 +2,7 @@
2
2
  title: Home
3
3
  description: Effortless and Beautiful Template.
4
4
  layout: editorial
5
+ navigation: false
5
6
  ---
6
7
 
7
8
  ::hero
@@ -1,5 +1,5 @@
1
1
  ---
2
- title: Home
2
+ title: Layout
3
3
  navigation: false
4
4
  layout: editorial
5
5
  header:
@@ -1,8 +1,31 @@
1
1
  ---
2
- title: test
2
+ title: Test
3
3
  layout: editorial
4
4
  header:
5
5
  position: over
6
+ sidebarRight:
7
+ enable: true
8
+ components:
9
+ - ButtonLink:
10
+ title: GitHub
11
+ variant: outline
12
+ to: https://github.com/wordup-md/nuxt-layer-shadcn-unocss
13
+ icon: lucide:github
14
+ class: w-full
15
+ - Menu:
16
+ title: Menu test
17
+ items:
18
+ - /getting-started
19
+ - title: Menu
20
+ to: /getting-started
21
+ icon: lucide:menu
22
+ - Alert:
23
+ title: New
24
+ to: /getting-started
25
+ icon: lucide:party-popper
26
+ navBadges:
27
+ - value: New
28
+ type: new
6
29
  ---
7
30
 
8
31
  ::hero
package/README.md CHANGED
@@ -12,13 +12,13 @@ npx create-nuxt-app <project-name>
12
12
 
13
13
  - Install the layer
14
14
  ```bash
15
- pnpm add @unpress/nuxt-layer-shadcn-unocss
15
+ pnpm add @wordup-md/nuxt-layer-shadcn-unocss
16
16
  ```
17
17
 
18
18
  - Extend the layer in your nuxt.config.ts
19
19
  ```ts
20
20
  defineNuxtConfig({
21
- extends: '@unpress/nuxt-layer-shadcn-unocss'
21
+ extends: '@wordup-md/nuxt-layer-shadcn-unocss'
22
22
  })
23
23
  ```
24
24
 
@@ -14,6 +14,9 @@
14
14
  && 'rounded-md px-1.5 py-0.5 text-xs font-normal leading-none',
15
15
  ]"
16
16
  >
17
+ <span v-if="title">
18
+ {{ title }}
19
+ </span>
17
20
  <ContentSlot unwrap="p" />
18
21
  </UiBadge>
19
22
  </NuxtLink>
@@ -32,6 +35,9 @@
32
35
  && 'px-3 text-base',
33
36
  ]"
34
37
  >
38
+ <span v-if="title">
39
+ {{ title }}
40
+ </span>
35
41
  <ContentSlot unwrap="p" />
36
42
  </UiBadge>
37
43
  </span>
@@ -44,6 +50,7 @@ const {
44
50
  size = 'md',
45
51
  } = defineProps<{
46
52
  type?: 'default' | 'primary' | 'secondary' | 'info' | 'warning' | 'success' | 'danger' | 'new'
53
+ title?: string
47
54
  to?: string
48
55
  target?: Target
49
56
  variant?: 'default' | 'fill' | 'outline' | 'text'
@@ -7,20 +7,23 @@
7
7
  <UiButton
8
8
  :variant
9
9
  :size
10
+ :class="String($attrs.class || '')"
10
11
  >
11
12
  <Icon
12
- v-if="leftIcon"
13
- :name="leftIcon"
14
- class="mr-1"
13
+ v-if="icon"
14
+ :name="icon"
15
+ class="mr-2"
15
16
  />
17
+
16
18
  <span v-if="title">
17
19
  {{ title }}
18
20
  </span>
19
21
  <ContentSlot unwrap="p" />
22
+
20
23
  <Icon
21
- v-if="rightIcon"
22
- :name="rightIcon"
23
- class="ml-1"
24
+ v-if="trailingIcon"
25
+ :name="trailingIcon"
26
+ class="ml-2"
24
27
  />
25
28
  </UiButton>
26
29
  </NuxtLink>
@@ -33,8 +36,8 @@ defineProps<{
33
36
  variant?: ButtonVariants['variant']
34
37
  size?: ButtonVariants['size']
35
38
  title?: string
36
- leftIcon?: string
37
- rightIcon?: string
39
+ icon?: string
40
+ trailingIcon?: string
38
41
  to?: string
39
42
  href?: string
40
43
  target?: Target
@@ -0,0 +1,19 @@
1
+ <script lang="ts" setup>
2
+ import { useUnpress } from '#imports'
3
+
4
+ const { client, logout, login } = useUnpress()
5
+ </script>
6
+
7
+ <template>
8
+ <UiButton
9
+ variant="ghost"
10
+ class="flex gap-2"
11
+ @click="!!client ? logout() : login()"
12
+ >
13
+ <Icon
14
+ :name="!!client ? 'lucide:log-out' : 'lucide:log-in'"
15
+ :size="20"
16
+ />
17
+ {{ !!client ? $t('Logout') : $t('Login') }}
18
+ </UiButton>
19
+ </template>
@@ -0,0 +1,103 @@
1
+ <script lang="ts" setup>
2
+ const props = defineProps<{
3
+ path: string
4
+ title?: string
5
+ size?: number
6
+ icon?: string
7
+ inStack?: boolean
8
+ external?: boolean
9
+ }>()
10
+
11
+ // Get the asset
12
+ const { data } = await useFetch(props.path)
13
+
14
+ // Compute size
15
+ const size = computed(() => {
16
+ return props.size ?? data.value?.size
17
+ })
18
+
19
+ // onMounted(async () => {
20
+ // // Download the asset and get the size
21
+ // const size = await fetch(data.value?.url).then(res => res.headers.get('content-length'))
22
+ // console.log(size.value)
23
+ // })
24
+
25
+ const files = {
26
+ pdf: 'i-mdi-file-pdf-outline',
27
+ jpeg: 'i-mdi-file-image',
28
+ svg: 'i-mdi-file-image',
29
+ }
30
+ function ext(name: string) {
31
+ const ext = name.split('.').slice(-1)
32
+ if (files[ext]) return files[ext]
33
+ return 'i-mdi-file'
34
+ }
35
+
36
+ function fileSize(size: number) {
37
+ if (props.size) return props.size
38
+ if (!size) return null
39
+ if (size < 1024)
40
+ return `${size} octets`
41
+ if (size < 1024 * 1024)
42
+ return `${(size / 1024).toFixed(2)} Ko`
43
+ return `${(size / 1024 / 1024).toFixed(2)} Mo`
44
+ }
45
+
46
+ const _icon = computed(() => {
47
+ return props.icon ?? ext(props.path.split('/').pop() ?? '')
48
+ })
49
+
50
+ const _title = computed(() => {
51
+ return props.title ?? props.path.split('/').pop()
52
+ })
53
+ </script>
54
+
55
+ <template>
56
+ <UiAlert
57
+ class="transition-all [&:not(:first-child)]:mt-5 group/card"
58
+ :class="[
59
+ path && 'hover:bg-muted/50',
60
+ path && 'cursor-pointer',
61
+ inStack && 'm-0 rounded-none border-none',
62
+ ]"
63
+ >
64
+ <a
65
+ :href="path"
66
+ :target="external ? '_blank' : undefined"
67
+ :download="external ? undefined : path"
68
+ >
69
+ <div
70
+ v-if="_title"
71
+ class="flex flex-row gap-2 items-center"
72
+ >
73
+ <Icon
74
+ v-if="_icon && _title"
75
+ :name="_icon"
76
+ :size="20"
77
+ />
78
+
79
+ <UiAlertTitle
80
+ class="mb-0 flex flex-row gap-2"
81
+ >
82
+ <span class="font-semibold">{{ _title }}</span>
83
+ <span
84
+ v-if="size"
85
+ class="text-sm font-normal text-muted-foreground"
86
+ >
87
+ ( {{ fileSize(size) }} )
88
+ </span>
89
+ </UiAlertTitle>
90
+ </div>
91
+ </a>
92
+
93
+ <div
94
+ v-if="path"
95
+ class="absolute right-3 top-3 flex z-1 p-1 transition bg-background/50 rounded group-hover/card:translate-y-1"
96
+ >
97
+ <NuxtIcon
98
+ name="i-mdi-download"
99
+ :size="20"
100
+ />
101
+ </div>
102
+ </UiAlert>
103
+ </template>
@@ -1,14 +1,14 @@
1
1
  <template>
2
- <section :class="cn('flex flex-col gap-8 mt-8', String($attrs.class || ''))">
2
+ <section :class="cn('flex flex-col gap-4 mt-4', String($attrs.class || ''))">
3
3
  <ContentList
4
- v-if="path.length || Object.keys(query).length"
4
+ v-if="path.length || Object.keys(normalizedQuery).length"
5
5
  :path
6
- :query
6
+ :query="normalizedQuery"
7
7
  >
8
8
  <template #default="{ list }">
9
9
  <component
10
10
  :is="component || 'Card'"
11
- v-for="data in sortedList(filterList(list))"
11
+ v-for="data in sortedList(list)"
12
12
  :key="data._path"
13
13
  v-bind="itemProps ? { ...data, to: data._path, ...itemProps } : { ...data, to: data._path }"
14
14
  :class="cn('mt-0!', String(itemClass))"
@@ -42,9 +42,28 @@ const {
42
42
  itemClass?: string
43
43
  }>()
44
44
 
45
- const filterList = (list: ParsedContent[]) => {
46
- return list.filter(item => !item?._file?.includes('index.md'))
47
- }
45
+ // const { data } = await useAsyncData('homeiiii', () =>
46
+ // queryContent(path)
47
+ // // regex should exclude .../index.md file
48
+ // .where({ _type: { $not: 'yaml' }, _id: { $not: { $regex: /index\.md$/ } } })
49
+ // .find(),
50
+ // )
51
+ // console.log(data.value)
52
+
53
+ const normalizedQuery = computed(() => {
54
+ const _query = { ...query }
55
+ // Extends query.where
56
+ _query.where = {
57
+ ..._query.where,
58
+ _type: { $not: 'yaml' },
59
+ _id: { $not: { $regex: /index\.md$/ } },
60
+ }
61
+
62
+ return {
63
+ ..._query,
64
+ limit: _query.limit ? Number(_query.limit) : undefined,
65
+ }
66
+ })
48
67
 
49
68
  const sortedList = (list: ParsedContent[]) => {
50
69
  if (query?.sort && 'date' in query.sort) {
@@ -0,0 +1,43 @@
1
+ <script lang="ts" setup>
2
+ import type { NavItem } from '@nuxt/content'
3
+
4
+ const { items, title } = defineProps<{
5
+ title?: string
6
+ items: NavItem[]
7
+ }>()
8
+
9
+ const { navigation } = useContent()
10
+
11
+ const _links = computed(() => {
12
+ return items?.map((link) => {
13
+ if (typeof link === 'string') {
14
+ return {
15
+ ...navigation.value?.find(n => n._path === link),
16
+ _path: link,
17
+ }
18
+ }
19
+
20
+ return {
21
+ ...link,
22
+ _path: link.to || link._path,
23
+ }
24
+ })
25
+ })
26
+ </script>
27
+
28
+ <template>
29
+ <div>
30
+ <p
31
+ v-if="title"
32
+ class="mb-2 text-base font-semibold"
33
+ >
34
+ {{ title }}
35
+ </p>
36
+
37
+ <MenuItem
38
+ v-for="link in _links"
39
+ :key="link._path"
40
+ :link="link"
41
+ />
42
+ </div>
43
+ </template>
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <NuxtLink
3
+ :to="link._path"
4
+ class="flex items-center gap-2 rounded-md p-2 text-sm text-foreground/80 hover:bg-muted hover:text-primary"
5
+ :class="[
6
+ isActive && 'bg-muted !text-primary',
7
+ !!link.navTruncate && 'h-8',
8
+ ]"
9
+ >
10
+ <LayoutAsideTreeItemButton :link />
11
+ </NuxtLink>
12
+ </template>
13
+
14
+ <script setup lang="ts">
15
+ import type { NavItem } from '@nuxt/content'
16
+
17
+ const { link } = defineProps<{
18
+ link: NavItem
19
+ }>()
20
+
21
+ const isActive = computed(() => link._path === useRoute().path)
22
+ </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="[&:not(:first-child)]:mt-5">
2
+ <div class="[&:not(:first-child)]:mt-4">
3
3
  <UiEditorHorizontalControls class="mb--1">
4
4
  <UiEditorInput
5
5
  v-model="mdcAttrs.data"