@sankhyatronics/sankhya-cms 0.1.18 → 0.3.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 (216) hide show
  1. package/custom-elements.json +11634 -3153
  2. package/dist/attention-panel/index.js +2 -2
  3. package/dist/bar-chart/index.js +2 -2
  4. package/dist/bento-grid/index.d.ts +33 -1
  5. package/dist/bento-grid/index.js +4 -3
  6. package/dist/booking/index.d.ts +309 -0
  7. package/dist/booking/index.js +20 -0
  8. package/dist/booking/index.js.map +1 -0
  9. package/dist/card/index.d.ts +3 -4
  10. package/dist/card/index.js +2 -2
  11. package/dist/carousel/index.d.ts +20 -6
  12. package/dist/carousel/index.js +3 -3
  13. package/dist/chip/index.js +2 -2
  14. package/dist/{chunk-JQY2G4QK.js → chunk-2GTR37PU.js} +2 -2
  15. package/dist/chunk-2GTR37PU.js.map +1 -0
  16. package/dist/{chunk-FLY7TNRT.js → chunk-2HMOX253.js} +128 -25
  17. package/dist/chunk-2HMOX253.js.map +1 -0
  18. package/dist/{chunk-DH53HZPB.js → chunk-37KFBKPD.js} +32 -4
  19. package/dist/chunk-37KFBKPD.js.map +1 -0
  20. package/dist/{chunk-ALI26WOB.js → chunk-4XPKKYVZ.js} +54 -15
  21. package/dist/chunk-4XPKKYVZ.js.map +1 -0
  22. package/dist/chunk-535QAZ6A.js +236 -0
  23. package/dist/chunk-535QAZ6A.js.map +1 -0
  24. package/dist/{chunk-AKJQ345O.js → chunk-5AWGZQWU.js} +2 -2
  25. package/dist/chunk-6OZKZG5J.js +300 -0
  26. package/dist/chunk-6OZKZG5J.js.map +1 -0
  27. package/dist/chunk-AYNT7G3J.js +805 -0
  28. package/dist/chunk-AYNT7G3J.js.map +1 -0
  29. package/dist/chunk-BEWX3E6P.js +32 -0
  30. package/dist/chunk-BEWX3E6P.js.map +1 -0
  31. package/dist/chunk-CZUGPKXV.js +275 -0
  32. package/dist/chunk-CZUGPKXV.js.map +1 -0
  33. package/dist/{chunk-LEXZKGQX.js → chunk-DJFWZOZM.js} +107 -11
  34. package/dist/chunk-DJFWZOZM.js.map +1 -0
  35. package/dist/chunk-DPANTC3O.js +1714 -0
  36. package/dist/chunk-DPANTC3O.js.map +1 -0
  37. package/dist/chunk-EKZFFY45.js +426 -0
  38. package/dist/chunk-EKZFFY45.js.map +1 -0
  39. package/dist/chunk-ER7MCPDV.js +7 -0
  40. package/dist/chunk-ER7MCPDV.js.map +1 -0
  41. package/dist/chunk-EW2RK5Y6.js +383 -0
  42. package/dist/chunk-EW2RK5Y6.js.map +1 -0
  43. package/dist/{chunk-BLQV2YMO.js → chunk-EZOKT7NJ.js} +2 -2
  44. package/dist/chunk-FF2LWEF3.js +386 -0
  45. package/dist/chunk-FF2LWEF3.js.map +1 -0
  46. package/dist/chunk-FOUK3NHR.js +7 -0
  47. package/dist/chunk-FOUK3NHR.js.map +1 -0
  48. package/dist/chunk-GB4NGCZI.js +181 -0
  49. package/dist/chunk-GB4NGCZI.js.map +1 -0
  50. package/dist/{chunk-7NLZND6Q.js → chunk-GOFSMD6W.js} +35 -11
  51. package/dist/chunk-GOFSMD6W.js.map +1 -0
  52. package/dist/{chunk-6D6ROU7X.js → chunk-IGMVF3KK.js} +2 -2
  53. package/dist/{chunk-INMSEYT6.js → chunk-IVPVYVWG.js} +2 -2
  54. package/dist/chunk-JURCF4OD.js +381 -0
  55. package/dist/chunk-JURCF4OD.js.map +1 -0
  56. package/dist/{chunk-FZ36KL73.js → chunk-KZ7PMFWS.js} +11 -1
  57. package/dist/chunk-KZ7PMFWS.js.map +1 -0
  58. package/dist/{chunk-EMCQBT3S.js → chunk-LO6TZBGD.js} +129 -35
  59. package/dist/chunk-LO6TZBGD.js.map +1 -0
  60. package/dist/chunk-MFRGAT6D.js +860 -0
  61. package/dist/chunk-MFRGAT6D.js.map +1 -0
  62. package/dist/chunk-MIBVQXRU.js +1098 -0
  63. package/dist/chunk-MIBVQXRU.js.map +1 -0
  64. package/dist/{chunk-35TX3AOA.js → chunk-NABSRUXG.js} +2 -2
  65. package/dist/{chunk-R5G6KFTJ.js → chunk-NXKDZWS7.js} +44 -6
  66. package/dist/chunk-NXKDZWS7.js.map +1 -0
  67. package/dist/{chunk-KMU6ABQF.js → chunk-NXUS2CH7.js} +14 -1
  68. package/dist/chunk-NXUS2CH7.js.map +1 -0
  69. package/dist/{chunk-GJO3RGOB.js → chunk-OCPGOLVF.js} +56 -11
  70. package/dist/chunk-OCPGOLVF.js.map +1 -0
  71. package/dist/chunk-OEOE6IFY.js +628 -0
  72. package/dist/chunk-OEOE6IFY.js.map +1 -0
  73. package/dist/{chunk-SMLR736E.js → chunk-PV6OCXXN.js} +2 -2
  74. package/dist/chunk-PV6OCXXN.js.map +1 -0
  75. package/dist/chunk-Q66CJO3P.js +534 -0
  76. package/dist/chunk-Q66CJO3P.js.map +1 -0
  77. package/dist/{chunk-MG2VTZA4.js → chunk-QS3ANOWN.js} +2 -2
  78. package/dist/{chunk-ZN4LIKVG.js → chunk-QSJ543V2.js} +2 -2
  79. package/dist/chunk-QSJ543V2.js.map +1 -0
  80. package/dist/{chunk-FML6AG2V.js → chunk-RANC3OI6.js} +2 -2
  81. package/dist/chunk-T4BIN37Q.js +32 -0
  82. package/dist/chunk-T4BIN37Q.js.map +1 -0
  83. package/dist/{chunk-YVTFQHVY.js → chunk-TEAZZPDQ.js} +2 -2
  84. package/dist/chunk-TJK55CJ2.js +49 -0
  85. package/dist/chunk-TJK55CJ2.js.map +1 -0
  86. package/dist/chunk-UKIVLF7S.js +32 -0
  87. package/dist/chunk-UKIVLF7S.js.map +1 -0
  88. package/dist/chunk-V4R7PYP5.js +905 -0
  89. package/dist/chunk-V4R7PYP5.js.map +1 -0
  90. package/dist/{chunk-AG2COC64.js → chunk-VVYQ2DDS.js} +2 -2
  91. package/dist/chunk-WAMOAAMN.js +16 -0
  92. package/dist/chunk-WAMOAAMN.js.map +1 -0
  93. package/dist/chunk-WAYHHL4J.js +1234 -0
  94. package/dist/chunk-WAYHHL4J.js.map +1 -0
  95. package/dist/{chunk-YQ42EBK5.js → chunk-WH6HE6SY.js} +10 -4
  96. package/dist/chunk-WH6HE6SY.js.map +1 -0
  97. package/dist/chunk-XP6DI3VY.js +180 -0
  98. package/dist/chunk-XP6DI3VY.js.map +1 -0
  99. package/dist/{chunk-5EBWMPJS.js → chunk-XS6LNTSH.js} +76 -14
  100. package/dist/chunk-XS6LNTSH.js.map +1 -0
  101. package/dist/{chunk-WT4OATGP.js → chunk-ZKFCDVB4.js} +16 -7
  102. package/dist/chunk-ZKFCDVB4.js.map +1 -0
  103. package/dist/cms-theme.css +29 -0
  104. package/dist/contact-form/index.d.ts +220 -0
  105. package/dist/contact-form/index.js +16 -0
  106. package/dist/contact-form/index.js.map +1 -0
  107. package/dist/content-block/index.d.ts +39 -4
  108. package/dist/content-block/index.js +8 -4
  109. package/dist/cookie-consent/index.d.ts +60 -12
  110. package/dist/cookie-consent/index.js +3 -2
  111. package/dist/date-tile/index.js +2 -2
  112. package/dist/dropdown/index.d.ts +29 -11
  113. package/dist/dropdown/index.js +4 -2
  114. package/dist/feature-split/index.d.ts +6 -1
  115. package/dist/feature-split/index.js +5 -4
  116. package/dist/features-section/index.d.ts +53 -9
  117. package/dist/features-section/index.js +6 -5
  118. package/dist/flow/index.d.ts +35 -0
  119. package/dist/flow/index.js +9 -0
  120. package/dist/flow/index.js.map +1 -0
  121. package/dist/footer/index.d.ts +13 -0
  122. package/dist/footer/index.js +2 -2
  123. package/dist/header/index.d.ts +135 -16
  124. package/dist/header/index.js +3 -2
  125. package/dist/hero/index.d.ts +92 -8
  126. package/dist/hero/index.js +6 -3
  127. package/dist/icon-button/index.d.ts +7 -7
  128. package/dist/icon-button/index.js +2 -2
  129. package/dist/index.d.ts +12 -3
  130. package/dist/index.js +121 -47
  131. package/dist/items-accordion/index.d.ts +9 -0
  132. package/dist/items-accordion/index.js +4 -3
  133. package/dist/kpi-card/index.js +2 -2
  134. package/dist/markdown/index.d.ts +19 -2
  135. package/dist/markdown/index.js +3 -2
  136. package/dist/mega-menu/index.d.ts +95 -7
  137. package/dist/mega-menu/index.js +7 -2
  138. package/dist/menu-grid/index.d.ts +2 -3
  139. package/dist/menu-grid/index.js +2 -2
  140. package/dist/menu-grid-item/index.d.ts +6 -8
  141. package/dist/menu-grid-item/index.js +2 -2
  142. package/dist/menu-item/index.d.ts +11 -7
  143. package/dist/menu-item/index.js +3 -2
  144. package/dist/plan-cards/index.d.ts +69 -0
  145. package/dist/plan-cards/index.js +13 -0
  146. package/dist/plan-cards/index.js.map +1 -0
  147. package/dist/product-nav/index.d.ts +127 -0
  148. package/dist/product-nav/index.js +11 -0
  149. package/dist/product-nav/index.js.map +1 -0
  150. package/dist/promo-banner/index.d.ts +42 -4
  151. package/dist/promo-banner/index.js +6 -3
  152. package/dist/quote-dialog/index.d.ts +174 -0
  153. package/dist/quote-dialog/index.js +22 -0
  154. package/dist/quote-dialog/index.js.map +1 -0
  155. package/dist/schema/index.d.ts +11 -0
  156. package/dist/schema/index.js +9 -0
  157. package/dist/schema/index.js.map +1 -1
  158. package/dist/screenshot-tour/index.d.ts +54 -0
  159. package/dist/screenshot-tour/index.js +9 -0
  160. package/dist/screenshot-tour/index.js.map +1 -0
  161. package/dist/section/index.d.ts +3 -0
  162. package/dist/section/index.js +3 -3
  163. package/dist/segmented-control/index.js +2 -2
  164. package/dist/select/index.js +2 -2
  165. package/dist/shared/styles.d.ts +7 -1
  166. package/dist/shared/styles.js +3 -1
  167. package/dist/stats/index.js +2 -2
  168. package/dist/steps/index.d.ts +45 -0
  169. package/dist/steps/index.js +11 -0
  170. package/dist/steps/index.js.map +1 -0
  171. package/dist/tag-strip/index.d.ts +33 -0
  172. package/dist/tag-strip/index.js +9 -0
  173. package/dist/tag-strip/index.js.map +1 -0
  174. package/dist/testimonials/index.d.ts +9 -1
  175. package/dist/testimonials/index.js +3 -3
  176. package/dist/tooltip/index.js +2 -2
  177. package/package.json +38 -2
  178. package/dist/chunk-5EBWMPJS.js.map +0 -1
  179. package/dist/chunk-76AVBQUA.js +0 -252
  180. package/dist/chunk-76AVBQUA.js.map +0 -1
  181. package/dist/chunk-7NLZND6Q.js.map +0 -1
  182. package/dist/chunk-ALI26WOB.js.map +0 -1
  183. package/dist/chunk-BMHMNXIA.js +0 -158
  184. package/dist/chunk-BMHMNXIA.js.map +0 -1
  185. package/dist/chunk-DH53HZPB.js.map +0 -1
  186. package/dist/chunk-EMCQBT3S.js.map +0 -1
  187. package/dist/chunk-FLY7TNRT.js.map +0 -1
  188. package/dist/chunk-FZ36KL73.js.map +0 -1
  189. package/dist/chunk-GJO3RGOB.js.map +0 -1
  190. package/dist/chunk-J6EO4R73.js +0 -633
  191. package/dist/chunk-J6EO4R73.js.map +0 -1
  192. package/dist/chunk-JKBWZLG4.js +0 -348
  193. package/dist/chunk-JKBWZLG4.js.map +0 -1
  194. package/dist/chunk-JQY2G4QK.js.map +0 -1
  195. package/dist/chunk-KMU6ABQF.js.map +0 -1
  196. package/dist/chunk-LEXZKGQX.js.map +0 -1
  197. package/dist/chunk-MSSH3HFK.js +0 -205
  198. package/dist/chunk-MSSH3HFK.js.map +0 -1
  199. package/dist/chunk-R5G6KFTJ.js.map +0 -1
  200. package/dist/chunk-SMLR736E.js.map +0 -1
  201. package/dist/chunk-VWS53WY4.js +0 -157
  202. package/dist/chunk-VWS53WY4.js.map +0 -1
  203. package/dist/chunk-WT4OATGP.js.map +0 -1
  204. package/dist/chunk-XWB4CKDU.js +0 -708
  205. package/dist/chunk-XWB4CKDU.js.map +0 -1
  206. package/dist/chunk-YQ42EBK5.js.map +0 -1
  207. package/dist/chunk-ZN4LIKVG.js.map +0 -1
  208. /package/dist/{chunk-AKJQ345O.js.map → chunk-5AWGZQWU.js.map} +0 -0
  209. /package/dist/{chunk-BLQV2YMO.js.map → chunk-EZOKT7NJ.js.map} +0 -0
  210. /package/dist/{chunk-6D6ROU7X.js.map → chunk-IGMVF3KK.js.map} +0 -0
  211. /package/dist/{chunk-INMSEYT6.js.map → chunk-IVPVYVWG.js.map} +0 -0
  212. /package/dist/{chunk-35TX3AOA.js.map → chunk-NABSRUXG.js.map} +0 -0
  213. /package/dist/{chunk-MG2VTZA4.js.map → chunk-QS3ANOWN.js.map} +0 -0
  214. /package/dist/{chunk-FML6AG2V.js.map → chunk-RANC3OI6.js.map} +0 -0
  215. /package/dist/{chunk-YVTFQHVY.js.map → chunk-TEAZZPDQ.js.map} +0 -0
  216. /package/dist/{chunk-AG2COC64.js.map → chunk-VVYQ2DDS.js.map} +0 -0
@@ -0,0 +1,905 @@
1
+ import {
2
+ CONTACT_FIELD_NAMES,
3
+ CONTACT_LIMITS,
4
+ COUNTER_SHOW_RATIO,
5
+ DEFAULT_ERROR_MESSAGES,
6
+ ERROR_SUMMARY_MIN,
7
+ buildContactPayload,
8
+ codePointLength,
9
+ counterBand,
10
+ fillTemplate,
11
+ firstInvalidField,
12
+ groupTopics,
13
+ normalizeTopics,
14
+ parseTopicsAttribute,
15
+ readContactQuery,
16
+ resolvePreselectedTopic,
17
+ safeMailto,
18
+ splitMailto,
19
+ submitContact,
20
+ validateContact
21
+ } from "./chunk-CZUGPKXV.js";
22
+ import {
23
+ controlBaseStyles,
24
+ fontFamilyStyles
25
+ } from "./chunk-NXUS2CH7.js";
26
+ import {
27
+ __decorateClass
28
+ } from "./chunk-EUXUH3YW.js";
29
+
30
+ // src/contact-form/ContactForm.ts
31
+ import { LitElement, css, html, nothing, svg } from "lit";
32
+ import { customElement, property, query, state } from "lit/decorators.js";
33
+
34
+ // src/contact-form/ContactFormEvents.ts
35
+ var CONTACT_FORM_SUBMIT_EVENT = "st-contact-form-submit";
36
+ var CONTACT_FORM_SENT_EVENT = "st-contact-form-sent";
37
+ var CONTACT_FORM_ERROR_EVENT = "st-contact-form-error";
38
+
39
+ // src/contact-form/ContactForm.ts
40
+ var SUCCESS_ICON = svg`<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round"></path></svg>`;
41
+ var FIELD_ORDER = CONTACT_FIELD_NAMES;
42
+ var ContactForm = class extends LitElement {
43
+ constructor() {
44
+ super(...arguments);
45
+ this.endpoint = "";
46
+ this.topics = [];
47
+ this.defaultTopic = "";
48
+ this.showPhone = true;
49
+ this.locale = "";
50
+ this.page = "";
51
+ this.nameLabel = "Full name";
52
+ this.emailLabel = "Work email";
53
+ this.companyLabel = "Company";
54
+ this.phoneLabel = "Phone (optional)";
55
+ this.topicLabel = "Topic";
56
+ this.topicPlaceholder = "Select a topic";
57
+ this.messageLabel = "Message";
58
+ this.namePlaceholder = "Your name";
59
+ this.emailPlaceholder = "you@company.com";
60
+ this.companyPlaceholder = "Your company";
61
+ this.messagePlaceholder = "Tell us what you need";
62
+ this.messageCounter = "{count} / {max}";
63
+ this.submitLabel = "Send message";
64
+ this.sendingLabel = "Sending\u2026";
65
+ this.requiredLabel = "required";
66
+ this.aboutLabel = "About:";
67
+ this.consentLabel = "I agree that Sankhyatronics may use these details to reply to my enquiry.";
68
+ this.privacyNote = "";
69
+ this.privacyLinkLabel = "Privacy Policy";
70
+ this.privacyHref = "/privacy-policy";
71
+ this.sentNote = "Thanks, your message has been sent. We will reply soon.";
72
+ this.referenceLabel = "Your reference:";
73
+ this.errorNote = "Sorry, your message could not be sent. Please try again later.";
74
+ this.rateLimitedNote = "You have sent several messages in a short time. Please wait {seconds} seconds and try again.";
75
+ this.rateLimitedGenericNote = "You have sent several messages in a short time. Please wait a little and try again.";
76
+ this.errorSummary = "Please fix {count} fields.";
77
+ this.errorSummaryOne = "Please fix {count} field.";
78
+ this.requiredNote = "* Required";
79
+ this.mailto = "";
80
+ this.errorMessages = {};
81
+ this.errors = {};
82
+ this.alertText = "";
83
+ this.alertOwn = false;
84
+ this.outcome = null;
85
+ this.sending = false;
86
+ this.messageLength = 0;
87
+ this.counterAnnouncement = "";
88
+ this.counterBandValue = 0;
89
+ /** `product` and `topic` from the page URL, read once on connect. */
90
+ this.queryParams = { product: null, topic: null };
91
+ this.inflight = null;
92
+ }
93
+ connectedCallback() {
94
+ super.connectedCallback();
95
+ this.queryParams = readContactQuery(window.location.search);
96
+ }
97
+ disconnectedCallback() {
98
+ this.inflight?.abort();
99
+ this.inflight = null;
100
+ this.sending = false;
101
+ super.disconnectedCallback();
102
+ }
103
+ get topicList() {
104
+ return normalizeTopics(this.topics);
105
+ }
106
+ get preselect() {
107
+ return resolvePreselectedTopic(this.topicList, {
108
+ defaultTopic: this.defaultTopic,
109
+ product: this.queryParams.product,
110
+ topic: this.queryParams.topic
111
+ });
112
+ }
113
+ labels() {
114
+ return {
115
+ name: this.nameLabel,
116
+ email: this.emailLabel,
117
+ company: this.companyLabel,
118
+ phone: this.phoneLabel,
119
+ topic: this.topicLabel,
120
+ message: this.messageLabel
121
+ };
122
+ }
123
+ /** The defaults, with each key replaced by the override when it is a string. */
124
+ messages() {
125
+ const merged = { ...DEFAULT_ERROR_MESSAGES };
126
+ for (const key of Object.keys(merged)) {
127
+ const override = this.errorMessages[key];
128
+ if (typeof override === "string") merged[key] = override;
129
+ }
130
+ return merged;
131
+ }
132
+ readText(form, name) {
133
+ const field = form.elements.namedItem(name);
134
+ return field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement || field instanceof HTMLSelectElement ? field.value : "";
135
+ }
136
+ readValues(form) {
137
+ const consent = form.elements.namedItem("consent");
138
+ return {
139
+ name: this.readText(form, "name"),
140
+ email: this.readText(form, "email"),
141
+ company: this.readText(form, "company"),
142
+ phone: this.readText(form, "phone"),
143
+ topic: this.readText(form, "topic"),
144
+ message: this.readText(form, "message"),
145
+ consent: consent instanceof HTMLInputElement && consent.checked,
146
+ website: this.readText(form, "website")
147
+ };
148
+ }
149
+ async onSubmit(event) {
150
+ event.preventDefault();
151
+ if (this.sending) return;
152
+ const form = event.currentTarget;
153
+ const values = this.readValues(form);
154
+ this.outcome = null;
155
+ const errors = validateContact(values, { labels: this.labels(), topics: this.topicList, messages: this.messages() });
156
+ this.errors = errors;
157
+ this.alertText = "";
158
+ this.alertOwn = false;
159
+ if (firstInvalidField(errors)) {
160
+ this.focusProblem(errors);
161
+ return;
162
+ }
163
+ this.dispatchEvent(
164
+ new CustomEvent(CONTACT_FORM_SUBMIT_EVENT, {
165
+ detail: { topic: values.topic.trim() },
166
+ bubbles: true,
167
+ composed: true
168
+ })
169
+ );
170
+ const payload = buildContactPayload(values, {
171
+ page: this.page || window.location.pathname,
172
+ locale: this.locale || document.documentElement.lang || "en",
173
+ now: /* @__PURE__ */ new Date()
174
+ });
175
+ const controller = new AbortController();
176
+ this.inflight = controller;
177
+ this.sending = true;
178
+ const hadFocus = this.shadowRoot?.activeElement === this.submitEl;
179
+ const result = await submitContact({ endpoint: this.endpoint.trim(), payload, signal: controller.signal });
180
+ if (this.inflight !== controller) return;
181
+ this.inflight = null;
182
+ this.sending = false;
183
+ this.applyResult(result, form);
184
+ if (hadFocus && result.kind !== "validation") {
185
+ void this.updateComplete.then(() => this.submitEl?.focus());
186
+ }
187
+ }
188
+ applyResult(result, form) {
189
+ switch (result.kind) {
190
+ case "sent":
191
+ form.reset();
192
+ this.errors = {};
193
+ this.alertText = "";
194
+ this.alertOwn = false;
195
+ this.messageLength = 0;
196
+ this.counterBandValue = 0;
197
+ this.counterAnnouncement = "";
198
+ this.outcome = result.reference === void 0 ? {} : { reference: result.reference };
199
+ this.dispatchEvent(
200
+ new CustomEvent(CONTACT_FORM_SENT_EVENT, {
201
+ detail: result.reference === void 0 ? {} : { reference: result.reference },
202
+ bubbles: true,
203
+ composed: true
204
+ })
205
+ );
206
+ return;
207
+ case "validation": {
208
+ const shown = {};
209
+ const hidden = [];
210
+ for (const name of FIELD_ORDER) {
211
+ const message = result.errors[name];
212
+ if (message === void 0) continue;
213
+ if (name === "phone" && !this.showPhone) hidden.push(message);
214
+ else shown[name] = message;
215
+ }
216
+ this.errors = shown;
217
+ this.alertText = [result.formMessage, ...hidden].filter(Boolean).join(" ");
218
+ this.alertOwn = false;
219
+ this.focusProblem(shown);
220
+ this.dispatchError("validation");
221
+ return;
222
+ }
223
+ case "rate_limited":
224
+ this.alertOwn = true;
225
+ this.alertText = result.retryAfterSeconds === void 0 ? this.rateLimitedGenericNote : fillTemplate(this.rateLimitedNote, { seconds: result.retryAfterSeconds });
226
+ this.dispatchError("rate_limited");
227
+ return;
228
+ case "unavailable":
229
+ this.alertOwn = true;
230
+ this.alertText = this.errorNote;
231
+ this.dispatchError("unavailable");
232
+ return;
233
+ }
234
+ }
235
+ focusField(name) {
236
+ if (!name) return;
237
+ void this.updateComplete.then(() => this.renderRoot.querySelector(`#cf-${name}`)?.focus());
238
+ }
239
+ /** Many failing fields: focus the summary, which links to each. One or two: the first field. */
240
+ focusProblem(errors) {
241
+ if (this.failingFields(errors).length >= ERROR_SUMMARY_MIN) {
242
+ void this.updateComplete.then(() => this.renderRoot.querySelector("#cf-summary")?.focus());
243
+ return;
244
+ }
245
+ this.focusField(firstInvalidField(errors));
246
+ }
247
+ failingFields(errors = this.errors) {
248
+ return FIELD_ORDER.filter((name) => errors[name] !== void 0 && errors[name] !== "");
249
+ }
250
+ onSummaryLink(event, name) {
251
+ event.preventDefault();
252
+ this.focusField(name);
253
+ }
254
+ dispatchError(kind) {
255
+ this.dispatchEvent(
256
+ new CustomEvent(CONTACT_FORM_ERROR_EVENT, {
257
+ detail: { kind },
258
+ bubbles: true,
259
+ composed: true
260
+ })
261
+ );
262
+ }
263
+ onMessageInput(event) {
264
+ const field = event.target;
265
+ this.messageLength = codePointLength(field.value.trim());
266
+ const band = counterBand(this.messageLength, CONTACT_LIMITS.messageMax);
267
+ if (band !== this.counterBandValue) {
268
+ this.counterBandValue = band;
269
+ this.counterAnnouncement = band === 0 ? "" : fillTemplate(this.messageCounter, { count: this.messageLength, max: CONTACT_LIMITS.messageMax });
270
+ }
271
+ }
272
+ errorSummaryText() {
273
+ const count = this.failingFields().length;
274
+ if (count === 0) return "";
275
+ return fillTemplate(count === 1 ? this.errorSummaryOne : this.errorSummary, { count });
276
+ }
277
+ /** The alert's text. Only the component's own notes get a link for `{mailto}`; server text stays plain. */
278
+ renderAlertText() {
279
+ if (!this.alertOwn) return this.alertText;
280
+ const address = safeMailto(this.mailto);
281
+ return splitMailto(this.alertText).map(
282
+ (piece) => piece !== null ? piece : address ? html`<a href="mailto:${address}">${address}</a>` : nothing
283
+ );
284
+ }
285
+ renderSummary() {
286
+ const failing = this.failingFields();
287
+ if (failing.length < ERROR_SUMMARY_MIN) return nothing;
288
+ return html`<div class="summary" part="summary" id="cf-summary" role="alert" tabindex="-1">
289
+ <p class="summary-title">${this.errorSummaryText()}</p>
290
+ <ul>
291
+ ${failing.map(
292
+ (name) => html`<li><a href="#cf-${name}" @click=${(event) => this.onSummaryLink(event, name)}>${this.errors[name]}</a></li>`
293
+ )}
294
+ </ul>
295
+ </div>`;
296
+ }
297
+ requiredMark() {
298
+ return html`<span aria-hidden="true"> *</span><span class="sr-only"> (${this.requiredLabel})</span>`;
299
+ }
300
+ renderInput(name, label, options) {
301
+ const error = this.errors[name];
302
+ return html`<div class="field" part="field">
303
+ <label class="label" part="label" for="cf-${name}">${label}${options.required ? this.requiredMark() : nothing}</label>
304
+ <input
305
+ class="input"
306
+ part="input"
307
+ id="cf-${name}"
308
+ name=${name}
309
+ type=${options.type}
310
+ autocomplete=${options.autocomplete}
311
+ inputmode=${options.inputmode ?? nothing}
312
+ placeholder=${options.placeholder || nothing}
313
+ ?required=${options.required}
314
+ aria-invalid=${error ? "true" : "false"}
315
+ aria-describedby=${error ? `cf-${name}-error` : nothing}
316
+ />
317
+ ${error ? html`<p class="error" part="error" id="cf-${name}-error">${error}</p>` : nothing}
318
+ </div>`;
319
+ }
320
+ /** Not `renderOptions`: LitElement already has that instance property. */
321
+ renderChoices(topics, selected) {
322
+ return topics.map(
323
+ (topic) => html`<option value=${topic.value} ?selected=${topic.value === selected}>${topic.label}</option>`
324
+ );
325
+ }
326
+ renderTopic(groups, selected) {
327
+ const error = this.errors.topic;
328
+ return html`<div class="field full" part="field">
329
+ <label class="label" part="label" for="cf-topic">${this.topicLabel}${this.requiredMark()}</label>
330
+ <select
331
+ class="input select"
332
+ part="input"
333
+ id="cf-topic"
334
+ name="topic"
335
+ required
336
+ aria-invalid=${error ? "true" : "false"}
337
+ aria-describedby=${error ? "cf-topic-error" : nothing}
338
+ >
339
+ <option value="" disabled ?selected=${selected === ""}>${this.topicPlaceholder}</option>
340
+ ${groups.map(
341
+ (group) => group.group === void 0 ? this.renderChoices(group.topics, selected) : html`<optgroup label=${group.group}>${this.renderChoices(group.topics, selected)}</optgroup>`
342
+ )}
343
+ </select>
344
+ ${error ? html`<p class="error" part="error" id="cf-topic-error">${error}</p>` : nothing}
345
+ </div>`;
346
+ }
347
+ renderMessage() {
348
+ const error = this.errors.message;
349
+ const max = CONTACT_LIMITS.messageMax;
350
+ const over = this.messageLength > max;
351
+ const showCounter = this.messageLength >= max * COUNTER_SHOW_RATIO;
352
+ const describedBy = [showCounter ? "cf-message-count" : "", error ? "cf-message-error" : ""].filter(Boolean).join(" ");
353
+ return html`<div class="field full" part="field">
354
+ <label class="label" part="label" for="cf-message">${this.messageLabel}${this.requiredMark()}</label>
355
+ <textarea
356
+ class="input"
357
+ part="input"
358
+ id="cf-message"
359
+ name="message"
360
+ rows="6"
361
+ placeholder=${this.messagePlaceholder || nothing}
362
+ required
363
+ aria-invalid=${error ? "true" : "false"}
364
+ aria-describedby=${describedBy || nothing}
365
+ @input=${this.onMessageInput}
366
+ ></textarea>
367
+ <p class="sr-only" id="cf-message-live" aria-live="polite">${this.counterAnnouncement}</p>
368
+ ${showCounter ? html`<p class="counter ${over ? "over" : ""}" id="cf-message-count" aria-hidden="true">
369
+ ${fillTemplate(this.messageCounter, { count: this.messageLength, max })}
370
+ </p>` : nothing}
371
+ ${error ? html`<p class="error" part="error" id="cf-message-error">${error}</p>` : nothing}
372
+ </div>`;
373
+ }
374
+ renderConsent() {
375
+ const error = this.errors.consent;
376
+ return html`<div class="field full" part="field">
377
+ <label class="consent" part="consent">
378
+ <input
379
+ type="checkbox"
380
+ id="cf-consent"
381
+ name="consent"
382
+ required
383
+ aria-invalid=${error ? "true" : "false"}
384
+ aria-describedby=${error ? "cf-consent-error" : nothing}
385
+ />
386
+ <span>${this.consentLabel}${this.requiredMark()}</span>
387
+ </label>
388
+ ${error ? html`<p class="error" part="error" id="cf-consent-error">${error}</p>` : nothing}
389
+ </div>`;
390
+ }
391
+ render() {
392
+ const preselect = this.preselect;
393
+ const topics = this.topicList;
394
+ const aboutTopic = preselect.fromQuery ? topics.find((item) => item.value === preselect.value) : void 0;
395
+ const sending = this.sending;
396
+ const outcome = this.outcome;
397
+ return html`
398
+ <div class="live" role="status">
399
+ ${outcome ? html`<div class="success" part="success">
400
+ <span class="success-icon" aria-hidden="true">${SUCCESS_ICON}</span>
401
+ <p class="success-text">
402
+ ${this.sentNote}${outcome.reference ? html` ${this.referenceLabel} <strong class="reference">${outcome.reference}</strong>` : nothing}
403
+ </p>
404
+ </div>` : nothing}
405
+ </div>
406
+ <div class="alert ${this.alertText ? "has-text" : ""}" part="alert" role="alert">${this.renderAlertText()}</div>
407
+ <form
408
+ part="form"
409
+ novalidate
410
+ aria-busy=${sending ? "true" : "false"}
411
+ aria-describedby=${this.requiredNote ? "cf-required-note" : nothing}
412
+ @submit=${this.onSubmit}
413
+ >
414
+ ${this.requiredNote ? html`<p class="required-note" part="required-note" id="cf-required-note">${this.requiredNote}</p>` : nothing}
415
+ ${this.renderSummary()}
416
+ <p class="sr-only" aria-live="polite">${this.failingFields().length < ERROR_SUMMARY_MIN ? this.errorSummaryText() : ""}</p>
417
+ ${aboutTopic ? html`<p class="about"><span class="pill" part="about">${this.aboutLabel} ${aboutTopic.label}</span></p>` : nothing}
418
+ <div class="grid">
419
+ ${this.renderInput("name", this.nameLabel, {
420
+ type: "text",
421
+ autocomplete: "name",
422
+ placeholder: this.namePlaceholder,
423
+ required: true
424
+ })}
425
+ ${this.renderInput("email", this.emailLabel, {
426
+ type: "email",
427
+ autocomplete: "email",
428
+ placeholder: this.emailPlaceholder,
429
+ required: true
430
+ })}
431
+ ${this.renderInput("company", this.companyLabel, {
432
+ type: "text",
433
+ autocomplete: "organization",
434
+ placeholder: this.companyPlaceholder,
435
+ required: true
436
+ })}
437
+ ${this.showPhone ? this.renderInput("phone", this.phoneLabel, { type: "tel", autocomplete: "tel", inputmode: "tel", required: false }) : nothing}
438
+ ${this.renderTopic(groupTopics(topics), preselect.value)}
439
+ </div>
440
+ ${this.renderMessage()}
441
+ ${this.renderConsent()}
442
+ ${this.privacyNote ? html`<p class="privacy">${this.privacyNote} <a href=${this.privacyHref}>${this.privacyLinkLabel}</a></p>` : nothing}
443
+ <div class="hp" aria-hidden="true" inert>
444
+ <input type="text" name="website" tabindex="-1" autocomplete="off" aria-hidden="true" />
445
+ </div>
446
+ <button class="submit" part="submit" type="submit" ?disabled=${sending}>
447
+ ${sending ? this.sendingLabel : this.submitLabel}
448
+ </button>
449
+ </form>
450
+ `;
451
+ }
452
+ };
453
+ ContactForm.styles = css`
454
+ ${controlBaseStyles}
455
+
456
+ :host {
457
+ display: block;
458
+ box-sizing: border-box;
459
+ ${fontFamilyStyles}
460
+ }
461
+
462
+ *,
463
+ *::before,
464
+ *::after {
465
+ box-sizing: border-box;
466
+ }
467
+
468
+ form {
469
+ display: flex;
470
+ flex-direction: column;
471
+ gap: 16px;
472
+ margin: 0;
473
+ min-width: 0;
474
+ }
475
+
476
+ .grid {
477
+ display: grid;
478
+ grid-template-columns: minmax(0, 1fr);
479
+ gap: 16px;
480
+ }
481
+
482
+ .full {
483
+ grid-column: 1 / -1;
484
+ }
485
+
486
+ @media (min-width: 560px) {
487
+ .grid {
488
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
489
+ }
490
+ }
491
+
492
+ .field {
493
+ display: flex;
494
+ flex-direction: column;
495
+ gap: 6px;
496
+ min-width: 0;
497
+ }
498
+
499
+ /* Text uses the theme's own colour tokens (they swap in dark themes). The --st-cms-text* tokens are fixed
500
+ light-surface colours and would be unreadable on a dark surface. */
501
+ .label {
502
+ font-size: 14px;
503
+ font-weight: var(--st-font-weight-semibold);
504
+ color: var(--st-color-text-strong);
505
+ }
506
+
507
+ .input {
508
+ width: 100%;
509
+ min-height: 44px;
510
+ padding: 10px 14px;
511
+ border: 1px solid var(--st-color-border, var(--st-cms-primary-200));
512
+ border-radius: 12px;
513
+ background: var(--st-color-surface);
514
+ color: var(--st-color-text-strong);
515
+ /* 16px stops iOS zooming into the field. */
516
+ font: inherit;
517
+ font-size: 16px;
518
+ }
519
+
520
+ /* Browsers dim the placeholder; the muted text token is already 4.5:1 on the surface in both themes. */
521
+ .input::placeholder {
522
+ color: var(--st-color-text-muted);
523
+ opacity: 1;
524
+ }
525
+
526
+ .select {
527
+ appearance: auto;
528
+ }
529
+
530
+ .required-note {
531
+ margin: 0;
532
+ font-size: 14px;
533
+ color: var(--st-color-text);
534
+ }
535
+
536
+ .summary {
537
+ margin: 0;
538
+ padding: 14px 16px;
539
+ border: 1px solid var(--st-color-danger);
540
+ border-radius: 12px;
541
+ background: var(--st-color-danger-subtle);
542
+ color: var(--st-color-danger-text);
543
+ font-size: 14px;
544
+ line-height: 1.5;
545
+ }
546
+
547
+ .summary:focus-visible {
548
+ outline: 2px solid var(--st-cms-brand-azure);
549
+ outline-offset: 2px;
550
+ }
551
+
552
+ .summary-title {
553
+ margin: 0 0 6px;
554
+ font-weight: var(--st-font-weight-semibold);
555
+ }
556
+
557
+ .summary ul {
558
+ margin: 0;
559
+ padding-left: 20px;
560
+ }
561
+
562
+ .summary a,
563
+ .alert a {
564
+ color: inherit;
565
+ font-weight: var(--st-font-weight-semibold);
566
+ text-decoration: underline;
567
+ }
568
+
569
+ textarea.input {
570
+ min-height: 144px;
571
+ resize: vertical;
572
+ }
573
+
574
+ .input:focus-visible {
575
+ outline: 2px solid var(--st-cms-brand-azure);
576
+ outline-offset: 2px;
577
+ }
578
+
579
+ .input[aria-invalid='true'] {
580
+ border-color: var(--st-color-danger);
581
+ box-shadow: inset 0 0 0 1px var(--st-color-danger);
582
+ }
583
+
584
+ .counter {
585
+ margin: 0;
586
+ align-self: flex-end;
587
+ font-size: 12px;
588
+ color: var(--st-color-text-muted);
589
+ }
590
+
591
+ .counter.over {
592
+ color: var(--st-color-danger-text);
593
+ font-weight: var(--st-font-weight-semibold);
594
+ }
595
+
596
+ .error {
597
+ margin: 0;
598
+ font-size: 13px;
599
+ line-height: 1.4;
600
+ color: var(--st-color-danger-text);
601
+ }
602
+
603
+ .sr-only {
604
+ position: absolute;
605
+ width: 1px;
606
+ height: 1px;
607
+ margin: -1px;
608
+ padding: 0;
609
+ overflow: hidden;
610
+ clip: rect(0 0 0 0);
611
+ white-space: nowrap;
612
+ border: 0;
613
+ }
614
+
615
+ /* Off-screen, not display:none: the browser still fills it in, a person and a screen reader do not see it. */
616
+ .hp {
617
+ position: absolute;
618
+ left: -10000px;
619
+ top: auto;
620
+ width: 1px;
621
+ height: 1px;
622
+ overflow: hidden;
623
+ }
624
+
625
+ .about {
626
+ margin: 0;
627
+ }
628
+
629
+ .pill {
630
+ display: inline-flex;
631
+ align-items: center;
632
+ min-height: 32px;
633
+ padding: 4px 12px;
634
+ border-radius: 9999px;
635
+ background: var(--st-color-subtle, var(--st-cms-surface-soft));
636
+ color: var(--st-color-text-strong);
637
+ font-size: 13px;
638
+ font-weight: var(--st-font-weight-semibold);
639
+ }
640
+
641
+ .consent {
642
+ display: flex;
643
+ align-items: flex-start;
644
+ gap: 10px;
645
+ min-height: 44px;
646
+ font-size: 14px;
647
+ line-height: 1.5;
648
+ color: var(--st-color-text);
649
+ cursor: pointer;
650
+ }
651
+
652
+ .consent input {
653
+ flex: none;
654
+ width: 20px;
655
+ height: 20px;
656
+ margin: 2px 0 0;
657
+ accent-color: var(--st-cms-brand-navy);
658
+ }
659
+
660
+ .privacy {
661
+ margin: 0;
662
+ font-size: 13px;
663
+ line-height: 1.5;
664
+ color: var(--st-color-text);
665
+ }
666
+
667
+ .privacy a {
668
+ color: var(--st-color-text-strong);
669
+ font-weight: var(--st-font-weight-semibold);
670
+ text-decoration: underline;
671
+ }
672
+
673
+ .submit {
674
+ display: inline-flex;
675
+ align-items: center;
676
+ justify-content: center;
677
+ width: 100%;
678
+ min-height: 48px;
679
+ padding: 0 24px;
680
+ border: 0;
681
+ border-radius: 9999px;
682
+ background: var(--st-cms-brand-navy);
683
+ color: var(--st-cms-on-dark);
684
+ font: inherit;
685
+ font-size: 16px;
686
+ font-weight: var(--st-font-weight-semibold);
687
+ cursor: pointer;
688
+ transition: opacity 150ms ease;
689
+ }
690
+
691
+ .submit:hover:not(:disabled) {
692
+ opacity: 0.92;
693
+ }
694
+
695
+ .submit:disabled {
696
+ opacity: 0.6;
697
+ cursor: progress;
698
+ }
699
+
700
+ .submit:focus-visible {
701
+ outline: 2px solid var(--st-cms-brand-azure);
702
+ outline-offset: 2px;
703
+ }
704
+
705
+ @media (prefers-reduced-motion: reduce) {
706
+ .submit {
707
+ transition: none;
708
+ }
709
+ }
710
+
711
+ .success {
712
+ display: flex;
713
+ align-items: flex-start;
714
+ gap: 12px;
715
+ margin-bottom: 16px;
716
+ padding: 16px 18px;
717
+ border-radius: 16px;
718
+ background: var(--st-color-subtle, var(--st-cms-surface-soft));
719
+ color: var(--st-color-text-strong);
720
+ }
721
+
722
+ .success-icon {
723
+ flex: none;
724
+ display: inline-flex;
725
+ align-items: center;
726
+ justify-content: center;
727
+ width: 32px;
728
+ height: 32px;
729
+ border-radius: 9999px;
730
+ background: var(--st-cms-highlight);
731
+ color: var(--st-cms-navy);
732
+ }
733
+
734
+ .success-icon svg {
735
+ width: 18px;
736
+ height: 18px;
737
+ }
738
+
739
+ .success-text {
740
+ margin: 0;
741
+ font-size: 15px;
742
+ line-height: 1.6;
743
+ }
744
+
745
+ .reference {
746
+ font-weight: var(--st-font-weight-bold);
747
+ }
748
+
749
+ .alert {
750
+ margin: 0;
751
+ }
752
+
753
+ .alert.has-text {
754
+ margin-bottom: 16px;
755
+ padding: 12px 14px;
756
+ border-radius: 12px;
757
+ background: var(--st-color-danger-subtle);
758
+ color: var(--st-color-danger-text);
759
+ font-size: 14px;
760
+ line-height: 1.5;
761
+ }
762
+ `;
763
+ __decorateClass([
764
+ property({ type: String })
765
+ ], ContactForm.prototype, "endpoint", 2);
766
+ __decorateClass([
767
+ property({ attribute: "topics", converter: { fromAttribute: parseTopicsAttribute } })
768
+ ], ContactForm.prototype, "topics", 2);
769
+ __decorateClass([
770
+ property({ type: String, attribute: "default-topic" })
771
+ ], ContactForm.prototype, "defaultTopic", 2);
772
+ __decorateClass([
773
+ property({ attribute: "show-phone", converter: { fromAttribute: (value) => value !== "false" } })
774
+ ], ContactForm.prototype, "showPhone", 2);
775
+ __decorateClass([
776
+ property({ type: String })
777
+ ], ContactForm.prototype, "locale", 2);
778
+ __decorateClass([
779
+ property({ type: String })
780
+ ], ContactForm.prototype, "page", 2);
781
+ __decorateClass([
782
+ property({ type: String, attribute: "name-label" })
783
+ ], ContactForm.prototype, "nameLabel", 2);
784
+ __decorateClass([
785
+ property({ type: String, attribute: "email-label" })
786
+ ], ContactForm.prototype, "emailLabel", 2);
787
+ __decorateClass([
788
+ property({ type: String, attribute: "company-label" })
789
+ ], ContactForm.prototype, "companyLabel", 2);
790
+ __decorateClass([
791
+ property({ type: String, attribute: "phone-label" })
792
+ ], ContactForm.prototype, "phoneLabel", 2);
793
+ __decorateClass([
794
+ property({ type: String, attribute: "topic-label" })
795
+ ], ContactForm.prototype, "topicLabel", 2);
796
+ __decorateClass([
797
+ property({ type: String, attribute: "topic-placeholder" })
798
+ ], ContactForm.prototype, "topicPlaceholder", 2);
799
+ __decorateClass([
800
+ property({ type: String, attribute: "message-label" })
801
+ ], ContactForm.prototype, "messageLabel", 2);
802
+ __decorateClass([
803
+ property({ type: String, attribute: "name-placeholder" })
804
+ ], ContactForm.prototype, "namePlaceholder", 2);
805
+ __decorateClass([
806
+ property({ type: String, attribute: "email-placeholder" })
807
+ ], ContactForm.prototype, "emailPlaceholder", 2);
808
+ __decorateClass([
809
+ property({ type: String, attribute: "company-placeholder" })
810
+ ], ContactForm.prototype, "companyPlaceholder", 2);
811
+ __decorateClass([
812
+ property({ type: String, attribute: "message-placeholder" })
813
+ ], ContactForm.prototype, "messagePlaceholder", 2);
814
+ __decorateClass([
815
+ property({ type: String, attribute: "message-counter" })
816
+ ], ContactForm.prototype, "messageCounter", 2);
817
+ __decorateClass([
818
+ property({ type: String, attribute: "submit-label" })
819
+ ], ContactForm.prototype, "submitLabel", 2);
820
+ __decorateClass([
821
+ property({ type: String, attribute: "sending-label" })
822
+ ], ContactForm.prototype, "sendingLabel", 2);
823
+ __decorateClass([
824
+ property({ type: String, attribute: "required-label" })
825
+ ], ContactForm.prototype, "requiredLabel", 2);
826
+ __decorateClass([
827
+ property({ type: String, attribute: "about-label" })
828
+ ], ContactForm.prototype, "aboutLabel", 2);
829
+ __decorateClass([
830
+ property({ type: String, attribute: "consent-label" })
831
+ ], ContactForm.prototype, "consentLabel", 2);
832
+ __decorateClass([
833
+ property({ type: String, attribute: "privacy-note" })
834
+ ], ContactForm.prototype, "privacyNote", 2);
835
+ __decorateClass([
836
+ property({ type: String, attribute: "privacy-link-label" })
837
+ ], ContactForm.prototype, "privacyLinkLabel", 2);
838
+ __decorateClass([
839
+ property({ type: String, attribute: "privacy-href" })
840
+ ], ContactForm.prototype, "privacyHref", 2);
841
+ __decorateClass([
842
+ property({ type: String, attribute: "sent-note" })
843
+ ], ContactForm.prototype, "sentNote", 2);
844
+ __decorateClass([
845
+ property({ type: String, attribute: "reference-label" })
846
+ ], ContactForm.prototype, "referenceLabel", 2);
847
+ __decorateClass([
848
+ property({ type: String, attribute: "error-note" })
849
+ ], ContactForm.prototype, "errorNote", 2);
850
+ __decorateClass([
851
+ property({ type: String, attribute: "rate-limited-note" })
852
+ ], ContactForm.prototype, "rateLimitedNote", 2);
853
+ __decorateClass([
854
+ property({ type: String, attribute: "rate-limited-generic-note" })
855
+ ], ContactForm.prototype, "rateLimitedGenericNote", 2);
856
+ __decorateClass([
857
+ property({ type: String, attribute: "error-summary" })
858
+ ], ContactForm.prototype, "errorSummary", 2);
859
+ __decorateClass([
860
+ property({ type: String, attribute: "error-summary-one" })
861
+ ], ContactForm.prototype, "errorSummaryOne", 2);
862
+ __decorateClass([
863
+ property({ type: String, attribute: "required-note" })
864
+ ], ContactForm.prototype, "requiredNote", 2);
865
+ __decorateClass([
866
+ property({ type: String })
867
+ ], ContactForm.prototype, "mailto", 2);
868
+ __decorateClass([
869
+ property({ attribute: false })
870
+ ], ContactForm.prototype, "errorMessages", 2);
871
+ __decorateClass([
872
+ state()
873
+ ], ContactForm.prototype, "errors", 2);
874
+ __decorateClass([
875
+ state()
876
+ ], ContactForm.prototype, "alertText", 2);
877
+ __decorateClass([
878
+ state()
879
+ ], ContactForm.prototype, "alertOwn", 2);
880
+ __decorateClass([
881
+ state()
882
+ ], ContactForm.prototype, "outcome", 2);
883
+ __decorateClass([
884
+ state()
885
+ ], ContactForm.prototype, "sending", 2);
886
+ __decorateClass([
887
+ state()
888
+ ], ContactForm.prototype, "messageLength", 2);
889
+ __decorateClass([
890
+ state()
891
+ ], ContactForm.prototype, "counterAnnouncement", 2);
892
+ __decorateClass([
893
+ query(".submit")
894
+ ], ContactForm.prototype, "submitEl", 2);
895
+ ContactForm = __decorateClass([
896
+ customElement("st-contact-form")
897
+ ], ContactForm);
898
+
899
+ export {
900
+ CONTACT_FORM_SUBMIT_EVENT,
901
+ CONTACT_FORM_SENT_EVENT,
902
+ CONTACT_FORM_ERROR_EVENT,
903
+ ContactForm
904
+ };
905
+ //# sourceMappingURL=chunk-V4R7PYP5.js.map