@bloklabs/angular 1.8.0 → 1.10.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bloklabs/angular",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "Angular block editor — official Angular bindings for Blok, the headless Notion-like rich text editor. Standalone components that render blocks and save to JSON (APF partial-Ivy bundle).",
5
5
  "license": "Apache-2.0",
6
6
  "author": "JackUait",
@@ -36,7 +36,7 @@
36
36
  "@angular/common": ">=20 <23",
37
37
  "@angular/core": ">=20 <23",
38
38
  "@angular/forms": ">=20 <23",
39
- "@bloklabs/core": "1.8.0"
39
+ "@bloklabs/core": "1.10.0"
40
40
  },
41
41
  "module": "fesm2022/bloklabs-angular.mjs",
42
42
  "typings": "./index.d.ts",
@@ -822,6 +822,28 @@ declare function createAngularBlock<Data = BlockToolData>(spec: CreateAngularBlo
822
822
  readonly isReadOnlySupported: boolean;
823
823
  };
824
824
 
825
+ /** Options for {@link injectBlocks}. */
826
+ interface InjectBlocksOptions {
827
+ /**
828
+ * Invalidate reads only for changes inside the subtree rooted at this block id
829
+ * (the block itself or any descendant). Omit — or pass `null` — for the
830
+ * document-wide default.
831
+ *
832
+ * This bounds REACTIVITY, not reads: the returned API still sees the whole
833
+ * tree, so a scoped consumer can still `getById` anything. Reach for it in a
834
+ * container block that renders only its own children — unscoped, such a block
835
+ * invalidates on every keystroke anywhere in the document, and a page of N
836
+ * containers turns one keystroke into N re-renders.
837
+ *
838
+ * Accepted as a plain value or a signal (like `editor`) and read at EMIT time,
839
+ * so changing it takes effect immediately with no re-subscription.
840
+ *
841
+ * A change whose block cannot be placed in the tree (a removal that emits
842
+ * after the block is gone) counts as in-scope: skipping it would leave a
843
+ * container rendering a child that no longer exists.
844
+ */
845
+ within?: Signal<string | null> | string | null;
846
+ }
825
847
  /**
826
848
  * Angular factory exposing an id/parentId-relative, reactive view of the block
827
849
  * tree. Reads refresh whenever the editor emits `block changed`; mutators route
@@ -855,8 +877,10 @@ declare function createAngularBlock<Data = BlockToolData>(spec: CreateAngularBlo
855
877
  * `ed === sub.editor` makes it a no-op, so no double-subscription occurs.
856
878
  *
857
879
  * @param editor - a signal of the Blok instance, or null pre-ready
880
+ * @param options - reactivity options; see {@link InjectBlocksOptions.within} to
881
+ * scope invalidation to one block's subtree
858
882
  */
859
- declare function injectBlocks(editor: Signal<Blok | null>): UseBlocksApi;
883
+ declare function injectBlocks(editor: Signal<Blok | null>, options?: InjectBlocksOptions): UseBlocksApi;
860
884
 
861
885
  /** How the caller names the DOM scope to observe. */
862
886
  type BlokReadyScope = (() => Element | ElementRef<Element> | null | undefined) | ElementRef<Element> | Element | null;
@@ -954,13 +978,44 @@ interface AngularBlockRenderContext<Data> {
954
978
  * by identity), so decoration is attributes, never wrapper elements.
955
979
  * Attributes the callback stops producing are removed on the next pass.
956
980
  *
981
+ * `childContentAttributes` is the same decoration applied one level IN — on
982
+ * each child's `[data-blok-element-content]` wrapper instead of its holder —
983
+ * and is remembered the same way. Core's decoration law blesses both, and a
984
+ * container needs both: the holder is the child's outer box (rails, indices,
985
+ * hover states), the content wrapper is where the child's own text box begins,
986
+ * which is what a numbered rail or a connector line has to align to. Reach for
987
+ * it instead of walking core's wrapper chain from a holder hook (`[data-step] >
988
+ * [data-blok-element-content] > …`) — those selectors encode engine DOM in host
989
+ * CSS and break when that structure changes. A child whose DOM has not
990
+ * committed yet has no wrapper to write to and is stamped on the next pass.
991
+ *
957
992
  * Writing on a child's holder is inert by design: core's mutation filter drops
958
993
  * a holder-targeted attribute record for the child block and suppresses it for
959
994
  * the container. The guarantee stops at the holder and its
960
995
  * `[data-blok-element-content]` wrapper — writing AT or BELOW a child's tool
961
996
  * root DOES score as that child's edit.
962
997
  */
963
- mountChildren: (host: HTMLElement, childAttributes?: ChildAttributesFn) => void;
998
+ mountChildren: (host: HTMLElement, childAttributes?: ChildAttributesFn, childContentAttributes?: ChildAttributesFn) => void;
999
+ /**
1000
+ * Name the element the +/drag toolbar should vertically center on, from inside
1001
+ * the component: `ctx.setToolbarAnchor(this.head().nativeElement)` in
1002
+ * `ngAfterViewInit`. The Angular counterpart of React's/Vue's
1003
+ * `toolbarAnchorRef` — core's `getToolbarAnchorElement` is otherwise a
1004
+ * `(host, block) => Element` hook resolved OUTSIDE the component, so pointing
1005
+ * at an element the template renders meant inventing a data attribute and
1006
+ * `querySelector`-ing for it from
1007
+ * `CreateAngularBlockSpec.getToolbarAnchorElement`.
1008
+ *
1009
+ * A container block whose own chrome is not editable needs an anchor: with
1010
+ * none, core centers the toolbar on the first `[contenteditable]` under the
1011
+ * host, which for a container is its FIRST CHILD BLOCK — parking the +/drag
1012
+ * handles halfway down, beside content that has a toolbar of its own.
1013
+ *
1014
+ * The element set here outranks the declared hook while it is MOUNTED; once it
1015
+ * detaches (or `null` is passed) the hook takes over again, so the toolbar is
1016
+ * never positioned against a stale node. Never calling it keeps core's default.
1017
+ */
1018
+ setToolbarAnchor: (element: HTMLElement | null) => void;
964
1019
  }
965
1020
  /** DI token carrying the per-block render context into the authored component. */
966
1021
  declare const BLOK_BLOCK_CONTEXT: InjectionToken<AngularBlockRenderContext<unknown>>;
@@ -997,4 +1052,4 @@ declare const BLOK_EDITOR_INSTANCE: InjectionToken<Signal<Blok | null>>;
997
1052
  declare function injectBlokInstance(): Signal<Blok | null>;
998
1053
 
999
1054
  export { BLOK_BLOCK_CONTEXT, BLOK_DEFAULT_CONFIG, BLOK_EDITOR_INSTANCE, BlokContentDirective, BlokEditorComponent, createAngularBlock, injectBlocks, injectBlokInstance, injectBlokReady, provideBlok };
1000
- export type { AngularBlockMountedContext, AngularBlockRenderContext, BlockNode, BlockToolStatics, BlokAngularConfig, BlokReadyScope, CaretTarget, ChildAttributes, ChildAttributesFn, CreateAngularBlockSpec, InjectBlokReadyOptions, InsertPosition, InsertSpec, MoveTarget, PropSchema, PropSchemaEntry, TreeInsertSpec, UseBlocksApi };
1055
+ export type { AngularBlockMountedContext, AngularBlockRenderContext, BlockNode, BlockToolStatics, BlokAngularConfig, BlokReadyScope, CaretTarget, ChildAttributes, ChildAttributesFn, CreateAngularBlockSpec, InjectBlocksOptions, InjectBlokReadyOptions, InsertPosition, InsertSpec, MoveTarget, PropSchema, PropSchemaEntry, TreeInsertSpec, UseBlocksApi };