@vectoriox/iox-builder 5.0.1 → 5.1.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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, inject, NgZone, EventEmitter, createComponent, Output, Input, Inject, Directive, ChangeDetectionStrategy, Component, InjectionToken, ViewChild, effect, Optional, ContentChildren, NO_ERRORS_SCHEMA, NgModule } from '@angular/core';
2
+ import { Injectable, inject, NgZone, InjectionToken, EventEmitter, createComponent, Output, Input, Inject, Directive, ChangeDetectionStrategy, Component, ViewChild, effect, Optional, ContentChildren, NO_ERRORS_SCHEMA, NgModule } from '@angular/core';
3
3
  import * as i2 from '@angular/common';
4
4
  import { DOCUMENT, CommonModule } from '@angular/common';
5
5
  import * as i16 from '@angular/forms';
@@ -16,7 +16,7 @@ import { SelectModule } from 'primeng/select';
16
16
  import { TooltipModule } from 'primeng/tooltip';
17
17
  import { DialogModule } from 'primeng/dialog';
18
18
  import * as i1 from '@vectoriox/iox-ui';
19
- import { VALIDATION_STATES as VALIDATION_STATES$1, VALIDATION_STATE_CLASS as VALIDATION_STATE_CLASS$1, DEFAULT_WIDTH_BY_TYPE, Breakpoint, BREAKPOINTS, countOverrides, setOverride, defaultElementStyleFor, applyElementStyle, stripSuppressedProps, DeclarationContext, buildPartSelector, planResponsiveRules, resolveStyleProps, buildTargetedStateSelector, statePseudoClass, compileTokenCssBlocks, compileDeclarations, wrapInBreakpointQuery, BreakpointQueryKind, breakpointDef, breakpointForWidth, FormRenderState, safeSetInput, ContextStore, ComponentInstanceRegistryService, isActionEnabled, isContextAction, contextActionEffect, resolveContextValue, composeVirtualTraits, withDefaultHoverTransition, stateNamesIn, partClassName, syncElementStyleMarker, resolveInputs, setInputOverride, collectContextSlotKeys, withContextSlots, compilePageStyle, nodeUsesContext, resolveBoundValue, IS_PREVIEW, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, IoxPageModule, PALETTE_PRESETS, PART_CLASS_NAMES } from '@vectoriox/iox-ui';
19
+ import { VALIDATION_STATES as VALIDATION_STATES$1, VALIDATION_STATE_CLASS as VALIDATION_STATE_CLASS$1, DEFAULT_WIDTH_BY_TYPE, COLOR_SCHEME_TRAIT, COLOR_SCHEMES, ColorScheme, Breakpoint, BREAKPOINTS, countOverrides, setOverride, defaultElementStyleFor, applyElementStyle, stripSuppressedProps, DeclarationContext, buildPartSelector, planResponsiveRules, resolveStyleProps, buildTargetedStateSelector, statePseudoClass, compileTokenCssBlocks, compileDeclarations, wrapInBreakpointQuery, BreakpointQueryKind, breakpointDef, breakpointForWidth, FormRenderState, safeSetInput, ContextStore, ComponentInstanceRegistryService, isActionEnabled, isContextAction, contextActionEffect, resolveContextValue, IS_PREVIEW, emptyImageSrc, composeVirtualTraits, withDefaultHoverTransition, stateNamesIn, partClassName, syncNodeDesignClasses, resolveInputs, setInputOverride, collectContextSlotKeys, withContextSlots, compilePageStyle, nodeUsesContext, resolveBoundValue, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, IoxPageModule, PALETTE_PRESETS, PART_CLASS_NAMES } from '@vectoriox/iox-ui';
20
20
  export { ComponentInstanceRegistryService, VIRTUAL_TRAIT_KEYS, composeVirtualTraits } from '@vectoriox/iox-ui';
21
21
  import Lenis from 'lenis';
22
22
  import { Subject, BehaviorSubject, of, forkJoin } from 'rxjs';
@@ -655,6 +655,15 @@ class ListGroupStyleConfig extends GroupStyleConfig {
655
655
  * Every call produces new TraitConfig instances so different component nodes
656
656
  * never share mutable state.
657
657
  */
658
+ /**
659
+ * The section colour scheme (design-system §3c) — a CONTENT trait, stored in `props` and saved with
660
+ * the page, never a style prop: it becomes the class `iox-scheme-<id>` (the shared
661
+ * `nodeDesignClasses`) where the token sheet re-declares the section's tokens. Edited in the Style
662
+ * panel beside the element style; the Bindings panel does not list it.
663
+ */
664
+ function buildColorSchemeTrait() {
665
+ return new TraitConfig(COLOR_SCHEME_TRAIT, 'Section colours', TraitInputType.Select, COLOR_SCHEMES.map(s => ({ label: s.label, value: s.id })), ColorScheme.Default);
666
+ }
658
667
  function buildFullStyleTraits() {
659
668
  return [
660
669
  new PositionGroupStyleConfig(),
@@ -4495,6 +4504,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
4495
4504
  args: [{ providedIn: 'root' }]
4496
4505
  }] });
4497
4506
 
4507
+ /**
4508
+ * Canvas data preview used to come from host-provided content services (IOX_CONTENT_SERVICE /
4509
+ * IOX_SHOP_SERVICE), whose `getContent(contentType, orgId)` hit the ADMIN resources endpoint and
4510
+ * accepted no filters — so the Repeater/Slider ignored every data-source filter. Data now flows
4511
+ * through BuilderDataSourceService + the shared planDataSource, configured with
4512
+ * IOX_DATA_SOURCE_ENDPOINTS. Those tokens are gone; do not reintroduce a fetch that bypasses it.
4513
+ */
4514
+ /** Optional font manager. Provide from the host app to populate the fontFamily dropdown. */
4515
+ const IOX_FONT_MANAGER = new InjectionToken('IOX_FONT_MANAGER');
4516
+ /**
4517
+ * Translates the builder library's OWN chrome.
4518
+ *
4519
+ * The library cannot depend on ngx-translate — that is the host app's choice — but its toolbar was
4520
+ * hardcoded English, which shows through as untranslated controls in a Hebrew/RTL admin. This token
4521
+ * lets the host route those strings through its own i18n while the library keeps working standalone:
4522
+ * unprovided, `defaultBuilderLabels` returns the English text, so nothing ever renders a raw key.
4523
+ *
4524
+ * Keys are namespaced `builder.chrome.*` and listed in `BUILDER_CHROME_EN` below — that object is
4525
+ * the contract. A host providing this token should add those keys to its own bundles.
4526
+ */
4527
+ const IOX_BUILDER_LABELS = new InjectionToken('IOX_BUILDER_LABELS', {
4528
+ providedIn: 'root',
4529
+ factory: () => defaultBuilderLabels,
4530
+ });
4531
+ /** Standalone behaviour: the English text the library ships with. */
4532
+ const defaultBuilderLabels = (_key, fallback) => fallback;
4533
+ /**
4534
+ * Every user-visible string in the builder's own chrome, so a host can copy this into its bundles
4535
+ * in one go rather than discovering keys one missing label at a time.
4536
+ */
4537
+ const BUILDER_CHROME_EN = Object.freeze({
4538
+ 'builder.chrome.select': 'Select',
4539
+ 'builder.chrome.pan': 'Pan',
4540
+ 'builder.chrome.style': 'Style',
4541
+ 'builder.chrome.publish': 'Publish',
4542
+ 'builder.chrome.unpublish': 'Unpublish',
4543
+ 'builder.chrome.breakpoint': 'Breakpoint',
4544
+ 'builder.chrome.screenWidth': 'Screen width',
4545
+ 'builder.chrome.zoom': 'Zoom',
4546
+ 'builder.chrome.audit': 'Responsive audit',
4547
+ 'builder.chrome.auditHint': 'Responsive audit — what is broken at this width',
4548
+ 'builder.chrome.undo': 'Undo',
4549
+ 'builder.chrome.redo': 'Redo',
4550
+ 'builder.chrome.save': 'Save',
4551
+ 'builder.chrome.preview': 'Preview',
4552
+ 'builder.chrome.addImage': 'Add image',
4553
+ });
4554
+
4498
4555
  // Module-level counter — unique drop-list ID per Section instance across the whole app session.
4499
4556
  let dropListCounter = 0;
4500
4557
  /**
@@ -4557,6 +4614,8 @@ class RenderDirective {
4557
4614
  this.onMouseEnter = new EventEmitter();
4558
4615
  this.onMouseLeave = new EventEmitter();
4559
4616
  this.childSubs = [];
4617
+ this.isPreview = inject(IS_PREVIEW, { optional: true }) ?? false;
4618
+ this.labels = inject(IOX_BUILDER_LABELS);
4560
4619
  /** Host element drag was registered on (collapsed path) — unregistered on destroy. */
4561
4620
  this.hostDragEl = null;
4562
4621
  }
@@ -4705,6 +4764,14 @@ class RenderDirective {
4705
4764
  // safeSetInput for every component that does not declare it.
4706
4765
  if (node.responsive)
4707
4766
  safeSetInput(componentRef, 'responsive', node.responsive);
4767
+ // Empty images (DS3): a MARKED Image with no source shows the shared placeholder — the
4768
+ // "Add image" label on the canvas, the bare blank in Preview (IS_PREVIEW), which is what the
4769
+ // live site shows. An unmarked Image gets null and renders exactly as before.
4770
+ if (node.type === 'Image') {
4771
+ const src = node.traits?.find(t => t.name === 'src')?.default;
4772
+ const label = this.isPreview ? null : this.labels('builder.chrome.addImage', 'Add image');
4773
+ safeSetInput(componentRef, 'emptySrc', emptyImageSrc(node, src, label));
4774
+ }
4708
4775
  // Build initial style map from styleTraits defaults.
4709
4776
  const initialStyle = {};
4710
4777
  if (node.styleTraits?.length) {
@@ -4824,10 +4891,12 @@ class RenderDirective {
4824
4891
  // For layout components the host element is <app-section>; for leaf components
4825
4892
  // it is e.g. <app-card>. Either way this is the correct inspectable element.
4826
4893
  const nativeEl = componentRef.location?.nativeElement ?? null;
4827
- // The element-style marker (design-system §3b-bis) — on the HOST, as both engine paths do:
4828
- // component CSS that carries the system look is scoped to it, so a node saved before DS2
4829
- // keeps its exact pre-DS2 look. Clones carry it too (they render the same look).
4830
- syncElementStyleMarker(nativeEl, node.elementStyle);
4894
+ // The design-system classes — the element-style marker (§3b-bis) and the section colour scheme
4895
+ // (§3c) — on the HOST, as both engine paths do, from the ONE shared helper. Component CSS that
4896
+ // carries the system look is scoped to the marker, so a node saved before DS2 keeps its exact
4897
+ // pre-DS2 look; the scheme class is where the token sheet re-declares the section's tokens.
4898
+ // Clones carry both (they render the same look).
4899
+ syncNodeDesignClasses(nativeEl, node);
4831
4900
  // Custom element host defaults to display:inline. Set it to block so it participates
4832
4901
  // properly in layout and CDK can capture its bounding rect. SKIP for directive-hosts: the
4833
4902
  // host is a real element with its own display, and an inline style here out-ranks both
@@ -5568,53 +5637,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
5568
5637
  type: Output
5569
5638
  }] } });
5570
5639
 
5571
- /**
5572
- * Canvas data preview used to come from host-provided content services (IOX_CONTENT_SERVICE /
5573
- * IOX_SHOP_SERVICE), whose `getContent(contentType, orgId)` hit the ADMIN resources endpoint and
5574
- * accepted no filters — so the Repeater/Slider ignored every data-source filter. Data now flows
5575
- * through BuilderDataSourceService + the shared planDataSource, configured with
5576
- * IOX_DATA_SOURCE_ENDPOINTS. Those tokens are gone; do not reintroduce a fetch that bypasses it.
5577
- */
5578
- /** Optional font manager. Provide from the host app to populate the fontFamily dropdown. */
5579
- const IOX_FONT_MANAGER = new InjectionToken('IOX_FONT_MANAGER');
5580
- /**
5581
- * Translates the builder library's OWN chrome.
5582
- *
5583
- * The library cannot depend on ngx-translate — that is the host app's choice — but its toolbar was
5584
- * hardcoded English, which shows through as untranslated controls in a Hebrew/RTL admin. This token
5585
- * lets the host route those strings through its own i18n while the library keeps working standalone:
5586
- * unprovided, `defaultBuilderLabels` returns the English text, so nothing ever renders a raw key.
5587
- *
5588
- * Keys are namespaced `builder.chrome.*` and listed in `BUILDER_CHROME_EN` below — that object is
5589
- * the contract. A host providing this token should add those keys to its own bundles.
5590
- */
5591
- const IOX_BUILDER_LABELS = new InjectionToken('IOX_BUILDER_LABELS', {
5592
- providedIn: 'root',
5593
- factory: () => defaultBuilderLabels,
5594
- });
5595
- /** Standalone behaviour: the English text the library ships with. */
5596
- const defaultBuilderLabels = (_key, fallback) => fallback;
5597
- /**
5598
- * Every user-visible string in the builder's own chrome, so a host can copy this into its bundles
5599
- * in one go rather than discovering keys one missing label at a time.
5600
- */
5601
- const BUILDER_CHROME_EN = Object.freeze({
5602
- 'builder.chrome.select': 'Select',
5603
- 'builder.chrome.pan': 'Pan',
5604
- 'builder.chrome.style': 'Style',
5605
- 'builder.chrome.publish': 'Publish',
5606
- 'builder.chrome.unpublish': 'Unpublish',
5607
- 'builder.chrome.breakpoint': 'Breakpoint',
5608
- 'builder.chrome.screenWidth': 'Screen width',
5609
- 'builder.chrome.zoom': 'Zoom',
5610
- 'builder.chrome.audit': 'Responsive audit',
5611
- 'builder.chrome.auditHint': 'Responsive audit — what is broken at this width',
5612
- 'builder.chrome.undo': 'Undo',
5613
- 'builder.chrome.redo': 'Redo',
5614
- 'builder.chrome.save': 'Save',
5615
- 'builder.chrome.preview': 'Preview',
5616
- });
5617
-
5618
5640
  class ToolbarComponent {
5619
5641
  get isPublished() {
5620
5642
  return this.pageStatus === 'published';
@@ -6543,7 +6565,7 @@ class BuilderComponent {
6543
6565
  this.initLenis();
6544
6566
  // Background / typography: until this existed the Page panel wrote a background
6545
6567
  // that only appeared once the site was published.
6546
- this.pageStyleCss = compilePageStyle(this.pageSettings?.style);
6568
+ this.pageStyleCss = compilePageStyle(this.pageSettings?.style, { designSystem: this.pageSettings?.designSystem === true });
6547
6569
  }
6548
6570
  if (changes['globalElements']) {
6549
6571
  // The *ngIf on the global overlay renders after this hook — defer so
@@ -10638,6 +10660,7 @@ class BuilderContainerComponentConfig extends ComponentConfig {
10638
10660
  this.children = [];
10639
10661
  this.traits = [
10640
10662
  new TraitConfig('htmlTag', 'HTML Tag', TraitInputType.Select, ['div', 'section', 'article', 'header', 'footer', 'main', 'nav', 'ul', 'ol', 'li'], 'div'),
10663
+ buildColorSchemeTrait(),
10641
10664
  ];
10642
10665
  this.styleTraits = buildFullStyleTraits();
10643
10666
  this.applyStyleDefaults({
@@ -11063,6 +11086,7 @@ class BuilderLinkedContainerConfig extends ComponentConfig {
11063
11086
  { label: 'Parent frame', value: '_parent' },
11064
11087
  { label: 'Full window', value: '_top' },
11065
11088
  ], '_self'),
11089
+ buildColorSchemeTrait(),
11066
11090
  ];
11067
11091
  this.styleTraits = buildFullStyleTraits();
11068
11092
  this.applyStyleDefaults({
@@ -11189,7 +11213,7 @@ class SectionComponentConfig extends ComponentConfig {
11189
11213
  constructor() {
11190
11214
  super('Section', 'app-section', 'ph-thin ph-rows', 'Layout');
11191
11215
  this.children = [];
11192
- this.traits = [];
11216
+ this.traits = [buildColorSchemeTrait()];
11193
11217
  this.styleTraits = buildFullStyleTraits();
11194
11218
  this.applyStyleDefaults({
11195
11219
  width: 'auto',