@falcondev-oss/nuxt-layers-base 0.43.1 → 0.43.3
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.
|
@@ -52,6 +52,8 @@ export default defineSetupComponent(
|
|
|
52
52
|
}
|
|
53
53
|
slots: {
|
|
54
54
|
'default': () => VNode[]
|
|
55
|
+
'navbar-left'?: () => VNode[]
|
|
56
|
+
'navbar-leading'?: () => VNode[]
|
|
55
57
|
'navbar-title'?: () => VNode[]
|
|
56
58
|
'navbar-trailing'?: () => VNode[]
|
|
57
59
|
'navbar-actions'?: () => VNode[]
|
|
@@ -62,6 +64,8 @@ export default defineSetupComponent(
|
|
|
62
64
|
props: ['panel', 'navbar', 'tabs', 'tools', 'toolbarUi'],
|
|
63
65
|
emits: [],
|
|
64
66
|
setup: (props, { slots }) => {
|
|
67
|
+
const appConfig = useAppConfig()
|
|
68
|
+
|
|
65
69
|
// rendered manually in the `left` slot below
|
|
66
70
|
const omitNavbarSlots = [
|
|
67
71
|
'navbar-left',
|
|
@@ -141,13 +145,33 @@ export default defineSetupComponent(
|
|
|
141
145
|
(props.tools?.left || toolsCrowded.value),
|
|
142
146
|
)
|
|
143
147
|
|
|
148
|
+
// This `h1` stands in for the navbar's own, which never renders once `left` is taken
|
|
149
|
+
// over — so everything upstream would have layered onto that slot has to be layered on
|
|
150
|
+
// by hand: the theme's own classes come from `app.config`, the per-instance ones from
|
|
151
|
+
// `ui.title`, and either may be a replacer function rather than classes to merge.
|
|
152
|
+
const navbarTitleClass = computed(() =>
|
|
153
|
+
mergeSlotClass(
|
|
154
|
+
props.navbar?.ui?.title,
|
|
155
|
+
mergeSlotClass(
|
|
156
|
+
appConfig.ui?.dashboardNavbar?.slots?.title,
|
|
157
|
+
'text-highlighted font-semibold whitespace-nowrap',
|
|
158
|
+
)(''),
|
|
159
|
+
)(''),
|
|
160
|
+
)
|
|
161
|
+
|
|
144
162
|
const navbarUi = computed<DashboardNavbarProps['ui']>(() => ({
|
|
145
163
|
...props.navbar?.ui,
|
|
146
164
|
toggle: mergeSlotClass(props.navbar?.ui?.toggle, '-ml-1'),
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
165
|
+
// Exactly as wide as the title and breadcrumb need — neither truncates, and no room
|
|
166
|
+
// is held back from the actions.
|
|
167
|
+
left: mergeSlotClass(
|
|
168
|
+
props.navbar?.ui?.left,
|
|
169
|
+
// A breadcrumb wraps, so this column may give way once the row runs short — down to
|
|
170
|
+
// the widest line it still has to show whole. With nothing to reflow, `shrink-0`
|
|
171
|
+
// instead keeps that edge put: an action giving way would otherwise free space for
|
|
172
|
+
// the title to grow into and come straight back.
|
|
173
|
+
props.navbar?.breadcrumb ? 'min-w-0' : 'shrink-0',
|
|
174
|
+
),
|
|
151
175
|
...(props.navbar?.breadcrumb && {
|
|
152
176
|
root: mergeSlotClass(props.navbar.ui?.root, 'h-auto min-h-(--ui-header-height) py-2'),
|
|
153
177
|
}),
|
|
@@ -168,38 +192,48 @@ export default defineSetupComponent(
|
|
|
168
192
|
title={props.navbar.title}
|
|
169
193
|
v-slots={vSlots(UDashboardNavbar, {
|
|
170
194
|
left: () => [
|
|
195
|
+
// the toggle stays outside `left` upstream, so it survives a
|
|
196
|
+
// `navbar-left` that replaces everything beside it
|
|
171
197
|
...(props.navbar?.sidebarToggle
|
|
172
198
|
? [<UDashboardSidebarCollapse class="-ml-1" />]
|
|
173
199
|
: []),
|
|
174
200
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
201
|
+
...(slots['navbar-left']?.() ?? [
|
|
202
|
+
<div class="flex min-w-0 flex-col items-start gap-0.5">
|
|
203
|
+
{/* title and breadcrumb size the column between them, so
|
|
204
|
+
neither is ever cut off */}
|
|
205
|
+
<div class="flex items-center gap-1.5">
|
|
206
|
+
{slots['navbar-leading']?.()}
|
|
207
|
+
<h1 data-slot="title" class={navbarTitleClass.value}>
|
|
208
|
+
{slots['navbar-title']?.() ?? props.navbar?.title}
|
|
209
|
+
</h1>
|
|
210
|
+
{slots['navbar-trailing']?.()}
|
|
211
|
+
</div>
|
|
185
212
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
213
|
+
{props.navbar?.breadcrumb ? (
|
|
214
|
+
<UBreadcrumb
|
|
215
|
+
items={props.navbar.breadcrumb}
|
|
216
|
+
ui={{
|
|
217
|
+
...props.navbar.breadcrumbUi,
|
|
218
|
+
link: mergeSlotClass(
|
|
219
|
+
props.navbar.breadcrumbUi?.link,
|
|
220
|
+
'text-xs',
|
|
221
|
+
),
|
|
222
|
+
separatorIcon: mergeSlotClass(
|
|
223
|
+
props.navbar.breadcrumbUi?.separatorIcon,
|
|
224
|
+
'size-3.5',
|
|
225
|
+
),
|
|
226
|
+
// onto further lines once the row runs short, rather
|
|
227
|
+
// than truncating the trail
|
|
228
|
+
list: mergeSlotClass(
|
|
229
|
+
props.navbar.breadcrumbUi?.list,
|
|
230
|
+
'flex-wrap',
|
|
231
|
+
),
|
|
232
|
+
}}
|
|
233
|
+
/>
|
|
234
|
+
) : null}
|
|
235
|
+
</div>,
|
|
236
|
+
]),
|
|
203
237
|
],
|
|
204
238
|
right: (slotProps) => [
|
|
205
239
|
<>{slots['navbar-right']?.(slotProps)}</>,
|
|
@@ -43,20 +43,17 @@ export default defineSetupComponent(
|
|
|
43
43
|
// sections draw their own top/left border shifted by -1px, so the outer ones get clipped
|
|
44
44
|
<div
|
|
45
45
|
class={[
|
|
46
|
-
'ring-default bg-elevated flex flex-wrap
|
|
46
|
+
'ring-default bg-elevated flex flex-wrap overflow-hidden rounded-t-lg shadow-[inset_0_2px_3px_-2px_rgb(0_0_0/0.06),inset_2px_0_3px_-2px_rgb(0_0_0/0.06),inset_-2px_0_3px_-2px_rgb(0_0_0/0.06)] ring',
|
|
47
47
|
slots.default ? '-mb-2 pb-2' : 'rounded-b-lg',
|
|
48
48
|
]}
|
|
49
49
|
>
|
|
50
50
|
{leadingSections}
|
|
51
51
|
|
|
52
|
-
{/* every section hugs its content, so the spare space collects here instead of
|
|
53
|
-
stretching the last leading section */}
|
|
54
|
-
<div class="flex-1" />
|
|
55
|
-
|
|
56
52
|
{endSections.length > 0 ? (
|
|
57
53
|
// one flex item, so the end sections wrap onto their own line as a group
|
|
58
|
-
// instead of splitting up — the leading sections give way first
|
|
59
|
-
|
|
54
|
+
// instead of splitting up — the leading sections give way first;
|
|
55
|
+
// `ml-auto` eats the spare space, so leading sections stay left on every line
|
|
56
|
+
<div class="ml-auto flex flex-wrap justify-end">{endSections}</div>
|
|
60
57
|
) : null}
|
|
61
58
|
</div>
|
|
62
59
|
) : null}
|
|
@@ -27,7 +27,10 @@ export default defineSetupComponent(
|
|
|
27
27
|
<div
|
|
28
28
|
data-end={props.end || undefined}
|
|
29
29
|
class={cnMerge(
|
|
30
|
-
|
|
30
|
+
// no `flex-none`/`min-w-fit`: a section still hugs its content (grow 0) and still wraps onto
|
|
31
|
+
// its own ribbon line, but one too wide for the whole ribbon shrinks instead of
|
|
32
|
+
// overflowing, so its content can wrap
|
|
33
|
+
'border-default -mt-px -ml-px flex flex-col gap-1.5 border-l px-3 py-2',
|
|
31
34
|
// the row separator spans the full ribbon width (clipped by its overflow-hidden), so a
|
|
32
35
|
// partially filled wrapped line still gets an unbroken line above it
|
|
33
36
|
'before:border-default relative before:absolute before:inset-x-[-100vw] before:top-0 before:border-t',
|
package/app/utils/ui.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import type { SlotClass
|
|
1
|
+
import type { SlotClass } from '@nuxt/ui'
|
|
2
2
|
import type { ClassValue } from 'tailwind-variants'
|
|
3
3
|
import { cnMerge } from 'tailwind-variants'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/** Always resolves to a class string, so the result also stands on its own as a `class`. */
|
|
6
|
+
export function mergeSlotClass(ui: SlotClass, extend: ClassValue): (defaults: string) => string {
|
|
6
7
|
return (defaults) => {
|
|
7
8
|
const withBase = cnMerge(defaults, extend)() ?? ''
|
|
8
9
|
if (typeof ui === 'function') {
|
|
9
|
-
return ui(withBase)
|
|
10
|
+
return cnMerge(ui(withBase))() ?? ''
|
|
10
11
|
}
|
|
11
12
|
return cnMerge(withBase, ui)() ?? ''
|
|
12
13
|
}
|