@lmvz-ds/components 0.19.0 → 0.21.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/CHANGELOG.md +16 -0
- package/assets/icons/checkmark.svg +4 -0
- package/cjs/{aria-loader-CfFuAbJn.js → aria-loader-Cec1zR2g.js} +1 -1
- package/cjs/icons-BQASWgk-.js +80 -0
- package/cjs/{index--7IqZZqn.js → index-3g9Z9sfF.js} +765 -2854
- package/cjs/index.cjs.js +4 -3
- package/cjs/lmvz-button.cjs.entry.js +3 -3
- package/cjs/lmvz-card.cjs.entry.js +1 -1
- package/cjs/lmvz-checkbox.cjs.entry.js +113 -0
- package/cjs/lmvz-chip.cjs.entry.js +3 -3
- package/cjs/lmvz-components.cjs.js +1 -1
- package/cjs/lmvz-header_2.cjs.entry.js +3 -3
- package/cjs/lmvz-icon.cjs.entry.js +9 -7
- package/cjs/lmvz-input.cjs.entry.js +4 -4
- package/cjs/lmvz-menuitem.cjs.entry.js +4 -4
- package/cjs/lmvz-select.cjs.entry.js +3 -3
- package/cjs/lmvz-toggle.cjs.entry.js +96 -0
- package/cjs/loader.cjs.js +1 -1
- package/cjs/{logger-Bn2yoZGP.js → logger-DsM6xg6V.js} +3063 -833
- package/cjs/{reactive-controller-host-Bi9eu2bV.js → reactive-controller-host-BA4ZhjKA.js} +1 -1
- package/cjs/{icons-Tg7ySOh-.js → svg-BMBduILB.js} +31 -85
- package/collection/assets/icons/checkmark.svg +4 -0
- package/collection/collection-manifest.json +2 -0
- package/collection/components/lmvz-button/lmvz-button.css +1 -2
- package/collection/components/lmvz-card/lmvz-card.css +1 -2
- package/collection/components/lmvz-checkbox/lmvz-checkbox.css +207 -0
- package/collection/components/lmvz-checkbox/lmvz-checkbox.js +424 -0
- package/collection/components/lmvz-chip/lmvz-chip.js +1 -1
- package/collection/components/lmvz-header/lmvz-header.js +1 -1
- package/collection/components/lmvz-icon/lmvz-icon.js +5 -5
- package/collection/components/lmvz-input/lmvz-input.js +2 -2
- package/collection/components/lmvz-menuitem/lmvz-menuitem.css +1 -1
- package/collection/components/lmvz-menuitem/lmvz-menuitem.js +1 -1
- package/collection/components/lmvz-select/lmvz-select.js +1 -1
- package/collection/components/lmvz-toggle/lmvz-toggle.css +118 -0
- package/collection/components/lmvz-toggle/lmvz-toggle.js +358 -0
- package/collection/integration/header-integration/header-integration.js +1 -1
- package/collection/utils/icons/icons.js +2 -13
- package/collection/utils/icons/icons.unit.js +3 -15
- package/components/index.d.ts +4 -0
- package/components/index.d.ts.bak +4 -0
- package/components/index.js +1 -1
- package/components/lmvz-button.js +1 -1
- package/components/lmvz-card.js +1 -1
- package/components/lmvz-checkbox.d.ts +11 -0
- package/components/lmvz-checkbox.d.ts.bak +11 -0
- package/components/lmvz-checkbox.js +1 -0
- package/components/lmvz-chip.js +1 -1
- package/components/lmvz-header.js +1 -1
- package/components/lmvz-icon.js +1 -1
- package/components/lmvz-input.js +1 -1
- package/components/lmvz-menuitem.js +1 -1
- package/components/lmvz-select.js +1 -1
- package/components/lmvz-toggle.d.ts +11 -0
- package/components/lmvz-toggle.d.ts.bak +11 -0
- package/components/lmvz-toggle.js +1 -0
- package/components/p-0s99QfRy.js +12 -0
- package/components/{p-DbeHBSOe.js → p-BuFx0tTm.js} +1 -1
- package/components/p-CGmJG63p.js +1 -0
- package/components/p-CcxjkCOx.js +1 -0
- package/esm/{aria-loader-CES8Ae1e.js → aria-loader-BVolm0lC.js} +1 -1
- package/esm/icons-CmuFKDRz.js +75 -0
- package/esm/{index-BvxaUA12.js → index-Dh_9sN0q.js} +389 -2478
- package/esm/index.js +4 -3
- package/esm/lmvz-button.entry.js +3 -3
- package/esm/lmvz-card.entry.js +1 -1
- package/esm/lmvz-checkbox.entry.js +111 -0
- package/esm/lmvz-chip.entry.js +3 -3
- package/esm/lmvz-components.js +1 -1
- package/esm/lmvz-header_2.entry.js +3 -3
- package/esm/lmvz-icon.entry.js +9 -7
- package/esm/lmvz-input.entry.js +4 -4
- package/esm/lmvz-menuitem.entry.js +4 -4
- package/esm/lmvz-select.entry.js +3 -3
- package/esm/lmvz-toggle.entry.js +94 -0
- package/esm/loader.js +1 -1
- package/esm/{logger-0bL3pydp.js → logger-CGmJG63p.js} +2870 -765
- package/esm/{reactive-controller-host-J2thAxVH.js → reactive-controller-host-DHcPpJW7.js} +1 -1
- package/esm/{icons-Bj4dF1-I.js → svg-B2YoIRuh.js} +29 -80
- package/hydrate/index.js +2551 -165
- package/hydrate/index.mjs +2551 -165
- package/lmvz-components/index.esm.js +1 -1
- package/lmvz-components/lmvz-components.esm.js +1 -1
- package/lmvz-components/{p-ec96c6b6.entry.js → p-0f7a4236.entry.js} +1 -1
- package/lmvz-components/p-0s99QfRy.js +12 -0
- package/lmvz-components/p-2f83d7a2.entry.js +1 -0
- package/lmvz-components/{p-6e8acbd9.entry.js → p-32171f4f.entry.js} +1 -1
- package/lmvz-components/{p-9212bd23.entry.js → p-400b2318.entry.js} +1 -1
- package/lmvz-components/{p-9626e951.entry.js → p-851969bd.entry.js} +1 -1
- package/lmvz-components/p-9f9d845d.entry.js +1 -0
- package/lmvz-components/p-CFsC37ww.js +1 -0
- package/lmvz-components/p-CGmJG63p.js +1 -0
- package/lmvz-components/p-CcxjkCOx.js +1 -0
- package/lmvz-components/{p-BxHnZA0M.js → p-GdMr6Qlp.js} +1 -1
- package/lmvz-components/p-a12f95da.entry.js +1 -0
- package/lmvz-components/{p-e1b847d2.entry.js → p-ab4437dc.entry.js} +1 -1
- package/lmvz-components/p-c3b7890d.entry.js +1 -0
- package/lmvz-components/{p-7a6bec13.entry.js → p-d0a0e206.entry.js} +1 -1
- package/lmvz-components/{p-DYaffOLo.js → p-dhVSUYqd.js} +1 -1
- package/manifest.json +833 -77
- package/package.json +9 -1
- package/types/components/lmvz-checkbox/lmvz-checkbox.d.ts +39 -0
- package/types/components/lmvz-toggle/lmvz-toggle.d.ts +31 -0
- package/types/components.d.ts +270 -0
- package/types/utils/icons/icons.d.ts +0 -1
- package/components/p-DXOTa5VF.js +0 -12
- package/components/p-fiRXhuXK.js +0 -1
- package/lmvz-components/p-0bL3pydp.js +0 -1
- package/lmvz-components/p-40569208.entry.js +0 -1
- package/lmvz-components/p-49ab22bd.entry.js +0 -1
- package/lmvz-components/p-Bu4Z_PMf.js +0 -1
- package/lmvz-components/p-DHZwxmLb.js +0 -12
|
@@ -1,41 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var logger = require('./logger-
|
|
4
|
-
|
|
5
|
-
const IconProviderRegistryKey = Symbol.for('LMVZ__iconProviderRegistry');
|
|
6
|
-
const inMemoryRegistry = {};
|
|
7
|
-
function getRegistry() {
|
|
8
|
-
if (typeof window === 'undefined') {
|
|
9
|
-
return inMemoryRegistry;
|
|
10
|
-
}
|
|
11
|
-
return window[IconProviderRegistryKey] ?? (window[IconProviderRegistryKey] = {});
|
|
12
|
-
}
|
|
13
|
-
function registerIconProvider(id, provider) {
|
|
14
|
-
const registry = getRegistry();
|
|
15
|
-
const providerName = id;
|
|
16
|
-
if (Object.prototype.hasOwnProperty.call(registry, providerName)) {
|
|
17
|
-
console.warn(`Icon provider with name "${providerName}" is already registered. Overwriting existing provider.`);
|
|
18
|
-
}
|
|
19
|
-
registry[providerName] = provider;
|
|
20
|
-
}
|
|
21
|
-
function getRegisteredIconProvider(id) {
|
|
22
|
-
const registry = getRegistry();
|
|
23
|
-
if (id) {
|
|
24
|
-
return registry[id];
|
|
25
|
-
}
|
|
26
|
-
const providerNames = Object.keys(registry);
|
|
27
|
-
if (providerNames.length === 0) {
|
|
28
|
-
return undefined;
|
|
29
|
-
}
|
|
30
|
-
if (providerNames.length > 1) {
|
|
31
|
-
console.warn(`Multiple icon providers registered (${providerNames.join(', ')}). Using the first one: "${providerNames[0]}".`);
|
|
32
|
-
}
|
|
33
|
-
const firstProviderName = providerNames[0];
|
|
34
|
-
if (!firstProviderName) {
|
|
35
|
-
return undefined;
|
|
36
|
-
}
|
|
37
|
-
return registry[firstProviderName];
|
|
38
|
-
}
|
|
3
|
+
var logger = require('./logger-DsM6xg6V.js');
|
|
39
4
|
|
|
40
5
|
/**
|
|
41
6
|
* This module provides types and utility functions to create and work with branded types,
|
|
@@ -92,11 +57,11 @@ class BrandValidationError extends logger.TaggedError('BrandValidationError') {
|
|
|
92
57
|
}
|
|
93
58
|
}
|
|
94
59
|
/**
|
|
95
|
-
*
|
|
60
|
+
* Creates a synchronous Micro effect that validates a string against the branded `SVGString` type.
|
|
96
61
|
*
|
|
97
62
|
* @param svg Raw SVG markup to validate.
|
|
98
63
|
*/
|
|
99
|
-
const
|
|
64
|
+
const validateSvg = (svg) => logger.try_({
|
|
100
65
|
try: () => SVGString(sanitizeSvg(svg)),
|
|
101
66
|
catch: (error) => new BrandValidationError(error, 'SVGString'),
|
|
102
67
|
});
|
|
@@ -108,10 +73,9 @@ const createValidSVGString = (svg) => logger.try_({
|
|
|
108
73
|
function isValidSVG(svg) {
|
|
109
74
|
if (typeof svg !== 'string')
|
|
110
75
|
return false;
|
|
111
|
-
const sanitizedSvg = sanitizeSvg(svg);
|
|
112
76
|
try {
|
|
113
77
|
const parser = new DOMParser();
|
|
114
|
-
const doc = parser.parseFromString(
|
|
78
|
+
const doc = parser.parseFromString(svg, 'image/svg+xml');
|
|
115
79
|
return doc.documentElement.nodeName === 'svg';
|
|
116
80
|
}
|
|
117
81
|
catch {
|
|
@@ -120,60 +84,42 @@ function isValidSVG(svg) {
|
|
|
120
84
|
}
|
|
121
85
|
function sanitizeSvg(svg) {
|
|
122
86
|
const dataUriPrefix = 'data:image/svg+xml,';
|
|
87
|
+
const dataUriPrefixWithEncoding = 'data:image/svg+xml;base64,';
|
|
123
88
|
const base = svg.trim();
|
|
89
|
+
if (base.startsWith(dataUriPrefixWithEncoding)) {
|
|
90
|
+
return atob(base.slice(dataUriPrefixWithEncoding.length));
|
|
91
|
+
}
|
|
124
92
|
return !base.startsWith(dataUriPrefix) ? base : decodeURIComponent(base.slice(dataUriPrefix.length));
|
|
125
93
|
}
|
|
126
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Returns a valid, empty SVG.
|
|
96
|
+
*/
|
|
127
97
|
const emptyDefaultSvg = () => SVGString(`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"></svg>`);
|
|
128
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Returns a valid SVG string, or a fallback empty SVG if the input is invalid.
|
|
100
|
+
*
|
|
101
|
+
* @param value The SVG string to validate.
|
|
102
|
+
*/
|
|
103
|
+
function toValidSvgStringWithFallback(value) {
|
|
129
104
|
try {
|
|
130
|
-
return
|
|
105
|
+
return logger.runSync(validateSvg(value));
|
|
131
106
|
}
|
|
132
107
|
catch {
|
|
133
|
-
console.
|
|
108
|
+
console.warn('Invalid SVG string:', value);
|
|
134
109
|
return emptyDefaultSvg();
|
|
135
110
|
}
|
|
136
111
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const resolved = await Promise.resolve(provider.resolve(icon));
|
|
147
|
-
if (!resolved?.svg) {
|
|
148
|
-
console.warn(`Icon "${icon}"${iconset ? ` from set "${iconset}"` : ''} not found in provider. Using default icon.`);
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
const validated = await toValidSvgStringWithFallback(resolved.svg);
|
|
152
|
-
if (validated) {
|
|
153
|
-
return validated;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
catch (error) {
|
|
157
|
-
console.error(`Error resolving icon "${icon}" with provider:`, error);
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
return;
|
|
161
|
-
})();
|
|
162
|
-
if (iconSvg)
|
|
163
|
-
return iconSvg;
|
|
164
|
-
console.error(`Icon "${icon}" not found${iconset ? ` in set "${iconset}"` : ''}. Using default icon.`);
|
|
165
|
-
return emptyDefaultSvg();
|
|
166
|
-
}
|
|
167
|
-
function typedIconFromSet(iconset, icon) {
|
|
168
|
-
return {
|
|
169
|
-
iconset,
|
|
170
|
-
icon,
|
|
171
|
-
};
|
|
112
|
+
function parseSvgString(value) {
|
|
113
|
+
try {
|
|
114
|
+
return logger.runSync(validateSvg(value));
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// this will be called by lmvz-icon, which might pass an icon name instead of an SVG string, so we log this at debug level to avoid spamming the console with warnings
|
|
118
|
+
console.debug('Invalid SVG string:', value);
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
172
121
|
}
|
|
173
122
|
|
|
174
|
-
exports.
|
|
175
|
-
exports.
|
|
176
|
-
exports.
|
|
177
|
-
exports.registerIconProvider = registerIconProvider;
|
|
178
|
-
exports.resolveIconSvg = resolveIconSvg;
|
|
179
|
-
exports.typedIconFromSet = typedIconFromSet;
|
|
123
|
+
exports.emptyDefaultSvg = emptyDefaultSvg;
|
|
124
|
+
exports.parseSvgString = parseSvgString;
|
|
125
|
+
exports.toValidSvgStringWithFallback = toValidSvgStringWithFallback;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none"
|
|
2
|
+
xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
|
|
3
|
+
<path d="M3.75 12.5625L8.83079 17.625L20.4375 6.375" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
</svg>
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
"components/lmvz-action/lmvz-action.js",
|
|
4
4
|
"components/lmvz-button/lmvz-button.js",
|
|
5
5
|
"components/lmvz-card/lmvz-card.js",
|
|
6
|
+
"components/lmvz-checkbox/lmvz-checkbox.js",
|
|
6
7
|
"components/lmvz-chip/lmvz-chip.js",
|
|
7
8
|
"components/lmvz-header/lmvz-header.js",
|
|
8
9
|
"components/lmvz-icon/lmvz-icon.js",
|
|
9
10
|
"components/lmvz-input/lmvz-input.js",
|
|
10
11
|
"components/lmvz-menuitem/lmvz-menuitem.js",
|
|
11
12
|
"components/lmvz-select/lmvz-select.js",
|
|
13
|
+
"components/lmvz-toggle/lmvz-toggle.js",
|
|
12
14
|
"integration/header-integration/header-integration.js"
|
|
13
15
|
],
|
|
14
16
|
"mixins": [],
|
|
@@ -91,8 +91,7 @@ button > * {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
button:focus-visible {
|
|
94
|
-
|
|
95
|
-
outline: var(--lmvz-semantic-border-width-default, 1px) solid var(--lmvz-semantic-color-status-active, #f1f9fe);
|
|
94
|
+
outline: var(--lmvz-semantic-border-width-default, 1px) solid var(--lmvz-semantic-color-status-on-active, #0e7ab4);
|
|
96
95
|
outline-offset: var(--lmvz-component-input-sm-padding-x, clamp(0.5rem, 0.44rem + 0.26vw, 0.75rem));
|
|
97
96
|
}
|
|
98
97
|
|
|
@@ -92,8 +92,7 @@ button > * {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
button:focus-visible {
|
|
95
|
-
|
|
96
|
-
outline: var(--lmvz-semantic-border-width-default, 1px) solid var(--lmvz-semantic-color-status-active, #f1f9fe);
|
|
95
|
+
outline: var(--lmvz-semantic-border-width-default, 1px) solid var(--lmvz-semantic-color-status-on-active, #0e7ab4);
|
|
97
96
|
outline-offset: var(--lmvz-component-input-sm-padding-x, clamp(0.5rem, 0.44rem + 0.26vw, 0.75rem));
|
|
98
97
|
}
|
|
99
98
|
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
|
|
2
|
+
@layer lmvz-ds.reset, lmvz-ds.theme, lmvz-ds.components, lmvz-ds.overrides;
|
|
3
|
+
/**
|
|
4
|
+
* This defines the order of our lmvz-ds' CSS layers. See readme.md for details.
|
|
5
|
+
* Important: Always import this file _before_ layering your own styles!
|
|
6
|
+
*/
|
|
7
|
+
@layer lmvz-ds.theme {
|
|
8
|
+
@font-face {
|
|
9
|
+
font-family: Router;
|
|
10
|
+
src:
|
|
11
|
+
local('Router-Book'),
|
|
12
|
+
url('/assets/fonts/Router-Book.woff') format('woff'),
|
|
13
|
+
local('Router');
|
|
14
|
+
font-weight: 400 normal;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@font-face {
|
|
18
|
+
font-family: Router;
|
|
19
|
+
src:
|
|
20
|
+
local('Router-Medium'),
|
|
21
|
+
url('/assets/fonts/Router-Medium.woff') format('woff'),
|
|
22
|
+
local('Router');
|
|
23
|
+
font-weight: 500;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@font-face {
|
|
27
|
+
font-family: Router;
|
|
28
|
+
src:
|
|
29
|
+
local('Router-Bold'),
|
|
30
|
+
url('/assets/fonts/Router-Bold.woff') format('woff'),
|
|
31
|
+
local('Router');
|
|
32
|
+
font-weight: 700 bold;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
:host {
|
|
37
|
+
display: inline-block;
|
|
38
|
+
|
|
39
|
+
--checkbox-box-size: var(--lmvz-global-s18, 18px); /* TODO: confirm this generic dimension token is intentional for checkbox box sizing */
|
|
40
|
+
--checkbox-border-radius: var(--lmvz-global-s4, 4px); /* TODO: consider component-specific token for border-radius */
|
|
41
|
+
|
|
42
|
+
--checkbox-bg: var(--lmvz-semantic-color-surface-input-primary, #ffffff);
|
|
43
|
+
--checkbox-border-color: var(--lmvz-semantic-color-border-default, #e0e0e0);
|
|
44
|
+
--checkbox-border-color-hover: var(--lmvz-semantic-color-border-hover, #c7c7c7);
|
|
45
|
+
--checkbox-border-color-checked: var(--lmvz-semantic-color-border-active, #0f8acc);
|
|
46
|
+
--checkbox-border-color-error: var(--lmvz-semantic-color-status-on-danger, #e52a31);
|
|
47
|
+
|
|
48
|
+
--checkbox-wrapper-bg-hover: var(--lmvz-semantic-color-int-tertiary-hover, #f0f0f0);
|
|
49
|
+
--checkbox-wrapper-bg-checked: var(--lmvz-semantic-color-status-active, #f1f9fe);
|
|
50
|
+
|
|
51
|
+
--checkbox-ripple-bg: var(--lmvz-semantic-color-int-secondary-hover, #e0e0e0);
|
|
52
|
+
|
|
53
|
+
--checkbox-checkmark-color: var(--lmvz-semantic-color-border-active, #0f8acc);
|
|
54
|
+
|
|
55
|
+
--checkbox-label-color: var(--lmvz-semantic-color-on-surface-primary, #000000);
|
|
56
|
+
--checkbox-label-color-checked: var(--lmvz-semantic-color-status-on-active, #0e7ab4);
|
|
57
|
+
--checkbox-helper-color: var(--lmvz-semantic-color-on-surface-secondary, #7a7a7a);
|
|
58
|
+
--checkbox-error-color: var(--lmvz-semantic-color-status-on-danger, #e52a31);
|
|
59
|
+
--checkbox-focus-color: var(--lmvz-semantic-color-status-on-active, #0e7ab4);
|
|
60
|
+
|
|
61
|
+
--checkbox-easing: var(--lmvz-global-easing-default, ease);
|
|
62
|
+
--checkbox-duration: 0.2s;
|
|
63
|
+
}
|
|
64
|
+
.pill {
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: var(--lmvz-component-input-md-gap-x, clamp(0.25rem, 0.16rem + 0.39vw, 0.63rem));
|
|
68
|
+
padding-block: var(--lmvz-dimension-2-8, clamp(0.13rem, 0.03rem + 0.39vw, 0.5rem));
|
|
69
|
+
padding-inline: var(--lmvz-dimension-4-10, clamp(0.25rem, 0.16rem + 0.39vw, 0.63rem));
|
|
70
|
+
border-radius: var(--lmvz-semantic-border-radius-round, 999px);
|
|
71
|
+
cursor: pointer;
|
|
72
|
+
/* WCAG 2.5.5 AAA: 44px minimum touch target */
|
|
73
|
+
/* min-block-size: 44px; */
|
|
74
|
+
text-decoration: none;
|
|
75
|
+
background-color: transparent;
|
|
76
|
+
transition: background-color var(--checkbox-duration) var(--checkbox-easing);
|
|
77
|
+
}
|
|
78
|
+
input {
|
|
79
|
+
position: absolute;
|
|
80
|
+
opacity: 0;
|
|
81
|
+
width: var(--checkbox-box-size);
|
|
82
|
+
height: var(--checkbox-box-size);
|
|
83
|
+
margin: 0;
|
|
84
|
+
cursor: pointer;
|
|
85
|
+
z-index: 1;
|
|
86
|
+
}
|
|
87
|
+
.box {
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
justify-content: center;
|
|
91
|
+
width: var(--checkbox-box-size);
|
|
92
|
+
height: var(--checkbox-box-size);
|
|
93
|
+
background-color: var(--checkbox-bg);
|
|
94
|
+
border: var(--lmvz-semantic-border-width-default, 1px) solid var(--checkbox-border-color);
|
|
95
|
+
border-radius: var(--checkbox-border-radius);
|
|
96
|
+
color: var(--checkbox-checkmark-color);
|
|
97
|
+
transition:
|
|
98
|
+
border-color var(--checkbox-duration) var(--checkbox-easing),
|
|
99
|
+
background-color var(--checkbox-duration) var(--checkbox-easing);
|
|
100
|
+
pointer-events: none;
|
|
101
|
+
flex-shrink: 0;
|
|
102
|
+
}
|
|
103
|
+
.indicator {
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
line-height: 0;
|
|
108
|
+
}
|
|
109
|
+
.content {
|
|
110
|
+
display: flex;
|
|
111
|
+
flex-direction: column;
|
|
112
|
+
overflow-wrap: break-word;
|
|
113
|
+
min-width: 0;
|
|
114
|
+
}
|
|
115
|
+
label {
|
|
116
|
+
font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.4
|
|
117
|
+
Router);
|
|
118
|
+
color: var(--checkbox-label-color);
|
|
119
|
+
transition: color var(--checkbox-duration) var(--checkbox-easing);
|
|
120
|
+
}
|
|
121
|
+
.helper-text {
|
|
122
|
+
font: var(--lmvz-typography-body-sm, 400 clamp(0.75rem, 0.73rem + 0.06vw, 0.81rem) / 1.4
|
|
123
|
+
Router);
|
|
124
|
+
/* font-weight: 400 per DS token standard (body-sm). Note: lmvz-input.css [role='status'] incorrectly uses font-weight: 500 — DS inconsistency, see lmvz-input.css line ~153 */
|
|
125
|
+
color: var(--checkbox-helper-color);
|
|
126
|
+
margin-block-start: 2px;
|
|
127
|
+
}
|
|
128
|
+
.error-text {
|
|
129
|
+
font: var(--lmvz-typography-body-sm, 400 clamp(0.75rem, 0.73rem + 0.06vw, 0.81rem) / 1.4
|
|
130
|
+
Router);
|
|
131
|
+
color: var(--checkbox-error-color);
|
|
132
|
+
display: block;
|
|
133
|
+
margin-block-start: 4px;
|
|
134
|
+
padding-inline: 10px;
|
|
135
|
+
}
|
|
136
|
+
/* Hover state, guarded to prevent sticky hover on touch devices */
|
|
137
|
+
@media (hover: hover) {
|
|
138
|
+
.pill:hover {
|
|
139
|
+
background-color: var(--checkbox-wrapper-bg-hover);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.pill:hover .box {
|
|
143
|
+
border-color: var(--checkbox-border-color-hover);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/* Checked state */
|
|
147
|
+
:host([checked]) .pill {
|
|
148
|
+
background-color: var(--checkbox-wrapper-bg-checked);
|
|
149
|
+
}
|
|
150
|
+
:host([checked]) .box {
|
|
151
|
+
border-color: var(--checkbox-border-color-checked);
|
|
152
|
+
}
|
|
153
|
+
:host([checked]) label {
|
|
154
|
+
color: var(--checkbox-label-color-checked);
|
|
155
|
+
/* Contrast ~4.4:1 on checked wrapper background (#f1f9fe) — exception accepted per DS decision 5.3; approximately at WCAG AA threshold; pending design review for formal verification */
|
|
156
|
+
}
|
|
157
|
+
/* Error state. MUST appear AFTER checked state rules (error takes visual precedence) */
|
|
158
|
+
:host([error]) .box {
|
|
159
|
+
border-color: var(--checkbox-border-color-error);
|
|
160
|
+
}
|
|
161
|
+
:host([error]) .helper-text {
|
|
162
|
+
color: var(--checkbox-error-color);
|
|
163
|
+
}
|
|
164
|
+
/* Disabled state */
|
|
165
|
+
:host([disabled]) {
|
|
166
|
+
opacity: var(--lmvz-component-input-disabled-opacity, 40%);
|
|
167
|
+
pointer-events: none;
|
|
168
|
+
}
|
|
169
|
+
:host([disabled]) .pill {
|
|
170
|
+
cursor: not-allowed;
|
|
171
|
+
}
|
|
172
|
+
:host([disabled]) input {
|
|
173
|
+
cursor: not-allowed;
|
|
174
|
+
}
|
|
175
|
+
/* Focus ring, applied via sibling combinator on the native input */
|
|
176
|
+
input:focus-visible ~ .box {
|
|
177
|
+
outline: 2px solid var(--checkbox-focus-color);
|
|
178
|
+
outline-offset: 2px;
|
|
179
|
+
/* box-shadow: 0 0 0 3px rgba(15, 138, 204, 0.2); TODO: no design token available for focus shadow color/spread */
|
|
180
|
+
box-shadow: 0 var(--lmvz-semantic-shadow-l1-1-position-y, 2px) 0 var(--lmvz-semantic-shadow-l1-1-blur, 4px) var(--lmvz-semantic-color-shadow-l1-colored, rgba(175, 223, 249, 0.42));
|
|
181
|
+
}
|
|
182
|
+
/* Forced Colors / Windows High Contrast */
|
|
183
|
+
@media (forced-colors: active) {
|
|
184
|
+
.box {
|
|
185
|
+
forced-color-adjust: auto;
|
|
186
|
+
border-color: ButtonText;
|
|
187
|
+
background-color: Field;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
:host([checked]) .box {
|
|
191
|
+
border-color: Highlight;
|
|
192
|
+
background-color: Field;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.indicator {
|
|
196
|
+
color: ButtonText;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
:host([checked]) .indicator {
|
|
200
|
+
color: HighlightText;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
input:focus-visible ~ .box {
|
|
204
|
+
outline-color: Highlight;
|
|
205
|
+
box-shadow: none;
|
|
206
|
+
}
|
|
207
|
+
}
|