@santi020k/lumen-elements 3.0.0 → 4.0.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.
Files changed (66) hide show
  1. package/README.md +497 -5
  2. package/dist/bullet-chart-html.d.ts +5 -0
  3. package/dist/bullet-chart-html.d.ts.map +1 -0
  4. package/dist/bullet-chart-html.js +56 -0
  5. package/dist/chart-activation.d.ts +15 -0
  6. package/dist/chart-activation.d.ts.map +1 -0
  7. package/dist/chart-activation.js +93 -0
  8. package/dist/chart-html.d.ts +22 -0
  9. package/dist/chart-html.d.ts.map +1 -0
  10. package/dist/chart-html.js +1 -0
  11. package/dist/comparison-chart-html.d.ts +4 -0
  12. package/dist/comparison-chart-html.d.ts.map +1 -0
  13. package/dist/comparison-chart-html.js +36 -0
  14. package/dist/components/ai-surfaces.d.ts +115 -0
  15. package/dist/components/ai-surfaces.d.ts.map +1 -0
  16. package/dist/components/ai-surfaces.js +270 -0
  17. package/dist/components/button.d.ts +51 -2
  18. package/dist/components/button.d.ts.map +1 -1
  19. package/dist/components/button.js +81 -2
  20. package/dist/components/card.d.ts +6 -0
  21. package/dist/components/card.d.ts.map +1 -1
  22. package/dist/components/card.js +6 -1
  23. package/dist/components/combobox.d.ts +1 -2
  24. package/dist/components/combobox.d.ts.map +1 -1
  25. package/dist/components/combobox.js +27 -121
  26. package/dist/components/dashboard.d.ts +41 -0
  27. package/dist/components/dashboard.d.ts.map +1 -0
  28. package/dist/components/dashboard.js +88 -0
  29. package/dist/components/device-frame.d.ts +31 -0
  30. package/dist/components/device-frame.d.ts.map +1 -0
  31. package/dist/components/device-frame.js +95 -0
  32. package/dist/components/foundations.d.ts +30 -2
  33. package/dist/components/foundations.d.ts.map +1 -1
  34. package/dist/components/foundations.js +27 -2
  35. package/dist/components/image-comparison.d.ts +33 -0
  36. package/dist/components/image-comparison.d.ts.map +1 -0
  37. package/dist/components/image-comparison.js +144 -0
  38. package/dist/components/media-selection.d.ts +41 -0
  39. package/dist/components/media-selection.d.ts.map +1 -0
  40. package/dist/components/media-selection.js +114 -0
  41. package/dist/components/media-viewport.d.ts +30 -0
  42. package/dist/components/media-viewport.d.ts.map +1 -0
  43. package/dist/components/media-viewport.js +108 -0
  44. package/dist/components/virtual-list.d.ts +38 -0
  45. package/dist/components/virtual-list.d.ts.map +1 -0
  46. package/dist/components/virtual-list.js +30 -0
  47. package/dist/components/visual-interactions.d.ts +65 -0
  48. package/dist/components/visual-interactions.d.ts.map +1 -0
  49. package/dist/components/visual-interactions.js +91 -0
  50. package/dist/components/world-map.d.ts +46 -0
  51. package/dist/components/world-map.d.ts.map +1 -0
  52. package/dist/components/world-map.js +312 -0
  53. package/dist/consumer-behaviors.d.ts +36 -0
  54. package/dist/consumer-behaviors.d.ts.map +1 -0
  55. package/dist/consumer-behaviors.js +1 -0
  56. package/dist/define.d.ts +229 -6
  57. package/dist/define.d.ts.map +1 -1
  58. package/dist/define.js +1 -1
  59. package/dist/element-base.js +1 -1
  60. package/dist/expanded-chart-html.d.ts +9 -0
  61. package/dist/expanded-chart-html.d.ts.map +1 -0
  62. package/dist/expanded-chart-html.js +61 -0
  63. package/dist/index.d.ts +2 -1
  64. package/dist/index.d.ts.map +1 -1
  65. package/package.json +34 -6
  66. package/styles/critical.css +634 -61
@@ -1,4 +1,4 @@
1
- import { type LumenCustomElementRegistry } from '../element-base.js';
1
+ import { type LumenCustomElementRegistry, LumenElement } from '../element-base.js';
2
2
  export declare const lumenButtonElementConfig: {
3
3
  readonly attributeClasses: {
4
4
  readonly variant: {
@@ -33,6 +33,55 @@ export declare const lumenButtonElementConfig: {
33
33
  readonly role: "button";
34
34
  readonly tagName: "lumen-button";
35
35
  };
36
- export declare const LumenButtonElement: import("../element-base.js").LumenElementConstructor;
36
+ export declare class LumenButtonElement extends LumenElement {
37
+ static config: {
38
+ readonly attributeClasses: {
39
+ readonly variant: {
40
+ readonly default: "ui-button--default";
41
+ readonly destructive: "ui-button--destructive";
42
+ readonly ghost: "ui-button--ghost";
43
+ readonly link: "ui-button--link";
44
+ readonly outline: "ui-button--outline";
45
+ readonly secondary: "ui-button--secondary";
46
+ };
47
+ readonly size: {
48
+ readonly default: "ui-button--default-size";
49
+ readonly icon: "ui-button--icon";
50
+ readonly lg: "ui-button--lg";
51
+ readonly sm: "ui-button--sm";
52
+ };
53
+ readonly disabled: {
54
+ readonly true: "ui-button--disabled";
55
+ };
56
+ readonly loading: {
57
+ readonly true: "ui-button--loading";
58
+ };
59
+ };
60
+ readonly baseClassName: "ui-button";
61
+ readonly defaults: {
62
+ readonly 'data-slot': "button";
63
+ readonly role: "button";
64
+ readonly size: "default";
65
+ readonly tabindex: "0";
66
+ readonly variant: "default";
67
+ };
68
+ readonly role: "button";
69
+ readonly tagName: "lumen-button";
70
+ };
71
+ private spacePressed;
72
+ private managedDisabled;
73
+ private originalAriaDisabled;
74
+ private hasBlockingAttribute;
75
+ private syncDisabledSemantics;
76
+ private isBlocked;
77
+ private activateAfterDispatch;
78
+ private onKeyDown;
79
+ private onKeyUp;
80
+ private onBlur;
81
+ private onClick;
82
+ connectedCallback(): void;
83
+ attributeChangedCallback(name?: string, previousValue?: string | null, value?: string | null): void;
84
+ disconnectedCallback(): void;
85
+ }
37
86
  export declare const defineLumenButton: (registry?: LumenCustomElementRegistry) => void;
38
87
  //# sourceMappingURL=button.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/components/button.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAEhC,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BE,CAAA;AAEvC,eAAO,MAAM,kBAAkB,sDAE9B,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,0BAA0B,KACpC,IAEF,CAAA"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/components/button.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,YAAY,EAEb,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BE,CAAA;AAEvC,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,OAAgB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAA2B;IACjD,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,oBAAoB,CAAsB;IAElD,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,SAAS,CAUhB;IAED,OAAO,CAAC,OAAO,CAQd;IAED,OAAO,CAAC,MAAM,CAEb;IAED,OAAO,CAAC,OAAO,CAMd;IAEQ,iBAAiB,IAAI,IAAI;IAczB,wBAAwB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAMnG,oBAAoB,IAAI,IAAI;CAatC;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,0BAA0B,KACpC,IAEF,CAAA"}
@@ -1,4 +1,4 @@
1
- import { createLumenElementClass, defineLumenElement } from '../element-base.js';
1
+ import { defineLumenElement, LumenElement } from '../element-base.js';
2
2
  export const lumenButtonElementConfig = {
3
3
  attributeClasses: {
4
4
  variant: {
@@ -29,7 +29,86 @@ export const lumenButtonElementConfig = {
29
29
  role: 'button',
30
30
  tagName: 'lumen-button'
31
31
  };
32
- export const LumenButtonElement = createLumenElementClass(lumenButtonElementConfig);
32
+ export class LumenButtonElement extends LumenElement {
33
+ static config = lumenButtonElementConfig;
34
+ spacePressed = false;
35
+ managedDisabled = false;
36
+ originalAriaDisabled = null;
37
+ hasBlockingAttribute() {
38
+ return ['disabled', 'loading'].some(name => this.hasAttribute(name) && this.getAttribute(name) !== 'false');
39
+ }
40
+ syncDisabledSemantics() {
41
+ if (this.hasBlockingAttribute()) {
42
+ if (!this.managedDisabled)
43
+ this.originalAriaDisabled = this.getAttribute('aria-disabled');
44
+ this.managedDisabled = true;
45
+ this.setAttribute('aria-disabled', 'true');
46
+ }
47
+ else if (this.managedDisabled) {
48
+ this.managedDisabled = false;
49
+ if (this.originalAriaDisabled === null)
50
+ this.removeAttribute('aria-disabled');
51
+ else
52
+ this.setAttribute('aria-disabled', this.originalAriaDisabled);
53
+ }
54
+ }
55
+ isBlocked() {
56
+ return this.hasBlockingAttribute() || this.getAttribute('aria-disabled') === 'true';
57
+ }
58
+ activateAfterDispatch(event) {
59
+ setTimeout(() => {
60
+ if (this.isConnected && !event.defaultPrevented && !this.isBlocked())
61
+ this.click();
62
+ }, 0);
63
+ }
64
+ onKeyDown = (event) => {
65
+ if (event.target !== this || event.defaultPrevented || event.repeat || event.isComposing || this.isBlocked())
66
+ return;
67
+ if (event.key === 'Enter')
68
+ this.activateAfterDispatch(event);
69
+ if (event.key === ' ') {
70
+ event.preventDefault();
71
+ this.spacePressed = true;
72
+ }
73
+ };
74
+ onKeyUp = (event) => {
75
+ if (event.key !== ' ')
76
+ return;
77
+ const spacePressed = this.spacePressed;
78
+ this.spacePressed = false;
79
+ if (event.target === this && spacePressed && !event.isComposing)
80
+ this.activateAfterDispatch(event);
81
+ };
82
+ onBlur = () => {
83
+ this.spacePressed = false;
84
+ };
85
+ onClick = (event) => {
86
+ if (!this.isBlocked())
87
+ return;
88
+ event.preventDefault();
89
+ event.stopImmediatePropagation();
90
+ };
91
+ connectedCallback() {
92
+ super.connectedCallback();
93
+ this.syncDisabledSemantics();
94
+ this.addEventListener('keydown', this.onKeyDown);
95
+ this.addEventListener('keyup', this.onKeyUp);
96
+ this.addEventListener('blur', this.onBlur);
97
+ this.addEventListener('click', this.onClick, true);
98
+ }
99
+ attributeChangedCallback(name, previousValue, value) {
100
+ super.attributeChangedCallback(name, previousValue, value);
101
+ this.syncDisabledSemantics();
102
+ }
103
+ disconnectedCallback() {
104
+ this.spacePressed = false;
105
+ this.removeEventListener('keydown', this.onKeyDown);
106
+ this.removeEventListener('keyup', this.onKeyUp);
107
+ this.removeEventListener('blur', this.onBlur);
108
+ this.removeEventListener('click', this.onClick, true);
109
+ super.disconnectedCallback();
110
+ }
111
+ }
33
112
  export const defineLumenButton = (registry) => {
34
113
  defineLumenElement(lumenButtonElementConfig, LumenButtonElement, registry);
35
114
  };
@@ -1,6 +1,11 @@
1
1
  import { type LumenCustomElementRegistry } from '../element-base.js';
2
2
  export declare const lumenCardElementConfig: {
3
3
  readonly attributeClasses: {
4
+ readonly density: {
5
+ readonly comfortable: "ui-card--comfortable";
6
+ readonly compact: "ui-card--compact";
7
+ readonly spacious: "ui-card--spacious";
8
+ };
4
9
  readonly glass: {
5
10
  readonly strong: "ui-card--glass ui-glass-strong";
6
11
  readonly subtle: "ui-card--glass ui-glass-subtle";
@@ -16,6 +21,7 @@ export declare const lumenCardElementConfig: {
16
21
  readonly baseClassName: "ui-card";
17
22
  readonly defaults: {
18
23
  readonly 'data-slot': "card";
24
+ readonly density: "comfortable";
19
25
  readonly variant: "default";
20
26
  };
21
27
  readonly tagName: "lumen-card";
@@ -1 +1 @@
1
- {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/components/card.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAEhC,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;CAiBI,CAAA;AAEvC,eAAO,MAAM,gBAAgB,sDAE5B,CAAA;AAED,eAAO,MAAM,eAAe,GAC1B,WAAW,0BAA0B,KACpC,IAEF,CAAA"}
1
+ {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/components/card.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAEhC,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;CAsBI,CAAA;AAEvC,eAAO,MAAM,gBAAgB,sDAE5B,CAAA;AAED,eAAO,MAAM,eAAe,GAC1B,WAAW,0BAA0B,KACpC,IAEF,CAAA"}
@@ -1,6 +1,11 @@
1
1
  import { createLumenElementClass, defineLumenElement } from '../element-base.js';
2
2
  export const lumenCardElementConfig = {
3
3
  attributeClasses: {
4
+ density: {
5
+ comfortable: 'ui-card--comfortable',
6
+ compact: 'ui-card--compact',
7
+ spacious: 'ui-card--spacious'
8
+ },
4
9
  glass: {
5
10
  strong: 'ui-card--glass ui-glass-strong',
6
11
  subtle: 'ui-card--glass ui-glass-subtle',
@@ -14,7 +19,7 @@ export const lumenCardElementConfig = {
14
19
  }
15
20
  },
16
21
  baseClassName: 'ui-card',
17
- defaults: { 'data-slot': 'card', variant: 'default' },
22
+ defaults: { 'data-slot': 'card', density: 'comfortable', variant: 'default' },
18
23
  tagName: 'lumen-card'
19
24
  };
20
25
  export const LumenCardElement = createLumenElementClass(lumenCardElementConfig);
@@ -7,6 +7,7 @@ export declare const lumenComboboxElementConfig: {
7
7
  readonly tagName: "lumen-combobox";
8
8
  };
9
9
  export declare class LumenComboboxElement extends LumenElement {
10
+ #private;
10
11
  static config: {
11
12
  readonly baseClassName: "ui-combobox";
12
13
  readonly defaults: {
@@ -14,10 +15,8 @@ export declare class LumenComboboxElement extends LumenElement {
14
15
  };
15
16
  readonly tagName: "lumen-combobox";
16
17
  };
17
- private abortController;
18
18
  connectedCallback(): void;
19
19
  disconnectedCallback(): void;
20
- private setupCombobox;
21
20
  }
22
21
  export declare const defineLumenCombobox: (registry?: LumenCustomElementRegistry) => void;
23
22
  //# sourceMappingURL=combobox.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/components/combobox.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,YAAY,EAEb,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,0BAA0B;;;;;;CAIA,CAAA;AAyBvC,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,OAAgB,MAAM;;;;;;MAA6B;IAEnD,OAAO,CAAC,eAAe,CAA6B;IAE3C,iBAAiB;IAYjB,oBAAoB;IAM7B,OAAO,CAAC,aAAa;CAmJtB;AAED,eAAO,MAAM,mBAAmB,GAC9B,WAAW,0BAA0B,KACpC,IAIF,CAAA"}
1
+ {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/components/combobox.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,YAAY,EAEb,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,0BAA0B;;;;;;CAIA,CAAA;AAEvC,qBAAa,oBAAqB,SAAQ,YAAY;;IACpD,OAAgB,MAAM;;;;;;MAA6B;IAsB1C,iBAAiB;IAcjB,oBAAoB;CAa9B;AAED,eAAO,MAAM,mBAAmB,GAC9B,WAAW,0BAA0B,KACpC,IAIF,CAAA"}
@@ -1,136 +1,42 @@
1
+ import { createLumenComboboxController } from '@santi020k/lumen-core';
1
2
  import { defineLumenElement, LumenElement } from '../element-base.js';
2
3
  export const lumenComboboxElementConfig = {
3
4
  baseClassName: 'ui-combobox',
4
5
  defaults: { 'data-ui-combobox': '' },
5
6
  tagName: 'lumen-combobox'
6
7
  };
7
- let comboboxId = 0;
8
- const createComboboxId = () => `ui-combobox-list-${++comboboxId}`;
9
- const getEventTarget = (event) => {
10
- const target = event.composedPath()[0] ?? event.target;
11
- return target instanceof Node ? target : null;
12
- };
13
- const getLoopedIndex = (key, currentIndex, itemCount) => {
14
- if (key === 'Home')
15
- return 0;
16
- if (key === 'End')
17
- return itemCount - 1;
18
- if (key === 'ArrowDown')
19
- return (currentIndex + 1) % itemCount;
20
- return (currentIndex - 1 + itemCount) % itemCount;
21
- };
22
8
  export class LumenComboboxElement extends LumenElement {
23
9
  static config = lumenComboboxElementConfig;
24
- abortController;
10
+ #controller;
11
+ #observer;
12
+ #input = null;
13
+ #list = null;
14
+ #bind() {
15
+ const input = this.querySelector('input[role="combobox"]');
16
+ const list = this.querySelector('[role="listbox"]');
17
+ if (input === this.#input && list === this.#list)
18
+ return;
19
+ this.#controller?.destroy();
20
+ this.#input = input;
21
+ this.#list = list;
22
+ this.#controller = input && list ? createLumenComboboxController(this) : undefined;
23
+ }
25
24
  connectedCallback() {
26
25
  super.connectedCallback();
27
- if (typeof document === 'undefined')
28
- return;
29
- this.abortController?.abort();
30
- this.abortController = new AbortController();
31
- this.setupCombobox(this.abortController.signal);
26
+ this.#observer?.disconnect();
27
+ this.#bind();
28
+ this.#observer = new MutationObserver(() => {
29
+ this.#bind();
30
+ });
31
+ this.#observer.observe(this, { childList: true, subtree: true });
32
32
  }
33
33
  disconnectedCallback() {
34
- this.abortController?.abort();
35
- this.abortController = undefined;
36
- }
37
- setupCombobox(signal) {
38
- const input = this.querySelector('input[role="combobox"]');
39
- const listbox = this.querySelector('[role="listbox"]');
40
- if (!input || !listbox)
41
- return;
42
- const items = [...listbox.querySelectorAll('[role="option"]')];
43
- if (!listbox.id)
44
- listbox.id = createComboboxId();
45
- input.setAttribute('aria-autocomplete', input.getAttribute('aria-autocomplete') ?? 'list');
46
- input.setAttribute('aria-controls', listbox.id);
47
- const getVisibleItems = () => items.filter(item => (!item.hidden && !item.hasAttribute('disabled') &&
48
- item.getAttribute('aria-disabled') !== 'true'));
49
- const close = () => {
50
- input.setAttribute('aria-expanded', 'false');
51
- listbox.hidden = true;
52
- listbox.dataset.state = 'closed';
53
- };
54
- const open = () => {
55
- input.setAttribute('aria-expanded', 'true');
56
- listbox.hidden = false;
57
- listbox.dataset.state = 'open';
58
- };
59
- const filter = () => {
60
- const query = input.value.trim().toLowerCase();
61
- for (const item of items) {
62
- const value = item.getAttribute('data-value') ?? item.textContent.trim();
63
- item.hidden = Boolean(query) && !value.toLowerCase().includes(query);
64
- }
65
- };
66
- const select = (item) => {
67
- input.value = item.getAttribute('data-value') ?? item.textContent.trim();
68
- input.dispatchEvent(new Event('input', { bubbles: true }));
69
- input.dispatchEvent(new Event('change', { bubbles: true }));
70
- input.focus({ preventScroll: true });
71
- close();
72
- };
73
- const focusItem = (item, key) => {
74
- const visibleItems = getVisibleItems();
75
- if (!visibleItems.length)
76
- return;
77
- const currentIndex = Math.max(0, visibleItems.indexOf(item));
78
- visibleItems[getLoopedIndex(key, currentIndex, visibleItems.length)]?.focus();
79
- };
80
- close();
81
- input.addEventListener('focus', open, { signal });
82
- input.addEventListener('input', () => {
83
- filter();
84
- open();
85
- }, { signal });
86
- input.addEventListener('keydown', event => {
87
- if (event.key === 'Escape') {
88
- close();
89
- return;
90
- }
91
- if (!['ArrowDown', 'ArrowUp', 'Enter'].includes(event.key))
92
- return;
93
- const visibleItems = getVisibleItems();
94
- if (!visibleItems.length)
95
- return;
96
- event.preventDefault();
97
- open();
98
- if (event.key === 'Enter') {
99
- const firstVisibleItem = visibleItems.at(0);
100
- if (firstVisibleItem)
101
- select(firstVisibleItem);
102
- return;
103
- }
104
- const targetIndex = event.key === 'ArrowUp' ? visibleItems.length - 1 : 0;
105
- visibleItems[targetIndex]?.focus();
106
- }, { signal });
107
- for (const item of items) {
108
- item.tabIndex = -1;
109
- item.addEventListener('click', () => {
110
- select(item);
111
- }, { signal });
112
- item.addEventListener('keydown', event => {
113
- if (event.key === 'Escape') {
114
- close();
115
- input.focus({ preventScroll: true });
116
- return;
117
- }
118
- if (event.key === 'Enter' || event.key === ' ') {
119
- event.preventDefault();
120
- select(item);
121
- return;
122
- }
123
- if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key))
124
- return;
125
- event.preventDefault();
126
- focusItem(item, event.key);
127
- }, { signal });
128
- }
129
- document.addEventListener('pointerdown', event => {
130
- const target = getEventTarget(event);
131
- if (target && !this.contains(target))
132
- close();
133
- }, { signal });
34
+ this.#observer?.disconnect();
35
+ this.#observer = undefined;
36
+ this.#controller?.destroy();
37
+ this.#controller = undefined;
38
+ this.#input = null;
39
+ this.#list = null;
134
40
  }
135
41
  }
136
42
  export const defineLumenCombobox = (registry) => {
@@ -0,0 +1,41 @@
1
+ import { type LumenChangeSummaryItem } from '@santi020k/lumen-core';
2
+ import { type LumenCustomElementRegistry, LumenElement } from '../element-base.js';
3
+ export declare const lumenChangeSummaryElementConfig: {
4
+ readonly baseClassName: "ui-change-summary";
5
+ readonly observedAttributes: readonly ["label", "summary", "before-label", "after-label", "changed-label", "unchanged-label"];
6
+ readonly role: "region";
7
+ readonly tagName: "lumen-change-summary";
8
+ };
9
+ export declare class LumenChangeSummaryElement extends LumenElement {
10
+ static config: {
11
+ readonly baseClassName: "ui-change-summary";
12
+ readonly observedAttributes: readonly ["label", "summary", "before-label", "after-label", "changed-label", "unchanged-label"];
13
+ readonly role: "region";
14
+ readonly tagName: "lumen-change-summary";
15
+ };
16
+ private records;
17
+ private content;
18
+ get items(): readonly LumenChangeSummaryItem[];
19
+ set items(value: readonly LumenChangeSummaryItem[]);
20
+ connectedCallback(): void;
21
+ attributeChangedCallback(): void;
22
+ private renderRecord;
23
+ private render;
24
+ }
25
+ export declare const lumenFilterBarElementConfig: {
26
+ readonly baseClassName: "ui-filter-bar";
27
+ readonly observedAttributes: readonly [];
28
+ readonly role: "region";
29
+ readonly tagName: "lumen-filter-bar";
30
+ };
31
+ export declare class LumenFilterBarElement extends LumenElement {
32
+ static config: {
33
+ readonly baseClassName: "ui-filter-bar";
34
+ readonly observedAttributes: readonly [];
35
+ readonly role: "region";
36
+ readonly tagName: "lumen-filter-bar";
37
+ };
38
+ }
39
+ export declare const defineLumenChangeSummary: (registry?: LumenCustomElementRegistry) => void;
40
+ export declare const defineLumenFilterBar: (registry?: LumenCustomElementRegistry) => void;
41
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/components/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,sBAAsB,EAA+B,MAAM,uBAAuB,CAAA;AAEhG,OAAO,EAAsB,KAAK,0BAA0B,EAAE,YAAY,EAA2B,MAAM,oBAAoB,CAAA;AAE/H,eAAO,MAAM,+BAA+B;;;;;CAKL,CAAA;AAYvC,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,OAAgB,MAAM;;;;;MAAkC;IACxD,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,OAAO,CAA4B;IAE3C,IAAI,KAAK,IAAI,SAAS,sBAAsB,EAAE,CAE7C;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,SAAS,sBAAsB,EAAE,EAIjD;IAEQ,iBAAiB,IAAI,IAAI;IAMzB,wBAAwB,IAAI,IAAI;IAMzC,OAAO,CAAC,YAAY;IA0BpB,OAAO,CAAC,MAAM;CA0Bf;AAGD,eAAO,MAAM,2BAA2B;;;;;CAKD,CAAA;AAEvC,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,OAAgB,MAAM;;;;;MAA8B;CACrD;AAED,eAAO,MAAM,wBAAwB,GAAI,WAAW,0BAA0B,KAAG,IAEhF,CAAA;AACD,eAAO,MAAM,oBAAoB,GAAI,WAAW,0BAA0B,KAAG,IAE5E,CAAA"}
@@ -0,0 +1,88 @@
1
+ import { readLumenChangeSummaryItems } from '@santi020k/lumen-core';
2
+ import { defineLumenElement, LumenElement } from '../element-base.js';
3
+ export const lumenChangeSummaryElementConfig = {
4
+ baseClassName: 'ui-change-summary',
5
+ observedAttributes: ['label', 'summary', 'before-label', 'after-label', 'changed-label', 'unchanged-label'],
6
+ role: 'region',
7
+ tagName: 'lumen-change-summary'
8
+ };
9
+ const textNode = (document, tag, text, className) => {
10
+ const node = document.createElement(tag);
11
+ node.textContent = text;
12
+ if (className)
13
+ node.className = className;
14
+ return node;
15
+ };
16
+ export class LumenChangeSummaryElement extends LumenElement {
17
+ static config = lumenChangeSummaryElementConfig;
18
+ records = [];
19
+ content;
20
+ get items() {
21
+ return this.records.map(item => ({ ...item }));
22
+ }
23
+ set items(value) {
24
+ this.records = readLumenChangeSummaryItems(value);
25
+ if (this.isConnected)
26
+ this.render();
27
+ }
28
+ connectedCallback() {
29
+ super.connectedCallback();
30
+ this.render();
31
+ }
32
+ attributeChangedCallback() {
33
+ super.attributeChangedCallback();
34
+ if (this.isConnected)
35
+ this.render();
36
+ }
37
+ renderRecord(item) {
38
+ const document = this.ownerDocument;
39
+ const row = document.createElement('div');
40
+ const term = textNode(document, 'dt', item.label);
41
+ row.className = 'ui-change-summary__item';
42
+ row.dataset.changed = String(item.changed);
43
+ term.append(textNode(document, 'span', this.getAttribute(item.changed ? 'changed-label' : 'unchanged-label') ??
44
+ (item.changed ? 'Changed' : 'Unchanged'), 'ui-change-summary__state'));
45
+ row.append(term);
46
+ for (const [name, value] of [['before', item.before], ['after', item.after]]) {
47
+ const detail = document.createElement('dd');
48
+ detail.append(textNode(document, 'span', this.getAttribute(`${name}-label`) ??
49
+ (name === 'before' ? 'Before' : 'After'), 'ui-change-summary__value-label'), document.createTextNode(value));
50
+ row.append(detail);
51
+ }
52
+ return row;
53
+ }
54
+ render() {
55
+ const document = this.ownerDocument;
56
+ const label = this.getAttribute('label') ?? 'Changes';
57
+ const content = this.content ?? document.createElement('div');
58
+ const list = document.createElement('dl');
59
+ const heading = textNode(document, 'h3', label, 'ui-change-summary__heading');
60
+ const summary = this.getAttribute('summary');
61
+ content.className = 'ui-change-summary';
62
+ this.setAttribute('aria-label', label);
63
+ list.className = 'ui-change-summary__list';
64
+ list.append(...this.records.map(item => this.renderRecord(item)));
65
+ content.replaceChildren(heading);
66
+ if (summary)
67
+ content.append(textNode(document, 'p', summary, 'ui-change-summary__summary'));
68
+ content.append(list);
69
+ if (!this.content)
70
+ this.prepend(content);
71
+ this.content = content;
72
+ }
73
+ }
74
+ export const lumenFilterBarElementConfig = {
75
+ baseClassName: 'ui-filter-bar',
76
+ observedAttributes: [],
77
+ role: 'region',
78
+ tagName: 'lumen-filter-bar'
79
+ };
80
+ export class LumenFilterBarElement extends LumenElement {
81
+ static config = lumenFilterBarElementConfig;
82
+ }
83
+ export const defineLumenChangeSummary = (registry) => {
84
+ defineLumenElement(lumenChangeSummaryElementConfig, LumenChangeSummaryElement, registry);
85
+ };
86
+ export const defineLumenFilterBar = (registry) => {
87
+ defineLumenElement(lumenFilterBarElementConfig, LumenFilterBarElement, registry);
88
+ };
@@ -0,0 +1,31 @@
1
+ import { type LumenCustomElementRegistry, LumenElement } from '../element-base.js';
2
+ export declare const lumenDeviceFrameElementConfig: {
3
+ readonly baseClassName: "ui-device-frame";
4
+ readonly defaults: {
5
+ readonly 'data-device': "laptop";
6
+ readonly 'data-tone': "dark";
7
+ };
8
+ readonly observedAttributes: readonly ["device", "orientation", "tone", "color", "screen-width", "screen-height", "scroll"];
9
+ readonly tagName: "lumen-device-frame";
10
+ };
11
+ export declare class LumenDeviceFrameElement extends LumenElement {
12
+ static config: {
13
+ readonly baseClassName: "ui-device-frame";
14
+ readonly defaults: {
15
+ readonly 'data-device': "laptop";
16
+ readonly 'data-tone': "dark";
17
+ };
18
+ readonly observedAttributes: readonly ["device", "orientation", "tone", "color", "screen-width", "screen-height", "scroll"];
19
+ readonly tagName: "lumen-device-frame";
20
+ };
21
+ private screen;
22
+ private cleanup;
23
+ private colorOverride;
24
+ connectedCallback(): void;
25
+ attributeChangedCallback(): void;
26
+ disconnectedCallback(): void;
27
+ private update;
28
+ private updateColor;
29
+ }
30
+ export declare const defineLumenDeviceFrame: (registry?: LumenCustomElementRegistry) => void;
31
+ //# sourceMappingURL=device-frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-frame.d.ts","sourceRoot":"","sources":["../../src/components/device-frame.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,0BAA0B,EAAE,YAAY,EAA2B,MAAM,oBAAoB,CAAA;AAI/H,eAAO,MAAM,6BAA6B;;;;;;;;CAKH,CAAA;AAEvC,qBAAa,uBAAwB,SAAQ,YAAY;IACvD,OAAgB,MAAM;;;;;;;;MAAgC;IACtD,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,aAAa,CAAiD;IAE7D,iBAAiB,IAAI,IAAI;IAmDzB,wBAAwB,IAAI,IAAI;IAMhC,oBAAoB,IAAI,IAAI;IAMrC,OAAO,CAAC,MAAM;IAiCd,OAAO,CAAC,WAAW;CAgBpB;AAED,eAAO,MAAM,sBAAsB,GAAI,WAAW,0BAA0B,KAAG,IAE9E,CAAA"}
@@ -0,0 +1,95 @@
1
+ import { lumenDeviceFrameSizes, observeLumenDeviceFrame, resolveLumenDeviceFrame, resolveLumenDeviceFrameColor } from '@santi020k/lumen-core';
2
+ import { defineLumenElement, LumenElement } from '../element-base.js';
3
+ const isDevice = (name) => name !== null && Object.hasOwn(lumenDeviceFrameSizes, name);
4
+ export const lumenDeviceFrameElementConfig = {
5
+ baseClassName: 'ui-device-frame',
6
+ defaults: { 'data-device': 'laptop', 'data-tone': 'dark' },
7
+ observedAttributes: ['device', 'orientation', 'tone', 'color', 'screen-width', 'screen-height', 'scroll'],
8
+ tagName: 'lumen-device-frame'
9
+ };
10
+ export class LumenDeviceFrameElement extends LumenElement {
11
+ static config = lumenDeviceFrameElementConfig;
12
+ screen;
13
+ cleanup;
14
+ colorOverride;
15
+ connectedCallback() {
16
+ super.connectedCallback();
17
+ if (!this.screen) {
18
+ const shell = this.ownerDocument.createElement('div');
19
+ const glass = this.ownerDocument.createElement('div');
20
+ const camera = this.ownerDocument.createElement('span');
21
+ const screen = this.ownerDocument.createElement('div');
22
+ const base = this.ownerDocument.createElement('span');
23
+ const hardware = this.ownerDocument.createElement('span');
24
+ hardware.className = 'ui-device-frame__hardware';
25
+ hardware.setAttribute('aria-hidden', 'true');
26
+ for (const part of ['action', 'volume-up', 'volume-down', 'power', 'rail-left', 'rail-right']) {
27
+ const detail = this.ownerDocument.createElement('span');
28
+ detail.className = `ui-device-frame__${part}`;
29
+ hardware.append(detail);
30
+ }
31
+ shell.className = 'ui-device-frame__shell';
32
+ glass.className = 'ui-device-frame__glass';
33
+ camera.className = 'ui-device-frame__camera';
34
+ camera.setAttribute('aria-hidden', 'true');
35
+ screen.className = 'ui-device-frame__screen';
36
+ base.className = 'ui-device-frame__base';
37
+ base.setAttribute('aria-hidden', 'true');
38
+ screen.append(...this.childNodes);
39
+ glass.append(camera, screen);
40
+ shell.append(hardware, glass);
41
+ this.append(shell, base);
42
+ this.screen = screen;
43
+ }
44
+ this.update();
45
+ }
46
+ attributeChangedCallback() {
47
+ super.attributeChangedCallback();
48
+ if (this.isConnected)
49
+ this.update();
50
+ }
51
+ disconnectedCallback() {
52
+ this.cleanup?.();
53
+ this.cleanup = undefined;
54
+ }
55
+ update() {
56
+ const screen = this.screen;
57
+ if (!screen)
58
+ return;
59
+ const rawDevice = this.getAttribute('device');
60
+ const device = isDevice(rawDevice) ? rawDevice : 'laptop';
61
+ const rawOrientation = this.getAttribute('orientation');
62
+ const orientation = rawOrientation === 'portrait' || rawOrientation === 'landscape' ? rawOrientation : undefined;
63
+ const size = resolveLumenDeviceFrame(device, orientation, Number(this.getAttribute('screen-width')), Number(this.getAttribute('screen-height')));
64
+ this.dataset.device = device;
65
+ this.dataset.tone = this.getAttribute('tone') === 'light' ? 'light' : 'dark';
66
+ if (orientation)
67
+ this.dataset.orientation = orientation;
68
+ else
69
+ delete this.dataset.orientation;
70
+ this.updateColor();
71
+ screen.dataset.scroll = String(this.getAttribute('scroll') !== 'false');
72
+ screen.style.aspectRatio = `${size.width} / ${size.height}`;
73
+ screen.style.setProperty('--ui-device-frame-width', `${size.width}px`);
74
+ screen.style.setProperty('--ui-device-frame-height', `${size.height}px`);
75
+ this.cleanup?.();
76
+ this.cleanup = observeLumenDeviceFrame(screen, size.width);
77
+ }
78
+ updateColor() {
79
+ const color = resolveLumenDeviceFrameColor(this.getAttribute('color'));
80
+ if (color) {
81
+ this.colorOverride ??= {
82
+ value: this.style.getPropertyValue('--ui-device-color'),
83
+ priority: this.style.getPropertyPriority('--ui-device-color')
84
+ };
85
+ this.style.setProperty('--ui-device-color', color);
86
+ }
87
+ else if (this.colorOverride) {
88
+ this.style.setProperty('--ui-device-color', this.colorOverride.value, this.colorOverride.priority);
89
+ this.colorOverride = undefined;
90
+ }
91
+ }
92
+ }
93
+ export const defineLumenDeviceFrame = (registry) => {
94
+ defineLumenElement(lumenDeviceFrameElementConfig, LumenDeviceFrameElement, registry);
95
+ };