@domternal/angular 0.6.2 → 0.7.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.
@@ -1,11 +1,13 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { OnDestroy, ElementRef } from '@angular/core';
3
3
  import { ControlValueAccessor } from '@angular/forms';
4
- import { AnyExtension, Content, FocusPosition, Editor, JSONContent, IconSet, ToolbarLayoutEntry, ToolbarGroup, ToolbarDropdown, ToolbarButton, ToolbarItem } from '@domternal/core';
4
+ import * as _domternal_core from '@domternal/core';
5
+ import { AnyExtension, Content, FocusPosition, Editor, JSONContent, IconSet, ToolbarLayoutEntry, ToolbarGroup, ToolbarDropdown, ToolbarButton, ToolbarItem, FloatingMenuItemsOverride, FloatingMenuItem } from '@domternal/core';
5
6
  export { AnyExtension, Content, Editor, FocusPosition, JSONContent } from '@domternal/core';
6
7
  import { SafeHtml } from '@angular/platform-browser';
7
8
  import * as prosemirror_state from 'prosemirror-state';
8
9
  import * as prosemirror_view from 'prosemirror-view';
10
+ import { FloatingMenuKeymap } from '@domternal/extension-block-menu';
9
11
 
10
12
  declare const DEFAULT_EXTENSIONS: AnyExtension[];
11
13
  declare class DomternalEditorComponent implements ControlValueAccessor, OnDestroy {
@@ -77,7 +79,7 @@ declare class DomternalToolbarComponent implements OnDestroy {
77
79
  private ngZone;
78
80
  private elRef;
79
81
  private sanitizer;
80
- /** SafeHtml cache same reference returned for same key, prevents DOM churn */
82
+ /** SafeHtml cache - same reference returned for same key, prevents DOM churn */
81
83
  private htmlCache;
82
84
  private readonly dropdownCaret;
83
85
  constructor();
@@ -89,7 +91,7 @@ declare class DomternalToolbarComponent implements OnDestroy {
89
91
  getDropdownTriggerHtml(dropdown: ToolbarDropdown): SafeHtml;
90
92
  /**
91
93
  * Returns 'true' when an emitEvent button's panel is open, null otherwise.
92
- * Maps to [attr.aria-expanded] null removes the attribute entirely.
94
+ * Maps to [attr.aria-expanded] - null removes the attribute entirely.
93
95
  */
94
96
  getAriaExpanded(item: ToolbarButton): string | null;
95
97
  getFlatIndex(name: string): number;
@@ -112,7 +114,7 @@ declare class DomternalToolbarComponent implements OnDestroy {
112
114
  private destroyController;
113
115
  private syncState;
114
116
  private getComputedStyleAtCursor;
115
- /** Read only inline style no computed fallback (used for font-family). */
117
+ /** Read only inline style - no computed fallback (used for font-family). */
116
118
  private getInlineStyleAtCursor;
117
119
  private focusCurrentButton;
118
120
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DomternalToolbarComponent, never>;
@@ -123,7 +125,7 @@ interface BubbleMenuSeparator {
123
125
  type: 'separator';
124
126
  name: string;
125
127
  }
126
- type BubbleMenuItem = ToolbarButton | BubbleMenuSeparator;
128
+ type BubbleMenuItem = ToolbarButton | ToolbarDropdown | BubbleMenuSeparator;
127
129
  declare class DomternalBubbleMenuComponent implements OnDestroy {
128
130
  readonly editor: _angular_core.InputSignal<Editor>;
129
131
  readonly shouldShow: _angular_core.InputSignal<(props: {
@@ -140,25 +142,72 @@ declare class DomternalBubbleMenuComponent implements OnDestroy {
140
142
  readonly items: _angular_core.InputSignal<string[]>;
141
143
  /** Context-aware: map context names to item arrays, `true` for all valid items, or `null` to disable */
142
144
  readonly contexts: _angular_core.InputSignal<Record<string, true | string[]>>;
143
- /** Internal — updated on transactions. Not meant to be set from outside. */
145
+ /**
146
+ * Custom icon overrides. Falls back to default Phosphor icons for unmapped keys.
147
+ * For nullable bindings, use `iconsSignal() ?? {}` to satisfy strict template checks.
148
+ */
149
+ readonly icons: _angular_core.InputSignal<IconSet>;
150
+ /**
151
+ * Returns the effective contexts map: the explicit `contexts` input
152
+ * when provided, the standard default when neither `contexts` nor
153
+ * `items` is set, or `undefined` (items-mode) when only `items` is set.
154
+ * The standard default is richer when the editor sits inside
155
+ * `.dm-notion-mode`.
156
+ */
157
+ private resolveContexts;
158
+ /** Internal - updated on transactions. Not meant to be set from outside. */
144
159
  readonly resolvedItems: _angular_core.WritableSignal<BubbleMenuItem[]>;
160
+ /** Internal - true when the BlockContextMenu extension is loaded; toggles the "..." trailing button. */
161
+ readonly showBlockMenuButton: _angular_core.WritableSignal<boolean>;
162
+ /** Internal - true when the selection spans more than one top-level block; the "..." trigger is disabled in that case because block-level commands have no unambiguous target. */
163
+ readonly blockMenuButtonDisabled: _angular_core.WritableSignal<boolean>;
164
+ /** Internal - true when the current selection is a NodeSelection (image, HR). The text-color and block-context triggers are hidden in that case: a node has no inline text to color and its bubble menu already exposes node-specific actions. */
165
+ readonly isNodeSelection: _angular_core.WritableSignal<boolean>;
166
+ /** Internal - true when the NotionColorPicker extension is loaded; toggles the "A" color trigger. */
167
+ readonly showColorPickerButton: _angular_core.WritableSignal<boolean>;
168
+ /** Current text color CSS variable expression for the trigger glyph (null = default). */
169
+ readonly currentTextColorVar: _angular_core.WritableSignal<string>;
170
+ /** Current background color CSS variable expression for the trigger underline (null = transparent). */
171
+ readonly currentBgColorVar: _angular_core.WritableSignal<string>;
172
+ /** Internal - true when the selection has any token-based text or background color applied. */
173
+ readonly hasAnyColor: _angular_core.WritableSignal<boolean>;
145
174
  private menuEl;
146
175
  private pluginKey;
147
176
  private sanitizer;
148
177
  private ngZone;
149
178
  private activeVersion;
150
179
  private itemMap;
180
+ private dropdownMap;
151
181
  private activeMap;
152
182
  private disabledMap;
153
183
  private htmlCache;
154
184
  private bubbleDefaults;
155
185
  private transactionHandler;
186
+ readonly openDropdown: _angular_core.WritableSignal<string>;
187
+ private dropdownCleanupFloating;
188
+ private dropdownOutsideHandler;
189
+ private dropdownKeydownHandler;
190
+ private dropdownDismissHandler;
191
+ private readonly dropdownCaret;
156
192
  constructor();
157
193
  ngOnDestroy(): void;
158
194
  isItemActive(item: ToolbarButton): boolean;
159
195
  isItemDisabled(item: ToolbarButton): boolean;
160
196
  getCachedIcon(name: string): SafeHtml;
161
- executeCommand(item: ToolbarButton): void;
197
+ executeCommand(item: ToolbarButton, event?: Event): void;
198
+ /**
199
+ * Emit the `notionColorOpen` event with the trigger button as the anchor.
200
+ * The framework popover component (DomternalNotionColorPickerComponent)
201
+ * listens for this event and positions itself against the anchor.
202
+ */
203
+ openColorPicker(anchor: HTMLElement): void;
204
+ /**
205
+ * Open the BlockContextMenu against the cursor's containing block. Skips
206
+ * the textblock for nested cases (cursor in `listItem > paragraph` targets
207
+ * the listItem, not the paragraph) so Delete / Turn into operate on the
208
+ * "visual block" the user is editing.
209
+ */
210
+ openBlockContextMenu(anchor: HTMLElement): void;
162
211
  private buildItemMap;
163
212
  private resolveNames;
164
213
  private getFormatItems;
@@ -168,12 +217,48 @@ declare class DomternalBubbleMenuComponent implements OnDestroy {
168
217
  private filterBySchema;
169
218
  private buildBubbleDefaults;
170
219
  private setupItemTracking;
220
+ /**
221
+ * Refresh state for the optional trailing buttons (A color trigger,
222
+ * "..." block menu) and the isNodeSelection flag. Called from both
223
+ * setupItemTracking init and the per-transaction handler so the two
224
+ * paths stay in sync.
225
+ */
226
+ private syncTrailingButtonsState;
227
+ /**
228
+ * Disable the "..." trigger when the selection spans more than one
229
+ * top-level block. The block context menu targets the block at $from, so
230
+ * a multi-block selection has no unambiguous target.
231
+ */
232
+ private syncBlockMenuButtonState;
233
+ /**
234
+ * Update the trigger's indicator colors to mirror the current selection.
235
+ * Used by the "A" button so the underline matches whatever the user has
236
+ * applied at the cursor (Notion-style live preview).
237
+ */
238
+ private syncColorTriggerState;
171
239
  private updateContextItems;
172
240
  private updateStates;
241
+ asButton(item: BubbleMenuItem): ToolbarButton;
242
+ asDropdown(item: BubbleMenuItem): ToolbarDropdown;
243
+ isDropdownActive(dropdown: ToolbarDropdown): boolean;
244
+ /** Trigger HTML: swap icon to the active child when `dynamicIcon` is set. */
245
+ getDropdownTriggerHtml(dropdown: ToolbarDropdown): SafeHtml;
246
+ getCachedItemContent(iconName: string, label: string): SafeHtml;
247
+ isSubItemActive(name: string): boolean;
248
+ onDropdownToggle(dropdown: ToolbarDropdown, event?: MouseEvent): void;
249
+ onDropdownItemClick(item: ToolbarButton): void;
250
+ private cleanupDropdown;
173
251
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DomternalBubbleMenuComponent, never>;
174
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DomternalBubbleMenuComponent, "domternal-bubble-menu", never, { "editor": { "alias": "editor"; "required": true; "isSignal": true; }; "shouldShow": { "alias": "shouldShow"; "required": false; "isSignal": true; }; "placement": { "alias": "placement"; "required": false; "isSignal": true; }; "offset": { "alias": "offset"; "required": false; "isSignal": true; }; "updateDelay": { "alias": "updateDelay"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "contexts": { "alias": "contexts"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
252
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DomternalBubbleMenuComponent, "domternal-bubble-menu", never, { "editor": { "alias": "editor"; "required": true; "isSignal": true; }; "shouldShow": { "alias": "shouldShow"; "required": false; "isSignal": true; }; "placement": { "alias": "placement"; "required": false; "isSignal": true; }; "offset": { "alias": "offset"; "required": false; "isSignal": true; }; "updateDelay": { "alias": "updateDelay"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "contexts": { "alias": "contexts"; "required": false; "isSignal": true; }; "icons": { "alias": "icons"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
175
253
  }
176
254
 
255
+ /**
256
+ * Block-insert floating menu for Angular.
257
+ *
258
+ * Renders defaults collected from the editor's extensions via
259
+ * `addFloatingMenuItems()`; use `items` to override the list and `icons`
260
+ * to swap the icon set.
261
+ */
177
262
  declare class DomternalFloatingMenuComponent implements OnDestroy {
178
263
  readonly editor: _angular_core.InputSignal<Editor>;
179
264
  readonly shouldShow: _angular_core.InputSignal<(props: {
@@ -182,12 +267,38 @@ declare class DomternalFloatingMenuComponent implements OnDestroy {
182
267
  state: prosemirror_state.EditorState;
183
268
  }) => boolean>;
184
269
  readonly offset: _angular_core.InputSignal<number>;
270
+ readonly items: _angular_core.InputSignal<FloatingMenuItemsOverride>;
271
+ readonly keymap: _angular_core.InputSignal<FloatingMenuKeymap>;
272
+ readonly icons: _angular_core.InputSignal<IconSet>;
273
+ /**
274
+ * When true, the menu does NOT auto-show on every empty paragraph;
275
+ * it only opens when the BlockHandle `+` button (or any caller of
276
+ * `showFloatingMenu`) explicitly triggers it. Notion-style behaviour
277
+ * - empty rows show a placeholder, the slash menu is the keyboard
278
+ * trigger, the `+` button is the gutter trigger.
279
+ * @default false
280
+ */
281
+ readonly requireExplicitTrigger: _angular_core.InputSignal<boolean>;
185
282
  private menuEl;
283
+ private ngZone;
284
+ private sanitizer;
186
285
  private pluginKey;
286
+ private controller;
287
+ private version;
288
+ private iconCache;
289
+ readonly groups: _angular_core.Signal<_domternal_core.FloatingMenuGroup[]>;
290
+ private flatNames;
291
+ private focusedIndex;
187
292
  constructor();
188
293
  ngOnDestroy(): void;
294
+ flatIndexOf(name: string): number;
295
+ tabIndexFor(name: string): 0 | -1;
296
+ isItemDisabled(item: FloatingMenuItem): boolean;
297
+ iconHtml(name?: string): SafeHtml | null;
298
+ onItemClick(item: FloatingMenuItem): void;
299
+ onKeyDown(e: KeyboardEvent): void;
189
300
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DomternalFloatingMenuComponent, never>;
190
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DomternalFloatingMenuComponent, "domternal-floating-menu", never, { "editor": { "alias": "editor"; "required": true; "isSignal": true; }; "shouldShow": { "alias": "shouldShow"; "required": false; "isSignal": true; }; "offset": { "alias": "offset"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
301
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DomternalFloatingMenuComponent, "domternal-floating-menu", never, { "editor": { "alias": "editor"; "required": true; "isSignal": true; }; "shouldShow": { "alias": "shouldShow"; "required": false; "isSignal": true; }; "offset": { "alias": "offset"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "keymap": { "alias": "keymap"; "required": false; "isSignal": true; }; "icons": { "alias": "icons"; "required": false; "isSignal": true; }; "requireExplicitTrigger": { "alias": "requireExplicitTrigger"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
191
302
  }
192
303
 
193
304
  interface EmojiPickerItem {
@@ -233,5 +344,48 @@ declare class DomternalEmojiPickerComponent implements OnDestroy {
233
344
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<DomternalEmojiPickerComponent, "domternal-emoji-picker", never, { "editor": { "alias": "editor"; "required": true; "isSignal": true; }; "emojis": { "alias": "emojis"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
234
345
  }
235
346
 
236
- export { DEFAULT_EXTENSIONS, DomternalBubbleMenuComponent, DomternalEditorComponent, DomternalEmojiPickerComponent, DomternalFloatingMenuComponent, DomternalToolbarComponent };
347
+ declare class DomternalNotionColorPickerComponent implements OnDestroy {
348
+ readonly editor: _angular_core.InputSignal<Editor>;
349
+ readonly isOpen: _angular_core.WritableSignal<boolean>;
350
+ readonly currentTextToken: _angular_core.WritableSignal<string>;
351
+ readonly currentBgToken: _angular_core.WritableSignal<string>;
352
+ readonly palette: _angular_core.WritableSignal<string[]>;
353
+ private anchorEl;
354
+ private panelEl;
355
+ private ngZone;
356
+ private elRef;
357
+ private eventHandler;
358
+ private clickOutsideHandler;
359
+ private keydownHandler;
360
+ private selectionHandler;
361
+ private cleanupFloating;
362
+ constructor();
363
+ ngOnDestroy(): void;
364
+ tokenLabel(token: string): string;
365
+ applyText(token: string | null): void;
366
+ applyBg(token: string | null): void;
367
+ /**
368
+ * Arrow-key navigation across the 5-column swatch grids. Arrows move
369
+ * within and across rows, Home/End jump to grid boundaries, Tab leaves
370
+ * the picker (browser default), Enter/Space activates the focused swatch.
371
+ * Focus moves sequentially through Text color → Background color so
372
+ * keyboard users can reach any swatch without re-grabbing Tab.
373
+ */
374
+ onPanelKeydown(event: KeyboardEvent): void;
375
+ close(opts?: {
376
+ refocus?: boolean;
377
+ }): void;
378
+ private setupEventListener;
379
+ private addGlobalListeners;
380
+ private removeGlobalListeners;
381
+ private syncFromSelection;
382
+ private readPalette;
383
+ private getStorage;
384
+ private setStorageOpen;
385
+ private cleanup;
386
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DomternalNotionColorPickerComponent, never>;
387
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DomternalNotionColorPickerComponent, "domternal-notion-color-picker", never, { "editor": { "alias": "editor"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
388
+ }
389
+
390
+ export { DEFAULT_EXTENSIONS, DomternalBubbleMenuComponent, DomternalEditorComponent, DomternalEmojiPickerComponent, DomternalFloatingMenuComponent, DomternalNotionColorPickerComponent, DomternalToolbarComponent };
237
391
  export type { EmojiPickerItem };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@domternal/angular",
3
- "version": "0.6.2",
3
+ "version": "0.7.1",
4
4
  "description": "Angular components for Domternal editor",
5
5
  "author": "https://github.com/ThomasNowHere",
6
6
  "license": "MIT",
@@ -16,7 +16,8 @@
16
16
  "peerDependencies": {
17
17
  "@angular/core": ">=17.1.0",
18
18
  "@angular/forms": ">=17.1.0",
19
- "@domternal/core": ">=0.6.1"
19
+ "@domternal/core": ">=0.7.0",
20
+ "@domternal/extension-block-menu": ">=0.7.0"
20
21
  },
21
22
  "files": [
22
23
  "dist"
@@ -41,6 +42,7 @@
41
42
  },
42
43
  "homepage": "https://domternal.dev",
43
44
  "scripts": {
44
- "build": "ng-packagr -p ng-package.json"
45
+ "build": "ng-packagr -p ng-package.json",
46
+ "lint": "eslint src"
45
47
  }
46
48
  }