@forjacms/sections 1.7.5 → 1.7.6

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 (82) hide show
  1. package/dist/cjs/altcha-BwmX5HQc.js +33 -0
  2. package/dist/cjs/forja-contact.cjs.entry.js +25 -2
  3. package/dist/cjs/forja-newsletter.cjs.entry.js +16 -1
  4. package/dist/cjs/forja-portfolio.cjs.entry.js +1 -1
  5. package/dist/cjs/forja-pricing.cjs.entry.js +1 -1
  6. package/dist/cjs/forja-projects.cjs.entry.js +1 -1
  7. package/dist/cjs/forja-sections.cjs.js +1 -1
  8. package/dist/cjs/forja-stats.cjs.entry.js +1 -1
  9. package/dist/cjs/forja-tag-cloud.cjs.entry.js +1 -1
  10. package/dist/cjs/forja-team.cjs.entry.js +1 -1
  11. package/dist/cjs/forja-testimonials.cjs.entry.js +1 -1
  12. package/dist/cjs/forja-text-block.cjs.entry.js +1 -1
  13. package/dist/cjs/forja-timeline.cjs.entry.js +1 -1
  14. package/dist/cjs/forja-video.cjs.entry.js +1 -1
  15. package/dist/cjs/loader.cjs.js +1 -1
  16. package/dist/collection/components/forja-contact/forja-contact.js +69 -2
  17. package/dist/collection/components/forja-newsletter/forja-newsletter.js +60 -1
  18. package/dist/collection/components/forja-portfolio/forja-portfolio.js +1 -1
  19. package/dist/collection/components/forja-pricing/forja-pricing.js +1 -1
  20. package/dist/collection/components/forja-projects/forja-projects.js +1 -1
  21. package/dist/collection/components/forja-stats/forja-stats.js +1 -1
  22. package/dist/collection/components/forja-tag-cloud/forja-tag-cloud.js +1 -1
  23. package/dist/collection/components/forja-team/forja-team.js +1 -1
  24. package/dist/collection/components/forja-testimonials/forja-testimonials.js +1 -1
  25. package/dist/collection/components/forja-text-block/forja-text-block.js +1 -1
  26. package/dist/collection/components/forja-timeline/forja-timeline.js +1 -1
  27. package/dist/collection/components/forja-video/forja-video.js +1 -1
  28. package/dist/collection/utils/altcha.js +27 -0
  29. package/dist/components/forja-contact.js +1 -1
  30. package/dist/components/forja-newsletter.js +1 -1
  31. package/dist/components/forja-portfolio.js +1 -1
  32. package/dist/components/forja-pricing.js +1 -1
  33. package/dist/components/forja-projects.js +1 -1
  34. package/dist/components/forja-stats.js +1 -1
  35. package/dist/components/forja-tag-cloud.js +1 -1
  36. package/dist/components/forja-team.js +1 -1
  37. package/dist/components/forja-testimonials.js +1 -1
  38. package/dist/components/forja-text-block.js +1 -1
  39. package/dist/components/forja-timeline.js +1 -1
  40. package/dist/components/forja-video.js +1 -1
  41. package/dist/components/p-UF_OIKbF.js +1 -0
  42. package/dist/esm/altcha-BauEO4NR.js +30 -0
  43. package/dist/esm/forja-contact.entry.js +25 -2
  44. package/dist/esm/forja-newsletter.entry.js +16 -1
  45. package/dist/esm/forja-portfolio.entry.js +1 -1
  46. package/dist/esm/forja-pricing.entry.js +1 -1
  47. package/dist/esm/forja-projects.entry.js +1 -1
  48. package/dist/esm/forja-sections.js +1 -1
  49. package/dist/esm/forja-stats.entry.js +1 -1
  50. package/dist/esm/forja-tag-cloud.entry.js +1 -1
  51. package/dist/esm/forja-team.entry.js +1 -1
  52. package/dist/esm/forja-testimonials.entry.js +1 -1
  53. package/dist/esm/forja-text-block.entry.js +1 -1
  54. package/dist/esm/forja-timeline.entry.js +1 -1
  55. package/dist/esm/forja-video.entry.js +1 -1
  56. package/dist/esm/loader.js +1 -1
  57. package/dist/forja-sections/forja-sections.esm.js +1 -1
  58. package/dist/forja-sections/{p-082156fb.entry.js → p-2374ab45.entry.js} +1 -1
  59. package/dist/forja-sections/{p-8caea1c1.entry.js → p-28d89696.entry.js} +1 -1
  60. package/dist/forja-sections/p-50efde20.entry.js +1 -0
  61. package/dist/forja-sections/{p-89b5326c.entry.js → p-52608627.entry.js} +1 -1
  62. package/dist/forja-sections/p-6160b635.entry.js +1 -0
  63. package/dist/forja-sections/p-680fe800.entry.js +1 -0
  64. package/dist/forja-sections/p-73d4139c.entry.js +1 -0
  65. package/dist/forja-sections/{p-a37a69c8.entry.js → p-7cd82cee.entry.js} +1 -1
  66. package/dist/forja-sections/p-7dff4916.entry.js +1 -0
  67. package/dist/forja-sections/p-B2hMSj1g.js +1 -0
  68. package/dist/forja-sections/{p-d763435e.entry.js → p-a4cc2ee9.entry.js} +1 -1
  69. package/dist/forja-sections/p-da58a406.entry.js +1 -0
  70. package/dist/forja-sections/p-df44677a.entry.js +1 -0
  71. package/dist/types/components/forja-contact/forja-contact.d.ts +18 -0
  72. package/dist/types/components/forja-newsletter/forja-newsletter.d.ts +8 -0
  73. package/dist/types/components.d.ts +40 -0
  74. package/dist/types/utils/altcha.d.ts +16 -0
  75. package/package.json +1 -1
  76. package/dist/forja-sections/p-37f0e324.entry.js +0 -1
  77. package/dist/forja-sections/p-450084d2.entry.js +0 -1
  78. package/dist/forja-sections/p-5d5eea44.entry.js +0 -1
  79. package/dist/forja-sections/p-8513ce7a.entry.js +0 -1
  80. package/dist/forja-sections/p-86732956.entry.js +0 -1
  81. package/dist/forja-sections/p-b37e7f5c.entry.js +0 -1
  82. package/dist/forja-sections/p-c61df346.entry.js +0 -1
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-DPGUrkdx.js');
4
+
5
+ /**
6
+ * Self-hosted ALTCHA helpers shared by the form sections (#773).
7
+ *
8
+ * The open-source `<altcha-widget>` custom element solves a server-issued
9
+ * proof-of-work challenge and injects a hidden `altcha` input carrying the
10
+ * solved payload. Forms forward that payload to the API as the submission's
11
+ * `bot_protection_token`. No Sentinel / paid features are involved; the host
12
+ * page registers the widget (e.g. `import 'altcha'`).
13
+ */
14
+ /** True once the widget has injected a non-empty solved `altcha` input. */
15
+ function altchaSolved(form) {
16
+ const input = form.querySelector('input[name="altcha"]');
17
+ return !!input && input.value.length > 0;
18
+ }
19
+ /**
20
+ * Render the ALTCHA widget bound to a per-form challenge endpoint. `testId`
21
+ * lets each section namespace its widget for e2e targeting.
22
+ */
23
+ function renderAltchaWidget(challengeUrl, testId) {
24
+ return index.h('altcha-widget', {
25
+ class: { 'forja-altcha': true },
26
+ name: 'altcha',
27
+ challengeurl: challengeUrl,
28
+ 'data-testid': testId,
29
+ });
30
+ }
31
+
32
+ exports.altchaSolved = altchaSolved;
33
+ exports.renderAltchaWidget = renderAltchaWidget;
@@ -2,23 +2,46 @@
2
2
 
3
3
  var index = require('./index-DPGUrkdx.js');
4
4
  var a11y = require('./a11y-IAJPjMwx.js');
5
+ var altcha = require('./altcha-BwmX5HQc.js');
5
6
 
6
7
  const ForjaContact = class {
7
8
  constructor(hostRef) {
8
9
  index.registerInstance(this, hostRef);
9
10
  this.forjaSubmit = index.createEvent(this, "forjaSubmit");
11
+ /**
12
+ * Bot-protection requirement for this form (#773). When `'mandatory'`, a
13
+ * self-hosted ALTCHA widget is rendered and submission is blocked until the
14
+ * visitor's browser has solved the proof-of-work. The open-source
15
+ * `<altcha-widget>` element must be registered by the host page (e.g.
16
+ * `import 'altcha'`) — no Sentinel/paid features are used.
17
+ */
18
+ this.botProtection = 'none';
19
+ /** Set when a Mandatory form is submitted before ALTCHA is solved. */
20
+ this.botProtectionUnsolved = false;
10
21
  this.handleSubmit = (e) => {
11
22
  e.preventDefault();
12
23
  const form = e.target;
24
+ // Block submission until the ALTCHA widget has injected a solved hidden
25
+ // `altcha` input. Checks the DOM directly (not FormData) so the gate is
26
+ // independent of the form-serialization step.
27
+ if (this.requiresAltcha && !altcha.altchaSolved(form)) {
28
+ this.botProtectionUnsolved = true;
29
+ return;
30
+ }
31
+ this.botProtectionUnsolved = false;
13
32
  this.forjaSubmit.emit(new FormData(form));
14
33
  };
15
34
  }
35
+ get requiresAltcha() {
36
+ return this.botProtection === 'mandatory';
37
+ }
16
38
  render() {
17
39
  const hasFields = this.fields && this.fields.length > 0;
18
- return (index.h("section", { key: '15bb71d6aa6d3d73c85ab4cdd7346696f3145074', class: "forja-contact", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Contact') }, index.h("slot", { key: '63820a89dd1c9812dc0b931fd8ce7b17a7b1782e', name: "before" }), index.h("div", { key: 'b74c9c884de525c6a08a92c982f0a1c8a2235c02', class: "forja-contact__content" }, this.sectionTitle && index.h("h2", { key: '53014e550127a34a191adcef4b8eaa3b01dfec7a', class: "forja-contact__title" }, this.sectionTitle), this.text && index.h("div", { key: '38d9ff63e255d33328da1113a3b7f2fe82871a23', class: "forja-contact__text", innerHTML: this.text }), this.buttonText && this.buttonHref && (index.h("a", { key: '15ebb06b95b3cb6d58fb3d4caaa1e713126a201a', href: this.buttonHref, class: "forja-contact__cta" }, this.buttonText))), hasFields ? (index.h("form", { class: "forja-contact__form", action: this.formAction, method: this.formAction ? 'post' : undefined, onSubmit: this.handleSubmit }, this.fields.map(field => {
40
+ return (index.h("section", { key: 'f5fa0e767bf2ed4abf6cf716b170fba8ac8fc569', class: "forja-contact", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Contact') }, index.h("slot", { key: 'ee7559a984260125a9f7bbece28a3383e5b8d383', name: "before" }), index.h("div", { key: '0ed33ac797e6f9e540d8b62a81f060b3d94f3303', class: "forja-contact__content" }, this.sectionTitle && index.h("h2", { key: '40d2850b9d1add8cd37b0238818c9bd351db2c0f', class: "forja-contact__title" }, this.sectionTitle), this.text && index.h("div", { key: '03487d7fdd10dfc55044eb320a26bc9ba69e122e', class: "forja-contact__text", innerHTML: this.text }), this.buttonText && this.buttonHref && (index.h("a", { key: '7836f8b9458ce0a90309ccca829fb5a452d2eeec', href: this.buttonHref, class: "forja-contact__cta" }, this.buttonText))), hasFields ? (index.h("form", { class: "forja-contact__form", action: this.formAction, method: this.formAction ? 'post' : undefined, onSubmit: this.handleSubmit }, this.fields.map(field => {
19
41
  const fieldId = a11y.sectionId(field.name, 'contact');
20
42
  return (index.h("div", { class: "forja-contact__field" }, index.h("label", { class: "forja-contact__label", htmlFor: fieldId }, field.label, field.required && index.h("span", { "aria-hidden": "true" }, " *")), field.type === 'textarea' ? (index.h("textarea", { id: fieldId, name: field.name, class: "forja-contact__input forja-contact__input--textarea", required: field.required, "aria-required": field.required ? 'true' : undefined, placeholder: field.placeholder })) : (index.h("input", { id: fieldId, name: field.name, type: field.type, class: "forja-contact__input", required: field.required, "aria-required": field.required ? 'true' : undefined, placeholder: field.placeholder }))));
21
- }), index.h("button", { type: "submit", class: "forja-contact__submit" }, this.buttonText || 'Send'))) : (index.h("slot", null)), index.h("slot", { key: '7ec1b5c2ee966906cbd6fa05a2c8a5a2ca13d7e2', name: "after" })));
43
+ }), this.requiresAltcha &&
44
+ altcha.renderAltchaWidget(this.altchaChallengeUrl, 'forja-contact-altcha'), this.botProtectionUnsolved && (index.h("p", { class: "forja-contact__error", role: "alert", "data-testid": "forja-contact-altcha-error" }, "Please complete the verification before submitting.")), index.h("button", { type: "submit", class: "forja-contact__submit" }, this.buttonText || 'Send'))) : (index.h("slot", null)), index.h("slot", { key: '71b4d6ede8b21c3e841a74477c1093a5e8fc33fa', name: "after" })));
22
45
  }
23
46
  };
24
47
 
@@ -2,22 +2,37 @@
2
2
 
3
3
  var index = require('./index-DPGUrkdx.js');
4
4
  var a11y = require('./a11y-IAJPjMwx.js');
5
+ var altcha = require('./altcha-BwmX5HQc.js');
5
6
 
6
7
  const ForjaNewsletter = class {
7
8
  constructor(hostRef) {
8
9
  index.registerInstance(this, hostRef);
9
10
  this.forjaSubmit = index.createEvent(this, "forjaSubmit");
10
11
  this.buttonText = 'Subscribe';
12
+ /** Bot-protection requirement (#773). When `'mandatory'`, renders a
13
+ * self-hosted ALTCHA widget and gates submission until it is solved. */
14
+ this.botProtection = 'none';
15
+ /** Set when a Mandatory form is submitted before ALTCHA is solved. */
16
+ this.botProtectionUnsolved = false;
11
17
  this.handleSubmit = (e) => {
12
18
  e.preventDefault();
13
19
  const form = e.target;
20
+ if (this.requiresAltcha && !altcha.altchaSolved(form)) {
21
+ this.botProtectionUnsolved = true;
22
+ return;
23
+ }
24
+ this.botProtectionUnsolved = false;
14
25
  this.forjaSubmit.emit(new FormData(form));
15
26
  };
16
27
  }
28
+ get requiresAltcha() {
29
+ return this.botProtection === 'mandatory';
30
+ }
17
31
  render() {
18
32
  const emailId = a11y.sectionId(this.sectionTitle, 'newsletter-email');
19
33
  const nameId = a11y.sectionId(this.sectionTitle, 'newsletter-name');
20
- return (index.h("section", { key: '2b01646d3aa10d12c9568551edc2f8836a1e6199', class: "forja-newsletter", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Newsletter') }, index.h("slot", { key: '020fd3a2e10a86f6bec4f9499e217818c534885f', name: "before" }), this.sectionTitle && index.h("h2", { key: 'e540517a30deb49e8d3b1271b8099fe2c5167f02', class: "forja-newsletter__title" }, this.sectionTitle), this.text && index.h("div", { key: 'c31f0ad333733992f426ca1b564a609603ce7f43', class: "forja-newsletter__text", innerHTML: this.text }), index.h("form", { key: '08ba3a98b082670794797a08048ab1cc683aaef4', class: "forja-newsletter__form", action: this.formAction, method: this.formAction ? 'post' : undefined, onSubmit: this.handleSubmit }, this.showName && (index.h("div", { key: '9537213f04bdd4d2e2008a783bc70a7e7a268865', class: "forja-newsletter__field" }, index.h("label", { key: '8feb551b009eb8f288cbcb54b18360c9fe09a694', class: "forja-newsletter__label", htmlFor: nameId }, "Name"), index.h("input", { key: 'b2df119a4d000e46a8e1cfb1ab2a2514be2f28a4', id: nameId, name: "name", type: "text", class: "forja-newsletter__input" }))), index.h("div", { key: '7fff741fe589ee3bc7f5eb278f07dfb78a4363c1', class: "forja-newsletter__field" }, index.h("label", { key: '2dda48f90d5303de371101b1da09e0402291a704', class: "forja-newsletter__label", htmlFor: emailId }, "Email"), index.h("input", { key: '7c913bcd86483511926cd2c6df3b2d8fae202a3b', id: emailId, name: "email", type: "email", class: "forja-newsletter__input", required: true, "aria-required": "true" })), index.h("button", { key: '374357cafdc13172944199b9537f32fa252fa274', type: "submit", class: "forja-newsletter__submit" }, this.buttonText)), index.h("slot", { key: '253f3650ec3839083c2ef1a768c78627fef141b3', name: "after" })));
34
+ return (index.h("section", { key: '0d15c9d013c2f1250999ad86d853cbb5126bbddc', class: "forja-newsletter", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Newsletter') }, index.h("slot", { key: 'aba062b799c952a6936267573bf841fb7403a350', name: "before" }), this.sectionTitle && index.h("h2", { key: 'f00db5dd8b536dca31d1f39453753e4e9126f97f', class: "forja-newsletter__title" }, this.sectionTitle), this.text && index.h("div", { key: '857102c1929b0615a5782d97ffc969d12bb3bec6', class: "forja-newsletter__text", innerHTML: this.text }), index.h("form", { key: '9ac77419043d02719d05c949e8ac6e13f411affe', class: "forja-newsletter__form", action: this.formAction, method: this.formAction ? 'post' : undefined, onSubmit: this.handleSubmit }, this.showName && (index.h("div", { key: '073625ebadd2dd040dc19e48f136adb4919d428b', class: "forja-newsletter__field" }, index.h("label", { key: '3133a36ccdf1c7f8a7204e2e83c71b16b1e4dcf2', class: "forja-newsletter__label", htmlFor: nameId }, "Name"), index.h("input", { key: 'f49b6e4e3b7f1037e6b7aaa18a6a4b10cb15d730', id: nameId, name: "name", type: "text", class: "forja-newsletter__input" }))), index.h("div", { key: '59b5408e884026f6351b1397e536fc184ac2c1de', class: "forja-newsletter__field" }, index.h("label", { key: '436373562856e04f27addcacba5083805155c913', class: "forja-newsletter__label", htmlFor: emailId }, "Email"), index.h("input", { key: '042c434c7fab15fd4235e1fe2d6b509db81d1e43', id: emailId, name: "email", type: "email", class: "forja-newsletter__input", required: true, "aria-required": "true" })), this.requiresAltcha &&
35
+ altcha.renderAltchaWidget(this.altchaChallengeUrl, 'forja-newsletter-altcha'), this.botProtectionUnsolved && (index.h("p", { key: '4375ea4a0f67a9dad1b6e1797e898c4b90125dfb', class: "forja-newsletter__error", role: "alert", "data-testid": "forja-newsletter-altcha-error" }, "Please complete the verification before submitting.")), index.h("button", { key: '7eddc2c91799598f71af799af6c46159d688195a', type: "submit", class: "forja-newsletter__submit" }, this.buttonText)), index.h("slot", { key: 'f13a320d972bbb402cb218ee6d4d2650f5f15161', name: "after" })));
21
36
  }
22
37
  };
23
38
 
@@ -30,7 +30,7 @@ const ForjaPortfolio = class {
30
30
  return (index.h("div", { class: "forja-portfolio__skills" }, index.h("h3", { class: "forja-portfolio__group-title" }, "Skills"), Object.entries(grouped).map(([category, items]) => (index.h("div", { class: "forja-portfolio__skill-group" }, Object.keys(grouped).length > 1 && (index.h("h4", { class: "forja-portfolio__skill-category" }, category)), index.h("ul", { class: "forja-portfolio__skill-list", "data-columns": this.columns }, items.map(skill => (index.h("li", { class: "forja-portfolio__skill" }, skill.name)))))))));
31
31
  }
32
32
  render() {
33
- return (index.h("section", { key: '96e2ad1a4250c58f0785ccf1dcf38c7ac5b8d53a', class: "forja-portfolio", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Portfolio') }, index.h("slot", { key: 'a4f4d1379d09a2019e5e92de5bf0f65d8a78bf62', name: "before" }), this.sectionTitle && index.h("h2", { key: '3419d7e33cda89d94ad2166c02df2b5451715ca7', class: "forja-portfolio__title" }, this.sectionTitle), this.text && index.h("div", { key: '1dc200413658bde80829bd57b166772e6e27b8be', class: "forja-portfolio__text", innerHTML: this.text }), this.renderExperiences(), this.renderEducation(), this.renderSkills(), index.h("slot", { key: '4ea0373f8e21524b516dd3f4b5a967acd3c7d7cf', name: "after" })));
33
+ return (index.h("section", { key: '506011a5c845a8cbee32a77a2081a269efa3c2d4', class: "forja-portfolio", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Portfolio') }, index.h("slot", { key: 'f4c91d111a4e49a2492a5056376b1c2245d7db1f', name: "before" }), this.sectionTitle && index.h("h2", { key: '801b3d72f636ed6e5d51f37748ad980970acc72c', class: "forja-portfolio__title" }, this.sectionTitle), this.text && index.h("div", { key: '2770e9835554376f00a46ad670cc2530651e6dfc', class: "forja-portfolio__text", innerHTML: this.text }), this.renderExperiences(), this.renderEducation(), this.renderSkills(), index.h("slot", { key: '48ded21e8a2ac6d279ea1e39d6fa6eaec32ef7aa', name: "after" })));
34
34
  }
35
35
  };
36
36
 
@@ -9,7 +9,7 @@ const ForjaPricing = class {
9
9
  }
10
10
  render() {
11
11
  const hasTiers = this.tiers && this.tiers.length > 0;
12
- return (index.h("section", { key: 'bae1df3d72dc351c1e55506fdfaad535f45814f6', class: "forja-pricing", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Pricing') }, index.h("slot", { key: '343e7d5490dfc07cc2024661d404b1c2a44c46a9', name: "before" }), (this.sectionTitle || this.text) && (index.h("div", { key: 'e91c8e1945da57bc28bbc6ee09b72dca1dd03d22', class: "forja-pricing__header" }, this.sectionTitle && index.h("h2", { key: '81000892bb72e034613283df85928c1c667a4f95', class: "forja-pricing__title" }, this.sectionTitle), this.text && index.h("div", { key: '56363c268fb40a5512ab90005463bf43402e8c2f', class: "forja-pricing__text", innerHTML: this.text }))), hasTiers ? (index.h("div", { class: "forja-pricing__tiers", role: "list", "data-columns": this.columns }, this.tiers.map(tier => (index.h("div", { class: `forja-pricing__tier${tier.highlighted ? ' forja-pricing__tier--highlighted' : ''}`, role: "listitem" }, index.h("h3", { class: "forja-pricing__tier-name" }, tier.name), index.h("div", { class: "forja-pricing__price" }, index.h("span", { class: "forja-pricing__amount" }, tier.price), tier.period && index.h("span", { class: "forja-pricing__period" }, tier.period)), tier.description && index.h("p", { class: "forja-pricing__description" }, tier.description), tier.features && tier.features.length > 0 && (index.h("ul", { class: "forja-pricing__features" }, tier.features.map(feature => (index.h("li", { class: "forja-pricing__feature" }, feature))))), tier.buttonText && tier.buttonHref && (index.h("a", { href: tier.buttonHref, class: "forja-pricing__cta" }, tier.buttonText))))))) : (index.h("div", { class: "forja-pricing__tiers", role: "list", "data-columns": this.columns }, index.h("slot", null))), index.h("slot", { key: 'd4ed110c1c8ab8a865ba7c1066caf5867c36494c', name: "after" })));
12
+ return (index.h("section", { key: 'ecb73e364f3f4892d3d937fc7fa5df7b1f1a338e', class: "forja-pricing", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Pricing') }, index.h("slot", { key: '08905beca81a6eb6afb74d161f47bc7e0f5b69c4', name: "before" }), (this.sectionTitle || this.text) && (index.h("div", { key: 'fa94236ab6731c6e2f7401075bba874ed39206b9', class: "forja-pricing__header" }, this.sectionTitle && index.h("h2", { key: '8ced20c10ac8235fd2525c6cbbc4b5689c10fe18', class: "forja-pricing__title" }, this.sectionTitle), this.text && index.h("div", { key: 'bf6f79ee461263f8e5bd9af2c2233683fe6cf110', class: "forja-pricing__text", innerHTML: this.text }))), hasTiers ? (index.h("div", { class: "forja-pricing__tiers", role: "list", "data-columns": this.columns }, this.tiers.map(tier => (index.h("div", { class: `forja-pricing__tier${tier.highlighted ? ' forja-pricing__tier--highlighted' : ''}`, role: "listitem" }, index.h("h3", { class: "forja-pricing__tier-name" }, tier.name), index.h("div", { class: "forja-pricing__price" }, index.h("span", { class: "forja-pricing__amount" }, tier.price), tier.period && index.h("span", { class: "forja-pricing__period" }, tier.period)), tier.description && index.h("p", { class: "forja-pricing__description" }, tier.description), tier.features && tier.features.length > 0 && (index.h("ul", { class: "forja-pricing__features" }, tier.features.map(feature => (index.h("li", { class: "forja-pricing__feature" }, feature))))), tier.buttonText && tier.buttonHref && (index.h("a", { href: tier.buttonHref, class: "forja-pricing__cta" }, tier.buttonText))))))) : (index.h("div", { class: "forja-pricing__tiers", role: "list", "data-columns": this.columns }, index.h("slot", null))), index.h("slot", { key: '138c32c758745fc0c225c981e15da56557659395', name: "after" })));
13
13
  }
14
14
  };
15
15
 
@@ -9,7 +9,7 @@ const ForjaProjects = class {
9
9
  }
10
10
  render() {
11
11
  const hasItems = this.items && this.items.length > 0;
12
- return (index.h("section", { key: '15db32b9f5878409c28debb36ded1047f657ce2a', class: "forja-projects", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Projects') }, index.h("slot", { key: 'f5dd2f0ca808fcfeaa11c4006dfaa88723ea4a47', name: "before" }), this.sectionTitle && index.h("h2", { key: 'fd5e121eb42bba78d4dc5b2719c1129182ebc030', class: "forja-projects__title" }, this.sectionTitle), this.text && index.h("div", { key: 'dd82836aaf6934f7420fa2cce02e9574e27b4781', class: "forja-projects__text", innerHTML: this.text }), hasItems ? (index.h("div", { class: "forja-projects__grid", role: "list", "data-columns": this.columns }, this.items.map(item => (index.h("article", { class: "forja-projects__card", role: "listitem" }, item.imageUrl && (index.h("img", { src: item.imageUrl, alt: "", class: "forja-projects__image", loading: "lazy" })), index.h("div", { class: "forja-projects__content" }, index.h("div", { class: "forja-projects__header" }, index.h("h3", { class: "forja-projects__name" }, item.href ? (index.h("a", { href: item.href, class: "forja-projects__link" }, item.title)) : (item.title)), item.status && (index.h("span", { class: "forja-projects__status" }, item.status))), item.description && (index.h("div", { class: "forja-projects__description", innerHTML: item.description })), item.tags && item.tags.length > 0 && (index.h("ul", { class: "forja-projects__tags" }, item.tags.map(tag => (index.h("li", { class: "forja-projects__tag" }, tag))))))))))) : (index.h("slot", null)), index.h("slot", { key: 'b7772bead8f5c04f3b3e857bc9da18adc29e38b7', name: "after" })));
12
+ return (index.h("section", { key: '4fddb0d0031673c60d81741111e6fff5ebbb20a6', class: "forja-projects", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Projects') }, index.h("slot", { key: '0a295eabcbfa33f584f1538b84b70cb85fd012ae', name: "before" }), this.sectionTitle && index.h("h2", { key: '3792ed7f5e6e86dc9fd36274a361bffcc1267d8e', class: "forja-projects__title" }, this.sectionTitle), this.text && index.h("div", { key: '246daa3ff95477f019d70c1d2c3c24ccade0ecb1', class: "forja-projects__text", innerHTML: this.text }), hasItems ? (index.h("div", { class: "forja-projects__grid", role: "list", "data-columns": this.columns }, this.items.map(item => (index.h("article", { class: "forja-projects__card", role: "listitem" }, item.imageUrl && (index.h("img", { src: item.imageUrl, alt: "", class: "forja-projects__image", loading: "lazy" })), index.h("div", { class: "forja-projects__content" }, index.h("div", { class: "forja-projects__header" }, index.h("h3", { class: "forja-projects__name" }, item.href ? (index.h("a", { href: item.href, class: "forja-projects__link" }, item.title)) : (item.title)), item.status && (index.h("span", { class: "forja-projects__status" }, item.status))), item.description && (index.h("div", { class: "forja-projects__description", innerHTML: item.description })), item.tags && item.tags.length > 0 && (index.h("ul", { class: "forja-projects__tags" }, item.tags.map(tag => (index.h("li", { class: "forja-projects__tag" }, tag))))))))))) : (index.h("slot", null)), index.h("slot", { key: '605aa0a889bdc8199dca6895248f3cf19d8d4c83', name: "after" })));
13
13
  }
14
14
  };
15
15
 
@@ -19,7 +19,7 @@ var patchBrowser = () => {
19
19
 
20
20
  patchBrowser().then(async (options) => {
21
21
  await appGlobals.globalScripts();
22
- return index.bootstrapLazy([["forja-blog.cjs",[[260,"forja-blog",{"sectionTitle":[1,"section-title"],"text":[1],"posts":[16],"columns":[2],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"]}]]],["forja-contact.cjs",[[260,"forja-contact",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"fields":[16],"formAction":[1,"form-action"]}]]],["forja-cta.cjs",[[260,"forja-cta",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"]}]]],["forja-divider.cjs",[[0,"forja-divider",{"dividerStyle":[1,"divider-style"],"label":[1]}]]],["forja-faq.cjs",[[260,"forja-faq",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16]}]]],["forja-features.cjs",[[260,"forja-features",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-footer.cjs",[[0,"forja-footer",{"siteName":[1,"site-name"],"homeHref":[1,"home-href"],"items":[16],"socialLinks":[16],"showRss":[4,"show-rss"],"showSitemap":[4,"show-sitemap"],"tagline":[1]}]]],["forja-gallery.cjs",[[260,"forja-gallery",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-hero.cjs",[[260,"forja-hero",{"sectionTitle":[1,"section-title"],"text":[1],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"fullWidth":[4,"full-width"],"gradient":[4]}]]],["forja-legal.cjs",[[260,"forja-legal",{"sectionTitle":[1,"section-title"],"intro":[1],"body":[1],"documentType":[1,"document-type"],"version":[2],"createdAt":[1,"created-at"],"updatedAt":[1,"updated-at"],"effectiveDate":[1,"effective-date"],"showDocumentType":[4,"show-document-type"],"showVersion":[4,"show-version"],"showDates":[4,"show-dates"],"showIntro":[4,"show-intro"]}]]],["forja-logo-cloud.cjs",[[260,"forja-logo-cloud",{"sectionTitle":[1,"section-title"],"text":[1],"logos":[16],"columns":[2],"grayscale":[4]}]]],["forja-nav.cjs",[[0,"forja-nav",{"siteName":[1,"site-name"],"homeHref":[1,"home-href"],"items":[16],"locales":[16],"currentLocale":[1,"current-locale"],"showThemeToggle":[4,"show-theme-toggle"],"mobileOpen":[32],"localeDropdownOpen":[32]}]]],["forja-newsletter.cjs",[[260,"forja-newsletter",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"formAction":[1,"form-action"],"showName":[4,"show-name"]}]]],["forja-portfolio.cjs",[[260,"forja-portfolio",{"sectionTitle":[1,"section-title"],"text":[1],"experiences":[16],"education":[16],"skills":[16],"columns":[2]}]]],["forja-pricing.cjs",[[260,"forja-pricing",{"sectionTitle":[1,"section-title"],"text":[1],"tiers":[16],"columns":[2]}]]],["forja-projects.cjs",[[260,"forja-projects",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-section-renderer.cjs",[[260,"forja-section-renderer",{"sectionType":[1,"section-type"],"sectionTitle":[1,"section-title"],"text":[1],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"items":[16],"settings":[16]}]]],["forja-stats.cjs",[[260,"forja-stats",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2],"statsStyle":[1,"stats-style"]}]]],["forja-tag-cloud.cjs",[[260,"forja-tag-cloud",{"sectionTitle":[1,"section-title"],"text":[1],"tags":[16]}]]],["forja-team.cjs",[[260,"forja-team",{"sectionTitle":[1,"section-title"],"text":[1],"members":[16],"columns":[2],"showRole":[4,"show-role"],"showBio":[4,"show-bio"]}]]],["forja-testimonials.cjs",[[260,"forja-testimonials",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-text-block.cjs",[[260,"forja-text-block",{"sectionTitle":[1,"section-title"],"text":[1],"width":[1],"alignment":[1]}]]],["forja-timeline.cjs",[[260,"forja-timeline",{"sectionTitle":[1,"section-title"],"text":[1],"events":[16],"layout":[1],"showDates":[4,"show-dates"]}]]],["forja-video.cjs",[[260,"forja-video",{"sectionTitle":[1,"section-title"],"text":[1],"videoUrl":[1,"video-url"],"provider":[1],"autoplay":[4],"aspectRatio":[1,"aspect-ratio"]}]]]], options);
22
+ return index.bootstrapLazy([["forja-blog.cjs",[[260,"forja-blog",{"sectionTitle":[1,"section-title"],"text":[1],"posts":[16],"columns":[2],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"]}]]],["forja-contact.cjs",[[260,"forja-contact",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"fields":[16],"formAction":[1,"form-action"],"botProtection":[1,"bot-protection"],"altchaChallengeUrl":[1,"altcha-challenge-url"],"botProtectionUnsolved":[32]}]]],["forja-cta.cjs",[[260,"forja-cta",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"]}]]],["forja-divider.cjs",[[0,"forja-divider",{"dividerStyle":[1,"divider-style"],"label":[1]}]]],["forja-faq.cjs",[[260,"forja-faq",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16]}]]],["forja-features.cjs",[[260,"forja-features",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-footer.cjs",[[0,"forja-footer",{"siteName":[1,"site-name"],"homeHref":[1,"home-href"],"items":[16],"socialLinks":[16],"showRss":[4,"show-rss"],"showSitemap":[4,"show-sitemap"],"tagline":[1]}]]],["forja-gallery.cjs",[[260,"forja-gallery",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-hero.cjs",[[260,"forja-hero",{"sectionTitle":[1,"section-title"],"text":[1],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"fullWidth":[4,"full-width"],"gradient":[4]}]]],["forja-legal.cjs",[[260,"forja-legal",{"sectionTitle":[1,"section-title"],"intro":[1],"body":[1],"documentType":[1,"document-type"],"version":[2],"createdAt":[1,"created-at"],"updatedAt":[1,"updated-at"],"effectiveDate":[1,"effective-date"],"showDocumentType":[4,"show-document-type"],"showVersion":[4,"show-version"],"showDates":[4,"show-dates"],"showIntro":[4,"show-intro"]}]]],["forja-logo-cloud.cjs",[[260,"forja-logo-cloud",{"sectionTitle":[1,"section-title"],"text":[1],"logos":[16],"columns":[2],"grayscale":[4]}]]],["forja-nav.cjs",[[0,"forja-nav",{"siteName":[1,"site-name"],"homeHref":[1,"home-href"],"items":[16],"locales":[16],"currentLocale":[1,"current-locale"],"showThemeToggle":[4,"show-theme-toggle"],"mobileOpen":[32],"localeDropdownOpen":[32]}]]],["forja-newsletter.cjs",[[260,"forja-newsletter",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"formAction":[1,"form-action"],"showName":[4,"show-name"],"botProtection":[1,"bot-protection"],"altchaChallengeUrl":[1,"altcha-challenge-url"],"botProtectionUnsolved":[32]}]]],["forja-portfolio.cjs",[[260,"forja-portfolio",{"sectionTitle":[1,"section-title"],"text":[1],"experiences":[16],"education":[16],"skills":[16],"columns":[2]}]]],["forja-pricing.cjs",[[260,"forja-pricing",{"sectionTitle":[1,"section-title"],"text":[1],"tiers":[16],"columns":[2]}]]],["forja-projects.cjs",[[260,"forja-projects",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-section-renderer.cjs",[[260,"forja-section-renderer",{"sectionType":[1,"section-type"],"sectionTitle":[1,"section-title"],"text":[1],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"items":[16],"settings":[16]}]]],["forja-stats.cjs",[[260,"forja-stats",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2],"statsStyle":[1,"stats-style"]}]]],["forja-tag-cloud.cjs",[[260,"forja-tag-cloud",{"sectionTitle":[1,"section-title"],"text":[1],"tags":[16]}]]],["forja-team.cjs",[[260,"forja-team",{"sectionTitle":[1,"section-title"],"text":[1],"members":[16],"columns":[2],"showRole":[4,"show-role"],"showBio":[4,"show-bio"]}]]],["forja-testimonials.cjs",[[260,"forja-testimonials",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-text-block.cjs",[[260,"forja-text-block",{"sectionTitle":[1,"section-title"],"text":[1],"width":[1],"alignment":[1]}]]],["forja-timeline.cjs",[[260,"forja-timeline",{"sectionTitle":[1,"section-title"],"text":[1],"events":[16],"layout":[1],"showDates":[4,"show-dates"]}]]],["forja-video.cjs",[[260,"forja-video",{"sectionTitle":[1,"section-title"],"text":[1],"videoUrl":[1,"video-url"],"provider":[1],"autoplay":[4],"aspectRatio":[1,"aspect-ratio"]}]]]], options);
23
23
  });
24
24
 
25
25
  exports.setNonce = index.setNonce;
@@ -13,7 +13,7 @@ const ForjaStats = class {
13
13
  'forja-stats',
14
14
  this.statsStyle && `forja-stats--${this.statsStyle}`,
15
15
  ].filter(Boolean).join(' ');
16
- return (index.h("section", { key: '3aa6f2f843bb0e295dcb84740af6c9fda39d8309', class: classes, "aria-label": a11y.sectionLabel(this.sectionTitle, 'Statistics') }, index.h("slot", { key: '9565f67c2e7192f8b965be5555eb7f43e271692c', name: "before" }), this.sectionTitle && index.h("h2", { key: 'cbf15bf5bc0e62702590a1725a6e188bea96639c', class: "forja-stats__title" }, this.sectionTitle), this.text && index.h("div", { key: '0beb283e6387a04c20a2ba853266b12769ac9725', class: "forja-stats__text", innerHTML: this.text }), hasItems ? (index.h("dl", { class: "forja-stats__list", "data-columns": this.columns }, this.items.map(item => (index.h("div", { class: "forja-stats__item" }, index.h("dd", { class: "forja-stats__value" }, item.value), index.h("dt", { class: "forja-stats__label" }, item.label)))))) : (index.h("slot", null)), index.h("slot", { key: '7a2ffd297dd37c72d0c16a42b268e8a6f607ad40', name: "after" })));
16
+ return (index.h("section", { key: 'cf1a9139a3b18e099e66f5abcfdcf7f5c90cdf74', class: classes, "aria-label": a11y.sectionLabel(this.sectionTitle, 'Statistics') }, index.h("slot", { key: 'fc61e06e592f1cc1d1f36d47b2b8fd33b520f421', name: "before" }), this.sectionTitle && index.h("h2", { key: '42026c0e7b55f0f7b185d969ca1219b1c44f7632', class: "forja-stats__title" }, this.sectionTitle), this.text && index.h("div", { key: 'd6f9d119958786dbef4aa39e6bae82a22465e21a', class: "forja-stats__text", innerHTML: this.text }), hasItems ? (index.h("dl", { class: "forja-stats__list", "data-columns": this.columns }, this.items.map(item => (index.h("div", { class: "forja-stats__item" }, index.h("dd", { class: "forja-stats__value" }, item.value), index.h("dt", { class: "forja-stats__label" }, item.label)))))) : (index.h("slot", null)), index.h("slot", { key: '468c62818cee963c316c57891964bac3d4f793a6', name: "after" })));
17
17
  }
18
18
  };
19
19
 
@@ -9,7 +9,7 @@ const ForjaTagCloud = class {
9
9
  }
10
10
  render() {
11
11
  const hasTags = this.tags && this.tags.length > 0;
12
- return (index.h("section", { key: 'dc9015d823c69a88c8252115948517887e7ce400', class: "forja-tag-cloud", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Tags') }, index.h("slot", { key: '4a860c211a75f97d67755a1811db76c20840740f', name: "before" }), this.sectionTitle && index.h("h2", { key: 'bfae3b68ba76c7ce14d01d52ee47a5b5b6f04f89', class: "forja-tag-cloud__title" }, this.sectionTitle), this.text && index.h("div", { key: '7175c987bfadf8e4bb433e2cb8b856412818c0d0', class: "forja-tag-cloud__text", innerHTML: this.text }), hasTags ? (index.h("nav", { class: "forja-tag-cloud__nav", "aria-label": "Tags" }, index.h("ul", { class: "forja-tag-cloud__list", role: "list" }, this.tags.map(tag => (index.h("li", { class: "forja-tag-cloud__item" }, tag.href ? (index.h("a", { href: tag.href, class: "forja-tag-cloud__tag" }, index.h("span", { class: "forja-tag-cloud__label" }, tag.label), tag.count != null && (index.h("span", { class: "forja-tag-cloud__count", "aria-label": `${tag.count} items` }, "(", tag.count, ")")))) : (index.h("span", { class: "forja-tag-cloud__tag" }, index.h("span", { class: "forja-tag-cloud__label" }, tag.label), tag.count != null && (index.h("span", { class: "forja-tag-cloud__count", "aria-label": `${tag.count} items` }, "(", tag.count, ")")))))))))) : (index.h("slot", null)), index.h("slot", { key: '673878f83e689016cf1a001e87774fe66c4c7baa', name: "after" })));
12
+ return (index.h("section", { key: 'eb6d00e49fa790e23e2397f4927e20d545222217', class: "forja-tag-cloud", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Tags') }, index.h("slot", { key: '8a34fd949d2f96dd8fd92d6479a052373fc09d00', name: "before" }), this.sectionTitle && index.h("h2", { key: '90fd03b82e40b74a16c91ba8c86100e9868239bb', class: "forja-tag-cloud__title" }, this.sectionTitle), this.text && index.h("div", { key: '7cf8c4c19943defa0e23f852ab27372307fa45b8', class: "forja-tag-cloud__text", innerHTML: this.text }), hasTags ? (index.h("nav", { class: "forja-tag-cloud__nav", "aria-label": "Tags" }, index.h("ul", { class: "forja-tag-cloud__list", role: "list" }, this.tags.map(tag => (index.h("li", { class: "forja-tag-cloud__item" }, tag.href ? (index.h("a", { href: tag.href, class: "forja-tag-cloud__tag" }, index.h("span", { class: "forja-tag-cloud__label" }, tag.label), tag.count != null && (index.h("span", { class: "forja-tag-cloud__count", "aria-label": `${tag.count} items` }, "(", tag.count, ")")))) : (index.h("span", { class: "forja-tag-cloud__tag" }, index.h("span", { class: "forja-tag-cloud__label" }, tag.label), tag.count != null && (index.h("span", { class: "forja-tag-cloud__count", "aria-label": `${tag.count} items` }, "(", tag.count, ")")))))))))) : (index.h("slot", null)), index.h("slot", { key: '9d24cb03b6ea67f87f11dd97410ae25ae389276b', name: "after" })));
13
13
  }
14
14
  };
15
15
 
@@ -11,7 +11,7 @@ const ForjaTeam = class {
11
11
  }
12
12
  render() {
13
13
  const hasMembers = this.members && this.members.length > 0;
14
- return (index.h("section", { key: 'b5d2dcb808386048367cfa97b31c6075732ba828', class: "forja-team", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Team') }, index.h("slot", { key: 'df3d484b90a7d755eda0a784f21edbd921e71401', name: "before" }), this.sectionTitle && index.h("h2", { key: '2818b057df2f2c6319af8d17a43537714a62db34', class: "forja-team__title" }, this.sectionTitle), this.text && index.h("div", { key: '265903df6beaae84ff4d6cc1a9d11ae3f51f15d5', class: "forja-team__text", innerHTML: this.text }), hasMembers ? (index.h("ul", { class: "forja-team__grid", role: "list", "data-columns": this.columns }, this.members.map(member => (index.h("li", { class: "forja-team__member" }, member.imageUrl && (index.h("figure", { class: "forja-team__photo" }, index.h("img", { src: member.imageUrl, alt: member.name, class: "forja-team__image", loading: "lazy" }))), index.h("h3", { class: "forja-team__name" }, member.name), this.showRole && member.role && index.h("p", { class: "forja-team__role" }, member.role), this.showBio && member.bio && index.h("p", { class: "forja-team__bio" }, member.bio)))))) : (index.h("slot", null)), index.h("slot", { key: '81263f35ba229207c4978b65890c527590dfdae5', name: "after" })));
14
+ return (index.h("section", { key: '65ab08dab0a410e178ce2b0a010987533b575bcd', class: "forja-team", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Team') }, index.h("slot", { key: 'daa75a84eb8bf43d21057b9f3620f96407d65007', name: "before" }), this.sectionTitle && index.h("h2", { key: '682f5ee8cf15e378cdb6b33cc80e078886ca29ce', class: "forja-team__title" }, this.sectionTitle), this.text && index.h("div", { key: '4ce99703de2127a6637bd7e86c3bc0944c6b5960', class: "forja-team__text", innerHTML: this.text }), hasMembers ? (index.h("ul", { class: "forja-team__grid", role: "list", "data-columns": this.columns }, this.members.map(member => (index.h("li", { class: "forja-team__member" }, member.imageUrl && (index.h("figure", { class: "forja-team__photo" }, index.h("img", { src: member.imageUrl, alt: member.name, class: "forja-team__image", loading: "lazy" }))), index.h("h3", { class: "forja-team__name" }, member.name), this.showRole && member.role && index.h("p", { class: "forja-team__role" }, member.role), this.showBio && member.bio && index.h("p", { class: "forja-team__bio" }, member.bio)))))) : (index.h("slot", null)), index.h("slot", { key: '97fff600c6ed995066a34008edee4a73a9c954d2', name: "after" })));
15
15
  }
16
16
  };
17
17
 
@@ -9,7 +9,7 @@ const ForjaTestimonials = class {
9
9
  }
10
10
  render() {
11
11
  const hasItems = this.items && this.items.length > 0;
12
- return (index.h("section", { key: '608ac151afb59df61bf99ea38f5eba2d819ef6ac', class: "forja-testimonials", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Testimonials') }, index.h("slot", { key: '016f3b316cec3979efaee8dd4e19497a623ca292', name: "before" }), this.sectionTitle && index.h("h2", { key: '5d0f9dac43cbd4e6d7ded6236c98a4d428d3723a', class: "forja-testimonials__title" }, this.sectionTitle), this.text && index.h("div", { key: '8d5bd0fd2c9b39aba0a461bef14df16a4b8197ba', class: "forja-testimonials__text", innerHTML: this.text }), hasItems ? (index.h("div", { class: "forja-testimonials__list", role: "list", "data-columns": this.columns }, this.items.map(item => (index.h("blockquote", { class: "forja-testimonials__item", role: "listitem" }, index.h("p", { class: "forja-testimonials__quote" }, item.quote), index.h("footer", { class: "forja-testimonials__attribution" }, item.avatarUrl && (index.h("img", { src: item.avatarUrl, alt: "", class: "forja-testimonials__avatar", loading: "lazy" })), index.h("cite", { class: "forja-testimonials__author" }, index.h("span", { class: "forja-testimonials__name" }, item.author), item.role && index.h("span", { class: "forja-testimonials__role" }, item.role)))))))) : (index.h("div", { class: "forja-testimonials__list", role: "list", "data-columns": this.columns }, index.h("slot", null))), index.h("slot", { key: 'f5079a207668e548632b607f174e630a46854cc8', name: "after" })));
12
+ return (index.h("section", { key: '348a3aea6d842d43dcbb8506111d2146347ecf65', class: "forja-testimonials", "aria-label": a11y.sectionLabel(this.sectionTitle, 'Testimonials') }, index.h("slot", { key: '4d372a82bb34fc2408cb168f349550f5213c1152', name: "before" }), this.sectionTitle && index.h("h2", { key: '52323f5e292192065b3ab8a54efb76bc2cb9247f', class: "forja-testimonials__title" }, this.sectionTitle), this.text && index.h("div", { key: 'f285a90d384919c0a6221b02ef2bdddf584c8636', class: "forja-testimonials__text", innerHTML: this.text }), hasItems ? (index.h("div", { class: "forja-testimonials__list", role: "list", "data-columns": this.columns }, this.items.map(item => (index.h("blockquote", { class: "forja-testimonials__item", role: "listitem" }, index.h("p", { class: "forja-testimonials__quote" }, item.quote), index.h("footer", { class: "forja-testimonials__attribution" }, item.avatarUrl && (index.h("img", { src: item.avatarUrl, alt: "", class: "forja-testimonials__avatar", loading: "lazy" })), index.h("cite", { class: "forja-testimonials__author" }, index.h("span", { class: "forja-testimonials__name" }, item.author), item.role && index.h("span", { class: "forja-testimonials__role" }, item.role)))))))) : (index.h("div", { class: "forja-testimonials__list", role: "list", "data-columns": this.columns }, index.h("slot", null))), index.h("slot", { key: '5c88e789b532b1039e2b0c74ec0afc4fb63185fb', name: "after" })));
13
13
  }
14
14
  };
15
15
 
@@ -15,7 +15,7 @@ const ForjaTextBlock = class {
15
15
  `forja-text--${this.width}`,
16
16
  `forja-text--${this.alignment}`,
17
17
  ].join(' ');
18
- return (index.h("section", { key: '2cc7f40271cc449ec8b4fc88576398a0b0763aca', class: classes, "aria-label": a11y.sectionLabel(this.sectionTitle, 'Content') }, index.h("slot", { key: '7da4597bc3dde56e4ae4179ae871f08f332c1c7f', name: "before" }), this.sectionTitle && index.h("h2", { key: 'ba03ee398659bf8926d6c434012b553e430a9413', class: "forja-text__title" }, this.sectionTitle), this.text ? (index.h("div", { class: "forja-text__content", innerHTML: this.text })) : (index.h("div", { class: "forja-text__content" }, index.h("slot", null))), index.h("slot", { key: '138eeef4fa534fd22772da123bbd6b7b30c20078', name: "after" })));
18
+ return (index.h("section", { key: '797f9ac88c3c03e2c41e7b8b3bf54b4d43dc3fd9', class: classes, "aria-label": a11y.sectionLabel(this.sectionTitle, 'Content') }, index.h("slot", { key: 'dc6cc88ac6fde0dc315651f0d7372c3fb44527fc', name: "before" }), this.sectionTitle && index.h("h2", { key: 'c3e5c0b9bbd3037a9c54db36027928b67a14318f', class: "forja-text__title" }, this.sectionTitle), this.text ? (index.h("div", { class: "forja-text__content", innerHTML: this.text })) : (index.h("div", { class: "forja-text__content" }, index.h("slot", null))), index.h("slot", { key: '8fe560073c81469ef6669ff945df4d102699152c', name: "after" })));
19
19
  }
20
20
  };
21
21
 
@@ -12,7 +12,7 @@ const ForjaTimeline = class {
12
12
  render() {
13
13
  const hasEvents = this.events && this.events.length > 0;
14
14
  const classes = ['forja-timeline', `forja-timeline--${this.layout}`].join(' ');
15
- return (index.h("section", { key: 'cebf45a5dea290fa21d427394db4916b4224df54', class: classes, "aria-label": a11y.sectionLabel(this.sectionTitle, 'Timeline') }, index.h("slot", { key: 'cf344c1df40eb02608a4255ec4b176f9efcd0ada', name: "before" }), this.sectionTitle && index.h("h2", { key: 'fab8e6c374c2e57fa345d092fc9453b0e4fc16ec', class: "forja-timeline__title" }, this.sectionTitle), this.text && index.h("div", { key: '0282811543111b55001d8b4fbe7e02cb7d944a7e', class: "forja-timeline__text", innerHTML: this.text }), hasEvents ? (index.h("ol", { class: "forja-timeline__list" }, this.events.map(event => (index.h("li", { class: "forja-timeline__item" }, this.showDates && event.date && (index.h("time", { class: "forja-timeline__date" }, event.date)), index.h("h3", { class: "forja-timeline__event-title" }, event.title), event.text && index.h("div", { class: "forja-timeline__event-text", innerHTML: event.text })))))) : (index.h("slot", null)), index.h("slot", { key: 'b56de78fa2dee0850de2ef5c0ca48243f8cf6e2c', name: "after" })));
15
+ return (index.h("section", { key: '2dce62c902a967d64dd5b6a611a177335db92965', class: classes, "aria-label": a11y.sectionLabel(this.sectionTitle, 'Timeline') }, index.h("slot", { key: 'a68408fe55ac0b4ff1717d90abf94df9744395e8', name: "before" }), this.sectionTitle && index.h("h2", { key: '59f55ce9bc8783f510050851f19d124e1e10c869', class: "forja-timeline__title" }, this.sectionTitle), this.text && index.h("div", { key: '16c053110be832993154c4e88b9f29370d3b66e0', class: "forja-timeline__text", innerHTML: this.text }), hasEvents ? (index.h("ol", { class: "forja-timeline__list" }, this.events.map(event => (index.h("li", { class: "forja-timeline__item" }, this.showDates && event.date && (index.h("time", { class: "forja-timeline__date" }, event.date)), index.h("h3", { class: "forja-timeline__event-title" }, event.title), event.text && index.h("div", { class: "forja-timeline__event-text", innerHTML: event.text })))))) : (index.h("slot", null)), index.h("slot", { key: '112addeae24306716d65f4500fb6a2dbafb8a977', name: "after" })));
16
16
  }
17
17
  };
18
18
 
@@ -23,7 +23,7 @@ const ForjaVideo = class {
23
23
  }
24
24
  render() {
25
25
  const classes = ['forja-video', this.getAspectClass()].join(' ');
26
- return (index.h("section", { key: '8f7dd28af86bfa7a3a1418bef19e6f9658d49cc6', class: classes, "aria-label": a11y.sectionLabel(this.sectionTitle, 'Video') }, index.h("slot", { key: '7b34145bcee01a80095725a5adba5266dc1af703', name: "before" }), this.sectionTitle && index.h("h2", { key: '4959dd55b6c5e146482c14057ebeffd39c45bedd', class: "forja-video__title" }, this.sectionTitle), this.text && index.h("div", { key: '42af3c36bad0c44ae1194f17217e969d46a01e8d', class: "forja-video__text", innerHTML: this.text }), this.videoUrl && (index.h("figure", { key: 'da0c9136b339b00f4f699deb077daff0bcc48715', class: "forja-video__container" }, this.isSelfHosted() ? (index.h("video", { class: "forja-video__player", src: this.videoUrl, controls: true, autoplay: this.autoplay }, index.h("track", { kind: "captions" }))) : (index.h("iframe", { class: "forja-video__embed", src: this.autoplay ? `${this.videoUrl}?autoplay=1` : this.videoUrl, title: this.sectionTitle || 'Embedded video', allowFullScreen: true, loading: "lazy" })))), index.h("slot", { key: '9c6b4f1345c7470b773c265a9884b799218a6d5f', name: "after" })));
26
+ return (index.h("section", { key: '3243f9bd00cd257d706cf6ca3ee463fc2f1de542', class: classes, "aria-label": a11y.sectionLabel(this.sectionTitle, 'Video') }, index.h("slot", { key: 'a95a30fcd2ce9e696a614b3e5614c32f23bb887c', name: "before" }), this.sectionTitle && index.h("h2", { key: 'd43d21c2d9e78ac33670d6c7073180d813c2d868', class: "forja-video__title" }, this.sectionTitle), this.text && index.h("div", { key: '98a11b54335f07c79f8ed7a0576378d223f91bfb', class: "forja-video__text", innerHTML: this.text }), this.videoUrl && (index.h("figure", { key: 'b6e4b9436e7c4f0040b00d8173ac2cf417acd575', class: "forja-video__container" }, this.isSelfHosted() ? (index.h("video", { class: "forja-video__player", src: this.videoUrl, controls: true, autoplay: this.autoplay }, index.h("track", { kind: "captions" }))) : (index.h("iframe", { class: "forja-video__embed", src: this.autoplay ? `${this.videoUrl}?autoplay=1` : this.videoUrl, title: this.sectionTitle || 'Embedded video', allowFullScreen: true, loading: "lazy" })))), index.h("slot", { key: '788a8b32e8e0e524cf681995cd25f3b4ed565371', name: "after" })));
27
27
  }
28
28
  };
29
29
 
@@ -6,7 +6,7 @@ var appGlobals = require('./app-globals-V2Kpy_OQ.js');
6
6
  const defineCustomElements = async (win, options) => {
7
7
  if (typeof window === 'undefined') return undefined;
8
8
  await appGlobals.globalScripts();
9
- return index.bootstrapLazy([["forja-blog.cjs",[[260,"forja-blog",{"sectionTitle":[1,"section-title"],"text":[1],"posts":[16],"columns":[2],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"]}]]],["forja-contact.cjs",[[260,"forja-contact",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"fields":[16],"formAction":[1,"form-action"]}]]],["forja-cta.cjs",[[260,"forja-cta",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"]}]]],["forja-divider.cjs",[[0,"forja-divider",{"dividerStyle":[1,"divider-style"],"label":[1]}]]],["forja-faq.cjs",[[260,"forja-faq",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16]}]]],["forja-features.cjs",[[260,"forja-features",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-footer.cjs",[[0,"forja-footer",{"siteName":[1,"site-name"],"homeHref":[1,"home-href"],"items":[16],"socialLinks":[16],"showRss":[4,"show-rss"],"showSitemap":[4,"show-sitemap"],"tagline":[1]}]]],["forja-gallery.cjs",[[260,"forja-gallery",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-hero.cjs",[[260,"forja-hero",{"sectionTitle":[1,"section-title"],"text":[1],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"fullWidth":[4,"full-width"],"gradient":[4]}]]],["forja-legal.cjs",[[260,"forja-legal",{"sectionTitle":[1,"section-title"],"intro":[1],"body":[1],"documentType":[1,"document-type"],"version":[2],"createdAt":[1,"created-at"],"updatedAt":[1,"updated-at"],"effectiveDate":[1,"effective-date"],"showDocumentType":[4,"show-document-type"],"showVersion":[4,"show-version"],"showDates":[4,"show-dates"],"showIntro":[4,"show-intro"]}]]],["forja-logo-cloud.cjs",[[260,"forja-logo-cloud",{"sectionTitle":[1,"section-title"],"text":[1],"logos":[16],"columns":[2],"grayscale":[4]}]]],["forja-nav.cjs",[[0,"forja-nav",{"siteName":[1,"site-name"],"homeHref":[1,"home-href"],"items":[16],"locales":[16],"currentLocale":[1,"current-locale"],"showThemeToggle":[4,"show-theme-toggle"],"mobileOpen":[32],"localeDropdownOpen":[32]}]]],["forja-newsletter.cjs",[[260,"forja-newsletter",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"formAction":[1,"form-action"],"showName":[4,"show-name"]}]]],["forja-portfolio.cjs",[[260,"forja-portfolio",{"sectionTitle":[1,"section-title"],"text":[1],"experiences":[16],"education":[16],"skills":[16],"columns":[2]}]]],["forja-pricing.cjs",[[260,"forja-pricing",{"sectionTitle":[1,"section-title"],"text":[1],"tiers":[16],"columns":[2]}]]],["forja-projects.cjs",[[260,"forja-projects",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-section-renderer.cjs",[[260,"forja-section-renderer",{"sectionType":[1,"section-type"],"sectionTitle":[1,"section-title"],"text":[1],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"items":[16],"settings":[16]}]]],["forja-stats.cjs",[[260,"forja-stats",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2],"statsStyle":[1,"stats-style"]}]]],["forja-tag-cloud.cjs",[[260,"forja-tag-cloud",{"sectionTitle":[1,"section-title"],"text":[1],"tags":[16]}]]],["forja-team.cjs",[[260,"forja-team",{"sectionTitle":[1,"section-title"],"text":[1],"members":[16],"columns":[2],"showRole":[4,"show-role"],"showBio":[4,"show-bio"]}]]],["forja-testimonials.cjs",[[260,"forja-testimonials",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-text-block.cjs",[[260,"forja-text-block",{"sectionTitle":[1,"section-title"],"text":[1],"width":[1],"alignment":[1]}]]],["forja-timeline.cjs",[[260,"forja-timeline",{"sectionTitle":[1,"section-title"],"text":[1],"events":[16],"layout":[1],"showDates":[4,"show-dates"]}]]],["forja-video.cjs",[[260,"forja-video",{"sectionTitle":[1,"section-title"],"text":[1],"videoUrl":[1,"video-url"],"provider":[1],"autoplay":[4],"aspectRatio":[1,"aspect-ratio"]}]]]], options);
9
+ return index.bootstrapLazy([["forja-blog.cjs",[[260,"forja-blog",{"sectionTitle":[1,"section-title"],"text":[1],"posts":[16],"columns":[2],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"]}]]],["forja-contact.cjs",[[260,"forja-contact",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"fields":[16],"formAction":[1,"form-action"],"botProtection":[1,"bot-protection"],"altchaChallengeUrl":[1,"altcha-challenge-url"],"botProtectionUnsolved":[32]}]]],["forja-cta.cjs",[[260,"forja-cta",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"]}]]],["forja-divider.cjs",[[0,"forja-divider",{"dividerStyle":[1,"divider-style"],"label":[1]}]]],["forja-faq.cjs",[[260,"forja-faq",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16]}]]],["forja-features.cjs",[[260,"forja-features",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-footer.cjs",[[0,"forja-footer",{"siteName":[1,"site-name"],"homeHref":[1,"home-href"],"items":[16],"socialLinks":[16],"showRss":[4,"show-rss"],"showSitemap":[4,"show-sitemap"],"tagline":[1]}]]],["forja-gallery.cjs",[[260,"forja-gallery",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-hero.cjs",[[260,"forja-hero",{"sectionTitle":[1,"section-title"],"text":[1],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"fullWidth":[4,"full-width"],"gradient":[4]}]]],["forja-legal.cjs",[[260,"forja-legal",{"sectionTitle":[1,"section-title"],"intro":[1],"body":[1],"documentType":[1,"document-type"],"version":[2],"createdAt":[1,"created-at"],"updatedAt":[1,"updated-at"],"effectiveDate":[1,"effective-date"],"showDocumentType":[4,"show-document-type"],"showVersion":[4,"show-version"],"showDates":[4,"show-dates"],"showIntro":[4,"show-intro"]}]]],["forja-logo-cloud.cjs",[[260,"forja-logo-cloud",{"sectionTitle":[1,"section-title"],"text":[1],"logos":[16],"columns":[2],"grayscale":[4]}]]],["forja-nav.cjs",[[0,"forja-nav",{"siteName":[1,"site-name"],"homeHref":[1,"home-href"],"items":[16],"locales":[16],"currentLocale":[1,"current-locale"],"showThemeToggle":[4,"show-theme-toggle"],"mobileOpen":[32],"localeDropdownOpen":[32]}]]],["forja-newsletter.cjs",[[260,"forja-newsletter",{"sectionTitle":[1,"section-title"],"text":[1],"buttonText":[1,"button-text"],"formAction":[1,"form-action"],"showName":[4,"show-name"],"botProtection":[1,"bot-protection"],"altchaChallengeUrl":[1,"altcha-challenge-url"],"botProtectionUnsolved":[32]}]]],["forja-portfolio.cjs",[[260,"forja-portfolio",{"sectionTitle":[1,"section-title"],"text":[1],"experiences":[16],"education":[16],"skills":[16],"columns":[2]}]]],["forja-pricing.cjs",[[260,"forja-pricing",{"sectionTitle":[1,"section-title"],"text":[1],"tiers":[16],"columns":[2]}]]],["forja-projects.cjs",[[260,"forja-projects",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-section-renderer.cjs",[[260,"forja-section-renderer",{"sectionType":[1,"section-type"],"sectionTitle":[1,"section-title"],"text":[1],"imageUrl":[1,"image-url"],"imageAlt":[1,"image-alt"],"buttonText":[1,"button-text"],"buttonHref":[1,"button-href"],"items":[16],"settings":[16]}]]],["forja-stats.cjs",[[260,"forja-stats",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2],"statsStyle":[1,"stats-style"]}]]],["forja-tag-cloud.cjs",[[260,"forja-tag-cloud",{"sectionTitle":[1,"section-title"],"text":[1],"tags":[16]}]]],["forja-team.cjs",[[260,"forja-team",{"sectionTitle":[1,"section-title"],"text":[1],"members":[16],"columns":[2],"showRole":[4,"show-role"],"showBio":[4,"show-bio"]}]]],["forja-testimonials.cjs",[[260,"forja-testimonials",{"sectionTitle":[1,"section-title"],"text":[1],"items":[16],"columns":[2]}]]],["forja-text-block.cjs",[[260,"forja-text-block",{"sectionTitle":[1,"section-title"],"text":[1],"width":[1],"alignment":[1]}]]],["forja-timeline.cjs",[[260,"forja-timeline",{"sectionTitle":[1,"section-title"],"text":[1],"events":[16],"layout":[1],"showDates":[4,"show-dates"]}]]],["forja-video.cjs",[[260,"forja-video",{"sectionTitle":[1,"section-title"],"text":[1],"videoUrl":[1,"video-url"],"provider":[1],"autoplay":[4],"aspectRatio":[1,"aspect-ratio"]}]]]], options);
10
10
  };
11
11
 
12
12
  exports.setNonce = index.setNonce;
@@ -1,19 +1,42 @@
1
1
  import { h } from "@stencil/core";
2
2
  import { sectionLabel, sectionId } from "../../utils/a11y";
3
+ import { altchaSolved, renderAltchaWidget } from "../../utils/altcha";
3
4
  export class ForjaContact {
4
5
  constructor() {
6
+ /**
7
+ * Bot-protection requirement for this form (#773). When `'mandatory'`, a
8
+ * self-hosted ALTCHA widget is rendered and submission is blocked until the
9
+ * visitor's browser has solved the proof-of-work. The open-source
10
+ * `<altcha-widget>` element must be registered by the host page (e.g.
11
+ * `import 'altcha'`) — no Sentinel/paid features are used.
12
+ */
13
+ this.botProtection = 'none';
14
+ /** Set when a Mandatory form is submitted before ALTCHA is solved. */
15
+ this.botProtectionUnsolved = false;
5
16
  this.handleSubmit = (e) => {
6
17
  e.preventDefault();
7
18
  const form = e.target;
19
+ // Block submission until the ALTCHA widget has injected a solved hidden
20
+ // `altcha` input. Checks the DOM directly (not FormData) so the gate is
21
+ // independent of the form-serialization step.
22
+ if (this.requiresAltcha && !altchaSolved(form)) {
23
+ this.botProtectionUnsolved = true;
24
+ return;
25
+ }
26
+ this.botProtectionUnsolved = false;
8
27
  this.forjaSubmit.emit(new FormData(form));
9
28
  };
10
29
  }
30
+ get requiresAltcha() {
31
+ return this.botProtection === 'mandatory';
32
+ }
11
33
  render() {
12
34
  const hasFields = this.fields && this.fields.length > 0;
13
- return (h("section", { key: '15bb71d6aa6d3d73c85ab4cdd7346696f3145074', class: "forja-contact", "aria-label": sectionLabel(this.sectionTitle, 'Contact') }, h("slot", { key: '63820a89dd1c9812dc0b931fd8ce7b17a7b1782e', name: "before" }), h("div", { key: 'b74c9c884de525c6a08a92c982f0a1c8a2235c02', class: "forja-contact__content" }, this.sectionTitle && h("h2", { key: '53014e550127a34a191adcef4b8eaa3b01dfec7a', class: "forja-contact__title" }, this.sectionTitle), this.text && h("div", { key: '38d9ff63e255d33328da1113a3b7f2fe82871a23', class: "forja-contact__text", innerHTML: this.text }), this.buttonText && this.buttonHref && (h("a", { key: '15ebb06b95b3cb6d58fb3d4caaa1e713126a201a', href: this.buttonHref, class: "forja-contact__cta" }, this.buttonText))), hasFields ? (h("form", { class: "forja-contact__form", action: this.formAction, method: this.formAction ? 'post' : undefined, onSubmit: this.handleSubmit }, this.fields.map(field => {
35
+ return (h("section", { key: 'f5fa0e767bf2ed4abf6cf716b170fba8ac8fc569', class: "forja-contact", "aria-label": sectionLabel(this.sectionTitle, 'Contact') }, h("slot", { key: 'ee7559a984260125a9f7bbece28a3383e5b8d383', name: "before" }), h("div", { key: '0ed33ac797e6f9e540d8b62a81f060b3d94f3303', class: "forja-contact__content" }, this.sectionTitle && h("h2", { key: '40d2850b9d1add8cd37b0238818c9bd351db2c0f', class: "forja-contact__title" }, this.sectionTitle), this.text && h("div", { key: '03487d7fdd10dfc55044eb320a26bc9ba69e122e', class: "forja-contact__text", innerHTML: this.text }), this.buttonText && this.buttonHref && (h("a", { key: '7836f8b9458ce0a90309ccca829fb5a452d2eeec', href: this.buttonHref, class: "forja-contact__cta" }, this.buttonText))), hasFields ? (h("form", { class: "forja-contact__form", action: this.formAction, method: this.formAction ? 'post' : undefined, onSubmit: this.handleSubmit }, this.fields.map(field => {
14
36
  const fieldId = sectionId(field.name, 'contact');
15
37
  return (h("div", { class: "forja-contact__field" }, h("label", { class: "forja-contact__label", htmlFor: fieldId }, field.label, field.required && h("span", { "aria-hidden": "true" }, " *")), field.type === 'textarea' ? (h("textarea", { id: fieldId, name: field.name, class: "forja-contact__input forja-contact__input--textarea", required: field.required, "aria-required": field.required ? 'true' : undefined, placeholder: field.placeholder })) : (h("input", { id: fieldId, name: field.name, type: field.type, class: "forja-contact__input", required: field.required, "aria-required": field.required ? 'true' : undefined, placeholder: field.placeholder }))));
16
- }), h("button", { type: "submit", class: "forja-contact__submit" }, this.buttonText || 'Send'))) : (h("slot", null)), h("slot", { key: '7ec1b5c2ee966906cbd6fa05a2c8a5a2ca13d7e2', name: "after" })));
38
+ }), this.requiresAltcha &&
39
+ renderAltchaWidget(this.altchaChallengeUrl, 'forja-contact-altcha'), this.botProtectionUnsolved && (h("p", { class: "forja-contact__error", role: "alert", "data-testid": "forja-contact-altcha-error" }, "Please complete the verification before submitting.")), h("button", { type: "submit", class: "forja-contact__submit" }, this.buttonText || 'Send'))) : (h("slot", null)), h("slot", { key: '71b4d6ede8b21c3e841a74477c1093a5e8fc33fa', name: "after" })));
17
40
  }
18
41
  static get is() { return "forja-contact"; }
19
42
  static get properties() {
@@ -136,9 +159,53 @@ export class ForjaContact {
136
159
  "setter": false,
137
160
  "reflect": false,
138
161
  "attribute": "form-action"
162
+ },
163
+ "botProtection": {
164
+ "type": "string",
165
+ "mutable": false,
166
+ "complexType": {
167
+ "original": "'none' | 'mandatory'",
168
+ "resolved": "\"mandatory\" | \"none\"",
169
+ "references": {}
170
+ },
171
+ "required": false,
172
+ "optional": false,
173
+ "docs": {
174
+ "tags": [],
175
+ "text": "Bot-protection requirement for this form (#773). When `'mandatory'`, a\nself-hosted ALTCHA widget is rendered and submission is blocked until the\nvisitor's browser has solved the proof-of-work. The open-source\n`<altcha-widget>` element must be registered by the host page (e.g.\n`import 'altcha'`) \u2014 no Sentinel/paid features are used."
176
+ },
177
+ "getter": false,
178
+ "setter": false,
179
+ "reflect": false,
180
+ "attribute": "bot-protection",
181
+ "defaultValue": "'none'"
182
+ },
183
+ "altchaChallengeUrl": {
184
+ "type": "string",
185
+ "mutable": false,
186
+ "complexType": {
187
+ "original": "string",
188
+ "resolved": "string | undefined",
189
+ "references": {}
190
+ },
191
+ "required": false,
192
+ "optional": true,
193
+ "docs": {
194
+ "tags": [],
195
+ "text": "Endpoint the ALTCHA widget fetches a fresh challenge from \u2014 typically the\nSDK's `/public/forms/{slug}/altcha-challenge`. The widget injects the\nsolved payload into the form as a hidden `altcha` field, which is emitted\nwith the submission for the consumer to forward as `botProtectionToken`."
196
+ },
197
+ "getter": false,
198
+ "setter": false,
199
+ "reflect": false,
200
+ "attribute": "altcha-challenge-url"
139
201
  }
140
202
  };
141
203
  }
204
+ static get states() {
205
+ return {
206
+ "botProtectionUnsolved": {}
207
+ };
208
+ }
142
209
  static get events() {
143
210
  return [{
144
211
  "method": "forjaSubmit",
@@ -1,18 +1,33 @@
1
1
  import { h } from "@stencil/core";
2
2
  import { sectionLabel, sectionId } from "../../utils/a11y";
3
+ import { altchaSolved, renderAltchaWidget } from "../../utils/altcha";
3
4
  export class ForjaNewsletter {
4
5
  constructor() {
5
6
  this.buttonText = 'Subscribe';
7
+ /** Bot-protection requirement (#773). When `'mandatory'`, renders a
8
+ * self-hosted ALTCHA widget and gates submission until it is solved. */
9
+ this.botProtection = 'none';
10
+ /** Set when a Mandatory form is submitted before ALTCHA is solved. */
11
+ this.botProtectionUnsolved = false;
6
12
  this.handleSubmit = (e) => {
7
13
  e.preventDefault();
8
14
  const form = e.target;
15
+ if (this.requiresAltcha && !altchaSolved(form)) {
16
+ this.botProtectionUnsolved = true;
17
+ return;
18
+ }
19
+ this.botProtectionUnsolved = false;
9
20
  this.forjaSubmit.emit(new FormData(form));
10
21
  };
11
22
  }
23
+ get requiresAltcha() {
24
+ return this.botProtection === 'mandatory';
25
+ }
12
26
  render() {
13
27
  const emailId = sectionId(this.sectionTitle, 'newsletter-email');
14
28
  const nameId = sectionId(this.sectionTitle, 'newsletter-name');
15
- return (h("section", { key: '2b01646d3aa10d12c9568551edc2f8836a1e6199', class: "forja-newsletter", "aria-label": sectionLabel(this.sectionTitle, 'Newsletter') }, h("slot", { key: '020fd3a2e10a86f6bec4f9499e217818c534885f', name: "before" }), this.sectionTitle && h("h2", { key: 'e540517a30deb49e8d3b1271b8099fe2c5167f02', class: "forja-newsletter__title" }, this.sectionTitle), this.text && h("div", { key: 'c31f0ad333733992f426ca1b564a609603ce7f43', class: "forja-newsletter__text", innerHTML: this.text }), h("form", { key: '08ba3a98b082670794797a08048ab1cc683aaef4', class: "forja-newsletter__form", action: this.formAction, method: this.formAction ? 'post' : undefined, onSubmit: this.handleSubmit }, this.showName && (h("div", { key: '9537213f04bdd4d2e2008a783bc70a7e7a268865', class: "forja-newsletter__field" }, h("label", { key: '8feb551b009eb8f288cbcb54b18360c9fe09a694', class: "forja-newsletter__label", htmlFor: nameId }, "Name"), h("input", { key: 'b2df119a4d000e46a8e1cfb1ab2a2514be2f28a4', id: nameId, name: "name", type: "text", class: "forja-newsletter__input" }))), h("div", { key: '7fff741fe589ee3bc7f5eb278f07dfb78a4363c1', class: "forja-newsletter__field" }, h("label", { key: '2dda48f90d5303de371101b1da09e0402291a704', class: "forja-newsletter__label", htmlFor: emailId }, "Email"), h("input", { key: '7c913bcd86483511926cd2c6df3b2d8fae202a3b', id: emailId, name: "email", type: "email", class: "forja-newsletter__input", required: true, "aria-required": "true" })), h("button", { key: '374357cafdc13172944199b9537f32fa252fa274', type: "submit", class: "forja-newsletter__submit" }, this.buttonText)), h("slot", { key: '253f3650ec3839083c2ef1a768c78627fef141b3', name: "after" })));
29
+ return (h("section", { key: '0d15c9d013c2f1250999ad86d853cbb5126bbddc', class: "forja-newsletter", "aria-label": sectionLabel(this.sectionTitle, 'Newsletter') }, h("slot", { key: 'aba062b799c952a6936267573bf841fb7403a350', name: "before" }), this.sectionTitle && h("h2", { key: 'f00db5dd8b536dca31d1f39453753e4e9126f97f', class: "forja-newsletter__title" }, this.sectionTitle), this.text && h("div", { key: '857102c1929b0615a5782d97ffc969d12bb3bec6', class: "forja-newsletter__text", innerHTML: this.text }), h("form", { key: '9ac77419043d02719d05c949e8ac6e13f411affe', class: "forja-newsletter__form", action: this.formAction, method: this.formAction ? 'post' : undefined, onSubmit: this.handleSubmit }, this.showName && (h("div", { key: '073625ebadd2dd040dc19e48f136adb4919d428b', class: "forja-newsletter__field" }, h("label", { key: '3133a36ccdf1c7f8a7204e2e83c71b16b1e4dcf2', class: "forja-newsletter__label", htmlFor: nameId }, "Name"), h("input", { key: 'f49b6e4e3b7f1037e6b7aaa18a6a4b10cb15d730', id: nameId, name: "name", type: "text", class: "forja-newsletter__input" }))), h("div", { key: '59b5408e884026f6351b1397e536fc184ac2c1de', class: "forja-newsletter__field" }, h("label", { key: '436373562856e04f27addcacba5083805155c913', class: "forja-newsletter__label", htmlFor: emailId }, "Email"), h("input", { key: '042c434c7fab15fd4235e1fe2d6b509db81d1e43', id: emailId, name: "email", type: "email", class: "forja-newsletter__input", required: true, "aria-required": "true" })), this.requiresAltcha &&
30
+ renderAltchaWidget(this.altchaChallengeUrl, 'forja-newsletter-altcha'), this.botProtectionUnsolved && (h("p", { key: '4375ea4a0f67a9dad1b6e1797e898c4b90125dfb', class: "forja-newsletter__error", role: "alert", "data-testid": "forja-newsletter-altcha-error" }, "Please complete the verification before submitting.")), h("button", { key: '7eddc2c91799598f71af799af6c46159d688195a', type: "submit", class: "forja-newsletter__submit" }, this.buttonText)), h("slot", { key: 'f13a320d972bbb402cb218ee6d4d2650f5f15161', name: "after" })));
16
31
  }
17
32
  static get is() { return "forja-newsletter"; }
18
33
  static get properties() {
@@ -112,9 +127,53 @@ export class ForjaNewsletter {
112
127
  "setter": false,
113
128
  "reflect": false,
114
129
  "attribute": "show-name"
130
+ },
131
+ "botProtection": {
132
+ "type": "string",
133
+ "mutable": false,
134
+ "complexType": {
135
+ "original": "'none' | 'mandatory'",
136
+ "resolved": "\"mandatory\" | \"none\"",
137
+ "references": {}
138
+ },
139
+ "required": false,
140
+ "optional": false,
141
+ "docs": {
142
+ "tags": [],
143
+ "text": "Bot-protection requirement (#773). When `'mandatory'`, renders a\nself-hosted ALTCHA widget and gates submission until it is solved."
144
+ },
145
+ "getter": false,
146
+ "setter": false,
147
+ "reflect": false,
148
+ "attribute": "bot-protection",
149
+ "defaultValue": "'none'"
150
+ },
151
+ "altchaChallengeUrl": {
152
+ "type": "string",
153
+ "mutable": false,
154
+ "complexType": {
155
+ "original": "string",
156
+ "resolved": "string | undefined",
157
+ "references": {}
158
+ },
159
+ "required": false,
160
+ "optional": true,
161
+ "docs": {
162
+ "tags": [],
163
+ "text": "Challenge endpoint the ALTCHA widget fetches from (#770)."
164
+ },
165
+ "getter": false,
166
+ "setter": false,
167
+ "reflect": false,
168
+ "attribute": "altcha-challenge-url"
115
169
  }
116
170
  };
117
171
  }
172
+ static get states() {
173
+ return {
174
+ "botProtectionUnsolved": {}
175
+ };
176
+ }
118
177
  static get events() {
119
178
  return [{
120
179
  "method": "forjaSubmit",
@@ -24,7 +24,7 @@ export class ForjaPortfolio {
24
24
  return (h("div", { class: "forja-portfolio__skills" }, h("h3", { class: "forja-portfolio__group-title" }, "Skills"), Object.entries(grouped).map(([category, items]) => (h("div", { class: "forja-portfolio__skill-group" }, Object.keys(grouped).length > 1 && (h("h4", { class: "forja-portfolio__skill-category" }, category)), h("ul", { class: "forja-portfolio__skill-list", "data-columns": this.columns }, items.map(skill => (h("li", { class: "forja-portfolio__skill" }, skill.name)))))))));
25
25
  }
26
26
  render() {
27
- return (h("section", { key: '96e2ad1a4250c58f0785ccf1dcf38c7ac5b8d53a', class: "forja-portfolio", "aria-label": sectionLabel(this.sectionTitle, 'Portfolio') }, h("slot", { key: 'a4f4d1379d09a2019e5e92de5bf0f65d8a78bf62', name: "before" }), this.sectionTitle && h("h2", { key: '3419d7e33cda89d94ad2166c02df2b5451715ca7', class: "forja-portfolio__title" }, this.sectionTitle), this.text && h("div", { key: '1dc200413658bde80829bd57b166772e6e27b8be', class: "forja-portfolio__text", innerHTML: this.text }), this.renderExperiences(), this.renderEducation(), this.renderSkills(), h("slot", { key: '4ea0373f8e21524b516dd3f4b5a967acd3c7d7cf', name: "after" })));
27
+ return (h("section", { key: '506011a5c845a8cbee32a77a2081a269efa3c2d4', class: "forja-portfolio", "aria-label": sectionLabel(this.sectionTitle, 'Portfolio') }, h("slot", { key: 'f4c91d111a4e49a2492a5056376b1c2245d7db1f', name: "before" }), this.sectionTitle && h("h2", { key: '801b3d72f636ed6e5d51f37748ad980970acc72c', class: "forja-portfolio__title" }, this.sectionTitle), this.text && h("div", { key: '2770e9835554376f00a46ad670cc2530651e6dfc', class: "forja-portfolio__text", innerHTML: this.text }), this.renderExperiences(), this.renderEducation(), this.renderSkills(), h("slot", { key: '48ded21e8a2ac6d279ea1e39d6fa6eaec32ef7aa', name: "after" })));
28
28
  }
29
29
  static get is() { return "forja-portfolio"; }
30
30
  static get properties() {