@threadlabs/looma 0.1.6 → 0.1.7

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.
Files changed (48) hide show
  1. package/dist/{chunk-3PASQ7DE.js → chunk-UMFO4QNN.js} +26 -26
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/looma.cjs.js +1 -1
  4. package/dist/cjs/ui-dialog.cjs.entry.js +3 -1
  5. package/dist/collection/components/ui-dialog/ui-dialog.js +22 -1
  6. package/dist/components/ui-dialog.js +1 -1
  7. package/dist/esm/loader.js +1 -1
  8. package/dist/esm/looma.js +1 -1
  9. package/dist/esm/ui-dialog.entry.js +3 -1
  10. package/dist/index.cjs +4 -2
  11. package/dist/index.js +2 -2
  12. package/dist/looma/looma.esm.js +1 -1
  13. package/dist/looma/p-5df568d8.entry.js +1 -0
  14. package/dist/types/components/ui-dialog/ui-dialog.d.ts +2 -0
  15. package/dist/types/components.d.ts +9 -0
  16. package/dist/{ui-avatar-group.entry-DBVLQ4KB.js → ui-avatar-group.entry-S6DFXYB7.js} +1 -1
  17. package/dist/{ui-avatar.entry-2WTBM2EC.js → ui-avatar.entry-MDRGXLWQ.js} +1 -1
  18. package/dist/{ui-badge.entry-XKIGBK5V.js → ui-badge.entry-RLL4YKPD.js} +1 -1
  19. package/dist/{ui-button.entry-PWT56MPD.js → ui-button.entry-IYMYLBFY.js} +1 -1
  20. package/dist/{ui-checkbox.entry-QT5S7EEL.js → ui-checkbox.entry-K5FGWDG2.js} +1 -1
  21. package/dist/{ui-context-menu.entry-NGWR3LOZ.js → ui-context-menu.entry-KWXXJ3ZV.js} +1 -1
  22. package/dist/{ui-dialog.entry-PEDDIALQ.js → ui-dialog.entry-RKHLQLQM.js} +4 -2
  23. package/dist/{ui-disclosure.entry-UKO7MAZM.js → ui-disclosure.entry-FRZKGEJP.js} +1 -1
  24. package/dist/{ui-floating-action-button.entry-SSGHRMCO.js → ui-floating-action-button.entry-BH4FDSTL.js} +1 -1
  25. package/dist/{ui-form-field.entry-6TZCWPYL.js → ui-form-field.entry-3CR2KSUH.js} +1 -1
  26. package/dist/{ui-icon-button.entry-WMCYMK2H.js → ui-icon-button.entry-LB54U25M.js} +1 -1
  27. package/dist/{ui-input.entry-AZ5BGQNA.js → ui-input.entry-5PQR37HS.js} +1 -1
  28. package/dist/{ui-menu-item.entry-L4NJDBKF.js → ui-menu-item.entry-2T3QWHLK.js} +1 -1
  29. package/dist/{ui-menu.entry-DGUYAE3Q.js → ui-menu.entry-Q5Z5YO5P.js} +1 -1
  30. package/dist/{ui-popover.entry-A54EKVZG.js → ui-popover.entry-4P2NWWAY.js} +1 -1
  31. package/dist/{ui-radio-group.entry-6YP4LY4N.js → ui-radio-group.entry-QKPRNV26.js} +1 -1
  32. package/dist/{ui-radio.entry-CGYNK7PN.js → ui-radio.entry-O4DOMFNU.js} +1 -1
  33. package/dist/{ui-search-result-row.entry-DGKSI2QM.js → ui-search-result-row.entry-BR5O3UCH.js} +1 -1
  34. package/dist/{ui-search-shell.entry-3F5ASGTW.js → ui-search-shell.entry-2ZBP7SA3.js} +1 -1
  35. package/dist/{ui-select.entry-SXSZPVXA.js → ui-select.entry-L75HQY72.js} +1 -1
  36. package/dist/{ui-switch.entry-AD4EVUWM.js → ui-switch.entry-L5QWD3BT.js} +1 -1
  37. package/dist/{ui-tabs.entry-WLKO5G5N.js → ui-tabs.entry-KWRD6Y7J.js} +1 -1
  38. package/dist/{ui-textarea.entry-IHPC7Q4R.js → ui-textarea.entry-JC3HPEBS.js} +1 -1
  39. package/dist/{ui-toast-region.entry-GCW2LJAC.js → ui-toast-region.entry-C6KK4OM4.js} +1 -1
  40. package/dist/{ui-tooltip.entry-EU2G6BH5.js → ui-tooltip.entry-G5EOCWP4.js} +1 -1
  41. package/dist/{ui-top-bar.entry-NMAFXVET.js → ui-top-bar.entry-YLKVAQFH.js} +1 -1
  42. package/editor/{chunk-KQQTYVRW.js → chunk-OK5NARJI.js} +30 -13
  43. package/editor/index.js +1 -1
  44. package/editor/ui.js +1 -1
  45. package/editor.css +111 -4
  46. package/package.json +1 -1
  47. package/vue/editor/index.js +91 -12
  48. package/dist/looma/p-a7be33fd.entry.js +0 -1
@@ -181,13 +181,19 @@ var LoomaEditor = defineComponent2({
181
181
  const tableToolbarShell = ref(null);
182
182
  const tableOverlayShell = ref(null);
183
183
  const tableMenuShell = ref(null);
184
+ const mobileToolbarShell = ref(null);
184
185
  const dragOver = ref(false);
185
186
  const uploading = ref(false);
186
187
  const tablePickerOpen = ref(false);
187
188
  const tablePickerStyle = ref({});
189
+ const mobileToolbarStyle = ref({});
190
+ const mobile = ref(false);
191
+ const editorFocused = ref(false);
192
+ const mobileToolbarMode = ref("formatting");
188
193
  let dragLeaveTimer = null;
189
194
  let tableResizeActive = false;
190
195
  let tableInteractionActive = false;
196
+ let mobileTableControlsDismissed = false;
191
197
  const slash = reactive({
192
198
  active: false,
193
199
  items: [],
@@ -243,6 +249,28 @@ var LoomaEditor = defineComponent2({
243
249
  tableUi.alignment = "left";
244
250
  tableUi.background = null;
245
251
  tableUi.capabilities = { ...EMPTY_CAPABILITIES };
252
+ mobileTableControlsDismissed = false;
253
+ mobileToolbarMode.value = "formatting";
254
+ };
255
+ const updateMobileViewport = () => {
256
+ mobile.value = window.innerWidth <= 767;
257
+ if (!mobile.value) {
258
+ mobileToolbarStyle.value = {};
259
+ return;
260
+ }
261
+ nextTick(() => {
262
+ const viewport = window.visualViewport;
263
+ const viewportLeft = viewport?.offsetLeft ?? 0;
264
+ const viewportTop = viewport?.offsetTop ?? 0;
265
+ const viewportWidth = viewport?.width ?? window.innerWidth;
266
+ const viewportHeight = viewport?.height ?? window.innerHeight;
267
+ const toolbarHeight = mobileToolbarShell.value?.getBoundingClientRect().height || 56;
268
+ mobileToolbarStyle.value = {
269
+ left: `${viewportLeft}px`,
270
+ top: `${Math.max(viewportTop, viewportTop + viewportHeight - toolbarHeight)}px`,
271
+ width: `${viewportWidth}px`
272
+ };
273
+ });
246
274
  };
247
275
  const updateTableUi = () => {
248
276
  const instance = editor.value;
@@ -257,14 +285,15 @@ var LoomaEditor = defineComponent2({
257
285
  closeTableUi();
258
286
  return;
259
287
  }
288
+ if (!mobileTableControlsDismissed) mobileToolbarMode.value = "table";
260
289
  const rect = table.getBoundingClientRect();
261
290
  const maxToolbarWidth = Math.min(420, window.innerWidth - 24);
262
291
  const toolbarLeft = Math.min(
263
292
  Math.max(12, rect.left + (rect.width - maxToolbarWidth) / 2),
264
293
  Math.max(12, window.innerWidth - maxToolbarWidth - 12)
265
294
  );
266
- tableUi.toolbarOpen = state.showToolbar;
267
- tableUi.overlayOpen = true;
295
+ tableUi.toolbarOpen = state.showToolbar && !mobile.value;
296
+ tableUi.overlayOpen = !mobile.value;
268
297
  tableUi.alignment = state.cellAlignment;
269
298
  tableUi.background = state.cellBackground;
270
299
  tableUi.capabilities = state.capabilities;
@@ -282,20 +311,31 @@ var LoomaEditor = defineComponent2({
282
311
  height: `${rect.height}px`
283
312
  };
284
313
  };
314
+ const onEditorFocus = () => {
315
+ editorFocused.value = true;
316
+ updateTableUi();
317
+ updateMobileViewport();
318
+ };
319
+ const onEditorBlur = () => {
320
+ updateTableUi();
321
+ setTimeout(() => {
322
+ if (!tableInteractionActive && !editor.value?.isFocused) editorFocused.value = false;
323
+ }, 0);
324
+ };
285
325
  const bindEditorUi = (instance) => {
286
326
  if (!instance) return;
287
327
  instance.on("selectionUpdate", updateTableUi);
288
328
  instance.on("transaction", updateTableUi);
289
- instance.on("focus", updateTableUi);
290
- instance.on("blur", updateTableUi);
329
+ instance.on("focus", onEditorFocus);
330
+ instance.on("blur", onEditorBlur);
291
331
  nextTick(updateTableUi);
292
332
  };
293
333
  const unbindEditorUi = (instance) => {
294
334
  if (!instance) return;
295
335
  instance.off("selectionUpdate", updateTableUi);
296
336
  instance.off("transaction", updateTableUi);
297
- instance.off("focus", updateTableUi);
298
- instance.off("blur", updateTableUi);
337
+ instance.off("focus", onEditorFocus);
338
+ instance.off("blur", onEditorBlur);
299
339
  };
300
340
  watch(editor, (instance, previous) => {
301
341
  unbindEditorUi(previous);
@@ -305,16 +345,29 @@ var LoomaEditor = defineComponent2({
305
345
  const anchor = tablePickerAnchor.value;
306
346
  if (!anchor) return;
307
347
  const rect = anchor.getBoundingClientRect();
348
+ const viewport = window.visualViewport;
349
+ const viewportLeft = viewport?.offsetLeft ?? 0;
350
+ const viewportTop = viewport?.offsetTop ?? 0;
351
+ const viewportWidth = viewport?.width ?? window.innerWidth;
352
+ const viewportHeight = viewport?.height ?? window.innerHeight;
308
353
  const width = 220;
309
- const left = Math.min(Math.max(12, rect.left), Math.max(12, window.innerWidth - width - 12));
354
+ const left = Math.min(
355
+ Math.max(viewportLeft + 12, rect.left),
356
+ Math.max(viewportLeft + 12, viewportLeft + viewportWidth - width - 12)
357
+ );
310
358
  const popoverHeight = tablePickerPopover.value?.getBoundingClientRect().height || 300;
311
359
  const top = Math.min(
312
- Math.max(12, rect.bottom + 8),
313
- Math.max(12, window.innerHeight - popoverHeight - 12)
360
+ Math.max(viewportTop + 12, rect.bottom + 8),
361
+ Math.max(viewportTop + 12, viewportTop + viewportHeight - popoverHeight - 12)
314
362
  );
315
- tablePickerStyle.value = window.innerWidth <= 767 ? { position: "fixed", left: `${left}px`, bottom: `${Math.max(12, window.innerHeight - rect.top + 8)}px` } : { position: "fixed", top: `${top}px`, left: `${left}px` };
363
+ tablePickerStyle.value = window.innerWidth <= 767 ? {
364
+ position: "fixed",
365
+ left: `${left}px`,
366
+ top: `${Math.max(viewportTop + 12, viewportTop + viewportHeight - popoverHeight - 64)}px`
367
+ } : { position: "fixed", top: `${top}px`, left: `${left}px` };
316
368
  };
317
369
  const onViewportChange = () => {
370
+ updateMobileViewport();
318
371
  updateTableUi();
319
372
  updateTablePickerPosition();
320
373
  tableUi.menuOpen = false;
@@ -324,7 +377,7 @@ var LoomaEditor = defineComponent2({
324
377
  const inElement = (element) => Boolean(
325
378
  element && (path.includes(element) || event.target instanceof Node && element.contains(event.target))
326
379
  );
327
- const inTableUi = inElement(tableToolbarShell.value) || inElement(tableOverlayShell.value) || inElement(tableMenuShell.value);
380
+ const inTableUi = inElement(tableToolbarShell.value) || inElement(tableOverlayShell.value) || inElement(tableMenuShell.value) || inElement(mobileToolbarShell.value);
328
381
  tableInteractionActive = inTableUi;
329
382
  if (inTableUi) setTimeout(() => {
330
383
  tableInteractionActive = false;
@@ -350,8 +403,11 @@ var LoomaEditor = defineComponent2({
350
403
  });
351
404
  };
352
405
  onMounted(() => {
406
+ updateMobileViewport();
353
407
  window.addEventListener("resize", onViewportChange);
354
408
  window.addEventListener("scroll", onViewportChange, true);
409
+ window.visualViewport?.addEventListener("resize", onViewportChange);
410
+ window.visualViewport?.addEventListener("scroll", onViewportChange);
355
411
  document.addEventListener("pointerdown", onDocumentPointerDown, true);
356
412
  document.addEventListener("pointerdown", onResizePointerDown, true);
357
413
  document.addEventListener("pointerup", onResizePointerUp, true);
@@ -359,6 +415,8 @@ var LoomaEditor = defineComponent2({
359
415
  onBeforeUnmount(() => {
360
416
  window.removeEventListener("resize", onViewportChange);
361
417
  window.removeEventListener("scroll", onViewportChange, true);
418
+ window.visualViewport?.removeEventListener("resize", onViewportChange);
419
+ window.visualViewport?.removeEventListener("scroll", onViewportChange);
362
420
  document.removeEventListener("pointerdown", onDocumentPointerDown, true);
363
421
  document.removeEventListener("pointerdown", onResizePointerDown, true);
364
422
  document.removeEventListener("pointerup", onResizePointerUp, true);
@@ -495,7 +553,7 @@ var LoomaEditor = defineComponent2({
495
553
  },
496
554
  onDrop
497
555
  }, [
498
- instance && props.editable ? h2(BubbleMenu, {
556
+ instance && props.editable && !mobile.value ? h2(BubbleMenu, {
499
557
  editor: instance,
500
558
  pluginKey: "looma-text-formatting-menu",
501
559
  shouldShow: ({ editor: menuEditor, from, to }) => shouldShowTextFormattingToolbar(menuEditor, from, to),
@@ -507,6 +565,27 @@ var LoomaEditor = defineComponent2({
507
565
  }
508
566
  }, { default: () => renderToolbar(instance) }) : null,
509
567
  instance ? h2(EditorContent, { editor: instance }) : null,
568
+ instance && props.editable && mobile.value && editorFocused.value ? h2("div", {
569
+ ref: mobileToolbarShell,
570
+ class: "looma-editor__mobile-toolbar-shell",
571
+ "data-mode": mobileToolbarMode.value,
572
+ style: mobileToolbarStyle.value,
573
+ role: "toolbar",
574
+ "aria-label": mobileToolbarMode.value === "table" ? "Table editing" : "Text formatting"
575
+ }, mobileToolbarMode.value === "table" ? [
576
+ h2("button", {
577
+ class: "looma-editor__mobile-toolbar-back",
578
+ type: "button",
579
+ "aria-label": "Formatting tools",
580
+ onClick: () => {
581
+ mobileTableControlsDismissed = true;
582
+ mobileToolbarMode.value = "formatting";
583
+ editor.value?.commands.focus();
584
+ nextTick(updateMobileViewport);
585
+ }
586
+ }, "\u2190 Formatting"),
587
+ h2(EditorTableToolbar, tableProps)
588
+ ] : [renderToolbar(instance)]) : null,
510
589
  h2("input", {
511
590
  ref: fileInput,
512
591
  class: "looma-editor__file-input",
@@ -1 +0,0 @@
1
- import{r as i,g as a,h as o,H as e}from"./p-CEeiinfk.js";import{o as r,c as t,r as s}from"./p-CR7f2MQC.js";import{d as n}from"./p-JwSoedEO.js";const d=class{constructor(a){i(this,a)}get host(){return a(this)}open=!1;defaultOpen=!1;modal=!0;dismissible=!0;internalOpen=!1;overlayId=`ui-dialog-${Math.random().toString(36).slice(2,11)}`;dialogRef;syncFromProp(){this.internalOpen=this.open}syncOpen(){this.dialogRef&&(this.internalOpen?(this.dialogRef.showModal(),r({id:this.overlayId,modal:this.modal,element:this.host,dismissible:this.dismissible,requestClose:(i,a)=>this.handleRequestClose(i,a)})):(this.dialogRef.close(),t(this.overlayId)))}componentDidLoad(){this.syncFromProp(),this.internalOpen=this.internalOpen||this.defaultOpen,this.dialogRef?.addEventListener("close",this.onDialogClose),this.syncOpen()}disconnectedCallback(){this.dialogRef?.removeEventListener("close",this.onDialogClose),t(this.overlayId)}componentDidUpdate(){this.syncOpen()}handleRequestClose(i,a){this.internalOpen=!1,n(this.host,"close",{open:!1,reason:i,trigger:a})}onDialogClose=()=>{this.internalOpen&&(this.internalOpen=!1,t(this.overlayId),n(this.host,"close",{open:!1,reason:"programmatic",trigger:"programmatic"}))};onKeydown=i=>{"Escape"===i.key&&s("escape","keyboard")};render(){return o(e,{key:"2a2fcdfa1e3fac5eb3c0e3d6748cebdf388c216d","data-open":this.internalOpen?"":void 0,onKeyDown:this.onKeydown},o("dialog",{key:"c3eef2bb3bec77fa518269fce38c19c2ededda49",ref:i=>this.dialogRef=i,open:this.internalOpen},o("slot",{key:"9ae5c30d57096184ec287fd9dd134ff566b9fd39"})))}static get watchers(){return{open:[{syncFromProp:0}],internalOpen:[{syncOpen:0}]}}};d.style=":host{display:block}:host:not([data-open]){display:none}:host dialog{--ui-dialog-duration:var(--ui-motion-base);--ui-dialog-viewport-gap:var(--ui-space-4, 1rem);position:fixed;inset:0;inline-size:min( calc(100% - (var(--ui-dialog-viewport-gap) * 2)), var(--ui-dialog-max-width, 440px) );max-inline-size:none;max-block-size:calc(100dvh - (var(--ui-dialog-viewport-gap) * 2));margin:auto;padding:var(--ui-space-4);overflow:auto;background:var(--ui-surface-elevated);border:1px solid var(--ui-border-default);border-radius:var(--ui-radius-dialog);box-shadow:var(--ui-shadow-dialog);visibility:hidden;pointer-events:none;opacity:0;transform:scale(0.96);transition:opacity var(--ui-dialog-duration) var(--ui-motion-ease), transform var(--ui-dialog-duration) var(--ui-motion-ease), visibility var(--ui-dialog-duration), display var(--ui-dialog-duration) var(--ui-motion-ease) allow-discrete, overlay var(--ui-dialog-duration) var(--ui-motion-ease) allow-discrete}:host dialog[open]{visibility:visible;pointer-events:auto;opacity:1;transform:scale(1);animation:ui-dialog-enter var(--ui-dialog-duration) var(--ui-motion-ease)}@keyframes ui-dialog-enter{from{opacity:0;transform:scale(0.96)}}:host dialog::backdrop{background-color:transparent;transition:background-color var(--ui-dialog-duration) var(--ui-motion-ease), display var(--ui-dialog-duration) var(--ui-motion-ease) allow-discrete, overlay var(--ui-dialog-duration) var(--ui-motion-ease) allow-discrete}:host dialog[open]::backdrop{background-color:var(--ui-overlay-backdrop);animation:ui-dialog-backdrop-enter var(--ui-dialog-duration) var(--ui-motion-ease)}@keyframes ui-dialog-backdrop-enter{from{background-color:transparent}}";export{d as ui_dialog}