@bagelink/vue 1.15.59 → 1.15.63
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/Avatar.vue.d.ts +5 -1
- package/dist/components/Avatar.vue.d.ts.map +1 -1
- package/dist/components/Badge.vue.d.ts +6 -1
- package/dist/components/Badge.vue.d.ts.map +1 -1
- package/dist/components/Dropdown.vue.d.ts.map +1 -1
- package/dist/components/ListItem.vue.d.ts +12 -0
- package/dist/components/ListItem.vue.d.ts.map +1 -1
- package/dist/components/Progress.vue.d.ts +38 -0
- package/dist/components/Progress.vue.d.ts.map +1 -0
- package/dist/components/Swiper.vue.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/layout/AppSidebar.vue.d.ts +1 -0
- package/dist/components/layout/AppSidebar.vue.d.ts.map +1 -1
- package/dist/components/layout/Divider.vue.d.ts +31 -0
- package/dist/components/layout/Divider.vue.d.ts.map +1 -0
- package/dist/components/layout/Layout.vue.d.ts.map +1 -1
- package/dist/components/layout/SidebarNavItem.vue.d.ts +20 -0
- package/dist/components/layout/SidebarNavItem.vue.d.ts.map +1 -0
- package/dist/components/layout/index.d.ts +1 -0
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/directives/index.d.ts +2 -0
- package/dist/directives/index.d.ts.map +1 -1
- package/dist/directives/reveal.d.ts +29 -0
- package/dist/directives/reveal.d.ts.map +1 -0
- package/dist/index.cjs +37 -37
- package/dist/index.mjs +8104 -7796
- package/dist/plugins/bagel.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Avatar.vue +20 -4
- package/src/components/Badge.vue +32 -2
- package/src/components/Dropdown.vue +7 -1
- package/src/components/ListItem.vue +151 -76
- package/src/components/Progress.vue +80 -0
- package/src/components/Swiper.vue +19 -1
- package/src/components/index.ts +1 -0
- package/src/components/layout/AppSidebar.vue +12 -15
- package/src/components/layout/Divider.vue +57 -0
- package/src/components/layout/Layout.vue +17 -4
- package/src/components/layout/SidebarNavItem.vue +227 -0
- package/src/components/layout/index.ts +1 -0
- package/src/directives/index.ts +2 -0
- package/src/directives/reveal.ts +78 -0
- package/src/plugins/bagel.ts +2 -1
- package/src/styles/appearance.css +11 -0
- package/src/styles/bagel.css +1 -0
- package/src/styles/dark.css +107 -2
- package/src/styles/layout.css +65 -13
- package/src/styles/motion.css +91 -0
- package/src/styles/text.css +38 -6
- package/src/utils/index.ts +1 -1
package/dist/utils/index.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export declare function normalizeDimension(value: string | number | undefined, d
|
|
|
44
44
|
export type { NormalizedOption } from './options';
|
|
45
45
|
export { getOptionIcon, getOptionLabel, getOptionValue, normalizeOption } from './options';
|
|
46
46
|
export type { ComparisonOperator, FilterCondition, LogicalOperator, QueryConditions, QueryFilter } from './queryFilter';
|
|
47
|
-
export { anyOf, parseQuery, queryFilter, range, search } from './queryFilter';
|
|
47
|
+
export { anyOf, buildQuery, evaluateQuery, parseQuery, queryFilter, range, search } from './queryFilter';
|
|
48
48
|
export type { ShowdownConverter, ShowdownOptions } from './showdown';
|
|
49
49
|
export declare function pathKeyToURL(pathKey?: string | null): string | undefined;
|
|
50
50
|
export declare function getNestedValue(obj: any, path?: string, defaultValue?: any): any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,23 +1,39 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
defineOptions({ name: 'BglAvatar' })
|
|
3
|
-
import type { IconType } from '@bagelink/vue'
|
|
3
|
+
import type { IconType, ThemeType } from '@bagelink/vue'
|
|
4
4
|
import { initials, Icon } from '@bagelink/vue'
|
|
5
|
+
import { computed } from 'vue'
|
|
5
6
|
import Image from './Image.vue'
|
|
6
7
|
|
|
7
|
-
withDefaults(defineProps<{
|
|
8
|
+
const props = withDefaults(defineProps<{
|
|
8
9
|
fallback?: string
|
|
9
10
|
src?: string
|
|
10
11
|
name?: string
|
|
11
12
|
icon?: IconType
|
|
12
13
|
alt?: string
|
|
13
14
|
size?: number
|
|
15
|
+
/** Rounded-square instead of a circle. `true` = themed radius, or pass a px radius. */
|
|
16
|
+
square?: boolean | number
|
|
17
|
+
/** Theme color → tinted background + matching icon/text color (e.g. an icon chip). */
|
|
18
|
+
color?: ThemeType
|
|
14
19
|
}>(), { size: 50 })
|
|
20
|
+
|
|
21
|
+
const radius = computed(() => {
|
|
22
|
+
if (!props.square) { return '1000px' } // circle (default)
|
|
23
|
+
if (props.square === true) { return 'var(--bgl-btn-border-radius)' }
|
|
24
|
+
return `${props.square}px`
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// When a theme color is given, tint the background and color the icon/initials.
|
|
28
|
+
const themed = computed(() => props.color
|
|
29
|
+
? { background: `var(--bgl-${props.color}-tint, color-mix(in srgb, var(--bgl-${props.color}) 14%, transparent))`, color: `var(--bgl-${props.color})`, border: 'none' }
|
|
30
|
+
: {})
|
|
15
31
|
</script>
|
|
16
32
|
|
|
17
33
|
<template>
|
|
18
34
|
<div
|
|
19
|
-
class="
|
|
20
|
-
:style="{ width: `${size}px`, height: `${size}px
|
|
35
|
+
class="overflow-hidden txt-center p-0 avatar flex justify-content-center align-items-center"
|
|
36
|
+
:style="{ width: `${size}px`, height: `${size}px`, borderRadius: radius, ...themed }"
|
|
21
37
|
>
|
|
22
38
|
<Image v-if="src" :src="src" :alt="alt || name" />
|
|
23
39
|
<Icon v-else-if="icon" :icon="icon" :size="size / 40" />
|
package/src/components/Badge.vue
CHANGED
|
@@ -17,10 +17,15 @@ const props = defineProps<{
|
|
|
17
17
|
icon?: IconType
|
|
18
18
|
iconEnd?: IconType
|
|
19
19
|
color?: ThemeType
|
|
20
|
-
variant?: 'solid' | 'flat' | 'outline'
|
|
20
|
+
variant?: 'solid' | 'flat' | 'outline' | 'glass'
|
|
21
21
|
/** Boolean variant shorthands: <Badge flat /> — same as variant="flat" */
|
|
22
22
|
flat?: boolean
|
|
23
23
|
outline?: boolean
|
|
24
|
+
/** Translucent frosted badge — readable on photos / gradients / dark heroes.
|
|
25
|
+
Shorthand for variant="glass". */
|
|
26
|
+
glass?: boolean
|
|
27
|
+
/** Leading status dot in the theme color (e.g. ● Live, ● Active). */
|
|
28
|
+
dot?: boolean
|
|
24
29
|
/** @deprecated Use `outline` */
|
|
25
30
|
border?: boolean
|
|
26
31
|
loading?: boolean
|
|
@@ -50,6 +55,12 @@ const computedPairClass = computed(() => {
|
|
|
50
55
|
return `pair-${theme}`
|
|
51
56
|
})
|
|
52
57
|
|
|
58
|
+
// Dot uses the badge's theme color (strip any -light/-tint suffix for a solid dot).
|
|
59
|
+
const dotColor = computed(() => {
|
|
60
|
+
const base = (computedTheme.value || 'primary').replace(/-(light|tint|10|20|30|40|50|60|70)$/, '')
|
|
61
|
+
return `var(--bgl-${base})`
|
|
62
|
+
})
|
|
63
|
+
|
|
53
64
|
const computedSize = computed(() => {
|
|
54
65
|
if (props.size) { return props.size }
|
|
55
66
|
if (props.sm) { return 'sm' }
|
|
@@ -59,6 +70,7 @@ const computedSize = computed(() => {
|
|
|
59
70
|
|
|
60
71
|
const computedVariant = computed(() => {
|
|
61
72
|
if (props.variant) { return props.variant }
|
|
73
|
+
if (props.glass) { return 'glass' }
|
|
62
74
|
if (props.flat) { return 'flat' }
|
|
63
75
|
if (props.outline || props.border) { return 'outline' }
|
|
64
76
|
return 'solid'
|
|
@@ -70,6 +82,7 @@ const computedClasses = computed(() => {
|
|
|
70
82
|
'round': props.round,
|
|
71
83
|
'bgl_flatPill': computedVariant.value === 'flat',
|
|
72
84
|
'bgl_pill-border': computedVariant.value === 'outline',
|
|
85
|
+
'bgl_glassPill': computedVariant.value === 'glass',
|
|
73
86
|
'pillLarge': computedSize.value === 'lg',
|
|
74
87
|
'pillSmall': computedSize.value === 'sm',
|
|
75
88
|
}
|
|
@@ -90,8 +103,9 @@ const computedClasses = computed(() => {
|
|
|
90
103
|
>
|
|
91
104
|
<div class="flex h-100 justify-content-center relative ">
|
|
92
105
|
<div v-if="loading" class="loading absolute inset-0 mx-auto" />
|
|
93
|
-
<div class="px-025 flex gap-025 justify-content-center" :class="{ 'opacity-0': loading }">
|
|
106
|
+
<div class="px-025 flex gap-025 justify-content-center align-items-center" :class="{ 'opacity-0': loading }">
|
|
94
107
|
<Btn v-if="btn" class="bgl_pill-btn -ms-025" icon-size="0.8" round v-bind="btn" />
|
|
108
|
+
<span v-if="dot" class="bgl_pill-dot" :style="{ background: dotColor }" />
|
|
95
109
|
<Icon v-if="icon" class="line-height-0" :icon="icon" style="font-size: var(--bgl-pill-font-size)" />
|
|
96
110
|
<slot :class="{ uppercase }" />
|
|
97
111
|
<template v-if="!slots.default">
|
|
@@ -119,6 +133,12 @@ const computedClasses = computed(() => {
|
|
|
119
133
|
.pillText{
|
|
120
134
|
font-size: var(--bgl-pill-font-size);
|
|
121
135
|
}
|
|
136
|
+
.bgl_pill-dot{
|
|
137
|
+
width: 6px;
|
|
138
|
+
height: 6px;
|
|
139
|
+
border-radius: 50%;
|
|
140
|
+
flex-shrink: 0;
|
|
141
|
+
}
|
|
122
142
|
.bgl_pill-btn{
|
|
123
143
|
color: var(--bgl-pill-btn-color);
|
|
124
144
|
background: var(--bgl-pill-btn-bg);
|
|
@@ -166,4 +186,14 @@ vertical-align: middle;
|
|
|
166
186
|
border-radius: 1000px;
|
|
167
187
|
}
|
|
168
188
|
|
|
189
|
+
/* Glass: frosted translucent badge for photos / gradients / dark heroes.
|
|
190
|
+
Defaults to light-on-dark; flip via --bgl-glass-bg / --bgl-glass-color. */
|
|
191
|
+
.bgl_glassPill {
|
|
192
|
+
background-color: var(--bgl-glass-bg, rgba(255, 255, 255, 0.18)) !important;
|
|
193
|
+
color: var(--bgl-glass-color, #fff) !important;
|
|
194
|
+
border: 1px solid var(--bgl-glass-border, rgba(255, 255, 255, 0.28));
|
|
195
|
+
backdrop-filter: blur(8px);
|
|
196
|
+
-webkit-backdrop-filter: blur(8px);
|
|
197
|
+
}
|
|
198
|
+
|
|
169
199
|
</style>
|
|
@@ -403,7 +403,7 @@ defineExpose({ show, hide, shown })
|
|
|
403
403
|
@focus="onPopoverMouseenter" @blur="onPopoverMouseleave" @keydown="onPopoverKeydown"
|
|
404
404
|
>
|
|
405
405
|
<div class="bgl-dropdown__backdrop" />
|
|
406
|
-
<div class="bgl-dropdown__content overflow-hidden" :class="{ 'display-flex column': props.card }"
|
|
406
|
+
<div class="bgl-dropdown__content overflow-hidden" :class="{ 'display-flex column bgl-dropdown__content--card': props.card }"
|
|
407
407
|
style="border-radius: var(--bgl-card-border-radius);">
|
|
408
408
|
<slot :hide :show :shown />
|
|
409
409
|
</div>
|
|
@@ -482,6 +482,12 @@ animation: bgl-dropdown-enter 0.18s ease 0.04s both;
|
|
|
482
482
|
transform-origin: top left;
|
|
483
483
|
}
|
|
484
484
|
|
|
485
|
+
/* Default menu breathing room so consumers don't wrap content in py-* just to
|
|
486
|
+
stop items touching the rounded edges. */
|
|
487
|
+
.bgl-dropdown__content--card .bgl_card{
|
|
488
|
+
padding-block: 0.375rem;
|
|
489
|
+
}
|
|
490
|
+
|
|
485
491
|
</style>
|
|
486
492
|
<!-- prettier-ignore-end -->
|
|
487
493
|
<!-- eslint-enable -->
|
|
@@ -22,25 +22,36 @@ const props = withDefaults(
|
|
|
22
22
|
fullWidth?: boolean
|
|
23
23
|
ellipsis?: boolean
|
|
24
24
|
ripple?: boolean
|
|
25
|
+
/** Make the whole row one hover/click target: the clickable button stretches
|
|
26
|
+
to the trailing edge and the #end meta floats over it (still clickable).
|
|
27
|
+
Great for simple rows with light trailing meta. Opt-in — the classic
|
|
28
|
+
layout (only the text area clickable) remains the default so rows with
|
|
29
|
+
wide trailing content aren't affected. Tune reserved room with the CSS
|
|
30
|
+
var --bgl-list-item-end-space. */
|
|
31
|
+
fullRow?: boolean
|
|
32
|
+
/** Render as an interactive row (cursor + hover) without needing a handler.
|
|
33
|
+
Implied when `to`, `href`, or `onClick` is set. */
|
|
34
|
+
clickable?: boolean
|
|
25
35
|
onClick?: () => void
|
|
26
36
|
}>(),
|
|
27
37
|
{
|
|
28
38
|
ellipsis: true,
|
|
29
|
-
ripple:
|
|
39
|
+
ripple: false,
|
|
40
|
+
fullRow: false,
|
|
30
41
|
}
|
|
31
42
|
)
|
|
32
43
|
|
|
44
|
+
const hasTo = computed(() => props.to !== undefined && props.to !== '')
|
|
45
|
+
const hasHref = computed(() => props.href !== undefined && props.href !== '')
|
|
46
|
+
const isClickable = computed(() => hasTo.value || hasHref.value || props.onClick !== undefined || props.clickable === true)
|
|
47
|
+
|
|
33
48
|
const isComponent = computed(() => {
|
|
34
|
-
if (
|
|
35
|
-
if (
|
|
36
|
-
if (
|
|
49
|
+
if (hasTo.value) { return 'router-link' }
|
|
50
|
+
if (hasHref.value) { return 'a' }
|
|
51
|
+
if (isClickable.value) { return 'button' }
|
|
37
52
|
return 'div'
|
|
38
53
|
})
|
|
39
54
|
|
|
40
|
-
const isClickable = computed(() => {
|
|
41
|
-
return (props.to !== undefined && props.to !== '') || (props.href !== undefined && props.href !== '') || (props.onClick !== undefined)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
55
|
const bind = computed(() => {
|
|
45
56
|
const obj: { [key: string]: any } = {}
|
|
46
57
|
if (props.to !== undefined && props.to !== '') { obj.to = props.to }
|
|
@@ -48,7 +59,7 @@ const bind = computed(() => {
|
|
|
48
59
|
if (props.target !== undefined && props.target !== undefined && ((props.to !== undefined && props.to !== '') || (props.href !== undefined && props.href !== ''))) { obj.target = props.target }
|
|
49
60
|
|
|
50
61
|
obj.class = {
|
|
51
|
-
'notClickable': !
|
|
62
|
+
'notClickable': !isClickable.value,
|
|
52
63
|
'no-border-list': props.flat,
|
|
53
64
|
}
|
|
54
65
|
if (props.disabled) { obj.disabled = true }
|
|
@@ -57,126 +68,190 @@ const bind = computed(() => {
|
|
|
57
68
|
</script>
|
|
58
69
|
|
|
59
70
|
<template>
|
|
60
|
-
<div
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
<div
|
|
72
|
+
class="flex space-between list-item-row"
|
|
73
|
+
:class="{ 'no-border-list': props.flat, 'list-item-flush': props.fullWidth, 'list-item-fullrow': fullRow && isClickable }"
|
|
74
|
+
>
|
|
75
|
+
<!-- Content rendered before the clickable area (e.g. a drag handle, avatar
|
|
76
|
+
or leading visual). Lives outside the clickable component so interacting
|
|
77
|
+
with it never triggers navigation/selection. -->
|
|
78
|
+
<div v-if="$slots.start" class="list-item-start flex align-items-center flex-shrink-0">
|
|
79
|
+
<slot name="start" />
|
|
80
|
+
</div>
|
|
65
81
|
<component
|
|
66
82
|
:is="isComponent" v-bind="bind" v-ripple="ripple && isClickable"
|
|
67
|
-
class="flex flex-grow-1 gap-
|
|
68
|
-
'py-
|
|
83
|
+
class="flex flex-grow-1 gap-075 align-items-center list-item" :class="{
|
|
84
|
+
'py-075': !props.thin,
|
|
69
85
|
'py-05': props.thin,
|
|
70
86
|
'px-1': !props.fullWidth,
|
|
71
87
|
'px-0': props.fullWidth,
|
|
72
|
-
}" @click="onClick"
|
|
88
|
+
}" @click="typeof onClick === 'function' && onClick()"
|
|
73
89
|
>
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
<!-- Leading visual INSIDE the clickable area. Use #media for custom art
|
|
91
|
+
(covers, thumbnails); `src`/`showAvatar` and `icon` are shortcuts. -->
|
|
92
|
+
<slot name="media">
|
|
93
|
+
<Avatar v-if="src || showAvatar" :name="title" :src="src" :size="thin ? 30 : 38" class="flex-shrink-0" />
|
|
94
|
+
<span v-if="icon" class="list-item-icon flex-shrink-0">
|
|
95
|
+
<Icon size="1.2" :icon="icon" />
|
|
96
|
+
</span>
|
|
97
|
+
</slot>
|
|
76
98
|
|
|
77
|
-
<div class="txt-start">
|
|
78
|
-
<p v-if="lead" class="
|
|
99
|
+
<div class="txt-start flex-grow-1 list-item-body">
|
|
100
|
+
<p v-if="lead" class="list-item-lead" :class="{ ellipsis }">
|
|
79
101
|
{{ lead }}
|
|
80
102
|
<slot name="lead" />
|
|
81
103
|
</p>
|
|
82
|
-
<p class="
|
|
104
|
+
<p class="list-item-title" :class="{ 'ellipsis-1': ellipsis }">
|
|
83
105
|
{{ title }}
|
|
84
106
|
<slot />
|
|
85
107
|
</p>
|
|
86
|
-
<p
|
|
87
|
-
v-if="subtitle" class="txt12 m-0 m-0 py-0 ps-0 pe-1-5 opacity-7 me-2"
|
|
88
|
-
:class="{ 'ellipsis-1': ellipsis }"
|
|
89
|
-
>
|
|
108
|
+
<p v-if="subtitle || $slots.subtitle" class="list-item-subtitle" :class="{ 'ellipsis-1': ellipsis }">
|
|
90
109
|
{{ subtitle }}
|
|
91
110
|
<slot name="subtitle" />
|
|
92
111
|
</p>
|
|
93
112
|
</div>
|
|
94
|
-
<div class="flex-grow-1" />
|
|
95
113
|
</component>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
114
|
+
<!-- Trailing meta. With fullRow, it overlaps the clickable button via a
|
|
115
|
+
negative margin so the button spans the whole row underneath it; the
|
|
116
|
+
end content itself stays on top and independently clickable. -->
|
|
117
|
+
<div class="list-item-end flex align-items-center gap-05 flex-shrink-0">
|
|
118
|
+
<slot name="end">
|
|
119
|
+
<span v-if="end" class="list-item-endtext" :class="{ 'ellipsis-1': ellipsis }" v-text="end" />
|
|
120
|
+
<Icon v-if="iconEnd" :icon="iconEnd" class="transition-400 opacity-4" />
|
|
121
|
+
</slot>
|
|
122
|
+
</div>
|
|
103
123
|
</div>
|
|
104
124
|
</template>
|
|
105
125
|
|
|
106
126
|
<style>
|
|
107
127
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
128
|
+
/* The row wraps the clickable area + start/end slots and owns the divider.
|
|
129
|
+
Center start/end slots against the (possibly taller) text block by default —
|
|
130
|
+
the common case for lists with a leading icon/handle and trailing meta. */
|
|
131
|
+
.list-item-row {
|
|
132
|
+
position: relative;
|
|
133
|
+
align-items: center;
|
|
111
134
|
gap: 0.5rem;
|
|
112
|
-
border: none;
|
|
113
|
-
background-color: unset;
|
|
114
|
-
width: 100%;
|
|
115
|
-
|
|
116
135
|
}
|
|
117
136
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
137
|
+
/* Full-row click target: the clickable button stretches to the row's trailing
|
|
138
|
+
edge so hover/active read across the whole item. The trailing meta is lifted
|
|
139
|
+
out of flow and floated over the button's end — staying visible and
|
|
140
|
+
independently clickable. The button reserves matching room so text never sits
|
|
141
|
+
under the meta. Tune the reserved width with --bgl-list-item-end-space. */
|
|
142
|
+
.list-item-fullrow {
|
|
143
|
+
--bgl-list-item-end-space: 3rem;
|
|
121
144
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
color: var(--bgl-text-color);
|
|
131
|
-
text-decoration: none;
|
|
132
|
-
position: relative;
|
|
145
|
+
.list-item-fullrow .list-item-end {
|
|
146
|
+
position: absolute;
|
|
147
|
+
inset-inline-end: 0.5rem;
|
|
148
|
+
top: 50%;
|
|
149
|
+
transform: translateY(-50%);
|
|
150
|
+
z-index: 1;
|
|
151
|
+
/* non-interactive meta lets clicks fall through to the row button… */
|
|
152
|
+
pointer-events: none;
|
|
133
153
|
}
|
|
134
|
-
|
|
135
|
-
.list-item
|
|
136
|
-
|
|
154
|
+
/* …interactive trailing controls stay clickable on top of the row button. */
|
|
155
|
+
.list-item-fullrow .list-item-end :where(button, a, input, select, label, [role="button"], [tabindex]) {
|
|
156
|
+
pointer-events: auto;
|
|
137
157
|
}
|
|
138
|
-
|
|
139
|
-
.list-item
|
|
158
|
+
.list-item-fullrow .list-item:not(.px-0) { padding-inline-end: var(--bgl-list-item-end-space); }
|
|
159
|
+
.list-item-fullrow.list-item-flush .list-item-end { inset-inline-end: 0; }
|
|
160
|
+
.list-item-row::after {
|
|
140
161
|
content: '';
|
|
141
162
|
position: absolute;
|
|
142
|
-
|
|
143
|
-
right: 0;
|
|
163
|
+
inset-inline: 0;
|
|
144
164
|
bottom: 0;
|
|
145
165
|
border-bottom: 1px solid var(--bgl-border-color);
|
|
146
166
|
}
|
|
147
|
-
|
|
148
|
-
.list-item
|
|
149
|
-
content: '';
|
|
150
|
-
position: absolute;
|
|
151
|
-
left: 0;
|
|
152
|
-
right: 0;
|
|
153
|
-
bottom: 0;
|
|
167
|
+
.list-item-row:last-child::after,
|
|
168
|
+
.list-item-row.no-border-list::after {
|
|
154
169
|
border-bottom: none;
|
|
155
170
|
}
|
|
156
171
|
|
|
172
|
+
button.list-item {
|
|
173
|
+
border: none;
|
|
174
|
+
background-color: unset;
|
|
175
|
+
width: 100%;
|
|
176
|
+
font: inherit;
|
|
177
|
+
text-align: inherit;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.list-item {
|
|
181
|
+
min-height: fit-content;
|
|
182
|
+
cursor: pointer;
|
|
183
|
+
transition: background-color 0.15s ease;
|
|
184
|
+
/* Inherit color so the component adapts to ANY surface (light, dark, a
|
|
185
|
+
hard-coded black panel) without per-consumer overrides. On a normal
|
|
186
|
+
Bagelink surface `currentColor` resolves to --bgl-text-color. */
|
|
187
|
+
color: inherit;
|
|
188
|
+
text-decoration: none;
|
|
189
|
+
border-radius: var(--bgl-btn-border-radius);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.list-item:disabled {
|
|
193
|
+
opacity: 0.5;
|
|
194
|
+
pointer-events: none;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* Hover/active use Bagelink's translucent gray tint, which already flips from
|
|
198
|
+
translucent-dark (light mode) to translucent-light (.bgl-dark-mode) — so it
|
|
199
|
+
reads correctly on any background. Override per-list with --bgl-list-item-hover. */
|
|
157
200
|
.list-item:hover,
|
|
158
201
|
.list-item.router-link-exact-active {
|
|
159
|
-
background-color: var(--bgl-
|
|
202
|
+
background-color: var(--bgl-list-item-hover, var(--bgl-gray-tint));
|
|
203
|
+
}
|
|
204
|
+
.list-item.router-link-exact-active {
|
|
205
|
+
background-color: var(--bgl-list-item-active, var(--bgl-primary-tint));
|
|
160
206
|
}
|
|
161
207
|
|
|
208
|
+
.notClickable,
|
|
162
209
|
.notClickable:hover {
|
|
163
210
|
background-color: unset;
|
|
164
211
|
cursor: default;
|
|
165
212
|
}
|
|
166
213
|
|
|
167
214
|
.list-item:active {
|
|
168
|
-
-webkit-filter: var(--bgl-hover-filter);
|
|
169
215
|
filter: var(--bgl-hover-filter);
|
|
170
216
|
}
|
|
171
217
|
|
|
172
|
-
|
|
173
|
-
|
|
218
|
+
/* Leading icon chip */
|
|
219
|
+
.list-item-icon {
|
|
220
|
+
display: grid;
|
|
221
|
+
place-items: center;
|
|
222
|
+
width: 34px;
|
|
223
|
+
height: 34px;
|
|
224
|
+
border-radius: 9px;
|
|
225
|
+
background: color-mix(in srgb, var(--bgl-primary) 10%, transparent);
|
|
226
|
+
color: var(--bgl-primary);
|
|
174
227
|
}
|
|
175
228
|
|
|
176
|
-
|
|
177
|
-
.list-item {
|
|
178
|
-
|
|
229
|
+
/* Text block: tight, clear hierarchy */
|
|
230
|
+
.list-item-body > p { margin: 0; padding: 0; }
|
|
231
|
+
.list-item-lead {
|
|
232
|
+
font-size: 0.6875rem;
|
|
233
|
+
font-weight: 600;
|
|
234
|
+
text-transform: uppercase;
|
|
235
|
+
letter-spacing: 0.04em;
|
|
236
|
+
opacity: 0.5;
|
|
237
|
+
line-height: 1.3;
|
|
238
|
+
}
|
|
239
|
+
.list-item-title {
|
|
240
|
+
font-size: 0.9375rem;
|
|
241
|
+
font-weight: 500;
|
|
242
|
+
line-height: 1.35;
|
|
243
|
+
}
|
|
244
|
+
.list-item-subtitle {
|
|
245
|
+
font-size: 0.8125rem;
|
|
246
|
+
opacity: 0.6;
|
|
247
|
+
line-height: 1.35;
|
|
248
|
+
margin-top: 1px;
|
|
179
249
|
}
|
|
250
|
+
.list-item-endtext {
|
|
251
|
+
font-size: 0.8125rem;
|
|
252
|
+
opacity: 0.6;
|
|
253
|
+
white-space: nowrap;
|
|
180
254
|
}
|
|
255
|
+
.list-item-end:empty { display: none; }
|
|
181
256
|
|
|
182
257
|
</style>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* <Progress :value="68" /> // linear bar
|
|
4
|
+
* <Progress :value="68" color="green" label /> // with % label
|
|
5
|
+
* <Progress :value="90" ring :size="86" color="pink">{{ v }}%</Progress> // ring/donut
|
|
6
|
+
*
|
|
7
|
+
* Covers both the dashboard "track + fill" bar and the conic-gradient ring/donut
|
|
8
|
+
* that views previously hand-rolled. Animates fill on value change; the ring
|
|
9
|
+
* center is a free-form slot.
|
|
10
|
+
*/
|
|
11
|
+
defineOptions({ name: 'BglProgress' })
|
|
12
|
+
import type { ThemeType } from '@bagelink/vue'
|
|
13
|
+
import { computed } from 'vue'
|
|
14
|
+
|
|
15
|
+
const props = withDefaults(defineProps<{
|
|
16
|
+
/** 0–100. */
|
|
17
|
+
value?: number
|
|
18
|
+
color?: ThemeType
|
|
19
|
+
/** Render as a circular ring/donut instead of a bar. */
|
|
20
|
+
ring?: boolean
|
|
21
|
+
/** Bar thickness (px) or ring diameter (px). */
|
|
22
|
+
size?: number
|
|
23
|
+
/** Ring stroke width (px). Ignored for bars. */
|
|
24
|
+
thickness?: number
|
|
25
|
+
/** Show a trailing % label (bar only, when no default slot). */
|
|
26
|
+
label?: boolean
|
|
27
|
+
}>(), { value: 0, color: 'primary', size: undefined, thickness: 9 })
|
|
28
|
+
|
|
29
|
+
const pct = computed(() => Math.max(0, Math.min(100, props.value)))
|
|
30
|
+
const accent = computed(() => `var(--bgl-${props.color})`)
|
|
31
|
+
const ringSize = computed(() => props.size ?? 86)
|
|
32
|
+
const barHeight = computed(() => props.size ?? 8)
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<template>
|
|
36
|
+
<!-- RING / DONUT -->
|
|
37
|
+
<div
|
|
38
|
+
v-if="ring"
|
|
39
|
+
class="bgl-progress-ring grid place-items-center"
|
|
40
|
+
:style="{
|
|
41
|
+
width: `${ringSize}px`,
|
|
42
|
+
height: `${ringSize}px`,
|
|
43
|
+
'--bgl-progress-pct': `${pct}`,
|
|
44
|
+
background: `conic-gradient(${accent} calc(var(--bgl-progress-pct) * 1%), var(--bgl-progress-track, var(--bgl-border-color)) 0)`,
|
|
45
|
+
}"
|
|
46
|
+
>
|
|
47
|
+
<div
|
|
48
|
+
class="bgl-progress-ring-hole grid place-items-center txt-center"
|
|
49
|
+
:style="{ width: `calc(100% - ${thickness * 2}px)`, height: `calc(100% - ${thickness * 2}px)` }"
|
|
50
|
+
>
|
|
51
|
+
<slot />
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<!-- LINEAR BAR -->
|
|
56
|
+
<div v-else class="flex gap-075 align-items-center">
|
|
57
|
+
<div class="bgl-progress-track flex-grow" :style="{ height: `${barHeight}px` }">
|
|
58
|
+
<div class="bgl-progress-fill" :style="{ width: `${pct}%`, background: accent }" />
|
|
59
|
+
</div>
|
|
60
|
+
<span v-if="label && !$slots.default" class="txt12 opacity-6 bgl-progress-label">{{ Math.round(pct) }}%</span>
|
|
61
|
+
<slot />
|
|
62
|
+
</div>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<style scoped>
|
|
66
|
+
.bgl-progress-ring { border-radius: 50%; }
|
|
67
|
+
.bgl-progress-ring-hole { border-radius: 50%; background: var(--bgl-box-bg); }
|
|
68
|
+
|
|
69
|
+
.bgl-progress-track {
|
|
70
|
+
border-radius: 100px;
|
|
71
|
+
background: var(--bgl-progress-track, var(--bgl-border-color));
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
}
|
|
74
|
+
.bgl-progress-fill {
|
|
75
|
+
height: 100%;
|
|
76
|
+
border-radius: 100px;
|
|
77
|
+
transition: width 0.5s cubic-bezier(0.16, 1, 0.3, 1);
|
|
78
|
+
}
|
|
79
|
+
.bgl-progress-label { font-variant-numeric: tabular-nums; min-width: 2.5em; text-align: end; }
|
|
80
|
+
</style>
|
|
@@ -464,6 +464,24 @@ width: 100%;
|
|
|
464
464
|
--swiper-pagination-color: white;
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
+
/* Pagination: keep Swiper's own horizontal centering (left:50% + translateX),
|
|
468
|
+
just give the wrapper a sane bottom offset and consistent bullet sizing so
|
|
469
|
+
consumers don't need :deep() overrides to fix position. Override the bullet
|
|
470
|
+
look with --swiper-pagination-* vars. */
|
|
471
|
+
.swi-wrap .swiper-pagination-bullets {
|
|
472
|
+
bottom: 8px;
|
|
473
|
+
}
|
|
474
|
+
.swi-wrap .swiper-pagination-bullet {
|
|
475
|
+
width: var(--swiper-pagination-bullet-width, 7px);
|
|
476
|
+
height: var(--swiper-pagination-bullet-height, 7px);
|
|
477
|
+
background: var(--swiper-pagination-bullet-inactive-color, #fff);
|
|
478
|
+
opacity: var(--swiper-pagination-bullet-inactive-opacity, 0.6);
|
|
479
|
+
}
|
|
480
|
+
.swi-wrap .swiper-pagination-bullet-active {
|
|
481
|
+
opacity: 1;
|
|
482
|
+
background: var(--swiper-pagination-color, #fff);
|
|
483
|
+
}
|
|
484
|
+
|
|
467
485
|
.swi-ctrl {
|
|
468
486
|
position: absolute;
|
|
469
487
|
top: 50%;
|
|
@@ -492,7 +510,7 @@ position: relative;
|
|
|
492
510
|
|
|
493
511
|
.swi-prev,
|
|
494
512
|
.swi-next {
|
|
495
|
-
background: var(--
|
|
513
|
+
background: var(--bgl-primary);
|
|
496
514
|
height: 40px;
|
|
497
515
|
width: 40px;
|
|
498
516
|
border-radius: 100%;
|
package/src/components/index.ts
CHANGED
|
@@ -37,6 +37,7 @@ export { default as Menu } from './Menu.vue'
|
|
|
37
37
|
export { default as NavBar } from './NavBar.vue'
|
|
38
38
|
export { default as PageTitle } from './PageTitle.vue'
|
|
39
39
|
export { default as Pagination } from './Pagination.vue'
|
|
40
|
+
export { default as Progress } from './Progress.vue'
|
|
40
41
|
export { default as Rating } from './Rating.vue'
|
|
41
42
|
export { default as RouterWrapper } from './RouterWrapper.vue'
|
|
42
43
|
export { default as Spreadsheet } from './Spreadsheet/Index.vue'
|