@bloklabs/angular 1.12.0 → 1.14.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @bloklabs/angular
2
2
 
3
- The Angular block editor bindings for [Blok](https://blokeditor.com) — a headless, Notion-like rich text editor whose content is JSON blocks, not HTML.
3
+ The Angular block editor bindings for [Blok](https://blokeditor.com). Blok is a headless, Notion-like rich text editor whose content is JSON blocks, not HTML.
4
4
 
5
5
  ## Install
6
6
 
@@ -312,10 +312,10 @@ class BlokContentDirective {
312
312
  this.registry = undefined;
313
313
  this.instance.set(null);
314
314
  }
315
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: BlokContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
316
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: BlokContentDirective, isStandalone: true, selector: "[blokContent]", inputs: { config: "config", recreateKey: "recreateKey" }, outputs: { ready: "ready" }, ngImport: i0 });
315
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: BlokContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
316
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: BlokContentDirective, isStandalone: true, selector: "[blokContent]", inputs: { config: "config", recreateKey: "recreateKey" }, outputs: { ready: "ready" }, ngImport: i0 });
317
317
  }
318
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: BlokContentDirective, decorators: [{
318
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: BlokContentDirective, decorators: [{
319
319
  type: Directive,
320
320
  args: [{
321
321
  selector: '[blokContent]',
@@ -2936,6 +2936,17 @@ const applyChildDecoration = (ledger, children, decorators) => {
2936
2936
  */
2937
2937
  const BlockChildrenMounted = 'block:childrenMounted';
2938
2938
 
2939
+ /**
2940
+ * Warning text for a controlled `data` change the adapter refuses to render
2941
+ * under collaboration. Kept verbatim in all three adapters (they share no code).
2942
+ * @param doc - the collaboration document id, for the reset endpoint in the text
2943
+ * @returns the message to warn with, once per adapter instance
2944
+ */
2945
+ const collaborationDataIgnoredMessage = (doc) => '[Blok] `data` is ignored while collaboration is on: the document lives on the sync service ' +
2946
+ 'and is shared with everyone editing it, so replacing it from this editor would overwrite their work. ' +
2947
+ `To replace the whole document, call POST /sync/${doc ?? '{doc}'}/reset on your server — ` +
2948
+ 'it reloads the document from your own document endpoint and every open editor picks it up. ' +
2949
+ 'To change part of it, use the blocks API (insert/update/delete).';
2939
2950
  /**
2940
2951
  * The blessed all-in-one Angular component for embedding Blok (mirrors React's
2941
2952
  * `BlokEditor`). Delegates instance lifecycle to an internal `BlokContentDirective`
@@ -3107,6 +3118,19 @@ class BlokEditorComponent {
3107
3118
  appliedInlineToolbar;
3108
3119
  seededEditor = null;
3109
3120
  renderChain = Promise.resolve();
3121
+ /** One collaboration warning per component instance (see the data effect). */
3122
+ collaborationWarned = false;
3123
+ /**
3124
+ * The `collaboration` the live editor was CONSTRUCTED with. The key is
3125
+ * mount-fixed, so dropping it from `[config]` (`collaboration: on ? {...} :
3126
+ * undefined`) cannot turn a live session into a single-player editor —
3127
+ * reading the current input instead would let that change fall through into
3128
+ * render(), which refuses under collaboration and rejects with nothing
3129
+ * surfaced anywhere.
3130
+ */
3131
+ constructedCollaboration;
3132
+ /** Editor the capture above belongs to (recaptured on recreate). */
3133
+ collaborationCapturedFor = null;
3110
3134
  /** Registered by `ControlValueAccessor.registerOnChange` (Angular forms). */
3111
3135
  cvaOnChange;
3112
3136
  cvaOnTouched;
@@ -3381,6 +3405,16 @@ class BlokEditorComponent {
3381
3405
  });
3382
3406
  }
3383
3407
  constructor() {
3408
+ // Registered FIRST so the capture lands before the data effect below can
3409
+ // read it. `collaboration` reaches the directive through `buildConfig()`,
3410
+ // which is read once per build; this records what that build received.
3411
+ effect(() => {
3412
+ const editor = this.instance();
3413
+ if (editor !== null && editor !== this.collaborationCapturedFor) {
3414
+ this.collaborationCapturedFor = editor;
3415
+ this.constructedCollaboration = this.escapeHatchConfig().collaboration;
3416
+ }
3417
+ });
3384
3418
  // Each effect reads `instance()` so it re-applies once the editor appears
3385
3419
  // (the Angular analog of React's `editor` effect-dependency).
3386
3420
  effect(() => {
@@ -3516,6 +3550,21 @@ class BlokEditorComponent {
3516
3550
  if (baseline !== undefined && equalsOutputData(data, baseline)) {
3517
3551
  return;
3518
3552
  }
3553
+ // Under collaboration the document belongs to the sync service, and
3554
+ // render() refuses a wholesale replace — so don't attempt one. The input's
3555
+ // premise ("this value IS the document") does not hold here. Decided
3556
+ // against the MOUNTED config, never the current input: `collaboration` is
3557
+ // mount-fixed, so a host that drops the key is still driving a
3558
+ // collaboration session and deserves the warning rather than a silently
3559
+ // rejected render.
3560
+ const collaboration = this.constructedCollaboration;
3561
+ if (collaboration !== undefined) {
3562
+ if (!this.collaborationWarned) {
3563
+ this.collaborationWarned = true;
3564
+ console.warn(collaborationDataIgnoredMessage(collaboration.doc));
3565
+ }
3566
+ return;
3567
+ }
3519
3568
  this.lastRenderedData = data;
3520
3569
  // `data` may be null (a controlled "clear to empty"); render() throws on
3521
3570
  // null, so normalize null → { blocks: [] } at the boundary.
@@ -3571,8 +3620,8 @@ class BlokEditorComponent {
3571
3620
  setDisabledState(isDisabled) {
3572
3621
  this.readOnly$.set(isDisabled);
3573
3622
  }
3574
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: BlokEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3575
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: BlokEditorComponent, isStandalone: true, selector: "blok-editor", inputs: { onBeforeRender: "onBeforeRender", onBeforePaste: "onBeforePaste", onError: "onError", readOnly: "readOnly", hideToolbar: "hideToolbar", toolbarPosition: "toolbarPosition", inlineToolbar: "inlineToolbar", theme: "theme", width: "width", placeholder: "placeholder", styleTokens: "styleTokens", i18n: "i18n", autofocus: "autofocus", data: "data", tools: "tools", migrations: "migrations", config: "config", recreateKey: "recreateKey" }, outputs: { ready: "ready", dataChange: "dataChange", save: "save", change: "change", afterRender: "afterRender", themeChange: "themeChange", blocksRendered: "blocksRendered", blockRendered: "blockRendered" }, providers: [
3623
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: BlokEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3624
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.4", type: BlokEditorComponent, isStandalone: true, selector: "blok-editor", inputs: { onBeforeRender: "onBeforeRender", onBeforePaste: "onBeforePaste", onError: "onError", readOnly: "readOnly", hideToolbar: "hideToolbar", toolbarPosition: "toolbarPosition", inlineToolbar: "inlineToolbar", theme: "theme", width: "width", placeholder: "placeholder", styleTokens: "styleTokens", i18n: "i18n", autofocus: "autofocus", data: "data", tools: "tools", migrations: "migrations", config: "config", recreateKey: "recreateKey" }, outputs: { ready: "ready", dataChange: "dataChange", save: "save", change: "change", afterRender: "afterRender", themeChange: "themeChange", blocksRendered: "blocksRendered", blockRendered: "blockRendered" }, providers: [
3576
3625
  {
3577
3626
  provide: NG_VALUE_ACCESSOR,
3578
3627
  useExisting: forwardRef(() => BlokEditorComponent),
@@ -3580,7 +3629,7 @@ class BlokEditorComponent {
3580
3629
  },
3581
3630
  ], viewQueries: [{ propertyName: "contentQuery", first: true, predicate: BlokContentDirective, descendants: true }], exportAs: ["blok"], ngImport: i0, template: `<div blokContent [config]="buildConfig()" [recreateKey]="recreateKey"></div>`, isInline: true, dependencies: [{ kind: "directive", type: BlokContentDirective, selector: "[blokContent]", inputs: ["config", "recreateKey"], outputs: ["ready"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3582
3631
  }
3583
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: BlokEditorComponent, decorators: [{
3632
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: BlokEditorComponent, decorators: [{
3584
3633
  type: Component,
3585
3634
  args: [{
3586
3635
  selector: 'blok-editor',