@jungherz-de/glasskit-elements 1.13.0 → 1.15.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 (45) hide show
  1. package/README.md +43 -6
  2. package/dist/components/base.js +253 -0
  3. package/dist/components/glk-accordion-item.js +2 -1
  4. package/dist/components/glk-accordion.js +2 -1
  5. package/dist/components/glk-avatar.js +2 -1
  6. package/dist/components/glk-badge.js +2 -1
  7. package/dist/components/glk-button.js +2 -1
  8. package/dist/components/glk-card.js +2 -1
  9. package/dist/components/glk-checkbox.js +2 -1
  10. package/dist/components/glk-divider.js +2 -1
  11. package/dist/components/glk-empty.js +53 -0
  12. package/dist/components/glk-input.js +2 -1
  13. package/dist/components/glk-list-item.js +2 -1
  14. package/dist/components/glk-list.js +2 -1
  15. package/dist/components/glk-modal.js +2 -1
  16. package/dist/components/glk-nav.js +2 -1
  17. package/dist/components/glk-pill.js +2 -1
  18. package/dist/components/glk-popover.js +2 -1
  19. package/dist/components/glk-progress.js +2 -1
  20. package/dist/components/glk-radio.js +2 -1
  21. package/dist/components/glk-range.js +2 -1
  22. package/dist/components/glk-search.js +2 -1
  23. package/dist/components/glk-segmented.js +124 -0
  24. package/dist/components/glk-select.js +2 -1
  25. package/dist/components/glk-sheet.js +141 -0
  26. package/dist/components/glk-status.js +2 -1
  27. package/dist/components/glk-steps.js +75 -0
  28. package/dist/components/glk-tab-accessory.js +2 -1
  29. package/dist/components/glk-tab-bar.js +2 -1
  30. package/dist/components/glk-tab-dock.js +2 -1
  31. package/dist/components/glk-tab-item.js +2 -1
  32. package/dist/components/glk-textarea.js +2 -1
  33. package/dist/components/glk-title.js +2 -1
  34. package/dist/components/glk-toast.js +2 -1
  35. package/dist/components/glk-toggle.js +2 -1
  36. package/dist/glasskit-elements.esm.js +380 -3
  37. package/dist/glasskit-elements.js +385 -2
  38. package/dist/glasskit-elements.min.js +1 -1
  39. package/package.json +4 -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 +10 -0
  45. package/dist/components/shared/base-ClsXgLON.js +0 -273
package/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
  <p align="center">
4
4
  <a href="https://www.npmjs.com/package/@jungherz-de/glasskit-elements"><img src="https://img.shields.io/npm/v/@jungherz-de/glasskit-elements?style=flat-square&color=f5a623&label=version" alt="Version"></a>
5
5
  <a href="#"><img src="https://img.shields.io/badge/vanilla_JS-no_dependencies-44cc11?style=flat-square" alt="Vanilla JS"></a>
6
- <a href="#"><img src="https://img.shields.io/badge/components-29-7ec8e3?style=flat-square" alt="29 Components"></a>
6
+ <a href="#"><img src="https://img.shields.io/badge/components-33-7ec8e3?style=flat-square" alt="33 Components"></a>
7
7
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="MIT License"></a>
8
- <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/changelog-v1.13.0-lightgrey?style=flat-square" alt="Changelog"></a>
8
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/changelog-v1.15.0-lightgrey?style=flat-square" alt="Changelog"></a>
9
9
  <a href="https://www.npmjs.com/package/@jungherz-de/glasskit-elements"><img src="https://img.shields.io/badge/npm-%40jungherz--de%2Fglasskit--elements-cb3837?style=flat-square&logo=npm" alt="npm"></a>
10
10
  </p>
11
11
 
@@ -51,7 +51,7 @@ It is the **app layer** of the GlassKit family — three layers, one design lang
51
51
  | Feature | Details |
52
52
  |---|---|
53
53
  | 🔌 **Shadow DOM** | Style encapsulation via `adoptedStyleSheets` — no CSS leaking |
54
- | 🧩 **29 Components** | Buttons, cards, toggles, modals, accordions, lists, popovers, tab bars (incl. floating + accessory), and more |
54
+ | 🧩 **33 Components** | Buttons, cards, toggles, modals, accordions, lists, popovers, tab bars (incl. floating + accessory), and more |
55
55
  | 🪶 **Lightweight** | 117 KB raw / 92 KB minified / 15 KB gzipped (IIFE bundle), no external dependencies |
56
56
  | 📦 **Three bundle formats** | IIFE for `<script>`, minified IIFE for production, ESM for bundlers & tree-shaking |
57
57
  | 🎛️ **Form Participation** | Input, toggle, checkbox, radio, select — all work natively with `<form>` via `ElementInternals` |
@@ -66,7 +66,7 @@ It is the **app layer** of the GlassKit family — three layers, one design lang
66
66
 
67
67
  ```html
68
68
  <!-- 1. GlassKit CSS -->
69
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit@1.12/glasskit.min.css">
69
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit@1.15/glasskit.min.css">
70
70
 
71
71
  <!-- 2. GlassKit Elements -->
72
72
  <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit-elements/dist/glasskit-elements.min.js"></script>
@@ -89,8 +89,13 @@ import '@jungherz-de/glasskit-elements';
89
89
  // Only import what you need
90
90
  import '@jungherz-de/glasskit-elements/components/glk-button.js';
91
91
  import '@jungherz-de/glasskit-elements/components/glk-toggle.js';
92
+
93
+ // The base classes, for elements of your own (same module the components use)
94
+ import { GlkElement, GlkFormElement } from '@jungherz-de/glasskit-elements/base.js';
92
95
  ```
93
96
 
97
+ The per-component files leave `@jungherz-de/glasskit/glasskit-styles.js` as an external import, so the GlassKit stylesheet exists once — a bundler resolves it from `node_modules`; a build-free project adds it to its import map next to the elements entries. Do not mix the `<script>` bundle with `base.js`: the bundle carries its own copy of the classes, so `instanceof` would fail across the two. With the bundle, take the class from it — `GlassKitElements.GlkElement`, or `import { GlkElement } from '@jungherz-de/glasskit-elements'` for the ESM bundle.
98
+
94
99
  ---
95
100
 
96
101
  ## 🚀 Quick Start
@@ -99,7 +104,7 @@ import '@jungherz-de/glasskit-elements/components/glk-toggle.js';
99
104
  <!DOCTYPE html>
100
105
  <html data-theme="dark">
101
106
  <head>
102
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit@1.12/glasskit.min.css">
107
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit@1.15/glasskit.min.css">
103
108
  <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit-elements/dist/glasskit-elements.min.js"></script>
104
109
  </head>
105
110
  <body>
@@ -124,6 +129,7 @@ import '@jungherz-de/glasskit-elements/components/glk-toggle.js';
124
129
  | `<glk-tab-item>` | Tab bar item | `label`, `active`, `badge` |
125
130
  | `<glk-tab-dock>` | Wrapper for floating tab bar + optional accessory | `accessory-left` |
126
131
  | `<glk-tab-accessory>` | Standalone glass capsule (search, compose…) | `label`, `variant` (accent, success, error), `disabled` |
132
+ | `<glk-steps>` | Progress through a short flow | `steps`, `current`, `label` |
127
133
 
128
134
  ### Content
129
135
 
@@ -135,6 +141,7 @@ import '@jungherz-de/glasskit-elements/components/glk-toggle.js';
135
141
  | `<glk-title>` | Styled heading | — |
136
142
  | `<glk-divider>` | Horizontal divider | — |
137
143
  | `<glk-status>` | Status notice | `message` |
144
+ | `<glk-empty>` | Empty state: icon, title, text, one action | `title`, `text` |
138
145
 
139
146
  ### Buttons
140
147
 
@@ -156,6 +163,7 @@ All form components support `name`, `value`, `disabled` and participate in nativ
156
163
  | `<glk-checkbox>` | Checkbox | `label`, `checked`, `disabled` |
157
164
  | `<glk-radio>` | Radio button | `label`, `name`, `value`, `checked` |
158
165
  | `<glk-range>` | Range slider | `label`, `min`, `max`, `value`, `step` |
166
+ | `<glk-segmented>` | Small exclusive choice as one control; form-associated | `options` (JSON), `value`, `full`, `label`, `name` |
159
167
 
160
168
  ### Feedback & Notifications
161
169
 
@@ -165,6 +173,7 @@ All form components support `name`, `value`, `disabled` and participate in nativ
165
173
  | `<glk-modal>` | Modal dialog | `open`, `title` |
166
174
  | `<glk-toast>` | Auto-dismissing notification | `message`, `variant` (success, error, warning), `duration` |
167
175
  | `<glk-popover>` | Anchored dropdown / menu | `open`, `placement` (top, bottom, start, end) |
176
+ | `<glk-sheet>` | Bottom sheet, the mobile sibling of the modal | `open`, `inline`, `title` |
168
177
 
169
178
  ### Containers
170
179
 
@@ -237,6 +246,33 @@ pages that never load `glasskit.css` still work and your brand file always wins.
237
246
  - **`GlkElement`** base class — handles Shadow DOM setup, theme sync, attribute reflection
238
247
  - **`GlkFormElement`** extends `GlkElement` — adds `ElementInternals` for native form participation
239
248
 
249
+ ### Build your own element
250
+
251
+ Since 1.14.0 both base classes are exported, so a project element inherits the whole setup — open shadow root with GlassKit's stylesheet adopted (`.glass-*` classes work inside), theme wrapper following `data-theme`, listeners re-armed when the element moves, `emit()` for bubbling, composed events:
252
+
253
+ ```js
254
+ import { GlkElement } from '@jungherz-de/glasskit-elements'; // or '…/base.js', or GlassKitElements.GlkElement from the CDN bundle
255
+
256
+ class DemoCounter extends GlkElement {
257
+ static get observedAttributes() { return ['count']; }
258
+ render() {
259
+ this._btn = this.createElement('button', ['glass-btn', 'glass-btn--secondary', 'glass-btn--sm', 'glass-btn--auto']);
260
+ this._wrapper.appendChild(this._btn);
261
+ }
262
+ setupEvents() {
263
+ this._onClick = () => { this.count += 1; this.emit('demo-count', { count: this.count }); };
264
+ this._btn.addEventListener('click', this._onClick);
265
+ }
266
+ teardownEvents() { this._btn?.removeEventListener('click', this._onClick); }
267
+ onAttributeChanged() { this._btn.textContent = `Clicked ${this.count}×`; }
268
+ get count() { return Number(this.getAttribute('count')) || 0; }
269
+ set count(v) { this.setAttribute('count', v); }
270
+ }
271
+ customElements.define('demo-counter', DemoCounter);
272
+ ```
273
+
274
+ Hooks: `render()` builds into `this._wrapper`, `setupEvents()` / `teardownEvents()` run on every connect / disconnect, `onAttributeChanged(name, old, value)` after the first render. `static get displayInline()` → `true` for inline elements; `static get observesLightDom()` → `true` re-runs `projectLightDom()` whenever light-DOM children change. `GlkFormElement` adds `setFormValue()`, `setValidity()`, `resetValue()` / `restoreValue()`.
275
+
240
276
  ---
241
277
 
242
278
  ## 📁 Project Structure
@@ -257,6 +293,7 @@ glasskit-elements/
257
293
  glasskit-elements.js # IIFE bundle (117 KB raw / 18 KB gzipped)
258
294
  glasskit-elements.min.js # IIFE minified (92 KB raw / 15 KB gzipped)
259
295
  glasskit-elements.esm.js # ES module bundle (112 KB raw / 17 KB gzipped)
296
+ components/ # one ESM file per element + base.js (GlkElement, GlkFormElement)
260
297
  index.html # Landing page
261
298
  docs.html # Documentation
262
299
  showcase.html # Interactive showcase
@@ -280,7 +317,7 @@ Requires `adoptedStyleSheets`, `ElementInternals`, and `customElements` v1.
280
317
 
281
318
  ## 🤖 AI / LLM Reference
282
319
 
283
- [`SKILL.md`](SKILL.md) is a tag-based, machine-readable reference for LLMs and AI copilots. It contains copy-paste-ready HTML for all 29 elements, attribute / slot / event tables, composition patterns, and a common-mistakes section. It is the companion to the class-based `SKILL.md` in [GlassKit CSS](https://github.com/JUNGHERZ/GlassKit) — use both together for complete coverage of the glass stack.
320
+ [`SKILL.md`](SKILL.md) is a tag-based, machine-readable reference for LLMs and AI copilots. It contains copy-paste-ready HTML for all 33 elements, attribute / slot / event tables, composition patterns, and a common-mistakes section. It is the companion to the class-based `SKILL.md` in [GlassKit CSS](https://github.com/JUNGHERZ/GlassKit) — use both together for complete coverage of the glass stack.
284
321
 
285
322
  ---
286
323
 
@@ -0,0 +1,253 @@
1
+ import { tokensCss, componentsSheet } from '@jungherz-de/glasskit/glasskit-styles.js';
2
+
3
+ // ── Design Tokens ──
4
+ // The shadow roots deliberately adopt the *components* sheet only. Adopting
5
+ // the full GlassKit sheet would bring its [data-theme] blocks along, and those
6
+ // match the .glk-wrapper below — the tokens would then be re-declared inside
7
+ // every shadow root, where a matching rule always beats an inherited value.
8
+ // A project's own `:root { --gl-color-primary: … }` would never arrive.
9
+ //
10
+ // So the token defaults go on the document once, and every shadow root
11
+ // inherits them like any other custom property. They are wrapped in a cascade
12
+ // layer so an ordinary (unlayered) brand stylesheet wins over them, no matter
13
+ // whether it loads before or after this module.
14
+
15
+ const TOKENS_INJECTED = '__glkDefaultTokensInjected';
16
+
17
+ function injectDefaultTokens() {
18
+ if (typeof document === 'undefined') return; // SSR / non-DOM
19
+ if (globalThis[TOKENS_INJECTED]) return; // another bundle copy did it
20
+ globalThis[TOKENS_INJECTED] = true;
21
+
22
+ const sheet = new CSSStyleSheet();
23
+ sheet.replaceSync(`@layer glasskit-defaults { ${tokensCss} }`);
24
+ // Append — never assign — so an app's own adopted sheets survive.
25
+ document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
26
+ }
27
+
28
+ injectDefaultTokens();
29
+
30
+ // ── Global Theme Sync ──
31
+ // Single MutationObserver that watches data-theme on <html>
32
+ // and notifies all GlkElement instances.
33
+
34
+ const instances = new Set();
35
+
36
+ function getCurrentTheme() {
37
+ return document.documentElement.getAttribute('data-theme') || 'dark';
38
+ }
39
+
40
+ function syncAllThemes() {
41
+ const theme = getCurrentTheme();
42
+ for (const instance of instances) {
43
+ instance._syncTheme(theme);
44
+ }
45
+ }
46
+
47
+ if (typeof window !== 'undefined' && typeof MutationObserver !== 'undefined') {
48
+ const observer = new MutationObserver(syncAllThemes);
49
+ observer.observe(document.documentElement, {
50
+ attributes: true,
51
+ attributeFilter: ['data-theme']
52
+ });
53
+ }
54
+
55
+ // ── Host Stylesheet ──
56
+ // Sets display:block on all custom elements by default.
57
+ // Inline components (badge, avatar) override this.
58
+
59
+ const hostSheet = new CSSStyleSheet();
60
+ hostSheet.replaceSync(`
61
+ :host { display: block; }
62
+ :host([hidden]) { display: none; }
63
+ .glk-wrapper { display: contents; }
64
+ `);
65
+
66
+ const inlineHostSheet = new CSSStyleSheet();
67
+ inlineHostSheet.replaceSync(`
68
+ :host { display: inline-block; }
69
+ :host([hidden]) { display: none; }
70
+ .glk-wrapper { display: contents; }
71
+ `);
72
+
73
+ // ── Base Class ──
74
+
75
+ class GlkElement extends HTMLElement {
76
+
77
+ /** Override in subclass to use inline-block display */
78
+ static get displayInline() { return false; }
79
+
80
+ /**
81
+ * Optional CSSStyleSheet with component-specific host rules, adopted after
82
+ * the shared sheets. Keeps per-component selectors out of the shared sheet
83
+ * so an attribute like [fill] only means something where it is documented.
84
+ */
85
+ static get hostStyles() { return null; }
86
+
87
+ /**
88
+ * Opt in when the component copies light-DOM children into its shadow tree.
89
+ * A MutationObserver then calls projectLightDom() again whenever those
90
+ * children change, so a framework that swaps them keeps the rendered element
91
+ * in step. Without it the copy is made once and silently goes stale.
92
+ */
93
+ static get observesLightDom() { return false; }
94
+
95
+ static get observedAttributes() {
96
+ return [];
97
+ }
98
+
99
+ constructor() {
100
+ super();
101
+ this._initialized = false;
102
+ this._shadow = this.attachShadow({ mode: 'open' });
103
+ const displaySheet = this.constructor.displayInline ? inlineHostSheet : hostSheet;
104
+ const sheets = [componentsSheet, displaySheet];
105
+ const extra = this.constructor.hostStyles;
106
+ if (extra) sheets.push(extra);
107
+ this._shadow.adoptedStyleSheets = sheets;
108
+ }
109
+
110
+ connectedCallback() {
111
+ if (!this._initialized) {
112
+ this._initialized = true;
113
+
114
+ // Create theme wrapper (display:contents makes it layout-transparent)
115
+ this._wrapper = document.createElement('div');
116
+ this._wrapper.className = 'glk-wrapper';
117
+ this._wrapper.setAttribute('data-theme', getCurrentTheme());
118
+ this._shadow.appendChild(this._wrapper);
119
+
120
+ this.render();
121
+ }
122
+
123
+ // Everything below runs on every connect, not just the first. Moving an
124
+ // element in the DOM disconnects and reconnects it, and disconnectedCallback
125
+ // tears all of this down — without re-arming it here a moved element would
126
+ // keep its markup but silently stop reacting.
127
+ this.setupEvents();
128
+ instances.add(this);
129
+
130
+ if (this.constructor.observesLightDom) {
131
+ this._lightDomObserver ??= new MutationObserver(records => this.projectLightDom(records));
132
+ this._lightDomObserver.observe(this, {
133
+ childList: true, subtree: true, characterData: true
134
+ });
135
+ }
136
+ }
137
+
138
+ disconnectedCallback() {
139
+ instances.delete(this);
140
+ this._lightDomObserver?.disconnect();
141
+ this.teardownEvents();
142
+ }
143
+
144
+ attributeChangedCallback(name, oldValue, newValue) {
145
+ if (!this._initialized) return;
146
+ if (oldValue === newValue) return;
147
+ this.onAttributeChanged(name, oldValue, newValue);
148
+ }
149
+
150
+ _syncTheme(theme) {
151
+ if (this._wrapper) {
152
+ this._wrapper.setAttribute('data-theme', theme);
153
+ }
154
+ }
155
+
156
+ /** Subclasses override to build inner DOM inside this._wrapper. */
157
+ render() {}
158
+
159
+ /** Subclasses override to attach event listeners. */
160
+ setupEvents() {}
161
+
162
+ /** Subclasses override to remove event listeners. */
163
+ teardownEvents() {}
164
+
165
+ /** Subclasses override to react to attribute changes. */
166
+ onAttributeChanged(name, oldValue, newValue) {}
167
+
168
+ /**
169
+ * Subclasses that set observesLightDom override this to (re-)copy their
170
+ * light-DOM children into the shadow tree. Runs on every change to those
171
+ * children, so it has to be safe to call repeatedly.
172
+ */
173
+ projectLightDom() {}
174
+
175
+ /**
176
+ * Escape hatch: re-copy the light-DOM children now. The observer covers the
177
+ * ordinary cases; this is for the ones it cannot see, so nobody has to reach
178
+ * into element.shadowRoot.
179
+ */
180
+ refresh() { this.projectLightDom(); }
181
+
182
+ // ── Utility Methods ──
183
+
184
+ getBoolAttr(name) {
185
+ return this.hasAttribute(name);
186
+ }
187
+
188
+ setBoolAttr(name, value) {
189
+ if (value) {
190
+ this.setAttribute(name, '');
191
+ } else {
192
+ this.removeAttribute(name);
193
+ }
194
+ }
195
+
196
+ createElement(tag, classes = [], attrs = {}) {
197
+ const el = document.createElement(tag);
198
+ if (classes.length) el.classList.add(...classes);
199
+ for (const [key, val] of Object.entries(attrs)) {
200
+ el.setAttribute(key, val);
201
+ }
202
+ return el;
203
+ }
204
+
205
+ emit(eventName, detail = null) {
206
+ this.dispatchEvent(new CustomEvent(eventName, {
207
+ bubbles: true,
208
+ composed: true,
209
+ detail
210
+ }));
211
+ }
212
+ }
213
+
214
+ // ── Form-Associated Base Class ──
215
+
216
+ class GlkFormElement extends GlkElement {
217
+
218
+ static formAssociated = true;
219
+
220
+ constructor() {
221
+ super();
222
+ this._internals = this.attachInternals();
223
+ }
224
+
225
+ get form() { return this._internals.form; }
226
+ get validationMessage() { return this._internals.validationMessage; }
227
+ get validity() { return this._internals.validity; }
228
+
229
+ checkValidity() { return this._internals.checkValidity(); }
230
+ reportValidity() { return this._internals.reportValidity(); }
231
+
232
+ formResetCallback() {
233
+ this.resetValue();
234
+ }
235
+
236
+ formStateRestoreCallback(state, mode) {
237
+ this.restoreValue(state);
238
+ }
239
+
240
+ /** Subclasses override. */
241
+ resetValue() {}
242
+ restoreValue(state) {}
243
+
244
+ setFormValue(value) {
245
+ this._internals.setFormValue(value);
246
+ }
247
+
248
+ setValidity(flags, message, anchor) {
249
+ this._internals.setValidity(flags, message, anchor);
250
+ }
251
+ }
252
+
253
+ export { GlkElement, GlkFormElement };
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  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
 
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkAccordion extends GlkElement {
4
5
  render() {
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  const SIZES = ['sm', 'lg'];
4
5
 
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  const VARIANTS = ['primary', 'success', 'error'];
4
5
 
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  const VARIANTS = ['primary', 'secondary', 'tertiary'];
4
5
  const SIZES = ['sm', 'md', 'lg', 'auto'];
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  // <glk-card fill> stretches the visible card to the height of its grid or flex
4
5
  // cell. The host must become a grid for this: it is stretched by the outer
@@ -1,4 +1,5 @@
1
- import { a as GlkFormElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkFormElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  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
 
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkDivider extends GlkElement {
4
5
  render() {
@@ -0,0 +1,53 @@
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
3
+
4
+ // Empty state for lists and result pages. Came back from EhrenPfoten in 1.15.0.
5
+ //
6
+ // Attributes: title, text — an empty one hides its element instead of
7
+ // leaving an empty paragraph
8
+ // Slots: default (icon, with a plain circle as slot fallback), action
9
+ // Parts: empty, icon, title, text, action
10
+
11
+ const FALLBACK_ICON = '<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M8 12h8"/></svg>';
12
+
13
+ class GlkEmpty extends GlkElement {
14
+ static get observedAttributes() { return ['title', 'text']; }
15
+
16
+ render() {
17
+ const root = this.createElement('div', ['glass-empty'], { part: 'empty' });
18
+ const icon = this.createElement('span', ['glass-empty__icon'], { part: 'icon' });
19
+ const iconSlot = document.createElement('slot');
20
+ iconSlot.innerHTML = FALLBACK_ICON;
21
+ icon.appendChild(iconSlot);
22
+ this._titleEl = this.createElement('p', ['glass-empty__title'], { part: 'title' });
23
+ this._textEl = this.createElement('p', ['glass-empty__text'], { part: 'text' });
24
+ const action = this.createElement('div', ['glass-empty__action'], { part: 'action' });
25
+ action.appendChild(this.createElement('slot', [], { name: 'action' }));
26
+ root.append(icon, this._titleEl, this._textEl, action);
27
+ this._wrapper.appendChild(root);
28
+ this._update();
29
+ }
30
+
31
+ _update() {
32
+ const title = this.getAttribute('title') || '';
33
+ const text = this.getAttribute('text') || '';
34
+ this._titleEl.textContent = title;
35
+ this._titleEl.hidden = !title;
36
+ this._textEl.textContent = text;
37
+ this._textEl.hidden = !text;
38
+ }
39
+
40
+ onAttributeChanged() {
41
+ if (this._titleEl) this._update();
42
+ }
43
+
44
+ get text() { return this.getAttribute('text') || ''; }
45
+ set text(v) {
46
+ if (v) this.setAttribute('text', v);
47
+ else this.removeAttribute('text');
48
+ }
49
+ }
50
+
51
+ customElements.define('glk-empty', GlkEmpty);
52
+
53
+ export { GlkEmpty };
@@ -1,4 +1,5 @@
1
- import { a as GlkFormElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkFormElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkInput extends GlkFormElement {
4
5
  static get observedAttributes() {
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  // Module-level override sheet — shared by all instances.
4
5
  // Suppresses the auto-divider when glk-list marks this item as the
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkList extends GlkElement {
4
5
  static get observedAttributes() {
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkModal extends GlkElement {
4
5
  static get observedAttributes() {
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkNav extends GlkElement {
4
5
  render() {
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkPill extends GlkElement {
4
5
  static get observedAttributes() {
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  const PLACEMENTS = ['top', 'bottom', 'start', 'end'];
4
5
 
@@ -1,4 +1,5 @@
1
- import { G as GlkElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  const VARIANTS = ['success', 'error'];
4
5
  const SIZES = ['sm', 'lg'];
@@ -1,4 +1,5 @@
1
- import { a as GlkFormElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkFormElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  // ── Grouping ──
4
5
  // Every <glk-radio> keeps its <input type="radio"> in its own shadow root, and
@@ -1,4 +1,5 @@
1
- import { a as GlkFormElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkFormElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  class GlkRange extends GlkFormElement {
4
5
  static get observedAttributes() {
@@ -1,4 +1,5 @@
1
- import { a as GlkFormElement } from './shared/base-ClsXgLON.js';
1
+ import { GlkFormElement } from './base.js';
2
+ import '@jungherz-de/glasskit/glasskit-styles.js';
2
3
 
3
4
  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