@bloklabs/angular 1.3.0 → 1.4.1
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 +192 -9
- package/fesm2022/bloklabs-angular.mjs.map +1 -1
- package/package.json +23 -3
- package/types/bloklabs-angular.d.ts +81 -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.1",
|
|
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.1"
|
|
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
|
|
@@ -67,8 +75,17 @@ declare class BlokEditorComponent implements AfterViewInit, ControlValueAccessor
|
|
|
67
75
|
* (possibly modified) html, or null to drop the paste.
|
|
68
76
|
*/
|
|
69
77
|
onBeforePaste?: (html: string) => string | null;
|
|
78
|
+
/**
|
|
79
|
+
* Error channel (core `onError`). Fires with the raised error whenever an
|
|
80
|
+
* editor operation — currently serialization — fails instead of only logging.
|
|
81
|
+
*/
|
|
82
|
+
onError?: BlokConfig['onError'];
|
|
70
83
|
private readonly readOnly$;
|
|
71
|
-
set readOnly(value:
|
|
84
|
+
set readOnly(value: BlokConfig['readOnly'] | undefined);
|
|
85
|
+
private readonly hideToolbar$;
|
|
86
|
+
set hideToolbar(value: boolean | undefined);
|
|
87
|
+
private readonly inlineToolbar$;
|
|
88
|
+
set inlineToolbar(value: boolean | string[] | undefined);
|
|
72
89
|
private readonly theme$;
|
|
73
90
|
set theme(value: ThemeMode | undefined);
|
|
74
91
|
private readonly width$;
|
|
@@ -82,6 +99,15 @@ declare class BlokEditorComponent implements AfterViewInit, ControlValueAccessor
|
|
|
82
99
|
*/
|
|
83
100
|
private readonly styleTokens$;
|
|
84
101
|
set styleTokens(value: Record<string, string> | undefined);
|
|
102
|
+
/**
|
|
103
|
+
* Locale, host message overrides and text direction. `config.i18n` was
|
|
104
|
+
* consumed once at boot, so a host driving a language switcher had to
|
|
105
|
+
* recreate the editor (losing caret, focus and undo stack) to relabel the
|
|
106
|
+
* UI; this drives the runtime `i18n.update` API instead. `defaultLocale` is
|
|
107
|
+
* not forwarded — it only affects the INITIAL locale resolution.
|
|
108
|
+
*/
|
|
109
|
+
private readonly i18n$;
|
|
110
|
+
set i18n(value: BlokConfig['i18n'] | undefined);
|
|
85
111
|
private readonly autofocus$;
|
|
86
112
|
set autofocus(value: boolean | undefined);
|
|
87
113
|
private readonly data$;
|
|
@@ -89,7 +115,7 @@ declare class BlokEditorComponent implements AfterViewInit, ControlValueAccessor
|
|
|
89
115
|
tools?: BlokConfig['tools'];
|
|
90
116
|
/**
|
|
91
117
|
* Escape hatch: a full config object for keys without a dedicated input
|
|
92
|
-
* (
|
|
118
|
+
* (sanitizer, minHeight, …). Layered between provideBlok
|
|
93
119
|
* defaults and the discrete inputs.
|
|
94
120
|
*/
|
|
95
121
|
config?: Partial<BlokAngularConfig>;
|
|
@@ -103,6 +129,12 @@ declare class BlokEditorComponent implements AfterViewInit, ControlValueAccessor
|
|
|
103
129
|
private lastRenderedData?;
|
|
104
130
|
/** Last token set pushed through `tokens.set`, for deep-equal deduping. */
|
|
105
131
|
private appliedTokens?;
|
|
132
|
+
/** Last i18n config pushed through `i18n.update`, for deep-equal deduping. */
|
|
133
|
+
private appliedI18n?;
|
|
134
|
+
/** Editor instance the i18n baseline above belongs to. */
|
|
135
|
+
private i18nAppliedFor;
|
|
136
|
+
/** Last value pushed through `tools.setInlineToolbar`, for content-compare deduping. */
|
|
137
|
+
private appliedInlineToolbar?;
|
|
106
138
|
private seededEditor;
|
|
107
139
|
private renderChain;
|
|
108
140
|
/** Registered by `ControlValueAccessor.registerOnChange` (Angular forms). */
|
|
@@ -141,7 +173,7 @@ declare class BlokEditorComponent implements AfterViewInit, ControlValueAccessor
|
|
|
141
173
|
/** Form disabled state maps to the editor's read-only mode (via the readOnly effect). */
|
|
142
174
|
setDisabledState(isDisabled: boolean): void;
|
|
143
175
|
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>;
|
|
176
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BlokEditorComponent, "blok-editor", ["blok"], { "onBeforeRender": { "alias": "onBeforeRender"; "required": false; }; "onBeforePaste": { "alias": "onBeforePaste"; "required": false; }; "onError": { "alias": "onError"; "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
177
|
}
|
|
146
178
|
|
|
147
179
|
/**
|
|
@@ -648,6 +680,47 @@ declare function createAngularBlock<Data = BlockToolData>(spec: CreateAngularBlo
|
|
|
648
680
|
*/
|
|
649
681
|
declare function injectBlocks(editor: Signal<Blok | null>): UseBlocksApi;
|
|
650
682
|
|
|
683
|
+
/** How the caller names the DOM scope to observe. */
|
|
684
|
+
type BlokReadyScope = (() => Element | ElementRef<Element> | null | undefined) | ElementRef<Element> | Element | null;
|
|
685
|
+
/** Options accepted by {@link injectBlokReady}. */
|
|
686
|
+
interface InjectBlokReadyOptions {
|
|
687
|
+
/**
|
|
688
|
+
* Restrict the wait to editors mounted inside this element. Accepts an
|
|
689
|
+
* element, an `ElementRef`, or a getter/signal returning either — the getter
|
|
690
|
+
* form lets you pass `() => this.scopeRef?.nativeElement` from a field
|
|
691
|
+
* initializer, before the view exists. It is re-read on every readiness
|
|
692
|
+
* change.
|
|
693
|
+
*
|
|
694
|
+
* Omit it to observe every editor on the page. Passing it while it still
|
|
695
|
+
* resolves to null reports NOT ready — an unresolved scope must never fall
|
|
696
|
+
* back to the page-global one.
|
|
697
|
+
*/
|
|
698
|
+
within?: BlokReadyScope;
|
|
699
|
+
/**
|
|
700
|
+
* `'ready'` (default) settles when each editor has finished booting.
|
|
701
|
+
* `'rendered'` also waits for its content to be in the DOM and re-arms on
|
|
702
|
+
* every post-boot re-render.
|
|
703
|
+
*/
|
|
704
|
+
settleOn?: 'ready' | 'rendered';
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Angular factory exposing the live readiness of the Blok editors in a DOM
|
|
708
|
+
* scope as a boolean signal.
|
|
709
|
+
*
|
|
710
|
+
* The readiness logic itself is framework-agnostic and lives in core
|
|
711
|
+
* (`Blok.readyState` / `Blok.subscribeReady`) — the SAME implementation behind
|
|
712
|
+
* React's and Vue's `useBlokReady`, so the three adapters cannot drift. This
|
|
713
|
+
* wrapper supplies only Angular's reactivity: a signal re-read on every
|
|
714
|
+
* registry change, unsubscribed through the injector's `DestroyRef`.
|
|
715
|
+
*
|
|
716
|
+
* Call it in an injection context (component constructor / field initializer).
|
|
717
|
+
* The signal starts `false` and takes its first real reading in
|
|
718
|
+
* `afterNextRender` — browser-only by contract, and late enough for a
|
|
719
|
+
* `@ViewChild` scope to exist. Over-waiting is safe; under-waiting is a bug.
|
|
720
|
+
* @param options - scope and readiness depth
|
|
721
|
+
*/
|
|
722
|
+
declare function injectBlokReady(options?: InjectBlokReadyOptions): Signal<boolean>;
|
|
723
|
+
|
|
651
724
|
/**
|
|
652
725
|
* Context handed to a `createAngularBlock` component. Delivered via DI (the
|
|
653
726
|
* BLOK_BLOCK_CONTEXT token) rather than @Input, because core constructs the tool
|
|
@@ -680,5 +753,5 @@ interface AngularBlockRenderContext<Data> {
|
|
|
680
753
|
/** DI token carrying the per-block render context into the authored component. */
|
|
681
754
|
declare const BLOK_BLOCK_CONTEXT: InjectionToken<AngularBlockRenderContext<unknown>>;
|
|
682
755
|
|
|
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 };
|
|
756
|
+
export { BLOK_BLOCK_CONTEXT, BLOK_DEFAULT_CONFIG, BlokContentDirective, BlokEditorComponent, createAngularBlock, injectBlocks, injectBlokReady, provideBlok };
|
|
757
|
+
export type { AngularBlockRenderContext, BlockNode, BlokAngularConfig, BlokReadyScope, CaretTarget, CreateAngularBlockSpec, InjectBlokReadyOptions, InsertPosition, InsertSpec, MoveTarget, PropSchema, PropSchemaEntry, TreeInsertSpec, UseBlocksApi };
|