@wordup-md/nuxt-layer-shadcn-unocss 0.2.0 → 0.2.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 (44) hide show
  1. package/.playground/app.config.ts +1 -1
  2. package/.playground/content/3.components/2.docs/stack.md +0 -1
  3. package/.playground/content/4.development/1.configuration/1.overview.md +1 -1
  4. package/.playground/content/4.development/1.configuration/4.edit-link.md +3 -3
  5. package/assets/css/mdc-editor.css +13 -6
  6. package/components/content/Alert.vue +4 -2
  7. package/components/content/ButtonLink.vue +5 -0
  8. package/components/content/Card.vue +31 -7
  9. package/components/content/Hero.vue +1 -1
  10. package/components/content/List.vue +60 -0
  11. package/components/content/ProseA.vue +3 -1
  12. package/components/content/ProseSection.vue +59 -5
  13. package/components/content/Steps.vue +1 -1
  14. package/components/content/global/AlertEditor.vue +4 -1
  15. package/components/content/global/ListEditor.vue +45 -0
  16. package/components/content/global/ReadMoreEditor.vue +3 -3
  17. package/components/content/global/StepsEditor.vue +17 -5
  18. package/components/layout/Banner.vue +26 -26
  19. package/components/layout/Breadcrumb.vue +9 -0
  20. package/components/layout/EditLink.vue +2 -2
  21. package/components/layout/Footer.vue +1 -1
  22. package/components/layout/Header.vue +1 -2
  23. package/components/layout/PageFooter.vue +23 -0
  24. package/components/layout/PrevNext.vue +18 -2
  25. package/components/layout/PrevNextButton.vue +1 -1
  26. package/components/layout/TocTree.vue +4 -4
  27. package/components/ui/button/index.ts +1 -1
  28. package/components/ui/card/CardDescription.vue +1 -1
  29. package/components/ui/card/CardTitle.vue +1 -1
  30. package/composables/useBreadcrumb.ts +6 -3
  31. package/composables/useConfig.ts +5 -1
  32. package/composables/useEditLink.ts +3 -3
  33. package/index.d.ts +21 -3
  34. package/layouts/editorial.vue +1 -1
  35. package/lib/uno-preset.ts +12 -3
  36. package/nuxt.config.ts +1 -0
  37. package/package.json +1 -1
  38. package/pages/[...slug].vue +16 -10
  39. package/pages/index.vue +1 -1
  40. package/plugins/wordup.ts +124 -124
  41. package/public/content-doc.json +4 -24
  42. package/.playground/content/3.components/2.docs/callout.md +0 -16
  43. package/components/content/Callout.vue +0 -17
  44. package/components/layout/DocsFooter.vue +0 -6
@@ -100,7 +100,7 @@ export default defineAppConfig({
100
100
  pattern: 'https://github.com/ZTL-UwU/shadcn-docs-nuxt/edit/main/content/:path',
101
101
  text: 'Edit this page',
102
102
  icon: 'lucide:square-pen',
103
- placement: ['docsFooter', 'toc'],
103
+ placement: ['pageFooter', 'toc'],
104
104
  },
105
105
  codeIcon: {
106
106
  'package.json': 'vscode-icons:file-type-node',
@@ -71,7 +71,6 @@ Stackable components:
71
71
  - `div`
72
72
  - Code Blocks
73
73
  - `alert`
74
- - `callout`
75
74
  - `read-more`
76
75
  - `code-group`
77
76
  - `card`
@@ -215,7 +215,7 @@ All configurable icons can be set to iconify icons, emojis and urls, using the [
215
215
  ::field{name="icon" type="string" default-value="lucide:square-pen"}
216
216
  The icon preceding the link.
217
217
  ::
218
- ::field{name="placement" type="('docsFooter' | 'toc')[]" default-value="['docsFooter']"}
218
+ ::field{name="placement" type="('pageFooter' | 'toc')[]" default-value="['pageFooter']"}
219
219
  Where to place the edit link.
220
220
  ::
221
221
  ::
@@ -15,7 +15,7 @@ export default defineAppConfig({
15
15
  pattern: 'https://github.com/ZTL-UwU/shadcn-docs-nuxt/edit/main/content/:path',
16
16
  text: 'Edit this page on GitHub',
17
17
  icon: 'lucide:square-pen',
18
- placement: ['docsFooter', 'toc'],
18
+ placement: ['pageFooter', 'toc'],
19
19
  },
20
20
  }
21
21
  },
@@ -29,7 +29,7 @@ export default defineAppConfig({
29
29
  - The `icon` option allows you to customize the icon (default is `lucide:square-pen`)
30
30
 
31
31
  - The `placement` option controls the places to put the edit link.
32
- - `docsFooter`: at the end of the page.
32
+ - `pageFooter`: at the end of the page.
33
33
  - `toc`: in the TOC links section.
34
34
 
35
35
  ### Front Matter
@@ -57,7 +57,7 @@ editLink: false
57
57
  ::field{name="icon" type="string" default-value="lucide:square-pen"}
58
58
  The icon preceding the link.
59
59
  ::
60
- ::field{name="placement" type="('docsFooter' | 'toc')[]" default-value="['docsFooter']"}
60
+ ::field{name="placement" type="('pageFooter' | 'toc')[]" default-value="['pageFooter']"}
61
61
  Where to place the edit link.
62
62
  ::
63
63
  ::
@@ -8,7 +8,8 @@
8
8
  outline: none;
9
9
  }
10
10
 
11
- & > p:not(:has(span)):not(:first-child) {
11
+ /* & > p:not(:has(span)):not(:first-child) { */
12
+ & > p:not(:first-child) {
12
13
  margin-top: 1.5rem;
13
14
  }
14
15
 
@@ -51,7 +52,7 @@
51
52
  }
52
53
  }
53
54
 
54
- & p a {
55
+ & p > a {
55
56
  text-underline-offset: 4px;
56
57
  text-decoration-line: underline;
57
58
  font-weight: 600;
@@ -61,11 +62,13 @@
61
62
  padding-top: 0.5rem;
62
63
  margin-left: 1.5rem;
63
64
 
64
- &:first-child,
65
- :not(&) + & {
65
+ &:first-child {
66
66
  padding-top: 1.5rem;
67
67
  }
68
68
  }
69
+ &:not(.prosemirror-flat-list) + .prosemirror-flat-list {
70
+ padding-top: 1.5rem;
71
+ }
69
72
 
70
73
  /* CodeGroupEditor */
71
74
  & .\[\&\:not\(\:first-child\)\]\:mt-5 {
@@ -76,16 +79,20 @@
76
79
  }
77
80
  }
78
81
 
82
+ .underline-none {
83
+ text-decoration: none !important;
84
+ }
85
+
79
86
  .animate-scroll-fade-in-up {
80
87
  animation: fade-in-up linear;
81
88
  animation-timeline: view();
82
89
  animation-range: 0 25dvh;
83
90
  }
84
91
 
85
- .docs-content:not(.EDITOR_CONTENT) > * {
92
+ .page-content:not(.EDITOR_CONTENT) > * {
86
93
  --una-enter-translate-y: 5dvh;
87
94
  --una-enter-opacity: 0.5;
88
95
  animation: una-in linear;
89
96
  animation-timeline: view();
90
97
  animation-range: 0 25dvh;
91
- }
98
+ }
@@ -9,7 +9,10 @@
9
9
  ]"
10
10
  @click="alertClick"
11
11
  >
12
- <div class="flex flex-row gap-2">
12
+ <div
13
+ v-if="title"
14
+ class="flex flex-row gap-2"
15
+ >
13
16
  <Icon
14
17
  v-if="icon && title"
15
18
  :name="icon"
@@ -17,7 +20,6 @@
17
20
  />
18
21
 
19
22
  <UiAlertTitle
20
- v-if="title"
21
23
  class="font-semibold mb-3"
22
24
  >
23
25
  {{ title }}
@@ -2,6 +2,7 @@
2
2
  <NuxtLink
3
3
  :to="to || href"
4
4
  :target="(blank && '_blank') || target"
5
+ class="button-link block"
5
6
  >
6
7
  <UiButton
7
8
  :variant
@@ -12,6 +13,9 @@
12
13
  :name="leftIcon"
13
14
  class="mr-1"
14
15
  />
16
+ <span v-if="title">
17
+ {{ title }}
18
+ </span>
15
19
  <ContentSlot unwrap="p" />
16
20
  <Icon
17
21
  v-if="rightIcon"
@@ -28,6 +32,7 @@ import type { ButtonVariants } from '../ui/button'
28
32
  defineProps<{
29
33
  variant?: ButtonVariants['variant']
30
34
  size?: ButtonVariants['size']
35
+ title?: string
31
36
  leftIcon?: string
32
37
  rightIcon?: string
33
38
  to?: string
@@ -10,14 +10,13 @@
10
10
  mediaPosition === 'bottom' && 'flex-col-reverse',
11
11
  ['cover', 'center'].includes(mediaPosition) && 'bg-opacity-0',
12
12
  mediaPosition === 'center' && 'text-center items-center flex-row p-8',
13
- $attrs.class,
14
13
  ]"
15
14
  >
16
15
  <div
17
16
  v-if="media || $slots.media"
18
- class="overflow-hidden"
17
+ class="card__media overflow-hidden"
19
18
  :class="{
20
- 'w-5/13 shrink-0': media && (mediaPosition === 'left' || mediaPosition === 'right'),
19
+ 'w-5/13 shrink-0': (media || $slots.media) && (mediaPosition === 'left' || mediaPosition === 'right'),
21
20
  'absolute inset-0': ['cover', 'center'].includes(mediaPosition),
22
21
  }"
23
22
  >
@@ -40,6 +39,7 @@
40
39
  v-if="
41
40
  icon || title || $slots.title || description || $slots.description
42
41
  "
42
+ class="card__header"
43
43
  :class="{
44
44
  'flex-row gap-5': iconPosition === 'left',
45
45
  'items-center': mediaPosition === 'center',
@@ -52,9 +52,18 @@
52
52
  :class="{ 'mb-2': iconPosition !== 'left' && (title || $slots.title) }"
53
53
  />
54
54
 
55
- <div class="flex flex-col gap-1.5 w-full">
55
+ <div class="flex flex-col gap-2 w-full">
56
+ <div
57
+ v-if="date"
58
+ class="card__date text-sm text-muted-foreground"
59
+ style="text-decoration: none !important"
60
+ >
61
+ {{ new Intl.DateTimeFormat(locale, { dateStyle: 'long' }).format(new Date(date)) }}
62
+ </div>
63
+
56
64
  <UiCardTitle
57
65
  v-if="title || $slots.title"
66
+ class="card__title"
58
67
  :class="{ 'group-hover/card:underline': to, 'pr-4': ['left', 'bottom'].includes(mediaPosition) && to }"
59
68
  >
60
69
  <ContentSlot
@@ -68,7 +77,10 @@
68
77
  />
69
78
  </UiCardTitle>
70
79
 
71
- <UiCardDescription v-if="description || $slots.description">
80
+ <UiCardDescription
81
+ v-if="description || $slots.description"
82
+ class="card__description"
83
+ >
72
84
  <ContentSlot
73
85
  :use="$slots.description"
74
86
  unwrap="p"
@@ -86,6 +98,7 @@
86
98
 
87
99
  <UiCardContent
88
100
  v-if="content || $slots.content || $slots.default"
101
+ class="card__content"
89
102
  :class="{ 'py-3': !icon && !(title || $slots.title) && !(description || $slots.description) }"
90
103
  >
91
104
  <ContentSlot unwrap="p" />
@@ -95,7 +108,10 @@
95
108
  />
96
109
  </UiCardContent>
97
110
 
98
- <UiCardFooter v-if="footer || $slots.footer">
111
+ <UiCardFooter
112
+ v-if="footer || $slots.footer"
113
+ class="card__footer"
114
+ >
99
115
  <ContentSlot
100
116
  :use="$slots.footer"
101
117
  unwrap="p"
@@ -117,7 +133,9 @@
117
133
  </UiCard>
118
134
  </UseTemplate>
119
135
 
120
- <div class="group/card group-has-[div]:mt-0 [&:not(:first-child)]:mt-5">
136
+ <div
137
+ :class="cn('group/card group-has-[div]:mt-0 [&:not(:first-child)]:mt-5', String($attrs.class || ''))"
138
+ >
121
139
  <NuxtLink
122
140
  v-if="to"
123
141
  :to
@@ -126,11 +144,14 @@
126
144
  >
127
145
  <CardInner />
128
146
  </NuxtLink>
147
+
129
148
  <CardInner v-else />
130
149
  </div>
131
150
  </template>
132
151
 
133
152
  <script setup lang="ts">
153
+ import { cn } from '@/lib/utils'
154
+
134
155
  defineOptions({
135
156
  inheritAttrs: false,
136
157
  })
@@ -146,6 +167,7 @@ const {
146
167
  } = defineProps<{
147
168
  title?: string
148
169
  description?: string
170
+ date?: string
149
171
  content?: string
150
172
  footer?: string
151
173
 
@@ -164,6 +186,8 @@ const {
164
186
  inStack?: boolean
165
187
  }>()
166
188
 
189
+ const { locale } = useI18nDocs()
190
+
167
191
  defineSlots()
168
192
 
169
193
  const [UseTemplate, CardInner] = createReusableTemplate()
@@ -93,7 +93,7 @@
93
93
  :name="action.leftIcon"
94
94
  class="mr-1"
95
95
  />
96
- {{ action.name }}
96
+ <span>{{ action.name }}</span>
97
97
  <Icon
98
98
  v-if="action.rightIcon"
99
99
  :name="action.rightIcon"
@@ -0,0 +1,60 @@
1
+ <template>
2
+ <section :class="cn('flex flex-col gap-8 mt-8', String($attrs.class || ''))">
3
+ <ContentList
4
+ v-if="path.length || Object.keys(query).length"
5
+ :path
6
+ :query
7
+ >
8
+ <template #default="{ list }">
9
+ <component
10
+ :is="component || 'Card'"
11
+ v-for="data in sortedList(filterList(list))"
12
+ :key="data._path"
13
+ v-bind="itemProps ? { ...data, to: data._path, ...itemProps } : { ...data, to: data._path }"
14
+ :class="cn('mt-0!', String(itemClass))"
15
+ />
16
+ </template>
17
+
18
+ <template #not-found>
19
+ <p>No articles found.</p>
20
+ </template>
21
+ </ContentList>
22
+ </section>
23
+ </template>
24
+
25
+ <script setup lang="ts">
26
+ import type { QueryBuilderParams, ParsedContent } from '@nuxt/content'
27
+ import { cn } from '@/lib/utils'
28
+
29
+ type ListQuery = QueryBuilderParams & { sort?: { date?: 'ASC' | 'DESC' | 1 | -1 } }
30
+
31
+ const {
32
+ path = '',
33
+ query = {} as ListQuery,
34
+ component = 'Card',
35
+ itemProps = {},
36
+ itemClass = '',
37
+ } = defineProps<{
38
+ path?: string
39
+ query?: ListQuery
40
+ component?: string
41
+ itemProps?: object
42
+ itemClass?: string
43
+ }>()
44
+
45
+ const filterList = (list: ParsedContent[]) => {
46
+ return list.filter(item => !item?._file?.includes('index.md'))
47
+ }
48
+
49
+ const sortedList = (list: ParsedContent[]) => {
50
+ if (query?.sort && 'date' in query.sort) {
51
+ return [...list].sort((a, b) =>
52
+ query.sort!.date === 'DESC' || query.sort!.date === -1
53
+ ? new Date(b.date).getTime() - new Date(a.date).getTime()
54
+ : new Date(a.date).getTime() - new Date(b.date).getTime(),
55
+ )
56
+ }
57
+
58
+ return list
59
+ }
60
+ </script>
@@ -3,13 +3,15 @@
3
3
  :to="href"
4
4
  :target="target"
5
5
  :external="external"
6
- class="font-semibold underline underline-offset-4"
6
+ :class="cn('font-semibold underline underline-offset-4', String($attrs.class || ''))"
7
7
  >
8
8
  <slot />
9
9
  </NuxtLink>
10
10
  </template>
11
11
 
12
12
  <script setup lang="ts">
13
+ import { cn } from '@/lib/utils'
14
+
13
15
  const {
14
16
  href = '',
15
17
  external = false,
@@ -7,21 +7,75 @@ defineOptions({
7
7
  })
8
8
 
9
9
  defineProps<{
10
- color?: string
10
+ title?: string
11
11
  }>()
12
+
13
+ defineSlots()
12
14
  </script>
13
15
 
14
16
  <template>
15
17
  <section
18
+ class="prose-section"
16
19
  :class="cn(
17
20
  'relative p-6 mt-6',
18
21
  classToString($attrs.class),
19
- color,
20
22
  )"
21
23
  >
22
- <!-- <span class="absolute bg-muted-foreground/05 -left-2 -top-1 -bottom-1 -right-2 md:-left-3 md:-top-0 md:-bottom-0 md:-right-3 -rotate-1" /> -->
23
- <div class="grid grid-cols-[repeat(auto-fit,minmax(300px,auto))] gap-6 [&>*]:mt-0!">
24
- <slot />
24
+ <div>
25
+ <div
26
+ v-if="$slots.before"
27
+ class="prose-section__before"
28
+ >
29
+ <ContentSlot
30
+ :use="$slots.before"
31
+ unwrap="p"
32
+ />
33
+ </div>
34
+
35
+ <ProseH2 v-if="title">
36
+ {{ title }}
37
+ </ProseH2>
38
+
39
+ <!-- <span class="absolute bg-muted-foreground/05 -left-2 -top-1 -bottom-1 -right-2 md:-left-3 md:-top-0 md:-bottom-0 md:-right-3 -rotate-1" /> -->
40
+ <!-- <div class="grid grid-cols-[repeat(auto-fit,minmax(300px,auto))] gap-6 [&>*]:mt-0!"> -->
41
+ <div
42
+ v-if="$slots.default"
43
+ class="prose-section__content"
44
+ >
45
+ <ContentSlot
46
+ :use="$slots.default"
47
+ unwrap="p"
48
+ />
49
+ </div>
50
+
51
+ <div
52
+ v-if="$slots.after"
53
+ class="prose-section__after"
54
+ >
55
+ <ContentSlot
56
+ :use="$slots.after"
57
+ unwrap="p"
58
+ />
59
+ </div>
25
60
  </div>
26
61
  </section>
27
62
  </template>
63
+
64
+ <style scoped>
65
+ .grid-flex {
66
+ display: grid;
67
+ gap: 1rem;
68
+ grid-template-columns: repeat(auto-fit, minmax(min(var(--min-column-size, 15ch), 100%), 1fr));
69
+ background: #f7f7f7;
70
+ border: 1px solid #e5e5e5;
71
+ padding: 0.25rem;
72
+ }
73
+
74
+ .grid-flex > div {
75
+ background-color: #ffdc00;
76
+ border: 1px solid #665800;
77
+ color: #665800;
78
+ padding: 1rem 2rem;
79
+ text-align: center;
80
+ }
81
+ </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div
3
- class="[&>li]:step ml-4 border-l pl-8 [counter-reset:step] [&:not(:first-child)]:mt-6 [&:not(:last-child)]:mb-12"
3
+ class="steps [&>li]:step ml-4 border-l-2 pl-8 [counter-reset:step] [&:not(:first-child)]:mt-6 [&:not(:last-child)]:mb-12"
4
4
  :class="levelClass[level]"
5
5
  >
6
6
  <slot />
@@ -12,7 +12,10 @@
12
12
  </UiEditorDropdown>
13
13
 
14
14
  <Alert v-bind="model">
15
- <div :ref="props.contentRef" />
15
+ <p
16
+ :ref="props.contentRef"
17
+ class="[&>div]:min-h-5.5"
18
+ />
16
19
  </Alert>
17
20
  </div>
18
21
  </template>
@@ -0,0 +1,45 @@
1
+ <script lang="ts" setup>
2
+ import type { VueNodeViewProps } from 'prosekit/vue'
3
+
4
+ const props = defineProps<VueNodeViewProps>()
5
+ const { getComponentProps } = useMdcEditor()
6
+
7
+ const { model, mdcAttrs } = getComponentProps(props, {
8
+ id: {
9
+ type: String,
10
+ },
11
+ class: {
12
+ type: String,
13
+ },
14
+ path: {
15
+ type: String,
16
+ },
17
+ query: {
18
+ type: Object,
19
+ },
20
+ component: {
21
+ type: String,
22
+ },
23
+ })
24
+ </script>
25
+
26
+ <template>
27
+ <div class="relative mt-8">
28
+ <UiEditorHorizontalControls>
29
+ <UiEditorInput
30
+ v-model="mdcAttrs.path"
31
+ flex-1
32
+ placeholder="Path to folder"
33
+ label="Chemin"
34
+ />
35
+ </UiEditorHorizontalControls>
36
+
37
+ <List
38
+ v-if="model.path || model.query"
39
+ :path="model.path"
40
+ :query="model.query"
41
+ :component="model.component"
42
+ contenteditable="false"
43
+ />
44
+ </div>
45
+ </template>
@@ -34,7 +34,7 @@ import type { VueNodeViewProps } from 'prosekit/vue'
34
34
  const props = defineProps<VueNodeViewProps>()
35
35
  const { getComponentProps } = useMdcEditor()
36
36
 
37
- const { model } = getComponentProps(props, {
37
+ const { mdcAttrs, model } = getComponentProps(props, {
38
38
  id: {
39
39
  type: String,
40
40
  },
@@ -62,9 +62,9 @@ const { model } = getComponentProps(props, {
62
62
 
63
63
  function updatePrefix(event: Event) {
64
64
  const target = event.target as HTMLDivElement
65
- model.prefix = target.innerHTML
65
+ mdcAttrs.prefix = target.innerHTML
66
66
  }
67
67
  function updateLink(to: string) {
68
- model.to = to
68
+ mdcAttrs.to = to
69
69
  }
70
70
  </script>
@@ -1,21 +1,24 @@
1
1
  <template>
2
2
  <div class="relative">
3
3
  <UiEditorDropdown
4
- v-model="mdcAttrs.level"
4
+ v-model="levelModel"
5
5
  chevron
6
6
  tooltip="Level"
7
7
  placement="bottom-end"
8
- :items="levels"
8
+ :items="levels.map(level => `H${level}`)"
9
9
  class="absolute right-1 top-1 z-10 opacity-25 transition-opacity group-hover:opacity-100"
10
10
  >
11
- <span class="text-xs font-mono capitalize">h{{ model.level }}</span>
11
+ <span class="text-xs font-mono capitalize">{{ levelModel }}</span>
12
12
  </UiEditorDropdown>
13
13
 
14
14
  <Steps
15
15
  v-bind="model"
16
- :class="levelClass[model.level]"
16
+ :class="levelClass[model.level as keyof typeof levelClass]"
17
17
  >
18
- <div :ref="props.contentRef" />
18
+ <div
19
+ :ref="props.contentRef"
20
+ class="[&>div]:min-h-5.5 [&_p]:mt-6"
21
+ />
19
22
  </Steps>
20
23
  </div>
21
24
  </template>
@@ -52,4 +55,13 @@ const { model, mdcAttrs } = getComponentProps(props, {
52
55
  },
53
56
  },
54
57
  })
58
+
59
+ const levelModel = computed({
60
+ get() {
61
+ return `H${model.level}`
62
+ },
63
+ set(value) {
64
+ mdcAttrs.level = value.replace('H', '')
65
+ },
66
+ })
55
67
  </script>
@@ -2,39 +2,39 @@
2
2
  <Transition>
3
3
  <div
4
4
  v-if="open === true"
5
- class="app__banner block transition-colors bg-primary/10"
5
+ class="app__banner block relative h-[var(--banner-height)] transition-colors bg-primary/10"
6
6
  :class="{
7
7
  'hover:cursor-pointer hover:bg-primary/25': to,
8
8
  'border-b': border,
9
9
  }"
10
10
  >
11
- <div class="container h-10 flex items-center justify-between px-4 md:px-8">
12
- <NuxtLink
11
+ <NuxtLink
12
+ :to
13
+ class="container flex items-stretch w-full md:px-8 h-full"
14
+ @click.stop="navigate"
15
+ >
16
+ <div class="hidden lg:block" />
17
+ <MDC
18
+ :value="content"
19
+ class="flex items-center justify-center text-primary text-lg w-full"
20
+ />
21
+ </NuxtLink>
13
22
 
14
- :to
15
- @click.prevent="navigate"
16
- >
17
- <div class="hidden lg:block" />
18
- <div class="text-sm">
19
- <MDC
20
- :value="content"
21
- class="flex items-center text-primary text-lg"
23
+ <div class="absolute right-0 top-0 w-full h-full">
24
+ <div class="container h-full flex items-stretch justify-end">
25
+ <UiButton
26
+ v-if="showClose"
27
+ variant="ghost"
28
+ class="z-40 h-auto px-3 [--accent:var(--primary)] !bg-opacity-25 rounded-none"
29
+ aria-label="Close banner"
30
+ @click.stop="open = Date.now()"
31
+ >
32
+ <NuxtIcon
33
+ name="lucide:x"
34
+ size="24"
22
35
  />
23
- </div>
24
- </NuxtLink>
25
-
26
- <UiButton
27
- v-if="showClose"
28
- variant="ghost"
29
- class="z-40 size-10 p-2 [--accent:var(--primary)] !bg-opacity-25 rounded-none"
30
- aria-label="Close banner"
31
- @click.prevent="open = Date.now()"
32
- >
33
- <NuxtIcon
34
- name="lucide:x"
35
- size="36"
36
- />
37
- </UiButton>
36
+ </UiButton>
37
+ </div>
38
38
  </div>
39
39
  </div>
40
40
  </Transition>
@@ -16,6 +16,11 @@
16
16
  :size="breadcrumb.iconSize || config.main.breadCrumb.iconSize || 14"
17
17
  :name="breadcrumb.icon"
18
18
  />
19
+ <Icon
20
+ v-if="(breadcrumb.media && showImage)"
21
+ :size="breadcrumb.iconSize || config.main.breadCrumb.iconSize || 14"
22
+ :name="breadcrumb.media"
23
+ />
19
24
  {{ breadcrumb.title }}
20
25
  </NuxtLink>
21
26
  </UiBreadcrumbItem>
@@ -27,6 +32,10 @@
27
32
  </template>
28
33
 
29
34
  <script setup lang="ts">
35
+ const { showImage = false } = defineProps<{
36
+ showImage?: boolean
37
+ }>()
38
+
30
39
  const route = useRoute()
31
40
  const config = useConfig()
32
41