@bloklabs/angular 1.3.0 → 1.4.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 +65 -0
- package/fesm2022/bloklabs-angular.mjs +181 -9
- package/fesm2022/bloklabs-angular.mjs.map +1 -1
- package/package.json +23 -3
- package/types/bloklabs-angular.d.ts +76 -8
package/package.json
CHANGED
|
@@ -1,14 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bloklabs/angular",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Angular bindings for the
|
|
3
|
+
"version": "1.4.0",
|
|
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",
|
|
7
|
+
"homepage": "https://blokeditor.com",
|
|
7
8
|
"repository": {
|
|
8
9
|
"type": "git",
|
|
9
10
|
"url": "git+https://github.com/JackUait/blok.git",
|
|
10
11
|
"directory": "packages/angular"
|
|
11
12
|
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/JackUait/blok/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"blok",
|
|
18
|
+
"angular",
|
|
19
|
+
"angular-component",
|
|
20
|
+
"block-editor",
|
|
21
|
+
"rich-text-editor",
|
|
22
|
+
"wysiwyg",
|
|
23
|
+
"editor",
|
|
24
|
+
"notion",
|
|
25
|
+
"notion-like",
|
|
26
|
+
"headless",
|
|
27
|
+
"block-based",
|
|
28
|
+
"contenteditable",
|
|
29
|
+
"json",
|
|
30
|
+
"typescript"
|
|
31
|
+
],
|
|
12
32
|
"publishConfig": {
|
|
13
33
|
"access": "public"
|
|
14
34
|
},
|
|
@@ -16,7 +36,7 @@
|
|
|
16
36
|
"@angular/common": ">=20 <23",
|
|
17
37
|
"@angular/core": ">=20 <23",
|
|
18
38
|
"@angular/forms": ">=20 <23",
|
|
19
|
-
"@bloklabs/core": "1.
|
|
39
|
+
"@bloklabs/core": "1.4.0"
|
|
20
40
|
},
|
|
21
41
|
"module": "fesm2022/bloklabs-angular.mjs",
|
|
22
42
|
"typings": "./index.d.ts",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { AfterViewInit, EventEmitter, OnDestroy, InjectionToken, EnvironmentProviders, Type, Signal } from '@angular/core';
|
|
2
|
+
import { AfterViewInit, EventEmitter, OnDestroy, InjectionToken, EnvironmentProviders, Type, Signal, ElementRef } from '@angular/core';
|
|
3
3
|
import { ControlValueAccessor } from '@angular/forms';
|
|
4
4
|
import { BlokConfig, EditorWidth, Blok, OutputData, API, BlockMutationEvent, ResolvedTheme, BlocksRenderedPayload, BlockRenderedPayload, OutputBlockData, ThemeMode, LooseOutputData, BlockToolData, BlockTuneData, MarkdownImportConfig, ToolboxConfig, BlockAPI, BlockToolConstructorOptions } from '@bloklabs/core';
|
|
5
5
|
|
|
@@ -18,8 +18,16 @@ type BlokAngularConfig = Omit<BlokConfig, 'holder'> & {
|
|
|
18
18
|
* `BlokEditor`). Delegates instance lifecycle to an internal `BlokContentDirective`
|
|
19
19
|
* and layers the typed reactive input/output API on top.
|
|
20
20
|
*
|
|
21
|
-
* Reactive inputs (`readOnly`, `
|
|
22
|
-
*
|
|
21
|
+
* Reactive inputs (`readOnly`, `hideToolbar`, `inlineToolbar`, `theme`,
|
|
22
|
+
* `width`, `placeholder`, `autofocus`, `styleTokens`, `i18n`, `data`) are
|
|
23
|
+
* synced in place after mount via effects — `hideToolbar` through
|
|
24
|
+
* `editor.toolbar.setHidden()`, `inlineToolbar` through
|
|
25
|
+
* `editor.tools.setInlineToolbar()` (content-compared),
|
|
26
|
+
* `styleTokens` through `editor.tokens.set()` (replace semantics),
|
|
27
|
+
* `i18n` through `editor.i18n.update()` (deep-equal–deduped; seeded at
|
|
28
|
+
* construction so the locale resolves during boot) and `data`
|
|
29
|
+
* through `editor.render()` (deep-equal–deduped); everything else seeds
|
|
30
|
+
* construction.
|
|
23
31
|
*
|
|
24
32
|
* Implementation note: classic `@Input()`/`@ViewChild()` decorators are used
|
|
25
33
|
* (not signal `input()`/`viewChild()`) for JIT compatibility — see
|
|
@@ -68,7 +76,11 @@ declare class BlokEditorComponent implements AfterViewInit, ControlValueAccessor
|
|
|
68
76
|
*/
|
|
69
77
|
onBeforePaste?: (html: string) => string | null;
|
|
70
78
|
private readonly readOnly$;
|
|
71
|
-
set readOnly(value:
|
|
79
|
+
set readOnly(value: BlokConfig['readOnly'] | undefined);
|
|
80
|
+
private readonly hideToolbar$;
|
|
81
|
+
set hideToolbar(value: boolean | undefined);
|
|
82
|
+
private readonly inlineToolbar$;
|
|
83
|
+
set inlineToolbar(value: boolean | string[] | undefined);
|
|
72
84
|
private readonly theme$;
|
|
73
85
|
set theme(value: ThemeMode | undefined);
|
|
74
86
|
private readonly width$;
|
|
@@ -82,6 +94,15 @@ declare class BlokEditorComponent implements AfterViewInit, ControlValueAccessor
|
|
|
82
94
|
*/
|
|
83
95
|
private readonly styleTokens$;
|
|
84
96
|
set styleTokens(value: Record<string, string> | undefined);
|
|
97
|
+
/**
|
|
98
|
+
* Locale, host message overrides and text direction. `config.i18n` was
|
|
99
|
+
* consumed once at boot, so a host driving a language switcher had to
|
|
100
|
+
* recreate the editor (losing caret, focus and undo stack) to relabel the
|
|
101
|
+
* UI; this drives the runtime `i18n.update` API instead. `defaultLocale` is
|
|
102
|
+
* not forwarded — it only affects the INITIAL locale resolution.
|
|
103
|
+
*/
|
|
104
|
+
private readonly i18n$;
|
|
105
|
+
set i18n(value: BlokConfig['i18n'] | undefined);
|
|
85
106
|
private readonly autofocus$;
|
|
86
107
|
set autofocus(value: boolean | undefined);
|
|
87
108
|
private readonly data$;
|
|
@@ -89,7 +110,7 @@ declare class BlokEditorComponent implements AfterViewInit, ControlValueAccessor
|
|
|
89
110
|
tools?: BlokConfig['tools'];
|
|
90
111
|
/**
|
|
91
112
|
* Escape hatch: a full config object for keys without a dedicated input
|
|
92
|
-
* (
|
|
113
|
+
* (sanitizer, minHeight, …). Layered between provideBlok
|
|
93
114
|
* defaults and the discrete inputs.
|
|
94
115
|
*/
|
|
95
116
|
config?: Partial<BlokAngularConfig>;
|
|
@@ -103,6 +124,12 @@ declare class BlokEditorComponent implements AfterViewInit, ControlValueAccessor
|
|
|
103
124
|
private lastRenderedData?;
|
|
104
125
|
/** Last token set pushed through `tokens.set`, for deep-equal deduping. */
|
|
105
126
|
private appliedTokens?;
|
|
127
|
+
/** Last i18n config pushed through `i18n.update`, for deep-equal deduping. */
|
|
128
|
+
private appliedI18n?;
|
|
129
|
+
/** Editor instance the i18n baseline above belongs to. */
|
|
130
|
+
private i18nAppliedFor;
|
|
131
|
+
/** Last value pushed through `tools.setInlineToolbar`, for content-compare deduping. */
|
|
132
|
+
private appliedInlineToolbar?;
|
|
106
133
|
private seededEditor;
|
|
107
134
|
private renderChain;
|
|
108
135
|
/** Registered by `ControlValueAccessor.registerOnChange` (Angular forms). */
|
|
@@ -141,7 +168,7 @@ declare class BlokEditorComponent implements AfterViewInit, ControlValueAccessor
|
|
|
141
168
|
/** Form disabled state maps to the editor's read-only mode (via the readOnly effect). */
|
|
142
169
|
setDisabledState(isDisabled: boolean): void;
|
|
143
170
|
static ɵfac: i0.ɵɵFactoryDeclaration<BlokEditorComponent, never>;
|
|
144
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<BlokEditorComponent, "blok-editor", ["blok"], { "onBeforeRender": { "alias": "onBeforeRender"; "required": false; }; "onBeforePaste": { "alias": "onBeforePaste"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; "width": { "alias": "width"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "styleTokens": { "alias": "styleTokens"; "required": false; }; "autofocus": { "alias": "autofocus"; "required": false; }; "data": { "alias": "data"; "required": false; }; "tools": { "alias": "tools"; "required": false; }; "config": { "alias": "config"; "required": false; }; "recreateKey": { "alias": "recreateKey"; "required": false; }; }, { "ready": "ready"; "dataChange": "dataChange"; "save": "save"; "change": "change"; "afterRender": "afterRender"; "themeChange": "themeChange"; "blocksRendered": "blocksRendered"; "blockRendered": "blockRendered"; }, never, never, true, never>;
|
|
171
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BlokEditorComponent, "blok-editor", ["blok"], { "onBeforeRender": { "alias": "onBeforeRender"; "required": false; }; "onBeforePaste": { "alias": "onBeforePaste"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; "hideToolbar": { "alias": "hideToolbar"; "required": false; }; "inlineToolbar": { "alias": "inlineToolbar"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; "width": { "alias": "width"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "styleTokens": { "alias": "styleTokens"; "required": false; }; "i18n": { "alias": "i18n"; "required": false; }; "autofocus": { "alias": "autofocus"; "required": false; }; "data": { "alias": "data"; "required": false; }; "tools": { "alias": "tools"; "required": false; }; "config": { "alias": "config"; "required": false; }; "recreateKey": { "alias": "recreateKey"; "required": false; }; }, { "ready": "ready"; "dataChange": "dataChange"; "save": "save"; "change": "change"; "afterRender": "afterRender"; "themeChange": "themeChange"; "blocksRendered": "blocksRendered"; "blockRendered": "blockRendered"; }, never, never, true, never>;
|
|
145
172
|
}
|
|
146
173
|
|
|
147
174
|
/**
|
|
@@ -648,6 +675,47 @@ declare function createAngularBlock<Data = BlockToolData>(spec: CreateAngularBlo
|
|
|
648
675
|
*/
|
|
649
676
|
declare function injectBlocks(editor: Signal<Blok | null>): UseBlocksApi;
|
|
650
677
|
|
|
678
|
+
/** How the caller names the DOM scope to observe. */
|
|
679
|
+
type BlokReadyScope = (() => Element | ElementRef<Element> | null | undefined) | ElementRef<Element> | Element | null;
|
|
680
|
+
/** Options accepted by {@link injectBlokReady}. */
|
|
681
|
+
interface InjectBlokReadyOptions {
|
|
682
|
+
/**
|
|
683
|
+
* Restrict the wait to editors mounted inside this element. Accepts an
|
|
684
|
+
* element, an `ElementRef`, or a getter/signal returning either — the getter
|
|
685
|
+
* form lets you pass `() => this.scopeRef?.nativeElement` from a field
|
|
686
|
+
* initializer, before the view exists. It is re-read on every readiness
|
|
687
|
+
* change.
|
|
688
|
+
*
|
|
689
|
+
* Omit it to observe every editor on the page. Passing it while it still
|
|
690
|
+
* resolves to null reports NOT ready — an unresolved scope must never fall
|
|
691
|
+
* back to the page-global one.
|
|
692
|
+
*/
|
|
693
|
+
within?: BlokReadyScope;
|
|
694
|
+
/**
|
|
695
|
+
* `'ready'` (default) settles when each editor has finished booting.
|
|
696
|
+
* `'rendered'` also waits for its content to be in the DOM and re-arms on
|
|
697
|
+
* every post-boot re-render.
|
|
698
|
+
*/
|
|
699
|
+
settleOn?: 'ready' | 'rendered';
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Angular factory exposing the live readiness of the Blok editors in a DOM
|
|
703
|
+
* scope as a boolean signal.
|
|
704
|
+
*
|
|
705
|
+
* The readiness logic itself is framework-agnostic and lives in core
|
|
706
|
+
* (`Blok.readyState` / `Blok.subscribeReady`) — the SAME implementation behind
|
|
707
|
+
* React's and Vue's `useBlokReady`, so the three adapters cannot drift. This
|
|
708
|
+
* wrapper supplies only Angular's reactivity: a signal re-read on every
|
|
709
|
+
* registry change, unsubscribed through the injector's `DestroyRef`.
|
|
710
|
+
*
|
|
711
|
+
* Call it in an injection context (component constructor / field initializer).
|
|
712
|
+
* The signal starts `false` and takes its first real reading in
|
|
713
|
+
* `afterNextRender` — browser-only by contract, and late enough for a
|
|
714
|
+
* `@ViewChild` scope to exist. Over-waiting is safe; under-waiting is a bug.
|
|
715
|
+
* @param options - scope and readiness depth
|
|
716
|
+
*/
|
|
717
|
+
declare function injectBlokReady(options?: InjectBlokReadyOptions): Signal<boolean>;
|
|
718
|
+
|
|
651
719
|
/**
|
|
652
720
|
* Context handed to a `createAngularBlock` component. Delivered via DI (the
|
|
653
721
|
* BLOK_BLOCK_CONTEXT token) rather than @Input, because core constructs the tool
|
|
@@ -680,5 +748,5 @@ interface AngularBlockRenderContext<Data> {
|
|
|
680
748
|
/** DI token carrying the per-block render context into the authored component. */
|
|
681
749
|
declare const BLOK_BLOCK_CONTEXT: InjectionToken<AngularBlockRenderContext<unknown>>;
|
|
682
750
|
|
|
683
|
-
export { BLOK_BLOCK_CONTEXT, BLOK_DEFAULT_CONFIG, BlokContentDirective, BlokEditorComponent, createAngularBlock, injectBlocks, provideBlok };
|
|
684
|
-
export type { AngularBlockRenderContext, BlockNode, BlokAngularConfig, CaretTarget, CreateAngularBlockSpec, InsertPosition, InsertSpec, MoveTarget, PropSchema, PropSchemaEntry, TreeInsertSpec, UseBlocksApi };
|
|
751
|
+
export { BLOK_BLOCK_CONTEXT, BLOK_DEFAULT_CONFIG, BlokContentDirective, BlokEditorComponent, createAngularBlock, injectBlocks, injectBlokReady, provideBlok };
|
|
752
|
+
export type { AngularBlockRenderContext, BlockNode, BlokAngularConfig, BlokReadyScope, CaretTarget, CreateAngularBlockSpec, InjectBlokReadyOptions, InsertPosition, InsertSpec, MoveTarget, PropSchema, PropSchemaEntry, TreeInsertSpec, UseBlocksApi };
|