@santi020k/lumen-elements 3.0.1 → 4.1.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/README.md +518 -5
- package/dist/bullet-chart-html.d.ts +5 -0
- package/dist/bullet-chart-html.d.ts.map +1 -0
- package/dist/bullet-chart-html.js +56 -0
- package/dist/chart-activation.d.ts +15 -0
- package/dist/chart-activation.d.ts.map +1 -0
- package/dist/chart-activation.js +93 -0
- package/dist/chart-html.d.ts +22 -0
- package/dist/chart-html.d.ts.map +1 -0
- package/dist/chart-html.js +1 -0
- package/dist/comparison-chart-html.d.ts +4 -0
- package/dist/comparison-chart-html.d.ts.map +1 -0
- package/dist/comparison-chart-html.js +36 -0
- package/dist/components/ai-surfaces.d.ts +115 -0
- package/dist/components/ai-surfaces.d.ts.map +1 -0
- package/dist/components/ai-surfaces.js +270 -0
- package/dist/components/button.d.ts +55 -2
- package/dist/components/button.d.ts.map +1 -1
- package/dist/components/button.js +110 -2
- package/dist/components/card.d.ts +6 -0
- package/dist/components/card.d.ts.map +1 -1
- package/dist/components/card.js +6 -1
- package/dist/components/combobox.d.ts +1 -2
- package/dist/components/combobox.d.ts.map +1 -1
- package/dist/components/combobox.js +27 -121
- package/dist/components/dashboard.d.ts +41 -0
- package/dist/components/dashboard.d.ts.map +1 -0
- package/dist/components/dashboard.js +88 -0
- package/dist/components/device-frame.d.ts +31 -0
- package/dist/components/device-frame.d.ts.map +1 -0
- package/dist/components/device-frame.js +95 -0
- package/dist/components/foundations.d.ts +58 -18
- package/dist/components/foundations.d.ts.map +1 -1
- package/dist/components/foundations.js +160 -9
- package/dist/components/image-comparison.d.ts +33 -0
- package/dist/components/image-comparison.d.ts.map +1 -0
- package/dist/components/image-comparison.js +144 -0
- package/dist/components/media-selection.d.ts +41 -0
- package/dist/components/media-selection.d.ts.map +1 -0
- package/dist/components/media-selection.js +114 -0
- package/dist/components/media-viewport.d.ts +30 -0
- package/dist/components/media-viewport.d.ts.map +1 -0
- package/dist/components/media-viewport.js +108 -0
- package/dist/components/virtual-list.d.ts +38 -0
- package/dist/components/virtual-list.d.ts.map +1 -0
- package/dist/components/virtual-list.js +30 -0
- package/dist/components/visual-interactions.d.ts +65 -0
- package/dist/components/visual-interactions.d.ts.map +1 -0
- package/dist/components/visual-interactions.js +91 -0
- package/dist/components/world-map.d.ts +46 -0
- package/dist/components/world-map.d.ts.map +1 -0
- package/dist/components/world-map.js +312 -0
- package/dist/consumer-behaviors.d.ts +36 -0
- package/dist/consumer-behaviors.d.ts.map +1 -0
- package/dist/consumer-behaviors.js +1 -0
- package/dist/define.d.ts +229 -6
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +1 -1
- package/dist/element-base.js +1 -1
- package/dist/expanded-chart-html.d.ts +9 -0
- package/dist/expanded-chart-html.d.ts.map +1 -0
- package/dist/expanded-chart-html.js +61 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +34 -6
- package/styles/critical.css +696 -66
|
@@ -1,8 +1,124 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { resolveLumenLoadingSemantics, resolveLumenSkeletonSize } from '@santi020k/lumen-core';
|
|
2
|
+
import { createLumenElementClass, defineLumenElement, LumenElement } from '../element-base.js';
|
|
3
|
+
const createFoundation = (config, element = createLumenElementClass(config)) => ({ config, element });
|
|
4
|
+
const loadingSemanticAttributes = ['aria-hidden', 'aria-label', 'aria-labelledby', 'role'];
|
|
5
|
+
const loadingOwnershipAttribute = 'data-ui-loading-managed';
|
|
6
|
+
const generatedLoadingValues = { 'aria-hidden': 'true', role: 'status' };
|
|
7
|
+
const isManagedLoadingAttribute = (value) => value === 'aria-hidden' || value === 'role';
|
|
8
|
+
const skeletonSizeProperties = { height: '--ui-skeleton-height', width: '--ui-skeleton-width' };
|
|
9
|
+
class LumenLoadingIndicatorElement extends LumenElement {
|
|
10
|
+
#applied = new Set();
|
|
11
|
+
#applying = false;
|
|
12
|
+
connectedCallback() {
|
|
13
|
+
super.connectedCallback();
|
|
14
|
+
this.#restoreOwnership();
|
|
15
|
+
this.syncLoadingState();
|
|
16
|
+
}
|
|
17
|
+
attributeChangedCallback(name, previousValue, value) {
|
|
18
|
+
super.attributeChangedCallback(name, previousValue, value);
|
|
19
|
+
if (this.#applying)
|
|
20
|
+
return;
|
|
21
|
+
if (name === 'aria-hidden' || name === 'role') {
|
|
22
|
+
this.#applied.delete(name);
|
|
23
|
+
if (previousValue !== null && previousValue !== undefined)
|
|
24
|
+
this.#forgetOwnership(name);
|
|
25
|
+
}
|
|
26
|
+
if (this.isConnected)
|
|
27
|
+
this.syncLoadingState();
|
|
28
|
+
}
|
|
29
|
+
#restoreOwnership() {
|
|
30
|
+
const recorded = this.getAttribute(loadingOwnershipAttribute)?.split(' ') ?? [];
|
|
31
|
+
for (const name of recorded) {
|
|
32
|
+
if (isManagedLoadingAttribute(name) && this.getAttribute(name) === generatedLoadingValues[name]) {
|
|
33
|
+
this.#applied.add(name);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
#recordOwnership() {
|
|
38
|
+
this.#writeOwnership([...this.#applied]);
|
|
39
|
+
}
|
|
40
|
+
#forgetOwnership(name) {
|
|
41
|
+
const recorded = this.getAttribute(loadingOwnershipAttribute)?.split(' ') ?? [];
|
|
42
|
+
const owned = [...recorded.filter(isManagedLoadingAttribute), ...this.#applied];
|
|
43
|
+
this.#writeOwnership(owned.filter(token => token !== name));
|
|
44
|
+
}
|
|
45
|
+
#writeOwnership(tokens) {
|
|
46
|
+
const owned = [...new Set(tokens)].sort().join(' ');
|
|
47
|
+
if ((this.getAttribute(loadingOwnershipAttribute) ?? '') === owned)
|
|
48
|
+
return;
|
|
49
|
+
this.#applying = true;
|
|
50
|
+
try {
|
|
51
|
+
if (owned)
|
|
52
|
+
this.setAttribute(loadingOwnershipAttribute, owned);
|
|
53
|
+
else
|
|
54
|
+
this.removeAttribute(loadingOwnershipAttribute);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
this.#applying = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
syncLoadingState() {
|
|
61
|
+
const semantics = resolveLumenLoadingSemantics({
|
|
62
|
+
ariaHidden: this.#readExplicit('aria-hidden'),
|
|
63
|
+
ariaLabel: this.getAttribute('aria-label'),
|
|
64
|
+
ariaLabelledby: this.getAttribute('aria-labelledby'),
|
|
65
|
+
role: this.#readExplicit('role')
|
|
66
|
+
});
|
|
67
|
+
this.#manage('aria-hidden', semantics.ariaHidden);
|
|
68
|
+
this.#manage('role', semantics.role);
|
|
69
|
+
}
|
|
70
|
+
#readExplicit(name) {
|
|
71
|
+
return this.#applied.has(name) ? null : this.getAttribute(name);
|
|
72
|
+
}
|
|
73
|
+
#manage(name, value) {
|
|
74
|
+
if (!this.#applied.has(name) && this.hasAttribute(name))
|
|
75
|
+
return;
|
|
76
|
+
this.#applying = true;
|
|
77
|
+
try {
|
|
78
|
+
if (value === undefined) {
|
|
79
|
+
this.removeAttribute(name);
|
|
80
|
+
this.#applied.delete(name);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
this.setAttribute(name, value);
|
|
84
|
+
this.#applied.add(name);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
this.#applying = false;
|
|
89
|
+
}
|
|
90
|
+
this.#recordOwnership();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
class LumenSkeletonBehaviorElement extends LumenLoadingIndicatorElement {
|
|
94
|
+
#appliedSizes = new Map();
|
|
95
|
+
syncLoadingState() {
|
|
96
|
+
super.syncLoadingState();
|
|
97
|
+
for (const [attribute, property] of Object.entries(skeletonSizeProperties)) {
|
|
98
|
+
const size = resolveLumenSkeletonSize(this.getAttribute(attribute));
|
|
99
|
+
const current = this.style.getPropertyValue(property);
|
|
100
|
+
const ownership = `data-ui-skeleton-${attribute}`;
|
|
101
|
+
if (!this.#appliedSizes.has(property) && current && current === this.getAttribute(ownership)) {
|
|
102
|
+
this.#appliedSizes.set(property, current);
|
|
103
|
+
}
|
|
104
|
+
const applied = this.#appliedSizes.get(property);
|
|
105
|
+
if (current && current !== applied) {
|
|
106
|
+
this.#appliedSizes.delete(property);
|
|
107
|
+
this.removeAttribute(ownership);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (size) {
|
|
111
|
+
this.style.setProperty(property, size);
|
|
112
|
+
this.#appliedSizes.set(property, size);
|
|
113
|
+
this.setAttribute(ownership, size);
|
|
114
|
+
}
|
|
115
|
+
else if (this.#appliedSizes.delete(property)) {
|
|
116
|
+
this.style.removeProperty(property);
|
|
117
|
+
this.removeAttribute(ownership);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
6
122
|
export const lumenCardContentElementConfig = {
|
|
7
123
|
baseClassName: 'ui-card__content',
|
|
8
124
|
defaults: { 'data-slot': 'card-content' },
|
|
@@ -58,6 +174,12 @@ export const lumenGridElementConfig = {
|
|
|
58
174
|
auto: 'ui-grid--columns-auto'
|
|
59
175
|
},
|
|
60
176
|
gap: {
|
|
177
|
+
'2xl': 'ui-grid--gap-2xl',
|
|
178
|
+
'3xl': 'ui-grid--gap-3xl',
|
|
179
|
+
group: 'ui-grid--gap-group',
|
|
180
|
+
related: 'ui-grid--gap-related',
|
|
181
|
+
section: 'ui-grid--gap-section',
|
|
182
|
+
xs: 'ui-grid--gap-xs',
|
|
61
183
|
lg: 'ui-grid--gap-lg',
|
|
62
184
|
md: 'ui-grid--gap-md',
|
|
63
185
|
none: 'ui-grid--gap-none',
|
|
@@ -66,7 +188,7 @@ export const lumenGridElementConfig = {
|
|
|
66
188
|
}
|
|
67
189
|
},
|
|
68
190
|
baseClassName: 'ui-grid',
|
|
69
|
-
defaults: { 'data-ui-grid': '', columns: 'auto', gap: '
|
|
191
|
+
defaults: { 'data-ui-grid': '', columns: 'auto', gap: 'group' },
|
|
70
192
|
tagName: 'lumen-grid'
|
|
71
193
|
};
|
|
72
194
|
export const lumenLabelElementConfig = {
|
|
@@ -85,20 +207,45 @@ export const lumenSeparatorElementConfig = {
|
|
|
85
207
|
tagName: 'lumen-separator'
|
|
86
208
|
};
|
|
87
209
|
export const lumenSkeletonElementConfig = {
|
|
210
|
+
attributeClasses: {
|
|
211
|
+
animation: { none: 'ui-skeleton--static', pulse: 'ui-skeleton--pulse' },
|
|
212
|
+
shape: { circle: 'ui-skeleton--circle', text: 'ui-skeleton--text' }
|
|
213
|
+
},
|
|
88
214
|
baseClassName: 'ui-skeleton',
|
|
215
|
+
observedAttributes: ['animation', 'height', 'shape', 'width', ...loadingSemanticAttributes],
|
|
89
216
|
tagName: 'lumen-skeleton'
|
|
90
217
|
};
|
|
91
218
|
export const lumenSpinnerElementConfig = {
|
|
92
219
|
baseClassName: 'ui-spinner',
|
|
220
|
+
observedAttributes: loadingSemanticAttributes,
|
|
93
221
|
tagName: 'lumen-spinner'
|
|
94
222
|
};
|
|
95
223
|
export const lumenStackElementConfig = {
|
|
96
224
|
attributeClasses: {
|
|
225
|
+
align: {
|
|
226
|
+
center: 'ui-stack--align-center',
|
|
227
|
+
end: 'ui-stack--align-end',
|
|
228
|
+
start: 'ui-stack--align-start',
|
|
229
|
+
stretch: 'ui-stack--align-stretch'
|
|
230
|
+
},
|
|
97
231
|
direction: {
|
|
98
232
|
horizontal: 'ui-stack--horizontal',
|
|
99
233
|
vertical: 'ui-stack--vertical'
|
|
100
234
|
},
|
|
235
|
+
justify: {
|
|
236
|
+
between: 'ui-stack--justify-between',
|
|
237
|
+
center: 'ui-stack--justify-center',
|
|
238
|
+
end: 'ui-stack--justify-end',
|
|
239
|
+
start: 'ui-stack--justify-start'
|
|
240
|
+
},
|
|
241
|
+
wrap: { '': 'ui-stack--wrap', true: 'ui-stack--wrap' },
|
|
101
242
|
gap: {
|
|
243
|
+
'2xl': 'ui-stack--gap-2xl',
|
|
244
|
+
'3xl': 'ui-stack--gap-3xl',
|
|
245
|
+
group: 'ui-stack--gap-group',
|
|
246
|
+
related: 'ui-stack--gap-related',
|
|
247
|
+
section: 'ui-stack--gap-section',
|
|
248
|
+
xs: 'ui-stack--gap-xs',
|
|
102
249
|
lg: 'ui-stack--gap-lg',
|
|
103
250
|
md: 'ui-stack--gap-md',
|
|
104
251
|
none: 'ui-stack--gap-none',
|
|
@@ -107,7 +254,7 @@ export const lumenStackElementConfig = {
|
|
|
107
254
|
}
|
|
108
255
|
},
|
|
109
256
|
baseClassName: 'ui-stack',
|
|
110
|
-
defaults: { 'data-ui-stack': '', direction: 'vertical', gap: '
|
|
257
|
+
defaults: { 'data-ui-stack': '', direction: 'vertical', gap: 'group' },
|
|
111
258
|
tagName: 'lumen-stack'
|
|
112
259
|
};
|
|
113
260
|
export const lumenTypographyElementConfig = {
|
|
@@ -129,8 +276,12 @@ const direction = createFoundation(lumenDirectionElementConfig);
|
|
|
129
276
|
const grid = createFoundation(lumenGridElementConfig);
|
|
130
277
|
const label = createFoundation(lumenLabelElementConfig);
|
|
131
278
|
const separator = createFoundation(lumenSeparatorElementConfig);
|
|
132
|
-
const skeleton = createFoundation(lumenSkeletonElementConfig
|
|
133
|
-
|
|
279
|
+
const skeleton = createFoundation(lumenSkeletonElementConfig, class extends LumenSkeletonBehaviorElement {
|
|
280
|
+
static config = lumenSkeletonElementConfig;
|
|
281
|
+
});
|
|
282
|
+
const spinner = createFoundation(lumenSpinnerElementConfig, class extends LumenLoadingIndicatorElement {
|
|
283
|
+
static config = lumenSpinnerElementConfig;
|
|
284
|
+
});
|
|
134
285
|
const stack = createFoundation(lumenStackElementConfig);
|
|
135
286
|
const typography = createFoundation(lumenTypographyElementConfig);
|
|
136
287
|
const visuallyHidden = createFoundation(lumenVisuallyHiddenElementConfig);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type LumenCustomElementRegistry, LumenElement } from '../element-base.js';
|
|
2
|
+
export declare const lumenImageComparisonElementConfig: {
|
|
3
|
+
readonly baseClassName: "ui-image-comparison";
|
|
4
|
+
readonly observedAttributes: readonly ["after-label", "before-label", "disabled", "fit", "label", "lang", "locale", "mode", "name", "ratio", "value"];
|
|
5
|
+
readonly tagName: "lumen-image-comparison";
|
|
6
|
+
};
|
|
7
|
+
export declare class LumenImageComparisonElement extends LumenElement {
|
|
8
|
+
static config: {
|
|
9
|
+
readonly baseClassName: "ui-image-comparison";
|
|
10
|
+
readonly observedAttributes: readonly ["after-label", "before-label", "disabled", "fit", "label", "lang", "locale", "mode", "name", "ratio", "value"];
|
|
11
|
+
readonly tagName: "lumen-image-comparison";
|
|
12
|
+
};
|
|
13
|
+
private abortController;
|
|
14
|
+
private frame;
|
|
15
|
+
private range;
|
|
16
|
+
private beforeLabel;
|
|
17
|
+
private afterLabel;
|
|
18
|
+
private controlLabel;
|
|
19
|
+
private reflectingInput;
|
|
20
|
+
get value(): number;
|
|
21
|
+
set value(value: number);
|
|
22
|
+
connectedCallback(): void;
|
|
23
|
+
disconnectedCallback(): void;
|
|
24
|
+
attributeChangedCallback(name: string): void;
|
|
25
|
+
private connect;
|
|
26
|
+
private createContent;
|
|
27
|
+
private get afterText();
|
|
28
|
+
private get locale();
|
|
29
|
+
private disabledForMode;
|
|
30
|
+
private update;
|
|
31
|
+
}
|
|
32
|
+
export declare const defineLumenImageComparison: (registry?: LumenCustomElementRegistry) => void;
|
|
33
|
+
//# sourceMappingURL=image-comparison.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-comparison.d.ts","sourceRoot":"","sources":["../../src/components/image-comparison.ts"],"names":[],"mappings":"AAOA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,YAAY,EAEb,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,iCAAiC;;;;CAIP,CAAA;AAEvC,qBAAa,2BAA4B,SAAQ,YAAY;IAC3D,OAAgB,MAAM;;;;MAAoC;IAE1D,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,eAAe,CAAQ;IAE/B,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAEtB;IAEQ,iBAAiB,IAAI,IAAI;IAUzB,oBAAoB,IAAI,IAAI;IAM5B,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQrD,OAAO,CAAC,OAAO;IA6Cf,OAAO,CAAC,aAAa;IAiErB,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,MAAM;CA8Bf;AAED,eAAO,MAAM,0BAA0B,GAAI,WAAW,0BAA0B,KAAG,IAElF,CAAA"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { formatLumenImageComparisonValue, normalizeLumenImageComparisonMode, normalizeLumenImageComparisonRatio, normalizeLumenImageComparisonValue, syncLumenImageComparisonMode } from '@santi020k/lumen-core';
|
|
2
|
+
import { defineLumenElement, LumenElement } from '../element-base.js';
|
|
3
|
+
export const lumenImageComparisonElementConfig = {
|
|
4
|
+
baseClassName: 'ui-image-comparison',
|
|
5
|
+
observedAttributes: ['after-label', 'before-label', 'disabled', 'fit', 'label', 'lang', 'locale', 'mode', 'name', 'ratio', 'value'],
|
|
6
|
+
tagName: 'lumen-image-comparison'
|
|
7
|
+
};
|
|
8
|
+
export class LumenImageComparisonElement extends LumenElement {
|
|
9
|
+
static config = lumenImageComparisonElementConfig;
|
|
10
|
+
abortController;
|
|
11
|
+
frame;
|
|
12
|
+
range;
|
|
13
|
+
beforeLabel;
|
|
14
|
+
afterLabel;
|
|
15
|
+
controlLabel;
|
|
16
|
+
reflectingInput = false;
|
|
17
|
+
get value() {
|
|
18
|
+
return normalizeLumenImageComparisonValue(this.getAttribute('value'));
|
|
19
|
+
}
|
|
20
|
+
set value(value) {
|
|
21
|
+
this.setAttribute('value', String(normalizeLumenImageComparisonValue(value)));
|
|
22
|
+
}
|
|
23
|
+
connectedCallback() {
|
|
24
|
+
super.connectedCallback();
|
|
25
|
+
this.connect();
|
|
26
|
+
queueMicrotask(() => {
|
|
27
|
+
if (this.isConnected && !this.range)
|
|
28
|
+
this.connect();
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
disconnectedCallback() {
|
|
32
|
+
this.abortController?.abort();
|
|
33
|
+
this.abortController = undefined;
|
|
34
|
+
}
|
|
35
|
+
attributeChangedCallback(name) {
|
|
36
|
+
super.attributeChangedCallback();
|
|
37
|
+
if (name === 'value' && this.range && !this.reflectingInput)
|
|
38
|
+
this.range.defaultValue = String(this.value);
|
|
39
|
+
this.update();
|
|
40
|
+
}
|
|
41
|
+
connect() {
|
|
42
|
+
if (!this.range)
|
|
43
|
+
this.createContent();
|
|
44
|
+
if (!this.range)
|
|
45
|
+
return;
|
|
46
|
+
this.abortController?.abort();
|
|
47
|
+
this.abortController = new AbortController();
|
|
48
|
+
const { signal } = this.abortController;
|
|
49
|
+
this.range.addEventListener('input', () => {
|
|
50
|
+
if (!this.range || this.range.disabled)
|
|
51
|
+
return;
|
|
52
|
+
this.reflectingInput = true;
|
|
53
|
+
try {
|
|
54
|
+
this.value = this.range.valueAsNumber;
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
this.reflectingInput = false;
|
|
58
|
+
}
|
|
59
|
+
this.dispatchEvent(new CustomEvent('ui:image-comparison-change', {
|
|
60
|
+
bubbles: true,
|
|
61
|
+
detail: { value: this.value }
|
|
62
|
+
}));
|
|
63
|
+
}, { signal });
|
|
64
|
+
this.ownerDocument.addEventListener('reset', event => {
|
|
65
|
+
const range = this.range;
|
|
66
|
+
if (!range)
|
|
67
|
+
return;
|
|
68
|
+
if (event.target !== range.form)
|
|
69
|
+
return;
|
|
70
|
+
window.setTimeout(() => {
|
|
71
|
+
if (signal.aborted || event.defaultPrevented || !this.isConnected)
|
|
72
|
+
return;
|
|
73
|
+
this.value = normalizeLumenImageComparisonValue(range.defaultValue);
|
|
74
|
+
});
|
|
75
|
+
}, { capture: true, signal });
|
|
76
|
+
this.update();
|
|
77
|
+
}
|
|
78
|
+
createContent() {
|
|
79
|
+
const before = this.querySelector(':scope > [slot="before"]');
|
|
80
|
+
const after = this.querySelector(':scope > [slot="after"]');
|
|
81
|
+
if (!before || !after)
|
|
82
|
+
return;
|
|
83
|
+
this.frame = this.ownerDocument.createElement('div');
|
|
84
|
+
this.frame.className = 'ui-image-comparison__frame';
|
|
85
|
+
const beforeLayer = this.ownerDocument.createElement('div');
|
|
86
|
+
const afterLayer = this.ownerDocument.createElement('div');
|
|
87
|
+
const divider = this.ownerDocument.createElement('div');
|
|
88
|
+
beforeLayer.className = 'ui-image-comparison__before';
|
|
89
|
+
afterLayer.className = 'ui-image-comparison__after';
|
|
90
|
+
divider.className = 'ui-image-comparison__divider';
|
|
91
|
+
divider.setAttribute('aria-hidden', 'true');
|
|
92
|
+
beforeLayer.append(before);
|
|
93
|
+
afterLayer.append(after);
|
|
94
|
+
this.frame.append(beforeLayer, afterLayer, divider);
|
|
95
|
+
const labels = this.ownerDocument.createElement('div');
|
|
96
|
+
labels.className = 'ui-image-comparison__labels';
|
|
97
|
+
labels.setAttribute('aria-hidden', 'true');
|
|
98
|
+
this.beforeLabel = this.ownerDocument.createElement('span');
|
|
99
|
+
this.afterLabel = this.ownerDocument.createElement('span');
|
|
100
|
+
labels.append(this.beforeLabel, this.afterLabel);
|
|
101
|
+
const control = this.ownerDocument.createElement('label');
|
|
102
|
+
control.className = 'ui-image-comparison__control';
|
|
103
|
+
this.controlLabel = this.ownerDocument.createElement('span');
|
|
104
|
+
this.range = this.ownerDocument.createElement('input');
|
|
105
|
+
this.range.className = 'ui-slider ui-image-comparison__range';
|
|
106
|
+
this.range.type = 'range';
|
|
107
|
+
this.range.min = '0';
|
|
108
|
+
this.range.max = '100';
|
|
109
|
+
this.range.step = '1';
|
|
110
|
+
this.range.defaultValue = String(this.value);
|
|
111
|
+
control.append(this.controlLabel, this.range);
|
|
112
|
+
this.prepend(this.frame, labels, control);
|
|
113
|
+
}
|
|
114
|
+
get afterText() {
|
|
115
|
+
return this.getAttribute('after-label') ?? 'After';
|
|
116
|
+
}
|
|
117
|
+
get locale() {
|
|
118
|
+
return this.getAttribute('locale') || this.closest('[lang]')?.getAttribute('lang') || undefined;
|
|
119
|
+
}
|
|
120
|
+
disabledForMode(mode) {
|
|
121
|
+
return this.hasAttribute('disabled') || mode !== 'reveal';
|
|
122
|
+
}
|
|
123
|
+
update() {
|
|
124
|
+
if (!this.range || !this.frame || !this.beforeLabel || !this.afterLabel || !this.controlLabel)
|
|
125
|
+
return;
|
|
126
|
+
const mode = normalizeLumenImageComparisonMode(this.getAttribute('mode'));
|
|
127
|
+
syncLumenImageComparisonMode(this, mode);
|
|
128
|
+
const afterLabel = this.afterText;
|
|
129
|
+
const locale = this.locale;
|
|
130
|
+
this.beforeLabel.textContent = this.getAttribute('before-label') ?? 'Before';
|
|
131
|
+
this.afterLabel.textContent = afterLabel;
|
|
132
|
+
this.controlLabel.textContent = this.getAttribute('label') ?? 'Compare images';
|
|
133
|
+
this.dataset.fit = this.getAttribute('fit') === 'contain' ? 'contain' : 'cover';
|
|
134
|
+
this.frame.style.setProperty('--ui-image-comparison-ratio', String(normalizeLumenImageComparisonRatio(this.getAttribute('ratio'))));
|
|
135
|
+
this.frame.style.setProperty('--ui-image-comparison-position', `${this.value}%`);
|
|
136
|
+
this.range.value = String(this.value);
|
|
137
|
+
this.range.disabled = this.disabledForMode(mode);
|
|
138
|
+
this.range.name = this.getAttribute('name') ?? '';
|
|
139
|
+
this.range.ariaValueText = formatLumenImageComparisonValue(this.value, afterLabel, locale);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
export const defineLumenImageComparison = (registry) => {
|
|
143
|
+
defineLumenElement(lumenImageComparisonElementConfig, LumenImageComparisonElement, registry);
|
|
144
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type LumenCustomElementRegistry, LumenElement } from '../element-base.js';
|
|
2
|
+
export declare const lumenMediaThumbnailElementConfig: {
|
|
3
|
+
readonly baseClassName: "ui-media-thumbnail";
|
|
4
|
+
readonly observedAttributes: readonly ["label", "media-id", "selected", "order", "state", "state-label", "disabled"];
|
|
5
|
+
readonly tagName: "lumen-media-thumbnail";
|
|
6
|
+
};
|
|
7
|
+
export declare class LumenMediaThumbnailElement extends LumenElement {
|
|
8
|
+
static config: {
|
|
9
|
+
readonly baseClassName: "ui-media-thumbnail";
|
|
10
|
+
readonly observedAttributes: readonly ["label", "media-id", "selected", "order", "state", "state-label", "disabled"];
|
|
11
|
+
readonly tagName: "lumen-media-thumbnail";
|
|
12
|
+
};
|
|
13
|
+
private button;
|
|
14
|
+
private labelNode;
|
|
15
|
+
private orderNode;
|
|
16
|
+
private stateNode;
|
|
17
|
+
connectedCallback(): void;
|
|
18
|
+
attributeChangedCallback(): void;
|
|
19
|
+
private createContent;
|
|
20
|
+
private update;
|
|
21
|
+
}
|
|
22
|
+
export declare const lumenMediaFilmstripElementConfig: {
|
|
23
|
+
readonly baseClassName: "ui-media-filmstrip";
|
|
24
|
+
readonly observedAttributes: readonly ["label", "selection-label"];
|
|
25
|
+
readonly tagName: "lumen-media-filmstrip";
|
|
26
|
+
};
|
|
27
|
+
export declare class LumenMediaFilmstripElement extends LumenElement {
|
|
28
|
+
static config: {
|
|
29
|
+
readonly baseClassName: "ui-media-filmstrip";
|
|
30
|
+
readonly observedAttributes: readonly ["label", "selection-label"];
|
|
31
|
+
readonly tagName: "lumen-media-filmstrip";
|
|
32
|
+
};
|
|
33
|
+
private labelNode;
|
|
34
|
+
private summary;
|
|
35
|
+
connectedCallback(): void;
|
|
36
|
+
attributeChangedCallback(): void;
|
|
37
|
+
private update;
|
|
38
|
+
}
|
|
39
|
+
export declare const defineLumenMediaThumbnail: (registry?: LumenCustomElementRegistry) => void;
|
|
40
|
+
export declare const defineLumenMediaFilmstrip: (registry?: LumenCustomElementRegistry) => void;
|
|
41
|
+
//# sourceMappingURL=media-selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-selection.d.ts","sourceRoot":"","sources":["../../src/components/media-selection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,0BAA0B,EAAE,YAAY,EAA2B,MAAM,oBAAoB,CAAA;AAE/H,eAAO,MAAM,gCAAgC;;;;CAIN,CAAA;AAEvC,qBAAa,0BAA2B,SAAQ,YAAY;IAC1D,OAAgB,MAAM;;;;MAAmC;IACzD,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,SAAS,CAA6B;IAErC,iBAAiB,IAAI,IAAI;IAQzB,wBAAwB,IAAI,IAAI;IAMzC,OAAO,CAAC,aAAa;IAgDrB,OAAO,CAAC,MAAM;CAyBf;AAED,eAAO,MAAM,gCAAgC;;;;CAIN,CAAA;AAEvC,qBAAa,0BAA2B,SAAQ,YAAY;IAC1D,OAAgB,MAAM;;;;MAAmC;IACzD,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,OAAO,CAA6B;IAEnC,iBAAiB,IAAI,IAAI;IA2BzB,wBAAwB,IAAI,IAAI;IAMzC,OAAO,CAAC,MAAM;CAWf;AAED,eAAO,MAAM,yBAAyB,GAAI,WAAW,0BAA0B,KAAG,IAEjF,CAAA;AAED,eAAO,MAAM,yBAAyB,GAAI,WAAW,0BAA0B,KAAG,IAEjF,CAAA"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { formatLumenMediaThumbnailState, resolveLumenMediaOrder, resolveLumenMediaThumbnailState } from '@santi020k/lumen-core/media-workspace';
|
|
2
|
+
import { defineLumenElement, LumenElement } from '../element-base.js';
|
|
3
|
+
export const lumenMediaThumbnailElementConfig = {
|
|
4
|
+
baseClassName: 'ui-media-thumbnail',
|
|
5
|
+
observedAttributes: ['label', 'media-id', 'selected', 'order', 'state', 'state-label', 'disabled'],
|
|
6
|
+
tagName: 'lumen-media-thumbnail'
|
|
7
|
+
};
|
|
8
|
+
export class LumenMediaThumbnailElement extends LumenElement {
|
|
9
|
+
static config = lumenMediaThumbnailElementConfig;
|
|
10
|
+
button;
|
|
11
|
+
labelNode;
|
|
12
|
+
orderNode;
|
|
13
|
+
stateNode;
|
|
14
|
+
connectedCallback() {
|
|
15
|
+
super.connectedCallback();
|
|
16
|
+
if (!this.button)
|
|
17
|
+
this.createContent();
|
|
18
|
+
this.update();
|
|
19
|
+
}
|
|
20
|
+
attributeChangedCallback() {
|
|
21
|
+
super.attributeChangedCallback();
|
|
22
|
+
this.update();
|
|
23
|
+
}
|
|
24
|
+
createContent() {
|
|
25
|
+
const button = this.ownerDocument.createElement('button');
|
|
26
|
+
const media = this.ownerDocument.createElement('span');
|
|
27
|
+
const content = this.ownerDocument.createElement('span');
|
|
28
|
+
button.className = 'ui-button ui-button--outline ui-media-thumbnail';
|
|
29
|
+
button.type = 'button';
|
|
30
|
+
content.className = 'ui-button__content';
|
|
31
|
+
media.className = 'ui-media-thumbnail__media';
|
|
32
|
+
media.setAttribute('aria-hidden', 'true');
|
|
33
|
+
media.append(...this.childNodes);
|
|
34
|
+
this.labelNode = this.ownerDocument.createElement('span');
|
|
35
|
+
this.labelNode.className = 'ui-media-thumbnail__label';
|
|
36
|
+
this.orderNode = this.ownerDocument.createElement('span');
|
|
37
|
+
this.orderNode.className = 'ui-media-thumbnail__order';
|
|
38
|
+
this.stateNode = this.ownerDocument.createElement('span');
|
|
39
|
+
this.stateNode.className = 'ui-media-thumbnail__state';
|
|
40
|
+
content.append(media, this.labelNode, this.orderNode, this.stateNode);
|
|
41
|
+
button.append(content);
|
|
42
|
+
button.addEventListener('click', () => {
|
|
43
|
+
const id = this.getAttribute('media-id');
|
|
44
|
+
if (button.disabled || !id)
|
|
45
|
+
return;
|
|
46
|
+
this.dispatchEvent(new CustomEvent('ui:media-selection-request', {
|
|
47
|
+
bubbles: true, detail: { id, selected: !this.hasAttribute('selected') }
|
|
48
|
+
}));
|
|
49
|
+
});
|
|
50
|
+
this.append(button);
|
|
51
|
+
this.button = button;
|
|
52
|
+
}
|
|
53
|
+
update() {
|
|
54
|
+
if (!this.button || !this.labelNode || !this.orderNode || !this.stateNode)
|
|
55
|
+
return;
|
|
56
|
+
const rawState = this.getAttribute('state');
|
|
57
|
+
const state = resolveLumenMediaThumbnailState(rawState);
|
|
58
|
+
const order = resolveLumenMediaOrder(Number(this.getAttribute('order')));
|
|
59
|
+
this.button.dataset.state = state;
|
|
60
|
+
this.button.disabled = this.hasAttribute('disabled') || state !== 'ready';
|
|
61
|
+
this.button.setAttribute('aria-pressed', String(this.hasAttribute('selected')));
|
|
62
|
+
this.button.setAttribute('aria-busy', String(state === 'loading'));
|
|
63
|
+
this.labelNode.textContent = this.getAttribute('label') ?? '';
|
|
64
|
+
this.orderNode.hidden = order === undefined;
|
|
65
|
+
this.orderNode.textContent = this.orderNode.hidden ? '' : String(order);
|
|
66
|
+
this.stateNode.hidden = state === 'ready';
|
|
67
|
+
this.stateNode.textContent = formatLumenMediaThumbnailState(state, this.getAttribute('state-label') ?? undefined);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export const lumenMediaFilmstripElementConfig = {
|
|
71
|
+
baseClassName: 'ui-media-filmstrip',
|
|
72
|
+
observedAttributes: ['label', 'selection-label'],
|
|
73
|
+
tagName: 'lumen-media-filmstrip'
|
|
74
|
+
};
|
|
75
|
+
export class LumenMediaFilmstripElement extends LumenElement {
|
|
76
|
+
static config = lumenMediaFilmstripElementConfig;
|
|
77
|
+
labelNode;
|
|
78
|
+
summary;
|
|
79
|
+
connectedCallback() {
|
|
80
|
+
super.connectedCallback();
|
|
81
|
+
if (!this.summary) {
|
|
82
|
+
const heading = this.ownerDocument.createElement('div');
|
|
83
|
+
const list = this.ownerDocument.createElement('ol');
|
|
84
|
+
heading.className = 'ui-media-filmstrip__heading';
|
|
85
|
+
list.className = 'ui-media-filmstrip__items';
|
|
86
|
+
this.labelNode = this.ownerDocument.createElement('span');
|
|
87
|
+
this.summary = this.ownerDocument.createElement('span');
|
|
88
|
+
this.summary.setAttribute('role', 'status');
|
|
89
|
+
heading.append(this.labelNode, this.summary);
|
|
90
|
+
list.append(...this.childNodes);
|
|
91
|
+
this.append(heading, list);
|
|
92
|
+
}
|
|
93
|
+
this.update();
|
|
94
|
+
}
|
|
95
|
+
attributeChangedCallback() {
|
|
96
|
+
super.attributeChangedCallback();
|
|
97
|
+
this.update();
|
|
98
|
+
}
|
|
99
|
+
update() {
|
|
100
|
+
const label = this.getAttribute('label') ?? 'Media selection';
|
|
101
|
+
this.setAttribute('role', 'region');
|
|
102
|
+
this.setAttribute('aria-label', label);
|
|
103
|
+
if (this.labelNode)
|
|
104
|
+
this.labelNode.textContent = label;
|
|
105
|
+
if (this.summary)
|
|
106
|
+
this.summary.textContent = this.getAttribute('selection-label') ?? '';
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export const defineLumenMediaThumbnail = (registry) => {
|
|
110
|
+
defineLumenElement(lumenMediaThumbnailElementConfig, LumenMediaThumbnailElement, registry);
|
|
111
|
+
};
|
|
112
|
+
export const defineLumenMediaFilmstrip = (registry) => {
|
|
113
|
+
defineLumenElement(lumenMediaFilmstripElementConfig, LumenMediaFilmstripElement, registry);
|
|
114
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type LumenMediaViewportLabels } from '@santi020k/lumen-core/media-viewport';
|
|
2
|
+
import { type LumenMediaViewportValue } from '@santi020k/lumen-core/media-workspace';
|
|
3
|
+
import { type LumenCustomElementRegistry, LumenElement } from '../element-base.js';
|
|
4
|
+
export declare const lumenMediaViewportElementConfig: {
|
|
5
|
+
readonly baseClassName: "ui-media-viewport";
|
|
6
|
+
readonly observedAttributes: readonly ["label", "disabled", "max-zoom", "zoom", "pan-x", "pan-y", "ratio", "locale", "lang"];
|
|
7
|
+
readonly tagName: "lumen-media-viewport";
|
|
8
|
+
};
|
|
9
|
+
export declare class LumenMediaViewportElement extends LumenElement {
|
|
10
|
+
static config: {
|
|
11
|
+
readonly baseClassName: "ui-media-viewport";
|
|
12
|
+
readonly observedAttributes: readonly ["label", "disabled", "max-zoom", "zoom", "pan-x", "pan-y", "ratio", "locale", "lang"];
|
|
13
|
+
readonly tagName: "lumen-media-viewport";
|
|
14
|
+
};
|
|
15
|
+
private cleanup;
|
|
16
|
+
private stage;
|
|
17
|
+
private copy;
|
|
18
|
+
get value(): LumenMediaViewportValue;
|
|
19
|
+
set value(value: LumenMediaViewportValue);
|
|
20
|
+
set labels(value: Partial<LumenMediaViewportLabels>);
|
|
21
|
+
private get maxZoom();
|
|
22
|
+
connectedCallback(): void;
|
|
23
|
+
disconnectedCallback(): void;
|
|
24
|
+
attributeChangedCallback(): void;
|
|
25
|
+
private createContent;
|
|
26
|
+
private get locale();
|
|
27
|
+
private update;
|
|
28
|
+
}
|
|
29
|
+
export declare const defineLumenMediaViewport: (registry?: LumenCustomElementRegistry) => void;
|
|
30
|
+
//# sourceMappingURL=media-viewport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-viewport.d.ts","sourceRoot":"","sources":["../../src/components/media-viewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,wBAAwB,EAG9B,MAAM,sCAAsC,CAAA;AAC7C,OAAO,EAAE,KAAK,uBAAuB,EAA+B,MAAM,uCAAuC,CAAA;AAEjH,OAAO,EAAsB,KAAK,0BAA0B,EAAE,YAAY,EAA2B,MAAM,oBAAoB,CAAA;AAE/H,eAAO,MAAM,+BAA+B;;;;CAIL,CAAA;AAEvC,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,OAAgB,MAAM;;;;MAAkC;IACxD,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,IAAI,CAAqD;IAEjE,IAAI,KAAK,IAAI,uBAAuB,CAEnC;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,uBAAuB,EAQvC;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,wBAAwB,CAAC,EAIlD;IAED,OAAO,KAAK,OAAO,GAElB;IAEQ,iBAAiB,IAAI,IAAI;IAqBzB,oBAAoB,IAAI,IAAI;IAM5B,wBAAwB,IAAI,IAAI;IAMzC,OAAO,CAAC,aAAa;IA0DrB,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,CAAC,MAAM;CAoBf;AAED,eAAO,MAAM,wBAAwB,GAAI,WAAW,0BAA0B,KAAG,IAEhF,CAAA"}
|