ngx-kit 9.1.0 → 9.2.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.
@@ -74,3 +74,39 @@ The emitted event follows the familiar `previousIndex/currentIndex` model, makin
74
74
  ```
75
75
 
76
76
  Resize is pointer based, supports all eight directions, minimum/maximum constraints and optional pixel snapping.
77
+
78
+ ## Page-builder usage (palette in the page, canvas in an `<iframe>`)
79
+
80
+ ```html
81
+ <div NgxDropListGroup>
82
+ <div NgxDropList> <!-- palette (host document) -->
83
+ <div NgxDraggable *ngFor="...">Hero</div>
84
+ </div>
85
+ <!-- inside the iframe's document, rendered by the same Angular app: -->
86
+ <main NgxDropList placeholderFit="stretch" (drop)="onDrop($event)">
87
+ <section NgxDraggable [noDragSelector]="'[data-no-drag], [contenteditable]'">…</section>
88
+ </main>
89
+ </div>
90
+ ```
91
+
92
+ What the engine handles for a same-origin iframe canvas:
93
+
94
+ - pointer capture keeps `pointermove/up` flowing while the pointer is over the iframe; the pointer is converted between the two viewports (iframe offset, border and `transform: scale()` on the `<iframe>` element);
95
+ - scroll and resize listeners are attached to **every** document that hosts a candidate list, so scrolling the canvas (wheel, scrollbar, auto-scroll) re-resolves the insertion point under a still pointer;
96
+ - auto-scroll scrolls the iframe's own scroller using the pointer converted into the iframe's coordinates (and `<html>`/`<body>` scrollers use the window viewport);
97
+ - only the visible part of the iframe counts as "over the list" (a tall canvas does not extend below the iframe), including iframes without `<!doctype>`;
98
+ - the placeholder is sized in the list's own CSS pixels (correct under scaled/zoomed ancestors and scaled iframes). `placeholderFit="stretch"` makes it fill the list's cross axis (a 150px palette tile in a full-width canvas).
99
+
100
+ Editing inside blocks:
101
+
102
+ - `[noDragSelector]` (default `[data-no-drag]`) and `[ignoreInteractive]` keep text caret / buttons / inputs usable;
103
+ - arrow keys only move a draggable/resizable when the element itself has focus (not when typed in an input or `contenteditable` inside it);
104
+ - the `click` the browser fires right after a real drag is swallowed (no accidental select / link follow).
105
+
106
+ Exporting: the directives add `ngx-*` classes, `tabindex="0"`, `aria-grabbed` and `touch-action:none`. Use `getCleanHtml(canvasEl)` (or `stripEditorArtifacts(clone)`) when saving the page.
107
+
108
+ Known limits: cross-origin iframes (no coordinate access), iframes clipped by an `overflow:hidden` ancestor in the host (not clip-tested), `touch-action:none` on draggables blocks touch scrolling that starts on a block (use `dragHandle`), the sorting preview of items with different collapsing margins is approximated until drop, `transform` on a rotated ancestor for resize hit-zones.
109
+
110
+ ## Tests
111
+
112
+ `tests/browser/*.spec.ts` run in real Chromium (Playwright + vitest, set `CHROMIUM_PATH`); `tests/browser/page-builder.spec.ts` covers palette → iframe canvas, iframe scroll/auto-scroll, scaled iframes, editing inside blocks, resizing and export cleanup.