@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,62 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ const CHEVRON_SVG = `<span class="glass-accordion__trigger-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><polyline points="6 9 12 15 18 9"/></svg></span>`;
4
+
5
+ class GlkAccordionItem extends GlkElement {
6
+ static get observedAttributes() {
7
+ return ['title', 'open'];
8
+ }
9
+
10
+ render() {
11
+ this._item = this.createElement('div', ['glass-accordion__item']);
12
+ if (this.getBoolAttr('open')) this._item.classList.add('is-open');
13
+
14
+ // Trigger button
15
+ this._trigger = this.createElement('button', ['glass-accordion__trigger']);
16
+ this._triggerText = document.createTextNode(this.getAttribute('title') || '');
17
+ this._trigger.appendChild(this._triggerText);
18
+ this._trigger.insertAdjacentHTML('beforeend', CHEVRON_SVG);
19
+
20
+ // Content
21
+ this._content = this.createElement('div', ['glass-accordion__content']);
22
+ const body = this.createElement('div', ['glass-accordion__body']);
23
+ body.appendChild(document.createElement('slot'));
24
+ this._content.appendChild(body);
25
+
26
+ this._item.appendChild(this._trigger);
27
+ this._item.appendChild(this._content);
28
+
29
+ this._wrapper.appendChild(this._item);
30
+ }
31
+
32
+ setupEvents() {
33
+ this._onClick = () => {
34
+ this.setBoolAttr('open', !this.getBoolAttr('open'));
35
+ this.emit('glk-toggle', { open: this.getBoolAttr('open') });
36
+ };
37
+ this._trigger.addEventListener('click', this._onClick);
38
+ }
39
+
40
+ teardownEvents() {
41
+ this._trigger?.removeEventListener('click', this._onClick);
42
+ }
43
+
44
+ onAttributeChanged(name) {
45
+ if (!this._item) return;
46
+ switch (name) {
47
+ case 'open':
48
+ this._item.classList.toggle('is-open', this.getBoolAttr('open'));
49
+ break;
50
+ case 'title':
51
+ this._triggerText.textContent = this.getAttribute('title') || '';
52
+ break;
53
+ }
54
+ }
55
+
56
+ get open() { return this.getBoolAttr('open'); }
57
+ set open(v) { this.setBoolAttr('open', v); }
58
+ }
59
+
60
+ customElements.define('glk-accordion-item', GlkAccordionItem);
61
+
62
+ export { GlkAccordionItem };
@@ -0,0 +1,13 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ class GlkAccordion extends GlkElement {
4
+ render() {
5
+ const container = this.createElement('div', ['glass-accordion']);
6
+ container.appendChild(document.createElement('slot'));
7
+ this._wrapper.appendChild(container);
8
+ }
9
+ }
10
+
11
+ customElements.define('glk-accordion', GlkAccordion);
12
+
13
+ export { GlkAccordion };
@@ -0,0 +1,59 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ const SIZES = ['sm', 'lg'];
4
+
5
+ class GlkAvatar extends GlkElement {
6
+ static get displayInline() { return true; }
7
+ static get observedAttributes() {
8
+ return ['size', 'src', 'alt'];
9
+ }
10
+
11
+ render() {
12
+ this._avatar = this.createElement('div', this._computeClasses());
13
+ this._updateContent();
14
+ this._wrapper.appendChild(this._avatar);
15
+ }
16
+
17
+ onAttributeChanged(name) {
18
+ if (!this._avatar) return;
19
+ if (name === 'size') {
20
+ this._avatar.className = this._computeClasses().join(' ');
21
+ } else if (name === 'src' || name === 'alt') {
22
+ this._updateContent();
23
+ }
24
+ }
25
+
26
+ _updateContent() {
27
+ const src = this.getAttribute('src');
28
+ this._avatar.innerHTML = '';
29
+ if (src) {
30
+ const img = this.createElement('img', [], {
31
+ src,
32
+ alt: this.getAttribute('alt') || ''
33
+ });
34
+ this._avatar.appendChild(img);
35
+ } else {
36
+ // Use slotted text content (initials)
37
+ this._avatar.appendChild(document.createElement('slot'));
38
+ }
39
+ }
40
+
41
+ _computeClasses() {
42
+ const classes = ['glass-avatar'];
43
+ const size = this.getAttribute('size');
44
+ if (size && SIZES.includes(size)) {
45
+ classes.push(`glass-avatar--${size}`);
46
+ }
47
+ return classes;
48
+ }
49
+
50
+ get size() { return this.getAttribute('size'); }
51
+ set size(v) { this.setAttribute('size', v); }
52
+
53
+ get src() { return this.getAttribute('src'); }
54
+ set src(v) { this.setAttribute('src', v); }
55
+ }
56
+
57
+ customElements.define('glk-avatar', GlkAvatar);
58
+
59
+ export { GlkAvatar };
@@ -0,0 +1,38 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ const VARIANTS = ['primary', 'success', 'error'];
4
+
5
+ class GlkBadge extends GlkElement {
6
+ static get displayInline() { return true; }
7
+ static get observedAttributes() {
8
+ return ['variant'];
9
+ }
10
+
11
+ render() {
12
+ this._badge = this.createElement('span', this._computeClasses());
13
+ this._badge.appendChild(document.createElement('slot'));
14
+ this._wrapper.appendChild(this._badge);
15
+ }
16
+
17
+ onAttributeChanged(name) {
18
+ if (name === 'variant' && this._badge) {
19
+ this._badge.className = this._computeClasses().join(' ');
20
+ }
21
+ }
22
+
23
+ _computeClasses() {
24
+ const classes = ['glass-badge'];
25
+ const variant = this.getAttribute('variant');
26
+ if (variant && VARIANTS.includes(variant)) {
27
+ classes.push(`glass-badge--${variant}`);
28
+ }
29
+ return classes;
30
+ }
31
+
32
+ get variant() { return this.getAttribute('variant'); }
33
+ set variant(v) { this.setAttribute('variant', v); }
34
+ }
35
+
36
+ customElements.define('glk-badge', GlkBadge);
37
+
38
+ export { GlkBadge };
@@ -0,0 +1,81 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ const VARIANTS = ['primary', 'secondary', 'tertiary'];
4
+ const SIZES = ['sm', 'md', 'lg', 'auto'];
5
+
6
+ class GlkButton extends GlkElement {
7
+ static get observedAttributes() {
8
+ return ['variant', 'size', 'disabled', 'type'];
9
+ }
10
+
11
+ render() {
12
+ this._btn = this.createElement('button', this._computeClasses(), {
13
+ type: this.getAttribute('type') || 'button'
14
+ });
15
+
16
+ if (this.getBoolAttr('disabled')) {
17
+ this._btn.disabled = true;
18
+ }
19
+
20
+ this._btn.appendChild(document.createElement('slot'));
21
+ this._wrapper.appendChild(this._btn);
22
+ }
23
+
24
+ setupEvents() {
25
+ this._onClick = (e) => {
26
+ if (this.getBoolAttr('disabled')) {
27
+ e.preventDefault();
28
+ e.stopPropagation();
29
+ return;
30
+ }
31
+ this.emit('glk-click');
32
+ };
33
+ this._btn.addEventListener('click', this._onClick);
34
+ }
35
+
36
+ teardownEvents() {
37
+ this._btn?.removeEventListener('click', this._onClick);
38
+ }
39
+
40
+ onAttributeChanged(name) {
41
+ if (!this._btn) return;
42
+ switch (name) {
43
+ case 'variant':
44
+ case 'size':
45
+ this._btn.className = this._computeClasses().join(' ');
46
+ break;
47
+ case 'disabled':
48
+ this._btn.disabled = this.getBoolAttr('disabled');
49
+ break;
50
+ case 'type':
51
+ this._btn.setAttribute('type', this.getAttribute('type') || 'button');
52
+ break;
53
+ }
54
+ }
55
+
56
+ _computeClasses() {
57
+ const classes = ['glass-btn'];
58
+ const variant = this.getAttribute('variant');
59
+ if (variant && VARIANTS.includes(variant)) {
60
+ classes.push(`glass-btn--${variant}`);
61
+ }
62
+ const size = this.getAttribute('size');
63
+ if (size && SIZES.includes(size)) {
64
+ classes.push(`glass-btn--${size}`);
65
+ }
66
+ return classes;
67
+ }
68
+
69
+ get variant() { return this.getAttribute('variant'); }
70
+ set variant(v) { this.setAttribute('variant', v); }
71
+
72
+ get size() { return this.getAttribute('size'); }
73
+ set size(v) { this.setAttribute('size', v); }
74
+
75
+ get disabled() { return this.getBoolAttr('disabled'); }
76
+ set disabled(v) { this.setBoolAttr('disabled', v); }
77
+ }
78
+
79
+ customElements.define('glk-button', GlkButton);
80
+
81
+ export { GlkButton };
@@ -0,0 +1,51 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ // <glk-card fill> stretches the visible card to the height of its grid or flex
4
+ // cell. The host must become a grid for this: it is stretched by the outer
5
+ // layout but keeps height:auto, so a percentage height on the inner card has
6
+ // nothing definite to resolve against. Making the host a grid stretches its
7
+ // single child instead, which needs no percentage at all. The card also becomes
8
+ // a flex column so a footer can be pushed down with margin-top:auto.
9
+ const fillSheet = new CSSStyleSheet();
10
+ fillSheet.replaceSync(`
11
+ :host([fill]) { display: grid; }
12
+ :host([fill]) .glass-card { display: flex; flex-direction: column; }
13
+ `);
14
+
15
+ class GlkCard extends GlkElement {
16
+ static get observedAttributes() {
17
+ return ['glow', 'fill'];
18
+ }
19
+
20
+ static get hostStyles() { return fillSheet; }
21
+
22
+ render() {
23
+ this._card = this.createElement('div', this._computeClasses(), { part: 'card' });
24
+ this._card.appendChild(document.createElement('slot'));
25
+ this._wrapper.appendChild(this._card);
26
+ }
27
+
28
+ onAttributeChanged(name) {
29
+ if (name === 'glow' && this._card) {
30
+ this._card.className = this._computeClasses().join(' ');
31
+ }
32
+ }
33
+
34
+ _computeClasses() {
35
+ const classes = ['glass-card'];
36
+ if (this.getBoolAttr('glow')) {
37
+ classes.push('glass-card--glow');
38
+ }
39
+ return classes;
40
+ }
41
+
42
+ get glow() { return this.getBoolAttr('glow'); }
43
+ set glow(v) { this.setBoolAttr('glow', v); }
44
+
45
+ get fill() { return this.getBoolAttr('fill'); }
46
+ set fill(v) { this.setBoolAttr('fill', v); }
47
+ }
48
+
49
+ customElements.define('glk-card', GlkCard);
50
+
51
+ export { GlkCard };
@@ -0,0 +1,104 @@
1
+ import { a as GlkFormElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ const CHECKMARK_SVG = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>`;
4
+
5
+ class GlkCheckbox extends GlkFormElement {
6
+ static get observedAttributes() {
7
+ return ['checked', 'disabled', 'label', 'name', 'value'];
8
+ }
9
+
10
+ render() {
11
+ const label = this.createElement('label', ['glass-checkbox']);
12
+
13
+ this._input = this.createElement('input', ['glass-checkbox__input'], {
14
+ type: 'checkbox'
15
+ });
16
+
17
+ const name = this.getAttribute('name');
18
+ if (name) this._input.setAttribute('name', name);
19
+
20
+ const box = this.createElement('span', ['glass-checkbox__box']);
21
+ box.innerHTML = CHECKMARK_SVG;
22
+
23
+ this._labelEl = this.createElement('span', ['glass-checkbox__label']);
24
+ this._labelEl.textContent = this.getAttribute('label') || '';
25
+
26
+ label.appendChild(this._input);
27
+ label.appendChild(box);
28
+ label.appendChild(this._labelEl);
29
+
30
+ if (this.getBoolAttr('checked')) this._input.checked = true;
31
+ if (this.getBoolAttr('disabled')) this._input.disabled = true;
32
+
33
+ this._defaultChecked = this.getBoolAttr('checked');
34
+ this._wrapper.appendChild(label);
35
+ this._syncFormValue();
36
+ }
37
+
38
+ setupEvents() {
39
+ this._onChange = () => {
40
+ this._syncing = true;
41
+ this.setBoolAttr('checked', this._input.checked);
42
+ this._syncing = false;
43
+ this._syncFormValue();
44
+ this.emit('glk-change', { checked: this._input.checked });
45
+ this.dispatchEvent(new Event('change', { bubbles: true }));
46
+ };
47
+ this._input.addEventListener('change', this._onChange);
48
+ }
49
+
50
+ teardownEvents() {
51
+ this._input?.removeEventListener('change', this._onChange);
52
+ }
53
+
54
+ onAttributeChanged(name) {
55
+ if (this._syncing) return;
56
+ if (!this._input) return;
57
+ switch (name) {
58
+ case 'checked':
59
+ this._input.checked = this.getBoolAttr('checked');
60
+ this._syncFormValue();
61
+ break;
62
+ case 'disabled':
63
+ this._input.disabled = this.getBoolAttr('disabled');
64
+ break;
65
+ case 'label':
66
+ this._labelEl.textContent = this.getAttribute('label') || '';
67
+ break;
68
+ case 'name':
69
+ this._input.setAttribute('name', this.getAttribute('name') || '');
70
+ break;
71
+ }
72
+ }
73
+
74
+ _syncFormValue() {
75
+ const val = this.getAttribute('value') || 'on';
76
+ this.setFormValue(this._input.checked ? val : null);
77
+ }
78
+
79
+ resetValue() {
80
+ this._input.checked = this._defaultChecked;
81
+ this.setBoolAttr('checked', this._defaultChecked);
82
+ this._syncFormValue();
83
+ }
84
+
85
+ get checked() { return this._input?.checked ?? false; }
86
+ set checked(v) {
87
+ if (this._input) this._input.checked = v;
88
+ this.setBoolAttr('checked', v);
89
+ this._syncFormValue();
90
+ }
91
+
92
+ get disabled() { return this.getBoolAttr('disabled'); }
93
+ set disabled(v) { this.setBoolAttr('disabled', v); }
94
+
95
+ get name() { return this.getAttribute('name'); }
96
+ set name(v) { this.setAttribute('name', v); }
97
+
98
+ get value() { return this.getAttribute('value') || 'on'; }
99
+ set value(v) { this.setAttribute('value', v); }
100
+ }
101
+
102
+ customElements.define('glk-checkbox', GlkCheckbox);
103
+
104
+ export { GlkCheckbox };
@@ -0,0 +1,12 @@
1
+ import { G as GlkElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ class GlkDivider extends GlkElement {
4
+ render() {
5
+ const hr = this.createElement('div', ['glass-divider']);
6
+ this._wrapper.appendChild(hr);
7
+ }
8
+ }
9
+
10
+ customElements.define('glk-divider', GlkDivider);
11
+
12
+ export { GlkDivider };
@@ -0,0 +1,139 @@
1
+ import { a as GlkFormElement } from './shared/base-Bm9Z714o.js';
2
+
3
+ class GlkInput extends GlkFormElement {
4
+ static get observedAttributes() {
5
+ return ['label', 'type', 'placeholder', 'error', 'hint', 'disabled', 'name', 'value', 'required'];
6
+ }
7
+
8
+ render() {
9
+ const group = this.createElement('div', ['glass-input-group']);
10
+
11
+ // Label
12
+ this._labelEl = this.createElement('label', ['glass-label']);
13
+ this._labelEl.textContent = this.getAttribute('label') || '';
14
+
15
+ // Input
16
+ this._input = this.createElement('input', this._computeInputClasses(), {
17
+ type: this.getAttribute('type') || 'text'
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
+ if (this.getBoolAttr('required')) this._input.required = true;
31
+
32
+ // Hint
33
+ this._hintEl = this.createElement('span', this._computeHintClasses());
34
+ this._hintEl.textContent = this.getAttribute('hint') || '';
35
+
36
+ group.appendChild(this._labelEl);
37
+ group.appendChild(this._input);
38
+ if (this.getAttribute('hint')) group.appendChild(this._hintEl);
39
+
40
+ this._group = group;
41
+ this._wrapper.appendChild(group);
42
+
43
+ this._syncFormValue();
44
+ }
45
+
46
+ setupEvents() {
47
+ this._onInput = () => {
48
+ this._syncFormValue();
49
+ this.emit('glk-input', { value: this._input.value });
50
+ this.dispatchEvent(new Event('input', { bubbles: true }));
51
+ };
52
+ this._onChangeNative = () => {
53
+ this.emit('glk-change', { value: this._input.value });
54
+ this.dispatchEvent(new Event('change', { bubbles: true }));
55
+ };
56
+ this._input.addEventListener('input', this._onInput);
57
+ this._input.addEventListener('change', this._onChangeNative);
58
+ }
59
+
60
+ teardownEvents() {
61
+ this._input?.removeEventListener('input', this._onInput);
62
+ this._input?.removeEventListener('change', this._onChangeNative);
63
+ }
64
+
65
+ onAttributeChanged(name) {
66
+ if (!this._input) return;
67
+ switch (name) {
68
+ case 'label':
69
+ this._labelEl.textContent = this.getAttribute('label') || '';
70
+ break;
71
+ case 'type':
72
+ this._input.setAttribute('type', this.getAttribute('type') || 'text');
73
+ break;
74
+ case 'placeholder':
75
+ this._input.setAttribute('placeholder', this.getAttribute('placeholder') || '');
76
+ break;
77
+ case 'error':
78
+ this._input.className = this._computeInputClasses().join(' ');
79
+ this._hintEl.className = this._computeHintClasses().join(' ');
80
+ break;
81
+ case 'hint':
82
+ this._hintEl.textContent = this.getAttribute('hint') || '';
83
+ if (this.getAttribute('hint') && !this._hintEl.parentNode) {
84
+ this._group.appendChild(this._hintEl);
85
+ }
86
+ break;
87
+ case 'disabled':
88
+ this._input.disabled = this.getBoolAttr('disabled');
89
+ break;
90
+ case 'name':
91
+ this._input.setAttribute('name', this.getAttribute('name') || '');
92
+ break;
93
+ case 'value':
94
+ this._input.value = this.getAttribute('value') || '';
95
+ this._syncFormValue();
96
+ break;
97
+ case 'required':
98
+ this._input.required = this.getBoolAttr('required');
99
+ break;
100
+ }
101
+ }
102
+
103
+ _computeInputClasses() {
104
+ const classes = ['glass-input'];
105
+ if (this.getBoolAttr('error')) classes.push('glass-input--error');
106
+ return classes;
107
+ }
108
+
109
+ _computeHintClasses() {
110
+ const classes = ['glass-hint'];
111
+ if (this.getBoolAttr('error')) classes.push('glass-hint--error');
112
+ return classes;
113
+ }
114
+
115
+ _syncFormValue() {
116
+ this.setFormValue(this._input.value);
117
+ }
118
+
119
+ resetValue() {
120
+ this._input.value = this.getAttribute('value') || '';
121
+ this._syncFormValue();
122
+ }
123
+
124
+ get value() { return this._input?.value ?? ''; }
125
+ set value(v) {
126
+ if (this._input) this._input.value = v;
127
+ this._syncFormValue();
128
+ }
129
+
130
+ get disabled() { return this.getBoolAttr('disabled'); }
131
+ set disabled(v) { this.setBoolAttr('disabled', v); }
132
+
133
+ get name() { return this.getAttribute('name'); }
134
+ set name(v) { this.setAttribute('name', v); }
135
+ }
136
+
137
+ customElements.define('glk-input', GlkInput);
138
+
139
+ export { GlkInput };