@malva-ui/editor 0.1.13 → 0.1.14
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 +5 -5
- package/fesm2022/malva-ui-editor-ai.mjs +17 -0
- package/fesm2022/malva-ui-editor-ai.mjs.map +1 -0
- package/fesm2022/malva-ui-editor.mjs +10227 -0
- package/fesm2022/malva-ui-editor.mjs.map +1 -0
- package/package.json +35 -26
- package/types/malva-ui-editor-ai.d.ts +1 -0
- package/types/malva-ui-editor.d.ts +2995 -0
- package/ai/index.d.ts +0 -12
- package/ai/malva-ui-editor-ai.d.ts +0 -5
- package/esm2022/ai/index.js +0 -12
- package/esm2022/ai/index.js.map +0 -1
- package/esm2022/ai/malva-ui-editor-ai.js +0 -5
- package/esm2022/ai/malva-ui-editor-ai.js.map +0 -1
- package/esm2022/index.js +0 -37
- package/esm2022/index.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-actions.js +0 -69
- package/esm2022/lib/ai/editor-ai-actions.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-context.js +0 -612
- package/esm2022/lib/ai/editor-ai-context.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-menu.js +0 -288
- package/esm2022/lib/ai/editor-ai-menu.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-review-bar.js +0 -223
- package/esm2022/lib/ai/editor-ai-review-bar.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-stream.js +0 -677
- package/esm2022/lib/ai/editor-ai-stream.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-suggestions.js +0 -751
- package/esm2022/lib/ai/editor-ai-suggestions.js.map +0 -1
- package/esm2022/lib/ai/editor-ai.tokens.js +0 -10
- package/esm2022/lib/ai/editor-ai.tokens.js.map +0 -1
- package/esm2022/lib/ai/editor-ai.types.js +0 -1
- package/esm2022/lib/ai/editor-ai.types.js.map +0 -1
- package/esm2022/lib/editor/editor.js +0 -985
- package/esm2022/lib/editor/editor.js.map +0 -1
- package/esm2022/lib/editor-extension-preflight.js +0 -83
- package/esm2022/lib/editor-extension-preflight.js.map +0 -1
- package/esm2022/lib/editor-serialization.js +0 -152
- package/esm2022/lib/editor-serialization.js.map +0 -1
- package/esm2022/lib/editor-toolbar-context.js +0 -259
- package/esm2022/lib/editor-toolbar-context.js.map +0 -1
- package/esm2022/lib/editor.tokens.js +0 -10
- package/esm2022/lib/editor.tokens.js.map +0 -1
- package/esm2022/lib/editor.types.js +0 -48
- package/esm2022/lib/editor.types.js.map +0 -1
- package/esm2022/lib/extensions/editor-block-handle.js +0 -760
- package/esm2022/lib/extensions/editor-block-handle.js.map +0 -1
- package/esm2022/lib/extensions/editor-extensions.js +0 -321
- package/esm2022/lib/extensions/editor-extensions.js.map +0 -1
- package/esm2022/lib/extensions/editor-markdown-compatibility.js +0 -162
- package/esm2022/lib/extensions/editor-markdown-compatibility.js.map +0 -1
- package/esm2022/lib/extensions/editor-upload-placeholder.js +0 -156
- package/esm2022/lib/extensions/editor-upload-placeholder.js.map +0 -1
- package/esm2022/lib/status/editor-status.js +0 -64
- package/esm2022/lib/status/editor-status.js.map +0 -1
- package/esm2022/lib/toolbar/editor-alignment.js +0 -203
- package/esm2022/lib/toolbar/editor-alignment.js.map +0 -1
- package/esm2022/lib/toolbar/editor-block-insert.js +0 -101
- package/esm2022/lib/toolbar/editor-block-insert.js.map +0 -1
- package/esm2022/lib/toolbar/editor-color-control.js +0 -71
- package/esm2022/lib/toolbar/editor-color-control.js.map +0 -1
- package/esm2022/lib/toolbar/editor-command-button.js +0 -115
- package/esm2022/lib/toolbar/editor-command-button.js.map +0 -1
- package/esm2022/lib/toolbar/editor-heading.js +0 -266
- package/esm2022/lib/toolbar/editor-heading.js.map +0 -1
- package/esm2022/lib/toolbar/editor-highlight.js +0 -84
- package/esm2022/lib/toolbar/editor-highlight.js.map +0 -1
- package/esm2022/lib/toolbar/editor-image-upload-dialog.js +0 -289
- package/esm2022/lib/toolbar/editor-image-upload-dialog.js.map +0 -1
- package/esm2022/lib/toolbar/editor-image-upload.js +0 -315
- package/esm2022/lib/toolbar/editor-image-upload.js.map +0 -1
- package/esm2022/lib/toolbar/editor-inline-marks.js +0 -124
- package/esm2022/lib/toolbar/editor-inline-marks.js.map +0 -1
- package/esm2022/lib/toolbar/editor-link.js +0 -265
- package/esm2022/lib/toolbar/editor-link.js.map +0 -1
- package/esm2022/lib/toolbar/editor-list.js +0 -249
- package/esm2022/lib/toolbar/editor-list.js.map +0 -1
- package/esm2022/lib/toolbar/editor-table.js +0 -292
- package/esm2022/lib/toolbar/editor-table.js.map +0 -1
- package/esm2022/lib/toolbar/editor-text-color.js +0 -82
- package/esm2022/lib/toolbar/editor-text-color.js.map +0 -1
- package/esm2022/lib/toolbar/editor-toolbar-widget.js +0 -41
- package/esm2022/lib/toolbar/editor-toolbar-widget.js.map +0 -1
- package/esm2022/lib/toolbar/editor-toolbar.defs.js +0 -60
- package/esm2022/lib/toolbar/editor-toolbar.defs.js.map +0 -1
- package/esm2022/lib/toolbar/editor-toolbar.js +0 -826
- package/esm2022/lib/toolbar/editor-toolbar.js.map +0 -1
- package/esm2022/lib/toolbar/editor-undo-redo.js +0 -72
- package/esm2022/lib/toolbar/editor-undo-redo.js.map +0 -1
- package/esm2022/lib/toolbar/editor-zoom.js +0 -330
- package/esm2022/lib/toolbar/editor-zoom.js.map +0 -1
- package/esm2022/lib/upload/editor-image-upload-coordinator.js +0 -480
- package/esm2022/lib/upload/editor-image-upload-coordinator.js.map +0 -1
- package/esm2022/malva-ui-editor.js +0 -5
- package/esm2022/malva-ui-editor.js.map +0 -1
- package/index.d.ts +0 -35
- package/lib/ai/editor-ai-actions.d.ts +0 -27
- package/lib/ai/editor-ai-context.d.ts +0 -307
- package/lib/ai/editor-ai-menu.d.ts +0 -142
- package/lib/ai/editor-ai-review-bar.d.ts +0 -116
- package/lib/ai/editor-ai-stream.d.ts +0 -207
- package/lib/ai/editor-ai-suggestions.d.ts +0 -219
- package/lib/ai/editor-ai.tokens.d.ts +0 -10
- package/lib/ai/editor-ai.types.d.ts +0 -176
- package/lib/editor/editor.d.ts +0 -243
- package/lib/editor-extension-preflight.d.ts +0 -23
- package/lib/editor-serialization.d.ts +0 -74
- package/lib/editor-toolbar-context.d.ts +0 -116
- package/lib/editor.tokens.d.ts +0 -6
- package/lib/editor.types.d.ts +0 -194
- package/lib/extensions/editor-block-handle.d.ts +0 -59
- package/lib/extensions/editor-extensions.d.ts +0 -165
- package/lib/extensions/editor-markdown-compatibility.d.ts +0 -11
- package/lib/extensions/editor-upload-placeholder.d.ts +0 -75
- package/lib/status/editor-status.d.ts +0 -24
- package/lib/toolbar/editor-alignment.d.ts +0 -61
- package/lib/toolbar/editor-block-insert.d.ts +0 -26
- package/lib/toolbar/editor-color-control.d.ts +0 -32
- package/lib/toolbar/editor-command-button.d.ts +0 -29
- package/lib/toolbar/editor-heading.d.ts +0 -68
- package/lib/toolbar/editor-highlight.d.ts +0 -21
- package/lib/toolbar/editor-image-upload-dialog.d.ts +0 -96
- package/lib/toolbar/editor-image-upload.d.ts +0 -71
- package/lib/toolbar/editor-inline-marks.d.ts +0 -30
- package/lib/toolbar/editor-link.d.ts +0 -78
- package/lib/toolbar/editor-list.d.ts +0 -67
- package/lib/toolbar/editor-table.d.ts +0 -133
- package/lib/toolbar/editor-text-color.d.ts +0 -21
- package/lib/toolbar/editor-toolbar-widget.d.ts +0 -19
- package/lib/toolbar/editor-toolbar.d.ts +0 -157
- package/lib/toolbar/editor-toolbar.defs.d.ts +0 -35
- package/lib/toolbar/editor-undo-redo.d.ts +0 -26
- package/lib/toolbar/editor-zoom.d.ts +0 -108
- package/lib/upload/editor-image-upload-coordinator.d.ts +0 -55
- package/malva-ui-editor.d.ts +0 -5
|
@@ -1,985 +0,0 @@
|
|
|
1
|
-
import { LiveAnnouncer } from '@angular/cdk/a11y';
|
|
2
|
-
import { isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
|
|
3
|
-
import { ChangeDetectionStrategy, Component, computed, contentChildren, DestroyRef, ElementRef, effect, forwardRef, inject, Injector, input, model, output, PLATFORM_ID, signal, viewChild, ViewEncapsulation, } from '@angular/core';
|
|
4
|
-
import { Editor } from '@tiptap/core';
|
|
5
|
-
import { MlvFade, MlvSpacer } from '@malva-ui/cdk/utils';
|
|
6
|
-
import { MlvFormControlWrapper, MlvFormControlWrapperControl, MlvHint, MlvLabel, MlvMessage, MlvSignalFormControlBase, MLV_FORM_CONTROL, } from '@malva-ui/core/form-utils';
|
|
7
|
-
import { MlvToolbar } from '@malva-ui/core/toolbar';
|
|
8
|
-
import { MlvDivider } from '@malva-ui/core/divider';
|
|
9
|
-
import { MLV_EDITOR_I18N } from '@malva-ui/i18n';
|
|
10
|
-
import { MLV_EDITOR_OVERLAY_REGISTRY, MLV_EDITOR_TOOLBAR_CONTEXT, MLV_EDITOR_TOOLBAR_ROVING, MLV_EDITOR_TOOLBAR_REVISION, MLV_EDITOR_UPLOAD_ABORT_REGISTRY, MlvEditorOverlayRegistry, MlvEditorToolbarRevision, MlvEditorToolbarRovingRegistry, MlvEditorUploadAbortRegistry, } from '../editor-toolbar-context';
|
|
11
|
-
import { MLV_EDITOR_DEFAULT_IMAGE_UPLOAD_OPTIONS, MLV_EDITOR_IMAGE_UPLOADER, } from '../editor.tokens';
|
|
12
|
-
import { MLV_EDITOR_AI_CONTEXT, MLV_EDITOR_AI_INPUT_PROVIDER, MlvEditorAiContext, } from '../ai/editor-ai-context';
|
|
13
|
-
import { editorValuesAreEquivalent, normalizeEditorValue, parseEditorJsonDocument, serializeEditorValue, } from '../editor-serialization';
|
|
14
|
-
import { preflightMlvEditorExtensions } from '../editor-extension-preflight';
|
|
15
|
-
import { mlvEditorDefaultExtensions } from '../extensions/editor-extensions';
|
|
16
|
-
import { createMlvEditorImageUploadCoordinator, MLV_EDITOR_IMAGE_UPLOAD_COORDINATOR, } from '../upload/editor-image-upload-coordinator';
|
|
17
|
-
import { MlvEditorAlignment } from '../toolbar/editor-alignment';
|
|
18
|
-
import { MlvEditorBlockInsert } from '../toolbar/editor-block-insert';
|
|
19
|
-
import { MlvEditorHeading } from '../toolbar/editor-heading';
|
|
20
|
-
import { MlvEditorHighlight } from '../toolbar/editor-highlight';
|
|
21
|
-
import { MlvEditorInlineMarks } from '../toolbar/editor-inline-marks';
|
|
22
|
-
import { MlvEditorList } from '../toolbar/editor-list';
|
|
23
|
-
import { MlvEditorLink } from '../toolbar/editor-link';
|
|
24
|
-
import { MlvEditorImageUpload, MlvEditorImageUploadStatus, } from '../toolbar/editor-image-upload';
|
|
25
|
-
import { MlvEditorTable } from '../toolbar/editor-table';
|
|
26
|
-
import { MlvEditorToolbarDef, MlvEditorToolbarEndDef, MlvEditorToolbarStartDef, } from '../toolbar/editor-toolbar.defs';
|
|
27
|
-
import { MlvEditorToolbarOverflow, MlvEditorToolbarRoot, } from '../toolbar/editor-toolbar';
|
|
28
|
-
import { MlvEditorUndoRedo } from '../toolbar/editor-undo-redo';
|
|
29
|
-
import { MlvEditorZoom } from '../toolbar/editor-zoom';
|
|
30
|
-
import { MlvEditorTextColor } from '../toolbar/editor-text-color';
|
|
31
|
-
import { MlvEditorStatus } from '../status/editor-status';
|
|
32
|
-
import * as i0 from "@angular/core";
|
|
33
|
-
/**
|
|
34
|
-
* Browser-only Tiptap form control with nullable HTML, Markdown, or JSON
|
|
35
|
-
* values.
|
|
36
|
-
*
|
|
37
|
-
* The component is a pure Angular `FormValueControl`; it deliberately does
|
|
38
|
-
* not implement a `ControlValueAccessor` or provide `NG_VALUE_ACCESSOR`.
|
|
39
|
-
*/
|
|
40
|
-
export class MlvEditor extends MlvSignalFormControlBase {
|
|
41
|
-
/** @private Tiptap instance owned exclusively by this component. */
|
|
42
|
-
_editor = signal(null, /* @ts-ignore */
|
|
43
|
-
...(ngDevMode ? [{ debugName: "_editor" }] : /* istanbul ignore next */ []));
|
|
44
|
-
/** Nullable editor model used by direct, reactive, template, and signal forms. */
|
|
45
|
-
value = model(null, /* @ts-ignore */
|
|
46
|
-
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
47
|
-
/** Serialization format for the visual editor. */
|
|
48
|
-
format = input('html', /* @ts-ignore */
|
|
49
|
-
...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
|
|
50
|
-
/** Width of the centred content column; a gutter is reserved at every value. */
|
|
51
|
-
contentWidth = input('default', /* @ts-ignore */
|
|
52
|
-
...(ngDevMode ? [{ debugName: "contentWidth" }] : /* istanbul ignore next */ []));
|
|
53
|
-
/** Complete Tiptap extension replacement; omit it for Malva's fresh preset. */
|
|
54
|
-
extensions = input(undefined, /* @ts-ignore */
|
|
55
|
-
...(ngDevMode ? [{ debugName: "extensions" }] : /* istanbul ignore next */ []));
|
|
56
|
-
/** Placeholder displayed by the default extension preset. */
|
|
57
|
-
placeholder = input('Write something…', /* @ts-ignore */
|
|
58
|
-
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
59
|
-
/** Maximum character count for Malva's default extension preset. */
|
|
60
|
-
characterLimit = input(null, /* @ts-ignore */
|
|
61
|
-
...(ngDevMode ? [{ debugName: "characterLimit" }] : /* istanbul ignore next */ []));
|
|
62
|
-
/** IDREF(s) naming the editable content region. */
|
|
63
|
-
ariaLabelledBy = input(undefined, /* @ts-ignore */
|
|
64
|
-
...(ngDevMode ? [{ debugName: "ariaLabelledBy" }] : /* istanbul ignore next */ []));
|
|
65
|
-
/** IDREF(s) describing the editable content region. */
|
|
66
|
-
ariaDescribedBy = input(undefined, /* @ts-ignore */
|
|
67
|
-
...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : /* istanbul ignore next */ []));
|
|
68
|
-
/** Per-editor image upload adapter, taking precedence over an injected adapter. */
|
|
69
|
-
imageUploader = input(undefined, /* @ts-ignore */
|
|
70
|
-
...(ngDevMode ? [{ debugName: "imageUploader" }] : /* istanbul ignore next */ []));
|
|
71
|
-
/** Image upload restrictions used by the later upload controls. */
|
|
72
|
-
imageUploadOptions = input(MLV_EDITOR_DEFAULT_IMAGE_UPLOAD_OPTIONS, /* @ts-ignore */
|
|
73
|
-
...(ngDevMode ? [{ debugName: "imageUploadOptions" }] : /* istanbul ignore next */ []));
|
|
74
|
-
/**
|
|
75
|
-
* Per-editor AI transport, taking precedence over an injected
|
|
76
|
-
* `MLV_EDITOR_AI_PROVIDER`. Without either, AI UI modules hide and AI
|
|
77
|
-
* commands report a recoverable `configuration` error.
|
|
78
|
-
*/
|
|
79
|
-
aiProvider = input(undefined, /* @ts-ignore */
|
|
80
|
-
...(ngDevMode ? [{ debugName: "aiProvider" }] : /* istanbul ignore next */ []));
|
|
81
|
-
/** Read-only signal exposing the one Tiptap editor instance after browser mount. */
|
|
82
|
-
editor = this._editor.asReadonly();
|
|
83
|
-
/** Exact editor-owned image upload capability forwarded to public toolbars. */
|
|
84
|
-
get imageUpload() {
|
|
85
|
-
return this._injector.get(MLV_EDITOR_IMAGE_UPLOAD_COORDINATOR);
|
|
86
|
-
}
|
|
87
|
-
/** View-only zoom percentage shared with the nearest toolbar. */
|
|
88
|
-
zoom = signal(100, /* @ts-ignore */
|
|
89
|
-
...(ngDevMode ? [{ debugName: "zoom" }] : /* istanbul ignore next */ []));
|
|
90
|
-
/** Whether the mounted editor currently accepts document mutations. */
|
|
91
|
-
editable = computed(() => this._editor() !== null && !this.computedDisabled() && !this.readonly(), /* @ts-ignore */
|
|
92
|
-
...(ngDevMode ? [{ debugName: "editable" }] : /* istanbul ignore next */ []));
|
|
93
|
-
/** Emits after the browser-only Tiptap editor has been created. */
|
|
94
|
-
editorReady = output();
|
|
95
|
-
/** Emits when focus enters the editable Tiptap content. */
|
|
96
|
-
// The public API deliberately mirrors the documented editor focus event.
|
|
97
|
-
// eslint-disable-next-line @angular-eslint/no-output-native
|
|
98
|
-
focus = output();
|
|
99
|
-
/** Emits when focus leaves the editor composite. */
|
|
100
|
-
// The public API deliberately mirrors the documented editor blur event.
|
|
101
|
-
// eslint-disable-next-line @angular-eslint/no-output-native
|
|
102
|
-
blur = output();
|
|
103
|
-
/** Emits Tiptap selection updates. */
|
|
104
|
-
selectionChange = output();
|
|
105
|
-
/** Emits every Tiptap transaction. */
|
|
106
|
-
transaction = output();
|
|
107
|
-
/** Emits recoverable construction, parsing, and serialization errors. */
|
|
108
|
-
editorError = output();
|
|
109
|
-
/** Emits after an image upload succeeds. */
|
|
110
|
-
imageUploadSuccess = output();
|
|
111
|
-
/** Emits after an image upload fails. */
|
|
112
|
-
imageUploadFailure = output();
|
|
113
|
-
/** Emits after an image upload is cancelled. */
|
|
114
|
-
imageUploadCancelled = output();
|
|
115
|
-
/** Whether the nullable model contains meaningful serialized content. */
|
|
116
|
-
hasValue = computed(() => this.value() !== null, /* @ts-ignore */
|
|
117
|
-
...(ngDevMode ? [{ debugName: "hasValue" }] : /* istanbul ignore next */ []));
|
|
118
|
-
/** @private Browser-only mount element for Tiptap's ProseMirror DOM. */
|
|
119
|
-
_content = viewChild.required('content', /* @ts-ignore */
|
|
120
|
-
...(ngDevMode ? [{ debugName: "_content" }] : /* istanbul ignore next */ []));
|
|
121
|
-
/**
|
|
122
|
-
* @private Zoom-transformed layer the floating block handle is mounted into.
|
|
123
|
-
*
|
|
124
|
-
* Deliberately optional rather than `viewChild.required`: the block-handle
|
|
125
|
-
* `mount` capability is typed `() => HTMLElement | null`, and the extension
|
|
126
|
-
* may call it from a ProseMirror plugin view during a user interaction. A
|
|
127
|
-
* required query throws `NG0951` while unresolved, which would surface as an
|
|
128
|
-
* uncaught error rather than the absent mount the contract already allows.
|
|
129
|
-
*/
|
|
130
|
-
_view = viewChild('view', /* @ts-ignore */
|
|
131
|
-
...(ngDevMode ? [{ debugName: "_view" }] : /* istanbul ignore next */ []));
|
|
132
|
-
/** @protected Complete projected toolbar replacement, if the consumer provides one. */
|
|
133
|
-
_toolbarDefs = contentChildren(MlvEditorToolbarDef, /* @ts-ignore */
|
|
134
|
-
...(ngDevMode ? [{ debugName: "_toolbarDefs" }] : /* istanbul ignore next */ []));
|
|
135
|
-
/** @protected Projected controls displayed before the built-in toolbar groups. */
|
|
136
|
-
_toolbarStartDefs = contentChildren(MlvEditorToolbarStartDef, /* @ts-ignore */
|
|
137
|
-
...(ngDevMode ? [{ debugName: "_toolbarStartDefs" }] : /* istanbul ignore next */ []));
|
|
138
|
-
/** @protected Projected controls displayed after the built-in toolbar groups. */
|
|
139
|
-
_toolbarEndDefs = contentChildren(MlvEditorToolbarEndDef, /* @ts-ignore */
|
|
140
|
-
...(ngDevMode ? [{ debugName: "_toolbarEndDefs" }] : /* istanbul ignore next */ []));
|
|
141
|
-
/** @protected Whether a consumer declared a complete toolbar replacement. */
|
|
142
|
-
_hasToolbarDef = computed(() => this._toolbarDefs().length > 0, /* @ts-ignore */
|
|
143
|
-
...(ngDevMode ? [{ debugName: "_hasToolbarDef" }] : /* istanbul ignore next */ []));
|
|
144
|
-
/** @protected Context supplied as the implicit value of projected toolbar templates. */
|
|
145
|
-
_toolbarContext = this;
|
|
146
|
-
/** @private Platform marker used to keep all editor construction out of SSR. */
|
|
147
|
-
_isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
148
|
-
/** @private Teardown registration for the browser editor instance. */
|
|
149
|
-
_destroyRef = inject(DestroyRef);
|
|
150
|
-
/** @private Registry for overlay roots logically owned by this composite control. */
|
|
151
|
-
_overlayRegistry = inject(MlvEditorOverlayRegistry);
|
|
152
|
-
/** @private Injector used after construction to resolve the editor coordinator safely. */
|
|
153
|
-
_injector = inject(Injector);
|
|
154
|
-
/** @private Invalidates built-in command state after Tiptap state changes. */
|
|
155
|
-
_toolbarRevision = inject(MlvEditorToolbarRevision);
|
|
156
|
-
/** @private Registry of in-flight upload abort callbacks. */
|
|
157
|
-
_uploadAbortRegistry = inject(MlvEditorUploadAbortRegistry);
|
|
158
|
-
/** @private Physical host used to determine the composite focus boundary. */
|
|
159
|
-
_host = inject(ElementRef);
|
|
160
|
-
/** @private Optional translated accessible defaults. */
|
|
161
|
-
_i18n = inject(MLV_EDITOR_I18N, { optional: true });
|
|
162
|
-
/** @private Announces block moves politely; the editor content itself is not a live region. */
|
|
163
|
-
_liveAnnouncer = inject(LiveAnnouncer);
|
|
164
|
-
/** @private Last external value applied to Tiptap without an update event. */
|
|
165
|
-
_lastAppliedValue;
|
|
166
|
-
/** @private Last value emitted from a user transaction or format conversion. */
|
|
167
|
-
_lastEmittedValue;
|
|
168
|
-
/** @private Active serialization mode for the current editor document. */
|
|
169
|
-
_activeFormat;
|
|
170
|
-
/** @private Guards against duplicate Tiptap teardown. */
|
|
171
|
-
_destroyed = false;
|
|
172
|
-
/** @private Suppresses document-transaction serialization while applying an external value. */
|
|
173
|
-
_applyingExternalValue = false;
|
|
174
|
-
/** @private Tracks the disabled edge so overlays/uploads close once per transition. */
|
|
175
|
-
_wasDisabled = false;
|
|
176
|
-
/** @private Tracks the readonly edge so uploads stop before they can mutate content. */
|
|
177
|
-
_wasReadonly = false;
|
|
178
|
-
/** @private Text selection retained while ProseMirror is made non-editable. */
|
|
179
|
-
_disabledSelection;
|
|
180
|
-
/** @private Stored marks retained with a collapsed selection while disabled. */
|
|
181
|
-
_disabledStoredMarks;
|
|
182
|
-
/** @private Avoids duplicate queued focus-leave checks. */
|
|
183
|
-
_blurCheckQueued = false;
|
|
184
|
-
/** @private The last boundary event, retained until the microtask resolves focus ownership. */
|
|
185
|
-
_pendingBlurEvent;
|
|
186
|
-
/** @private Stable capture listener for focus entering the physical host. */
|
|
187
|
-
_onHostFocusIn = (event) => this._handleCompositeFocusIn(event);
|
|
188
|
-
/** @private Stable capture listener for focus leaving the physical host. */
|
|
189
|
-
_onHostFocusOut = (event) => this._handleCompositeFocusOut(event);
|
|
190
|
-
/** @private Stable capture listener that blocks disabled projected controls. */
|
|
191
|
-
_onDisabledPointerOrClick = (event) => this._blockDisabledInteraction(event);
|
|
192
|
-
/** @private Stable capture listener that blocks disabled keyboard activation. */
|
|
193
|
-
_onDisabledKeydown = (event) => {
|
|
194
|
-
if (event.key !== 'Enter' &&
|
|
195
|
-
event.key !== ' ' &&
|
|
196
|
-
event.key !== 'Spacebar') {
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
this._blockDisabledInteraction(event);
|
|
200
|
-
};
|
|
201
|
-
/** @protected Fallback-accessible name when no visible label is supplied. */
|
|
202
|
-
_resolvedAriaLabel = computed(() => this.ariaLabel() ?? this._i18n?.().editorLabel ?? 'Rich text editor', /* @ts-ignore */
|
|
203
|
-
...(ngDevMode ? [{ debugName: "_resolvedAriaLabel" }] : /* istanbul ignore next */ []));
|
|
204
|
-
/** @protected Descriptions supplied explicitly or by the inherited validation message. */
|
|
205
|
-
_resolvedAriaDescribedBy = computed(() => this.ariaDescribedBy() ??
|
|
206
|
-
(this.message() ? `${this.id()}-message` : undefined), /* @ts-ignore */
|
|
207
|
-
...(ngDevMode ? [{ debugName: "_resolvedAriaDescribedBy" }] : /* istanbul ignore next */ []));
|
|
208
|
-
/** @protected ID used to connect a visible inherited label to ProseMirror. */
|
|
209
|
-
_labelId = computed(() => `${this.id()}-label`, /* @ts-ignore */
|
|
210
|
-
...(ngDevMode ? [{ debugName: "_labelId" }] : /* istanbul ignore next */ []));
|
|
211
|
-
/** @protected Accessible label for the projected toolbar region. */
|
|
212
|
-
_toolbarAriaLabel = computed(() => this._i18n?.().toolbarLabel ?? 'Editor toolbar', /* @ts-ignore */
|
|
213
|
-
...(ngDevMode ? [{ debugName: "_toolbarAriaLabel" }] : /* istanbul ignore next */ []));
|
|
214
|
-
constructor() {
|
|
215
|
-
super();
|
|
216
|
-
effect(() => {
|
|
217
|
-
const editor = this._editor();
|
|
218
|
-
const disabled = this.computedDisabled();
|
|
219
|
-
const readonly = this.readonly();
|
|
220
|
-
const wasDisabled = this._wasDisabled;
|
|
221
|
-
if (disabled && !wasDisabled) {
|
|
222
|
-
this._disabledSelection = editor
|
|
223
|
-
? { from: editor.state.selection.from, to: editor.state.selection.to }
|
|
224
|
-
: undefined;
|
|
225
|
-
this._disabledStoredMarks = editor
|
|
226
|
-
? (editor.state.storedMarks ?? editor.state.selection.$from.marks())
|
|
227
|
-
: undefined;
|
|
228
|
-
this._removeCompositeFocusForDisabledState();
|
|
229
|
-
this._overlayRegistry.closeAll();
|
|
230
|
-
this._abortInFlightUploads();
|
|
231
|
-
}
|
|
232
|
-
this._wasDisabled = disabled;
|
|
233
|
-
if (readonly && !this._wasReadonly) {
|
|
234
|
-
this._abortInFlightUploads();
|
|
235
|
-
}
|
|
236
|
-
this._wasReadonly = readonly;
|
|
237
|
-
if (!editor)
|
|
238
|
-
return;
|
|
239
|
-
editor.setEditable(!disabled && !readonly);
|
|
240
|
-
if (!disabled && wasDisabled && this._disabledSelection) {
|
|
241
|
-
editor.commands.setTextSelection(this._disabledSelection);
|
|
242
|
-
if (this._disabledStoredMarks) {
|
|
243
|
-
editor.view.dispatch(editor.state.tr.setStoredMarks(this._disabledStoredMarks));
|
|
244
|
-
}
|
|
245
|
-
this._disabledSelection = undefined;
|
|
246
|
-
this._disabledStoredMarks = undefined;
|
|
247
|
-
}
|
|
248
|
-
this._synchronizeContentSurfaceState(editor);
|
|
249
|
-
});
|
|
250
|
-
effect(() => this._synchronizeEditor());
|
|
251
|
-
this._overlayRegistry.setFocusHandlers((event) => this._handleCompositeFocusIn(event), (event) => this._handleCompositeFocusOut(event));
|
|
252
|
-
this._destroyRef.onDestroy(() => {
|
|
253
|
-
this._destroyed = true;
|
|
254
|
-
this._removeCompositeFocusForDisabledState();
|
|
255
|
-
this._overlayRegistry.closeAll();
|
|
256
|
-
this._abortInFlightUploads();
|
|
257
|
-
this._overlayRegistry.destroy();
|
|
258
|
-
this._destroyEditor();
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
/** Creates the one Tiptap editor after Angular has rendered the mount element. */
|
|
262
|
-
ngAfterViewInit() {
|
|
263
|
-
if (!this._isBrowser || this._editor() || this._destroyed)
|
|
264
|
-
return;
|
|
265
|
-
this._bindCompositeFocusEvents();
|
|
266
|
-
const initialFormat = this.format();
|
|
267
|
-
const initialRawValue = this.value();
|
|
268
|
-
const initialValue = normalizeEditorValue(initialRawValue);
|
|
269
|
-
if (initialRawValue !== initialValue) {
|
|
270
|
-
this._lastEmittedValue = initialValue;
|
|
271
|
-
this.value.set(initialValue);
|
|
272
|
-
}
|
|
273
|
-
try {
|
|
274
|
-
// A consumer array remains a literal replacement. Defaults are selected
|
|
275
|
-
// once so preflight and Tiptap receive the identical extension objects.
|
|
276
|
-
const selectedExtensions = this.extensions() ??
|
|
277
|
-
mlvEditorDefaultExtensions({
|
|
278
|
-
format: 'markdown',
|
|
279
|
-
placeholder: this.placeholder(),
|
|
280
|
-
characterLimit: this.characterLimit(),
|
|
281
|
-
allowedMimeTypes: ['image/*'],
|
|
282
|
-
fileHandlingEnabled: () => {
|
|
283
|
-
if (this._destroyed || this.computedDisabled() || this.readonly()) {
|
|
284
|
-
return false;
|
|
285
|
-
}
|
|
286
|
-
return this._injector
|
|
287
|
-
.get(MLV_EDITOR_IMAGE_UPLOAD_COORDINATOR)
|
|
288
|
-
.available();
|
|
289
|
-
},
|
|
290
|
-
acceptsMimeType: (mimeType) => this._acceptsImageMimeType(mimeType),
|
|
291
|
-
onFiles: ({ files, source, position }) => {
|
|
292
|
-
if (this._destroyed || this.computedDisabled() || this.readonly()) {
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
const acceptedImages = files.filter((file) => file.type.startsWith('image/') &&
|
|
296
|
-
this._acceptsImageMimeType(file.type));
|
|
297
|
-
if (!acceptedImages.length)
|
|
298
|
-
return;
|
|
299
|
-
this._injector
|
|
300
|
-
.get(MLV_EDITOR_IMAGE_UPLOAD_COORDINATOR)
|
|
301
|
-
.start(acceptedImages, source, {
|
|
302
|
-
...(position === undefined ? {} : { position }),
|
|
303
|
-
});
|
|
304
|
-
},
|
|
305
|
-
blockHandle: {
|
|
306
|
-
mount: () => this._view()?.nativeElement ?? null,
|
|
307
|
-
label: () => this._i18n?.().dragBlock ?? 'Drag block',
|
|
308
|
-
enabled: () => !this._destroyed && !this.computedDisabled() && !this.readonly(),
|
|
309
|
-
announceMove: (move) => this._announceBlockMove(move),
|
|
310
|
-
},
|
|
311
|
-
});
|
|
312
|
-
const preflight = preflightMlvEditorExtensions(selectedExtensions, initialFormat);
|
|
313
|
-
if (!preflight.ok) {
|
|
314
|
-
this.editorError.emit(preflight.error);
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
const editor = new Editor({
|
|
318
|
-
element: this._content().nativeElement,
|
|
319
|
-
...this._emptyDocumentOptions(initialFormat),
|
|
320
|
-
// The factory itself deliberately adds Markdown only for `format:
|
|
321
|
-
// 'markdown'`. The shell always keeps that capability so an in-place
|
|
322
|
-
// switch between any two formats can serialize the existing document
|
|
323
|
-
// without constructing a second editor. A supplied array remains
|
|
324
|
-
// literal.
|
|
325
|
-
extensions: selectedExtensions,
|
|
326
|
-
editable: !this.computedDisabled() && !this.readonly(),
|
|
327
|
-
enableContentCheck: true,
|
|
328
|
-
editorProps: { attributes: this._editorAttributes() },
|
|
329
|
-
onTransaction: ({ editor: changedEditor, transaction }) => {
|
|
330
|
-
if (this._destroyed)
|
|
331
|
-
return;
|
|
332
|
-
this.transaction.emit({ editor: changedEditor, transaction });
|
|
333
|
-
this._toolbarRevision.revision.update((revision) => revision + 1);
|
|
334
|
-
if (transaction.docChanged && !this._applyingExternalValue) {
|
|
335
|
-
this._serializeAndWrite(changedEditor, this.format());
|
|
336
|
-
}
|
|
337
|
-
},
|
|
338
|
-
onSelectionUpdate: ({ editor: changedEditor, transaction }) => {
|
|
339
|
-
if (this._destroyed)
|
|
340
|
-
return;
|
|
341
|
-
this.selectionChange.emit({ editor: changedEditor, transaction });
|
|
342
|
-
this._toolbarRevision.revision.update((revision) => revision + 1);
|
|
343
|
-
},
|
|
344
|
-
onContentError: ({ error }) => {
|
|
345
|
-
if (this._destroyed)
|
|
346
|
-
return;
|
|
347
|
-
this.editorError.emit({
|
|
348
|
-
code: 'parse',
|
|
349
|
-
message: 'Unable to parse the editor value with the configured extensions.',
|
|
350
|
-
recoverable: true,
|
|
351
|
-
cause: error,
|
|
352
|
-
});
|
|
353
|
-
},
|
|
354
|
-
});
|
|
355
|
-
this._activeFormat = initialFormat;
|
|
356
|
-
this._lastAppliedValue = null;
|
|
357
|
-
this._editor.set(editor);
|
|
358
|
-
this._applyInitialValue(editor, initialValue, initialFormat);
|
|
359
|
-
// Consumers may immediately issue commands from `editorReady`; emit only
|
|
360
|
-
// after the initial model has either been applied or recovered from.
|
|
361
|
-
this.editorReady.emit(editor);
|
|
362
|
-
}
|
|
363
|
-
catch (cause) {
|
|
364
|
-
this.editorError.emit({
|
|
365
|
-
code: 'configuration',
|
|
366
|
-
message: 'Unable to create the editor with the configured extensions.',
|
|
367
|
-
recoverable: true,
|
|
368
|
-
cause,
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
/** Clears the document through Tiptap when the shared form wrapper is clearable. */
|
|
373
|
-
clearValue() {
|
|
374
|
-
if (this.computedDisabled() || this.readonly())
|
|
375
|
-
return;
|
|
376
|
-
this._editor()?.commands.clearContent();
|
|
377
|
-
}
|
|
378
|
-
/** @private Formats a completed block move and announces it politely. */
|
|
379
|
-
_announceBlockMove(move) {
|
|
380
|
-
if (this._destroyed)
|
|
381
|
-
return;
|
|
382
|
-
const template = this._i18n?.().blockMoved;
|
|
383
|
-
const message = template
|
|
384
|
-
? template
|
|
385
|
-
.replace('{type}', move.type)
|
|
386
|
-
.replace('{position}', String(move.position))
|
|
387
|
-
.replace('{total}', String(move.total))
|
|
388
|
-
: `Moved ${move.type} to position ${move.position} of ${move.total}`;
|
|
389
|
-
this._liveAnnouncer.announce(message, 'polite');
|
|
390
|
-
}
|
|
391
|
-
/** @private Whether a browser MIME type matches the current coordinator options. */
|
|
392
|
-
_acceptsImageMimeType(mimeType) {
|
|
393
|
-
const normalizedMimeType = mimeType.trim().toLowerCase();
|
|
394
|
-
if (!normalizedMimeType.startsWith('image/'))
|
|
395
|
-
return false;
|
|
396
|
-
return this.imageUploadOptions().accept.some((pattern) => {
|
|
397
|
-
const normalizedPattern = pattern.trim().toLowerCase();
|
|
398
|
-
if (normalizedPattern === '*/*')
|
|
399
|
-
return true;
|
|
400
|
-
if (normalizedPattern.endsWith('/*')) {
|
|
401
|
-
return normalizedMimeType.startsWith(normalizedPattern.slice(0, -1));
|
|
402
|
-
}
|
|
403
|
-
return normalizedMimeType === normalizedPattern;
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
/** Runs a Tiptap mutation command when the editor is available and editable. */
|
|
407
|
-
run(command) {
|
|
408
|
-
if (this.computedDisabled() || this.readonly())
|
|
409
|
-
return false;
|
|
410
|
-
const editor = this._editor();
|
|
411
|
-
if (!editor)
|
|
412
|
-
return false;
|
|
413
|
-
try {
|
|
414
|
-
return command(editor) === true;
|
|
415
|
-
}
|
|
416
|
-
catch {
|
|
417
|
-
return false;
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
/** Checks a Tiptap command when the editor is available and editable. */
|
|
421
|
-
can(command) {
|
|
422
|
-
if (this.computedDisabled() || this.readonly())
|
|
423
|
-
return false;
|
|
424
|
-
const editor = this._editor();
|
|
425
|
-
if (!editor)
|
|
426
|
-
return false;
|
|
427
|
-
try {
|
|
428
|
-
return command(editor) === true;
|
|
429
|
-
}
|
|
430
|
-
catch {
|
|
431
|
-
return false;
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
/** Safely reads a Tiptap active state without requiring a particular extension. */
|
|
435
|
-
isActive(name, attributes) {
|
|
436
|
-
this._toolbarRevision.revision();
|
|
437
|
-
const editor = this._editor();
|
|
438
|
-
if (!editor)
|
|
439
|
-
return false;
|
|
440
|
-
try {
|
|
441
|
-
return editor.isActive(name, attributes);
|
|
442
|
-
}
|
|
443
|
-
catch {
|
|
444
|
-
return false;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
/** Reports a typed recoverable error through the owning editor output. */
|
|
448
|
-
reportError(error) {
|
|
449
|
-
this.editorError.emit(error);
|
|
450
|
-
}
|
|
451
|
-
/** @private Applies the current inputs to the already-created editor instance. */
|
|
452
|
-
_synchronizeEditor() {
|
|
453
|
-
const editor = this._editor();
|
|
454
|
-
if (!editor)
|
|
455
|
-
return;
|
|
456
|
-
const requestedFormat = this.format();
|
|
457
|
-
editor.setOptions({
|
|
458
|
-
editorProps: { attributes: this._editorAttributes() },
|
|
459
|
-
});
|
|
460
|
-
this._synchronizeContentSurfaceState(editor);
|
|
461
|
-
const rawIncoming = this.value();
|
|
462
|
-
const incoming = normalizeEditorValue(rawIncoming);
|
|
463
|
-
// Tracked values were produced under the currently active format, so the
|
|
464
|
-
// comparison runs in that format rather than the requested one. JSON is
|
|
465
|
-
// compared structurally there; a host value that only reorders keys or
|
|
466
|
-
// reflows whitespace describes the mounted document and is not an
|
|
467
|
-
// external change.
|
|
468
|
-
const trackedFormat = this._activeFormat ?? requestedFormat;
|
|
469
|
-
const hasExternalValue = !editorValuesAreEquivalent(incoming, this._lastAppliedValue, trackedFormat) &&
|
|
470
|
-
!editorValuesAreEquivalent(incoming, this._lastEmittedValue, trackedFormat);
|
|
471
|
-
if (this._activeFormat !== requestedFormat) {
|
|
472
|
-
if (hasExternalValue) {
|
|
473
|
-
if (requestedFormat === 'markdown' && !this._supportsMarkdown(editor)) {
|
|
474
|
-
this._emitUnsupportedMarkdownError('configuration');
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
this._activeFormat = requestedFormat;
|
|
478
|
-
this._applyExternalValue(editor, incoming, requestedFormat);
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
if (this._activeFormat !== undefined) {
|
|
482
|
-
if (!this._supportsMarkdown(editor) && requestedFormat === 'markdown') {
|
|
483
|
-
this._emitUnsupportedMarkdownError('configuration');
|
|
484
|
-
return;
|
|
485
|
-
}
|
|
486
|
-
if (!this._serializeAndWrite(editor, requestedFormat))
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
this._activeFormat = requestedFormat;
|
|
490
|
-
}
|
|
491
|
-
if (rawIncoming !== incoming) {
|
|
492
|
-
this._lastEmittedValue = incoming;
|
|
493
|
-
this.value.set(incoming);
|
|
494
|
-
}
|
|
495
|
-
if (!hasExternalValue) {
|
|
496
|
-
this._lastAppliedValue = incoming;
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
this._applyExternalValue(editor, incoming, requestedFormat);
|
|
500
|
-
}
|
|
501
|
-
/** @private Applies an external value without reflecting it back through `onUpdate`. */
|
|
502
|
-
_applyExternalValue(editor, value, format) {
|
|
503
|
-
const prepared = value === null ? null : this._prepareContent(editor, value, format);
|
|
504
|
-
if (prepared !== null && !prepared.ok) {
|
|
505
|
-
this._recoverFromInvalidValue(prepared.cause);
|
|
506
|
-
return;
|
|
507
|
-
}
|
|
508
|
-
try {
|
|
509
|
-
this._applyingExternalValue = true;
|
|
510
|
-
// External applications must stay invisible to user undo history:
|
|
511
|
-
// Tiptap's setContent/clearContent never set `addToHistory`, so a bare
|
|
512
|
-
// command would land the initial or programmatic document as an undoable
|
|
513
|
-
// step whose undo empties the editor. The chain shares one transaction,
|
|
514
|
-
// so the meta covers the whole application.
|
|
515
|
-
if (prepared === null) {
|
|
516
|
-
editor.chain().setMeta('addToHistory', false).clearContent(false).run();
|
|
517
|
-
}
|
|
518
|
-
else {
|
|
519
|
-
editor
|
|
520
|
-
.chain()
|
|
521
|
-
.setMeta('addToHistory', false)
|
|
522
|
-
.setContent(prepared.content, prepared.options)
|
|
523
|
-
.run();
|
|
524
|
-
}
|
|
525
|
-
this._lastAppliedValue = value;
|
|
526
|
-
this._lastEmittedValue = undefined;
|
|
527
|
-
}
|
|
528
|
-
catch (cause) {
|
|
529
|
-
this._recoverFromInvalidValue(cause);
|
|
530
|
-
}
|
|
531
|
-
finally {
|
|
532
|
-
this._applyingExternalValue = false;
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
/**
|
|
536
|
-
* @private Converts one nonempty external value into Tiptap content and
|
|
537
|
-
* options.
|
|
538
|
-
*
|
|
539
|
-
* The branch is exhaustive over every format rather than special-casing one:
|
|
540
|
-
* HTML is parsed from its own markup, Markdown declares its content type so
|
|
541
|
-
* the Markdown manager parses it, and JSON is handed over as an
|
|
542
|
-
* already-parsed document node because Tiptap reads any string argument as
|
|
543
|
-
* HTML. A rejected JSON value carries its cause instead of a document.
|
|
544
|
-
*/
|
|
545
|
-
_prepareContent(editor, value, format) {
|
|
546
|
-
switch (format) {
|
|
547
|
-
case 'html':
|
|
548
|
-
return {
|
|
549
|
-
ok: true,
|
|
550
|
-
content: value,
|
|
551
|
-
options: { emitUpdate: false, errorOnInvalidContent: true },
|
|
552
|
-
};
|
|
553
|
-
case 'markdown':
|
|
554
|
-
return {
|
|
555
|
-
ok: true,
|
|
556
|
-
content: value,
|
|
557
|
-
options: {
|
|
558
|
-
emitUpdate: false,
|
|
559
|
-
errorOnInvalidContent: true,
|
|
560
|
-
contentType: 'markdown',
|
|
561
|
-
},
|
|
562
|
-
};
|
|
563
|
-
case 'json': {
|
|
564
|
-
const parsed = parseEditorJsonDocument(value, editor.schema.topNodeType.name);
|
|
565
|
-
return parsed.ok
|
|
566
|
-
? {
|
|
567
|
-
ok: true,
|
|
568
|
-
content: parsed.document,
|
|
569
|
-
options: { emitUpdate: false, errorOnInvalidContent: true },
|
|
570
|
-
}
|
|
571
|
-
: { ok: false, cause: parsed.cause };
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
/**
|
|
576
|
-
* @private Construction options mounting an empty document for one format.
|
|
577
|
-
*
|
|
578
|
-
* Tiptap is always constructed against an empty document so every real
|
|
579
|
-
* value travels the same strict parsing path. Markdown still declares its
|
|
580
|
-
* content type here because the Markdown manager validates that declaration
|
|
581
|
-
* against the supplied content before the first document is published. HTML
|
|
582
|
-
* needs no declaration, and JSON never reaches Tiptap as a string at all.
|
|
583
|
-
*/
|
|
584
|
-
_emptyDocumentOptions(format) {
|
|
585
|
-
switch (format) {
|
|
586
|
-
case 'html':
|
|
587
|
-
return { content: '' };
|
|
588
|
-
case 'markdown':
|
|
589
|
-
return { content: '', contentType: 'markdown' };
|
|
590
|
-
case 'json':
|
|
591
|
-
return { content: '' };
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
/** @private Restores the last valid value and reports a recoverable parse failure. */
|
|
595
|
-
_recoverFromInvalidValue(cause) {
|
|
596
|
-
const lastValidValue = this._lastAppliedValue ?? null;
|
|
597
|
-
this._lastEmittedValue = lastValidValue;
|
|
598
|
-
if (this.value() !== lastValidValue) {
|
|
599
|
-
this.value.set(lastValidValue);
|
|
600
|
-
}
|
|
601
|
-
this.editorError.emit({
|
|
602
|
-
code: 'parse',
|
|
603
|
-
message: 'Unable to parse the editor value with the configured extensions.',
|
|
604
|
-
recoverable: true,
|
|
605
|
-
cause,
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* @private Serializes an editor transaction and writes only valid distinct
|
|
610
|
-
* values.
|
|
611
|
-
*
|
|
612
|
-
* The distinctness check runs in the serialized format, so a JSON document
|
|
613
|
-
* that differs from the model only by key order or whitespace is not
|
|
614
|
-
* re-emitted. An emission therefore follows only a real user transaction or
|
|
615
|
-
* an explicit format conversion.
|
|
616
|
-
*/
|
|
617
|
-
_serializeAndWrite(editor, format) {
|
|
618
|
-
const result = serializeEditorValue(editor, format);
|
|
619
|
-
if (!result.ok) {
|
|
620
|
-
this.editorError.emit(result.error);
|
|
621
|
-
return false;
|
|
622
|
-
}
|
|
623
|
-
this._lastAppliedValue = result.value;
|
|
624
|
-
this._lastEmittedValue = result.value;
|
|
625
|
-
if (!editorValuesAreEquivalent(this.value(), result.value, format)) {
|
|
626
|
-
this.value.set(result.value);
|
|
627
|
-
}
|
|
628
|
-
return true;
|
|
629
|
-
}
|
|
630
|
-
/**
|
|
631
|
-
* @private Applies the initial model through the same strict parsing path as
|
|
632
|
-
* later updates.
|
|
633
|
-
*
|
|
634
|
-
* Only Markdown has a capability requirement; HTML and JSON mount against
|
|
635
|
-
* any valid extension set.
|
|
636
|
-
*/
|
|
637
|
-
_applyInitialValue(editor, value, format) {
|
|
638
|
-
switch (format) {
|
|
639
|
-
case 'markdown':
|
|
640
|
-
if (!this._supportsMarkdown(editor)) {
|
|
641
|
-
this._emitUnsupportedMarkdownError('configuration');
|
|
642
|
-
this._lastAppliedValue = null;
|
|
643
|
-
this._lastEmittedValue = null;
|
|
644
|
-
if (this.value() !== null)
|
|
645
|
-
this.value.set(null);
|
|
646
|
-
return;
|
|
647
|
-
}
|
|
648
|
-
break;
|
|
649
|
-
case 'html':
|
|
650
|
-
case 'json':
|
|
651
|
-
break;
|
|
652
|
-
}
|
|
653
|
-
this._applyExternalValue(editor, value, format);
|
|
654
|
-
}
|
|
655
|
-
/** @private Whether the runtime editor exposes Tiptap Markdown serialization. */
|
|
656
|
-
_supportsMarkdown(editor) {
|
|
657
|
-
return typeof editor.getMarkdown === 'function';
|
|
658
|
-
}
|
|
659
|
-
/** @private Emits the stable unsupported-Markdown error without throwing through Angular. */
|
|
660
|
-
_emitUnsupportedMarkdownError(code) {
|
|
661
|
-
this.editorError.emit({
|
|
662
|
-
code,
|
|
663
|
-
message: 'Markdown requires the configured extensions to include Tiptap Markdown.',
|
|
664
|
-
recoverable: true,
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
/** @private Builds the exact accessible attributes assigned to Tiptap's contenteditable root. */
|
|
668
|
-
_editorAttributes() {
|
|
669
|
-
const attributes = {
|
|
670
|
-
id: this.id(),
|
|
671
|
-
role: 'textbox',
|
|
672
|
-
'aria-multiline': 'true',
|
|
673
|
-
};
|
|
674
|
-
const labelledBy = this.ariaLabelledBy();
|
|
675
|
-
if (labelledBy) {
|
|
676
|
-
attributes['aria-labelledby'] = labelledBy;
|
|
677
|
-
}
|
|
678
|
-
else if (this.ariaLabel()) {
|
|
679
|
-
attributes['aria-label'] = this._resolvedAriaLabel();
|
|
680
|
-
}
|
|
681
|
-
else if (this.label()) {
|
|
682
|
-
attributes['aria-labelledby'] = this._labelId();
|
|
683
|
-
}
|
|
684
|
-
else {
|
|
685
|
-
attributes['aria-label'] = this._resolvedAriaLabel();
|
|
686
|
-
}
|
|
687
|
-
const describedBy = this._resolvedAriaDescribedBy();
|
|
688
|
-
if (describedBy) {
|
|
689
|
-
attributes['aria-describedby'] = describedBy;
|
|
690
|
-
}
|
|
691
|
-
if (this.resolvedState() === 'error') {
|
|
692
|
-
attributes['aria-invalid'] = 'true';
|
|
693
|
-
}
|
|
694
|
-
if (this.computedDisabled()) {
|
|
695
|
-
attributes['aria-disabled'] = 'true';
|
|
696
|
-
attributes['tabindex'] = '-1';
|
|
697
|
-
}
|
|
698
|
-
else {
|
|
699
|
-
attributes['tabindex'] = '0';
|
|
700
|
-
}
|
|
701
|
-
if (this.readonly()) {
|
|
702
|
-
attributes['aria-readonly'] = 'true';
|
|
703
|
-
}
|
|
704
|
-
return attributes;
|
|
705
|
-
}
|
|
706
|
-
/** @internal Capture handler for focus entering the host or an owned overlay root. */
|
|
707
|
-
_handleCompositeFocusIn(event) {
|
|
708
|
-
if (this._destroyed || this.computedDisabled() || this.focused())
|
|
709
|
-
return;
|
|
710
|
-
const editor = this._editor();
|
|
711
|
-
if (!editor)
|
|
712
|
-
return;
|
|
713
|
-
this.setFocused(true);
|
|
714
|
-
this.focus.emit({ editor, event });
|
|
715
|
-
}
|
|
716
|
-
/** @internal Capture handler for focus leaving the host or an owned overlay root. */
|
|
717
|
-
_handleCompositeFocusOut(event) {
|
|
718
|
-
if (this._destroyed || !this.focused())
|
|
719
|
-
return;
|
|
720
|
-
this._pendingBlurEvent = event;
|
|
721
|
-
if (this._blurCheckQueued)
|
|
722
|
-
return;
|
|
723
|
-
this._blurCheckQueued = true;
|
|
724
|
-
queueMicrotask(() => {
|
|
725
|
-
this._blurCheckQueued = false;
|
|
726
|
-
const pendingEvent = this._pendingBlurEvent;
|
|
727
|
-
this._pendingBlurEvent = undefined;
|
|
728
|
-
if (!pendingEvent ||
|
|
729
|
-
this._destroyed ||
|
|
730
|
-
this._isFocusInsideComposite(pendingEvent.relatedTarget)) {
|
|
731
|
-
return;
|
|
732
|
-
}
|
|
733
|
-
const editor = this._editor();
|
|
734
|
-
if (!editor)
|
|
735
|
-
return;
|
|
736
|
-
this.setFocused(false);
|
|
737
|
-
this._markTouched();
|
|
738
|
-
this.blur.emit({ editor, event: pendingEvent });
|
|
739
|
-
});
|
|
740
|
-
}
|
|
741
|
-
/** @private Whether the browser's current focus remains in the host or an owned overlay. */
|
|
742
|
-
_isFocusInsideComposite(relatedTarget) {
|
|
743
|
-
if (typeof Node !== 'undefined' && relatedTarget instanceof Node) {
|
|
744
|
-
return this._isOwnedFocusNode(relatedTarget);
|
|
745
|
-
}
|
|
746
|
-
if (typeof document === 'undefined')
|
|
747
|
-
return false;
|
|
748
|
-
return this._isOwnedFocusNode(document.activeElement);
|
|
749
|
-
}
|
|
750
|
-
/** @private Whether a node belongs to the physical shell or an owned overlay. */
|
|
751
|
-
_isOwnedFocusNode(node) {
|
|
752
|
-
return (node !== null &&
|
|
753
|
-
(this._host.nativeElement.contains(node) ||
|
|
754
|
-
this._overlayRegistry.contains(node)));
|
|
755
|
-
}
|
|
756
|
-
/** @private Installs native capture listeners because overlay focus is outside Angular's view tree. */
|
|
757
|
-
_bindCompositeFocusEvents() {
|
|
758
|
-
const host = this._host.nativeElement;
|
|
759
|
-
host.addEventListener('focusin', this._onHostFocusIn, true);
|
|
760
|
-
host.addEventListener('focusout', this._onHostFocusOut, true);
|
|
761
|
-
host.addEventListener('pointerdown', this._onDisabledPointerOrClick, true);
|
|
762
|
-
host.addEventListener('click', this._onDisabledPointerOrClick, true);
|
|
763
|
-
host.addEventListener('keydown', this._onDisabledKeydown, true);
|
|
764
|
-
this._destroyRef.onDestroy(() => {
|
|
765
|
-
host.removeEventListener('focusin', this._onHostFocusIn, true);
|
|
766
|
-
host.removeEventListener('focusout', this._onHostFocusOut, true);
|
|
767
|
-
host.removeEventListener('pointerdown', this._onDisabledPointerOrClick, true);
|
|
768
|
-
host.removeEventListener('click', this._onDisabledPointerOrClick, true);
|
|
769
|
-
host.removeEventListener('keydown', this._onDisabledKeydown, true);
|
|
770
|
-
});
|
|
771
|
-
}
|
|
772
|
-
/** @private Stops all pointer/click/activation-key command surfaces while disabled. */
|
|
773
|
-
_blockDisabledInteraction(event) {
|
|
774
|
-
if (!this.computedDisabled())
|
|
775
|
-
return;
|
|
776
|
-
event.preventDefault();
|
|
777
|
-
event.stopImmediatePropagation();
|
|
778
|
-
}
|
|
779
|
-
/** @private Removes browser focus when the composite becomes disabled without marking it touched. */
|
|
780
|
-
_removeCompositeFocusForDisabledState() {
|
|
781
|
-
if (typeof document === 'undefined' || typeof HTMLElement === 'undefined') {
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
784
|
-
const activeElement = document.activeElement;
|
|
785
|
-
if (!(activeElement instanceof HTMLElement) ||
|
|
786
|
-
!this._isOwnedFocusNode(activeElement)) {
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
this.setFocused(false);
|
|
790
|
-
activeElement.blur();
|
|
791
|
-
}
|
|
792
|
-
/** @private Keeps the real ProseMirror root in sync with dynamic ARIA/tabindex state. */
|
|
793
|
-
_synchronizeContentSurfaceState(editor) {
|
|
794
|
-
const element = editor.view.dom;
|
|
795
|
-
const attributes = this._editorAttributes();
|
|
796
|
-
const managedAttributes = [
|
|
797
|
-
'aria-disabled',
|
|
798
|
-
'aria-readonly',
|
|
799
|
-
'tabindex',
|
|
800
|
-
'aria-invalid',
|
|
801
|
-
];
|
|
802
|
-
for (const name of managedAttributes) {
|
|
803
|
-
const value = attributes[name];
|
|
804
|
-
if (value === undefined) {
|
|
805
|
-
element.removeAttribute(name);
|
|
806
|
-
}
|
|
807
|
-
else {
|
|
808
|
-
element.setAttribute(name, value);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
/** @private Aborts registered upload work while preserving the document/editor instance. */
|
|
813
|
-
_abortInFlightUploads() {
|
|
814
|
-
this._uploadAbortRegistry.abortAll();
|
|
815
|
-
}
|
|
816
|
-
/** @private Destroys the owned Tiptap editor exactly once. */
|
|
817
|
-
_destroyEditor() {
|
|
818
|
-
const editor = this._editor();
|
|
819
|
-
if (!editor)
|
|
820
|
-
return;
|
|
821
|
-
this._editor.set(null);
|
|
822
|
-
editor?.destroy();
|
|
823
|
-
}
|
|
824
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvEditor, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
825
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MlvEditor, isStandalone: true, selector: "mlv-editor", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, contentWidth: { classPropertyName: "contentWidth", publicName: "contentWidth", isSignal: true, isRequired: false, transformFunction: null }, extensions: { classPropertyName: "extensions", publicName: "extensions", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, characterLimit: { classPropertyName: "characterLimit", publicName: "characterLimit", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "ariaLabelledBy", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, imageUploader: { classPropertyName: "imageUploader", publicName: "imageUploader", isSignal: true, isRequired: false, transformFunction: null }, imageUploadOptions: { classPropertyName: "imageUploadOptions", publicName: "imageUploadOptions", isSignal: true, isRequired: false, transformFunction: null }, aiProvider: { classPropertyName: "aiProvider", publicName: "aiProvider", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", editorReady: "editorReady", focus: "focus", blur: "blur", selectionChange: "selectionChange", transaction: "transaction", editorError: "editorError", imageUploadSuccess: "imageUploadSuccess", imageUploadFailure: "imageUploadFailure", imageUploadCancelled: "imageUploadCancelled" }, host: { properties: { "class": "\"mlv-editor--content-width-\" + contentWidth()", "class.mlv-editor--disabled": "computedDisabled()", "class.mlv-editor--readonly": "readonly()", "class.mlv-editor--focused": "focused()", "attr.aria-disabled": "computedDisabled() || null", "attr.inert": "computedDisabled() ? \"\" : null", "style.--mlv-editor-zoom": "zoom() / 100" }, classAttribute: "mlv-editor" }, providers: [
|
|
826
|
-
MlvEditorOverlayRegistry,
|
|
827
|
-
MlvEditorToolbarRevision,
|
|
828
|
-
MlvEditorToolbarRovingRegistry,
|
|
829
|
-
MlvEditorUploadAbortRegistry,
|
|
830
|
-
{
|
|
831
|
-
provide: MLV_FORM_CONTROL,
|
|
832
|
-
useExisting: forwardRef(() => MlvEditor),
|
|
833
|
-
},
|
|
834
|
-
{
|
|
835
|
-
provide: MLV_EDITOR_TOOLBAR_CONTEXT,
|
|
836
|
-
useExisting: forwardRef(() => MlvEditor),
|
|
837
|
-
},
|
|
838
|
-
{
|
|
839
|
-
provide: MLV_EDITOR_TOOLBAR_REVISION,
|
|
840
|
-
useFactory: (state) => state.revision,
|
|
841
|
-
deps: [MlvEditorToolbarRevision],
|
|
842
|
-
},
|
|
843
|
-
{
|
|
844
|
-
provide: MLV_EDITOR_TOOLBAR_ROVING,
|
|
845
|
-
useExisting: MlvEditorToolbarRovingRegistry,
|
|
846
|
-
},
|
|
847
|
-
{
|
|
848
|
-
provide: MLV_EDITOR_OVERLAY_REGISTRY,
|
|
849
|
-
useExisting: MlvEditorOverlayRegistry,
|
|
850
|
-
},
|
|
851
|
-
{
|
|
852
|
-
provide: MLV_EDITOR_UPLOAD_ABORT_REGISTRY,
|
|
853
|
-
useExisting: MlvEditorUploadAbortRegistry,
|
|
854
|
-
},
|
|
855
|
-
MlvEditorAiContext,
|
|
856
|
-
{
|
|
857
|
-
provide: MLV_EDITOR_AI_CONTEXT,
|
|
858
|
-
useExisting: MlvEditorAiContext,
|
|
859
|
-
},
|
|
860
|
-
{
|
|
861
|
-
provide: MLV_EDITOR_AI_INPUT_PROVIDER,
|
|
862
|
-
useFactory: () => {
|
|
863
|
-
const owner = inject(forwardRef(() => MlvEditor));
|
|
864
|
-
return owner.aiProvider;
|
|
865
|
-
},
|
|
866
|
-
},
|
|
867
|
-
{
|
|
868
|
-
provide: MLV_EDITOR_IMAGE_UPLOAD_COORDINATOR,
|
|
869
|
-
useFactory: () => {
|
|
870
|
-
const owner = inject(forwardRef(() => MlvEditor));
|
|
871
|
-
return createMlvEditorImageUploadCoordinator({
|
|
872
|
-
editor: owner.editor,
|
|
873
|
-
imageUploader: owner.imageUploader,
|
|
874
|
-
imageUploadOptions: owner.imageUploadOptions,
|
|
875
|
-
disabled: () => owner.computedDisabled(),
|
|
876
|
-
readonly: () => owner.readonly(),
|
|
877
|
-
emitSuccess: (event) => owner.imageUploadSuccess.emit(event),
|
|
878
|
-
emitFailure: (event) => owner.imageUploadFailure.emit(event),
|
|
879
|
-
emitCancelled: (event) => owner.imageUploadCancelled.emit(event),
|
|
880
|
-
emitError: (error) => owner.editorError.emit(error),
|
|
881
|
-
}, inject(MLV_EDITOR_IMAGE_UPLOADER, { optional: true }) ?? undefined, inject(MLV_EDITOR_UPLOAD_ABORT_REGISTRY));
|
|
882
|
-
},
|
|
883
|
-
},
|
|
884
|
-
], queries: [{ propertyName: "_toolbarDefs", predicate: MlvEditorToolbarDef, isSignal: true }, { propertyName: "_toolbarStartDefs", predicate: MlvEditorToolbarStartDef, isSignal: true }, { propertyName: "_toolbarEndDefs", predicate: MlvEditorToolbarEndDef, isSignal: true }], viewQueries: [{ propertyName: "_content", first: true, predicate: ["content"], descendants: true, isSignal: true }, { propertyName: "_view", first: true, predicate: ["view"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<mlv-form-control-wrapper (clear)=\"clearValue()\">\n @if (label() || hint()) {\n <mlv-label [for]=\"id()\" [id]=\"_labelId()\">\n {{ label() }} @if (hint()) {\n <mlv-hint>{{ hint() }}</mlv-hint>\n }\n </mlv-label>\n }\n\n <ng-template mlvFormControlWrapperControl>\n <div class=\"mlv-editor__surface\">\n <div\n mlvEditorToolbarRoot\n #toolbarRoot=\"mlvEditorToolbarRoot\"\n class=\"mlv-editor__toolbar\"\n [ariaLabel]=\"_toolbarAriaLabel()\"\n [disabled]=\"computedDisabled()\"\n >\n @if (_hasToolbarDef()) {\n <ng-content select=\"[mlvEditorToolbar]\" />\n @for (definition of _toolbarDefs(); track definition) { @if\n (definition.templateRef; as toolbarTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"toolbarTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: _toolbarContext }\"\n />\n } } } @else {\n <ng-content select=\"[mlvEditorToolbarStart]\" />\n @for (definition of _toolbarStartDefs(); track definition) { @if\n (definition.templateRef; as startTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"startTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: _toolbarContext }\"\n />\n } }\n <div mlvFade class=\"mlv-editor__toolbar-scroll\">\n <mlv-toolbar>\n <mlv-editor-undo-redo />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n />\n <mlv-editor-zoom />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n />\n <mlv-editor-heading />\n <mlv-editor-list />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-inline-marks [hidden]=\"toolbarRoot.narrow()\" />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-text-color />\n <mlv-editor-highlight />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-alignment [hidden]=\"toolbarRoot.narrow()\" />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-link />\n <mlv-editor-table />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-block-insert [hidden]=\"toolbarRoot.narrow()\" />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-image-upload />\n </mlv-toolbar>\n </div>\n <mlv-editor-toolbar-overflow />\n @for (definition of _toolbarEndDefs(); track definition) { @if\n (definition.templateRef; as endTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"endTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: _toolbarContext }\"\n />\n } }\n <ng-content select=\"[mlvEditorToolbarEnd]\" />\n }\n </div>\n\n <div class=\"mlv-editor__viewport\">\n <div #view class=\"mlv-editor__view\">\n <div #content class=\"mlv-editor__content\"></div>\n </div>\n </div>\n <mlv-editor-image-upload-status />\n </div>\n </ng-template>\n\n @if (message()) {\n <mlv-message [state]=\"resolvedState()\" [id]=\"id() + '-message'\">\n {{ message() }}\n </mlv-message>\n }\n</mlv-form-control-wrapper>\n\n<div\n class=\"mlv-editor__status\"\n [attr.aria-disabled]=\"computedDisabled() || null\"\n>\n <ng-content select=\"[mlvEditorStatus]\" />\n <mlv-spacer />\n <mlv-editor-status [characterLimit]=\"characterLimit()\" />\n</div>\n", styles: [".mlv-editor{--mlv-editor-gutter: var(--mlv-spacing-6);--mlv-editor-measure: 45rem;--mlv-editor-drop-gap: 1.5rem;box-sizing:border-box;padding:0;margin:0;font-family:var(--mlv-typography-family-text);font-size:var(--mlv-font-size-m)}.mlv-editor *{box-sizing:border-box}.mlv-editor{display:block;color:var(--mlv-text-primary)}.mlv-editor .mlv-form-control-wrapper__control-container{height:auto;min-height:var(--form-ctrl-height);padding:0;overflow:hidden;background:var(--mlv-background-base);transition:border-color var(--mlv-duration-fast) var(--mlv-ease-default),box-shadow var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-editor .mlv-form-control-wrapper__control-row{align-items:stretch}.mlv-form-control-wrapper--state-error .mlv-editor__surface{box-shadow:inset 0 0 0 var(--mlv-stroke-width) var(--mlv-border-error)}.mlv-editor__surface{display:flex;flex:1 1 auto;flex-direction:column;min-width:0;width:100%;background:var(--mlv-elevation-bg-3)}.mlv-editor__toolbar{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--mlv-spacing-1);min-width:0;padding:var(--mlv-padding-xs);overflow:hidden;border-bottom:var(--mlv-stroke-width) solid var(--mlv-border-normal);background:var(--mlv-elevation-bg-3)}.mlv-editor__toolbar [hidden]{display:none!important}.mlv-editor__toolbar-scroll{flex:1 1 auto;min-width:0}.mlv-editor__toolbar-scroll>.mlv-toolbar{width:max-content;min-width:100%;flex-wrap:nowrap}.mlv-editor .mlv-editor-toolbar__separator{flex:0 0 auto;min-height:var(--mlv-height-s);margin-inline:var(--mlv-spacing-1)}.mlv-editor .mlv-editor-toolbar__overflow,.mlv-editor .mlv-editor-undo-redo,.mlv-editor .mlv-editor-inline-marks,.mlv-editor .mlv-editor-block-insert{display:inline-flex;flex:0 0 auto;flex-direction:row;align-items:center;gap:var(--mlv-spacing-1)}.mlv-editor mlv-editor-zoom,.mlv-editor mlv-editor-heading,.mlv-editor mlv-editor-list,.mlv-editor mlv-editor-text-color,.mlv-editor mlv-editor-highlight,.mlv-editor mlv-editor-alignment,.mlv-editor mlv-editor-link,.mlv-editor mlv-editor-table,.mlv-editor mlv-editor-image-upload{flex:0 0 auto}.mlv-editor__viewport{min-block-size:8rem;overflow:auto;overscroll-behavior:contain}.mlv-editor__view{position:relative;min-inline-size:100%;transform:scale(var(--mlv-editor-zoom, 1));transform-origin:left top;transition:transform var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-editor__content{min-block-size:8rem;padding-block:var(--mlv-spacing-2);padding-inline:var(--mlv-editor-gutter);border:0;outline:none}.mlv-editor__block-handle{position:absolute;inset-inline-start:max(0rem,(100% - 2 * var(--mlv-editor-gutter) - var(--mlv-editor-measure)) / 2);display:inline-flex;align-items:center;justify-content:center;inline-size:var(--mlv-editor-gutter);block-size:var(--mlv-height-xs);border-radius:var(--mlv-radius-s);color:var(--mlv-text-tertiary);cursor:grab;opacity:0;pointer-events:none;transition:opacity var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-editor__block-handle svg{inline-size:var(--mlv-spacing-4);block-size:var(--mlv-spacing-4);fill:currentcolor}.mlv-editor__block-handle:hover{background-color:var(--mlv-background-neutral-1-hover);color:var(--mlv-text-secondary)}.mlv-editor__block-handle[data-visible=true]{opacity:1;pointer-events:auto}.mlv-editor__drop-indicator{position:absolute;inset-inline:calc(max(0rem,(100% - 2 * var(--mlv-editor-gutter) - var(--mlv-editor-measure)) / 2) + var(--mlv-editor-gutter));block-size:var(--mlv-stroke-width-medium);border-radius:var(--mlv-radius-full);background-color:var(--mlv-border-focus);opacity:0;pointer-events:none;transform:translateY(calc(var(--mlv-editor-drop-gap) / 2 - var(--mlv-stroke-width-medium) / 2));transition:top var(--mlv-duration-normal) var(--mlv-ease-out),opacity var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-editor__drop-indicator[data-visible=true]{opacity:1}.mlv-editor .mlv-editor__block--dragging{opacity:var(--mlv-disabled-opacity)}.mlv-editor .ProseMirror--block-dragging>*{transition:transform var(--mlv-duration-normal) var(--mlv-ease-out)}.mlv-editor__status{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--mlv-spacing-2);min-block-size:var(--mlv-spacing-4);margin-block-start:var(--mlv-spacing-1)}.mlv-editor__upload-placeholder{position:relative;display:inline-block;inline-size:var(--mlv-height-l);block-size:var(--mlv-height-l);margin-inline:var(--mlv-spacing-1);border:var(--mlv-stroke-width) dashed var(--mlv-border-focus);border-radius:var(--mlv-radius-m);background:var(--mlv-background-accent-1-pale);vertical-align:middle}.mlv-editor__upload-placeholder:after{position:absolute;inset:var(--mlv-spacing-2);border:var(--mlv-stroke-width-medium) solid var(--mlv-border-normal);border-block-start-color:var(--mlv-border-focus);border-radius:var(--mlv-radius-full);animation:mlv-editor-upload-spin var(--mlv-duration-slower) var(--mlv-ease-linear) infinite;content:\"\"}.mlv-editor__ai-streaming{border-radius:var(--mlv-radius-xs);background-color:var(--mlv-background-accent-1-pale)}.mlv-editor__ai-streaming-chunk{animation:mlv-editor-ai-chunk-in var(--mlv-duration-normal) var(--mlv-ease-out)}.mlv-editor__ai-caret{position:relative;display:inline-block;inline-size:0;block-size:1em;pointer-events:none}.mlv-editor__ai-caret:after{position:absolute;inset-block:0;inset-inline-start:.0625rem;inline-size:.35em;border-radius:var(--mlv-radius-xs);background:linear-gradient(to bottom,var(--mlv-background-accent-1),var(--mlv-background-accent-2));content:\"\";animation:mlv-editor-ai-caret-pulse var(--mlv-duration-sluggish) var(--mlv-ease-in-out) infinite}.mlv-editor__ai-suggestion-insert{border-radius:var(--mlv-radius-xs);background-color:var(--mlv-background-success-pale)}.mlv-editor__ai-suggestion-delete{border-radius:var(--mlv-radius-xs);background-color:var(--mlv-background-danger-1-pale);color:var(--mlv-text-negative);text-decoration-line:line-through}.mlv-editor__ai-suggestion-current{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:.125rem}.mlv-editor--content-width-default{--mlv-editor-measure: 45rem}.mlv-editor--content-width-wide{--mlv-editor-measure: 60rem}.mlv-editor--content-width-full{--mlv-editor-measure: 100%}.mlv-editor--focused .mlv-form-control-wrapper__control-container{border-color:var(--mlv-border-focus);box-shadow:var(--mlv-focus-ring)}.mlv-editor--readonly .ProseMirror{cursor:text}.mlv-editor--readonly .ProseMirror ::selection{background:var(--mlv-background-accent-1-pale)}.mlv-editor--disabled{opacity:var(--mlv-disabled-opacity)}.mlv-editor--disabled .mlv-editor__surface,.mlv-editor--disabled .mlv-editor__status{pointer-events:none}.mlv-editor--disabled .mlv-editor__content,.mlv-editor--disabled .ProseMirror{cursor:default;-webkit-user-select:none;user-select:none}.mlv-editor .ProseMirror{min-block-size:inherit;max-inline-size:var(--mlv-editor-measure);margin-inline:auto;color:var(--mlv-text-primary);font-family:var(--mlv-typography-family-text);font-size:var(--mlv-typography-body-m-size);font-weight:var(--mlv-typography-body-m-weight);line-height:var(--mlv-typography-body-m-line-height);overflow-wrap:anywhere;white-space:pre-wrap}.mlv-editor .ProseMirror:focus-visible{outline:none}.mlv-editor .ProseMirror>*:first-child{margin-block-start:0}.mlv-editor .ProseMirror>*:last-child{margin-block-end:0}.mlv-editor .ProseMirror p{margin-block:0 var(--mlv-spacing-3)}.mlv-editor .ProseMirror h1,.mlv-editor .ProseMirror h2,.mlv-editor .ProseMirror h3,.mlv-editor .ProseMirror h4,.mlv-editor .ProseMirror h5,.mlv-editor .ProseMirror h6{margin-block:var(--mlv-spacing-6) var(--mlv-spacing-3);color:var(--mlv-text-heading);font-family:var(--mlv-typography-family-heading)}.mlv-editor .ProseMirror h1{font-size:var(--mlv-typography-heading-h1-size);font-weight:var(--mlv-typography-heading-h1-weight);line-height:var(--mlv-typography-heading-h1-line-height)}.mlv-editor .ProseMirror h2{font-size:var(--mlv-typography-heading-h2-size);font-weight:var(--mlv-typography-heading-h2-weight);line-height:var(--mlv-typography-heading-h2-line-height)}.mlv-editor .ProseMirror h3{font-size:var(--mlv-typography-heading-h3-size);font-weight:var(--mlv-typography-heading-h3-weight);line-height:var(--mlv-typography-heading-h3-line-height)}.mlv-editor .ProseMirror h4{font-size:var(--mlv-typography-heading-h4-size);font-weight:var(--mlv-typography-heading-h4-weight);line-height:var(--mlv-typography-heading-h4-line-height)}.mlv-editor .ProseMirror h5{font-size:var(--mlv-typography-heading-h5-size);font-weight:var(--mlv-typography-heading-h5-weight);line-height:var(--mlv-typography-heading-h5-line-height)}.mlv-editor .ProseMirror h6{font-size:var(--mlv-typography-heading-h6-size);font-weight:var(--mlv-typography-heading-h6-weight);line-height:var(--mlv-typography-heading-h6-line-height)}.mlv-editor .ProseMirror h1{letter-spacing:var(--mlv-typography-heading-h1-letter-spacing)}.mlv-editor .ProseMirror h2{letter-spacing:var(--mlv-typography-heading-h2-letter-spacing)}.mlv-editor .ProseMirror h3,.mlv-editor .ProseMirror h4,.mlv-editor .ProseMirror h5,.mlv-editor .ProseMirror h6{letter-spacing:var(--mlv-letter-spacing-normal)}.mlv-editor .ProseMirror strong{font-weight:var(--mlv-font-weight-bold)}.mlv-editor .ProseMirror em{font-style:italic}.mlv-editor .ProseMirror s{text-decoration:line-through}.mlv-editor .ProseMirror u{text-underline-offset:var(--mlv-spacing-0-5)}.mlv-editor .ProseMirror a{color:var(--mlv-text-action);text-decoration:underline;text-underline-offset:var(--mlv-spacing-0-5);transition:color var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-editor .ProseMirror a:visited{color:var(--mlv-text-action)}.mlv-editor .ProseMirror a:hover{color:var(--mlv-text-action-hover)}.mlv-editor .ProseMirror a:focus-visible{border-radius:var(--mlv-radius-xs);outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:var(--mlv-spacing-0-5)}.mlv-editor .ProseMirror ul,.mlv-editor .ProseMirror ol{padding-inline-start:var(--mlv-spacing-6);margin-block:0 var(--mlv-spacing-3)}.mlv-editor .ProseMirror ul ul,.mlv-editor .ProseMirror ul ol,.mlv-editor .ProseMirror ol ul,.mlv-editor .ProseMirror ol ol{margin-block:var(--mlv-spacing-1) 0}.mlv-editor .ProseMirror ul{list-style:disc}.mlv-editor .ProseMirror ul ul{list-style:circle}.mlv-editor .ProseMirror ol{list-style:decimal}.mlv-editor .ProseMirror li{margin-block:var(--mlv-spacing-1)}.mlv-editor .ProseMirror li>p{margin:0}.mlv-editor .ProseMirror ul[data-type=taskList]{padding:0;list-style:none}.mlv-editor .ProseMirror ul[data-type=taskList] li[data-type=taskItem]{display:flex;align-items:flex-start;gap:var(--mlv-spacing-2)}.mlv-editor .ProseMirror ul[data-type=taskList] li[data-type=taskItem]>label{display:inline-flex;align-items:center;min-block-size:var(--mlv-height-xs);cursor:pointer;-webkit-user-select:none;user-select:none}.mlv-editor .ProseMirror ul[data-type=taskList] li[data-type=taskItem]>label input{accent-color:var(--mlv-background-accent-1)}.mlv-editor .ProseMirror ul[data-type=taskList] li[data-type=taskItem]>label input:focus-visible{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:var(--mlv-spacing-0-5)}.mlv-editor .ProseMirror ul[data-type=taskList] li[data-type=taskItem]>div{flex:1 1 auto;min-width:0}.mlv-editor .ProseMirror blockquote{padding-inline-start:var(--mlv-spacing-4);margin:var(--mlv-spacing-4) 0;border-inline-start:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);color:var(--mlv-text-secondary)}.mlv-editor .ProseMirror code{padding:var(--mlv-spacing-0-5) var(--mlv-spacing-1);border-radius:var(--mlv-radius-s);background:var(--mlv-background-neutral-1);color:var(--mlv-text-primary);font-family:var(--mlv-typography-family-code);font-size:var(--mlv-typography-code-size)}.mlv-editor .ProseMirror pre{padding:var(--mlv-padding-m);margin-block:var(--mlv-spacing-4);overflow:auto;border:var(--mlv-stroke-width) solid var(--mlv-border-normal);border-radius:var(--mlv-radius-m);background:var(--mlv-background-sunken);color:var(--mlv-text-primary);font-family:var(--mlv-typography-family-code);font-size:var(--mlv-typography-code-size);line-height:var(--mlv-typography-body-m-line-height);tab-size:2}.mlv-editor .ProseMirror pre code{padding:0;background:transparent;color:inherit;font-size:inherit}.mlv-editor .ProseMirror hr{height:var(--mlv-stroke-width);margin-block:var(--mlv-spacing-6);border:0;background:var(--mlv-border-normal)}.mlv-editor .ProseMirror img{display:block;max-inline-size:100%;block-size:auto;margin-block:var(--mlv-spacing-4);border-radius:var(--mlv-radius-m)}.mlv-editor .ProseMirror img.ProseMirror-selectednode{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:0}.mlv-editor .ProseMirror .ProseMirror-selectednode,.mlv-editor .ProseMirror [data-resize-state=true]{border-radius:var(--mlv-radius-s);outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:var(--mlv-spacing-1)}.mlv-editor .ProseMirror [data-resize-container]{margin-block:var(--mlv-spacing-4)}.mlv-editor .ProseMirror [data-resize-container] img{margin-block:0}.mlv-editor .ProseMirror [data-resize-container].ProseMirror-selectednode,.mlv-editor .ProseMirror [data-resize-container][data-resize-state=true]{outline:none}.mlv-editor .ProseMirror [data-resize-container].ProseMirror-selectednode>[data-resize-wrapper],.mlv-editor .ProseMirror [data-resize-container][data-resize-state=true]>[data-resize-wrapper]{border-radius:var(--mlv-radius-m);outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:0}.mlv-editor .ProseMirror [data-resize-handle],.mlv-editor .ProseMirror .resize-handle{inline-size:var(--mlv-spacing-3);block-size:var(--mlv-spacing-3);border:var(--mlv-stroke-width) solid var(--mlv-background-base);border-radius:var(--mlv-radius-full);background:var(--mlv-background-accent-1);box-shadow:var(--mlv-shadow-raised)}.mlv-editor .ProseMirror [data-resize-handle]:focus-visible,.mlv-editor .ProseMirror .resize-handle:focus-visible{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:var(--mlv-spacing-0-5)}.mlv-editor .ProseMirror .is-editor-empty:first-child:before{float:left;height:0;color:var(--mlv-text-placeholder);content:attr(data-placeholder);pointer-events:none}.mlv-editor .tableWrapper{margin-block:var(--mlv-spacing-3);overflow-x:auto}.mlv-editor table{width:100%;border-collapse:collapse;table-layout:fixed}.mlv-editor th,.mlv-editor td{position:relative;min-width:3rem;padding:var(--mlv-spacing-2) var(--mlv-spacing-3);border:var(--mlv-stroke-width) solid var(--mlv-border-normal);vertical-align:top}.mlv-editor th{background:var(--mlv-background-neutral-1);font-weight:var(--mlv-font-weight-semibold)}.mlv-editor .selectedCell:after{position:absolute;inset:0;z-index:1;background:var(--mlv-background-accent-1-pale);content:\"\";opacity:.55;pointer-events:none}.mlv-editor .ProseMirror-focused .selectedCell:after{box-shadow:inset 0 0 0 var(--mlv-stroke-width-medium) var(--mlv-border-focus)}.mlv-editor .column-resize-handle{position:absolute;inset-block:0;inset-inline-end:calc(var(--mlv-stroke-width) * -1);z-index:2;width:calc(var(--mlv-stroke-width) * 2);background:var(--mlv-border-focus);pointer-events:none}.mlv-editor .resize-cursor{cursor:col-resize}@keyframes mlv-editor-upload-spin{to{transform:rotate(1turn)}}@keyframes mlv-editor-ai-chunk-in{0%{opacity:0;filter:blur(.125rem)}to{opacity:1;filter:blur(0)}}@keyframes mlv-editor-ai-caret-pulse{0%,to{opacity:1}50%{opacity:.35}}@media(max-width:40rem){.mlv-editor{--mlv-editor-gutter: var(--mlv-spacing-3)}.mlv-editor__toolbar{flex-wrap:nowrap;overflow-x:auto}.mlv-editor__content{padding-block:var(--mlv-spacing-1-5)}.mlv-editor__status{justify-content:flex-start}.mlv-editor .ProseMirror h1{font-size:var(--mlv-typography-heading-h2-size)}.mlv-editor .ProseMirror h2{font-size:var(--mlv-typography-heading-h3-size)}}@media print{.mlv-editor__toolbar,.mlv-editor__status,.mlv-editor__block-handle,.mlv-editor__drop-indicator,.mlv-editor .mlv-editor-image-upload-status,.mlv-editor__upload-placeholder,.mlv-editor__ai-suggestion-delete,.mlv-editor__ai-caret{display:none}.mlv-editor__ai-suggestion-current{outline:none}.mlv-editor__ai-streaming-chunk{animation:none}.mlv-editor__viewport{overflow:visible}.mlv-editor__view{transform:none}.mlv-editor__content,.mlv-editor .ProseMirror{min-block-size:0;padding:0}.mlv-editor table{break-inside:avoid}}@media(hover:none){.mlv-editor__block-handle{display:none}}@media(prefers-reduced-motion:reduce){.mlv-editor .mlv-form-control-wrapper__control-container,.mlv-editor__view,.mlv-editor__block-handle,.mlv-editor__drop-indicator,.mlv-editor .ProseMirror--block-dragging>*,.mlv-editor .ProseMirror a{transition-duration:var(--mlv-duration-instant)}.mlv-editor__upload-placeholder:after,.mlv-editor__ai-streaming-chunk,.mlv-editor__ai-caret:after{animation:none}}.mlv-editor__drag-ghost{max-block-size:12rem;padding:var(--mlv-spacing-2);overflow:hidden;border-radius:var(--mlv-radius-m);background-color:var(--mlv-background-raised);box-shadow:var(--mlv-shadow-floating);opacity:.9;-webkit-mask-image:linear-gradient(to bottom,black 70%,transparent 100%);mask-image:linear-gradient(to bottom,black 70%,transparent 100%);scale:.85;transform-origin:top left}\n"], dependencies: [{ kind: "component", type: MlvFormControlWrapper, selector: "mlv-form-control-wrapper", outputs: ["clear"] }, { kind: "directive", type: MlvFormControlWrapperControl, selector: "[mlvFormControlWrapperControl]" }, { kind: "component", type: MlvHint, selector: "mlv-hint" }, { kind: "component", type: MlvLabel, selector: "mlv-label", inputs: ["for", "required"] }, { kind: "component", type: MlvMessage, selector: "mlv-message", inputs: ["state"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MlvFade, selector: "[mlvFade]", inputs: ["mlvFadeHeight", "mlvFadeSize", "mlvFadeOffset", "mlvFade"] }, { kind: "component", type: MlvToolbar, selector: "mlv-toolbar", inputs: ["gap", "equalSize"] }, { kind: "component", type: MlvDivider, selector: "mlv-divider", inputs: ["orientation", "dashed", "muted"] }, { kind: "directive", type: MlvEditorToolbarRoot, selector: "[mlvEditorToolbarRoot]", inputs: ["ariaLabel", "disabled", "orientation", "wrap"], exportAs: ["mlvEditorToolbarRoot"] }, { kind: "component", type: MlvEditorToolbarOverflow, selector: "mlv-editor-toolbar-overflow" }, { kind: "component", type: MlvEditorUndoRedo, selector: "mlv-editor-undo-redo" }, { kind: "component", type: MlvEditorZoom, selector: "mlv-editor-zoom", inputs: ["zoom", "zoomLevels", "min", "max", "fitToContainer"], outputs: ["zoomChange"] }, { kind: "component", type: MlvEditorHeading, selector: "mlv-editor-heading", inputs: ["levels"] }, { kind: "component", type: MlvEditorList, selector: "mlv-editor-list" }, { kind: "component", type: MlvEditorInlineMarks, selector: "mlv-editor-inline-marks" }, { kind: "component", type: MlvEditorTextColor, selector: "mlv-editor-text-color" }, { kind: "component", type: MlvEditorStatus, selector: "mlv-editor-status", inputs: ["characterLimit"] }, { kind: "component", type: MlvEditorHighlight, selector: "mlv-editor-highlight" }, { kind: "component", type: MlvEditorLink, selector: "mlv-editor-link", inputs: ["allowedProtocols"] }, { kind: "component", type: MlvEditorImageUpload, selector: "mlv-editor-image-upload" }, { kind: "component", type: MlvEditorImageUploadStatus, selector: "mlv-editor-image-upload-status" }, { kind: "component", type: MlvEditorTable, selector: "mlv-editor-table" }, { kind: "component", type: MlvEditorAlignment, selector: "mlv-editor-alignment" }, { kind: "component", type: MlvEditorBlockInsert, selector: "mlv-editor-block-insert" }, { kind: "component", type: MlvSpacer, selector: "mlv-spacer" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
885
|
-
}
|
|
886
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvEditor, decorators: [{
|
|
887
|
-
type: Component,
|
|
888
|
-
args: [{ selector: 'mlv-editor', imports: [
|
|
889
|
-
MlvFormControlWrapper,
|
|
890
|
-
MlvFormControlWrapperControl,
|
|
891
|
-
MlvHint,
|
|
892
|
-
MlvLabel,
|
|
893
|
-
MlvMessage,
|
|
894
|
-
NgTemplateOutlet,
|
|
895
|
-
MlvFade,
|
|
896
|
-
MlvToolbar,
|
|
897
|
-
MlvDivider,
|
|
898
|
-
MlvEditorToolbarRoot,
|
|
899
|
-
MlvEditorToolbarOverflow,
|
|
900
|
-
MlvEditorUndoRedo,
|
|
901
|
-
MlvEditorZoom,
|
|
902
|
-
MlvEditorHeading,
|
|
903
|
-
MlvEditorList,
|
|
904
|
-
MlvEditorInlineMarks,
|
|
905
|
-
MlvEditorTextColor,
|
|
906
|
-
MlvEditorStatus,
|
|
907
|
-
MlvEditorHighlight,
|
|
908
|
-
MlvEditorLink,
|
|
909
|
-
MlvEditorImageUpload,
|
|
910
|
-
MlvEditorImageUploadStatus,
|
|
911
|
-
MlvEditorTable,
|
|
912
|
-
MlvEditorAlignment,
|
|
913
|
-
MlvEditorBlockInsert,
|
|
914
|
-
MlvSpacer,
|
|
915
|
-
], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
916
|
-
MlvEditorOverlayRegistry,
|
|
917
|
-
MlvEditorToolbarRevision,
|
|
918
|
-
MlvEditorToolbarRovingRegistry,
|
|
919
|
-
MlvEditorUploadAbortRegistry,
|
|
920
|
-
{
|
|
921
|
-
provide: MLV_FORM_CONTROL,
|
|
922
|
-
useExisting: forwardRef(() => MlvEditor),
|
|
923
|
-
},
|
|
924
|
-
{
|
|
925
|
-
provide: MLV_EDITOR_TOOLBAR_CONTEXT,
|
|
926
|
-
useExisting: forwardRef(() => MlvEditor),
|
|
927
|
-
},
|
|
928
|
-
{
|
|
929
|
-
provide: MLV_EDITOR_TOOLBAR_REVISION,
|
|
930
|
-
useFactory: (state) => state.revision,
|
|
931
|
-
deps: [MlvEditorToolbarRevision],
|
|
932
|
-
},
|
|
933
|
-
{
|
|
934
|
-
provide: MLV_EDITOR_TOOLBAR_ROVING,
|
|
935
|
-
useExisting: MlvEditorToolbarRovingRegistry,
|
|
936
|
-
},
|
|
937
|
-
{
|
|
938
|
-
provide: MLV_EDITOR_OVERLAY_REGISTRY,
|
|
939
|
-
useExisting: MlvEditorOverlayRegistry,
|
|
940
|
-
},
|
|
941
|
-
{
|
|
942
|
-
provide: MLV_EDITOR_UPLOAD_ABORT_REGISTRY,
|
|
943
|
-
useExisting: MlvEditorUploadAbortRegistry,
|
|
944
|
-
},
|
|
945
|
-
MlvEditorAiContext,
|
|
946
|
-
{
|
|
947
|
-
provide: MLV_EDITOR_AI_CONTEXT,
|
|
948
|
-
useExisting: MlvEditorAiContext,
|
|
949
|
-
},
|
|
950
|
-
{
|
|
951
|
-
provide: MLV_EDITOR_AI_INPUT_PROVIDER,
|
|
952
|
-
useFactory: () => {
|
|
953
|
-
const owner = inject(forwardRef(() => MlvEditor));
|
|
954
|
-
return owner.aiProvider;
|
|
955
|
-
},
|
|
956
|
-
},
|
|
957
|
-
{
|
|
958
|
-
provide: MLV_EDITOR_IMAGE_UPLOAD_COORDINATOR,
|
|
959
|
-
useFactory: () => {
|
|
960
|
-
const owner = inject(forwardRef(() => MlvEditor));
|
|
961
|
-
return createMlvEditorImageUploadCoordinator({
|
|
962
|
-
editor: owner.editor,
|
|
963
|
-
imageUploader: owner.imageUploader,
|
|
964
|
-
imageUploadOptions: owner.imageUploadOptions,
|
|
965
|
-
disabled: () => owner.computedDisabled(),
|
|
966
|
-
readonly: () => owner.readonly(),
|
|
967
|
-
emitSuccess: (event) => owner.imageUploadSuccess.emit(event),
|
|
968
|
-
emitFailure: (event) => owner.imageUploadFailure.emit(event),
|
|
969
|
-
emitCancelled: (event) => owner.imageUploadCancelled.emit(event),
|
|
970
|
-
emitError: (error) => owner.editorError.emit(error),
|
|
971
|
-
}, inject(MLV_EDITOR_IMAGE_UPLOADER, { optional: true }) ?? undefined, inject(MLV_EDITOR_UPLOAD_ABORT_REGISTRY));
|
|
972
|
-
},
|
|
973
|
-
},
|
|
974
|
-
], host: {
|
|
975
|
-
class: 'mlv-editor',
|
|
976
|
-
'[class]': '"mlv-editor--content-width-" + contentWidth()',
|
|
977
|
-
'[class.mlv-editor--disabled]': 'computedDisabled()',
|
|
978
|
-
'[class.mlv-editor--readonly]': 'readonly()',
|
|
979
|
-
'[class.mlv-editor--focused]': 'focused()',
|
|
980
|
-
'[attr.aria-disabled]': 'computedDisabled() || null',
|
|
981
|
-
'[attr.inert]': 'computedDisabled() ? "" : null',
|
|
982
|
-
'[style.--mlv-editor-zoom]': 'zoom() / 100',
|
|
983
|
-
}, template: "<mlv-form-control-wrapper (clear)=\"clearValue()\">\n @if (label() || hint()) {\n <mlv-label [for]=\"id()\" [id]=\"_labelId()\">\n {{ label() }} @if (hint()) {\n <mlv-hint>{{ hint() }}</mlv-hint>\n }\n </mlv-label>\n }\n\n <ng-template mlvFormControlWrapperControl>\n <div class=\"mlv-editor__surface\">\n <div\n mlvEditorToolbarRoot\n #toolbarRoot=\"mlvEditorToolbarRoot\"\n class=\"mlv-editor__toolbar\"\n [ariaLabel]=\"_toolbarAriaLabel()\"\n [disabled]=\"computedDisabled()\"\n >\n @if (_hasToolbarDef()) {\n <ng-content select=\"[mlvEditorToolbar]\" />\n @for (definition of _toolbarDefs(); track definition) { @if\n (definition.templateRef; as toolbarTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"toolbarTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: _toolbarContext }\"\n />\n } } } @else {\n <ng-content select=\"[mlvEditorToolbarStart]\" />\n @for (definition of _toolbarStartDefs(); track definition) { @if\n (definition.templateRef; as startTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"startTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: _toolbarContext }\"\n />\n } }\n <div mlvFade class=\"mlv-editor__toolbar-scroll\">\n <mlv-toolbar>\n <mlv-editor-undo-redo />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n />\n <mlv-editor-zoom />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n />\n <mlv-editor-heading />\n <mlv-editor-list />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-inline-marks [hidden]=\"toolbarRoot.narrow()\" />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-text-color />\n <mlv-editor-highlight />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-alignment [hidden]=\"toolbarRoot.narrow()\" />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-link />\n <mlv-editor-table />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-block-insert [hidden]=\"toolbarRoot.narrow()\" />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-image-upload />\n </mlv-toolbar>\n </div>\n <mlv-editor-toolbar-overflow />\n @for (definition of _toolbarEndDefs(); track definition) { @if\n (definition.templateRef; as endTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"endTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: _toolbarContext }\"\n />\n } }\n <ng-content select=\"[mlvEditorToolbarEnd]\" />\n }\n </div>\n\n <div class=\"mlv-editor__viewport\">\n <div #view class=\"mlv-editor__view\">\n <div #content class=\"mlv-editor__content\"></div>\n </div>\n </div>\n <mlv-editor-image-upload-status />\n </div>\n </ng-template>\n\n @if (message()) {\n <mlv-message [state]=\"resolvedState()\" [id]=\"id() + '-message'\">\n {{ message() }}\n </mlv-message>\n }\n</mlv-form-control-wrapper>\n\n<div\n class=\"mlv-editor__status\"\n [attr.aria-disabled]=\"computedDisabled() || null\"\n>\n <ng-content select=\"[mlvEditorStatus]\" />\n <mlv-spacer />\n <mlv-editor-status [characterLimit]=\"characterLimit()\" />\n</div>\n", styles: [".mlv-editor{--mlv-editor-gutter: var(--mlv-spacing-6);--mlv-editor-measure: 45rem;--mlv-editor-drop-gap: 1.5rem;box-sizing:border-box;padding:0;margin:0;font-family:var(--mlv-typography-family-text);font-size:var(--mlv-font-size-m)}.mlv-editor *{box-sizing:border-box}.mlv-editor{display:block;color:var(--mlv-text-primary)}.mlv-editor .mlv-form-control-wrapper__control-container{height:auto;min-height:var(--form-ctrl-height);padding:0;overflow:hidden;background:var(--mlv-background-base);transition:border-color var(--mlv-duration-fast) var(--mlv-ease-default),box-shadow var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-editor .mlv-form-control-wrapper__control-row{align-items:stretch}.mlv-form-control-wrapper--state-error .mlv-editor__surface{box-shadow:inset 0 0 0 var(--mlv-stroke-width) var(--mlv-border-error)}.mlv-editor__surface{display:flex;flex:1 1 auto;flex-direction:column;min-width:0;width:100%;background:var(--mlv-elevation-bg-3)}.mlv-editor__toolbar{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--mlv-spacing-1);min-width:0;padding:var(--mlv-padding-xs);overflow:hidden;border-bottom:var(--mlv-stroke-width) solid var(--mlv-border-normal);background:var(--mlv-elevation-bg-3)}.mlv-editor__toolbar [hidden]{display:none!important}.mlv-editor__toolbar-scroll{flex:1 1 auto;min-width:0}.mlv-editor__toolbar-scroll>.mlv-toolbar{width:max-content;min-width:100%;flex-wrap:nowrap}.mlv-editor .mlv-editor-toolbar__separator{flex:0 0 auto;min-height:var(--mlv-height-s);margin-inline:var(--mlv-spacing-1)}.mlv-editor .mlv-editor-toolbar__overflow,.mlv-editor .mlv-editor-undo-redo,.mlv-editor .mlv-editor-inline-marks,.mlv-editor .mlv-editor-block-insert{display:inline-flex;flex:0 0 auto;flex-direction:row;align-items:center;gap:var(--mlv-spacing-1)}.mlv-editor mlv-editor-zoom,.mlv-editor mlv-editor-heading,.mlv-editor mlv-editor-list,.mlv-editor mlv-editor-text-color,.mlv-editor mlv-editor-highlight,.mlv-editor mlv-editor-alignment,.mlv-editor mlv-editor-link,.mlv-editor mlv-editor-table,.mlv-editor mlv-editor-image-upload{flex:0 0 auto}.mlv-editor__viewport{min-block-size:8rem;overflow:auto;overscroll-behavior:contain}.mlv-editor__view{position:relative;min-inline-size:100%;transform:scale(var(--mlv-editor-zoom, 1));transform-origin:left top;transition:transform var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-editor__content{min-block-size:8rem;padding-block:var(--mlv-spacing-2);padding-inline:var(--mlv-editor-gutter);border:0;outline:none}.mlv-editor__block-handle{position:absolute;inset-inline-start:max(0rem,(100% - 2 * var(--mlv-editor-gutter) - var(--mlv-editor-measure)) / 2);display:inline-flex;align-items:center;justify-content:center;inline-size:var(--mlv-editor-gutter);block-size:var(--mlv-height-xs);border-radius:var(--mlv-radius-s);color:var(--mlv-text-tertiary);cursor:grab;opacity:0;pointer-events:none;transition:opacity var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-editor__block-handle svg{inline-size:var(--mlv-spacing-4);block-size:var(--mlv-spacing-4);fill:currentcolor}.mlv-editor__block-handle:hover{background-color:var(--mlv-background-neutral-1-hover);color:var(--mlv-text-secondary)}.mlv-editor__block-handle[data-visible=true]{opacity:1;pointer-events:auto}.mlv-editor__drop-indicator{position:absolute;inset-inline:calc(max(0rem,(100% - 2 * var(--mlv-editor-gutter) - var(--mlv-editor-measure)) / 2) + var(--mlv-editor-gutter));block-size:var(--mlv-stroke-width-medium);border-radius:var(--mlv-radius-full);background-color:var(--mlv-border-focus);opacity:0;pointer-events:none;transform:translateY(calc(var(--mlv-editor-drop-gap) / 2 - var(--mlv-stroke-width-medium) / 2));transition:top var(--mlv-duration-normal) var(--mlv-ease-out),opacity var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-editor__drop-indicator[data-visible=true]{opacity:1}.mlv-editor .mlv-editor__block--dragging{opacity:var(--mlv-disabled-opacity)}.mlv-editor .ProseMirror--block-dragging>*{transition:transform var(--mlv-duration-normal) var(--mlv-ease-out)}.mlv-editor__status{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--mlv-spacing-2);min-block-size:var(--mlv-spacing-4);margin-block-start:var(--mlv-spacing-1)}.mlv-editor__upload-placeholder{position:relative;display:inline-block;inline-size:var(--mlv-height-l);block-size:var(--mlv-height-l);margin-inline:var(--mlv-spacing-1);border:var(--mlv-stroke-width) dashed var(--mlv-border-focus);border-radius:var(--mlv-radius-m);background:var(--mlv-background-accent-1-pale);vertical-align:middle}.mlv-editor__upload-placeholder:after{position:absolute;inset:var(--mlv-spacing-2);border:var(--mlv-stroke-width-medium) solid var(--mlv-border-normal);border-block-start-color:var(--mlv-border-focus);border-radius:var(--mlv-radius-full);animation:mlv-editor-upload-spin var(--mlv-duration-slower) var(--mlv-ease-linear) infinite;content:\"\"}.mlv-editor__ai-streaming{border-radius:var(--mlv-radius-xs);background-color:var(--mlv-background-accent-1-pale)}.mlv-editor__ai-streaming-chunk{animation:mlv-editor-ai-chunk-in var(--mlv-duration-normal) var(--mlv-ease-out)}.mlv-editor__ai-caret{position:relative;display:inline-block;inline-size:0;block-size:1em;pointer-events:none}.mlv-editor__ai-caret:after{position:absolute;inset-block:0;inset-inline-start:.0625rem;inline-size:.35em;border-radius:var(--mlv-radius-xs);background:linear-gradient(to bottom,var(--mlv-background-accent-1),var(--mlv-background-accent-2));content:\"\";animation:mlv-editor-ai-caret-pulse var(--mlv-duration-sluggish) var(--mlv-ease-in-out) infinite}.mlv-editor__ai-suggestion-insert{border-radius:var(--mlv-radius-xs);background-color:var(--mlv-background-success-pale)}.mlv-editor__ai-suggestion-delete{border-radius:var(--mlv-radius-xs);background-color:var(--mlv-background-danger-1-pale);color:var(--mlv-text-negative);text-decoration-line:line-through}.mlv-editor__ai-suggestion-current{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:.125rem}.mlv-editor--content-width-default{--mlv-editor-measure: 45rem}.mlv-editor--content-width-wide{--mlv-editor-measure: 60rem}.mlv-editor--content-width-full{--mlv-editor-measure: 100%}.mlv-editor--focused .mlv-form-control-wrapper__control-container{border-color:var(--mlv-border-focus);box-shadow:var(--mlv-focus-ring)}.mlv-editor--readonly .ProseMirror{cursor:text}.mlv-editor--readonly .ProseMirror ::selection{background:var(--mlv-background-accent-1-pale)}.mlv-editor--disabled{opacity:var(--mlv-disabled-opacity)}.mlv-editor--disabled .mlv-editor__surface,.mlv-editor--disabled .mlv-editor__status{pointer-events:none}.mlv-editor--disabled .mlv-editor__content,.mlv-editor--disabled .ProseMirror{cursor:default;-webkit-user-select:none;user-select:none}.mlv-editor .ProseMirror{min-block-size:inherit;max-inline-size:var(--mlv-editor-measure);margin-inline:auto;color:var(--mlv-text-primary);font-family:var(--mlv-typography-family-text);font-size:var(--mlv-typography-body-m-size);font-weight:var(--mlv-typography-body-m-weight);line-height:var(--mlv-typography-body-m-line-height);overflow-wrap:anywhere;white-space:pre-wrap}.mlv-editor .ProseMirror:focus-visible{outline:none}.mlv-editor .ProseMirror>*:first-child{margin-block-start:0}.mlv-editor .ProseMirror>*:last-child{margin-block-end:0}.mlv-editor .ProseMirror p{margin-block:0 var(--mlv-spacing-3)}.mlv-editor .ProseMirror h1,.mlv-editor .ProseMirror h2,.mlv-editor .ProseMirror h3,.mlv-editor .ProseMirror h4,.mlv-editor .ProseMirror h5,.mlv-editor .ProseMirror h6{margin-block:var(--mlv-spacing-6) var(--mlv-spacing-3);color:var(--mlv-text-heading);font-family:var(--mlv-typography-family-heading)}.mlv-editor .ProseMirror h1{font-size:var(--mlv-typography-heading-h1-size);font-weight:var(--mlv-typography-heading-h1-weight);line-height:var(--mlv-typography-heading-h1-line-height)}.mlv-editor .ProseMirror h2{font-size:var(--mlv-typography-heading-h2-size);font-weight:var(--mlv-typography-heading-h2-weight);line-height:var(--mlv-typography-heading-h2-line-height)}.mlv-editor .ProseMirror h3{font-size:var(--mlv-typography-heading-h3-size);font-weight:var(--mlv-typography-heading-h3-weight);line-height:var(--mlv-typography-heading-h3-line-height)}.mlv-editor .ProseMirror h4{font-size:var(--mlv-typography-heading-h4-size);font-weight:var(--mlv-typography-heading-h4-weight);line-height:var(--mlv-typography-heading-h4-line-height)}.mlv-editor .ProseMirror h5{font-size:var(--mlv-typography-heading-h5-size);font-weight:var(--mlv-typography-heading-h5-weight);line-height:var(--mlv-typography-heading-h5-line-height)}.mlv-editor .ProseMirror h6{font-size:var(--mlv-typography-heading-h6-size);font-weight:var(--mlv-typography-heading-h6-weight);line-height:var(--mlv-typography-heading-h6-line-height)}.mlv-editor .ProseMirror h1{letter-spacing:var(--mlv-typography-heading-h1-letter-spacing)}.mlv-editor .ProseMirror h2{letter-spacing:var(--mlv-typography-heading-h2-letter-spacing)}.mlv-editor .ProseMirror h3,.mlv-editor .ProseMirror h4,.mlv-editor .ProseMirror h5,.mlv-editor .ProseMirror h6{letter-spacing:var(--mlv-letter-spacing-normal)}.mlv-editor .ProseMirror strong{font-weight:var(--mlv-font-weight-bold)}.mlv-editor .ProseMirror em{font-style:italic}.mlv-editor .ProseMirror s{text-decoration:line-through}.mlv-editor .ProseMirror u{text-underline-offset:var(--mlv-spacing-0-5)}.mlv-editor .ProseMirror a{color:var(--mlv-text-action);text-decoration:underline;text-underline-offset:var(--mlv-spacing-0-5);transition:color var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-editor .ProseMirror a:visited{color:var(--mlv-text-action)}.mlv-editor .ProseMirror a:hover{color:var(--mlv-text-action-hover)}.mlv-editor .ProseMirror a:focus-visible{border-radius:var(--mlv-radius-xs);outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:var(--mlv-spacing-0-5)}.mlv-editor .ProseMirror ul,.mlv-editor .ProseMirror ol{padding-inline-start:var(--mlv-spacing-6);margin-block:0 var(--mlv-spacing-3)}.mlv-editor .ProseMirror ul ul,.mlv-editor .ProseMirror ul ol,.mlv-editor .ProseMirror ol ul,.mlv-editor .ProseMirror ol ol{margin-block:var(--mlv-spacing-1) 0}.mlv-editor .ProseMirror ul{list-style:disc}.mlv-editor .ProseMirror ul ul{list-style:circle}.mlv-editor .ProseMirror ol{list-style:decimal}.mlv-editor .ProseMirror li{margin-block:var(--mlv-spacing-1)}.mlv-editor .ProseMirror li>p{margin:0}.mlv-editor .ProseMirror ul[data-type=taskList]{padding:0;list-style:none}.mlv-editor .ProseMirror ul[data-type=taskList] li[data-type=taskItem]{display:flex;align-items:flex-start;gap:var(--mlv-spacing-2)}.mlv-editor .ProseMirror ul[data-type=taskList] li[data-type=taskItem]>label{display:inline-flex;align-items:center;min-block-size:var(--mlv-height-xs);cursor:pointer;-webkit-user-select:none;user-select:none}.mlv-editor .ProseMirror ul[data-type=taskList] li[data-type=taskItem]>label input{accent-color:var(--mlv-background-accent-1)}.mlv-editor .ProseMirror ul[data-type=taskList] li[data-type=taskItem]>label input:focus-visible{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:var(--mlv-spacing-0-5)}.mlv-editor .ProseMirror ul[data-type=taskList] li[data-type=taskItem]>div{flex:1 1 auto;min-width:0}.mlv-editor .ProseMirror blockquote{padding-inline-start:var(--mlv-spacing-4);margin:var(--mlv-spacing-4) 0;border-inline-start:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);color:var(--mlv-text-secondary)}.mlv-editor .ProseMirror code{padding:var(--mlv-spacing-0-5) var(--mlv-spacing-1);border-radius:var(--mlv-radius-s);background:var(--mlv-background-neutral-1);color:var(--mlv-text-primary);font-family:var(--mlv-typography-family-code);font-size:var(--mlv-typography-code-size)}.mlv-editor .ProseMirror pre{padding:var(--mlv-padding-m);margin-block:var(--mlv-spacing-4);overflow:auto;border:var(--mlv-stroke-width) solid var(--mlv-border-normal);border-radius:var(--mlv-radius-m);background:var(--mlv-background-sunken);color:var(--mlv-text-primary);font-family:var(--mlv-typography-family-code);font-size:var(--mlv-typography-code-size);line-height:var(--mlv-typography-body-m-line-height);tab-size:2}.mlv-editor .ProseMirror pre code{padding:0;background:transparent;color:inherit;font-size:inherit}.mlv-editor .ProseMirror hr{height:var(--mlv-stroke-width);margin-block:var(--mlv-spacing-6);border:0;background:var(--mlv-border-normal)}.mlv-editor .ProseMirror img{display:block;max-inline-size:100%;block-size:auto;margin-block:var(--mlv-spacing-4);border-radius:var(--mlv-radius-m)}.mlv-editor .ProseMirror img.ProseMirror-selectednode{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:0}.mlv-editor .ProseMirror .ProseMirror-selectednode,.mlv-editor .ProseMirror [data-resize-state=true]{border-radius:var(--mlv-radius-s);outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:var(--mlv-spacing-1)}.mlv-editor .ProseMirror [data-resize-container]{margin-block:var(--mlv-spacing-4)}.mlv-editor .ProseMirror [data-resize-container] img{margin-block:0}.mlv-editor .ProseMirror [data-resize-container].ProseMirror-selectednode,.mlv-editor .ProseMirror [data-resize-container][data-resize-state=true]{outline:none}.mlv-editor .ProseMirror [data-resize-container].ProseMirror-selectednode>[data-resize-wrapper],.mlv-editor .ProseMirror [data-resize-container][data-resize-state=true]>[data-resize-wrapper]{border-radius:var(--mlv-radius-m);outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:0}.mlv-editor .ProseMirror [data-resize-handle],.mlv-editor .ProseMirror .resize-handle{inline-size:var(--mlv-spacing-3);block-size:var(--mlv-spacing-3);border:var(--mlv-stroke-width) solid var(--mlv-background-base);border-radius:var(--mlv-radius-full);background:var(--mlv-background-accent-1);box-shadow:var(--mlv-shadow-raised)}.mlv-editor .ProseMirror [data-resize-handle]:focus-visible,.mlv-editor .ProseMirror .resize-handle:focus-visible{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:var(--mlv-spacing-0-5)}.mlv-editor .ProseMirror .is-editor-empty:first-child:before{float:left;height:0;color:var(--mlv-text-placeholder);content:attr(data-placeholder);pointer-events:none}.mlv-editor .tableWrapper{margin-block:var(--mlv-spacing-3);overflow-x:auto}.mlv-editor table{width:100%;border-collapse:collapse;table-layout:fixed}.mlv-editor th,.mlv-editor td{position:relative;min-width:3rem;padding:var(--mlv-spacing-2) var(--mlv-spacing-3);border:var(--mlv-stroke-width) solid var(--mlv-border-normal);vertical-align:top}.mlv-editor th{background:var(--mlv-background-neutral-1);font-weight:var(--mlv-font-weight-semibold)}.mlv-editor .selectedCell:after{position:absolute;inset:0;z-index:1;background:var(--mlv-background-accent-1-pale);content:\"\";opacity:.55;pointer-events:none}.mlv-editor .ProseMirror-focused .selectedCell:after{box-shadow:inset 0 0 0 var(--mlv-stroke-width-medium) var(--mlv-border-focus)}.mlv-editor .column-resize-handle{position:absolute;inset-block:0;inset-inline-end:calc(var(--mlv-stroke-width) * -1);z-index:2;width:calc(var(--mlv-stroke-width) * 2);background:var(--mlv-border-focus);pointer-events:none}.mlv-editor .resize-cursor{cursor:col-resize}@keyframes mlv-editor-upload-spin{to{transform:rotate(1turn)}}@keyframes mlv-editor-ai-chunk-in{0%{opacity:0;filter:blur(.125rem)}to{opacity:1;filter:blur(0)}}@keyframes mlv-editor-ai-caret-pulse{0%,to{opacity:1}50%{opacity:.35}}@media(max-width:40rem){.mlv-editor{--mlv-editor-gutter: var(--mlv-spacing-3)}.mlv-editor__toolbar{flex-wrap:nowrap;overflow-x:auto}.mlv-editor__content{padding-block:var(--mlv-spacing-1-5)}.mlv-editor__status{justify-content:flex-start}.mlv-editor .ProseMirror h1{font-size:var(--mlv-typography-heading-h2-size)}.mlv-editor .ProseMirror h2{font-size:var(--mlv-typography-heading-h3-size)}}@media print{.mlv-editor__toolbar,.mlv-editor__status,.mlv-editor__block-handle,.mlv-editor__drop-indicator,.mlv-editor .mlv-editor-image-upload-status,.mlv-editor__upload-placeholder,.mlv-editor__ai-suggestion-delete,.mlv-editor__ai-caret{display:none}.mlv-editor__ai-suggestion-current{outline:none}.mlv-editor__ai-streaming-chunk{animation:none}.mlv-editor__viewport{overflow:visible}.mlv-editor__view{transform:none}.mlv-editor__content,.mlv-editor .ProseMirror{min-block-size:0;padding:0}.mlv-editor table{break-inside:avoid}}@media(hover:none){.mlv-editor__block-handle{display:none}}@media(prefers-reduced-motion:reduce){.mlv-editor .mlv-form-control-wrapper__control-container,.mlv-editor__view,.mlv-editor__block-handle,.mlv-editor__drop-indicator,.mlv-editor .ProseMirror--block-dragging>*,.mlv-editor .ProseMirror a{transition-duration:var(--mlv-duration-instant)}.mlv-editor__upload-placeholder:after,.mlv-editor__ai-streaming-chunk,.mlv-editor__ai-caret:after{animation:none}}.mlv-editor__drag-ghost{max-block-size:12rem;padding:var(--mlv-spacing-2);overflow:hidden;border-radius:var(--mlv-radius-m);background-color:var(--mlv-background-raised);box-shadow:var(--mlv-shadow-floating);opacity:.9;-webkit-mask-image:linear-gradient(to bottom,black 70%,transparent 100%);mask-image:linear-gradient(to bottom,black 70%,transparent 100%);scale:.85;transform-origin:top left}\n"] }]
|
|
984
|
-
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], contentWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentWidth", required: false }] }], extensions: [{ type: i0.Input, args: [{ isSignal: true, alias: "extensions", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], characterLimit: [{ type: i0.Input, args: [{ isSignal: true, alias: "characterLimit", required: false }] }], ariaLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledBy", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], imageUploader: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageUploader", required: false }] }], imageUploadOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageUploadOptions", required: false }] }], aiProvider: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiProvider", required: false }] }], editorReady: [{ type: i0.Output, args: ["editorReady"] }], focus: [{ type: i0.Output, args: ["focus"] }], blur: [{ type: i0.Output, args: ["blur"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], transaction: [{ type: i0.Output, args: ["transaction"] }], editorError: [{ type: i0.Output, args: ["editorError"] }], imageUploadSuccess: [{ type: i0.Output, args: ["imageUploadSuccess"] }], imageUploadFailure: [{ type: i0.Output, args: ["imageUploadFailure"] }], imageUploadCancelled: [{ type: i0.Output, args: ["imageUploadCancelled"] }], _content: [{ type: i0.ViewChild, args: ['content', { isSignal: true }] }], _view: [{ type: i0.ViewChild, args: ['view', { isSignal: true }] }], _toolbarDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MlvEditorToolbarDef), { isSignal: true }] }], _toolbarStartDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MlvEditorToolbarStartDef), { isSignal: true }] }], _toolbarEndDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MlvEditorToolbarEndDef), { isSignal: true }] }] } });
|
|
985
|
-
//# sourceMappingURL=editor.js.map
|