@phcdevworks/spectre-components 0.0.1 → 1.1.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 (62) hide show
  1. package/README.md +113 -40
  2. package/dist/base-2rD8EmdC.d.cts +32 -0
  3. package/dist/base-2rD8EmdC.d.ts +32 -0
  4. package/dist/button.cjs +295 -170
  5. package/dist/button.cjs.map +1 -1
  6. package/dist/button.d.cts +30 -61
  7. package/dist/button.d.ts +30 -61
  8. package/dist/button.js +296 -171
  9. package/dist/button.js.map +1 -1
  10. package/dist/checkbox.cjs +286 -71
  11. package/dist/checkbox.cjs.map +1 -1
  12. package/dist/checkbox.d.cts +38 -43
  13. package/dist/checkbox.d.ts +38 -43
  14. package/dist/checkbox.js +287 -72
  15. package/dist/checkbox.js.map +1 -1
  16. package/dist/fieldset.cjs +233 -88
  17. package/dist/fieldset.cjs.map +1 -1
  18. package/dist/fieldset.d.cts +23 -40
  19. package/dist/fieldset.d.ts +23 -40
  20. package/dist/fieldset.js +233 -88
  21. package/dist/fieldset.js.map +1 -1
  22. package/dist/form-iI7vV-3W.d.cts +6 -0
  23. package/dist/form-iI7vV-3W.d.ts +6 -0
  24. package/dist/index.cjs +564 -1029
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +5 -2
  27. package/dist/index.d.ts +5 -2
  28. package/dist/index.js +566 -1030
  29. package/dist/index.js.map +1 -1
  30. package/dist/input.cjs +232 -119
  31. package/dist/input.cjs.map +1 -1
  32. package/dist/input.d.cts +52 -68
  33. package/dist/input.d.ts +52 -68
  34. package/dist/input.js +232 -119
  35. package/dist/input.js.map +1 -1
  36. package/dist/label.cjs +232 -73
  37. package/dist/label.cjs.map +1 -1
  38. package/dist/label.d.cts +13 -22
  39. package/dist/label.d.ts +13 -22
  40. package/dist/label.js +232 -73
  41. package/dist/label.js.map +1 -1
  42. package/dist/projectable-BzDQ4xp_.d.cts +17 -0
  43. package/dist/projectable-s3SgvjGX.d.ts +17 -0
  44. package/dist/radio.cjs +286 -71
  45. package/dist/radio.cjs.map +1 -1
  46. package/dist/radio.d.cts +38 -43
  47. package/dist/radio.d.ts +38 -43
  48. package/dist/radio.js +287 -72
  49. package/dist/radio.js.map +1 -1
  50. package/dist/select.cjs +292 -163
  51. package/dist/select.cjs.map +1 -1
  52. package/dist/select.d.cts +35 -58
  53. package/dist/select.d.ts +35 -58
  54. package/dist/select.js +293 -163
  55. package/dist/select.js.map +1 -1
  56. package/dist/textarea.cjs +191 -290
  57. package/dist/textarea.cjs.map +1 -1
  58. package/dist/textarea.d.cts +41 -58
  59. package/dist/textarea.d.ts +41 -58
  60. package/dist/textarea.js +191 -290
  61. package/dist/textarea.js.map +1 -1
  62. package/package.json +13 -12
package/dist/index.cjs CHANGED
@@ -6,6 +6,265 @@ var spectreUi = require('@phcdevworks/spectre-ui');
6
6
  var live_js = require('lit/directives/live.js');
7
7
 
8
8
  // src/components/button/sp-button.ts
9
+ var SpectreBaseElement = class extends lit.LitElement {
10
+ constructor() {
11
+ super(...arguments);
12
+ this._ariaLabel = null;
13
+ this._ariaLabelledBy = null;
14
+ this._ariaDescribedBy = null;
15
+ this._title = "";
16
+ this._id = "";
17
+ }
18
+ get ariaLabel() {
19
+ return this._ariaLabel;
20
+ }
21
+ set ariaLabel(value) {
22
+ if (this._ariaLabel === value) {
23
+ return;
24
+ }
25
+ this._ariaLabel = value;
26
+ this._removeHostAttribute("aria-label");
27
+ this.requestUpdate();
28
+ }
29
+ get ariaLabelledBy() {
30
+ return this._ariaLabelledBy;
31
+ }
32
+ set ariaLabelledBy(value) {
33
+ if (this._ariaLabelledBy === value) {
34
+ return;
35
+ }
36
+ this._ariaLabelledBy = value;
37
+ this._removeHostAttribute("aria-labelledby");
38
+ this.requestUpdate();
39
+ }
40
+ get ariaDescribedBy() {
41
+ return this._ariaDescribedBy;
42
+ }
43
+ set ariaDescribedBy(value) {
44
+ if (this._ariaDescribedBy === value) {
45
+ return;
46
+ }
47
+ this._ariaDescribedBy = value;
48
+ this._removeHostAttribute("aria-describedby");
49
+ this.requestUpdate();
50
+ }
51
+ get title() {
52
+ return this._title;
53
+ }
54
+ set title(value) {
55
+ const normalizedValue = value ?? "";
56
+ if (this._title === normalizedValue) {
57
+ return;
58
+ }
59
+ this._title = normalizedValue;
60
+ this._removeHostAttribute("title");
61
+ this.requestUpdate();
62
+ }
63
+ get id() {
64
+ return this._id;
65
+ }
66
+ set id(value) {
67
+ const normalizedValue = value ?? "";
68
+ if (this._id === normalizedValue) {
69
+ return;
70
+ }
71
+ this._id = normalizedValue;
72
+ this._removeHostAttribute("id");
73
+ this.requestUpdate();
74
+ }
75
+ // Spectre components intentionally render in light DOM so the global
76
+ // `@phcdevworks/spectre-ui` styling contract can apply directly.
77
+ createRenderRoot() {
78
+ return this;
79
+ }
80
+ connectedCallback() {
81
+ super.connectedCallback();
82
+ const proxiedAttributes = [
83
+ "id",
84
+ "title",
85
+ "aria-label",
86
+ "aria-labelledby",
87
+ "aria-describedby"
88
+ ];
89
+ proxiedAttributes.forEach((attr) => {
90
+ const value = super.getAttribute(attr);
91
+ if (value !== null) {
92
+ this.setAttribute(attr, value);
93
+ }
94
+ });
95
+ }
96
+ getAttribute(qualifiedName) {
97
+ switch (qualifiedName) {
98
+ case "id":
99
+ return this.id || null;
100
+ case "title":
101
+ return this.title || null;
102
+ case "aria-label":
103
+ return this.ariaLabel;
104
+ case "aria-labelledby":
105
+ return this.ariaLabelledBy;
106
+ case "aria-describedby":
107
+ return this.ariaDescribedBy;
108
+ default:
109
+ return super.getAttribute(qualifiedName);
110
+ }
111
+ }
112
+ hasAttribute(qualifiedName) {
113
+ switch (qualifiedName) {
114
+ case "id":
115
+ return this.id !== "";
116
+ case "title":
117
+ return this.title !== "";
118
+ case "aria-label":
119
+ return this.ariaLabel !== null;
120
+ case "aria-labelledby":
121
+ return this.ariaLabelledBy !== null;
122
+ case "aria-describedby":
123
+ return this.ariaDescribedBy !== null;
124
+ default:
125
+ return super.hasAttribute(qualifiedName);
126
+ }
127
+ }
128
+ setAttribute(qualifiedName, value) {
129
+ switch (qualifiedName) {
130
+ case "id":
131
+ this.id = value;
132
+ break;
133
+ case "title":
134
+ this.title = value;
135
+ break;
136
+ case "aria-label":
137
+ this.ariaLabel = value;
138
+ break;
139
+ case "aria-labelledby":
140
+ this.ariaLabelledBy = value;
141
+ break;
142
+ case "aria-describedby":
143
+ this.ariaDescribedBy = value;
144
+ break;
145
+ default:
146
+ super.setAttribute(qualifiedName, value);
147
+ }
148
+ }
149
+ removeAttribute(qualifiedName) {
150
+ switch (qualifiedName) {
151
+ case "id":
152
+ this.id = "";
153
+ break;
154
+ case "title":
155
+ this.title = "";
156
+ break;
157
+ case "aria-label":
158
+ this.ariaLabel = null;
159
+ break;
160
+ case "aria-labelledby":
161
+ this.ariaLabelledBy = null;
162
+ break;
163
+ case "aria-describedby":
164
+ this.ariaDescribedBy = null;
165
+ break;
166
+ default:
167
+ super.removeAttribute(qualifiedName);
168
+ }
169
+ }
170
+ _removeHostAttribute(name) {
171
+ const host = this;
172
+ if (HTMLElement.prototype.hasAttribute.call(host, name)) {
173
+ HTMLElement.prototype.removeAttribute.call(host, name);
174
+ }
175
+ }
176
+ get forwardedAriaLabel() {
177
+ const value = this.ariaLabel?.trim();
178
+ return value ? value : void 0;
179
+ }
180
+ get forwardedAriaLabelledBy() {
181
+ const value = this.ariaLabelledBy?.trim();
182
+ return value ? value : void 0;
183
+ }
184
+ get forwardedAriaDescribedBy() {
185
+ const value = this.ariaDescribedBy?.trim();
186
+ return value ? value : void 0;
187
+ }
188
+ };
189
+ SpectreBaseElement.properties = {};
190
+
191
+ // src/utils/dom.ts
192
+ function hasMeaningfulContent(nodes) {
193
+ return nodes.some((node) => {
194
+ if (node.nodeType === Node.ELEMENT_NODE) {
195
+ return true;
196
+ }
197
+ if (node.nodeType === Node.TEXT_NODE) {
198
+ return (node.textContent?.trim().length ?? 0) > 0;
199
+ }
200
+ return false;
201
+ });
202
+ }
203
+
204
+ // src/utils/projectable.ts
205
+ var SpectreProjectableElement = class extends SpectreBaseElement {
206
+ constructor() {
207
+ super(...arguments);
208
+ this.projectedContent = [];
209
+ }
210
+ get hasProjectedContent() {
211
+ return hasMeaningfulContent(this.projectedContent);
212
+ }
213
+ connectedCallback() {
214
+ super.connectedCallback();
215
+ this.syncProjectedContent();
216
+ this.startContentObserver();
217
+ }
218
+ disconnectedCallback() {
219
+ this.stopContentObserver();
220
+ super.disconnectedCallback();
221
+ }
222
+ update(changedProperties) {
223
+ this.stopContentObserver();
224
+ super.update(changedProperties);
225
+ this.startContentObserver();
226
+ }
227
+ syncProjectedContent() {
228
+ const nextProjectedContent = [];
229
+ const sourceNodes = [
230
+ ...this.childNodes,
231
+ ...this.getContentContainer()?.childNodes ?? []
232
+ ];
233
+ sourceNodes.forEach((node) => {
234
+ if (!this.isInternalNode(node) && !nextProjectedContent.includes(node)) {
235
+ nextProjectedContent.push(node);
236
+ }
237
+ });
238
+ const hasChanged = nextProjectedContent.length !== this.projectedContent.length || nextProjectedContent.some((node, index) => node !== this.projectedContent[index]);
239
+ if (hasChanged) {
240
+ this.projectedContent = nextProjectedContent;
241
+ }
242
+ return hasChanged;
243
+ }
244
+ startContentObserver() {
245
+ if (this.contentObserver) {
246
+ return;
247
+ }
248
+ this.contentObserver = new MutationObserver((mutations) => {
249
+ const isInternalMovement = mutations.every(
250
+ (mutation) => [...mutation.removedNodes].every(
251
+ (node) => this.isInternalNode(node) || this.contains(node)
252
+ ) && [...mutation.addedNodes].every((node) => this.isInternalNode(node))
253
+ );
254
+ if (isInternalMovement) {
255
+ return;
256
+ }
257
+ if (this.syncProjectedContent()) {
258
+ this.requestUpdate();
259
+ }
260
+ });
261
+ this.contentObserver.observe(this, { childList: true });
262
+ }
263
+ stopContentObserver() {
264
+ this.contentObserver?.disconnect();
265
+ this.contentObserver = void 0;
266
+ }
267
+ };
9
268
  var spectreButtonVariants = [
10
269
  "primary",
11
270
  "secondary",
@@ -26,23 +285,9 @@ function isButtonSize(value) {
26
285
  function isButtonType(value) {
27
286
  return spectreButtonTypes.includes(value);
28
287
  }
29
- function hasMeaningfulContent(nodes) {
30
- return nodes.some((node) => {
31
- if (node.nodeType === Node.ELEMENT_NODE) {
32
- return true;
33
- }
34
- if (node.nodeType === Node.TEXT_NODE) {
35
- return (node.textContent?.trim().length ?? 0) > 0;
36
- }
37
- return false;
38
- });
39
- }
40
- var SpectreButtonElement = class extends lit.LitElement {
288
+ var SpectreButtonElement = class extends SpectreProjectableElement {
41
289
  constructor() {
42
290
  super(...arguments);
43
- this.ariaLabel = null;
44
- this.ariaLabelledBy = null;
45
- this.ariaDescribedBy = null;
46
291
  this.autofocus = false;
47
292
  this.disabled = false;
48
293
  this.fullWidth = false;
@@ -50,68 +295,19 @@ var SpectreButtonElement = class extends lit.LitElement {
50
295
  this.loadingLabel = "Loading";
51
296
  this.pill = false;
52
297
  this.size = "md";
53
- this.title = "";
54
298
  this.type = "button";
55
299
  this.variant = "primary";
56
- // Native slot projection is a Shadow DOM feature, so in light DOM we keep
57
- // host-provided content reactive by tracking and reusing the host nodes.
58
- this.projectedContent = [];
59
- }
60
- get id() {
61
- return this._id ?? "";
62
- }
63
- set id(value) {
64
- if ((this._id ?? "") === value) {
65
- return;
66
- }
67
- this._id = value;
68
- const host = this;
69
- if (HTMLElement.prototype.hasAttribute.call(host, "id")) {
70
- HTMLElement.prototype.removeAttribute.call(host, "id");
71
- }
72
- this.requestUpdate();
73
- }
74
- createRenderRoot() {
75
- return this;
76
- }
77
- connectedCallback() {
78
- super.connectedCallback();
79
- const hostId = super.getAttribute("id");
80
- if (hostId !== null) {
81
- this.id = hostId;
82
- }
83
- this.syncProjectedContent();
84
- this.startContentObserver();
85
- }
86
- getAttribute(qualifiedName) {
87
- if (qualifiedName === "id") {
88
- return this.id || null;
89
- }
90
- return super.getAttribute(qualifiedName);
91
- }
92
- hasAttribute(qualifiedName) {
93
- if (qualifiedName === "id") {
94
- return this.id !== "";
95
- }
96
- return super.hasAttribute(qualifiedName);
300
+ this.value = "";
97
301
  }
98
- setAttribute(qualifiedName, value) {
99
- if (qualifiedName === "id") {
100
- this.id = value;
101
- return;
102
- }
103
- super.setAttribute(qualifiedName, value);
302
+ getContentContainer() {
303
+ return this.querySelector("[data-sp-button-native]");
104
304
  }
105
- removeAttribute(qualifiedName) {
106
- if (qualifiedName === "id") {
107
- this.id = "";
108
- return;
305
+ isInternalNode(node) {
306
+ if (node.nodeType !== Node.ELEMENT_NODE) {
307
+ return false;
109
308
  }
110
- super.removeAttribute(qualifiedName);
111
- }
112
- disconnectedCallback() {
113
- this.stopContentObserver();
114
- super.disconnectedCallback();
309
+ const el = node;
310
+ return el.hasAttribute("data-sp-button-native") || el.hasAttribute("data-sp-button-loading-label") || el.hasAttribute("data-sp-button-label-fallback");
115
311
  }
116
312
  willUpdate(changedProperties) {
117
313
  if (changedProperties.has("variant") && !isButtonVariant(this.variant)) {
@@ -128,11 +324,9 @@ var SpectreButtonElement = class extends lit.LitElement {
128
324
  this.loadingLabel = "Loading";
129
325
  }
130
326
  }
131
- }
132
- update(changedProperties) {
133
- this.stopContentObserver();
134
- super.update(changedProperties);
135
- this.startContentObserver();
327
+ if (changedProperties.has("value") && this.value == null) {
328
+ this.value = "";
329
+ }
136
330
  }
137
331
  get buttonClasses() {
138
332
  return spectreUi.getButtonClasses({
@@ -147,118 +341,50 @@ var SpectreButtonElement = class extends lit.LitElement {
147
341
  get isDisabled() {
148
342
  return this.disabled || this.loading;
149
343
  }
150
- get hasProjectedContent() {
151
- return hasMeaningfulContent(this.projectedContent);
152
- }
153
344
  get visibleLabelFallback() {
154
345
  const trimmedLabel = this.label?.trim();
155
346
  return trimmedLabel ? trimmedLabel : void 0;
156
347
  }
157
- get forwardedAriaLabel() {
158
- const ariaLabel = this.ariaLabel?.trim();
159
- return ariaLabel ? ariaLabel : void 0;
160
- }
161
- get forwardedAriaLabelledBy() {
162
- const ariaLabelledBy = this.ariaLabelledBy?.trim();
163
- return ariaLabelledBy ? ariaLabelledBy : void 0;
164
- }
165
- get forwardedAriaDescribedBy() {
166
- const ariaDescribedBy = this.ariaDescribedBy?.trim();
167
- return ariaDescribedBy ? ariaDescribedBy : void 0;
168
- }
169
- startContentObserver() {
170
- if (this.contentObserver) {
171
- return;
172
- }
173
- this.contentObserver = new MutationObserver((mutations) => {
174
- const isInternalMovement = mutations.every((mutation) => {
175
- return Array.from(mutation.removedNodes).every(
176
- (node) => this.isInternalButtonNode(node) || this.contains(node)
177
- ) && Array.from(mutation.addedNodes).every((node) => this.isInternalButtonNode(node));
178
- });
179
- if (isInternalMovement) {
180
- return;
181
- }
182
- if (this.syncProjectedContent()) {
183
- this.requestUpdate();
184
- }
185
- });
186
- this.contentObserver.observe(this, {
187
- childList: true
188
- });
189
- }
190
- stopContentObserver() {
191
- this.contentObserver?.disconnect();
192
- this.contentObserver = void 0;
193
- }
194
- syncProjectedContent() {
195
- const nextProjectedContent = [];
196
- Array.from(this.childNodes).forEach((node) => {
197
- if (this.isInternalButtonNode(node)) {
198
- this.projectedContent.forEach((pNode) => {
199
- if (pNode.parentNode !== this && this.contains(pNode)) {
200
- nextProjectedContent.push(pNode);
201
- }
202
- });
203
- } else {
204
- nextProjectedContent.push(node);
205
- }
206
- });
207
- const hasChanged = nextProjectedContent.length !== this.projectedContent.length || nextProjectedContent.some((node, index) => node !== this.projectedContent[index]);
208
- if (hasChanged) {
209
- this.projectedContent = nextProjectedContent;
210
- }
211
- return hasChanged;
212
- }
213
- isInternalButtonNode(node) {
214
- return node.nodeType === Node.ELEMENT_NODE && node.hasAttribute("data-sp-button-native");
215
- }
216
- get nativeButton() {
217
- return this.querySelector("[data-sp-button-native]");
218
- }
219
348
  focus(options) {
220
- this.nativeButton?.focus(options);
349
+ this.getContentContainer()?.focus(options);
221
350
  }
222
351
  blur() {
223
- this.nativeButton?.blur();
352
+ this.getContentContainer()?.blur();
224
353
  }
225
354
  renderButtonContent() {
226
355
  if (this.loading) {
227
- return this.loadingLabel;
356
+ return lit.html`<span data-sp-button-loading-label>${this.loadingLabel}</span>`;
228
357
  }
229
358
  if (this.hasProjectedContent) {
230
359
  return this.projectedContent;
231
360
  }
232
- return this.visibleLabelFallback ?? "";
361
+ return this.visibleLabelFallback ? lit.html`<span data-sp-button-label-fallback>${this.visibleLabelFallback}</span>` : lit.nothing;
233
362
  }
234
363
  render() {
235
- return lit.html`
236
- <button
237
- aria-busy=${this.loading ? "true" : "false"}
238
- aria-describedby=${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}
239
- aria-label=${ifDefined_js.ifDefined(this.forwardedAriaLabel)}
240
- aria-labelledby=${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}
241
- ?autofocus=${this.autofocus}
242
- class=${this.buttonClasses}
243
- data-sp-button-native
244
- ?disabled=${this.isDisabled}
245
- id=${ifDefined_js.ifDefined(this.id || void 0)}
246
- name=${ifDefined_js.ifDefined(this.name)}
247
- title=${ifDefined_js.ifDefined(this.title || void 0)}
248
- type=${this.type}
249
- value=${ifDefined_js.ifDefined(this.value)}
250
- >
251
- ${this.renderButtonContent() || lit.nothing}
252
- </button>
253
- `;
364
+ return lit.html`<button
365
+ aria-busy="${this.loading ? "true" : "false"}"
366
+ aria-describedby="${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}"
367
+ aria-label="${ifDefined_js.ifDefined(this.forwardedAriaLabel)}"
368
+ aria-labelledby="${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}"
369
+ ?autofocus="${this.autofocus}"
370
+ class="${this.buttonClasses}"
371
+ data-sp-button-native
372
+ ?disabled="${this.isDisabled}"
373
+ form="${ifDefined_js.ifDefined(this.form || void 0)}"
374
+ id="${ifDefined_js.ifDefined(this.id || void 0)}"
375
+ name="${ifDefined_js.ifDefined(this.name || void 0)}"
376
+ title="${ifDefined_js.ifDefined(this.title || void 0)}"
377
+ type="${this.type}"
378
+ value="${ifDefined_js.ifDefined(this.value || void 0)}"
379
+ >
380
+ ${this.renderButtonContent()}
381
+ </button>`;
254
382
  }
255
383
  };
256
384
  SpectreButtonElement.properties = {
257
- ariaLabel: { attribute: "aria-label", type: String },
258
- ariaLabelledBy: { attribute: "aria-labelledby", type: String },
259
- ariaDescribedBy: { attribute: "aria-describedby", type: String },
260
385
  autofocus: { type: Boolean, reflect: true },
261
386
  disabled: { type: Boolean, reflect: true },
387
+ form: { type: String },
262
388
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
263
389
  label: { type: String, reflect: true },
264
390
  loading: { type: Boolean, reflect: true },
@@ -266,10 +392,9 @@ SpectreButtonElement.properties = {
266
392
  name: { type: String, reflect: true },
267
393
  pill: { type: Boolean, reflect: true },
268
394
  size: { type: String, reflect: true },
269
- title: { type: String, reflect: true },
270
395
  type: { type: String, reflect: true },
271
396
  variant: { type: String, reflect: true },
272
- value: { type: String, reflect: true }
397
+ value: { type: String }
273
398
  };
274
399
  function defineSpectreButton(tagName = "sp-button") {
275
400
  const existingElement = customElements.get(tagName);
@@ -279,6 +404,10 @@ function defineSpectreButton(tagName = "sp-button") {
279
404
  customElements.define(tagName, SpectreButtonElement);
280
405
  return SpectreButtonElement;
281
406
  }
407
+ var spectreInputSizes = ["sm", "md", "lg"];
408
+ function isInputSize(value) {
409
+ return spectreInputSizes.includes(value);
410
+ }
282
411
  var spectreInputTypes = [
283
412
  "text",
284
413
  "email",
@@ -293,19 +422,18 @@ var spectreInputTypes = [
293
422
  "time",
294
423
  "week"
295
424
  ];
296
- var spectreInputSizes = ["sm", "md", "lg"];
297
425
  function isInputType(value) {
298
426
  return spectreInputTypes.includes(value);
299
427
  }
300
- function isInputSize(value) {
301
- return spectreInputSizes.includes(value);
428
+ function normalizeInt(value, fallback, min = 0) {
429
+ if (value == null || typeof value !== "number" || !Number.isInteger(value) || value < min) {
430
+ return fallback;
431
+ }
432
+ return value;
302
433
  }
303
- var SpectreInputElement = class extends lit.LitElement {
434
+ var SpectreInputElement = class extends SpectreBaseElement {
304
435
  constructor() {
305
436
  super(...arguments);
306
- this.ariaLabel = null;
307
- this.ariaLabelledBy = null;
308
- this.ariaDescribedBy = null;
309
437
  this.autofocus = false;
310
438
  this.disabled = false;
311
439
  this.fullWidth = false;
@@ -316,60 +444,9 @@ var SpectreInputElement = class extends lit.LitElement {
316
444
  this.required = false;
317
445
  this.size = "md";
318
446
  this.success = false;
319
- this.title = "";
320
447
  this.type = "text";
321
448
  this.value = "";
322
449
  }
323
- get id() {
324
- return this._id ?? "";
325
- }
326
- set id(value) {
327
- if ((this._id ?? "") === value) {
328
- return;
329
- }
330
- this._id = value;
331
- const host = this;
332
- if (HTMLElement.prototype.hasAttribute.call(host, "id")) {
333
- HTMLElement.prototype.removeAttribute.call(host, "id");
334
- }
335
- this.requestUpdate();
336
- }
337
- createRenderRoot() {
338
- return this;
339
- }
340
- connectedCallback() {
341
- super.connectedCallback();
342
- const hostId = super.getAttribute("id");
343
- if (hostId !== null) {
344
- this.id = hostId;
345
- }
346
- }
347
- getAttribute(qualifiedName) {
348
- if (qualifiedName === "id") {
349
- return this.id || null;
350
- }
351
- return super.getAttribute(qualifiedName);
352
- }
353
- hasAttribute(qualifiedName) {
354
- if (qualifiedName === "id") {
355
- return this.id !== "";
356
- }
357
- return super.hasAttribute(qualifiedName);
358
- }
359
- setAttribute(qualifiedName, value) {
360
- if (qualifiedName === "id") {
361
- this.id = value;
362
- return;
363
- }
364
- super.setAttribute(qualifiedName, value);
365
- }
366
- removeAttribute(qualifiedName) {
367
- if (qualifiedName === "id") {
368
- this.id = "";
369
- return;
370
- }
371
- super.removeAttribute(qualifiedName);
372
- }
373
450
  willUpdate(changedProperties) {
374
451
  if (changedProperties.has("size") && !isInputSize(this.size)) {
375
452
  this.size = "md";
@@ -381,14 +458,10 @@ var SpectreInputElement = class extends lit.LitElement {
381
458
  this.value = "";
382
459
  }
383
460
  if (changedProperties.has("maxlength")) {
384
- if (this.maxlength == null || !Number.isInteger(this.maxlength) || this.maxlength < 0) {
385
- this.maxlength = void 0;
386
- }
461
+ this.maxlength = normalizeInt(this.maxlength, void 0);
387
462
  }
388
463
  if (changedProperties.has("minlength")) {
389
- if (this.minlength == null || !Number.isInteger(this.minlength) || this.minlength < 0) {
390
- this.minlength = void 0;
391
- }
464
+ this.minlength = normalizeInt(this.minlength, void 0);
392
465
  }
393
466
  }
394
467
  get inputClasses() {
@@ -405,18 +478,6 @@ var SpectreInputElement = class extends lit.LitElement {
405
478
  get nativeInput() {
406
479
  return this.querySelector("[data-sp-input-native]");
407
480
  }
408
- get forwardedAriaLabel() {
409
- const ariaLabel = this.ariaLabel?.trim();
410
- return ariaLabel ? ariaLabel : void 0;
411
- }
412
- get forwardedAriaLabelledBy() {
413
- const ariaLabelledBy = this.ariaLabelledBy?.trim();
414
- return ariaLabelledBy ? ariaLabelledBy : void 0;
415
- }
416
- get forwardedAriaDescribedBy() {
417
- const ariaDescribedBy = this.ariaDescribedBy?.trim();
418
- return ariaDescribedBy ? ariaDescribedBy : void 0;
419
- }
420
481
  handleInput(event) {
421
482
  const input = event.currentTarget;
422
483
  this.value = input.value;
@@ -432,62 +493,58 @@ var SpectreInputElement = class extends lit.LitElement {
432
493
  this.nativeInput?.blur();
433
494
  }
434
495
  render() {
435
- return lit.html`
436
- <input
437
- aria-busy=${this.loading ? "true" : "false"}
438
- aria-describedby=${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}
439
- aria-invalid=${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}
440
- aria-label=${ifDefined_js.ifDefined(this.forwardedAriaLabel)}
441
- aria-labelledby=${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}
442
- autocomplete=${ifDefined_js.ifDefined(this.autocomplete)}
443
- ?autofocus=${this.autofocus}
444
- class=${this.inputClasses}
445
- data-sp-input-native
446
- ?disabled=${this.isDisabled}
447
- ?readonly=${this.readonly}
448
- ?required=${this.required}
449
- id=${ifDefined_js.ifDefined(this.id || void 0)}
450
- inputmode=${ifDefined_js.ifDefined(this.inputmode)}
451
- max=${ifDefined_js.ifDefined(this.max)}
452
- maxlength=${ifDefined_js.ifDefined(this.maxlength)}
453
- min=${ifDefined_js.ifDefined(this.min)}
454
- minlength=${ifDefined_js.ifDefined(this.minlength)}
455
- name=${ifDefined_js.ifDefined(this.name)}
456
- placeholder=${ifDefined_js.ifDefined(this.placeholder)}
457
- step=${ifDefined_js.ifDefined(this.step)}
458
- title=${ifDefined_js.ifDefined(this.title || void 0)}
459
- type=${this.type}
460
- .value=${live_js.live(this.value)}
461
- @change=${this.handleChange}
462
- @input=${this.handleInput}
463
- />
464
- `;
496
+ return lit.html`<input
497
+ aria-busy="${this.loading ? "true" : "false"}"
498
+ aria-describedby="${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}"
499
+ aria-invalid="${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}"
500
+ aria-label="${ifDefined_js.ifDefined(this.forwardedAriaLabel)}"
501
+ aria-labelledby="${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}"
502
+ autocomplete="${ifDefined_js.ifDefined(this.autocomplete || void 0)}"
503
+ ?autofocus="${this.autofocus}"
504
+ class="${this.inputClasses}"
505
+ data-sp-input-native
506
+ ?disabled="${this.isDisabled}"
507
+ form="${ifDefined_js.ifDefined(this.form || void 0)}"
508
+ ?readonly="${this.readonly}"
509
+ ?required="${this.required}"
510
+ id="${ifDefined_js.ifDefined(this.id || void 0)}"
511
+ inputmode="${ifDefined_js.ifDefined(this.inputmode || void 0)}"
512
+ max="${ifDefined_js.ifDefined(this.max || void 0)}"
513
+ maxlength="${ifDefined_js.ifDefined(this.maxlength)}"
514
+ min="${ifDefined_js.ifDefined(this.min || void 0)}"
515
+ minlength="${ifDefined_js.ifDefined(this.minlength)}"
516
+ name="${ifDefined_js.ifDefined(this.name || void 0)}"
517
+ placeholder="${ifDefined_js.ifDefined(this.placeholder || void 0)}"
518
+ step="${ifDefined_js.ifDefined(this.step || void 0)}"
519
+ title="${ifDefined_js.ifDefined(this.title || void 0)}"
520
+ type="${this.type}"
521
+ .value="${live_js.live(this.value)}"
522
+ @change="${this.handleChange}"
523
+ @input="${this.handleInput}"
524
+ />`;
465
525
  }
466
526
  };
467
527
  SpectreInputElement.properties = {
468
- ariaLabel: { attribute: "aria-label", type: String },
469
- ariaLabelledBy: { attribute: "aria-labelledby", type: String },
470
- ariaDescribedBy: { attribute: "aria-describedby", type: String },
471
- autocomplete: { type: String },
528
+ autocomplete: { type: String, reflect: true },
472
529
  autofocus: { type: Boolean, reflect: true },
473
530
  disabled: { type: Boolean, reflect: true },
531
+ form: { type: String },
474
532
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
475
- inputmode: { type: String },
533
+ inputmode: { type: String, reflect: true },
476
534
  invalid: { type: Boolean, reflect: true },
477
535
  loading: { type: Boolean, reflect: true },
478
- max: { type: String },
479
- maxlength: { type: Number },
480
- min: { type: String },
481
- minlength: { type: Number },
482
- name: { type: String },
536
+ max: { type: String, reflect: true },
537
+ maxlength: { type: Number, reflect: true },
538
+ min: { type: String, reflect: true },
539
+ minlength: { type: Number, reflect: true },
540
+ name: { type: String, reflect: true },
483
541
  pill: { type: Boolean, reflect: true },
484
- placeholder: { type: String },
542
+ placeholder: { type: String, reflect: true },
485
543
  readonly: { type: Boolean, reflect: true },
486
544
  required: { type: Boolean, reflect: true },
487
545
  size: { type: String, reflect: true },
488
- step: { type: String },
546
+ step: { type: String, reflect: true },
489
547
  success: { type: Boolean, reflect: true },
490
- title: { type: String, reflect: true },
491
548
  type: { type: String, reflect: true },
492
549
  value: { type: String }
493
550
  };
@@ -500,12 +557,9 @@ function defineSpectreInput(tagName = "sp-input") {
500
557
  return SpectreInputElement;
501
558
  }
502
559
  var DEFAULT_ROWS = 2;
503
- var SpectreTextareaElement = class extends lit.LitElement {
560
+ var SpectreTextareaElement = class extends SpectreBaseElement {
504
561
  constructor() {
505
562
  super(...arguments);
506
- this.ariaLabel = null;
507
- this.ariaLabelledBy = null;
508
- this.ariaDescribedBy = null;
509
563
  this.autofocus = false;
510
564
  this.disabled = false;
511
565
  this.fullWidth = false;
@@ -517,80 +571,23 @@ var SpectreTextareaElement = class extends lit.LitElement {
517
571
  this.rows = DEFAULT_ROWS;
518
572
  this.size = "md";
519
573
  this.success = false;
520
- this.title = "";
521
574
  this.value = "";
522
575
  }
523
- get id() {
524
- return this._id ?? "";
525
- }
526
- set id(value) {
527
- if ((this._id ?? "") === value) {
528
- return;
529
- }
530
- this._id = value;
531
- const host = this;
532
- if (HTMLElement.prototype.hasAttribute.call(host, "id")) {
533
- HTMLElement.prototype.removeAttribute.call(host, "id");
534
- }
535
- this.requestUpdate();
536
- }
537
- createRenderRoot() {
538
- return this;
539
- }
540
- connectedCallback() {
541
- super.connectedCallback();
542
- const hostId = super.getAttribute("id");
543
- if (hostId !== null) {
544
- this.id = hostId;
545
- }
546
- }
547
- getAttribute(qualifiedName) {
548
- if (qualifiedName === "id") {
549
- return this.id || null;
550
- }
551
- return super.getAttribute(qualifiedName);
552
- }
553
- hasAttribute(qualifiedName) {
554
- if (qualifiedName === "id") {
555
- return this.id !== "";
556
- }
557
- return super.hasAttribute(qualifiedName);
558
- }
559
- setAttribute(qualifiedName, value) {
560
- if (qualifiedName === "id") {
561
- this.id = value;
562
- return;
563
- }
564
- super.setAttribute(qualifiedName, value);
565
- }
566
- removeAttribute(qualifiedName) {
567
- if (qualifiedName === "id") {
568
- this.id = "";
569
- return;
570
- }
571
- super.removeAttribute(qualifiedName);
572
- }
573
576
  willUpdate(changedProperties) {
574
577
  if (changedProperties.has("size") && !isInputSize(this.size)) {
575
578
  this.size = "md";
576
579
  }
577
580
  if (changedProperties.has("rows")) {
578
- if (this.rows == null || !Number.isInteger(this.rows) || this.rows < 1) {
579
- this.rows = DEFAULT_ROWS;
580
- }
581
+ this.rows = normalizeInt(this.rows, DEFAULT_ROWS, 1);
581
582
  }
582
583
  if (changedProperties.has("value") && this.value == null) {
583
584
  this.value = "";
584
585
  }
585
586
  if (changedProperties.has("maxlength")) {
586
- if (this.maxlength == null || !Number.isInteger(this.maxlength) || this.maxlength < 0) {
587
- this.maxlength = void 0;
588
- }
587
+ this.maxlength = normalizeInt(this.maxlength, void 0);
589
588
  }
590
589
  if (changedProperties.has("minlength")) {
591
- if (this.minlength == null || !Number.isInteger(this.minlength) || this.minlength < 0) {
592
- this.minlength = void 0;
593
- }
590
+ this.minlength = normalizeInt(this.minlength, void 0);
594
591
  }
595
592
  }
596
593
  get textareaClasses() {
@@ -607,18 +604,6 @@ var SpectreTextareaElement = class extends lit.LitElement {
607
604
  get nativeTextarea() {
608
605
  return this.querySelector("[data-sp-textarea-native]");
609
606
  }
610
- get forwardedAriaLabel() {
611
- const ariaLabel = this.ariaLabel?.trim();
612
- return ariaLabel ? ariaLabel : void 0;
613
- }
614
- get forwardedAriaLabelledBy() {
615
- const ariaLabelledBy = this.ariaLabelledBy?.trim();
616
- return ariaLabelledBy ? ariaLabelledBy : void 0;
617
- }
618
- get forwardedAriaDescribedBy() {
619
- const ariaDescribedBy = this.ariaDescribedBy?.trim();
620
- return ariaDescribedBy ? ariaDescribedBy : void 0;
621
- }
622
607
  handleInput(event) {
623
608
  const textarea = event.currentTarget;
624
609
  this.value = textarea.value;
@@ -634,57 +619,53 @@ var SpectreTextareaElement = class extends lit.LitElement {
634
619
  this.nativeTextarea?.blur();
635
620
  }
636
621
  render() {
637
- return lit.html`
638
- <textarea
639
- aria-busy=${this.loading ? "true" : "false"}
640
- aria-describedby=${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}
641
- aria-invalid=${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}
642
- aria-label=${ifDefined_js.ifDefined(this.forwardedAriaLabel)}
643
- aria-labelledby=${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}
644
- autocomplete=${ifDefined_js.ifDefined(this.autocomplete)}
645
- ?autofocus=${this.autofocus}
646
- class=${this.textareaClasses}
647
- data-sp-textarea-native
648
- ?disabled=${this.isDisabled}
649
- inputmode=${ifDefined_js.ifDefined(this.inputmode)}
650
- ?readonly=${this.readonly}
651
- ?required=${this.required}
652
- id=${ifDefined_js.ifDefined(this.id || void 0)}
653
- maxlength=${ifDefined_js.ifDefined(this.maxlength)}
654
- minlength=${ifDefined_js.ifDefined(this.minlength)}
655
- name=${ifDefined_js.ifDefined(this.name)}
656
- placeholder=${ifDefined_js.ifDefined(this.placeholder)}
657
- rows=${this.rows}
658
- title=${ifDefined_js.ifDefined(this.title || void 0)}
659
- .value=${live_js.live(this.value)}
660
- @change=${this.handleChange}
661
- @input=${this.handleInput}
662
- ></textarea>
663
- `;
622
+ return lit.html`<textarea
623
+ aria-busy="${this.loading ? "true" : "false"}"
624
+ aria-describedby="${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}"
625
+ aria-invalid="${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}"
626
+ aria-label="${ifDefined_js.ifDefined(this.forwardedAriaLabel)}"
627
+ aria-labelledby="${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}"
628
+ autocomplete="${ifDefined_js.ifDefined(this.autocomplete || void 0)}"
629
+ ?autofocus="${this.autofocus}"
630
+ class="${this.textareaClasses}"
631
+ data-sp-textarea-native
632
+ ?disabled="${this.isDisabled}"
633
+ form="${ifDefined_js.ifDefined(this.form || void 0)}"
634
+ inputmode="${ifDefined_js.ifDefined(this.inputmode || void 0)}"
635
+ ?readonly="${this.readonly}"
636
+ ?required="${this.required}"
637
+ id="${ifDefined_js.ifDefined(this.id || void 0)}"
638
+ maxlength="${ifDefined_js.ifDefined(this.maxlength)}"
639
+ minlength="${ifDefined_js.ifDefined(this.minlength)}"
640
+ name="${ifDefined_js.ifDefined(this.name || void 0)}"
641
+ placeholder="${ifDefined_js.ifDefined(this.placeholder || void 0)}"
642
+ rows="${this.rows}"
643
+ title="${ifDefined_js.ifDefined(this.title || void 0)}"
644
+ .value="${live_js.live(this.value)}"
645
+ @change="${this.handleChange}"
646
+ @input="${this.handleInput}"
647
+ ></textarea>`;
664
648
  }
665
649
  };
666
650
  SpectreTextareaElement.properties = {
667
- ariaLabel: { attribute: "aria-label", type: String },
668
- ariaLabelledBy: { attribute: "aria-labelledby", type: String },
669
- ariaDescribedBy: { attribute: "aria-describedby", type: String },
670
- autocomplete: { type: String },
651
+ autocomplete: { type: String, reflect: true },
671
652
  autofocus: { type: Boolean, reflect: true },
672
653
  disabled: { type: Boolean, reflect: true },
654
+ form: { type: String },
673
655
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
674
- inputmode: { type: String },
656
+ inputmode: { type: String, reflect: true },
675
657
  invalid: { type: Boolean, reflect: true },
676
658
  loading: { type: Boolean, reflect: true },
677
- maxlength: { type: Number },
678
- minlength: { type: Number },
679
- name: { type: String },
659
+ maxlength: { type: Number, reflect: true },
660
+ minlength: { type: Number, reflect: true },
661
+ name: { type: String, reflect: true },
680
662
  pill: { type: Boolean, reflect: true },
681
- placeholder: { type: String },
663
+ placeholder: { type: String, reflect: true },
682
664
  readonly: { type: Boolean, reflect: true },
683
665
  required: { type: Boolean, reflect: true },
684
666
  rows: { type: Number },
685
667
  size: { type: String, reflect: true },
686
668
  success: { type: Boolean, reflect: true },
687
- title: { type: String, reflect: true },
688
669
  value: { type: String }
689
670
  };
690
671
  function defineSpectreTextarea(tagName = "sp-textarea") {
@@ -695,26 +676,9 @@ function defineSpectreTextarea(tagName = "sp-textarea") {
695
676
  customElements.define(tagName, SpectreTextareaElement);
696
677
  return SpectreTextareaElement;
697
678
  }
698
- var spectreSelectSizes = ["sm", "md", "lg"];
699
- function isSelectSize(value) {
700
- return spectreSelectSizes.includes(value);
701
- }
702
- function isSelectableContent(node) {
703
- if (node.nodeType === Node.ELEMENT_NODE) {
704
- const tagName = node.tagName;
705
- return tagName === "OPTION" || tagName === "OPTGROUP";
706
- }
707
- if (node.nodeType === Node.TEXT_NODE) {
708
- return (node.textContent?.trim().length ?? 0) > 0;
709
- }
710
- return false;
711
- }
712
- var SpectreSelectElement = class extends lit.LitElement {
679
+ var SpectreSelectElement = class extends SpectreProjectableElement {
713
680
  constructor() {
714
681
  super(...arguments);
715
- this.ariaLabel = null;
716
- this.ariaLabelledBy = null;
717
- this.ariaDescribedBy = null;
718
682
  this.autofocus = false;
719
683
  this.disabled = false;
720
684
  this.fullWidth = false;
@@ -724,93 +688,43 @@ var SpectreSelectElement = class extends lit.LitElement {
724
688
  this.required = false;
725
689
  this.size = "md";
726
690
  this.success = false;
727
- this.title = "";
728
691
  this.value = "";
729
- this.projectedOptions = [];
730
- }
731
- get id() {
732
- return this._id ?? "";
733
692
  }
734
- set id(value) {
735
- if ((this._id ?? "") === value) {
736
- return;
737
- }
738
- this._id = value;
739
- const host = this;
740
- if (HTMLElement.prototype.hasAttribute.call(host, "id")) {
741
- HTMLElement.prototype.removeAttribute.call(host, "id");
742
- }
743
- this.requestUpdate();
744
- }
745
- createRenderRoot() {
746
- return this;
747
- }
748
- connectedCallback() {
749
- super.connectedCallback();
750
- const hostId = super.getAttribute("id");
751
- if (hostId !== null) {
752
- this.id = hostId;
753
- }
754
- this.syncProjectedOptions();
755
- this.startContentObserver();
756
- }
757
- disconnectedCallback() {
758
- this.stopContentObserver();
759
- super.disconnectedCallback();
760
- }
761
- getAttribute(qualifiedName) {
762
- if (qualifiedName === "id") {
763
- return this.id || null;
764
- }
765
- return super.getAttribute(qualifiedName);
766
- }
767
- hasAttribute(qualifiedName) {
768
- if (qualifiedName === "id") {
769
- return this.id !== "";
770
- }
771
- return super.hasAttribute(qualifiedName);
772
- }
773
- setAttribute(qualifiedName, value) {
774
- if (qualifiedName === "id") {
775
- this.id = value;
776
- return;
777
- }
778
- super.setAttribute(qualifiedName, value);
693
+ getContentContainer() {
694
+ return this.querySelector("[data-sp-select-native]");
779
695
  }
780
- removeAttribute(qualifiedName) {
781
- if (qualifiedName === "id") {
782
- this.id = "";
783
- return;
696
+ isInternalNode(node) {
697
+ if (node.nodeType !== Node.ELEMENT_NODE) {
698
+ return false;
784
699
  }
785
- super.removeAttribute(qualifiedName);
700
+ const el = node;
701
+ return el.hasAttribute("data-sp-select-native");
786
702
  }
787
703
  willUpdate(changedProperties) {
788
- if (changedProperties.has("size") && !isSelectSize(this.size)) {
704
+ if (changedProperties.has("size") && !isInputSize(this.size)) {
789
705
  this.size = "md";
790
706
  }
791
707
  if (changedProperties.has("value") && this.value == null) {
792
708
  this.value = "";
793
709
  }
794
710
  }
795
- update(changedProperties) {
796
- this.stopContentObserver();
797
- super.update(changedProperties);
798
- this.startContentObserver();
799
- }
800
711
  updated(changedProperties) {
801
712
  super.updated(changedProperties);
802
- const nativeSelect = this.nativeSelect;
713
+ const nativeSelect = this.getContentContainer();
803
714
  if (!nativeSelect) {
804
715
  return;
805
716
  }
806
717
  if (this.value !== "" && nativeSelect.value !== this.value) {
807
718
  nativeSelect.value = this.value;
808
- return;
809
719
  }
810
720
  if (this.value === "" && !this.hasAttribute("value")) {
811
721
  const nativeValue = nativeSelect.value ?? "";
812
- if (nativeValue !== "") {
813
- this.value = nativeValue;
722
+ if (nativeValue !== "" && nativeValue !== this.value) {
723
+ this.updateComplete.then(() => {
724
+ if (this.value === "" && !this.hasAttribute("value")) {
725
+ this.value = nativeValue;
726
+ }
727
+ });
814
728
  }
815
729
  }
816
730
  }
@@ -819,75 +733,11 @@ var SpectreSelectElement = class extends lit.LitElement {
819
733
  fullWidth: this.fullWidth,
820
734
  pill: this.pill,
821
735
  size: this.size,
822
- state: this.isDisabled ? this.disabled ? "disabled" : "loading" : this.invalid ? "error" : this.success ? "success" : "default"
823
- });
824
- }
825
- get isDisabled() {
826
- return this.disabled || this.loading;
827
- }
828
- get nativeSelect() {
829
- return this.querySelector("[data-sp-select-native]");
830
- }
831
- get forwardedAriaLabel() {
832
- const ariaLabel = this.ariaLabel?.trim();
833
- return ariaLabel ? ariaLabel : void 0;
834
- }
835
- get forwardedAriaLabelledBy() {
836
- const ariaLabelledBy = this.ariaLabelledBy?.trim();
837
- return ariaLabelledBy ? ariaLabelledBy : void 0;
838
- }
839
- get forwardedAriaDescribedBy() {
840
- const ariaDescribedBy = this.ariaDescribedBy?.trim();
841
- return ariaDescribedBy ? ariaDescribedBy : void 0;
842
- }
843
- startContentObserver() {
844
- if (this.contentObserver) {
845
- return;
846
- }
847
- this.contentObserver = new MutationObserver((mutations) => {
848
- const isInternalMovement = mutations.every((mutation) => {
849
- return Array.from(mutation.removedNodes).every(
850
- (node) => this.isInternalSelectNode(node) || this.contains(node)
851
- ) && Array.from(mutation.addedNodes).every((node) => this.isInternalSelectNode(node));
852
- });
853
- if (isInternalMovement) {
854
- return;
855
- }
856
- if (this.syncProjectedOptions()) {
857
- this.requestUpdate();
858
- }
859
- });
860
- this.contentObserver.observe(this, {
861
- childList: true
862
- });
863
- }
864
- stopContentObserver() {
865
- this.contentObserver?.disconnect();
866
- this.contentObserver = void 0;
867
- }
868
- syncProjectedOptions() {
869
- const nextProjectedOptions = [];
870
- Array.from(this.childNodes).forEach((node) => {
871
- if (this.isInternalSelectNode(node)) {
872
- this.projectedOptions.forEach((projectedNode) => {
873
- if (projectedNode.parentNode !== this && this.contains(projectedNode)) {
874
- nextProjectedOptions.push(projectedNode);
875
- }
876
- });
877
- return;
878
- }
879
- if (isSelectableContent(node)) {
880
- nextProjectedOptions.push(node);
881
- }
882
- });
883
- const hasChanged = nextProjectedOptions.length !== this.projectedOptions.length || nextProjectedOptions.some((node, index) => node !== this.projectedOptions[index]);
884
- if (hasChanged) {
885
- this.projectedOptions = nextProjectedOptions;
886
- }
887
- return hasChanged;
736
+ state: this.isDisabled ? this.disabled ? "disabled" : "loading" : this.invalid ? "error" : this.success ? "success" : "default"
737
+ });
888
738
  }
889
- isInternalSelectNode(node) {
890
- return node.nodeType === Node.ELEMENT_NODE && node.hasAttribute("data-sp-select-native");
739
+ get isDisabled() {
740
+ return this.disabled || this.loading;
891
741
  }
892
742
  handleInput(event) {
893
743
  const select = event.currentTarget;
@@ -898,51 +748,49 @@ var SpectreSelectElement = class extends lit.LitElement {
898
748
  this.value = select.value;
899
749
  }
900
750
  focus(options) {
901
- this.nativeSelect?.focus(options);
751
+ this.getContentContainer()?.focus(options);
902
752
  }
903
753
  blur() {
904
- this.nativeSelect?.blur();
754
+ this.getContentContainer()?.blur();
905
755
  }
906
756
  render() {
907
- return lit.html`
908
- <select
909
- aria-busy=${this.loading ? "true" : "false"}
910
- aria-describedby=${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}
911
- aria-invalid=${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}
912
- aria-label=${ifDefined_js.ifDefined(this.forwardedAriaLabel)}
913
- aria-labelledby=${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}
914
- ?autofocus=${this.autofocus}
915
- class=${this.selectClasses}
916
- data-sp-select-native
917
- ?disabled=${this.isDisabled}
918
- id=${ifDefined_js.ifDefined(this.id || void 0)}
919
- name=${ifDefined_js.ifDefined(this.name)}
920
- ?required=${this.required}
921
- title=${ifDefined_js.ifDefined(this.title || void 0)}
922
- .value=${live_js.live(this.value)}
923
- @change=${this.handleChange}
924
- @input=${this.handleInput}
925
- >
926
- ${this.projectedOptions.length > 0 ? this.projectedOptions : lit.nothing}
927
- </select>
928
- `;
757
+ return lit.html`<select
758
+ aria-busy="${this.loading ? "true" : "false"}"
759
+ aria-describedby="${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}"
760
+ aria-invalid="${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}"
761
+ aria-label="${ifDefined_js.ifDefined(this.forwardedAriaLabel)}"
762
+ aria-labelledby="${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}"
763
+ autocomplete="${ifDefined_js.ifDefined(this.autocomplete || void 0)}"
764
+ ?autofocus="${this.autofocus}"
765
+ class="${this.selectClasses}"
766
+ data-sp-select-native
767
+ ?disabled="${this.isDisabled}"
768
+ form="${ifDefined_js.ifDefined(this.form || void 0)}"
769
+ id="${ifDefined_js.ifDefined(this.id || void 0)}"
770
+ name="${ifDefined_js.ifDefined(this.name || void 0)}"
771
+ ?required="${this.required}"
772
+ title="${ifDefined_js.ifDefined(this.title || void 0)}"
773
+ .value="${live_js.live(this.value)}"
774
+ @change="${this.handleChange}"
775
+ @input="${this.handleInput}"
776
+ >
777
+ ${this.hasProjectedContent ? this.projectedContent : lit.nothing}
778
+ </select>`;
929
779
  }
930
780
  };
931
781
  SpectreSelectElement.properties = {
932
- ariaLabel: { attribute: "aria-label", type: String },
933
- ariaLabelledBy: { attribute: "aria-labelledby", type: String },
934
- ariaDescribedBy: { attribute: "aria-describedby", type: String },
782
+ autocomplete: { type: String, reflect: true },
935
783
  autofocus: { type: Boolean, reflect: true },
936
784
  disabled: { type: Boolean, reflect: true },
785
+ form: { type: String },
937
786
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
938
787
  invalid: { type: Boolean, reflect: true },
939
788
  loading: { type: Boolean, reflect: true },
940
- name: { type: String },
789
+ name: { type: String, reflect: true },
941
790
  pill: { type: Boolean, reflect: true },
942
791
  required: { type: Boolean, reflect: true },
943
792
  size: { type: String, reflect: true },
944
793
  success: { type: Boolean, reflect: true },
945
- title: { type: String, reflect: true },
946
794
  value: { type: String }
947
795
  };
948
796
  function defineSpectreSelect(tagName = "sp-select") {
@@ -953,70 +801,27 @@ function defineSpectreSelect(tagName = "sp-select") {
953
801
  customElements.define(tagName, SpectreSelectElement);
954
802
  return SpectreSelectElement;
955
803
  }
956
- var SpectreCheckboxElement = class extends lit.LitElement {
804
+ var SpectreCheckboxElement = class extends SpectreProjectableElement {
957
805
  constructor() {
958
806
  super(...arguments);
959
- this.ariaLabel = null;
960
- this.ariaLabelledBy = null;
961
- this.ariaDescribedBy = null;
962
807
  this.autofocus = false;
963
808
  this.checked = false;
964
809
  this.disabled = false;
965
810
  this.invalid = false;
966
- this.label = "";
811
+ this.loading = false;
967
812
  this.required = false;
968
- this.title = "";
813
+ this.success = false;
969
814
  this.value = "on";
970
815
  }
971
- get id() {
972
- return this._id ?? "";
973
- }
974
- set id(value) {
975
- if ((this._id ?? "") === value) {
976
- return;
977
- }
978
- this._id = value;
979
- const host = this;
980
- if (HTMLElement.prototype.hasAttribute.call(host, "id")) {
981
- HTMLElement.prototype.removeAttribute.call(host, "id");
982
- }
983
- this.requestUpdate();
984
- }
985
- createRenderRoot() {
986
- return this;
987
- }
988
- connectedCallback() {
989
- super.connectedCallback();
990
- const hostId = super.getAttribute("id");
991
- if (hostId !== null) {
992
- this.id = hostId;
993
- }
994
- }
995
- getAttribute(qualifiedName) {
996
- if (qualifiedName === "id") {
997
- return this.id || null;
998
- }
999
- return super.getAttribute(qualifiedName);
1000
- }
1001
- hasAttribute(qualifiedName) {
1002
- if (qualifiedName === "id") {
1003
- return this.id !== "";
1004
- }
1005
- return super.hasAttribute(qualifiedName);
1006
- }
1007
- setAttribute(qualifiedName, value) {
1008
- if (qualifiedName === "id") {
1009
- this.id = value;
1010
- return;
1011
- }
1012
- super.setAttribute(qualifiedName, value);
816
+ getContentContainer() {
817
+ return this.querySelector("[data-sp-checkbox-label]");
1013
818
  }
1014
- removeAttribute(qualifiedName) {
1015
- if (qualifiedName === "id") {
1016
- this.id = "";
1017
- return;
819
+ isInternalNode(node) {
820
+ if (node.nodeType !== Node.ELEMENT_NODE) {
821
+ return false;
1018
822
  }
1019
- super.removeAttribute(qualifiedName);
823
+ const el = node;
824
+ return el.hasAttribute("data-sp-checkbox-label") || el.hasAttribute("data-sp-checkbox-native") || el.hasAttribute("data-sp-checkbox-label-fallback") || el.hasAttribute("data-sp-checkbox-indicator");
1020
825
  }
1021
826
  willUpdate(changedProperties) {
1022
827
  if (changedProperties.has("value") && this.value == null) {
@@ -1026,17 +831,12 @@ var SpectreCheckboxElement = class extends lit.LitElement {
1026
831
  get nativeInput() {
1027
832
  return this.querySelector("[data-sp-checkbox-native]");
1028
833
  }
1029
- get forwardedAriaLabel() {
1030
- const value = this.ariaLabel?.trim();
1031
- return value ? value : void 0;
1032
- }
1033
- get forwardedAriaLabelledBy() {
1034
- const value = this.ariaLabelledBy?.trim();
1035
- return value ? value : void 0;
834
+ get isDisabled() {
835
+ return this.disabled || this.loading;
1036
836
  }
1037
- get forwardedAriaDescribedBy() {
1038
- const value = this.ariaDescribedBy?.trim();
1039
- return value ? value : void 0;
837
+ get visibleLabelFallback() {
838
+ const trimmedLabel = this.label?.trim();
839
+ return trimmedLabel ? trimmedLabel : void 0;
1040
840
  }
1041
841
  handleInput(event) {
1042
842
  const input = event.currentTarget;
@@ -1053,43 +853,44 @@ var SpectreCheckboxElement = class extends lit.LitElement {
1053
853
  this.nativeInput?.blur();
1054
854
  }
1055
855
  render() {
1056
- return lit.html`
1057
- <label>
1058
- <input
1059
- aria-describedby=${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}
1060
- aria-invalid=${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}
1061
- aria-label=${ifDefined_js.ifDefined(this.forwardedAriaLabel)}
1062
- aria-labelledby=${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}
1063
- ?autofocus=${this.autofocus}
1064
- data-sp-checkbox-native
1065
- ?checked=${this.checked}
1066
- ?disabled=${this.disabled}
1067
- id=${ifDefined_js.ifDefined(this.id || void 0)}
1068
- name=${ifDefined_js.ifDefined(this.name)}
1069
- ?required=${this.required}
1070
- title=${ifDefined_js.ifDefined(this.title || void 0)}
1071
- type='checkbox'
1072
- value=${ifDefined_js.ifDefined(this.value || void 0)}
1073
- @change=${this.handleChange}
1074
- @input=${this.handleInput}
1075
- />
1076
- <span class='sp-label'>${this.label}</span>
1077
- </label>
1078
- `;
856
+ const labelContent = this.hasProjectedContent ? this.projectedContent : this.visibleLabelFallback ? lit.html`<span class="sp-label" data-sp-checkbox-label-fallback>${this.visibleLabelFallback}</span>` : lit.nothing;
857
+ return lit.html`<label data-sp-checkbox-label>
858
+ <input
859
+ aria-busy="${this.loading ? "true" : "false"}"
860
+ aria-describedby="${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}"
861
+ aria-invalid="${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}"
862
+ aria-label="${ifDefined_js.ifDefined(this.forwardedAriaLabel)}"
863
+ aria-labelledby="${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}"
864
+ ?autofocus="${this.autofocus}"
865
+ data-sp-checkbox-native
866
+ .checked="${live_js.live(this.checked)}"
867
+ ?disabled="${this.isDisabled}"
868
+ form="${ifDefined_js.ifDefined(this.form || void 0)}"
869
+ id="${ifDefined_js.ifDefined(this.id || void 0)}"
870
+ name="${ifDefined_js.ifDefined(this.name || void 0)}"
871
+ ?required="${this.required}"
872
+ title="${ifDefined_js.ifDefined(this.title || void 0)}"
873
+ type="checkbox"
874
+ value="${ifDefined_js.ifDefined(this.value)}"
875
+ @change="${this.handleChange}"
876
+ @input="${this.handleInput}"
877
+ />
878
+ <span class="sp-checkbox-indicator" data-sp-checkbox-indicator></span>
879
+ ${labelContent}
880
+ </label>`;
1079
881
  }
1080
882
  };
1081
883
  SpectreCheckboxElement.properties = {
1082
- ariaLabel: { attribute: "aria-label", type: String },
1083
- ariaLabelledBy: { attribute: "aria-labelledby", type: String },
1084
- ariaDescribedBy: { attribute: "aria-describedby", type: String },
1085
884
  autofocus: { type: Boolean, reflect: true },
1086
885
  checked: { type: Boolean, reflect: true },
1087
886
  disabled: { type: Boolean, reflect: true },
887
+ form: { type: String },
1088
888
  invalid: { type: Boolean, reflect: true },
889
+ loading: { type: Boolean, reflect: true },
1089
890
  label: { type: String, reflect: true },
1090
- name: { type: String },
891
+ name: { type: String, reflect: true },
1091
892
  required: { type: Boolean, reflect: true },
1092
- title: { type: String, reflect: true },
893
+ success: { type: Boolean, reflect: true },
1093
894
  value: { type: String }
1094
895
  };
1095
896
  function defineSpectreCheckbox(tagName = "sp-checkbox") {
@@ -1100,70 +901,27 @@ function defineSpectreCheckbox(tagName = "sp-checkbox") {
1100
901
  customElements.define(tagName, SpectreCheckboxElement);
1101
902
  return SpectreCheckboxElement;
1102
903
  }
1103
- var SpectreRadioElement = class extends lit.LitElement {
904
+ var SpectreRadioElement = class extends SpectreProjectableElement {
1104
905
  constructor() {
1105
906
  super(...arguments);
1106
- this.ariaLabel = null;
1107
- this.ariaLabelledBy = null;
1108
- this.ariaDescribedBy = null;
1109
907
  this.autofocus = false;
1110
908
  this.checked = false;
1111
909
  this.disabled = false;
1112
910
  this.invalid = false;
1113
- this.label = "";
911
+ this.loading = false;
1114
912
  this.required = false;
1115
- this.title = "";
913
+ this.success = false;
1116
914
  this.value = "on";
1117
915
  }
1118
- get id() {
1119
- return this._id ?? "";
1120
- }
1121
- set id(value) {
1122
- if ((this._id ?? "") === value) {
1123
- return;
1124
- }
1125
- this._id = value;
1126
- const host = this;
1127
- if (HTMLElement.prototype.hasAttribute.call(host, "id")) {
1128
- HTMLElement.prototype.removeAttribute.call(host, "id");
1129
- }
1130
- this.requestUpdate();
1131
- }
1132
- createRenderRoot() {
1133
- return this;
1134
- }
1135
- connectedCallback() {
1136
- super.connectedCallback();
1137
- const hostId = super.getAttribute("id");
1138
- if (hostId !== null) {
1139
- this.id = hostId;
1140
- }
1141
- }
1142
- getAttribute(qualifiedName) {
1143
- if (qualifiedName === "id") {
1144
- return this.id || null;
1145
- }
1146
- return super.getAttribute(qualifiedName);
1147
- }
1148
- hasAttribute(qualifiedName) {
1149
- if (qualifiedName === "id") {
1150
- return this.id !== "";
1151
- }
1152
- return super.hasAttribute(qualifiedName);
1153
- }
1154
- setAttribute(qualifiedName, value) {
1155
- if (qualifiedName === "id") {
1156
- this.id = value;
1157
- return;
1158
- }
1159
- super.setAttribute(qualifiedName, value);
916
+ getContentContainer() {
917
+ return this.querySelector("[data-sp-radio-label]");
1160
918
  }
1161
- removeAttribute(qualifiedName) {
1162
- if (qualifiedName === "id") {
1163
- this.id = "";
1164
- return;
919
+ isInternalNode(node) {
920
+ if (node.nodeType !== Node.ELEMENT_NODE) {
921
+ return false;
1165
922
  }
1166
- super.removeAttribute(qualifiedName);
923
+ const el = node;
924
+ return el.hasAttribute("data-sp-radio-label") || el.hasAttribute("data-sp-radio-native") || el.hasAttribute("data-sp-radio-label-fallback") || el.hasAttribute("data-sp-radio-indicator");
1167
925
  }
1168
926
  willUpdate(changedProperties) {
1169
927
  if (changedProperties.has("value") && this.value == null) {
@@ -1173,17 +931,12 @@ var SpectreRadioElement = class extends lit.LitElement {
1173
931
  get nativeInput() {
1174
932
  return this.querySelector("[data-sp-radio-native]");
1175
933
  }
1176
- get forwardedAriaLabel() {
1177
- const value = this.ariaLabel?.trim();
1178
- return value ? value : void 0;
1179
- }
1180
- get forwardedAriaLabelledBy() {
1181
- const value = this.ariaLabelledBy?.trim();
1182
- return value ? value : void 0;
934
+ get isDisabled() {
935
+ return this.disabled || this.loading;
1183
936
  }
1184
- get forwardedAriaDescribedBy() {
1185
- const value = this.ariaDescribedBy?.trim();
1186
- return value ? value : void 0;
937
+ get visibleLabelFallback() {
938
+ const trimmedLabel = this.label?.trim();
939
+ return trimmedLabel ? trimmedLabel : void 0;
1187
940
  }
1188
941
  handleInput(event) {
1189
942
  const input = event.currentTarget;
@@ -1200,43 +953,44 @@ var SpectreRadioElement = class extends lit.LitElement {
1200
953
  this.nativeInput?.blur();
1201
954
  }
1202
955
  render() {
1203
- return lit.html`
1204
- <label>
1205
- <input
1206
- aria-describedby=${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}
1207
- aria-invalid=${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}
1208
- aria-label=${ifDefined_js.ifDefined(this.forwardedAriaLabel)}
1209
- aria-labelledby=${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}
1210
- ?autofocus=${this.autofocus}
1211
- data-sp-radio-native
1212
- ?checked=${this.checked}
1213
- ?disabled=${this.disabled}
1214
- id=${ifDefined_js.ifDefined(this.id || void 0)}
1215
- name=${ifDefined_js.ifDefined(this.name)}
1216
- ?required=${this.required}
1217
- title=${ifDefined_js.ifDefined(this.title || void 0)}
1218
- type='radio'
1219
- value=${ifDefined_js.ifDefined(this.value || void 0)}
1220
- @change=${this.handleChange}
1221
- @input=${this.handleInput}
1222
- />
1223
- <span class='sp-label'>${this.label}</span>
1224
- </label>
1225
- `;
956
+ const labelContent = this.hasProjectedContent ? this.projectedContent : this.visibleLabelFallback ? lit.html`<span class="sp-label" data-sp-radio-label-fallback>${this.visibleLabelFallback}</span>` : lit.nothing;
957
+ return lit.html`<label data-sp-radio-label>
958
+ <input
959
+ aria-busy="${this.loading ? "true" : "false"}"
960
+ aria-describedby="${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}"
961
+ aria-invalid="${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}"
962
+ aria-label="${ifDefined_js.ifDefined(this.forwardedAriaLabel)}"
963
+ aria-labelledby="${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}"
964
+ ?autofocus="${this.autofocus}"
965
+ data-sp-radio-native
966
+ .checked="${live_js.live(this.checked)}"
967
+ ?disabled="${this.isDisabled}"
968
+ form="${ifDefined_js.ifDefined(this.form || void 0)}"
969
+ id="${ifDefined_js.ifDefined(this.id || void 0)}"
970
+ name="${ifDefined_js.ifDefined(this.name || void 0)}"
971
+ ?required="${this.required}"
972
+ title="${ifDefined_js.ifDefined(this.title || void 0)}"
973
+ type="radio"
974
+ value="${ifDefined_js.ifDefined(this.value)}"
975
+ @change="${this.handleChange}"
976
+ @input="${this.handleInput}"
977
+ />
978
+ <span class="sp-radio-indicator" data-sp-radio-indicator></span>
979
+ ${labelContent}
980
+ </label>`;
1226
981
  }
1227
982
  };
1228
983
  SpectreRadioElement.properties = {
1229
- ariaLabel: { attribute: "aria-label", type: String },
1230
- ariaLabelledBy: { attribute: "aria-labelledby", type: String },
1231
- ariaDescribedBy: { attribute: "aria-describedby", type: String },
1232
984
  autofocus: { type: Boolean, reflect: true },
1233
985
  checked: { type: Boolean, reflect: true },
1234
986
  disabled: { type: Boolean, reflect: true },
987
+ form: { type: String },
1235
988
  invalid: { type: Boolean, reflect: true },
989
+ loading: { type: Boolean, reflect: true },
1236
990
  label: { type: String, reflect: true },
1237
- name: { type: String },
991
+ name: { type: String, reflect: true },
1238
992
  required: { type: Boolean, reflect: true },
1239
- title: { type: String, reflect: true },
993
+ success: { type: Boolean, reflect: true },
1240
994
  value: { type: String }
1241
995
  };
1242
996
  function defineSpectreRadio(tagName = "sp-radio") {
@@ -1247,142 +1001,40 @@ function defineSpectreRadio(tagName = "sp-radio") {
1247
1001
  customElements.define(tagName, SpectreRadioElement);
1248
1002
  return SpectreRadioElement;
1249
1003
  }
1250
- var SpectreLabelElement = class extends lit.LitElement {
1251
- constructor() {
1252
- super(...arguments);
1253
- this.projectedContent = [];
1254
- }
1255
- get id() {
1256
- return this._id ?? "";
1257
- }
1258
- set id(value) {
1259
- if ((this._id ?? "") === value) {
1260
- return;
1261
- }
1262
- this._id = value;
1263
- const host = this;
1264
- if (HTMLElement.prototype.hasAttribute.call(host, "id")) {
1265
- HTMLElement.prototype.removeAttribute.call(host, "id");
1266
- }
1267
- this.requestUpdate();
1268
- }
1269
- createRenderRoot() {
1270
- return this;
1271
- }
1272
- connectedCallback() {
1273
- super.connectedCallback();
1274
- const hostId = super.getAttribute("id");
1275
- if (hostId !== null) {
1276
- this.id = hostId;
1277
- }
1278
- this.syncProjectedContent();
1279
- this.startContentObserver();
1280
- }
1281
- disconnectedCallback() {
1282
- this.stopContentObserver();
1283
- super.disconnectedCallback();
1284
- }
1285
- getAttribute(qualifiedName) {
1286
- if (qualifiedName === "id") {
1287
- return this.id || null;
1288
- }
1289
- return super.getAttribute(qualifiedName);
1290
- }
1291
- hasAttribute(qualifiedName) {
1292
- if (qualifiedName === "id") {
1293
- return this.id !== "";
1294
- }
1295
- return super.hasAttribute(qualifiedName);
1296
- }
1297
- setAttribute(qualifiedName, value) {
1298
- if (qualifiedName === "id") {
1299
- this.id = value;
1300
- return;
1301
- }
1302
- super.setAttribute(qualifiedName, value);
1303
- }
1304
- removeAttribute(qualifiedName) {
1305
- if (qualifiedName === "id") {
1306
- this.id = "";
1307
- return;
1308
- }
1309
- super.removeAttribute(qualifiedName);
1310
- }
1311
- update(changedProperties) {
1312
- this.stopContentObserver();
1313
- super.update(changedProperties);
1314
- this.startContentObserver();
1315
- }
1316
- get nativeLabel() {
1004
+ var SpectreLabelElement = class extends SpectreProjectableElement {
1005
+ getContentContainer() {
1317
1006
  return this.querySelector("[data-sp-label-native]");
1318
1007
  }
1319
- startContentObserver() {
1320
- if (this.contentObserver) {
1321
- return;
1322
- }
1323
- this.contentObserver = new MutationObserver((mutations) => {
1324
- const isInternalMovement = mutations.every((mutation) => {
1325
- return Array.from(mutation.removedNodes).every(
1326
- (node) => this.isInternalLabelNode(node) || this.contains(node)
1327
- ) && Array.from(mutation.addedNodes).every((node) => this.isInternalLabelNode(node));
1328
- });
1329
- if (isInternalMovement) {
1330
- return;
1331
- }
1332
- if (this.syncProjectedContent()) {
1333
- this.requestUpdate();
1334
- }
1335
- });
1336
- this.contentObserver.observe(this, { childList: true });
1337
- }
1338
- stopContentObserver() {
1339
- this.contentObserver?.disconnect();
1340
- this.contentObserver = void 0;
1341
- }
1342
- syncProjectedContent() {
1343
- const nextProjectedContent = [];
1344
- Array.from(this.childNodes).forEach((node) => {
1345
- if (this.isInternalLabelNode(node)) {
1346
- this.projectedContent.forEach((projectedNode) => {
1347
- if (projectedNode.parentNode !== this && this.contains(projectedNode)) {
1348
- nextProjectedContent.push(projectedNode);
1349
- }
1350
- });
1351
- return;
1352
- }
1353
- nextProjectedContent.push(node);
1354
- });
1355
- if (nextProjectedContent.length === this.projectedContent.length && nextProjectedContent.every((node, index) => node === this.projectedContent[index])) {
1008
+ isInternalNode(node) {
1009
+ if (node.nodeType !== Node.ELEMENT_NODE) {
1356
1010
  return false;
1357
1011
  }
1358
- this.projectedContent = nextProjectedContent;
1359
- return true;
1360
- }
1361
- isInternalLabelNode(node) {
1362
- return node === this.nativeLabel;
1012
+ const el = node;
1013
+ return el.hasAttribute("data-sp-label-native");
1363
1014
  }
1364
1015
  focus(options) {
1365
- this.nativeLabel?.focus(options);
1016
+ this.getContentContainer()?.focus(options);
1366
1017
  }
1367
1018
  blur() {
1368
- this.nativeLabel?.blur();
1019
+ this.getContentContainer()?.blur();
1369
1020
  }
1370
1021
  render() {
1371
- return lit.html`
1372
- <label
1373
- class='sp-label'
1374
- data-sp-label-native
1375
- for=${ifDefined_js.ifDefined(this.htmlFor)}
1376
- id=${ifDefined_js.ifDefined(this.id || void 0)}
1377
- tabindex='-1'
1378
- >
1379
- ${this.projectedContent.length > 0 ? this.projectedContent : lit.nothing}
1380
- </label>
1381
- `;
1022
+ return lit.html`<label
1023
+ aria-describedby="${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}"
1024
+ aria-label="${ifDefined_js.ifDefined(this.forwardedAriaLabel)}"
1025
+ aria-labelledby="${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}"
1026
+ class="sp-label"
1027
+ data-sp-label-native
1028
+ for="${ifDefined_js.ifDefined(this.htmlFor || void 0)}"
1029
+ id="${ifDefined_js.ifDefined(this.id || void 0)}"
1030
+ title="${ifDefined_js.ifDefined(this.title || void 0)}"
1031
+ >
1032
+ ${this.hasProjectedContent ? this.projectedContent : lit.nothing}
1033
+ </label>`;
1382
1034
  }
1383
1035
  };
1384
1036
  SpectreLabelElement.properties = {
1385
- htmlFor: { attribute: "for", type: String }
1037
+ htmlFor: { attribute: "for", type: String, reflect: true }
1386
1038
  };
1387
1039
  function defineSpectreLabel(tagName = "sp-label") {
1388
1040
  const existingElement = customElements.get(tagName);
@@ -1392,165 +1044,49 @@ function defineSpectreLabel(tagName = "sp-label") {
1392
1044
  customElements.define(tagName, SpectreLabelElement);
1393
1045
  return SpectreLabelElement;
1394
1046
  }
1395
- var SpectreFieldsetElement = class extends lit.LitElement {
1047
+ var SpectreFieldsetElement = class extends SpectreProjectableElement {
1396
1048
  constructor() {
1397
1049
  super(...arguments);
1398
- this.ariaLabel = null;
1399
- this.ariaLabelledBy = null;
1400
- this.ariaDescribedBy = null;
1401
1050
  this.disabled = false;
1402
- this.legend = "";
1403
- this.projectedContent = [];
1404
- }
1405
- get id() {
1406
- return this._id ?? "";
1407
- }
1408
- set id(value) {
1409
- if ((this._id ?? "") === value) {
1410
- return;
1411
- }
1412
- this._id = value;
1413
- const host = this;
1414
- if (HTMLElement.prototype.hasAttribute.call(host, "id")) {
1415
- HTMLElement.prototype.removeAttribute.call(host, "id");
1416
- }
1417
- this.requestUpdate();
1418
- }
1419
- createRenderRoot() {
1420
- return this;
1421
- }
1422
- connectedCallback() {
1423
- super.connectedCallback();
1424
- const hostId = super.getAttribute("id");
1425
- if (hostId !== null) {
1426
- this.id = hostId;
1427
- }
1428
- this.syncProjectedContent();
1429
- this.startContentObserver();
1430
- }
1431
- disconnectedCallback() {
1432
- this.stopContentObserver();
1433
- super.disconnectedCallback();
1434
- }
1435
- getAttribute(qualifiedName) {
1436
- if (qualifiedName === "id") {
1437
- return this.id || null;
1438
- }
1439
- return super.getAttribute(qualifiedName);
1440
- }
1441
- hasAttribute(qualifiedName) {
1442
- if (qualifiedName === "id") {
1443
- return this.id !== "";
1444
- }
1445
- return super.hasAttribute(qualifiedName);
1446
- }
1447
- setAttribute(qualifiedName, value) {
1448
- if (qualifiedName === "id") {
1449
- this.id = value;
1450
- return;
1451
- }
1452
- super.setAttribute(qualifiedName, value);
1453
- }
1454
- removeAttribute(qualifiedName) {
1455
- if (qualifiedName === "id") {
1456
- this.id = "";
1457
- return;
1458
- }
1459
- super.removeAttribute(qualifiedName);
1460
- }
1461
- update(changedProperties) {
1462
- this.stopContentObserver();
1463
- super.update(changedProperties);
1464
- this.startContentObserver();
1465
1051
  }
1466
- get nativeFieldset() {
1052
+ getContentContainer() {
1467
1053
  return this.querySelector("[data-sp-fieldset-native]");
1468
1054
  }
1469
- get forwardedAriaLabel() {
1470
- const value = this.ariaLabel?.trim();
1471
- return value ? value : void 0;
1472
- }
1473
- get forwardedAriaLabelledBy() {
1474
- const value = this.ariaLabelledBy?.trim();
1475
- return value ? value : void 0;
1476
- }
1477
- get forwardedAriaDescribedBy() {
1478
- const value = this.ariaDescribedBy?.trim();
1479
- return value ? value : void 0;
1480
- }
1481
- startContentObserver() {
1482
- if (this.contentObserver) {
1483
- return;
1484
- }
1485
- this.contentObserver = new MutationObserver((mutations) => {
1486
- const isInternalMovement = mutations.every((mutation) => {
1487
- return Array.from(mutation.removedNodes).every(
1488
- (node) => this.isInternalFieldsetNode(node) || this.contains(node)
1489
- ) && Array.from(mutation.addedNodes).every((node) => this.isInternalFieldsetNode(node));
1490
- });
1491
- if (isInternalMovement) {
1492
- return;
1493
- }
1494
- if (this.syncProjectedContent()) {
1495
- this.requestUpdate();
1496
- }
1497
- });
1498
- this.contentObserver.observe(this, { childList: true });
1499
- }
1500
- stopContentObserver() {
1501
- this.contentObserver?.disconnect();
1502
- this.contentObserver = void 0;
1503
- }
1504
- syncProjectedContent() {
1505
- const nextProjectedContent = [];
1506
- Array.from(this.childNodes).forEach((node) => {
1507
- if (this.isInternalFieldsetNode(node)) {
1508
- this.projectedContent.forEach((projectedNode) => {
1509
- if (projectedNode.parentNode !== this && this.contains(projectedNode)) {
1510
- nextProjectedContent.push(projectedNode);
1511
- }
1512
- });
1513
- return;
1514
- }
1515
- nextProjectedContent.push(node);
1516
- });
1517
- if (nextProjectedContent.length === this.projectedContent.length && nextProjectedContent.every((node, index) => node === this.projectedContent[index])) {
1055
+ isInternalNode(node) {
1056
+ if (node.nodeType !== Node.ELEMENT_NODE) {
1518
1057
  return false;
1519
1058
  }
1520
- this.projectedContent = nextProjectedContent;
1521
- return true;
1522
- }
1523
- isInternalFieldsetNode(node) {
1524
- return node === this.nativeFieldset;
1059
+ const el = node;
1060
+ return el.hasAttribute("data-sp-fieldset-native") || el.hasAttribute("data-sp-fieldset-legend");
1525
1061
  }
1526
1062
  focus(options) {
1527
- this.nativeFieldset?.focus(options);
1063
+ this.getContentContainer()?.focus(options);
1528
1064
  }
1529
1065
  blur() {
1530
- this.nativeFieldset?.blur();
1066
+ this.getContentContainer()?.blur();
1531
1067
  }
1532
1068
  render() {
1533
- return lit.html`
1534
- <fieldset
1535
- aria-describedby=${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}
1536
- aria-label=${ifDefined_js.ifDefined(this.forwardedAriaLabel)}
1537
- aria-labelledby=${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}
1538
- data-sp-fieldset-native
1539
- ?disabled=${this.disabled}
1540
- id=${ifDefined_js.ifDefined(this.id || void 0)}
1541
- >
1542
- ${this.legend ? lit.html`<legend class='sp-label'>${this.legend}</legend>` : lit.nothing}
1543
- ${this.projectedContent.length > 0 ? this.projectedContent : lit.nothing}
1544
- </fieldset>
1545
- `;
1069
+ return lit.html`<fieldset
1070
+ aria-describedby="${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}"
1071
+ aria-label="${ifDefined_js.ifDefined(this.forwardedAriaLabel)}"
1072
+ aria-labelledby="${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}"
1073
+ data-sp-fieldset-native
1074
+ ?disabled="${this.disabled}"
1075
+ form="${ifDefined_js.ifDefined(this.form || void 0)}"
1076
+ id="${ifDefined_js.ifDefined(this.id || void 0)}"
1077
+ name="${ifDefined_js.ifDefined(this.name || void 0)}"
1078
+ title="${ifDefined_js.ifDefined(this.title || void 0)}"
1079
+ >
1080
+ ${this.legend ? lit.html`<legend class="sp-label" data-sp-fieldset-legend>${this.legend}</legend>` : lit.nothing}
1081
+ ${this.hasProjectedContent ? this.projectedContent : lit.nothing}
1082
+ </fieldset>`;
1546
1083
  }
1547
1084
  };
1548
1085
  SpectreFieldsetElement.properties = {
1549
- ariaLabel: { attribute: "aria-label", type: String },
1550
- ariaLabelledBy: { attribute: "aria-labelledby", type: String },
1551
- ariaDescribedBy: { attribute: "aria-describedby", type: String },
1552
1086
  disabled: { type: Boolean, reflect: true },
1553
- legend: { type: String, reflect: true }
1087
+ form: { type: String },
1088
+ legend: { type: String, reflect: true },
1089
+ name: { type: String, reflect: true }
1554
1090
  };
1555
1091
  function defineSpectreFieldset(tagName = "sp-fieldset") {
1556
1092
  const existingElement = customElements.get(tagName);
@@ -1595,6 +1131,5 @@ exports.spectreButtonTypes = spectreButtonTypes;
1595
1131
  exports.spectreButtonVariants = spectreButtonVariants;
1596
1132
  exports.spectreInputSizes = spectreInputSizes;
1597
1133
  exports.spectreInputTypes = spectreInputTypes;
1598
- exports.spectreSelectSizes = spectreSelectSizes;
1599
1134
  //# sourceMappingURL=index.cjs.map
1600
1135
  //# sourceMappingURL=index.cjs.map