@phcdevworks/spectre-components 1.20.0 → 1.21.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 (350) hide show
  1. package/README.md +672 -49
  2. package/dist/accordion-item.cjs +540 -0
  3. package/dist/accordion-item.cjs.map +1 -0
  4. package/dist/accordion-item.d.cts +59 -0
  5. package/dist/accordion-item.d.ts +59 -0
  6. package/dist/accordion-item.js +537 -0
  7. package/dist/accordion-item.js.map +1 -0
  8. package/dist/accordion.cjs +468 -0
  9. package/dist/accordion.cjs.map +1 -0
  10. package/dist/accordion.d.cts +38 -0
  11. package/dist/accordion.d.ts +38 -0
  12. package/dist/accordion.js +465 -0
  13. package/dist/accordion.js.map +1 -0
  14. package/dist/alert.cjs +166 -65
  15. package/dist/alert.cjs.map +1 -1
  16. package/dist/alert.d.cts +41 -8
  17. package/dist/alert.d.ts +41 -8
  18. package/dist/alert.js +168 -67
  19. package/dist/alert.js.map +1 -1
  20. package/dist/avatar.cjs +27 -1
  21. package/dist/avatar.cjs.map +1 -1
  22. package/dist/avatar.d.cts +19 -3
  23. package/dist/avatar.d.ts +19 -3
  24. package/dist/avatar.js +27 -1
  25. package/dist/avatar.js.map +1 -1
  26. package/dist/badge.cjs +35 -2
  27. package/dist/badge.cjs.map +1 -1
  28. package/dist/badge.d.cts +31 -3
  29. package/dist/badge.d.ts +31 -3
  30. package/dist/badge.js +35 -2
  31. package/dist/badge.js.map +1 -1
  32. package/dist/breadcrumb.cjs +464 -0
  33. package/dist/breadcrumb.cjs.map +1 -0
  34. package/dist/breadcrumb.d.cts +32 -0
  35. package/dist/breadcrumb.d.ts +32 -0
  36. package/dist/breadcrumb.js +461 -0
  37. package/dist/breadcrumb.js.map +1 -0
  38. package/dist/button.cjs +32 -2
  39. package/dist/button.cjs.map +1 -1
  40. package/dist/button.d.cts +19 -3
  41. package/dist/button.d.ts +19 -3
  42. package/dist/button.js +32 -2
  43. package/dist/button.js.map +1 -1
  44. package/dist/card-bleed.cjs +458 -0
  45. package/dist/card-bleed.cjs.map +1 -0
  46. package/dist/card-bleed.d.cts +37 -0
  47. package/dist/card-bleed.d.ts +37 -0
  48. package/dist/card-bleed.js +455 -0
  49. package/dist/card-bleed.js.map +1 -0
  50. package/dist/card.cjs +27 -1
  51. package/dist/card.cjs.map +1 -1
  52. package/dist/card.d.cts +19 -3
  53. package/dist/card.d.ts +19 -3
  54. package/dist/card.js +27 -1
  55. package/dist/card.js.map +1 -1
  56. package/dist/carousel.cjs +655 -0
  57. package/dist/carousel.cjs.map +1 -0
  58. package/dist/carousel.d.cts +79 -0
  59. package/dist/carousel.d.ts +79 -0
  60. package/dist/carousel.js +652 -0
  61. package/dist/carousel.js.map +1 -0
  62. package/dist/checkbox.cjs +3 -1
  63. package/dist/checkbox.cjs.map +1 -1
  64. package/dist/checkbox.js +3 -1
  65. package/dist/checkbox.js.map +1 -1
  66. package/dist/choice-card.cjs +524 -0
  67. package/dist/choice-card.cjs.map +1 -0
  68. package/dist/choice-card.d.cts +81 -0
  69. package/dist/choice-card.d.ts +81 -0
  70. package/dist/choice-card.js +521 -0
  71. package/dist/choice-card.js.map +1 -0
  72. package/dist/container.cjs +23 -6
  73. package/dist/container.cjs.map +1 -1
  74. package/dist/container.d.cts +9 -3
  75. package/dist/container.d.ts +9 -3
  76. package/dist/container.js +23 -7
  77. package/dist/container.js.map +1 -1
  78. package/dist/datepicker.cjs +580 -0
  79. package/dist/datepicker.cjs.map +1 -0
  80. package/dist/datepicker.d.cts +78 -0
  81. package/dist/datepicker.d.ts +78 -0
  82. package/dist/datepicker.js +577 -0
  83. package/dist/datepicker.js.map +1 -0
  84. package/dist/dom-CX9bgbcQ.d.cts +3 -0
  85. package/dist/dom-CX9bgbcQ.d.ts +3 -0
  86. package/dist/dropdown.cjs +24 -0
  87. package/dist/dropdown.cjs.map +1 -1
  88. package/dist/dropdown.d.cts +3 -2
  89. package/dist/dropdown.d.ts +3 -2
  90. package/dist/dropdown.js +25 -1
  91. package/dist/dropdown.js.map +1 -1
  92. package/dist/external-auth-button.cjs +494 -0
  93. package/dist/external-auth-button.cjs.map +1 -0
  94. package/dist/external-auth-button.d.cts +71 -0
  95. package/dist/external-auth-button.d.ts +71 -0
  96. package/dist/external-auth-button.js +491 -0
  97. package/dist/external-auth-button.js.map +1 -0
  98. package/dist/fieldset.cjs +3 -1
  99. package/dist/fieldset.cjs.map +1 -1
  100. package/dist/fieldset.js +3 -1
  101. package/dist/fieldset.js.map +1 -1
  102. package/dist/file-input.cjs +371 -0
  103. package/dist/file-input.cjs.map +1 -0
  104. package/dist/file-input.d.cts +96 -0
  105. package/dist/file-input.d.ts +96 -0
  106. package/dist/file-input.js +367 -0
  107. package/dist/file-input.js.map +1 -0
  108. package/dist/footer-chip.cjs +22 -2
  109. package/dist/footer-chip.cjs.map +1 -1
  110. package/dist/footer-chip.d.cts +12 -1
  111. package/dist/footer-chip.d.ts +12 -1
  112. package/dist/footer-chip.js +22 -2
  113. package/dist/footer-chip.js.map +1 -1
  114. package/dist/footer-link.cjs +19 -1
  115. package/dist/footer-link.cjs.map +1 -1
  116. package/dist/footer-link.d.cts +12 -1
  117. package/dist/footer-link.d.ts +12 -1
  118. package/dist/footer-link.js +19 -1
  119. package/dist/footer-link.js.map +1 -1
  120. package/dist/footer.cjs +30 -1
  121. package/dist/footer.cjs.map +1 -1
  122. package/dist/footer.d.cts +2 -1
  123. package/dist/footer.d.ts +2 -1
  124. package/dist/footer.js +31 -2
  125. package/dist/footer.js.map +1 -1
  126. package/dist/{form-DpPtizpY.d.cts → form-CVO7mlDa.d.cts} +38 -9
  127. package/dist/{form-DpPtizpY.d.ts → form-CVO7mlDa.d.ts} +38 -9
  128. package/dist/grid.cjs +35 -1
  129. package/dist/grid.cjs.map +1 -1
  130. package/dist/grid.d.cts +9 -3
  131. package/dist/grid.d.ts +9 -3
  132. package/dist/grid.js +35 -2
  133. package/dist/grid.js.map +1 -1
  134. package/dist/icon-box.cjs +27 -1
  135. package/dist/icon-box.cjs.map +1 -1
  136. package/dist/icon-box.d.cts +19 -3
  137. package/dist/icon-box.d.ts +19 -3
  138. package/dist/icon-box.js +27 -1
  139. package/dist/icon-box.js.map +1 -1
  140. package/dist/index.cjs +3654 -107
  141. package/dist/index.cjs.map +1 -1
  142. package/dist/index.d.cts +26 -1
  143. package/dist/index.d.ts +26 -1
  144. package/dist/index.js +3594 -110
  145. package/dist/index.js.map +1 -1
  146. package/dist/input-group.cjs +471 -0
  147. package/dist/input-group.cjs.map +1 -0
  148. package/dist/input-group.d.cts +31 -0
  149. package/dist/input-group.d.ts +31 -0
  150. package/dist/input-group.js +468 -0
  151. package/dist/input-group.js.map +1 -0
  152. package/dist/input.cjs +96 -4
  153. package/dist/input.cjs.map +1 -1
  154. package/dist/input.d.cts +45 -6
  155. package/dist/input.d.ts +45 -6
  156. package/dist/input.js +98 -6
  157. package/dist/input.js.map +1 -1
  158. package/dist/label.cjs +3 -1
  159. package/dist/label.cjs.map +1 -1
  160. package/dist/label.js +3 -1
  161. package/dist/label.js.map +1 -1
  162. package/dist/list-group-item.cjs +367 -0
  163. package/dist/list-group-item.cjs.map +1 -0
  164. package/dist/list-group-item.d.cts +73 -0
  165. package/dist/list-group-item.d.ts +73 -0
  166. package/dist/list-group-item.js +364 -0
  167. package/dist/list-group-item.js.map +1 -0
  168. package/dist/list-group.cjs +610 -0
  169. package/dist/list-group.cjs.map +1 -0
  170. package/dist/list-group.d.cts +58 -0
  171. package/dist/list-group.d.ts +58 -0
  172. package/dist/list-group.js +607 -0
  173. package/dist/list-group.js.map +1 -0
  174. package/dist/modal.cjs +38 -35
  175. package/dist/modal.cjs.map +1 -1
  176. package/dist/modal.d.cts +1 -3
  177. package/dist/modal.d.ts +1 -3
  178. package/dist/modal.js +38 -35
  179. package/dist/modal.js.map +1 -1
  180. package/dist/nav-item.cjs +107 -4
  181. package/dist/nav-item.cjs.map +1 -1
  182. package/dist/nav-item.d.cts +52 -2
  183. package/dist/nav-item.d.ts +52 -2
  184. package/dist/nav-item.js +108 -5
  185. package/dist/nav-item.js.map +1 -1
  186. package/dist/nav.cjs +25 -1
  187. package/dist/nav.cjs.map +1 -1
  188. package/dist/nav.d.cts +2 -1
  189. package/dist/nav.d.ts +2 -1
  190. package/dist/nav.js +26 -2
  191. package/dist/nav.js.map +1 -1
  192. package/dist/offcanvas.cjs +621 -0
  193. package/dist/offcanvas.cjs.map +1 -0
  194. package/dist/offcanvas.d.cts +61 -0
  195. package/dist/offcanvas.d.ts +61 -0
  196. package/dist/offcanvas.js +617 -0
  197. package/dist/offcanvas.js.map +1 -0
  198. package/dist/pagination.cjs +452 -0
  199. package/dist/pagination.cjs.map +1 -0
  200. package/dist/pagination.d.cts +69 -0
  201. package/dist/pagination.d.ts +69 -0
  202. package/dist/pagination.js +448 -0
  203. package/dist/pagination.js.map +1 -0
  204. package/dist/popover.cjs +534 -0
  205. package/dist/popover.cjs.map +1 -0
  206. package/dist/popover.d.cts +59 -0
  207. package/dist/popover.d.ts +59 -0
  208. package/dist/popover.js +530 -0
  209. package/dist/popover.js.map +1 -0
  210. package/dist/pricing-card.cjs +121 -64
  211. package/dist/pricing-card.cjs.map +1 -1
  212. package/dist/pricing-card.d.cts +21 -7
  213. package/dist/pricing-card.d.ts +21 -7
  214. package/dist/pricing-card.js +122 -65
  215. package/dist/pricing-card.js.map +1 -1
  216. package/dist/progress.cjs +403 -0
  217. package/dist/progress.cjs.map +1 -0
  218. package/dist/progress.d.cts +70 -0
  219. package/dist/progress.d.ts +70 -0
  220. package/dist/progress.js +398 -0
  221. package/dist/progress.js.map +1 -0
  222. package/dist/prose.cjs +425 -0
  223. package/dist/prose.cjs.map +1 -0
  224. package/dist/prose.d.cts +21 -0
  225. package/dist/prose.d.ts +21 -0
  226. package/dist/prose.js +422 -0
  227. package/dist/prose.js.map +1 -0
  228. package/dist/radio.cjs +3 -1
  229. package/dist/radio.cjs.map +1 -1
  230. package/dist/radio.js +3 -1
  231. package/dist/radio.js.map +1 -1
  232. package/dist/range.cjs +381 -0
  233. package/dist/range.cjs.map +1 -0
  234. package/dist/range.d.cts +76 -0
  235. package/dist/range.d.ts +76 -0
  236. package/dist/range.js +378 -0
  237. package/dist/range.js.map +1 -0
  238. package/dist/rating.cjs +33 -0
  239. package/dist/rating.cjs.map +1 -1
  240. package/dist/rating.d.cts +38 -3
  241. package/dist/rating.d.ts +38 -3
  242. package/dist/rating.js +33 -0
  243. package/dist/rating.js.map +1 -1
  244. package/dist/section.cjs +27 -3
  245. package/dist/section.cjs.map +1 -1
  246. package/dist/section.d.cts +16 -1
  247. package/dist/section.d.ts +16 -1
  248. package/dist/section.js +27 -4
  249. package/dist/section.js.map +1 -1
  250. package/dist/select.cjs +6 -1
  251. package/dist/select.cjs.map +1 -1
  252. package/dist/select.d.cts +7 -1
  253. package/dist/select.d.ts +7 -1
  254. package/dist/select.js +6 -1
  255. package/dist/select.js.map +1 -1
  256. package/dist/sidebar-link.cjs +19 -1
  257. package/dist/sidebar-link.cjs.map +1 -1
  258. package/dist/sidebar-link.d.cts +13 -2
  259. package/dist/sidebar-link.d.ts +13 -2
  260. package/dist/sidebar-link.js +19 -1
  261. package/dist/sidebar-link.js.map +1 -1
  262. package/dist/sidebar-toggle.cjs +3 -1
  263. package/dist/sidebar-toggle.cjs.map +1 -1
  264. package/dist/sidebar-toggle.js +3 -1
  265. package/dist/sidebar-toggle.js.map +1 -1
  266. package/dist/sidebar.cjs +33 -1
  267. package/dist/sidebar.cjs.map +1 -1
  268. package/dist/sidebar.d.cts +1 -0
  269. package/dist/sidebar.d.ts +1 -0
  270. package/dist/sidebar.js +34 -2
  271. package/dist/sidebar.js.map +1 -1
  272. package/dist/spinner.cjs +2 -1
  273. package/dist/spinner.cjs.map +1 -1
  274. package/dist/spinner.d.cts +2 -2
  275. package/dist/spinner.d.ts +2 -2
  276. package/dist/spinner.js +2 -1
  277. package/dist/spinner.js.map +1 -1
  278. package/dist/stack.cjs +4 -2
  279. package/dist/stack.cjs.map +1 -1
  280. package/dist/stack.d.cts +2 -2
  281. package/dist/stack.d.ts +2 -2
  282. package/dist/stack.js +4 -2
  283. package/dist/stack.js.map +1 -1
  284. package/dist/states-Bgzwu_XZ.d.cts +9 -0
  285. package/dist/states-Bgzwu_XZ.d.ts +9 -0
  286. package/dist/stepper.cjs +495 -0
  287. package/dist/stepper.cjs.map +1 -0
  288. package/dist/stepper.d.cts +40 -0
  289. package/dist/stepper.d.ts +40 -0
  290. package/dist/stepper.js +491 -0
  291. package/dist/stepper.js.map +1 -0
  292. package/dist/switch.cjs +492 -0
  293. package/dist/switch.cjs.map +1 -0
  294. package/dist/switch.d.cts +82 -0
  295. package/dist/switch.d.ts +82 -0
  296. package/dist/switch.js +488 -0
  297. package/dist/switch.js.map +1 -0
  298. package/dist/tab-panel.cjs +465 -0
  299. package/dist/tab-panel.cjs.map +1 -0
  300. package/dist/tab-panel.d.cts +48 -0
  301. package/dist/tab-panel.d.ts +48 -0
  302. package/dist/tab-panel.js +462 -0
  303. package/dist/tab-panel.js.map +1 -0
  304. package/dist/table.cjs +506 -0
  305. package/dist/table.cjs.map +1 -0
  306. package/dist/table.d.cts +54 -0
  307. package/dist/table.d.ts +54 -0
  308. package/dist/table.js +501 -0
  309. package/dist/table.js.map +1 -0
  310. package/dist/tabs.cjs +596 -0
  311. package/dist/tabs.cjs.map +1 -0
  312. package/dist/tabs.d.cts +65 -0
  313. package/dist/tabs.d.ts +65 -0
  314. package/dist/tabs.js +592 -0
  315. package/dist/tabs.js.map +1 -0
  316. package/dist/tag.cjs +27 -1
  317. package/dist/tag.cjs.map +1 -1
  318. package/dist/tag.d.cts +19 -3
  319. package/dist/tag.d.ts +19 -3
  320. package/dist/tag.js +27 -1
  321. package/dist/tag.js.map +1 -1
  322. package/dist/testimonial.cjs +130 -64
  323. package/dist/testimonial.cjs.map +1 -1
  324. package/dist/testimonial.d.cts +23 -8
  325. package/dist/testimonial.d.ts +23 -8
  326. package/dist/testimonial.js +131 -65
  327. package/dist/testimonial.js.map +1 -1
  328. package/dist/text.cjs +65 -6
  329. package/dist/text.cjs.map +1 -1
  330. package/dist/text.d.cts +24 -3
  331. package/dist/text.d.ts +24 -3
  332. package/dist/text.js +64 -8
  333. package/dist/text.js.map +1 -1
  334. package/dist/textarea.cjs +3 -0
  335. package/dist/textarea.cjs.map +1 -1
  336. package/dist/textarea.d.cts +7 -1
  337. package/dist/textarea.d.ts +7 -1
  338. package/dist/textarea.js +3 -0
  339. package/dist/textarea.js.map +1 -1
  340. package/dist/toast.cjs +2 -1
  341. package/dist/toast.cjs.map +1 -1
  342. package/dist/toast.d.cts +2 -2
  343. package/dist/toast.d.ts +2 -2
  344. package/dist/toast.js +2 -1
  345. package/dist/toast.js.map +1 -1
  346. package/dist/tooltip.cjs.map +1 -1
  347. package/dist/tooltip.d.cts +2 -2
  348. package/dist/tooltip.d.ts +2 -2
  349. package/dist/tooltip.js.map +1 -1
  350. package/package.json +126 -11
@@ -0,0 +1,468 @@
1
+ import { LitElement, html } from 'lit';
2
+ import { ifDefined } from 'lit/directives/if-defined.js';
3
+ import { getInputGroupAddonClasses, getInputGroupClasses, getFileInputClasses, getInputClasses, getSelectClasses, getButtonClasses } from '@phcdevworks/spectre-ui';
4
+
5
+ // src/components/input-group/sp-input-group.ts
6
+ var SpectreBaseElement = class extends LitElement {
7
+ constructor() {
8
+ super(...arguments);
9
+ this._ariaLabel = null;
10
+ this._ariaLabelledBy = null;
11
+ this._ariaDescribedBy = null;
12
+ this._autocapitalize = "";
13
+ this._autofocus = false;
14
+ this._spellcheck = 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 autocapitalize() {
52
+ return this._autocapitalize;
53
+ }
54
+ set autocapitalize(value) {
55
+ const normalizedValue = value ?? "";
56
+ if (this._autocapitalize === normalizedValue) {
57
+ return;
58
+ }
59
+ this._autocapitalize = normalizedValue;
60
+ this._removeHostAttribute("autocapitalize");
61
+ this.requestUpdate();
62
+ }
63
+ get spellcheck() {
64
+ return this._spellcheck ?? super.spellcheck;
65
+ }
66
+ set spellcheck(value) {
67
+ if (this._spellcheck === value) {
68
+ return;
69
+ }
70
+ this._spellcheck = value ?? null;
71
+ this._removeHostAttribute("spellcheck");
72
+ this.requestUpdate();
73
+ }
74
+ get title() {
75
+ return this._title;
76
+ }
77
+ set title(value) {
78
+ const normalizedValue = value ?? "";
79
+ if (this._title === normalizedValue) {
80
+ return;
81
+ }
82
+ this._title = normalizedValue;
83
+ this._removeHostAttribute("title");
84
+ this.requestUpdate();
85
+ }
86
+ get id() {
87
+ return this._id;
88
+ }
89
+ set id(value) {
90
+ const normalizedValue = value ?? "";
91
+ if (this._id === normalizedValue) {
92
+ return;
93
+ }
94
+ this._id = normalizedValue;
95
+ this._removeHostAttribute("id");
96
+ this.requestUpdate();
97
+ }
98
+ get autofocus() {
99
+ return this._autofocus;
100
+ }
101
+ set autofocus(value) {
102
+ const normalizedValue = !!value;
103
+ if (this._autofocus === normalizedValue) {
104
+ return;
105
+ }
106
+ this._autofocus = normalizedValue;
107
+ this._removeHostAttribute("autofocus");
108
+ this.requestUpdate();
109
+ }
110
+ // Spectre components intentionally render in light DOM so the global
111
+ // `@phcdevworks/spectre-ui` styling contract can apply directly.
112
+ createRenderRoot() {
113
+ return this;
114
+ }
115
+ connectedCallback() {
116
+ super.connectedCallback();
117
+ const proxiedAttributes = [
118
+ "id",
119
+ "title",
120
+ "autocapitalize",
121
+ "autofocus",
122
+ "spellcheck",
123
+ "aria-label",
124
+ "aria-labelledby",
125
+ "aria-describedby"
126
+ ];
127
+ proxiedAttributes.forEach((attr) => {
128
+ const value = super.getAttribute(attr);
129
+ if (value !== null) {
130
+ this.setAttribute(attr, value);
131
+ }
132
+ });
133
+ }
134
+ getAttribute(qualifiedName) {
135
+ switch (qualifiedName) {
136
+ case "id":
137
+ return this.id || null;
138
+ case "title":
139
+ return this.title || null;
140
+ case "autocapitalize":
141
+ return this.autocapitalize || null;
142
+ case "autofocus":
143
+ return this.autofocus ? "" : null;
144
+ case "spellcheck":
145
+ return this._spellcheck !== null ? String(this._spellcheck) : null;
146
+ case "aria-label":
147
+ return this.ariaLabel;
148
+ case "aria-labelledby":
149
+ return this.ariaLabelledBy;
150
+ case "aria-describedby":
151
+ return this.ariaDescribedBy;
152
+ default:
153
+ return super.getAttribute(qualifiedName);
154
+ }
155
+ }
156
+ hasAttribute(qualifiedName) {
157
+ switch (qualifiedName) {
158
+ case "id":
159
+ return this.id !== "";
160
+ case "title":
161
+ return this.title !== "";
162
+ case "autocapitalize":
163
+ return this.autocapitalize !== "";
164
+ case "autofocus":
165
+ return this.autofocus;
166
+ case "spellcheck":
167
+ return this._spellcheck !== null;
168
+ case "aria-label":
169
+ return this.ariaLabel !== null;
170
+ case "aria-labelledby":
171
+ return this.ariaLabelledBy !== null;
172
+ case "aria-describedby":
173
+ return this.ariaDescribedBy !== null;
174
+ default:
175
+ return super.hasAttribute(qualifiedName);
176
+ }
177
+ }
178
+ setAttribute(qualifiedName, value) {
179
+ switch (qualifiedName) {
180
+ case "id":
181
+ this.id = value;
182
+ break;
183
+ case "title":
184
+ this.title = value;
185
+ break;
186
+ case "autocapitalize":
187
+ this.autocapitalize = value;
188
+ break;
189
+ case "autofocus":
190
+ this.autofocus = true;
191
+ break;
192
+ case "spellcheck":
193
+ this.spellcheck = value !== "false";
194
+ break;
195
+ case "aria-label":
196
+ this.ariaLabel = value;
197
+ break;
198
+ case "aria-labelledby":
199
+ this.ariaLabelledBy = value;
200
+ break;
201
+ case "aria-describedby":
202
+ this.ariaDescribedBy = value;
203
+ break;
204
+ default:
205
+ super.setAttribute(qualifiedName, value);
206
+ }
207
+ }
208
+ removeAttribute(qualifiedName) {
209
+ switch (qualifiedName) {
210
+ case "id":
211
+ this.id = "";
212
+ break;
213
+ case "title":
214
+ this.title = "";
215
+ break;
216
+ case "autocapitalize":
217
+ this.autocapitalize = "";
218
+ break;
219
+ case "autofocus":
220
+ this.autofocus = false;
221
+ break;
222
+ case "spellcheck":
223
+ this.spellcheck = null;
224
+ break;
225
+ case "aria-label":
226
+ this.ariaLabel = null;
227
+ break;
228
+ case "aria-labelledby":
229
+ this.ariaLabelledBy = null;
230
+ break;
231
+ case "aria-describedby":
232
+ this.ariaDescribedBy = null;
233
+ break;
234
+ default:
235
+ super.removeAttribute(qualifiedName);
236
+ }
237
+ }
238
+ _removeHostAttribute(name) {
239
+ const host = this;
240
+ if (HTMLElement.prototype.hasAttribute.call(host, name)) {
241
+ HTMLElement.prototype.removeAttribute.call(host, name);
242
+ }
243
+ }
244
+ get forwardedAriaLabel() {
245
+ const value = this.ariaLabel?.trim();
246
+ return value ? value : void 0;
247
+ }
248
+ get forwardedAriaLabelledBy() {
249
+ const value = this.ariaLabelledBy?.trim();
250
+ return value ? value : void 0;
251
+ }
252
+ get forwardedAriaDescribedBy() {
253
+ const value = this.ariaDescribedBy?.trim();
254
+ return value ? value : void 0;
255
+ }
256
+ // Subclasses that expose `disabled`/`loading` properties get this disabled
257
+ // calculation for free instead of redeclaring it per component.
258
+ get isDisabled() {
259
+ const self = this;
260
+ return (self.disabled ?? false) || (self.loading ?? false);
261
+ }
262
+ // Subclasses get this for free instead of redeclaring it per component.
263
+ get hasForwardedLabel() {
264
+ return Boolean(this.forwardedAriaLabel || this.forwardedAriaLabelledBy);
265
+ }
266
+ };
267
+ SpectreBaseElement.properties = {};
268
+
269
+ // src/utils/parts.ts
270
+ function applyPartClasses(elements, parts) {
271
+ for (const element of elements) {
272
+ const part = element.getAttribute("slot");
273
+ const classes = part ? parts[part] : void 0;
274
+ if (classes) {
275
+ element.classList.add(...classes.split(/\s+/).filter(Boolean));
276
+ }
277
+ }
278
+ }
279
+
280
+ // src/utils/dom.ts
281
+ function hasMeaningfulContent(nodes) {
282
+ return nodes.some((node) => {
283
+ if (node.nodeType === Node.ELEMENT_NODE) {
284
+ return true;
285
+ }
286
+ if (node.nodeType === Node.TEXT_NODE) {
287
+ return (node.textContent?.trim().length ?? 0) > 0;
288
+ }
289
+ return false;
290
+ });
291
+ }
292
+
293
+ // src/utils/projection.ts
294
+ function slotOf(node) {
295
+ if (node.nodeType !== Node.ELEMENT_NODE) {
296
+ return void 0;
297
+ }
298
+ return node.getAttribute("slot") ?? void 0;
299
+ }
300
+ var ProjectionController = class {
301
+ constructor(host, internalAttributes) {
302
+ this.host = host;
303
+ this.internalAttributes = internalAttributes;
304
+ this.projected = [];
305
+ host.addController(this);
306
+ }
307
+ hostConnected() {
308
+ this.sync();
309
+ this.observe();
310
+ }
311
+ hostDisconnected() {
312
+ this.disconnect();
313
+ }
314
+ hostUpdate() {
315
+ this.sync();
316
+ this.disconnect();
317
+ }
318
+ hostUpdated() {
319
+ this.observe();
320
+ }
321
+ // Every projected node in authored order, regardless of slot.
322
+ all() {
323
+ return [...this.projected];
324
+ }
325
+ // Omitting `slot` returns the nodes without a slot attribute.
326
+ nodes(slot) {
327
+ return this.projected.filter((node) => slotOf(node) === slot);
328
+ }
329
+ elements(slot) {
330
+ return this.nodes(slot).filter(
331
+ (node) => node.nodeType === Node.ELEMENT_NODE
332
+ );
333
+ }
334
+ has(slot) {
335
+ return hasMeaningfulContent(this.nodes(slot));
336
+ }
337
+ isInternalNode(node) {
338
+ return node.nodeType === Node.ELEMENT_NODE && this.internalAttributes.some(
339
+ (name) => node.hasAttribute(name)
340
+ );
341
+ }
342
+ isProjectable(node) {
343
+ if (node.nodeType === Node.COMMENT_NODE || this.isInternalNode(node)) {
344
+ return false;
345
+ }
346
+ if (node.nodeType === Node.TEXT_NODE && this.hostHasRendered) {
347
+ return Boolean(node.textContent?.trim());
348
+ }
349
+ return true;
350
+ }
351
+ get hostHasRendered() {
352
+ return this.host.hasUpdated;
353
+ }
354
+ sync() {
355
+ const next = [
356
+ .../* @__PURE__ */ new Set([
357
+ ...this.projected.filter((node) => this.host.contains(node)),
358
+ ...Array.from(this.host.childNodes).filter(
359
+ (node) => this.isProjectable(node)
360
+ )
361
+ ])
362
+ ];
363
+ const changed = next.length !== this.projected.length || next.some((node, index) => node !== this.projected[index]);
364
+ if (changed) {
365
+ this.projected = next;
366
+ }
367
+ return changed;
368
+ }
369
+ observe() {
370
+ if (this.observer || !this.host.isConnected) {
371
+ return;
372
+ }
373
+ this.observer = new MutationObserver(() => {
374
+ if (this.sync()) {
375
+ this.host.requestUpdate();
376
+ }
377
+ });
378
+ this.observer.observe(this.host, { childList: true });
379
+ }
380
+ disconnect() {
381
+ this.observer?.disconnect();
382
+ this.observer = void 0;
383
+ }
384
+ };
385
+ function controlClasses(element) {
386
+ if (element instanceof HTMLInputElement) {
387
+ return element.type === "file" ? getFileInputClasses() : getInputClasses();
388
+ }
389
+ if (element instanceof HTMLSelectElement) {
390
+ return getSelectClasses();
391
+ }
392
+ if (element instanceof HTMLButtonElement) {
393
+ return getButtonClasses({ variant: "secondary" });
394
+ }
395
+ return void 0;
396
+ }
397
+ var SpectreInputGroupElement = class extends SpectreBaseElement {
398
+ constructor() {
399
+ super(...arguments);
400
+ this.disabled = false;
401
+ this.projection = new ProjectionController(this, [
402
+ "data-sp-input-group-native"
403
+ ]);
404
+ }
405
+ get id() {
406
+ return super.id;
407
+ }
408
+ set id(value) {
409
+ super.id = value;
410
+ }
411
+ get title() {
412
+ return super.title;
413
+ }
414
+ set title(value) {
415
+ super.title = value;
416
+ }
417
+ connectedCallback() {
418
+ var _a;
419
+ super.connectedCallback();
420
+ (_a = this.style).display || (_a.display = "block");
421
+ }
422
+ // Native controls without an author-chosen `sp-*` class get their recipe
423
+ // class; `slot="addon"` children become addons.
424
+ updated(changedProperties) {
425
+ super.updated(changedProperties);
426
+ this.projection.elements().forEach((element) => {
427
+ const styled = Array.from(element.classList).some(
428
+ (name) => name.startsWith("sp-")
429
+ );
430
+ const classes = styled ? void 0 : controlClasses(element);
431
+ if (classes) {
432
+ element.classList.add(...classes.split(/\s+/).filter(Boolean));
433
+ }
434
+ });
435
+ applyPartClasses(this.projection.elements("addon"), {
436
+ addon: getInputGroupAddonClasses()
437
+ });
438
+ }
439
+ render() {
440
+ return html`<div
441
+ aria-disabled="${ifDefined(this.disabled ? "true" : void 0)}"
442
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
443
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
444
+ class="${getInputGroupClasses({ disabled: this.disabled ?? false })}"
445
+ data-sp-input-group-native
446
+ id="${ifDefined(this.id || void 0)}"
447
+ role="group"
448
+ title="${ifDefined(this.title || void 0)}"
449
+ >
450
+ ${this.projection.all()}
451
+ </div>`;
452
+ }
453
+ };
454
+ SpectreInputGroupElement.properties = {
455
+ disabled: { type: Boolean, reflect: true }
456
+ };
457
+ function defineSpectreInputGroup(tagName = "sp-input-group") {
458
+ const existingElement = customElements.get(tagName);
459
+ if (existingElement) {
460
+ return existingElement;
461
+ }
462
+ customElements.define(tagName, SpectreInputGroupElement);
463
+ return SpectreInputGroupElement;
464
+ }
465
+
466
+ export { SpectreInputGroupElement, defineSpectreInputGroup };
467
+ //# sourceMappingURL=input-group.js.map
468
+ //# sourceMappingURL=input-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/base.ts","../src/utils/parts.ts","../src/utils/dom.ts","../src/utils/projection.ts","../src/components/input-group/sp-input-group.ts"],"names":[],"mappings":"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","file":"input-group.js","sourcesContent":["import { LitElement, type PropertyDeclarations } from 'lit'\n\nexport class SpectreBaseElement extends LitElement {\n static properties: PropertyDeclarations = {}\n\n private _ariaLabel: string | null = null\n private _ariaLabelledBy: string | null = null\n private _ariaDescribedBy: string | null = null\n private _autocapitalize = ''\n private _autofocus = false\n private _spellcheck: boolean | null = null\n private _title = ''\n private _id = ''\n\n get ariaLabel(): string | null {\n return this._ariaLabel\n }\n\n set ariaLabel(value: string | null) {\n if (this._ariaLabel === value) {\n return\n }\n this._ariaLabel = value\n this._removeHostAttribute('aria-label')\n this.requestUpdate()\n }\n\n get ariaLabelledBy(): string | null {\n return this._ariaLabelledBy\n }\n\n set ariaLabelledBy(value: string | null) {\n if (this._ariaLabelledBy === value) {\n return\n }\n this._ariaLabelledBy = value\n this._removeHostAttribute('aria-labelledby')\n this.requestUpdate()\n }\n\n get ariaDescribedBy(): string | null {\n return this._ariaDescribedBy\n }\n\n set ariaDescribedBy(value: string | null) {\n if (this._ariaDescribedBy === value) {\n return\n }\n this._ariaDescribedBy = value\n this._removeHostAttribute('aria-describedby')\n this.requestUpdate()\n }\n\n override get autocapitalize(): string {\n return this._autocapitalize\n }\n\n override set autocapitalize(value: string | undefined | null) {\n const normalizedValue = value ?? ''\n if (this._autocapitalize === normalizedValue) {\n return\n }\n this._autocapitalize = normalizedValue\n this._removeHostAttribute('autocapitalize')\n this.requestUpdate()\n }\n\n override get spellcheck(): boolean {\n return this._spellcheck ?? super.spellcheck\n }\n\n override set spellcheck(value: boolean | undefined | null) {\n if (this._spellcheck === value) {\n return\n }\n this._spellcheck = value ?? null\n this._removeHostAttribute('spellcheck')\n this.requestUpdate()\n }\n\n override get title(): string {\n return this._title\n }\n\n override set title(value: string | undefined | null) {\n const normalizedValue = value ?? ''\n if (this._title === normalizedValue) {\n return\n }\n this._title = normalizedValue\n this._removeHostAttribute('title')\n this.requestUpdate()\n }\n\n override get id(): string {\n return this._id\n }\n\n override set id(value: string | undefined | null) {\n const normalizedValue = value ?? ''\n if (this._id === normalizedValue) {\n return\n }\n this._id = normalizedValue\n this._removeHostAttribute('id')\n this.requestUpdate()\n }\n\n override get autofocus(): boolean {\n return this._autofocus\n }\n\n override set autofocus(value: boolean | undefined | null) {\n const normalizedValue = !!value\n if (this._autofocus === normalizedValue) {\n return\n }\n this._autofocus = normalizedValue\n this._removeHostAttribute('autofocus')\n this.requestUpdate()\n }\n\n // Spectre components intentionally render in light DOM so the global\n // `@phcdevworks/spectre-ui` styling contract can apply directly.\n createRenderRoot(): this {\n return this\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n\n const proxiedAttributes = [\n 'id',\n 'title',\n 'autocapitalize',\n 'autofocus',\n 'spellcheck',\n 'aria-label',\n 'aria-labelledby',\n 'aria-describedby'\n ]\n\n proxiedAttributes.forEach((attr) => {\n const value = super.getAttribute(attr)\n if (value !== null) {\n this.setAttribute(attr, value)\n }\n })\n }\n\n override getAttribute(qualifiedName: string): string | null {\n switch (qualifiedName) {\n case 'id':\n return this.id || null\n case 'title':\n return this.title || null\n case 'autocapitalize':\n return this.autocapitalize || null\n case 'autofocus':\n return this.autofocus ? '' : null\n case 'spellcheck':\n return this._spellcheck !== null ? String(this._spellcheck) : null\n case 'aria-label':\n return this.ariaLabel\n case 'aria-labelledby':\n return this.ariaLabelledBy\n case 'aria-describedby':\n return this.ariaDescribedBy\n default:\n return super.getAttribute(qualifiedName)\n }\n }\n\n override hasAttribute(qualifiedName: string): boolean {\n switch (qualifiedName) {\n case 'id':\n return this.id !== ''\n case 'title':\n return this.title !== ''\n case 'autocapitalize':\n return this.autocapitalize !== ''\n case 'autofocus':\n return this.autofocus\n case 'spellcheck':\n return this._spellcheck !== null\n case 'aria-label':\n return this.ariaLabel !== null\n case 'aria-labelledby':\n return this.ariaLabelledBy !== null\n case 'aria-describedby':\n return this.ariaDescribedBy !== null\n default:\n return super.hasAttribute(qualifiedName)\n }\n }\n\n override setAttribute(qualifiedName: string, value: string): void {\n switch (qualifiedName) {\n case 'id':\n this.id = value\n break\n case 'title':\n this.title = value\n break\n case 'autocapitalize':\n this.autocapitalize = value\n break\n case 'autofocus':\n this.autofocus = true\n break\n case 'spellcheck':\n this.spellcheck = value !== 'false'\n break\n case 'aria-label':\n this.ariaLabel = value\n break\n case 'aria-labelledby':\n this.ariaLabelledBy = value\n break\n case 'aria-describedby':\n this.ariaDescribedBy = value\n break\n default:\n super.setAttribute(qualifiedName, value)\n }\n }\n\n override removeAttribute(qualifiedName: string): void {\n switch (qualifiedName) {\n case 'id':\n this.id = ''\n break\n case 'title':\n this.title = ''\n break\n case 'autocapitalize':\n this.autocapitalize = ''\n break\n case 'autofocus':\n this.autofocus = false\n break\n case 'spellcheck':\n this.spellcheck = null\n break\n case 'aria-label':\n this.ariaLabel = null\n break\n case 'aria-labelledby':\n this.ariaLabelledBy = null\n break\n case 'aria-describedby':\n this.ariaDescribedBy = null\n break\n default:\n super.removeAttribute(qualifiedName)\n }\n }\n\n private _removeHostAttribute(name: string): void {\n const host = this as unknown as HTMLElement\n if (HTMLElement.prototype.hasAttribute.call(host, name)) {\n // Use the native removeAttribute to avoid our own overridden version\n // which would reset the internal state.\n HTMLElement.prototype.removeAttribute.call(host, name)\n }\n }\n\n protected get forwardedAriaLabel(): string | undefined {\n const value = this.ariaLabel?.trim()\n return value ? value : undefined\n }\n\n protected get forwardedAriaLabelledBy(): string | undefined {\n const value = this.ariaLabelledBy?.trim()\n return value ? value : undefined\n }\n\n protected get forwardedAriaDescribedBy(): string | undefined {\n const value = this.ariaDescribedBy?.trim()\n return value ? value : undefined\n }\n\n // Subclasses that expose `disabled`/`loading` properties get this disabled\n // calculation for free instead of redeclaring it per component.\n protected get isDisabled(): boolean {\n const self = this as unknown as { disabled?: boolean; loading?: boolean }\n return (self.disabled ?? false) || (self.loading ?? false)\n }\n\n // Subclasses get this for free instead of redeclaring it per component.\n protected get hasForwardedLabel(): boolean {\n return Boolean(this.forwardedAriaLabel || this.forwardedAriaLabelledBy)\n }\n}\n","// Adds a recipe's part classes to authored elements that opt in with\n// `slot=\"<part>\"`. The elements stay where they were authored, so free-form\n// layouts (footer columns, menu groups) keep their order.\nexport function applyPartClasses(\n elements: Iterable<Element>,\n parts: Readonly<Record<string, string>>\n): void {\n for (const element of elements) {\n const part = element.getAttribute('slot')\n const classes = part ? parts[part] : undefined\n if (classes) {\n element.classList.add(...classes.split(/\\s+/).filter(Boolean))\n }\n }\n}\n\nexport function childElements(nodes: readonly Node[]): Element[] {\n return nodes.filter(\n (node): node is Element => node.nodeType === Node.ELEMENT_NODE\n )\n}\n","export function hasMeaningfulContent(nodes: readonly Node[]): boolean {\n return nodes.some((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n return true\n }\n\n if (node.nodeType === Node.TEXT_NODE) {\n return (node.textContent?.trim().length ?? 0) > 0\n }\n\n return false\n })\n}\n\nlet idCounter = 0\n\nexport function createUniqueId(prefix: string): string {\n idCounter += 1\n return `${prefix}-${idCounter}`\n}\n\n// Swaps the recipe classes this component previously applied to `element`\n// without touching classes the author set.\nexport function replaceClasses(\n element: Element,\n previous: string,\n next: string\n): void {\n const nextTokens = next.split(/\\s+/).filter(Boolean)\n previous\n .split(/\\s+/)\n .filter((token) => token && !nextTokens.includes(token))\n .forEach((token) => element.classList.remove(token))\n element.classList.add(...nextTokens)\n}\n\n// Parent/child component pairs identify each other through a global symbol\n// rather than `instanceof`, because every subpath entry bundles its own copy\n// of the child class.\nexport const spectreKindKey: unique symbol = Symbol.for(\n 'phcdevworks.spectre-components.kind'\n)\n\nexport function isSpectreKind<T extends Element>(\n node: Node,\n kind: string\n): node is T {\n return (node as { [spectreKindKey]?: string })[spectreKindKey] === kind\n}\n","import type { ReactiveController, ReactiveControllerHost } from 'lit'\n\nimport { hasMeaningfulContent } from './dom'\n\ntype ProjectionHost = ReactiveControllerHost & HTMLElement\n\nfunction slotOf(node: Node): string | undefined {\n if (node.nodeType !== Node.ELEMENT_NODE) {\n return undefined\n }\n return (node as Element).getAttribute('slot') ?? undefined\n}\n\n// Tracks authored light-DOM nodes for components that project content into\n// more than one rendered container, partitioned by their `slot` attribute.\nexport class ProjectionController implements ReactiveController {\n private projected: Node[] = []\n private observer: MutationObserver | undefined\n\n constructor(\n private readonly host: ProjectionHost,\n private readonly internalAttributes: readonly string[]\n ) {\n host.addController(this)\n }\n\n hostConnected(): void {\n this.sync()\n this.observe()\n }\n\n hostDisconnected(): void {\n this.disconnect()\n }\n\n hostUpdate(): void {\n this.sync()\n this.disconnect()\n }\n\n hostUpdated(): void {\n this.observe()\n }\n\n // Every projected node in authored order, regardless of slot.\n all(): Node[] {\n return [...this.projected]\n }\n\n // Omitting `slot` returns the nodes without a slot attribute.\n nodes(slot?: string): Node[] {\n return this.projected.filter((node) => slotOf(node) === slot)\n }\n\n elements(slot?: string): Element[] {\n return this.nodes(slot).filter(\n (node): node is Element => node.nodeType === Node.ELEMENT_NODE\n )\n }\n\n has(slot?: string): boolean {\n return hasMeaningfulContent(this.nodes(slot))\n }\n\n private isInternalNode(node: Node): boolean {\n return (\n node.nodeType === Node.ELEMENT_NODE &&\n this.internalAttributes.some((name) =>\n (node as Element).hasAttribute(name)\n )\n )\n }\n\n private isProjectable(node: Node): boolean {\n if (node.nodeType === Node.COMMENT_NODE || this.isInternalNode(node)) {\n return false\n }\n // After the first render, whitespace between rendered siblings belongs to\n // the template, not the author.\n if (node.nodeType === Node.TEXT_NODE && this.hostHasRendered) {\n return Boolean(node.textContent?.trim())\n }\n return true\n }\n\n private get hostHasRendered(): boolean {\n return (this.host as unknown as { hasUpdated: boolean }).hasUpdated\n }\n\n private sync(): boolean {\n // Authored nodes already moved into rendered containers are retained;\n // re-reading those containers would also capture Lit's own nodes.\n const next = [\n ...new Set([\n ...this.projected.filter((node) => this.host.contains(node)),\n ...Array.from(this.host.childNodes).filter((node) =>\n this.isProjectable(node)\n )\n ])\n ]\n\n const changed =\n next.length !== this.projected.length ||\n next.some((node, index) => node !== this.projected[index])\n\n if (changed) {\n this.projected = next\n }\n return changed\n }\n\n private observe(): void {\n if (this.observer || !this.host.isConnected) {\n return\n }\n this.observer = new MutationObserver(() => {\n if (this.sync()) {\n this.host.requestUpdate()\n }\n })\n this.observer.observe(this.host, { childList: true })\n }\n\n private disconnect(): void {\n this.observer?.disconnect()\n this.observer = undefined\n }\n}\n","import { html } from 'lit'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport { SpectreBaseElement } from '../../utils/base'\nimport { applyPartClasses } from '../../utils/parts'\nimport { ProjectionController } from '../../utils/projection'\n\nimport {\n getButtonClasses,\n getFileInputClasses,\n getInputClasses,\n getInputGroupAddonClasses,\n getInputGroupClasses,\n getSelectClasses\n} from '@phcdevworks/spectre-ui'\n\nexport interface SpectreInputGroupProps {\n ariaLabel?: string | null\n ariaLabelledBy?: string | null\n disabled?: boolean | undefined\n id?: string | null | undefined\n title?: string | null | undefined\n}\n\nfunction controlClasses(element: Element): string | undefined {\n if (element instanceof HTMLInputElement) {\n return element.type === 'file' ? getFileInputClasses() : getInputClasses()\n }\n if (element instanceof HTMLSelectElement) {\n return getSelectClasses()\n }\n if (element instanceof HTMLButtonElement) {\n return getButtonClasses({ variant: 'secondary' })\n }\n return undefined\n}\n\n// The recipe fuses its *direct* children (`> :first-child` radii, overlapping\n// borders), so it takes native controls rather than `sp-*` wrapper hosts.\nexport class SpectreInputGroupElement\n extends SpectreBaseElement\n implements SpectreInputGroupProps\n{\n static properties = {\n disabled: { type: Boolean, reflect: true }\n }\n\n disabled: boolean | undefined = false\n\n private readonly projection = new ProjectionController(this, [\n 'data-sp-input-group-native'\n ])\n\n override get id(): string {\n return super.id\n }\n\n override set id(value: string | null | undefined) {\n super.id = value\n }\n\n override get title(): string {\n return super.title\n }\n\n override set title(value: string | null | undefined) {\n super.title = value\n }\n\n override connectedCallback(): void {\n super.connectedCallback()\n this.style.display ||= 'block'\n }\n\n // Native controls without an author-chosen `sp-*` class get their recipe\n // class; `slot=\"addon\"` children become addons.\n protected override updated(\n changedProperties: Map<PropertyKey, unknown>\n ): void {\n super.updated(changedProperties)\n this.projection.elements().forEach((element) => {\n const styled = Array.from(element.classList).some((name) =>\n name.startsWith('sp-')\n )\n const classes = styled ? undefined : controlClasses(element)\n if (classes) {\n element.classList.add(...classes.split(/\\s+/).filter(Boolean))\n }\n })\n applyPartClasses(this.projection.elements('addon'), {\n addon: getInputGroupAddonClasses()\n })\n }\n\n override render() {\n return html`<div\n aria-disabled=\"${ifDefined(this.disabled ? 'true' : undefined)}\"\n aria-label=\"${ifDefined(this.forwardedAriaLabel)}\"\n aria-labelledby=\"${ifDefined(this.forwardedAriaLabelledBy)}\"\n class=\"${getInputGroupClasses({ disabled: this.disabled ?? false })}\"\n data-sp-input-group-native\n id=\"${ifDefined(this.id || undefined)}\"\n role=\"group\"\n title=\"${ifDefined(this.title || undefined)}\"\n >\n ${this.projection.all()}\n </div>`\n }\n}\n\nexport function defineSpectreInputGroup(\n tagName = 'sp-input-group'\n): typeof SpectreInputGroupElement {\n const existingElement = customElements.get(tagName)\n\n if (existingElement) {\n return existingElement as unknown as typeof SpectreInputGroupElement\n }\n\n customElements.define(tagName, SpectreInputGroupElement)\n return SpectreInputGroupElement\n}\n"]}
package/dist/input.cjs CHANGED
@@ -268,6 +268,13 @@ var SpectreBaseElement = class extends lit.LitElement {
268
268
  }
269
269
  };
270
270
  SpectreBaseElement.properties = {};
271
+
272
+ // src/utils/dom.ts
273
+ var idCounter = 0;
274
+ function createUniqueId(prefix) {
275
+ idCounter += 1;
276
+ return `${prefix}-${idCounter}`;
277
+ }
271
278
  var spectreInputSizes = ["sm", "md", "lg"];
272
279
  function isInputSize(value) {
273
280
  return spectreInputSizes.includes(value);
@@ -295,9 +302,31 @@ function normalizeInt(value, fallback, min = 0) {
295
302
  }
296
303
  return value;
297
304
  }
305
+
306
+ // src/utils/states.ts
307
+ var hoverFocusStateProperties = {
308
+ focused: { type: Boolean, reflect: true },
309
+ hovered: { type: Boolean, reflect: true }
310
+ };
311
+ var interactionStateProperties = {
312
+ ...hoverFocusStateProperties,
313
+ active: { type: Boolean, reflect: true }
314
+ };
315
+ function hoverFocusStates(element) {
316
+ return {
317
+ focused: element.focused ?? false,
318
+ hovered: element.hovered ?? false
319
+ };
320
+ }
321
+ function interactionStates(element) {
322
+ return { ...hoverFocusStates(element), active: element.active ?? false };
323
+ }
298
324
  var SpectreInputElement = class extends SpectreBaseElement {
299
325
  constructor() {
300
326
  super(...arguments);
327
+ this.active = false;
328
+ this.focused = false;
329
+ this.hovered = false;
301
330
  this.disabled = false;
302
331
  this.fullWidth = false;
303
332
  this.invalid = false;
@@ -309,6 +338,10 @@ var SpectreInputElement = class extends SpectreBaseElement {
309
338
  this.success = false;
310
339
  this.type = "text";
311
340
  this.value = "";
341
+ this.errorMessage = void 0;
342
+ this.helperText = void 0;
343
+ this.label = void 0;
344
+ this.generatedId = createUniqueId("sp-input");
312
345
  }
313
346
  get autocapitalize() {
314
347
  return super.autocapitalize;
@@ -383,12 +416,30 @@ var SpectreInputElement = class extends SpectreBaseElement {
383
416
  }
384
417
  get inputClasses() {
385
418
  return spectreUi.getInputClasses({
419
+ ...interactionStates(this),
386
420
  fullWidth: this.fullWidth ?? false,
387
421
  pill: this.pill ?? false,
388
422
  size: this.size,
389
- state: this.isDisabled ? this.disabled ? "disabled" : "loading" : this.invalid ? "error" : this.success ? "success" : "default"
423
+ state: this.isDisabled ? this.disabled ? "disabled" : "loading" : this.invalid || this.errorMessage ? "error" : this.success ? "success" : "default"
390
424
  });
391
425
  }
426
+ get inputId() {
427
+ return this.id || this.generatedId;
428
+ }
429
+ get hasFieldChrome() {
430
+ return Boolean(this.label || this.helperText || this.errorMessage);
431
+ }
432
+ // An error message replaces the helper text while it is shown.
433
+ get messageId() {
434
+ if (this.errorMessage) {
435
+ return `${this.inputId}-error`;
436
+ }
437
+ return this.helperText ? `${this.inputId}-helper` : void 0;
438
+ }
439
+ get describedBy() {
440
+ const ids = [this.forwardedAriaDescribedBy, this.messageId].filter(Boolean);
441
+ return ids.length > 0 ? ids.join(" ") : void 0;
442
+ }
392
443
  get nativeInput() {
393
444
  return this.querySelector("[data-sp-input-native]");
394
445
  }
@@ -406,11 +457,48 @@ var SpectreInputElement = class extends SpectreBaseElement {
406
457
  blur() {
407
458
  this.nativeInput?.blur();
408
459
  }
460
+ renderMessage() {
461
+ if (this.errorMessage) {
462
+ return lit.html`<p
463
+ aria-atomic="true"
464
+ aria-live="polite"
465
+ class="${spectreUi.getInputErrorMessageClasses()}"
466
+ id="${this.inputId}-error"
467
+ >
468
+ ${this.errorMessage}
469
+ </p>`;
470
+ }
471
+ if (this.helperText) {
472
+ return lit.html`<p
473
+ class="${spectreUi.getInputHelperTextClasses({ disabled: this.isDisabled })}"
474
+ id="${this.inputId}-helper"
475
+ >
476
+ ${this.helperText}
477
+ </p>`;
478
+ }
479
+ return lit.nothing;
480
+ }
481
+ // Without a label or message the native input renders alone, as before.
409
482
  render() {
483
+ if (!this.hasFieldChrome) {
484
+ return this.renderInput();
485
+ }
486
+ return lit.html`<div class="${spectreUi.getInputWrapperClasses()}" data-sp-input-wrapper>
487
+ ${this.label ? lit.html`<label
488
+ class="${spectreUi.getInputLabelClasses({ disabled: this.isDisabled })}"
489
+ for="${this.inputId}"
490
+ >${this.label}</label
491
+ >` : lit.nothing}
492
+ ${this.renderInput()} ${this.renderMessage()}
493
+ </div>`;
494
+ }
495
+ renderInput() {
410
496
  return lit.html`<input
411
497
  aria-busy="${this.loading ? "true" : "false"}"
412
- aria-describedby="${ifDefined_js.ifDefined(this.forwardedAriaDescribedBy)}"
413
- aria-invalid="${ifDefined_js.ifDefined(this.invalid ? "true" : void 0)}"
498
+ aria-describedby="${ifDefined_js.ifDefined(this.describedBy)}"
499
+ aria-invalid="${ifDefined_js.ifDefined(
500
+ this.invalid || this.errorMessage ? "true" : void 0
501
+ )}"
414
502
  aria-label="${ifDefined_js.ifDefined(this.forwardedAriaLabel)}"
415
503
  aria-labelledby="${ifDefined_js.ifDefined(this.forwardedAriaLabelledBy)}"
416
504
  autocapitalize="${ifDefined_js.ifDefined(this.autocapitalize || void 0)}"
@@ -423,7 +511,7 @@ var SpectreInputElement = class extends SpectreBaseElement {
423
511
  form="${ifDefined_js.ifDefined(this.form || void 0)}"
424
512
  ?readonly="${this.readonly}"
425
513
  ?required="${this.required}"
426
- id="${ifDefined_js.ifDefined(this.id || void 0)}"
514
+ id="${ifDefined_js.ifDefined(this.hasFieldChrome ? this.inputId : this.id || void 0)}"
427
515
  inputmode="${ifDefined_js.ifDefined(this.inputmode || void 0)}"
428
516
  list="${ifDefined_js.ifDefined(this.list || void 0)}"
429
517
  max="${ifDefined_js.ifDefined(this.max || void 0)}"
@@ -444,9 +532,13 @@ var SpectreInputElement = class extends SpectreBaseElement {
444
532
  }
445
533
  };
446
534
  SpectreInputElement.properties = {
535
+ ...interactionStateProperties,
447
536
  autocomplete: { type: String, reflect: true },
448
537
  disabled: { type: Boolean, reflect: true },
449
538
  enterkeyhint: { type: String, reflect: true },
539
+ errorMessage: { attribute: "error-message", type: String },
540
+ helperText: { attribute: "helper-text", type: String },
541
+ label: { type: String },
450
542
  form: { type: String },
451
543
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
452
544
  inputmode: { type: String, reflect: true },