@vectoriox/iox-builder 11.5.0 → 11.6.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 { TooltipModule } from 'primeng/tooltip';
17
17
  import * as i20 from 'primeng/dialog';
18
18
  import { DialogModule } from 'primeng/dialog';
19
19
  import * as i1$1 from '@vectoriox/iox-ui';
20
- import { nodeCssId, needsGroupName, resolveBoundValue, VALIDATION_STATES as VALIDATION_STATES$1, VALIDATION_STATE_CLASS as VALIDATION_STATE_CLASS$1, DEFAULT_WIDTH_BY_TYPE, TEXT_DIRECTION_KEY, TEXT_ALIGN_KEY, TextAlign, COLOR_SCHEME_TRAIT, COLOR_SCHEMES, ColorScheme, LinkType, MAX_LINES_KEY, A11yTrait, BREAKPOINTS, Breakpoint, withSchemeInk, stripSuppressedProps, DeclarationContext, buildPartSelector, planResponsiveRules, resolveStyleProps, targetedStateSelector, stateSelectorSuffix, compileTokenCssBlocks, catalogFontId, fontsForTokens, GOOGLE_FONTS_FILE_ORIGIN, googleFontHref, compileDeclarations, isLastEmittedStateKey, wrapInBreakpointQuery, BreakpointQueryKind, NEW_NODE_STYLE_DEFAULTS, defaultElementStyleFor, applyElementStyle, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, ContextStore, ENTRANCE_ACTION_TYPES, EXIT_ACTION_TYPES, ComponentInstanceRegistryService, entranceStartsHidden, isActionEnabled, isContextAction, contextActionEffect, resolveContextValue, effectiveActionType, INTERACTION_HIDDEN_ATTRIBUTE, motionAllowed, finalKeyframe, entranceDelay, repeatedRowIndex, keyframeStyleEntries, buildInteractionKeyframes, declaredInputNames, emptyImagePlaceholder, syncNodeDesignClasses, nodeTraitValue, syncNodeA11yAttributes, nodeA11yAttributes, safeSetInput, colorSchemeOf, composeVirtualTraits, withDefaultHoverTransition, stateNamesIn, partClassName, switchElementStyle, releaseElementStyle, countOverrides, setOverride, breakpointDef, breakpointForWidth, FormRenderState, needsAccessibleName, resolveInputs, setInputOverride, barReserveClass, collectContextSlotKeys, withContextSlots, compilePageStyle, nodeUsesContext, IS_PREVIEW, buttonBlockHref, bootSlider, IoxPageModule, PALETTE_PRESETS, elementStyleById, PART_CLASS_NAMES } from '@vectoriox/iox-ui';
20
+ import { nodeCssId, needsGroupName, resolveBoundValue, VALIDATION_STATES as VALIDATION_STATES$1, VALIDATION_STATE_CLASS as VALIDATION_STATE_CLASS$1, DEFAULT_WIDTH_BY_TYPE, TEXT_DIRECTION_KEY, TEXT_ALIGN_KEY, TextAlign, COLOR_SCHEME_TRAIT, COLOR_SCHEMES, ColorScheme, LinkType, MAX_LINES_KEY, A11yTrait, BREAKPOINTS, Breakpoint, withSchemeInk, stripSuppressedProps, DeclarationContext, buildPartSelector, planResponsiveRules, resolveStyleProps, targetedStateSelector, stateSelectorSuffix, compileTokenCssBlocks, catalogFontId, fontsForTokens, GOOGLE_FONTS_FILE_ORIGIN, googleFontHref, compileDeclarations, isLastEmittedStateKey, wrapInBreakpointQuery, BreakpointQueryKind, NEW_NODE_STYLE_DEFAULTS, defaultElementStyleFor, applyElementStyle, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, ContextStore, ENTRANCE_ACTION_TYPES, EXIT_ACTION_TYPES, ComponentInstanceRegistryService, entranceStartsHidden, isActionEnabled, isContextAction, contextActionEffect, resolveContextValue, effectiveActionType, INTERACTION_HIDDEN_ATTRIBUTE, motionAllowed, finalKeyframe, entranceDelay, repeatedRowIndex, keyframeStyleEntries, buildInteractionKeyframes, cascadeChain, declaredInputNames, emptyImagePlaceholder, syncNodeDesignClasses, nodeTraitValue, syncNodeA11yAttributes, nodeA11yAttributes, safeSetInput, colorSchemeOf, composeVirtualTraits, withDefaultHoverTransition, stateNamesIn, partClassName, switchElementStyle, releaseElementStyle, countOverrides, setOverride, breakpointDef, breakpointForWidth, FormRenderState, needsAccessibleName, resolveInputs, setInputOverride, barReserveClass, collectContextSlotKeys, withContextSlots, compilePageStyle, nodeUsesContext, IS_PREVIEW, buttonBlockHref, bootSlider, IoxPageModule, PALETTE_PRESETS, elementStyleById, PART_CLASS_NAMES } from '@vectoriox/iox-ui';
21
21
  export { ComponentInstanceRegistryService, VIRTUAL_TRAIT_KEYS, composeVirtualTraits } from '@vectoriox/iox-ui';
22
22
  import { StructureEdit, isAccordionPart, isDisclosurePart, isSliderPart, isTabsPart, isSegmentedPart, structureRefusal, StructureRefusal, SegmentedRole, SEGMENTED_MAX_OPTIONS, AccordionRole, SEGMENTED_MIN_OPTIONS, isExclusiveItemPart, TabsRole, ITEM_OPEN_STATE, readStyle, isSegmentedRoot, segmentedDefaultOn, segmentedOptions, isTabsRoot, isTabsFromContent, tabsTriggers, isAccordionRoot, isAccordionFromContent, accordionItems, initialAccordionOpen, accordionBehaviour, exclusiveItemLabel, exclusiveRootOf, tabTriggerOf, tabLabel, removeTabPair, tabPanelOf, tabsListOf, tabsPanelsOf, nextTabKey, CompositeBehaviourTrait, ACCORDION_DEFAULT_ONS, TabsBehaviourTrait, TABS_ACTIVATE_ONS, TABS_ORIENTATIONS, onCompositeItemState, isCompositeItemOn, runCompositeItemAction, shouldScrollToItem, rowIndexOf as rowIndexOf$1, slideIndexForRow, DisclosureRole, isExclusiveTrigger, compositeScopeId, compositeRowKeys, isExclusiveRoot, ExclusiveRuntime, exclusiveDefaultOf, exclusiveLabelOf, exclusiveBehaviourOf, exclusiveKindOf, compositeKindOfRole, AccordionRuntime, isToggleKind, closestAccordionItem, isAnyCompositeRoot, isExclusiveList, buildCardRecipe, buildBadge, buildChip, buildAccordionRecipe, buildDisclosureRecipe, buildTabsRecipe, buildSegmentedRecipe, buildLightboxRecipe, NO_ELEMENT_STYLE, CompositeKind, SliderRole, accordionItemLabel, segmentedOptionLabel, isExclusivePanels, isLockedPart, accordionRootOf, accordionItemOf, addAccordionItem, addTabPair, segmentedAddRefusal, addSegmentedOption, isCompositeItem, accordionHeadingLevel, isCompositePanel, isCompositeTrigger, splitSliderChildren, hasSliderParts } from '@vectoriox/iox-ui/composite-core';
23
23
  import { formContentInHost, isInteractiveHost, findFormContentInHosts } from '@vectoriox/iox-ui/forms-core';
@@ -26,12 +26,12 @@ import interact from 'interactjs';
26
26
  import { map, catchError } from 'rxjs/operators';
27
27
  import * as i1 from '@angular/common/http';
28
28
  import { itemActionOf, BEHAVIOUR_ACTION_TYPES, SERVER_ELEMENT_ACTION_TYPES, CONSENT_ACTION_TYPES, opensAtClickedItem, openedDialogId, DIALOG_CLOSING_ATTRIBUTE, cancelExit, runExitMotion } from '@vectoriox/iox-ui/actions-core';
29
+ import { NavRole, navShapeBreakpoint, entranceInteraction, entranceAction, sectionEntrances, EntrancePart } from '@vectoriox/iox-ui/generation-core';
29
30
  import Lenis from 'lenis';
30
31
  import Moveable from 'moveable';
31
32
  import Selecto from 'selecto';
32
33
  import * as i18 from 'primeng/api';
33
34
  import { planVideo, VideoSource, VIDEO_PROVIDER_LABEL, VideoTrait, VideoMode } from '@vectoriox/iox-ui/media-core';
34
- import { entranceInteraction, entranceAction, sectionEntrances, EntrancePart } from '@vectoriox/iox-ui/generation-core';
35
35
  import { ConsentCategory } from '@vectoriox/iox-ui/consent-core';
36
36
 
37
37
  /**
@@ -115,6 +115,13 @@ const BUILDER_CHROME_EN = Object.freeze({
115
115
  'builder.chrome.addItem': 'Add item',
116
116
  'builder.chrome.kindTabs': 'Tabs',
117
117
  'builder.chrome.kindNav': 'Navigation bar',
118
+ 'builder.chrome.menuPreview': 'Menu',
119
+ 'builder.chrome.menuPreviewShow': 'Show the phone menu on the canvas (design only, never saved)',
120
+ 'builder.chrome.menuPreviewHide': 'Hide the phone menu on the canvas',
121
+ 'builder.chrome.menuOpener': 'Opens and closes the menu',
122
+ 'builder.chrome.actionOpenDialog': 'Open dialog',
123
+ 'builder.chrome.actionCloseDialog': 'Close dialog',
124
+ 'builder.chrome.actionToggleDialog': 'Open or close dialog',
118
125
  'builder.chrome.addTab': 'Add tab',
119
126
  'builder.chrome.refuseLockedTabsPart': 'Tabs keep their tab list and their panels. Delete the whole Tabs instead.',
120
127
  'builder.chrome.refuseLockedTabsPartMove': 'This part belongs to its Tabs — it can’t be moved out.',
@@ -4840,12 +4847,69 @@ function pathToNode(roots, target) {
4840
4847
  return [];
4841
4848
  }
4842
4849
 
4850
+ const NAV_CONTEXT_ROLES = new Set([NavRole.Root, NavRole.Drawer, NavRole.Bar]);
4851
+ function findRole(nodes, role) {
4852
+ for (const n of nodes) {
4853
+ if (n.role === role)
4854
+ return n;
4855
+ const below = findRole(n.children ?? [], role);
4856
+ if (below)
4857
+ return below;
4858
+ }
4859
+ return null;
4860
+ }
4861
+ /** True when the selection (root → selected) is the Navigation bar, its drawer, its bottom bar, or anything inside them. */
4862
+ function inPhoneMenuContext(path) {
4863
+ return path.some(n => !!n.role && NAV_CONTEXT_ROLES.has(n.role));
4864
+ }
4865
+ /**
4866
+ * The phone menu a selection belongs to, or null when the selection is outside a navigation or the site has no drawer
4867
+ * (no phone shape yet, or the Bottom bar shape). The drawer is looked up in the selection's own Navigation bar first,
4868
+ * then in the globals (the Both shape makes it a global of its own).
4869
+ */
4870
+ function phoneMenuOf(path, globals = []) {
4871
+ if (!inPhoneMenuContext(path))
4872
+ return null;
4873
+ const root = path.find(n => n.role === NavRole.Root) ?? null;
4874
+ const scopes = root ? [root, ...globals] : [...globals];
4875
+ const drawer = path.find(n => n.role === NavRole.Drawer) ?? findRole(scopes, NavRole.Drawer);
4876
+ if (!drawer)
4877
+ return null;
4878
+ const menuButton = findRole(scopes, NavRole.MenuButton);
4879
+ const at = navShapeBreakpoint(scopes);
4880
+ return { root, drawer, menuButton, at };
4881
+ }
4882
+ /** True when the canvas, at `breakpoint`, shows the phone menu that takes over at `at` (that width or narrower). */
4883
+ function phoneMenuShowsAt(at, breakpoint) {
4884
+ return cascadeChain(breakpoint).includes(at);
4885
+ }
4886
+ const OPENER_TRIGGER = 'click';
4887
+ /** The dialog actions a phone menu's opener runs (generation-core stamps Toggle; CC1 menus still hold Open). */
4888
+ var PhoneMenuOpenerAction;
4889
+ (function (PhoneMenuOpenerAction) {
4890
+ PhoneMenuOpenerAction["Open"] = "openDialog";
4891
+ PhoneMenuOpenerAction["Toggle"] = "toggleDialog";
4892
+ })(PhoneMenuOpenerAction || (PhoneMenuOpenerAction = {}));
4893
+ const OPENER_ACTIONS = new Set(Object.values(PhoneMenuOpenerAction));
4894
+ /** True when `interaction` is the phone menu's own opener: the menu button's (or More's) click opening the drawer. */
4895
+ function isPhoneMenuOpener(node, interaction, drawerId) {
4896
+ if (!drawerId || (node?.role !== NavRole.MenuButton && node?.role !== NavRole.More))
4897
+ return false;
4898
+ const actions = interaction?.actions ?? [];
4899
+ return interaction?.trigger === OPENER_TRIGGER && actions.length === 1
4900
+ && OPENER_ACTIONS.has(actions[0].type ?? '') && actions[0].target === drawerId;
4901
+ }
4902
+
4843
4903
  /** What a hidden-at-rest part shows on the canvas when the author picks it in "Showing on canvas". */
4844
4904
  var CanvasShowState;
4845
4905
  (function (CanvasShowState) {
4846
4906
  CanvasShowState["Closed"] = "closed";
4847
4907
  CanvasShowState["Open"] = "open";
4848
4908
  })(CanvasShowState || (CanvasShowState = {}));
4909
+ const EMPTY_SNAPSHOT = () => ({
4910
+ revealed: new Set(), selectedTriggers: new Set(), pinned: new Set(), triggeredBySelection: new Set(), shown: new Map(), items: new Map(),
4911
+ runtime: new Set(), menu: null,
4912
+ });
4849
4913
  /**
4850
4914
  * The canvas's DESIGN state (complex-components R2; composite plan §5a's CompositeDesignStateService,
4851
4915
  * started here for the navigation and reused by Accordion in CC2): which parts that are hidden at rest
@@ -4862,7 +4926,7 @@ var CanvasShowState;
4862
4926
  */
4863
4927
  class CanvasDesignStateService {
4864
4928
  constructor() {
4865
- this._state$ = new BehaviorSubject({ revealed: new Set(), selectedTriggers: new Set(), pinned: new Set(), triggeredBySelection: new Set(), shown: new Map(), items: new Map() });
4929
+ this._state$ = new BehaviorSubject(EMPTY_SNAPSHOT());
4866
4930
  this.state$ = this._state$.asObservable();
4867
4931
  this._pagePath$ = new BehaviorSubject(null);
4868
4932
  /** The app path of the page on the canvas (`/work`), or null when unknown. */
@@ -4881,26 +4945,29 @@ class CanvasDesignStateService {
4881
4945
  }
4882
4946
  /**
4883
4947
  * The selection moved. The hidden-at-rest PARTS on its path are revealed and every other part is not
4884
- * (R2); a free-standing overlay on the path is pinned open until it is closed (A4).
4948
+ * (R2); a free-standing overlay on the path is pinned open until it is closed (A4). `globals` lets it find the
4949
+ * phone menu the selection belongs to when its drawer lives outside the path (the Both shape).
4885
4950
  */
4886
- setSelectionPath(path) {
4951
+ setSelectionPath(path, globals = []) {
4887
4952
  const ids = (reveal) => path.filter(n => selectionRevealOf(n) === reveal).map(n => n.id).filter((id) => !!id);
4888
4953
  const revealed = new Set(ids(SelectionReveal.WhileSelected));
4889
4954
  const selectedTriggers = new Set(path.filter(n => isExclusiveTrigger(n)).map(n => n.id).filter((id) => !!id));
4890
4955
  const triggeredBySelection = new Set(path.map(displayTriggerOf).filter((id) => !!id));
4891
4956
  const { revealed: was, pinned: held, selectedTriggers: wasTriggers, triggeredBySelection: wasTriggered } = this._state$.value;
4892
4957
  const pinned = new Set([...held, ...ids(SelectionReveal.UntilClosed)]);
4893
- if (sameSet(revealed, was) && sameSet(pinned, held) && sameSet(selectedTriggers, wasTriggers) && sameSet(triggeredBySelection, wasTriggered))
4958
+ const menu = phoneMenuOf(path, globals);
4959
+ if (sameSet(revealed, was) && sameSet(pinned, held) && sameSet(selectedTriggers, wasTriggers) && sameSet(triggeredBySelection, wasTriggered)
4960
+ && sameMenu(menu, this._state$.value.menu))
4894
4961
  return;
4895
- this._state$.next({ ...this._state$.value, revealed, pinned, selectedTriggers, triggeredBySelection });
4962
+ this._state$.next({ ...this._state$.value, revealed, pinned, selectedTriggers, triggeredBySelection, menu });
4896
4963
  }
4897
4964
  /** Closed on the canvas (its X, its backdrop, the eye): no longer pinned, switched open or revealed by the
4898
4965
  * selection — selecting into it again reveals it again. */
4899
4966
  dismiss(nodeId) {
4900
4967
  if (!nodeId)
4901
4968
  return;
4902
- const { pinned, shown, revealed } = this._state$.value;
4903
- if (!pinned.has(nodeId) && !shown.has(nodeId) && !revealed.has(nodeId))
4969
+ const { pinned, shown, revealed, runtime } = this._state$.value;
4970
+ if (!pinned.has(nodeId) && !shown.has(nodeId) && !revealed.has(nodeId) && !runtime.has(nodeId))
4904
4971
  return;
4905
4972
  const nextPinned = new Set(pinned);
4906
4973
  nextPinned.delete(nodeId);
@@ -4908,7 +4975,15 @@ class CanvasDesignStateService {
4908
4975
  nextShown.delete(nodeId);
4909
4976
  const nextRevealed = new Set(revealed);
4910
4977
  nextRevealed.delete(nodeId);
4911
- this._state$.next({ ...this._state$.value, pinned: nextPinned, shown: nextShown, revealed: nextRevealed });
4978
+ const nextRuntime = new Set(runtime);
4979
+ nextRuntime.delete(nodeId);
4980
+ this._state$.next({ ...this._state$.value, pinned: nextPinned, shown: nextShown, revealed: nextRevealed, runtime: nextRuntime });
4981
+ }
4982
+ /** An action opened the overlay on the canvas (a click on the menu button): shown until something closes it. */
4983
+ markOpened(nodeId) {
4984
+ if (!nodeId || this._state$.value.runtime.has(nodeId))
4985
+ return;
4986
+ this._state$.next({ ...this._state$.value, runtime: new Set([...this._state$.value.runtime, nodeId]) });
4912
4987
  }
4913
4988
  /** The switcher's choice for one part (null = back to the saved default). */
4914
4989
  setShown(nodeId, state) {
@@ -4938,12 +5013,12 @@ class CanvasDesignStateService {
4938
5013
  shownState(nodeId) {
4939
5014
  return (nodeId && this._state$.value.shown.get(nodeId)) || CanvasShowState.Closed;
4940
5015
  }
4941
- /** True when the canvas shows the part: selected into, or switched open. */
5016
+ /** True when the canvas shows the part: selected into, switched open, or opened by an action. */
4942
5017
  isShown(nodeId) {
4943
5018
  if (!nodeId)
4944
5019
  return false;
4945
- const { revealed, pinned, shown } = this._state$.value;
4946
- return revealed.has(nodeId) || pinned.has(nodeId) || shown.get(nodeId) === CanvasShowState.Open;
5020
+ const { revealed, pinned, shown, runtime } = this._state$.value;
5021
+ return revealed.has(nodeId) || pinned.has(nodeId) || runtime.has(nodeId) || shown.get(nodeId) === CanvasShowState.Open;
4947
5022
  }
4948
5023
  /** True when the canvas shows an item because the selection is styled "when it is on" (the switcher's hint). */
4949
5024
  isTriggeredBySelection(triggerId) {
@@ -4955,7 +5030,7 @@ class CanvasDesignStateService {
4955
5030
  }
4956
5031
  /** A new page on the canvas: nothing is revealed or switched open. */
4957
5032
  reset() {
4958
- this._state$.next({ revealed: new Set(), selectedTriggers: new Set(), pinned: new Set(), triggeredBySelection: new Set(), shown: new Map(), items: new Map() });
5033
+ this._state$.next(EMPTY_SNAPSHOT());
4959
5034
  }
4960
5035
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: CanvasDesignStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4961
5036
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: CanvasDesignStateService }); }
@@ -4963,9 +5038,33 @@ class CanvasDesignStateService {
4963
5038
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: CanvasDesignStateService, decorators: [{
4964
5039
  type: Injectable
4965
5040
  }] });
5041
+ function sameMenu(a, b) {
5042
+ if (!a || !b)
5043
+ return a === b;
5044
+ return a.drawer === b.drawer && a.menuButton === b.menuButton && a.root === b.root && a.at === b.at;
5045
+ }
4966
5046
  function sameSet(a, b) {
4967
5047
  return a.size === b.size && [...a].every(id => b.has(id));
4968
5048
  }
5049
+ /**
5050
+ * Show or hide an overlay part (the Menu drawer) for DESIGN — ONE move for every control that previews it (the
5051
+ * Bindings ▸ Phone menu row, the canvas's Menu chip). Opening switches it open; closing closes its canvas twin the way
5052
+ * its own Close does (the exit plays, the reveal and the switch are cleared, a selection inside it moves to its
5053
+ * opener), so a drawer shown because the selection sits in it closes too.
5054
+ */
5055
+ function setOverlayPreview(state, twins, id, open) {
5056
+ if (!id)
5057
+ return;
5058
+ if (open) {
5059
+ state.setShown(id, CanvasShowState.Open);
5060
+ return;
5061
+ }
5062
+ const twin = twins?.get(id);
5063
+ if (twin?.close)
5064
+ twin.close();
5065
+ else
5066
+ state.dismiss(id);
5067
+ }
4969
5068
 
4970
5069
  /** The node whose "Showing on canvas" choice a rendered root follows: itself, or — a preview row's copy — its
4971
5070
  * template (a copy shares its template's style id). */
@@ -7596,6 +7695,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
7596
7695
  }] });
7597
7696
 
7598
7697
  const FROM_ROW_KEY = 'builder.chrome.fromRow';
7698
+ const MENU_CHIP_KEY = 'builder.chrome.menuPreview';
7699
+ const MENU_SHOW_KEY = 'builder.chrome.menuPreviewShow';
7700
+ const MENU_HIDE_KEY = 'builder.chrome.menuPreviewHide';
7701
+ const MENU_OPENER_KEY = 'builder.chrome.menuOpener';
7702
+ /** The interaction badge's words for a dialog action (it showed the raw `toggleDialog`). */
7703
+ const DIALOG_ACTION_KEYS = {
7704
+ openDialog: 'builder.chrome.actionOpenDialog', closeDialog: 'builder.chrome.actionCloseDialog', toggleDialog: 'builder.chrome.actionToggleDialog',
7705
+ };
7599
7706
  const ADD_ITEM_KEY = 'builder.chrome.addItem';
7600
7707
  /** The kind label a composite part's selection badge shows (Card v2: "Card · card.title"). */
7601
7708
  const COMPOSITE_KIND_KEYS = { card: 'builder.chrome.kindCard', accordion: 'builder.chrome.kindAccordion', disclosure: 'builder.chrome.kindDisclosure', tabs: 'builder.chrome.kindTabs', segmented: 'builder.chrome.kindSegmented', slider: 'builder.chrome.kindSlider', nav: 'builder.chrome.kindNav' };
@@ -7614,7 +7721,7 @@ const ADD_TAB_KEY = 'builder.chrome.addTab';
7614
7721
  /** A Segmented control says "Add option" (board 10). */
7615
7722
  const ADD_OPTION_KEY = 'builder.chrome.addOption';
7616
7723
  class OverlayComponent {
7617
- constructor(elRef, instanceRegistry, overlayService, viewportService, presetRegistry, symbolRegistry, interactionPresetRegistry, interactionEngine, clipboard, styleRegistry, panelEventService, cdr, dragEngine, labels) {
7724
+ constructor(elRef, instanceRegistry, overlayService, viewportService, presetRegistry, symbolRegistry, interactionPresetRegistry, interactionEngine, clipboard, styleRegistry, panelEventService, cdr, dragEngine, labels, designState) {
7618
7725
  this.elRef = elRef;
7619
7726
  this.instanceRegistry = instanceRegistry;
7620
7727
  this.overlayService = overlayService;
@@ -7628,6 +7735,7 @@ class OverlayComponent {
7628
7735
  this.panelEventService = panelEventService;
7629
7736
  this.cdr = cdr;
7630
7737
  this.dragEngine = dragEngine;
7738
+ this.designState = designState;
7631
7739
  this.toolbarAction = new EventEmitter();
7632
7740
  /** Element types the selected node can be wrapped in (Wrap-in submenu). Phase 1: layout containers. */
7633
7741
  this.wrapTargets = [
@@ -7675,6 +7783,12 @@ class OverlayComponent {
7675
7783
  this.boundUpdate = () => this.scheduleUpdate();
7676
7784
  this.boundScrollUpdate = () => this.scheduleUpdate();
7677
7785
  this.activeScrollContainer = null;
7786
+ /** CC1.3: the phone menu the selection belongs to, while the canvas is at a width where it shows — the toolbar's
7787
+ * Menu chip previews its drawer (the same design state as Bindings ▸ Phone menu ▸ Preview on canvas). */
7788
+ this.menuChip = null;
7789
+ this.menuChipOpen = false;
7790
+ this.menuChipLabel = '';
7791
+ this.menuChipTitle = '';
7678
7792
  this.builderLabels = labels ?? defaultBuilderLabels;
7679
7793
  }
7680
7794
  /** Resolves the selected node's OWNING dropzone id dynamically — the drag-handle isn't
@@ -7697,8 +7811,12 @@ class OverlayComponent {
7697
7811
  this.cdr.markForCheck();
7698
7812
  }));
7699
7813
  window.addEventListener('resize', this.boundUpdate, { passive: true });
7814
+ // CC1.3: the Menu chip follows the selection's phone menu and whether its drawer is shown.
7815
+ if (this.designState)
7816
+ this.subs.push(this.designState.state$.subscribe(() => { this.refreshMenuChip(); this.cdr.markForCheck(); }));
7700
7817
  // Re-calculate overlay positions whenever zoom / device changes.
7701
7818
  this.subs.push(this.viewportService.state$.subscribe(() => {
7819
+ this.refreshMenuChip();
7702
7820
  // Delay one frame so the DOM has applied the new transform/width.
7703
7821
  this.scheduleUpdate();
7704
7822
  }));
@@ -7924,7 +8042,11 @@ class OverlayComponent {
7924
8042
  rotate: 'Rotate', show: 'Show', hide: 'Hide',
7925
8043
  toggleVisibility: 'Toggle',
7926
8044
  };
7927
- const label = labels[first.type] ?? first.type;
8045
+ if (isPhoneMenuOpener(this.selectEntry?.node, ix, this.designState?.snapshot.menu?.drawer.id)) {
8046
+ return this.builderLabels(MENU_OPENER_KEY, BUILDER_CHROME_EN[MENU_OPENER_KEY]);
8047
+ }
8048
+ const dialogKey = DIALOG_ACTION_KEYS[first.type];
8049
+ const label = dialogKey ? this.builderLabels(dialogKey, BUILDER_CHROME_EN[dialogKey]) : (labels[first.type] ?? first.type);
7928
8050
  return ix.actions.length > 1 ? `${label} +${ix.actions.length - 1}` : label;
7929
8051
  }
7930
8052
  get hasPresetInClipboard() { return !!this.clipboard.getPresetId(); }
@@ -8045,9 +8167,24 @@ class OverlayComponent {
8045
8167
  return this.selectEntry?.node?.type === 'SliderContainer';
8046
8168
  }
8047
8169
  /** Boards A4/A5: a closed dialog has NO canvas presence — this toolbar eye (and the layer
8048
- * tree row) is how an author opens and closes it for design. */
8170
+ * tree row) is how an author opens and closes it for design. The Menu drawer has the Menu chip instead. */
8049
8171
  get isDialog() {
8050
- return this.selectEntry?.node?.type === 'Dialog';
8172
+ return this.selectEntry?.node?.type === 'Dialog' && this.selectEntry?.node?.id !== this.menuChip?.drawer.id;
8173
+ }
8174
+ refreshMenuChip() {
8175
+ const menu = this.designState?.snapshot.menu ?? null;
8176
+ this.menuChip = menu && phoneMenuShowsAt(menu.at, this.viewportService.getState().breakpoint) ? menu : null;
8177
+ this.menuChipOpen = !!this.menuChip && !!this.designState?.isShown(this.menuChip.drawer.id);
8178
+ this.menuChipLabel = this.builderLabels(MENU_CHIP_KEY, BUILDER_CHROME_EN[MENU_CHIP_KEY]);
8179
+ const titleKey = this.menuChipOpen ? MENU_HIDE_KEY : MENU_SHOW_KEY;
8180
+ this.menuChipTitle = this.builderLabels(titleKey, BUILDER_CHROME_EN[titleKey]);
8181
+ }
8182
+ onToggleMenuChip(event) {
8183
+ event.stopPropagation();
8184
+ if (!this.menuChip || !this.designState)
8185
+ return;
8186
+ setOverlayPreview(this.designState, this.instanceRegistry, this.menuChip.drawer.id, !this.menuChipOpen);
8187
+ this.scheduleUpdate();
8051
8188
  }
8052
8189
  get dialogDesignOpen() {
8053
8190
  const id = this.selectEntry?.node?.id;
@@ -8199,17 +8336,19 @@ class OverlayComponent {
8199
8336
  // is a zero-area line — prevents diagonal edge triangle artifacts.
8200
8337
  return `polygon(evenodd, 0px 0px, ${w}px 0px, ${w}px ${h}px, 0px ${h}px, 0px 0px, ${x1}px ${y1}px, ${x2}px ${y1}px, ${x2}px ${y2}px, ${x1}px ${y2}px, ${x1}px ${y1}px)`;
8201
8338
  }
8202
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: OverlayComponent, deps: [{ token: i0.ElementRef }, { token: i1$1.ComponentInstanceRegistryService }, { token: OverlayService }, { token: ViewportService }, { token: PresetRegistryService }, { token: SymbolRegistryService }, { token: InteractionPresetRegistryService }, { token: InteractionEngineService }, { token: BuilderClipboardService }, { token: StyleRegistryService }, { token: PanelEventService }, { token: i0.ChangeDetectorRef }, { token: DragEngineService }, { token: IOX_BUILDER_LABELS, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
8203
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: OverlayComponent, isStandalone: false, selector: "app-overlay", outputs: { toolbarAction: "toolbarAction" }, ngImport: i0, template: "<div class=\"overlay-root\">\n\n <!-- HOVER \u2014 Chrome DevTools-style rings (content area stays transparent) -->\n <ng-container *ngIf=\"hoverEntry\">\n <div class=\"hi-outline\" [ngStyle]=\"hiOutlineStyle\"></div>\n <div class=\"hi-margin\" [ngStyle]=\"hiMarginStyle\"></div>\n <div class=\"hi-padding\" [ngStyle]=\"hiPaddingStyle\"></div>\n </ng-container>\n\n <!-- SELECT \u2014 IOX pink outline + toolbar -->\n <div class=\"select-outline\" *ngIf=\"selectEntry\" [ngStyle]=\"selectOutlineStyle\">\n\n <!-- Preset badges container \u2014 below the outline, start-aligned -->\n <div class=\"preset-badge\" *ngIf=\"selectedRoleBadge || selectedPresetName || interactions.length\">\n <!-- A composite part (Card v2): its kind and role, read-only \u2014 what the layer tree's chip says. -->\n <div *ngIf=\"selectedRoleBadge\" class=\"preset-badge__item preset-badge__item--kind\" [title]=\"selectedRoleBadge\">\n <i [class]=\"selectedRoleIcon\" aria-hidden=\"true\"></i>\n <span>{{ selectedRoleBadge }}</span>\n </div>\n <div *ngIf=\"selectedPresetName\"\n class=\"preset-badge__item\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'style'\"\n title=\"Style preset: {{ selectedPresetName }} \u2014 click to edit, right-click to copy\"\n (mousedown)=\"onEditPreset($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'style')\">\n <i class=\"ph-fill ph-paint-bucket\"></i>\n <span>{{ selectedPresetName }}</span>\n </div>\n <div *ngFor=\"let ix of interactions\"\n class=\"preset-badge__item preset-badge__item--interaction\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'interaction'\"\n [title]=\"triggerLabel(ix.trigger) + ': ' + actionLabel(ix) + ' \u2014 click to edit, right-click to remove'\"\n (mousedown)=\"onEditInteractionPreset($event, ix)\"\n (click)=\"onBadgeClickSwallow($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'interaction', ix)\">\n <i [class]=\"triggerIcon(ix.trigger)\"></i>\n <span>{{ triggerLabel(ix.trigger) }}: {{ actionLabel(ix) }}</span>\n </div>\n </div>\n\n <div class=\"select-toolbar\" [class.select-toolbar--inside]=\"toolbarInside\" (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n\n <!-- Drag handle \u2014 grab here to move the selected element. A click-and-hold ANYWHERE\n on the element body would otherwise grab whatever nested child the pointer lands\n on; DragEngineService redirects any drag starting here to the selected node. -->\n <button *ngIf=\"selectEntry?.node\" class=\"toolbar-btn toolbar-btn--drag-handle\"\n ioxDraggable data-iox-drag-handle\n [ioxDragData]=\"selectEntry?.node\"\n [ioxDragSourceId]=\"dragHandleSourceId\"\n title=\"Drag to move\">\n <i class=\"ph-thin ph-dots-six-vertical\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Component name -->\n <span class=\"toolbar-name\">{{ toolbarName }}</span>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Quick actions -->\n <button *ngIf=\"isDialog\" class=\"toolbar-btn\"\n [title]=\"dialogDesignOpen ? 'Close the dialog (design)' : 'Open the dialog (design)'\"\n [attr.aria-label]=\"dialogDesignOpen ? 'Close the dialog for design' : 'Open the dialog for design'\"\n (mousedown)=\"onToggleDialogOpen($event)\">\n <i [class]=\"dialogDesignOpen ? 'ph-thin ph-eye-slash' : 'ph-thin ph-eye'\"></i>\n </button>\n <button *ngIf=\"isSliderContainer\" class=\"toolbar-btn toolbar-btn--add-slide\" title=\"Add slide\" (mousedown)=\"onAddSlide($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n <span class=\"toolbar-btn__label\">Add slide</span>\n </button>\n @if (canAddItem) {\n <button class=\"toolbar-btn toolbar-btn--add-slide\" [title]=\"addItemLabel\" (mousedown)=\"onAddItem($event)\">\n <i class=\"ph-thin ph-plus\" aria-hidden=\"true\"></i>\n <span class=\"toolbar-btn__label\">{{ addItemLabel }}</span>\n </button>\n }\n <button class=\"toolbar-btn\" title=\"Add an element here\" aria-label=\"Add an element here\" (mousedown)=\"onAddElement($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n </button>\n <button class=\"toolbar-btn\" title=\"Duplicate\" (mousedown)=\"onDuplicate($event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n <button *ngIf=\"hasInteractions\" class=\"toolbar-btn toolbar-btn--play\" title=\"Play animations\" (mousedown)=\"onPlay($event)\">\n <i class=\"ph-thin ph-play\"></i>\n </button>\n <button *ngIf=\"isLinkedSymbol\" class=\"toolbar-btn toolbar-btn--symbol\"\n [title]=\"(linkedSymbolName ? linkedSymbolName : 'Symbol') + ' \u2014 click to detach'\"\n (mousedown)=\"onDetachSymbol($event)\">\n <i class=\"ph-thin ph-link\"></i>\n <span class=\"toolbar-btn__label\">{{ linkedSymbolName || 'Symbol' }}</span>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"toolbar-btn toolbar-btn--resync\"\n title=\"Detached \u2014 click to re-link\"\n (mousedown)=\"onResyncSymbol($event)\">\n <i class=\"ph-thin ph-link-break\"></i>\n <span class=\"toolbar-btn__label\">Detached</span>\n </button>\n <button class=\"toolbar-btn toolbar-btn--danger\" title=\"Delete\" (mousedown)=\"onDelete($event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n <button class=\"toolbar-btn\" title=\"Select parent\" (mousedown)=\"onSelectParent($event)\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n </button>\n\n <!-- More menu trigger \u2014 opens a fixed-position dropdown at the cursor -->\n <button class=\"toolbar-btn toolbar-btn--more\" title=\"More actions\" (mousedown)=\"onToggleMore($event)\">\n <i class=\"ph-thin ph-dots-three\"></i>\n </button>\n </div>\n </div>\n\n <!-- Shared more/context menu \u2014 fixed-position, opened by \u22EF button or right-click -->\n <div *ngIf=\"moreMenuVisible\" class=\"toolbar-more-dropdown\" [ngStyle]=\"moreMenuStyle\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <button class=\"more-item\" (mousedown)=\"onSelectParent($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n Select parent\n </button>\n <button class=\"more-item\" (mousedown)=\"onDuplicate($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-copy\"></i>\n Duplicate\n </button>\n <div *ngIf=\"canWrap\" class=\"more-item-submenu\"\n (mouseenter)=\"wrapSubmenuOpen = true\" (mouseleave)=\"wrapSubmenuOpen = false\">\n <button class=\"more-item\" (mousedown)=\"$event.stopPropagation()\">\n <i class=\"ph-thin ph-selection-plus\"></i>\n Wrap in\n <i class=\"ph-thin ph-caret-right more-item__chevron\"></i>\n </button>\n <div *ngIf=\"wrapSubmenuOpen\" class=\"more-submenu-flyout\">\n <button *ngFor=\"let target of wrapTargets\" class=\"more-item\"\n (mousedown)=\"onWrap($event, target.type); closeMoreMenu()\">\n <i [class]=\"target.icon\"></i>\n {{ target.label }}\n </button>\n </div>\n </div>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onDelete($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-trash\"></i>\n Delete\n </button>\n <div class=\"more-divider\"></div>\n <button class=\"more-item\" (mousedown)=\"onCopyNode($event)\">\n <i class=\"ph-thin ph-scissors\"></i>\n Copy element\n </button>\n <button *ngIf=\"hasCopiedNode\" class=\"more-item\" (mousedown)=\"onPasteNode($event)\">\n <i class=\"ph-thin ph-clipboard\"></i>\n Paste element\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"selectEntry?.node?.stylePresetId\" class=\"more-item\" (mousedown)=\"onCopyPreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Copy style preset\n </button>\n <button *ngIf=\"hasPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPastePreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Paste style preset\n </button>\n <button *ngIf=\"selectEntry?.node?.interactionPresetId\" class=\"more-item\" (mousedown)=\"onCopyInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Copy interaction preset\n </button>\n <button *ngIf=\"hasInteractionPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPasteInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Paste interaction preset\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"isLinkedSymbol\" class=\"more-item\" (mousedown)=\"onDetachSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link-break\"></i>\n Detach from symbol<ng-container *ngIf=\"linkedSymbolName\"> ({{ linkedSymbolName }})</ng-container>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"more-item more-item--resync\" (mousedown)=\"onResyncSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link\"></i>\n Re-link to symbol\n </button>\n <button class=\"more-item\" (mousedown)=\"onSaveAsBlock($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-bookmark\"></i>\n Save as reusable block\n </button>\n <button *ngIf=\"hasInteractions\" class=\"more-item more-item--play\" (mousedown)=\"onPlay($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-play\"></i>\n Play animations\n </button>\n <div class=\"more-divider\"></div>\n <ng-container *ngIf=\"!selectedNodeIsGlobal; else removeGlobalItem\">\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'before')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (Before Content)\n </button>\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'after')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (After Content)\n </button>\n </ng-container>\n <ng-template #removeGlobalItem>\n <button class=\"more-item\" (mousedown)=\"onRemoveGlobal($event)\">\n <i class=\"ph-thin ph-globe\"></i>\n Remove from Global\n </button>\n </ng-template>\n </div>\n\n <!-- Backdrop to close the more menu -->\n <div *ngIf=\"moreMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeMoreMenu()\">\n </div>\n\n <!-- Badge context menu \u2014 options differ by badge type -->\n <div *ngIf=\"badgeMenuVisible\" class=\"badge-context-menu\"\n [ngStyle]=\"{ top: badgeMenuPos.y + 'px', left: badgeMenuPos.x + 'px' }\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <ng-container *ngIf=\"badgeMenuType === 'style'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeCopy()\">\n <i class=\"ph-thin ph-copy\"></i>\n Copy preset\n </button>\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit preset\n </button>\n </ng-container>\n <ng-container *ngIf=\"badgeMenuType === 'interaction'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit in panel\n </button>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onBadgeRemoveInteraction()\">\n <i class=\"ph-thin ph-trash\"></i>\n Remove interaction\n </button>\n </ng-container>\n </div>\n <div *ngIf=\"badgeMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeBadgeMenu()\">\n </div>\n\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;position:absolute;inset:0;pointer-events:none;z-index:12;overflow:visible}.hi-outline,.hi-margin,.hi-padding{position:fixed;pointer-events:none;transition:none;box-sizing:border-box}.hi-outline{box-shadow:inset 0 0 0 1.5px #cb9090}.hi-margin{background:#f6b23361}.hi-padding{background:#60c38366}.select-outline{position:fixed;z-index:999;box-shadow:inset 0 0 0 1px #cb9090;pointer-events:none;transition:none;overflow:visible;will-change:transform;box-sizing:border-box}.select-toolbar{position:absolute;top:0;left:0;transform:translateY(-100%)}.select-toolbar.select-toolbar--inside{transform:translateY(0);border-radius:0 0 3px 3px}.select-toolbar{display:flex;align-items:center;background:#cb9090;border-radius:3px 3px 0 0;pointer-events:all;white-space:nowrap;overflow:visible}.select-toolbar .toolbar-name{padding:0 8px;font-size:11px;font-weight:500;color:#fff;max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:22px}.select-toolbar .toolbar-sep{width:1px;height:14px;background:#ffffff59;margin:0 2px;flex-shrink:0}.select-toolbar .toolbar-btn{display:flex;align-items:center;justify-content:center;width:24px;height:22px;padding:0;border:none;background:transparent;color:#fff;font-size:13px;cursor:pointer;transition:background .15s;flex-shrink:0}.select-toolbar .toolbar-btn:hover{background:#ffffff2e}.select-toolbar .toolbar-btn--danger:hover{background:#c8323259}.select-toolbar .toolbar-btn--drag-handle{cursor:grab}.select-toolbar .toolbar-btn--drag-handle:active{cursor:grabbing}.select-toolbar .toolbar-btn--symbol{width:auto;padding:0 7px;gap:4px;color:#fff;background:#f59e0b;border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--symbol:hover{background:#d97706}.select-toolbar .toolbar-btn--resync{width:auto;padding:0 7px;gap:4px;color:#fff;background:var(--iox-success-fill, #2E7D45);border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--resync:hover{background:color-mix(in srgb,var(--iox-success-fill, #2E7D45) 86%,#000)}.select-toolbar .toolbar-btn--add-slide{width:auto;padding:0 7px;gap:4px;border-radius:3px}.select-toolbar .toolbar-btn .toolbar-btn__label{font-size:11px;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select-toolbar .toolbar-btn--more{border-radius:0 3px 0 0}.toolbar-more-dropdown{position:fixed;z-index:1000;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:200px;pointer-events:all}.toolbar-more-dropdown .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:8px 14px;border:none;background:transparent;font-size:13px;color:var(--p-text-color, #333);cursor:pointer;text-align:start;white-space:nowrap}.toolbar-more-dropdown .more-item i{font-size:14px}.toolbar-more-dropdown .more-item:hover{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item--danger{color:#c84040}.toolbar-more-dropdown .more-item--danger:hover{background:#c8404014}.toolbar-more-dropdown .more-item--play{color:var(--p-text-color, #333)}.toolbar-more-dropdown .more-item--resync{color:var(--iox-success-text, #1B5E32)}.toolbar-more-dropdown .more-item--resync:hover{background:var(--iox-success-bg, #E8F3EC)}.toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.toolbar-more-dropdown .more-item-submenu{position:relative}.toolbar-more-dropdown .more-item-submenu .more-item__chevron{margin-inline-start:auto;font-size:12px;opacity:.6}.toolbar-more-dropdown .more-item-submenu:hover>.more-item{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item-submenu .more-submenu-flyout{position:absolute;top:-4px;inset-inline-start:100%;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:180px;z-index:1001}.preset-badge{position:absolute;bottom:-26px;inset-inline-start:0;display:flex;align-items:center;gap:4px;pointer-events:none;white-space:nowrap}.preset-badge__item{display:flex;align-items:center;gap:5px;padding:3px 9px;background:#cb9090;color:#fff;font-size:11px;font-weight:500;border-radius:20px;pointer-events:all;cursor:pointer;box-shadow:0 2px 6px #0000002e;transition:background .15s,outline-color .15s;outline:2px solid transparent;outline-offset:2px}.preset-badge__item i{font-size:12px}.preset-badge__item:hover{background:#be7474}.preset-badge__item--active{outline-color:#ffffffd9}.preset-badge__item--interaction{background:#7a9ecb}.preset-badge__item--interaction:hover{background:#5d89c0}.preset-badge__item--kind{background:#8a3a72;cursor:default}.preset-badge__item--kind:hover{background:#8a3a72}.badge-context-menu{position:fixed;z-index:1001;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:160px;pointer-events:all}.badge-context-menu .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 14px;border:none;background:transparent;font-size:12px;color:#333;cursor:pointer;text-align:start;white-space:nowrap}.badge-context-menu .more-item:hover{background:var(--p-surface-50, #f9fafb)}.badge-context-menu .more-item i{font-size:13px;color:#888}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: IoxDraggableDirective, selector: "[ioxDraggable]", inputs: ["ioxDragData", "ioxDragSourceId", "ioxDragDisabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8339
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: OverlayComponent, deps: [{ token: i0.ElementRef }, { token: i1$1.ComponentInstanceRegistryService }, { token: OverlayService }, { token: ViewportService }, { token: PresetRegistryService }, { token: SymbolRegistryService }, { token: InteractionPresetRegistryService }, { token: InteractionEngineService }, { token: BuilderClipboardService }, { token: StyleRegistryService }, { token: PanelEventService }, { token: i0.ChangeDetectorRef }, { token: DragEngineService }, { token: IOX_BUILDER_LABELS, optional: true }, { token: CanvasDesignStateService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
8340
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: OverlayComponent, isStandalone: false, selector: "app-overlay", outputs: { toolbarAction: "toolbarAction" }, ngImport: i0, template: "<div class=\"overlay-root\">\n\n <!-- HOVER \u2014 Chrome DevTools-style rings (content area stays transparent) -->\n <ng-container *ngIf=\"hoverEntry\">\n <div class=\"hi-outline\" [ngStyle]=\"hiOutlineStyle\"></div>\n <div class=\"hi-margin\" [ngStyle]=\"hiMarginStyle\"></div>\n <div class=\"hi-padding\" [ngStyle]=\"hiPaddingStyle\"></div>\n </ng-container>\n\n <!-- SELECT \u2014 IOX pink outline + toolbar -->\n <div class=\"select-outline\" *ngIf=\"selectEntry\" [ngStyle]=\"selectOutlineStyle\">\n\n <!-- Preset badges container \u2014 below the outline, start-aligned -->\n <div class=\"preset-badge\" *ngIf=\"selectedRoleBadge || selectedPresetName || interactions.length\">\n <!-- A composite part (Card v2): its kind and role, read-only \u2014 what the layer tree's chip says. -->\n <div *ngIf=\"selectedRoleBadge\" class=\"preset-badge__item preset-badge__item--kind\" [title]=\"selectedRoleBadge\">\n <i [class]=\"selectedRoleIcon\" aria-hidden=\"true\"></i>\n <span>{{ selectedRoleBadge }}</span>\n </div>\n <div *ngIf=\"selectedPresetName\"\n class=\"preset-badge__item\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'style'\"\n title=\"Style preset: {{ selectedPresetName }} \u2014 click to edit, right-click to copy\"\n (mousedown)=\"onEditPreset($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'style')\">\n <i class=\"ph-fill ph-paint-bucket\"></i>\n <span>{{ selectedPresetName }}</span>\n </div>\n <div *ngFor=\"let ix of interactions\"\n class=\"preset-badge__item preset-badge__item--interaction\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'interaction'\"\n [title]=\"triggerLabel(ix.trigger) + ': ' + actionLabel(ix) + ' \u2014 click to edit, right-click to remove'\"\n (mousedown)=\"onEditInteractionPreset($event, ix)\"\n (click)=\"onBadgeClickSwallow($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'interaction', ix)\">\n <i [class]=\"triggerIcon(ix.trigger)\"></i>\n <span>{{ triggerLabel(ix.trigger) }}: {{ actionLabel(ix) }}</span>\n </div>\n </div>\n\n <div class=\"select-toolbar\" [class.select-toolbar--inside]=\"toolbarInside\" (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n\n <!-- Drag handle \u2014 grab here to move the selected element. A click-and-hold ANYWHERE\n on the element body would otherwise grab whatever nested child the pointer lands\n on; DragEngineService redirects any drag starting here to the selected node. -->\n <button *ngIf=\"selectEntry?.node\" class=\"toolbar-btn toolbar-btn--drag-handle\"\n ioxDraggable data-iox-drag-handle\n [ioxDragData]=\"selectEntry?.node\"\n [ioxDragSourceId]=\"dragHandleSourceId\"\n title=\"Drag to move\">\n <i class=\"ph-thin ph-dots-six-vertical\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Component name -->\n <span class=\"toolbar-name\">{{ toolbarName }}</span>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Quick actions -->\n @if (menuChip) {\n <!-- CC1.3: the phone menu's drawer, shown or hidden for design from anywhere in the navigation. -->\n <button class=\"toolbar-btn toolbar-btn--menu\" [class.toolbar-btn--on]=\"menuChipOpen\"\n [title]=\"menuChipTitle\" [attr.aria-label]=\"menuChipTitle\" [attr.aria-pressed]=\"menuChipOpen\"\n (mousedown)=\"onToggleMenuChip($event)\">\n <i [class]=\"menuChipOpen ? 'ph-thin ph-eye-slash' : 'ph-thin ph-eye'\" aria-hidden=\"true\"></i>\n <span class=\"toolbar-btn__label\">{{ menuChipLabel }}</span>\n </button>\n }\n <button *ngIf=\"isDialog\" class=\"toolbar-btn\"\n [title]=\"dialogDesignOpen ? 'Close the dialog (design)' : 'Open the dialog (design)'\"\n [attr.aria-label]=\"dialogDesignOpen ? 'Close the dialog for design' : 'Open the dialog for design'\"\n (mousedown)=\"onToggleDialogOpen($event)\">\n <i [class]=\"dialogDesignOpen ? 'ph-thin ph-eye-slash' : 'ph-thin ph-eye'\"></i>\n </button>\n <button *ngIf=\"isSliderContainer\" class=\"toolbar-btn toolbar-btn--add-slide\" title=\"Add slide\" (mousedown)=\"onAddSlide($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n <span class=\"toolbar-btn__label\">Add slide</span>\n </button>\n @if (canAddItem) {\n <button class=\"toolbar-btn toolbar-btn--add-slide\" [title]=\"addItemLabel\" (mousedown)=\"onAddItem($event)\">\n <i class=\"ph-thin ph-plus\" aria-hidden=\"true\"></i>\n <span class=\"toolbar-btn__label\">{{ addItemLabel }}</span>\n </button>\n }\n <button class=\"toolbar-btn\" title=\"Add an element here\" aria-label=\"Add an element here\" (mousedown)=\"onAddElement($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n </button>\n <button class=\"toolbar-btn\" title=\"Duplicate\" (mousedown)=\"onDuplicate($event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n <button *ngIf=\"hasInteractions\" class=\"toolbar-btn toolbar-btn--play\" title=\"Play animations\" (mousedown)=\"onPlay($event)\">\n <i class=\"ph-thin ph-play\"></i>\n </button>\n <button *ngIf=\"isLinkedSymbol\" class=\"toolbar-btn toolbar-btn--symbol\"\n [title]=\"(linkedSymbolName ? linkedSymbolName : 'Symbol') + ' \u2014 click to detach'\"\n (mousedown)=\"onDetachSymbol($event)\">\n <i class=\"ph-thin ph-link\"></i>\n <span class=\"toolbar-btn__label\">{{ linkedSymbolName || 'Symbol' }}</span>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"toolbar-btn toolbar-btn--resync\"\n title=\"Detached \u2014 click to re-link\"\n (mousedown)=\"onResyncSymbol($event)\">\n <i class=\"ph-thin ph-link-break\"></i>\n <span class=\"toolbar-btn__label\">Detached</span>\n </button>\n <button class=\"toolbar-btn toolbar-btn--danger\" title=\"Delete\" (mousedown)=\"onDelete($event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n <button class=\"toolbar-btn\" title=\"Select parent\" (mousedown)=\"onSelectParent($event)\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n </button>\n\n <!-- More menu trigger \u2014 opens a fixed-position dropdown at the cursor -->\n <button class=\"toolbar-btn toolbar-btn--more\" title=\"More actions\" (mousedown)=\"onToggleMore($event)\">\n <i class=\"ph-thin ph-dots-three\"></i>\n </button>\n </div>\n </div>\n\n <!-- Shared more/context menu \u2014 fixed-position, opened by \u22EF button or right-click -->\n <div *ngIf=\"moreMenuVisible\" class=\"toolbar-more-dropdown\" [ngStyle]=\"moreMenuStyle\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <button class=\"more-item\" (mousedown)=\"onSelectParent($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n Select parent\n </button>\n <button class=\"more-item\" (mousedown)=\"onDuplicate($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-copy\"></i>\n Duplicate\n </button>\n <div *ngIf=\"canWrap\" class=\"more-item-submenu\"\n (mouseenter)=\"wrapSubmenuOpen = true\" (mouseleave)=\"wrapSubmenuOpen = false\">\n <button class=\"more-item\" (mousedown)=\"$event.stopPropagation()\">\n <i class=\"ph-thin ph-selection-plus\"></i>\n Wrap in\n <i class=\"ph-thin ph-caret-right more-item__chevron\"></i>\n </button>\n <div *ngIf=\"wrapSubmenuOpen\" class=\"more-submenu-flyout\">\n <button *ngFor=\"let target of wrapTargets\" class=\"more-item\"\n (mousedown)=\"onWrap($event, target.type); closeMoreMenu()\">\n <i [class]=\"target.icon\"></i>\n {{ target.label }}\n </button>\n </div>\n </div>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onDelete($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-trash\"></i>\n Delete\n </button>\n <div class=\"more-divider\"></div>\n <button class=\"more-item\" (mousedown)=\"onCopyNode($event)\">\n <i class=\"ph-thin ph-scissors\"></i>\n Copy element\n </button>\n <button *ngIf=\"hasCopiedNode\" class=\"more-item\" (mousedown)=\"onPasteNode($event)\">\n <i class=\"ph-thin ph-clipboard\"></i>\n Paste element\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"selectEntry?.node?.stylePresetId\" class=\"more-item\" (mousedown)=\"onCopyPreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Copy style preset\n </button>\n <button *ngIf=\"hasPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPastePreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Paste style preset\n </button>\n <button *ngIf=\"selectEntry?.node?.interactionPresetId\" class=\"more-item\" (mousedown)=\"onCopyInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Copy interaction preset\n </button>\n <button *ngIf=\"hasInteractionPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPasteInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Paste interaction preset\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"isLinkedSymbol\" class=\"more-item\" (mousedown)=\"onDetachSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link-break\"></i>\n Detach from symbol<ng-container *ngIf=\"linkedSymbolName\"> ({{ linkedSymbolName }})</ng-container>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"more-item more-item--resync\" (mousedown)=\"onResyncSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link\"></i>\n Re-link to symbol\n </button>\n <button class=\"more-item\" (mousedown)=\"onSaveAsBlock($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-bookmark\"></i>\n Save as reusable block\n </button>\n <button *ngIf=\"hasInteractions\" class=\"more-item more-item--play\" (mousedown)=\"onPlay($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-play\"></i>\n Play animations\n </button>\n <div class=\"more-divider\"></div>\n <ng-container *ngIf=\"!selectedNodeIsGlobal; else removeGlobalItem\">\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'before')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (Before Content)\n </button>\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'after')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (After Content)\n </button>\n </ng-container>\n <ng-template #removeGlobalItem>\n <button class=\"more-item\" (mousedown)=\"onRemoveGlobal($event)\">\n <i class=\"ph-thin ph-globe\"></i>\n Remove from Global\n </button>\n </ng-template>\n </div>\n\n <!-- Backdrop to close the more menu -->\n <div *ngIf=\"moreMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeMoreMenu()\">\n </div>\n\n <!-- Badge context menu \u2014 options differ by badge type -->\n <div *ngIf=\"badgeMenuVisible\" class=\"badge-context-menu\"\n [ngStyle]=\"{ top: badgeMenuPos.y + 'px', left: badgeMenuPos.x + 'px' }\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <ng-container *ngIf=\"badgeMenuType === 'style'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeCopy()\">\n <i class=\"ph-thin ph-copy\"></i>\n Copy preset\n </button>\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit preset\n </button>\n </ng-container>\n <ng-container *ngIf=\"badgeMenuType === 'interaction'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit in panel\n </button>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onBadgeRemoveInteraction()\">\n <i class=\"ph-thin ph-trash\"></i>\n Remove interaction\n </button>\n </ng-container>\n </div>\n <div *ngIf=\"badgeMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeBadgeMenu()\">\n </div>\n\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;position:absolute;inset:0;pointer-events:none;z-index:12;overflow:visible}.hi-outline,.hi-margin,.hi-padding{position:fixed;pointer-events:none;transition:none;box-sizing:border-box}.hi-outline{box-shadow:inset 0 0 0 1.5px #cb9090}.hi-margin{background:#f6b23361}.hi-padding{background:#60c38366}.select-outline{position:fixed;z-index:999;box-shadow:inset 0 0 0 1px #cb9090;pointer-events:none;transition:none;overflow:visible;will-change:transform;box-sizing:border-box}.select-toolbar{position:absolute;top:0;left:0;transform:translateY(-100%)}.select-toolbar.select-toolbar--inside{transform:translateY(0);border-radius:0 0 3px 3px}.select-toolbar{display:flex;align-items:center;background:#cb9090;border-radius:3px 3px 0 0;pointer-events:all;white-space:nowrap;overflow:visible}.select-toolbar .toolbar-name{padding:0 8px;font-size:11px;font-weight:500;color:#fff;max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:22px}.select-toolbar .toolbar-sep{width:1px;height:14px;background:#ffffff59;margin:0 2px;flex-shrink:0}.select-toolbar .toolbar-btn{display:flex;align-items:center;justify-content:center;width:24px;height:22px;padding:0;border:none;background:transparent;color:#fff;font-size:13px;cursor:pointer;transition:background .15s;flex-shrink:0}.select-toolbar .toolbar-btn:hover{background:#ffffff2e}.select-toolbar .toolbar-btn--danger:hover{background:#c8323259}.select-toolbar .toolbar-btn--drag-handle{cursor:grab}.select-toolbar .toolbar-btn--drag-handle:active{cursor:grabbing}.select-toolbar .toolbar-btn--symbol{width:auto;padding:0 7px;gap:4px;color:#fff;background:#f59e0b;border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--symbol:hover{background:#d97706}.select-toolbar .toolbar-btn--resync{width:auto;padding:0 7px;gap:4px;color:#fff;background:var(--iox-success-fill, #2E7D45);border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--resync:hover{background:color-mix(in srgb,var(--iox-success-fill, #2E7D45) 86%,#000)}.select-toolbar .toolbar-btn--add-slide,.select-toolbar .toolbar-btn--menu{width:auto;padding:0 7px;gap:4px;border-radius:3px}.select-toolbar .toolbar-btn--on{background:#ffffff3d}.select-toolbar .toolbar-btn .toolbar-btn__label{font-size:11px;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select-toolbar .toolbar-btn--more{border-radius:0 3px 0 0}.toolbar-more-dropdown{position:fixed;z-index:1000;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:200px;pointer-events:all}.toolbar-more-dropdown .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:8px 14px;border:none;background:transparent;font-size:13px;color:var(--p-text-color, #333);cursor:pointer;text-align:start;white-space:nowrap}.toolbar-more-dropdown .more-item i{font-size:14px}.toolbar-more-dropdown .more-item:hover{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item--danger{color:#c84040}.toolbar-more-dropdown .more-item--danger:hover{background:#c8404014}.toolbar-more-dropdown .more-item--play{color:var(--p-text-color, #333)}.toolbar-more-dropdown .more-item--resync{color:var(--iox-success-text, #1B5E32)}.toolbar-more-dropdown .more-item--resync:hover{background:var(--iox-success-bg, #E8F3EC)}.toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.toolbar-more-dropdown .more-item-submenu{position:relative}.toolbar-more-dropdown .more-item-submenu .more-item__chevron{margin-inline-start:auto;font-size:12px;opacity:.6}.toolbar-more-dropdown .more-item-submenu:hover>.more-item{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item-submenu .more-submenu-flyout{position:absolute;top:-4px;inset-inline-start:100%;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:180px;z-index:1001}.preset-badge{position:absolute;bottom:-26px;inset-inline-start:0;display:flex;align-items:center;gap:4px;pointer-events:none;white-space:nowrap}.preset-badge__item{display:flex;align-items:center;gap:5px;padding:3px 9px;background:#cb9090;color:#fff;font-size:11px;font-weight:500;border-radius:20px;pointer-events:all;cursor:pointer;box-shadow:0 2px 6px #0000002e;transition:background .15s,outline-color .15s;outline:2px solid transparent;outline-offset:2px}.preset-badge__item i{font-size:12px}.preset-badge__item:hover{background:#be7474}.preset-badge__item--active{outline-color:#ffffffd9}.preset-badge__item--interaction{background:#7a9ecb}.preset-badge__item--interaction:hover{background:#5d89c0}.preset-badge__item--kind{background:#8a3a72;cursor:default}.preset-badge__item--kind:hover{background:#8a3a72}.badge-context-menu{position:fixed;z-index:1001;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:160px;pointer-events:all}.badge-context-menu .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 14px;border:none;background:transparent;font-size:12px;color:#333;cursor:pointer;text-align:start;white-space:nowrap}.badge-context-menu .more-item:hover{background:var(--p-surface-50, #f9fafb)}.badge-context-menu .more-item i{font-size:13px;color:#888}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: IoxDraggableDirective, selector: "[ioxDraggable]", inputs: ["ioxDragData", "ioxDragSourceId", "ioxDragDisabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8204
8341
  }
8205
8342
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: OverlayComponent, decorators: [{
8206
8343
  type: Component,
8207
- args: [{ selector: 'app-overlay', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"overlay-root\">\n\n <!-- HOVER \u2014 Chrome DevTools-style rings (content area stays transparent) -->\n <ng-container *ngIf=\"hoverEntry\">\n <div class=\"hi-outline\" [ngStyle]=\"hiOutlineStyle\"></div>\n <div class=\"hi-margin\" [ngStyle]=\"hiMarginStyle\"></div>\n <div class=\"hi-padding\" [ngStyle]=\"hiPaddingStyle\"></div>\n </ng-container>\n\n <!-- SELECT \u2014 IOX pink outline + toolbar -->\n <div class=\"select-outline\" *ngIf=\"selectEntry\" [ngStyle]=\"selectOutlineStyle\">\n\n <!-- Preset badges container \u2014 below the outline, start-aligned -->\n <div class=\"preset-badge\" *ngIf=\"selectedRoleBadge || selectedPresetName || interactions.length\">\n <!-- A composite part (Card v2): its kind and role, read-only \u2014 what the layer tree's chip says. -->\n <div *ngIf=\"selectedRoleBadge\" class=\"preset-badge__item preset-badge__item--kind\" [title]=\"selectedRoleBadge\">\n <i [class]=\"selectedRoleIcon\" aria-hidden=\"true\"></i>\n <span>{{ selectedRoleBadge }}</span>\n </div>\n <div *ngIf=\"selectedPresetName\"\n class=\"preset-badge__item\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'style'\"\n title=\"Style preset: {{ selectedPresetName }} \u2014 click to edit, right-click to copy\"\n (mousedown)=\"onEditPreset($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'style')\">\n <i class=\"ph-fill ph-paint-bucket\"></i>\n <span>{{ selectedPresetName }}</span>\n </div>\n <div *ngFor=\"let ix of interactions\"\n class=\"preset-badge__item preset-badge__item--interaction\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'interaction'\"\n [title]=\"triggerLabel(ix.trigger) + ': ' + actionLabel(ix) + ' \u2014 click to edit, right-click to remove'\"\n (mousedown)=\"onEditInteractionPreset($event, ix)\"\n (click)=\"onBadgeClickSwallow($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'interaction', ix)\">\n <i [class]=\"triggerIcon(ix.trigger)\"></i>\n <span>{{ triggerLabel(ix.trigger) }}: {{ actionLabel(ix) }}</span>\n </div>\n </div>\n\n <div class=\"select-toolbar\" [class.select-toolbar--inside]=\"toolbarInside\" (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n\n <!-- Drag handle \u2014 grab here to move the selected element. A click-and-hold ANYWHERE\n on the element body would otherwise grab whatever nested child the pointer lands\n on; DragEngineService redirects any drag starting here to the selected node. -->\n <button *ngIf=\"selectEntry?.node\" class=\"toolbar-btn toolbar-btn--drag-handle\"\n ioxDraggable data-iox-drag-handle\n [ioxDragData]=\"selectEntry?.node\"\n [ioxDragSourceId]=\"dragHandleSourceId\"\n title=\"Drag to move\">\n <i class=\"ph-thin ph-dots-six-vertical\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Component name -->\n <span class=\"toolbar-name\">{{ toolbarName }}</span>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Quick actions -->\n <button *ngIf=\"isDialog\" class=\"toolbar-btn\"\n [title]=\"dialogDesignOpen ? 'Close the dialog (design)' : 'Open the dialog (design)'\"\n [attr.aria-label]=\"dialogDesignOpen ? 'Close the dialog for design' : 'Open the dialog for design'\"\n (mousedown)=\"onToggleDialogOpen($event)\">\n <i [class]=\"dialogDesignOpen ? 'ph-thin ph-eye-slash' : 'ph-thin ph-eye'\"></i>\n </button>\n <button *ngIf=\"isSliderContainer\" class=\"toolbar-btn toolbar-btn--add-slide\" title=\"Add slide\" (mousedown)=\"onAddSlide($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n <span class=\"toolbar-btn__label\">Add slide</span>\n </button>\n @if (canAddItem) {\n <button class=\"toolbar-btn toolbar-btn--add-slide\" [title]=\"addItemLabel\" (mousedown)=\"onAddItem($event)\">\n <i class=\"ph-thin ph-plus\" aria-hidden=\"true\"></i>\n <span class=\"toolbar-btn__label\">{{ addItemLabel }}</span>\n </button>\n }\n <button class=\"toolbar-btn\" title=\"Add an element here\" aria-label=\"Add an element here\" (mousedown)=\"onAddElement($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n </button>\n <button class=\"toolbar-btn\" title=\"Duplicate\" (mousedown)=\"onDuplicate($event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n <button *ngIf=\"hasInteractions\" class=\"toolbar-btn toolbar-btn--play\" title=\"Play animations\" (mousedown)=\"onPlay($event)\">\n <i class=\"ph-thin ph-play\"></i>\n </button>\n <button *ngIf=\"isLinkedSymbol\" class=\"toolbar-btn toolbar-btn--symbol\"\n [title]=\"(linkedSymbolName ? linkedSymbolName : 'Symbol') + ' \u2014 click to detach'\"\n (mousedown)=\"onDetachSymbol($event)\">\n <i class=\"ph-thin ph-link\"></i>\n <span class=\"toolbar-btn__label\">{{ linkedSymbolName || 'Symbol' }}</span>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"toolbar-btn toolbar-btn--resync\"\n title=\"Detached \u2014 click to re-link\"\n (mousedown)=\"onResyncSymbol($event)\">\n <i class=\"ph-thin ph-link-break\"></i>\n <span class=\"toolbar-btn__label\">Detached</span>\n </button>\n <button class=\"toolbar-btn toolbar-btn--danger\" title=\"Delete\" (mousedown)=\"onDelete($event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n <button class=\"toolbar-btn\" title=\"Select parent\" (mousedown)=\"onSelectParent($event)\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n </button>\n\n <!-- More menu trigger \u2014 opens a fixed-position dropdown at the cursor -->\n <button class=\"toolbar-btn toolbar-btn--more\" title=\"More actions\" (mousedown)=\"onToggleMore($event)\">\n <i class=\"ph-thin ph-dots-three\"></i>\n </button>\n </div>\n </div>\n\n <!-- Shared more/context menu \u2014 fixed-position, opened by \u22EF button or right-click -->\n <div *ngIf=\"moreMenuVisible\" class=\"toolbar-more-dropdown\" [ngStyle]=\"moreMenuStyle\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <button class=\"more-item\" (mousedown)=\"onSelectParent($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n Select parent\n </button>\n <button class=\"more-item\" (mousedown)=\"onDuplicate($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-copy\"></i>\n Duplicate\n </button>\n <div *ngIf=\"canWrap\" class=\"more-item-submenu\"\n (mouseenter)=\"wrapSubmenuOpen = true\" (mouseleave)=\"wrapSubmenuOpen = false\">\n <button class=\"more-item\" (mousedown)=\"$event.stopPropagation()\">\n <i class=\"ph-thin ph-selection-plus\"></i>\n Wrap in\n <i class=\"ph-thin ph-caret-right more-item__chevron\"></i>\n </button>\n <div *ngIf=\"wrapSubmenuOpen\" class=\"more-submenu-flyout\">\n <button *ngFor=\"let target of wrapTargets\" class=\"more-item\"\n (mousedown)=\"onWrap($event, target.type); closeMoreMenu()\">\n <i [class]=\"target.icon\"></i>\n {{ target.label }}\n </button>\n </div>\n </div>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onDelete($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-trash\"></i>\n Delete\n </button>\n <div class=\"more-divider\"></div>\n <button class=\"more-item\" (mousedown)=\"onCopyNode($event)\">\n <i class=\"ph-thin ph-scissors\"></i>\n Copy element\n </button>\n <button *ngIf=\"hasCopiedNode\" class=\"more-item\" (mousedown)=\"onPasteNode($event)\">\n <i class=\"ph-thin ph-clipboard\"></i>\n Paste element\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"selectEntry?.node?.stylePresetId\" class=\"more-item\" (mousedown)=\"onCopyPreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Copy style preset\n </button>\n <button *ngIf=\"hasPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPastePreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Paste style preset\n </button>\n <button *ngIf=\"selectEntry?.node?.interactionPresetId\" class=\"more-item\" (mousedown)=\"onCopyInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Copy interaction preset\n </button>\n <button *ngIf=\"hasInteractionPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPasteInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Paste interaction preset\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"isLinkedSymbol\" class=\"more-item\" (mousedown)=\"onDetachSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link-break\"></i>\n Detach from symbol<ng-container *ngIf=\"linkedSymbolName\"> ({{ linkedSymbolName }})</ng-container>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"more-item more-item--resync\" (mousedown)=\"onResyncSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link\"></i>\n Re-link to symbol\n </button>\n <button class=\"more-item\" (mousedown)=\"onSaveAsBlock($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-bookmark\"></i>\n Save as reusable block\n </button>\n <button *ngIf=\"hasInteractions\" class=\"more-item more-item--play\" (mousedown)=\"onPlay($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-play\"></i>\n Play animations\n </button>\n <div class=\"more-divider\"></div>\n <ng-container *ngIf=\"!selectedNodeIsGlobal; else removeGlobalItem\">\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'before')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (Before Content)\n </button>\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'after')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (After Content)\n </button>\n </ng-container>\n <ng-template #removeGlobalItem>\n <button class=\"more-item\" (mousedown)=\"onRemoveGlobal($event)\">\n <i class=\"ph-thin ph-globe\"></i>\n Remove from Global\n </button>\n </ng-template>\n </div>\n\n <!-- Backdrop to close the more menu -->\n <div *ngIf=\"moreMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeMoreMenu()\">\n </div>\n\n <!-- Badge context menu \u2014 options differ by badge type -->\n <div *ngIf=\"badgeMenuVisible\" class=\"badge-context-menu\"\n [ngStyle]=\"{ top: badgeMenuPos.y + 'px', left: badgeMenuPos.x + 'px' }\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <ng-container *ngIf=\"badgeMenuType === 'style'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeCopy()\">\n <i class=\"ph-thin ph-copy\"></i>\n Copy preset\n </button>\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit preset\n </button>\n </ng-container>\n <ng-container *ngIf=\"badgeMenuType === 'interaction'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit in panel\n </button>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onBadgeRemoveInteraction()\">\n <i class=\"ph-thin ph-trash\"></i>\n Remove interaction\n </button>\n </ng-container>\n </div>\n <div *ngIf=\"badgeMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeBadgeMenu()\">\n </div>\n\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;position:absolute;inset:0;pointer-events:none;z-index:12;overflow:visible}.hi-outline,.hi-margin,.hi-padding{position:fixed;pointer-events:none;transition:none;box-sizing:border-box}.hi-outline{box-shadow:inset 0 0 0 1.5px #cb9090}.hi-margin{background:#f6b23361}.hi-padding{background:#60c38366}.select-outline{position:fixed;z-index:999;box-shadow:inset 0 0 0 1px #cb9090;pointer-events:none;transition:none;overflow:visible;will-change:transform;box-sizing:border-box}.select-toolbar{position:absolute;top:0;left:0;transform:translateY(-100%)}.select-toolbar.select-toolbar--inside{transform:translateY(0);border-radius:0 0 3px 3px}.select-toolbar{display:flex;align-items:center;background:#cb9090;border-radius:3px 3px 0 0;pointer-events:all;white-space:nowrap;overflow:visible}.select-toolbar .toolbar-name{padding:0 8px;font-size:11px;font-weight:500;color:#fff;max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:22px}.select-toolbar .toolbar-sep{width:1px;height:14px;background:#ffffff59;margin:0 2px;flex-shrink:0}.select-toolbar .toolbar-btn{display:flex;align-items:center;justify-content:center;width:24px;height:22px;padding:0;border:none;background:transparent;color:#fff;font-size:13px;cursor:pointer;transition:background .15s;flex-shrink:0}.select-toolbar .toolbar-btn:hover{background:#ffffff2e}.select-toolbar .toolbar-btn--danger:hover{background:#c8323259}.select-toolbar .toolbar-btn--drag-handle{cursor:grab}.select-toolbar .toolbar-btn--drag-handle:active{cursor:grabbing}.select-toolbar .toolbar-btn--symbol{width:auto;padding:0 7px;gap:4px;color:#fff;background:#f59e0b;border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--symbol:hover{background:#d97706}.select-toolbar .toolbar-btn--resync{width:auto;padding:0 7px;gap:4px;color:#fff;background:var(--iox-success-fill, #2E7D45);border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--resync:hover{background:color-mix(in srgb,var(--iox-success-fill, #2E7D45) 86%,#000)}.select-toolbar .toolbar-btn--add-slide{width:auto;padding:0 7px;gap:4px;border-radius:3px}.select-toolbar .toolbar-btn .toolbar-btn__label{font-size:11px;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select-toolbar .toolbar-btn--more{border-radius:0 3px 0 0}.toolbar-more-dropdown{position:fixed;z-index:1000;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:200px;pointer-events:all}.toolbar-more-dropdown .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:8px 14px;border:none;background:transparent;font-size:13px;color:var(--p-text-color, #333);cursor:pointer;text-align:start;white-space:nowrap}.toolbar-more-dropdown .more-item i{font-size:14px}.toolbar-more-dropdown .more-item:hover{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item--danger{color:#c84040}.toolbar-more-dropdown .more-item--danger:hover{background:#c8404014}.toolbar-more-dropdown .more-item--play{color:var(--p-text-color, #333)}.toolbar-more-dropdown .more-item--resync{color:var(--iox-success-text, #1B5E32)}.toolbar-more-dropdown .more-item--resync:hover{background:var(--iox-success-bg, #E8F3EC)}.toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.toolbar-more-dropdown .more-item-submenu{position:relative}.toolbar-more-dropdown .more-item-submenu .more-item__chevron{margin-inline-start:auto;font-size:12px;opacity:.6}.toolbar-more-dropdown .more-item-submenu:hover>.more-item{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item-submenu .more-submenu-flyout{position:absolute;top:-4px;inset-inline-start:100%;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:180px;z-index:1001}.preset-badge{position:absolute;bottom:-26px;inset-inline-start:0;display:flex;align-items:center;gap:4px;pointer-events:none;white-space:nowrap}.preset-badge__item{display:flex;align-items:center;gap:5px;padding:3px 9px;background:#cb9090;color:#fff;font-size:11px;font-weight:500;border-radius:20px;pointer-events:all;cursor:pointer;box-shadow:0 2px 6px #0000002e;transition:background .15s,outline-color .15s;outline:2px solid transparent;outline-offset:2px}.preset-badge__item i{font-size:12px}.preset-badge__item:hover{background:#be7474}.preset-badge__item--active{outline-color:#ffffffd9}.preset-badge__item--interaction{background:#7a9ecb}.preset-badge__item--interaction:hover{background:#5d89c0}.preset-badge__item--kind{background:#8a3a72;cursor:default}.preset-badge__item--kind:hover{background:#8a3a72}.badge-context-menu{position:fixed;z-index:1001;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:160px;pointer-events:all}.badge-context-menu .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 14px;border:none;background:transparent;font-size:12px;color:#333;cursor:pointer;text-align:start;white-space:nowrap}.badge-context-menu .more-item:hover{background:var(--p-surface-50, #f9fafb)}.badge-context-menu .more-item i{font-size:13px;color:#888}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}\n"] }]
8344
+ args: [{ selector: 'app-overlay', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"overlay-root\">\n\n <!-- HOVER \u2014 Chrome DevTools-style rings (content area stays transparent) -->\n <ng-container *ngIf=\"hoverEntry\">\n <div class=\"hi-outline\" [ngStyle]=\"hiOutlineStyle\"></div>\n <div class=\"hi-margin\" [ngStyle]=\"hiMarginStyle\"></div>\n <div class=\"hi-padding\" [ngStyle]=\"hiPaddingStyle\"></div>\n </ng-container>\n\n <!-- SELECT \u2014 IOX pink outline + toolbar -->\n <div class=\"select-outline\" *ngIf=\"selectEntry\" [ngStyle]=\"selectOutlineStyle\">\n\n <!-- Preset badges container \u2014 below the outline, start-aligned -->\n <div class=\"preset-badge\" *ngIf=\"selectedRoleBadge || selectedPresetName || interactions.length\">\n <!-- A composite part (Card v2): its kind and role, read-only \u2014 what the layer tree's chip says. -->\n <div *ngIf=\"selectedRoleBadge\" class=\"preset-badge__item preset-badge__item--kind\" [title]=\"selectedRoleBadge\">\n <i [class]=\"selectedRoleIcon\" aria-hidden=\"true\"></i>\n <span>{{ selectedRoleBadge }}</span>\n </div>\n <div *ngIf=\"selectedPresetName\"\n class=\"preset-badge__item\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'style'\"\n title=\"Style preset: {{ selectedPresetName }} \u2014 click to edit, right-click to copy\"\n (mousedown)=\"onEditPreset($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'style')\">\n <i class=\"ph-fill ph-paint-bucket\"></i>\n <span>{{ selectedPresetName }}</span>\n </div>\n <div *ngFor=\"let ix of interactions\"\n class=\"preset-badge__item preset-badge__item--interaction\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'interaction'\"\n [title]=\"triggerLabel(ix.trigger) + ': ' + actionLabel(ix) + ' \u2014 click to edit, right-click to remove'\"\n (mousedown)=\"onEditInteractionPreset($event, ix)\"\n (click)=\"onBadgeClickSwallow($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'interaction', ix)\">\n <i [class]=\"triggerIcon(ix.trigger)\"></i>\n <span>{{ triggerLabel(ix.trigger) }}: {{ actionLabel(ix) }}</span>\n </div>\n </div>\n\n <div class=\"select-toolbar\" [class.select-toolbar--inside]=\"toolbarInside\" (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n\n <!-- Drag handle \u2014 grab here to move the selected element. A click-and-hold ANYWHERE\n on the element body would otherwise grab whatever nested child the pointer lands\n on; DragEngineService redirects any drag starting here to the selected node. -->\n <button *ngIf=\"selectEntry?.node\" class=\"toolbar-btn toolbar-btn--drag-handle\"\n ioxDraggable data-iox-drag-handle\n [ioxDragData]=\"selectEntry?.node\"\n [ioxDragSourceId]=\"dragHandleSourceId\"\n title=\"Drag to move\">\n <i class=\"ph-thin ph-dots-six-vertical\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Component name -->\n <span class=\"toolbar-name\">{{ toolbarName }}</span>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Quick actions -->\n @if (menuChip) {\n <!-- CC1.3: the phone menu's drawer, shown or hidden for design from anywhere in the navigation. -->\n <button class=\"toolbar-btn toolbar-btn--menu\" [class.toolbar-btn--on]=\"menuChipOpen\"\n [title]=\"menuChipTitle\" [attr.aria-label]=\"menuChipTitle\" [attr.aria-pressed]=\"menuChipOpen\"\n (mousedown)=\"onToggleMenuChip($event)\">\n <i [class]=\"menuChipOpen ? 'ph-thin ph-eye-slash' : 'ph-thin ph-eye'\" aria-hidden=\"true\"></i>\n <span class=\"toolbar-btn__label\">{{ menuChipLabel }}</span>\n </button>\n }\n <button *ngIf=\"isDialog\" class=\"toolbar-btn\"\n [title]=\"dialogDesignOpen ? 'Close the dialog (design)' : 'Open the dialog (design)'\"\n [attr.aria-label]=\"dialogDesignOpen ? 'Close the dialog for design' : 'Open the dialog for design'\"\n (mousedown)=\"onToggleDialogOpen($event)\">\n <i [class]=\"dialogDesignOpen ? 'ph-thin ph-eye-slash' : 'ph-thin ph-eye'\"></i>\n </button>\n <button *ngIf=\"isSliderContainer\" class=\"toolbar-btn toolbar-btn--add-slide\" title=\"Add slide\" (mousedown)=\"onAddSlide($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n <span class=\"toolbar-btn__label\">Add slide</span>\n </button>\n @if (canAddItem) {\n <button class=\"toolbar-btn toolbar-btn--add-slide\" [title]=\"addItemLabel\" (mousedown)=\"onAddItem($event)\">\n <i class=\"ph-thin ph-plus\" aria-hidden=\"true\"></i>\n <span class=\"toolbar-btn__label\">{{ addItemLabel }}</span>\n </button>\n }\n <button class=\"toolbar-btn\" title=\"Add an element here\" aria-label=\"Add an element here\" (mousedown)=\"onAddElement($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n </button>\n <button class=\"toolbar-btn\" title=\"Duplicate\" (mousedown)=\"onDuplicate($event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n <button *ngIf=\"hasInteractions\" class=\"toolbar-btn toolbar-btn--play\" title=\"Play animations\" (mousedown)=\"onPlay($event)\">\n <i class=\"ph-thin ph-play\"></i>\n </button>\n <button *ngIf=\"isLinkedSymbol\" class=\"toolbar-btn toolbar-btn--symbol\"\n [title]=\"(linkedSymbolName ? linkedSymbolName : 'Symbol') + ' \u2014 click to detach'\"\n (mousedown)=\"onDetachSymbol($event)\">\n <i class=\"ph-thin ph-link\"></i>\n <span class=\"toolbar-btn__label\">{{ linkedSymbolName || 'Symbol' }}</span>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"toolbar-btn toolbar-btn--resync\"\n title=\"Detached \u2014 click to re-link\"\n (mousedown)=\"onResyncSymbol($event)\">\n <i class=\"ph-thin ph-link-break\"></i>\n <span class=\"toolbar-btn__label\">Detached</span>\n </button>\n <button class=\"toolbar-btn toolbar-btn--danger\" title=\"Delete\" (mousedown)=\"onDelete($event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n <button class=\"toolbar-btn\" title=\"Select parent\" (mousedown)=\"onSelectParent($event)\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n </button>\n\n <!-- More menu trigger \u2014 opens a fixed-position dropdown at the cursor -->\n <button class=\"toolbar-btn toolbar-btn--more\" title=\"More actions\" (mousedown)=\"onToggleMore($event)\">\n <i class=\"ph-thin ph-dots-three\"></i>\n </button>\n </div>\n </div>\n\n <!-- Shared more/context menu \u2014 fixed-position, opened by \u22EF button or right-click -->\n <div *ngIf=\"moreMenuVisible\" class=\"toolbar-more-dropdown\" [ngStyle]=\"moreMenuStyle\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <button class=\"more-item\" (mousedown)=\"onSelectParent($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n Select parent\n </button>\n <button class=\"more-item\" (mousedown)=\"onDuplicate($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-copy\"></i>\n Duplicate\n </button>\n <div *ngIf=\"canWrap\" class=\"more-item-submenu\"\n (mouseenter)=\"wrapSubmenuOpen = true\" (mouseleave)=\"wrapSubmenuOpen = false\">\n <button class=\"more-item\" (mousedown)=\"$event.stopPropagation()\">\n <i class=\"ph-thin ph-selection-plus\"></i>\n Wrap in\n <i class=\"ph-thin ph-caret-right more-item__chevron\"></i>\n </button>\n <div *ngIf=\"wrapSubmenuOpen\" class=\"more-submenu-flyout\">\n <button *ngFor=\"let target of wrapTargets\" class=\"more-item\"\n (mousedown)=\"onWrap($event, target.type); closeMoreMenu()\">\n <i [class]=\"target.icon\"></i>\n {{ target.label }}\n </button>\n </div>\n </div>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onDelete($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-trash\"></i>\n Delete\n </button>\n <div class=\"more-divider\"></div>\n <button class=\"more-item\" (mousedown)=\"onCopyNode($event)\">\n <i class=\"ph-thin ph-scissors\"></i>\n Copy element\n </button>\n <button *ngIf=\"hasCopiedNode\" class=\"more-item\" (mousedown)=\"onPasteNode($event)\">\n <i class=\"ph-thin ph-clipboard\"></i>\n Paste element\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"selectEntry?.node?.stylePresetId\" class=\"more-item\" (mousedown)=\"onCopyPreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Copy style preset\n </button>\n <button *ngIf=\"hasPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPastePreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Paste style preset\n </button>\n <button *ngIf=\"selectEntry?.node?.interactionPresetId\" class=\"more-item\" (mousedown)=\"onCopyInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Copy interaction preset\n </button>\n <button *ngIf=\"hasInteractionPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPasteInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Paste interaction preset\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"isLinkedSymbol\" class=\"more-item\" (mousedown)=\"onDetachSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link-break\"></i>\n Detach from symbol<ng-container *ngIf=\"linkedSymbolName\"> ({{ linkedSymbolName }})</ng-container>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"more-item more-item--resync\" (mousedown)=\"onResyncSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link\"></i>\n Re-link to symbol\n </button>\n <button class=\"more-item\" (mousedown)=\"onSaveAsBlock($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-bookmark\"></i>\n Save as reusable block\n </button>\n <button *ngIf=\"hasInteractions\" class=\"more-item more-item--play\" (mousedown)=\"onPlay($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-play\"></i>\n Play animations\n </button>\n <div class=\"more-divider\"></div>\n <ng-container *ngIf=\"!selectedNodeIsGlobal; else removeGlobalItem\">\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'before')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (Before Content)\n </button>\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'after')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (After Content)\n </button>\n </ng-container>\n <ng-template #removeGlobalItem>\n <button class=\"more-item\" (mousedown)=\"onRemoveGlobal($event)\">\n <i class=\"ph-thin ph-globe\"></i>\n Remove from Global\n </button>\n </ng-template>\n </div>\n\n <!-- Backdrop to close the more menu -->\n <div *ngIf=\"moreMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeMoreMenu()\">\n </div>\n\n <!-- Badge context menu \u2014 options differ by badge type -->\n <div *ngIf=\"badgeMenuVisible\" class=\"badge-context-menu\"\n [ngStyle]=\"{ top: badgeMenuPos.y + 'px', left: badgeMenuPos.x + 'px' }\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <ng-container *ngIf=\"badgeMenuType === 'style'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeCopy()\">\n <i class=\"ph-thin ph-copy\"></i>\n Copy preset\n </button>\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit preset\n </button>\n </ng-container>\n <ng-container *ngIf=\"badgeMenuType === 'interaction'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit in panel\n </button>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onBadgeRemoveInteraction()\">\n <i class=\"ph-thin ph-trash\"></i>\n Remove interaction\n </button>\n </ng-container>\n </div>\n <div *ngIf=\"badgeMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeBadgeMenu()\">\n </div>\n\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;position:absolute;inset:0;pointer-events:none;z-index:12;overflow:visible}.hi-outline,.hi-margin,.hi-padding{position:fixed;pointer-events:none;transition:none;box-sizing:border-box}.hi-outline{box-shadow:inset 0 0 0 1.5px #cb9090}.hi-margin{background:#f6b23361}.hi-padding{background:#60c38366}.select-outline{position:fixed;z-index:999;box-shadow:inset 0 0 0 1px #cb9090;pointer-events:none;transition:none;overflow:visible;will-change:transform;box-sizing:border-box}.select-toolbar{position:absolute;top:0;left:0;transform:translateY(-100%)}.select-toolbar.select-toolbar--inside{transform:translateY(0);border-radius:0 0 3px 3px}.select-toolbar{display:flex;align-items:center;background:#cb9090;border-radius:3px 3px 0 0;pointer-events:all;white-space:nowrap;overflow:visible}.select-toolbar .toolbar-name{padding:0 8px;font-size:11px;font-weight:500;color:#fff;max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:22px}.select-toolbar .toolbar-sep{width:1px;height:14px;background:#ffffff59;margin:0 2px;flex-shrink:0}.select-toolbar .toolbar-btn{display:flex;align-items:center;justify-content:center;width:24px;height:22px;padding:0;border:none;background:transparent;color:#fff;font-size:13px;cursor:pointer;transition:background .15s;flex-shrink:0}.select-toolbar .toolbar-btn:hover{background:#ffffff2e}.select-toolbar .toolbar-btn--danger:hover{background:#c8323259}.select-toolbar .toolbar-btn--drag-handle{cursor:grab}.select-toolbar .toolbar-btn--drag-handle:active{cursor:grabbing}.select-toolbar .toolbar-btn--symbol{width:auto;padding:0 7px;gap:4px;color:#fff;background:#f59e0b;border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--symbol:hover{background:#d97706}.select-toolbar .toolbar-btn--resync{width:auto;padding:0 7px;gap:4px;color:#fff;background:var(--iox-success-fill, #2E7D45);border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--resync:hover{background:color-mix(in srgb,var(--iox-success-fill, #2E7D45) 86%,#000)}.select-toolbar .toolbar-btn--add-slide,.select-toolbar .toolbar-btn--menu{width:auto;padding:0 7px;gap:4px;border-radius:3px}.select-toolbar .toolbar-btn--on{background:#ffffff3d}.select-toolbar .toolbar-btn .toolbar-btn__label{font-size:11px;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select-toolbar .toolbar-btn--more{border-radius:0 3px 0 0}.toolbar-more-dropdown{position:fixed;z-index:1000;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:200px;pointer-events:all}.toolbar-more-dropdown .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:8px 14px;border:none;background:transparent;font-size:13px;color:var(--p-text-color, #333);cursor:pointer;text-align:start;white-space:nowrap}.toolbar-more-dropdown .more-item i{font-size:14px}.toolbar-more-dropdown .more-item:hover{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item--danger{color:#c84040}.toolbar-more-dropdown .more-item--danger:hover{background:#c8404014}.toolbar-more-dropdown .more-item--play{color:var(--p-text-color, #333)}.toolbar-more-dropdown .more-item--resync{color:var(--iox-success-text, #1B5E32)}.toolbar-more-dropdown .more-item--resync:hover{background:var(--iox-success-bg, #E8F3EC)}.toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.toolbar-more-dropdown .more-item-submenu{position:relative}.toolbar-more-dropdown .more-item-submenu .more-item__chevron{margin-inline-start:auto;font-size:12px;opacity:.6}.toolbar-more-dropdown .more-item-submenu:hover>.more-item{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item-submenu .more-submenu-flyout{position:absolute;top:-4px;inset-inline-start:100%;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:180px;z-index:1001}.preset-badge{position:absolute;bottom:-26px;inset-inline-start:0;display:flex;align-items:center;gap:4px;pointer-events:none;white-space:nowrap}.preset-badge__item{display:flex;align-items:center;gap:5px;padding:3px 9px;background:#cb9090;color:#fff;font-size:11px;font-weight:500;border-radius:20px;pointer-events:all;cursor:pointer;box-shadow:0 2px 6px #0000002e;transition:background .15s,outline-color .15s;outline:2px solid transparent;outline-offset:2px}.preset-badge__item i{font-size:12px}.preset-badge__item:hover{background:#be7474}.preset-badge__item--active{outline-color:#ffffffd9}.preset-badge__item--interaction{background:#7a9ecb}.preset-badge__item--interaction:hover{background:#5d89c0}.preset-badge__item--kind{background:#8a3a72;cursor:default}.preset-badge__item--kind:hover{background:#8a3a72}.badge-context-menu{position:fixed;z-index:1001;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:160px;pointer-events:all}.badge-context-menu .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 14px;border:none;background:transparent;font-size:12px;color:#333;cursor:pointer;text-align:start;white-space:nowrap}.badge-context-menu .more-item:hover{background:var(--p-surface-50, #f9fafb)}.badge-context-menu .more-item i{font-size:13px;color:#888}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}\n"] }]
8208
8345
  }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1$1.ComponentInstanceRegistryService }, { type: OverlayService }, { type: ViewportService }, { type: PresetRegistryService }, { type: SymbolRegistryService }, { type: InteractionPresetRegistryService }, { type: InteractionEngineService }, { type: BuilderClipboardService }, { type: StyleRegistryService }, { type: PanelEventService }, { type: i0.ChangeDetectorRef }, { type: DragEngineService }, { type: undefined, decorators: [{
8209
8346
  type: Optional
8210
8347
  }, {
8211
8348
  type: Inject,
8212
8349
  args: [IOX_BUILDER_LABELS]
8350
+ }] }, { type: CanvasDesignStateService, decorators: [{
8351
+ type: Optional
8213
8352
  }] }], propDecorators: { toolbarAction: [{
8214
8353
  type: Output
8215
8354
  }] } });
@@ -9204,8 +9343,9 @@ class BuilderComponent {
9204
9343
  set selectedPath(path) {
9205
9344
  this._selectedPath = path;
9206
9345
  this.formStateService.setTarget(nearestFormNode(path));
9207
- // R2 (CC1): a part hidden at rest that the selection sits in (a closed drawer) shows while selected.
9208
- this.canvasDesignState.setSelectionPath(path);
9346
+ // R2 (CC1): a part hidden at rest that the selection sits in (a closed drawer) shows while selected; the
9347
+ // globals let it name the phone menu the selection belongs to (CC1.3: the Menu chip, Bindings ▸ Phone menu).
9348
+ this.canvasDesignState.setSelectionPath(path, this.globalElements);
9209
9349
  }
9210
9350
  // Type-safe event forwarding for toolbar outputs
9211
9351
  handleToolbarModeChange(mode) {
@@ -9508,6 +9648,8 @@ class BuilderComponent {
9508
9648
  }
9509
9649
  if (changes['globalElements']) {
9510
9650
  this.refreshCanvasBarReserve();
9651
+ // A phone-menu edit (Drawer · Bottom bar · Both) adds or removes the drawer: the selection's menu follows.
9652
+ this.canvasDesignState.setSelectionPath(this._selectedPath, this.globalElements);
9511
9653
  // The *ngIf on the global overlay renders after this hook — defer so
9512
9654
  // globalOverlayRef is in the DOM before we try to set CSS vars on it.
9513
9655
  setTimeout(() => this.updatePreviewVh());
@@ -11351,7 +11493,14 @@ class BuilderDialogComponent {
11351
11493
  this.designOpen = false;
11352
11494
  this.cdr.markForCheck();
11353
11495
  }
11354
- openRuntime() { this.runtimeOpen = true; this.dismissed = false; this.recompute(); }
11496
+ /** Opened by an action (or the eye): the design state hears it too, so the Phone menu's preview and the Menu chip
11497
+ * say "open" whichever way it opened (CC1.3). */
11498
+ openRuntime() {
11499
+ this.runtimeOpen = true;
11500
+ this.dismissed = false;
11501
+ this.recompute();
11502
+ this.designState?.markOpened(this.nodeId);
11503
+ }
11355
11504
  closeRuntime() {
11356
11505
  // A selection INSIDE the dialog (its Close, picked to style it) would be left on an element about to leave
11357
11506
  // the DOM — the selection chrome drawn at the viewport's corner (Doron's live test). It moves to the
@@ -14414,5 +14563,5 @@ class BuilderSpacerComponentConfig extends ComponentConfig {
14414
14563
  * Generated bundle index. Do not edit.
14415
14564
  */
14416
14565
 
14417
- export { ACTION_TYPE_OPTIONS, AuditCode, AuditPanelComponent, AuditSeverity, BODY_CRUMB_LABEL, BOUND_ICON, BREAKPOINT_PRESENTATION, BUILDER_CANVAS_CONTAINER, BUILDER_CHROME_EN, BUILDER_FONT_LINK_ATTR, BUILDER_TOKEN_SCOPE_CLASS, BackgroundGroupStyleConfig, BorderGroupStyleConfig, BreadcrumbBarComponent, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderClipboardService, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDataSourceService, BuilderDialogComponent, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderHistoryService, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderListComponentConfig, BuilderListItemComponentConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, BusinessSpecimenView, ButtonBlockComponentConfig, CANVAS_EMPTY_IMAGE_LABEL_EN, CANVAS_EMPTY_IMAGE_LABEL_KEY, CANVAS_ROOT_RESET_CSS, COMPOSITE_PRESETS, CanvasDesignStateService, CanvasShowState, CardComponentConfig, ChildLayoutGroupStyleConfig, ComponentConfig, ComponentRegistryService, CompositeCanvasService, CompositePaletteGroup, CompositePresetId, DEFAULT_ESSENTIAL_TRAITS, DESCRIPTOR_MAX_LENGTH, DRAG_HANDLE_ATTR, DROP_REFUSED_CLASS, DataSourceRegistryService, DataSourceType, DialogComponentConfig, DimensionsGroupStyleConfig, DragEngineService, EASING_OPTIONS, EDITOR_CHROME_ATTRIBUTE, ESSENTIAL_TRAITS_BY_TYPE, EffectsGroupStyleConfig, FIELD_KIND_PRESETS, FIELD_PARTS, FORM_STATE_BLOCK_TYPES, FORM_TYPE, FieldComponentConfig, FieldGroupComponentConfig, FormComponentConfig, FormErrorComponentConfig, FormStateService, FormSuccessComponentConfig, GLOBALS_AFTER_CLASS, GalleryConfig, GlobalCanvasLayer, GroupStyleConfig, HIDDEN_AT_REST_LABEL_KEY, HIDDEN_AT_REST_ROLES, HIDDEN_AT_REST_TYPES, INSERT_REFUSAL_LABEL_KEYS, INTERACTION_STATES, INVERSE_ACTION, IOX_BUILDER_CANVAS, IOX_BUILDER_LABELS, IOX_CONTENT_TYPE_LABELS, IOX_DATA_SOURCE_ENDPOINTS, InsertRefusal, InteractionEngineService, InteractionPresetRegistryService, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LAYOUT_PRESETS, LayerTreeComponent, LayoutGroupStyleConfig, ListGroupStyleConfig, NodeAction, OverlayComponent, OverlayService, PAGE_TRANSITION_EASING_OPTIONS, PALETTE_PRESET_DEFS, PanelChildComponent, PanelComponent, PanelEventService, PanelEventTypes, PanelTypes, PositionGroupStyleConfig, PresetRegistryService, RELATIONAL_STATES, RELATIONAL_STATE_BASE, REPEATER_SOURCE_PROP, REPEATER_TYPE, REVEALED_WHILE_SELECTED_ROLES, ROOT_ESCAPE_PX, ROUTE_ANIMATION_OPTIONS, RenderDirective, RepeaterComponentConfig, RootZone, SCREEN_WIDTH_OPTIONS, SILENT_REFUSALS, STRUCTURAL_STATES, SUPPORTED_STATES, SectionComponent, SectionComponentConfig, SelectionReveal, SizeGroupStyleConfig, SliderContainerComponent, SliderContainerConfig, SliderSlideComponent, SliderSlideConfig, SpacingGroupStyleConfig, StructureFix, StyleCategory, StyleRegistryService, TraitConfig as StyleTraitConfig, SubmitButtonComponentConfig, SymbolRegistryService, TARGETED_STATES, TARGETED_STATE_BASE, TOGGLE_PART_ROLES, TRIGGER_OPTIONS, TextBlockComponentConfig, ToolbarAction, ToolbarComponent, TraitConfig, TraitInputType, TypographyGroupStyleConfig, UNITS_ALL, UNITS_DEG, UNITS_FIXED, UNITS_NO_VW, VALIDATION_STATES, VALIDATION_STATE_CLASS, VideoConfig, ViewportService, ZOOM_OPTIONS, arrayItemSchemaFields, arraySchemaFields, auditNodes, bindingLabel, bindingLabels, buildBusinessSpecimen, buildCompositePreset, buildConsentPreset, buildElementStyleSpecimen, buildFieldKindPreset, buildFlavorSpecimen, buildFormPreset, buildFullStyleTraits, buildLayoutPreset, buildPalettePreset, buildPresetStyleTraits, builderCompositeFactory, canFluidise, canvasEmptyImageLabel, canvasHostDisplay, collapseColumnsProps, columnCountOf, compositeStructureFindings, defaultBuilderLabels, defaultPageSettings, deleteTabPair, displayTriggerOf, dropChildren, dropTargetLabel, duplicateTabPair, escapesRoot, essentialTraitsFor, findNodeLocation, findParentOf, flattenLayerTree, flattenSchemaFields, fluidiseProps, generateNodeId, globalCanvasLayer, hiddenAtBase, hiddenUntilItemOn, insertRefusal, insertRefusalLabel, interactionTargets, isHiddenAt, isHiddenAtRest, isPinnedGlobal, isSpecimen, itemsOnAtRest, markSpecimen, matchesControlSearch, nearestFormNode, neverShown, nodeAncestorPath, nodeAncestorPathInEither, nodeDescriptor, nodeStyleMap, overlayGlobals, pathToNode, refreshSubtree, regenerateNodeIds, removalRefusal, reorderProps, repeaterSourceAlias, repeaterSubLabel, resolveInsertTarget, resolveTraitControllerType, resolveTraitOptions, retypeNode, rootEscapeBand, rootZone, selectionRevealOf, setStyleTrait, setTrait, shortDescriptor, shownBeforeControl, sourceContentType, sourceTypeLabel, stackChildrenProps, summarise, syncEmptyImagePlaceholder, syncNodeDesign, syncNodeInputs, tabPairLabel, tabsRootForPart, textNode, upsertNodeStyles, visibilityProps, walkNodes, wrapNode };
14566
+ export { ACTION_TYPE_OPTIONS, AuditCode, AuditPanelComponent, AuditSeverity, BODY_CRUMB_LABEL, BOUND_ICON, BREAKPOINT_PRESENTATION, BUILDER_CANVAS_CONTAINER, BUILDER_CHROME_EN, BUILDER_FONT_LINK_ATTR, BUILDER_TOKEN_SCOPE_CLASS, BackgroundGroupStyleConfig, BorderGroupStyleConfig, BreadcrumbBarComponent, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderClipboardService, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDataSourceService, BuilderDialogComponent, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderHistoryService, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderListComponentConfig, BuilderListItemComponentConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, BusinessSpecimenView, ButtonBlockComponentConfig, CANVAS_EMPTY_IMAGE_LABEL_EN, CANVAS_EMPTY_IMAGE_LABEL_KEY, CANVAS_ROOT_RESET_CSS, COMPOSITE_PRESETS, CanvasDesignStateService, CanvasShowState, CardComponentConfig, ChildLayoutGroupStyleConfig, ComponentConfig, ComponentRegistryService, CompositeCanvasService, CompositePaletteGroup, CompositePresetId, DEFAULT_ESSENTIAL_TRAITS, DESCRIPTOR_MAX_LENGTH, DRAG_HANDLE_ATTR, DROP_REFUSED_CLASS, DataSourceRegistryService, DataSourceType, DialogComponentConfig, DimensionsGroupStyleConfig, DragEngineService, EASING_OPTIONS, EDITOR_CHROME_ATTRIBUTE, ESSENTIAL_TRAITS_BY_TYPE, EffectsGroupStyleConfig, FIELD_KIND_PRESETS, FIELD_PARTS, FORM_STATE_BLOCK_TYPES, FORM_TYPE, FieldComponentConfig, FieldGroupComponentConfig, FormComponentConfig, FormErrorComponentConfig, FormStateService, FormSuccessComponentConfig, GLOBALS_AFTER_CLASS, GalleryConfig, GlobalCanvasLayer, GroupStyleConfig, HIDDEN_AT_REST_LABEL_KEY, HIDDEN_AT_REST_ROLES, HIDDEN_AT_REST_TYPES, INSERT_REFUSAL_LABEL_KEYS, INTERACTION_STATES, INVERSE_ACTION, IOX_BUILDER_CANVAS, IOX_BUILDER_LABELS, IOX_CONTENT_TYPE_LABELS, IOX_DATA_SOURCE_ENDPOINTS, InsertRefusal, InteractionEngineService, InteractionPresetRegistryService, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LAYOUT_PRESETS, LayerTreeComponent, LayoutGroupStyleConfig, ListGroupStyleConfig, NodeAction, OverlayComponent, OverlayService, PAGE_TRANSITION_EASING_OPTIONS, PALETTE_PRESET_DEFS, PanelChildComponent, PanelComponent, PanelEventService, PanelEventTypes, PanelTypes, PhoneMenuOpenerAction, PositionGroupStyleConfig, PresetRegistryService, RELATIONAL_STATES, RELATIONAL_STATE_BASE, REPEATER_SOURCE_PROP, REPEATER_TYPE, REVEALED_WHILE_SELECTED_ROLES, ROOT_ESCAPE_PX, ROUTE_ANIMATION_OPTIONS, RenderDirective, RepeaterComponentConfig, RootZone, SCREEN_WIDTH_OPTIONS, SILENT_REFUSALS, STRUCTURAL_STATES, SUPPORTED_STATES, SectionComponent, SectionComponentConfig, SelectionReveal, SizeGroupStyleConfig, SliderContainerComponent, SliderContainerConfig, SliderSlideComponent, SliderSlideConfig, SpacingGroupStyleConfig, StructureFix, StyleCategory, StyleRegistryService, TraitConfig as StyleTraitConfig, SubmitButtonComponentConfig, SymbolRegistryService, TARGETED_STATES, TARGETED_STATE_BASE, TOGGLE_PART_ROLES, TRIGGER_OPTIONS, TextBlockComponentConfig, ToolbarAction, ToolbarComponent, TraitConfig, TraitInputType, TypographyGroupStyleConfig, UNITS_ALL, UNITS_DEG, UNITS_FIXED, UNITS_NO_VW, VALIDATION_STATES, VALIDATION_STATE_CLASS, VideoConfig, ViewportService, ZOOM_OPTIONS, arrayItemSchemaFields, arraySchemaFields, auditNodes, bindingLabel, bindingLabels, buildBusinessSpecimen, buildCompositePreset, buildConsentPreset, buildElementStyleSpecimen, buildFieldKindPreset, buildFlavorSpecimen, buildFormPreset, buildFullStyleTraits, buildLayoutPreset, buildPalettePreset, buildPresetStyleTraits, builderCompositeFactory, canFluidise, canvasEmptyImageLabel, canvasHostDisplay, collapseColumnsProps, columnCountOf, compositeStructureFindings, defaultBuilderLabels, defaultPageSettings, deleteTabPair, displayTriggerOf, dropChildren, dropTargetLabel, duplicateTabPair, escapesRoot, essentialTraitsFor, findNodeLocation, findParentOf, flattenLayerTree, flattenSchemaFields, fluidiseProps, generateNodeId, globalCanvasLayer, hiddenAtBase, hiddenUntilItemOn, inPhoneMenuContext, insertRefusal, insertRefusalLabel, interactionTargets, isHiddenAt, isHiddenAtRest, isPhoneMenuOpener, isPinnedGlobal, isSpecimen, itemsOnAtRest, markSpecimen, matchesControlSearch, nearestFormNode, neverShown, nodeAncestorPath, nodeAncestorPathInEither, nodeDescriptor, nodeStyleMap, overlayGlobals, pathToNode, phoneMenuOf, phoneMenuShowsAt, refreshSubtree, regenerateNodeIds, removalRefusal, reorderProps, repeaterSourceAlias, repeaterSubLabel, resolveInsertTarget, resolveTraitControllerType, resolveTraitOptions, retypeNode, rootEscapeBand, rootZone, selectionRevealOf, setOverlayPreview, setStyleTrait, setTrait, shortDescriptor, shownBeforeControl, sourceContentType, sourceTypeLabel, stackChildrenProps, summarise, syncEmptyImagePlaceholder, syncNodeDesign, syncNodeInputs, tabPairLabel, tabsRootForPart, textNode, upsertNodeStyles, visibilityProps, walkNodes, wrapNode };
14418
14567
  //# sourceMappingURL=vectoriox-iox-builder.mjs.map