@bluevolt-tech/lumen 1.3.2 → 1.5.0
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/bv-button/bv-button.js +2 -182
- package/dist/components/bv-course-detail-modal/bv-course-detail-modal.js +2 -182
- package/dist/components/bv-course-grid-card/bv-course-grid-card.d.ts +12 -0
- package/dist/components/bv-course-grid-card/bv-course-grid-card.js +87 -185
- package/dist/components/bv-course-list-card/bv-course-list-card.d.ts +11 -0
- package/dist/components/bv-course-list-card/bv-course-list-card.js +77 -185
- package/dist/components/bv-empty-state/bv-empty-state.d.ts +22 -1
- package/dist/components/bv-empty-state/bv-empty-state.js +410 -5
- package/dist/components/bv-empty-state/illustrations.d.ts +3 -0
- package/dist/components/bv-filter-panel/bv-filter-panel.d.ts +4 -0
- package/dist/components/bv-filter-panel/bv-filter-panel.js +30 -3
- package/dist/components/bv-portal-header/bv-portal-header.d.ts +1 -0
- package/dist/components/bv-portal-header/bv-portal-header.js +99 -195
- package/dist/components/bv-promo-banner/bv-promo-banner.d.ts +4 -0
- package/dist/components/bv-promo-banner/bv-promo-banner.js +16 -1
- package/dist/components/bv-user-row/bv-user-row.d.ts +6 -0
- package/dist/components/bv-user-row/bv-user-row.js +59 -193
- package/dist/storybook/stories/screens/course-catalog.data.js +1842 -153
- package/dist/themes/base.css +1 -1
- package/package.json +1 -1
- package/themes/base.css +1 -1
|
@@ -1,188 +1,8 @@
|
|
|
1
1
|
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-course-list-card/bv-course-list-card.css
|
|
2
|
-
var bv_course_list_card_default = ":host {\n display: block;\n}\n\n.card {\n display: flex;\n align-items: stretch;\n gap: var(--bv-spacing-md);\n padding: 12px;\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-xl);\n box-shadow: var(--bv-shadow-sm);\n cursor: pointer;\n transition:\n background var(--bv-transition-fast),\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n:host([selected]) .card {\n background: var(--bv-color-primary-50);\n border-color: var(--bv-color-primary);\n box-shadow: none;\n}\n\n/* Thumbnail */\n.thumbnail-wrap {\n position: relative;\n flex-shrink: 0;\n width: 200px;\n min-height: 123px;\n border-radius: var(--bv-radius-lg);\n overflow: hidden;\n background: var(--bv-color-neutral-200);\n}\n\n.thumbnail {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n\n.status-badge {\n position: absolute;\n top: 6px;\n right: 6px;\n padding: 0 var(--bv-spacing-sm);\n border-radius: var(--bv-radius-sm);\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-medium);\n line-height: 18px;\n background: var(--bv-color-success-light);\n color: var(--bv-color-success-dark);\n}\n\n/* Content */\n.content {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n justify-content: space-between;\n}\n\n.meta {\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n\n.title {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-md);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-900);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.publisher {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-500);\n}\n\n.publisher strong {\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-900);\n}\n\n.description-wrap {\n height: 40px;\n display: flex;\n align-items: center;\n overflow: hidden;\n}\n\n.description {\n margin: 0;\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n line-height: 20px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.info-row {\n display: flex;\n gap: var(--bv-spacing-md);\n}\n\n.info-item {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-900);\n}\n\n.info-item strong {\n font-weight: var(--bv-font-weight-bold);\n}\n\n/* Actions */\n.actions {\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-sm);\n flex-shrink: 0;\n width: 209px;\n justify-content: center;\n}\n";
|
|
2
|
+
var bv_course_list_card_default = ":host {\n display: block;\n}\n\n.card {\n display: flex;\n align-items: stretch;\n gap: var(--bv-spacing-md);\n padding: 12px;\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-xl);\n box-shadow: var(--bv-shadow-sm);\n cursor: pointer;\n transition:\n background var(--bv-transition-fast),\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n:host([selected]) .card {\n background: var(--bv-color-primary-50);\n border-color: var(--bv-color-primary);\n box-shadow: none;\n}\n\n/* Thumbnail */\n.thumbnail-wrap {\n position: relative;\n flex-shrink: 0;\n width: 200px;\n min-height: 123px;\n border-radius: var(--bv-radius-lg);\n overflow: hidden;\n background: var(--bv-color-neutral-200);\n}\n\n.thumbnail {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n\n.status-badge {\n position: absolute;\n top: 6px;\n right: 6px;\n padding: 0 var(--bv-spacing-sm);\n border-radius: var(--bv-radius-sm);\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-medium);\n line-height: 18px;\n background: var(--bv-color-success-light);\n color: var(--bv-color-success-dark);\n}\n\n/* Content */\n.content {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n justify-content: space-between;\n}\n\n.meta {\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n\n.title {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-md);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-900);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.publisher {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-500);\n}\n\n.publisher strong {\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-900);\n}\n\n.description-wrap {\n height: 40px;\n display: flex;\n align-items: center;\n overflow: hidden;\n}\n\n.description {\n margin: 0;\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n line-height: 20px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.info-row {\n display: flex;\n gap: var(--bv-spacing-md);\n}\n\n.info-item {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-900);\n}\n\n.info-item strong {\n font-weight: var(--bv-font-weight-bold);\n}\n\n/* Actions */\n.actions {\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-sm);\n flex-shrink: 0;\n width: 209px;\n justify-content: center;\n}\n\n/* Disabled selection: card body is no longer interactive */\n:host([disable-selection]) .card {\n cursor: default;\n}\n\n/* Loading skeleton */\n.skeleton {\n display: none;\n align-items: stretch;\n gap: var(--bv-spacing-md);\n flex: 1;\n min-width: 0;\n}\n\n:host([loading]) .card {\n cursor: default;\n}\n\n:host([loading]) .thumbnail-wrap,\n:host([loading]) .content,\n:host([loading]) .actions {\n display: none;\n}\n\n:host([loading]) .skeleton {\n display: flex;\n}\n\n.skeleton-thumb {\n flex-shrink: 0;\n width: 200px;\n min-height: 123px;\n border-radius: var(--bv-radius-lg);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.skeleton-content {\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-sm);\n flex: 1;\n min-width: 0;\n justify-content: center;\n}\n\n.skeleton-line {\n height: 12px;\n border-radius: var(--bv-radius-sm);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.skeleton-title-line {\n height: 20px;\n width: 60%;\n}\n\n.skeleton-short-line {\n width: 40%;\n}\n\n.skeleton-actions {\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-sm);\n flex-shrink: 0;\n width: 209px;\n justify-content: center;\n}\n\n.skeleton-button {\n height: 40px;\n border-radius: var(--bv-radius-md);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n@keyframes bv-skeleton-shimmer {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n";
|
|
3
3
|
|
|
4
4
|
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-button/bv-button.css
|
|
5
|
-
var bv_button_default =
|
|
6
|
-
Apps can override these three properties per-instance:
|
|
7
|
-
|
|
8
|
-
HTML: <bv-button style="--bv-button-bg: #e53e3e;">
|
|
9
|
-
Angular: <bv-button [style.--bv-button-bg]="brandColor">
|
|
10
|
-
JavaScript: btn.style.setProperty('--bv-button-bg', value)
|
|
11
|
-
|
|
12
|
-
Hover is auto-computed from the base colors via color-mix().
|
|
13
|
-
Override --bv-button-bg-hover / --bv-button-border-color-hover
|
|
14
|
-
if you need explicit control over the hovered state.
|
|
15
|
-
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
16
|
-
:host {
|
|
17
|
-
/* Default values \u2014 map to global tokens (primary variant) */
|
|
18
|
-
--bv-button-bg: var(--bv-color-primary);
|
|
19
|
-
--bv-button-bg-hover: color-mix(in srgb, var(--bv-button-bg) 82%, black);
|
|
20
|
-
--bv-button-color: var(--bv-color-neutral-0);
|
|
21
|
-
--bv-button-border-color: var(--bv-color-primary);
|
|
22
|
-
--bv-button-border-color-hover: color-mix(in srgb, var(--bv-button-border-color) 82%, black);
|
|
23
|
-
--bv-button-font-family: var(--bv-font-family-base);
|
|
24
|
-
--bv-button-font-size: var(--bv-font-size-sm);
|
|
25
|
-
|
|
26
|
-
display: inline-block;
|
|
27
|
-
font-family: var(--bv-font-family-base);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
:host([hidden]) {
|
|
31
|
-
display: none;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
:host([full-width]) {
|
|
35
|
-
display: block;
|
|
36
|
-
width: 100%;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/* \u2500\u2500 Variant tokens \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
40
|
-
Each variant re-points the component tokens to different global
|
|
41
|
-
tokens. Apps can still override with inline styles \u2014 inline style
|
|
42
|
-
always wins due to higher specificity.
|
|
43
|
-
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
44
|
-
|
|
45
|
-
:host([variant='secondary']) {
|
|
46
|
-
--bv-button-bg: var(--bv-color-secondary);
|
|
47
|
-
--bv-button-border-color: var(--bv-color-secondary);
|
|
48
|
-
--bv-button-color: var(--bv-color-secondary-foreground);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
:host([variant='tertiary']) {
|
|
52
|
-
--bv-button-bg: var(--bv-color-tertiary);
|
|
53
|
-
--bv-button-border-color: var(--bv-color-tertiary);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
:host([variant='danger']) {
|
|
57
|
-
--bv-button-bg: var(--bv-color-danger);
|
|
58
|
-
--bv-button-border-color: var(--bv-color-danger);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
:host([variant='ghost']) {
|
|
62
|
-
--bv-button-bg: transparent;
|
|
63
|
-
--bv-button-bg-hover: var(--bv-color-primary-light);
|
|
64
|
-
--bv-button-color: var(--bv-color-primary);
|
|
65
|
-
--bv-button-border-color: transparent;
|
|
66
|
-
--bv-button-border-color-hover: transparent;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
:host([variant='outline']) {
|
|
70
|
-
--bv-button-bg: transparent;
|
|
71
|
-
--bv-button-bg-hover: var(--bv-color-primary-light);
|
|
72
|
-
--bv-button-color: var(--bv-color-primary);
|
|
73
|
-
--bv-button-border-color: var(--bv-color-primary);
|
|
74
|
-
--bv-button-border-color-hover: var(--bv-color-primary);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/* \u2500\u2500 Base button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
78
|
-
All visual properties read from the component-level tokens above.
|
|
79
|
-
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
80
|
-
|
|
81
|
-
.btn {
|
|
82
|
-
display: inline-flex;
|
|
83
|
-
align-items: center;
|
|
84
|
-
justify-content: center;
|
|
85
|
-
gap: var(--bv-spacing-xs);
|
|
86
|
-
padding: 10px var(--bv-spacing-md);
|
|
87
|
-
min-height: 40px;
|
|
88
|
-
width: auto;
|
|
89
|
-
font-family: var(--bv-button-font-family);
|
|
90
|
-
font-size: var(--bv-button-font-size);
|
|
91
|
-
font-style: normal;
|
|
92
|
-
font-weight: var(--bv-font-weight-semibold);
|
|
93
|
-
line-height: 20px;
|
|
94
|
-
border: 1px solid var(--bv-button-border-color);
|
|
95
|
-
border-radius: var(--bv-radius-lg);
|
|
96
|
-
cursor: pointer;
|
|
97
|
-
transition:
|
|
98
|
-
background var(--bv-transition-fast),
|
|
99
|
-
color var(--bv-transition-fast),
|
|
100
|
-
border-color var(--bv-transition-fast),
|
|
101
|
-
box-shadow var(--bv-transition-fast),
|
|
102
|
-
opacity var(--bv-transition-fast);
|
|
103
|
-
white-space: nowrap;
|
|
104
|
-
user-select: none;
|
|
105
|
-
text-decoration: none;
|
|
106
|
-
outline: none;
|
|
107
|
-
box-sizing: border-box;
|
|
108
|
-
background: var(--bv-button-bg);
|
|
109
|
-
color: var(--bv-button-color);
|
|
110
|
-
box-shadow: var(--bv-shadow-sm);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
:host([full-width]) .btn {
|
|
114
|
-
width: 100%;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.btn:hover:not(:disabled) {
|
|
118
|
-
background: var(--bv-button-bg-hover);
|
|
119
|
-
border-color: var(--bv-button-border-color-hover);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
.btn:active:not(:disabled) {
|
|
123
|
-
transform: translateY(1px);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.btn:focus-visible {
|
|
127
|
-
outline: 2px solid var(--bv-button-border-color);
|
|
128
|
-
outline-offset: 2px;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.btn:disabled {
|
|
132
|
-
opacity: 0.5;
|
|
133
|
-
cursor: not-allowed;
|
|
134
|
-
pointer-events: none;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/* \u2500\u2500 Sizes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/
|
|
138
|
-
|
|
139
|
-
:host([size='sm']) .btn {
|
|
140
|
-
padding: 6px 12px;
|
|
141
|
-
min-height: 32px;
|
|
142
|
-
font-size: var(--bv-font-size-sm);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
:host([size='lg']) .btn {
|
|
146
|
-
padding: 12px var(--bv-spacing-lg);
|
|
147
|
-
min-height: 48px;
|
|
148
|
-
font-size: var(--bv-font-size-md);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/* \u2500\u2500 Icon \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/
|
|
152
|
-
|
|
153
|
-
.btn-icon {
|
|
154
|
-
display: inline-flex;
|
|
155
|
-
align-items: center;
|
|
156
|
-
flex-shrink: 0;
|
|
157
|
-
line-height: 0;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/* \u2500\u2500 Count badge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/
|
|
161
|
-
|
|
162
|
-
.btn-count {
|
|
163
|
-
opacity: 0.8;
|
|
164
|
-
font-weight: var(--bv-font-weight-regular);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/* \u2500\u2500 Loading spinner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/
|
|
168
|
-
|
|
169
|
-
.spinner {
|
|
170
|
-
display: inline-block;
|
|
171
|
-
width: 1em;
|
|
172
|
-
height: 1em;
|
|
173
|
-
border: 2px solid currentColor;
|
|
174
|
-
border-top-color: transparent;
|
|
175
|
-
border-radius: 50%;
|
|
176
|
-
flex-shrink: 0;
|
|
177
|
-
animation: bv-spin 700ms linear infinite;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
@keyframes bv-spin {
|
|
181
|
-
to {
|
|
182
|
-
transform: rotate(360deg);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
`;
|
|
5
|
+
var bv_button_default = "/* \u2500\u2500 Public theming API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Apps can override these three properties per-instance:\n\n HTML: <bv-button style=\"--bv-button-bg: #e53e3e;\">\n Angular: <bv-button [style.--bv-button-bg]=\"brandColor\">\n JavaScript: btn.style.setProperty('--bv-button-bg', value)\n\n Hover is auto-computed from the base colors via color-mix().\n Override --bv-button-bg-hover / --bv-button-border-color-hover\n if you need explicit control over the hovered state.\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n:host {\n /* Default values \u2014 map to global tokens (primary variant) */\n --bv-button-bg: var(--bv-color-primary);\n --bv-button-bg-hover: color-mix(in srgb, var(--bv-button-bg) 82%, black);\n --bv-button-color: var(--bv-color-neutral-0);\n --bv-button-border-color: var(--bv-color-primary);\n --bv-button-border-color-hover: color-mix(in srgb, var(--bv-button-border-color) 82%, black);\n --bv-button-font-family: var(--bv-font-family-base);\n --bv-button-font-size: var(--bv-font-size-sm);\n\n display: inline-block;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n /* `!important` so `hidden` always wins over :host([full-width]) / other display rules. */\n display: none !important;\n}\n\n:host([full-width]) {\n display: block;\n width: 100%;\n}\n\n/* \u2500\u2500 Variant tokens \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Each variant re-points the component tokens to different global\n tokens. Apps can still override with inline styles \u2014 inline style\n always wins due to higher specificity.\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n:host([variant='secondary']) {\n --bv-button-bg: var(--bv-color-secondary);\n --bv-button-border-color: var(--bv-color-secondary);\n --bv-button-color: var(--bv-color-secondary-foreground);\n}\n\n:host([variant='tertiary']) {\n --bv-button-bg: var(--bv-color-tertiary);\n --bv-button-border-color: var(--bv-color-tertiary);\n}\n\n:host([variant='danger']) {\n --bv-button-bg: var(--bv-color-danger);\n --bv-button-border-color: var(--bv-color-danger);\n}\n\n:host([variant='ghost']) {\n --bv-button-bg: transparent;\n --bv-button-bg-hover: var(--bv-color-primary-light);\n --bv-button-color: var(--bv-color-primary);\n --bv-button-border-color: transparent;\n --bv-button-border-color-hover: transparent;\n}\n\n:host([variant='outline']) {\n --bv-button-bg: transparent;\n --bv-button-bg-hover: var(--bv-color-primary-light);\n --bv-button-color: var(--bv-color-primary);\n --bv-button-border-color: var(--bv-color-primary);\n --bv-button-border-color-hover: var(--bv-color-primary);\n}\n\n/* \u2500\u2500 Base button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n All visual properties read from the component-level tokens above.\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--bv-spacing-xs);\n padding: 10px var(--bv-spacing-md);\n min-height: 40px;\n width: auto;\n font-family: var(--bv-button-font-family);\n font-size: var(--bv-button-font-size);\n font-style: normal;\n font-weight: var(--bv-font-weight-semibold);\n line-height: 20px;\n border: 1px solid var(--bv-button-border-color);\n border-radius: var(--bv-radius-lg);\n cursor: pointer;\n transition:\n background var(--bv-transition-fast),\n color var(--bv-transition-fast),\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast),\n opacity var(--bv-transition-fast);\n white-space: nowrap;\n user-select: none;\n text-decoration: none;\n outline: none;\n box-sizing: border-box;\n background: var(--bv-button-bg);\n color: var(--bv-button-color);\n box-shadow: var(--bv-shadow-sm);\n}\n\n:host([full-width]) .btn {\n width: 100%;\n}\n\n.btn:hover:not(:disabled) {\n background: var(--bv-button-bg-hover);\n border-color: var(--bv-button-border-color-hover);\n}\n\n.btn:active:not(:disabled) {\n transform: translateY(1px);\n}\n\n.btn:focus-visible {\n outline: 2px solid var(--bv-button-border-color);\n outline-offset: 2px;\n}\n\n.btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n/* \u2500\u2500 Sizes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/\n\n:host([size='sm']) .btn {\n padding: 6px 12px;\n min-height: 32px;\n font-size: var(--bv-font-size-sm);\n}\n\n:host([size='lg']) .btn {\n padding: 12px var(--bv-spacing-lg);\n min-height: 48px;\n font-size: var(--bv-font-size-md);\n}\n\n/* \u2500\u2500 Icon \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/\n\n.btn-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n line-height: 0;\n}\n\n/* \u2500\u2500 Count badge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/\n\n.btn-count {\n opacity: 0.8;\n font-weight: var(--bv-font-weight-regular);\n}\n\n/* \u2500\u2500 Loading spinner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/\n\n.spinner {\n display: inline-block;\n width: 1em;\n height: 1em;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n flex-shrink: 0;\n animation: bv-spin 700ms linear infinite;\n}\n\n@keyframes bv-spin {\n to {\n transform: rotate(360deg);\n }\n}\n";
|
|
186
6
|
|
|
187
7
|
// components/bv-icon/icons.ts
|
|
188
8
|
var icons = {
|
|
@@ -366,7 +186,7 @@ var BvButton = class extends HTMLElement {
|
|
|
366
186
|
}
|
|
367
187
|
btn.querySelectorAll(".btn-icon").forEach((el) => el.remove());
|
|
368
188
|
const iconName = this.getAttribute("icon");
|
|
369
|
-
if (iconName) {
|
|
189
|
+
if (iconName && !this.loading) {
|
|
370
190
|
const svg = getIconSvg(iconName, 16);
|
|
371
191
|
if (svg) {
|
|
372
192
|
const iconEl = document.createElement("span");
|
|
@@ -407,9 +227,14 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
407
227
|
"primary-label",
|
|
408
228
|
"primary-variant",
|
|
409
229
|
"primary-icon",
|
|
230
|
+
"primary-loading",
|
|
231
|
+
"primary-disabled",
|
|
410
232
|
"secondary-label",
|
|
411
233
|
"secondary-icon",
|
|
412
|
-
"selected"
|
|
234
|
+
"selected",
|
|
235
|
+
"disable-selection",
|
|
236
|
+
"hide-secondary",
|
|
237
|
+
"loading"
|
|
413
238
|
];
|
|
414
239
|
get selected() {
|
|
415
240
|
return this.hasAttribute("selected");
|
|
@@ -418,6 +243,41 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
418
243
|
if (v) this.setAttribute("selected", "");
|
|
419
244
|
else this.removeAttribute("selected");
|
|
420
245
|
}
|
|
246
|
+
get disableSelection() {
|
|
247
|
+
return this.hasAttribute("disable-selection");
|
|
248
|
+
}
|
|
249
|
+
set disableSelection(v) {
|
|
250
|
+
if (v) this.setAttribute("disable-selection", "");
|
|
251
|
+
else this.removeAttribute("disable-selection");
|
|
252
|
+
}
|
|
253
|
+
get hideSecondary() {
|
|
254
|
+
return this.hasAttribute("hide-secondary");
|
|
255
|
+
}
|
|
256
|
+
set hideSecondary(v) {
|
|
257
|
+
if (v) this.setAttribute("hide-secondary", "");
|
|
258
|
+
else this.removeAttribute("hide-secondary");
|
|
259
|
+
}
|
|
260
|
+
get primaryLoading() {
|
|
261
|
+
return this.hasAttribute("primary-loading");
|
|
262
|
+
}
|
|
263
|
+
set primaryLoading(v) {
|
|
264
|
+
if (v) this.setAttribute("primary-loading", "");
|
|
265
|
+
else this.removeAttribute("primary-loading");
|
|
266
|
+
}
|
|
267
|
+
get primaryDisabled() {
|
|
268
|
+
return this.hasAttribute("primary-disabled");
|
|
269
|
+
}
|
|
270
|
+
set primaryDisabled(v) {
|
|
271
|
+
if (v) this.setAttribute("primary-disabled", "");
|
|
272
|
+
else this.removeAttribute("primary-disabled");
|
|
273
|
+
}
|
|
274
|
+
get loading() {
|
|
275
|
+
return this.hasAttribute("loading");
|
|
276
|
+
}
|
|
277
|
+
set loading(v) {
|
|
278
|
+
if (v) this.setAttribute("loading", "");
|
|
279
|
+
else this.removeAttribute("loading");
|
|
280
|
+
}
|
|
421
281
|
_rendered = false;
|
|
422
282
|
_els = {};
|
|
423
283
|
constructor() {
|
|
@@ -473,12 +333,28 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
473
333
|
var _a2;
|
|
474
334
|
(_a2 = this._els.primaryBtn) == null ? void 0 : _a2.setAttribute("icon", val ?? "");
|
|
475
335
|
},
|
|
336
|
+
"primary-loading": () => {
|
|
337
|
+
var _a2, _b;
|
|
338
|
+
if (val === null) (_a2 = this._els.primaryBtn) == null ? void 0 : _a2.removeAttribute("loading");
|
|
339
|
+
else (_b = this._els.primaryBtn) == null ? void 0 : _b.setAttribute("loading", "");
|
|
340
|
+
},
|
|
341
|
+
"primary-disabled": () => {
|
|
342
|
+
var _a2, _b;
|
|
343
|
+
if (val === null) (_a2 = this._els.primaryBtn) == null ? void 0 : _a2.removeAttribute("disabled");
|
|
344
|
+
else (_b = this._els.primaryBtn) == null ? void 0 : _b.setAttribute("disabled", "");
|
|
345
|
+
},
|
|
476
346
|
"secondary-label": () => {
|
|
477
347
|
if (this._els.secondaryBtn) this._els.secondaryBtn.textContent = val ?? "";
|
|
478
348
|
},
|
|
479
349
|
"secondary-icon": () => {
|
|
480
350
|
var _a2;
|
|
481
351
|
(_a2 = this._els.secondaryBtn) == null ? void 0 : _a2.setAttribute("icon", val ?? "");
|
|
352
|
+
},
|
|
353
|
+
"hide-secondary": () => {
|
|
354
|
+
if (this._els.secondaryBtn) this._els.secondaryBtn.hidden = this.hideSecondary;
|
|
355
|
+
},
|
|
356
|
+
loading: () => {
|
|
357
|
+
this._syncLoading();
|
|
482
358
|
}
|
|
483
359
|
};
|
|
484
360
|
(_a = map[name]) == null ? void 0 : _a.call(map);
|
|
@@ -494,6 +370,7 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
494
370
|
}
|
|
495
371
|
const card = document.createElement("div");
|
|
496
372
|
card.className = "card";
|
|
373
|
+
this._els.card = card;
|
|
497
374
|
const thumbWrap = document.createElement("div");
|
|
498
375
|
thumbWrap.className = "thumbnail-wrap";
|
|
499
376
|
const thumb = document.createElement("img");
|
|
@@ -547,6 +424,8 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
547
424
|
primaryBtn.setAttribute("icon", this.getAttribute("primary-icon") ?? "");
|
|
548
425
|
primaryBtn.setAttribute("full-width", "");
|
|
549
426
|
primaryBtn.textContent = this.getAttribute("primary-label") ?? "Enroll Now";
|
|
427
|
+
if (this.primaryLoading) primaryBtn.setAttribute("loading", "");
|
|
428
|
+
if (this.primaryDisabled) primaryBtn.setAttribute("disabled", "");
|
|
550
429
|
primaryBtn.addEventListener("click", () => {
|
|
551
430
|
this.dispatchEvent(new CustomEvent("bv-primary-action", { bubbles: true, composed: true }));
|
|
552
431
|
});
|
|
@@ -556,15 +435,23 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
556
435
|
secondaryBtn.setAttribute("icon", this.getAttribute("secondary-icon") ?? "");
|
|
557
436
|
secondaryBtn.setAttribute("full-width", "");
|
|
558
437
|
secondaryBtn.textContent = this.getAttribute("secondary-label") ?? "View Details";
|
|
438
|
+
secondaryBtn.hidden = this.hideSecondary;
|
|
559
439
|
secondaryBtn.addEventListener("click", () => {
|
|
560
440
|
this.dispatchEvent(new CustomEvent("bv-secondary-action", { bubbles: true, composed: true }));
|
|
561
441
|
});
|
|
562
442
|
this._els.secondaryBtn = secondaryBtn;
|
|
563
443
|
actions.append(primaryBtn, secondaryBtn);
|
|
564
444
|
this._els.actions = actions;
|
|
565
|
-
|
|
445
|
+
const skeleton = document.createElement("div");
|
|
446
|
+
skeleton.className = "skeleton";
|
|
447
|
+
skeleton.setAttribute("aria-hidden", "true");
|
|
448
|
+
skeleton.innerHTML = '<div class="skeleton-thumb"></div><div class="skeleton-content"><div class="skeleton-line skeleton-title-line"></div><div class="skeleton-line skeleton-short-line"></div><div class="skeleton-line"></div><div class="skeleton-line skeleton-short-line"></div></div><div class="skeleton-actions"><div class="skeleton-button"></div><div class="skeleton-button"></div></div>';
|
|
449
|
+
this._els.skeleton = skeleton;
|
|
450
|
+
card.append(thumbWrap, content, actions, skeleton);
|
|
566
451
|
shadow.appendChild(card);
|
|
452
|
+
this._syncLoading();
|
|
567
453
|
card.addEventListener("click", (e) => {
|
|
454
|
+
if (this.disableSelection || this.loading) return;
|
|
568
455
|
if (e.composedPath().includes(this._els.actions)) return;
|
|
569
456
|
this.selected = !this.selected;
|
|
570
457
|
this.dispatchEvent(
|
|
@@ -576,6 +463,11 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
576
463
|
);
|
|
577
464
|
});
|
|
578
465
|
}
|
|
466
|
+
_syncLoading() {
|
|
467
|
+
var _a;
|
|
468
|
+
const loading = this.loading;
|
|
469
|
+
(_a = this._els.card) == null ? void 0 : _a.setAttribute("aria-busy", loading ? "true" : "false");
|
|
470
|
+
}
|
|
579
471
|
};
|
|
580
472
|
if (!customElements.get("bv-course-list-card")) {
|
|
581
473
|
customElements.define("bv-course-list-card", BvCourseListCard);
|
|
@@ -1,10 +1,31 @@
|
|
|
1
|
+
import { type EmptyStateIllustration } from './illustrations.ts';
|
|
2
|
+
import '../bv-button/bv-button.ts';
|
|
3
|
+
export type { EmptyStateIllustration };
|
|
1
4
|
export declare class BvEmptyState extends HTMLElement {
|
|
2
|
-
static readonly observedAttributes:
|
|
5
|
+
static readonly observedAttributes: readonly ["title", "description", "icon-svg", "illustration", "contact-support", "contact-support-label", "contact-support-href", "contact-support-target"];
|
|
3
6
|
private _rendered;
|
|
4
7
|
private _titleEl;
|
|
5
8
|
private _descEl;
|
|
9
|
+
private _iconWrap;
|
|
10
|
+
private _iconSlot;
|
|
11
|
+
private _actionSlot;
|
|
12
|
+
private _wrapEl;
|
|
6
13
|
constructor();
|
|
14
|
+
get iconSvg(): string;
|
|
15
|
+
set iconSvg(v: string);
|
|
16
|
+
get illustration(): EmptyStateIllustration | 'none';
|
|
17
|
+
set illustration(v: EmptyStateIllustration | 'none');
|
|
18
|
+
get contactSupport(): boolean;
|
|
19
|
+
set contactSupport(v: boolean);
|
|
20
|
+
get contactSupportLabel(): string;
|
|
21
|
+
set contactSupportLabel(v: string);
|
|
22
|
+
get contactSupportHref(): string;
|
|
23
|
+
set contactSupportHref(v: string);
|
|
24
|
+
get contactSupportTarget(): string;
|
|
25
|
+
set contactSupportTarget(v: string);
|
|
7
26
|
connectedCallback(): void;
|
|
8
27
|
attributeChangedCallback(name: string, _old: string | null, val: string | null): void;
|
|
9
28
|
private _render;
|
|
29
|
+
private _syncIconFallback;
|
|
30
|
+
private _syncActionFallback;
|
|
10
31
|
}
|