@jungherz-de/glasskit-elements 1.6.2 → 1.8.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 (38) hide show
  1. package/dist/components/glk-accordion-item.js +62 -0
  2. package/dist/components/glk-accordion.js +13 -0
  3. package/dist/components/glk-avatar.js +59 -0
  4. package/dist/components/glk-badge.js +38 -0
  5. package/dist/components/glk-button.js +81 -0
  6. package/dist/components/glk-card.js +51 -0
  7. package/dist/components/glk-checkbox.js +104 -0
  8. package/dist/components/glk-divider.js +12 -0
  9. package/dist/components/glk-input.js +139 -0
  10. package/dist/components/glk-list-item.js +188 -0
  11. package/dist/components/glk-list.js +75 -0
  12. package/dist/components/glk-modal.js +101 -0
  13. package/dist/components/glk-nav.js +13 -0
  14. package/dist/components/glk-pill.js +49 -0
  15. package/dist/components/glk-popover.js +109 -0
  16. package/dist/components/glk-progress.js +78 -0
  17. package/dist/components/glk-radio.js +110 -0
  18. package/dist/components/glk-range.js +113 -0
  19. package/dist/components/glk-search.js +88 -0
  20. package/dist/components/glk-select.js +97 -0
  21. package/dist/components/glk-status.js +36 -0
  22. package/dist/components/glk-tab-accessory.js +66 -0
  23. package/dist/components/glk-tab-bar.js +59 -0
  24. package/dist/components/glk-tab-dock.js +52 -0
  25. package/dist/components/glk-tab-item.js +93 -0
  26. package/dist/components/glk-textarea.js +96 -0
  27. package/dist/components/glk-title.js +17 -0
  28. package/dist/components/glk-toast.js +105 -0
  29. package/dist/components/glk-toggle.js +122 -0
  30. package/dist/components/shared/base-Bm9Z714o.js +199 -0
  31. package/dist/glasskit-elements.esm.js +39 -12
  32. package/dist/glasskit-elements.js +39 -12
  33. package/dist/glasskit-elements.min.js +1 -1
  34. package/package.json +7 -4
  35. package/src/base.js +11 -1
  36. package/src/components/containers/glk-list.js +2 -2
  37. package/src/components/content/glk-card.js +19 -2
  38. package/src/components/feedback/glk-modal.js +5 -5
@@ -0,0 +1,110 @@
1
+ import { a as GlkFormElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ class GlkRadio extends GlkFormElement {
4
+ static get observedAttributes() {
5
+ return ['checked', 'disabled', 'label', 'name', 'value'];
6
+ }
7
+
8
+ render() {
9
+ const label = this.createElement('label', ['glass-radio']);
10
+
11
+ this._input = this.createElement('input', ['glass-radio__input'], {
12
+ type: 'radio'
13
+ });
14
+
15
+ const name = this.getAttribute('name');
16
+ if (name) this._input.setAttribute('name', name);
17
+
18
+ const val = this.getAttribute('value');
19
+ if (val) this._input.setAttribute('value', val);
20
+
21
+ const circle = this.createElement('span', ['glass-radio__circle']);
22
+ const dot = this.createElement('span', ['glass-radio__dot']);
23
+ circle.appendChild(dot);
24
+
25
+ this._labelEl = this.createElement('span', ['glass-radio__label']);
26
+ this._labelEl.textContent = this.getAttribute('label') || '';
27
+
28
+ label.appendChild(this._input);
29
+ label.appendChild(circle);
30
+ label.appendChild(this._labelEl);
31
+
32
+ if (this.getBoolAttr('checked')) this._input.checked = true;
33
+ if (this.getBoolAttr('disabled')) this._input.disabled = true;
34
+
35
+ this._defaultChecked = this.getBoolAttr('checked');
36
+ this._wrapper.appendChild(label);
37
+ this._syncFormValue();
38
+ }
39
+
40
+ setupEvents() {
41
+ this._onChange = () => {
42
+ this._syncing = true;
43
+ this.setBoolAttr('checked', this._input.checked);
44
+ this._syncing = false;
45
+ this._syncFormValue();
46
+ this.emit('glk-change', { checked: this._input.checked, value: this._input.value });
47
+ this.dispatchEvent(new Event('change', { bubbles: true }));
48
+ };
49
+ this._input.addEventListener('change', this._onChange);
50
+ }
51
+
52
+ teardownEvents() {
53
+ this._input?.removeEventListener('change', this._onChange);
54
+ }
55
+
56
+ onAttributeChanged(name) {
57
+ if (this._syncing) return;
58
+ if (!this._input) return;
59
+ switch (name) {
60
+ case 'checked':
61
+ this._input.checked = this.getBoolAttr('checked');
62
+ this._syncFormValue();
63
+ break;
64
+ case 'disabled':
65
+ this._input.disabled = this.getBoolAttr('disabled');
66
+ break;
67
+ case 'label':
68
+ this._labelEl.textContent = this.getAttribute('label') || '';
69
+ break;
70
+ case 'name':
71
+ this._input.setAttribute('name', this.getAttribute('name') || '');
72
+ break;
73
+ case 'value':
74
+ this._input.setAttribute('value', this.getAttribute('value') || '');
75
+ this._syncFormValue();
76
+ break;
77
+ }
78
+ }
79
+
80
+ _syncFormValue() {
81
+ const val = this.getAttribute('value') || '';
82
+ this.setFormValue(this._input.checked ? val : null);
83
+ }
84
+
85
+ resetValue() {
86
+ this._input.checked = this._defaultChecked;
87
+ this.setBoolAttr('checked', this._defaultChecked);
88
+ this._syncFormValue();
89
+ }
90
+
91
+ get checked() { return this._input?.checked ?? false; }
92
+ set checked(v) {
93
+ if (this._input) this._input.checked = v;
94
+ this.setBoolAttr('checked', v);
95
+ this._syncFormValue();
96
+ }
97
+
98
+ get disabled() { return this.getBoolAttr('disabled'); }
99
+ set disabled(v) { this.setBoolAttr('disabled', v); }
100
+
101
+ get name() { return this.getAttribute('name'); }
102
+ set name(v) { this.setAttribute('name', v); }
103
+
104
+ get value() { return this.getAttribute('value'); }
105
+ set value(v) { this.setAttribute('value', v); }
106
+ }
107
+
108
+ customElements.define('glk-radio', GlkRadio);
109
+
110
+ export { GlkRadio };
@@ -0,0 +1,113 @@
1
+ import { a as GlkFormElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ class GlkRange extends GlkFormElement {
4
+ static get observedAttributes() {
5
+ return ['label', 'min', 'max', 'value', 'step', 'name', 'disabled'];
6
+ }
7
+
8
+ render() {
9
+ const group = this.createElement('div', ['glass-range-group']);
10
+
11
+ const header = this.createElement('div', ['glass-range-header']);
12
+
13
+ this._labelEl = this.createElement('label', []);
14
+ this._labelEl.textContent = this.getAttribute('label') || '';
15
+
16
+ this._valueEl = this.createElement('span', ['glass-range-value']);
17
+
18
+ header.appendChild(this._labelEl);
19
+ header.appendChild(this._valueEl);
20
+
21
+ this._input = this.createElement('input', ['glass-range'], {
22
+ type: 'range',
23
+ min: this.getAttribute('min') || '0',
24
+ max: this.getAttribute('max') || '100',
25
+ value: this.getAttribute('value') || '50'
26
+ });
27
+
28
+ const step = this.getAttribute('step');
29
+ if (step) this._input.setAttribute('step', step);
30
+
31
+ const name = this.getAttribute('name');
32
+ if (name) this._input.setAttribute('name', name);
33
+
34
+ if (this.getBoolAttr('disabled')) this._input.disabled = true;
35
+
36
+ this._updateValueDisplay();
37
+
38
+ group.appendChild(header);
39
+ group.appendChild(this._input);
40
+
41
+ this._wrapper.appendChild(group);
42
+ this._defaultValue = this._input.value;
43
+ this._syncFormValue();
44
+ }
45
+
46
+ setupEvents() {
47
+ this._onInput = () => {
48
+ this._updateValueDisplay();
49
+ this._syncFormValue();
50
+ this.emit('glk-input', { value: this._input.value });
51
+ this.dispatchEvent(new Event('input', { bubbles: true }));
52
+ };
53
+ this._input.addEventListener('input', this._onInput);
54
+ }
55
+
56
+ teardownEvents() {
57
+ this._input?.removeEventListener('input', this._onInput);
58
+ }
59
+
60
+ onAttributeChanged(name) {
61
+ if (!this._input) return;
62
+ switch (name) {
63
+ case 'label':
64
+ this._labelEl.textContent = this.getAttribute('label') || '';
65
+ break;
66
+ case 'min':
67
+ this._input.min = this.getAttribute('min') || '0';
68
+ break;
69
+ case 'max':
70
+ this._input.max = this.getAttribute('max') || '100';
71
+ break;
72
+ case 'value':
73
+ this._input.value = this.getAttribute('value') || '50';
74
+ this._updateValueDisplay();
75
+ this._syncFormValue();
76
+ break;
77
+ case 'step':
78
+ this._input.step = this.getAttribute('step') || '';
79
+ break;
80
+ case 'name':
81
+ this._input.setAttribute('name', this.getAttribute('name') || '');
82
+ break;
83
+ case 'disabled':
84
+ this._input.disabled = this.getBoolAttr('disabled');
85
+ break;
86
+ }
87
+ }
88
+
89
+ _updateValueDisplay() {
90
+ this._valueEl.textContent = `${this._input.value}%`;
91
+ }
92
+
93
+ _syncFormValue() {
94
+ this.setFormValue(this._input.value);
95
+ }
96
+
97
+ resetValue() {
98
+ this._input.value = this._defaultValue;
99
+ this._updateValueDisplay();
100
+ this._syncFormValue();
101
+ }
102
+
103
+ get value() { return this._input?.value ?? ''; }
104
+ set value(v) {
105
+ if (this._input) this._input.value = v;
106
+ this._updateValueDisplay();
107
+ this._syncFormValue();
108
+ }
109
+ }
110
+
111
+ customElements.define('glk-range', GlkRange);
112
+
113
+ export { GlkRange };
@@ -0,0 +1,88 @@
1
+ import { a as GlkFormElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ const SEARCH_SVG = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>`;
4
+
5
+ class GlkSearch extends GlkFormElement {
6
+ static get observedAttributes() {
7
+ return ['placeholder', 'name', 'value', 'disabled'];
8
+ }
9
+
10
+ render() {
11
+ const container = this.createElement('div', ['glass-search']);
12
+
13
+ const icon = this.createElement('span', ['glass-search__icon']);
14
+ icon.innerHTML = SEARCH_SVG;
15
+
16
+ this._input = this.createElement('input', ['glass-input'], {
17
+ type: 'search'
18
+ });
19
+
20
+ const placeholder = this.getAttribute('placeholder');
21
+ if (placeholder) this._input.setAttribute('placeholder', placeholder);
22
+
23
+ const name = this.getAttribute('name');
24
+ if (name) this._input.setAttribute('name', name);
25
+
26
+ const value = this.getAttribute('value');
27
+ if (value) this._input.value = value;
28
+
29
+ if (this.getBoolAttr('disabled')) this._input.disabled = true;
30
+
31
+ container.appendChild(icon);
32
+ container.appendChild(this._input);
33
+
34
+ this._wrapper.appendChild(container);
35
+ this._syncFormValue();
36
+ }
37
+
38
+ setupEvents() {
39
+ this._onInput = () => {
40
+ this._syncFormValue();
41
+ this.emit('glk-input', { value: this._input.value });
42
+ this.dispatchEvent(new Event('input', { bubbles: true }));
43
+ };
44
+ this._input.addEventListener('input', this._onInput);
45
+ }
46
+
47
+ teardownEvents() {
48
+ this._input?.removeEventListener('input', this._onInput);
49
+ }
50
+
51
+ onAttributeChanged(name) {
52
+ if (!this._input) return;
53
+ switch (name) {
54
+ case 'placeholder':
55
+ this._input.setAttribute('placeholder', this.getAttribute('placeholder') || '');
56
+ break;
57
+ case 'name':
58
+ this._input.setAttribute('name', this.getAttribute('name') || '');
59
+ break;
60
+ case 'value':
61
+ this._input.value = this.getAttribute('value') || '';
62
+ this._syncFormValue();
63
+ break;
64
+ case 'disabled':
65
+ this._input.disabled = this.getBoolAttr('disabled');
66
+ break;
67
+ }
68
+ }
69
+
70
+ _syncFormValue() {
71
+ this.setFormValue(this._input.value);
72
+ }
73
+
74
+ resetValue() {
75
+ this._input.value = this.getAttribute('value') || '';
76
+ this._syncFormValue();
77
+ }
78
+
79
+ get value() { return this._input?.value ?? ''; }
80
+ set value(v) {
81
+ if (this._input) this._input.value = v;
82
+ this._syncFormValue();
83
+ }
84
+ }
85
+
86
+ customElements.define('glk-search', GlkSearch);
87
+
88
+ export { GlkSearch };
@@ -0,0 +1,97 @@
1
+ import { a as GlkFormElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ class GlkSelect extends GlkFormElement {
4
+ static get observedAttributes() {
5
+ return ['label', 'disabled', 'name', 'value', 'required'];
6
+ }
7
+
8
+ render() {
9
+ const group = this.createElement('div', ['glass-input-group']);
10
+
11
+ this._labelEl = this.createElement('label', ['glass-label']);
12
+ this._labelEl.textContent = this.getAttribute('label') || '';
13
+
14
+ this._select = this.createElement('select', ['glass-select']);
15
+
16
+ const name = this.getAttribute('name');
17
+ if (name) this._select.setAttribute('name', name);
18
+
19
+ if (this.getBoolAttr('disabled')) this._select.disabled = true;
20
+ if (this.getBoolAttr('required')) this._select.required = true;
21
+
22
+ group.appendChild(this._labelEl);
23
+ group.appendChild(this._select);
24
+
25
+ this._wrapper.appendChild(group);
26
+
27
+ // Defer option copying — children may not be parsed yet in connectedCallback
28
+ requestAnimationFrame(() => {
29
+ this._moveOptions();
30
+ const value = this.getAttribute('value');
31
+ if (value) this._select.value = value;
32
+ this._syncFormValue();
33
+ });
34
+ }
35
+
36
+ _moveOptions() {
37
+ this._select.innerHTML = '';
38
+ const options = this.querySelectorAll('option');
39
+ options.forEach(opt => {
40
+ this._select.appendChild(opt.cloneNode(true));
41
+ });
42
+ }
43
+
44
+ setupEvents() {
45
+ this._onChange = () => {
46
+ this._syncFormValue();
47
+ this.emit('glk-change', { value: this._select.value });
48
+ this.dispatchEvent(new Event('change', { bubbles: true }));
49
+ };
50
+ this._select.addEventListener('change', this._onChange);
51
+ }
52
+
53
+ teardownEvents() {
54
+ this._select?.removeEventListener('change', this._onChange);
55
+ }
56
+
57
+ onAttributeChanged(name) {
58
+ if (!this._select) return;
59
+ switch (name) {
60
+ case 'label':
61
+ this._labelEl.textContent = this.getAttribute('label') || '';
62
+ break;
63
+ case 'disabled':
64
+ this._select.disabled = this.getBoolAttr('disabled');
65
+ break;
66
+ case 'name':
67
+ this._select.setAttribute('name', this.getAttribute('name') || '');
68
+ break;
69
+ case 'value':
70
+ this._select.value = this.getAttribute('value') || '';
71
+ this._syncFormValue();
72
+ break;
73
+ }
74
+ }
75
+
76
+ _syncFormValue() {
77
+ this.setFormValue(this._select.value);
78
+ }
79
+
80
+ resetValue() {
81
+ this._select.selectedIndex = 0;
82
+ this._syncFormValue();
83
+ }
84
+
85
+ get value() { return this._select?.value ?? ''; }
86
+ set value(v) {
87
+ if (this._select) this._select.value = v;
88
+ this._syncFormValue();
89
+ }
90
+
91
+ get disabled() { return this.getBoolAttr('disabled'); }
92
+ set disabled(v) { this.setBoolAttr('disabled', v); }
93
+ }
94
+
95
+ customElements.define('glk-select', GlkSelect);
96
+
97
+ export { GlkSelect };
@@ -0,0 +1,36 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ class GlkStatus extends GlkElement {
4
+ static get observedAttributes() {
5
+ return ['message'];
6
+ }
7
+
8
+ render() {
9
+ this._container = this.createElement('div', ['glass-status']);
10
+
11
+ // Icon via slot
12
+ this._iconSlot = this.createElement('span', []);
13
+ this._iconSlot.appendChild(this.createElement('slot', [], { name: 'icon' }));
14
+
15
+ // Message
16
+ this._messageEl = this.createElement('p', []);
17
+ this._messageEl.textContent = this.getAttribute('message') || '';
18
+
19
+ this._container.appendChild(this._iconSlot);
20
+ this._container.appendChild(this._messageEl);
21
+ this._wrapper.appendChild(this._container);
22
+ }
23
+
24
+ onAttributeChanged(name) {
25
+ if (name === 'message' && this._messageEl) {
26
+ this._messageEl.textContent = this.getAttribute('message') || '';
27
+ }
28
+ }
29
+
30
+ get message() { return this.getAttribute('message'); }
31
+ set message(v) { this.setAttribute('message', v); }
32
+ }
33
+
34
+ customElements.define('glk-status', GlkStatus);
35
+
36
+ export { GlkStatus };
@@ -0,0 +1,66 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ const VARIANTS = ['accent', 'success', 'error'];
4
+
5
+ class GlkTabAccessory extends GlkElement {
6
+ static get observedAttributes() {
7
+ return ['label', 'disabled', 'variant'];
8
+ }
9
+
10
+ render() {
11
+ this._btn = this.createElement('button', ['glass-tab-bar__accessory']);
12
+
13
+ if (this.getBoolAttr('disabled')) this._btn.disabled = true;
14
+
15
+ const ariaLabel = this.getAttribute('label');
16
+ if (ariaLabel) this._btn.setAttribute('aria-label', ariaLabel);
17
+
18
+ this._applyVariant();
19
+
20
+ this._btn.appendChild(document.createElement('slot'));
21
+ this._wrapper.appendChild(this._btn);
22
+ }
23
+
24
+ _applyVariant() {
25
+ if (!this._btn) return;
26
+ for (const v of VARIANTS) {
27
+ this._btn.classList.remove(`glass-tab-bar__accessory--${v}`);
28
+ }
29
+ const variant = this.getAttribute('variant');
30
+ if (variant && VARIANTS.includes(variant)) {
31
+ this._btn.classList.add(`glass-tab-bar__accessory--${variant}`);
32
+ }
33
+ }
34
+
35
+ setupEvents() {
36
+ this._onClick = () => {
37
+ if (!this.getBoolAttr('disabled')) {
38
+ this.emit('glk-click');
39
+ }
40
+ };
41
+ this._btn.addEventListener('click', this._onClick);
42
+ }
43
+
44
+ teardownEvents() {
45
+ this._btn?.removeEventListener('click', this._onClick);
46
+ }
47
+
48
+ onAttributeChanged(name) {
49
+ if (!this._btn) return;
50
+ switch (name) {
51
+ case 'label':
52
+ this._btn.setAttribute('aria-label', this.getAttribute('label') || '');
53
+ break;
54
+ case 'disabled':
55
+ this._btn.disabled = this.getBoolAttr('disabled');
56
+ break;
57
+ case 'variant':
58
+ this._applyVariant();
59
+ break;
60
+ }
61
+ }
62
+ }
63
+
64
+ customElements.define('glk-tab-accessory', GlkTabAccessory);
65
+
66
+ export { GlkTabAccessory };
@@ -0,0 +1,59 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ class GlkTabBar extends GlkElement {
4
+ static get observedAttributes() {
5
+ return ['static', 'floating'];
6
+ }
7
+
8
+ render() {
9
+ const nav = this.createElement('nav', ['glass-tab-bar']);
10
+ nav.appendChild(document.createElement('slot'));
11
+ this._wrapper.appendChild(nav);
12
+ this._nav = nav;
13
+
14
+ if (this.getBoolAttr('floating')) {
15
+ nav.classList.add('glass-tab-bar--floating');
16
+ }
17
+
18
+ if (this.getBoolAttr('static')) {
19
+ this._applyStatic();
20
+ }
21
+ }
22
+
23
+ onAttributeChanged(name) {
24
+ if (!this._nav) return;
25
+ if (name === 'static') {
26
+ this._applyStatic();
27
+ } else if (name === 'floating') {
28
+ this._nav.classList.toggle('glass-tab-bar--floating', this.getBoolAttr('floating'));
29
+ }
30
+ }
31
+
32
+ _applyStatic() {
33
+ this._nav.style.position = 'relative';
34
+ this._nav.style.borderRadius = '16px';
35
+ }
36
+
37
+ setupEvents() {
38
+ // Listen for tab selection events from child glk-tab-item elements
39
+ this._onTabSelect = (e) => {
40
+ // Deactivate all other tabs
41
+ const items = this.querySelectorAll('glk-tab-item');
42
+ items.forEach(item => {
43
+ if (item !== e.target) {
44
+ item.removeAttribute('active');
45
+ }
46
+ });
47
+ this.emit('glk-tab-change', { tab: e.target });
48
+ };
49
+ this.addEventListener('glk-tab-select', this._onTabSelect);
50
+ }
51
+
52
+ teardownEvents() {
53
+ this.removeEventListener('glk-tab-select', this._onTabSelect);
54
+ }
55
+ }
56
+
57
+ customElements.define('glk-tab-bar', GlkTabBar);
58
+
59
+ export { GlkTabBar };
@@ -0,0 +1,52 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ class GlkTabDock extends GlkElement {
4
+ static get observedAttributes() {
5
+ return ['accessory-left', 'static'];
6
+ }
7
+
8
+ render() {
9
+ this._dock = this.createElement('div', ['glass-tab-bar-dock']);
10
+ if (this.getBoolAttr('accessory-left')) {
11
+ this._dock.classList.add('glass-tab-bar-dock--accessory-left');
12
+ }
13
+ this._dock.appendChild(document.createElement('slot'));
14
+ this._wrapper.appendChild(this._dock);
15
+
16
+ if (this.getBoolAttr('static')) {
17
+ this._applyStatic();
18
+ }
19
+ }
20
+
21
+ onAttributeChanged(name) {
22
+ if (!this._dock) return;
23
+ if (name === 'accessory-left') {
24
+ this._dock.classList.toggle(
25
+ 'glass-tab-bar-dock--accessory-left',
26
+ this.getBoolAttr('accessory-left')
27
+ );
28
+ } else if (name === 'static') {
29
+ this._applyStatic();
30
+ }
31
+ }
32
+
33
+ _applyStatic() {
34
+ if (this.getBoolAttr('static')) {
35
+ this._dock.style.position = 'relative';
36
+ this._dock.style.left = 'auto';
37
+ this._dock.style.bottom = 'auto';
38
+ this._dock.style.transform = 'none';
39
+ this._dock.style.justifyContent = 'center';
40
+ } else {
41
+ this._dock.style.position = '';
42
+ this._dock.style.left = '';
43
+ this._dock.style.bottom = '';
44
+ this._dock.style.transform = '';
45
+ this._dock.style.justifyContent = '';
46
+ }
47
+ }
48
+ }
49
+
50
+ customElements.define('glk-tab-dock', GlkTabDock);
51
+
52
+ export { GlkTabDock };