@bluevolt-tech/lumen 1.3.2 → 1.4.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.
- package/dist/components/bv-button/bv-button.js +1 -181
- package/dist/components/bv-course-detail-modal/bv-course-detail-modal.js +1 -181
- package/dist/components/bv-course-grid-card/bv-course-grid-card.d.ts +8 -0
- package/dist/components/bv-course-grid-card/bv-course-grid-card.js +58 -184
- package/dist/components/bv-course-list-card/bv-course-list-card.d.ts +7 -0
- package/dist/components/bv-course-list-card/bv-course-list-card.js +48 -184
- 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 +98 -194
- 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 +58 -192
- 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-grid-card/bv-course-grid-card.css
|
|
2
|
-
var bv_course_grid_card_default = ":host {\n display: block;\n}\n\n.card {\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-sm);\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 width: 100%;\n height: 153px;\n border-radius: var(--bv-radius-lg);\n overflow: hidden;\n background: var(--bv-color-neutral-200);\n flex-shrink: 0;\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 gap: 4px;\n flex: 1;\n min-width: 0;\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 {\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 margin: 0;\n}\n\n.info-row {\n display: flex;\n gap: var(--bv-spacing-md);\n margin-top: 2px;\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 gap: var(--bv-spacing-sm);\n align-items: stretch;\n}\n\n.primary-action {\n display: block;\n flex: 1;\n min-width: 0;\n}\n\n.secondary-action {\n display: block;\n width: 48px;\n flex-shrink: 0;\n}\n";
|
|
2
|
+
var bv_course_grid_card_default = ":host {\n display: block;\n}\n\n.card {\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-sm);\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 width: 100%;\n height: 153px;\n border-radius: var(--bv-radius-lg);\n overflow: hidden;\n background: var(--bv-color-neutral-200);\n flex-shrink: 0;\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 gap: 4px;\n flex: 1;\n min-width: 0;\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 {\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 margin: 0;\n}\n\n.info-row {\n display: flex;\n gap: var(--bv-spacing-md);\n margin-top: 2px;\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 gap: var(--bv-spacing-sm);\n align-items: stretch;\n}\n\n.primary-action {\n display: block;\n flex: 1;\n min-width: 0;\n}\n\n.secondary-action {\n display: block;\n width: 48px;\n flex-shrink: 0;\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 flex-direction: column;\n gap: var(--bv-spacing-sm);\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 width: 100%;\n height: 153px;\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-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: 70%;\n}\n\n.skeleton-short-line {\n width: 45%;\n}\n\n.skeleton-actions {\n display: flex;\n gap: var(--bv-spacing-sm);\n align-items: stretch;\n margin-top: 2px;\n}\n\n.skeleton-button {\n height: 44px;\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.skeleton-primary {\n flex: 1;\n min-width: 0;\n}\n\n.skeleton-icon-btn {\n width: 48px;\n flex-shrink: 0;\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 = {
|
|
@@ -407,8 +227,12 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
407
227
|
"primary-label",
|
|
408
228
|
"primary-variant",
|
|
409
229
|
"primary-icon",
|
|
230
|
+
"secondary-label",
|
|
410
231
|
"secondary-icon",
|
|
411
|
-
"selected"
|
|
232
|
+
"selected",
|
|
233
|
+
"disable-selection",
|
|
234
|
+
"hide-secondary",
|
|
235
|
+
"loading"
|
|
412
236
|
];
|
|
413
237
|
get selected() {
|
|
414
238
|
return this.hasAttribute("selected");
|
|
@@ -417,6 +241,27 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
417
241
|
if (v) this.setAttribute("selected", "");
|
|
418
242
|
else this.removeAttribute("selected");
|
|
419
243
|
}
|
|
244
|
+
get disableSelection() {
|
|
245
|
+
return this.hasAttribute("disable-selection");
|
|
246
|
+
}
|
|
247
|
+
set disableSelection(v) {
|
|
248
|
+
if (v) this.setAttribute("disable-selection", "");
|
|
249
|
+
else this.removeAttribute("disable-selection");
|
|
250
|
+
}
|
|
251
|
+
get hideSecondary() {
|
|
252
|
+
return this.hasAttribute("hide-secondary");
|
|
253
|
+
}
|
|
254
|
+
set hideSecondary(v) {
|
|
255
|
+
if (v) this.setAttribute("hide-secondary", "");
|
|
256
|
+
else this.removeAttribute("hide-secondary");
|
|
257
|
+
}
|
|
258
|
+
get loading() {
|
|
259
|
+
return this.hasAttribute("loading");
|
|
260
|
+
}
|
|
261
|
+
set loading(v) {
|
|
262
|
+
if (v) this.setAttribute("loading", "");
|
|
263
|
+
else this.removeAttribute("loading");
|
|
264
|
+
}
|
|
420
265
|
_rendered = false;
|
|
421
266
|
_els = {};
|
|
422
267
|
constructor() {
|
|
@@ -472,9 +317,18 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
472
317
|
var _a2;
|
|
473
318
|
(_a2 = this._els.primaryBtn) == null ? void 0 : _a2.setAttribute("icon", val ?? "");
|
|
474
319
|
},
|
|
320
|
+
"secondary-label": () => {
|
|
321
|
+
this._syncSecondaryLabel();
|
|
322
|
+
},
|
|
475
323
|
"secondary-icon": () => {
|
|
476
324
|
var _a2;
|
|
477
325
|
(_a2 = this._els.secondaryBtn) == null ? void 0 : _a2.setAttribute("icon", val ?? "");
|
|
326
|
+
},
|
|
327
|
+
"hide-secondary": () => {
|
|
328
|
+
if (this._els.secondaryBtn) this._els.secondaryBtn.hidden = this.hideSecondary;
|
|
329
|
+
},
|
|
330
|
+
loading: () => {
|
|
331
|
+
this._syncLoading();
|
|
478
332
|
}
|
|
479
333
|
};
|
|
480
334
|
(_a = map[name]) == null ? void 0 : _a.call(map);
|
|
@@ -490,6 +344,7 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
490
344
|
}
|
|
491
345
|
const card = document.createElement("div");
|
|
492
346
|
card.className = "card";
|
|
347
|
+
this._els.card = card;
|
|
493
348
|
const thumbWrap = document.createElement("div");
|
|
494
349
|
thumbWrap.className = "thumbnail-wrap";
|
|
495
350
|
const thumb = document.createElement("img");
|
|
@@ -549,15 +404,24 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
549
404
|
secondaryBtn.setAttribute("size", "lg");
|
|
550
405
|
secondaryBtn.setAttribute("full-width", "");
|
|
551
406
|
secondaryBtn.className = "secondary-action";
|
|
407
|
+
secondaryBtn.hidden = this.hideSecondary;
|
|
552
408
|
secondaryBtn.addEventListener("click", () => {
|
|
553
409
|
this.dispatchEvent(new CustomEvent("bv-secondary-action", { bubbles: true, composed: true }));
|
|
554
410
|
});
|
|
555
411
|
this._els.secondaryBtn = secondaryBtn;
|
|
412
|
+
this._syncSecondaryLabel();
|
|
556
413
|
actions.append(primaryBtn, secondaryBtn);
|
|
557
414
|
this._els.actions = actions;
|
|
558
|
-
|
|
415
|
+
const skeleton = document.createElement("div");
|
|
416
|
+
skeleton.className = "skeleton";
|
|
417
|
+
skeleton.setAttribute("aria-hidden", "true");
|
|
418
|
+
skeleton.innerHTML = '<div class="skeleton-thumb"></div><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 class="skeleton-actions"><div class="skeleton-button skeleton-primary"></div><div class="skeleton-button skeleton-icon-btn"></div></div>';
|
|
419
|
+
this._els.skeleton = skeleton;
|
|
420
|
+
card.append(thumbWrap, content, actions, skeleton);
|
|
559
421
|
shadow.appendChild(card);
|
|
422
|
+
this._syncLoading();
|
|
560
423
|
card.addEventListener("click", (e) => {
|
|
424
|
+
if (this.disableSelection || this.loading) return;
|
|
561
425
|
if (e.composedPath().includes(this._els.actions)) return;
|
|
562
426
|
this.selected = !this.selected;
|
|
563
427
|
this.dispatchEvent(
|
|
@@ -569,6 +433,16 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
569
433
|
);
|
|
570
434
|
});
|
|
571
435
|
}
|
|
436
|
+
_syncSecondaryLabel() {
|
|
437
|
+
if (!this._els.secondaryBtn) return;
|
|
438
|
+
const label = this.getAttribute("secondary-label");
|
|
439
|
+
this._els.secondaryBtn.textContent = label ?? "";
|
|
440
|
+
}
|
|
441
|
+
_syncLoading() {
|
|
442
|
+
var _a;
|
|
443
|
+
const loading = this.loading;
|
|
444
|
+
(_a = this._els.card) == null ? void 0 : _a.setAttribute("aria-busy", loading ? "true" : "false");
|
|
445
|
+
}
|
|
572
446
|
};
|
|
573
447
|
if (!customElements.get("bv-course-grid-card")) {
|
|
574
448
|
customElements.define("bv-course-grid-card", BvCourseGridCard);
|
|
@@ -3,10 +3,17 @@ export declare class BvCourseListCard extends HTMLElement {
|
|
|
3
3
|
static readonly observedAttributes: string[];
|
|
4
4
|
get selected(): boolean;
|
|
5
5
|
set selected(v: boolean);
|
|
6
|
+
get disableSelection(): boolean;
|
|
7
|
+
set disableSelection(v: boolean);
|
|
8
|
+
get hideSecondary(): boolean;
|
|
9
|
+
set hideSecondary(v: boolean);
|
|
10
|
+
get loading(): boolean;
|
|
11
|
+
set loading(v: boolean);
|
|
6
12
|
private _rendered;
|
|
7
13
|
private _els;
|
|
8
14
|
constructor();
|
|
9
15
|
connectedCallback(): void;
|
|
10
16
|
attributeChangedCallback(name: string, _old: string | null, val: string | null): void;
|
|
11
17
|
private _render;
|
|
18
|
+
private _syncLoading;
|
|
12
19
|
}
|
|
@@ -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 = {
|
|
@@ -409,7 +229,10 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
409
229
|
"primary-icon",
|
|
410
230
|
"secondary-label",
|
|
411
231
|
"secondary-icon",
|
|
412
|
-
"selected"
|
|
232
|
+
"selected",
|
|
233
|
+
"disable-selection",
|
|
234
|
+
"hide-secondary",
|
|
235
|
+
"loading"
|
|
413
236
|
];
|
|
414
237
|
get selected() {
|
|
415
238
|
return this.hasAttribute("selected");
|
|
@@ -418,6 +241,27 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
418
241
|
if (v) this.setAttribute("selected", "");
|
|
419
242
|
else this.removeAttribute("selected");
|
|
420
243
|
}
|
|
244
|
+
get disableSelection() {
|
|
245
|
+
return this.hasAttribute("disable-selection");
|
|
246
|
+
}
|
|
247
|
+
set disableSelection(v) {
|
|
248
|
+
if (v) this.setAttribute("disable-selection", "");
|
|
249
|
+
else this.removeAttribute("disable-selection");
|
|
250
|
+
}
|
|
251
|
+
get hideSecondary() {
|
|
252
|
+
return this.hasAttribute("hide-secondary");
|
|
253
|
+
}
|
|
254
|
+
set hideSecondary(v) {
|
|
255
|
+
if (v) this.setAttribute("hide-secondary", "");
|
|
256
|
+
else this.removeAttribute("hide-secondary");
|
|
257
|
+
}
|
|
258
|
+
get loading() {
|
|
259
|
+
return this.hasAttribute("loading");
|
|
260
|
+
}
|
|
261
|
+
set loading(v) {
|
|
262
|
+
if (v) this.setAttribute("loading", "");
|
|
263
|
+
else this.removeAttribute("loading");
|
|
264
|
+
}
|
|
421
265
|
_rendered = false;
|
|
422
266
|
_els = {};
|
|
423
267
|
constructor() {
|
|
@@ -479,6 +323,12 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
479
323
|
"secondary-icon": () => {
|
|
480
324
|
var _a2;
|
|
481
325
|
(_a2 = this._els.secondaryBtn) == null ? void 0 : _a2.setAttribute("icon", val ?? "");
|
|
326
|
+
},
|
|
327
|
+
"hide-secondary": () => {
|
|
328
|
+
if (this._els.secondaryBtn) this._els.secondaryBtn.hidden = this.hideSecondary;
|
|
329
|
+
},
|
|
330
|
+
loading: () => {
|
|
331
|
+
this._syncLoading();
|
|
482
332
|
}
|
|
483
333
|
};
|
|
484
334
|
(_a = map[name]) == null ? void 0 : _a.call(map);
|
|
@@ -494,6 +344,7 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
494
344
|
}
|
|
495
345
|
const card = document.createElement("div");
|
|
496
346
|
card.className = "card";
|
|
347
|
+
this._els.card = card;
|
|
497
348
|
const thumbWrap = document.createElement("div");
|
|
498
349
|
thumbWrap.className = "thumbnail-wrap";
|
|
499
350
|
const thumb = document.createElement("img");
|
|
@@ -556,15 +407,23 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
556
407
|
secondaryBtn.setAttribute("icon", this.getAttribute("secondary-icon") ?? "");
|
|
557
408
|
secondaryBtn.setAttribute("full-width", "");
|
|
558
409
|
secondaryBtn.textContent = this.getAttribute("secondary-label") ?? "View Details";
|
|
410
|
+
secondaryBtn.hidden = this.hideSecondary;
|
|
559
411
|
secondaryBtn.addEventListener("click", () => {
|
|
560
412
|
this.dispatchEvent(new CustomEvent("bv-secondary-action", { bubbles: true, composed: true }));
|
|
561
413
|
});
|
|
562
414
|
this._els.secondaryBtn = secondaryBtn;
|
|
563
415
|
actions.append(primaryBtn, secondaryBtn);
|
|
564
416
|
this._els.actions = actions;
|
|
565
|
-
|
|
417
|
+
const skeleton = document.createElement("div");
|
|
418
|
+
skeleton.className = "skeleton";
|
|
419
|
+
skeleton.setAttribute("aria-hidden", "true");
|
|
420
|
+
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>';
|
|
421
|
+
this._els.skeleton = skeleton;
|
|
422
|
+
card.append(thumbWrap, content, actions, skeleton);
|
|
566
423
|
shadow.appendChild(card);
|
|
424
|
+
this._syncLoading();
|
|
567
425
|
card.addEventListener("click", (e) => {
|
|
426
|
+
if (this.disableSelection || this.loading) return;
|
|
568
427
|
if (e.composedPath().includes(this._els.actions)) return;
|
|
569
428
|
this.selected = !this.selected;
|
|
570
429
|
this.dispatchEvent(
|
|
@@ -576,6 +435,11 @@ var BvCourseListCard = class extends HTMLElement {
|
|
|
576
435
|
);
|
|
577
436
|
});
|
|
578
437
|
}
|
|
438
|
+
_syncLoading() {
|
|
439
|
+
var _a;
|
|
440
|
+
const loading = this.loading;
|
|
441
|
+
(_a = this._els.card) == null ? void 0 : _a.setAttribute("aria-busy", loading ? "true" : "false");
|
|
442
|
+
}
|
|
579
443
|
};
|
|
580
444
|
if (!customElements.get("bv-course-list-card")) {
|
|
581
445
|
customElements.define("bv-course-list-card", BvCourseListCard);
|