@threadlabs/looma 0.33.1 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/shared/overlay.js +8 -2
- package/components/shared/surface-material.js +21 -0
- package/components/ui-button/ui-button.html +63 -47
- package/components/ui-card/ui-card.html +44 -2
- package/components/ui-curve-editor/curve.js +10 -0
- package/components/ui-curve-editor/ui-curve-editor.html +181 -0
- package/components/ui-curve-editor/ui-curve-editor.js +51 -0
- package/components/ui-dialog/ui-dialog.html +62 -1
- package/components/ui-dialog/ui-dialog.js +9 -1
- package/components/ui-icon-button/ui-icon-button.html +75 -23
- package/components/ui-menu/ui-menu.html +60 -0
- package/components/ui-menu/ui-menu.js +1 -1
- package/components/ui-number-input/arithmetic.js +47 -0
- package/components/ui-number-input/ui-number-input.html +62 -0
- package/components/ui-number-input/ui-number-input.js +44 -0
- package/components/ui-popover/ui-popover.html +64 -1
- package/components/ui-popover/ui-popover.js +1 -1
- package/components/ui-slider/ui-slider.html +84 -0
- package/components/ui-slider/ui-slider.js +29 -0
- package/components/ui-tabs/ui-tabs.html +6 -1
- package/components/ui-text/ui-text.html +31 -6
- package/components/ui-tooltip/ui-tooltip.html +60 -0
- package/components/ui-tooltip/ui-tooltip.js +1 -1
- package/dist/index.js +46 -43
- package/docs/README.md +34 -4
- package/docs/card.html +16 -2
- package/docs/card.js +17 -2
- package/docs/catalog.json +1154 -144
- package/docs/customizer-render.mjs +35 -9
- package/docs/customizer.js +83 -20
- package/docs/documentation.css +9 -1
- package/docs/index.d.ts +4 -2
- package/docs/index.mjs +1 -1
- package/docs/preview.js +2 -0
- package/docs/render.mjs +15 -6
- package/docs/site.mjs +50 -9
- package/docs/theme-session.mjs +51 -0
- package/docs/theme.mjs +134 -15
- package/docs/value-editors.mjs +33 -0
- package/package.json +2 -2
- package/styles/ui-button.css +45 -45
- package/styles/ui-card.css +47 -0
- package/styles/ui-curve-editor.css +109 -0
- package/styles/ui-dialog.css +132 -0
- package/styles/ui-icon-button.css +63 -20
- package/styles/ui-menu.css +72 -0
- package/styles/ui-number-input.css +34 -0
- package/styles/ui-popover.css +74 -0
- package/styles/ui-slider.css +53 -0
- package/styles/ui-tabs.css +6 -1
- package/styles/ui-text.css +23 -1
- package/styles/ui-tooltip.css +72 -0
- package/theme-system.css +26 -10
- package/tokens.css +8 -2
- package/vanilla/UiButton.d.ts +1 -0
- package/vanilla/UiButton.js +195 -130
- package/vanilla/UiCard.d.ts +1 -1
- package/vanilla/UiCard.js +1 -1
- package/vanilla/UiCurveEditor.d.ts +28 -0
- package/vanilla/UiCurveEditor.js +134 -0
- package/vanilla/UiIconButton.d.ts +2 -1
- package/vanilla/UiIconButton.js +58 -31
- package/vanilla/UiNumberInput.d.ts +33 -0
- package/vanilla/UiNumberInput.js +79 -0
- package/vanilla/UiSlider.d.ts +33 -0
- package/vanilla/UiSlider.js +125 -0
- package/vanilla/UiText.d.ts +2 -2
- package/vanilla/UiText.js +45 -11
- package/vanilla/index.js +3 -0
- package/vue/UiButton.d.ts +6 -0
- package/vue/UiButton.vue +155 -56
- package/vue/UiCard.d.ts +2 -2
- package/vue/UiCard.vue +55 -5
- package/vue/UiCurveEditor.d.ts +53 -0
- package/vue/UiCurveEditor.js +2 -0
- package/vue/UiCurveEditor.vue +427 -0
- package/vue/UiDialog.vue +177 -1
- package/vue/UiIconButton.d.ts +8 -2
- package/vue/UiIconButton.vue +164 -34
- package/vue/UiMenu.vue +89 -0
- package/vue/UiNumberInput.d.ts +83 -0
- package/vue/UiNumberInput.js +2 -0
- package/vue/UiNumberInput.vue +370 -0
- package/vue/UiPopover.vue +92 -1
- package/vue/UiSlider.d.ts +83 -0
- package/vue/UiSlider.js +2 -0
- package/vue/UiSlider.vue +412 -0
- package/vue/UiTabs.vue +6 -1
- package/vue/UiText.d.ts +7 -5
- package/vue/UiText.vue +104 -22
- package/vue/UiTooltip.vue +89 -0
- package/vue/chunks/UiActionBar.js +1 -1
- package/vue/chunks/UiAffordanceScope.js +2 -2
- package/vue/chunks/UiAvatar.js +2 -2
- package/vue/chunks/UiAvatarGroup.js +2 -2
- package/vue/chunks/UiBadge.js +2 -2
- package/vue/chunks/UiBreadcrumbItem.js +2 -2
- package/vue/chunks/UiBreadcrumbs.js +2 -2
- package/vue/chunks/UiButton.js +94 -11
- package/vue/chunks/UiCallout.js +2 -2
- package/vue/chunks/UiCard.js +6 -5
- package/vue/chunks/UiCheckbox.js +2 -2
- package/vue/chunks/UiCluster.js +2 -2
- package/vue/chunks/UiColorPicker.js +2 -2
- package/vue/chunks/UiCombobox.js +2 -2
- package/vue/chunks/UiContainer.js +2 -2
- package/vue/chunks/UiContextMenu.js +2 -2
- package/vue/chunks/UiCover.js +2 -2
- package/vue/chunks/UiCurveEditor.js +413 -0
- package/vue/chunks/UiDescriptionItem.js +2 -2
- package/vue/chunks/UiDescriptionList.js +2 -2
- package/vue/chunks/UiDialog.js +4 -4
- package/vue/chunks/UiDisclosure.js +2 -2
- package/vue/chunks/UiEditable.js +2 -2
- package/vue/chunks/UiEditorBlockActions.js +2 -2
- package/vue/chunks/UiEditorChipEditor.js +2 -2
- package/vue/chunks/UiEditorCodeLanguage.js +2 -2
- package/vue/chunks/UiEditorFootnoteEditor.js +2 -2
- package/vue/chunks/UiEditorImageToolbar.js +3 -3
- package/vue/chunks/UiEditorInsertTableGrid.js +2 -2
- package/vue/chunks/UiEditorLinkCard.js +3 -3
- package/vue/chunks/UiEditorLinkForm.js +3 -3
- package/vue/chunks/UiEditorMentionMenu.js +2 -2
- package/vue/chunks/UiEditorMentionMenuItem.js +2 -2
- package/vue/chunks/UiEditorSlashMenu.js +2 -2
- package/vue/chunks/UiEditorSlashMenuGroup.js +2 -2
- package/vue/chunks/UiEditorSlashMenuItem.js +2 -2
- package/vue/chunks/UiEditorSurface.js +2 -2
- package/vue/chunks/UiEditorTableContextMenu.js +2 -2
- package/vue/chunks/UiEditorTableOverlay.js +2 -2
- package/vue/chunks/UiEditorTableToolbar.js +2 -2
- package/vue/chunks/UiEditorToolbar.js +2 -2
- package/vue/chunks/UiFloatingActionButton.js +2 -2
- package/vue/chunks/UiFormField.js +2 -2
- package/vue/chunks/UiGrid.js +2 -2
- package/vue/chunks/UiIcon.js +2 -2
- package/vue/chunks/UiIconButton.js +77 -11
- package/vue/chunks/UiImage.js +2 -2
- package/vue/chunks/UiInput.js +2 -2
- package/vue/chunks/UiInputGroup.js +2 -2
- package/vue/chunks/UiList.js +2 -2
- package/vue/chunks/UiListItem.js +2 -2
- package/vue/chunks/UiListbox.js +2 -2
- package/vue/chunks/UiMenu.js +3 -3
- package/vue/chunks/UiMenuGroup.js +2 -2
- package/vue/chunks/UiMenuItem.js +2 -2
- package/vue/chunks/UiMeter.js +2 -2
- package/vue/chunks/UiNavItem.js +2 -2
- package/vue/chunks/UiNumberInput.js +390 -0
- package/vue/chunks/UiPageHeader.js +2 -2
- package/vue/chunks/UiPopover.js +4 -4
- package/vue/chunks/UiRadio.js +2 -2
- package/vue/chunks/UiRadioGroup.js +2 -2
- package/vue/chunks/UiReel.js +2 -2
- package/vue/chunks/UiScrollArea.js +2 -2
- package/vue/chunks/UiSearchResultRow.js +2 -2
- package/vue/chunks/UiSearchShell.js +2 -2
- package/vue/chunks/UiSection.js +2 -2
- package/vue/chunks/UiSelect.js +2 -2
- package/vue/chunks/UiSeparator.js +2 -2
- package/vue/chunks/UiSidebar.js +2 -2
- package/vue/chunks/UiSlider.js +396 -0
- package/vue/chunks/UiSpinner.js +2 -2
- package/vue/chunks/UiStack.js +2 -2
- package/vue/chunks/UiStatusMessage.js +2 -2
- package/vue/chunks/UiSwatch.js +2 -2
- package/vue/chunks/UiSwitch.js +2 -2
- package/vue/chunks/UiSwitcher.js +2 -2
- package/vue/chunks/UiTable.js +2 -2
- package/vue/chunks/UiTabs.js +3 -3
- package/vue/chunks/UiText.js +53 -12
- package/vue/chunks/UiTextarea.js +2 -2
- package/vue/chunks/UiToast.js +2 -2
- package/vue/chunks/UiToastRegion.js +2 -2
- package/vue/chunks/UiTooltip.js +3 -3
- package/vue/chunks/UiTopBar.js +1 -1
- package/vue/chunks/UiTree.js +2 -2
- package/vue/chunks/UiTreeItem.js +2 -2
- package/vue/chunks/_plugin-vue_export-helper.js +68 -2
- package/vue/chunks/props.js +24 -1
- package/vue/components.css +2215 -1203
- package/vue/editor/index.js +623 -211
- package/vue/index.d.ts +3 -0
- package/vue/index.js +5 -2
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { updateSurfaceMaterial } from "./surface-material.js";
|
|
2
|
+
|
|
1
3
|
const dialogInvokers = new WeakMap();
|
|
2
4
|
|
|
3
5
|
function stateFor(document) {
|
|
@@ -345,7 +347,10 @@ export function createViewportSurface(surface, options = {}) {
|
|
|
345
347
|
let frame = null;
|
|
346
348
|
const position = () => {
|
|
347
349
|
frame = null;
|
|
348
|
-
if (stop)
|
|
350
|
+
if (stop) {
|
|
351
|
+
if (options.materialRole) updateSurfaceMaterial(surface, options.materialRole);
|
|
352
|
+
options.position?.();
|
|
353
|
+
}
|
|
349
354
|
};
|
|
350
355
|
const refresh = () => {
|
|
351
356
|
if (stop && frame === null) frame = owner.requestAnimationFrame(position);
|
|
@@ -378,6 +383,7 @@ export function createViewportSurface(surface, options = {}) {
|
|
|
378
383
|
show() {
|
|
379
384
|
if (destroyed) return;
|
|
380
385
|
show(surface);
|
|
386
|
+
if (options.materialRole) updateSurfaceMaterial(surface, options.materialRole);
|
|
381
387
|
stop ??= observeOverlayViewport(surface.ownerDocument, position);
|
|
382
388
|
options.position?.();
|
|
383
389
|
if (!sizeObserver && owner.ResizeObserver) {
|
|
@@ -435,7 +441,7 @@ export function createAnchoredSurface(surface, options = {}) {
|
|
|
435
441
|
surface.style.position = "fixed";
|
|
436
442
|
surface.style.setProperty("margin", "0", "important");
|
|
437
443
|
// `bare` resets the browser's popover chrome on a surface that has none of its own.
|
|
438
|
-
const presentation = createViewportSurface(surface, { position, bare: options.bare });
|
|
444
|
+
const presentation = createViewportSurface(surface, { position, bare: options.bare, materialRole: options.materialRole });
|
|
439
445
|
// Resize and scroll events do not report an ancestor's transition or layout shift.
|
|
440
446
|
// While visible, sample the live anchor and only re-position when its bounds change.
|
|
441
447
|
const trackAnchor = () => {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Purpose has greater influence than size: even a large menu stays lighter than a dialog.
|
|
2
|
+
const roleWeight = Object.freeze({ tooltip: 0.08, menu: 0.28, popover: 0.55, dialog: 1, panel: 0.65 });
|
|
3
|
+
|
|
4
|
+
/** Derive a bounded material scale from a surface's purpose and rendered border box. */
|
|
5
|
+
export function surfaceMaterialScale(role, width, height) {
|
|
6
|
+
if (!Object.hasOwn(roleWeight, role)) throw new Error(`Unknown surface material role: ${role}`);
|
|
7
|
+
const measured = [width, height].every(value => Number.isFinite(value) && value > 0);
|
|
8
|
+
const size = measured ? Math.max(0.8, Math.min(1.35, Math.sqrt(width * height / (320 * 240)))) : 1;
|
|
9
|
+
return Math.round(roleWeight[role] * size * 1000) / 1000;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Update component-owned material geometry; a tolerance prevents its rim feeding tiny resize changes back into itself. */
|
|
13
|
+
export function updateSurfaceMaterial(element, role) {
|
|
14
|
+
const width = element.offsetWidth;
|
|
15
|
+
const height = element.offsetHeight;
|
|
16
|
+
const next = surfaceMaterialScale(role, width, height);
|
|
17
|
+
const previous = Number.parseFloat(element.style.getPropertyValue("--_ui-material-scale"));
|
|
18
|
+
if (!Number.isFinite(previous) || Math.abs(next - previous) >= Math.max(0.002, Math.abs(previous) * 0.04)) {
|
|
19
|
+
element.style.setProperty("--_ui-material-scale", String(next));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
<link rel="component" href="../ui-icon/ui-icon.html">
|
|
3
3
|
<template component="ui-button" module="./ui-button.js">
|
|
4
4
|
<defs>
|
|
5
|
+
<prop name="preset" type="keyword" values="none, primary, standard, quiet, destructive" default="none"
|
|
6
|
+
>A shortcut that sets appearance and tone together: primary is solid accent, standard is solid neutral, quiet is ghost neutral, and destructive is solid
|
|
7
|
+
danger. A named preset takes precedence over variant and tone. Leave it at none to choose variant and tone independently.</prop>
|
|
8
|
+
<computed name="appearance" from="{ none: $variant, primary: 'solid', standard: 'solid', quiet: 'ghost', destructive: 'solid' }[$preset]"></computed>
|
|
9
|
+
<computed
|
|
10
|
+
name="colorTone"
|
|
11
|
+
from="{ none: { true: 'danger', false: $tone }[concat($variant = 'danger')], primary: 'accent', standard: 'neutral', quiet: 'neutral', destructive: 'danger' }[$preset]"
|
|
12
|
+
></computed>
|
|
5
13
|
<prop name="variant" type="keyword" values="outline, solid, danger, ghost, link, card, field" default="outline"
|
|
6
14
|
>Emphasis: how loudly the button asks. solid fills with its tone, outline draws its tone at the edge over a wash of it, ghost carries only text until it is
|
|
7
15
|
hovered, and link is an inline text action that reads as a link. danger is solid in the danger tone, kept for the call sites that name it. card uses the
|
|
@@ -42,7 +50,9 @@
|
|
|
42
50
|
</defs>
|
|
43
51
|
<template $match>
|
|
44
52
|
<a
|
|
45
|
-
|
|
53
|
+
from:data-appearance="$appearance"
|
|
54
|
+
from:data-tone="$colorTone"
|
|
55
|
+
$when="$appearance = 'card' and $as = 'a'"
|
|
46
56
|
from:href="{ true: null, false: $href }[concat($disabled or $loading or $pending)]"
|
|
47
57
|
from:target="$target"
|
|
48
58
|
from:rel="$rel"
|
|
@@ -57,7 +67,9 @@
|
|
|
57
67
|
<span class="card-action"><slot name="action"><ui-icon name="chevron-right" aria-hidden="true"></ui-icon></slot></span>
|
|
58
68
|
</a>
|
|
59
69
|
<button
|
|
60
|
-
|
|
70
|
+
from:data-appearance="$appearance"
|
|
71
|
+
from:data-tone="$colorTone"
|
|
72
|
+
$when="$appearance = 'card'"
|
|
61
73
|
from:type="$type"
|
|
62
74
|
from:disabled="$disabled"
|
|
63
75
|
from:aria-disabled="{ true: 'true', false: null }[concat($loading or $pending)]"
|
|
@@ -70,6 +82,8 @@
|
|
|
70
82
|
<span class="card-action"><slot name="action"><ui-icon name="chevron-right" aria-hidden="true"></ui-icon></slot></span>
|
|
71
83
|
</button>
|
|
72
84
|
<a
|
|
85
|
+
from:data-appearance="$appearance"
|
|
86
|
+
from:data-tone="$colorTone"
|
|
73
87
|
$when="$as = 'a'"
|
|
74
88
|
from:href="{ true: null, false: $href }[concat($disabled or $loading or $pending)]"
|
|
75
89
|
from:target="$target"
|
|
@@ -83,6 +97,8 @@
|
|
|
83
97
|
<span class="badge"><slot name="badge"></slot></span>
|
|
84
98
|
</a>
|
|
85
99
|
<button
|
|
100
|
+
from:data-appearance="$appearance"
|
|
101
|
+
from:data-tone="$colorTone"
|
|
86
102
|
$else
|
|
87
103
|
from:type="$type"
|
|
88
104
|
from:disabled="$disabled"
|
|
@@ -255,7 +271,7 @@
|
|
|
255
271
|
|
|
256
272
|
/* A count is an adornment, not another line of label text. Keep the standard control height
|
|
257
273
|
with enough inset for a 24px mark; large content can still grow the button naturally. */
|
|
258
|
-
:host:not([
|
|
274
|
+
:host:not([data-appearance="link"]):has(.badge:not(:empty)) {
|
|
259
275
|
padding-block: var(--ui-space-0-5) !important;
|
|
260
276
|
}
|
|
261
277
|
|
|
@@ -300,7 +316,7 @@
|
|
|
300
316
|
|
|
301
317
|
/* Card actions inherit Button's palette and behavior; only their shared layout changes.
|
|
302
318
|
The icon may contain any decorative composition. Empty icons remove their column. */
|
|
303
|
-
:host
|
|
319
|
+
:host[data-appearance="card"] {
|
|
304
320
|
display: grid !important;
|
|
305
321
|
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
306
322
|
align-content: center !important;
|
|
@@ -313,10 +329,10 @@
|
|
|
313
329
|
box-shadow: none;
|
|
314
330
|
background-image: none;
|
|
315
331
|
}
|
|
316
|
-
:host
|
|
332
|
+
:host[data-appearance="card"][size="lg"] {
|
|
317
333
|
min-block-size: max(var(--ui-control-min-block-size), var(--ui-control-size-lg));
|
|
318
334
|
}
|
|
319
|
-
:host
|
|
335
|
+
:host[data-appearance="card"]:has(.card-icon:empty) {
|
|
320
336
|
grid-template-columns: minmax(0, 1fr) auto;
|
|
321
337
|
}
|
|
322
338
|
.card-icon {
|
|
@@ -343,11 +359,11 @@
|
|
|
343
359
|
}
|
|
344
360
|
|
|
345
361
|
/* A neutral card encloses content quietly; ordinary outlines keep their action-tone edge. */
|
|
346
|
-
:host
|
|
362
|
+
:host[data-appearance="card"][data-tone="neutral"] {
|
|
347
363
|
border-color: var(--ui-button-border, var(--ui-border));
|
|
348
364
|
}
|
|
349
365
|
|
|
350
|
-
:host
|
|
366
|
+
:host[data-appearance="card"][data-tone="neutral"]:hover:not(:disabled, [aria-disabled="true"]) {
|
|
351
367
|
border-color: var(--ui-button-hover-border, var(--ui-border-strong));
|
|
352
368
|
}
|
|
353
369
|
|
|
@@ -359,19 +375,19 @@
|
|
|
359
375
|
box-shadow: var(--ui-pressed);
|
|
360
376
|
}
|
|
361
377
|
|
|
362
|
-
:host
|
|
378
|
+
:host[data-appearance="solid"], :host[data-appearance="danger"] {
|
|
363
379
|
border-color: var(--_tone);
|
|
364
380
|
background-color: var(--_tone);
|
|
365
381
|
color: var(--_on-tone);
|
|
366
382
|
box-shadow: var(--ui-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow)));
|
|
367
383
|
}
|
|
368
384
|
|
|
369
|
-
:is(:host
|
|
385
|
+
:is(:host[data-appearance="solid"], :host[data-appearance="danger"]):hover:not(:disabled, [aria-disabled="true"]) {
|
|
370
386
|
background-color: var(--_tone-hover);
|
|
371
387
|
border-color: var(--_tone-hover);
|
|
372
388
|
}
|
|
373
389
|
|
|
374
|
-
:is(:host
|
|
390
|
+
:is(:host[data-appearance="solid"], :host[data-appearance="danger"]):active:not(:disabled, [aria-disabled="true"]) {
|
|
375
391
|
background-color: var(--_tone-active);
|
|
376
392
|
border-color: var(--_tone-active);
|
|
377
393
|
background-image: none;
|
|
@@ -380,7 +396,7 @@
|
|
|
380
396
|
|
|
381
397
|
/* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a
|
|
382
398
|
destructive secondary action, not a special case. */
|
|
383
|
-
:host
|
|
399
|
+
:host[data-tone="neutral"] {
|
|
384
400
|
--_hue: var(--ui-text);
|
|
385
401
|
--_hue-hover: var(--ui-text);
|
|
386
402
|
--_hue-active: var(--ui-text);
|
|
@@ -388,40 +404,40 @@
|
|
|
388
404
|
--_on-hue: var(--ui-surface);
|
|
389
405
|
}
|
|
390
406
|
|
|
391
|
-
:host
|
|
407
|
+
:host[data-tone="danger"], :host[data-appearance="danger"] {
|
|
392
408
|
--_hue: var(--ui-danger);
|
|
393
409
|
--_hue-hover: var(--ui-danger-hover);
|
|
394
|
-
--_hue-active: var(--ui-danger-hover);
|
|
395
|
-
--_hue-text: var(--ui-danger-
|
|
410
|
+
--_hue-active: var(--ui-danger-active, var(--ui-danger-hover));
|
|
411
|
+
--_hue-text: var(--ui-danger-subtle-text);
|
|
396
412
|
--_on-hue: var(--ui-on-danger);
|
|
397
413
|
}
|
|
398
414
|
|
|
399
|
-
:host
|
|
415
|
+
:host[data-tone="success"] {
|
|
400
416
|
--_hue: var(--ui-success);
|
|
401
|
-
--_hue-hover:
|
|
402
|
-
--_hue-active:
|
|
403
|
-
--_hue-text:
|
|
404
|
-
--_on-hue: var(--ui-
|
|
417
|
+
--_hue-hover: var(--ui-success-hover);
|
|
418
|
+
--_hue-active: var(--ui-success-active);
|
|
419
|
+
--_hue-text: var(--ui-success-subtle-text);
|
|
420
|
+
--_on-hue: var(--ui-success-on-strong);
|
|
405
421
|
}
|
|
406
422
|
|
|
407
|
-
:host
|
|
423
|
+
:host[data-tone="warning"] {
|
|
408
424
|
--_hue: var(--ui-warning);
|
|
409
|
-
--_hue-hover:
|
|
410
|
-
--_hue-active:
|
|
411
|
-
--_hue-text:
|
|
412
|
-
--_on-hue: var(--ui-
|
|
425
|
+
--_hue-hover: var(--ui-warning-hover);
|
|
426
|
+
--_hue-active: var(--ui-warning-active);
|
|
427
|
+
--_hue-text: var(--ui-warning-subtle-text);
|
|
428
|
+
--_on-hue: var(--ui-warning-on-strong);
|
|
413
429
|
}
|
|
414
430
|
|
|
415
|
-
:host
|
|
431
|
+
:host[data-tone="info"] {
|
|
416
432
|
--_hue: var(--ui-info);
|
|
417
|
-
--_hue-hover:
|
|
418
|
-
--_hue-active:
|
|
419
|
-
--_hue-text:
|
|
420
|
-
--_on-hue: var(--ui-
|
|
433
|
+
--_hue-hover: var(--ui-info-hover);
|
|
434
|
+
--_hue-active: var(--ui-info-active);
|
|
435
|
+
--_hue-text: var(--ui-info-subtle-text);
|
|
436
|
+
--_on-hue: var(--ui-info-on-strong);
|
|
421
437
|
}
|
|
422
438
|
|
|
423
439
|
/* A value picker is a field, with Select's quiet edge and resting lift. */
|
|
424
|
-
:host
|
|
440
|
+
:host[data-appearance="field"] {
|
|
425
441
|
--_ui-field-shadow: var(--ui-shadow-sm);
|
|
426
442
|
border-color: var(--ui-button-border, var(--ui-control-border, var(--ui-border-strong)));
|
|
427
443
|
border-radius: var(--ui-button-radius, var(--ui-field-radius, var(--ui-radius-md)));
|
|
@@ -431,23 +447,23 @@
|
|
|
431
447
|
box-shadow: var(--ui-button-shadow, var(--_ui-field-shadow));
|
|
432
448
|
}
|
|
433
449
|
|
|
434
|
-
:host
|
|
450
|
+
:host[data-appearance="field"]:hover:not(:disabled, [aria-disabled="true"]) {
|
|
435
451
|
border-color: var(--ui-button-hover-border, var(--ui-control-border-hover, var(--ui-text-secondary)));
|
|
436
452
|
background-color: var(--ui-button-hover-surface, var(--ui-control-surface, var(--ui-surface-elevated)));
|
|
437
453
|
}
|
|
438
454
|
|
|
439
|
-
:host
|
|
455
|
+
:host[data-appearance="field"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"]) {
|
|
440
456
|
--_ui-field-shadow: var(--ui-pressed);
|
|
441
457
|
}
|
|
442
458
|
|
|
443
|
-
:host
|
|
459
|
+
:host[data-appearance="field"]:focus-visible {
|
|
444
460
|
border-color: var(--ui-control-focus, var(--ui-accent-solid));
|
|
445
461
|
box-shadow:
|
|
446
462
|
var(--ui-button-shadow, var(--_ui-field-shadow)),
|
|
447
463
|
var(--ui-control-focus-halo-shadow);
|
|
448
464
|
}
|
|
449
465
|
|
|
450
|
-
:host
|
|
466
|
+
:host[data-appearance="ghost"] {
|
|
451
467
|
border-color: transparent;
|
|
452
468
|
background: transparent;
|
|
453
469
|
box-shadow: none;
|
|
@@ -455,14 +471,14 @@
|
|
|
455
471
|
}
|
|
456
472
|
|
|
457
473
|
/* Tints derive from the text colour, not a surface token, so hover and press show on any background. */
|
|
458
|
-
:host
|
|
474
|
+
:host[data-appearance="ghost"]:hover:not(:disabled, [aria-disabled="true"]) {
|
|
459
475
|
background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));
|
|
460
476
|
border-color: transparent;
|
|
461
477
|
}
|
|
462
478
|
|
|
463
479
|
/* Pressed, or holding its menu open, a ghost button sinks slightly: a light surface with a faint
|
|
464
480
|
edge and a soft inner shadow. Lighter than hover, so an open menu's trigger never reads as heavy. */
|
|
465
|
-
:host
|
|
481
|
+
:host[data-appearance="ghost"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"]) {
|
|
466
482
|
background-color: var(--ui-button-ghost-active-surface, color-mix(in oklch, var(--ui-surface), var(--_tone) 3%));
|
|
467
483
|
border-color: transparent;
|
|
468
484
|
box-shadow: inset 0 0 0 1px oklch(from var(--_tone) l c h / 10%), inset 0 1px 2px oklch(from var(--_tone) l c h / 8%);
|
|
@@ -476,13 +492,13 @@
|
|
|
476
492
|
var(--ui-focus-halo);
|
|
477
493
|
}
|
|
478
494
|
|
|
479
|
-
:host
|
|
495
|
+
:host[data-appearance="solid"]:focus-visible {
|
|
480
496
|
box-shadow:
|
|
481
497
|
var(--ui-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow))),
|
|
482
498
|
var(--ui-focus-halo);
|
|
483
499
|
}
|
|
484
500
|
|
|
485
|
-
:is(:host
|
|
501
|
+
:is(:host[data-appearance="ghost"], :host[data-appearance="link"], :host[data-appearance="card"]):focus-visible {
|
|
486
502
|
box-shadow: var(--ui-focus-halo);
|
|
487
503
|
}
|
|
488
504
|
|
|
@@ -504,7 +520,7 @@
|
|
|
504
520
|
}
|
|
505
521
|
|
|
506
522
|
/* Ghost keeps no border, but gains the same neutral surface as other disabled buttons. */
|
|
507
|
-
:host
|
|
523
|
+
:host[data-appearance="ghost"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])) {
|
|
508
524
|
background-color: var(--ui-disabled-surface);
|
|
509
525
|
border-color: transparent;
|
|
510
526
|
}
|
|
@@ -521,12 +537,12 @@
|
|
|
521
537
|
a link-style one keeps its text size, so a standalone one ("See all" under a list) needs the
|
|
522
538
|
area. xs sits inside a line of text the same way, so it keeps its size and gains the area too.
|
|
523
539
|
Only these need it: a hit area on every button would reach over its neighbours. */
|
|
524
|
-
html[data-ui-input-modality="touch"] :host
|
|
540
|
+
html[data-ui-input-modality="touch"] :host[data-appearance="link"],
|
|
525
541
|
html[data-ui-input-modality="touch"] :host([size="xs"]) {
|
|
526
542
|
position: relative;
|
|
527
543
|
}
|
|
528
544
|
|
|
529
|
-
html[data-ui-input-modality="touch"] :host
|
|
545
|
+
html[data-ui-input-modality="touch"] :host[data-appearance="link"]::after,
|
|
530
546
|
html[data-ui-input-modality="touch"] :host([size="xs"])::after {
|
|
531
547
|
position: absolute;
|
|
532
548
|
inset: 50% auto auto 50%;
|
|
@@ -538,7 +554,7 @@
|
|
|
538
554
|
|
|
539
555
|
/* Link: an inline text action. No box, padding, or minimum height (inline targets are exempt under
|
|
540
556
|
WCAG 2.5.8); the inherited font; an underline that strengthens on hover; a visible focus ring. */
|
|
541
|
-
:host
|
|
557
|
+
:host[data-appearance="link"] {
|
|
542
558
|
display: inline !important;
|
|
543
559
|
min-block-size: 0;
|
|
544
560
|
padding: 0 !important;
|
|
@@ -555,24 +571,24 @@
|
|
|
555
571
|
transition: color var(--ui-motion-fast) var(--ui-motion-ease), text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
556
572
|
}
|
|
557
573
|
|
|
558
|
-
:host
|
|
574
|
+
:host[data-appearance="link"]:hover:not(:disabled, [aria-disabled="true"]) {
|
|
559
575
|
color: var(--ui-button-link-hover-text, var(--ui-text-primary));
|
|
560
576
|
text-decoration-color: currentColor;
|
|
561
577
|
background: none;
|
|
562
578
|
transform: none;
|
|
563
579
|
}
|
|
564
580
|
|
|
565
|
-
:host
|
|
581
|
+
:host[data-appearance="link"]:active:not(:disabled, [aria-disabled="true"]) {
|
|
566
582
|
background: none;
|
|
567
583
|
transform: none;
|
|
568
584
|
}
|
|
569
585
|
|
|
570
|
-
:host
|
|
586
|
+
:host[data-appearance="link"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])) {
|
|
571
587
|
background: none;
|
|
572
588
|
border-color: transparent;
|
|
573
589
|
}
|
|
574
590
|
|
|
575
|
-
:host
|
|
591
|
+
:host[data-appearance="link"]:focus-visible {
|
|
576
592
|
box-shadow: none;
|
|
577
593
|
/* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */
|
|
578
594
|
outline: var(--ui-focus-width) solid var(--ui-focus-ring);
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
<defs>
|
|
3
3
|
<prop name="size" type="keyword" values="content, sm, md, lg" default="content"
|
|
4
4
|
>Optional size preset. content keeps the existing intrinsic sizing; the other sizes constrain the surface for compact, medium, or large content.</prop>
|
|
5
|
-
<prop name="variant" type="keyword" values="outlined, subtle, elevated" default="outlined"
|
|
5
|
+
<prop name="variant" type="keyword" values="outlined, subtle, elevated, glass" default="outlined"
|
|
6
6
|
>The surface. outlined is a bordered panel on the page; subtle is a quiet filled one with no border, for supporting details set apart from the flow;
|
|
7
|
-
elevated floats above the page with a shadow, for a view's one card, such as sign-in
|
|
7
|
+
elevated floats above the page with a shadow, for a view's one card, such as sign-in. glass frames an opaque readable content plane with frosted material;
|
|
8
|
+
shared glassiness and surface separation govern its treatment.</prop>
|
|
8
9
|
<prop name="padding" type="keyword" values="xs, sm, md, lg" default="md"
|
|
9
10
|
>The space inside the card: xs is compact (0.5rem), sm is snug (0.75rem), md is the default (1.5rem), and lg is roomy (2rem).</prop>
|
|
10
11
|
<prop name="tone" type="keyword" values="neutral, accent, info, success, warning, danger" default="neutral"
|
|
@@ -62,6 +63,47 @@
|
|
|
62
63
|
box-shadow: var(--ui-shadow-lg);
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
:host([variant="glass"]) {
|
|
67
|
+
--_ui-panel-glass: clamp(0, var(--ui-glassiness, 0), 1);
|
|
68
|
+
--_ui-panel-separation: clamp(0, var(--ui-surface-separation, 0), 1);
|
|
69
|
+
--_ui-panel-rim: calc((var(--_ui-panel-separation) + var(--_ui-panel-glass) * 0.25) * 0.65 * 8px);
|
|
70
|
+
border-width: calc(var(--ui-border-width) + var(--_ui-panel-rim));
|
|
71
|
+
border-color: transparent;
|
|
72
|
+
background:
|
|
73
|
+
linear-gradient(var(--_ui-card-surface), var(--_ui-card-surface)) padding-box,
|
|
74
|
+
linear-gradient(var(--ui-material-glass, var(--ui-surface-raised)), var(--ui-material-glass, var(--ui-surface-raised))) border-box,
|
|
75
|
+
var(--_ui-card-surface) padding-box;
|
|
76
|
+
box-shadow:
|
|
77
|
+
var(--ui-shadow-lg),
|
|
78
|
+
inset 0 0 0 var(--ui-border-width) var(--ui-material-edge, var(--ui-border-strong));
|
|
79
|
+
backdrop-filter: blur(calc(var(--_ui-panel-glass) * 0.65 * 18px)) saturate(calc(1 + var(--_ui-panel-glass) * 0.65 * 0.18));
|
|
80
|
+
-webkit-backdrop-filter: blur(calc(var(--_ui-panel-glass) * 0.65 * 18px)) saturate(calc(1 + var(--_ui-panel-glass) * 0.65 * 0.18));
|
|
81
|
+
}
|
|
82
|
+
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
|
|
83
|
+
:host([variant="glass"]) {
|
|
84
|
+
background: var(--_ui-card-surface);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
88
|
+
:host([variant="glass"]) {
|
|
89
|
+
background: var(--_ui-card-surface);
|
|
90
|
+
border-width: var(--ui-border-width);
|
|
91
|
+
border-color: var(--ui-border-strong);
|
|
92
|
+
backdrop-filter: none;
|
|
93
|
+
-webkit-backdrop-filter: none;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
@media (forced-colors: active) {
|
|
97
|
+
:host([variant="glass"]) {
|
|
98
|
+
background: Canvas;
|
|
99
|
+
color: CanvasText;
|
|
100
|
+
border: var(--ui-border-width) solid CanvasText;
|
|
101
|
+
box-shadow: none;
|
|
102
|
+
backdrop-filter: none;
|
|
103
|
+
-webkit-backdrop-filter: none;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
65
107
|
:host([tone="accent"]) {
|
|
66
108
|
border-color: color-mix(in srgb, var(--ui-accent) 25%, var(--ui-border-default));
|
|
67
109
|
--_ui-card-surface: color-mix(in srgb, var(--ui-accent) 6%, var(--ui-surface-default));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function curvePoints(value) {
|
|
2
|
+
const presets = { linear: [0, 0, 1, 1], ease: [.25, .1, .25, 1], "ease-in": [.42, 0, 1, 1], "ease-out": [0, 0, .58, 1], "ease-in-out": [.42, 0, .58, 1] };
|
|
3
|
+
if (presets[value]) return [...presets[value]];
|
|
4
|
+
const match = /^cubic-bezier\(\s*([^)]*)\s*\)$/.exec(String(value));
|
|
5
|
+
const parts = match?.[1].split(",");
|
|
6
|
+
const points = parts?.map(part => part.trim() === "" ? NaN : Number(part));
|
|
7
|
+
if (!points || points.length !== 4 || points.some(number => !Number.isFinite(number))) throw new Error("Use a cubic-bezier curve.");
|
|
8
|
+
return points.map((number, index) => Math.min(index % 2 ? 2 : 1, Math.max(index % 2 ? -1 : 0, number)));
|
|
9
|
+
}
|
|
10
|
+
export function curveText(points) { return `cubic-bezier(${points.map(number => Number(number.toFixed(3))).join(", ")})`; }
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<link rel="component" href="../ui-number-input/ui-number-input.html">
|
|
2
|
+
<template component="ui-curve-editor" module="./ui-curve-editor.js">
|
|
3
|
+
<defs>
|
|
4
|
+
<state name="point0" type="string" value="0.25"></state>
|
|
5
|
+
<state name="point1" type="string" value="0.1"></state>
|
|
6
|
+
<state name="point2" type="string" value="0.25"></state>
|
|
7
|
+
<state name="point3" type="string" value="1"></state>
|
|
8
|
+
|
|
9
|
+
<prop name="value" type="string" default="cubic-bezier(0.25, 0.1, 0.25, 1)"
|
|
10
|
+
>CSS cubic-bezier or a standard easing keyword. X stays within 0–1; Y is bounded to -1–2 for a limited overshoot.</prop>
|
|
11
|
+
<prop name="label" type="string" default="Value">Accessible name for the editing control.</prop>
|
|
12
|
+
<prop name="size" type="keyword" values="sm, md, lg" default="md">Shared field and button height.</prop>
|
|
13
|
+
<prop name="disabled" type="boolean" default="false">Prevents typing, stepping and pointer or keyboard changes while keeping the value visible.</prop>
|
|
14
|
+
<event name="input" type="object"><prop name="value" type="string" required></prop></event>
|
|
15
|
+
<event name="change" type="object"><prop name="value" type="string" required></prop></event>
|
|
16
|
+
</defs>
|
|
17
|
+
<span>
|
|
18
|
+
<span class="plot-frame" from:aria-label="$label" role="group"><span class="plot" $ref="plot">
|
|
19
|
+
<svg viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">
|
|
20
|
+
<path class="guide" d="M0 66.667 H100 M0 33.333 H100"></path>
|
|
21
|
+
<path $ref="firstLine" class="guide" d="M0 66.667 L25 63.333"></path>
|
|
22
|
+
<path $ref="secondLine" class="guide" d="M100 33.333 L25 33.333"></path>
|
|
23
|
+
<path $ref="curve" d="M0 66.667 C25 63.333 25 33.333 100 33.333"></path>
|
|
24
|
+
</svg>
|
|
25
|
+
<button $ref="first" class="handle" type="button" from:disabled="$disabled" aria-label="First curve handle. Arrow keys adjust; Shift moves faster.">
|
|
26
|
+
</button>
|
|
27
|
+
<button
|
|
28
|
+
$ref="second"
|
|
29
|
+
class="handle second"
|
|
30
|
+
type="button"
|
|
31
|
+
from:disabled="$disabled"
|
|
32
|
+
aria-label="Second curve handle. Arrow keys adjust; Shift moves faster."
|
|
33
|
+
>
|
|
34
|
+
</button>
|
|
35
|
+
</span></span>
|
|
36
|
+
<span class="coordinates">
|
|
37
|
+
<span class="coordinate"><span>X1</span><ui-number-input
|
|
38
|
+
data-curve-coordinate="0"
|
|
39
|
+
from:value="$point0"
|
|
40
|
+
min="0"
|
|
41
|
+
max="1"
|
|
42
|
+
step="0.01"
|
|
43
|
+
label="First handle X"
|
|
44
|
+
from:size="$size"
|
|
45
|
+
from:disabled="$disabled"
|
|
46
|
+
></ui-number-input></span>
|
|
47
|
+
<span class="coordinate"><span>Y1</span><ui-number-input
|
|
48
|
+
data-curve-coordinate="1"
|
|
49
|
+
from:value="$point1"
|
|
50
|
+
min="-1"
|
|
51
|
+
max="2"
|
|
52
|
+
step="0.01"
|
|
53
|
+
label="First handle Y"
|
|
54
|
+
from:size="$size"
|
|
55
|
+
from:disabled="$disabled"
|
|
56
|
+
></ui-number-input></span>
|
|
57
|
+
<span class="coordinate"><span>X2</span><ui-number-input
|
|
58
|
+
data-curve-coordinate="2"
|
|
59
|
+
from:value="$point2"
|
|
60
|
+
min="0"
|
|
61
|
+
max="1"
|
|
62
|
+
step="0.01"
|
|
63
|
+
label="Second handle X"
|
|
64
|
+
from:size="$size"
|
|
65
|
+
from:disabled="$disabled"
|
|
66
|
+
></ui-number-input></span>
|
|
67
|
+
<span class="coordinate"><span>Y2</span><ui-number-input
|
|
68
|
+
data-curve-coordinate="3"
|
|
69
|
+
from:value="$point3"
|
|
70
|
+
min="-1"
|
|
71
|
+
max="2"
|
|
72
|
+
step="0.01"
|
|
73
|
+
label="Second handle Y"
|
|
74
|
+
from:size="$size"
|
|
75
|
+
from:disabled="$disabled"
|
|
76
|
+
></ui-number-input></span>
|
|
77
|
+
</span>
|
|
78
|
+
<output $ref="result">{$value}</output>
|
|
79
|
+
</span>
|
|
80
|
+
<style>
|
|
81
|
+
:host {
|
|
82
|
+
display: grid !important;
|
|
83
|
+
gap: var(--ui-space-3) !important;
|
|
84
|
+
margin: 0 !important;
|
|
85
|
+
padding: 0 !important;
|
|
86
|
+
min-inline-size: 0;
|
|
87
|
+
}
|
|
88
|
+
.plot-frame {
|
|
89
|
+
box-sizing: border-box !important;
|
|
90
|
+
display: block !important;
|
|
91
|
+
block-size: 12rem;
|
|
92
|
+
padding: max(var(--ui-space-4), 0.75rem, calc(var(--ui-control-min-block-size) / 2)) !important;
|
|
93
|
+
margin: 0 !important;
|
|
94
|
+
border: var(--ui-border-width) solid var(--ui-control-border);
|
|
95
|
+
border-radius: var(--ui-field-radius, var(--ui-radius-md));
|
|
96
|
+
background: var(--ui-control-surface, var(--ui-surface));
|
|
97
|
+
}
|
|
98
|
+
.plot {
|
|
99
|
+
position: relative;
|
|
100
|
+
display: block !important;
|
|
101
|
+
inline-size: 100%;
|
|
102
|
+
block-size: 100%;
|
|
103
|
+
}
|
|
104
|
+
svg {
|
|
105
|
+
inline-size: 100%;
|
|
106
|
+
block-size: 100%;
|
|
107
|
+
overflow: visible;
|
|
108
|
+
}
|
|
109
|
+
path {
|
|
110
|
+
fill: none;
|
|
111
|
+
stroke: var(--ui-accent-solid);
|
|
112
|
+
stroke-width: 2;
|
|
113
|
+
vector-effect: non-scaling-stroke;
|
|
114
|
+
}
|
|
115
|
+
.guide {
|
|
116
|
+
stroke: var(--ui-control-border);
|
|
117
|
+
stroke-width: 1;
|
|
118
|
+
}
|
|
119
|
+
.handle {
|
|
120
|
+
position: absolute;
|
|
121
|
+
left: 25%;
|
|
122
|
+
top: 63.333%;
|
|
123
|
+
translate: -50% -50%;
|
|
124
|
+
inline-size: max(1.5rem, var(--ui-control-min-block-size));
|
|
125
|
+
block-size: max(1.5rem, var(--ui-control-min-block-size));
|
|
126
|
+
border: 0;
|
|
127
|
+
border-radius: 50%;
|
|
128
|
+
background: transparent;
|
|
129
|
+
color: var(--ui-text-primary);
|
|
130
|
+
touch-action: none;
|
|
131
|
+
cursor: grab;
|
|
132
|
+
padding: 0 !important;
|
|
133
|
+
margin: 0 !important;
|
|
134
|
+
}
|
|
135
|
+
.second {
|
|
136
|
+
top: 33.333%;
|
|
137
|
+
}
|
|
138
|
+
.handle::after {
|
|
139
|
+
content: "";
|
|
140
|
+
position: absolute;
|
|
141
|
+
inset: 25%;
|
|
142
|
+
border: var(--ui-border-width) solid var(--ui-accent-solid);
|
|
143
|
+
background: var(--ui-surface-raised);
|
|
144
|
+
border-radius: 50%;
|
|
145
|
+
box-shadow: var(--ui-shadow-xs);
|
|
146
|
+
}
|
|
147
|
+
.handle::before {
|
|
148
|
+
content: "";
|
|
149
|
+
position: absolute;
|
|
150
|
+
inset: 40%;
|
|
151
|
+
background: var(--ui-accent-solid);
|
|
152
|
+
border-radius: 50%;
|
|
153
|
+
z-index: 1;
|
|
154
|
+
}
|
|
155
|
+
.handle:focus-visible {
|
|
156
|
+
outline: var(--ui-focus-width) solid var(--ui-control-focus, var(--ui-accent-solid));
|
|
157
|
+
outline-offset: var(--ui-space-1);
|
|
158
|
+
}
|
|
159
|
+
.handle:disabled {
|
|
160
|
+
cursor: not-allowed;
|
|
161
|
+
}
|
|
162
|
+
.coordinates {
|
|
163
|
+
display: grid !important;
|
|
164
|
+
grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
|
|
165
|
+
gap: var(--ui-space-2) !important;
|
|
166
|
+
}
|
|
167
|
+
.coordinate {
|
|
168
|
+
display: grid !important;
|
|
169
|
+
gap: var(--ui-space-1) !important;
|
|
170
|
+
font-size: var(--ui-font-size-sm);
|
|
171
|
+
}
|
|
172
|
+
output {
|
|
173
|
+
overflow-wrap: anywhere;
|
|
174
|
+
font-family: var(--ui-font-mono, monospace);
|
|
175
|
+
font-size: var(--ui-font-size-sm);
|
|
176
|
+
}
|
|
177
|
+
:host[hidden] {
|
|
178
|
+
display: none !important;
|
|
179
|
+
}
|
|
180
|
+
</style>
|
|
181
|
+
</template>
|