@domternal/angular 0.14.0 → 1.0.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 +18 -5
- package/dist/README.md +18 -5
- package/dist/fesm2022/domternal-angular.mjs +229 -312
- package/dist/fesm2022/domternal-angular.mjs.map +1 -1
- package/dist/types/domternal-angular.d.ts +38 -21
- package/package.json +11 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { viewChild, input, output, signal, inject, NgZone, afterNextRender, effect, untracked, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component, ElementRef, computed } from '@angular/core';
|
|
3
3
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
|
-
import { Document, Paragraph, Text, BaseKeymap, History, Editor, refocusEditorAfterCommand, positionFloatingOnce, defaultIcons, ToolbarController, defaultBubbleContexts, PluginKey, createBubbleMenuPlugin, createFloatingMenuPlugin, FloatingMenuController, positionFloating } from '@domternal/core';
|
|
4
|
+
import { Document, Paragraph, Text, BaseKeymap, History, Editor, refocusEditorAfterCommand, positionFloatingOnce, defaultIcons, ToolbarController, defaultBubbleContexts, PluginKey, createBubbleShouldShow, createBubbleMenuPlugin, buildBubbleItemMaps, resolveBubbleNames, resolveBubbleMenuItems, createFloatingMenuPlugin, FloatingMenuController, positionFloating } from '@domternal/core';
|
|
5
5
|
export { Editor } from '@domternal/core';
|
|
6
6
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
7
7
|
|
|
@@ -18,6 +18,12 @@ class DomternalEditorComponent {
|
|
|
18
18
|
history = input(true, ...(ngDevMode ? [{ debugName: "history" }] : /* istanbul ignore next */ []));
|
|
19
19
|
content = input('', ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
|
|
20
20
|
editable = input(true, ...(ngDevMode ? [{ debugName: "editable" }] : /* istanbul ignore next */ []));
|
|
21
|
+
/**
|
|
22
|
+
* Editing experience preset. `'notion'` paints `dm-notion-mode` on this
|
|
23
|
+
* component's host and switches preset-aware extensions to their Notion
|
|
24
|
+
* behavior, replacing the hand-written class. Create-time only.
|
|
25
|
+
*/
|
|
26
|
+
preset = input(undefined, ...(ngDevMode ? [{ debugName: "preset" }] : /* istanbul ignore next */ []));
|
|
21
27
|
autofocus = input(false, ...(ngDevMode ? [{ debugName: "autofocus" }] : /* istanbul ignore next */ []));
|
|
22
28
|
outputFormat = input('html', ...(ngDevMode ? [{ debugName: "outputFormat" }] : /* istanbul ignore next */ []));
|
|
23
29
|
// === Outputs ===
|
|
@@ -146,12 +152,14 @@ class DomternalEditorComponent {
|
|
|
146
152
|
const defaults = this.history()
|
|
147
153
|
? DEFAULT_EXTENSIONS
|
|
148
154
|
: DEFAULT_EXTENSIONS.filter((extension) => extension.name !== 'history');
|
|
155
|
+
const preset = this.preset();
|
|
149
156
|
this._editor = new Editor({
|
|
150
157
|
element: this.editorRef().nativeElement,
|
|
151
158
|
extensions: [...defaults, ...this.extensions()],
|
|
152
159
|
content: initialContent,
|
|
153
160
|
editable: this.editable(),
|
|
154
161
|
autofocus: this.autofocus(),
|
|
162
|
+
...(preset ? { preset } : {}),
|
|
155
163
|
});
|
|
156
164
|
this._isEditable.set(this.editable());
|
|
157
165
|
// Set initial signal values
|
|
@@ -198,8 +206,8 @@ class DomternalEditorComponent {
|
|
|
198
206
|
this.editorCreated.emit(editor);
|
|
199
207
|
});
|
|
200
208
|
}
|
|
201
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
202
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.
|
|
209
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
210
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.20", type: DomternalEditorComponent, isStandalone: true, selector: "domternal-editor", inputs: { extensions: { classPropertyName: "extensions", publicName: "extensions", isSignal: true, isRequired: false, transformFunction: null }, history: { classPropertyName: "history", publicName: "history", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, preset: { classPropertyName: "preset", publicName: "preset", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, outputFormat: { classPropertyName: "outputFormat", publicName: "outputFormat", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { editorCreated: "editorCreated", contentUpdated: "contentUpdated", selectionChanged: "selectionChanged", focusChanged: "focusChanged", blurChanged: "blurChanged", editorDestroyed: "editorDestroyed" }, host: { attributes: { "data-dm-editor-ui": "" }, classAttribute: "dm-editor" }, providers: [
|
|
203
211
|
{
|
|
204
212
|
provide: NG_VALUE_ACCESSOR,
|
|
205
213
|
useExisting: forwardRef(() => DomternalEditorComponent),
|
|
@@ -207,7 +215,7 @@ class DomternalEditorComponent {
|
|
|
207
215
|
},
|
|
208
216
|
], viewQueries: [{ propertyName: "editorRef", first: true, predicate: ["editorRef"], descendants: true, isSignal: true }], ngImport: i0, template: '<div #editorRef></div>', isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
209
217
|
}
|
|
210
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
218
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalEditorComponent, decorators: [{
|
|
211
219
|
type: Component,
|
|
212
220
|
args: [{ selector: 'domternal-editor', template: '<div #editorRef></div>', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'dm-editor', 'data-dm-editor-ui': '' }, providers: [
|
|
213
221
|
{
|
|
@@ -216,7 +224,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
216
224
|
multi: true,
|
|
217
225
|
},
|
|
218
226
|
], styles: [":host{display:block}\n"] }]
|
|
219
|
-
}], ctorParameters: () => [], propDecorators: { editorRef: [{ type: i0.ViewChild, args: ['editorRef', { isSignal: true }] }], extensions: [{ type: i0.Input, args: [{ isSignal: true, alias: "extensions", required: false }] }], history: [{ type: i0.Input, args: [{ isSignal: true, alias: "history", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], outputFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "outputFormat", required: false }] }], editorCreated: [{ type: i0.Output, args: ["editorCreated"] }], contentUpdated: [{ type: i0.Output, args: ["contentUpdated"] }], selectionChanged: [{ type: i0.Output, args: ["selectionChanged"] }], focusChanged: [{ type: i0.Output, args: ["focusChanged"] }], blurChanged: [{ type: i0.Output, args: ["blurChanged"] }], editorDestroyed: [{ type: i0.Output, args: ["editorDestroyed"] }] } });
|
|
227
|
+
}], ctorParameters: () => [], propDecorators: { editorRef: [{ type: i0.ViewChild, args: ['editorRef', { isSignal: true }] }], extensions: [{ type: i0.Input, args: [{ isSignal: true, alias: "extensions", required: false }] }], history: [{ type: i0.Input, args: [{ isSignal: true, alias: "history", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], preset: [{ type: i0.Input, args: [{ isSignal: true, alias: "preset", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], outputFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "outputFormat", required: false }] }], editorCreated: [{ type: i0.Output, args: ["editorCreated"] }], contentUpdated: [{ type: i0.Output, args: ["contentUpdated"] }], selectionChanged: [{ type: i0.Output, args: ["selectionChanged"] }], focusChanged: [{ type: i0.Output, args: ["focusChanged"] }], blurChanged: [{ type: i0.Output, args: ["blurChanged"] }], editorDestroyed: [{ type: i0.Output, args: ["editorDestroyed"] }] } });
|
|
220
228
|
|
|
221
229
|
const isMac = typeof navigator !== 'undefined' && /Mac|iPhone|iPad|iPod/.test(navigator.userAgent);
|
|
222
230
|
class DomternalToolbarComponent {
|
|
@@ -231,6 +239,7 @@ class DomternalToolbarComponent {
|
|
|
231
239
|
activeVersion = signal(0, ...(ngDevMode ? [{ debugName: "activeVersion" }] : /* istanbul ignore next */ []));
|
|
232
240
|
controller = null;
|
|
233
241
|
clickOutsideHandler = null;
|
|
242
|
+
escapeKeydownHandler = null;
|
|
234
243
|
dismissOverlayHandler = null;
|
|
235
244
|
editorEl = null;
|
|
236
245
|
cleanupFloating = null;
|
|
@@ -569,6 +578,26 @@ class DomternalToolbarComponent {
|
|
|
569
578
|
}
|
|
570
579
|
};
|
|
571
580
|
document.addEventListener('mousedown', this.clickOutsideHandler);
|
|
581
|
+
// Escape from anywhere: opening a dropdown with the mouse leaves focus
|
|
582
|
+
// outside the toolbar, so the host keydown handler never sees the key.
|
|
583
|
+
// Focus stays put, since the caret is usually still in the editor.
|
|
584
|
+
this.escapeKeydownHandler = (e) => {
|
|
585
|
+
if (!this.openDropdown())
|
|
586
|
+
return;
|
|
587
|
+
if (e.key !== 'Escape')
|
|
588
|
+
return;
|
|
589
|
+
// Focus inside the toolbar belongs to the host handler, which also
|
|
590
|
+
// restores focus. Not defaultPrevented: ProseMirror prevents Escape
|
|
591
|
+
// first whenever the caret is in the editor.
|
|
592
|
+
if (this.elRef.nativeElement.contains(document.activeElement))
|
|
593
|
+
return;
|
|
594
|
+
this.cleanupFloating?.();
|
|
595
|
+
this.cleanupFloating = null;
|
|
596
|
+
this.controller?.closeDropdown();
|
|
597
|
+
this.ngZone.run(() => { this.syncState(); });
|
|
598
|
+
e.preventDefault();
|
|
599
|
+
};
|
|
600
|
+
document.addEventListener('keydown', this.escapeKeydownHandler);
|
|
572
601
|
// Listen for dismiss-overlays (e.g. table handle clicks that stopPropagation on mousedown)
|
|
573
602
|
this.editorEl = editor.view.dom.closest('.dm-editor');
|
|
574
603
|
if (this.editorEl) {
|
|
@@ -590,6 +619,10 @@ class DomternalToolbarComponent {
|
|
|
590
619
|
document.removeEventListener('mousedown', this.clickOutsideHandler);
|
|
591
620
|
this.clickOutsideHandler = null;
|
|
592
621
|
}
|
|
622
|
+
if (this.escapeKeydownHandler) {
|
|
623
|
+
document.removeEventListener('keydown', this.escapeKeydownHandler);
|
|
624
|
+
this.escapeKeydownHandler = null;
|
|
625
|
+
}
|
|
593
626
|
if (this.dismissOverlayHandler && this.editorEl) {
|
|
594
627
|
this.editorEl.removeEventListener('dm:dismiss-overlays', this.dismissOverlayHandler);
|
|
595
628
|
this.dismissOverlayHandler = null;
|
|
@@ -652,8 +685,8 @@ class DomternalToolbarComponent {
|
|
|
652
685
|
const buttons = this.elRef.nativeElement.querySelectorAll('.dm-toolbar-button');
|
|
653
686
|
buttons[idx]?.focus();
|
|
654
687
|
}
|
|
655
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
656
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
688
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
689
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: DomternalToolbarComponent, isStandalone: true, selector: "domternal-toolbar", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, icons: { classPropertyName: "icons", publicName: "icons", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "toolbar", "data-dm-editor-ui": "" }, listeners: { "keydown": "onKeydown($event)" }, properties: { "attr.aria-label": "\"Editor formatting\"" }, classAttribute: "dm-toolbar" }, ngImport: i0, template: `
|
|
657
690
|
@for (group of groups(); track group.name; let gi = $index) {
|
|
658
691
|
@if (gi > 0) {
|
|
659
692
|
<div class="dm-toolbar-separator" role="separator"></div>
|
|
@@ -755,7 +788,7 @@ class DomternalToolbarComponent {
|
|
|
755
788
|
}
|
|
756
789
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
757
790
|
}
|
|
758
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
791
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalToolbarComponent, decorators: [{
|
|
759
792
|
type: Component,
|
|
760
793
|
args: [{
|
|
761
794
|
selector: 'domternal-toolbar',
|
|
@@ -872,15 +905,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
872
905
|
}]
|
|
873
906
|
}], ctorParameters: () => [], propDecorators: { editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], icons: [{ type: i0.Input, args: [{ isSignal: true, alias: "icons", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }] } });
|
|
874
907
|
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
const name = $pos.node(d).type.name;
|
|
879
|
-
if (name === 'tableCell' || name === 'tableHeader')
|
|
880
|
-
return true;
|
|
881
|
-
}
|
|
882
|
-
return false;
|
|
883
|
-
}
|
|
908
|
+
/* The item pipeline (which list this selection gets, what the schema allows,
|
|
909
|
+
which separators survive) is core's. This component renders the answer and
|
|
910
|
+
owns nothing about how it is reached. */
|
|
884
911
|
class DomternalBubbleMenuComponent {
|
|
885
912
|
editor = input.required(...(ngDevMode ? [{ debugName: "editor" }] : /* istanbul ignore next */ []));
|
|
886
913
|
shouldShow = input(...(ngDevMode ? [undefined, { debugName: "shouldShow" }] : /* istanbul ignore next */ []));
|
|
@@ -889,7 +916,17 @@ class DomternalBubbleMenuComponent {
|
|
|
889
916
|
updateDelay = input(0, ...(ngDevMode ? [{ debugName: "updateDelay" }] : /* istanbul ignore next */ []));
|
|
890
917
|
/** Fixed item names (e.g. ['bold', 'italic', 'code']). Omit for auto mode (all format items). */
|
|
891
918
|
items = input(undefined, ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
892
|
-
/**
|
|
919
|
+
/**
|
|
920
|
+
* Context-aware: map context names to item arrays, `true` for all valid
|
|
921
|
+
* items, or `null` to disable.
|
|
922
|
+
*
|
|
923
|
+
* Typed through core's `BubbleContexts` rather than the same shape written
|
|
924
|
+
* out here. Angular emits an input's declared type into the package types,
|
|
925
|
+
* and an inline union came out of that emit as `Record<string, true |
|
|
926
|
+
* string[]>`: the `null` that disables a context was missing from the
|
|
927
|
+
* published type, so the documented way to switch one off did not
|
|
928
|
+
* type-check. A named type survives the trip intact.
|
|
929
|
+
*/
|
|
893
930
|
contexts = input(undefined, ...(ngDevMode ? [{ debugName: "contexts" }] : /* istanbul ignore next */ []));
|
|
894
931
|
/**
|
|
895
932
|
* Custom icon overrides. Falls back to default Phosphor icons for unmapped keys.
|
|
@@ -913,6 +950,15 @@ class DomternalBubbleMenuComponent {
|
|
|
913
950
|
}
|
|
914
951
|
/** Internal - updated on transactions. Not meant to be set from outside. */
|
|
915
952
|
resolvedItems = signal([], ...(ngDevMode ? [{ debugName: "resolvedItems" }] : /* istanbul ignore next */ []));
|
|
953
|
+
/**
|
|
954
|
+
* The list core hands back, stored once. A default or fallback list comes
|
|
955
|
+
* back by reference and a signal set to its current value notifies nobody,
|
|
956
|
+
* so those passes cost nothing; a list resolved from names is rebuilt each
|
|
957
|
+
* time, as it always was.
|
|
958
|
+
*/
|
|
959
|
+
setResolvedItems(items) {
|
|
960
|
+
this.resolvedItems.set(items);
|
|
961
|
+
}
|
|
916
962
|
/** Internal - true when the BlockContextMenu extension is loaded; toggles the "..." trailing button. */
|
|
917
963
|
showBlockMenuButton = signal(false, ...(ngDevMode ? [{ debugName: "showBlockMenuButton" }] : /* istanbul ignore next */ []));
|
|
918
964
|
/** 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. */
|
|
@@ -921,6 +967,14 @@ class DomternalBubbleMenuComponent {
|
|
|
921
967
|
isNodeSelection = signal(false, ...(ngDevMode ? [{ debugName: "isNodeSelection" }] : /* istanbul ignore next */ []));
|
|
922
968
|
/** Internal - true when the NotionColorPicker extension is loaded; toggles the "A" color trigger. */
|
|
923
969
|
showColorPickerButton = signal(false, ...(ngDevMode ? [{ debugName: "showColorPickerButton" }] : /* istanbul ignore next */ []));
|
|
970
|
+
/**
|
|
971
|
+
* The trailing triggers, resolved once for the template: each is read twice,
|
|
972
|
+
* for the button and for the separator that may lead it.
|
|
973
|
+
*/
|
|
974
|
+
showColorTrigger = computed(() => this.showColorPickerButton() && !this.isNodeSelection(), ...(ngDevMode ? [{ debugName: "showColorTrigger" }] : /* istanbul ignore next */ []));
|
|
975
|
+
showBlockTrigger = computed(() => this.showBlockMenuButton() && !this.isNodeSelection(), ...(ngDevMode ? [{ debugName: "showBlockTrigger" }] : /* istanbul ignore next */ []));
|
|
976
|
+
/** notionColorPicker extension loaded (immutable per editor). */
|
|
977
|
+
hasNotionColorPicker = false;
|
|
924
978
|
/** Current text color CSS variable expression for the trigger glyph (null = default). */
|
|
925
979
|
currentTextColorVar = signal(null, ...(ngDevMode ? [{ debugName: "currentTextColorVar" }] : /* istanbul ignore next */ []));
|
|
926
980
|
/** Current background color CSS variable expression for the trigger underline (null = transparent). */
|
|
@@ -932,12 +986,15 @@ class DomternalBubbleMenuComponent {
|
|
|
932
986
|
sanitizer = inject(DomSanitizer);
|
|
933
987
|
ngZone = inject(NgZone);
|
|
934
988
|
activeVersion = signal(0, ...(ngDevMode ? [{ debugName: "activeVersion" }] : /* istanbul ignore next */ []));
|
|
935
|
-
|
|
936
|
-
|
|
989
|
+
/** Rebuilt per editor by `setupItemTracking`; empty until then. */
|
|
990
|
+
maps = {
|
|
991
|
+
itemMap: new Map(),
|
|
992
|
+
dropdownMap: new Map(),
|
|
993
|
+
bubbleDefaults: new Map(),
|
|
994
|
+
};
|
|
937
995
|
activeMap = new Map();
|
|
938
996
|
disabledMap = new Map();
|
|
939
997
|
htmlCache = new Map();
|
|
940
|
-
bubbleDefaults = new Map();
|
|
941
998
|
transactionHandler = null;
|
|
942
999
|
// Dropdown state for bubble-menu-embedded dropdowns (e.g. text-align).
|
|
943
1000
|
openDropdown = signal(null, ...(ngDevMode ? [{ debugName: "openDropdown" }] : /* istanbul ignore next */ []));
|
|
@@ -948,11 +1005,8 @@ class DomternalBubbleMenuComponent {
|
|
|
948
1005
|
dropdownCaret = '<svg class="dm-dropdown-caret" width="10" height="10" viewBox="0 0 10 10">' +
|
|
949
1006
|
'<path d="M2 4l3 3 3-3" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
|
950
1007
|
constructor() {
|
|
951
|
-
// Each component instance needs a unique plugin key so that multiple
|
|
952
|
-
//
|
|
953
|
-
// crypto.randomUUID over Math.random() for collision-free uniqueness
|
|
954
|
-
// (Math.random across two simultaneous mounts has a small but real
|
|
955
|
-
// collision probability, and SSR may share the random seed).
|
|
1008
|
+
// Each component instance needs a unique plugin key so that multiple bubble-
|
|
1009
|
+
// menus mounted in the same editor do not collide.
|
|
956
1010
|
const crypto = globalThis.crypto;
|
|
957
1011
|
const suffix = crypto?.randomUUID?.().slice(0, 8) ?? Math.random().toString(36).slice(2, 8);
|
|
958
1012
|
this.pluginKey = new PluginKey('angularBubbleMenu-' + suffix);
|
|
@@ -963,37 +1017,15 @@ class DomternalBubbleMenuComponent {
|
|
|
963
1017
|
});
|
|
964
1018
|
afterNextRender(() => {
|
|
965
1019
|
const editor = this.editor();
|
|
1020
|
+
/* Item tracking first, and the order is load-bearing: it is what builds
|
|
1021
|
+
`this.maps`, and the visibility rule below reads that object once.
|
|
1022
|
+
With the plugin registered first the rule closed over an empty map,
|
|
1023
|
+
and `bubbleDefaults.has(...)` was false for every node selection, so
|
|
1024
|
+
an image never got a menu at all. */
|
|
1025
|
+
this.setupItemTracking(editor);
|
|
966
1026
|
const ctxs = this.resolveContexts(editor);
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
if (ctxs) {
|
|
970
|
-
shouldShowFn = ({ state }) => {
|
|
971
|
-
const context = this.detectContext(state.selection, ctxs);
|
|
972
|
-
if (!context)
|
|
973
|
-
return false;
|
|
974
|
-
if (context in ctxs) {
|
|
975
|
-
const val = ctxs[context];
|
|
976
|
-
if (val === null)
|
|
977
|
-
return false;
|
|
978
|
-
return val === true || (Array.isArray(val) && val.length > 0);
|
|
979
|
-
}
|
|
980
|
-
return this.bubbleDefaults.has(context);
|
|
981
|
-
};
|
|
982
|
-
}
|
|
983
|
-
else {
|
|
984
|
-
// Auto/items mode: show when any endpoint's parent allows marks
|
|
985
|
-
shouldShowFn = ({ state }) => {
|
|
986
|
-
if (state.selection.empty)
|
|
987
|
-
return false;
|
|
988
|
-
if (state.selection.node)
|
|
989
|
-
return this.bubbleDefaults.has(state.selection.node.type.name);
|
|
990
|
-
if (isInsideTableCell(state.selection.$from))
|
|
991
|
-
return false;
|
|
992
|
-
return state.selection.$from.parent.type.spec.marks !== ''
|
|
993
|
-
|| state.selection.$to.parent.type.spec.marks !== '';
|
|
994
|
-
};
|
|
995
|
-
}
|
|
996
|
-
}
|
|
1027
|
+
const shouldShowFn = this.shouldShow() ??
|
|
1028
|
+
createBubbleShouldShow(this.maps, ctxs);
|
|
997
1029
|
const plugin = createBubbleMenuPlugin({
|
|
998
1030
|
pluginKey: this.pluginKey,
|
|
999
1031
|
editor,
|
|
@@ -1004,7 +1036,6 @@ class DomternalBubbleMenuComponent {
|
|
|
1004
1036
|
updateDelay: this.updateDelay(),
|
|
1005
1037
|
});
|
|
1006
1038
|
editor.registerPlugin(plugin);
|
|
1007
|
-
this.setupItemTracking(editor);
|
|
1008
1039
|
});
|
|
1009
1040
|
}
|
|
1010
1041
|
ngOnDestroy() {
|
|
@@ -1079,168 +1110,29 @@ class DomternalBubbleMenuComponent {
|
|
|
1079
1110
|
}));
|
|
1080
1111
|
}
|
|
1081
1112
|
// === Internal ===
|
|
1082
|
-
buildItemMap(editor) {
|
|
1083
|
-
this.itemMap.clear();
|
|
1084
|
-
this.dropdownMap.clear();
|
|
1085
|
-
for (const item of editor.toolbarItems) {
|
|
1086
|
-
if (item.type === 'button') {
|
|
1087
|
-
this.itemMap.set(item.name, item);
|
|
1088
|
-
}
|
|
1089
|
-
else if (item.type === 'dropdown') {
|
|
1090
|
-
this.dropdownMap.set(item.name, item);
|
|
1091
|
-
for (const sub of item.items) {
|
|
1092
|
-
this.itemMap.set(sub.name, sub);
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
resolveNames(names) {
|
|
1098
|
-
const result = [];
|
|
1099
|
-
let sepIdx = 0;
|
|
1100
|
-
for (const name of names) {
|
|
1101
|
-
if (name === '|') {
|
|
1102
|
-
result.push({ type: 'separator', name: `sep-${String(sepIdx++)}` });
|
|
1103
|
-
}
|
|
1104
|
-
else {
|
|
1105
|
-
const dropdown = this.dropdownMap.get(name);
|
|
1106
|
-
if (dropdown) {
|
|
1107
|
-
result.push(dropdown);
|
|
1108
|
-
continue;
|
|
1109
|
-
}
|
|
1110
|
-
const item = this.itemMap.get(name);
|
|
1111
|
-
if (item)
|
|
1112
|
-
result.push(item);
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
return result;
|
|
1116
|
-
}
|
|
1117
|
-
getFormatItems() {
|
|
1118
|
-
return Array.from(this.itemMap.values())
|
|
1119
|
-
.filter(item => item.group === 'format')
|
|
1120
|
-
.sort((a, b) => (b.priority ?? 100) - (a.priority ?? 100));
|
|
1121
|
-
}
|
|
1122
|
-
detectContext(selection, ctxs) {
|
|
1123
|
-
// CellSelection (duck-type: has $anchorCell) - never show bubble menu
|
|
1124
|
-
if ('$anchorCell' in selection)
|
|
1125
|
-
return null;
|
|
1126
|
-
if (selection.node)
|
|
1127
|
-
return selection.node.type.name;
|
|
1128
|
-
if (selection.empty)
|
|
1129
|
-
return null;
|
|
1130
|
-
// TextSelection inside a table cell → 'table' context.
|
|
1131
|
-
// Cross-cell TextSelection (drag across cells) → hide bubble menu.
|
|
1132
|
-
const fromCell = this.findCellNode(selection.$from);
|
|
1133
|
-
if (fromCell) {
|
|
1134
|
-
const toCell = this.findCellNode(selection.$to);
|
|
1135
|
-
if (toCell && fromCell !== toCell)
|
|
1136
|
-
return null;
|
|
1137
|
-
return 'table';
|
|
1138
|
-
}
|
|
1139
|
-
const fromName = selection.$from.parent.type.name;
|
|
1140
|
-
if (fromName in ctxs)
|
|
1141
|
-
return fromName;
|
|
1142
|
-
if ('text' in ctxs && selection.$from.parent.type.spec.marks !== '')
|
|
1143
|
-
return 'text';
|
|
1144
|
-
// Cross-block: also check $to so bold/italic is offered when any endpoint allows marks
|
|
1145
|
-
const toName = selection.$to.parent.type.name;
|
|
1146
|
-
if (toName in ctxs)
|
|
1147
|
-
return toName;
|
|
1148
|
-
if ('text' in ctxs && selection.$to.parent.type.spec.marks !== '')
|
|
1149
|
-
return 'text';
|
|
1150
|
-
return null;
|
|
1151
|
-
}
|
|
1152
|
-
findCellNode(pos) {
|
|
1153
|
-
for (let d = pos.depth; d > 0; d--) {
|
|
1154
|
-
const node = pos.node(d);
|
|
1155
|
-
if (node.type.name === 'tableCell' || node.type.name === 'tableHeader') {
|
|
1156
|
-
return node;
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
return null;
|
|
1160
|
-
}
|
|
1161
|
-
/** Filters out mark items that the context node type doesn't allow (e.g. bold on codeBlock) */
|
|
1162
|
-
filterBySchema(editor, contextName, items) {
|
|
1163
|
-
if (contextName === 'text' || contextName === 'table')
|
|
1164
|
-
return items;
|
|
1165
|
-
const schema = editor.state.schema;
|
|
1166
|
-
if (!schema)
|
|
1167
|
-
return items;
|
|
1168
|
-
const nodeType = schema.nodes[contextName];
|
|
1169
|
-
if (!nodeType)
|
|
1170
|
-
return items;
|
|
1171
|
-
return items.filter(item => {
|
|
1172
|
-
const markName = typeof item.isActive === 'string' ? item.isActive : null;
|
|
1173
|
-
if (!markName)
|
|
1174
|
-
return true;
|
|
1175
|
-
const markType = schema.marks[markName];
|
|
1176
|
-
if (!markType)
|
|
1177
|
-
return true;
|
|
1178
|
-
return nodeType.allowsMarkType(markType);
|
|
1179
|
-
});
|
|
1180
|
-
}
|
|
1181
|
-
buildBubbleDefaults(editor) {
|
|
1182
|
-
this.bubbleDefaults.clear();
|
|
1183
|
-
const byCtx = new Map();
|
|
1184
|
-
const addItem = (btn) => {
|
|
1185
|
-
const ctx = btn['bubbleMenu'];
|
|
1186
|
-
if (!ctx)
|
|
1187
|
-
return;
|
|
1188
|
-
let arr = byCtx.get(ctx);
|
|
1189
|
-
if (!arr) {
|
|
1190
|
-
arr = [];
|
|
1191
|
-
byCtx.set(ctx, arr);
|
|
1192
|
-
}
|
|
1193
|
-
arr.push(btn);
|
|
1194
|
-
};
|
|
1195
|
-
for (const item of editor.toolbarItems) {
|
|
1196
|
-
if (item.type === 'button')
|
|
1197
|
-
addItem(item);
|
|
1198
|
-
else if (item.type === 'dropdown') {
|
|
1199
|
-
for (const sub of item.items)
|
|
1200
|
-
addItem(sub);
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
for (const [ctx, items] of byCtx) {
|
|
1204
|
-
items.sort((a, b) => (b.priority ?? 100) - (a.priority ?? 100));
|
|
1205
|
-
const result = [];
|
|
1206
|
-
let lastGroup;
|
|
1207
|
-
let sepIdx = 0;
|
|
1208
|
-
for (const item of items) {
|
|
1209
|
-
if (lastGroup !== undefined && item.group !== lastGroup) {
|
|
1210
|
-
result.push({ type: 'separator', name: `bsep-${String(sepIdx++)}` });
|
|
1211
|
-
}
|
|
1212
|
-
result.push(item);
|
|
1213
|
-
lastGroup = item.group;
|
|
1214
|
-
}
|
|
1215
|
-
this.bubbleDefaults.set(ctx, result);
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
1113
|
setupItemTracking(editor) {
|
|
1219
|
-
|
|
1220
|
-
|
|
1114
|
+
/* One pipeline, built once per editor. Every renderer asks core the same
|
|
1115
|
+
question, so none of them answers it. */
|
|
1116
|
+
this.maps = buildBubbleItemMaps(editor);
|
|
1221
1117
|
this.showBlockMenuButton.set(editor.extensionManager.extensions.some((e) => e.name === 'blockContextMenu'));
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1118
|
+
// Presence cached; the show decision needs a live listener (per sync below).
|
|
1119
|
+
this.hasNotionColorPicker =
|
|
1120
|
+
editor.extensionManager.extensions.some((e) => e.name === 'notionColorPicker');
|
|
1121
|
+
const fallbackItems = resolveBubbleNames(this.items() ?? ['bold', 'italic', 'underline'], this.maps.itemMap, this.maps.dropdownMap);
|
|
1122
|
+
const refreshItems = () => {
|
|
1123
|
+
this.setResolvedItems(resolveBubbleMenuItems({
|
|
1124
|
+
editor,
|
|
1125
|
+
maps: this.maps,
|
|
1126
|
+
contexts: this.resolveContexts(editor),
|
|
1127
|
+
fallbackItems,
|
|
1128
|
+
}));
|
|
1129
|
+
};
|
|
1130
|
+
refreshItems();
|
|
1231
1131
|
this.transactionHandler = () => {
|
|
1232
1132
|
this.ngZone.run(() => {
|
|
1233
1133
|
const sel = editor.state.selection;
|
|
1234
1134
|
this.isNodeSelection.set(!!sel.node);
|
|
1235
|
-
|
|
1236
|
-
this.updateContextItems(editor);
|
|
1237
|
-
}
|
|
1238
|
-
else if (sel.node && this.bubbleDefaults.has(sel.node.type.name)) {
|
|
1239
|
-
this.resolvedItems.set(this.bubbleDefaults.get(sel.node.type.name) ?? []);
|
|
1240
|
-
}
|
|
1241
|
-
else {
|
|
1242
|
-
this.resolvedItems.set(defaultItems);
|
|
1243
|
-
}
|
|
1135
|
+
refreshItems();
|
|
1244
1136
|
this.updateStates(editor);
|
|
1245
1137
|
this.syncTrailingButtonsState(editor);
|
|
1246
1138
|
this.activeVersion.update((v) => v + 1);
|
|
@@ -1258,6 +1150,8 @@ class DomternalBubbleMenuComponent {
|
|
|
1258
1150
|
*/
|
|
1259
1151
|
syncTrailingButtonsState(editor) {
|
|
1260
1152
|
this.isNodeSelection.set(!!editor.state.selection.node);
|
|
1153
|
+
// Hidden without a live notionColorOpen listener: the trigger would be dead.
|
|
1154
|
+
this.showColorPickerButton.set(this.hasNotionColorPicker && editor.listenerCount('notionColorOpen') > 0);
|
|
1261
1155
|
if (this.showColorPickerButton())
|
|
1262
1156
|
this.syncColorTriggerState(editor);
|
|
1263
1157
|
if (this.showBlockMenuButton())
|
|
@@ -1293,35 +1187,6 @@ class DomternalBubbleMenuComponent {
|
|
|
1293
1187
|
this.currentBgColorVar.set(bgToken ? `var(--dm-block-bg-${bgToken})` : null);
|
|
1294
1188
|
this.hasAnyColor.set(textToken !== null || bgToken !== null);
|
|
1295
1189
|
}
|
|
1296
|
-
updateContextItems(editor) {
|
|
1297
|
-
const ctxs = this.resolveContexts(editor);
|
|
1298
|
-
if (!ctxs)
|
|
1299
|
-
return;
|
|
1300
|
-
const ctx = this.detectContext(editor.state.selection, ctxs);
|
|
1301
|
-
if (!ctx) {
|
|
1302
|
-
this.resolvedItems.set([]);
|
|
1303
|
-
return;
|
|
1304
|
-
}
|
|
1305
|
-
if (ctx in ctxs) {
|
|
1306
|
-
const val = ctxs[ctx];
|
|
1307
|
-
if (val === null || (Array.isArray(val) && val.length === 0)) {
|
|
1308
|
-
this.resolvedItems.set([]);
|
|
1309
|
-
return;
|
|
1310
|
-
}
|
|
1311
|
-
if (val === true) {
|
|
1312
|
-
this.resolvedItems.set(this.filterBySchema(editor, ctx, this.getFormatItems()));
|
|
1313
|
-
}
|
|
1314
|
-
else if (Array.isArray(val)) {
|
|
1315
|
-
const resolved = this.resolveNames(val);
|
|
1316
|
-
const buttons = resolved.filter((i) => i.type !== 'separator');
|
|
1317
|
-
const filtered = new Set(this.filterBySchema(editor, ctx, buttons).map(b => b.name));
|
|
1318
|
-
this.resolvedItems.set(resolved.filter(i => i.type === 'separator' || filtered.has(i.name)));
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
else {
|
|
1322
|
-
this.resolvedItems.set(this.bubbleDefaults.get(ctx) ?? []);
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
1190
|
updateStates(editor) {
|
|
1326
1191
|
let canProxy = null;
|
|
1327
1192
|
try {
|
|
@@ -1401,21 +1266,13 @@ class DomternalBubbleMenuComponent {
|
|
|
1401
1266
|
if (!isOpening)
|
|
1402
1267
|
return;
|
|
1403
1268
|
this.openDropdown.set(dropdown.name);
|
|
1404
|
-
// NOTE: we deliberately do NOT broadcast `dm:dismiss-overlays` here.
|
|
1405
|
-
//
|
|
1406
|
-
//
|
|
1407
|
-
// Other overlays (color picker, link popover) close themselves via
|
|
1408
|
-
// their own click-outside handlers when the user clicks our trigger,
|
|
1409
|
-
// so cooperative dismissal still works.
|
|
1269
|
+
// NOTE: we deliberately do NOT broadcast `dm:dismiss-overlays` here. The
|
|
1270
|
+
// bubble menu plugin in core listens for that event and would hide itself -
|
|
1271
|
+
// taking our just-opened dropdown's trigger with it.
|
|
1410
1272
|
const editorElBroadcast = this.menuEl().nativeElement.closest('.dm-editor');
|
|
1411
|
-
// Position the panel against the trigger after Angular renders it.
|
|
1412
|
-
//
|
|
1413
|
-
//
|
|
1414
|
-
// / --dm-button-active-color). Reparenting into `.dm-editor` was
|
|
1415
|
-
// tempting for consistency with the color picker, but that dropped
|
|
1416
|
-
// the active-state colors because those tokens aren't defined at
|
|
1417
|
-
// editor scope. floating-ui handles cross-element positioning fine
|
|
1418
|
-
// without reparenting.
|
|
1273
|
+
// Position the panel against the trigger after Angular renders it. We
|
|
1274
|
+
// deliberately keep the panel INSIDE `.dm-bubble-menu` so it inherits the
|
|
1275
|
+
// bubble-menu-scoped button tokens (--dm-button-active-bg / --dm-button-
|
|
1419
1276
|
requestAnimationFrame(() => {
|
|
1420
1277
|
const trigger = event?.currentTarget
|
|
1421
1278
|
?? this.menuEl().nativeElement.querySelector(`[data-dropdown="${dropdown.name}"]`);
|
|
@@ -1484,8 +1341,8 @@ class DomternalBubbleMenuComponent {
|
|
|
1484
1341
|
this.dropdownCleanupFloating = null;
|
|
1485
1342
|
this.openDropdown.set(null);
|
|
1486
1343
|
}
|
|
1487
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1488
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
1344
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalBubbleMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1345
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: DomternalBubbleMenuComponent, isStandalone: true, selector: "domternal-bubble-menu", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, shouldShow: { classPropertyName: "shouldShow", publicName: "shouldShow", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, updateDelay: { classPropertyName: "updateDelay", publicName: "updateDelay", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, contexts: { classPropertyName: "contexts", publicName: "contexts", isSignal: true, isRequired: false, transformFunction: null }, icons: { classPropertyName: "icons", publicName: "icons", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "menuEl", first: true, predicate: ["menuEl"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1489
1346
|
<div #menuEl class="dm-bubble-menu" role="toolbar" aria-label="Text formatting">
|
|
1490
1347
|
@for (item of resolvedItems(); track item.name) {
|
|
1491
1348
|
@if (item.type === 'separator') {
|
|
@@ -1532,8 +1389,10 @@ class DomternalBubbleMenuComponent {
|
|
|
1532
1389
|
(click)="executeCommand(asButton(item), $event)"></button>
|
|
1533
1390
|
}
|
|
1534
1391
|
}
|
|
1535
|
-
@if (
|
|
1536
|
-
|
|
1392
|
+
@if (showColorTrigger()) {
|
|
1393
|
+
@if (resolvedItems().length > 0) {
|
|
1394
|
+
<span class="dm-toolbar-separator" role="separator"></span>
|
|
1395
|
+
}
|
|
1537
1396
|
<button #colorBtn type="button" class="dm-toolbar-button dm-ncp-trigger"
|
|
1538
1397
|
[class.dm-toolbar-button--active]="hasAnyColor()"
|
|
1539
1398
|
title="Text and background color"
|
|
@@ -1547,8 +1406,10 @@ class DomternalBubbleMenuComponent {
|
|
|
1547
1406
|
[style.background-color]="currentBgColorVar()"></span>
|
|
1548
1407
|
</button>
|
|
1549
1408
|
}
|
|
1550
|
-
@if (
|
|
1551
|
-
|
|
1409
|
+
@if (showBlockTrigger()) {
|
|
1410
|
+
@if (resolvedItems().length > 0 || showColorTrigger()) {
|
|
1411
|
+
<span class="dm-toolbar-separator" role="separator"></span>
|
|
1412
|
+
}
|
|
1552
1413
|
<button #blockMenuBtn type="button" class="dm-toolbar-button"
|
|
1553
1414
|
[disabled]="blockMenuButtonDisabled()"
|
|
1554
1415
|
[title]="blockMenuButtonDisabled() ? 'Block actions (select within a single block)' : 'More options'"
|
|
@@ -1562,7 +1423,7 @@ class DomternalBubbleMenuComponent {
|
|
|
1562
1423
|
</div>
|
|
1563
1424
|
`, isInline: true, styles: [":host{display:contents}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1564
1425
|
}
|
|
1565
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1426
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalBubbleMenuComponent, decorators: [{
|
|
1566
1427
|
type: Component,
|
|
1567
1428
|
args: [{ selector: 'domternal-bubble-menu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
|
|
1568
1429
|
<div #menuEl class="dm-bubble-menu" role="toolbar" aria-label="Text formatting">
|
|
@@ -1611,8 +1472,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
1611
1472
|
(click)="executeCommand(asButton(item), $event)"></button>
|
|
1612
1473
|
}
|
|
1613
1474
|
}
|
|
1614
|
-
@if (
|
|
1615
|
-
|
|
1475
|
+
@if (showColorTrigger()) {
|
|
1476
|
+
@if (resolvedItems().length > 0) {
|
|
1477
|
+
<span class="dm-toolbar-separator" role="separator"></span>
|
|
1478
|
+
}
|
|
1616
1479
|
<button #colorBtn type="button" class="dm-toolbar-button dm-ncp-trigger"
|
|
1617
1480
|
[class.dm-toolbar-button--active]="hasAnyColor()"
|
|
1618
1481
|
title="Text and background color"
|
|
@@ -1626,8 +1489,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
1626
1489
|
[style.background-color]="currentBgColorVar()"></span>
|
|
1627
1490
|
</button>
|
|
1628
1491
|
}
|
|
1629
|
-
@if (
|
|
1630
|
-
|
|
1492
|
+
@if (showBlockTrigger()) {
|
|
1493
|
+
@if (resolvedItems().length > 0 || showColorTrigger()) {
|
|
1494
|
+
<span class="dm-toolbar-separator" role="separator"></span>
|
|
1495
|
+
}
|
|
1631
1496
|
<button #blockMenuBtn type="button" class="dm-toolbar-button"
|
|
1632
1497
|
[disabled]="blockMenuButtonDisabled()"
|
|
1633
1498
|
[title]="blockMenuButtonDisabled() ? 'Block actions (select within a single block)' : 'More options'"
|
|
@@ -1818,8 +1683,8 @@ class DomternalFloatingMenuComponent {
|
|
|
1818
1683
|
return;
|
|
1819
1684
|
}
|
|
1820
1685
|
}
|
|
1821
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1822
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
1686
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalFloatingMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1687
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: DomternalFloatingMenuComponent, isStandalone: true, selector: "domternal-floating-menu", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, shouldShow: { classPropertyName: "shouldShow", publicName: "shouldShow", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, keymap: { classPropertyName: "keymap", publicName: "keymap", isSignal: true, isRequired: false, transformFunction: null }, icons: { classPropertyName: "icons", publicName: "icons", isSignal: true, isRequired: false, transformFunction: null }, requireExplicitTrigger: { classPropertyName: "requireExplicitTrigger", publicName: "requireExplicitTrigger", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "menuEl", first: true, predicate: ["menuEl"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1823
1688
|
<div
|
|
1824
1689
|
#menuEl
|
|
1825
1690
|
class="dm-floating-menu"
|
|
@@ -1865,7 +1730,7 @@ class DomternalFloatingMenuComponent {
|
|
|
1865
1730
|
</div>
|
|
1866
1731
|
`, isInline: true, styles: [":host{display:contents}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1867
1732
|
}
|
|
1868
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1733
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalFloatingMenuComponent, decorators: [{
|
|
1869
1734
|
type: Component,
|
|
1870
1735
|
args: [{ selector: 'domternal-floating-menu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
|
|
1871
1736
|
<div
|
|
@@ -1920,10 +1785,10 @@ const CATEGORY_ICONS = {
|
|
|
1920
1785
|
'Animals & Nature': '\u{1F431}',
|
|
1921
1786
|
'Food & Drink': '\u{1F355}',
|
|
1922
1787
|
'Travel & Places': '\u{1F697}',
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1788
|
+
Activities: '\u{26BD}',
|
|
1789
|
+
Objects: '\u{1F4A1}',
|
|
1790
|
+
Symbols: '\u{1F523}',
|
|
1791
|
+
Flags: '\u{1F3C1}',
|
|
1927
1792
|
};
|
|
1928
1793
|
class DomternalEmojiPickerComponent {
|
|
1929
1794
|
editor = input.required(...(ngDevMode ? [{ debugName: "editor" }] : /* istanbul ignore next */ []));
|
|
@@ -1960,8 +1825,7 @@ class DomternalEmojiPickerComponent {
|
|
|
1960
1825
|
if (searchFn) {
|
|
1961
1826
|
return searchFn(query);
|
|
1962
1827
|
}
|
|
1963
|
-
return this.emojis().filter((item) => item.name.includes(query) ||
|
|
1964
|
-
item.group.toLowerCase().includes(query));
|
|
1828
|
+
return this.emojis().filter((item) => item.name.includes(query) || item.group.toLowerCase().includes(query));
|
|
1965
1829
|
}, ...(ngDevMode ? [{ debugName: "filteredEmojis" }] : /* istanbul ignore next */ []));
|
|
1966
1830
|
frequentlyUsed = computed(() => {
|
|
1967
1831
|
// Re-evaluate when panel opens (isOpen changes)
|
|
@@ -1978,12 +1842,17 @@ class DomternalEmojiPickerComponent {
|
|
|
1978
1842
|
const nameMap = storage['_nameMap'];
|
|
1979
1843
|
if (!nameMap)
|
|
1980
1844
|
return [];
|
|
1981
|
-
return names
|
|
1845
|
+
return names
|
|
1846
|
+
.slice(0, 16)
|
|
1847
|
+
.map((n) => nameMap.get(n))
|
|
1848
|
+
.filter(Boolean);
|
|
1982
1849
|
}, ...(ngDevMode ? [{ debugName: "frequentlyUsed" }] : /* istanbul ignore next */ []));
|
|
1983
1850
|
constructor() {
|
|
1984
1851
|
effect(() => {
|
|
1985
1852
|
const editor = this.editor();
|
|
1986
|
-
untracked(() => {
|
|
1853
|
+
untracked(() => {
|
|
1854
|
+
this.setupEventListener(editor);
|
|
1855
|
+
});
|
|
1987
1856
|
});
|
|
1988
1857
|
}
|
|
1989
1858
|
ngOnDestroy() {
|
|
@@ -2025,7 +1894,8 @@ class DomternalEmojiPickerComponent {
|
|
|
2025
1894
|
// Focus first emoji swatch after scroll completes
|
|
2026
1895
|
setTimeout(() => {
|
|
2027
1896
|
const firstSwatch = label.nextElementSibling;
|
|
2028
|
-
if (firstSwatch instanceof HTMLElement &&
|
|
1897
|
+
if (firstSwatch instanceof HTMLElement &&
|
|
1898
|
+
firstSwatch.classList.contains('dm-emoji-swatch')) {
|
|
2029
1899
|
firstSwatch.focus();
|
|
2030
1900
|
}
|
|
2031
1901
|
}, 50);
|
|
@@ -2050,7 +1920,7 @@ class DomternalEmojiPickerComponent {
|
|
|
2050
1920
|
return;
|
|
2051
1921
|
}
|
|
2052
1922
|
const cols = 8;
|
|
2053
|
-
let next
|
|
1923
|
+
let next;
|
|
2054
1924
|
switch (event.key) {
|
|
2055
1925
|
case 'ArrowRight':
|
|
2056
1926
|
event.preventDefault();
|
|
@@ -2073,7 +1943,8 @@ class DomternalEmojiPickerComponent {
|
|
|
2073
1943
|
event.preventDefault();
|
|
2074
1944
|
swatches[idx]?.click();
|
|
2075
1945
|
return;
|
|
2076
|
-
default:
|
|
1946
|
+
default:
|
|
1947
|
+
return;
|
|
2077
1948
|
}
|
|
2078
1949
|
swatches[next]?.focus();
|
|
2079
1950
|
}
|
|
@@ -2145,14 +2016,18 @@ class DomternalEmojiPickerComponent {
|
|
|
2145
2016
|
!this.elRef.nativeElement.contains(target) &&
|
|
2146
2017
|
target !== this.anchorEl &&
|
|
2147
2018
|
!this.anchorEl?.contains(target)) {
|
|
2148
|
-
this.ngZone.run(() => {
|
|
2019
|
+
this.ngZone.run(() => {
|
|
2020
|
+
this.close();
|
|
2021
|
+
});
|
|
2149
2022
|
}
|
|
2150
2023
|
};
|
|
2151
2024
|
document.addEventListener('mousedown', this.clickOutsideHandler);
|
|
2152
2025
|
this.keydownHandler = (e) => {
|
|
2153
2026
|
if (e.key === 'Escape' && this.isOpen()) {
|
|
2154
2027
|
e.preventDefault();
|
|
2155
|
-
this.ngZone.run(() => {
|
|
2028
|
+
this.ngZone.run(() => {
|
|
2029
|
+
this.close();
|
|
2030
|
+
});
|
|
2156
2031
|
}
|
|
2157
2032
|
};
|
|
2158
2033
|
document.addEventListener('keydown', this.keydownHandler);
|
|
@@ -2188,8 +2063,8 @@ class DomternalEmojiPickerComponent {
|
|
|
2188
2063
|
this.eventHandler = null;
|
|
2189
2064
|
}
|
|
2190
2065
|
}
|
|
2191
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
2192
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
2066
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalEmojiPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2067
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: DomternalEmojiPickerComponent, isStandalone: true, selector: "domternal-emoji-picker", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, emojis: { classPropertyName: "emojis", publicName: "emojis", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "dm-emoji-picker-host" }, ngImport: i0, template: `
|
|
2193
2068
|
@if (isOpen()) {
|
|
2194
2069
|
<div class="dm-emoji-picker">
|
|
2195
2070
|
<div class="dm-emoji-picker-search">
|
|
@@ -2216,11 +2091,18 @@ class DomternalEmojiPickerComponent {
|
|
|
2216
2091
|
[attr.aria-label]="cat"
|
|
2217
2092
|
(mousedown)="$event.preventDefault()"
|
|
2218
2093
|
(click)="scrollToCategory(cat)"
|
|
2219
|
-
>
|
|
2094
|
+
>
|
|
2095
|
+
{{ categoryIcon(cat) }}
|
|
2096
|
+
</button>
|
|
2220
2097
|
}
|
|
2221
2098
|
</div>
|
|
2222
2099
|
|
|
2223
|
-
<div
|
|
2100
|
+
<div
|
|
2101
|
+
class="dm-emoji-picker-grid"
|
|
2102
|
+
#grid
|
|
2103
|
+
(scroll)="onGridScroll()"
|
|
2104
|
+
(keydown)="onGridKeydown($event)"
|
|
2105
|
+
>
|
|
2224
2106
|
@if (searchQuery()) {
|
|
2225
2107
|
@for (item of filteredEmojis(); track item.name) {
|
|
2226
2108
|
<button
|
|
@@ -2231,9 +2113,10 @@ class DomternalEmojiPickerComponent {
|
|
|
2231
2113
|
[attr.aria-label]="formatName(item.name)"
|
|
2232
2114
|
(mousedown)="$event.preventDefault()"
|
|
2233
2115
|
(click)="selectEmoji(item)"
|
|
2234
|
-
>
|
|
2235
|
-
|
|
2236
|
-
|
|
2116
|
+
>
|
|
2117
|
+
{{ item.emoji }}
|
|
2118
|
+
</button>
|
|
2119
|
+
} @empty {
|
|
2237
2120
|
<div class="dm-emoji-picker-empty">No emoji found</div>
|
|
2238
2121
|
}
|
|
2239
2122
|
} @else {
|
|
@@ -2248,7 +2131,9 @@ class DomternalEmojiPickerComponent {
|
|
|
2248
2131
|
[attr.aria-label]="formatName(item.name)"
|
|
2249
2132
|
(mousedown)="$event.preventDefault()"
|
|
2250
2133
|
(click)="selectEmoji(item)"
|
|
2251
|
-
>
|
|
2134
|
+
>
|
|
2135
|
+
{{ item.emoji }}
|
|
2136
|
+
</button>
|
|
2252
2137
|
}
|
|
2253
2138
|
}
|
|
2254
2139
|
@for (cat of categoryNames(); track cat) {
|
|
@@ -2262,7 +2147,9 @@ class DomternalEmojiPickerComponent {
|
|
|
2262
2147
|
[attr.aria-label]="formatName(item.name)"
|
|
2263
2148
|
(mousedown)="$event.preventDefault()"
|
|
2264
2149
|
(click)="selectEmoji(item)"
|
|
2265
|
-
>
|
|
2150
|
+
>
|
|
2151
|
+
{{ item.emoji }}
|
|
2152
|
+
</button>
|
|
2266
2153
|
}
|
|
2267
2154
|
}
|
|
2268
2155
|
}
|
|
@@ -2271,13 +2158,13 @@ class DomternalEmojiPickerComponent {
|
|
|
2271
2158
|
}
|
|
2272
2159
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2273
2160
|
}
|
|
2274
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2161
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalEmojiPickerComponent, decorators: [{
|
|
2275
2162
|
type: Component,
|
|
2276
2163
|
args: [{
|
|
2277
2164
|
selector: 'domternal-emoji-picker',
|
|
2278
2165
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2279
2166
|
encapsulation: ViewEncapsulation.None,
|
|
2280
|
-
host: {
|
|
2167
|
+
host: { class: 'dm-emoji-picker-host' },
|
|
2281
2168
|
template: `
|
|
2282
2169
|
@if (isOpen()) {
|
|
2283
2170
|
<div class="dm-emoji-picker">
|
|
@@ -2305,11 +2192,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
2305
2192
|
[attr.aria-label]="cat"
|
|
2306
2193
|
(mousedown)="$event.preventDefault()"
|
|
2307
2194
|
(click)="scrollToCategory(cat)"
|
|
2308
|
-
>
|
|
2195
|
+
>
|
|
2196
|
+
{{ categoryIcon(cat) }}
|
|
2197
|
+
</button>
|
|
2309
2198
|
}
|
|
2310
2199
|
</div>
|
|
2311
2200
|
|
|
2312
|
-
<div
|
|
2201
|
+
<div
|
|
2202
|
+
class="dm-emoji-picker-grid"
|
|
2203
|
+
#grid
|
|
2204
|
+
(scroll)="onGridScroll()"
|
|
2205
|
+
(keydown)="onGridKeydown($event)"
|
|
2206
|
+
>
|
|
2313
2207
|
@if (searchQuery()) {
|
|
2314
2208
|
@for (item of filteredEmojis(); track item.name) {
|
|
2315
2209
|
<button
|
|
@@ -2320,9 +2214,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
2320
2214
|
[attr.aria-label]="formatName(item.name)"
|
|
2321
2215
|
(mousedown)="$event.preventDefault()"
|
|
2322
2216
|
(click)="selectEmoji(item)"
|
|
2323
|
-
>
|
|
2324
|
-
|
|
2325
|
-
|
|
2217
|
+
>
|
|
2218
|
+
{{ item.emoji }}
|
|
2219
|
+
</button>
|
|
2220
|
+
} @empty {
|
|
2326
2221
|
<div class="dm-emoji-picker-empty">No emoji found</div>
|
|
2327
2222
|
}
|
|
2328
2223
|
} @else {
|
|
@@ -2337,7 +2232,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
2337
2232
|
[attr.aria-label]="formatName(item.name)"
|
|
2338
2233
|
(mousedown)="$event.preventDefault()"
|
|
2339
2234
|
(click)="selectEmoji(item)"
|
|
2340
|
-
>
|
|
2235
|
+
>
|
|
2236
|
+
{{ item.emoji }}
|
|
2237
|
+
</button>
|
|
2341
2238
|
}
|
|
2342
2239
|
}
|
|
2343
2240
|
@for (cat of categoryNames(); track cat) {
|
|
@@ -2351,7 +2248,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
2351
2248
|
[attr.aria-label]="formatName(item.name)"
|
|
2352
2249
|
(mousedown)="$event.preventDefault()"
|
|
2353
2250
|
(click)="selectEmoji(item)"
|
|
2354
|
-
>
|
|
2251
|
+
>
|
|
2252
|
+
{{ item.emoji }}
|
|
2253
|
+
</button>
|
|
2355
2254
|
}
|
|
2356
2255
|
}
|
|
2357
2256
|
}
|
|
@@ -2362,6 +2261,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
2362
2261
|
}]
|
|
2363
2262
|
}], ctorParameters: () => [], propDecorators: { editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], emojis: [{ type: i0.Input, args: [{ isSignal: true, alias: "emojis", required: true }] }] } });
|
|
2364
2263
|
|
|
2264
|
+
function paletteFromExtensionOptions(options) {
|
|
2265
|
+
if (typeof options !== 'object' || options === null || !('palette' in options))
|
|
2266
|
+
return [];
|
|
2267
|
+
const palette = options.palette;
|
|
2268
|
+
if (!Array.isArray(palette) || !palette.every((token) => typeof token === 'string')) {
|
|
2269
|
+
return [];
|
|
2270
|
+
}
|
|
2271
|
+
return [...palette];
|
|
2272
|
+
}
|
|
2365
2273
|
/**
|
|
2366
2274
|
* Display labels for the named-token palette. Used in tooltips / aria labels;
|
|
2367
2275
|
* unknown tokens fall back to a title-cased version of the raw key.
|
|
@@ -2399,7 +2307,9 @@ class DomternalNotionColorPickerComponent {
|
|
|
2399
2307
|
constructor() {
|
|
2400
2308
|
effect(() => {
|
|
2401
2309
|
const editor = this.editor();
|
|
2402
|
-
untracked(() => {
|
|
2310
|
+
untracked(() => {
|
|
2311
|
+
this.setupEventListener(editor);
|
|
2312
|
+
});
|
|
2403
2313
|
});
|
|
2404
2314
|
}
|
|
2405
2315
|
ngOnDestroy() {
|
|
@@ -2439,7 +2349,7 @@ class DomternalNotionColorPickerComponent {
|
|
|
2439
2349
|
const idx = active ? swatches.indexOf(active) : -1;
|
|
2440
2350
|
if (idx === -1)
|
|
2441
2351
|
return;
|
|
2442
|
-
let next
|
|
2352
|
+
let next;
|
|
2443
2353
|
switch (event.key) {
|
|
2444
2354
|
case 'ArrowRight':
|
|
2445
2355
|
event.preventDefault();
|
|
@@ -2561,13 +2471,17 @@ class DomternalNotionColorPickerComponent {
|
|
|
2561
2471
|
return;
|
|
2562
2472
|
if (this.anchorEl?.contains(target))
|
|
2563
2473
|
return;
|
|
2564
|
-
this.ngZone.run(() => {
|
|
2474
|
+
this.ngZone.run(() => {
|
|
2475
|
+
this.close({ refocus: false });
|
|
2476
|
+
});
|
|
2565
2477
|
};
|
|
2566
2478
|
document.addEventListener('mousedown', this.clickOutsideHandler);
|
|
2567
2479
|
this.keydownHandler = (e) => {
|
|
2568
2480
|
if (e.key === 'Escape' && this.isOpen()) {
|
|
2569
2481
|
e.preventDefault();
|
|
2570
|
-
this.ngZone.run(() => {
|
|
2482
|
+
this.ngZone.run(() => {
|
|
2483
|
+
this.close({ refocus: true });
|
|
2484
|
+
});
|
|
2571
2485
|
}
|
|
2572
2486
|
};
|
|
2573
2487
|
document.addEventListener('keydown', this.keydownHandler);
|
|
@@ -2580,11 +2494,15 @@ class DomternalNotionColorPickerComponent {
|
|
|
2580
2494
|
// (hideout, route change). Positioning against a detached anchor is
|
|
2581
2495
|
// a no-op; close instead. Matches React/Vue behaviour.
|
|
2582
2496
|
if (this.anchorEl && !this.anchorEl.isConnected) {
|
|
2583
|
-
this.ngZone.run(() => {
|
|
2497
|
+
this.ngZone.run(() => {
|
|
2498
|
+
this.close({ refocus: false });
|
|
2499
|
+
});
|
|
2584
2500
|
return;
|
|
2585
2501
|
}
|
|
2586
2502
|
if (this.editor().state.selection.empty) {
|
|
2587
|
-
this.ngZone.run(() => {
|
|
2503
|
+
this.ngZone.run(() => {
|
|
2504
|
+
this.close({ refocus: false });
|
|
2505
|
+
});
|
|
2588
2506
|
}
|
|
2589
2507
|
else {
|
|
2590
2508
|
// Selection changed but stays non-empty (e.g. shift+arrow): refresh
|
|
@@ -2638,8 +2556,7 @@ class DomternalNotionColorPickerComponent {
|
|
|
2638
2556
|
}
|
|
2639
2557
|
readPalette() {
|
|
2640
2558
|
const ext = this.editor().extensionManager.extensions.find((e) => e.name === 'notionColorPicker');
|
|
2641
|
-
|
|
2642
|
-
return options?.palette ? [...options.palette] : [];
|
|
2559
|
+
return paletteFromExtensionOptions(ext?.options);
|
|
2643
2560
|
}
|
|
2644
2561
|
getStorage() {
|
|
2645
2562
|
const storage = this.editor().storage;
|
|
@@ -2663,8 +2580,8 @@ class DomternalNotionColorPickerComponent {
|
|
|
2663
2580
|
this.eventHandler = null;
|
|
2664
2581
|
}
|
|
2665
2582
|
}
|
|
2666
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
2667
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
2583
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalNotionColorPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2584
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: DomternalNotionColorPickerComponent, isStandalone: true, selector: "domternal-notion-color-picker", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
|
|
2668
2585
|
@if (isOpen()) {
|
|
2669
2586
|
<div
|
|
2670
2587
|
class="dm-notion-color-picker"
|
|
@@ -2738,7 +2655,7 @@ class DomternalNotionColorPickerComponent {
|
|
|
2738
2655
|
}
|
|
2739
2656
|
`, isInline: true, styles: [":host{display:contents}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2740
2657
|
}
|
|
2741
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2658
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DomternalNotionColorPickerComponent, decorators: [{
|
|
2742
2659
|
type: Component,
|
|
2743
2660
|
args: [{ selector: 'domternal-notion-color-picker', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
|
|
2744
2661
|
@if (isOpen()) {
|