@phcdevworks/spectre-components 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -0
  3. package/dist/button.cjs +288 -0
  4. package/dist/button.cjs.map +1 -0
  5. package/dist/button.d.cts +142 -0
  6. package/dist/button.d.ts +142 -0
  7. package/dist/button.js +282 -0
  8. package/dist/button.js.map +1 -0
  9. package/dist/checkbox.cjs +158 -0
  10. package/dist/checkbox.cjs.map +1 -0
  11. package/dist/checkbox.d.cts +98 -0
  12. package/dist/checkbox.d.ts +98 -0
  13. package/dist/checkbox.js +155 -0
  14. package/dist/checkbox.js.map +1 -0
  15. package/dist/fieldset.cjs +179 -0
  16. package/dist/fieldset.cjs.map +1 -0
  17. package/dist/fieldset.d.cts +63 -0
  18. package/dist/fieldset.d.ts +63 -0
  19. package/dist/fieldset.js +176 -0
  20. package/dist/fieldset.js.map +1 -0
  21. package/dist/index.cjs +1600 -0
  22. package/dist/index.cjs.map +1 -0
  23. package/dist/index.d.cts +14 -0
  24. package/dist/index.d.ts +14 -0
  25. package/dist/index.js +1576 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/input.cjs +235 -0
  28. package/dist/input.cjs.map +1 -0
  29. package/dist/input.d.cts +175 -0
  30. package/dist/input.d.ts +175 -0
  31. package/dist/input.js +230 -0
  32. package/dist/input.js.map +1 -0
  33. package/dist/label.cjs +156 -0
  34. package/dist/label.cjs.map +1 -0
  35. package/dist/label.d.cts +39 -0
  36. package/dist/label.d.ts +39 -0
  37. package/dist/label.js +153 -0
  38. package/dist/label.js.map +1 -0
  39. package/dist/radio.cjs +158 -0
  40. package/dist/radio.cjs.map +1 -0
  41. package/dist/radio.d.cts +98 -0
  42. package/dist/radio.d.ts +98 -0
  43. package/dist/radio.js +155 -0
  44. package/dist/radio.js.map +1 -0
  45. package/dist/select.cjs +272 -0
  46. package/dist/select.cjs.map +1 -0
  47. package/dist/select.d.cts +130 -0
  48. package/dist/select.d.ts +130 -0
  49. package/dist/select.js +268 -0
  50. package/dist/select.js.map +1 -0
  51. package/dist/textarea.cjs +423 -0
  52. package/dist/textarea.cjs.map +1 -0
  53. package/dist/textarea.d.cts +156 -0
  54. package/dist/textarea.d.ts +156 -0
  55. package/dist/textarea.js +420 -0
  56. package/dist/textarea.js.map +1 -0
  57. package/package.json +124 -0
@@ -0,0 +1,130 @@
1
+ import * as lit_html from 'lit-html';
2
+ import { LitElement } from 'lit';
3
+
4
+ declare const spectreSelectSizes: readonly ["sm", "md", "lg"];
5
+ type SpectreSelectSize = (typeof spectreSelectSizes)[number];
6
+ interface SpectreSelectProps {
7
+ autofocus?: boolean;
8
+ disabled?: boolean;
9
+ fullWidth?: boolean;
10
+ invalid?: boolean;
11
+ loading?: boolean;
12
+ name?: string;
13
+ pill?: boolean;
14
+ required?: boolean;
15
+ size?: SpectreSelectSize;
16
+ success?: boolean;
17
+ title?: string;
18
+ value?: string;
19
+ }
20
+ declare class SpectreSelectElement extends LitElement implements SpectreSelectProps {
21
+ static properties: {
22
+ ariaLabel: {
23
+ attribute: string;
24
+ type: StringConstructor;
25
+ };
26
+ ariaLabelledBy: {
27
+ attribute: string;
28
+ type: StringConstructor;
29
+ };
30
+ ariaDescribedBy: {
31
+ attribute: string;
32
+ type: StringConstructor;
33
+ };
34
+ autofocus: {
35
+ type: BooleanConstructor;
36
+ reflect: boolean;
37
+ };
38
+ disabled: {
39
+ type: BooleanConstructor;
40
+ reflect: boolean;
41
+ };
42
+ fullWidth: {
43
+ attribute: string;
44
+ type: BooleanConstructor;
45
+ reflect: boolean;
46
+ };
47
+ invalid: {
48
+ type: BooleanConstructor;
49
+ reflect: boolean;
50
+ };
51
+ loading: {
52
+ type: BooleanConstructor;
53
+ reflect: boolean;
54
+ };
55
+ name: {
56
+ type: StringConstructor;
57
+ };
58
+ pill: {
59
+ type: BooleanConstructor;
60
+ reflect: boolean;
61
+ };
62
+ required: {
63
+ type: BooleanConstructor;
64
+ reflect: boolean;
65
+ };
66
+ size: {
67
+ type: StringConstructor;
68
+ reflect: boolean;
69
+ };
70
+ success: {
71
+ type: BooleanConstructor;
72
+ reflect: boolean;
73
+ };
74
+ title: {
75
+ type: StringConstructor;
76
+ reflect: boolean;
77
+ };
78
+ value: {
79
+ type: StringConstructor;
80
+ };
81
+ };
82
+ ariaLabel: string | null;
83
+ ariaLabelledBy: string | null;
84
+ ariaDescribedBy: string | null;
85
+ autofocus: boolean;
86
+ disabled: boolean;
87
+ fullWidth: boolean;
88
+ invalid: boolean;
89
+ loading: boolean;
90
+ name?: string;
91
+ pill: boolean;
92
+ required: boolean;
93
+ size: SpectreSelectSize;
94
+ success: boolean;
95
+ title: string;
96
+ value: string;
97
+ private _id?;
98
+ private projectedOptions;
99
+ private contentObserver?;
100
+ get id(): string;
101
+ set id(value: string);
102
+ createRenderRoot(): this;
103
+ connectedCallback(): void;
104
+ disconnectedCallback(): void;
105
+ getAttribute(qualifiedName: string): string | null;
106
+ hasAttribute(qualifiedName: string): boolean;
107
+ setAttribute(qualifiedName: string, value: string): void;
108
+ removeAttribute(qualifiedName: string): void;
109
+ protected willUpdate(changedProperties: Map<PropertyKey, unknown>): void;
110
+ protected update(changedProperties: Map<PropertyKey, unknown>): void;
111
+ protected updated(changedProperties: Map<PropertyKey, unknown>): void;
112
+ private get selectClasses();
113
+ private get isDisabled();
114
+ private get nativeSelect();
115
+ private get forwardedAriaLabel();
116
+ private get forwardedAriaLabelledBy();
117
+ private get forwardedAriaDescribedBy();
118
+ private startContentObserver;
119
+ private stopContentObserver;
120
+ private syncProjectedOptions;
121
+ private isInternalSelectNode;
122
+ private handleInput;
123
+ private handleChange;
124
+ focus(options?: FocusOptions): void;
125
+ blur(): void;
126
+ render(): lit_html.TemplateResult<1>;
127
+ }
128
+ declare function defineSpectreSelect(tagName?: string): typeof SpectreSelectElement;
129
+
130
+ export { SpectreSelectElement, type SpectreSelectProps, type SpectreSelectSize, defineSpectreSelect, spectreSelectSizes };
@@ -0,0 +1,130 @@
1
+ import * as lit_html from 'lit-html';
2
+ import { LitElement } from 'lit';
3
+
4
+ declare const spectreSelectSizes: readonly ["sm", "md", "lg"];
5
+ type SpectreSelectSize = (typeof spectreSelectSizes)[number];
6
+ interface SpectreSelectProps {
7
+ autofocus?: boolean;
8
+ disabled?: boolean;
9
+ fullWidth?: boolean;
10
+ invalid?: boolean;
11
+ loading?: boolean;
12
+ name?: string;
13
+ pill?: boolean;
14
+ required?: boolean;
15
+ size?: SpectreSelectSize;
16
+ success?: boolean;
17
+ title?: string;
18
+ value?: string;
19
+ }
20
+ declare class SpectreSelectElement extends LitElement implements SpectreSelectProps {
21
+ static properties: {
22
+ ariaLabel: {
23
+ attribute: string;
24
+ type: StringConstructor;
25
+ };
26
+ ariaLabelledBy: {
27
+ attribute: string;
28
+ type: StringConstructor;
29
+ };
30
+ ariaDescribedBy: {
31
+ attribute: string;
32
+ type: StringConstructor;
33
+ };
34
+ autofocus: {
35
+ type: BooleanConstructor;
36
+ reflect: boolean;
37
+ };
38
+ disabled: {
39
+ type: BooleanConstructor;
40
+ reflect: boolean;
41
+ };
42
+ fullWidth: {
43
+ attribute: string;
44
+ type: BooleanConstructor;
45
+ reflect: boolean;
46
+ };
47
+ invalid: {
48
+ type: BooleanConstructor;
49
+ reflect: boolean;
50
+ };
51
+ loading: {
52
+ type: BooleanConstructor;
53
+ reflect: boolean;
54
+ };
55
+ name: {
56
+ type: StringConstructor;
57
+ };
58
+ pill: {
59
+ type: BooleanConstructor;
60
+ reflect: boolean;
61
+ };
62
+ required: {
63
+ type: BooleanConstructor;
64
+ reflect: boolean;
65
+ };
66
+ size: {
67
+ type: StringConstructor;
68
+ reflect: boolean;
69
+ };
70
+ success: {
71
+ type: BooleanConstructor;
72
+ reflect: boolean;
73
+ };
74
+ title: {
75
+ type: StringConstructor;
76
+ reflect: boolean;
77
+ };
78
+ value: {
79
+ type: StringConstructor;
80
+ };
81
+ };
82
+ ariaLabel: string | null;
83
+ ariaLabelledBy: string | null;
84
+ ariaDescribedBy: string | null;
85
+ autofocus: boolean;
86
+ disabled: boolean;
87
+ fullWidth: boolean;
88
+ invalid: boolean;
89
+ loading: boolean;
90
+ name?: string;
91
+ pill: boolean;
92
+ required: boolean;
93
+ size: SpectreSelectSize;
94
+ success: boolean;
95
+ title: string;
96
+ value: string;
97
+ private _id?;
98
+ private projectedOptions;
99
+ private contentObserver?;
100
+ get id(): string;
101
+ set id(value: string);
102
+ createRenderRoot(): this;
103
+ connectedCallback(): void;
104
+ disconnectedCallback(): void;
105
+ getAttribute(qualifiedName: string): string | null;
106
+ hasAttribute(qualifiedName: string): boolean;
107
+ setAttribute(qualifiedName: string, value: string): void;
108
+ removeAttribute(qualifiedName: string): void;
109
+ protected willUpdate(changedProperties: Map<PropertyKey, unknown>): void;
110
+ protected update(changedProperties: Map<PropertyKey, unknown>): void;
111
+ protected updated(changedProperties: Map<PropertyKey, unknown>): void;
112
+ private get selectClasses();
113
+ private get isDisabled();
114
+ private get nativeSelect();
115
+ private get forwardedAriaLabel();
116
+ private get forwardedAriaLabelledBy();
117
+ private get forwardedAriaDescribedBy();
118
+ private startContentObserver;
119
+ private stopContentObserver;
120
+ private syncProjectedOptions;
121
+ private isInternalSelectNode;
122
+ private handleInput;
123
+ private handleChange;
124
+ focus(options?: FocusOptions): void;
125
+ blur(): void;
126
+ render(): lit_html.TemplateResult<1>;
127
+ }
128
+ declare function defineSpectreSelect(tagName?: string): typeof SpectreSelectElement;
129
+
130
+ export { SpectreSelectElement, type SpectreSelectProps, type SpectreSelectSize, defineSpectreSelect, spectreSelectSizes };
package/dist/select.js ADDED
@@ -0,0 +1,268 @@
1
+ import { LitElement, nothing, html } from 'lit';
2
+ import { live } from 'lit/directives/live.js';
3
+ import { ifDefined } from 'lit/directives/if-defined.js';
4
+ import { getInputClasses } from '@phcdevworks/spectre-ui';
5
+
6
+ // src/components/select/sp-select.ts
7
+ var spectreSelectSizes = ["sm", "md", "lg"];
8
+ function isSelectSize(value) {
9
+ return spectreSelectSizes.includes(value);
10
+ }
11
+ function isSelectableContent(node) {
12
+ if (node.nodeType === Node.ELEMENT_NODE) {
13
+ const tagName = node.tagName;
14
+ return tagName === "OPTION" || tagName === "OPTGROUP";
15
+ }
16
+ if (node.nodeType === Node.TEXT_NODE) {
17
+ return (node.textContent?.trim().length ?? 0) > 0;
18
+ }
19
+ return false;
20
+ }
21
+ var SpectreSelectElement = class extends LitElement {
22
+ constructor() {
23
+ super(...arguments);
24
+ this.ariaLabel = null;
25
+ this.ariaLabelledBy = null;
26
+ this.ariaDescribedBy = null;
27
+ this.autofocus = false;
28
+ this.disabled = false;
29
+ this.fullWidth = false;
30
+ this.invalid = false;
31
+ this.loading = false;
32
+ this.pill = false;
33
+ this.required = false;
34
+ this.size = "md";
35
+ this.success = false;
36
+ this.title = "";
37
+ this.value = "";
38
+ this.projectedOptions = [];
39
+ }
40
+ get id() {
41
+ return this._id ?? "";
42
+ }
43
+ set id(value) {
44
+ if ((this._id ?? "") === value) {
45
+ return;
46
+ }
47
+ this._id = value;
48
+ const host = this;
49
+ if (HTMLElement.prototype.hasAttribute.call(host, "id")) {
50
+ HTMLElement.prototype.removeAttribute.call(host, "id");
51
+ }
52
+ this.requestUpdate();
53
+ }
54
+ createRenderRoot() {
55
+ return this;
56
+ }
57
+ connectedCallback() {
58
+ super.connectedCallback();
59
+ const hostId = super.getAttribute("id");
60
+ if (hostId !== null) {
61
+ this.id = hostId;
62
+ }
63
+ this.syncProjectedOptions();
64
+ this.startContentObserver();
65
+ }
66
+ disconnectedCallback() {
67
+ this.stopContentObserver();
68
+ super.disconnectedCallback();
69
+ }
70
+ getAttribute(qualifiedName) {
71
+ if (qualifiedName === "id") {
72
+ return this.id || null;
73
+ }
74
+ return super.getAttribute(qualifiedName);
75
+ }
76
+ hasAttribute(qualifiedName) {
77
+ if (qualifiedName === "id") {
78
+ return this.id !== "";
79
+ }
80
+ return super.hasAttribute(qualifiedName);
81
+ }
82
+ setAttribute(qualifiedName, value) {
83
+ if (qualifiedName === "id") {
84
+ this.id = value;
85
+ return;
86
+ }
87
+ super.setAttribute(qualifiedName, value);
88
+ }
89
+ removeAttribute(qualifiedName) {
90
+ if (qualifiedName === "id") {
91
+ this.id = "";
92
+ return;
93
+ }
94
+ super.removeAttribute(qualifiedName);
95
+ }
96
+ willUpdate(changedProperties) {
97
+ if (changedProperties.has("size") && !isSelectSize(this.size)) {
98
+ this.size = "md";
99
+ }
100
+ if (changedProperties.has("value") && this.value == null) {
101
+ this.value = "";
102
+ }
103
+ }
104
+ update(changedProperties) {
105
+ this.stopContentObserver();
106
+ super.update(changedProperties);
107
+ this.startContentObserver();
108
+ }
109
+ updated(changedProperties) {
110
+ super.updated(changedProperties);
111
+ const nativeSelect = this.nativeSelect;
112
+ if (!nativeSelect) {
113
+ return;
114
+ }
115
+ if (this.value !== "" && nativeSelect.value !== this.value) {
116
+ nativeSelect.value = this.value;
117
+ return;
118
+ }
119
+ if (this.value === "" && !this.hasAttribute("value")) {
120
+ const nativeValue = nativeSelect.value ?? "";
121
+ if (nativeValue !== "") {
122
+ this.value = nativeValue;
123
+ }
124
+ }
125
+ }
126
+ get selectClasses() {
127
+ return getInputClasses({
128
+ fullWidth: this.fullWidth,
129
+ pill: this.pill,
130
+ size: this.size,
131
+ state: this.isDisabled ? this.disabled ? "disabled" : "loading" : this.invalid ? "error" : this.success ? "success" : "default"
132
+ });
133
+ }
134
+ get isDisabled() {
135
+ return this.disabled || this.loading;
136
+ }
137
+ get nativeSelect() {
138
+ return this.querySelector("[data-sp-select-native]");
139
+ }
140
+ get forwardedAriaLabel() {
141
+ const ariaLabel = this.ariaLabel?.trim();
142
+ return ariaLabel ? ariaLabel : void 0;
143
+ }
144
+ get forwardedAriaLabelledBy() {
145
+ const ariaLabelledBy = this.ariaLabelledBy?.trim();
146
+ return ariaLabelledBy ? ariaLabelledBy : void 0;
147
+ }
148
+ get forwardedAriaDescribedBy() {
149
+ const ariaDescribedBy = this.ariaDescribedBy?.trim();
150
+ return ariaDescribedBy ? ariaDescribedBy : void 0;
151
+ }
152
+ startContentObserver() {
153
+ if (this.contentObserver) {
154
+ return;
155
+ }
156
+ this.contentObserver = new MutationObserver((mutations) => {
157
+ const isInternalMovement = mutations.every((mutation) => {
158
+ return Array.from(mutation.removedNodes).every(
159
+ (node) => this.isInternalSelectNode(node) || this.contains(node)
160
+ ) && Array.from(mutation.addedNodes).every((node) => this.isInternalSelectNode(node));
161
+ });
162
+ if (isInternalMovement) {
163
+ return;
164
+ }
165
+ if (this.syncProjectedOptions()) {
166
+ this.requestUpdate();
167
+ }
168
+ });
169
+ this.contentObserver.observe(this, {
170
+ childList: true
171
+ });
172
+ }
173
+ stopContentObserver() {
174
+ this.contentObserver?.disconnect();
175
+ this.contentObserver = void 0;
176
+ }
177
+ syncProjectedOptions() {
178
+ const nextProjectedOptions = [];
179
+ Array.from(this.childNodes).forEach((node) => {
180
+ if (this.isInternalSelectNode(node)) {
181
+ this.projectedOptions.forEach((projectedNode) => {
182
+ if (projectedNode.parentNode !== this && this.contains(projectedNode)) {
183
+ nextProjectedOptions.push(projectedNode);
184
+ }
185
+ });
186
+ return;
187
+ }
188
+ if (isSelectableContent(node)) {
189
+ nextProjectedOptions.push(node);
190
+ }
191
+ });
192
+ const hasChanged = nextProjectedOptions.length !== this.projectedOptions.length || nextProjectedOptions.some((node, index) => node !== this.projectedOptions[index]);
193
+ if (hasChanged) {
194
+ this.projectedOptions = nextProjectedOptions;
195
+ }
196
+ return hasChanged;
197
+ }
198
+ isInternalSelectNode(node) {
199
+ return node.nodeType === Node.ELEMENT_NODE && node.hasAttribute("data-sp-select-native");
200
+ }
201
+ handleInput(event) {
202
+ const select = event.currentTarget;
203
+ this.value = select.value;
204
+ }
205
+ handleChange(event) {
206
+ const select = event.currentTarget;
207
+ this.value = select.value;
208
+ }
209
+ focus(options) {
210
+ this.nativeSelect?.focus(options);
211
+ }
212
+ blur() {
213
+ this.nativeSelect?.blur();
214
+ }
215
+ render() {
216
+ return html`
217
+ <select
218
+ aria-busy=${this.loading ? "true" : "false"}
219
+ aria-describedby=${ifDefined(this.forwardedAriaDescribedBy)}
220
+ aria-invalid=${ifDefined(this.invalid ? "true" : void 0)}
221
+ aria-label=${ifDefined(this.forwardedAriaLabel)}
222
+ aria-labelledby=${ifDefined(this.forwardedAriaLabelledBy)}
223
+ ?autofocus=${this.autofocus}
224
+ class=${this.selectClasses}
225
+ data-sp-select-native
226
+ ?disabled=${this.isDisabled}
227
+ id=${ifDefined(this.id || void 0)}
228
+ name=${ifDefined(this.name)}
229
+ ?required=${this.required}
230
+ title=${ifDefined(this.title || void 0)}
231
+ .value=${live(this.value)}
232
+ @change=${this.handleChange}
233
+ @input=${this.handleInput}
234
+ >
235
+ ${this.projectedOptions.length > 0 ? this.projectedOptions : nothing}
236
+ </select>
237
+ `;
238
+ }
239
+ };
240
+ SpectreSelectElement.properties = {
241
+ ariaLabel: { attribute: "aria-label", type: String },
242
+ ariaLabelledBy: { attribute: "aria-labelledby", type: String },
243
+ ariaDescribedBy: { attribute: "aria-describedby", type: String },
244
+ autofocus: { type: Boolean, reflect: true },
245
+ disabled: { type: Boolean, reflect: true },
246
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
247
+ invalid: { type: Boolean, reflect: true },
248
+ loading: { type: Boolean, reflect: true },
249
+ name: { type: String },
250
+ pill: { type: Boolean, reflect: true },
251
+ required: { type: Boolean, reflect: true },
252
+ size: { type: String, reflect: true },
253
+ success: { type: Boolean, reflect: true },
254
+ title: { type: String, reflect: true },
255
+ value: { type: String }
256
+ };
257
+ function defineSpectreSelect(tagName = "sp-select") {
258
+ const existingElement = customElements.get(tagName);
259
+ if (existingElement) {
260
+ return existingElement;
261
+ }
262
+ customElements.define(tagName, SpectreSelectElement);
263
+ return SpectreSelectElement;
264
+ }
265
+
266
+ export { SpectreSelectElement, defineSpectreSelect, spectreSelectSizes };
267
+ //# sourceMappingURL=select.js.map
268
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/select/sp-select.ts"],"names":[],"mappings":"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","file":"select.js","sourcesContent":["import { LitElement, html, nothing } from 'lit';\nimport { live } from 'lit/directives/live.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\n\nimport {\n getInputClasses,\n type InputSize,\n} from '@phcdevworks/spectre-ui';\n\nexport const spectreSelectSizes = ['sm', 'md', 'lg'] as const;\n\nexport type SpectreSelectSize = (typeof spectreSelectSizes)[number];\n\nexport interface SpectreSelectProps {\n autofocus?: boolean;\n disabled?: boolean;\n fullWidth?: boolean;\n invalid?: boolean;\n loading?: boolean;\n name?: string;\n pill?: boolean;\n required?: boolean;\n size?: SpectreSelectSize;\n success?: boolean;\n title?: string;\n value?: string;\n}\n\nfunction isSelectSize(value: string): value is InputSize {\n return (spectreSelectSizes as readonly string[]).includes(value);\n}\n\nfunction isSelectableContent(node: Node): boolean {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const tagName = (node as Element).tagName;\n return tagName === 'OPTION' || tagName === 'OPTGROUP';\n }\n\n if (node.nodeType === Node.TEXT_NODE) {\n return (node.textContent?.trim().length ?? 0) > 0;\n }\n\n return false;\n}\n\nexport class SpectreSelectElement extends LitElement implements SpectreSelectProps {\n static properties = {\n ariaLabel: { attribute: 'aria-label', type: String },\n ariaLabelledBy: { attribute: 'aria-labelledby', type: String },\n ariaDescribedBy: { attribute: 'aria-describedby', type: String },\n autofocus: { type: Boolean, reflect: true },\n disabled: { type: Boolean, reflect: true },\n fullWidth: { attribute: 'full-width', type: Boolean, reflect: true },\n invalid: { type: Boolean, reflect: true },\n loading: { type: Boolean, reflect: true },\n name: { type: String },\n pill: { type: Boolean, reflect: true },\n required: { type: Boolean, reflect: true },\n size: { type: String, reflect: true },\n success: { type: Boolean, reflect: true },\n title: { type: String, reflect: true },\n value: { type: String },\n };\n\n ariaLabel: string | null = null;\n ariaLabelledBy: string | null = null;\n ariaDescribedBy: string | null = null;\n autofocus = false;\n disabled = false;\n fullWidth = false;\n invalid = false;\n loading = false;\n name?: string;\n pill = false;\n required = false;\n size: SpectreSelectSize = 'md';\n success = false;\n override title = '';\n value = '';\n private _id?: string;\n private projectedOptions: Node[] = [];\n private contentObserver?: MutationObserver | undefined;\n\n override get id(): string {\n return this._id ?? '';\n }\n\n override set id(value: string) {\n if ((this._id ?? '') === value) {\n return;\n }\n\n this._id = value;\n\n const host = this as unknown as HTMLElement;\n if (HTMLElement.prototype.hasAttribute.call(host, 'id')) {\n HTMLElement.prototype.removeAttribute.call(host, 'id');\n }\n\n this.requestUpdate();\n }\n\n createRenderRoot(): this {\n // Spectre components intentionally render in light DOM so the global\n // Spectre UI styling contract can apply directly.\n return this;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n const hostId = super.getAttribute('id');\n\n if (hostId !== null) {\n this.id = hostId;\n }\n\n this.syncProjectedOptions();\n this.startContentObserver();\n }\n\n override disconnectedCallback(): void {\n this.stopContentObserver();\n super.disconnectedCallback();\n }\n\n override getAttribute(qualifiedName: string): string | null {\n if (qualifiedName === 'id') {\n return this.id || null;\n }\n\n return super.getAttribute(qualifiedName);\n }\n\n override hasAttribute(qualifiedName: string): boolean {\n if (qualifiedName === 'id') {\n return this.id !== '';\n }\n\n return super.hasAttribute(qualifiedName);\n }\n\n override setAttribute(qualifiedName: string, value: string): void {\n if (qualifiedName === 'id') {\n this.id = value;\n return;\n }\n\n super.setAttribute(qualifiedName, value);\n }\n\n override removeAttribute(qualifiedName: string): void {\n if (qualifiedName === 'id') {\n this.id = '';\n return;\n }\n\n super.removeAttribute(qualifiedName);\n }\n\n protected override willUpdate(changedProperties: Map<PropertyKey, unknown>): void {\n if (changedProperties.has('size') && !isSelectSize(this.size)) {\n this.size = 'md';\n }\n\n if (changedProperties.has('value') && this.value == null) {\n this.value = '';\n }\n\n }\n\n protected override update(changedProperties: Map<PropertyKey, unknown>): void {\n this.stopContentObserver();\n super.update(changedProperties);\n this.startContentObserver();\n }\n\n protected override updated(changedProperties: Map<PropertyKey, unknown>): void {\n super.updated(changedProperties);\n\n const nativeSelect = this.nativeSelect;\n if (!nativeSelect) {\n return;\n }\n\n if (this.value !== '' && nativeSelect.value !== this.value) {\n nativeSelect.value = this.value;\n return;\n }\n\n if (this.value === '' && !this.hasAttribute('value')) {\n const nativeValue = nativeSelect.value ?? '';\n if (nativeValue !== '') {\n this.value = nativeValue;\n }\n }\n }\n\n private get selectClasses(): string {\n return getInputClasses({\n fullWidth: this.fullWidth,\n pill: this.pill,\n size: this.size,\n state: this.isDisabled\n ? this.disabled\n ? 'disabled'\n : 'loading'\n : this.invalid\n ? 'error'\n : this.success\n ? 'success'\n : 'default',\n });\n }\n\n private get isDisabled(): boolean {\n return this.disabled || this.loading;\n }\n\n private get nativeSelect(): HTMLSelectElement | null {\n return this.querySelector('[data-sp-select-native]');\n }\n\n private get forwardedAriaLabel(): string | undefined {\n const ariaLabel = this.ariaLabel?.trim();\n return ariaLabel ? ariaLabel : undefined;\n }\n\n private get forwardedAriaLabelledBy(): string | undefined {\n const ariaLabelledBy = this.ariaLabelledBy?.trim();\n return ariaLabelledBy ? ariaLabelledBy : undefined;\n }\n\n private get forwardedAriaDescribedBy(): string | undefined {\n const ariaDescribedBy = this.ariaDescribedBy?.trim();\n return ariaDescribedBy ? ariaDescribedBy : undefined;\n }\n\n private startContentObserver(): void {\n if (this.contentObserver) {\n return;\n }\n\n this.contentObserver = new MutationObserver((mutations) => {\n const isInternalMovement = mutations.every((mutation) => {\n return (\n Array.from(mutation.removedNodes).every(\n (node) => this.isInternalSelectNode(node) || this.contains(node),\n ) &&\n Array.from(mutation.addedNodes).every((node) => this.isInternalSelectNode(node))\n );\n });\n\n if (isInternalMovement) {\n return;\n }\n\n if (this.syncProjectedOptions()) {\n this.requestUpdate();\n }\n });\n\n this.contentObserver.observe(this, {\n childList: true,\n });\n }\n\n private stopContentObserver(): void {\n this.contentObserver?.disconnect();\n this.contentObserver = undefined;\n }\n\n private syncProjectedOptions(): boolean {\n const nextProjectedOptions: Node[] = [];\n\n Array.from(this.childNodes).forEach((node) => {\n if (this.isInternalSelectNode(node)) {\n this.projectedOptions.forEach((projectedNode) => {\n if (projectedNode.parentNode !== this && this.contains(projectedNode)) {\n nextProjectedOptions.push(projectedNode);\n }\n });\n return;\n }\n\n if (isSelectableContent(node)) {\n nextProjectedOptions.push(node);\n }\n });\n\n const hasChanged =\n nextProjectedOptions.length !== this.projectedOptions.length ||\n nextProjectedOptions.some((node, index) => node !== this.projectedOptions[index]);\n\n if (hasChanged) {\n this.projectedOptions = nextProjectedOptions;\n }\n\n return hasChanged;\n }\n\n private isInternalSelectNode(node: Node): boolean {\n return (\n node.nodeType === Node.ELEMENT_NODE && (node as Element).hasAttribute('data-sp-select-native')\n );\n }\n\n private handleInput(event: Event): void {\n const select = event.currentTarget as HTMLSelectElement;\n this.value = select.value;\n }\n\n private handleChange(event: Event): void {\n const select = event.currentTarget as HTMLSelectElement;\n this.value = select.value;\n }\n\n override focus(options?: FocusOptions): void {\n this.nativeSelect?.focus(options);\n }\n\n override blur(): void {\n this.nativeSelect?.blur();\n }\n\n\n override render() {\n return html`\n <select\n aria-busy=${this.loading ? 'true' : 'false'}\n aria-describedby=${ifDefined(this.forwardedAriaDescribedBy)}\n aria-invalid=${ifDefined(this.invalid ? 'true' : undefined)}\n aria-label=${ifDefined(this.forwardedAriaLabel)}\n aria-labelledby=${ifDefined(this.forwardedAriaLabelledBy)}\n ?autofocus=${this.autofocus}\n class=${this.selectClasses}\n data-sp-select-native\n ?disabled=${this.isDisabled}\n id=${ifDefined(this.id || undefined)}\n name=${ifDefined(this.name)}\n ?required=${this.required}\n title=${ifDefined(this.title || undefined)}\n .value=${live(this.value)}\n @change=${this.handleChange}\n @input=${this.handleInput}\n >\n ${this.projectedOptions.length > 0 ? this.projectedOptions : nothing}\n </select>\n `;\n }\n}\n\nexport function defineSpectreSelect(tagName = 'sp-select'): typeof SpectreSelectElement {\n const existingElement = customElements.get(tagName);\n\n if (existingElement) {\n return existingElement as unknown as typeof SpectreSelectElement;\n }\n\n customElements.define(tagName, SpectreSelectElement);\n return SpectreSelectElement;\n}\n"]}