@threadlabs/looma 0.1.11 → 0.1.12

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 (56) hide show
  1. package/dist/{chunk-DYIMEQY7.js → chunk-DQZJTDIB.js} +27 -27
  2. package/dist/cjs/ui-affordance-scope.cjs.entry.js +5 -4
  3. package/dist/collection/components/ui-affordance-scope/ui-affordance-scope.js +4 -4
  4. package/dist/collection/icons.js +66 -0
  5. package/dist/collection/overlay/positioning.js +3 -2
  6. package/dist/components/ui-affordance-scope.js +1 -1
  7. package/dist/esm/ui-affordance-scope.entry.js +5 -4
  8. package/dist/index.cjs +79 -7
  9. package/dist/index.d.cts +52 -1
  10. package/dist/index.d.ts +52 -1
  11. package/dist/index.js +112 -3
  12. package/dist/looma/looma.esm.js +1 -1
  13. package/dist/looma/p-3ac2e0d4.entry.js +1 -0
  14. package/dist/types/components.d.ts +2 -2
  15. package/dist/types/icons.d.ts +48 -0
  16. package/dist/types/overlay/positioning.d.ts +1 -0
  17. package/dist/{ui-affordance-scope.entry-ZKUJ5AT4.js → ui-affordance-scope.entry-SWTDTGGU.js} +6 -5
  18. package/dist/{ui-avatar-group.entry-I4XM44BI.js → ui-avatar-group.entry-VUYE2XOM.js} +1 -1
  19. package/dist/{ui-avatar.entry-ZZAMZAVF.js → ui-avatar.entry-2CKHEJTS.js} +1 -1
  20. package/dist/{ui-badge.entry-DQXYMC3E.js → ui-badge.entry-4SWSD3R5.js} +1 -1
  21. package/dist/{ui-button.entry-DM7BUZLI.js → ui-button.entry-SS3AS32R.js} +1 -1
  22. package/dist/{ui-checkbox.entry-X3PPWKIJ.js → ui-checkbox.entry-V7OYTOLW.js} +1 -1
  23. package/dist/{ui-context-menu.entry-KAW4NIFE.js → ui-context-menu.entry-UCLTQESP.js} +1 -1
  24. package/dist/{ui-dialog.entry-D23SNXWB.js → ui-dialog.entry-PXIVZF7D.js} +1 -1
  25. package/dist/{ui-disclosure.entry-DOG6JZU7.js → ui-disclosure.entry-ZADBPM2D.js} +1 -1
  26. package/dist/{ui-floating-action-button.entry-VPQ7VBFS.js → ui-floating-action-button.entry-WNBWY36T.js} +1 -1
  27. package/dist/{ui-form-field.entry-SYZ6XSCG.js → ui-form-field.entry-RZPSWN6Y.js} +1 -1
  28. package/dist/{ui-icon-button.entry-2SZBOIH5.js → ui-icon-button.entry-ILU7RD7M.js} +1 -1
  29. package/dist/{ui-input.entry-PALICYLZ.js → ui-input.entry-FEIUK4EE.js} +1 -1
  30. package/dist/{ui-menu-item.entry-W6TEFP5Y.js → ui-menu-item.entry-UJVECPSK.js} +1 -1
  31. package/dist/{ui-menu.entry-7NARDV6S.js → ui-menu.entry-MTCE3F5U.js} +1 -1
  32. package/dist/{ui-popover.entry-ZXYHLDTP.js → ui-popover.entry-OAME35VB.js} +1 -1
  33. package/dist/{ui-radio-group.entry-XEUKMD6J.js → ui-radio-group.entry-CPFX4LVA.js} +1 -1
  34. package/dist/{ui-radio.entry-4ABBHDLN.js → ui-radio.entry-44OTRYPB.js} +1 -1
  35. package/dist/{ui-search-result-row.entry-3HHM7OV4.js → ui-search-result-row.entry-ZU5SL5OP.js} +1 -1
  36. package/dist/{ui-search-shell.entry-PJTFOBPT.js → ui-search-shell.entry-G7HG4RKU.js} +1 -1
  37. package/dist/{ui-select.entry-A3RI5XCG.js → ui-select.entry-NAONXMFG.js} +1 -1
  38. package/dist/{ui-switch.entry-JNRS2YTN.js → ui-switch.entry-SE4ZTCS2.js} +1 -1
  39. package/dist/{ui-tabs.entry-MQ4V5XCP.js → ui-tabs.entry-2YG2JE3K.js} +1 -1
  40. package/dist/{ui-textarea.entry-JJXJQZQR.js → ui-textarea.entry-PV3APDLY.js} +1 -1
  41. package/dist/{ui-toast-region.entry-STHVESL5.js → ui-toast-region.entry-WH2OL3FR.js} +1 -1
  42. package/dist/{ui-tooltip.entry-4W7CRIKI.js → ui-tooltip.entry-FY563DP4.js} +1 -1
  43. package/dist/{ui-top-bar.entry-WM3SS2HR.js → ui-top-bar.entry-LJSZXFAH.js} +1 -1
  44. package/editor/{chunk-F4AYF33M.js → chunk-OHD4OS32.js} +11 -11
  45. package/editor/{chunk-4VGVEHU2.js → chunk-RTHHTPWK.js} +110 -69
  46. package/editor/extensions/index.d.ts +4 -3
  47. package/editor/extensions/index.js +1 -1
  48. package/editor/index.d.ts +2 -1
  49. package/editor/index.js +2 -2
  50. package/editor/{table-overlay-jjvdARTJ.d.ts → table-overlay-DoiLie4h.d.ts} +2 -1
  51. package/editor/ui.d.ts +4 -2
  52. package/editor/ui.js +1 -1
  53. package/editor.css +107 -60
  54. package/package.json +2 -1
  55. package/vue/editor/index.js +88 -36
  56. package/dist/looma/p-95340a13.entry.js +0 -1
@@ -6010,7 +6010,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6010
6010
  {
6011
6011
  title: "Text",
6012
6012
  description: "Plain paragraph",
6013
- icon: "\xB6",
6013
+ icon: "pilcrow",
6014
6014
  keywords: ["text", "paragraph", "plain", "p"],
6015
6015
  command: ({ editor, range }) => {
6016
6016
  editor.chain().focus().deleteRange(range).setParagraph().run();
@@ -6019,7 +6019,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6019
6019
  ...[1, 2, 3].map((level) => ({
6020
6020
  title: `Heading ${level}`,
6021
6021
  description: level === 1 ? "Big section title" : level === 2 ? "Medium section title" : "Small section title",
6022
- icon: `H${level}`,
6022
+ icon: `heading-${level}`,
6023
6023
  keywords: [`h${level}`, "heading", "title"],
6024
6024
  command: ({ editor, range }) => {
6025
6025
  editor.chain().focus().deleteRange(range).setHeading({ level }).run();
@@ -6028,7 +6028,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6028
6028
  {
6029
6029
  title: "Bullet list",
6030
6030
  description: "Unordered list",
6031
- icon: "\u2022",
6031
+ icon: "list",
6032
6032
  keywords: ["bullet", "list", "ul", "unordered"],
6033
6033
  command: ({ editor, range }) => {
6034
6034
  editor.chain().focus().deleteRange(range).toggleBulletList().run();
@@ -6037,7 +6037,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6037
6037
  {
6038
6038
  title: "Numbered list",
6039
6039
  description: "Ordered list",
6040
- icon: "1.",
6040
+ icon: "list-ordered",
6041
6041
  keywords: ["numbered", "ordered", "list", "ol"],
6042
6042
  command: ({ editor, range }) => {
6043
6043
  editor.chain().focus().deleteRange(range).toggleOrderedList().run();
@@ -6046,7 +6046,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6046
6046
  {
6047
6047
  title: "Checklist",
6048
6048
  description: "Interactive to-do items",
6049
- icon: "\u2611",
6049
+ icon: "list-todo",
6050
6050
  keywords: ["check", "task", "todo", "checklist"],
6051
6051
  command: ({ editor, range }) => {
6052
6052
  editor.chain().focus().deleteRange(range).toggleTaskList().run();
@@ -6055,7 +6055,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6055
6055
  {
6056
6056
  title: "Blockquote",
6057
6057
  description: "Highlighted quote",
6058
- icon: '"',
6058
+ icon: "quote",
6059
6059
  keywords: ["quote", "blockquote", "callout"],
6060
6060
  command: ({ editor, range }) => {
6061
6061
  editor.chain().focus().deleteRange(range).toggleBlockquote().run();
@@ -6064,7 +6064,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6064
6064
  {
6065
6065
  title: "Inline code",
6066
6066
  description: "Monospace code span",
6067
- icon: "`",
6067
+ icon: "code-xml",
6068
6068
  keywords: ["code", "inline", "monospace"],
6069
6069
  command: ({ editor, range }) => {
6070
6070
  editor.chain().focus().deleteRange(range).toggleCode().run();
@@ -6073,7 +6073,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6073
6073
  {
6074
6074
  title: "Code block",
6075
6075
  description: "Formatted code block",
6076
- icon: "<>",
6076
+ icon: "braces",
6077
6077
  keywords: ["codeblock", "pre", "syntax", "snippet"],
6078
6078
  command: ({ editor, range }) => {
6079
6079
  editor.chain().focus().deleteRange(range).toggleCodeBlock().run();
@@ -6082,7 +6082,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6082
6082
  {
6083
6083
  title: "Table",
6084
6084
  description: "Insert a table",
6085
- icon: "\u229E",
6085
+ icon: "table",
6086
6086
  keywords: ["table", "grid", "rows", "columns"],
6087
6087
  command: ({ editor, range }) => {
6088
6088
  insertTableAtRange(editor, range);
@@ -6091,7 +6091,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6091
6091
  {
6092
6092
  title: "Divider",
6093
6093
  description: "Horizontal rule",
6094
- icon: "\u2014",
6094
+ icon: "minus",
6095
6095
  keywords: ["divider", "hr", "rule", "line"],
6096
6096
  command: ({ editor, range }) => {
6097
6097
  editor.chain().focus().deleteRange(range).setHorizontalRule().run();
@@ -6100,7 +6100,7 @@ function getDefaultSlashCommands(onOpenImagePicker) {
6100
6100
  {
6101
6101
  title: "Image",
6102
6102
  description: "Upload an image",
6103
- icon: "\u25A7",
6103
+ icon: "image",
6104
6104
  keywords: ["image", "photo", "picture", "upload"],
6105
6105
  command: ({ editor, range }) => {
6106
6106
  editor.chain().focus().deleteRange(range).run();
@@ -3,7 +3,11 @@ import {
3
3
  } from "./chunk-CX4QDKSV.js";
4
4
 
5
5
  // src/table-context-menu.ts
6
- import { clampRectToViewport, getVisualViewportRect } from "@threadlabs/looma/core";
6
+ import {
7
+ clampRectToViewport,
8
+ getVisualViewportRect,
9
+ loomaIconMarkup
10
+ } from "@threadlabs/looma/core";
7
11
  var TAG = "ui-editor-table-context-menu";
8
12
  function dispatchTableAction(element, action) {
9
13
  element.dispatchEvent(
@@ -96,26 +100,26 @@ if (typeof HTMLElement !== "undefined") {
96
100
  {
97
101
  heading: "Structure",
98
102
  actions: [
99
- { action: "add-row-before", label: "Add row above", can: "can-add-row-before" },
100
- { action: "add-row-after", label: "Add row below", can: "can-add-row-after" },
101
- { action: "add-column-before", label: "Add column left", can: "can-add-column-before" },
102
- { action: "add-column-after", label: "Add column right", can: "can-add-column-after" }
103
+ { action: "add-row-before", label: "Add row above", icon: "panel-top", can: "can-add-row-before" },
104
+ { action: "add-row-after", label: "Add row below", icon: "panel-bottom", can: "can-add-row-after" },
105
+ { action: "add-column-before", label: "Add column left", icon: "panel-left", can: "can-add-column-before" },
106
+ { action: "add-column-after", label: "Add column right", icon: "panel-right", can: "can-add-column-after" }
103
107
  ]
104
108
  },
105
109
  {
106
110
  heading: "Cells",
107
111
  actions: [
108
- { action: "clear-cells", label: "Clear selected cells" },
109
- { action: "merge-cells", label: "Merge cells", can: "can-merge-cells" },
110
- { action: "split-cell", label: "Split cell", can: "can-split-cell" }
112
+ { action: "clear-cells", label: "Clear selected cells", icon: "eraser" },
113
+ { action: "merge-cells", label: "Merge cells", icon: "merge", can: "can-merge-cells" },
114
+ { action: "split-cell", label: "Split cell", icon: "split", can: "can-split-cell" }
111
115
  ]
112
116
  },
113
117
  {
114
118
  heading: "Table",
115
119
  actions: [
116
- { action: "delete-row", label: "Delete row", can: "can-delete-row", tone: "danger" },
117
- { action: "delete-column", label: "Delete column", can: "can-delete-column", tone: "danger" },
118
- { action: "delete-table", label: "Delete table", can: "can-delete-table", tone: "danger" }
120
+ { action: "delete-row", label: "Delete row", icon: "trash", can: "can-delete-row", tone: "danger" },
121
+ { action: "delete-column", label: "Delete column", icon: "trash", can: "can-delete-column", tone: "danger" },
122
+ { action: "delete-table", label: "Delete table", icon: "trash", can: "can-delete-table", tone: "danger" }
119
123
  ]
120
124
  }
121
125
  ];
@@ -145,7 +149,7 @@ if (typeof HTMLElement !== "undefined") {
145
149
  } else {
146
150
  section.actions.forEach((action) => {
147
151
  const tone = "tone" in action ? action.tone : void 0;
148
- html += `<button type="button" role="menuitem" data-action="${action.action}"${tone ? ` data-tone="${tone}"` : ""}>${action.label}</button>`;
152
+ html += `<button type="button" role="menuitem" data-action="${action.action}"${tone ? ` data-tone="${tone}"` : ""}>${loomaIconMarkup(action.icon)}<span>${action.label}</span></button>`;
149
153
  });
150
154
  }
151
155
  html += "</div>";
@@ -161,6 +165,7 @@ if (typeof HTMLElement !== "undefined") {
161
165
  }
162
166
 
163
167
  // src/table-toolbar.ts
168
+ import { loomaIconMarkup as loomaIconMarkup2 } from "@threadlabs/looma/core";
164
169
  var TAG2 = "ui-editor-table-toolbar";
165
170
  function dispatchTableAction2(element, action) {
166
171
  element.dispatchEvent(
@@ -257,36 +262,36 @@ if (typeof HTMLElement !== "undefined") {
257
262
  const activeAlignment = this.getAlignmentAttr();
258
263
  const currentBackground = this.getAttribute("cell-background");
259
264
  const alignmentActions = [
260
- { action: "align-left", label: "Left" },
261
- { action: "align-center", label: "Center" },
262
- { action: "align-right", label: "Right" }
265
+ { action: "align-left", label: "Align left", icon: "align-left" },
266
+ { action: "align-center", label: "Align center", icon: "align-center" },
267
+ { action: "align-right", label: "Align right", icon: "align-right" }
263
268
  ];
264
269
  const structuralActions = [
265
- { action: "add-row-after", label: "Add row", can: "can-add-row-after" },
266
- { action: "add-column-after", label: "Add column", can: "can-add-column-after" }
270
+ { action: "add-row-after", label: "Add row", icon: "rows", can: "can-add-row-after" },
271
+ { action: "add-column-after", label: "Add column", icon: "columns", can: "can-add-column-after" }
267
272
  ].filter((action) => this.getBoolAttr(action.can));
268
273
  const overflowSections = [
269
274
  {
270
275
  heading: "Structure",
271
276
  actions: [
272
- { action: "add-row-before", label: "Add row above", can: "can-add-row-before" },
273
- { action: "add-column-before", label: "Add column left", can: "can-add-column-before" }
277
+ { action: "add-row-before", label: "Add row above", icon: "panel-top", can: "can-add-row-before" },
278
+ { action: "add-column-before", label: "Add column left", icon: "panel-left", can: "can-add-column-before" }
274
279
  ]
275
280
  },
276
281
  {
277
282
  heading: "Cells",
278
283
  actions: [
279
- { action: "clear-cells", label: "Clear selected cells" },
280
- { action: "merge-cells", label: "Merge selected cells", can: "can-merge-cells" },
281
- { action: "split-cell", label: "Split merged cell", can: "can-split-cell" }
284
+ { action: "clear-cells", label: "Clear selected cells", icon: "eraser" },
285
+ { action: "merge-cells", label: "Merge selected cells", icon: "merge", can: "can-merge-cells" },
286
+ { action: "split-cell", label: "Split merged cell", icon: "split", can: "can-split-cell" }
282
287
  ]
283
288
  },
284
289
  {
285
290
  heading: "Table",
286
291
  actions: [
287
- { action: "delete-row", label: "Delete row", can: "can-delete-row", tone: "danger" },
288
- { action: "delete-column", label: "Delete column", can: "can-delete-column", tone: "danger" },
289
- { action: "delete-table", label: "Delete table", can: "can-delete-table", tone: "danger" }
292
+ { action: "delete-row", label: "Delete row", icon: "trash", can: "can-delete-row", tone: "danger" },
293
+ { action: "delete-column", label: "Delete column", icon: "trash", can: "can-delete-column", tone: "danger" },
294
+ { action: "delete-table", label: "Delete table", icon: "trash", can: "can-delete-table", tone: "danger" }
290
295
  ]
291
296
  }
292
297
  ];
@@ -298,18 +303,18 @@ if (typeof HTMLElement !== "undefined") {
298
303
  '<div class="ui-editor-table-toolbar" role="toolbar" aria-label="Table actions">',
299
304
  '<div class="ui-editor-table-toolbar__group" role="group" aria-label="Cell alignment">',
300
305
  alignmentActions.map(
301
- (action) => `<button type="button" data-action="${action.action}" aria-pressed="${action.action === activeAlignment ? "true" : "false"}" data-active="${action.action === activeAlignment ? "true" : "false"}">${action.label}</button>`
306
+ (action) => `<button type="button" class="ui-editor-table-toolbar__icon-button" data-action="${action.action}" aria-label="${action.label}" title="${action.label}" aria-pressed="${action.action === activeAlignment ? "true" : "false"}" data-active="${action.action === activeAlignment ? "true" : "false"}">${loomaIconMarkup2(action.icon)}</button>`
302
307
  ).join(""),
303
308
  "</div>",
304
309
  structuralActions.length > 0 ? '<div class="ui-editor-table-toolbar__sep" aria-hidden="true"></div>' : "",
305
310
  structuralActions.length > 0 ? '<div class="ui-editor-table-toolbar__group" role="group" aria-label="Table structure">' : "",
306
311
  structuralActions.map(
307
- (action) => `<button type="button" data-action="${action.action}">${action.label}</button>`
312
+ (action) => `<button type="button" data-action="${action.action}">${loomaIconMarkup2(action.icon)}<span>${action.label}</span></button>`
308
313
  ).join(""),
309
314
  structuralActions.length > 0 ? "</div>" : "",
310
315
  '<div class="ui-editor-table-toolbar__sep" aria-hidden="true"></div>',
311
316
  '<div class="ui-editor-table-toolbar__overflow">',
312
- `<button type="button" class="ui-editor-table-toolbar__more" data-action="toggle-overflow" aria-haspopup="menu" aria-expanded="${this.#overflowOpen ? "true" : "false"}">Table options</button>`,
317
+ `<button type="button" class="ui-editor-table-toolbar__more" data-action="toggle-overflow" aria-haspopup="menu" aria-expanded="${this.#overflowOpen ? "true" : "false"}">${loomaIconMarkup2("table")}<span>Table options</span>${loomaIconMarkup2("chevron-down", "looma-icon looma-icon--chevron")}</button>`,
313
318
  this.#overflowOpen ? [
314
319
  '<div class="ui-editor-table-toolbar__menu" role="menu" aria-label="More table actions">',
315
320
  '<div class="ui-editor-table-toolbar__menu-section" role="none">',
@@ -327,7 +332,7 @@ if (typeof HTMLElement !== "undefined") {
327
332
  `<div class="ui-editor-table-toolbar__menu-heading" role="presentation">${section.heading}</div>`,
328
333
  section.actions.map((action) => {
329
334
  const tone = "tone" in action ? action.tone : void 0;
330
- return `<button type="button" role="menuitem" data-action="${action.action}"${tone ? ` data-tone="${tone}"` : ""}>${action.label}</button>`;
335
+ return `<button type="button" role="menuitem" data-action="${action.action}"${tone ? ` data-tone="${tone}"` : ""}>${loomaIconMarkup2(action.icon)}<span>${action.label}</span></button>`;
331
336
  }).join(""),
332
337
  "</div>"
333
338
  ].join("")
@@ -360,17 +365,19 @@ if (typeof HTMLElement !== "undefined") {
360
365
  #previewRows = null;
361
366
  #previewCols = null;
362
367
  #withHeaderRow = true;
363
- #selectionPinned = false;
368
+ #selectionCommitted = false;
364
369
  connectedCallback() {
365
370
  this.#maxRows = Math.min(10, Math.max(1, parseInt(this.getAttribute("max-rows") ?? String(DEFAULT_MAX_ROWS), 10) || DEFAULT_MAX_ROWS));
366
371
  this.#maxCols = Math.min(10, Math.max(1, parseInt(this.getAttribute("max-cols") ?? String(DEFAULT_MAX_COLS), 10) || DEFAULT_MAX_COLS));
367
372
  this.render();
368
373
  this.addEventListener("click", this.onClick);
369
374
  this.addEventListener("mouseover", this.onMouseOver);
375
+ this.addEventListener("mouseleave", this.onMouseLeave);
370
376
  }
371
377
  disconnectedCallback() {
372
378
  this.removeEventListener("click", this.onClick);
373
379
  this.removeEventListener("mouseover", this.onMouseOver);
380
+ this.removeEventListener("mouseleave", this.onMouseLeave);
374
381
  }
375
382
  attributeChangedCallback(name) {
376
383
  if (name === "max-rows") this.#maxRows = Math.min(10, Math.max(1, parseInt(this.getAttribute("max-rows") ?? String(DEFAULT_MAX_ROWS), 10) || DEFAULT_MAX_ROWS));
@@ -384,7 +391,7 @@ if (typeof HTMLElement !== "undefined") {
384
391
  this.#selectedCols = parseInt(cell.getAttribute("data-col") ?? "1", 10);
385
392
  this.#previewRows = null;
386
393
  this.#previewCols = null;
387
- this.#selectionPinned = true;
394
+ this.#selectionCommitted = true;
388
395
  this.updateSelectionPreview();
389
396
  return;
390
397
  }
@@ -402,27 +409,33 @@ if (typeof HTMLElement !== "undefined") {
402
409
  }
403
410
  }
404
411
  onMouseOver(e) {
405
- if (this.#selectionPinned) {
406
- return;
407
- }
408
412
  const cell = e.target.closest("[data-row][data-col]");
409
- if (cell) {
410
- const nextRows = parseInt(cell.getAttribute("data-row") ?? "1", 10);
411
- const nextCols = parseInt(cell.getAttribute("data-col") ?? "1", 10);
412
- if (nextRows === this.#previewRows && nextCols === this.#previewCols) {
413
- return;
414
- }
415
- this.#previewRows = nextRows;
416
- this.#previewCols = nextCols;
417
- this.updateSelectionPreview();
413
+ if (!cell) {
414
+ this.#clearPreview();
415
+ return;
418
416
  }
417
+ const nextRows = parseInt(cell.getAttribute("data-row") ?? "1", 10);
418
+ const nextCols = parseInt(cell.getAttribute("data-col") ?? "1", 10);
419
+ if (nextRows === this.#previewRows && nextCols === this.#previewCols) return;
420
+ this.#previewRows = nextRows;
421
+ this.#previewCols = nextCols;
422
+ this.updateSelectionPreview();
423
+ }
424
+ onMouseLeave = () => {
425
+ this.#clearPreview();
426
+ };
427
+ #clearPreview() {
428
+ if (this.#previewRows === null && this.#previewCols === null) return;
429
+ this.#previewRows = null;
430
+ this.#previewCols = null;
431
+ this.updateSelectionPreview();
419
432
  }
420
433
  updateSelectionPreview() {
421
434
  const activeRows = this.#previewRows ?? this.#selectedRows;
422
435
  const activeCols = this.#previewCols ?? this.#selectedCols;
423
436
  const hint = this.querySelector(".ui-editor-insert-table-grid__hint");
424
437
  if (hint) {
425
- hint.textContent = this.#selectionPinned ? `${this.#selectedRows} \xD7 ${this.#selectedCols} selected` : `${activeRows} \xD7 ${activeCols}`;
438
+ hint.textContent = this.#previewRows !== null && this.#previewCols !== null ? `${activeRows} \xD7 ${activeCols}` : `${this.#selectedRows} \xD7 ${this.#selectedCols}${this.#selectionCommitted ? " selected" : ""}`;
426
439
  }
427
440
  const cells = this.querySelectorAll("[data-row][data-col]");
428
441
  for (const cell of cells) {
@@ -439,7 +452,7 @@ if (typeof HTMLElement !== "undefined") {
439
452
  if (!open) return;
440
453
  let html = '<div class="ui-editor-insert-table-grid">';
441
454
  html += `<p class="ui-editor-insert-table-grid__hint">${this.#selectedRows} \xD7 ${this.#selectedCols}</p>`;
442
- html += '<div class="ui-editor-insert-table-grid__grid" role="group" aria-label="Table dimensions">';
455
+ html += `<div class="ui-editor-insert-table-grid__grid" role="group" aria-label="Table dimensions" style="--ui-editor-table-grid-rows:${this.#maxRows};--ui-editor-table-grid-cols:${this.#maxCols}">`;
443
456
  for (let r = 1; r <= this.#maxRows; r++) {
444
457
  for (let c = 1; c <= this.#maxCols; c++) {
445
458
  const selected = r <= this.#selectedRows && c <= this.#selectedCols;
@@ -468,7 +481,8 @@ if (typeof HTMLElement !== "undefined") {
468
481
 
469
482
  // src/table-overlay.ts
470
483
  import {
471
- createProximityCoordinator
484
+ createProximityCoordinator,
485
+ loomaIconMarkup as loomaIconMarkup3
472
486
  } from "@threadlabs/looma/core";
473
487
  var TAG4 = "ui-editor-table-overlay";
474
488
  var DEFAULT_ROWS = 3;
@@ -484,7 +498,7 @@ function sameActiveCell(left, right) {
484
498
  function sameGeometry(left, right) {
485
499
  if (left === right) return true;
486
500
  if (!left || !right) return false;
487
- return sameNumbers(left.rowBoundaries, right.rowBoundaries) && sameNumbers(left.columnBoundaries, right.columnBoundaries) && sameActiveCell(left.activeCell, right.activeCell);
501
+ return sameNumbers(left.rowBoundaries, right.rowBoundaries) && sameNumbers(left.columnBoundaries, right.columnBoundaries) && sameActiveCell(left.activeCell, right.activeCell) && sameActiveCell(left.hoveredCell ?? null, right.hoveredCell ?? null);
488
502
  }
489
503
  function mapTableCells(table) {
490
504
  const rows = Array.from(table.rows);
@@ -515,7 +529,7 @@ function resolveTableCellAt(table, rowIndex, columnIndex) {
515
529
  function uniqueSorted(values) {
516
530
  return values.sort((left, right) => left - right).filter((value, index, all) => index === 0 || Math.abs(value - (all[index - 1] ?? value)) >= 0.5).map((value) => Math.round(value * 100) / 100);
517
531
  }
518
- function measureTableOverlayGeometry(table, activeCell) {
532
+ function measureTableOverlayGeometry(table, activeCell, hoveredCell = null) {
519
533
  const tableRect = table.getBoundingClientRect();
520
534
  const rows = Array.from(table.rows);
521
535
  const cells = rows.flatMap((row) => Array.from(row.cells));
@@ -529,21 +543,32 @@ function measureTableOverlayGeometry(table, activeCell) {
529
543
  return [rect.left - tableRect.left, rect.right - tableRect.left];
530
544
  }));
531
545
  if (!activeCell || !table.contains(activeCell)) {
532
- return { rowBoundaries, columnBoundaries, activeCell: null };
546
+ return {
547
+ rowBoundaries,
548
+ columnBoundaries,
549
+ activeCell: null,
550
+ hoveredCell: measureCellRect(table, hoveredCell, coordinates)
551
+ };
533
552
  }
534
- const cellRect = activeCell.getBoundingClientRect();
535
- const coordinate = coordinates.get(activeCell);
536
553
  return {
537
554
  rowBoundaries,
538
555
  columnBoundaries,
539
- activeCell: {
540
- left: Math.round((cellRect.left - tableRect.left) * 100) / 100,
541
- top: Math.round((cellRect.top - tableRect.top) * 100) / 100,
542
- width: Math.round(cellRect.width * 100) / 100,
543
- height: Math.round(cellRect.height * 100) / 100,
544
- rowIndex: coordinate?.rowIndex ?? 0,
545
- columnIndex: coordinate?.columnIndex ?? 0
546
- }
556
+ activeCell: measureCellRect(table, activeCell, coordinates),
557
+ hoveredCell: measureCellRect(table, hoveredCell, coordinates)
558
+ };
559
+ }
560
+ function measureCellRect(table, cell, coordinates) {
561
+ if (!cell || !table.contains(cell)) return null;
562
+ const tableRect = table.getBoundingClientRect();
563
+ const cellRect = cell.getBoundingClientRect();
564
+ const coordinate = coordinates.get(cell);
565
+ return {
566
+ left: Math.round((cellRect.left - tableRect.left) * 100) / 100,
567
+ top: Math.round((cellRect.top - tableRect.top) * 100) / 100,
568
+ width: Math.round(cellRect.width * 100) / 100,
569
+ height: Math.round(cellRect.height * 100) / 100,
570
+ rowIndex: coordinate?.rowIndex ?? 0,
571
+ columnIndex: coordinate?.columnIndex ?? 0
547
572
  };
548
573
  }
549
574
  function finiteNumbers(value) {
@@ -557,7 +582,7 @@ function fallbackBoundaries(segments, length) {
557
582
  if (typeof HTMLElement !== "undefined") {
558
583
  class UIEditorTableOverlayElement extends HTMLElement {
559
584
  static get observedAttributes() {
560
- return ["open", "rows", "cols", "row-boundaries", "column-boundaries", "active-cell"];
585
+ return ["open", "rows", "cols", "row-boundaries", "column-boundaries", "active-cell", "hovered-cell"];
561
586
  }
562
587
  #rows = DEFAULT_ROWS;
563
588
  #cols = DEFAULT_COLS;
@@ -630,6 +655,14 @@ if (typeof HTMLElement !== "undefined") {
630
655
  if (left === void 0 || top === void 0 || width === void 0 || height === void 0 || rowIndex === void 0 || columnIndex === void 0) return null;
631
656
  return { left, top, width, height, rowIndex, columnIndex };
632
657
  }
658
+ #hoveredCell() {
659
+ if (this.#geometry) return this.#geometry.hoveredCell ?? null;
660
+ const values = finiteNumbers(this.getAttribute("hovered-cell"));
661
+ if (values.length !== 6) return null;
662
+ const [left, top, width, height, rowIndex, columnIndex] = values;
663
+ if (left === void 0 || top === void 0 || width === void 0 || height === void 0 || rowIndex === void 0 || columnIndex === void 0) return null;
664
+ return { left, top, width, height, rowIndex, columnIndex };
665
+ }
633
666
  dispatch(detail) {
634
667
  this.dispatchEvent(new CustomEvent(
635
668
  "looma-editor-table-overlay-action",
@@ -710,22 +743,25 @@ if (typeof HTMLElement !== "undefined") {
710
743
  '<span class="ui-editor-table-overlay__guide" data-ui-guide aria-hidden="true"></span>',
711
744
  `<button type="button" class="ui-editor-table-overlay__handle" data-ui-affordance="insert-${noun}"`,
712
745
  ` data-action="${action}" data-boundary-index="${index}" aria-label="${label}">`,
713
- '<span aria-hidden="true">+</span>',
746
+ loomaIconMarkup3("plus"),
714
747
  `<span class="ui-editor-table-overlay__tooltip" role="tooltip">${label}</span>`,
715
748
  "</button>",
716
749
  "</div>"
717
750
  ].join("");
718
751
  }
719
- #activeCellControls(cell) {
752
+ #cellSelectors(cell) {
720
753
  const centerX = cell.left + cell.width / 2;
721
754
  const centerY = cell.top + cell.height / 2;
722
755
  const indexes = `data-row-index="${cell.rowIndex}" data-column-index="${cell.columnIndex}"`;
723
756
  return [
724
- `<button type="button" class="ui-editor-table-overlay__selector ui-editor-table-overlay__selector--row" style="top:${centerY}px" data-action="select-row" ${indexes} title="Select row" aria-label="Select row"><span aria-hidden="true"></span></button>`,
725
- `<button type="button" class="ui-editor-table-overlay__selector ui-editor-table-overlay__selector--column" style="left:${centerX}px" data-action="select-column" ${indexes} title="Select column" aria-label="Select column"><span aria-hidden="true"></span></button>`,
726
- `<button type="button" class="ui-editor-table-overlay__cell-menu" style="left:${cell.left + cell.width - 30}px;top:${cell.top + 6}px" data-action="open-cell-menu" ${indexes} title="Cell actions" aria-label="Cell actions"><span aria-hidden="true">\u2304</span></button>`
757
+ `<button type="button" class="ui-editor-table-overlay__selector ui-editor-table-overlay__selector--row" style="top:${centerY}px" data-action="select-row" ${indexes} title="Select row" aria-label="Select row">${loomaIconMarkup3("grip-vertical")}</button>`,
758
+ `<button type="button" class="ui-editor-table-overlay__selector ui-editor-table-overlay__selector--column" style="left:${centerX}px" data-action="select-column" ${indexes} title="Select column" aria-label="Select column">${loomaIconMarkup3("grip-horizontal")}</button>`
727
759
  ].join("");
728
760
  }
761
+ #cellMenu(cell) {
762
+ const indexes = `data-row-index="${cell.rowIndex}" data-column-index="${cell.columnIndex}"`;
763
+ return `<button type="button" class="ui-editor-table-overlay__cell-menu" style="left:${cell.left + cell.width - 30}px;top:${cell.top + 6}px" data-action="open-cell-menu" ${indexes} title="Cell actions" aria-label="Cell actions">${loomaIconMarkup3("chevron-down")}</button>`;
764
+ }
729
765
  render() {
730
766
  const open = this.hasAttribute("open") && this.getAttribute("open") !== "false";
731
767
  this.hidden = !open;
@@ -735,7 +771,8 @@ if (typeof HTMLElement !== "undefined") {
735
771
  }
736
772
  const rows = this.#boundaries("row-boundaries", this.#rows);
737
773
  const columns = this.#boundaries("column-boundaries", this.#cols);
738
- const cell = this.#activeCell();
774
+ const activeCell = this.#activeCell();
775
+ const hoveredCell = this.#hoveredCell();
739
776
  this.innerHTML = [
740
777
  '<div class="ui-editor-table-overlay" aria-label="Table controls">',
741
778
  '<div class="ui-editor-table-overlay__rows">',
@@ -744,7 +781,8 @@ if (typeof HTMLElement !== "undefined") {
744
781
  '<div class="ui-editor-table-overlay__cols">',
745
782
  columns.map((position, index) => this.#insertionControl("col", index, position)).join(""),
746
783
  "</div>",
747
- cell ? this.#activeCellControls(cell) : "",
784
+ hoveredCell ? this.#cellSelectors(hoveredCell) : "",
785
+ activeCell ? this.#cellMenu(activeCell) : "",
748
786
  "</div>"
749
787
  ].join("");
750
788
  this.#syncActiveControl();
@@ -757,7 +795,10 @@ if (typeof HTMLElement !== "undefined") {
757
795
  }
758
796
 
759
797
  // src/slash-menu.ts
760
- import { getVisualViewportRect as getVisualViewportRect2 } from "@threadlabs/looma/core";
798
+ import {
799
+ getVisualViewportRect as getVisualViewportRect2,
800
+ loomaIconMarkup as loomaIconMarkup4
801
+ } from "@threadlabs/looma/core";
761
802
  var TAG5 = "ui-editor-slash-menu";
762
803
  var MOBILE_BREAKPOINT = 768;
763
804
  var MENU_HEIGHT_ESTIMATE = 320;
@@ -965,7 +1006,7 @@ if (typeof HTMLElement !== "undefined") {
965
1006
  ` aria-selected="${index === this.#selectedIndex ? "true" : "false"}"`,
966
1007
  ` data-index="${index}"`,
967
1008
  `>`,
968
- `<span class="ui-editor-slash-menu__icon" aria-hidden="true">${escapeHtml(item.icon)}</span>`,
1009
+ `<span class="ui-editor-slash-menu__icon" aria-hidden="true">${loomaIconMarkup4(item.icon)}</span>`,
969
1010
  `<span class="ui-editor-slash-menu__body">`,
970
1011
  `<span class="ui-editor-slash-menu__title">${escapeHtml(item.title)}</span>`,
971
1012
  `<span class="ui-editor-slash-menu__description">${escapeHtml(item.description)}</span>`,
@@ -1,6 +1,7 @@
1
1
  import { AnyExtension, Editor, Range, Extension } from '@tiptap/core';
2
- import { d as TableContextMenuActionEventDetail, g as TableOverlayActionEventDetail } from '../table-overlay-jjvdARTJ.js';
3
- export { a as TABLE_CELL_BACKGROUND_PRESETS } from '../table-overlay-jjvdARTJ.js';
2
+ import { d as TableContextMenuActionEventDetail, g as TableOverlayActionEventDetail } from '../table-overlay-DoiLie4h.js';
3
+ export { a as TABLE_CELL_BACKGROUND_PRESETS } from '../table-overlay-DoiLie4h.js';
4
+ import { LoomaIconName } from '@threadlabs/looma/core';
4
5
 
5
6
  /**
6
7
  * Default Tiptap extension preset for Looma editor.
@@ -113,7 +114,7 @@ declare function getDefaultSlashCommands(onOpenImagePicker?: () => void): LoomaS
113
114
  interface LoomaSlashCommand {
114
115
  title: string;
115
116
  description: string;
116
- icon: string;
117
+ icon: LoomaIconName;
117
118
  keywords: string[];
118
119
  command: (context: LoomaSlashCommandContext) => void;
119
120
  }
@@ -18,7 +18,7 @@ import {
18
18
  setActiveTableCellAlignment,
19
19
  setActiveTableCellBackground,
20
20
  shouldShowTextFormattingToolbar
21
- } from "../chunk-F4AYF33M.js";
21
+ } from "../chunk-OHD4OS32.js";
22
22
  import {
23
23
  TABLE_CELL_BACKGROUND_PRESETS
24
24
  } from "../chunk-CX4QDKSV.js";
package/editor/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { A as ActiveCellRect, T as TABLE_CELL_BACKGROUND_OPTIONS, a as TABLE_CELL_BACKGROUND_PRESETS, b as TableCellBackgroundAction, c as TableContextMenuAction, d as TableContextMenuActionEventDetail, e as TableInsertionAction, f as TableOverlayAction, g as TableOverlayActionEventDetail, h as TableOverlayGeometry, d as TableToolbarActionEventDetail, m as measureTableOverlayGeometry, r as resolveTableCellAt } from './table-overlay-jjvdARTJ.js';
1
+ export { A as ActiveCellRect, T as TABLE_CELL_BACKGROUND_OPTIONS, a as TABLE_CELL_BACKGROUND_PRESETS, b as TableCellBackgroundAction, c as TableContextMenuAction, d as TableContextMenuActionEventDetail, e as TableInsertionAction, f as TableOverlayAction, g as TableOverlayActionEventDetail, h as TableOverlayGeometry, d as TableToolbarActionEventDetail, m as measureTableOverlayGeometry, r as resolveTableCellAt } from './table-overlay-DoiLie4h.js';
2
2
  export { InsertTableEventDetail, SlashMenuAnchorRect, SlashMenuHighlightEventDetail, SlashMenuItem, SlashMenuSelectEventDetail } from './ui.js';
3
3
  export { ActiveTableUiState, DefaultEditorExtensionsOptions, InsertTableAtRangeOptions, LoomaSlashCommand, LoomaSlashCommandContext, LoomaSlashCommand as LoomaSlashCommandItem, LoomaSlashCommandOptions, LoomaSlashMenuSnapshot, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, TableActionCapabilities, TableCellAlignment, TableCellBackground, createLoomaSlashCommandExtension, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, handleTableAction, handleTableOverlayAction, insertTableAtRange, normalizeActiveTableColumnWidths, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar } from './extensions/index.js';
4
+ import '@threadlabs/looma/core';
4
5
  import '@tiptap/core';
package/editor/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  measureTableOverlayGeometry,
3
3
  resolveTableCellAt
4
- } from "./chunk-4VGVEHU2.js";
4
+ } from "./chunk-RTHHTPWK.js";
5
5
  import {
6
6
  LoomaSlashCommand,
7
7
  LoomaTable,
@@ -22,7 +22,7 @@ import {
22
22
  setActiveTableCellAlignment,
23
23
  setActiveTableCellBackground,
24
24
  shouldShowTextFormattingToolbar
25
- } from "./chunk-F4AYF33M.js";
25
+ } from "./chunk-OHD4OS32.js";
26
26
  import {
27
27
  TABLE_CELL_BACKGROUND_OPTIONS,
28
28
  TABLE_CELL_BACKGROUND_PRESETS
@@ -86,10 +86,11 @@ interface TableOverlayGeometry {
86
86
  rowBoundaries: number[];
87
87
  columnBoundaries: number[];
88
88
  activeCell: ActiveCellRect | null;
89
+ hoveredCell?: ActiveCellRect | null;
89
90
  }
90
91
  /** Resolves a logical table coordinate, including cells that span rows or columns. */
91
92
  declare function resolveTableCellAt(table: HTMLTableElement, rowIndex: number, columnIndex: number): HTMLTableCellElement | null;
92
93
  /** Measures real rendered boundaries, including non-uniform and merged cells. */
93
- declare function measureTableOverlayGeometry(table: HTMLTableElement, activeCell: HTMLTableCellElement | null): TableOverlayGeometry;
94
+ declare function measureTableOverlayGeometry(table: HTMLTableElement, activeCell: HTMLTableCellElement | null, hoveredCell?: HTMLTableCellElement | null): TableOverlayGeometry;
94
95
 
95
96
  export { type ActiveCellRect as A, TABLE_CELL_BACKGROUND_OPTIONS as T, TABLE_CELL_BACKGROUND_PRESETS as a, type TableCellBackgroundAction as b, type TableContextMenuAction as c, type TableContextMenuActionEventDetail as d, type TableInsertionAction as e, type TableOverlayAction as f, type TableOverlayActionEventDetail as g, type TableOverlayGeometry as h, measureTableOverlayGeometry as m, resolveTableCellAt as r };
package/editor/ui.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { A as ActiveCellRect, T as TABLE_CELL_BACKGROUND_OPTIONS, a as TABLE_CELL_BACKGROUND_PRESETS, b as TableCellBackgroundAction, c as TableContextMenuAction, d as TableContextMenuActionEventDetail, e as TableInsertionAction, f as TableOverlayAction, g as TableOverlayActionEventDetail, h as TableOverlayGeometry, d as TableToolbarActionEventDetail, m as measureTableOverlayGeometry, r as resolveTableCellAt } from './table-overlay-jjvdARTJ.js';
1
+ export { A as ActiveCellRect, T as TABLE_CELL_BACKGROUND_OPTIONS, a as TABLE_CELL_BACKGROUND_PRESETS, b as TableCellBackgroundAction, c as TableContextMenuAction, d as TableContextMenuActionEventDetail, e as TableInsertionAction, f as TableOverlayAction, g as TableOverlayActionEventDetail, h as TableOverlayGeometry, d as TableToolbarActionEventDetail, m as measureTableOverlayGeometry, r as resolveTableCellAt } from './table-overlay-DoiLie4h.js';
2
+ import { LoomaIconName } from '@threadlabs/looma/core';
2
3
 
3
4
  /**
4
5
  * ui-editor-insert-table-grid — web component for picking table dimensions.
@@ -15,10 +16,11 @@ interface InsertTableEventDetail {
15
16
  * ui-editor-slash-menu — floating slash-command menu.
16
17
  * Apps own the command list and suggestion state; Looma owns the chrome.
17
18
  */
19
+
18
20
  interface SlashMenuItem {
19
21
  title: string;
20
22
  description: string;
21
- icon: string;
23
+ icon: LoomaIconName;
22
24
  }
23
25
  interface SlashMenuHighlightEventDetail {
24
26
  index: number;
package/editor/ui.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  measureTableOverlayGeometry,
3
3
  resolveTableCellAt
4
- } from "./chunk-4VGVEHU2.js";
4
+ } from "./chunk-RTHHTPWK.js";
5
5
  import {
6
6
  TABLE_CELL_BACKGROUND_OPTIONS,
7
7
  TABLE_CELL_BACKGROUND_PRESETS