@vectoriox/iox-builder 2.9.0 → 2.10.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.
@@ -17,7 +17,7 @@ import { SelectModule } from 'primeng/select';
17
17
  import { TooltipModule } from 'primeng/tooltip';
18
18
  import { DialogModule } from 'primeng/dialog';
19
19
  import * as i16 from '@vectoriox/iox-ui';
20
- import { DEFAULT_WIDTH_BY_TYPE, ComponentInstanceRegistryService, compileDeclarations, composeVirtualTraits, IS_PREVIEW, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, IoxPageModule } from '@vectoriox/iox-ui';
20
+ import { DEFAULT_WIDTH_BY_TYPE, ComponentInstanceRegistryService, buildTargetedStateSelector, compileDeclarations, composeVirtualTraits, IS_PREVIEW, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, IoxPageModule } from '@vectoriox/iox-ui';
21
21
  export { ComponentInstanceRegistryService, VIRTUAL_TRAIT_KEYS, composeVirtualTraits } from '@vectoriox/iox-ui';
22
22
  import Lenis from 'lenis';
23
23
  import { Subject, BehaviorSubject, of, forkJoin } from 'rxjs';
@@ -113,7 +113,22 @@ const RELATIONAL_STATES = ['parent-hover'];
113
113
  const RELATIONAL_STATE_BASE = {
114
114
  'parent-hover': 'hover',
115
115
  };
116
- const SUPPORTED_STATES = [...INTERACTION_STATES, ...STRUCTURAL_STATES, ...RELATIONAL_STATES];
116
+ /**
117
+ * Targeted relational pseudo-classes — the styled element restyles when an ARBITRARY
118
+ * chosen element (the `trigger`, not the DOM parent) matches a pseudo-class. Compiled to
119
+ * `.iox-node-{scopeId}:has(.iox-node-{triggerId}:{base}) .iox-node-{id} { … }`, where
120
+ * `scopeId` is the NEAREST COMMON ANCESTOR of the styled node and the trigger. Scoping the
121
+ * `:has()` to that ancestor keeps the rule repetition-safe (each cloned subtree matches
122
+ * independently) with a single shared CSS rule.
123
+ *
124
+ * The trigger node id per state is stored on `ComponentNode.stateTriggers`.
125
+ * `TARGETED_STATE_BASE` maps each targeted state to the trigger's pseudo-class.
126
+ */
127
+ const TARGETED_STATES = ['trigger-hover'];
128
+ const TARGETED_STATE_BASE = {
129
+ 'trigger-hover': 'hover',
130
+ };
131
+ const SUPPORTED_STATES = [...INTERACTION_STATES, ...STRUCTURAL_STATES, ...RELATIONAL_STATES, ...TARGETED_STATES];
117
132
  /**
118
133
  * Build a full StyleTraitGroup[] schema populated with values from a flat
119
134
  * styleProps map. Used when editing a preset in the Style panel — the panel
@@ -2605,15 +2620,35 @@ class StyleRegistryService {
2605
2620
  * @param state Optional pseudo-class state ('hover' | 'active' | 'focus' | …).
2606
2621
  * When provided, compiles to `.iox-node-{id}:{state} { … }`.
2607
2622
  * State rules are NOT partitioned into inner/outer.
2608
- * @param relativeToId Ancestor css id, required for RELATIONAL states
2609
- * (e.g. 'parent-hover'). Compiles to
2610
- * `.iox-node-{relativeToId}:{base} .iox-node-{nodeId} { … }`.
2623
+ * @param relativeToId For RELATIONAL states (e.g. 'parent-hover') this is the ancestor
2624
+ * css id; compiles to `.iox-node-{relativeToId}:{base} .iox-node-{nodeId} { … }`.
2625
+ * For TARGETED states (e.g. 'trigger-hover') this is the SCOPE css id
2626
+ * (nearest common ancestor of the styled node + trigger).
2627
+ * @param triggerId For TARGETED states only: the css id of the trigger node whose
2628
+ * pseudo-class drives the state. Compiles a `:has()`-scoped selector.
2611
2629
  */
2612
- upsert(nodeId, styles, state, relativeToId) {
2630
+ upsert(nodeId, styles, state, relativeToId, triggerId) {
2613
2631
  if (!nodeId)
2614
2632
  return;
2615
2633
  if (state) {
2616
2634
  const key = `${nodeId}:${state}`;
2635
+ // Targeted states (trigger-hover): the styled node restyles when an ARBITRARY chosen
2636
+ // element is hovered. The selector is `:has()`-scoped to `relativeToId` (the nearest
2637
+ // common ancestor of styled + trigger) so it stays repetition-safe with one shared rule.
2638
+ if (TARGETED_STATES.includes(state)) {
2639
+ const base = TARGETED_STATE_BASE[state];
2640
+ const css = (relativeToId && triggerId && base)
2641
+ ? this.compile(buildTargetedStateSelector(relativeToId, triggerId, nodeId, base), styles)
2642
+ : '';
2643
+ if (css) {
2644
+ this.rules.set(key, css);
2645
+ }
2646
+ else {
2647
+ this.rules.delete(key);
2648
+ }
2649
+ this.flush();
2650
+ return;
2651
+ }
2617
2652
  // Relational states (parent-hover): the pseudo-class lives on an ANCESTOR
2618
2653
  // and cascades to this element. Requires the ancestor's css id.
2619
2654
  if (RELATIONAL_STATES.includes(state)) {