@vectoriox/iox-builder 4.32.1 → 4.32.3

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.
@@ -920,6 +920,9 @@ var PanelEventTypes;
920
920
  /** Insert prebuilt node(s) as GLOBAL elements (data = ComponentNode[]) — the consent preset's
921
921
  * path (D-C5: site-wide by construction). Mirrors the MakeGlobal toolbar action. */
922
922
  PanelEventTypes["INSERT_GLOBAL"] = "insertglobal";
923
+ /** A click on a compound component's PART (Field label/control/help/…) — the style panel
924
+ * activates that part (data = { part }). Doron 2026-10-10: "both shall be selectable". */
925
+ PanelEventTypes["PART_SELECT"] = "partselect";
923
926
  /** A panel wants to select a NODE it already has a reference to (e.g. the Form's nested field
924
927
  * list). Carries `{ node }`. `OverlayService.setSelect()` alone only updates the overlay's own
925
928
  * visual state — `selectedItem`/`selectedPath` (breadcrumb) and every other panel's idea of
@@ -10060,25 +10063,34 @@ function button(label, createConfig, interaction, styles = {}) {
10060
10063
  return btn;
10061
10064
  }
10062
10065
  /** The C1/C2 board button voices — Swiss by fallback, the brand's the moment tokens seed. */
10066
+ // width:'auto' + flexShrink:'0' on every voice: a consent button never stretches to its row's
10067
+ // height nor shrinks until its label wraps — both happened on the canvas (Rule 0, 2026-10-10).
10063
10068
  const SOLID = {
10064
10069
  backgroundColor: TOKEN$1('brand-500', '#1f1d1b'), color: TOKEN$1('brandInk', '#ffffff'),
10065
10070
  fontSize: '12px', fontWeight: '600', padding: '9px 16px',
10066
10071
  borderRadius: TOKEN$1('radius-control', '4px'),
10072
+ width: 'auto', flexShrink: '0',
10067
10073
  };
10068
10074
  const OUTLINED = {
10069
10075
  backgroundColor: 'transparent', color: TOKEN$1('ink', '#1f1d1b'),
10070
10076
  borderWidth: '1px', borderStyle: 'solid', borderColor: TOKEN$1('ink', '#1f1d1b'),
10071
10077
  fontSize: '12px', fontWeight: '600', padding: '8px 16px',
10072
10078
  borderRadius: TOKEN$1('radius-control', '4px'),
10079
+ width: 'auto', flexShrink: '0',
10073
10080
  };
10074
10081
  const QUIET = {
10075
10082
  backgroundColor: 'transparent', color: TOKEN$1('inkMuted', '#4a453f'),
10076
10083
  fontSize: '11px', fontWeight: '400', padding: '2px 4px', textDecoration: 'underline',
10084
+ width: 'auto', flexShrink: '0',
10077
10085
  };
10078
10086
  function row(createConfig, styles, children) {
10079
10087
  const container = createConfig('Container');
10080
10088
  if (!container || children.some(c => !c))
10081
10089
  return null;
10090
+ // The Container config defaults (minHeight 200px — the canvas droppability affordance) are
10091
+ // serialized with the node, so a preset box must OWN its height or every card ships 200px
10092
+ // tall with dead space (Rule 0 catch, 2026-10-10). Callers may still override.
10093
+ setStyleTrait(container, 'minHeight', 'auto');
10082
10094
  for (const [prop, value] of Object.entries(styles))
10083
10095
  setStyleTrait(container, prop, value);
10084
10096
  container.children = children;
@@ -10108,7 +10120,9 @@ function buildConsentPreset(createConfig) {
10108
10120
  const heading = text$1('Cookies on this site', { fontSize: '13px', fontWeight: '600', color: TOKEN$1('ink', '#1f1d1b') }, createConfig);
10109
10121
  // The first layer NAMES the three categories (plan §7) — the board does it in the copy.
10110
10122
  const body = text$1('We use analytics and marketing cookies only if you allow them. Necessary ones always run.', { fontSize: '11px', color: TOKEN$1('inkMuted', '#4a453f'), lineHeight: '1.5', maxWidth: '330px' }, createConfig);
10111
- const textCol = row(createConfig, { display: 'flex', flexDirection: 'column', gap: '4px', flexGrow: '1' }, [heading, body]);
10123
+ // width:'auto' throughout — the Container default is 100%, and two 100%-wide columns
10124
+ // cannot share the bar's row (they wrap into a stack; Rule 0 catch, 2026-10-10).
10125
+ const textCol = row(createConfig, { display: 'flex', flexDirection: 'column', gap: '4px', flexGrow: '1', width: 'auto' }, [heading, body]);
10112
10126
  const accept = button('Accept all', createConfig, click([
10113
10127
  { type: 'grantConsent' },
10114
10128
  { type: 'closeDialog', target: banner.id },
@@ -10120,9 +10134,9 @@ function buildConsentPreset(createConfig) {
10120
10134
  const prefs = button('Preferences', createConfig, click([
10121
10135
  { type: 'openConsentPreferences', target: preferences.id },
10122
10136
  ]), QUIET);
10123
- const acceptRejectRow = row(createConfig, { display: 'flex', gap: '7px' }, [accept, reject]);
10124
- const buttonsCol = row(createConfig, { display: 'flex', flexDirection: 'column', gap: '7px', alignItems: 'center' }, [acceptRejectRow, prefs]);
10125
- const bannerRow = row(createConfig, { display: 'flex', gap: '18px', alignItems: 'flex-start', flexWrap: 'wrap' }, [textCol, buttonsCol]);
10137
+ const acceptRejectRow = row(createConfig, { display: 'flex', gap: '7px', alignItems: 'center', width: 'auto' }, [accept, reject]);
10138
+ const buttonsCol = row(createConfig, { display: 'flex', flexDirection: 'column', gap: '7px', alignItems: 'center', width: 'auto', flexShrink: '0' }, [acceptRejectRow, prefs]);
10139
+ const bannerRow = row(createConfig, { display: 'flex', gap: '18px', alignItems: 'center', flexWrap: 'wrap' }, [textCol, buttonsCol]);
10126
10140
  if (!bannerRow)
10127
10141
  return null;
10128
10142
  banner.children = [bannerRow];
@@ -10144,11 +10158,12 @@ function buildConsentPreset(createConfig) {
10144
10158
  };
10145
10159
  const nameText = (s) => text$1(s, { fontSize: '13px', fontWeight: '600', color: TOKEN$1('ink', '#1f1d1b') }, createConfig);
10146
10160
  const descText = (s) => text$1(s, { fontSize: '11px', color: TOKEN$1('inkMuted', '#6b6560'), lineHeight: '1.5' }, createConfig);
10147
- const textColOf = (name, desc) => row(createConfig, { display: 'flex', flexDirection: 'column', gap: '2px', flexGrow: '1' }, [nameText(name), descText(desc)]);
10161
+ const textColOf = (name, desc) => row(createConfig, { display: 'flex', flexDirection: 'column', gap: '2px', flexGrow: '1', width: 'auto' }, [nameText(name), descText(desc)]);
10148
10162
  const alwaysOn = text$1('ALWAYS ON', {
10149
10163
  fontSize: '10px', fontWeight: '600', color: TOKEN$1('inkMuted', '#6b6560'),
10150
10164
  borderWidth: '1px', borderStyle: 'solid', borderColor: TOKEN$1('line', '#e6e3e1'),
10151
10165
  borderRadius: '999px', padding: '3px 8px',
10166
+ width: 'auto', flexShrink: '0', // a chip hugs its word (Text defaults to 100%)
10152
10167
  }, createConfig);
10153
10168
  const necessaryCard = row(createConfig, CARD, [
10154
10169
  textColOf('Necessary', 'Keeps the site working: your session, your language, this very choice. Always on.'),
@@ -10166,6 +10181,7 @@ function buildConsentPreset(createConfig) {
10166
10181
  setTrait(sw, 'control', 'switch');
10167
10182
  setTrait(sw, 'name', `consent-${category}`);
10168
10183
  setStyleTrait(sw, 'width', 'auto');
10184
+ setStyleTrait(sw, 'flexShrink', '0');
10169
10185
  return row(createConfig, CARD, [textColOf(name, desc), sw]);
10170
10186
  };
10171
10187
  const analyticsCard = categoryCard('analytics', 'Analytics', 'Anonymous counts of visits and pages. Off means the analytics script never loads.');
@@ -10182,8 +10198,11 @@ function buildConsentPreset(createConfig) {
10182
10198
  { type: 'grantConsent' },
10183
10199
  { type: 'closeDialog', target: preferences.id },
10184
10200
  ]), SOLID);
10185
- const spacer = row(createConfig, { flexGrow: '1' }, []);
10186
- const footer = row(createConfig, { display: 'flex', gap: '8px', alignItems: 'center' }, [prefsReject, spacer, prefsDone, prefsAccept]);
10201
+ // No spacer Container — an EMPTY container paints the canvas "click to select" placeholder
10202
+ // and squeezes the buttons until their labels wrap (Rule 0 catch). space-between + an end
10203
+ // group is the same board layout with no empty node.
10204
+ const footerEnd = row(createConfig, { display: 'flex', gap: '8px', alignItems: 'center', width: 'auto', flexShrink: '0' }, [prefsDone, prefsAccept]);
10205
+ const footer = row(createConfig, { display: 'flex', gap: '8px', alignItems: 'center', justifyContent: 'space-between' }, [prefsReject, footerEnd]);
10187
10206
  if (!prefsHeading || !prefsSub || !necessaryCard || !analyticsCard || !marketingCard || !footer)
10188
10207
  return null;
10189
10208
  preferences.children = [prefsHeading, prefsSub, necessaryCard, analyticsCard, marketingCard, footer];