@threadlabs/looma 0.24.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -219,8 +219,16 @@ export function createAnchoredSurface(surface, options = {}) {
219
219
  fallbackPosition(surface, { left: point.x, right: point.x, top: point.y, bottom: point.y, width: 0, height: 0 }, "bottom-start", gap(), viewportGap);
220
220
  return;
221
221
  }
222
- if (!anchor) return;
223
- lastAnchorRect = anchor.getBoundingClientRect();
222
+ const rect = anchor?.getBoundingClientRect();
223
+ // A disappearing trigger has no usable position. Keep the last valid position, or wait before first opening.
224
+ if (!anchor || anchor.isConnected === false || !rect || rect.width === 0 && rect.height === 0
225
+ || anchor instanceof owner.Element && owner.getComputedStyle(anchor).visibility !== "visible") {
226
+ if (lastAnchorRect) fallbackPosition(surface, lastAnchorRect, placement, gap(), viewportGap);
227
+ else hide(surface);
228
+ return;
229
+ }
230
+ lastAnchorRect = rect;
231
+ show(surface);
224
232
  fallbackPosition(surface, lastAnchorRect, placement, gap(), viewportGap);
225
233
  };
226
234
  const schedule = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.24.0",
3
+ "version": "0.24.1",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -5,7 +5,7 @@ import { Extension, Node as Node$1, getText, getTextSerializersFromSchema, merge
5
5
  import { BubbleMenu, EditorContent, useEditor } from "@tiptap/vue-3";
6
6
  import { closeHistory } from "@tiptap/pm/history";
7
7
  import { createLowlight } from "lowlight";
8
- import { NodeSelection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
8
+ import { AllSelection, NodeSelection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
9
9
  import { Decoration, DecorationSet } from "@tiptap/pm/view";
10
10
  import { DOMParser, DOMSerializer, Fragment as Fragment$1 } from "@tiptap/pm/model";
11
11
  export * from "@threadlabs/looma/editor";
@@ -1801,6 +1801,7 @@ var LoomaEditor = defineComponent({
1801
1801
  let heldPressTimer;
1802
1802
  let heldPress = null;
1803
1803
  const floatingFormattingMode = () => props.toolbarMode !== "sticky" && !(props.toolbarMode === "popover" && props.toolbarOpen) && !mobile.value;
1804
+ const formattingPickerOpen = () => linkOpen.value || tablePickerOpen.value;
1804
1805
  const cancelHeldPress = () => {
1805
1806
  clearTimeout(heldPressTimer);
1806
1807
  heldPressTimer = void 0;
@@ -1808,7 +1809,7 @@ var LoomaEditor = defineComponent({
1808
1809
  };
1809
1810
  const formattingSelectionActive = (instance) => {
1810
1811
  const selection = instance.state.selection;
1811
- return selection instanceof TextSelection && !dismissedFormattingSelection?.eq(selection) && (!selection.empty || Boolean(heldFormattingSelection?.eq(selection)));
1812
+ return (selection instanceof TextSelection || selection instanceof AllSelection && Boolean(instance.state.doc.textContent)) && !dismissedFormattingSelection?.eq(selection) && (!selection.empty || Boolean(heldFormattingSelection?.eq(selection)));
1812
1813
  };
1813
1814
  const editorStateVersion = ref(0);
1814
1815
  const mobileToolbarMode = ref("formatting");
@@ -2473,6 +2474,11 @@ var LoomaEditor = defineComponent({
2473
2474
  });
2474
2475
  if (!editable) chipOpen.value = false;
2475
2476
  });
2477
+ watch([linkOpen, tablePickerOpen], ([link, table]) => {
2478
+ if (link || table || !floatingFormattingMode() || editor.value?.isFocused || formattingPopup?.popper.contains(document.activeElement)) return;
2479
+ heldFormattingSelection = null;
2480
+ formattingPopup?.hide();
2481
+ });
2476
2482
  watch(() => props.label, (label) => {
2477
2483
  editor.value?.setOptions({ editorProps: { attributes: {
2478
2484
  role: "textbox",
@@ -2667,7 +2673,7 @@ var LoomaEditor = defineComponent({
2667
2673
  updateCodeUi();
2668
2674
  setTimeout(() => {
2669
2675
  if (!tableInteractionActive && !editor.value?.isFocused) editorFocused.value = false;
2670
- if (!editor.value?.isFocused && !formattingPopup?.popper.contains(document.activeElement)) heldFormattingSelection = null;
2676
+ if (!editor.value?.isFocused && !formattingPickerOpen() && !formattingPopup?.popper.contains(document.activeElement)) heldFormattingSelection = null;
2671
2677
  }, 0);
2672
2678
  };
2673
2679
  const bindEditorUi = (instance) => {
@@ -2741,7 +2747,7 @@ var LoomaEditor = defineComponent({
2741
2747
  cancelHeldPress();
2742
2748
  if (event.key !== "Escape" || !floatingFormattingMode() || !(event.target instanceof Node) || !(root.value?.contains(event.target) || formattingPopup?.popper.contains(event.target))) return;
2743
2749
  const selection = editor.value?.state.selection;
2744
- dismissedFormattingSelection = selection instanceof TextSelection ? selection : null;
2750
+ dismissedFormattingSelection = selection instanceof TextSelection || selection instanceof AllSelection ? selection : null;
2745
2751
  heldFormattingSelection = null;
2746
2752
  formattingPopup?.hide();
2747
2753
  hideTool();
@@ -3208,7 +3214,7 @@ var LoomaEditor = defineComponent({
3208
3214
  editor: instance,
3209
3215
  pluginKey: "looma-text-formatting-menu",
3210
3216
  updateDelay: 0,
3211
- shouldShow: ({ editor: menuEditor }) => (props.toolbarMode !== "popover" || !props.toolbarOpen) && !slash.active && !mention.active && (menuEditor.isFocused || linkContextEditing.value) && formattingSelectionActive(menuEditor),
3217
+ shouldShow: ({ editor: menuEditor }) => (props.toolbarMode !== "popover" || !props.toolbarOpen) && !slash.active && !mention.active && (menuEditor.isFocused || linkContextEditing.value || formattingPickerOpen()) && formattingSelectionActive(menuEditor),
3212
3218
  tippyOptions: {
3213
3219
  onCreate: (popup) => {
3214
3220
  formattingPopup = popup;
@@ -3218,6 +3224,7 @@ var LoomaEditor = defineComponent({
3218
3224
  },
3219
3225
  appendTo: () => root.value?.closest("dialog[open], [popover]") ?? document.body,
3220
3226
  onShow: () => announceOverlayOpen(root.value?.ownerDocument ?? document, root.value),
3227
+ onHide: () => instance.isEditable && floatingFormattingMode() && formattingPickerOpen() && formattingSelectionActive(instance) ? false : void 0,
3221
3228
  duration: 100,
3222
3229
  maxWidth: "none",
3223
3230
  placement: "top",