@kubex/zinc 1.1.94 → 1.1.96

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.
Files changed (39) hide show
  1. package/dist/custom-elements.json +653 -89
  2. package/dist/vscode.html-custom-data.json +73 -18
  3. package/dist/web-types.json +145 -35
  4. package/dist/zn.d.ts +204 -39
  5. package/dist/zn.min.css +1 -1
  6. package/dist/zn.min.js +374 -308
  7. package/docs/pages/components/flow-builder.md +17 -1
  8. package/docs/pages/components/page-builder.md +31 -0
  9. package/docs/pages/components/slash-menu.md +132 -6
  10. package/docs/pages/components/textarea.md +16 -0
  11. package/package.json +1 -1
  12. package/scss/_root.scss +7 -1
  13. package/src/components/button/button.scss +5 -2
  14. package/src/components/flow-builder/flow-builder.component.ts +16 -1
  15. package/src/components/flow-builder/flow-builder.test.ts +206 -1
  16. package/src/components/flow-builder/flow-geometry.test.ts +102 -0
  17. package/src/components/flow-builder/flow.types.ts +82 -15
  18. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.component.ts +163 -108
  19. package/src/components/flow-builder/modules/flow-step/flow-step.component.ts +2 -0
  20. package/src/components/inline-edit/inline-edit.component.ts +6 -1
  21. package/src/components/input/input.component.ts +12 -2
  22. package/src/components/page/page.scss +7 -2
  23. package/src/components/page-builder/modules/page-section-card/page-section-card.component.ts +16 -9
  24. package/src/components/page-builder/modules/page-section-card/page-section-card.scss +13 -0
  25. package/src/components/page-builder/modules/page-section-card/page-section-card.test.ts +9 -0
  26. package/src/components/page-builder/page-builder.component.ts +62 -4
  27. package/src/components/page-builder/page-builder.test.ts +94 -0
  28. package/src/components/remarkd-editor/remarkd-editor.component.ts +227 -12
  29. package/src/components/remarkd-editor/remarkd-editor.scss +81 -0
  30. package/src/components/remarkd-editor/remarkd-editor.test.ts +258 -0
  31. package/src/components/settings-container/settings-container.scss +2 -1
  32. package/src/components/slash-item/slash-item.component.ts +1 -1
  33. package/src/components/slash-menu/slash-menu-items.ts +48 -0
  34. package/src/components/slash-menu/slash-menu.component.ts +134 -27
  35. package/src/components/slash-menu/slash-menu.scss +90 -12
  36. package/src/components/slash-menu/slash-menu.test.ts +107 -0
  37. package/src/components/textarea/textarea.component.ts +12 -2
  38. package/src/components/textarea/textarea.test.ts +2 -2
  39. package/src/components/translations/translations.component.ts +5 -1
package/dist/zn.d.ts CHANGED
@@ -1901,6 +1901,14 @@ declare module "components/slash-menu/slash-menu-items" {
1901
1901
  export function parseSlashItems(value: string | null | undefined): SlashMenuItem[];
1902
1902
  /** Filters and ranks items against a query. An empty query keeps every item in its declared order. */
1903
1903
  export function filterSlashItems(items: SlashMenuItem[], query: string): SlashMenuItem[];
1904
+ /** The identity an item is remembered by in a menu's recently used list. */
1905
+ export function slashItemKey(item: SlashMenuItem): string;
1906
+ /** The keys of the items most recently chosen from the menu stored under `key`, newest first. */
1907
+ export function readRecentSlashItems(key: string): string[];
1908
+ /** Moves an item to the front of the recently used list stored under `key`, and returns the list. */
1909
+ export function recordRecentSlashItem(key: string, item: SlashMenuItem): string[];
1910
+ /** Forgets the recently used items stored under `key`. */
1911
+ export function clearRecentSlashItems(key: string): void;
1904
1912
  }
1905
1913
  declare module "utilities/caret-position" {
1906
1914
  export interface CaretCoordinates {
@@ -1927,7 +1935,7 @@ declare module "utilities/caret-position" {
1927
1935
  declare module "components/slash-menu/slash-menu.component" {
1928
1936
  import ZincElement from "internal/zinc-element";
1929
1937
  import ZnIcon from "components/icon/index";
1930
- import type { CSSResultGroup, PropertyValues } from 'lit';
1938
+ import type { CSSResultGroup, PropertyValues, TemplateResult } from 'lit';
1931
1939
  import type { Placement, VirtualElement } from '@floating-ui/dom';
1932
1940
  import type { SlashMenuItem } from "components/slash-menu/slash-menu-items";
1933
1941
  export const SLASH_ITEM_SELECT = "zn-slash-item-select";
@@ -1943,12 +1951,19 @@ declare module "components/slash-menu/slash-menu.component" {
1943
1951
  * component driving the menu (e.g. `zn-textarea`) re-emits it as `zn-slash-select`.
1944
1952
  *
1945
1953
  * @csspart panel - The floating panel that holds the list.
1946
- * @csspart heading - The panel's heading.
1954
+ * @csspart list - The scrolling list of items.
1947
1955
  * @csspart item - An item in the list.
1956
+ * @csspart icon - The chip holding an item's icon.
1948
1957
  * @csspart group-heading - A group heading between items.
1958
+ * @csspart divider - The rule closing the recently used section, when the items below it have no heading of their own.
1949
1959
  * @csspart footer - The truncation footer, shown when not every match fits.
1960
+ * @csspart hints - The pinned footer of keyboard hints.
1961
+ * @csspart hint - A single keyboard hint within the footer.
1962
+ * @csspart hint-key - The key shown against a hint.
1950
1963
  *
1951
1964
  * @cssproperty --slash-menu-width - The width of the panel.
1965
+ * @cssproperty --slash-menu-border-radius - The corner radius of the panel.
1966
+ * @cssproperty --slash-menu-item-border-radius - The corner radius of the items and their icon chips.
1952
1967
  * @cssproperty --slash-menu-max-height - The maximum height of the panel before it scrolls.
1953
1968
  */
1954
1969
  export default class ZnSlashMenu extends ZincElement {
@@ -1957,6 +1972,7 @@ declare module "components/slash-menu/slash-menu.component" {
1957
1972
  'zn-icon': typeof ZnIcon;
1958
1973
  };
1959
1974
  private panel;
1975
+ private list;
1960
1976
  private stopAutoUpdate?;
1961
1977
  /** Whether the menu is showing. */
1962
1978
  open: boolean;
@@ -1964,7 +1980,7 @@ declare module "components/slash-menu/slash-menu.component" {
1964
1980
  items: SlashMenuItem[];
1965
1981
  /** The query the items were matched against, shown in the heading. */
1966
1982
  query: string;
1967
- /** The heading shown when there is no query. */
1983
+ /** The name the list is announced by when there is no query. */
1968
1984
  heading: string;
1969
1985
  /** Shown in place of the list when there are no items. */
1970
1986
  emptyText: string;
@@ -1972,6 +1988,18 @@ declare module "components/slash-menu/slash-menu.component" {
1972
1988
  maxItems: number;
1973
1989
  /** Hides the insertion key (the item's value) normally shown against each item. */
1974
1990
  hideKeys: boolean;
1991
+ /** Hides the pinned footer of keyboard hints. */
1992
+ hideHints: boolean;
1993
+ /**
1994
+ * Remembers the items chosen here and lists the most recent of them first, under their own heading.
1995
+ * The key scopes the list to where the menu is used, so each place keeps its own history in
1996
+ * `localStorage`. Leave unset to offer no recently used section.
1997
+ */
1998
+ recentKey: string;
1999
+ /** The most recently used items to list. */
2000
+ maxRecent: number;
2001
+ /** The heading shown above the recently used items. */
2002
+ recentHeading: string;
1975
2003
  /** The element or caret rect the panel is positioned against. */
1976
2004
  anchor: Element | VirtualElement | null;
1977
2005
  /** The preferred placement of the panel. */
@@ -1979,11 +2007,22 @@ declare module "components/slash-menu/slash-menu.component" {
1979
2007
  /** The gap between the caret and the panel. */
1980
2008
  distance: number;
1981
2009
  private activeIndex;
2010
+ private recentKeys;
2011
+ /** How many recently used items the last update listed, to spot the list appearing or reordering. */
2012
+ private recentCount;
2013
+ private get listItems();
2014
+ /**
2015
+ * The remembered items that are in the current list, newest first. Only offered without a query —
2016
+ * once the user is searching, the ranked matches are the better answer.
2017
+ */
2018
+ private get recentItems();
1982
2019
  private get visibleItems();
1983
2020
  /** The item that Enter would insert. */
1984
2021
  get activeItem(): SlashMenuItem | undefined;
1985
2022
  show(): void;
1986
2023
  hide(): void;
2024
+ /** Forgets the items remembered under `recent-key`. */
2025
+ clearRecent(): void;
1987
2026
  /** Sets the active item by index, wrapping at both ends and skipping disabled items. */
1988
2027
  setActiveIndex(index: number): void;
1989
2028
  /** Moves the active item by `delta` places. */
@@ -2006,7 +2045,9 @@ declare module "components/slash-menu/slash-menu.component" {
2006
2045
  protected updated(changed: PropertyValues): void;
2007
2046
  private renderItem;
2008
2047
  private renderItems;
2009
- render(): import("lit-html").TemplateResult<1>;
2048
+ private renderHint;
2049
+ private renderHints;
2050
+ render(): TemplateResult<1>;
2010
2051
  }
2011
2052
  }
2012
2053
  declare module "components/slash-menu/slash-menu-controller" {
@@ -2080,10 +2121,22 @@ declare module "components/slash-menu/slash-menu-controller" {
2080
2121
  private replace;
2081
2122
  }
2082
2123
  }
2124
+ declare module "components/slash-menu/index" {
2125
+ import ZnSlashMenu from "components/slash-menu/slash-menu.component";
2126
+ export * from "components/slash-menu/slash-menu.component";
2127
+ export * from "components/slash-menu/slash-menu-controller";
2128
+ export * from "components/slash-menu/slash-menu-items";
2129
+ export default ZnSlashMenu;
2130
+ global {
2131
+ interface HTMLElementTagNameMap {
2132
+ 'zn-slash-menu': ZnSlashMenu;
2133
+ }
2134
+ }
2135
+ }
2083
2136
  declare module "components/slash-item/slash-item.component" {
2084
2137
  import ZincElement from "internal/zinc-element";
2085
2138
  import type { CSSResultGroup } from 'lit';
2086
- import type { SlashMenuItem } from "components/slash-menu/slash-menu-items";
2139
+ import type { SlashMenuItem } from "components/slash-menu/index";
2087
2140
  /**
2088
2141
  * @summary Declares a single insertion for a slash menu. Renders nothing itself — it describes an
2089
2142
  * entry for the component it is slotted into, e.g. `<zn-textarea>`'s `slash-items` slot.
@@ -2132,18 +2185,6 @@ declare module "components/slash-item/index" {
2132
2185
  }
2133
2186
  }
2134
2187
  }
2135
- declare module "components/slash-menu/index" {
2136
- import ZnSlashMenu from "components/slash-menu/slash-menu.component";
2137
- export * from "components/slash-menu/slash-menu.component";
2138
- export * from "components/slash-menu/slash-menu-controller";
2139
- export * from "components/slash-menu/slash-menu-items";
2140
- export default ZnSlashMenu;
2141
- global {
2142
- interface HTMLElementTagNameMap {
2143
- 'zn-slash-menu': ZnSlashMenu;
2144
- }
2145
- }
2146
- }
2147
2188
  declare module "components/input/input.component" {
2148
2189
  import { type SlashMenuItem } from "components/slash-menu/slash-menu-items";
2149
2190
  import ZincElement from "internal/zinc-element";
@@ -2337,10 +2378,15 @@ declare module "components/input/input.component" {
2337
2378
  slashPreset: string;
2338
2379
  /** The characters that open the slash menu. */
2339
2380
  slashTrigger: string;
2340
- /** The heading shown above the slash menu's items. */
2381
+ /** The name the slash menu's list is announced by. */
2341
2382
  slashHeading: string;
2342
2383
  /** Hides the insertion keys normally shown against the slash menu's items. */
2343
2384
  slashHideKeys: boolean;
2385
+ /**
2386
+ * Lists the items most recently chosen here above the rest, remembered in `localStorage` under this
2387
+ * key. Share a key between the fields that should share a history; leave unset to offer no such list.
2388
+ */
2389
+ slashRecentKey: string;
2344
2390
  /**
2345
2391
  * Resolves additional items each time the menu opens, for lists that come from elsewhere (e.g. an
2346
2392
  * API). Receives the current query and may return a promise. JavaScript only.
@@ -5233,10 +5279,12 @@ declare module "components/inline-edit/inline-edit.component" {
5233
5279
  slashPreset: string;
5234
5280
  /** The characters that open the slash menu. */
5235
5281
  slashTrigger: string;
5236
- /** The heading shown above the slash menu's items. */
5282
+ /** The name the slash menu's list is announced by. */
5237
5283
  slashHeading: string;
5238
5284
  /** Hides the insertion keys normally shown against the slash menu's items. */
5239
5285
  slashHideKeys: boolean;
5286
+ /** Lists the slash menu items most recently chosen here above the rest, remembered under this key. */
5287
+ slashRecentKey: string;
5240
5288
  /** Resolves additional slash menu items each time the menu opens. JavaScript only. */
5241
5289
  slashItemsProvider?: (query: string) => SlashMenuItem[] | Promise<SlashMenuItem[]>;
5242
5290
  options: {
@@ -6680,10 +6728,15 @@ declare module "components/textarea/textarea.component" {
6680
6728
  slashPreset: string;
6681
6729
  /** The characters that open the slash menu. */
6682
6730
  slashTrigger: string;
6683
- /** The heading shown above the slash menu's items. */
6731
+ /** The name the slash menu's list is announced by. */
6684
6732
  slashHeading: string;
6685
6733
  /** Hides the insertion keys normally shown against the slash menu's items. */
6686
6734
  slashHideKeys: boolean;
6735
+ /**
6736
+ * Lists the items most recently chosen here above the rest, remembered in `localStorage` under this
6737
+ * key. Share a key between the fields that should share a history; leave unset to offer no such list.
6738
+ */
6739
+ slashRecentKey: string;
6687
6740
  /**
6688
6741
  * Resolves additional items each time the menu opens, for lists that come from elsewhere (e.g. an
6689
6742
  * API). Receives the current query and may return a promise. JavaScript only.
@@ -8724,10 +8777,12 @@ declare module "components/translations/translations.component" {
8724
8777
  slashPreset: string;
8725
8778
  /** The characters that open the slash menu. */
8726
8779
  slashTrigger: string;
8727
- /** The heading shown above the slash menu's items. */
8780
+ /** The name the slash menu's list is announced by. */
8728
8781
  slashHeading: string;
8729
8782
  /** Hides the insertion keys normally shown against the slash menu's items. */
8730
8783
  slashHideKeys: boolean;
8784
+ /** Lists the slash menu items most recently chosen here above the rest, remembered under this key. */
8785
+ slashRecentKey: string;
8731
8786
  /** Resolves additional slash menu items each time the menu opens. JavaScript only. */
8732
8787
  slashItemsProvider?: (query: string) => SlashMenuItem[] | Promise<SlashMenuItem[]>;
8733
8788
  /** When true, hides the individual language navbar and defers language control to a parent zn-translation-group. */
@@ -9278,6 +9333,8 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9278
9333
  * @csspart raw - The full-document textarea shown in raw source mode.
9279
9334
  * @csspart slash-menu - The `zn-slash-menu` opened by typing "/" in an empty block.
9280
9335
  * @csspart image-controls - The caption / alignment / size panel shown when an image block is clicked.
9336
+ * @csspart include - The chip rendered in place of an `include::` directive.
9337
+ * @csspart include-picker - The inline Include picker opened from the toolbar or "/include".
9281
9338
  */
9282
9339
  export default class ZnRemarkdEditor extends ZincElement implements ZincFormControl {
9283
9340
  static styles: CSSResultGroup;
@@ -9287,6 +9344,7 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9287
9344
  private readonly formControlController;
9288
9345
  private readonly slashController;
9289
9346
  private editingDraft;
9347
+ private includeRequest;
9290
9348
  private rawEntryValue;
9291
9349
  private suppressValueSync;
9292
9350
  private suppressBlurCommit;
@@ -9294,6 +9352,11 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9294
9352
  private slashMenuElement;
9295
9353
  private blocks;
9296
9354
  private editingIndex;
9355
+ /**
9356
+ * Lists the blocks most recently inserted here above the rest of the slash menu, remembered in
9357
+ * `localStorage` under this key. Leave unset to offer no recently used section.
9358
+ */
9359
+ slashRecentKey: string;
9297
9360
  /** Renders the slash menu only once it has been needed. */
9298
9361
  private hasSlashMenu;
9299
9362
  private imagePickerIndex;
@@ -9302,6 +9365,10 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9302
9365
  private dragIndex;
9303
9366
  private editShell;
9304
9367
  private rawMode;
9368
+ private includeOptions;
9369
+ private includeLoadFailed;
9370
+ private includePickerIndex;
9371
+ private includeQuery;
9305
9372
  private pendingDragHandle;
9306
9373
  private dragStartX;
9307
9374
  private dragStartY;
@@ -9320,6 +9387,12 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9320
9387
  * to `uploadUrl` and the returned `uploadPath` is embedded as the image URL.
9321
9388
  */
9322
9389
  attachmentUrl: string;
9390
+ /**
9391
+ * Endpoint listing the Includes this document may embed, as
9392
+ * `{"items":[{id,title,description,scope,keywords,languages,url}]}`. Labels the
9393
+ * chips rendered for `include::` directives and feeds the include picker.
9394
+ */
9395
+ includeUrl: string;
9323
9396
  /** Adds a toolbar toggle that swaps the block view for the full remarkd source. */
9324
9397
  allowRaw: boolean;
9325
9398
  /** Makes the editor required for form submission. */
@@ -9341,6 +9414,7 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9341
9414
  protected firstUpdated(_changedProperties: PropertyValues): void;
9342
9415
  disconnectedCallback(): void;
9343
9416
  handleValueChange(): void;
9417
+ handleIncludeUrlChange(): void;
9344
9418
  /**
9345
9419
  * Splits remarkd source into blocks on blank lines, keeping fenced /
9346
9420
  * delimited containers (``` ==== !!!! .... ----) as single blocks.
@@ -9352,6 +9426,8 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9352
9426
  private handleRenderedClick;
9353
9427
  /** Parses a block that is purely an image (with optional caption/align lines). */
9354
9428
  private parseImageBlock;
9429
+ /** Parses a block that is nothing but an include directive. */
9430
+ private parseIncludeBlock;
9355
9431
  private serializeImageBlock;
9356
9432
  private toggleCheckbox;
9357
9433
  private startEdit;
@@ -9398,10 +9474,24 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9398
9474
  private createDragGhost;
9399
9475
  private moveDragGhost;
9400
9476
  private pickImage;
9477
+ private pickInclude;
9478
+ private closeIncludePicker;
9479
+ private insertInclude;
9401
9480
  private closeImagePicker;
9402
9481
  private handleImagePicked;
9403
9482
  private insertImage;
9404
9483
  private uploadImage;
9484
+ /**
9485
+ * Resolves an app-relative path the way the console's pagelet handler does:
9486
+ * an app fragment's URLs sit under the app base, and the console puts the app's
9487
+ * `gaid` on the host element. Links rendered here live in the shadow root,
9488
+ * where a click retargets to the host, so that handler never sees them — the
9489
+ * href has to carry the base itself.
9490
+ */
9491
+ private appPath;
9492
+ private hasIncludeBlock;
9493
+ /** Fetches the include list once; every later caller shares the same promise. */
9494
+ private loadIncludeOptions;
9405
9495
  private autosize;
9406
9496
  private toggleRawMode;
9407
9497
  private focusRaw;
@@ -9419,11 +9509,13 @@ declare module "components/remarkd-editor/remarkd-editor.component" {
9419
9509
  private commitRaw;
9420
9510
  private handleToolbarInsert;
9421
9511
  private renderImageControls;
9512
+ private renderIncludeChip;
9422
9513
  private renderBlock;
9423
9514
  render(): import("lit-html").TemplateResult<1>;
9424
9515
  private renderRaw;
9425
9516
  /** The block views, with the inline image picker spliced in when active. */
9426
9517
  private renderBody;
9518
+ private renderIncludePicker;
9427
9519
  private renderImagePicker;
9428
9520
  }
9429
9521
  }
@@ -9525,6 +9617,14 @@ declare module "components/flow-builder/flow.types" {
9525
9617
  inputs?: FlowPort[];
9526
9618
  /** Output ports. Defaults to a single unlabelled output. e.g. TRUE/FALSE for a split. */
9527
9619
  outputs?: FlowPort[];
9620
+ /**
9621
+ * The type's branches are the only ones it has: the canvas offers no delete
9622
+ * on their pills, and clicking a fully-wired node's output adds nothing.
9623
+ * For steps whose branches mirror fixed fields in the consumer's own model
9624
+ * (a success / failure / skip triple, say), where an extra or missing branch
9625
+ * has nowhere to be stored.
9626
+ */
9627
+ fixedOutputs?: boolean;
9528
9628
  /** Initial `data` for a freshly placed node. */
9529
9629
  defaultData?: Record<string, unknown>;
9530
9630
  /**
@@ -9611,12 +9711,17 @@ declare module "components/flow-builder/flow.types" {
9611
9711
  /** Extra pill height per wrapped line (matches the pill's CSS line-height). */
9612
9712
  export const PILL_LINE_HEIGHT = 20;
9613
9713
  /**
9614
- * Canvas y of a branch pill's top edge. A pill on a wire to a child below is
9615
- * centred along the run from its node's bottom to the child's top — equal wire
9616
- * above and below, however long or tight. A sole output's wire is a straight
9617
- * stem with no bus to respect, so its pill may rise above the bus line to stay
9618
- * centred; fan branches stop at the bus. Open branches and loop/side wires
9619
- * keep the fixed drop below the bus.
9714
+ * Canvas y of a branch pill's top edge. A pill on a wire to a child in the next
9715
+ * row down is centred along the run from its node's bottom to the child's top —
9716
+ * equal wire above and below. A sole output's wire is a straight stem with no
9717
+ * bus to respect, so its pill may rise above the bus line to stay centred; fan
9718
+ * branches stop at the bus.
9719
+ *
9720
+ * A branch reaching past the next row sits right under the bus instead: it
9721
+ * reads as belonging to the node it hangs from rather than to whatever it flies
9722
+ * over, and it leaves the whole gap below free for the wire to route around
9723
+ * what is in the way. Open branches and loop/side wires keep the fixed drop
9724
+ * below the bus, where their "+" has room.
9620
9725
  */
9621
9726
  export function branchPillTop(node: Pick<FlowNodeInstance, 'y'>, pillH: number, child?: Pick<FlowNodeInstance, 'y'>, soleOutput?: boolean): number;
9622
9727
  /**
@@ -9643,13 +9748,19 @@ declare module "components/flow-builder/flow.types" {
9643
9748
  /** A function resolving a node type key to its registered type. */
9644
9749
  export type FlowTypeOf = (type: string) => FlowNodeType | undefined;
9645
9750
  /**
9646
- * Canvas x for each of a node's branch drops: the natural fan position under
9647
- * the source. Pills never shift sideways to chase their child the wire into
9648
- * a pill is always a straight vertical, and any lateral offset to the child is
9649
- * taken up by the elbow below the pill (which still enters the child from
9650
- * straight above).
9751
+ * Canvas x for each of a node's branch drops. Neighbours are spaced by what
9752
+ * they actually occupy two child lanes keep the full spread, while a branch
9753
+ * with nothing wired to it needs only its pill and the run is then shifted so
9754
+ * the *wired* branches stay centred on the node. A step that declares branches
9755
+ * it is not using therefore still runs straight down, instead of fanning empty
9756
+ * lanes across the canvas; and a fully wired fan is spaced exactly as before.
9757
+ *
9758
+ * Pills never shift sideways to chase their child — the wire into a pill is
9759
+ * always a straight vertical, and any lateral offset to the child is taken up
9760
+ * by the elbow below the pill (which still enters the child from straight
9761
+ * above).
9651
9762
  */
9652
- export function branchDropXs(node: FlowNodeInstance, typeOf: FlowTypeOf): number[];
9763
+ export function branchDropXs(node: FlowNodeInstance, typeOf: FlowTypeOf, connections?: FlowConnection[]): number[];
9653
9764
  /**
9654
9765
  * The rects a node occupies on the canvas: its card plus each branch-name pill,
9655
9766
  * at the exact positions the canvas draws them.
@@ -10019,20 +10130,40 @@ declare module "components/flow-builder/modules/flow-canvas/flow-canvas.componen
10019
10130
  */
10020
10131
  private _elbowMidOffsets;
10021
10132
  /**
10022
- * Whether an orthogonal segment passes through any node card (with margin)
10023
- * or the approach zone above one, where incoming arrows land. A foreign wire
10024
- * running just over a card's input port reads as connecting to it, so routes
10025
- * keep well clear of that strip too.
10133
+ * Whether an orthogonal segment passes through any node card (with margin).
10134
+ * With `keepApproachClear`, the strip above each card - where incoming arrows
10135
+ * land - counts as occupied too: a foreign wire running just over a card's
10136
+ * input port reads as connecting to it.
10026
10137
  */
10027
10138
  private _segmentBlocked;
10028
10139
  private _routeClear;
10029
10140
  /**
10030
10141
  * Orthogonal waypoints from a branch exit to a child's input. The wire always
10031
10142
  * enters the input from above (arrow pointing down), and never passes through
10032
- * a node card: each candidate route is checked against every card, scanning
10033
- * alternative lanes / side-steps / detours until one is clear.
10143
+ * a node card.
10144
+ *
10145
+ * The search runs twice: first keeping clear of the strip above every card as
10146
+ * well as the cards themselves, then - if the corridor is genuinely too tight
10147
+ * for that - clear of the cards alone. Only when nothing at all fits does the
10148
+ * wire fall back to the direct line, so a wire drawn over a card now means
10149
+ * there was no way around it rather than that the search gave up.
10034
10150
  */
10035
10151
  private _routePoints;
10152
+ /**
10153
+ * Candidate routes to a child below, tidiest first: the straight drop or the
10154
+ * single elbow, then the same elbow on neighbouring lines, then out around
10155
+ * whatever sits between the two (the shape a loop-back uses - far more
10156
+ * readable than threading a corridor when a wire skips a row it has nothing
10157
+ * to do with), and finally a side-step that jogs out and back.
10158
+ */
10159
+ private _forwardRoutes;
10160
+ /**
10161
+ * Routes that leave the exit, run down the outside of everything they span
10162
+ * vertically, and come back in above the input. Loop-backs always travel this
10163
+ * way rather than squeezing through corridors inside the flow; a forward wire
10164
+ * uses it when the corridor between it and its child is occupied.
10165
+ */
10166
+ private _aroundRoutes;
10036
10167
  private static _pathFrom;
10037
10168
  /**
10038
10169
  * Open output slots ("+" add-points) across all nodes — only rendered while
@@ -10343,6 +10474,13 @@ declare module "components/flow-builder/flow-builder.component" {
10343
10474
  private _duplicateNode;
10344
10475
  /** Canvas position for a node newly placed off a source node's output. */
10345
10476
  private _positionBelowOutput;
10477
+ /**
10478
+ * Whether a node refuses the branch being asked of it: a fixed-output type
10479
+ * has only the branches it declares, so the "new branch" sentinel has nowhere
10480
+ * to go. Checked before the history push, so a refused gesture is a no-op
10481
+ * rather than an empty undo step.
10482
+ */
10483
+ private _refusesBranch;
10346
10484
  /**
10347
10485
  * Resolve an output port id on a node: the "new branch" sentinel materialises a
10348
10486
  * fresh, labelled output port (per-instance), so it exists before connecting.
@@ -10504,6 +10642,8 @@ declare module "components/flow-builder/modules/flow-step/flow-step.component" {
10504
10642
  inputs: string;
10505
10643
  /** JSON array of outputs (`"a"` or `{"id","label"}`), e.g. `'[{"id":"true","label":"TRUE"}]'`. Omit for one default output. */
10506
10644
  outputs: string;
10645
+ /** The declared outputs are the only branches this step has — none can be deleted or added on the canvas. */
10646
+ fixedOutputs: boolean;
10507
10647
  connectedCallback(): void;
10508
10648
  disconnectedCallback(): void;
10509
10649
  protected updated(changed: PropertyValues): void;
@@ -10683,6 +10823,8 @@ declare module "components/page-builder/modules/page-section-card/page-section-c
10683
10823
  selected: boolean;
10684
10824
  /** Set when the section's type has no registered template — renders greyed. */
10685
10825
  unknown: boolean;
10826
+ /** Set when the builder pins this section to the page — drops the remove action. */
10827
+ locked: boolean;
10686
10828
  protected updated(changed: PropertyValues): void;
10687
10829
  private _action;
10688
10830
  private _actionKeydown;
@@ -10758,6 +10900,13 @@ declare module "components/page-builder/page-builder.component" {
10758
10900
  config: string;
10759
10901
  heading: string;
10760
10902
  subheading: string;
10903
+ /**
10904
+ * Section type key that must lead the page. The builder hoists an existing section of
10905
+ * that type to the top, or inserts an empty one, and pins it there: it can't be
10906
+ * removed, reordered or dragged into a slot, and nothing can be dropped above it.
10907
+ * Its content stays fully editable in the inspector.
10908
+ */
10909
+ requiredFirst: string;
10761
10910
  /** Section types to make available, registered into the internal registry. */
10762
10911
  sectionTypes: PageSectionType[];
10763
10912
  /** Collapses the left palette. Auto-set when the builder becomes narrow. */
@@ -10809,6 +10958,7 @@ declare module "components/page-builder/page-builder.component" {
10809
10958
  /** Sets a custom validation message. Pass an empty string to restore validity. */
10810
10959
  setCustomValidity(_message?: string): void;
10811
10960
  handleConfigChange(): void;
10961
+ handleRequiredFirstChange(): void;
10812
10962
  handleSectionTypesChange(): void;
10813
10963
  registerSectionType(type: PageSectionType): this;
10814
10964
  registerSectionTypes(types: PageSectionType[]): this;
@@ -10854,6 +11004,21 @@ declare module "components/page-builder/page-builder.component" {
10854
11004
  private _registerSlottedTemplates;
10855
11005
  /** Normalises and installs an externally provided state; resets selection. */
10856
11006
  private _applyExternalState;
11007
+ /**
11008
+ * Id of the section pinned to the top of the page, or null when `required-first`
11009
+ * is unset. Derived from the state rather than stored on it, so nothing about the
11010
+ * lock leaks into the persisted config.
11011
+ */
11012
+ private get _pinnedId();
11013
+ private _isPinned;
11014
+ /** Lowest top-level index a section may be added or moved to. */
11015
+ private get _firstFreeIndex();
11016
+ /**
11017
+ * Sections reordered so `required-first` leads the page: an existing section of that
11018
+ * type is hoisted to the front, otherwise an empty one is prepended. Returns the
11019
+ * argument unchanged when there is nothing to do, so callers can compare by identity.
11020
+ */
11021
+ private _requireFirst;
10857
11022
  /** Finds a section by id, searching top-level sections and slotted children. */
10858
11023
  private _findSection;
10859
11024
  /** New sections array with the section patched wherever it lives (top level or slot). */