@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
package/editor.css CHANGED
@@ -179,8 +179,10 @@
179
179
  pointer-events: none;
180
180
  }
181
181
 
182
- .looma-editor__drop-glyph {
183
- font-size: var(--ui-font-size-2xl);
182
+ .looma-editor__drop-overlay > .looma-icon {
183
+ width: var(--ui-font-size-2xl);
184
+ height: var(--ui-font-size-2xl);
185
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
184
186
  }
185
187
 
186
188
  .looma-editor__toolbar-button {
@@ -189,16 +191,10 @@
189
191
  --ui-icon-button-icon-size: var(--ui-editor-toolbar-icon-size, 1rem);
190
192
  }
191
193
 
192
- .looma-editor__toolbar-glyph {
193
- display: inline-flex;
194
- align-items: center;
195
- justify-content: center;
196
- min-width: 1em;
197
- color: inherit;
198
- font-family: var(--ui-font-family-sans);
199
- font-size: var(--ui-editor-toolbar-glyph-size, 0.75rem);
200
- font-weight: var(--ui-font-semibold);
201
- line-height: 1;
194
+ .looma-editor__toolbar-button > .looma-icon {
195
+ width: var(--ui-editor-toolbar-icon-size, 1rem);
196
+ height: var(--ui-editor-toolbar-icon-size, 1rem);
197
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
202
198
  }
203
199
 
204
200
  .looma-editor__table-picker-anchor {
@@ -279,6 +275,10 @@
279
275
  }
280
276
 
281
277
  .looma-editor__mobile-toolbar-back {
278
+ display: inline-flex;
279
+ align-items: center;
280
+ justify-content: center;
281
+ gap: var(--ui-space-1-5, 6px);
282
282
  min-width: 44px;
283
283
  min-height: 44px;
284
284
  padding: 0 var(--ui-space-3, 12px);
@@ -291,6 +291,12 @@
291
291
  white-space: nowrap;
292
292
  }
293
293
 
294
+ .looma-editor__mobile-toolbar-back .looma-icon {
295
+ width: 1rem;
296
+ height: 1rem;
297
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
298
+ }
299
+
294
300
  .looma-editor__mobile-toolbar-back:is(:hover, :focus-visible) {
295
301
  background: var(--ui-surface-hover, #f3f4f6);
296
302
  color: var(--ui-text-primary, #111827);
@@ -512,6 +518,12 @@ ui-editor-toolbar[floating] {
512
518
  color: var(--ui-accent-contrast, #fff);
513
519
  }
514
520
 
521
+ .ui-editor-slash-menu__icon .looma-icon {
522
+ width: 1rem;
523
+ height: 1rem;
524
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
525
+ }
526
+
515
527
  .ui-editor-slash-menu__body {
516
528
  display: flex;
517
529
  min-width: 0;
@@ -588,7 +600,9 @@ ui-editor-toolbar[floating] {
588
600
  }
589
601
 
590
602
  .ui-editor-table-context-menu button {
591
- display: block;
603
+ display: flex;
604
+ align-items: center;
605
+ gap: var(--ui-space-2, 8px);
592
606
  width: 100%;
593
607
  text-align: left;
594
608
  min-height: 32px;
@@ -601,6 +615,13 @@ ui-editor-toolbar[floating] {
601
615
  color: var(--ui-text, #111);
602
616
  }
603
617
 
618
+ .ui-editor-table-context-menu button > .looma-icon {
619
+ width: 1rem;
620
+ height: 1rem;
621
+ flex: 0 0 auto;
622
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
623
+ }
624
+
604
625
  .ui-editor-table-context-menu button:hover:not(:disabled) {
605
626
  background: var(--ui-surface-hover, #f3f4f6);
606
627
  }
@@ -685,10 +706,8 @@ ui-editor-toolbar[floating] {
685
706
  .ui-editor-table-toolbar__group {
686
707
  display: inline-flex;
687
708
  align-items: center;
688
- gap: 0;
709
+ gap: 2px;
689
710
  overflow: hidden;
690
- border: 1px solid var(--ui-border, #e5e7eb);
691
- border-radius: var(--ui-radius-md, 6px);
692
711
  }
693
712
 
694
713
  .ui-editor-table-toolbar__sep {
@@ -705,6 +724,7 @@ ui-editor-toolbar[floating] {
705
724
  display: inline-flex;
706
725
  align-items: center;
707
726
  justify-content: center;
727
+ gap: var(--ui-space-1-5, 6px);
708
728
  min-height: 32px;
709
729
  border: 0;
710
730
  border-radius: var(--ui-radius-sm, 4px);
@@ -728,26 +748,37 @@ ui-editor-toolbar[floating] {
728
748
  }
729
749
 
730
750
  .ui-editor-table-toolbar__group button {
731
- border-radius: 0;
751
+ border-radius: var(--ui-radius-sm, 4px);
732
752
  }
733
753
 
734
754
  .ui-editor-table-toolbar__group button + button {
735
- border-left: 1px solid var(--ui-border, #e5e7eb);
755
+ border-left: 0;
736
756
  }
737
757
 
738
758
  .ui-editor-table-toolbar__more {
739
- border: 1px solid var(--ui-border, #e5e7eb) !important;
740
- border-radius: var(--ui-radius-md, 6px) !important;
759
+ border: 0 !important;
760
+ border-radius: var(--ui-radius-sm, 4px) !important;
741
761
  }
742
762
 
743
763
  .ui-editor-table-toolbar button[data-tone="danger"] {
744
764
  color: var(--ui-danger, #dc2626);
745
765
  }
746
766
 
747
- .ui-editor-table-toolbar__more::after {
748
- content: "▾";
749
- margin-left: var(--ui-space-1, 4px);
750
- font-size: 0.75em;
767
+ .ui-editor-table-toolbar .looma-icon {
768
+ width: var(--ui-editor-toolbar-icon-size, 1rem);
769
+ height: var(--ui-editor-toolbar-icon-size, 1rem);
770
+ flex: 0 0 auto;
771
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
772
+ }
773
+
774
+ .ui-editor-table-toolbar .looma-icon--chevron {
775
+ width: 0.875rem;
776
+ height: 0.875rem;
777
+ }
778
+
779
+ .ui-editor-table-toolbar__icon-button {
780
+ width: 32px;
781
+ padding-inline: 0 !important;
751
782
  }
752
783
 
753
784
  .ui-editor-table-toolbar__menu {
@@ -782,7 +813,8 @@ ui-editor-toolbar[floating] {
782
813
  }
783
814
 
784
815
  .ui-editor-table-toolbar__menu button {
785
- display: block;
816
+ display: flex;
817
+ justify-content: flex-start;
786
818
  width: 100%;
787
819
  text-align: left;
788
820
  }
@@ -834,8 +866,8 @@ ui-editor-toolbar[floating] {
834
866
 
835
867
  .ui-editor-insert-table-grid__grid {
836
868
  display: grid;
837
- grid-template-columns: repeat(8, 1.25rem);
838
- grid-template-rows: repeat(8, 1.25rem);
869
+ grid-template-columns: repeat(var(--ui-editor-table-grid-cols, 8), 1.25rem);
870
+ grid-template-rows: repeat(var(--ui-editor-table-grid-rows, 8), 1.25rem);
839
871
  gap: 2px;
840
872
  margin-bottom: var(--ui-space-2, 8px);
841
873
  }
@@ -944,6 +976,12 @@ ui-editor-table-overlay {
944
976
  cursor: pointer;
945
977
  }
946
978
 
979
+ .ui-editor-table-overlay__handle > .looma-icon {
980
+ width: 14px;
981
+ height: 14px;
982
+ stroke-width: var(--ui-editor-table-affordance-icon-stroke-width, 2);
983
+ }
984
+
947
985
  .ui-editor-table-overlay__handle[data-ui-proximity="near"],
948
986
  .ui-editor-table-overlay__control[data-active="true"] .ui-editor-table-overlay__handle,
949
987
  .ui-editor-table-overlay__handle:focus-visible {
@@ -974,7 +1012,7 @@ ui-editor-table-overlay {
974
1012
 
975
1013
  .ui-editor-table-overlay__control--row .ui-editor-table-overlay__handle {
976
1014
  top: -12px;
977
- left: -36px;
1015
+ left: -30px;
978
1016
  }
979
1017
 
980
1018
  .ui-editor-table-overlay__control--col {
@@ -984,7 +1022,7 @@ ui-editor-table-overlay {
984
1022
  }
985
1023
 
986
1024
  .ui-editor-table-overlay__control--col .ui-editor-table-overlay__handle {
987
- top: -36px;
1025
+ top: -30px;
988
1026
  left: -12px;
989
1027
  }
990
1028
 
@@ -1074,60 +1112,62 @@ ui-editor-table-overlay {
1074
1112
  align-items: center;
1075
1113
  justify-content: center;
1076
1114
  padding: 0;
1077
- border: 1px solid var(--ui-border-strong, #c8c8c4);
1078
- background: var(--ui-surface-elevated, #fff);
1115
+ border: 1px solid transparent;
1116
+ background: transparent;
1079
1117
  color: var(--ui-text-secondary, #5c5c5c);
1080
- box-shadow: var(--ui-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.05));
1118
+ box-shadow: none;
1081
1119
  pointer-events: auto;
1082
1120
  cursor: pointer;
1121
+ transition:
1122
+ color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
1123
+ background-color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
1124
+ border-color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
1125
+ box-shadow var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
1083
1126
  }
1084
1127
 
1085
1128
  .ui-editor-table-overlay__selector:hover,
1086
1129
  .ui-editor-table-overlay__cell-menu:hover {
1087
- border-color: var(--ui-affordance-direct-color, var(--ui-accent-solid, #5b55d6));
1088
- color: var(--ui-affordance-direct-color, var(--ui-accent-solid, #5b55d6));
1130
+ background: var(--ui-icon-button-hover-bg, var(--ui-surface-muted, #f3f4f6));
1131
+ color: var(--ui-icon-button-hover-color, var(--ui-text-primary, #1a1a1a));
1132
+ box-shadow: var(--ui-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.05));
1089
1133
  }
1090
1134
 
1091
1135
  .ui-editor-table-overlay__selector {
1092
1136
  border-radius: var(--ui-radius-round, 999px);
1093
1137
  }
1094
1138
 
1095
- .ui-editor-table-overlay__selector span {
1139
+ .ui-editor-table-overlay__selector .looma-icon {
1096
1140
  display: block;
1097
- border-radius: var(--ui-radius-round, 999px);
1098
- background: currentColor;
1141
+ width: 14px;
1142
+ height: 14px;
1143
+ stroke-width: var(--ui-editor-table-affordance-icon-stroke-width, 2);
1099
1144
  }
1100
1145
 
1101
1146
  .ui-editor-table-overlay__selector--row {
1102
- left: -26px;
1103
- width: 14px;
1104
- height: 30px;
1147
+ left: -9px;
1148
+ width: 18px;
1149
+ height: 32px;
1105
1150
  transform: translateY(-50%);
1106
1151
  }
1107
1152
 
1108
- .ui-editor-table-overlay__selector--row span {
1109
- width: 4px;
1110
- height: 16px;
1111
- }
1112
-
1113
1153
  .ui-editor-table-overlay__selector--column {
1114
- top: -26px;
1115
- width: 30px;
1116
- height: 14px;
1154
+ top: -9px;
1155
+ width: 32px;
1156
+ height: 18px;
1117
1157
  transform: translateX(-50%);
1118
1158
  }
1119
1159
 
1120
- .ui-editor-table-overlay__selector--column span {
1121
- width: 16px;
1122
- height: 4px;
1123
- }
1124
-
1125
1160
  .ui-editor-table-overlay__cell-menu {
1126
1161
  width: 24px;
1127
1162
  height: 24px;
1128
1163
  border-radius: var(--ui-radius-1, 4px);
1129
- font-size: 16px;
1130
- line-height: 1;
1164
+ background: color-mix(in srgb, var(--ui-surface-muted, #f3f4f6) 78%, transparent);
1165
+ }
1166
+
1167
+ .ui-editor-table-overlay__cell-menu .looma-icon {
1168
+ width: 15px;
1169
+ height: 15px;
1170
+ stroke-width: var(--ui-editor-table-affordance-icon-stroke-width, 2);
1131
1171
  }
1132
1172
 
1133
1173
  .ProseMirror .tableWrapper {
@@ -1160,6 +1200,7 @@ ui-editor-table-overlay {
1160
1200
 
1161
1201
  .ProseMirror th,
1162
1202
  .ProseMirror td {
1203
+ position: relative;
1163
1204
  border: 1px solid var(--ui-border, #e5e7eb);
1164
1205
  padding: var(--ui-space-2, 8px) var(--ui-space-3, 12px);
1165
1206
  vertical-align: top;
@@ -1168,8 +1209,14 @@ ui-editor-table-overlay {
1168
1209
  overflow-wrap: anywhere;
1169
1210
  }
1170
1211
 
1171
- .ProseMirror :is(th, td) > p:last-child {
1172
- margin-bottom: 0;
1212
+ .ProseMirror :is(th, td) > p,
1213
+ .looma-editor .ProseMirror :is(th, td) > p {
1214
+ margin: 0;
1215
+ }
1216
+
1217
+ .ProseMirror :is(th, td) > p + p,
1218
+ .looma-editor .ProseMirror :is(th, td) > p + p {
1219
+ margin-top: var(--ui-editor-table-paragraph-gap, var(--ui-space-2, 8px));
1173
1220
  }
1174
1221
 
1175
1222
  .ProseMirror th {
@@ -1216,8 +1263,8 @@ ui-editor-table-overlay {
1216
1263
  content: "Drag to resize column";
1217
1264
  position: absolute;
1218
1265
  z-index: 4;
1219
- top: -32px;
1220
- left: 50%;
1266
+ top: 4px;
1267
+ left: calc(100% + 6px);
1221
1268
  width: max-content;
1222
1269
  padding: var(--ui-space-1, 4px) var(--ui-space-2, 8px);
1223
1270
  border-radius: var(--ui-radius-1, 4px);
@@ -1226,7 +1273,7 @@ ui-editor-table-overlay {
1226
1273
  font-size: var(--ui-font-size-xs, 0.75rem);
1227
1274
  line-height: var(--ui-line-height-md, 1.4);
1228
1275
  opacity: 0;
1229
- transform: translateX(-50%);
1276
+ transform: none;
1230
1277
  transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
1231
1278
  pointer-events: none;
1232
1279
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "description": "Looma web components, responsive layout primitives, a complete editor, and supported Vue adapters.",
6
6
  "license": "MIT",
@@ -94,6 +94,7 @@
94
94
  "./*.css"
95
95
  ],
96
96
  "dependencies": {
97
+ "lucide": "~0.554.0",
97
98
  "lowlight": "^3.3.0"
98
99
  },
99
100
  "peerDependencies": {
@@ -125,7 +125,11 @@ import {
125
125
  resolveTableCellAt,
126
126
  shouldShowTextFormattingToolbar
127
127
  } from "@threadlabs/looma/editor";
128
- import { clampRectToViewport, getVisualViewportRect } from "@threadlabs/looma/core";
128
+ import {
129
+ clampRectToViewport,
130
+ getVisualViewportRect,
131
+ LOOMA_ICONS
132
+ } from "@threadlabs/looma/core";
129
133
  var EMPTY_DOCUMENT = { type: "doc", content: [] };
130
134
  var EMPTY_CAPABILITIES = {
131
135
  canAddRowBefore: false,
@@ -151,6 +155,20 @@ function selectedTableCellElement(editor) {
151
155
  const element = node instanceof HTMLElement ? node : node.parentElement;
152
156
  return element?.closest("td, th");
153
157
  }
158
+ function loomaIcon(name) {
159
+ return h2("svg", {
160
+ class: "looma-icon",
161
+ "data-looma-icon": name,
162
+ "aria-hidden": "true",
163
+ focusable: "false",
164
+ viewBox: "0 0 24 24",
165
+ fill: "none",
166
+ stroke: "currentColor",
167
+ "stroke-width": 2,
168
+ "stroke-linecap": "round",
169
+ "stroke-linejoin": "round"
170
+ }, LOOMA_ICONS[name].map(([tag, attributes]) => h2(tag, attributes)));
171
+ }
154
172
  var LoomaEditor = defineComponent2({
155
173
  name: "LoomaEditor",
156
174
  inheritAttrs: false,
@@ -193,7 +211,7 @@ var LoomaEditor = defineComponent2({
193
211
  const tablePickerOpen = ref(false);
194
212
  const tablePickerStyle = ref({});
195
213
  const mobileToolbarStyle = ref({});
196
- const mobile = ref(false);
214
+ const mobile = ref(typeof window !== "undefined" && window.innerWidth <= 767);
197
215
  const editorFocused = ref(false);
198
216
  const mobileToolbarMode = ref("formatting");
199
217
  let dragLeaveTimer = null;
@@ -201,6 +219,7 @@ var LoomaEditor = defineComponent2({
201
219
  let tableInteractionActive = false;
202
220
  let mobileTableControlsDismissed = false;
203
221
  let hoveredTableCell = null;
222
+ let overlayTableElement = null;
204
223
  let tablePointerFrame = null;
205
224
  const slash = reactive({
206
225
  active: false,
@@ -259,6 +278,7 @@ var LoomaEditor = defineComponent2({
259
278
  tableUi.background = null;
260
279
  tableUi.geometry = null;
261
280
  tableUi.capabilities = { ...EMPTY_CAPABILITIES };
281
+ overlayTableElement = null;
262
282
  mobileTableControlsDismissed = false;
263
283
  mobileToolbarMode.value = "formatting";
264
284
  };
@@ -280,32 +300,37 @@ var LoomaEditor = defineComponent2({
280
300
  };
281
301
  const updateTableUi = () => {
282
302
  const instance = editor.value;
283
- if (!instance || !props.editable || !instance.isFocused && !tableInteractionActive) {
303
+ if (!instance || !props.editable || !instance.isFocused && !tableInteractionActive && !hoveredTableCell) {
284
304
  closeTableUi();
285
305
  return;
286
306
  }
287
307
  const state = getActiveTableUiState(instance);
288
- const table = selectedTableElement(instance);
289
- if (!state.active || !table) {
308
+ const selectedTable = selectedTableElement(instance);
309
+ const hoveredTable = hoveredTableCell?.closest("table") ?? null;
310
+ const table = hoveredTable ?? selectedTable;
311
+ if (!table) {
290
312
  closeTableUi();
291
313
  return;
292
314
  }
293
- if (!mobileTableControlsDismissed) mobileToolbarMode.value = "table";
315
+ const selectedTableIsActive = state.active && selectedTable === table;
316
+ overlayTableElement = table;
317
+ if (selectedTableIsActive && !mobileTableControlsDismissed) mobileToolbarMode.value = "table";
294
318
  const rect = table.getBoundingClientRect();
295
319
  const maxToolbarWidth = Math.min(420, window.innerWidth - 24);
296
320
  const toolbarLeft = Math.min(
297
321
  Math.max(12, rect.left + (rect.width - maxToolbarWidth) / 2),
298
322
  Math.max(12, window.innerWidth - maxToolbarWidth - 12)
299
323
  );
300
- tableUi.toolbarOpen = state.showToolbar && !mobile.value;
324
+ tableUi.toolbarOpen = selectedTableIsActive && state.showToolbar && !mobile.value;
301
325
  tableUi.overlayOpen = !mobile.value;
302
- tableUi.alignment = state.cellAlignment;
303
- tableUi.background = state.cellBackground;
304
- tableUi.capabilities = state.capabilities;
305
- const selectedCell = selectedTableCellElement(instance);
326
+ tableUi.alignment = selectedTableIsActive ? state.cellAlignment : "left";
327
+ tableUi.background = selectedTableIsActive ? state.cellBackground : null;
328
+ tableUi.capabilities = selectedTableIsActive ? state.capabilities : { ...EMPTY_CAPABILITIES };
329
+ const selectedCell = selectedTableIsActive ? selectedTableCellElement(instance) : null;
306
330
  const geometry = measureTableOverlayGeometry(
307
331
  table,
308
- hoveredTableCell && table.contains(hoveredTableCell) ? hoveredTableCell : selectedCell
332
+ selectedCell,
333
+ hoveredTableCell && table.contains(hoveredTableCell) ? hoveredTableCell : null
309
334
  );
310
335
  tableUi.rows = Math.max(0, geometry.rowBoundaries.length - 1);
311
336
  tableUi.cols = Math.max(0, geometry.columnBoundaries.length - 1);
@@ -489,9 +514,18 @@ var LoomaEditor = defineComponent2({
489
514
  const runOverlayAction = (detail) => {
490
515
  const instance = editor.value;
491
516
  if (!instance) return;
517
+ const table = overlayTableElement ?? selectedTableElement(instance);
518
+ if (!table) return;
519
+ const targetCell = "rowIndex" in detail ? resolveTableCellAt(table, detail.rowIndex, detail.columnIndex) : resolveTableCellAt(
520
+ table,
521
+ detail.action.startsWith("add-row") ? Math.max(0, detail.boundaryIndex - 1) : 0,
522
+ detail.action.startsWith("add-column") ? Math.max(0, detail.boundaryIndex - 1) : 0
523
+ );
524
+ if (targetCell && selectedTableElement(instance) !== table) {
525
+ instance.chain().focus().setTextSelection(instance.view.posAtDOM(targetCell, 0) + 1).run();
526
+ }
492
527
  if (detail.action === "open-cell-menu") {
493
528
  const selectedCell = selectedTableCellElement(instance);
494
- const table = selectedTableElement(instance);
495
529
  const cell = table ? resolveTableCellAt(table, detail.rowIndex, detail.columnIndex) ?? selectedCell : selectedCell;
496
530
  if (cell && selectedCell !== cell && !cell.classList.contains("selectedCell")) {
497
531
  instance.chain().focus().setTextSelection(instance.view.posAtDOM(cell, 0) + 1).run();
@@ -520,6 +554,15 @@ var LoomaEditor = defineComponent2({
520
554
  updateTableUi();
521
555
  });
522
556
  };
557
+ const onEditorPointerOut = (event) => {
558
+ const fromCell = event.target instanceof HTMLElement ? event.target.closest("td, th") : null;
559
+ if (!fromCell || fromCell !== hoveredTableCell) return;
560
+ const next = event.relatedTarget;
561
+ const toCell = next instanceof HTMLElement ? next.closest("td, th") : null;
562
+ if (toCell || next instanceof Node && tableOverlayShell.value?.contains(next)) return;
563
+ hoveredTableCell = null;
564
+ nextTick(updateTableUi);
565
+ };
523
566
  const onEditorPointerLeave = (event) => {
524
567
  const next = event.relatedTarget;
525
568
  if (next instanceof Node && (tableOverlayShell.value?.contains(next) || tableToolbarShell.value?.contains(next) || tableMenuShell.value?.contains(next))) return;
@@ -527,6 +570,13 @@ var LoomaEditor = defineComponent2({
527
570
  hoveredTableCell = null;
528
571
  nextTick(updateTableUi);
529
572
  };
573
+ const onTableOverlayPointerLeave = (event) => {
574
+ const next = event.relatedTarget;
575
+ if (next instanceof Node && (root.value?.contains(next) || tableToolbarShell.value?.contains(next) || tableMenuShell.value?.contains(next))) return;
576
+ if (!hoveredTableCell) return;
577
+ hoveredTableCell = null;
578
+ nextTick(updateTableUi);
579
+ };
530
580
  const commandButton = (label, icon, active, disabled, run) => h2(IconButton, {
531
581
  class: "looma-editor__toolbar-button",
532
582
  label,
@@ -536,36 +586,36 @@ var LoomaEditor = defineComponent2({
536
586
  disabled,
537
587
  "data-active": active ? "true" : "false",
538
588
  onClick: run
539
- }, () => h2("span", { class: "looma-editor__toolbar-glyph", "aria-hidden": "true" }, icon));
589
+ }, () => loomaIcon(icon));
540
590
  const renderToolbar = (instance) => {
541
591
  const buttons = [
542
- commandButton("Bold", "B", instance.isActive("bold"), !instance.can().toggleBold(), () => instance.chain().focus().toggleBold().run()),
543
- commandButton("Italic", "I", instance.isActive("italic"), !instance.can().toggleItalic(), () => instance.chain().focus().toggleItalic().run()),
544
- commandButton("Underline", "U", instance.isActive("underline"), !instance.can().toggleUnderline(), () => instance.chain().focus().toggleUnderline().run()),
545
- commandButton("Strike", "S", instance.isActive("strike"), !instance.can().toggleStrike(), () => instance.chain().focus().toggleStrike().run()),
546
- commandButton("Highlight", "\u25B0", instance.isActive("highlight"), !instance.can().toggleHighlight(), () => instance.chain().focus().toggleHighlight().run()),
547
- commandButton("Inline code", "</>", instance.isActive("code"), !instance.can().toggleCode(), () => instance.chain().focus().toggleCode().run()),
592
+ commandButton("Bold", "bold", instance.isActive("bold"), !instance.can().toggleBold(), () => instance.chain().focus().toggleBold().run()),
593
+ commandButton("Italic", "italic", instance.isActive("italic"), !instance.can().toggleItalic(), () => instance.chain().focus().toggleItalic().run()),
594
+ commandButton("Underline", "underline", instance.isActive("underline"), !instance.can().toggleUnderline(), () => instance.chain().focus().toggleUnderline().run()),
595
+ commandButton("Strike", "strikethrough", instance.isActive("strike"), !instance.can().toggleStrike(), () => instance.chain().focus().toggleStrike().run()),
596
+ commandButton("Highlight", "highlighter", instance.isActive("highlight"), !instance.can().toggleHighlight(), () => instance.chain().focus().toggleHighlight().run()),
597
+ commandButton("Inline code", "code-xml", instance.isActive("code"), !instance.can().toggleCode(), () => instance.chain().focus().toggleCode().run()),
548
598
  h2("span", { class: "ui-editor-toolbar__divider", "aria-hidden": "true" }),
549
- commandButton("Heading 1", "H1", instance.isActive("heading", { level: 1 }), false, () => instance.chain().focus().toggleHeading({ level: 1 }).run()),
550
- commandButton("Heading 2", "H2", instance.isActive("heading", { level: 2 }), false, () => instance.chain().focus().toggleHeading({ level: 2 }).run()),
551
- commandButton("Heading 3", "H3", instance.isActive("heading", { level: 3 }), false, () => instance.chain().focus().toggleHeading({ level: 3 }).run()),
552
- commandButton("Bullet list", "\u2022", instance.isActive("bulletList"), false, () => instance.chain().focus().toggleBulletList().run()),
553
- commandButton("Numbered list", "1.", instance.isActive("orderedList"), false, () => instance.chain().focus().toggleOrderedList().run()),
554
- commandButton("Checklist", "\u2611", instance.isActive("taskList"), false, () => instance.chain().focus().toggleTaskList().run()),
555
- commandButton("Blockquote", "\u275D", instance.isActive("blockquote"), !instance.can().toggleBlockquote(), () => instance.chain().focus().toggleBlockquote().run()),
556
- commandButton("Code block", "{ }", instance.isActive("codeBlock"), !instance.can().toggleCodeBlock(), () => instance.chain().focus().toggleCodeBlock().run()),
557
- commandButton("Divider", "\u2014", false, !instance.can().setHorizontalRule(), () => instance.chain().focus().setHorizontalRule().run()),
599
+ commandButton("Heading 1", "heading-1", instance.isActive("heading", { level: 1 }), false, () => instance.chain().focus().toggleHeading({ level: 1 }).run()),
600
+ commandButton("Heading 2", "heading-2", instance.isActive("heading", { level: 2 }), false, () => instance.chain().focus().toggleHeading({ level: 2 }).run()),
601
+ commandButton("Heading 3", "heading-3", instance.isActive("heading", { level: 3 }), false, () => instance.chain().focus().toggleHeading({ level: 3 }).run()),
602
+ commandButton("Bullet list", "list", instance.isActive("bulletList"), false, () => instance.chain().focus().toggleBulletList().run()),
603
+ commandButton("Numbered list", "list-ordered", instance.isActive("orderedList"), false, () => instance.chain().focus().toggleOrderedList().run()),
604
+ commandButton("Checklist", "list-todo", instance.isActive("taskList"), false, () => instance.chain().focus().toggleTaskList().run()),
605
+ commandButton("Blockquote", "quote", instance.isActive("blockquote"), !instance.can().toggleBlockquote(), () => instance.chain().focus().toggleBlockquote().run()),
606
+ commandButton("Code block", "braces", instance.isActive("codeBlock"), !instance.can().toggleCodeBlock(), () => instance.chain().focus().toggleCodeBlock().run()),
607
+ commandButton("Divider", "minus", false, !instance.can().setHorizontalRule(), () => instance.chain().focus().setHorizontalRule().run()),
558
608
  h2("span", { class: "ui-editor-toolbar__divider", "aria-hidden": "true" }),
559
609
  h2("span", { ref: tablePickerAnchor, class: "looma-editor__table-picker-anchor" }, [
560
- commandButton("Insert table", "\u229E", false, false, () => {
610
+ commandButton("Insert table", "table", false, false, () => {
561
611
  tablePickerOpen.value = !tablePickerOpen.value;
562
612
  nextTick(updateTablePickerPosition);
563
613
  })
564
614
  ]),
565
- commandButton(uploading.value ? "Uploading image" : "Insert image", "\u25A7", false, uploading.value || !props.uploadImage, () => fileInput.value?.click()),
615
+ commandButton(uploading.value ? "Uploading image" : "Insert image", "image", false, uploading.value || !props.uploadImage, () => fileInput.value?.click()),
566
616
  h2("span", { class: "ui-editor-toolbar__divider", "aria-hidden": "true" }),
567
- commandButton("Undo", "\u21B6", false, !instance.can().undo(), () => instance.chain().focus().undo().run()),
568
- commandButton("Redo", "\u21B7", false, !instance.can().redo(), () => instance.chain().focus().redo().run())
617
+ commandButton("Undo", "undo", false, !instance.can().undo(), () => instance.chain().focus().undo().run()),
618
+ commandButton("Redo", "redo", false, !instance.can().redo(), () => instance.chain().focus().redo().run())
569
619
  ];
570
620
  return h2(EditorToolbar, { floating: "" }, () => buttons);
571
621
  };
@@ -596,6 +646,7 @@ var LoomaEditor = defineComponent2({
596
646
  class: ["looma-editor", attrs.class, { "looma-editor--readonly": !props.editable, "looma-editor--drag-over": dragOver.value }],
597
647
  onContextmenu: onContextMenu,
598
648
  onPointerover: onEditorPointerOver,
649
+ onPointerout: onEditorPointerOut,
599
650
  onPointerleave: onEditorPointerLeave,
600
651
  onDragover: (event) => {
601
652
  event.preventDefault();
@@ -639,7 +690,7 @@ var LoomaEditor = defineComponent2({
639
690
  editor.value?.commands.focus();
640
691
  nextTick(updateMobileViewport);
641
692
  }
642
- }, "\u2190 Formatting"),
693
+ }, [loomaIcon("chevron-left"), h2("span", "Formatting")]),
643
694
  h2(EditorTableToolbar, tableProps)
644
695
  ] : [renderToolbar(instance)]) : null,
645
696
  h2("input", {
@@ -653,7 +704,7 @@ var LoomaEditor = defineComponent2({
653
704
  onChange: onFileChange
654
705
  }),
655
706
  dragOver.value ? h2("div", { class: "looma-editor__drop-overlay", "aria-hidden": "true" }, [
656
- h2("span", { class: "looma-editor__drop-glyph" }, "\u25A7"),
707
+ loomaIcon("image"),
657
708
  h2("span", "Drop image to upload")
658
709
  ]) : null,
659
710
  tablePickerOpen.value ? h2("div", {
@@ -688,7 +739,8 @@ var LoomaEditor = defineComponent2({
688
739
  tableUi.overlayOpen ? h2("div", {
689
740
  ref: tableOverlayShell,
690
741
  class: "looma-editor__table-overlay-shell",
691
- style: tableUi.overlayStyle
742
+ style: tableUi.overlayStyle,
743
+ onPointerleave: onTableOverlayPointerLeave
692
744
  }, [h2(EditorTableOverlay, {
693
745
  open: true,
694
746
  rows: tableUi.rows,
@@ -1 +0,0 @@
1
- import{r as t,g as a,h as e,H as i}from"./p-CEeiinfk.js";function n(t,a){const e=Math.max(a.left-t.x,0,t.x-a.right),i=Math.max(a.top-t.y,0,t.y-a.bottom);return Math.hypot(e,i)}const o=class{constructor(a){t(this,a)}get host(){return a(this)}nearRadius=32;coordinator=null;componentDidLoad(){this.connectCoordinator()}disconnectedCallback(){this.coordinator?.destroy(),this.coordinator=null}connectCoordinator(){this.coordinator?.destroy(),this.coordinator=function(t,a={}){const e=t.ownerDocument.defaultView??window,i=a.pointerTarget??t,o=a.anchorSelector??"[data-ui-affordance]",r=a.nearRadius??32,s=Number.isFinite(r)?Math.max(0,r):32,c=new AbortController;let d=[],l=null,u=null,h=!1;const f=()=>{for(const{element:t}of d)t.hasAttribute("data-ui-proximity")&&t.removeAttribute("data-ui-proximity");t.hasAttribute("data-ui-interaction")&&t.removeAttribute("data-ui-interaction")},p=()=>{d=Array.from(t.querySelectorAll(o)).filter((t=>!t.hasAttribute("disabled")&&"true"!==t.getAttribute("aria-disabled"))).map((t=>({element:t,rect:t.getBoundingClientRect()}))),h=!1},g=()=>{if(l=null,h&&p(),!u)return void f();let a=!1;for(const t of d){const e=n(u,t.rect)<=s;e&&"near"!==t.element.getAttribute("data-ui-proximity")?t.element.setAttribute("data-ui-proximity","near"):!e&&t.element.hasAttribute("data-ui-proximity")&&t.element.removeAttribute("data-ui-proximity"),a||=e}a&&"engaged"!==t.getAttribute("data-ui-interaction")?t.setAttribute("data-ui-interaction","engaged"):!a&&t.hasAttribute("data-ui-interaction")&&t.removeAttribute("data-ui-interaction")},m=()=>{null===l&&(l=e.requestAnimationFrame(g))},y=()=>{h=!0,m()};return i.addEventListener("pointermove",(t=>{u="touch"===t.pointerType?null:{x:t.clientX,y:t.clientY},m()}),{passive:!0,signal:c.signal}),e.addEventListener("resize",y,{passive:!0,signal:c.signal}),e.addEventListener("scroll",y,{passive:!0,capture:!0,signal:c.signal}),e.visualViewport?.addEventListener("resize",y,{passive:!0,signal:c.signal}),e.visualViewport?.addEventListener("scroll",y,{passive:!0,signal:c.signal}),p(),{refresh:y,destroy(){c.abort(),null!==l&&e.cancelAnimationFrame(l),l=null,u=null,f(),d=[]}}}(this.host,{nearRadius:this.nearRadius})}onSlotChange=()=>{this.coordinator?.refresh()};render(){return e(i,{key:"2bc861652826e6227deaba6d1030ecf43753f575"},e("slot",{key:"5e0544939e6b20747f12023dbb45329eb3853715",onSlotchange:this.onSlotChange}))}static get watchers(){return{nearRadius:[{connectCoordinator:0}]}}};o.style=":host{display:contents;--ui-affordance-scope-engaged:0}:host([data-ui-interaction='engaged']){--ui-affordance-scope-engaged:1}";export{o as ui_affordance_scope}