logisheets-engine 1.1.1 → 1.1.2

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.
@@ -5035,6 +5035,11 @@ const STALE_REACTION = new (class StaleReactionError extends Error {
5035
5035
  message = 'The reaction that called `getAbortSignal()` was re-run or destroyed';
5036
5036
  })();
5037
5037
 
5038
+ const IS_XHTML =
5039
+ // We gotta write it like this because after downleveling the pure comment may end up in the wrong location
5040
+ !!globalThis.document?.contentType &&
5041
+ /* @__PURE__ */ globalThis.document.contentType.includes('xml');
5042
+
5038
5043
  /* This file is generated by scripts/process-messages/index.js. Do not edit! */
5039
5044
 
5040
5045
 
@@ -12163,6 +12168,30 @@ function set_style(dom, value, prev_styles, next_styles) {
12163
12168
 
12164
12169
  const IS_CUSTOM_ELEMENT = Symbol('is custom element');
12165
12170
  const IS_HTML = Symbol('is html');
12171
+ const PROGRESS_TAG = IS_XHTML ? 'progress' : 'PROGRESS';
12172
+
12173
+ /**
12174
+ * @param {Element} element
12175
+ * @param {any} value
12176
+ */
12177
+ function set_value(element, value) {
12178
+ var attributes = get_attributes(element);
12179
+
12180
+ if (
12181
+ attributes.value ===
12182
+ (attributes.value =
12183
+ // treat null and undefined the same for the initial value
12184
+ value ?? undefined) ||
12185
+ // @ts-expect-error
12186
+ // `progress` elements always need their value set when it's `0`
12187
+ (element.value === value && (value !== 0 || element.nodeName !== PROGRESS_TAG))
12188
+ ) {
12189
+ return;
12190
+ }
12191
+
12192
+ // @ts-expect-error
12193
+ element.value = value ?? '';
12194
+ }
12166
12195
 
12167
12196
  /**
12168
12197
  * @param {Element} element
@@ -14018,301 +14047,6 @@ function Scrollbar($$anchor, $$props) {
14018
14047
 
14019
14048
  delegate(['mousedown', 'mouseup']);
14020
14049
 
14021
- var root$1 = from_html(`<span class="menu-icon svelte-192vamk"> </span>`);
14022
- var root_1$1 = from_html(`<span class="menu-icon-placeholder svelte-192vamk"></span>`);
14023
- var root_2$1 = from_html(`<span class="menu-shortcut svelte-192vamk"> </span>`);
14024
- var root_3$1 = from_html(`<span class="menu-arrow svelte-192vamk">▶</span>`);
14025
- var root_4$1 = from_html(`<div class="menu-separator svelte-192vamk"></div>`);
14026
- var root_5 = from_html(`<button role="menuitem"><!> <span class="menu-label svelte-192vamk"> </span> <!></button> <!>`, 1);
14027
- var root_6 = from_html(`<div class="submenu svelte-192vamk"></div>`);
14028
- var root_7 = from_html(`<div class="menu-item-wrapper svelte-192vamk"><button role="menuitem"><!> <span class="menu-label svelte-192vamk"> </span> <!> <!></button> <!></div> <!>`, 1);
14029
- var root_8 = from_html(`<div class="context-menu svelte-192vamk" role="menu" tabindex="-1"></div>`);
14030
-
14031
- function ContextMenu($$anchor, $$props) {
14032
- push($$props, true);
14033
-
14034
- // ========================================================================
14035
- // Props
14036
- // ========================================================================
14037
- /** Whether the menu is visible */
14038
- /** X position of the menu */
14039
- /** Y position of the menu */
14040
- /** Menu items to display */
14041
- /** Context when menu was triggered */
14042
- /** Called when a menu item is clicked */
14043
- /** Called when menu should close */
14044
- // ========================================================================
14045
- // State
14046
- // ========================================================================
14047
- let menuEl = state(null);
14048
-
14049
- let adjustedX = state(0);
14050
- let adjustedY = state(0);
14051
- let activeSubmenu = state(null);
14052
-
14053
- // ========================================================================
14054
- // Position adjustment to keep menu in viewport
14055
- // ========================================================================
14056
- user_effect(() => {
14057
- if ($$props.visible && get(menuEl)) {
14058
- const rect = get(menuEl).getBoundingClientRect();
14059
- const viewportWidth = window.innerWidth;
14060
- const viewportHeight = window.innerHeight;
14061
- let newX = $$props.x;
14062
- let newY = $$props.y;
14063
-
14064
- // Adjust horizontal position
14065
- if ($$props.x + rect.width > viewportWidth - 10) {
14066
- newX = viewportWidth - rect.width - 10;
14067
- }
14068
-
14069
- // Adjust vertical position
14070
- if ($$props.y + rect.height > viewportHeight - 10) {
14071
- newY = viewportHeight - rect.height - 10;
14072
- }
14073
-
14074
- set(adjustedX, Math.max(10, newX), true);
14075
- set(adjustedY, Math.max(10, newY), true);
14076
- }
14077
- });
14078
-
14079
- // ========================================================================
14080
- // Event Handlers
14081
- // ========================================================================
14082
- function handleItemClick(item, e) {
14083
- e.stopPropagation();
14084
-
14085
- if (item.disabled) return;
14086
-
14087
- if (item.children && item.children.length > 0) {
14088
- // Toggle submenu
14089
- set(activeSubmenu, get(activeSubmenu) === item.id ? null : item.id, true);
14090
-
14091
- return;
14092
- }
14093
-
14094
- $$props.onItemClick?.(item, $$props.context);
14095
- $$props.onClose?.();
14096
- }
14097
-
14098
- function handleKeyDown(e) {
14099
- if (e.key === 'Escape') {
14100
- $$props.onClose?.();
14101
- }
14102
- }
14103
-
14104
- function handleClickOutside(e) {
14105
- if (get(menuEl) && !get(menuEl).contains(e.target)) {
14106
- $$props.onClose?.();
14107
- }
14108
- }
14109
-
14110
- onMount(() => {
14111
- document.addEventListener('mousedown', handleClickOutside);
14112
-
14113
- return () => {
14114
- document.removeEventListener('mousedown', handleClickOutside);
14115
- };
14116
- });
14117
-
14118
- var fragment = comment();
14119
-
14120
- event('keydown', $window, handleKeyDown);
14121
-
14122
- var node = first_child(fragment);
14123
-
14124
- {
14125
- var consequent_8 = ($$anchor) => {
14126
- var div = root_8();
14127
-
14128
- each(div, 21, () => $$props.items, (item) => item.id, ($$anchor, item) => {
14129
- var fragment_1 = root_7();
14130
- var div_1 = first_child(fragment_1);
14131
- var button = child(div_1);
14132
- let classes;
14133
- var node_1 = child(button);
14134
-
14135
- {
14136
- var consequent = ($$anchor) => {
14137
- var span = root$1();
14138
- var text = child(span);
14139
- template_effect(() => set_text(text, get(item).icon));
14140
- append($$anchor, span);
14141
- };
14142
-
14143
- var alternate = ($$anchor) => {
14144
- var span_1 = root_1$1();
14145
-
14146
- append($$anchor, span_1);
14147
- };
14148
-
14149
- if_block(node_1, ($$render) => {
14150
- if (get(item).icon) $$render(consequent); else $$render(alternate, -1);
14151
- });
14152
- }
14153
-
14154
- var span_2 = sibling(node_1, 2);
14155
- var text_1 = child(span_2);
14156
-
14157
- var node_2 = sibling(span_2, 2);
14158
-
14159
- {
14160
- var consequent_1 = ($$anchor) => {
14161
- var span_3 = root_2$1();
14162
- var text_2 = child(span_3);
14163
- template_effect(() => set_text(text_2, get(item).shortcut));
14164
- append($$anchor, span_3);
14165
- };
14166
-
14167
- if_block(node_2, ($$render) => {
14168
- if (get(item).shortcut) $$render(consequent_1);
14169
- });
14170
- }
14171
-
14172
- var node_3 = sibling(node_2, 2);
14173
-
14174
- {
14175
- var consequent_2 = ($$anchor) => {
14176
- var span_4 = root_3$1();
14177
-
14178
- append($$anchor, span_4);
14179
- };
14180
-
14181
- if_block(node_3, ($$render) => {
14182
- if (get(item).children && get(item).children.length > 0) $$render(consequent_2);
14183
- });
14184
- }
14185
-
14186
- var node_4 = sibling(button, 2);
14187
-
14188
- {
14189
- var consequent_6 = ($$anchor) => {
14190
- var div_2 = root_6();
14191
-
14192
- each(div_2, 21, () => get(item).children, (child) => child.id, ($$anchor, child$1) => {
14193
- var fragment_2 = root_5();
14194
- var button_1 = first_child(fragment_2);
14195
- let classes_1;
14196
- var node_5 = child(button_1);
14197
-
14198
- {
14199
- var consequent_3 = ($$anchor) => {
14200
- var span_5 = root$1();
14201
- var text_3 = child(span_5);
14202
- template_effect(() => set_text(text_3, get(child$1).icon));
14203
- append($$anchor, span_5);
14204
- };
14205
-
14206
- var alternate_1 = ($$anchor) => {
14207
- var span_6 = root_1$1();
14208
-
14209
- append($$anchor, span_6);
14210
- };
14211
-
14212
- if_block(node_5, ($$render) => {
14213
- if (get(child$1).icon) $$render(consequent_3); else $$render(alternate_1, -1);
14214
- });
14215
- }
14216
-
14217
- var span_7 = sibling(node_5, 2);
14218
- var text_4 = child(span_7);
14219
-
14220
- var node_6 = sibling(span_7, 2);
14221
-
14222
- {
14223
- var consequent_4 = ($$anchor) => {
14224
- var span_8 = root_2$1();
14225
- var text_5 = child(span_8);
14226
- template_effect(() => set_text(text_5, get(child$1).shortcut));
14227
- append($$anchor, span_8);
14228
- };
14229
-
14230
- if_block(node_6, ($$render) => {
14231
- if (get(child$1).shortcut) $$render(consequent_4);
14232
- });
14233
- }
14234
-
14235
- var node_7 = sibling(button_1, 2);
14236
-
14237
- {
14238
- var consequent_5 = ($$anchor) => {
14239
- var div_3 = root_4$1();
14240
-
14241
- append($$anchor, div_3);
14242
- };
14243
-
14244
- if_block(node_7, ($$render) => {
14245
- if (get(child$1).separator) $$render(consequent_5);
14246
- });
14247
- }
14248
-
14249
- template_effect(() => {
14250
- classes_1 = set_class(button_1, 1, 'menu-item svelte-192vamk', null, classes_1, { disabled: get(child$1).disabled });
14251
- set_attribute(button_1, 'aria-disabled', get(child$1).disabled);
14252
- set_text(text_4, get(child$1).label);
14253
- });
14254
-
14255
- delegated('click', button_1, (e) => handleItemClick(get(child$1), e));
14256
- append($$anchor, fragment_2);
14257
- });
14258
- append($$anchor, div_2);
14259
- };
14260
-
14261
- if_block(node_4, ($$render) => {
14262
- if (get(item).children && get(item).children.length > 0 && get(activeSubmenu) === get(item).id) $$render(consequent_6);
14263
- });
14264
- }
14265
-
14266
- var node_8 = sibling(div_1, 2);
14267
-
14268
- {
14269
- var consequent_7 = ($$anchor) => {
14270
- var div_4 = root_4$1();
14271
-
14272
- append($$anchor, div_4);
14273
- };
14274
-
14275
- if_block(node_8, ($$render) => {
14276
- if (get(item).separator) $$render(consequent_7);
14277
- });
14278
- }
14279
-
14280
- template_effect(() => {
14281
- classes = set_class(button, 1, 'menu-item svelte-192vamk', null, classes, {
14282
- disabled: get(item).disabled,
14283
- 'has-children': get(item).children && get(item).children.length > 0
14284
- });
14285
-
14286
- set_attribute(button, 'aria-disabled', get(item).disabled);
14287
- set_text(text_1, get(item).label);
14288
- });
14289
-
14290
- delegated('click', button, (e) => handleItemClick(get(item), e));
14291
-
14292
- event('mouseenter', button, () => {
14293
- if (get(item).children && get(item).children.length > 0) {
14294
- set(activeSubmenu, get(item).id, true);
14295
- }
14296
- });
14297
-
14298
- append($$anchor, fragment_1);
14299
- });
14300
- bind_this(div, ($$value) => set(menuEl, $$value), () => get(menuEl));
14301
- template_effect(() => set_style(div, `left: ${get(adjustedX) ?? ''}px; top: ${get(adjustedY) ?? ''}px;`));
14302
- append($$anchor, div);
14303
- };
14304
-
14305
- if_block(node, ($$render) => {
14306
- if ($$props.visible) $$render(consequent_8);
14307
- });
14308
- }
14309
-
14310
- append($$anchor, fragment);
14311
- pop();
14312
- }
14313
-
14314
- delegate(['click']);
14315
-
14316
14050
  function isApplePlatform() {
14317
14051
  if (typeof navigator === "undefined") return false;
14318
14052
  const p = (
@@ -14435,11 +14169,11 @@ function dispatchShortcut(e, handlers) {
14435
14169
  return true;
14436
14170
  }
14437
14171
 
14438
- var root = from_html(`<!> <div class="fill-handle svelte-rlol6m" role="presentation"></div>`, 1);
14439
- var root_1 = from_html(`<div class="fill-preview svelte-rlol6m"></div>`);
14440
- var root_2 = from_html(`<div class="fill-tooltip svelte-rlol6m"> </div>`);
14441
- var root_3 = from_html(`<div class="scrollbar-y svelte-rlol6m"><!></div> <div class="scrollbar-x svelte-rlol6m"><!></div>`, 1);
14442
- var root_4 = from_html(`<div class="spreadsheet-container svelte-rlol6m"><div><div class="canvas-wrapper svelte-rlol6m"><div class="corner-cell svelte-rlol6m"></div> <!> <!> <canvas tabindex="0" class="main-canvas svelte-rlol6m">Your browser does not support canvas.</canvas> <!> <!> <!> <!></div></div> <!> <!></div>`);
14172
+ var root$1 = from_html(`<!> <div class="fill-handle svelte-rlol6m" role="presentation"></div>`, 1);
14173
+ var root_1$1 = from_html(`<div class="fill-preview svelte-rlol6m"></div>`);
14174
+ var root_2$1 = from_html(`<div class="fill-tooltip svelte-rlol6m"> </div>`);
14175
+ var root_3$1 = from_html(`<div class="scrollbar-y svelte-rlol6m"><!></div> <div class="scrollbar-x svelte-rlol6m"><!></div>`, 1);
14176
+ var root_4$1 = from_html(`<div class="spreadsheet-container svelte-rlol6m"><div><div class="canvas-wrapper svelte-rlol6m"><div class="corner-cell svelte-rlol6m"></div> <!> <!> <canvas tabindex="0" class="main-canvas svelte-rlol6m">Your browser does not support canvas.</canvas> <!> <!> <!> <!></div></div> <!></div>`);
14443
14177
 
14444
14178
  function Spreadsheet($$anchor, $$props) {
14445
14179
  push($$props, true);
@@ -14470,12 +14204,15 @@ function Spreadsheet($$anchor, $$props) {
14470
14204
  /** Engine configuration */
14471
14205
  /** Show sheet tabs at bottom */
14472
14206
  /** Show scrollbars */
14473
- /** Custom context menu items */
14474
14207
  /** Callback when selection changes */
14475
14208
  /** Callback when active sheet changes */
14476
14209
  /** Callback when grid updates */
14477
14210
  /** Callback when sheets list changes */
14478
- /** Callback when context menu item is clicked */
14211
+ /**
14212
+ * The user opened the context menu (right-clicked a cell or a
14213
+ * row/column header). The engine renders no menu itself — the host
14214
+ * uses this to render its own menu at `(x, y)` (viewport coords).
14215
+ */
14479
14216
  /** Callback when user wants to start editing a cell (double-click or direct typing) */
14480
14217
  /** Callback when an invalid formula is entered */
14481
14218
  /** Callback for the Save shortcut (Ctrl/⌘+S) — host decides how to persist. */
@@ -14489,7 +14226,6 @@ function Spreadsheet($$anchor, $$props) {
14489
14226
  let config = prop($$props, 'config', 19, () => ({})),
14490
14227
  showSheetTabs = prop($$props, 'showSheetTabs', 3, true),
14491
14228
  showScrollbars = prop($$props, 'showScrollbars', 3, true),
14492
- contextMenuItems = prop($$props, 'contextMenuItems', 19, () => []),
14493
14229
  externalDataService = prop($$props, 'dataService', 3, null);
14494
14230
 
14495
14231
  // ========================================================================
@@ -14599,13 +14335,6 @@ function Spreadsheet($$anchor, $$props) {
14599
14335
  let lastClickRow = -1;
14600
14336
  let lastClickCol = -1;
14601
14337
 
14602
- // Context menu state
14603
- let contextMenuVisible = state(false);
14604
-
14605
- let contextMenuX = state(0);
14606
- let contextMenuY = state(0);
14607
- let contextMenuContext = state(null);
14608
-
14609
14338
  // Cleanup references
14610
14339
  let resizeObserver = null;
14611
14340
 
@@ -15057,6 +14786,63 @@ function Spreadsheet($$anchor, $$props) {
15057
14786
  },
15058
14787
  true
15059
14788
  );
14789
+ } else if (sel.ty === 'line') {
14790
+ // Whole-row / whole-column selection. The box spans the selected
14791
+ // lines along one axis and the full visible grid along the other,
14792
+ // clamped to what's currently rendered (null if scrolled away).
14793
+ if (sel.d.type === 'row') {
14794
+ const visStartRow = Math.max(sel.d.start, firstRow);
14795
+ const visEndRow = Math.min(sel.d.end, lastRow);
14796
+
14797
+ if (visStartRow > visEndRow) {
14798
+ set(selector, null);
14799
+
14800
+ return;
14801
+ }
14802
+
14803
+ const startY = yForRowStart(visStartRow, g);
14804
+ const endY = yForRowEnd(visEndRow, g);
14805
+ const startX = xForColStart(firstCol, g);
14806
+ const endX = xForColEnd(lastCol, g);
14807
+
14808
+ set(
14809
+ selector,
14810
+ {
14811
+ x: get(LeftTop).width + startX - 1,
14812
+ y: get(LeftTop).height + startY - 1,
14813
+ width: Math.max(0, endX - startX),
14814
+ height: Math.max(0, endY - startY)
14815
+ },
14816
+ true
14817
+ );
14818
+ } else {
14819
+ const visStartCol = Math.max(sel.d.start, firstCol);
14820
+ const visEndCol = Math.min(sel.d.end, lastCol);
14821
+
14822
+ if (visStartCol > visEndCol) {
14823
+ set(selector, null);
14824
+
14825
+ return;
14826
+ }
14827
+
14828
+ const startX = xForColStart(visStartCol, g);
14829
+ const endX = xForColEnd(visEndCol, g);
14830
+ const startY = yForRowStart(firstRow, g);
14831
+ const endY = yForRowEnd(lastRow, g);
14832
+
14833
+ set(
14834
+ selector,
14835
+ {
14836
+ x: get(LeftTop).width + startX - 1,
14837
+ y: get(LeftTop).height + startY - 1,
14838
+ width: Math.max(0, endX - startX),
14839
+ height: Math.max(0, endY - startY)
14840
+ },
14841
+ true
14842
+ );
14843
+ }
14844
+ } else {
14845
+ set(selector, null);
15060
14846
  }
15061
14847
  }
15062
14848
 
@@ -15493,12 +15279,12 @@ function Spreadsheet($$anchor, $$props) {
15493
15279
  window.addEventListener('mouseup', handleUp);
15494
15280
  }
15495
15281
 
15496
- function onContextMenu(e) {
15282
+ function handleCanvasContextMenu(e) {
15497
15283
  e.preventDefault();
15498
15284
  e.stopPropagation();
15499
15285
 
15500
- // Only show if we have custom menu items
15501
- if (contextMenuItems().length === 0) return;
15286
+ // Nothing to do if the host isn't listening for the menu trigger.
15287
+ if (!$$props.onContextMenu) return;
15502
15288
 
15503
15289
  if (!get(grid) || !get(canvasEl)) return;
15504
15290
 
@@ -15531,8 +15317,7 @@ function Spreadsheet($$anchor, $$props) {
15531
15317
  $$props.onSelectedDataChange?.(data);
15532
15318
  }
15533
15319
 
15534
- set(
15535
- contextMenuContext,
15320
+ $$props.onContextMenu(
15536
15321
  {
15537
15322
  selectedData: selectedData(),
15538
15323
  target: 'cell',
@@ -15540,53 +15325,33 @@ function Spreadsheet($$anchor, $$props) {
15540
15325
  col,
15541
15326
  event: e
15542
15327
  },
15543
- true
15328
+ e.clientX,
15329
+ e.clientY
15544
15330
  );
15545
15331
  } else {
15546
- set(contextMenuContext, { selectedData: selectedData(), target: 'cell', event: e }, true);
15332
+ $$props.onContextMenu({ selectedData: selectedData(), target: 'cell', event: e }, e.clientX, e.clientY);
15547
15333
  }
15548
-
15549
- set(contextMenuX, e.clientX, true);
15550
- set(contextMenuY, e.clientY, true);
15551
- set(contextMenuVisible, true);
15552
- }
15553
-
15554
- function closeContextMenu() {
15555
- set(contextMenuVisible, false);
15556
- set(contextMenuContext, null);
15557
- }
15558
-
15559
- function handleContextMenuItemClick(item, context) {
15560
- $$props.onContextMenuItemClick?.(item, context);
15561
- closeContextMenu();
15562
15334
  }
15563
15335
 
15564
15336
  function onColumnContextMenu(col, e) {
15565
- if (contextMenuItems().length === 0) return;
15337
+ if (!$$props.onContextMenu) return;
15566
15338
 
15567
- set(
15568
- contextMenuContext,
15339
+ $$props.onContextMenu(
15569
15340
  {
15570
15341
  selectedData: selectedData(),
15571
15342
  target: 'column',
15572
15343
  col,
15573
15344
  event: e
15574
15345
  },
15575
- true
15346
+ e.clientX,
15347
+ e.clientY
15576
15348
  );
15577
-
15578
- set(contextMenuX, e.clientX, true);
15579
- set(contextMenuY, e.clientY, true);
15580
- set(contextMenuVisible, true);
15581
15349
  }
15582
15350
 
15583
15351
  function onRowContextMenu(row, e) {
15584
- if (contextMenuItems().length === 0) return;
15352
+ if (!$$props.onContextMenu) return;
15585
15353
 
15586
- set(contextMenuContext, { selectedData: selectedData(), target: 'row', row, event: e }, true);
15587
- set(contextMenuX, e.clientX, true);
15588
- set(contextMenuY, e.clientY, true);
15589
- set(contextMenuVisible, true);
15354
+ $$props.onContextMenu({ selectedData: selectedData(), target: 'row', row, event: e }, e.clientX, e.clientY);
15590
15355
  }
15591
15356
 
15592
15357
  // ========================================================================
@@ -16103,7 +15868,7 @@ function Spreadsheet($$anchor, $$props) {
16103
15868
  selectRange
16104
15869
  };
16105
15870
 
16106
- var div = root_4();
15871
+ var div = root_4$1();
16107
15872
  var div_1 = child(div);
16108
15873
  let classes;
16109
15874
  var div_2 = child(div_1);
@@ -16188,7 +15953,7 @@ function Spreadsheet($$anchor, $$props) {
16188
15953
 
16189
15954
  {
16190
15955
  var consequent = ($$anchor) => {
16191
- var fragment = root();
15956
+ var fragment = root$1();
16192
15957
  var node_3 = first_child(fragment);
16193
15958
 
16194
15959
  Selector(node_3, spread_props(() => get(selector)));
@@ -16209,7 +15974,7 @@ function Spreadsheet($$anchor, $$props) {
16209
15974
 
16210
15975
  {
16211
15976
  var consequent_1 = ($$anchor) => {
16212
- var div_5 = root_1();
15977
+ var div_5 = root_1$1();
16213
15978
 
16214
15979
  template_effect(() => set_style(div_5, `left: ${get(fillPreview).x ?? ''}px; top: ${get(fillPreview).y ?? ''}px; width: ${get(fillPreview).width ?? ''}px; height: ${get(fillPreview).height ?? ''}px;`));
16215
15980
  append($$anchor, div_5);
@@ -16224,7 +15989,7 @@ function Spreadsheet($$anchor, $$props) {
16224
15989
 
16225
15990
  {
16226
15991
  var consequent_2 = ($$anchor) => {
16227
- var div_6 = root_2();
15992
+ var div_6 = root_2$1();
16228
15993
  var text_1 = child(div_6);
16229
15994
 
16230
15995
  template_effect(() => {
@@ -16244,7 +16009,7 @@ function Spreadsheet($$anchor, $$props) {
16244
16009
 
16245
16010
  {
16246
16011
  var consequent_3 = ($$anchor) => {
16247
- var fragment_1 = root_3();
16012
+ var fragment_1 = root_3$1();
16248
16013
  var div_7 = first_child(fragment_1);
16249
16014
  var node_7 = child(div_7);
16250
16015
 
@@ -16314,32 +16079,6 @@ function Spreadsheet($$anchor, $$props) {
16314
16079
 
16315
16080
  var node_9 = sibling(div_1, 2);
16316
16081
 
16317
- ContextMenu(node_9, {
16318
- get visible() {
16319
- return get(contextMenuVisible);
16320
- },
16321
-
16322
- get x() {
16323
- return get(contextMenuX);
16324
- },
16325
-
16326
- get y() {
16327
- return get(contextMenuY);
16328
- },
16329
-
16330
- get items() {
16331
- return contextMenuItems();
16332
- },
16333
-
16334
- get context() {
16335
- return get(contextMenuContext);
16336
- },
16337
- onItemClick: handleContextMenuItemClick,
16338
- onClose: closeContextMenu
16339
- });
16340
-
16341
- var node_10 = sibling(node_9, 2);
16342
-
16343
16082
  {
16344
16083
  var consequent_4 = ($$anchor) => {
16345
16084
  SheetTabs($$anchor, {
@@ -16386,7 +16125,7 @@ function Spreadsheet($$anchor, $$props) {
16386
16125
  });
16387
16126
  };
16388
16127
 
16389
- if_block(node_10, ($$render) => {
16128
+ if_block(node_9, ($$render) => {
16390
16129
  if (showSheetTabs()) $$render(consequent_4);
16391
16130
  });
16392
16131
  }
@@ -16399,7 +16138,7 @@ function Spreadsheet($$anchor, $$props) {
16399
16138
  });
16400
16139
 
16401
16140
  delegated('mousedown', canvas, onMouseDown);
16402
- delegated('contextmenu', canvas, onContextMenu);
16141
+ delegated('contextmenu', canvas, handleCanvasContextMenu);
16403
16142
  event('wheel', canvas, onWheel);
16404
16143
  delegated('keydown', canvas, onKeyDown);
16405
16144
  append($$anchor, div);
@@ -16421,6 +16160,7 @@ class Session {
16421
16160
  "activeSheetChange",
16422
16161
  "startEdit",
16423
16162
  "invalidFormula",
16163
+ "contextMenu",
16424
16164
  "error"
16425
16165
  ].forEach((type) => {
16426
16166
  this._listeners.set(type, /* @__PURE__ */ new Set());
@@ -16470,7 +16210,6 @@ class Session {
16470
16210
  config: this._config,
16471
16211
  showSheetTabs: options.showSheetTabs ?? true,
16472
16212
  showScrollbars: options.showScrollbars ?? true,
16473
- contextMenuItems: options.contextMenuItems ?? [],
16474
16213
  getIsEditingFormula: options.getIsEditingFormula,
16475
16214
  onSelectedDataChange: (data) => {
16476
16215
  this._selectedData = data;
@@ -16487,7 +16226,9 @@ class Session {
16487
16226
  onSheetsChange: (sheets) => {
16488
16227
  this._host.notifySheetsChange(sheets);
16489
16228
  },
16490
- onContextMenuItemClick: (_item, _context) => {
16229
+ // Engine renders no menu — surface the trigger so the host can.
16230
+ onContextMenu: (context, x, y) => {
16231
+ this._emit("contextMenu", { context, x, y });
16491
16232
  },
16492
16233
  onStartEdit: (row, col, initialText) => {
16493
16234
  this._emit("startEdit", { row, col, initialText });
@@ -16663,6 +16404,7 @@ const SESSION_EVENT_TYPES = [
16663
16404
  "activeSheetChange",
16664
16405
  "startEdit",
16665
16406
  "invalidFormula",
16407
+ "contextMenu",
16666
16408
  "error"
16667
16409
  ];
16668
16410
  function isSessionEvent(type) {
@@ -19894,4 +19636,420 @@ function convertCanvasPropsToAdapterProps(props) {
19894
19636
  };
19895
19637
  }
19896
19638
 
19639
+ var root = from_html(`<div class="menu-separator svelte-192vamk"></div>`);
19640
+ var root_1 = from_html(`<div class="menu-stepper svelte-192vamk" role="group"><span class="menu-icon-placeholder svelte-192vamk"></span> <span class="menu-label svelte-192vamk"> </span> <div class="stepper-control svelte-192vamk"><button type="button" class="stepper-btn svelte-192vamk" aria-label="decrease">−</button> <input class="stepper-input svelte-192vamk" type="number"/> <button type="button" class="stepper-btn svelte-192vamk" aria-label="increase">+</button></div></div> <!>`, 1);
19641
+ var root_2 = from_html(`<span class="menu-icon svelte-192vamk"> </span>`);
19642
+ var root_3 = from_html(`<span class="menu-icon-placeholder svelte-192vamk"></span>`);
19643
+ var root_4 = from_html(`<span class="menu-shortcut svelte-192vamk"> </span>`);
19644
+ var root_5 = from_html(`<span class="menu-arrow svelte-192vamk">▶</span>`);
19645
+ var root_6 = from_html(`<button role="menuitem"><!> <span class="menu-label svelte-192vamk"> </span> <!></button> <!>`, 1);
19646
+ var root_7 = from_html(`<div class="submenu svelte-192vamk"></div>`);
19647
+ var root_8 = from_html(`<div class="menu-item-wrapper svelte-192vamk"><button role="menuitem"><!> <span class="menu-label svelte-192vamk"> </span> <!> <!></button> <!></div> <!>`, 1);
19648
+ var root_9 = from_html(`<div class="context-menu svelte-192vamk" role="menu" tabindex="-1"></div>`);
19649
+
19650
+ function ContextMenu($$anchor, $$props) {
19651
+ push($$props, true);
19652
+
19653
+ // ========================================================================
19654
+ // Props
19655
+ // ========================================================================
19656
+ /** Whether the menu is visible */
19657
+ /** X position of the menu */
19658
+ /** Y position of the menu */
19659
+ /** Menu items to display */
19660
+ /** Context when menu was triggered */
19661
+ /**
19662
+ * Called when a menu item is clicked. `value` is the current amount
19663
+ * from a `stepper` item in the same menu (if any), so action items can
19664
+ * act on the user-chosen quantity.
19665
+ */
19666
+ /** Called when menu should close */
19667
+ // ========================================================================
19668
+ // State
19669
+ // ========================================================================
19670
+ let menuEl = state(null);
19671
+
19672
+ let adjustedX = state(0);
19673
+ let adjustedY = state(0);
19674
+ let activeSubmenu = state(null);
19675
+
19676
+ // Current value of each `stepper` item, keyed by item id. Reset to the
19677
+ // item's default every time the menu (re)opens so it tracks the latest
19678
+ // selection-derived default.
19679
+ let stepperValues = state(proxy({}));
19680
+
19681
+ user_effect(() => {
19682
+ if (!$$props.visible) return;
19683
+
19684
+ const next = {};
19685
+
19686
+ for (const it of $$props.items) {
19687
+ if (it.type === 'stepper') next[it.id] = it.value ?? it.min ?? 1;
19688
+ }
19689
+
19690
+ set(stepperValues, next, true);
19691
+ });
19692
+
19693
+ function clampStepper(item, v) {
19694
+ const min = item.min ?? 1;
19695
+ const max = item.max ?? 1000;
19696
+
19697
+ if (Number.isNaN(v)) return min;
19698
+
19699
+ return Math.min(max, Math.max(min, Math.round(v)));
19700
+ }
19701
+
19702
+ function adjustStepper(item, delta) {
19703
+ const cur = get(stepperValues)[item.id] ?? item.min ?? 1;
19704
+
19705
+ set(
19706
+ stepperValues,
19707
+ {
19708
+ ...get(stepperValues),
19709
+ [item.id]: clampStepper(item, cur + delta)
19710
+ },
19711
+ true
19712
+ );
19713
+ }
19714
+
19715
+ function setStepper(item, v) {
19716
+ set(stepperValues, { ...get(stepperValues), [item.id]: clampStepper(item, v) }, true);
19717
+ }
19718
+
19719
+ // The amount an action item should act on: the first stepper's value, or
19720
+ // undefined when the menu has no stepper.
19721
+ function currentStepperValue() {
19722
+ for (const it of $$props.items) {
19723
+ if (it.type === 'stepper') return get(stepperValues)[it.id];
19724
+ }
19725
+
19726
+ return undefined;
19727
+ }
19728
+
19729
+ // ========================================================================
19730
+ // Position adjustment to keep menu in viewport
19731
+ // ========================================================================
19732
+ user_effect(() => {
19733
+ if ($$props.visible && get(menuEl)) {
19734
+ const rect = get(menuEl).getBoundingClientRect();
19735
+ const viewportWidth = window.innerWidth;
19736
+ const viewportHeight = window.innerHeight;
19737
+ let newX = $$props.x;
19738
+ let newY = $$props.y;
19739
+
19740
+ // Adjust horizontal position
19741
+ if ($$props.x + rect.width > viewportWidth - 10) {
19742
+ newX = viewportWidth - rect.width - 10;
19743
+ }
19744
+
19745
+ // Adjust vertical position
19746
+ if ($$props.y + rect.height > viewportHeight - 10) {
19747
+ newY = viewportHeight - rect.height - 10;
19748
+ }
19749
+
19750
+ set(adjustedX, Math.max(10, newX), true);
19751
+ set(adjustedY, Math.max(10, newY), true);
19752
+ }
19753
+ });
19754
+
19755
+ // ========================================================================
19756
+ // Event Handlers
19757
+ // ========================================================================
19758
+ function handleItemClick(item, e) {
19759
+ e.stopPropagation();
19760
+
19761
+ if (item.disabled) return;
19762
+
19763
+ if (item.children && item.children.length > 0) {
19764
+ // Toggle submenu
19765
+ set(activeSubmenu, get(activeSubmenu) === item.id ? null : item.id, true);
19766
+
19767
+ return;
19768
+ }
19769
+
19770
+ $$props.onItemClick?.(item, $$props.context, currentStepperValue());
19771
+ $$props.onClose?.();
19772
+ }
19773
+
19774
+ function handleKeyDown(e) {
19775
+ if (e.key === 'Escape') {
19776
+ $$props.onClose?.();
19777
+ }
19778
+ }
19779
+
19780
+ function handleClickOutside(e) {
19781
+ if (get(menuEl) && !get(menuEl).contains(e.target)) {
19782
+ $$props.onClose?.();
19783
+ }
19784
+ }
19785
+
19786
+ onMount(() => {
19787
+ document.addEventListener('mousedown', handleClickOutside);
19788
+
19789
+ return () => {
19790
+ document.removeEventListener('mousedown', handleClickOutside);
19791
+ };
19792
+ });
19793
+
19794
+ var fragment = comment();
19795
+
19796
+ event('keydown', $window, handleKeyDown);
19797
+
19798
+ var node = first_child(fragment);
19799
+
19800
+ {
19801
+ var consequent_10 = ($$anchor) => {
19802
+ var div = root_9();
19803
+
19804
+ each(div, 21, () => $$props.items, (item) => item.id, ($$anchor, item) => {
19805
+ var fragment_1 = comment();
19806
+ var node_1 = first_child(fragment_1);
19807
+
19808
+ {
19809
+ var consequent_1 = ($$anchor) => {
19810
+ var fragment_2 = root_1();
19811
+ var div_1 = first_child(fragment_2);
19812
+ var span = sibling(child(div_1), 2);
19813
+ var text = child(span);
19814
+
19815
+ var div_2 = sibling(span, 2);
19816
+ var button = child(div_2);
19817
+ var input = sibling(button, 2);
19818
+
19819
+ var button_1 = sibling(input, 2);
19820
+
19821
+ var node_2 = sibling(div_1, 2);
19822
+
19823
+ {
19824
+ var consequent = ($$anchor) => {
19825
+ var div_3 = root();
19826
+
19827
+ append($$anchor, div_3);
19828
+ };
19829
+
19830
+ if_block(node_2, ($$render) => {
19831
+ if (get(item).separator) $$render(consequent);
19832
+ });
19833
+ }
19834
+
19835
+ template_effect(() => {
19836
+ set_attribute(div_1, 'aria-label', get(item).label);
19837
+ set_text(text, get(item).label);
19838
+ set_attribute(input, 'min', get(item).min ?? 1);
19839
+ set_attribute(input, 'max', get(item).max ?? 1000);
19840
+ set_value(input, get(stepperValues)[get(item).id] ?? get(item).min ?? 1);
19841
+ });
19842
+
19843
+ delegated('click', button, (e) => {
19844
+ e.stopPropagation();
19845
+ adjustStepper(get(item), -1);
19846
+ });
19847
+
19848
+ delegated('click', input, (e) => e.stopPropagation());
19849
+ delegated('input', input, (e) => setStepper(get(item), parseInt(e.currentTarget.value, 10)));
19850
+
19851
+ delegated('click', button_1, (e) => {
19852
+ e.stopPropagation();
19853
+ adjustStepper(get(item), 1);
19854
+ });
19855
+
19856
+ append($$anchor, fragment_2);
19857
+ };
19858
+
19859
+ var alternate_2 = ($$anchor) => {
19860
+ var fragment_3 = root_8();
19861
+ var div_4 = first_child(fragment_3);
19862
+ var button_2 = child(div_4);
19863
+ let classes;
19864
+ var node_3 = child(button_2);
19865
+
19866
+ {
19867
+ var consequent_2 = ($$anchor) => {
19868
+ var span_1 = root_2();
19869
+ var text_1 = child(span_1);
19870
+ template_effect(() => set_text(text_1, get(item).icon));
19871
+ append($$anchor, span_1);
19872
+ };
19873
+
19874
+ var alternate = ($$anchor) => {
19875
+ var span_2 = root_3();
19876
+
19877
+ append($$anchor, span_2);
19878
+ };
19879
+
19880
+ if_block(node_3, ($$render) => {
19881
+ if (get(item).icon) $$render(consequent_2); else $$render(alternate, -1);
19882
+ });
19883
+ }
19884
+
19885
+ var span_3 = sibling(node_3, 2);
19886
+ var text_2 = child(span_3);
19887
+
19888
+ var node_4 = sibling(span_3, 2);
19889
+
19890
+ {
19891
+ var consequent_3 = ($$anchor) => {
19892
+ var span_4 = root_4();
19893
+ var text_3 = child(span_4);
19894
+ template_effect(() => set_text(text_3, get(item).shortcut));
19895
+ append($$anchor, span_4);
19896
+ };
19897
+
19898
+ if_block(node_4, ($$render) => {
19899
+ if (get(item).shortcut) $$render(consequent_3);
19900
+ });
19901
+ }
19902
+
19903
+ var node_5 = sibling(node_4, 2);
19904
+
19905
+ {
19906
+ var consequent_4 = ($$anchor) => {
19907
+ var span_5 = root_5();
19908
+
19909
+ append($$anchor, span_5);
19910
+ };
19911
+
19912
+ if_block(node_5, ($$render) => {
19913
+ if (get(item).children && get(item).children.length > 0) $$render(consequent_4);
19914
+ });
19915
+ }
19916
+
19917
+ var node_6 = sibling(button_2, 2);
19918
+
19919
+ {
19920
+ var consequent_8 = ($$anchor) => {
19921
+ var div_5 = root_7();
19922
+
19923
+ each(div_5, 21, () => get(item).children, (child) => child.id, ($$anchor, child$1) => {
19924
+ var fragment_4 = root_6();
19925
+ var button_3 = first_child(fragment_4);
19926
+ let classes_1;
19927
+ var node_7 = child(button_3);
19928
+
19929
+ {
19930
+ var consequent_5 = ($$anchor) => {
19931
+ var span_6 = root_2();
19932
+ var text_4 = child(span_6);
19933
+ template_effect(() => set_text(text_4, get(child$1).icon));
19934
+ append($$anchor, span_6);
19935
+ };
19936
+
19937
+ var alternate_1 = ($$anchor) => {
19938
+ var span_7 = root_3();
19939
+
19940
+ append($$anchor, span_7);
19941
+ };
19942
+
19943
+ if_block(node_7, ($$render) => {
19944
+ if (get(child$1).icon) $$render(consequent_5); else $$render(alternate_1, -1);
19945
+ });
19946
+ }
19947
+
19948
+ var span_8 = sibling(node_7, 2);
19949
+ var text_5 = child(span_8);
19950
+
19951
+ var node_8 = sibling(span_8, 2);
19952
+
19953
+ {
19954
+ var consequent_6 = ($$anchor) => {
19955
+ var span_9 = root_4();
19956
+ var text_6 = child(span_9);
19957
+ template_effect(() => set_text(text_6, get(child$1).shortcut));
19958
+ append($$anchor, span_9);
19959
+ };
19960
+
19961
+ if_block(node_8, ($$render) => {
19962
+ if (get(child$1).shortcut) $$render(consequent_6);
19963
+ });
19964
+ }
19965
+
19966
+ var node_9 = sibling(button_3, 2);
19967
+
19968
+ {
19969
+ var consequent_7 = ($$anchor) => {
19970
+ var div_6 = root();
19971
+
19972
+ append($$anchor, div_6);
19973
+ };
19974
+
19975
+ if_block(node_9, ($$render) => {
19976
+ if (get(child$1).separator) $$render(consequent_7);
19977
+ });
19978
+ }
19979
+
19980
+ template_effect(() => {
19981
+ classes_1 = set_class(button_3, 1, 'menu-item svelte-192vamk', null, classes_1, { disabled: get(child$1).disabled });
19982
+ set_attribute(button_3, 'aria-disabled', get(child$1).disabled);
19983
+ set_text(text_5, get(child$1).label);
19984
+ });
19985
+
19986
+ delegated('click', button_3, (e) => handleItemClick(get(child$1), e));
19987
+ append($$anchor, fragment_4);
19988
+ });
19989
+ append($$anchor, div_5);
19990
+ };
19991
+
19992
+ if_block(node_6, ($$render) => {
19993
+ if (get(item).children && get(item).children.length > 0 && get(activeSubmenu) === get(item).id) $$render(consequent_8);
19994
+ });
19995
+ }
19996
+
19997
+ var node_10 = sibling(div_4, 2);
19998
+
19999
+ {
20000
+ var consequent_9 = ($$anchor) => {
20001
+ var div_7 = root();
20002
+
20003
+ append($$anchor, div_7);
20004
+ };
20005
+
20006
+ if_block(node_10, ($$render) => {
20007
+ if (get(item).separator) $$render(consequent_9);
20008
+ });
20009
+ }
20010
+
20011
+ template_effect(() => {
20012
+ classes = set_class(button_2, 1, 'menu-item svelte-192vamk', null, classes, {
20013
+ disabled: get(item).disabled,
20014
+ 'has-children': get(item).children && get(item).children.length > 0
20015
+ });
20016
+
20017
+ set_attribute(button_2, 'aria-disabled', get(item).disabled);
20018
+ set_text(text_2, get(item).label);
20019
+ });
20020
+
20021
+ delegated('click', button_2, (e) => handleItemClick(get(item), e));
20022
+
20023
+ event('mouseenter', button_2, () => {
20024
+ if (get(item).children && get(item).children.length > 0) {
20025
+ set(activeSubmenu, get(item).id, true);
20026
+ }
20027
+ });
20028
+
20029
+ append($$anchor, fragment_3);
20030
+ };
20031
+
20032
+ if_block(node_1, ($$render) => {
20033
+ if (get(item).type === 'stepper') $$render(consequent_1); else $$render(alternate_2, -1);
20034
+ });
20035
+ }
20036
+
20037
+ append($$anchor, fragment_1);
20038
+ });
20039
+ bind_this(div, ($$value) => set(menuEl, $$value), () => get(menuEl));
20040
+ template_effect(() => set_style(div, `left: ${get(adjustedX) ?? ''}px; top: ${get(adjustedY) ?? ''}px;`));
20041
+ append($$anchor, div);
20042
+ };
20043
+
20044
+ if_block(node, ($$render) => {
20045
+ if ($$props.visible) $$render(consequent_10);
20046
+ });
20047
+ }
20048
+
20049
+ append($$anchor, fragment);
20050
+ pop();
20051
+ }
20052
+
20053
+ delegate(['click', 'input']);
20054
+
19897
20055
  export { ActionEffectBuilder, AsyncFuncResultBuilder, BindFormSchemaBuilder, BindRandomSchemaBuilder, BlockInputBuilder, BlockLineNameFieldUpdateBuilder, BlockLineStyleUpdateBuilder, BlockManager, BlockStyleUpdateBuilder, Calculator, Cell$1 as Cell, Cell as CellClass, CellClearBuilder, CellFormatBrushBuilder, CellInputBuilder, CellStyleUpdateBuilder, CellValue, ColumnHeaders, ContextMenu, ConvertBlockBuilder, CraftCalc, CreateAppendixBuilder, CreateBlockBuilder, CreateDiyCellBuilder, CreateDiyCellByIdBuilder, CreateSheetBuilder, CustomFunc, DEFAULT_ENGINE_CONFIG, DataService, DeleteColsBuilder, DeleteColsInBlockBuilder, DeleteRowsBuilder, DeleteRowsInBlockBuilder, DeleteSheetBuilder, Engine, EnumSetManager, EphemeralCellInputBuilder, EphemeralCellRemoveBuilder, EphemeralCellStyleUpdateBuilder, FIELD_AND_VALIDATION_TAG, FieldManager, InsertColsBuilder, InsertColsInBlockBuilder, InsertRowsBuilder, InsertRowsInBlockBuilder, LOGISHEETS_BUILTIN_CRAFT_ID, LineFormatBrushBuilder, LineStyleUpdateBuilder, MergeCellsBuilder, MoveBlockBuilder, MoveBlockLineBuilder, OffscreenClient, OffscreenWorkerService, RandomSchemaUnitBuilder, Range$1 as RangeClass, RemoveAppendixBuilder, RemoveBlockBuilder, RemoveDiyCellBuilder, RemoveDiyCellByIdBuilder, ReproduceCellsBuilder, ResizeBlockBuilder, RestoreCheckpointBuilder, RowHeaders, Scrollbar, Selector, Session, SetColWidthBuilder, SetRowHeightBuilder, SetSheetColorBuilder, SetSheetVisibleBuilder, SetVisibleBuilder, SheetCellIdBuilder, SheetColIdBuilder, SheetRenameBuilder, SheetRowIdBuilder, SheetTabs, SplitMergedCellsBuilder, Spreadsheet, StyleUpdateTypeBuilder, UpsertFieldFormulasBuilder, UpsertFieldRenderInfoBuilder, Workbook, WorkbookClient, WorkbookWorkerService, Worksheet, acquireCraftCalc, buildSelectedDataFromCell, buildSelectedDataFromCellRange, buildSelectedDataFromLines, convertCanvasPropsToAdapterProps, Engine as default, findVisibleColIdxRange, findVisibleRowIdxRange, getCellRect, getFirstCell, getPatternFill, getPosition, getReferenceHighlightRects, getReferenceString, getSelectedCellRange, getSelectedColumns, getSelectedLines, getSelectedRows, __wbg_init as initWasm, isCellInGridWindow, isErrorMessage, match, ptToPx$1 as ptToPx, pxToPt$1 as pxToPt, pxToWidth$1 as pxToWidth, simpleUuid, toA1notation$1 as toA1notation, xForColEnd, xForColStart, yForRowEnd, yForRowStart };