@threadlabs/looma 0.18.1 → 0.18.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.18.1",
3
+ "version": "0.18.3",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -8662,17 +8662,18 @@ html[data-ui-input-modality="touch"]
8662
8662
  font-size: var(--ui-font-size-sm);
8663
8663
  }
8664
8664
 
8665
- .looma-editor .ProseMirror pre.looma-editor__code-block--has-language {
8666
- position: relative;
8667
- padding-block-start: calc(var(--ui-space-4) + 2rem);
8668
- }
8669
-
8665
+ /* Same surface as the floating formatting and table toolbars. */
8670
8666
  .looma-editor__code-language {
8671
- position: absolute;
8672
- inset-block-start: var(--ui-space-2);
8673
- inset-inline-end: var(--ui-space-2);
8674
- inline-size: min(8.5rem, calc(100% - 2 * var(--ui-space-2)));
8675
- z-index: 1;
8667
+ position: fixed;
8668
+ z-index: var(--ui-editor-popover-z-index, 300);
8669
+ box-sizing: content-box;
8670
+ inline-size: 8.5rem;
8671
+ padding: var(--ui-editor-toolbar-floating-padding, 4px);
8672
+ background: color-mix(in srgb, var(--ui-editor-toolbar-surface, var(--ui-surface)) 96%, transparent);
8673
+ border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border-strong));
8674
+ border-radius: var(--ui-editor-toolbar-floating-radius, var(--ui-radius-lg));
8675
+ box-shadow: var(--ui-editor-toolbar-floating-shadow, var(--ui-shadow-lg, 0 10px 24px rgb(0 0 0 / 0.12)));
8676
+ backdrop-filter: blur(10px);
8676
8677
  font-family: var(--ui-font-family-sans, sans-serif);
8677
8678
  }
8678
8679
 
@@ -21,10 +21,11 @@ export interface LoomaImageUploadResult extends Omit<LoomaImageDescriptor, "src"
21
21
  */
22
22
  export type LoomaImageUploader = (file: File) => Promise<string | LoomaImageUploadResult>;
23
23
  /**
24
- * Chooses whether formatting controls follow a selection or occupy persistent
25
- * editor chrome; it does not alter document commands or stored content.
24
+ * Chooses whether formatting controls follow a selection, occupy persistent
25
+ * editor chrome, or open from an app-owned button (`popover`, with a text-only
26
+ * bubble for selections); it does not alter document commands or stored content.
26
27
  */
27
- export type LoomaEditorToolbarMode = "bubble" | "sticky";
28
+ export type LoomaEditorToolbarMode = "bubble" | "sticky" | "popover";
28
29
  /**
29
30
  * Turnkey Vue editor that composes Looma's framework-neutral Tiptap extensions
30
31
  * with declarative menus, image delivery, and table interaction chrome.
@@ -99,6 +100,19 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
99
100
  type: PropType<LoomaEditorToolbarMode>;
100
101
  default: string;
101
102
  };
103
+ /**
104
+ * In `popover` mode, the ID of the app's button that toggles the full toolbar and anchors it.
105
+ * The button needs no click handler of its own.
106
+ */
107
+ toolbarTriggerId: {
108
+ type: StringConstructor;
109
+ default: string;
110
+ };
111
+ /** In `popover` mode, whether the full toolbar is open. Use with `v-model:toolbar-open`. */
112
+ toolbarOpen: {
113
+ type: BooleanConstructor;
114
+ default: boolean;
115
+ };
102
116
  /**
103
117
  * Authors can't highlight: no toolbar button, shortcut, `==text==` rule, or `<mark>` paste.
104
118
  * Highlights already in the document still show. Read once, when the editor is created.
@@ -111,6 +125,7 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
111
125
  [key: string]: any;
112
126
  }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
113
127
  "update:modelValue": (_value: JSONContent) => true;
128
+ "update:toolbarOpen": (_value: boolean) => true;
114
129
  update: (_value: JSONContent) => true;
115
130
  ready: (_editor: Editor) => true;
116
131
  uploadError: (_error: unknown, _file: File) => true;
@@ -178,6 +193,19 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
178
193
  type: PropType<LoomaEditorToolbarMode>;
179
194
  default: string;
180
195
  };
196
+ /**
197
+ * In `popover` mode, the ID of the app's button that toggles the full toolbar and anchors it.
198
+ * The button needs no click handler of its own.
199
+ */
200
+ toolbarTriggerId: {
201
+ type: StringConstructor;
202
+ default: string;
203
+ };
204
+ /** In `popover` mode, whether the full toolbar is open. Use with `v-model:toolbar-open`. */
205
+ toolbarOpen: {
206
+ type: BooleanConstructor;
207
+ default: boolean;
208
+ };
181
209
  /**
182
210
  * Authors can't highlight: no toolbar button, shortcut, `==text==` rule, or `<mark>` paste.
183
211
  * Highlights already in the document still show. Read once, when the editor is created.
@@ -188,6 +216,7 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
188
216
  };
189
217
  }>> & Readonly<{
190
218
  "onUpdate:modelValue"?: ((_value: JSONContent) => any) | undefined;
219
+ "onUpdate:toolbarOpen"?: ((_value: boolean) => any) | undefined;
191
220
  onUpdate?: ((_value: JSONContent) => any) | undefined;
192
221
  onReady?: ((_editor: Editor) => any) | undefined;
193
222
  onUploadError?: ((_error: unknown, _file: File) => any) | undefined;
@@ -207,4 +236,6 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
207
236
  uploadImage: LoomaImageUploader | undefined;
208
237
  resolveImageAttributes: LoomaImageAttributeResolver | undefined;
209
238
  toolbarMode: LoomaEditorToolbarMode;
239
+ toolbarTriggerId: string;
240
+ toolbarOpen: boolean;
210
241
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -1,12 +1,12 @@
1
1
  import { computed, defineComponent, h, nextTick, onBeforeUnmount, onMounted, reactive, ref, useId, watch } from "vue";
2
2
  import { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_CHIP_COLORS, LOOMA_ICONS, createLoomaMentionExtension, createLoomaSlashCommandExtension, getActiveTableUiState, getDefaultEditorExtensions, getVisualViewportRect, handleTableAction, handleTableOverlayAction, measureTableOverlayGeometry, normalizeActiveTableColumnWidths, normalizeLoomaChipColor, resolveTableCellAt, shouldShowTextFormattingToolbar } from "@threadlabs/looma/editor";
3
3
  import { Combobox, EditorInsertTableGrid, EditorMentionMenu, EditorSlashMenu, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, IconButton, Menu, MenuItem, Popover, Tooltip } from "@threadlabs/looma/vue";
4
- import { BubbleMenu, EditorContent, NodeViewContent, NodeViewWrapper, VueNodeViewRenderer, nodeViewProps, useEditor } from "@tiptap/vue-3";
4
+ import { BubbleMenu, EditorContent, useEditor } from "@tiptap/vue-3";
5
+ import { closeHistory } from "@tiptap/pm/history";
6
+ import { createLowlight } from "lowlight";
5
7
  import { Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
6
8
  import { Extension } from "@tiptap/core";
7
9
  import { Decoration, DecorationSet } from "@tiptap/pm/view";
8
- import { closeHistory } from "@tiptap/pm/history";
9
- import { createLowlight } from "lowlight";
10
10
  export * from "@threadlabs/looma/editor";
11
11
  //#region src/vue/editor/primitives.ts
12
12
  /** Each Vue editor component's element tag, for tooling that enumerates them. */
@@ -180,69 +180,6 @@ function imageUploadContent(image) {
180
180
  };
181
181
  }
182
182
  //#endregion
183
- //#region src/vue/editor/code-block-view.ts
184
- /** Per-block language control; the document stores only the code and explicit language. */
185
- function createCodeBlockView(languages, isEditable) {
186
- const lowlight = createLowlight(languages);
187
- const names = Object.keys(languages).sort();
188
- return defineComponent({
189
- name: "LoomaCodeBlockView",
190
- props: nodeViewProps,
191
- setup(props) {
192
- const selected = computed(() => {
193
- const language = props.node.attrs.language;
194
- return typeof language === "string" && language ? language : "auto";
195
- });
196
- const detected = computed(() => {
197
- if (!props.node.textContent.trim()) return null;
198
- const language = lowlight.highlightAuto(props.node.textContent).data?.language;
199
- return typeof language === "string" ? language : null;
200
- });
201
- const options = computed(() => [
202
- {
203
- id: "auto",
204
- value: "auto",
205
- label: detected.value ? `Auto (${detected.value.toUpperCase()})` : "Auto"
206
- },
207
- ...selected.value !== "auto" && !Object.hasOwn(languages, selected.value) ? [{
208
- id: selected.value,
209
- value: selected.value,
210
- label: `${selected.value.toUpperCase()} (unavailable)`
211
- }] : [],
212
- ...names.map((name) => ({
213
- id: name,
214
- value: name,
215
- label: name.toUpperCase()
216
- }))
217
- ]);
218
- const choose = (detail) => {
219
- if (detail.kind !== "selection" || !detail.value) return;
220
- const language = detail.value === "auto" ? null : detail.value;
221
- if (language !== null && !Object.hasOwn(languages, language)) return;
222
- props.editor.view.dispatch(closeHistory(props.editor.state.tr));
223
- props.updateAttributes({ language });
224
- props.editor.view.dispatch(closeHistory(props.editor.state.tr));
225
- };
226
- const showControl = () => names.length > 0 && isEditable() && props.editor.isEditable;
227
- return () => h(NodeViewWrapper, {
228
- as: "pre",
229
- class: showControl() ? "looma-editor__code-block--has-language" : void 0
230
- }, () => [showControl() ? h("div", {
231
- class: "looma-editor__code-language",
232
- contenteditable: "false"
233
- }, [h(Combobox, {
234
- label: "Code language",
235
- labelVisibility: "sr-only",
236
- size: "sm",
237
- disclosure: true,
238
- filter: "label",
239
- value: selected.value,
240
- onValueChange: choose
241
- }, () => options.value.map((option) => h("option", { value: option.value }, option.label)))]) : null, h(NodeViewContent, { as: "code" })]);
242
- }
243
- });
244
- }
245
- //#endregion
246
183
  //#region src/vue/editor/LoomaEditor.ts
247
184
  var EMPTY_DOCUMENT = {
248
185
  type: "doc",
@@ -394,6 +331,19 @@ var LoomaEditor = defineComponent({
394
331
  default: "bubble"
395
332
  },
396
333
  /**
334
+ * In `popover` mode, the ID of the app's button that toggles the full toolbar and anchors it.
335
+ * The button needs no click handler of its own.
336
+ */
337
+ toolbarTriggerId: {
338
+ type: String,
339
+ default: ""
340
+ },
341
+ /** In `popover` mode, whether the full toolbar is open. Use with `v-model:toolbar-open`. */
342
+ toolbarOpen: {
343
+ type: Boolean,
344
+ default: false
345
+ },
346
+ /**
397
347
  * Authors can't highlight: no toolbar button, shortcut, `==text==` rule, or `<mark>` paste.
398
348
  * Highlights already in the document still show. Read once, when the editor is created.
399
349
  */
@@ -404,6 +354,7 @@ var LoomaEditor = defineComponent({
404
354
  },
405
355
  emits: {
406
356
  "update:modelValue": (_value) => true,
357
+ "update:toolbarOpen": (_value) => true,
407
358
  update: (_value) => true,
408
359
  ready: (_editor) => true,
409
360
  uploadError: (_error, _file) => true,
@@ -459,6 +410,7 @@ var LoomaEditor = defineComponent({
459
410
  const tableOverlayShell = ref(null);
460
411
  const tableMenuShell = ref(null);
461
412
  const mobileToolbarShell = ref(null);
413
+ const codeLanguageShell = ref(null);
462
414
  const dragOver = ref(false);
463
415
  const uploading = ref(false);
464
416
  const failedUpload = ref(null);
@@ -583,8 +535,7 @@ var LoomaEditor = defineComponent({
583
535
  placeholder: props.placeholder,
584
536
  mention: mentionExtension ?? false,
585
537
  disableHighlight: props.disableHighlight,
586
- codeLanguages: props.codeLanguages,
587
- codeBlockNodeView: VueNodeViewRenderer(createCodeBlockView(props.codeLanguages, () => props.editable))
538
+ codeLanguages: props.codeLanguages
588
539
  }),
589
540
  imageDelivery.extension,
590
541
  slashExtension,
@@ -794,6 +745,77 @@ var LoomaEditor = defineComponent({
794
745
  };
795
746
  });
796
747
  };
748
+ const codeLanguageNames = Object.keys(props.codeLanguages).sort();
749
+ const codeLowlight = createLowlight(props.codeLanguages);
750
+ const codeUi = reactive({
751
+ open: false,
752
+ pos: 0,
753
+ language: "auto",
754
+ text: "",
755
+ style: {}
756
+ });
757
+ let codeBlurTimer;
758
+ const updateCodeUi = (focusSettled = false) => {
759
+ const instance = editor.value?.isDestroyed ? void 0 : editor.value;
760
+ const selection = instance?.state.selection;
761
+ const block = selection?.$from.parent;
762
+ const dom = instance && block?.type.name === "codeBlock" && selection.$from.sameParent(selection.$to) ? instance.view.nodeDOM(selection.$from.before()) : null;
763
+ if (!instance || !props.editable || !codeLanguageNames.length || !(dom instanceof HTMLElement)) {
764
+ codeUi.open = false;
765
+ return;
766
+ }
767
+ if (!instance.isFocused && !codeLanguageShell.value?.contains(document.activeElement)) {
768
+ clearTimeout(codeBlurTimer);
769
+ if (codeUi.open && !focusSettled) codeBlurTimer = setTimeout(() => updateCodeUi(true), 0);
770
+ else codeUi.open = false;
771
+ return;
772
+ }
773
+ const rect = dom.getBoundingClientRect();
774
+ const above = rect.top > 76;
775
+ codeUi.open = true;
776
+ codeUi.pos = selection.$from.before();
777
+ codeUi.language = typeof block.attrs.language === "string" && block.attrs.language ? block.attrs.language : "auto";
778
+ codeUi.text = block.textContent;
779
+ codeUi.style = {
780
+ top: `${above ? rect.top - 8 : rect.bottom + 8}px`,
781
+ left: `${rect.left + rect.width / 2}px`,
782
+ transform: `translate(-50%, ${above ? "-100%" : "0"})`
783
+ };
784
+ };
785
+ const codeLanguageOptions = computed(() => {
786
+ const detected = codeUi.open && codeUi.text.trim() ? codeLowlight.highlightAuto(codeUi.text).data?.language : null;
787
+ return [
788
+ {
789
+ value: "auto",
790
+ label: typeof detected === "string" ? `Auto (${detected.toUpperCase()})` : "Auto"
791
+ },
792
+ ...codeUi.language !== "auto" && !Object.hasOwn(props.codeLanguages, codeUi.language) ? [{
793
+ value: codeUi.language,
794
+ label: `${codeUi.language.toUpperCase()} (unavailable)`
795
+ }] : [],
796
+ ...codeLanguageNames.map((name) => ({
797
+ value: name,
798
+ label: name.toUpperCase()
799
+ }))
800
+ ];
801
+ });
802
+ const chooseCodeLanguage = (detail) => {
803
+ const instance = editor.value;
804
+ if (!instance || detail.kind !== "selection" || !detail.value) return;
805
+ const language = detail.value === "auto" ? null : detail.value;
806
+ if (language !== null && !Object.hasOwn(props.codeLanguages, language)) return;
807
+ const node = instance.state.doc.nodeAt(codeUi.pos);
808
+ if (node?.type.name !== "codeBlock") return;
809
+ instance.view.dispatch(closeHistory(instance.state.tr));
810
+ instance.view.dispatch(instance.state.tr.setNodeMarkup(codeUi.pos, void 0, {
811
+ ...node.attrs,
812
+ language
813
+ }));
814
+ instance.view.dispatch(closeHistory(instance.state.tr));
815
+ };
816
+ const onCodeTransaction = () => updateCodeUi();
817
+ watch(() => props.editable, () => nextTick(onCodeTransaction));
818
+ onBeforeUnmount(() => clearTimeout(codeBlurTimer));
797
819
  const updateTableUi = () => {
798
820
  const instance = editor.value;
799
821
  if (!instance || !props.editable || !instance.isFocused && !tableInteractionActive && !hoveredTableCell) {
@@ -840,10 +862,12 @@ var LoomaEditor = defineComponent({
840
862
  const onEditorFocus = () => {
841
863
  editorFocused.value = true;
842
864
  updateTableUi();
865
+ updateCodeUi();
843
866
  updateMobileViewport();
844
867
  };
845
868
  const onEditorBlur = () => {
846
869
  updateTableUi();
870
+ updateCodeUi();
847
871
  setTimeout(() => {
848
872
  if (!tableInteractionActive && !editor.value?.isFocused) editorFocused.value = false;
849
873
  }, 0);
@@ -852,6 +876,7 @@ var LoomaEditor = defineComponent({
852
876
  if (!instance) return;
853
877
  instance.on("selectionUpdate", updateTableUi);
854
878
  instance.on("transaction", updateTableUi);
879
+ instance.on("transaction", onCodeTransaction);
855
880
  instance.on("focus", onEditorFocus);
856
881
  instance.on("blur", onEditorBlur);
857
882
  nextTick(updateTableUi);
@@ -860,6 +885,7 @@ var LoomaEditor = defineComponent({
860
885
  if (!instance) return;
861
886
  instance.off("selectionUpdate", updateTableUi);
862
887
  instance.off("transaction", updateTableUi);
888
+ instance.off("transaction", onCodeTransaction);
863
889
  instance.off("focus", onEditorFocus);
864
890
  instance.off("blur", onEditorBlur);
865
891
  };
@@ -870,6 +896,7 @@ var LoomaEditor = defineComponent({
870
896
  const onViewportChange = () => {
871
897
  updateMobileViewport();
872
898
  updateTableUi();
899
+ updateCodeUi();
873
900
  tableUi.menuOpen = false;
874
901
  };
875
902
  const onDocumentPointerDown = (event) => {
@@ -1140,14 +1167,17 @@ var LoomaEditor = defineComponent({
1140
1167
  onClick: run
1141
1168
  }, () => loomaIcon(icon));
1142
1169
  };
1143
- const renderToolbar = (instance, floating = true) => {
1144
- const buttons = [
1170
+ const renderToolbar = (instance, floating = true, textOnly = false) => {
1171
+ const textButtons = [
1145
1172
  commandButton("Bold", "bold", instance.isActive("bold"), !instance.can().toggleBold(), () => instance.chain().focus().toggleBold().run()),
1146
1173
  commandButton("Italic", "italic", instance.isActive("italic"), !instance.can().toggleItalic(), () => instance.chain().focus().toggleItalic().run()),
1147
1174
  commandButton("Underline", "underline", instance.isActive("underline"), !instance.can().toggleUnderline(), () => instance.chain().focus().toggleUnderline().run()),
1148
1175
  commandButton("Strike", "strikethrough", instance.isActive("strike"), !instance.can().toggleStrike(), () => instance.chain().focus().toggleStrike().run()),
1149
1176
  ...authorHighlight ? [commandButton("Highlight", "highlighter", instance.isActive("highlight"), !instance.can().toggleHighlight(), () => instance.chain().focus().toggleHighlight().run())] : [],
1150
- commandButton("Inline code", "code-xml", instance.isActive("code"), !instance.can().toggleCode(), () => instance.chain().focus().toggleCode().run()),
1177
+ commandButton("Inline code", "code-xml", instance.isActive("code"), !instance.can().toggleCode(), () => instance.chain().focus().toggleCode().run())
1178
+ ];
1179
+ const buttons = textOnly ? textButtons : [
1180
+ ...textButtons,
1151
1181
  h(IconButton, {
1152
1182
  id: linkAnchorId,
1153
1183
  class: "looma-editor__toolbar-button",
@@ -1300,7 +1330,7 @@ var LoomaEditor = defineComponent({
1300
1330
  onDblclick: onImageDoubleClick,
1301
1331
  onKeydown: onImageKeyDown
1302
1332
  }, [
1303
- instance && props.editable && !mobile.value && props.toolbarMode === "bubble" ? h(BubbleMenu, {
1333
+ instance && props.editable && !mobile.value && (props.toolbarMode === "bubble" || props.toolbarMode === "popover" && !props.toolbarOpen) ? h(BubbleMenu, {
1304
1334
  editor: instance,
1305
1335
  pluginKey: "looma-text-formatting-menu",
1306
1336
  shouldShow: ({ editor: menuEditor, from, to }) => shouldShowTextFormattingToolbar(menuEditor, from, to),
@@ -1310,13 +1340,37 @@ var LoomaEditor = defineComponent({
1310
1340
  maxWidth: "none",
1311
1341
  placement: "top"
1312
1342
  }
1313
- }, { default: () => renderToolbar(instance) }) : null,
1343
+ }, { default: () => renderToolbar(instance, true, props.toolbarMode === "popover") }) : null,
1344
+ instance && props.editable && !mobile.value && props.toolbarMode === "popover" && props.toolbarTriggerId ? h(Popover, {
1345
+ class: "looma-editor__formatting-popover",
1346
+ role: "region",
1347
+ "aria-label": "Formatting tools",
1348
+ open: props.toolbarOpen,
1349
+ for: props.toolbarTriggerId,
1350
+ placement: "bottom-end",
1351
+ onOpen: () => emit("update:toolbarOpen", true),
1352
+ onClose: () => emit("update:toolbarOpen", false)
1353
+ }, () => [renderToolbar(instance, false)]) : null,
1314
1354
  instance && props.editable && !mobile.value && props.toolbarMode === "sticky" ? h("div", {
1315
1355
  class: "looma-editor__sticky-toolbar-shell",
1316
1356
  role: "toolbar",
1317
1357
  "aria-label": "Editor tools"
1318
1358
  }, [renderToolbar(instance, false)]) : null,
1319
1359
  instance ? h(EditorContent, { editor: instance }) : null,
1360
+ codeUi.open ? h("div", {
1361
+ ref: codeLanguageShell,
1362
+ class: "looma-editor__code-language",
1363
+ style: codeUi.style,
1364
+ onFocusout: () => updateCodeUi()
1365
+ }, [h(Combobox, {
1366
+ label: "Code language",
1367
+ labelVisibility: "sr-only",
1368
+ size: "sm",
1369
+ disclosure: true,
1370
+ filter: "label",
1371
+ value: codeUi.language,
1372
+ onValueChange: chooseCodeLanguage
1373
+ }, () => codeLanguageOptions.value.map((option) => h("option", { value: option.value }, option.label)))]) : null,
1320
1374
  instance && props.editable && mobile.value && editorFocused.value ? h("div", {
1321
1375
  ref: mobileToolbarShell,
1322
1376
  class: "looma-editor__mobile-toolbar-shell",
@@ -1,29 +0,0 @@
1
- import type { LoomaCodeLanguages } from "@threadlabs/looma/editor";
2
- /** Per-block language control; the document stores only the code and explicit language. */
3
- export declare function createCodeBlockView(languages: LoomaCodeLanguages, isEditable: () => boolean): import("vue").DefineComponent<{
4
- decorations: readonly import("@tiptap/core").DecorationWithType[];
5
- selected: boolean;
6
- updateAttributes: (attributes: Record<string, any>) => void;
7
- deleteNode: () => void;
8
- node: Parameters<import("@tiptap/pm/view").NodeViewConstructor>[0];
9
- view: Parameters<import("@tiptap/pm/view").NodeViewConstructor>[1];
10
- getPos: () => number;
11
- innerDecorations: Parameters<import("@tiptap/pm/view").NodeViewConstructor>[4];
12
- editor: import("@tiptap/core").Editor;
13
- extension: import("@tiptap/core").Node;
14
- HTMLAttributes: Record<string, any>;
15
- }, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
16
- [key: string]: any;
17
- }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
18
- decorations: readonly import("@tiptap/core").DecorationWithType[];
19
- selected: boolean;
20
- updateAttributes: (attributes: Record<string, any>) => void;
21
- deleteNode: () => void;
22
- node: Parameters<import("@tiptap/pm/view").NodeViewConstructor>[0];
23
- view: Parameters<import("@tiptap/pm/view").NodeViewConstructor>[1];
24
- getPos: () => number;
25
- innerDecorations: Parameters<import("@tiptap/pm/view").NodeViewConstructor>[4];
26
- editor: import("@tiptap/core").Editor;
27
- extension: import("@tiptap/core").Node;
28
- HTMLAttributes: Record<string, any>;
29
- }> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;