@jungherz-de/glasskit-elements 1.14.0 → 1.15.1

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 (44) hide show
  1. package/README.md +12 -6
  2. package/dist/components/base.js +1 -21
  3. package/dist/components/glk-accordion-item.js +1 -0
  4. package/dist/components/glk-accordion.js +1 -0
  5. package/dist/components/glk-avatar.js +1 -0
  6. package/dist/components/glk-badge.js +1 -0
  7. package/dist/components/glk-button.js +1 -0
  8. package/dist/components/glk-card.js +1 -0
  9. package/dist/components/glk-checkbox.js +1 -0
  10. package/dist/components/glk-divider.js +1 -0
  11. package/dist/components/glk-empty.js +53 -0
  12. package/dist/components/glk-input.js +1 -0
  13. package/dist/components/glk-list-item.js +1 -0
  14. package/dist/components/glk-list.js +1 -0
  15. package/dist/components/glk-modal.js +1 -0
  16. package/dist/components/glk-nav.js +1 -0
  17. package/dist/components/glk-pill.js +1 -0
  18. package/dist/components/glk-popover.js +1 -0
  19. package/dist/components/glk-progress.js +1 -0
  20. package/dist/components/glk-radio.js +1 -0
  21. package/dist/components/glk-range.js +1 -0
  22. package/dist/components/glk-search.js +1 -0
  23. package/dist/components/glk-segmented.js +124 -0
  24. package/dist/components/glk-select.js +1 -0
  25. package/dist/components/glk-sheet.js +141 -0
  26. package/dist/components/glk-status.js +1 -0
  27. package/dist/components/glk-steps.js +75 -0
  28. package/dist/components/glk-tab-accessory.js +1 -0
  29. package/dist/components/glk-tab-bar.js +1 -0
  30. package/dist/components/glk-tab-dock.js +1 -0
  31. package/dist/components/glk-tab-item.js +1 -0
  32. package/dist/components/glk-textarea.js +1 -0
  33. package/dist/components/glk-title.js +1 -0
  34. package/dist/components/glk-toast.js +1 -0
  35. package/dist/components/glk-toggle.js +1 -0
  36. package/dist/glasskit-elements.esm.js +380 -3
  37. package/dist/glasskit-elements.js +383 -2
  38. package/dist/glasskit-elements.min.js +1 -1
  39. package/package.json +3 -3
  40. package/src/components/content/glk-empty.js +51 -0
  41. package/src/components/feedback/glk-sheet.js +139 -0
  42. package/src/components/forms/glk-segmented.js +122 -0
  43. package/src/components/navigation/glk-steps.js +73 -0
  44. package/src/index.js +4 -0
@@ -0,0 +1,141 @@
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
3
+
4
+ // Bottom sheet — the mobile sibling of <glk-modal>. Came back from
5
+ // EhrenPfoten in 1.15.0.
6
+ //
7
+ // Attributes: open, inline (no overlay, always visible), title
8
+ // Properties: open, inline · Methods: show(), close()
9
+ // Slots: default (content), actions
10
+ // Event: glk-close — only when the user closes it (scrim click, Escape),
11
+ // like <glk-modal>
12
+ // Parts: overlay, sheet, title, body, actions
13
+ //
14
+ // Opening and closing are animated by the CSS block: the overlay gets
15
+ // .is-active one frame after it is unhidden, and on closing it is hidden
16
+ // only after transitionend (safety net 400 ms), so the blurred overlay
17
+ // leaves the layout instead of idling at opacity 0. Under
18
+ // prefers-reduced-motion it switches at once.
19
+
20
+ const HIDE_FALLBACK_MS = 400;
21
+
22
+ function reducedMotion() {
23
+ return typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;
24
+ }
25
+
26
+ class GlkSheet extends GlkElement {
27
+ static get observedAttributes() { return ['open', 'inline', 'title']; }
28
+
29
+ render() {
30
+ this._overlay = this.createElement('div', [], { part: 'overlay' });
31
+ this._panel = this.createElement('div', ['glass-sheet'], { role: 'dialog', part: 'sheet' });
32
+ this._panel.appendChild(this.createElement('div', ['glass-sheet__grip'], { 'aria-hidden': 'true' }));
33
+ this._titleEl = this.createElement('h2', ['glass-sheet__title'], { part: 'title' });
34
+ const body = this.createElement('div', ['glass-sheet__body'], { part: 'body' });
35
+ body.appendChild(document.createElement('slot'));
36
+ const actions = this.createElement('div', ['glass-sheet__actions'], { part: 'actions' });
37
+ actions.appendChild(this.createElement('slot', [], { name: 'actions' }));
38
+ this._panel.append(this._titleEl, body, actions);
39
+ this._overlay.appendChild(this._panel);
40
+ this._wrapper.appendChild(this._overlay);
41
+ this._applyTitle();
42
+ this._applyMode();
43
+ }
44
+
45
+ _applyTitle() {
46
+ const title = this.getAttribute('title') || '';
47
+ this._titleEl.textContent = title;
48
+ this._titleEl.hidden = !title;
49
+ if (title) this._panel.setAttribute('aria-label', title);
50
+ else this._panel.removeAttribute('aria-label');
51
+ }
52
+
53
+ _applyMode() {
54
+ const inline = this.inline;
55
+ this._overlay.classList.toggle('glass-sheet-overlay', !inline);
56
+ this._panel.classList.toggle('glass-sheet--inline', inline);
57
+ this._panel.setAttribute('aria-modal', String(!inline));
58
+ clearTimeout(this._hideTimer);
59
+ if (inline) {
60
+ this._overlay.classList.remove('is-active');
61
+ this._overlay.hidden = false;
62
+ } else if (this.open) {
63
+ this._show();
64
+ } else {
65
+ this._overlay.classList.remove('is-active');
66
+ this._overlay.hidden = true;
67
+ }
68
+ }
69
+
70
+ _show() {
71
+ clearTimeout(this._hideTimer);
72
+ this._panel.removeEventListener('transitionend', this._onHidden);
73
+ this._overlay.hidden = false;
74
+ void this._overlay.offsetHeight; // reflow, so the transition starts from the hidden state
75
+ requestAnimationFrame(() => {
76
+ if (this.open && !this.inline) this._overlay.classList.add('is-active');
77
+ });
78
+ }
79
+
80
+ _hide() {
81
+ this._overlay.classList.remove('is-active');
82
+ this._onHidden = () => {
83
+ clearTimeout(this._hideTimer);
84
+ this._panel.removeEventListener('transitionend', this._onHidden);
85
+ if (!this.open && !this.inline) this._overlay.hidden = true;
86
+ };
87
+ if (reducedMotion()) {
88
+ this._onHidden();
89
+ return;
90
+ }
91
+ this._panel.addEventListener('transitionend', this._onHidden);
92
+ this._hideTimer = setTimeout(this._onHidden, HIDE_FALLBACK_MS);
93
+ }
94
+
95
+ _dismiss() {
96
+ this.removeAttribute('open');
97
+ this.emit('glk-close');
98
+ }
99
+
100
+ setupEvents() {
101
+ this._onOverlayClick = (event) => {
102
+ if (!this.inline && event.target === this._overlay) this._dismiss();
103
+ };
104
+ this._onKeydown = (event) => {
105
+ if (event.key === 'Escape' && this.open && !this.inline) this._dismiss();
106
+ };
107
+ this._overlay.addEventListener('click', this._onOverlayClick);
108
+ document.addEventListener('keydown', this._onKeydown);
109
+ }
110
+
111
+ teardownEvents() {
112
+ this._overlay?.removeEventListener('click', this._onOverlayClick);
113
+ document.removeEventListener('keydown', this._onKeydown);
114
+ }
115
+
116
+ onAttributeChanged(name) {
117
+ if (!this._overlay) return;
118
+ switch (name) {
119
+ case 'open':
120
+ if (this.inline) return;
121
+ if (this.open) this._show();
122
+ else this._hide();
123
+ break;
124
+ case 'inline': this._applyMode(); break;
125
+ case 'title': this._applyTitle(); break;
126
+ }
127
+ }
128
+
129
+ show() { this.setAttribute('open', ''); }
130
+ close() { this.removeAttribute('open'); }
131
+
132
+ get open() { return this.getBoolAttr('open'); }
133
+ set open(v) { this.setBoolAttr('open', v); }
134
+
135
+ get inline() { return this.getBoolAttr('inline'); }
136
+ set inline(v) { this.setBoolAttr('inline', v); }
137
+ }
138
+
139
+ customElements.define('glk-sheet', GlkSheet);
140
+
141
+ export { GlkSheet };
@@ -1,4 +1,5 @@
1
1
  import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkStatus extends GlkElement {
4
5
  static get observedAttributes() {
@@ -0,0 +1,75 @@
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
3
+
4
+ // Progress through a short flow — purely presentational. Came back from
5
+ // EhrenPfoten in 1.15.0.
6
+ //
7
+ // Attributes: steps (comma-separated labels), current (0-based), label
8
+ // (aria-label of the list, optional)
9
+ // Property: current, steps (array or comma-separated text)
10
+ // Part: steps
11
+ //
12
+ // The narrowing in tight frames is the CSS block's container query; the
13
+ // element knows nothing about it. Done steps show an SVG check, not a text
14
+ // glyph, so the mark does not depend on the font.
15
+
16
+ const CHECK = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12l5 5 9-10"/></svg>';
17
+
18
+ class GlkSteps extends GlkElement {
19
+ static get observedAttributes() { return ['steps', 'current', 'label']; }
20
+
21
+ render() {
22
+ this._list = this.createElement('ol', ['glass-steps'], { part: 'steps' });
23
+ this._wrapper.appendChild(this._list);
24
+ this._build();
25
+ this._applyLabel();
26
+ }
27
+
28
+ _build() {
29
+ const items = this.steps;
30
+ const current = this.current;
31
+ this._list.replaceChildren();
32
+ items.forEach((label, i) => {
33
+ const item = this.createElement('li', ['glass-steps__item']);
34
+ if (i < current) item.classList.add('glass-steps__item--done');
35
+ if (i === current) {
36
+ item.classList.add('glass-steps__item--current');
37
+ item.setAttribute('aria-current', 'step');
38
+ }
39
+ const num = this.createElement('span', ['glass-steps__num']);
40
+ if (i < current) num.innerHTML = CHECK;
41
+ else num.textContent = String(i + 1);
42
+ const text = this.createElement('span', ['glass-steps__label']);
43
+ text.textContent = label;
44
+ item.append(num, text);
45
+ this._list.appendChild(item);
46
+ if (i < items.length - 1) {
47
+ this._list.appendChild(this.createElement('li', ['glass-steps__line'], { 'aria-hidden': 'true' }));
48
+ }
49
+ });
50
+ }
51
+
52
+ _applyLabel() {
53
+ const label = this.getAttribute('label');
54
+ if (label) this._list.setAttribute('aria-label', label);
55
+ else this._list.removeAttribute('aria-label');
56
+ }
57
+
58
+ onAttributeChanged(name) {
59
+ if (!this._list) return;
60
+ if (name === 'label') this._applyLabel();
61
+ else this._build();
62
+ }
63
+
64
+ get current() { return Number(this.getAttribute('current')) || 0; }
65
+ set current(v) { this.setAttribute('current', String(Number(v) || 0)); }
66
+
67
+ get steps() {
68
+ return (this.getAttribute('steps') || '').split(',').map(s => s.trim()).filter(Boolean);
69
+ }
70
+ set steps(v) { this.setAttribute('steps', Array.isArray(v) ? v.join(',') : String(v ?? '')); }
71
+ }
72
+
73
+ customElements.define('glk-steps', GlkSteps);
74
+
75
+ export { GlkSteps };
@@ -1,4 +1,5 @@
1
1
  import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  const VARIANTS = ['accent', 'success', 'error'];
4
5
 
@@ -1,4 +1,5 @@
1
1
  import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkTabBar extends GlkElement {
4
5
  static get observedAttributes() {
@@ -1,4 +1,5 @@
1
1
  import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkTabDock extends GlkElement {
4
5
  static get observedAttributes() {
@@ -1,4 +1,5 @@
1
1
  import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkTabItem extends GlkElement {
4
5
  static get observedAttributes() {
@@ -1,4 +1,5 @@
1
1
  import { GlkFormElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkTextarea extends GlkFormElement {
4
5
  static get observedAttributes() {
@@ -1,4 +1,5 @@
1
1
  import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkTitle extends GlkElement {
4
5
  static get observedAttributes() {
@@ -1,4 +1,5 @@
1
1
  import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  const VARIANTS = ['success', 'error', 'warning'];
4
5
 
@@ -1,4 +1,5 @@
1
1
  import { GlkFormElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkToggle extends GlkFormElement {
4
5
  static get observedAttributes() {