@phcdevworks/spectre-components 1.4.0 → 1.5.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 (88) hide show
  1. package/README.md +164 -22
  2. package/dist/alert.cjs +455 -0
  3. package/dist/alert.cjs.map +1 -0
  4. package/dist/alert.d.cts +68 -0
  5. package/dist/alert.d.ts +68 -0
  6. package/dist/alert.js +450 -0
  7. package/dist/alert.js.map +1 -0
  8. package/dist/avatar.cjs +454 -0
  9. package/dist/avatar.cjs.map +1 -0
  10. package/dist/avatar.d.cts +74 -0
  11. package/dist/avatar.d.ts +74 -0
  12. package/dist/avatar.js +449 -0
  13. package/dist/avatar.js.map +1 -0
  14. package/dist/badge.cjs +5 -1
  15. package/dist/badge.cjs.map +1 -1
  16. package/dist/badge.d.cts +3 -2
  17. package/dist/badge.d.ts +3 -2
  18. package/dist/badge.js +5 -1
  19. package/dist/badge.js.map +1 -1
  20. package/dist/button.cjs.map +1 -1
  21. package/dist/button.d.cts +2 -2
  22. package/dist/button.d.ts +2 -2
  23. package/dist/button.js.map +1 -1
  24. package/dist/card.cjs +11 -2
  25. package/dist/card.cjs.map +1 -1
  26. package/dist/card.d.cts +3 -2
  27. package/dist/card.d.ts +3 -2
  28. package/dist/card.js +11 -2
  29. package/dist/card.js.map +1 -1
  30. package/dist/form-BumNzIay.d.cts +28 -0
  31. package/dist/form-BumNzIay.d.ts +28 -0
  32. package/dist/icon-box.cjs +5 -1
  33. package/dist/icon-box.cjs.map +1 -1
  34. package/dist/icon-box.d.cts +3 -2
  35. package/dist/icon-box.d.ts +3 -2
  36. package/dist/icon-box.js +5 -1
  37. package/dist/icon-box.js.map +1 -1
  38. package/dist/index.cjs +582 -9
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +6 -1
  41. package/dist/index.d.ts +6 -1
  42. package/dist/index.js +566 -11
  43. package/dist/index.js.map +1 -1
  44. package/dist/input.cjs.map +1 -1
  45. package/dist/input.d.cts +2 -2
  46. package/dist/input.d.ts +2 -2
  47. package/dist/input.js.map +1 -1
  48. package/dist/pricing-card.cjs +432 -0
  49. package/dist/pricing-card.cjs.map +1 -0
  50. package/dist/pricing-card.d.cts +60 -0
  51. package/dist/pricing-card.d.ts +60 -0
  52. package/dist/pricing-card.js +429 -0
  53. package/dist/pricing-card.js.map +1 -0
  54. package/dist/rating.cjs +6 -2
  55. package/dist/rating.cjs.map +1 -1
  56. package/dist/rating.d.cts +3 -2
  57. package/dist/rating.d.ts +3 -2
  58. package/dist/rating.js +6 -2
  59. package/dist/rating.js.map +1 -1
  60. package/dist/select.cjs.map +1 -1
  61. package/dist/select.d.cts +1 -1
  62. package/dist/select.d.ts +1 -1
  63. package/dist/select.js.map +1 -1
  64. package/dist/spinner.cjs +356 -0
  65. package/dist/spinner.cjs.map +1 -0
  66. package/dist/spinner.d.cts +52 -0
  67. package/dist/spinner.d.ts +52 -0
  68. package/dist/spinner.js +351 -0
  69. package/dist/spinner.js.map +1 -0
  70. package/dist/tag.cjs +473 -0
  71. package/dist/tag.cjs.map +1 -0
  72. package/dist/tag.d.cts +80 -0
  73. package/dist/tag.d.ts +80 -0
  74. package/dist/tag.js +468 -0
  75. package/dist/tag.js.map +1 -0
  76. package/dist/testimonial.cjs +14 -3
  77. package/dist/testimonial.cjs.map +1 -1
  78. package/dist/testimonial.d.cts +3 -2
  79. package/dist/testimonial.d.ts +3 -2
  80. package/dist/testimonial.js +14 -3
  81. package/dist/testimonial.js.map +1 -1
  82. package/dist/textarea.cjs.map +1 -1
  83. package/dist/textarea.d.cts +1 -1
  84. package/dist/textarea.d.ts +1 -1
  85. package/dist/textarea.js.map +1 -1
  86. package/package.json +36 -8
  87. package/dist/form-Dg6kuOS7.d.cts +0 -18
  88. package/dist/form-Dg6kuOS7.d.ts +0 -18
package/README.md CHANGED
@@ -627,6 +627,133 @@ recipe.
627
627
 
628
628
  **Internal target** — `[data-sp-testimonial-native]` selects the native `<div>`.
629
629
 
630
+ ---
631
+
632
+ ### sp-alert
633
+
634
+ Renders a `<div role="alert">` display primitive backed by the Spectre alert
635
+ recipe.
636
+
637
+ **Attributes**
638
+
639
+ | Attribute | Type | Default | Description |
640
+ | ------------------------- | ------------------------------------------------- | ------- | ------------------------------- |
641
+ | `variant` | `info \| success \| warning \| danger \| neutral` | `info` | Visual style |
642
+ | `size` | `sm \| md \| lg` | `md` | Alert size |
643
+ | `dismissed` | boolean | `false` | Dismissed visual state |
644
+ | `disabled` | boolean | `false` | Disabled visual state |
645
+ | `loading` | boolean | `false` | Busy visual state |
646
+ | `full-width` | boolean | `false` | Spans full container width |
647
+ | `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
648
+
649
+ **Content projection** — children become the alert content.
650
+
651
+ **Accessibility** — renders `role="alert"` and reflects the `loading` state to
652
+ `aria-busy`.
653
+
654
+ **Internal target** — `[data-sp-alert-native]` selects the native `<div>`.
655
+
656
+ ---
657
+
658
+ ### sp-avatar
659
+
660
+ Renders a `<div>` avatar container backed by the Spectre avatar recipe.
661
+
662
+ **Attributes**
663
+
664
+ | Attribute | Type | Default | Description |
665
+ | ------------------------- | ---------------------------- | -------- | -------------------------------- |
666
+ | `size` | `xs \| sm \| md \| lg \| xl` | `md` | Avatar size |
667
+ | `shape` | `circle \| square` | `circle` | Avatar shape |
668
+ | `interactive` | boolean | `false` | Applies interactive styling |
669
+ | `disabled` | boolean | `false` | Disabled visual state |
670
+ | `loading` | boolean | `false` | Busy visual state |
671
+ | `full-width` | boolean | `false` | Spans full container width |
672
+ | `placeholder` | boolean | `false` | Placeholder background and color |
673
+ | `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
674
+
675
+ **Content projection** — children become the avatar content (an `<img>`,
676
+ initials, or an icon).
677
+
678
+ **Accessibility** — reflects the `loading` state to `aria-busy`.
679
+
680
+ **Internal target** — `[data-sp-avatar-native]` selects the native `<div>`.
681
+
682
+ ---
683
+
684
+ ### sp-spinner
685
+
686
+ Renders a `<div role="status">` loading indicator backed by the Spectre spinner
687
+ recipe.
688
+
689
+ **Attributes**
690
+
691
+ | Attribute | Type | Default | Description |
692
+ | ------------------------- | ------------------------------------------------------------------------------------------ | ------- | ------------------------------- |
693
+ | `variant` | `primary \| secondary \| success \| warning \| danger \| info \| neutral \| accent \| cta` | — | Arc color |
694
+ | `size` | `sm \| md \| lg` | `md` | Spinner size |
695
+ | `disabled` | boolean | `false` | Disabled visual state |
696
+ | `loading` | boolean | `true` | Busy visual state |
697
+ | `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
698
+
699
+ **Accessibility** — renders `role="status"` and reflects the `loading` state to
700
+ `aria-busy`. Defaults `aria-label` to `Loading` unless `aria-label` is provided.
701
+
702
+ **Internal target** — `[data-sp-spinner-native]` selects the native `<div>`.
703
+
704
+ ---
705
+
706
+ ### sp-tag
707
+
708
+ Renders a `<span>` tag/chip backed by the Spectre tag recipe.
709
+
710
+ **Attributes**
711
+
712
+ | Attribute | Type | Default | Description |
713
+ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------- | --------------------------------- |
714
+ | `variant` | `default \| primary \| secondary \| success \| warning \| danger \| info \| neutral \| accent \| cta \| outline \| ghost` | `default` | Tag color |
715
+ | `size` | `sm \| md \| lg` | `md` | Tag size |
716
+ | `interactive` | boolean | `false` | Applies interactive styling |
717
+ | `selected` | boolean | `false` | Selected/active visual state |
718
+ | `dismissible` | boolean | `false` | Reserves space for a dismiss icon |
719
+ | `disabled` | boolean | `false` | Disabled visual state |
720
+ | `loading` | boolean | `false` | Busy visual state |
721
+ | `full-width` | boolean | `false` | Spans full container width |
722
+ | `id` / `title` / `aria-*` | string | — | Forwarded to the native `<span>` |
723
+
724
+ **Content projection** — children become the tag label (and any projected
725
+ dismiss icon).
726
+
727
+ **Accessibility** — reflects the `loading` state to `aria-busy`.
728
+
729
+ **Internal target** — `[data-sp-tag-native]` selects the native `<span>`.
730
+
731
+ ---
732
+
733
+ ### sp-pricing-card
734
+
735
+ Renders a `<div>` pricing card container backed by the Spectre pricing-card
736
+ recipe.
737
+
738
+ **Attributes**
739
+
740
+ | Attribute | Type | Default | Description |
741
+ | ------------------------- | ------- | ------- | ------------------------------- |
742
+ | `featured` | boolean | `false` | Highlights the card as featured |
743
+ | `interactive` | boolean | `false` | Applies interactive styling |
744
+ | `disabled` | boolean | `false` | Disabled visual state |
745
+ | `loading` | boolean | `false` | Busy visual state |
746
+ | `full-height` | boolean | `false` | Spans full container height |
747
+ | `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
748
+
749
+ **Content projection** — children become the pricing card content (heading,
750
+ price, feature list, call-to-action, etc.).
751
+
752
+ **Accessibility** — reflects the `loading` state to `aria-busy`.
753
+
754
+ **Internal target** — `[data-sp-pricing-card-native]` selects the native
755
+ `<div>`.
756
+
630
757
  ## Package exports / API surface
631
758
 
632
759
  ### Root — `@phcdevworks/spectre-components`
@@ -646,13 +773,16 @@ defineSpectreComponents() // registers all sp-* elements
646
773
  `defineSpectreSelect`, `defineSpectreCheckbox`, `defineSpectreRadio`,
647
774
  `defineSpectreLabel`, `defineSpectreFieldset`, `defineSpectreBadge`,
648
775
  `defineSpectreCard`, `defineSpectreIconBox`, `defineSpectreRating`,
649
- `defineSpectreTestimonial`
776
+ `defineSpectreTestimonial`, `defineSpectreAlert`, `defineSpectreAvatar`,
777
+ `defineSpectreSpinner`, `defineSpectreTag`, `defineSpectrePricingCard`
650
778
 
651
779
  **Element classes**: `SpectreButtonElement`, `SpectreInputElement`,
652
780
  `SpectreTextareaElement`, `SpectreSelectElement`, `SpectreCheckboxElement`,
653
781
  `SpectreRadioElement`, `SpectreLabelElement`, `SpectreFieldsetElement`,
654
782
  `SpectreBadgeElement`, `SpectreCardElement`, `SpectreIconBoxElement`,
655
- `SpectreRatingElement`, `SpectreTestimonialElement`
783
+ `SpectreRatingElement`, `SpectreTestimonialElement`, `SpectreAlertElement`,
784
+ `SpectreAvatarElement`, `SpectreSpinnerElement`, `SpectreTagElement`,
785
+ `SpectrePricingCardElement`
656
786
 
657
787
  **Button constants and types**: `spectreButtonVariants`, `spectreButtonSizes`,
658
788
  `spectreButtonTypes`, `SpectreButtonVariant`, `SpectreButtonSize`,
@@ -668,31 +798,43 @@ defineSpectreComponents() // registers all sp-* elements
668
798
 
669
799
  **Display constants and types**: `spectreBadgeVariants`, `spectreBadgeSizes`,
670
800
  `spectreCardVariants`, `spectreIconBoxVariants`, `spectreIconBoxSizes`,
671
- `spectreRatingSizes`, `spectreTestimonialVariants`, `SpectreBadgeVariant`,
672
- `SpectreBadgeSize`, `SpectreCardVariant`, `SpectreIconBoxVariant`,
673
- `SpectreIconBoxSize`, `SpectreRatingSize`, `SpectreTestimonialVariant`,
674
- `SpectreBadgeProps`, `SpectreCardProps`, `SpectreIconBoxProps`,
675
- `SpectreRatingProps`, `SpectreTestimonialProps`
801
+ `spectreRatingSizes`, `spectreTestimonialVariants`, `spectreAlertVariants`,
802
+ `spectreAlertSizes`, `spectreAvatarShapes`, `spectreAvatarSizes`,
803
+ `spectreSpinnerVariants`, `spectreSpinnerSizes`, `spectreTagVariants`,
804
+ `spectreTagSizes`, `SpectreBadgeVariant`, `SpectreBadgeSize`,
805
+ `SpectreCardVariant`, `SpectreIconBoxVariant`, `SpectreIconBoxSize`,
806
+ `SpectreRatingSize`, `SpectreTestimonialVariant`, `SpectreAlertVariant`,
807
+ `SpectreAlertSize`, `SpectreAvatarShape`, `SpectreAvatarSize`,
808
+ `SpectreSpinnerVariant`, `SpectreSpinnerSize`, `SpectreTagVariant`,
809
+ `SpectreTagSize`, `SpectreBadgeProps`, `SpectreCardProps`,
810
+ `SpectreIconBoxProps`, `SpectreRatingProps`, `SpectreTestimonialProps`,
811
+ `SpectreAlertProps`, `SpectreAvatarProps`, `SpectreSpinnerProps`,
812
+ `SpectreTagProps`, `SpectrePricingCardProps`
676
813
 
677
814
  ### Subpath entry points
678
815
 
679
816
  Each entry point registers only that component and exports only its surface:
680
817
 
681
- | Entry point | Registers | Key exports |
682
- | ----------------- | ---------------- | ---------------------------------------------------------------------------------------- |
683
- | `.../button` | `sp-button` | `defineSpectreButton`, `SpectreButtonElement`, button constants and types |
684
- | `.../input` | `sp-input` | `defineSpectreInput`, `SpectreInputElement`, input constants and types |
685
- | `.../textarea` | `sp-textarea` | `defineSpectreTextarea`, `SpectreTextareaElement`, `SpectreTextareaProps` |
686
- | `.../select` | `sp-select` | `defineSpectreSelect`, `SpectreSelectElement`, `SpectreSelectProps` |
687
- | `.../checkbox` | `sp-checkbox` | `defineSpectreCheckbox`, `SpectreCheckboxElement`, `SpectreCheckboxProps` |
688
- | `.../radio` | `sp-radio` | `defineSpectreRadio`, `SpectreRadioElement`, `SpectreRadioProps` |
689
- | `.../label` | `sp-label` | `defineSpectreLabel`, `SpectreLabelElement`, `SpectreLabelProps` |
690
- | `.../fieldset` | `sp-fieldset` | `defineSpectreFieldset`, `SpectreFieldsetElement`, `SpectreFieldsetProps` |
691
- | `.../badge` | `sp-badge` | `defineSpectreBadge`, `SpectreBadgeElement`, badge constants and types |
692
- | `.../card` | `sp-card` | `defineSpectreCard`, `SpectreCardElement`, card constants and types |
693
- | `.../icon-box` | `sp-icon-box` | `defineSpectreIconBox`, `SpectreIconBoxElement`, icon-box constants and types |
694
- | `.../rating` | `sp-rating` | `defineSpectreRating`, `SpectreRatingElement`, rating constants and types |
695
- | `.../testimonial` | `sp-testimonial` | `defineSpectreTestimonial`, `SpectreTestimonialElement`, testimonial constants and types |
818
+ | Entry point | Registers | Key exports |
819
+ | ------------------ | ----------------- | ---------------------------------------------------------------------------------------- |
820
+ | `.../button` | `sp-button` | `defineSpectreButton`, `SpectreButtonElement`, button constants and types |
821
+ | `.../input` | `sp-input` | `defineSpectreInput`, `SpectreInputElement`, input constants and types |
822
+ | `.../textarea` | `sp-textarea` | `defineSpectreTextarea`, `SpectreTextareaElement`, `SpectreTextareaProps` |
823
+ | `.../select` | `sp-select` | `defineSpectreSelect`, `SpectreSelectElement`, `SpectreSelectProps` |
824
+ | `.../checkbox` | `sp-checkbox` | `defineSpectreCheckbox`, `SpectreCheckboxElement`, `SpectreCheckboxProps` |
825
+ | `.../radio` | `sp-radio` | `defineSpectreRadio`, `SpectreRadioElement`, `SpectreRadioProps` |
826
+ | `.../label` | `sp-label` | `defineSpectreLabel`, `SpectreLabelElement`, `SpectreLabelProps` |
827
+ | `.../fieldset` | `sp-fieldset` | `defineSpectreFieldset`, `SpectreFieldsetElement`, `SpectreFieldsetProps` |
828
+ | `.../badge` | `sp-badge` | `defineSpectreBadge`, `SpectreBadgeElement`, badge constants and types |
829
+ | `.../card` | `sp-card` | `defineSpectreCard`, `SpectreCardElement`, card constants and types |
830
+ | `.../icon-box` | `sp-icon-box` | `defineSpectreIconBox`, `SpectreIconBoxElement`, icon-box constants and types |
831
+ | `.../rating` | `sp-rating` | `defineSpectreRating`, `SpectreRatingElement`, rating constants and types |
832
+ | `.../testimonial` | `sp-testimonial` | `defineSpectreTestimonial`, `SpectreTestimonialElement`, testimonial constants and types |
833
+ | `.../alert` | `sp-alert` | `defineSpectreAlert`, `SpectreAlertElement`, alert constants and types |
834
+ | `.../avatar` | `sp-avatar` | `defineSpectreAvatar`, `SpectreAvatarElement`, avatar constants and types |
835
+ | `.../spinner` | `sp-spinner` | `defineSpectreSpinner`, `SpectreSpinnerElement`, spinner constants and types |
836
+ | `.../tag` | `sp-tag` | `defineSpectreTag`, `SpectreTagElement`, tag constants and types |
837
+ | `.../pricing-card` | `sp-pricing-card` | `defineSpectrePricingCard`, `SpectrePricingCardElement`, `SpectrePricingCardProps` |
696
838
 
697
839
  Size constants are shared between input, textarea, and select. Import
698
840
  `spectreInputSizes` / `SpectreInputSize` from `.../input` when needed alongside
package/dist/alert.cjs ADDED
@@ -0,0 +1,455 @@
1
+ 'use strict';
2
+
3
+ var spectreUi = require('@phcdevworks/spectre-ui');
4
+ var lit = require('lit');
5
+ var ifDefined_js = require('lit/directives/if-defined.js');
6
+
7
+ // src/utils/form.ts
8
+ var spectreInputSizes = ["sm", "md", "lg"];
9
+ function isInputSize(value) {
10
+ return spectreInputSizes.includes(value);
11
+ }
12
+ var spectreAlertVariants = [
13
+ "info",
14
+ "success",
15
+ "warning",
16
+ "danger",
17
+ "neutral"
18
+ ];
19
+ function isAlertVariant(value) {
20
+ return spectreAlertVariants.includes(value);
21
+ }
22
+ var SpectreBaseElement = class extends lit.LitElement {
23
+ constructor() {
24
+ super(...arguments);
25
+ this._ariaLabel = null;
26
+ this._ariaLabelledBy = null;
27
+ this._ariaDescribedBy = null;
28
+ this._autocapitalize = "";
29
+ this._autofocus = false;
30
+ this._spellcheck = null;
31
+ this._title = "";
32
+ this._id = "";
33
+ }
34
+ get ariaLabel() {
35
+ return this._ariaLabel;
36
+ }
37
+ set ariaLabel(value) {
38
+ if (this._ariaLabel === value) {
39
+ return;
40
+ }
41
+ this._ariaLabel = value;
42
+ this._removeHostAttribute("aria-label");
43
+ this.requestUpdate();
44
+ }
45
+ get ariaLabelledBy() {
46
+ return this._ariaLabelledBy;
47
+ }
48
+ set ariaLabelledBy(value) {
49
+ if (this._ariaLabelledBy === value) {
50
+ return;
51
+ }
52
+ this._ariaLabelledBy = value;
53
+ this._removeHostAttribute("aria-labelledby");
54
+ this.requestUpdate();
55
+ }
56
+ get ariaDescribedBy() {
57
+ return this._ariaDescribedBy;
58
+ }
59
+ set ariaDescribedBy(value) {
60
+ if (this._ariaDescribedBy === value) {
61
+ return;
62
+ }
63
+ this._ariaDescribedBy = value;
64
+ this._removeHostAttribute("aria-describedby");
65
+ this.requestUpdate();
66
+ }
67
+ get autocapitalize() {
68
+ return this._autocapitalize;
69
+ }
70
+ set autocapitalize(value) {
71
+ const normalizedValue = value ?? "";
72
+ if (this._autocapitalize === normalizedValue) {
73
+ return;
74
+ }
75
+ this._autocapitalize = normalizedValue;
76
+ this._removeHostAttribute("autocapitalize");
77
+ this.requestUpdate();
78
+ }
79
+ get spellcheck() {
80
+ return this._spellcheck ?? super.spellcheck;
81
+ }
82
+ set spellcheck(value) {
83
+ if (this._spellcheck === value) {
84
+ return;
85
+ }
86
+ this._spellcheck = value ?? null;
87
+ this._removeHostAttribute("spellcheck");
88
+ this.requestUpdate();
89
+ }
90
+ get title() {
91
+ return this._title;
92
+ }
93
+ set title(value) {
94
+ const normalizedValue = value ?? "";
95
+ if (this._title === normalizedValue) {
96
+ return;
97
+ }
98
+ this._title = normalizedValue;
99
+ this._removeHostAttribute("title");
100
+ this.requestUpdate();
101
+ }
102
+ get id() {
103
+ return this._id;
104
+ }
105
+ set id(value) {
106
+ const normalizedValue = value ?? "";
107
+ if (this._id === normalizedValue) {
108
+ return;
109
+ }
110
+ this._id = normalizedValue;
111
+ this._removeHostAttribute("id");
112
+ this.requestUpdate();
113
+ }
114
+ get autofocus() {
115
+ return this._autofocus;
116
+ }
117
+ set autofocus(value) {
118
+ const normalizedValue = !!value;
119
+ if (this._autofocus === normalizedValue) {
120
+ return;
121
+ }
122
+ this._autofocus = normalizedValue;
123
+ this._removeHostAttribute("autofocus");
124
+ this.requestUpdate();
125
+ }
126
+ // Spectre components intentionally render in light DOM so the global
127
+ // `@phcdevworks/spectre-ui` styling contract can apply directly.
128
+ createRenderRoot() {
129
+ return this;
130
+ }
131
+ connectedCallback() {
132
+ super.connectedCallback();
133
+ const proxiedAttributes = [
134
+ "id",
135
+ "title",
136
+ "autocapitalize",
137
+ "autofocus",
138
+ "spellcheck",
139
+ "aria-label",
140
+ "aria-labelledby",
141
+ "aria-describedby"
142
+ ];
143
+ proxiedAttributes.forEach((attr) => {
144
+ const value = super.getAttribute(attr);
145
+ if (value !== null) {
146
+ this.setAttribute(attr, value);
147
+ }
148
+ });
149
+ }
150
+ getAttribute(qualifiedName) {
151
+ switch (qualifiedName) {
152
+ case "id":
153
+ return this.id || null;
154
+ case "title":
155
+ return this.title || null;
156
+ case "autocapitalize":
157
+ return this.autocapitalize || null;
158
+ case "autofocus":
159
+ return this.autofocus ? "" : null;
160
+ case "spellcheck":
161
+ return this._spellcheck !== null ? String(this._spellcheck) : null;
162
+ case "aria-label":
163
+ return this.ariaLabel;
164
+ case "aria-labelledby":
165
+ return this.ariaLabelledBy;
166
+ case "aria-describedby":
167
+ return this.ariaDescribedBy;
168
+ default:
169
+ return super.getAttribute(qualifiedName);
170
+ }
171
+ }
172
+ hasAttribute(qualifiedName) {
173
+ switch (qualifiedName) {
174
+ case "id":
175
+ return this.id !== "";
176
+ case "title":
177
+ return this.title !== "";
178
+ case "autocapitalize":
179
+ return this.autocapitalize !== "";
180
+ case "autofocus":
181
+ return this.autofocus;
182
+ case "spellcheck":
183
+ return this._spellcheck !== null;
184
+ case "aria-label":
185
+ return this.ariaLabel !== null;
186
+ case "aria-labelledby":
187
+ return this.ariaLabelledBy !== null;
188
+ case "aria-describedby":
189
+ return this.ariaDescribedBy !== null;
190
+ default:
191
+ return super.hasAttribute(qualifiedName);
192
+ }
193
+ }
194
+ setAttribute(qualifiedName, value) {
195
+ switch (qualifiedName) {
196
+ case "id":
197
+ this.id = value;
198
+ break;
199
+ case "title":
200
+ this.title = value;
201
+ break;
202
+ case "autocapitalize":
203
+ this.autocapitalize = value;
204
+ break;
205
+ case "autofocus":
206
+ this.autofocus = true;
207
+ break;
208
+ case "spellcheck":
209
+ this.spellcheck = value !== "false";
210
+ break;
211
+ case "aria-label":
212
+ this.ariaLabel = value;
213
+ break;
214
+ case "aria-labelledby":
215
+ this.ariaLabelledBy = value;
216
+ break;
217
+ case "aria-describedby":
218
+ this.ariaDescribedBy = value;
219
+ break;
220
+ default:
221
+ super.setAttribute(qualifiedName, value);
222
+ }
223
+ }
224
+ removeAttribute(qualifiedName) {
225
+ switch (qualifiedName) {
226
+ case "id":
227
+ this.id = "";
228
+ break;
229
+ case "title":
230
+ this.title = "";
231
+ break;
232
+ case "autocapitalize":
233
+ this.autocapitalize = "";
234
+ break;
235
+ case "autofocus":
236
+ this.autofocus = false;
237
+ break;
238
+ case "spellcheck":
239
+ this.spellcheck = null;
240
+ break;
241
+ case "aria-label":
242
+ this.ariaLabel = null;
243
+ break;
244
+ case "aria-labelledby":
245
+ this.ariaLabelledBy = null;
246
+ break;
247
+ case "aria-describedby":
248
+ this.ariaDescribedBy = null;
249
+ break;
250
+ default:
251
+ super.removeAttribute(qualifiedName);
252
+ }
253
+ }
254
+ _removeHostAttribute(name) {
255
+ const host = this;
256
+ if (HTMLElement.prototype.hasAttribute.call(host, name)) {
257
+ HTMLElement.prototype.removeAttribute.call(host, name);
258
+ }
259
+ }
260
+ get forwardedAriaLabel() {
261
+ const value = this.ariaLabel?.trim();
262
+ return value ? value : void 0;
263
+ }
264
+ get forwardedAriaLabelledBy() {
265
+ const value = this.ariaLabelledBy?.trim();
266
+ return value ? value : void 0;
267
+ }
268
+ get forwardedAriaDescribedBy() {
269
+ const value = this.ariaDescribedBy?.trim();
270
+ return value ? value : void 0;
271
+ }
272
+ };
273
+ SpectreBaseElement.properties = {};
274
+
275
+ // src/utils/dom.ts
276
+ function hasMeaningfulContent(nodes) {
277
+ return nodes.some((node) => {
278
+ if (node.nodeType === Node.ELEMENT_NODE) {
279
+ return true;
280
+ }
281
+ if (node.nodeType === Node.TEXT_NODE) {
282
+ return (node.textContent?.trim().length ?? 0) > 0;
283
+ }
284
+ return false;
285
+ });
286
+ }
287
+
288
+ // src/utils/projectable.ts
289
+ var SpectreProjectableElement = class extends SpectreBaseElement {
290
+ constructor() {
291
+ super(...arguments);
292
+ this.projectedContent = [];
293
+ }
294
+ get hasProjectedContent() {
295
+ return hasMeaningfulContent(this.projectedContent);
296
+ }
297
+ connectedCallback() {
298
+ super.connectedCallback();
299
+ this.syncProjectedContent();
300
+ this.startContentObserver();
301
+ }
302
+ disconnectedCallback() {
303
+ this.stopContentObserver();
304
+ super.disconnectedCallback();
305
+ }
306
+ update(changedProperties) {
307
+ this.stopContentObserver();
308
+ super.update(changedProperties);
309
+ this.startContentObserver();
310
+ }
311
+ syncProjectedContent() {
312
+ const nextProjectedContent = [];
313
+ const sourceNodes = [
314
+ ...this.childNodes,
315
+ ...this.getContentContainer()?.childNodes ?? []
316
+ ];
317
+ sourceNodes.forEach((node) => {
318
+ if (!this.isInternalNode(node) && !nextProjectedContent.includes(node)) {
319
+ nextProjectedContent.push(node);
320
+ }
321
+ });
322
+ const hasChanged = nextProjectedContent.length !== this.projectedContent.length || nextProjectedContent.some((node, index) => node !== this.projectedContent[index]);
323
+ if (hasChanged) {
324
+ this.projectedContent = nextProjectedContent;
325
+ }
326
+ return hasChanged;
327
+ }
328
+ startContentObserver() {
329
+ if (this.contentObserver) {
330
+ return;
331
+ }
332
+ this.contentObserver = new MutationObserver((mutations) => {
333
+ const isInternalMovement = mutations.every(
334
+ (mutation) => [...mutation.removedNodes].every(
335
+ (node) => this.isInternalNode(node) || this.contains(node)
336
+ ) && [...mutation.addedNodes].every((node) => this.isInternalNode(node))
337
+ );
338
+ if (isInternalMovement) {
339
+ return;
340
+ }
341
+ if (this.syncProjectedContent()) {
342
+ this.requestUpdate();
343
+ }
344
+ });
345
+ this.contentObserver.observe(this, { childList: true });
346
+ }
347
+ stopContentObserver() {
348
+ this.contentObserver?.disconnect();
349
+ this.contentObserver = void 0;
350
+ }
351
+ };
352
+ var SpectreAlertElement = class extends SpectreProjectableElement {
353
+ constructor() {
354
+ super(...arguments);
355
+ this.dismissed = false;
356
+ this.disabled = false;
357
+ this.fullWidth = false;
358
+ this.loading = false;
359
+ this.size = "md";
360
+ this.variant = "info";
361
+ }
362
+ get id() {
363
+ return super.id;
364
+ }
365
+ set id(value) {
366
+ super.id = value;
367
+ }
368
+ get title() {
369
+ return super.title;
370
+ }
371
+ set title(value) {
372
+ super.title = value;
373
+ }
374
+ getContentContainer() {
375
+ return this.querySelector("[data-sp-alert-native]");
376
+ }
377
+ isInternalNode(node) {
378
+ if (node.nodeType !== Node.ELEMENT_NODE) {
379
+ return false;
380
+ }
381
+ const el = node;
382
+ return el.hasAttribute("data-sp-alert-native");
383
+ }
384
+ willUpdate(changedProperties) {
385
+ if (changedProperties.has("dismissed") && this.dismissed == null) {
386
+ this.dismissed = false;
387
+ }
388
+ if (changedProperties.has("disabled") && this.disabled == null) {
389
+ this.disabled = false;
390
+ }
391
+ if (changedProperties.has("fullWidth") && this.fullWidth == null) {
392
+ this.fullWidth = false;
393
+ }
394
+ if (changedProperties.has("loading") && this.loading == null) {
395
+ this.loading = false;
396
+ }
397
+ if (changedProperties.has("variant") && (this.variant == null || !isAlertVariant(this.variant))) {
398
+ this.variant = "info";
399
+ }
400
+ if (changedProperties.has("size") && (this.size == null || !isInputSize(this.size))) {
401
+ this.size = "md";
402
+ }
403
+ }
404
+ get alertClasses() {
405
+ return spectreUi.getAlertClasses({
406
+ disabled: this.isDisabled,
407
+ dismissed: this.dismissed ?? false,
408
+ fullWidth: this.fullWidth ?? false,
409
+ loading: this.loading ?? false,
410
+ size: this.size,
411
+ variant: this.variant
412
+ });
413
+ }
414
+ get isDisabled() {
415
+ return (this.disabled ?? false) || (this.loading ?? false);
416
+ }
417
+ render() {
418
+ return lit.html`<div
419
+ aria-busy="${this.loading ? "true" : "false"}"
420
+ aria-describedby="${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}"
421
+ aria-label="${ifDefined_js.ifDefined(this.forwardedAriaLabel)}"
422
+ aria-labelledby="${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}"
423
+ class="${this.alertClasses}"
424
+ data-sp-alert-native
425
+ id="${ifDefined_js.ifDefined(this.id || void 0)}"
426
+ role="alert"
427
+ title="${ifDefined_js.ifDefined(this.title || void 0)}"
428
+ >
429
+ ${this.hasProjectedContent ? this.projectedContent : lit.nothing}
430
+ </div>`;
431
+ }
432
+ };
433
+ SpectreAlertElement.properties = {
434
+ dismissed: { type: Boolean, reflect: true },
435
+ disabled: { type: Boolean, reflect: true },
436
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
437
+ loading: { type: Boolean, reflect: true },
438
+ size: { type: String, reflect: true },
439
+ variant: { type: String, reflect: true }
440
+ };
441
+ function defineSpectreAlert(tagName = "sp-alert") {
442
+ const existingElement = customElements.get(tagName);
443
+ if (existingElement) {
444
+ return existingElement;
445
+ }
446
+ customElements.define(tagName, SpectreAlertElement);
447
+ return SpectreAlertElement;
448
+ }
449
+
450
+ exports.SpectreAlertElement = SpectreAlertElement;
451
+ exports.defineSpectreAlert = defineSpectreAlert;
452
+ exports.spectreAlertSizes = spectreInputSizes;
453
+ exports.spectreAlertVariants = spectreAlertVariants;
454
+ //# sourceMappingURL=alert.cjs.map
455
+ //# sourceMappingURL=alert.cjs.map