@vectoriox/iox-ui 5.29.0 → 5.30.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.
@@ -3742,9 +3742,13 @@ var FormPresetId;
3742
3742
  FormPresetId["Application"] = "application";
3743
3743
  FormPresetId["Booking"] = "booking";
3744
3744
  })(FormPresetId || (FormPresetId = {}));
3745
- const FORM_PRESETS = Object.freeze([
3745
+ // forms-core is imported by both renderers (the field runtime), and a renderer that never reads the presets
3746
+
3747
+ // to it by form-presets.spec) — a read of `FormPresetId.X` counts as a side effect to a bundler and kept the
3748
+ // whole list in the engine's bundle.
3749
+ const FORM_PRESETS = /* @__PURE__ */ Object.freeze([
3746
3750
  {
3747
- id: FormPresetId.Contact, name: 'Contact', icon: 'ph-thin ph-envelope-simple',
3751
+ id: 'contact', name: 'Contact', icon: 'ph-thin ph-envelope-simple',
3748
3752
  description: 'Name, email and a message. Stored, and emailed to you.',
3749
3753
  formName: 'Contact form',
3750
3754
  fields: [
@@ -3757,7 +3761,7 @@ const FORM_PRESETS = Object.freeze([
3757
3761
  errorText: 'We couldn’t send your message. Please try again — your answers are still here.',
3758
3762
  },
3759
3763
  {
3760
- id: FormPresetId.Newsletter, name: 'Newsletter', icon: 'ph-thin ph-paper-plane-tilt',
3764
+ id: 'newsletter', name: 'Newsletter', icon: 'ph-thin ph-paper-plane-tilt',
3761
3765
  description: 'One email field plus consent. Stored.',
3762
3766
  formName: 'Newsletter signup',
3763
3767
  fields: [
@@ -3771,7 +3775,7 @@ const FORM_PRESETS = Object.freeze([
3771
3775
  errorText: 'We couldn’t sign you up. Please try again.',
3772
3776
  },
3773
3777
  {
3774
- id: FormPresetId.Application, name: 'Application', icon: 'ph-thin ph-read-cv-logo',
3778
+ id: 'application', name: 'Application', icon: 'ph-thin ph-read-cv-logo',
3775
3779
  description: 'Details plus a CV upload. Stored, with an auto-reply.',
3776
3780
  formName: 'Application',
3777
3781
  fields: [
@@ -3787,7 +3791,7 @@ const FORM_PRESETS = Object.freeze([
3787
3791
  errorText: 'We couldn’t submit your application. Please try again.',
3788
3792
  },
3789
3793
  {
3790
- id: FormPresetId.Booking, name: 'Booking request', icon: 'ph-thin ph-calendar-check',
3794
+ id: 'booking', name: 'Booking request', icon: 'ph-thin ph-calendar-check',
3791
3795
  description: 'Date and party size. Stored, and it notifies you.',
3792
3796
  formName: 'Booking request',
3793
3797
  fields: [
@@ -3807,6 +3811,79 @@ function formPresetById(id) {
3807
3811
  return FORM_PRESETS.find(p => p.id === id);
3808
3812
  }
3809
3813
 
3814
+ // Where form content may NOT render (Doron, 2026-10-20): inside a link or a button.
3815
+ //
3816
+ // HTML forbids interactive content inside `<a>` and `<button>`, and a click in a field may follow the
3817
+ // link. ONE table and ONE walk, shared by the builder's insert rule (refuse it), the builder's audit
3818
+ // (find it in a page saved before the rule) and the engine (warn about it, never rewrite it).
3819
+ var InteractiveTag;
3820
+ (function (InteractiveTag) {
3821
+ InteractiveTag["Anchor"] = "a";
3822
+ InteractiveTag["Button"] = "button";
3823
+ })(InteractiveTag || (InteractiveTag = {}));
3824
+ /**
3825
+ * Every node type that renders as an interactive element, and the element(s) it can render. A ButtonBlock
3826
+ * renders `<a>` or `<button>` by its `tag` trait — both interactive, so switching the tag never lifts the
3827
+ * rule. Pinned to the engine components' selectors by `interactive-hosts.spec.ts`.
3828
+ */
3829
+ const INTERACTIVE_HOST_TAGS = Object.freeze({
3830
+ LinkedContainer: [InteractiveTag.Anchor],
3831
+ Link: [InteractiveTag.Anchor],
3832
+ Button: [InteractiveTag.Anchor],
3833
+ ButtonBlock: [InteractiveTag.Anchor, InteractiveTag.Button],
3834
+ SubmitButton: [InteractiveTag.Button],
3835
+ });
3836
+ const FIELD_GROUP_NODE_TYPE = 'FieldGroup';
3837
+ const SUBMIT_BUTTON_NODE_TYPE = 'SubmitButton';
3838
+ /**
3839
+ * Form content — what a link or a button must never hold: a Form (its controls), a Field (an input, select
3840
+ * or textarea), a SubmitButton (a `<button>`) and a FieldGroup (it exists only to hold fields, so it moves as
3841
+ * one). A Success / Error block is text and lives only inside its form, so it is not on the list.
3842
+ */
3843
+ const FORM_CONTENT_TYPES = new Set([
3844
+ FORM_NODE_TYPE, FIELD_NODE_TYPE, FIELD_GROUP_NODE_TYPE, SUBMIT_BUTTON_NODE_TYPE,
3845
+ ]);
3846
+ function isInteractiveHost(node) {
3847
+ return !!node?.type && Object.prototype.hasOwnProperty.call(INTERACTIVE_HOST_TAGS, node.type);
3848
+ }
3849
+ function isFormContent(node) {
3850
+ return !!node?.type && FORM_CONTENT_TYPES.has(node.type);
3851
+ }
3852
+ /**
3853
+ * The first form-content node in `node`'s subtree that sits inside an interactive host, or null. `insideHost`
3854
+ * is true when `node` is placed under a host already — so a Form dropped into a link and a link that holds a
3855
+ * Form are the same finding.
3856
+ */
3857
+ function formContentInHost(node, insideHost = false) {
3858
+ if (!node)
3859
+ return null;
3860
+ if (insideHost && isFormContent(node))
3861
+ return node;
3862
+ const nowInside = insideHost || isInteractiveHost(node);
3863
+ for (const child of node.children ?? []) {
3864
+ const found = formContentInHost(child, nowInside);
3865
+ if (found)
3866
+ return found;
3867
+ }
3868
+ return null;
3869
+ }
3870
+ /** Every form-content subtree a tree holds inside an interactive host, in document order. */
3871
+ function findFormContentInHosts(roots) {
3872
+ const out = [];
3873
+ const visit = (node, host) => {
3874
+ if (host && isFormContent(node)) {
3875
+ out.push({ host, content: node });
3876
+ return;
3877
+ }
3878
+ const nextHost = host ?? (isInteractiveHost(node) ? node : null);
3879
+ for (const child of (node.children ?? []))
3880
+ visit(child, nextHost);
3881
+ };
3882
+ for (const root of roots ?? [])
3883
+ visit(root, null);
3884
+ return out;
3885
+ }
3886
+
3810
3887
  /*
3811
3888
  * @vectoriox/iox-ui/forms-core — the shared, FRAMEWORK-FREE core of the forms feature.
3812
3889
  *
@@ -4972,6 +5049,9 @@ class IoxComponentRegistryService {
4972
5049
  hasComponent(type) {
4973
5050
  return this.map.has(type);
4974
5051
  }
5052
+ registeredTypes() {
5053
+ return [...this.map.keys()];
5054
+ }
4975
5055
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxComponentRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4976
5056
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxComponentRegistryService, providedIn: 'root' }); }
4977
5057
  }