@threadlabs/looma 0.18.2 → 0.18.4

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.
@@ -9205,12 +9205,28 @@ function setActiveTableCellBackground(editor, backgroundColor) {
9205
9205
  * Default Tiptap extension preset for Looma editor.
9206
9206
  * Uses the Vanilla JS Tiptap API; apps provide @tiptap/core and Looma ships the preset extensions.
9207
9207
  */
9208
- var LoomaCodeBlock = CodeBlockLowlight.extend({ addInputRules() {
9209
- return [...this.parent?.() ?? [], textblockTypeInputRule({
9210
- find: /^```$/,
9211
- type: this.type
9212
- })];
9213
- } });
9208
+ var LoomaCodeBlock = CodeBlockLowlight.extend({
9209
+ renderHTML({ node, HTMLAttributes }) {
9210
+ return [
9211
+ "pre",
9212
+ mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { spellcheck: "false" }),
9213
+ [
9214
+ "code",
9215
+ {
9216
+ class: node.attrs.language ? `${this.options.languageClassPrefix}${node.attrs.language}` : null,
9217
+ spellcheck: "false"
9218
+ },
9219
+ 0
9220
+ ]
9221
+ ];
9222
+ },
9223
+ addInputRules() {
9224
+ return [...this.parent?.() ?? [], textblockTypeInputRule({
9225
+ find: /^```$/,
9226
+ type: this.type
9227
+ })];
9228
+ }
9229
+ });
9214
9230
  var StoredOnlyHighlight = Highlight.extend({
9215
9231
  parseHTML: () => [],
9216
9232
  addKeyboardShortcuts: () => ({}),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.18.2",
3
+ "version": "0.18.4",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -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>;
@@ -331,6 +331,19 @@ var LoomaEditor = defineComponent({
331
331
  default: "bubble"
332
332
  },
333
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
+ /**
334
347
  * Authors can't highlight: no toolbar button, shortcut, `==text==` rule, or `<mark>` paste.
335
348
  * Highlights already in the document still show. Read once, when the editor is created.
336
349
  */
@@ -341,6 +354,7 @@ var LoomaEditor = defineComponent({
341
354
  },
342
355
  emits: {
343
356
  "update:modelValue": (_value) => true,
357
+ "update:toolbarOpen": (_value) => true,
344
358
  update: (_value) => true,
345
359
  ready: (_editor) => true,
346
360
  uploadError: (_error, _file) => true,
@@ -1153,14 +1167,17 @@ var LoomaEditor = defineComponent({
1153
1167
  onClick: run
1154
1168
  }, () => loomaIcon(icon));
1155
1169
  };
1156
- const renderToolbar = (instance, floating = true) => {
1157
- const buttons = [
1170
+ const renderToolbar = (instance, floating = true, textOnly = false) => {
1171
+ const textButtons = [
1158
1172
  commandButton("Bold", "bold", instance.isActive("bold"), !instance.can().toggleBold(), () => instance.chain().focus().toggleBold().run()),
1159
1173
  commandButton("Italic", "italic", instance.isActive("italic"), !instance.can().toggleItalic(), () => instance.chain().focus().toggleItalic().run()),
1160
1174
  commandButton("Underline", "underline", instance.isActive("underline"), !instance.can().toggleUnderline(), () => instance.chain().focus().toggleUnderline().run()),
1161
1175
  commandButton("Strike", "strikethrough", instance.isActive("strike"), !instance.can().toggleStrike(), () => instance.chain().focus().toggleStrike().run()),
1162
1176
  ...authorHighlight ? [commandButton("Highlight", "highlighter", instance.isActive("highlight"), !instance.can().toggleHighlight(), () => instance.chain().focus().toggleHighlight().run())] : [],
1163
- 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,
1164
1181
  h(IconButton, {
1165
1182
  id: linkAnchorId,
1166
1183
  class: "looma-editor__toolbar-button",
@@ -1313,7 +1330,7 @@ var LoomaEditor = defineComponent({
1313
1330
  onDblclick: onImageDoubleClick,
1314
1331
  onKeydown: onImageKeyDown
1315
1332
  }, [
1316
- 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, {
1317
1334
  editor: instance,
1318
1335
  pluginKey: "looma-text-formatting-menu",
1319
1336
  shouldShow: ({ editor: menuEditor, from, to }) => shouldShowTextFormattingToolbar(menuEditor, from, to),
@@ -1323,7 +1340,17 @@ var LoomaEditor = defineComponent({
1323
1340
  maxWidth: "none",
1324
1341
  placement: "top"
1325
1342
  }
1326
- }, { 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,
1327
1354
  instance && props.editable && !mobile.value && props.toolbarMode === "sticky" ? h("div", {
1328
1355
  class: "looma-editor__sticky-toolbar-shell",
1329
1356
  role: "toolbar",