@mono-lit/helper 0.0.1 → 0.0.2
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/LICENSE.md +55 -55
- package/README.md +35 -35
- package/dist/data-source-controller-B_rgHCjw.js +241 -0
- package/dist/{data-source-controller-C50Qyfzh.js → data-source-controller-Dbb4fd8I.js} +69 -6
- package/dist/{data-source-options-BTpfrOZ_.js → data-source-options-CP-X62Pa.js} +2 -2
- package/dist/{data-source-options-CQSTZHPE.js → data-source-options-Jqj7LU3Z.js} +1 -1
- package/dist/{data-source-read-CUX-lgrQ.js → data-source-read-B4DGp6UQ.js} +1 -1
- package/dist/{export-BvlBx_GZ.js → export-BiGVyxt6.js} +2 -2
- package/dist/{field-icons-BoOG6KrL.js → field-icons-DELrSdqJ.js} +36 -1
- package/dist/index.js +7 -7
- package/dist/{index.node-DjvYOL-J.js → index.node-BIqEGehH.js} +5 -4
- package/dist/index.node.js +7 -7
- package/dist/{mono-button-CoVnBLav.js → mono-button-simcTQdW.js} +2 -2
- package/dist/{mono-button.shadow-FfP_hMH4.js → mono-button.shadow-B_rKOY9N.js} +2 -2
- package/dist/{mono-data-chart-ChU4Ii3p.js → mono-data-chart-CEv29_NS.js} +53 -12
- package/dist/{mono-data-dropdown-BAUl58kW.js → mono-data-dropdown-Wnoke6zO.js} +1 -1
- package/dist/{mono-data-grid-CLBK8clE.js → mono-data-grid-CjkEqxgE.js} +5 -232
- package/dist/{mono-data-grid-Db80FzdZ.js → mono-data-grid-YjR3n9Ar.js} +3 -230
- package/dist/{data-search-Bwo5bg8K.js → normalize-error-Gcgmgh5i.js} +299 -1
- package/dist/{reactive-BHsqVjRh.js → reactive-Di3mTMnV.js} +299 -1
- package/dist/src/components/card/card-core.d.ts +1 -0
- package/dist/src/components/chart/chart-types.d.ts +19 -0
- package/dist/src/components/select/select-types.d.ts +26 -0
- package/dist/src/components/tag-input/tag-input-types.d.ts +26 -0
- package/dist/src/composables/data-source-controller.d.ts +29 -0
- package/dist/src/composables/field-icons.d.ts +8 -0
- package/dist/src/utils/normalize-error.d.ts +30 -0
- package/dist/{tooltip-CysgRgBi.js → tooltip-DQqNpqk2.js} +62 -27
- package/dist/tooltip.js +1 -1
- package/dist/ui/alert.js +1 -1
- package/dist/ui/button-dropdown.js +1 -1
- package/dist/ui/button.js +1 -1
- package/dist/ui/card.js +15 -2
- package/dist/ui/chart.js +81 -4
- package/dist/ui/dropdown-table.js +2 -2
- package/dist/ui/index.css +181 -18
- package/dist/ui/modal.js +3 -2
- package/dist/ui/select.js +153 -19
- package/dist/ui/shadow/alert.js +1 -1
- package/dist/ui/shadow/button-dropdown.js +1 -1
- package/dist/ui/shadow/button.js +1 -1
- package/dist/ui/shadow/card.js +16 -2
- package/dist/ui/shadow/chart.js +133 -17
- package/dist/ui/shadow/dropdown-table.js +2 -2
- package/dist/ui/shadow/modal.js +3 -2
- package/dist/ui/shadow/select.js +153 -19
- package/dist/ui/shadow/table.js +4 -4
- package/dist/ui/shadow/tag-input.js +154 -26
- package/dist/ui/table.js +3 -3
- package/dist/ui/tag-input.js +153 -25
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PanelSizeProps } from '../../composables/css-size';
|
|
2
|
+
import { DescribedError } from '../../utils/normalize-error';
|
|
2
3
|
import { MonoDataSource, LoadMoreMode } from '../../composables/data-source-controller';
|
|
3
4
|
import { VisibilityProps } from '../../composables/visibility';
|
|
4
5
|
import { MonoSearchValue } from '../../search/data-search';
|
|
@@ -221,6 +222,19 @@ export interface SelectProps extends VisibilityProps {
|
|
|
221
222
|
required?: boolean;
|
|
222
223
|
/** Shows a clear button to reset the selected value. */
|
|
223
224
|
clearable?: boolean;
|
|
225
|
+
/** Show "Loading…" + a spinner and lock the select — the app is still fetching its options. */
|
|
226
|
+
loading?: boolean;
|
|
227
|
+
/** Text shown while loading (default `'Loading…'`). */
|
|
228
|
+
loadingText?: string;
|
|
229
|
+
'loading-text'?: string;
|
|
230
|
+
loadingtext?: string;
|
|
231
|
+
/** The app's fetch failed: a string or the error itself. Painted with ↻, which fires `retry`. */
|
|
232
|
+
loadingError?: unknown;
|
|
233
|
+
'loading-error'?: unknown;
|
|
234
|
+
loadingerror?: unknown;
|
|
235
|
+
/** Accessible name of the ↻ button (default `'Retry'`). */
|
|
236
|
+
retryLabel?: string;
|
|
237
|
+
'retry-label'?: string;
|
|
224
238
|
/** Accessible label used when no visible label is present. */
|
|
225
239
|
ariaLabelText?: string;
|
|
226
240
|
ariaLabel?: string;
|
|
@@ -248,11 +262,23 @@ export interface SelectProps extends VisibilityProps {
|
|
|
248
262
|
cssclass?: SelectCssClass;
|
|
249
263
|
'css-class'?: SelectCssClass | string;
|
|
250
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* ↻ was pressed on a failed field. `source: 'dataSource'` — the bound source
|
|
267
|
+
* failed and is already being re-run; `'app'` — it was `loading-error`, so the
|
|
268
|
+
* app re-runs its own fetch.
|
|
269
|
+
*/
|
|
270
|
+
export type MonoRetryEvent = CustomEvent<{
|
|
271
|
+
error: DescribedError;
|
|
272
|
+
source: 'app' | 'dataSource';
|
|
273
|
+
}>;
|
|
251
274
|
export interface SelectEvents {
|
|
252
275
|
change: SelectModelEvent;
|
|
253
276
|
clear: SelectModelEvent;
|
|
277
|
+
retry: MonoRetryEvent;
|
|
254
278
|
'mno-change': SelectModelEvent;
|
|
255
279
|
mnoChange: SelectModelEvent;
|
|
256
280
|
'mno-clear': SelectModelEvent;
|
|
257
281
|
mnoClear: SelectModelEvent;
|
|
282
|
+
'mno-retry': MonoRetryEvent;
|
|
283
|
+
mnoRetry: MonoRetryEvent;
|
|
258
284
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MonoDataSource, LoadMoreMode } from '../../composables/data-source-controller';
|
|
2
2
|
import { PanelSizeProps } from '../../composables/css-size';
|
|
3
|
+
import { DescribedError } from '../../utils/normalize-error';
|
|
3
4
|
import { VisibilityProps } from '../../composables/visibility';
|
|
4
5
|
import { MonoSearchValue } from '../../search/data-search';
|
|
5
6
|
import { ChipBehaviour, ChipColor, ChipCssClass, ChipRounded, ChipSize, ChipVariant } from '../chip/chip-types';
|
|
@@ -310,6 +311,19 @@ export interface TagInputProps extends VisibilityProps {
|
|
|
310
311
|
disabled?: boolean;
|
|
311
312
|
/** Makes the tag input read-only. */
|
|
312
313
|
readonly?: boolean;
|
|
314
|
+
/** Show "Loading…" + a spinner and lock the tag input — the app is still fetching its options. */
|
|
315
|
+
loading?: boolean;
|
|
316
|
+
/** Text shown while loading (default `'Loading…'`). */
|
|
317
|
+
loadingText?: string;
|
|
318
|
+
'loading-text'?: string;
|
|
319
|
+
loadingtext?: string;
|
|
320
|
+
/** The app's fetch failed: a string or the error itself. Painted with ↻, which fires `retry`. */
|
|
321
|
+
loadingError?: unknown;
|
|
322
|
+
'loading-error'?: unknown;
|
|
323
|
+
loadingerror?: unknown;
|
|
324
|
+
/** Accessible name of the ↻ button (default `'Retry'`). */
|
|
325
|
+
retryLabel?: string;
|
|
326
|
+
'retry-label'?: string;
|
|
313
327
|
/** Marks the field as required. */
|
|
314
328
|
required?: boolean;
|
|
315
329
|
/** Shows a clear button to remove all tags. */
|
|
@@ -378,11 +392,21 @@ export interface TagInputProps extends VisibilityProps {
|
|
|
378
392
|
cssclass?: TagInputCssClass;
|
|
379
393
|
'css-class'?: TagInputCssClass | string;
|
|
380
394
|
}
|
|
395
|
+
/**
|
|
396
|
+
* ↻ was pressed on a failed field. `source: 'dataSource'` — the bound source
|
|
397
|
+
* failed and is already being re-run; `'app'` — it was `loading-error`, so the
|
|
398
|
+
* app re-runs its own fetch.
|
|
399
|
+
*/
|
|
400
|
+
export type TagInputRetryEvent = CustomEvent<{
|
|
401
|
+
error: DescribedError;
|
|
402
|
+
source: 'app' | 'dataSource';
|
|
403
|
+
}>;
|
|
381
404
|
export interface TagInputEvents {
|
|
382
405
|
change: TagInputModelEvent;
|
|
383
406
|
add: TagInputModelEvent;
|
|
384
407
|
remove: TagInputModelEvent;
|
|
385
408
|
clear: TagInputModelEvent;
|
|
409
|
+
retry: TagInputRetryEvent;
|
|
386
410
|
'mno-change': TagInputModelEvent;
|
|
387
411
|
mnoChange: TagInputModelEvent;
|
|
388
412
|
'mno-add': TagInputModelEvent;
|
|
@@ -391,4 +415,6 @@ export interface TagInputEvents {
|
|
|
391
415
|
mnoRemove: TagInputModelEvent;
|
|
392
416
|
'mno-clear': TagInputModelEvent;
|
|
393
417
|
mnoClear: TagInputModelEvent;
|
|
418
|
+
'mno-retry': TagInputRetryEvent;
|
|
419
|
+
mnoRetry: TagInputRetryEvent;
|
|
394
420
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
import { DescribedError } from '../utils/normalize-error';
|
|
2
3
|
/**
|
|
3
4
|
* Minimal structural shape of a devextreme DataSource. Declared locally so
|
|
4
5
|
* @mono-lit/helper stays dependency-free; a real devextreme DataSource satisfies it.
|
|
@@ -49,6 +50,9 @@ export declare class DataSourceController<T = unknown> implements ReactiveContro
|
|
|
49
50
|
private _dsLoading;
|
|
50
51
|
private _loadingMore;
|
|
51
52
|
private _isLastPage;
|
|
53
|
+
private _error;
|
|
54
|
+
private _hasLoaded;
|
|
55
|
+
private _retrying;
|
|
52
56
|
private _visibleCount;
|
|
53
57
|
private _internalLoad;
|
|
54
58
|
private _bound;
|
|
@@ -64,18 +68,43 @@ export declare class DataSourceController<T = unknown> implements ReactiveContro
|
|
|
64
68
|
resetVisible(): void;
|
|
65
69
|
/** Load/reveal the next page and append it to the accumulated list. */
|
|
66
70
|
loadMore(): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Re-run the request after a failure. Reloads the source as it stands, so a
|
|
73
|
+
* failed search is retried with the same query. While it runs the field is
|
|
74
|
+
* {@link busy} again.
|
|
75
|
+
*
|
|
76
|
+
* `load` replaces the plain `ds.load()` — a host whose failed request was a
|
|
77
|
+
* search passes one that clears the query on the source and reloads.
|
|
78
|
+
*/
|
|
79
|
+
retry(load?: () => unknown): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Record a failure from a request the host drove itself (e.g. a server
|
|
82
|
+
* select-all drain). Cancelled loads are ignored.
|
|
83
|
+
*/
|
|
84
|
+
setError(raw: unknown): void;
|
|
67
85
|
/** Raw source array: accumulated DataSource items, or the plain `items`. */
|
|
68
86
|
get sourceItems(): T[];
|
|
69
87
|
/** Rows to actually render (array-mode reveals a slice; else everything). */
|
|
70
88
|
get visibleItems(): T[];
|
|
71
89
|
get loading(): boolean;
|
|
72
90
|
get loadingMore(): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* The field must be locked: the FIRST load (or a retry) is in flight. A
|
|
93
|
+
* search / filter reload after the source has answered once does not count —
|
|
94
|
+
* the person is typing into the field and it must stay usable.
|
|
95
|
+
*/
|
|
96
|
+
get busy(): boolean;
|
|
97
|
+
/** The last load failure, described for a person; null once a load succeeds. */
|
|
98
|
+
get error(): DescribedError | null;
|
|
73
99
|
/** load-more is driving a plain `items` array (no DataSource bound). */
|
|
74
100
|
get isArrayLoadMore(): boolean;
|
|
75
101
|
/** Whether there's nothing left to load/reveal. */
|
|
76
102
|
get atLastPage(): boolean;
|
|
77
103
|
private readonly _onChanged;
|
|
78
104
|
private readonly _onLoadingChanged;
|
|
105
|
+
private readonly _onLoadError;
|
|
106
|
+
/** A load answered: the source is usable and any earlier failure is over. */
|
|
107
|
+
private _markLoaded;
|
|
79
108
|
private _sync;
|
|
80
109
|
/** Load the first page, replacing the accumulated list. */
|
|
81
110
|
private _loadFirstPage;
|
|
@@ -5,3 +5,11 @@ export declare function caretIcon(): TemplateResult;
|
|
|
5
5
|
export declare function closeIcon(): TemplateResult;
|
|
6
6
|
/** Left (`-1`) or right (`1`) chevron, matching {@link caretIcon}'s weight. */
|
|
7
7
|
export declare function chevronIcon(dir: -1 | 1): TemplateResult;
|
|
8
|
+
/**
|
|
9
|
+
* Busy arc for a field whose data source is still answering. Spun by the
|
|
10
|
+
* component's own CSS (`[mono-ds-spinner] > svg`) so a reduced-motion rule can
|
|
11
|
+
* stop it.
|
|
12
|
+
*/
|
|
13
|
+
export declare function spinnerIcon(): TemplateResult;
|
|
14
|
+
/** ↻ — the retry affordance a field shows after its data source failed. */
|
|
15
|
+
export declare function refreshIcon(): TemplateResult;
|
|
@@ -37,6 +37,19 @@ export declare function resolveErrorMessages(local?: MonoErrorMessages): Record<
|
|
|
37
37
|
* `Error`.
|
|
38
38
|
*/
|
|
39
39
|
export declare function errorStatus(raw: unknown): number | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Every message an error carries, combined the way `monoFetch`'s
|
|
42
|
+
* `extractErrorMessage` does it: each key whose name contains "message"
|
|
43
|
+
* (`message`, `errorMessage`, `Message`, …) holding text — or OData's
|
|
44
|
+
* `{ message: { value } }` — at any depth up to 3, plus a JSON body still in
|
|
45
|
+
* `responseText` / `responseJSON` / `response`, plus an `Error`'s own
|
|
46
|
+
* (non-enumerable) `message`. The usual body fields `detail` / `title` and a
|
|
47
|
+
* plain-text `response.data` count too.
|
|
48
|
+
*
|
|
49
|
+
* Deduplicated by {@link uniqueMessages}, transport boilerplate ("Bad Request",
|
|
50
|
+
* "Failed to fetch") dropped, in the order found.
|
|
51
|
+
*/
|
|
52
|
+
export declare function collectErrorMessages(raw: unknown, status?: number | undefined): string[];
|
|
40
53
|
export interface DescribedError {
|
|
41
54
|
/** The headline: the preset for the status when there is one, else the error's own text. */
|
|
42
55
|
message: string;
|
|
@@ -47,7 +60,19 @@ export interface DescribedError {
|
|
|
47
60
|
* user CAN act on ("Budget period is closed"). Never a bare reason phrase.
|
|
48
61
|
*/
|
|
49
62
|
detail?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Every distinct message the error carried (see {@link collectErrorMessages}) —
|
|
65
|
+
* what `detail` joins. Empty when the error said nothing beyond its status.
|
|
66
|
+
*/
|
|
67
|
+
messages: string[];
|
|
50
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* The one line a field shows for `err`: what the server said, every distinct
|
|
71
|
+
* message combined (`monoFetch` style), or the headline when it said nothing.
|
|
72
|
+
*/
|
|
73
|
+
export declare function errorText(err: DescribedError, separator?: string): string;
|
|
74
|
+
/** The hover text: the headline, then everything the server said, each once. */
|
|
75
|
+
export declare function errorTitle(err: DescribedError): string;
|
|
51
76
|
/**
|
|
52
77
|
* The line a person should read for `raw`.
|
|
53
78
|
*
|
|
@@ -58,3 +83,8 @@ export interface DescribedError {
|
|
|
58
83
|
* returns an empty `message`.
|
|
59
84
|
*/
|
|
60
85
|
export declare function describeError(raw: unknown, messages?: MonoErrorMessages): DescribedError;
|
|
86
|
+
/**
|
|
87
|
+
* A load a newer load superseded (devextreme rejects it with `'canceled'`).
|
|
88
|
+
* Not a failure — nothing should be shown for it.
|
|
89
|
+
*/
|
|
90
|
+
export declare function isCanceled(err: any): boolean;
|
|
@@ -186,34 +186,55 @@ function isFocusVisible(el) {
|
|
|
186
186
|
return true;
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
-
/**
|
|
190
|
-
|
|
191
|
-
* straight part of the edge. A fixed 4px let a `-start` / `-end` arrow land on the
|
|
192
|
-
* curve of a well-rounded flavor (a pill, in the extreme), where the edge has
|
|
193
|
-
* already pulled away and the diamond hung off the corner.
|
|
194
|
-
*
|
|
195
|
-
* Read from the PAINTED radius, so every flavor and radius preset is covered.
|
|
196
|
-
* CSS scales radii that overflow the box down to fit it (a `9999px` pill paints
|
|
197
|
-
* half its height), hence the clamp to half the smaller side. The diamond is the
|
|
198
|
-
* arrow box rotated 45°: where it meets the edge it is `size·√2` wide, so it
|
|
199
|
-
* overhangs its own box by `size·(√2−1)/2` on each side. Floating UI caps the
|
|
200
|
-
* padding itself when the bubble is too short for it — the arrow then centres on
|
|
201
|
-
* the edge and the bubble shifts so it still points at the trigger.
|
|
202
|
-
*/
|
|
203
|
-
function arrowPadding(bubble, arrowEl) {
|
|
189
|
+
/** The bubble's four computed corner radii — read once per open, BEFORE any cap lands. */
|
|
190
|
+
function readCorners(bubble) {
|
|
204
191
|
const cs = getComputedStyle(bubble);
|
|
205
|
-
|
|
206
|
-
const radius = Math.max(...[
|
|
192
|
+
return [
|
|
207
193
|
cs.borderTopLeftRadius,
|
|
208
194
|
cs.borderTopRightRadius,
|
|
209
195
|
cs.borderBottomRightRadius,
|
|
210
196
|
cs.borderBottomLeftRadius
|
|
211
|
-
]
|
|
197
|
+
];
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Where the arrow may sit on the edge of `side`, and whether the bubble's rounding
|
|
201
|
+
* has to give way for it.
|
|
202
|
+
*
|
|
203
|
+
* `padding` keeps the arrow past the rounding, on the straight part of the edge. A
|
|
204
|
+
* fixed 4px let a `-start` / `-end` arrow land on the curve of a well-rounded
|
|
205
|
+
* flavor, where the edge has already pulled away and the diamond hung off the
|
|
206
|
+
* corner.
|
|
207
|
+
*
|
|
208
|
+
* `cap` handles the edge that has NO straight part: a pill's short side is all
|
|
209
|
+
* curve (height = 2 × radius), so whatever the padding, the diamond sat on a curve
|
|
210
|
+
* and looked glued to the corner. When the edge can't fit the arrow between its two
|
|
211
|
+
* roundings, the radius is capped to the widest value that still leaves the
|
|
212
|
+
* diamond a straight run — the bubble turns from a pill into a rounded rectangle
|
|
213
|
+
* only on the placements that need it. `null` = the painted radius already fits.
|
|
214
|
+
*
|
|
215
|
+
* Read from the PAINTED radius, so every flavor and radius preset is covered. CSS
|
|
216
|
+
* scales radii that overflow the box down to fit it (a `9999px` pill paints half
|
|
217
|
+
* its height), hence the clamp to half the smaller side. The diamond is the arrow
|
|
218
|
+
* box rotated 45°: where it meets the edge it is `size·√2` wide, so it overhangs
|
|
219
|
+
* its own box by `size·(√2−1)/2` on each side.
|
|
220
|
+
*/
|
|
221
|
+
function arrowGeometry(bubble, arrowEl, corners, side) {
|
|
222
|
+
const width = bubble.offsetWidth;
|
|
223
|
+
const height = bubble.offsetHeight;
|
|
224
|
+
const half = Math.min(width, height) / 2;
|
|
225
|
+
const painted = Math.min(half, Math.max(...corners.map((v) => {
|
|
212
226
|
const n = parseFloat(v) || 0;
|
|
213
227
|
return v.trim().endsWith("%") ? n / 100 * half * 2 : n;
|
|
214
|
-
}));
|
|
215
|
-
const
|
|
216
|
-
|
|
228
|
+
})));
|
|
229
|
+
const size = arrowEl.offsetWidth;
|
|
230
|
+
const diagonal = size * Math.SQRT2;
|
|
231
|
+
const overhang = (diagonal - size) / 2;
|
|
232
|
+
const fit = Math.max(0, Math.floor(((side === "left" || side === "right" ? height : width) - diagonal) / 2) - 2);
|
|
233
|
+
const radius = Math.min(painted, fit);
|
|
234
|
+
return {
|
|
235
|
+
padding: Math.max(4, Math.ceil(radius + overhang) + 1),
|
|
236
|
+
cap: radius < painted ? radius : null
|
|
237
|
+
};
|
|
217
238
|
}
|
|
218
239
|
function toDelays(delay) {
|
|
219
240
|
if (Array.isArray(delay)) return [Number(delay[0]) || 0, Number(delay[1]) || 0];
|
|
@@ -247,6 +268,7 @@ var TooltipInstance = class {
|
|
|
247
268
|
this._reasons = /* @__PURE__ */ new Set();
|
|
248
269
|
this._token = 0;
|
|
249
270
|
this._pending = null;
|
|
271
|
+
this._pendingReason = null;
|
|
250
272
|
this._suppressed = null;
|
|
251
273
|
this._lastPath = [];
|
|
252
274
|
this._destroyed = false;
|
|
@@ -374,8 +396,13 @@ var TooltipInstance = class {
|
|
|
374
396
|
}
|
|
375
397
|
if (anchor && o.hideOnClick) {
|
|
376
398
|
this._suppressed = anchor;
|
|
377
|
-
if (this._pending === anchor)
|
|
378
|
-
|
|
399
|
+
if (this._pending === anchor) {
|
|
400
|
+
if (this._pendingReason !== "focus") this._cancelShow();
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (this._open?.anchor !== anchor || this._reasons.has("manual")) return;
|
|
404
|
+
if (this._reasons.has("focus")) this._reasons.delete("hover");
|
|
405
|
+
else this._close(false);
|
|
379
406
|
}
|
|
380
407
|
}
|
|
381
408
|
_resolved(anchor) {
|
|
@@ -409,6 +436,7 @@ var TooltipInstance = class {
|
|
|
409
436
|
clearTimeout(this._showTimer);
|
|
410
437
|
this._showTimer = void 0;
|
|
411
438
|
this._pending = null;
|
|
439
|
+
this._pendingReason = null;
|
|
412
440
|
}
|
|
413
441
|
_cancelHide() {
|
|
414
442
|
clearTimeout(this._hideTimer);
|
|
@@ -416,7 +444,7 @@ var TooltipInstance = class {
|
|
|
416
444
|
}
|
|
417
445
|
/** One reason to stay open went away — close once none is left. */
|
|
418
446
|
_dropReason(reason) {
|
|
419
|
-
if (this._pending && !this._open) {
|
|
447
|
+
if (this._pending && !this._open && this._pendingReason === reason) {
|
|
420
448
|
this._cancelShow();
|
|
421
449
|
this._token++;
|
|
422
450
|
}
|
|
@@ -441,12 +469,14 @@ var TooltipInstance = class {
|
|
|
441
469
|
const token = ++this._token;
|
|
442
470
|
if (delay > 0) {
|
|
443
471
|
this._pending = anchor;
|
|
472
|
+
this._pendingReason = reason;
|
|
444
473
|
await new Promise((resolve) => {
|
|
445
474
|
this._showTimer = setTimeout(resolve, delay);
|
|
446
475
|
});
|
|
447
476
|
if (token !== this._token) return;
|
|
448
477
|
}
|
|
449
478
|
this._pending = null;
|
|
479
|
+
this._pendingReason = null;
|
|
450
480
|
await this._mount(anchor, reason, token);
|
|
451
481
|
}
|
|
452
482
|
async _mount(anchor, reason, token) {
|
|
@@ -521,10 +551,12 @@ var TooltipInstance = class {
|
|
|
521
551
|
const middleware = [offset(o.offset)];
|
|
522
552
|
if (o.flip) middleware.push(flip({ padding: o.padding }));
|
|
523
553
|
if (o.shift) middleware.push(shift({ padding: o.padding }));
|
|
524
|
-
|
|
554
|
+
const corners = state.corners ??= readCorners(state.el);
|
|
555
|
+
const geometry = (placement) => arrowGeometry(state.el, state.arrow, corners, placement.split("-")[0]);
|
|
556
|
+
if (o.arrow) middleware.push(arrow(({ placement }) => ({
|
|
525
557
|
element: state.arrow,
|
|
526
|
-
padding:
|
|
527
|
-
}));
|
|
558
|
+
padding: geometry(placement).padding
|
|
559
|
+
})));
|
|
528
560
|
middleware.push(hide());
|
|
529
561
|
const { x, y, placement, middlewareData } = await computePosition(state.anchor, state.el, {
|
|
530
562
|
placement: o.placement,
|
|
@@ -538,6 +570,9 @@ var TooltipInstance = class {
|
|
|
538
570
|
state.el.setAttribute("data-side", side);
|
|
539
571
|
if (align) state.el.setAttribute("data-align", align);
|
|
540
572
|
else state.el.removeAttribute("data-align");
|
|
573
|
+
const cap = o.arrow ? geometry(placement).cap : null;
|
|
574
|
+
if (cap === null) state.el.style.removeProperty("--_mono-tooltip-radius-cap");
|
|
575
|
+
else state.el.style.setProperty("--_mono-tooltip-radius-cap", `${cap}px`);
|
|
541
576
|
const a = middlewareData.arrow;
|
|
542
577
|
state.arrow.style.left = a?.x != null ? `${a.x}px` : "";
|
|
543
578
|
state.arrow.style.top = a?.y != null ? `${a.y}px` : "";
|
package/dist/tooltip.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as resetMonoTooltip, c as loadFloatingUi, d as resolveTooltipOptions, i as readTooltipAttributes, l as DEFAULT_TOOLTIP_OPTIONS, n as createMonoTooltip, o as controlMonoTooltip, r as destroyAllMonoTooltips, s as monoTooltip, t as TOOLTIP_ATTRIBUTE_SELECTOR, u as getMonoTooltipGlobal } from "./tooltip-
|
|
1
|
+
import { a as resetMonoTooltip, c as loadFloatingUi, d as resolveTooltipOptions, i as readTooltipAttributes, l as DEFAULT_TOOLTIP_OPTIONS, n as createMonoTooltip, o as controlMonoTooltip, r as destroyAllMonoTooltips, s as monoTooltip, t as TOOLTIP_ATTRIBUTE_SELECTOR, u as getMonoTooltipGlobal } from "./tooltip-DQqNpqk2.js";
|
|
2
2
|
export { DEFAULT_TOOLTIP_OPTIONS, TOOLTIP_ATTRIBUTE_SELECTOR, controlMonoTooltip, createMonoTooltip, destroyAllMonoTooltips, getMonoTooltipGlobal, loadFloatingUi, monoTooltip, readTooltipAttributes, resetMonoTooltip, resolveTooltipOptions };
|
package/dist/ui/alert.js
CHANGED
|
@@ -2,7 +2,7 @@ import { t as customElement } from "../mono-element-B0kP_96P.js";
|
|
|
2
2
|
import { a as defineHybridPropAliases, i as defineHybridPropAlias, r as booleanStringConverter, t as __decorate } from "../decorate-DEXtNagw.js";
|
|
3
3
|
import { a as parkDetachedNodes, n as bucketHasContent, o as placeLightSlots, r as captureLightSlots } from "../light-slots-DW1WgfgT.js";
|
|
4
4
|
import { t as isIconifyClass } from "../icon-dVhYJUIH.js";
|
|
5
|
-
import { r as closeIcon } from "../field-icons-
|
|
5
|
+
import { r as closeIcon } from "../field-icons-DELrSdqJ.js";
|
|
6
6
|
import { LitElement, html, nothing, unsafeCSS } from "lit";
|
|
7
7
|
import { property, state } from "lit/decorators.js";
|
|
8
8
|
//#region src/components/alert/alert-core.ts
|
|
@@ -3,7 +3,7 @@ import { t as customElement } from "../mono-element-B0kP_96P.js";
|
|
|
3
3
|
import { a as defineHybridPropAliases, o as numberStringConverter, r as booleanStringConverter, t as __decorate } from "../decorate-DEXtNagw.js";
|
|
4
4
|
import { t as dispatchMonoEvent } from "../mono-event-Bi1qP9uN.js";
|
|
5
5
|
import { a as rateLimitHasChanged } from "../rate-limit-BBa2PO79.js";
|
|
6
|
-
import { n as button_default } from "../mono-button-
|
|
6
|
+
import { n as button_default } from "../mono-button-simcTQdW.js";
|
|
7
7
|
import { t as PopupPortalController } from "../popup-portal-BziRX1yG.js";
|
|
8
8
|
import { LitElement, html, isServer, nothing, unsafeCSS } from "lit";
|
|
9
9
|
import { ref } from "lit/directives/ref.js";
|
package/dist/ui/button.js
CHANGED
package/dist/ui/card.js
CHANGED
|
@@ -134,6 +134,15 @@ var MonoCardCore = (superClass) => {
|
|
|
134
134
|
get _hasHeader() {
|
|
135
135
|
return Boolean(this._hasIcon || this._hasTitle || this._hasSubtitle || this._hasHeaderSlot || this.title || this.subtitle);
|
|
136
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* The header shows a title with NO subtitle under it — drives `mono-no-subtitle`,
|
|
139
|
+
* which centres the icon chip and that lone title on one axis. With a subtitle
|
|
140
|
+
* the row stays top-aligned (icon level with the first line); a `slot="header"`
|
|
141
|
+
* owns its own layout, so it never counts.
|
|
142
|
+
*/
|
|
143
|
+
get _noSubtitle() {
|
|
144
|
+
return !this._hasHeaderSlot && !this._hasSubtitle && !this.subtitle;
|
|
145
|
+
}
|
|
137
146
|
get _cardClasses() {
|
|
138
147
|
const classes = ["mono-card"];
|
|
139
148
|
classes.push(this.size);
|
|
@@ -268,7 +277,7 @@ var MonoCardCore = (superClass) => {
|
|
|
268
277
|
};
|
|
269
278
|
//#endregion
|
|
270
279
|
//#region src/components/card/card.css?raw
|
|
271
|
-
var card_default = "/* =========================================================================\r\n mono-card — a port of Basecoat's `.card` (basecoat-css@1.0.2, vega style).\r\n\r\n Styled by ATTRIBUTE, like Basecoat — and the attributes mirror the element's\r\n props one for one, so hand-written markup reads like the Lit / Vue tag:\r\n\r\n <mono-card size=\"sm\" variant=\"outlined\" color=\"primary\" title=\"Title\">\r\n <div mono-card mono-size=\"sm\" mono-variant=\"outlined\" mono-color=\"primary\">\r\n <div mono-header>\r\n <div mono-header-content><h3 mono-title>Title</h3></div>\r\n </div>\r\n <div mono-body><p>…</p></div>\r\n <div mono-footer>…</div>\r\n </div>\r\n\r\n An absent attribute is the prop's default (`:not([mono-size])` = md,\r\n `:not([mono-variant])` = elevated, `:not([mono-color])` = neutral). The element\r\n renders these attributes on its root (both builds) plus the STATES\r\n `mono-bordered` / `mono-hoverable` / `mono-clickable` / `mono-selected` /\r\n `mono-disabled` / `mono-loading`, and the negatives `mono-no-header-divider` /\r\n `mono-no-footer-divider` (both dividers default ON, so the attribute marks the\r\n exception). The old classes (`.mono-card.md.elevated.primary`) are still\r\n emitted as inert hooks until 2.0 but no rule here reads them.\r\n\r\n Selector map (ours ≡ upstream):\r\n [mono-card] ≡ .card (flex-col gap-6 py-6 rounded-xl bg-card text-card-foreground text-sm shadow-xs ring-1 ring-foreground/10 overflow-hidden)\r\n — the ring is drawn as an INSET box-shadow, see --_mono-card-edge-*\r\n [mono-card] > [mono-header] ≡ .card > header (grid auto-rows-min gap-1 px-6)\r\n [mono-title] ≡ .card > header > :is(h2, h3, [data-title], .card-title) (text-base font-medium leading-normal)\r\n [mono-subtitle] ≡ .card > header > :is(p, [data-description], .card-description) (text-sm text-muted-foreground)\r\n [mono-body] ≡ .card > section (px-6)\r\n [mono-footer] / [mono-actions] ≡ .card > footer (flex items-center px-6)\r\n [mono-size=\"sm\"] ≡ .card[data-size='sm'] (gap-4 py-4, px-4 on every region)\r\n [mono-size=\"xs|lg|xl|xxl\"] ≡ EXTENSION (the same ladder continued)\r\n [mono-variant=\"outlined\"] ≡ .card verbatim (the ring + shadow-xs)\r\n [mono-variant=\"elevated|flat|tonal|glass\"] ≡ EXTENSION (shadow-md / none / an accent tint / a blurred pane)\r\n [mono-color=\"…\"] ≡ EXTENSION (the ring and the title in the role's colour)\r\n [mono-media] ≡ .card [&>img:first-child]:rounded-t-xl — a full-bleed media band\r\n [mono-icon], [mono-loading], [mono-selected] ≡ EXTENSION\r\n\r\n `gradient` is GONE (variant and colour alike): the port drops every colour\r\n gradient. `--mono-card-gradient-*` are no-ops until 2.0.\r\n\r\n Specificity contract (same as the pre-port class sheet): a part's RESTING rule\r\n is exactly one attribute strong — `:where([mono-card]) [mono-body]` = (0,1,0)\r\n — so a utility class handed in through `cssClass` wins by source order, while\r\n prop and state rules stay heavier and win over it.\r\n\r\n Inner parts: [mono-media], [mono-header] > [mono-icon] / [mono-header-content]\r\n > [mono-title] / [mono-subtitle], [mono-body], [mono-actions], [mono-footer],\r\n [mono-loading] > [mono-spinner]. The shadow build renders every region and\r\n marks the empty ones [mono-empty]; this sheet hides them.\r\n\r\n FLAVORS set `--mono-card-{radius,shadow,ring-color,ring-width,padding-<size>,\r\n gap-<size>,title-font-<size>,…}` (the per-style `.card` deltas); every fallback\r\n here is vega's value (`node scripts/basecoat-styles.mjs --varying \"^\\.card\"`).\r\n ========================================================================= */\r\n\r\nmono-card {\r\n display: block;\r\n}\r\n\r\n[mono-card] {\r\n /* ── palette: each slot is a public knob over a Basecoat token ─────────── */\r\n --_mono-card-bg: var(--mono-card-bg, var(--card));\r\n --_mono-card-text: var(--mono-card-text, var(--card-foreground));\r\n --_mono-card-subtext: var(--mono-card-subtext, var(--muted-foreground));\r\n --_mono-card-accent: var(--mono-card-accent, var(--_mono-card-accent-preset, var(--neutral)));\r\n /* ring-1 ring-foreground/10 — Basecoat rings the card, it does not border it;\r\n `bordered` adds a real border on top (EXTENSION) */\r\n --_mono-card-ring-color: var(--mono-card-ring-color, color-mix(in oklab, var(--foreground) 10%, transparent));\r\n --_mono-card-ring-width: var(--mono-card-ring-width, var(--mono-border-width));\r\n --_mono-card-shadow: var(--mono-card-shadow, var(--mono-shadow-xs));\r\n --_mono-card-shadow-elevated: var(--mono-card-shadow-elevated, var(--mono-shadow-md));\r\n --_mono-card-shadow-hover: var(--mono-card-shadow-hover, var(--mono-shadow-lg));\r\n /* the ONE knob a prop also drives: `rounded` writes --_mono-card-radius-preset\r\n on the element, so a FLAVOR must write that same preset tier (an inherited\r\n preset loses to the element's own) while --mono-card-radius stays the\r\n consumer's override and wins over both */\r\n --_mono-card-radius: var(--mono-card-radius, var(--_mono-card-radius-preset, var(--mono-radius-xl)));\r\n --_mono-card-border-width: var(--mono-card-border-width, var(--mono-border-width));\r\n --_mono-card-border-color: var(--mono-card-border-color, var(--border));\r\n --_mono-card-divider-color: var(--mono-card-divider-color, var(--border));\r\n --_mono-card-focus-ring-color: var(--mono-card-focus-ring-color, var(--ring));\r\n --_mono-card-focus-ring-width: var(--mono-card-focus-ring-width, var(--mono-ring-width));\r\n --_mono-card-focus-ring-alpha: var(--mono-card-focus-ring-alpha, var(--mono-ring-alpha));\r\n\r\n /* ── md metrics live on the unqualified root ON PURPOSE ────────────────────\r\n basecoat@1.0.2 styles/vega.css .card — gap-6 py-6 text-sm; .card > header —\r\n gap-1 px-6; .card > section / > footer — px-6 */\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-md, calc(var(--mono-spacing) * 6)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-md, calc(var(--mono-spacing) * 6)));\r\n --_mono-card-header-gap: var(--mono-card-header-gap, var(--mono-card-header-gap-md, calc(var(--mono-spacing) * 1)));\r\n --_mono-card-actions-gap: var(--mono-card-actions-gap, var(--mono-card-actions-gap-md, calc(var(--mono-spacing) * 2)));\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-md, var(--mono-text-sm)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-md, var(--mono-text-base)));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-md, var(--mono-text-sm)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-md, calc(var(--mono-spacing) * 9)));\r\n --_mono-card-icon-glyph: var(--mono-card-icon-glyph, 55%);\r\n\r\n /* The edge and the elevation are independent, so a variant can drop one\r\n without touching the other.\r\n\r\n DEVIATION from upstream: Basecoat draws the edge with `ring-1`, a box-shadow\r\n OUTSIDE the border box. That pixel is lost wherever the card is flush against\r\n anything that clips — a container with `overflow: hidden` (every demo stage),\r\n a horizontal scroller, or the viewport itself — which hid the left edge of a\r\n full-width card at most widths. The same hairline drawn INSIDE the box is\r\n unclippable: an INSET box-shadow, layered under the elevation. (It used to\r\n be an outline with a negative offset; an outline is rasterised as a stroke\r\n of its own, and on fractional display scales it landed one device pixel\r\n inside the background's edge, so the card read as a DOUBLE border. An inset\r\n shadow is part of the background's own box and cannot separate from it.)\r\n It paints under the descendants, so a full-bleed child must stop one\r\n edge-width short of the box, or cover it knowingly. */\r\n --_mono-card-edge-width: var(--_mono-card-ring-width);\r\n --_mono-card-edge-color: var(--_mono-card-ring-color);\r\n --_mono-card-elevation: var(--_mono-card-shadow);\r\n\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--_mono-card-gap);\r\n position: relative;\r\n min-width: 0;\r\n padding-block: var(--_mono-card-padding);\r\n overflow: hidden;\r\n border-radius: var(--_mono-card-radius);\r\n background-color: var(--_mono-card-bg);\r\n color: var(--_mono-card-text);\r\n font-family: inherit;\r\n font-size: var(--_mono-card-font);\r\n box-shadow:\r\n inset 0 0 0 var(--_mono-card-edge-width) var(--_mono-card-edge-color),\r\n var(--_mono-card-elevation);\r\n text-decoration: none;\r\n transition-property: background-color, border-color, box-shadow, transform, opacity;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration);\r\n}\r\n\r\n[mono-card],\r\n:where([mono-card]) *,\r\n:where([mono-card]) *::before,\r\n:where([mono-card]) *::after {\r\n box-sizing: border-box;\r\n}\r\n\r\n/* The shadow build renders EVERY region up front (so DSD can project into them\r\n server-side) and marks the ones with nothing in them; the light build renders\r\n only what exists. Hiding them here is what keeps the two builds identical —\r\n and why the media rules below test `:not([mono-empty])`.\r\n\r\n NOT wrapped in `:where()`, unlike the other parts: a region rule such as\r\n `[mono-header] > [mono-icon]` is two attributes strong, so a zero-weight hide\r\n would tie and lose on source order — the icon box kept its 36px in the shadow\r\n build while the light one rendered nothing at all. */\r\n[mono-card] :is(\r\n [mono-media],\r\n [mono-header],\r\n [mono-icon],\r\n [mono-title],\r\n [mono-subtitle],\r\n [mono-body],\r\n [mono-actions],\r\n [mono-footer]\r\n)[mono-empty] {\r\n display: none;\r\n}\r\n\r\n/* =========================================\r\n Sizes — `sm` is upstream's data-size='sm'; the rest continue the ladder\r\n ========================================= */\r\n\r\n[mono-card][mono-size=\"xs\"] {\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-xs, calc(var(--mono-spacing) * 2.5)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-xs, calc(var(--mono-spacing) * 2.5)));\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-xs, var(--mono-text-xs)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-xs, 0.8125rem));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-xs, var(--mono-text-xs)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-xs, calc(var(--mono-spacing) * 6)));\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .card[data-size='sm'] — gap-4 py-4 (px-4 on every region) */\r\n[mono-card][mono-size=\"sm\"] {\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-sm, calc(var(--mono-spacing) * 4)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-sm, calc(var(--mono-spacing) * 4)));\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-sm, var(--mono-text-sm)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-sm, var(--mono-text-sm)));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-sm, var(--mono-text-sm)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-sm, calc(var(--mono-spacing) * 7.5)));\r\n}\r\n\r\n[mono-card][mono-size=\"lg\"] {\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-lg, calc(var(--mono-spacing) * 7)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-lg, calc(var(--mono-spacing) * 7)));\r\n /* lg keeps md's body and subtitle type by DEFAULT, but still reads its own\r\n knobs — every step of the ladder has to be settable, or a flavor's value is\r\n silently inert (the theme lint catches that). */\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-lg, var(--mono-text-sm)));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-lg, var(--mono-text-sm)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-lg, var(--mono-text-lg)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-lg, calc(var(--mono-spacing) * 10)));\r\n}\r\n\r\n[mono-card][mono-size=\"xl\"] {\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-xl, calc(var(--mono-spacing) * 8)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-xl, calc(var(--mono-spacing) * 8)));\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-xl, var(--mono-text-base)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-xl, var(--mono-text-xl)));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-xl, var(--mono-text-base)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-xl, calc(var(--mono-spacing) * 11)));\r\n}\r\n\r\n[mono-card][mono-size=\"xxl\"] {\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-xxl, calc(var(--mono-spacing) * 9)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-xxl, calc(var(--mono-spacing) * 9)));\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-xxl, var(--mono-text-base)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-xxl, calc(var(--mono-text-xl) * 1.125)));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-xxl, var(--mono-text-lg)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-xxl, calc(var(--mono-spacing) * 12)));\r\n}\r\n\r\n/* =========================================\r\n Corners — the library-wide radius scale\r\n ========================================= */\r\n\r\n[mono-card][mono-rounded=\"none\"] {\r\n --_mono-card-radius-preset: 0;\r\n}\r\n[mono-card][mono-rounded=\"xs\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-sm);\r\n}\r\n[mono-card][mono-rounded=\"sm\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-sm);\r\n}\r\n[mono-card][mono-rounded=\"md\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-md);\r\n}\r\n[mono-card][mono-rounded=\"lg\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-lg);\r\n}\r\n[mono-card][mono-rounded=\"xl\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-xl);\r\n}\r\n[mono-card][mono-rounded=\"xxl\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-2xl);\r\n}\r\n[mono-card][mono-rounded=\"full\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-full);\r\n}\r\n\r\n/* =========================================\r\n Colours — EXTENSION: the ring and the title take the role's colour\r\n ========================================= */\r\n\r\n[mono-card][mono-color=\"primary\"] {\r\n --_mono-card-accent-preset: var(--primary);\r\n}\r\n[mono-card][mono-color=\"secondary\"] {\r\n --_mono-card-accent-preset: var(--secondary-foreground);\r\n}\r\n[mono-card][mono-color=\"success\"] {\r\n --_mono-card-accent-preset: var(--success);\r\n}\r\n[mono-card][mono-color=\"danger\"] {\r\n --_mono-card-accent-preset: var(--destructive);\r\n}\r\n[mono-card][mono-color=\"warning\"] {\r\n --_mono-card-accent-preset: var(--warning);\r\n}\r\n[mono-card][mono-color=\"info\"] {\r\n --_mono-card-accent-preset: var(--info);\r\n}\r\n[mono-card][mono-color=\"teal\"] {\r\n --_mono-card-accent-preset: var(--teal);\r\n}\r\n[mono-card][mono-color=\"purple\"] {\r\n --_mono-card-accent-preset: var(--purple);\r\n}\r\n[mono-card][mono-color=\"dark\"] {\r\n --_mono-card-accent-preset: var(--dark);\r\n}\r\n[mono-card][mono-color=\"neutral\"] {\r\n --_mono-card-accent-preset: var(--neutral);\r\n}\r\n[mono-card][mono-color=\"light\"] {\r\n --_mono-card-accent-preset: var(--muted-foreground);\r\n}\r\n\r\n/* =========================================\r\n Variants\r\n ========================================= */\r\n\r\n/* `outlined` IS upstream's `.card`: the ring and shadow-xs already on the root */\r\n[mono-card][mono-variant=\"outlined\"] {\r\n --_mono-card-ring-color: var(--mono-card-ring-color, color-mix(in oklab, var(--_mono-card-accent) 34%, transparent));\r\n}\r\n\r\n/* EXTENSION — a lifted card; the ring stays, the elevation grows */\r\n[mono-card]:is(:not([mono-variant]), [mono-variant=\"elevated\"]) {\r\n --_mono-card-elevation: var(--_mono-card-shadow-elevated);\r\n}\r\n\r\n/* EXTENSION — no elevation at all */\r\n[mono-card][mono-variant=\"flat\"] {\r\n --_mono-card-elevation: 0 0 #0000;\r\n}\r\n\r\n/* EXTENSION — an accent wash (flat tint, never a gradient) */\r\n[mono-card][mono-variant=\"tonal\"] {\r\n --_mono-card-elevation: 0 0 #0000;\r\n --_mono-card-ring-color: var(--mono-card-ring-color, color-mix(in oklab, var(--_mono-card-accent) 22%, transparent));\r\n background-color: color-mix(in oklab, var(--_mono-card-accent) var(--mono-mode-tint), var(--_mono-card-bg));\r\n}\r\n\r\n/* EXTENSION — a blurred pane over whatever is behind it */\r\n[mono-card][mono-variant=\"glass\"] {\r\n --_mono-card-elevation: var(--mono-shadow-lg);\r\n --_mono-card-ring-color: var(--mono-card-glass-border, color-mix(in oklab, var(--foreground) 12%, transparent));\r\n background-color: var(--mono-card-glass-bg, color-mix(in oklab, var(--card) 45%, transparent));\r\n backdrop-filter: blur(var(--mono-card-glass-blur, 12px));\r\n}\r\n\r\n/* =========================================\r\n States\r\n ========================================= */\r\n\r\n/* EXTENSION — a real border on top of the ring */\r\n[mono-card][mono-bordered] {\r\n border: var(--_mono-card-border-width) solid var(--_mono-card-border-color);\r\n}\r\n\r\n[mono-card][mono-clickable] {\r\n cursor: pointer;\r\n}\r\n\r\n@media (hover: hover) {\r\n [mono-card]:is([mono-hoverable], [mono-clickable]):not([mono-disabled]):hover {\r\n --_mono-card-elevation: var(--_mono-card-shadow-hover);\r\n }\r\n}\r\n\r\n/* EXTENSION — the chosen card, in the accent (Basecoat's own `has-[:checked]`\r\n treatment for a selectable label: primary/5 with a primary/30 edge) */\r\n[mono-card][mono-selected] {\r\n --_mono-card-edge-color: color-mix(in oklab, var(--_mono-card-accent) var(--mono-mode-checked-border), transparent);\r\n --_mono-card-edge-width: calc(var(--mono-border-width) * 2);\r\n background-color: color-mix(in oklab, var(--_mono-card-accent) var(--mono-mode-checked-bg), var(--_mono-card-bg));\r\n}\r\n\r\n[mono-card][mono-disabled] {\r\n cursor: not-allowed;\r\n opacity: 0.5;\r\n pointer-events: none;\r\n}\r\n\r\n/* the focus ring is that same inside edge, recoloured and thickened — an\r\n outside ring would be clipped exactly where the resting one was */\r\n[mono-card]:focus-visible {\r\n --_mono-card-edge-width: var(--_mono-card-focus-ring-width);\r\n --_mono-card-edge-color: color-mix(in oklab, var(--_mono-card-focus-ring-color) var(--_mono-card-focus-ring-alpha), transparent);\r\n}\r\n\r\n/* =========================================\r\n Regions — every one of them is inset by the card's padding, which is how\r\n upstream does it (`px-6` per region, `py-6` on the card) so a media band can\r\n run full-bleed between them\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 components/card.css .card >> > header\r\n — grid auto-rows-min items-start (grid-cols-[1fr_auto] when an action is present) */\r\n/* basecoat@1.0.2 styles/vega.css .card > header — gap-1 px-6 */\r\n:where([mono-card]) > [mono-header] {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: var(--_mono-card-actions-gap);\r\n padding-inline: var(--_mono-card-padding);\r\n}\r\n\r\n:where([mono-card]) > [mono-header] > [mono-header-content] {\r\n display: grid;\r\n align-content: start;\r\n gap: var(--_mono-card-header-gap);\r\n min-width: 0;\r\n flex: 1 1 auto;\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .card > header > :is(h2, h3, [data-title], .card-title)\r\n — text-base leading-normal font-medium (upstream also sets `leading-none` in\r\n components/card.css; vega's `leading-normal` wins) */\r\n:where([mono-card]) [mono-title] {\r\n margin: 0;\r\n font-size: var(--_mono-card-title-font);\r\n line-height: var(--mono-card-title-line-height, var(--mono-leading-normal));\r\n font-weight: var(--mono-card-title-font-weight, var(--mono-font-weight-medium));\r\n letter-spacing: var(--mono-card-title-tracking, normal);\r\n text-transform: var(--mono-card-title-transform, none);\r\n color: var(--mono-card-title-color, var(--_mono-card-text));\r\n}\r\n\r\n/* the colour prop tints the title, nothing else — `color` is an accent, not a fill */\r\n[mono-card][mono-color]:not([mono-color=\"neutral\"]) [mono-title] {\r\n color: var(--mono-card-title-color, var(--_mono-card-accent));\r\n}\r\n\r\n/* A heading handed in as <h2>/<h3>/<p> brings its own margins and type, and a\r\n host page styles those tags too (`.vp-doc h3` is a class selector, so it beats\r\n any sane rule here). The card OWNS the header type — Basecoat's own\r\n `.card > header > :is(h2, h3, …)` does the same — so both twins are important:\r\n the light one to beat the page, the slotted one because an inner-tree rule\r\n cannot otherwise reach outer-tree content at all. */\r\n:where([mono-card]) :is([mono-title], [mono-subtitle]) > * {\r\n margin: 0 !important;\r\n font: inherit !important;\r\n letter-spacing: inherit !important;\r\n color: inherit !important;\r\n}\r\n\r\n:where([mono-card]) :is([mono-title], [mono-subtitle]) slot::slotted(*) {\r\n margin: 0 !important;\r\n font: inherit !important;\r\n letter-spacing: inherit !important;\r\n color: inherit !important;\r\n}\r\n\r\n[mono-card] :is(h1, h2, h3, h4, h5, h6, p, small)[mono-title] {\r\n margin: 0;\r\n font-size: var(--_mono-card-title-font);\r\n line-height: var(--mono-card-title-line-height, var(--mono-leading-normal));\r\n font-weight: var(--mono-card-title-font-weight, var(--mono-font-weight-medium));\r\n letter-spacing: var(--mono-card-title-tracking, normal);\r\n}\r\n\r\n[mono-card] :is(h1, h2, h3, h4, h5, h6, p, small)[mono-subtitle] {\r\n margin: 0;\r\n font-size: var(--_mono-card-subtitle-font);\r\n line-height: var(--mono-card-subtitle-line-height, var(--mono-leading-normal));\r\n font-weight: var(--mono-font-weight-normal);\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .card > header > :is(p, [data-description], .card-description)\r\n — text-muted-foreground text-sm */\r\n:where([mono-card]) [mono-subtitle] {\r\n margin: 0;\r\n font-size: var(--_mono-card-subtitle-font);\r\n line-height: var(--mono-card-subtitle-line-height, var(--mono-leading-normal));\r\n font-weight: var(--mono-font-weight-normal);\r\n color: var(--_mono-card-subtext);\r\n}\r\n\r\n/* EXTENSION — the header's leading glyph box */\r\n:where([mono-card]) > [mono-header] > [mono-icon] {\r\n flex: 0 0 auto;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: var(--_mono-card-icon-size);\r\n height: var(--_mono-card-icon-size);\r\n border-radius: var(--mono-card-icon-radius, var(--mono-radius-md));\r\n line-height: 1;\r\n background-color: color-mix(in oklab, var(--_mono-card-accent) var(--mono-mode-tint), transparent);\r\n color: var(--_mono-card-accent);\r\n overflow: hidden;\r\n}\r\n\r\n/* `:not(slot)`: in the shadow build the region's only child IS a <slot>, a real\r\n element that this rule would size — and then `::slotted()` would size the\r\n glyph again, to 55% of that 55%. The glyph came out half the size of its light\r\n twin. */\r\n:where([mono-card]) > [mono-header] > [mono-icon] > *:not(slot) {\r\n display: block;\r\n width: var(--_mono-card-icon-glyph);\r\n height: var(--_mono-card-icon-glyph);\r\n}\r\n\r\n:where([mono-card]) > [mono-header] > [mono-icon] slot::slotted(*) {\r\n display: block !important;\r\n width: var(--_mono-card-icon-glyph) !important;\r\n height: var(--_mono-card-icon-glyph) !important;\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .card > section — px-6 */\r\n:where([mono-card]) > [mono-body] {\r\n padding-inline: var(--_mono-card-padding);\r\n min-width: 0;\r\n}\r\n\r\n[mono-card] > :is(p, ul, ol, dl, blockquote)[mono-body] {\r\n margin-block: 0;\r\n}\r\n\r\n:where([mono-card]) > [mono-body]:empty {\r\n display: none;\r\n}\r\n\r\n/* The body's own children keep their block margins out of the card's rhythm —\r\n the card's `gap` is what spaces the regions, and content that wants paragraph\r\n spacing brings its own.\r\n\r\n ALL children, not just the first and last: in the shadow build `::slotted()`\r\n sees the HOST's child order, so `:first-child` there means \"first child of the\r\n card element\" — a body paragraph that follows a `slot=\"title\"` heading is not\r\n first, and kept the page's margins while its light twin did not.\r\n\r\n `!important` on the slotted twins is not a style choice: a `::slotted()` rule\r\n is an INNER-tree declaration, and a normal declaration from the outer tree (a\r\n page's `p { margin: … }`) beats it at any specificity. Marking it important\r\n inverts that order. The light twins need no such thing — they are ordinary\r\n descendant rules in the same tree as the page. */\r\n:where([mono-card]) > [mono-body] > * {\r\n margin-block: 0 !important;\r\n}\r\n\r\n:where([mono-card]) > [mono-body] slot::slotted(*) {\r\n margin-block: 0 !important;\r\n}\r\n\r\n/* basecoat@1.0.2 components/card.css .card >> > footer — flex items-center */\r\n/* basecoat@1.0.2 styles/vega.css .card > footer — rounded-b-xl px-6 [.border-t]:pt-6 */\r\n:where([mono-card]) > :is([mono-actions], [mono-footer]) {\r\n display: flex;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n gap: var(--_mono-card-actions-gap);\r\n padding-inline: var(--_mono-card-padding);\r\n}\r\n\r\n:where([mono-card]) > [mono-actions] {\r\n justify-content: flex-end;\r\n}\r\n\r\n/* the dividers: upstream's `[.border-b]:pb-6` idiom — a divided region pays the\r\n padding back on the divided edge. Both are ON by default, so the ATTRIBUTE\r\n marks the exception. */\r\n[mono-card]:not([mono-no-header-divider]) > [mono-header]:not([mono-empty]) {\r\n padding-bottom: var(--_mono-card-padding);\r\n border-bottom: var(--mono-border-width) solid var(--_mono-card-divider-color);\r\n}\r\n\r\n[mono-card]:not([mono-no-footer-divider]) > :is([mono-actions], [mono-footer]):not([mono-empty]) {\r\n padding-top: var(--_mono-card-padding);\r\n border-top: var(--mono-border-width) solid var(--_mono-card-divider-color);\r\n}\r\n\r\n/* =========================================\r\n Media — a full-bleed band; upstream gives the first/last child image the\r\n card's own corners and drops the padding on that edge\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .card\r\n — has-[>img:first-child]:pt-0 [&>img:first-child]:rounded-t-xl [&>img:last-child]:rounded-b-xl */\r\n:where([mono-card]) > [mono-media] {\r\n display: block;\r\n overflow: hidden;\r\n line-height: 0;\r\n}\r\n\r\n:where([mono-card]) > [mono-media] :is(img, picture, video, canvas, svg) {\r\n display: block;\r\n width: 100%;\r\n max-width: 100%;\r\n height: auto;\r\n object-fit: cover;\r\n}\r\n\r\n:where([mono-card]) > [mono-media] slot::slotted(:is(img, picture, video, canvas, svg)) {\r\n display: block !important;\r\n width: 100% !important;\r\n max-width: 100% !important;\r\n height: auto !important;\r\n object-fit: cover !important;\r\n}\r\n\r\n[mono-card]:has(> [mono-media]:not([mono-empty]):first-child) {\r\n padding-top: 0;\r\n}\r\n\r\n[mono-card]:has(> [mono-media]:not([mono-empty]):last-child) {\r\n padding-bottom: 0;\r\n}\r\n\r\n/* =========================================\r\n Loading — EXTENSION: a blurred veil with a spinner\r\n ========================================= */\r\n\r\n:where([mono-card]) > [mono-loading] {\r\n position: absolute;\r\n inset: 0;\r\n z-index: 2;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background-color: var(--mono-card-loading-bg, color-mix(in oklab, var(--card) 58%, transparent));\r\n backdrop-filter: blur(var(--mono-card-loading-blur, 2px));\r\n}\r\n\r\n:where([mono-card]) [mono-spinner] {\r\n display: block;\r\n width: var(--mono-card-spinner-size, calc(var(--mono-spacing) * 5.5));\r\n height: var(--mono-card-spinner-size, calc(var(--mono-spacing) * 5.5));\r\n border: var(--mono-card-spinner-width, 2px) solid color-mix(in oklab, var(--_mono-card-accent) 25%, transparent);\r\n border-top-color: var(--_mono-card-accent);\r\n border-radius: var(--mono-radius-full);\r\n animation: mono-card-spin var(--mono-card-spinner-speed, 0.65s) linear infinite;\r\n}\r\n\r\n@keyframes mono-card-spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n@media (prefers-reduced-motion: reduce) {\r\n [mono-card] {\r\n transition: none;\r\n }\r\n\r\n :where([mono-card]) [mono-spinner] {\r\n animation-duration: 2.4s;\r\n }\r\n}\r\n";
|
|
280
|
+
var card_default = "/* =========================================================================\r\n mono-card — a port of Basecoat's `.card` (basecoat-css@1.0.2, vega style).\r\n\r\n Styled by ATTRIBUTE, like Basecoat — and the attributes mirror the element's\r\n props one for one, so hand-written markup reads like the Lit / Vue tag:\r\n\r\n <mono-card size=\"sm\" variant=\"outlined\" color=\"primary\" title=\"Title\">\r\n <div mono-card mono-size=\"sm\" mono-variant=\"outlined\" mono-color=\"primary\">\r\n <div mono-header>\r\n <div mono-header-content><h3 mono-title>Title</h3></div>\r\n </div>\r\n <div mono-body><p>…</p></div>\r\n <div mono-footer>…</div>\r\n </div>\r\n\r\n An absent attribute is the prop's default (`:not([mono-size])` = md,\r\n `:not([mono-variant])` = elevated, `:not([mono-color])` = neutral). The element\r\n renders these attributes on its root (both builds) plus the STATES\r\n `mono-bordered` / `mono-hoverable` / `mono-clickable` / `mono-selected` /\r\n `mono-disabled` / `mono-loading`, and the negatives `mono-no-header-divider` /\r\n `mono-no-footer-divider` (both dividers default ON, so the attribute marks the\r\n exception). The old classes (`.mono-card.md.elevated.primary`) are still\r\n emitted as inert hooks until 2.0 but no rule here reads them.\r\n\r\n Selector map (ours ≡ upstream):\r\n [mono-card] ≡ .card (flex-col gap-6 py-6 rounded-xl bg-card text-card-foreground text-sm shadow-xs ring-1 ring-foreground/10 overflow-hidden)\r\n — the ring is drawn as an INSET box-shadow, see --_mono-card-edge-*\r\n [mono-card] > [mono-header] ≡ .card > header (grid auto-rows-min gap-1 px-6)\r\n [mono-title] ≡ .card > header > :is(h2, h3, [data-title], .card-title) (text-base font-medium leading-normal)\r\n [mono-subtitle] ≡ .card > header > :is(p, [data-description], .card-description) (text-sm text-muted-foreground)\r\n [mono-body] ≡ .card > section (px-6)\r\n [mono-footer] / [mono-actions] ≡ .card > footer (flex items-center px-6)\r\n [mono-size=\"sm\"] ≡ .card[data-size='sm'] (gap-4 py-4, px-4 on every region)\r\n [mono-size=\"xs|lg|xl|xxl\"] ≡ EXTENSION (the same ladder continued)\r\n [mono-variant=\"outlined\"] ≡ .card verbatim (the ring + shadow-xs)\r\n [mono-variant=\"elevated|flat|tonal|glass\"] ≡ EXTENSION (shadow-md / none / an accent tint / a blurred pane)\r\n [mono-color=\"…\"] ≡ EXTENSION (the ring and the title in the role's colour)\r\n [mono-media] ≡ .card [&>img:first-child]:rounded-t-xl — a full-bleed media band\r\n [mono-icon], [mono-loading], [mono-selected] ≡ EXTENSION\r\n\r\n `gradient` is GONE (variant and colour alike): the port drops every colour\r\n gradient. `--mono-card-gradient-*` are no-ops until 2.0.\r\n\r\n Specificity contract (same as the pre-port class sheet): a part's RESTING rule\r\n is exactly one attribute strong — `:where([mono-card]) [mono-body]` = (0,1,0)\r\n — so a utility class handed in through `cssClass` wins by source order, while\r\n prop and state rules stay heavier and win over it.\r\n\r\n Inner parts: [mono-media], [mono-header] > [mono-icon] / [mono-header-content]\r\n > [mono-title] / [mono-subtitle], [mono-body], [mono-actions], [mono-footer],\r\n [mono-loading] > [mono-spinner]. The shadow build renders every region and\r\n marks the empty ones [mono-empty]; this sheet hides them.\r\n\r\n FLAVORS set `--mono-card-{radius,shadow,ring-color,ring-width,padding-<size>,\r\n gap-<size>,title-font-<size>,…}` (the per-style `.card` deltas); every fallback\r\n here is vega's value (`node scripts/basecoat-styles.mjs --varying \"^\\.card\"`).\r\n ========================================================================= */\r\n\r\nmono-card {\r\n display: block;\r\n}\r\n\r\n[mono-card] {\r\n /* ── palette: each slot is a public knob over a Basecoat token ─────────── */\r\n --_mono-card-bg: var(--mono-card-bg, var(--card));\r\n --_mono-card-text: var(--mono-card-text, var(--card-foreground));\r\n --_mono-card-subtext: var(--mono-card-subtext, var(--muted-foreground));\r\n --_mono-card-accent: var(--mono-card-accent, var(--_mono-card-accent-preset, var(--neutral)));\r\n /* ring-1 ring-foreground/10 — Basecoat rings the card, it does not border it;\r\n `bordered` adds a real border on top (EXTENSION) */\r\n --_mono-card-ring-color: var(--mono-card-ring-color, color-mix(in oklab, var(--foreground) 10%, transparent));\r\n --_mono-card-ring-width: var(--mono-card-ring-width, var(--mono-border-width));\r\n --_mono-card-shadow: var(--mono-card-shadow, var(--mono-shadow-xs));\r\n --_mono-card-shadow-elevated: var(--mono-card-shadow-elevated, var(--mono-shadow-md));\r\n --_mono-card-shadow-hover: var(--mono-card-shadow-hover, var(--mono-shadow-lg));\r\n /* the ONE knob a prop also drives: `rounded` writes --_mono-card-radius-preset\r\n on the element, so a FLAVOR must write that same preset tier (an inherited\r\n preset loses to the element's own) while --mono-card-radius stays the\r\n consumer's override and wins over both */\r\n --_mono-card-radius: var(--mono-card-radius, var(--_mono-card-radius-preset, var(--mono-radius-xl)));\r\n --_mono-card-border-width: var(--mono-card-border-width, var(--mono-border-width));\r\n --_mono-card-border-color: var(--mono-card-border-color, var(--border));\r\n --_mono-card-divider-color: var(--mono-card-divider-color, var(--border));\r\n --_mono-card-focus-ring-color: var(--mono-card-focus-ring-color, var(--ring));\r\n --_mono-card-focus-ring-width: var(--mono-card-focus-ring-width, var(--mono-ring-width));\r\n --_mono-card-focus-ring-alpha: var(--mono-card-focus-ring-alpha, var(--mono-ring-alpha));\r\n\r\n /* ── md metrics live on the unqualified root ON PURPOSE ────────────────────\r\n basecoat@1.0.2 styles/vega.css .card — gap-6 py-6 text-sm; .card > header —\r\n gap-1 px-6; .card > section / > footer — px-6 */\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-md, calc(var(--mono-spacing) * 6)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-md, calc(var(--mono-spacing) * 6)));\r\n --_mono-card-header-gap: var(--mono-card-header-gap, var(--mono-card-header-gap-md, calc(var(--mono-spacing) * 1)));\r\n --_mono-card-actions-gap: var(--mono-card-actions-gap, var(--mono-card-actions-gap-md, calc(var(--mono-spacing) * 2)));\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-md, var(--mono-text-sm)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-md, var(--mono-text-base)));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-md, var(--mono-text-sm)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-md, calc(var(--mono-spacing) * 9)));\r\n --_mono-card-icon-glyph: var(--mono-card-icon-glyph, 55%);\r\n\r\n /* The edge and the elevation are independent, so a variant can drop one\r\n without touching the other.\r\n\r\n DEVIATION from upstream: Basecoat draws the edge with `ring-1`, a box-shadow\r\n OUTSIDE the border box. That pixel is lost wherever the card is flush against\r\n anything that clips — a container with `overflow: hidden` (every demo stage),\r\n a horizontal scroller, or the viewport itself — which hid the left edge of a\r\n full-width card at most widths. The same hairline drawn INSIDE the box is\r\n unclippable: an INSET box-shadow, layered under the elevation. (It used to\r\n be an outline with a negative offset; an outline is rasterised as a stroke\r\n of its own, and on fractional display scales it landed one device pixel\r\n inside the background's edge, so the card read as a DOUBLE border. An inset\r\n shadow is part of the background's own box and cannot separate from it.)\r\n It paints under the descendants, so a full-bleed child must stop one\r\n edge-width short of the box, or cover it knowingly. */\r\n --_mono-card-edge-width: var(--_mono-card-ring-width);\r\n --_mono-card-edge-color: var(--_mono-card-ring-color);\r\n --_mono-card-elevation: var(--_mono-card-shadow);\r\n\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--_mono-card-gap);\r\n position: relative;\r\n min-width: 0;\r\n padding-block: var(--_mono-card-padding);\r\n overflow: hidden;\r\n border-radius: var(--_mono-card-radius);\r\n background-color: var(--_mono-card-bg);\r\n color: var(--_mono-card-text);\r\n font-family: inherit;\r\n font-size: var(--_mono-card-font);\r\n box-shadow:\r\n inset 0 0 0 var(--_mono-card-edge-width) var(--_mono-card-edge-color),\r\n var(--_mono-card-elevation);\r\n text-decoration: none;\r\n transition-property: background-color, border-color, box-shadow, transform, opacity;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration);\r\n}\r\n\r\n[mono-card],\r\n:where([mono-card]) *,\r\n:where([mono-card]) *::before,\r\n:where([mono-card]) *::after {\r\n box-sizing: border-box;\r\n}\r\n\r\n/* The shadow build renders EVERY region up front (so DSD can project into them\r\n server-side) and marks the ones with nothing in them; the light build renders\r\n only what exists. Hiding them here is what keeps the two builds identical —\r\n and why the media rules below test `:not([mono-empty])`.\r\n\r\n NOT wrapped in `:where()`, unlike the other parts: a region rule such as\r\n `[mono-header] > [mono-icon]` is two attributes strong, so a zero-weight hide\r\n would tie and lose on source order — the icon box kept its 36px in the shadow\r\n build while the light one rendered nothing at all. */\r\n[mono-card] :is(\r\n [mono-media],\r\n [mono-header],\r\n [mono-icon],\r\n [mono-title],\r\n [mono-subtitle],\r\n [mono-body],\r\n [mono-actions],\r\n [mono-footer]\r\n)[mono-empty] {\r\n display: none;\r\n}\r\n\r\n/* =========================================\r\n Sizes — `sm` is upstream's data-size='sm'; the rest continue the ladder\r\n ========================================= */\r\n\r\n[mono-card][mono-size=\"xs\"] {\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-xs, calc(var(--mono-spacing) * 2.5)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-xs, calc(var(--mono-spacing) * 2.5)));\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-xs, var(--mono-text-xs)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-xs, 0.8125rem));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-xs, var(--mono-text-xs)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-xs, calc(var(--mono-spacing) * 6)));\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .card[data-size='sm'] — gap-4 py-4 (px-4 on every region) */\r\n[mono-card][mono-size=\"sm\"] {\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-sm, calc(var(--mono-spacing) * 4)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-sm, calc(var(--mono-spacing) * 4)));\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-sm, var(--mono-text-sm)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-sm, var(--mono-text-sm)));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-sm, var(--mono-text-sm)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-sm, calc(var(--mono-spacing) * 7.5)));\r\n}\r\n\r\n[mono-card][mono-size=\"lg\"] {\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-lg, calc(var(--mono-spacing) * 7)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-lg, calc(var(--mono-spacing) * 7)));\r\n /* lg keeps md's body and subtitle type by DEFAULT, but still reads its own\r\n knobs — every step of the ladder has to be settable, or a flavor's value is\r\n silently inert (the theme lint catches that). */\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-lg, var(--mono-text-sm)));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-lg, var(--mono-text-sm)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-lg, var(--mono-text-lg)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-lg, calc(var(--mono-spacing) * 10)));\r\n}\r\n\r\n[mono-card][mono-size=\"xl\"] {\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-xl, calc(var(--mono-spacing) * 8)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-xl, calc(var(--mono-spacing) * 8)));\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-xl, var(--mono-text-base)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-xl, var(--mono-text-xl)));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-xl, var(--mono-text-base)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-xl, calc(var(--mono-spacing) * 11)));\r\n}\r\n\r\n[mono-card][mono-size=\"xxl\"] {\r\n --_mono-card-padding: var(--mono-card-padding, var(--mono-card-padding-xxl, calc(var(--mono-spacing) * 9)));\r\n --_mono-card-gap: var(--mono-card-gap, var(--mono-card-gap-xxl, calc(var(--mono-spacing) * 9)));\r\n --_mono-card-font: var(--mono-card-font, var(--mono-card-font-xxl, var(--mono-text-base)));\r\n --_mono-card-title-font: var(--mono-card-title-font, var(--mono-card-title-font-xxl, calc(var(--mono-text-xl) * 1.125)));\r\n --_mono-card-subtitle-font: var(--mono-card-subtitle-font, var(--mono-card-subtitle-font-xxl, var(--mono-text-lg)));\r\n --_mono-card-icon-size: var(--mono-card-icon-size, var(--mono-card-icon-size-xxl, calc(var(--mono-spacing) * 12)));\r\n}\r\n\r\n/* =========================================\r\n Corners — the library-wide radius scale\r\n ========================================= */\r\n\r\n[mono-card][mono-rounded=\"none\"] {\r\n --_mono-card-radius-preset: 0;\r\n}\r\n[mono-card][mono-rounded=\"xs\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-sm);\r\n}\r\n[mono-card][mono-rounded=\"sm\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-sm);\r\n}\r\n[mono-card][mono-rounded=\"md\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-md);\r\n}\r\n[mono-card][mono-rounded=\"lg\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-lg);\r\n}\r\n[mono-card][mono-rounded=\"xl\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-xl);\r\n}\r\n[mono-card][mono-rounded=\"xxl\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-2xl);\r\n}\r\n[mono-card][mono-rounded=\"full\"] {\r\n --_mono-card-radius-preset: var(--mono-radius-full);\r\n}\r\n\r\n/* =========================================\r\n Colours — EXTENSION: the ring and the title take the role's colour\r\n ========================================= */\r\n\r\n[mono-card][mono-color=\"primary\"] {\r\n --_mono-card-accent-preset: var(--primary);\r\n}\r\n[mono-card][mono-color=\"secondary\"] {\r\n --_mono-card-accent-preset: var(--secondary-foreground);\r\n}\r\n[mono-card][mono-color=\"success\"] {\r\n --_mono-card-accent-preset: var(--success);\r\n}\r\n[mono-card][mono-color=\"danger\"] {\r\n --_mono-card-accent-preset: var(--destructive);\r\n}\r\n[mono-card][mono-color=\"warning\"] {\r\n --_mono-card-accent-preset: var(--warning);\r\n}\r\n[mono-card][mono-color=\"info\"] {\r\n --_mono-card-accent-preset: var(--info);\r\n}\r\n[mono-card][mono-color=\"teal\"] {\r\n --_mono-card-accent-preset: var(--teal);\r\n}\r\n[mono-card][mono-color=\"purple\"] {\r\n --_mono-card-accent-preset: var(--purple);\r\n}\r\n[mono-card][mono-color=\"dark\"] {\r\n --_mono-card-accent-preset: var(--dark);\r\n}\r\n[mono-card][mono-color=\"neutral\"] {\r\n --_mono-card-accent-preset: var(--neutral);\r\n}\r\n[mono-card][mono-color=\"light\"] {\r\n --_mono-card-accent-preset: var(--muted-foreground);\r\n}\r\n\r\n/* =========================================\r\n Variants\r\n ========================================= */\r\n\r\n/* `outlined` IS upstream's `.card`: the ring and shadow-xs already on the root */\r\n[mono-card][mono-variant=\"outlined\"] {\r\n --_mono-card-ring-color: var(--mono-card-ring-color, color-mix(in oklab, var(--_mono-card-accent) 34%, transparent));\r\n}\r\n\r\n/* EXTENSION — a lifted card; the ring stays, the elevation grows */\r\n[mono-card]:is(:not([mono-variant]), [mono-variant=\"elevated\"]) {\r\n --_mono-card-elevation: var(--_mono-card-shadow-elevated);\r\n}\r\n\r\n/* EXTENSION — no elevation at all */\r\n[mono-card][mono-variant=\"flat\"] {\r\n --_mono-card-elevation: 0 0 #0000;\r\n}\r\n\r\n/* EXTENSION — an accent wash (flat tint, never a gradient) */\r\n[mono-card][mono-variant=\"tonal\"] {\r\n --_mono-card-elevation: 0 0 #0000;\r\n --_mono-card-ring-color: var(--mono-card-ring-color, color-mix(in oklab, var(--_mono-card-accent) 22%, transparent));\r\n background-color: color-mix(in oklab, var(--_mono-card-accent) var(--mono-mode-tint), var(--_mono-card-bg));\r\n}\r\n\r\n/* EXTENSION — a blurred pane over whatever is behind it */\r\n[mono-card][mono-variant=\"glass\"] {\r\n --_mono-card-elevation: var(--mono-shadow-lg);\r\n --_mono-card-ring-color: var(--mono-card-glass-border, color-mix(in oklab, var(--foreground) 12%, transparent));\r\n background-color: var(--mono-card-glass-bg, color-mix(in oklab, var(--card) 45%, transparent));\r\n backdrop-filter: blur(var(--mono-card-glass-blur, 12px));\r\n}\r\n\r\n/* =========================================\r\n States\r\n ========================================= */\r\n\r\n/* EXTENSION — a real border on top of the ring */\r\n[mono-card][mono-bordered] {\r\n border: var(--_mono-card-border-width) solid var(--_mono-card-border-color);\r\n}\r\n\r\n[mono-card][mono-clickable] {\r\n cursor: pointer;\r\n}\r\n\r\n@media (hover: hover) {\r\n [mono-card]:is([mono-hoverable], [mono-clickable]):not([mono-disabled]):hover {\r\n --_mono-card-elevation: var(--_mono-card-shadow-hover);\r\n }\r\n}\r\n\r\n/* EXTENSION — the chosen card, in the accent (Basecoat's own `has-[:checked]`\r\n treatment for a selectable label: primary/5 with a primary/30 edge) */\r\n[mono-card][mono-selected] {\r\n --_mono-card-edge-color: color-mix(in oklab, var(--_mono-card-accent) var(--mono-mode-checked-border), transparent);\r\n --_mono-card-edge-width: calc(var(--mono-border-width) * 2);\r\n background-color: color-mix(in oklab, var(--_mono-card-accent) var(--mono-mode-checked-bg), var(--_mono-card-bg));\r\n}\r\n\r\n[mono-card][mono-disabled] {\r\n cursor: not-allowed;\r\n opacity: 0.5;\r\n pointer-events: none;\r\n}\r\n\r\n/* the focus ring is that same inside edge, recoloured and thickened — an\r\n outside ring would be clipped exactly where the resting one was */\r\n[mono-card]:focus-visible {\r\n --_mono-card-edge-width: var(--_mono-card-focus-ring-width);\r\n --_mono-card-edge-color: color-mix(in oklab, var(--_mono-card-focus-ring-color) var(--_mono-card-focus-ring-alpha), transparent);\r\n}\r\n\r\n/* =========================================\r\n Regions — every one of them is inset by the card's padding, which is how\r\n upstream does it (`px-6` per region, `py-6` on the card) so a media band can\r\n run full-bleed between them\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 components/card.css .card >> > header\r\n — grid auto-rows-min items-start (grid-cols-[1fr_auto] when an action is present) */\r\n/* basecoat@1.0.2 styles/vega.css .card > header — gap-1 px-6 */\r\n:where([mono-card]) > [mono-header] {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: var(--_mono-card-actions-gap);\r\n padding-inline: var(--_mono-card-padding);\r\n}\r\n\r\n/* No subtitle: the title is a single line beside a taller icon chip, so\r\n top-aligning pinned it to the chip's top edge. Centre the row instead.\r\n With a subtitle the row stays top-aligned (icon level with the title). */\r\n:where([mono-card]) > [mono-header][mono-no-subtitle] {\r\n align-items: center;\r\n}\r\n\r\n:where([mono-card]) > [mono-header] > [mono-header-content] {\r\n display: grid;\r\n align-content: start;\r\n gap: var(--_mono-card-header-gap);\r\n min-width: 0;\r\n flex: 1 1 auto;\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .card > header > :is(h2, h3, [data-title], .card-title)\r\n — text-base leading-normal font-medium (upstream also sets `leading-none` in\r\n components/card.css; vega's `leading-normal` wins) */\r\n:where([mono-card]) [mono-title] {\r\n margin: 0;\r\n font-size: var(--_mono-card-title-font);\r\n line-height: var(--mono-card-title-line-height, var(--mono-leading-normal));\r\n font-weight: var(--mono-card-title-font-weight, var(--mono-font-weight-medium));\r\n letter-spacing: var(--mono-card-title-tracking, normal);\r\n text-transform: var(--mono-card-title-transform, none);\r\n color: var(--mono-card-title-color, var(--_mono-card-text));\r\n}\r\n\r\n/* the colour prop tints the title, nothing else — `color` is an accent, not a fill */\r\n[mono-card][mono-color]:not([mono-color=\"neutral\"]) [mono-title] {\r\n color: var(--mono-card-title-color, var(--_mono-card-accent));\r\n}\r\n\r\n/* A heading handed in as <h2>/<h3>/<p> brings its own margins and type, and a\r\n host page styles those tags too (`.vp-doc h3` is a class selector, so it beats\r\n any sane rule here). The card OWNS the header type — Basecoat's own\r\n `.card > header > :is(h2, h3, …)` does the same — so both twins are important:\r\n the light one to beat the page, the slotted one because an inner-tree rule\r\n cannot otherwise reach outer-tree content at all. */\r\n:where([mono-card]) :is([mono-title], [mono-subtitle]) > * {\r\n margin: 0 !important;\r\n font: inherit !important;\r\n letter-spacing: inherit !important;\r\n color: inherit !important;\r\n}\r\n\r\n:where([mono-card]) :is([mono-title], [mono-subtitle]) slot::slotted(*) {\r\n margin: 0 !important;\r\n font: inherit !important;\r\n letter-spacing: inherit !important;\r\n color: inherit !important;\r\n}\r\n\r\n[mono-card] :is(h1, h2, h3, h4, h5, h6, p, small)[mono-title] {\r\n margin: 0;\r\n font-size: var(--_mono-card-title-font);\r\n line-height: var(--mono-card-title-line-height, var(--mono-leading-normal));\r\n font-weight: var(--mono-card-title-font-weight, var(--mono-font-weight-medium));\r\n letter-spacing: var(--mono-card-title-tracking, normal);\r\n}\r\n\r\n[mono-card] :is(h1, h2, h3, h4, h5, h6, p, small)[mono-subtitle] {\r\n margin: 0;\r\n font-size: var(--_mono-card-subtitle-font);\r\n line-height: var(--mono-card-subtitle-line-height, var(--mono-leading-normal));\r\n font-weight: var(--mono-font-weight-normal);\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .card > header > :is(p, [data-description], .card-description)\r\n — text-muted-foreground text-sm */\r\n:where([mono-card]) [mono-subtitle] {\r\n margin: 0;\r\n font-size: var(--_mono-card-subtitle-font);\r\n line-height: var(--mono-card-subtitle-line-height, var(--mono-leading-normal));\r\n font-weight: var(--mono-font-weight-normal);\r\n color: var(--_mono-card-subtext);\r\n}\r\n\r\n/* EXTENSION — the header's leading glyph box */\r\n:where([mono-card]) > [mono-header] > [mono-icon] {\r\n flex: 0 0 auto;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: var(--_mono-card-icon-size);\r\n height: var(--_mono-card-icon-size);\r\n border-radius: var(--mono-card-icon-radius, var(--mono-radius-md));\r\n line-height: 1;\r\n background-color: color-mix(in oklab, var(--_mono-card-accent) var(--mono-mode-tint), transparent);\r\n color: var(--_mono-card-accent);\r\n overflow: hidden;\r\n}\r\n\r\n/* `:not(slot)`: in the shadow build the region's only child IS a <slot>, a real\r\n element that this rule would size — and then `::slotted()` would size the\r\n glyph again, to 55% of that 55%. The glyph came out half the size of its light\r\n twin. */\r\n:where([mono-card]) > [mono-header] > [mono-icon] > *:not(slot) {\r\n display: block;\r\n width: var(--_mono-card-icon-glyph);\r\n height: var(--_mono-card-icon-glyph);\r\n}\r\n\r\n:where([mono-card]) > [mono-header] > [mono-icon] slot::slotted(*) {\r\n display: block !important;\r\n width: var(--_mono-card-icon-glyph) !important;\r\n height: var(--_mono-card-icon-glyph) !important;\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .card > section — px-6 */\r\n:where([mono-card]) > [mono-body] {\r\n padding-inline: var(--_mono-card-padding);\r\n min-width: 0;\r\n}\r\n\r\n[mono-card] > :is(p, ul, ol, dl, blockquote)[mono-body] {\r\n margin-block: 0;\r\n}\r\n\r\n:where([mono-card]) > [mono-body]:empty {\r\n display: none;\r\n}\r\n\r\n/* The body's own children keep their block margins out of the card's rhythm —\r\n the card's `gap` is what spaces the regions, and content that wants paragraph\r\n spacing brings its own.\r\n\r\n ALL children, not just the first and last: in the shadow build `::slotted()`\r\n sees the HOST's child order, so `:first-child` there means \"first child of the\r\n card element\" — a body paragraph that follows a `slot=\"title\"` heading is not\r\n first, and kept the page's margins while its light twin did not.\r\n\r\n `!important` on the slotted twins is not a style choice: a `::slotted()` rule\r\n is an INNER-tree declaration, and a normal declaration from the outer tree (a\r\n page's `p { margin: … }`) beats it at any specificity. Marking it important\r\n inverts that order. The light twins need no such thing — they are ordinary\r\n descendant rules in the same tree as the page. */\r\n:where([mono-card]) > [mono-body] > * {\r\n margin-block: 0 !important;\r\n}\r\n\r\n:where([mono-card]) > [mono-body] slot::slotted(*) {\r\n margin-block: 0 !important;\r\n}\r\n\r\n/* basecoat@1.0.2 components/card.css .card >> > footer — flex items-center */\r\n/* basecoat@1.0.2 styles/vega.css .card > footer — rounded-b-xl px-6 [.border-t]:pt-6 */\r\n:where([mono-card]) > :is([mono-actions], [mono-footer]) {\r\n display: flex;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n gap: var(--_mono-card-actions-gap);\r\n padding-inline: var(--_mono-card-padding);\r\n}\r\n\r\n:where([mono-card]) > [mono-actions] {\r\n justify-content: flex-end;\r\n}\r\n\r\n/* the dividers: upstream's `[.border-b]:pb-6` idiom — a divided region pays the\r\n padding back on the divided edge. Both are ON by default, so the ATTRIBUTE\r\n marks the exception. */\r\n[mono-card]:not([mono-no-header-divider]) > [mono-header]:not([mono-empty]) {\r\n padding-bottom: var(--_mono-card-padding);\r\n border-bottom: var(--mono-border-width) solid var(--_mono-card-divider-color);\r\n}\r\n\r\n[mono-card]:not([mono-no-footer-divider]) > :is([mono-actions], [mono-footer]):not([mono-empty]) {\r\n padding-top: var(--_mono-card-padding);\r\n border-top: var(--mono-border-width) solid var(--_mono-card-divider-color);\r\n}\r\n\r\n/* =========================================\r\n Media — a full-bleed band; upstream gives the first/last child image the\r\n card's own corners and drops the padding on that edge\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .card\r\n — has-[>img:first-child]:pt-0 [&>img:first-child]:rounded-t-xl [&>img:last-child]:rounded-b-xl */\r\n:where([mono-card]) > [mono-media] {\r\n display: block;\r\n overflow: hidden;\r\n line-height: 0;\r\n}\r\n\r\n:where([mono-card]) > [mono-media] :is(img, picture, video, canvas, svg) {\r\n display: block;\r\n width: 100%;\r\n max-width: 100%;\r\n height: auto;\r\n object-fit: cover;\r\n}\r\n\r\n:where([mono-card]) > [mono-media] slot::slotted(:is(img, picture, video, canvas, svg)) {\r\n display: block !important;\r\n width: 100% !important;\r\n max-width: 100% !important;\r\n height: auto !important;\r\n object-fit: cover !important;\r\n}\r\n\r\n[mono-card]:has(> [mono-media]:not([mono-empty]):first-child) {\r\n padding-top: 0;\r\n}\r\n\r\n[mono-card]:has(> [mono-media]:not([mono-empty]):last-child) {\r\n padding-bottom: 0;\r\n}\r\n\r\n/* =========================================\r\n Loading — EXTENSION: a blurred veil with a spinner\r\n ========================================= */\r\n\r\n:where([mono-card]) > [mono-loading] {\r\n position: absolute;\r\n inset: 0;\r\n z-index: 2;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background-color: var(--mono-card-loading-bg, color-mix(in oklab, var(--card) 58%, transparent));\r\n backdrop-filter: blur(var(--mono-card-loading-blur, 2px));\r\n}\r\n\r\n:where([mono-card]) [mono-spinner] {\r\n display: block;\r\n width: var(--mono-card-spinner-size, calc(var(--mono-spacing) * 5.5));\r\n height: var(--mono-card-spinner-size, calc(var(--mono-spacing) * 5.5));\r\n border: var(--mono-card-spinner-width, 2px) solid color-mix(in oklab, var(--_mono-card-accent) 25%, transparent);\r\n border-top-color: var(--_mono-card-accent);\r\n border-radius: var(--mono-radius-full);\r\n animation: mono-card-spin var(--mono-card-spinner-speed, 0.65s) linear infinite;\r\n}\r\n\r\n@keyframes mono-card-spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n@media (prefers-reduced-motion: reduce) {\r\n [mono-card] {\r\n transition: none;\r\n }\r\n\r\n :where([mono-card]) [mono-spinner] {\r\n animation-duration: 2.4s;\r\n }\r\n}\r\n";
|
|
272
281
|
//#endregion
|
|
273
282
|
//#region src/components/card/mono-card.ts
|
|
274
283
|
/** Named regions the card lays out. The unnamed body is the fallback bucket. */
|
|
@@ -302,7 +311,11 @@ var MonoCard = class MonoCard extends MonoCardCore(LitElement) {
|
|
|
302
311
|
_renderHeader() {
|
|
303
312
|
if (!this._hasHeader) return nothing;
|
|
304
313
|
return html`
|
|
305
|
-
<div
|
|
314
|
+
<div
|
|
315
|
+
class=${this._cls("mono-card-header", "header")}
|
|
316
|
+
mono-header
|
|
317
|
+
?mono-no-subtitle=${this._noSubtitle}
|
|
318
|
+
>
|
|
306
319
|
${this._hasIcon && !this._hasHeaderSlot ? html`
|
|
307
320
|
<div class=${this._cls("card-icon", "icon")} mono-icon data-mono-slot="icon"></div>
|
|
308
321
|
` : nothing}
|