@bagelink/vue 1.15.141 → 1.15.145
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/dist/components/ListItem.vue.d.ts +36 -0
- package/dist/components/ListItem.vue.d.ts.map +1 -1
- package/dist/index.cjs +38 -38
- package/dist/index.mjs +4060 -4024
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/ListItem.vue +135 -30
- package/src/components/layout/AppContent.vue +4 -3
package/package.json
CHANGED
|
@@ -30,12 +30,47 @@ const props = withDefaults(
|
|
|
30
30
|
md?: boolean
|
|
31
31
|
lg?: boolean
|
|
32
32
|
xl?: boolean
|
|
33
|
+
/** Fine-grained size overrides — take precedence over `size`. Accept any CSS
|
|
34
|
+
length (e.g. `'1.1rem'`, `'18px'`) or a raw number (treated as `rem` for
|
|
35
|
+
text, `px` for the avatar). Leave unset to inherit from `size`.
|
|
36
|
+
Under the hood these set public CSS vars you can also drive externally:
|
|
37
|
+
`--bgl-list-item-title-size`, `--bgl-list-item-subtitle-size`,
|
|
38
|
+
`--bgl-list-item-lead-size`, `--bgl-list-item-icon-chip-size`. */
|
|
39
|
+
fontSize?: string | number
|
|
40
|
+
titleSize?: string | number
|
|
41
|
+
subtitleSize?: string | number
|
|
42
|
+
leadSize?: string | number
|
|
43
|
+
/** Font weights — take precedence over `size`/defaults. Accept a number
|
|
44
|
+
(`600`) or a keyword (`'bold'`). Leave unset to keep the defaults
|
|
45
|
+
(title 600, subtitle 300, lead 600). Set the same public CSS vars:
|
|
46
|
+
`--bgl-list-item-title-weight`, `--bgl-list-item-subtitle-weight`,
|
|
47
|
+
`--bgl-list-item-lead-weight`. */
|
|
48
|
+
fontWeight?: string | number
|
|
49
|
+
titleWeight?: string | number
|
|
50
|
+
subtitleWeight?: string | number
|
|
51
|
+
leadWeight?: string | number
|
|
52
|
+
/** Glyph size of the leading `icon` (and, if a number, of the trailing
|
|
53
|
+
`iconEnd`). Any CSS length or number-as-rem. */
|
|
54
|
+
iconSize?: string | number
|
|
55
|
+
/** Box size of the leading icon-chip (the tinted square). CSS length / px. */
|
|
56
|
+
iconChipSize?: string | number
|
|
57
|
+
/** Toggle the leading icon's tinted background chip. Defaults `true` (the
|
|
58
|
+
tinted rounded square). Set `:icon-chip="false"` to drop the background
|
|
59
|
+
and render the bare glyph (still accent-colored). */
|
|
60
|
+
iconChip?: boolean
|
|
61
|
+
/** Override the leading avatar diameter (px). */
|
|
62
|
+
avatarSize?: number
|
|
33
63
|
fullWidth?: boolean
|
|
34
64
|
ellipsis?: boolean
|
|
35
65
|
ripple?: boolean
|
|
36
66
|
/** Theme accent for the leading icon-chip and hover/active tint.
|
|
37
67
|
Defaults to the surface's primary. e.g. `color="purple"`. */
|
|
38
68
|
color?: ThemeType
|
|
69
|
+
/** Color of the leading icon glyph ONLY — overrides the accent for the
|
|
70
|
+
glyph without touching the chip background or hover/active tint.
|
|
71
|
+
Accepts a theme name (`'purple'` → `var(--bgl-purple)`) or any raw CSS
|
|
72
|
+
color (`'#f00'`, `'currentColor'`). */
|
|
73
|
+
iconColor?: ThemeType | (string & {})
|
|
39
74
|
/** Card-style row: rounded, no divider, tinted hover. Use for standalone
|
|
40
75
|
selectable lists (vs. the default flush divided rows in a panel). */
|
|
41
76
|
rounded?: boolean
|
|
@@ -48,6 +83,7 @@ const props = withDefaults(
|
|
|
48
83
|
{
|
|
49
84
|
ellipsis: true,
|
|
50
85
|
ripple: false,
|
|
86
|
+
iconChip: true,
|
|
51
87
|
}
|
|
52
88
|
)
|
|
53
89
|
|
|
@@ -95,12 +131,62 @@ const computedSize = computed(() => {
|
|
|
95
131
|
// behavior (thin → 30px avatar, else 38px; 1.2rem icon glyph).
|
|
96
132
|
const avatarSizeMap = { xs: 20, sm: 24, md: 38, lg: 46, xl: 56 } as const
|
|
97
133
|
const iconSizeMap = { xs: 0.8, sm: 0.9, md: 1.2, lg: 1.5, xl: 1.8 } as const
|
|
134
|
+
|
|
135
|
+
// Normalize a size prop to a usable CSS length: bare numbers → `rem` (text/glyph)
|
|
136
|
+
// or `px` (box), while any string (`'1.1rem'`, `'18px'`, `'2em'`) passes through.
|
|
137
|
+
const toRem = (v: string | number | undefined) =>
|
|
138
|
+
v === undefined ? undefined : (typeof v === 'number' ? `${v}rem` : v)
|
|
139
|
+
const toPx = (v: string | number | undefined) =>
|
|
140
|
+
v === undefined ? undefined : (typeof v === 'number' ? `${v}px` : v)
|
|
141
|
+
|
|
142
|
+
// Effective avatar diameter: explicit `avatarSize` prop wins, then `size`, then
|
|
143
|
+
// the historical thin/default fallback.
|
|
98
144
|
const avatarSize = computed(() =>
|
|
99
|
-
computedSize.value ? avatarSizeMap[computedSize.value] : (props.thin ? 30 : 38),
|
|
100
|
-
)
|
|
101
|
-
const iconSize = computed(() =>
|
|
102
|
-
computedSize.value ? iconSizeMap[computedSize.value] : 1.2,
|
|
145
|
+
props.avatarSize ?? (computedSize.value ? avatarSizeMap[computedSize.value] : (props.thin ? 30 : 38)),
|
|
103
146
|
)
|
|
147
|
+
// Effective leading-icon glyph size passed to <Icon :size>. `<Icon>` appends
|
|
148
|
+
// `rem` to its `size`, so we resolve to a bare rem number: a numeric prop is used
|
|
149
|
+
// as-is; a `'1.5rem'` string has its number extracted; a `size` step maps via
|
|
150
|
+
// iconSizeMap; otherwise the historical 1.2rem. (For px control of the chip box,
|
|
151
|
+
// use `iconChipSize`.)
|
|
152
|
+
const iconSize = computed(() => {
|
|
153
|
+
if (typeof props.iconSize === 'number') { return props.iconSize }
|
|
154
|
+
if (typeof props.iconSize === 'string') {
|
|
155
|
+
const n = Number.parseFloat(props.iconSize)
|
|
156
|
+
if (!Number.isNaN(n)) { return n }
|
|
157
|
+
}
|
|
158
|
+
return computedSize.value ? iconSizeMap[computedSize.value] : 1.2
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
// Inline CSS vars set from the fine-grained size props. These map onto the same
|
|
162
|
+
// public custom properties consumers can set externally, so a `prop` is just a
|
|
163
|
+
// convenient way to set the var for a single row.
|
|
164
|
+
// A theme name (`blue`, `purple-light`, …) maps to its `--bgl-<name>` token; any
|
|
165
|
+
// other value (hex, rgb(), currentColor, a custom var) is used verbatim. Theme
|
|
166
|
+
// names are plain lowercase identifiers with optional `-` (e.g. `blue-light`).
|
|
167
|
+
const resolveColor = (v: string) =>
|
|
168
|
+
/^[a-z]+(-[a-z]+)*$/.test(v) ? `var(--bgl-${v})` : v
|
|
169
|
+
|
|
170
|
+
const listItemVars = computed(() => {
|
|
171
|
+
const vars: Record<string, string> = {}
|
|
172
|
+
if (props.color) { vars['--bgl-list-item-accent'] = `var(--bgl-${props.color})` }
|
|
173
|
+
if (props.iconColor) { vars['--bgl-list-item-icon-color'] = resolveColor(props.iconColor) }
|
|
174
|
+
const title = toRem(props.titleSize ?? props.fontSize)
|
|
175
|
+
if (title) { vars['--bgl-list-item-title-size'] = title }
|
|
176
|
+
const subtitle = toRem(props.subtitleSize)
|
|
177
|
+
if (subtitle) { vars['--bgl-list-item-subtitle-size'] = subtitle }
|
|
178
|
+
const lead = toRem(props.leadSize)
|
|
179
|
+
if (lead) { vars['--bgl-list-item-lead-size'] = lead }
|
|
180
|
+
const chip = toPx(props.iconChipSize)
|
|
181
|
+
if (chip) { vars['--bgl-list-item-icon-chip-size'] = chip }
|
|
182
|
+
// Font weights — a number or keyword passes through as-is. `fontWeight` acts
|
|
183
|
+
// as the base for the title unless a more specific `titleWeight` is given.
|
|
184
|
+
const titleW = props.titleWeight ?? props.fontWeight
|
|
185
|
+
if (titleW !== undefined) { vars['--bgl-list-item-title-weight'] = String(titleW) }
|
|
186
|
+
if (props.subtitleWeight !== undefined) { vars['--bgl-list-item-subtitle-weight'] = String(props.subtitleWeight) }
|
|
187
|
+
if (props.leadWeight !== undefined) { vars['--bgl-list-item-lead-weight'] = String(props.leadWeight) }
|
|
188
|
+
return vars
|
|
189
|
+
})
|
|
104
190
|
|
|
105
191
|
const hasTo = computed(() => props.to !== undefined && props.to !== '')
|
|
106
192
|
const hasHref = computed(() => props.href !== undefined && props.href !== '')
|
|
@@ -143,7 +229,7 @@ const bind = computed(() => {
|
|
|
143
229
|
{ 'no-border-list': props.flat || rounded, 'list-item-flush': props.fullWidth, 'list-item-fullrow': isClickable, 'list-item-has-end': hasEnd, 'list-item-rounded': rounded, 'list-item-active': active },
|
|
144
230
|
computedSize ? `list-item-${computedSize}` : '',
|
|
145
231
|
]"
|
|
146
|
-
:style="
|
|
232
|
+
:style="listItemVars"
|
|
147
233
|
>
|
|
148
234
|
<!-- Content rendered before the clickable area (e.g. a drag handle, avatar
|
|
149
235
|
or leading visual). Lives outside the clickable component so interacting
|
|
@@ -162,7 +248,7 @@ const bind = computed(() => {
|
|
|
162
248
|
(covers, thumbnails); `src`/`showAvatar` and `icon` are shortcuts. -->
|
|
163
249
|
<slot name="media">
|
|
164
250
|
<Avatar v-if="src || showAvatar" :name="title" :src="src" :size="avatarSize" class="flex-shrink-0" />
|
|
165
|
-
<span v-if="icon" class="list-item-icon flex-shrink-0">
|
|
251
|
+
<span v-if="icon" class="list-item-icon flex-shrink-0" :class="{ 'list-item-icon-nobg': !iconChip }">
|
|
166
252
|
<Icon :size="iconSize" :icon="icon" />
|
|
167
253
|
</span>
|
|
168
254
|
</slot>
|
|
@@ -345,15 +431,32 @@ background-color: var(--bgl-list-item-hover, color-mix(in srgb, var(--bgl-list-i
|
|
|
345
431
|
filter: var(--bgl-hover-filter);
|
|
346
432
|
}
|
|
347
433
|
|
|
348
|
-
/* Leading icon chip — tinted with the row accent (primary by default).
|
|
434
|
+
/* Leading icon chip — tinted with the row accent (primary by default).
|
|
435
|
+
The tinted square's box size is driven by a public CSS var so consumers (or
|
|
436
|
+
the `iconChipSize` prop) can retune it without a `size` step:
|
|
437
|
+
--bgl-list-item-icon-chip-size → the tinted square (default 34px)
|
|
438
|
+
The glyph *inside* it is sized via the `iconSize` prop (→ <Icon :size>). */
|
|
349
439
|
.list-item-icon {
|
|
350
440
|
display: grid;
|
|
351
441
|
place-items: center;
|
|
352
|
-
width: 34px;
|
|
353
|
-
height: 34px;
|
|
442
|
+
width: var(--bgl-list-item-icon-chip-size, 34px);
|
|
443
|
+
height: var(--bgl-list-item-icon-chip-size, 34px);
|
|
354
444
|
border-radius: 9px;
|
|
355
445
|
background: color-mix(in srgb, var(--bgl-list-item-accent) 12%, transparent);
|
|
356
|
-
color:
|
|
446
|
+
/* Glyph color: an explicit `iconColor` (→ --bgl-list-item-icon-color) wins;
|
|
447
|
+
otherwise fall back to the row accent so existing rows are unchanged. The
|
|
448
|
+
chip background above stays tied to the accent regardless. */
|
|
449
|
+
color: var(--bgl-list-item-icon-color, var(--bgl-list-item-accent));
|
|
450
|
+
}
|
|
451
|
+
/* `:icon-chip="false"` → drop the tinted square and its fixed box so the bare
|
|
452
|
+
glyph sits at its natural size (still accent-colored). The `.list-item-row`
|
|
453
|
+
prefix lifts specificity above the per-size `.list-item-<sz> .list-item-icon`
|
|
454
|
+
rules below, which also pin width/height. */
|
|
455
|
+
.list-item-row .list-item-icon-nobg {
|
|
456
|
+
width: auto;
|
|
457
|
+
height: auto;
|
|
458
|
+
background: none;
|
|
459
|
+
border-radius: 0;
|
|
357
460
|
}
|
|
358
461
|
|
|
359
462
|
/* Text block: tight, clear hierarchy. min-width:0 lets the ellipsis titles/
|
|
@@ -362,24 +465,28 @@ color: var(--bgl-list-item-accent);
|
|
|
362
465
|
min-width: 0;
|
|
363
466
|
}
|
|
364
467
|
.list-item-body > p { margin: 0; padding: 0; }
|
|
468
|
+
/* Type sizes read a public CSS var with the historical value as fallback, so
|
|
469
|
+
consumers / the fontSize·titleSize·subtitleSize·leadSize props can retune the
|
|
470
|
+
text without stepping the whole `size` scale:
|
|
471
|
+
--bgl-list-item-title-size · --bgl-list-item-subtitle-size · --bgl-list-item-lead-size */
|
|
365
472
|
.list-item-lead {
|
|
366
|
-
font-size: 0.6875rem;
|
|
367
|
-
font-weight: 600;
|
|
473
|
+
font-size: var(--bgl-list-item-lead-size, 0.6875rem);
|
|
474
|
+
font-weight: var(--bgl-list-item-lead-weight, 600);
|
|
368
475
|
text-transform: uppercase;
|
|
369
476
|
letter-spacing: 0.04em;
|
|
370
477
|
opacity: 0.5;
|
|
371
478
|
line-height: 1.3;
|
|
372
479
|
}
|
|
373
480
|
.list-item-title {
|
|
374
|
-
font-size: 0.9375rem;
|
|
375
|
-
font-weight: 600;
|
|
481
|
+
font-size: var(--bgl-list-item-title-size, 0.9375rem);
|
|
482
|
+
font-weight: var(--bgl-list-item-title-weight, 600);
|
|
376
483
|
line-height: 1.35;
|
|
377
484
|
}
|
|
378
485
|
.list-item-subtitle {
|
|
379
|
-
font-size: 0.8125rem;
|
|
486
|
+
font-size: var(--bgl-list-item-subtitle-size, 0.8125rem);
|
|
380
487
|
opacity: 0.6;
|
|
381
488
|
line-height: 1.35;
|
|
382
|
-
font-weight: 300;
|
|
489
|
+
font-weight: var(--bgl-list-item-subtitle-weight, 300);
|
|
383
490
|
margin-top: 1px;
|
|
384
491
|
}
|
|
385
492
|
.list-item-endtext {
|
|
@@ -395,29 +502,27 @@ min-width: 0;
|
|
|
395
502
|
row's vertical padding + horizontal gutter. `md` matches the historical
|
|
396
503
|
defaults, so unsized rows are unchanged. `size` composes with `thin` (which
|
|
397
504
|
only trims vertical padding). */
|
|
398
|
-
|
|
505
|
+
/* Each size sets the public type vars (not font-size directly) so a per-row
|
|
506
|
+
fontSize/titleSize/… prop — which sets the same var inline — still wins over
|
|
507
|
+
the chosen `size`. The icon-chip box size stays a direct width/height here;
|
|
508
|
+
its border-radius keeps its per-size tuning. */
|
|
509
|
+
.list-item-xs { --list-item-padding-inline: 0.4rem; --bgl-list-item-title-size: 0.75rem; --bgl-list-item-subtitle-size: 0.625rem; }
|
|
399
510
|
/* !important needed to beat the base .py-075/.py-05 utility classes. */
|
|
400
511
|
.list-item-xs .list-item { padding-block: 0.1rem !important; gap: 0.4rem; }
|
|
401
|
-
.list-item-xs .list-item-icon { width: 22px; height: 22px; border-radius: 6px; }
|
|
402
|
-
.list-item-xs .list-item-title { font-size: 0.75rem; }
|
|
403
|
-
.list-item-xs .list-item-subtitle { font-size: 0.625rem; }
|
|
512
|
+
.list-item-xs .list-item-icon { width: var(--bgl-list-item-icon-chip-size, 22px); height: var(--bgl-list-item-icon-chip-size, 22px); border-radius: 6px; }
|
|
404
513
|
|
|
405
|
-
.list-item-sm { --list-item-padding-inline: 0.55rem; }
|
|
514
|
+
.list-item-sm { --list-item-padding-inline: 0.55rem; --bgl-list-item-title-size: 0.8125rem; --bgl-list-item-subtitle-size: 0.6875rem; }
|
|
406
515
|
.list-item-sm .list-item { padding-block: 0.2rem !important; gap: 0.5rem; }
|
|
407
|
-
.list-item-sm .list-item-icon { width: 26px; height: 26px; border-radius: 7px; }
|
|
408
|
-
.list-item-sm .list-item-title { font-size: 0.8125rem; }
|
|
409
|
-
.list-item-sm .list-item-subtitle { font-size: 0.6875rem; }
|
|
516
|
+
.list-item-sm .list-item-icon { width: var(--bgl-list-item-icon-chip-size, 26px); height: var(--bgl-list-item-icon-chip-size, 26px); border-radius: 7px; }
|
|
410
517
|
|
|
411
518
|
/* md = defaults (no overrides needed). */
|
|
412
519
|
|
|
520
|
+
.list-item-lg { --bgl-list-item-title-size: 1.0625rem; --bgl-list-item-subtitle-size: 0.875rem; }
|
|
413
521
|
.list-item-lg .list-item { padding-block: 0.85rem !important; gap: 0.85rem; }
|
|
414
|
-
.list-item-lg .list-item-icon { width: 42px; height: 42px; border-radius: 11px; }
|
|
415
|
-
.list-item-lg .list-item-title { font-size: 1.0625rem; }
|
|
416
|
-
.list-item-lg .list-item-subtitle { font-size: 0.875rem; }
|
|
522
|
+
.list-item-lg .list-item-icon { width: var(--bgl-list-item-icon-chip-size, 42px); height: var(--bgl-list-item-icon-chip-size, 42px); border-radius: 11px; }
|
|
417
523
|
|
|
524
|
+
.list-item-xl { --bgl-list-item-title-size: 1.1875rem; --bgl-list-item-subtitle-size: 0.9375rem; }
|
|
418
525
|
.list-item-xl .list-item { padding-block: 1.1rem !important; gap: 1rem; }
|
|
419
|
-
.list-item-xl .list-item-icon { width: 50px; height: 50px; border-radius: 13px; }
|
|
420
|
-
.list-item-xl .list-item-title { font-size: 1.1875rem; }
|
|
421
|
-
.list-item-xl .list-item-subtitle { font-size: 0.9375rem; }
|
|
526
|
+
.list-item-xl .list-item-icon { width: var(--bgl-list-item-icon-chip-size, 50px); height: var(--bgl-list-item-icon-chip-size, 50px); border-radius: 13px; }
|
|
422
527
|
|
|
423
528
|
</style>
|
|
@@ -325,7 +325,8 @@ flex-grow: 1;
|
|
|
325
325
|
the row and it wraps), rather than the header force-stacking every left side. */
|
|
326
326
|
.endNavTools {
|
|
327
327
|
margin-inline-start: auto;
|
|
328
|
-
justify-content: flex-end;
|
|
328
|
+
/* justify-content: flex-end; */
|
|
329
|
+
width: auto;
|
|
329
330
|
}
|
|
330
331
|
/* Mobile: don't push the trailing side to the far edge — let it sit right after the
|
|
331
332
|
leading side (no auto margin, start-aligned) so the header reads as one compact
|
|
@@ -333,7 +334,7 @@ justify-content: flex-end;
|
|
|
333
334
|
@media screen and (max-width: 910px) {
|
|
334
335
|
.endNavTools {
|
|
335
336
|
margin-inline-start: 0;
|
|
336
|
-
justify-content: flex-start;
|
|
337
|
+
/* justify-content: flex-start; */
|
|
337
338
|
}
|
|
338
339
|
}
|
|
339
340
|
|
|
@@ -444,7 +445,7 @@ padding-top: 0;
|
|
|
444
445
|
.pageContent--fill {
|
|
445
446
|
display: flex;
|
|
446
447
|
flex-direction: column;
|
|
447
|
-
overflow: hidden;
|
|
448
|
+
/* overflow: hidden; */
|
|
448
449
|
}
|
|
449
450
|
.pageContent--fill > * {
|
|
450
451
|
flex: 1 1 auto;
|