wordinweb 0.1.13 → 0.1.14

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.
package/dist/index.js CHANGED
@@ -10,8 +10,8 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
10
10
  if (typeof require !== "undefined") return require.apply(this, arguments);
11
11
  throw Error('Dynamic require of "' + x + '" is not supported');
12
12
  });
13
- var __commonJS = (cb, mod) => function __require2() {
14
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
13
+ var __commonJS = (cb, mod2) => function __require2() {
14
+ return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
15
15
  };
16
16
  var __copyProps = (to, from, except, desc) => {
17
17
  if (from && typeof from === "object" || typeof from === "function") {
@@ -21,13 +21,13 @@ var __copyProps = (to, from, except, desc) => {
21
21
  }
22
22
  return to;
23
23
  };
24
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
25
25
  // If the importer is in node compatibility mode or this is not an ESM
26
26
  // file that has been converted to a CommonJS file using a Babel-
27
27
  // compatible transform (i.e. "__esModule" has not been set), then set
28
28
  // "default" to the CommonJS "module.exports" for node compatibility.
29
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
- mod
29
+ isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target,
30
+ mod2
31
31
  ));
32
32
 
33
33
  // (disabled):fs
@@ -1923,7 +1923,7 @@ var require_cfb = __commonJS({
1923
1923
  });
1924
1924
 
1925
1925
  // src/index.tsx
1926
- import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
1926
+ import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
1927
1927
 
1928
1928
  // ../core/src/units.ts
1929
1929
  var PX_PER_PT = 96 / 72;
@@ -4484,7 +4484,7 @@ function parseDrawing(drawing, ctx) {
4484
4484
  }
4485
4485
  };
4486
4486
  }
4487
- if (anchor && (paths.length > 0 || lines.length + images.length > 1 || texts.length > 0)) {
4487
+ if (anchor && (paths.length > 0 || lines.length > 0 || images.length > 1 || texts.length > 0)) {
4488
4488
  const docPr = child(anchor, "docPr");
4489
4489
  const docPrName = attr(docPr, "name") ?? "";
4490
4490
  const ink = attr(docPr, "descr") === "WordInWeb ink" || /^Ink(?:\s|$)/i.test(docPrName);
@@ -11327,7 +11327,12 @@ function laidOutPage(p) {
11327
11327
  items: p.items,
11328
11328
  bodyTop: p.bodyTop,
11329
11329
  bodyBottom: p.bodyBottom,
11330
- hfStart: p.hfStart ?? p.items.length
11330
+ hfStart: p.hfStart ?? p.items.length,
11331
+ columnBands: p.bands.map((band) => ({
11332
+ top: band.top,
11333
+ colXs: [...band.colXs],
11334
+ colWidths: [...band.colWidths]
11335
+ }))
11331
11336
  };
11332
11337
  }
11333
11338
  var PAGE_FMT = {
@@ -14961,19 +14966,19 @@ var Engine = class {
14961
14966
  for (const pth of shape.paths) {
14962
14967
  const x = ox + pth.x - fx;
14963
14968
  const y = oy + pth.y - fy;
14964
- page.items.push({ kind: "path", x, y, width: pth.width, height: pth.height, d: pth.d, viewW: pth.viewW, viewH: pth.viewH, fill: pth.fill, stroke: pth.stroke, ...rotate ? { rotate: rotate(x, y) } : {}, z: shape.z });
14969
+ page.items.push({ kind: "path", x, y, width: pth.width, height: pth.height, d: pth.d, viewW: pth.viewW, viewH: pth.viewH, fill: pth.fill, stroke: pth.stroke, ...rotate ? { rotate: rotate(x, y) } : {}, ...shape.behind ? { behind: true } : { front: true }, z: shape.z });
14965
14970
  }
14966
14971
  for (const l of shape.lines) {
14967
14972
  const x1 = ox + l.x1 - fx;
14968
14973
  const y1 = oy + l.y1 - fy;
14969
14974
  const x2 = ox + l.x2 - fx;
14970
14975
  const y2 = oy + l.y2 - fy;
14971
- page.items.push({ kind: "edge", x1, y1, x2, y2, border: { style: "single", width: l.weight, color: l.color, space: 0 }, ...rotate ? { rotate: rotate(Math.min(x1, x2), Math.min(y1, y2)) } : {}, z: shape.z });
14976
+ page.items.push({ kind: "edge", x1, y1, x2, y2, border: { style: "single", width: l.weight, color: l.color, space: 0 }, ...rotate ? { rotate: rotate(Math.min(x1, x2), Math.min(y1, y2)) } : {}, ...shape.behind ? { behind: true } : { front: true }, z: shape.z });
14972
14977
  }
14973
14978
  for (const img of shape.images) {
14974
14979
  const x = ox + img.x - fx;
14975
14980
  const y = oy + img.y - fy;
14976
- page.items.push({ kind: "image", x, y, width: img.width, height: img.height, part: img.part, behind: shape.behind, ...rotate ? { rotate: rotate(x, y) } : {}, z: shape.z });
14981
+ page.items.push({ kind: "image", x, y, width: img.width, height: img.height, part: img.part, behind: shape.behind, ...!shape.behind ? { front: true } : {}, ...rotate ? { rotate: rotate(x, y) } : {}, z: shape.z });
14977
14982
  }
14978
14983
  if (shape.srcDrawing) {
14979
14984
  page.items.push({
@@ -14986,6 +14991,7 @@ var Engine = class {
14986
14991
  anchored: true,
14987
14992
  ink: shape.ink,
14988
14993
  belowText: !shape.behind,
14994
+ behind: shape.behind,
14989
14995
  ...rotate ? { rotate: rotate(ox - fx, oy - fy) } : {},
14990
14996
  z: shape.z
14991
14997
  });
@@ -15125,6 +15131,7 @@ var Engine = class {
15125
15131
  y2,
15126
15132
  border: b,
15127
15133
  ...rotate ? { rotate: rotate(Math.min(x1, x2), Math.min(y1, y2)) } : {},
15134
+ ...behind ? { behind: true } : {},
15128
15135
  ...front ? { front: true } : {},
15129
15136
  z: shape.z
15130
15137
  });
@@ -15145,7 +15152,7 @@ var Engine = class {
15145
15152
  const texts = inner.items.filter((it) => it.kind === "text");
15146
15153
  const str = texts.map((it) => it.text).join("").replace(/\s+/g, " ").trim();
15147
15154
  if (str) {
15148
- if (front && shape.srcDrawing) {
15155
+ if (shape.srcDrawing) {
15149
15156
  page.items.push({
15150
15157
  kind: "drawingHit",
15151
15158
  x: ox - fx,
@@ -15155,8 +15162,9 @@ var Engine = class {
15155
15162
  src: shape.srcDrawing,
15156
15163
  anchored: true,
15157
15164
  belowText: true,
15165
+ ...behind ? { behind: true } : {},
15158
15166
  ...rotate ? { rotate: rotate(ox - fx, oy - fy) } : {},
15159
- z: shape.z
15167
+ z: shape.wordArt ? (shape.z ?? 0) + 1 : shape.z
15160
15168
  });
15161
15169
  }
15162
15170
  const f = texts[0].font;
@@ -15194,7 +15202,7 @@ var Engine = class {
15194
15202
  this.textboxChains.set(shape.chainId, { blocks: storyBlocks, consumedY: cut });
15195
15203
  }
15196
15204
  const independentStory = !!shape.textboxStory && !shape.wordArt;
15197
- if (front && shape.srcDrawing) {
15205
+ if (shape.srcDrawing) {
15198
15206
  page.items.push({
15199
15207
  kind: "drawingHit",
15200
15208
  x: ox - fx,
@@ -15204,9 +15212,10 @@ var Engine = class {
15204
15212
  src: shape.srcDrawing,
15205
15213
  anchored: true,
15206
15214
  belowText: !shape.wordArt,
15215
+ ...behind ? { behind: true } : {},
15207
15216
  ...independentStory ? { textboxStory: true } : {},
15208
15217
  ...rotate ? { rotate: rotate(ox - fx, oy - fy) } : {},
15209
- z: shape.z
15218
+ z: shape.wordArt ? (shape.z ?? 0) + 1 : shape.z
15210
15219
  });
15211
15220
  }
15212
15221
  for (const it of inner.items) {
@@ -15223,7 +15232,7 @@ var Engine = class {
15223
15232
  } else if (rotate && it.kind === "edge") {
15224
15233
  it.rotate = rotate(Math.min(it.x1, it.x2), Math.min(it.y1, it.y2));
15225
15234
  }
15226
- if (behind && (it.kind === "text" || it.kind === "rect")) it.behind = true;
15235
+ if (behind && (it.kind === "text" || it.kind === "rect" || it.kind === "edge" || it.kind === "image" || it.kind === "path" || it.kind === "drawingHit")) it.behind = true;
15227
15236
  if (front && (it.kind === "text" || it.kind === "rect" || it.kind === "edge")) it.front = true;
15228
15237
  if (it.kind === "text" || it.kind === "rect" || it.kind === "edge" || it.kind === "image" || it.kind === "path" || it.kind === "drawingHit") it.z = shape.z;
15229
15238
  page.items.push(it);
@@ -17571,7 +17580,7 @@ function itemEq(a, b, depth) {
17571
17580
  }
17572
17581
  function pageEq(a, b) {
17573
17582
  if (a === b) return true;
17574
- if (a.width !== b.width || a.height !== b.height || a.number !== b.number || a.index !== b.index || a.bodyTop !== b.bodyTop || a.bodyBottom !== b.bodyBottom || a.hfStart !== b.hfStart || a.items.length !== b.items.length) {
17583
+ if (a.width !== b.width || a.height !== b.height || a.number !== b.number || a.index !== b.index || a.bodyTop !== b.bodyTop || a.bodyBottom !== b.bodyBottom || a.hfStart !== b.hfStart || JSON.stringify(a.columnBands) !== JSON.stringify(b.columnBands) || a.items.length !== b.items.length) {
17575
17584
  return false;
17576
17585
  }
17577
17586
  for (let i = 0; i < a.items.length; i++) {
@@ -17715,6 +17724,7 @@ function renderPageShell(page, zoom, options) {
17715
17724
  }
17716
17725
  el16.dataset.bodyTop = String(page.bodyTop);
17717
17726
  el16.dataset.bodyBottom = String(page.bodyBottom);
17727
+ el16.dataset.columnBands = JSON.stringify(page.columnBands);
17718
17728
  return el16;
17719
17729
  }
17720
17730
  function renderEmptyPageRecord(page, zoom, options) {
@@ -18398,6 +18408,7 @@ function ensureStylesheet() {
18398
18408
  .dxw-body-mode .dxw-page span[data-dxw-hf]:not([data-dxw-textbox-story]),
18399
18409
  .dxw-body-mode .dxw-page a[data-dxw-hf]:not([data-dxw-textbox-story]),
18400
18410
  .dxw-body-mode .dxw-page img[data-dxw-hf] { opacity: .55; }
18411
+ .dxw-body-mode .dxw-page [data-dxw-drawing][data-dxw-hf]:not([data-dxw-textbox-story-object]) { pointer-events: none; }
18401
18412
  .dxw-comment-hl { background: var(--dxw-comment-hl, rgba(255, 200, 90, .38)); }
18402
18413
  .dxw-comment-hl.dxw-hot { background: var(--dxw-comment-hl-active, rgba(255, 170, 0, .55)); }
18403
18414
  .dxw-comment-card {
@@ -18655,7 +18666,7 @@ function renderItem(doc, item, urls, interactive) {
18655
18666
  hit.style.width = `${item.width}px`;
18656
18667
  hit.style.height = `${item.height}px`;
18657
18668
  hit.style.cursor = "move";
18658
- hit.style.zIndex = item.z !== void 0 ? String(item.z) : item.belowText ? "1" : "6";
18669
+ hit.style.zIndex = item.behind ? "-1" : item.z !== void 0 ? String(item.z) : item.belowText ? "1" : "6";
18659
18670
  if (item.rotate) {
18660
18671
  hit.style.transform = `rotate(${item.rotate.deg}deg)`;
18661
18672
  hit.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
@@ -18969,7 +18980,7 @@ function renderItem(doc, item, urls, interactive) {
18969
18980
  return node;
18970
18981
  }
18971
18982
  case "text":
18972
- return renderText(item);
18983
+ return renderText(item, interactive);
18973
18984
  case "wordart":
18974
18985
  return renderWordArt(item);
18975
18986
  case "warptext":
@@ -19234,7 +19245,7 @@ function renderWarpText(item) {
19234
19245
  svg.appendChild(text);
19235
19246
  return svg;
19236
19247
  }
19237
- function renderText(item) {
19248
+ function renderText(item, interactive) {
19238
19249
  const tag = item.href ? "a" : "span";
19239
19250
  const el16 = document.createElement(tag);
19240
19251
  el16.style.position = "absolute";
@@ -19325,9 +19336,22 @@ function renderText(item) {
19325
19336
  el16.style.cursor = "pointer";
19326
19337
  }
19327
19338
  if (item.href) {
19328
- el16.href = item.href;
19329
- el16.target = "_blank";
19330
- el16.rel = "noreferrer noopener";
19339
+ const anchor = el16;
19340
+ anchor.href = item.href;
19341
+ anchor.target = "_blank";
19342
+ anchor.rel = "noreferrer noopener";
19343
+ anchor.title = item.href;
19344
+ if (interactive) {
19345
+ anchor.addEventListener("mouseup", (event) => {
19346
+ if (event.metaKey || event.ctrlKey) event.stopPropagation();
19347
+ });
19348
+ anchor.addEventListener("click", (event) => {
19349
+ event.preventDefault();
19350
+ if (event.metaKey || event.ctrlKey) {
19351
+ window.open(anchor.href, "_blank", "noopener,noreferrer");
19352
+ }
19353
+ });
19354
+ }
19331
19355
  if (!props.color) el16.style.color = "#0563c1";
19332
19356
  }
19333
19357
  if (item.rotate) {
@@ -19653,7 +19677,11 @@ function setPageLayout(doc, patch, target) {
19653
19677
  if (patch.columns !== void 0) {
19654
19678
  sectPr.children = sectPr.children.filter((c) => localName(c.name) !== "cols");
19655
19679
  if (patch.columns > 1) {
19656
- const cols = el2(`${w}cols`, { [`${w}num`]: String(patch.columns), [`${w}space`]: "720" });
19680
+ const cols = el2(`${w}cols`, {
19681
+ [`${w}num`]: String(patch.columns),
19682
+ [`${w}space`]: "720",
19683
+ ...patch.columnSeparator ? { [`${w}sep`]: "1" } : {}
19684
+ });
19657
19685
  const idx = sectPr.children.indexOf(pgMar);
19658
19686
  sectPr.children.splice(idx + 1, 0, cols);
19659
19687
  }
@@ -20638,12 +20666,26 @@ function resizeDrawing(doc, drawingEl, widthPx, heightPx) {
20638
20666
  const EMU = 9525;
20639
20667
  const cx = String(Math.max(Math.round(widthPx * EMU), EMU));
20640
20668
  const cy = String(Math.max(Math.round(heightPx * EMU), EMU));
20669
+ let lineExtent;
20670
+ const findLineExtent = (node) => {
20671
+ if (lineExtent) return;
20672
+ if (localName(node.name) === "spPr") {
20673
+ const preset = attr(child(node, "prstGeom"), "prst") ?? "";
20674
+ if (preset === "line" || preset.startsWith("straightConnector")) {
20675
+ lineExtent = child(child(node, "xfrm"), "ext");
20676
+ return;
20677
+ }
20678
+ }
20679
+ for (const childNode of node.children) findLineExtent(childNode);
20680
+ };
20681
+ findLineExtent(drawingEl);
20682
+ const keepHorizontal = lineExtent ? parseInt(lineExtent.attrs[Object.keys(lineExtent.attrs).find((key) => localName(key) === "cy") ?? "cy"] ?? "0", 10) === 0 : false;
20641
20683
  let touched = false;
20642
20684
  const setExt = (el16) => {
20643
20685
  const cxKey = Object.keys(el16.attrs).find((k) => localName(k) === "cx") ?? "cx";
20644
20686
  const cyKey = Object.keys(el16.attrs).find((k) => localName(k) === "cy") ?? "cy";
20645
20687
  el16.attrs[cxKey] = cx;
20646
- el16.attrs[cyKey] = cy;
20688
+ el16.attrs[cyKey] = el16 === lineExtent && keepHorizontal ? "0" : cy;
20647
20689
  touched = true;
20648
20690
  };
20649
20691
  const walk2 = (el16, insideGroup) => {
@@ -20919,10 +20961,23 @@ function sectPrAt(doc, t) {
20919
20961
  }
20920
20962
  return seen ? bodySectPr : bodySectPr;
20921
20963
  }
20964
+ function sectionContextAt(doc, t) {
20965
+ const body = bodyOf(doc);
20966
+ const target = sectPrAt(doc, t);
20967
+ if (!body || !target) return null;
20968
+ const sections = [];
20969
+ const visit = (node) => {
20970
+ if (localName(node.name) === "sectPr") sections.push(node);
20971
+ else for (const child4 of node.children) visit(child4);
20972
+ };
20973
+ visit(body);
20974
+ const index = sections.indexOf(target);
20975
+ return index < 0 ? null : { index: index + 1, count: sections.length };
20976
+ }
20922
20977
  function insertBreakAt(doc, t, offset, kind) {
20923
20978
  const rEl = doc.findParentOf(t);
20924
20979
  const pEl = rEl && doc.findParentOf(rEl);
20925
- if (!rEl || !pEl || localName(rEl.name) !== "r") return false;
20980
+ if (!rEl || !pEl || localName(rEl.name) !== "r") return null;
20926
20981
  const rw = rEl.name.includes(":") ? rEl.name.slice(0, rEl.name.indexOf(":") + 1) : "";
20927
20982
  const rPr = rEl.children.find((c) => localName(c.name) === "rPr");
20928
20983
  const brRun = el4(`${rw}r`, {}, [
@@ -20930,8 +20985,11 @@ function insertBreakAt(doc, t, offset, kind) {
20930
20985
  el4(`${rw}br`, { [`${rw}type`]: kind })
20931
20986
  ]);
20932
20987
  const rIdx = pEl.children.indexOf(rEl);
20988
+ let destination = t;
20933
20989
  if (offset >= t.text.length) {
20934
- pEl.children.splice(rIdx + 1, 0, brRun);
20990
+ destination = el4(`${rw}t`, { "xml:space": "preserve" }, [], "");
20991
+ const tail = el4(`${rw}r`, {}, [...rPr ? [cloneDeep(rPr)] : [], destination]);
20992
+ pEl.children.splice(rIdx + 1, 0, brRun, tail);
20935
20993
  } else if (offset <= 0) {
20936
20994
  pEl.children.splice(rIdx, 0, brRun);
20937
20995
  } else {
@@ -20939,9 +20997,10 @@ function insertBreakAt(doc, t, offset, kind) {
20939
20997
  t.text = t.text.slice(0, offset);
20940
20998
  const tail = el4(`${rw}r`, {}, [...rPr ? [cloneDeep(rPr)] : [], tailT]);
20941
20999
  pEl.children.splice(rIdx + 1, 0, brRun, tail);
21000
+ destination = tailT;
20942
21001
  }
20943
21002
  doc.refresh();
20944
- return true;
21003
+ return { t: destination, offset: 0 };
20945
21004
  }
20946
21005
  function insertBlankPageAt(doc, t, offset) {
20947
21006
  const rEl = doc.findParentOf(t);
@@ -21626,13 +21685,14 @@ function insertShapeAt(doc, caretT, preset, text = "") {
21626
21685
  const height = isLine ? 2 : preset === "textBox" ? 72 : 96;
21627
21686
  const cx = String(Math.round(width * EMU_PER_PX4));
21628
21687
  const cy = String(Math.round(height * EMU_PER_PX4));
21688
+ const shapeCy = isLine ? "0" : cy;
21629
21689
  const geometry = preset === "roundedRectangle" ? "roundRect" : preset === "rectangle" || preset === "textBox" ? "rect" : preset;
21630
21690
  const isTextBox = preset === "textBox";
21631
21691
  const shapeName = isLine ? `Line ${id}` : isTextBox ? `Text Box ${id}` : `Shape ${id}`;
21632
21692
  const spPr = [
21633
21693
  el6("a:xfrm", {}, [
21634
21694
  el6("a:off", { x: "0", y: "0" }),
21635
- el6("a:ext", { cx, cy })
21695
+ el6("a:ext", { cx, cy: shapeCy })
21636
21696
  ]),
21637
21697
  el6("a:prstGeom", { prst: geometry }, [el6("a:avLst")]),
21638
21698
  isTextBox || isLine ? el6("a:noFill") : el6("a:solidFill", {}, [el6("a:srgbClr", { val: "4472C4" })]),
@@ -21734,6 +21794,10 @@ function insertWordArtAt(doc, caretT, text, preset = "plain") {
21734
21794
  function isDrawingWordArt(drawing) {
21735
21795
  return (descendant3(drawing, "docPr")?.attrs.name ?? "").startsWith("WordArt ");
21736
21796
  }
21797
+ function isDrawingLine(drawing) {
21798
+ const preset = descendant3(drawing, "prstGeom")?.attrs.prst ?? "";
21799
+ return preset === "line" || preset.startsWith("straightConnector");
21800
+ }
21737
21801
  function drawingWordArtText(drawing) {
21738
21802
  return isDrawingWordArt(drawing) ? descendant3(drawing, "t")?.text ?? "" : "";
21739
21803
  }
@@ -21746,15 +21810,42 @@ function setDrawingWordArtText(doc, drawing, text) {
21746
21810
  return true;
21747
21811
  }
21748
21812
  function drawingLineStyle(drawing) {
21813
+ const spPr = descendant3(drawing, "spPr");
21814
+ if (!spPr) return null;
21749
21815
  const line2 = descendant3(drawing, "ln");
21750
- if (!line2) return null;
21816
+ if (!line2) return { color: "#000000", width: 0.75 };
21751
21817
  const color = descendant3(line2, "srgbClr")?.attrs.val ?? "000000";
21752
21818
  const width = Math.max((parseInt(line2.attrs.w ?? "0", 10) || 0) / EMU_PER_PX4, 0.75);
21753
21819
  return { color: `#${color.toUpperCase()}`, width };
21754
21820
  }
21821
+ function drawingFillColor(drawing) {
21822
+ const spPr = descendant3(drawing, "spPr");
21823
+ if (!spPr || spPr.children.some((child4) => localName(child4.name) === "noFill")) return null;
21824
+ const solidFill = spPr.children.find((child4) => localName(child4.name) === "solidFill");
21825
+ const color = solidFill ? descendant3(solidFill, "srgbClr")?.attrs.val : void 0;
21826
+ return color ? `#${color.toUpperCase()}` : null;
21827
+ }
21828
+ function setDrawingFill(doc, drawing, color) {
21829
+ const spPr = descendant3(drawing, "spPr");
21830
+ if (!spPr) return false;
21831
+ spPr.children = spPr.children.filter((child4) => {
21832
+ const name = localName(child4.name);
21833
+ return name !== "solidFill" && name !== "noFill";
21834
+ });
21835
+ const fill = color ? el6("a:solidFill", {}, [el6("a:srgbClr", { val: color.replace(/^#/, "").toUpperCase() })]) : el6("a:noFill");
21836
+ const lineIndex = spPr.children.findIndex((child4) => localName(child4.name) === "ln");
21837
+ spPr.children.splice(lineIndex === -1 ? spPr.children.length : lineIndex, 0, fill);
21838
+ doc.refresh();
21839
+ return true;
21840
+ }
21755
21841
  function setDrawingLineStyle(doc, drawing, color, widthPx) {
21756
- const line2 = descendant3(drawing, "ln");
21757
- if (!line2) return false;
21842
+ const spPr = descendant3(drawing, "spPr");
21843
+ if (!spPr) return false;
21844
+ let line2 = spPr.children.find((child4) => localName(child4.name) === "ln");
21845
+ if (!line2) {
21846
+ line2 = el6("a:ln");
21847
+ spPr.children.push(line2);
21848
+ }
21758
21849
  line2.attrs.w = String(Math.max(1, Math.round(widthPx * EMU_PER_PX4)));
21759
21850
  line2.children = line2.children.filter((child4) => {
21760
21851
  const name = localName(child4.name);
@@ -23194,7 +23285,14 @@ function emptyParagraphLike(el16) {
23194
23285
  };
23195
23286
  }
23196
23287
  function removeDrawingRun(doc, src) {
23197
- let run = doc.findParentOf(src);
23288
+ let drawing = src;
23289
+ while (drawing) {
23290
+ const name = localName(drawing.name);
23291
+ if (name === "drawing" || name === "pict" || name === "object" || name === "AlternateContent") break;
23292
+ drawing = doc.findParentOf(drawing);
23293
+ }
23294
+ if (!drawing) return false;
23295
+ let run = doc.findParentOf(drawing);
23198
23296
  while (run && localName(run.name) !== "r") run = doc.findParentOf(run);
23199
23297
  const parent = run ? doc.findParentOf(run) : void 0;
23200
23298
  if (!run || !parent) return false;
@@ -23516,7 +23614,7 @@ var _DocxEditor = class _DocxEditor {
23516
23614
  this.focusText();
23517
23615
  return;
23518
23616
  }
23519
- if (this.imageOverlay?.contains(e.target)) return;
23617
+ if (this.imageOverlay?.contains(e.target) || this.imageToolbar?.contains(e.target)) return;
23520
23618
  if (this.wordArtOverlay?.contains(e.target)) return;
23521
23619
  if (this.wordArtTextEditor?.input.contains(e.target)) return;
23522
23620
  if (this.selectedInkGroup?.overlay.contains(e.target)) return;
@@ -23541,6 +23639,9 @@ var _DocxEditor = class _DocxEditor {
23541
23639
  }
23542
23640
  const onGlyph = this.caretFromPoint(e.clientX, e.clientY);
23543
23641
  let caret = onGlyph ?? this.nearestCaret(e.clientX, e.clientY);
23642
+ if (!onGlyph && !this.inHeaderFooter && e.detail === 1 && !e.shiftKey) {
23643
+ caret = this.extendCaretAfterPageTable(e.clientX, e.clientY) ?? caret;
23644
+ }
23544
23645
  let region = caret ? this.regionOf(caret.t) : "body";
23545
23646
  const storyObject = e.target?.closest?.(
23546
23647
  "[data-dxw-textbox-story-object]"
@@ -23617,7 +23718,8 @@ var _DocxEditor = class _DocxEditor {
23617
23718
  this.hfPage = null;
23618
23719
  }
23619
23720
  if (caret && region === "body" && !onGlyph && e.detail === 1 && !e.shiftKey) {
23620
- caret = this.extendCaretBelowFloatingTable(caret, e.clientX, e.clientY) ?? this.extendCaretIntoBodyWhitespace(caret, e.clientX, e.clientY) ?? caret;
23721
+ const columnCaret = this.extendCaretIntoLaterColumn(caret, e.clientX, e.clientY);
23722
+ caret = columnCaret ? this.extendCaretIntoBodyWhitespace(columnCaret, e.clientX, e.clientY, false) ?? columnCaret : this.extendCaretBelowFloatingTable(caret, e.clientX, e.clientY) ?? this.extendCaretIntoBodyWhitespace(caret, e.clientX, e.clientY) ?? caret;
23621
23723
  }
23622
23724
  if (caret && e.shiftKey) {
23623
23725
  const anchor = this.anchorPoint();
@@ -23677,7 +23779,7 @@ var _DocxEditor = class _DocxEditor {
23677
23779
  menu.setAttribute("role", "menu");
23678
23780
  menu.style.cssText = `position:fixed;left:${event.clientX}px;top:${event.clientY}px;z-index:2147483647;min-width:210px;padding:5px;background:#fff;border:1px solid #dadce0;border-radius:8px;box-shadow:0 4px 18px rgba(0,0,0,.2);font:13px system-ui,sans-serif;color:#202124;`;
23679
23781
  const isApplePlatform = /Mac|iPhone|iPad/.test(navigator.platform);
23680
- const mod = isApplePlatform ? "\u2318" : "Ctrl+";
23782
+ const mod2 = isApplePlatform ? "\u2318" : "Ctrl+";
23681
23783
  const item = (label, shortcut, disabled, action) => {
23682
23784
  const button = document.createElement("button");
23683
23785
  button.type = "button";
@@ -23712,35 +23814,35 @@ var _DocxEditor = class _DocxEditor {
23712
23814
  const selectedText = selectionTextLogical(this.host.doc, this.getSelectionSegments());
23713
23815
  const clipboard = navigator.clipboard;
23714
23816
  const copy = () => clipboard.writeText(selectedText);
23715
- item("Copy", `${mod}C`, !selectedText || !clipboard?.writeText, () => void copy());
23716
- item("Cut", `${mod}X`, !selectedText || !clipboard?.writeText, () => {
23817
+ item("Copy", `${mod2}C`, !selectedText || !clipboard?.writeText, () => void copy());
23818
+ item("Cut", `${mod2}X`, !selectedText || !clipboard?.writeText, () => {
23717
23819
  void copy().then(() => {
23718
23820
  this.host.history?.checkpoint();
23719
23821
  this.removeSelectedText();
23720
23822
  this.commit();
23721
23823
  });
23722
23824
  });
23723
- item("Paste", `${mod}V`, !clipboard?.readText, () => {
23825
+ item("Paste", `${mod2}V`, !clipboard?.readText, () => {
23724
23826
  void clipboard.readText().then((text) => {
23725
23827
  if (text) this.insertText(text);
23726
23828
  });
23727
23829
  });
23728
23830
  separator();
23729
- item("Bold", `${mod}B`, !selectedText, () => this.host.onFormatShortcut?.("bold"));
23730
- item("Italic", `${mod}I`, !selectedText, () => this.host.onFormatShortcut?.("italic"));
23731
- item("Underline", `${mod}U`, !selectedText, () => this.host.onFormatShortcut?.("underline"));
23831
+ item("Bold", `${mod2}B`, !selectedText, () => this.host.onFormatShortcut?.("bold"));
23832
+ item("Italic", `${mod2}I`, !selectedText, () => this.host.onFormatShortcut?.("italic"));
23833
+ item("Underline", `${mod2}U`, !selectedText, () => this.host.onFormatShortcut?.("underline"));
23732
23834
  separator();
23733
- item("Link\u2026", `${mod}K`, !selectedText, () => this.host.onTextCommand?.("link"));
23835
+ item("Link\u2026", `${mod2}K`, !selectedText, () => this.host.onTextCommand?.("link"));
23734
23836
  item("New comment\u2026", isApplePlatform ? "\u2318\u2325A" : "Ctrl+Alt+M", !selectedText, () => this.host.onTextCommand?.("comment"));
23735
- item("Bulleted list", `${mod}Shift+L`, false, () => this.host.onTextCommand?.("bullet"));
23736
- item("Numbered list", `${mod}Shift+7`, false, () => this.host.onTextCommand?.("number"));
23837
+ item("Bulleted list", `${mod2}Shift+L`, false, () => this.host.onTextCommand?.("bullet"));
23838
+ item("Numbered list", `${mod2}Shift+7`, false, () => this.host.onTextCommand?.("number"));
23737
23839
  separator();
23738
- item("Align left", `${mod}L`, false, () => this.host.onTextCommand?.("alignLeft"));
23739
- item("Center", `${mod}E`, false, () => this.host.onTextCommand?.("alignCenter"));
23740
- item("Align right", `${mod}R`, false, () => this.host.onTextCommand?.("alignRight"));
23741
- item("Justify", `${mod}J`, false, () => this.host.onTextCommand?.("justify"));
23840
+ item("Align left", `${mod2}L`, false, () => this.host.onTextCommand?.("alignLeft"));
23841
+ item("Center", `${mod2}E`, false, () => this.host.onTextCommand?.("alignCenter"));
23842
+ item("Align right", `${mod2}R`, false, () => this.host.onTextCommand?.("alignRight"));
23843
+ item("Justify", `${mod2}J`, false, () => this.host.onTextCommand?.("justify"));
23742
23844
  separator();
23743
- item("Select all", `${mod}A`, false, () => this.selectAll());
23845
+ item("Select all", `${mod2}A`, false, () => this.selectAll());
23744
23846
  document.body.appendChild(menu);
23745
23847
  const rect = menu.getBoundingClientRect();
23746
23848
  menu.style.left = `${Math.max(6, Math.min(event.clientX, window.innerWidth - rect.width - 6))}px`;
@@ -23839,7 +23941,11 @@ var _DocxEditor = class _DocxEditor {
23839
23941
  if (e.key === "Enter" && (e.metaKey || e.ctrlKey) && this.caret) {
23840
23942
  e.preventDefault();
23841
23943
  this.host.history?.checkpoint();
23842
- if (insertBreakAt(this.host.doc, this.caret.t, this.caret.offset, "page")) this.commit();
23944
+ const destination = insertBreakAt(this.host.doc, this.caret.t, this.caret.offset, e.shiftKey ? "column" : "page");
23945
+ if (destination) {
23946
+ this.caret = { ...this.caret, ...destination };
23947
+ this.commit();
23948
+ }
23843
23949
  return;
23844
23950
  }
23845
23951
  if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "z") {
@@ -24611,6 +24717,13 @@ var _DocxEditor = class _DocxEditor {
24611
24717
  getSelectedDrawingSource() {
24612
24718
  return this.selectedImage?.src ?? null;
24613
24719
  }
24720
+ /** Whether Layout's contextual object commands currently have a target. */
24721
+ hasSelectedObject() {
24722
+ return this.selectedImage !== null || this.selectedInkGroup !== null;
24723
+ }
24724
+ notifyObjectSelection() {
24725
+ document.dispatchEvent(new CustomEvent("dxw-object-selection", { detail: this.hasSelectedObject() }));
24726
+ }
24614
24727
  /** Restore an object selection after a render replaced its DOM element. */
24615
24728
  reselectDrawing(src) {
24616
24729
  this.reselectImage(src);
@@ -25235,8 +25348,10 @@ var _DocxEditor = class _DocxEditor {
25235
25348
  return setImageWrap(this.host.doc, drawingEl, "square", { x, y: 0 });
25236
25349
  }
25237
25350
  deselectInkGroup() {
25351
+ const changed = this.selectedInkGroup !== null;
25238
25352
  this.selectedInkGroup?.overlay.remove();
25239
25353
  this.selectedInkGroup = null;
25354
+ if (changed) this.notifyObjectSelection();
25240
25355
  }
25241
25356
  selectInkGroup(bindings) {
25242
25357
  this.deselectInkGroup();
@@ -25254,6 +25369,7 @@ var _DocxEditor = class _DocxEditor {
25254
25369
  overlay.style.cssText = `position:absolute;left:${left}px;top:${top}px;width:${right - left}px;height:${bottom - top}px;border:1.5px dashed #1a73e8;background:rgba(26,115,232,.04);box-sizing:border-box;cursor:move;z-index:9;`;
25255
25370
  surface.appendChild(overlay);
25256
25371
  this.selectedInkGroup = { sources, bindings, overlay };
25372
+ this.notifyObjectSelection();
25257
25373
  this.hideCaret();
25258
25374
  this.focusText();
25259
25375
  }
@@ -25351,12 +25467,14 @@ var _DocxEditor = class _DocxEditor {
25351
25467
  return true;
25352
25468
  }
25353
25469
  deselectImage() {
25470
+ const changed = this.selectedImage !== null;
25354
25471
  this.wordArtTextEditor?.finish(true, false);
25355
25472
  this.imageOverlay?.remove();
25356
25473
  this.imageToolbar?.remove();
25357
25474
  this.imageOverlay = null;
25358
25475
  this.imageToolbar = null;
25359
25476
  this.selectedImage = null;
25477
+ if (changed) this.notifyObjectSelection();
25360
25478
  }
25361
25479
  /** Re-select the same drawing after a re-render replaced its element.
25362
25480
  * A header/footer drawing paints one instance per page from the same src;
@@ -25397,13 +25515,32 @@ var _DocxEditor = class _DocxEditor {
25397
25515
  overlay.style.boxSizing = "border-box";
25398
25516
  overlay.style.pointerEvents = "none";
25399
25517
  overlay.style.zIndex = "2147483647";
25518
+ const line2 = kind === "drawing" && isDrawingLine(src);
25519
+ if (line2) {
25520
+ const move = document.createElement("div");
25521
+ move.dataset.dxwObjectMove = "1";
25522
+ move.title = "Drag to move line";
25523
+ move.style.cssText = "position:absolute;left:5px;right:5px;top:calc(50% - 7px);height:14px;pointer-events:auto;cursor:move;";
25524
+ overlay.appendChild(move);
25525
+ }
25400
25526
  for (const [dir, fx, fy] of _DocxEditor.HANDLE_DIRS) {
25527
+ if (line2 && dir !== "e" && dir !== "w") continue;
25401
25528
  const h = document.createElement("div");
25402
25529
  const corner = dir.length === 2;
25403
25530
  h.style.cssText = `position:absolute;width:9px;height:9px;background:#fff;border:1.5px solid #1a73e8;box-sizing:border-box;border-radius:${corner ? "50%" : "2px"};pointer-events:auto;left:calc(${fx * 100}% - 5px);top:calc(${fy * 100}% - 5px);cursor:${_DocxEditor.handleCursor(dir)};box-shadow:0 1px 2px rgba(0,0,0,.25);`;
25404
25531
  h.dataset.dxwImgHandle = dir;
25405
25532
  overlay.appendChild(h);
25406
25533
  }
25534
+ if (el16.dataset.dxwModel3d) {
25535
+ const move = document.createElement("button");
25536
+ move.type = "button";
25537
+ move.dataset.dxwObjectMove = "1";
25538
+ move.title = "Drag to move 3D object";
25539
+ move.setAttribute("aria-label", "Move 3D object");
25540
+ move.textContent = "Move";
25541
+ move.style.cssText = "position:absolute;left:6px;top:6px;border:1px solid #8ab4f8;border-radius:4px;padding:3px 7px;background:rgba(255,255,255,.94);color:#174ea6;font:600 11px system-ui,sans-serif;pointer-events:auto;cursor:move;box-shadow:0 1px 3px rgba(0,0,0,.2);";
25542
+ overlay.appendChild(move);
25543
+ }
25407
25544
  const bar = document.createElement("div");
25408
25545
  bar.style.cssText = "position:absolute;display:flex;gap:2px;background:#fff;border:1px solid #dadce0;border-radius:5px;box-shadow:0 2px 8px rgba(0,0,0,.18);padding:2px;pointer-events:auto;font:11px system-ui,sans-serif;white-space:nowrap;z-index:2147483647;";
25409
25546
  const isFloating = isFloatingDrawing(src);
@@ -25507,6 +25644,42 @@ var _DocxEditor = class _DocxEditor {
25507
25644
  });
25508
25645
  });
25509
25646
  if (kind === "drawing") {
25647
+ extra("Rotate", "Set rotation (degrees)", () => {
25648
+ void requestTextInputDialog(this.host.container, {
25649
+ title: "Rotation",
25650
+ label: "Degrees clockwise",
25651
+ value: String(drawingRotation(src)),
25652
+ placeholder: "90"
25653
+ }).then((next) => {
25654
+ if (next === null) return;
25655
+ const degrees = parseFloat(next);
25656
+ if (!Number.isFinite(degrees)) return;
25657
+ this.host.history?.checkpoint();
25658
+ if (setDrawingRotation(this.host.doc, src, degrees)) {
25659
+ this.host.rerender(void 0, "global");
25660
+ this.reselectImage(src);
25661
+ }
25662
+ });
25663
+ });
25664
+ if (!isDrawingLine(src)) {
25665
+ extra("Fill", "Shape fill color", () => {
25666
+ void requestTextInputDialog(this.host.container, {
25667
+ title: "Fill",
25668
+ label: "Color or none",
25669
+ value: drawingFillColor(src) ?? "none",
25670
+ placeholder: "#4472C4 or none"
25671
+ }).then((next) => {
25672
+ if (next === null) return;
25673
+ const color = /^\s*none\s*$/i.test(next) ? null : /^\s*#?([0-9a-f]{6})\s*$/i.exec(next)?.[1];
25674
+ if (color === void 0) return;
25675
+ this.host.history?.checkpoint();
25676
+ if (setDrawingFill(this.host.doc, src, color ? `#${color}` : null)) {
25677
+ this.host.rerender();
25678
+ this.reselectImage(src);
25679
+ }
25680
+ });
25681
+ });
25682
+ }
25510
25683
  extra("Outline", "Outline color and weight", () => {
25511
25684
  const style = drawingLineStyle(src);
25512
25685
  if (!style) return;
@@ -25525,10 +25698,11 @@ var _DocxEditor = class _DocxEditor {
25525
25698
  }
25526
25699
  });
25527
25700
  });
25701
+ extra("Delete", "Delete shape", () => this.deleteSelectedImage());
25528
25702
  }
25529
25703
  const drawingBinding = kind === "drawing" ? this.host.getHandle()?.drawings.find((binding) => binding.item.src === src) : void 0;
25530
25704
  if (drawingBinding?.item.textboxStory && !isDrawingWordArt(src)) {
25531
- extra("Edit text", "Edit shape text", () => {
25705
+ extra("Edit text", "Edit shape text with the Home font controls", () => {
25532
25706
  const rect = drawingBinding.el.getBoundingClientRect();
25533
25707
  this.enterTextboxStory(src, rect.left + rect.width / 2, rect.top + rect.height / 2);
25534
25708
  });
@@ -25578,6 +25752,7 @@ var _DocxEditor = class _DocxEditor {
25578
25752
  bar.style.left = `${left}px`;
25579
25753
  this.imageOverlay = overlay;
25580
25754
  this.imageToolbar = bar;
25755
+ this.notifyObjectSelection();
25581
25756
  this.focusText();
25582
25757
  }
25583
25758
  deleteSelectedImage() {
@@ -25586,7 +25761,7 @@ var _DocxEditor = class _DocxEditor {
25586
25761
  this.host.history?.checkpoint();
25587
25762
  if (removeDrawingRun(this.host.doc, src)) {
25588
25763
  this.host.doc.refresh();
25589
- this.host.rerender();
25764
+ this.host.rerender(void 0, "global");
25590
25765
  }
25591
25766
  this.deselectImage();
25592
25767
  }
@@ -25774,12 +25949,18 @@ var _DocxEditor = class _DocxEditor {
25774
25949
  /** Handle mousedown on images / their resize handle. Returns true if consumed. */
25775
25950
  startImageInteraction(e, target) {
25776
25951
  const zoom = this.host.zoom ?? 1;
25952
+ const objectMove = target.closest?.("[data-dxw-object-move]");
25953
+ if (this.imageToolbar?.contains(target)) {
25954
+ this.suppressNextMouseUp = true;
25955
+ return true;
25956
+ }
25777
25957
  if (target.closest?.("[data-dxw-model3d-viewer]")) return true;
25778
25958
  if (target.dataset.dxwImgHandle && this.selectedImage) {
25779
25959
  e.preventDefault();
25780
25960
  e.stopPropagation();
25781
25961
  const dir = target.dataset.dxwImgHandle;
25782
25962
  const { el: el16, src } = this.selectedImage;
25963
+ const line2 = this.selectedImage.kind === "drawing" && isDrawingLine(src);
25783
25964
  const nearPt = { x: el16.getBoundingClientRect().left, y: el16.getBoundingClientRect().top };
25784
25965
  const w0 = parseFloat(el16.style.width);
25785
25966
  const h0 = parseFloat(el16.style.height);
@@ -25806,7 +25987,7 @@ var _DocxEditor = class _DocxEditor {
25806
25987
  h = h0 * scale;
25807
25988
  }
25808
25989
  w = Math.max(8, w);
25809
- h = Math.max(8, h);
25990
+ h = line2 ? h0 : Math.max(8, h);
25810
25991
  apply(el16);
25811
25992
  if (this.imageOverlay) apply(this.imageOverlay);
25812
25993
  };
@@ -25841,8 +26022,8 @@ var _DocxEditor = class _DocxEditor {
25841
26022
  }
25842
26023
  const mathTarget = target.closest?.("[data-dxw-math]");
25843
26024
  if (mathTarget) {
25844
- const handle = this.host.getHandle();
25845
- const mathBinding = handle?.bindings.find((b) => b.el === mathTarget);
26025
+ const handle2 = this.host.getHandle();
26026
+ const mathBinding = handle2?.bindings.find((b) => b.el === mathTarget);
25846
26027
  const oMathEl = mathBinding?.item.mathSrc;
25847
26028
  if (oMathEl) {
25848
26029
  e.preventDefault();
@@ -25869,9 +26050,21 @@ var _DocxEditor = class _DocxEditor {
25869
26050
  return true;
25870
26051
  }
25871
26052
  }
25872
- if (target.dataset.dxwDrawing) {
25873
- const handle = this.host.getHandle();
25874
- const binding = handle?.drawings.find((b) => b.el === target);
26053
+ const drawingTarget = objectMove && this.selectedImage?.kind === "drawing" ? this.selectedImage.el : target.closest?.("[data-dxw-drawing]");
26054
+ const handle = this.host.getHandle();
26055
+ let drawingBinding = drawingTarget ? handle?.drawings.find((b) => b.el === drawingTarget) : void 0;
26056
+ if (!drawingBinding && !target.closest("button")) {
26057
+ const pointCaret2 = this.caretFromPoint(e.clientX, e.clientY);
26058
+ if (!pointCaret2 || !this.inActiveRegion(pointCaret2.t)) {
26059
+ drawingBinding = handle?.drawings.find((candidate) => {
26060
+ if (!candidate.item.behind) return false;
26061
+ const rect = candidate.el.getBoundingClientRect();
26062
+ return e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
26063
+ });
26064
+ }
26065
+ }
26066
+ if (drawingBinding) {
26067
+ const binding = drawingBinding;
25875
26068
  if (!binding) return false;
25876
26069
  const textboxStory = binding.item.textboxStory === true;
25877
26070
  if (!textboxStory && this.regionOf(binding.item.src) === "hf" !== this.inHeaderFooter) return false;
@@ -25891,11 +26084,41 @@ var _DocxEditor = class _DocxEditor {
25891
26084
  }
25892
26085
  const startX = e.clientX;
25893
26086
  const startY = e.clientY;
26087
+ const el16 = binding.el;
26088
+ const left0 = parseFloat(el16.style.left) || 0;
26089
+ const top0 = parseFloat(el16.style.top) || 0;
25894
26090
  const rect0 = binding.el.getBoundingClientRect();
25895
26091
  let moved = false;
26092
+ let toolbarLeft0 = 0;
26093
+ let toolbarTop0 = 0;
25896
26094
  const onMove = (me) => {
25897
- if (!moved && Math.hypot(me.clientX - startX, me.clientY - startY) > 5) moved = true;
25898
- if (moved && !binding.item.anchored) this.showDropIndicator(me.clientX, me.clientY);
26095
+ if (!moved && Math.hypot(me.clientX - startX, me.clientY - startY) > 5) {
26096
+ moved = true;
26097
+ if (binding.item.anchored) {
26098
+ if (this.selectedImage?.src !== binding.item.src) {
26099
+ this.selectImage(el16, binding.item.src, void 0, "drawing");
26100
+ }
26101
+ toolbarLeft0 = parseFloat(this.imageToolbar?.style.left ?? "") || 0;
26102
+ toolbarTop0 = parseFloat(this.imageToolbar?.style.top ?? "") || 0;
26103
+ }
26104
+ }
26105
+ if (!moved) return;
26106
+ if (binding.item.anchored) {
26107
+ const dx = (me.clientX - startX) / zoom;
26108
+ const dy = (me.clientY - startY) / zoom;
26109
+ el16.style.left = `${left0 + dx}px`;
26110
+ el16.style.top = `${top0 + dy}px`;
26111
+ if (this.imageOverlay) {
26112
+ this.imageOverlay.style.left = `${left0 + dx}px`;
26113
+ this.imageOverlay.style.top = `${top0 + dy}px`;
26114
+ }
26115
+ if (this.imageToolbar) {
26116
+ this.imageToolbar.style.left = `${toolbarLeft0 + dx}px`;
26117
+ this.imageToolbar.style.top = `${toolbarTop0 + dy}px`;
26118
+ }
26119
+ } else {
26120
+ this.showDropIndicator(me.clientX, me.clientY);
26121
+ }
25899
26122
  };
25900
26123
  const onUp = (me) => {
25901
26124
  document.removeEventListener("mousemove", onMove);
@@ -25903,15 +26126,31 @@ var _DocxEditor = class _DocxEditor {
25903
26126
  this.hideDropIndicator();
25904
26127
  this.suppressNextMouseUp = false;
25905
26128
  if (!moved) {
25906
- this.selectImage(target, binding.item.src, void 0, "drawing");
26129
+ this.selectImage(binding.el, binding.item.src, void 0, "drawing");
25907
26130
  return;
25908
26131
  }
25909
26132
  if (binding.item.anchored) {
25910
26133
  this.host.history?.checkpoint();
25911
- const want = { x: rect0.left + me.clientX - startX, y: rect0.top + me.clientY - startY };
25912
- if (this.moveFloatingDrawing(binding, me.clientX - startX, me.clientY - startY)) {
26134
+ const dxClient = me.clientX - startX;
26135
+ const dyClient = me.clientY - startY;
26136
+ const want = { x: rect0.left + dxClient, y: rect0.top + dyClient };
26137
+ const pageRect = el16.closest(".dxw-page")?.getBoundingClientRect();
26138
+ const centerX = want.x + rect0.width / 2;
26139
+ const centerY = want.y + rect0.height / 2;
26140
+ const staysOnPage = !!pageRect && centerX >= pageRect.left && centerX <= pageRect.right && centerY >= pageRect.top && centerY <= pageRect.bottom;
26141
+ el16.style.left = `${left0}px`;
26142
+ el16.style.top = `${top0}px`;
26143
+ const changed = staysOnPage ? setFloatingPagePosition(
26144
+ this.host.doc,
26145
+ binding.item.src,
26146
+ left0 + dxClient / zoom,
26147
+ top0 + dyClient / zoom
26148
+ ) : this.moveFloatingDrawing(binding, dxClient, dyClient);
26149
+ if (changed) {
25913
26150
  this.host.rerender();
25914
26151
  this.reselectImage(binding.item.src, want);
26152
+ } else {
26153
+ this.reselectImage(binding.item.src, { x: rect0.left, y: rect0.top });
25915
26154
  }
25916
26155
  return;
25917
26156
  }
@@ -25930,12 +26169,18 @@ var _DocxEditor = class _DocxEditor {
25930
26169
  return true;
25931
26170
  }
25932
26171
  let imageBinding;
25933
- if (target.tagName === "IMG") {
25934
- const handle = this.host.getHandle();
25935
- imageBinding = handle?.images.find((b) => b.el === target || b.el.contains(target));
25936
- } else if (!target.closest("button") && !target.dataset.dxwImgHandle && !this.imageOverlay?.contains(target) && !this.caretFromPoint(e.clientX, e.clientY)) {
25937
- const handle = this.host.getHandle();
25938
- imageBinding = handle?.images.find((b) => {
26172
+ const pointCaret = this.caretFromPoint(e.clientX, e.clientY);
26173
+ if (objectMove && this.selectedImage?.kind === "image") {
26174
+ const selected = this.selectedImage;
26175
+ imageBinding = this.host.getHandle()?.images.find(
26176
+ (binding) => binding.el === selected.el && binding.item.src === selected.src
26177
+ );
26178
+ } else if (target.tagName === "IMG") {
26179
+ const handle2 = this.host.getHandle();
26180
+ imageBinding = handle2?.images.find((b) => b.el === target || b.el.contains(target));
26181
+ } else if (!target.closest("button") && !target.dataset.dxwImgHandle && !this.imageOverlay?.contains(target) && (!pointCaret || !this.inActiveRegion(pointCaret.t))) {
26182
+ const handle2 = this.host.getHandle();
26183
+ imageBinding = handle2?.images.find((b) => {
25939
26184
  if (!b.item.behind) return false;
25940
26185
  const r = b.el.getBoundingClientRect();
25941
26186
  return e.clientX >= r.left && e.clientX <= r.right && e.clientY >= r.top && e.clientY <= r.bottom;
@@ -25950,30 +26195,37 @@ var _DocxEditor = class _DocxEditor {
25950
26195
  const startX = e.clientX;
25951
26196
  const startY = e.clientY;
25952
26197
  const floating = isFloatingDrawing(binding.item.src);
26198
+ const moveAsObject = !!objectMove;
25953
26199
  const el16 = binding.el;
25954
26200
  const left0 = parseFloat(el16.style.left) || 0;
25955
26201
  const top0 = parseFloat(el16.style.top) || 0;
25956
26202
  const rect0 = el16.getBoundingClientRect();
25957
26203
  let moved = false;
25958
26204
  let ghost = null;
26205
+ let toolbarLeft0 = parseFloat(this.imageToolbar?.style.left ?? "") || 0;
26206
+ let toolbarTop0 = parseFloat(this.imageToolbar?.style.top ?? "") || 0;
25959
26207
  const grabX = e.clientX - el16.getBoundingClientRect().left;
25960
26208
  const grabY = e.clientY - el16.getBoundingClientRect().top;
25961
26209
  const onMove = (me) => {
25962
26210
  if (!moved && Math.hypot(me.clientX - startX, me.clientY - startY) > 5) {
25963
26211
  moved = true;
25964
- if (!floating) {
26212
+ if (!floating && !moveAsObject) {
25965
26213
  ghost = el16.cloneNode(true);
25966
26214
  ghost.style.position = "fixed";
25967
26215
  ghost.style.opacity = "0.5";
25968
26216
  ghost.style.pointerEvents = "none";
25969
26217
  ghost.style.zIndex = "1000";
25970
26218
  document.body.appendChild(ghost);
25971
- } else if (this.imageOverlay === null) {
26219
+ } else if (this.selectedImage?.src !== binding.item.src) {
25972
26220
  this.selectImage(el16, binding.item.src, binding.item);
25973
26221
  }
26222
+ if (floating || moveAsObject) {
26223
+ toolbarLeft0 = parseFloat(this.imageToolbar?.style.left ?? "") || 0;
26224
+ toolbarTop0 = parseFloat(this.imageToolbar?.style.top ?? "") || 0;
26225
+ }
25974
26226
  }
25975
26227
  if (!moved) return;
25976
- if (floating) {
26228
+ if (floating || moveAsObject) {
25977
26229
  const nl = left0 + (me.clientX - startX) / zoom;
25978
26230
  const nt = top0 + (me.clientY - startY) / zoom;
25979
26231
  el16.style.left = `${nl}px`;
@@ -25982,6 +26234,10 @@ var _DocxEditor = class _DocxEditor {
25982
26234
  this.imageOverlay.style.left = `${nl}px`;
25983
26235
  this.imageOverlay.style.top = `${nt}px`;
25984
26236
  }
26237
+ if (this.imageToolbar) {
26238
+ this.imageToolbar.style.left = `${toolbarLeft0 + (me.clientX - startX) / zoom}px`;
26239
+ this.imageToolbar.style.top = `${toolbarTop0 + (me.clientY - startY) / zoom}px`;
26240
+ }
25985
26241
  } else if (ghost) {
25986
26242
  ghost.style.left = `${me.clientX - grabX}px`;
25987
26243
  ghost.style.top = `${me.clientY - grabY}px`;
@@ -26049,6 +26305,18 @@ var _DocxEditor = class _DocxEditor {
26049
26305
  el16.style.top = `${top0}px`;
26050
26306
  this.reselectImage(src, { x: rect0.left, y: rect0.top });
26051
26307
  }
26308
+ } else if (moveAsObject) {
26309
+ const src = binding.item.src;
26310
+ const dx = (me.clientX - startX) / zoom;
26311
+ const dy = (me.clientY - startY) / zoom;
26312
+ const want = { x: rect0.left + me.clientX - startX, y: rect0.top + me.clientY - startY };
26313
+ el16.style.left = `${left0}px`;
26314
+ el16.style.top = `${top0}px`;
26315
+ setImageWrap(this.host.doc, src, "square", { x: 0, y: 0 });
26316
+ if (setFloatingPagePosition(this.host.doc, src, binding.item.x + dx, binding.item.y + dy)) {
26317
+ this.host.rerender();
26318
+ this.reselectImage(src, want);
26319
+ }
26052
26320
  } else {
26053
26321
  const imgRegion = this.regionOf(binding.item.src);
26054
26322
  let dest = this.caretFromPoint(me.clientX, me.clientY) ?? this.nearestCaret(me.clientX, me.clientY);
@@ -26482,6 +26750,154 @@ var _DocxEditor = class _DocxEditor {
26482
26750
  bias: logicalAfter && item.text.length > 0 ? "end" : void 0
26483
26751
  };
26484
26752
  }
26753
+ columnAtPoint(page, x, y) {
26754
+ const bands = JSON.parse(page.dataset.columnBands ?? "[]");
26755
+ let band = bands[0];
26756
+ for (const candidate of bands) {
26757
+ if (candidate.top <= y + 0.01) band = candidate;
26758
+ else break;
26759
+ }
26760
+ if (!band || band.colXs.length < 2) return null;
26761
+ let best = 0;
26762
+ let bestDistance = Infinity;
26763
+ for (let i = 0; i < band.colXs.length; i++) {
26764
+ const left = band.colXs[i];
26765
+ const right = left + band.colWidths[i];
26766
+ const distance = x < left ? left - x : x > right ? x - right : 0;
26767
+ if (distance < bestDistance) {
26768
+ best = i;
26769
+ bestDistance = distance;
26770
+ }
26771
+ }
26772
+ return {
26773
+ index: best,
26774
+ left: band.colXs[best],
26775
+ right: band.colXs[best] + band.colWidths[best]
26776
+ };
26777
+ }
26778
+ /** Word columns are one text flow. Clicking an empty later column inserts
26779
+ * the column break that Word otherwise exposes through Layout > Breaks, then
26780
+ * keeps click-and-type's vertical placement inside that column. */
26781
+ extendCaretIntoLaterColumn(caret, x, y) {
26782
+ const handle = this.host.getHandle();
26783
+ const page = document.elementFromPoint(x, y)?.closest(".dxw-page");
26784
+ const surface = page?.firstElementChild;
26785
+ if (!handle || !page || !surface) return null;
26786
+ const rect = surface.getBoundingClientRect();
26787
+ const zoom = this.host.zoom ?? 1;
26788
+ const lx = (x - rect.left) / zoom;
26789
+ const ly = (y - rect.top) / zoom;
26790
+ const targetColumn = this.columnAtPoint(page, lx, ly);
26791
+ if (!targetColumn) return null;
26792
+ const binding = handle.bindings.filter(
26793
+ (candidate) => candidate.el.parentElement === surface && candidate.item.src?.t === caret.t && caret.offset >= candidate.item.src.offset && caret.offset <= candidate.item.src.offset + candidate.item.text.length
26794
+ ).sort((a, b) => Math.abs(a.item.lineTop - ly) - Math.abs(b.item.lineTop - ly))[0];
26795
+ if (!binding) return null;
26796
+ const sourceColumn = this.columnAtPoint(
26797
+ page,
26798
+ binding.item.x + Math.max(1, binding.item.width) / 2,
26799
+ binding.item.lineTop
26800
+ );
26801
+ if (!sourceColumn || targetColumn.index <= sourceColumn.index) return null;
26802
+ const rEl = this.host.doc.findParentOf(caret.t);
26803
+ const pEl = rEl && this.host.doc.findParentOf(rEl);
26804
+ if (!rEl || !pEl || localName(rEl.name) !== "r" || localName(pEl.name) !== "p") return null;
26805
+ const prefix = rEl.name.includes(":") ? rEl.name.slice(0, rEl.name.indexOf(":") + 1) : "";
26806
+ const rPr = rEl.children.find((child4) => localName(child4.name) === "rPr");
26807
+ const breakRuns = [];
26808
+ for (let i = sourceColumn.index; i < targetColumn.index; i++) {
26809
+ breakRuns.push({
26810
+ name: `${prefix}r`,
26811
+ attrs: {},
26812
+ children: [
26813
+ ...rPr ? [cloneXml(rPr)] : [],
26814
+ { name: `${prefix}br`, attrs: { [`${prefix}type`]: "column" }, children: [], text: "" }
26815
+ ],
26816
+ text: ""
26817
+ });
26818
+ }
26819
+ const runIndex = pEl.children.indexOf(rEl);
26820
+ const oldText = caret.t.text;
26821
+ let targetText = caret.t;
26822
+ this.host.history?.checkpoint();
26823
+ if (caret.offset <= 0) {
26824
+ pEl.children.splice(runIndex, 0, ...breakRuns);
26825
+ } else {
26826
+ const tailText = {
26827
+ name: caret.t.name,
26828
+ attrs: { ...caret.t.attrs, "xml:space": "preserve" },
26829
+ children: [],
26830
+ text: oldText.slice(caret.offset)
26831
+ };
26832
+ const tailRun = {
26833
+ name: rEl.name,
26834
+ attrs: {},
26835
+ children: [...rPr ? [cloneXml(rPr)] : [], tailText],
26836
+ text: ""
26837
+ };
26838
+ caret.t.text = oldText.slice(0, caret.offset);
26839
+ pEl.children.splice(runIndex + 1, 0, ...breakRuns, tailRun);
26840
+ targetText = tailText;
26841
+ }
26842
+ this.caret = { t: targetText, run: caret.run, offset: 0 };
26843
+ this.pendingClickTypeCheckpoint = true;
26844
+ this.commit(false, "global");
26845
+ return this.nearestCaret(x, y, "body") ?? this.caret;
26846
+ }
26847
+ /** A table can end partway through an intermediate page while the next body
26848
+ * block starts on a later page. Word still lets the user click the open body
26849
+ * area below that table. Materialize ordinary empty paragraphs between the
26850
+ * table and the following block so the requested line becomes editable. */
26851
+ extendCaretAfterPageTable(x, y) {
26852
+ const handle = this.host.getHandle();
26853
+ const page = document.elementFromPoint(x, y)?.closest(".dxw-page");
26854
+ const surface = page?.firstElementChild;
26855
+ if (!handle || !page || !surface) return null;
26856
+ const rect = surface.getBoundingClientRect();
26857
+ const zoom = this.host.zoom ?? 1;
26858
+ const lx = (x - rect.left) / zoom;
26859
+ const ly = (y - rect.top) / zoom;
26860
+ const bodyTop = parseFloat(page.dataset.bodyTop ?? "0");
26861
+ const bodyBottom = parseFloat(page.dataset.bodyBottom ?? "0");
26862
+ if (ly < bodyTop || ly > bodyBottom) return null;
26863
+ if (this.nearestCaret(x, y, "body")) return null;
26864
+ const table2 = handle.grips.filter((grip) => {
26865
+ if (grip.item.axis !== "move" || grip.el.parentElement !== surface) return false;
26866
+ if (ly <= grip.item.y2 + 1 || lx < grip.item.x || lx > (grip.item.x2 ?? grip.item.x)) return false;
26867
+ const parent2 = this.host.doc.findParentOf(grip.item.tbl);
26868
+ if (!parent2 || localName(parent2.name) !== "body") return false;
26869
+ const tblPr = grip.item.tbl.children.find((child4) => localName(child4.name) === "tblPr");
26870
+ return tblPr?.children.some((child4) => localName(child4.name) === "tblpPr") !== true;
26871
+ }).sort((a, b) => b.item.y2 - a.item.y2)[0];
26872
+ if (!table2) return null;
26873
+ const parent = this.host.doc.findParentOf(table2.item.tbl);
26874
+ const nearby = handle.bindings.filter(
26875
+ (binding2) => binding2.el.parentElement === surface && binding2.item.src?.t && this.regionOf(binding2.item.src.t) === "body" && binding2.item.lineTop <= table2.item.y2 + 1
26876
+ ).sort((a, b) => b.item.lineTop - a.item.lineTop)[0];
26877
+ const lineHeight = Math.max(1, nearby?.item.lineHeight ?? 16);
26878
+ const lineCount = Math.max(1, Math.round((ly - table2.item.y2) / lineHeight) + 1);
26879
+ const w = table2.item.tbl.name.includes(":") ? table2.item.tbl.name.slice(0, table2.item.tbl.name.indexOf(":") + 1) : "";
26880
+ const paragraphs = [];
26881
+ let targetText = null;
26882
+ for (let i = 0; i < lineCount; i++) {
26883
+ const created = emptyParagraphLike(table2.item.tbl);
26884
+ if (i === 0) {
26885
+ created.paragraph.children.unshift({ name: `${w}pPr`, attrs: {}, children: [], text: "" });
26886
+ }
26887
+ paragraphs.push(created.paragraph);
26888
+ targetText = created.text;
26889
+ }
26890
+ this.host.history?.checkpoint();
26891
+ parent.children.splice(parent.children.indexOf(table2.item.tbl) + 1, 0, ...paragraphs);
26892
+ this.pendingClickTypeCheckpoint = true;
26893
+ this.host.doc.refresh();
26894
+ this.host.rerender(void 0, "global");
26895
+ const binding = targetText ? this.host.getHandle()?.bindingsByText.get(targetText)?.[0] : void 0;
26896
+ if (!targetText || !binding?.item.src) return null;
26897
+ this.caret = { t: targetText, run: binding.item.src.run, offset: 0 };
26898
+ this.focusText();
26899
+ return this.caret;
26900
+ }
26485
26901
  /** Materialize Word's click-and-type position below a moved floating table. */
26486
26902
  extendCaretBelowFloatingTable(caret, x, y) {
26487
26903
  const handle = this.host.getHandle();
@@ -26545,7 +26961,7 @@ var _DocxEditor = class _DocxEditor {
26545
26961
  /** Word-style click-and-type: clicking below the final body line on a page
26546
26962
  * creates the intervening empty paragraphs so vertical arrows visit every
26547
26963
  * visible line instead of jumping across synthetic paragraph spacing. */
26548
- extendCaretIntoBodyWhitespace(caret, x, y) {
26964
+ extendCaretIntoBodyWhitespace(caret, x, y, checkpoint = true) {
26549
26965
  const handle = this.host.getHandle();
26550
26966
  const page = document.elementFromPoint(x, y)?.closest(".dxw-page");
26551
26967
  const surface = page?.firstElementChild;
@@ -26570,7 +26986,7 @@ var _DocxEditor = class _DocxEditor {
26570
26986
  );
26571
26987
  if (hasLaterLine) return null;
26572
26988
  const lineCount = Math.max(1, Math.round((ly - binding.item.lineTop) / lineHeight));
26573
- this.host.history?.checkpoint();
26989
+ if (checkpoint) this.host.history?.checkpoint();
26574
26990
  this.caret = {
26575
26991
  t: endText,
26576
26992
  run: binding.item.src.run,
@@ -26661,7 +27077,7 @@ var _DocxEditor = class _DocxEditor {
26661
27077
  const binding = this.host.getHandle()?.bindings.find((b) => b.el === el16 || el16 !== null && b.el === el16.parentElement);
26662
27078
  if (!binding?.item.src?.t) return null;
26663
27079
  const r = binding.el.getBoundingClientRect();
26664
- if (y < r.top - 4 || y > r.bottom + 4) return null;
27080
+ if (x < r.left - 4 || x > r.right + 4 || y < r.top - 4 || y > r.bottom + 4) return null;
26665
27081
  const local = Math.min(offset, binding.item.text.length);
26666
27082
  return {
26667
27083
  t: binding.item.src.t,
@@ -28187,7 +28603,10 @@ function setParagraphSpacing(doc, targets, patch) {
28187
28603
  sp = { name: `${w}spacing`, attrs: {}, children: [], text: "" };
28188
28604
  pPr.children.push(sp);
28189
28605
  }
28190
- if (patch.lineMultiple !== void 0) {
28606
+ if (patch.exactLinePt !== void 0) {
28607
+ sp.attrs[attrKey(sp, "line", w)] = String(Math.round(patch.exactLinePt * 20));
28608
+ sp.attrs[attrKey(sp, "lineRule", w)] = "exact";
28609
+ } else if (patch.lineMultiple !== void 0) {
28191
28610
  sp.attrs[attrKey(sp, "line", w)] = String(Math.round(patch.lineMultiple * 240));
28192
28611
  sp.attrs[attrKey(sp, "lineRule", w)] = "auto";
28193
28612
  }
@@ -28758,9 +29177,471 @@ function detectMissingFonts(layout) {
28758
29177
  }
28759
29178
 
28760
29179
  // src/toolbar.tsx
28761
- import { Fragment, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
29180
+ import { Fragment, useCallback, useEffect as useEffect2, useId, useLayoutEffect, useRef as useRef2, useState as useState2 } from "react";
29181
+ import { createPortal as createPortal2 } from "react-dom";
29182
+
29183
+ // src/help.tsx
29184
+ import { useEffect, useMemo, useRef, useState } from "react";
28762
29185
  import { createPortal } from "react-dom";
28763
- import { Fragment as Fragment2, jsx, jsxs } from "react/jsx-runtime";
29186
+ import { jsx, jsxs } from "react/jsx-runtime";
29187
+ var GUIDE_GROUPS = [
29188
+ {
29189
+ title: "Start editing",
29190
+ items: [
29191
+ {
29192
+ title: "Type and select text",
29193
+ description: "Click text or available white space to place the caret. Drag across text to select it, then use Home or the right-click menu to format it."
29194
+ },
29195
+ {
29196
+ title: "Right-click text",
29197
+ description: "The text menu includes cut, copy, paste, formatting, links, comments, lists, alignment, and Select all. Selection-dependent actions become available after selecting text."
29198
+ },
29199
+ {
29200
+ title: "Move through the document",
29201
+ description: "Use the arrow keys for character and line movement. Home and End move to visual line edges. Modified arrow keys jump to line edges or adjacent paragraphs."
29202
+ },
29203
+ {
29204
+ title: "Save your work",
29205
+ description: "Use Download to save the edited DOCX. Hosts can also persist drafts from the editor's saved DOCX bytes."
29206
+ }
29207
+ ]
29208
+ },
29209
+ {
29210
+ title: "Demo workspace",
29211
+ items: [
29212
+ {
29213
+ title: "Open or upload a document",
29214
+ description: "Choose a sample from Try a template or use Upload .docx to edit a local Word file in the browser."
29215
+ },
29216
+ {
29217
+ title: "Zoom, review, and author",
29218
+ description: "Change Zoom without changing the DOCX. Switch between Editing and Suggesting, set the author stamped on comments and revisions, and show or hide comment balloons."
29219
+ },
29220
+ {
29221
+ title: "Find and replace",
29222
+ description: "Press Cmd/Ctrl+F in the demo to open Find. Step through matches, replace the current match, or replace every match."
29223
+ },
29224
+ {
29225
+ title: "Save, download, print",
29226
+ description: "Save keeps the demo workspace in this browser, Download writes a DOCX file, and Print opens the browser's print or PDF workflow."
29227
+ }
29228
+ ]
29229
+ },
29230
+ {
29231
+ title: "Home tools",
29232
+ items: [
29233
+ {
29234
+ title: "Undo and redo",
29235
+ description: "Reverse or restore text, formatting, layout, and object edits with the arrow buttons or keyboard shortcuts."
29236
+ },
29237
+ {
29238
+ title: "Styles, font, and size",
29239
+ description: "Apply document paragraph styles, choose an available typeface, and set the selected text size."
29240
+ },
29241
+ {
29242
+ title: "Character formatting",
29243
+ description: "Bold, italicize, underline, strike, superscript, subscript, change case, clear formatting, or change text and highlight colors."
29244
+ },
29245
+ {
29246
+ title: "Paragraph formatting",
29247
+ description: "Align text, adjust indentation, and set line or paragraph spacing. These controls apply to the selected paragraphs or the paragraph containing the caret."
29248
+ },
29249
+ {
29250
+ title: "Lists",
29251
+ description: "Start or remove bulleted and numbered lists. Tab changes the level of the current list item; Shift+Tab promotes it."
29252
+ }
29253
+ ]
29254
+ },
29255
+ {
29256
+ title: "Insert tools",
29257
+ items: [
29258
+ {
29259
+ title: "Pages, breaks, and sections",
29260
+ description: "Insert a cover page, full blank page, page break, column break, or next-page/continuous section break at the caret."
29261
+ },
29262
+ {
29263
+ title: "Tables",
29264
+ description: "Choose a row and column count from the Table grid. Tab moves to the next cell, Shift+Tab moves back, and Tab in the last cell adds a row."
29265
+ },
29266
+ {
29267
+ title: "Images, icons, and screenshots",
29268
+ description: "Insert an image or SVG file, or capture a screen, window, or browser tab. Select the result to resize, position, wrap, layer, replace, or add alternative text."
29269
+ },
29270
+ {
29271
+ title: "3D models",
29272
+ description: "Insert a GLB file. Drag the model itself to rotate it, use the move grip to reposition it, resize from the handles, and use Reset 3D to restore its original view."
29273
+ },
29274
+ {
29275
+ title: "Shapes and lines",
29276
+ description: "Insert a line, rectangle, rounded rectangle, ellipse, arrow, or callout. Select it to move, resize, rotate, change wrapping and layering, or edit fill and outline."
29277
+ },
29278
+ {
29279
+ title: "Text boxes and WordArt",
29280
+ description: "Insert positioned text. Double-click a text box or text-bearing shape to edit its story, then use Home for font and text color. Escape returns to object selection for fill, outline, position, rotation, and wrapping."
29281
+ },
29282
+ {
29283
+ title: "Charts and SmartArt",
29284
+ description: "Insert native editable charts or diagrams. Select an existing chart or SmartArt object before opening its Insert control to update its data or layout."
29285
+ },
29286
+ {
29287
+ title: "Links, comments, and notes",
29288
+ description: "Select text before adding a hyperlink or comment. Footnotes insert at the caret and remain editable in the note area."
29289
+ },
29290
+ {
29291
+ title: "Bookmarks and cross-references",
29292
+ description: "Create a named bookmark at a selection, then insert a live text or page reference to that bookmark elsewhere."
29293
+ },
29294
+ {
29295
+ title: "Headers, footers, and page numbers",
29296
+ description: "Open the repeating header or footer layer, type or insert page fields and objects, then choose Close or press Escape to return to the body."
29297
+ },
29298
+ {
29299
+ title: "Dates, fields, symbols, and drop caps",
29300
+ description: "Insert updating date/time and page fields, Unicode or custom symbols, and dropped or margin capitals at the caret."
29301
+ },
29302
+ {
29303
+ title: "Equations",
29304
+ description: "Choose Insert \u2192 Equation and enter linear math. Use / for fractions, ^ for powers, \u221A for roots, [a&b;c&d] for matrices, and braces to group expressions."
29305
+ },
29306
+ {
29307
+ title: "Media and embedded files",
29308
+ description: "Insert online-video metadata with a browser-safe poster, or embed another file in the DOCX package."
29309
+ }
29310
+ ]
29311
+ },
29312
+ {
29313
+ title: "Draw tools",
29314
+ items: [
29315
+ {
29316
+ title: "Pen and highlighter",
29317
+ description: "Choose Pen or Highlighter, then drag on a page. Set color and width before drawing. Escape or Select returns to normal editing."
29318
+ },
29319
+ {
29320
+ title: "Erase and select ink",
29321
+ description: "Stroke eraser removes a whole touched stroke. Lasso surrounds ink to select it as a group; drag or nudge the selected group to reposition it."
29322
+ }
29323
+ ]
29324
+ },
29325
+ {
29326
+ title: "Layout tools",
29327
+ items: [
29328
+ {
29329
+ title: "Document or section scope",
29330
+ description: "Choose Whole document for a global change or This section when only the caret's current section should change."
29331
+ },
29332
+ {
29333
+ title: "Margins, orientation, and page size",
29334
+ description: "Choose presets or exact custom page dimensions and margins. Orientation swaps the page between portrait and landscape."
29335
+ },
29336
+ {
29337
+ title: "Columns",
29338
+ description: "Choose one, two, two with divider, or three columns. Insert a column break when text should begin in the next column immediately."
29339
+ },
29340
+ {
29341
+ title: "Page borders and line numbers",
29342
+ description: "Apply a repeating page border and enable continuous, per-page, per-section, or interval-based line numbering."
29343
+ },
29344
+ {
29345
+ title: "Arrange selected objects",
29346
+ description: "With a floating object selected, align it to the page, rotate it by 90\xB0, or change its stacking order with Bring to front and Send to back."
29347
+ }
29348
+ ]
29349
+ },
29350
+ {
29351
+ title: "Object controls",
29352
+ items: [
29353
+ {
29354
+ title: "Move, resize, rotate, and delete",
29355
+ description: "Click an object to select it. Drag its body or move grip, drag a square handle to resize, choose Rotate for an exact angle, and press Delete or Backspace to remove it."
29356
+ },
29357
+ {
29358
+ title: "Text wrapping and layering",
29359
+ description: "Inline moves with text. Wrap lets text flow around the object. Top+Bottom clears text from its sides. In front and Behind control its relationship to text."
29360
+ },
29361
+ {
29362
+ title: "Exact object properties",
29363
+ description: "Use Size to set the object's width \xD7 height, Position for exact page coordinates, Fill for a shape's interior color, and Outline for its border or line color and thickness."
29364
+ }
29365
+ ]
29366
+ },
29367
+ {
29368
+ title: "Special-case recipes",
29369
+ items: [
29370
+ {
29371
+ title: "California pleading paper",
29372
+ description: "Create the fixed 1\u201328 pleading grid in the repeating header layer. Place the numbers in a text box as separate paragraphs, set paragraph spacing to 0 pt, and set the exact line height to 24 pt.",
29373
+ steps: [
29374
+ "Open Insert \u2192 Header, then insert a text box in the repeating header layer.",
29375
+ "Enter 1 through 28 as separate paragraphs and select all of those numbered paragraphs.",
29376
+ "Open Home \u2192 Line & paragraph spacing \u2192 Exactly 24 pt, then choose Remove space before and Remove space after.",
29377
+ "Use Insert \u2192 Shape \u2192 Line for each vertical rule, rotate and position it in the same repeating header layer.",
29378
+ "Choose Close to return to body text."
29379
+ ]
29380
+ },
29381
+ {
29382
+ title: "Magazine columns with a middle rule",
29383
+ description: "Use the document's native column divider so the rule tracks layout automatically.",
29384
+ steps: [
29385
+ "Open Layout \u2192 Columns & divider \u2192 Two + divider line.",
29386
+ "Type normally to flow from the first column into the second.",
29387
+ "Use Insert \u2192 Break \u2192 Column break to move to the second column early."
29388
+ ]
29389
+ },
29390
+ {
29391
+ title: "Resume horizontal rule",
29392
+ description: "Use a body line when the rule belongs to one location in the document.",
29393
+ steps: [
29394
+ "Place the caret near the intended rule and choose Insert \u2192 Shape \u2192 Line.",
29395
+ "Drag to position and size it; use Position for exact placement.",
29396
+ "Choose Inline, Wrap, In front, or Behind according to how nearby text should flow."
29397
+ ]
29398
+ },
29399
+ {
29400
+ title: "Repeating page art",
29401
+ description: "Put lines, logos, and other repeating objects in the header or footer layer. A body object belongs to one page location; a header/footer object repeats with that section."
29402
+ },
29403
+ {
29404
+ title: "Border around every page",
29405
+ description: "Choose Layout \u2192 Page border for a true page border. Use header shapes when the design needs custom partial rules or ornaments."
29406
+ }
29407
+ ]
29408
+ }
29409
+ ];
29410
+ var mod = (apple, key) => apple ? `\u2318${key}` : `Ctrl+${key}`;
29411
+ var modShift = (apple, key) => apple ? `\u21E7\u2318${key}` : `Ctrl+Shift+${key}`;
29412
+ var SHORTCUT_GROUPS = [
29413
+ {
29414
+ title: "History and clipboard",
29415
+ items: [
29416
+ { action: "Undo", keys: (apple) => mod(apple, "Z") },
29417
+ { action: "Redo", keys: (apple) => apple ? "\u21E7\u2318Z" : "Ctrl+Y or Ctrl+Shift+Z" },
29418
+ { action: "Cut", keys: (apple) => mod(apple, "X") },
29419
+ { action: "Copy", keys: (apple) => mod(apple, "C") },
29420
+ { action: "Paste", keys: (apple) => mod(apple, "V") },
29421
+ { action: "Select all in the active story", keys: (apple) => mod(apple, "A") },
29422
+ { action: "Find and replace in the demo", keys: (apple) => mod(apple, "F") }
29423
+ ]
29424
+ },
29425
+ {
29426
+ title: "Text and paragraphs",
29427
+ items: [
29428
+ { action: "Bold", keys: (apple) => mod(apple, "B"), detail: "Requires selected text." },
29429
+ { action: "Italic", keys: (apple) => mod(apple, "I"), detail: "Requires selected text." },
29430
+ { action: "Underline", keys: (apple) => mod(apple, "U"), detail: "Requires selected text." },
29431
+ { action: "Insert or edit link", keys: (apple) => mod(apple, "K"), detail: "Requires selected text." },
29432
+ { action: "New comment", keys: (apple) => apple ? "\u2318\u2325A" : "Ctrl+Alt+M", detail: "Requires selected text." },
29433
+ { action: "Bulleted list", keys: (apple) => modShift(apple, "L") },
29434
+ { action: "Numbered list", keys: (apple) => modShift(apple, "7") },
29435
+ { action: "Align left", keys: (apple) => mod(apple, "L") },
29436
+ { action: "Center", keys: (apple) => mod(apple, "E") },
29437
+ { action: "Align right", keys: (apple) => mod(apple, "R") },
29438
+ { action: "Justify", keys: (apple) => mod(apple, "J") },
29439
+ { action: "Heading 1\u20136", keys: (apple) => apple ? "\u2318\u23251\u20136" : "Ctrl+Alt+1\u20136" },
29440
+ { action: "Normal paragraph", keys: (apple) => apple ? "\u2318\u23250" : "Ctrl+Alt+0" }
29441
+ ]
29442
+ },
29443
+ {
29444
+ title: "Structure and navigation",
29445
+ items: [
29446
+ { action: "Page break", keys: (apple) => mod(apple, "Enter") },
29447
+ { action: "Column break", keys: (apple) => modShift(apple, "Enter") },
29448
+ { action: "Move by character or visual line", keys: () => "Arrow keys" },
29449
+ { action: "Select by character or visual line", keys: () => "Shift+Arrow keys" },
29450
+ { action: "Move to visual line edge", keys: () => "Home / End" },
29451
+ { action: "Select to visual line edge", keys: () => "Shift+Home / Shift+End" },
29452
+ { action: "Move to line edge or adjacent paragraph", keys: (apple) => apple ? "\u2318+Arrow keys" : "Ctrl+Arrow keys" },
29453
+ { action: "Extend to line edge or adjacent paragraph", keys: (apple) => apple ? "\u21E7\u2318+Arrow keys" : "Ctrl+Shift+Arrow keys" },
29454
+ { action: "Next or previous table cell", keys: () => "Tab / Shift+Tab" },
29455
+ { action: "Change list level", keys: () => "Tab / Shift+Tab" }
29456
+ ]
29457
+ },
29458
+ {
29459
+ title: "Objects and editing modes",
29460
+ items: [
29461
+ { action: "Nudge selected floating object or ink", keys: () => "Arrow keys", detail: "Moves one pixel." },
29462
+ { action: "Nudge selected object farther", keys: () => "Shift+Arrow keys", detail: "Moves ten pixels." },
29463
+ { action: "Delete selected object", keys: () => "Delete / Backspace" },
29464
+ { action: "Leave drawing, text-box, header/footer, or object selection", keys: () => "Escape" },
29465
+ { action: "Open this help guide", keys: (apple) => `${mod(apple, "/")} or F1` }
29466
+ ]
29467
+ }
29468
+ ];
29469
+ var panel = {
29470
+ background: "var(--dxw-popover-bg, #fff)",
29471
+ color: "var(--dxw-toolbar-fg, #3c4043)",
29472
+ border: "1px solid var(--dxw-toolbar-border, #dadce0)",
29473
+ borderRadius: 12
29474
+ };
29475
+ function HelpGuide({ open, onClose, returnFocus }) {
29476
+ const [tab, setTab] = useState("guides");
29477
+ const [query, setQuery] = useState("");
29478
+ const searchRef = useRef(null);
29479
+ const previousFocus = useRef(null);
29480
+ const apple = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform);
29481
+ useEffect(() => {
29482
+ if (!open) return;
29483
+ previousFocus.current = document.activeElement;
29484
+ const frame = requestAnimationFrame(() => searchRef.current?.focus());
29485
+ const keydown = (event) => {
29486
+ if (event.key === "Escape") {
29487
+ event.preventDefault();
29488
+ onClose();
29489
+ }
29490
+ };
29491
+ document.addEventListener("keydown", keydown);
29492
+ return () => {
29493
+ cancelAnimationFrame(frame);
29494
+ document.removeEventListener("keydown", keydown);
29495
+ requestAnimationFrame(() => (returnFocus?.current ?? previousFocus.current)?.focus({ preventScroll: true }));
29496
+ };
29497
+ }, [open, onClose, returnFocus]);
29498
+ const needle = query.trim().toLowerCase();
29499
+ const guideGroups = useMemo(() => GUIDE_GROUPS.map((group) => ({
29500
+ ...group,
29501
+ items: group.items.filter(
29502
+ (item) => !needle || `${group.title} ${item.title} ${item.description} ${(item.steps ?? []).join(" ")}`.toLowerCase().includes(needle)
29503
+ )
29504
+ })).filter((group) => group.items.length > 0), [needle]);
29505
+ const shortcutGroups = useMemo(() => SHORTCUT_GROUPS.map((group) => ({
29506
+ ...group,
29507
+ items: group.items.filter(
29508
+ (item) => !needle || `${group.title} ${item.action} ${item.keys(apple)} ${item.detail ?? ""}`.toLowerCase().includes(needle)
29509
+ )
29510
+ })).filter((group) => group.items.length > 0), [apple, needle]);
29511
+ if (!open) return null;
29512
+ return createPortal(
29513
+ /* @__PURE__ */ jsx(
29514
+ "div",
29515
+ {
29516
+ "data-dxw-help-backdrop": "",
29517
+ onMouseDown: (event) => {
29518
+ if (event.target === event.currentTarget) onClose();
29519
+ },
29520
+ style: {
29521
+ position: "fixed",
29522
+ inset: 0,
29523
+ zIndex: 1e4,
29524
+ display: "grid",
29525
+ placeItems: "center",
29526
+ padding: 18,
29527
+ background: "rgba(32,33,36,.48)",
29528
+ fontFamily: "system-ui, sans-serif"
29529
+ },
29530
+ children: /* @__PURE__ */ jsxs(
29531
+ "div",
29532
+ {
29533
+ role: "dialog",
29534
+ "aria-modal": "true",
29535
+ "aria-labelledby": "dxw-help-title",
29536
+ "data-dxw-help-dialog": "",
29537
+ style: {
29538
+ ...panel,
29539
+ width: "min(980px, calc(100vw - 36px))",
29540
+ maxHeight: "min(820px, calc(100vh - 36px))",
29541
+ display: "flex",
29542
+ flexDirection: "column",
29543
+ overflow: "hidden",
29544
+ boxShadow: "0 18px 60px rgba(0,0,0,.28)"
29545
+ },
29546
+ children: [
29547
+ /* @__PURE__ */ jsxs("header", { style: { padding: "18px 20px 14px", borderBottom: "1px solid var(--dxw-toolbar-border, #dadce0)" }, children: [
29548
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "flex-start", gap: 16 }, children: [
29549
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1 }, children: [
29550
+ /* @__PURE__ */ jsx("h2", { id: "dxw-help-title", style: { margin: 0, fontSize: 22, color: "var(--dxw-toolbar-fg, #202124)" }, children: "WordInWeb help" }),
29551
+ /* @__PURE__ */ jsx("p", { style: { margin: "4px 0 0", color: "var(--dxw-toolbar-muted, #5f6368)", fontSize: 13 }, children: "Tool guides, editing recipes, and keyboard shortcuts." })
29552
+ ] }),
29553
+ /* @__PURE__ */ jsx(
29554
+ "button",
29555
+ {
29556
+ type: "button",
29557
+ "aria-label": "Close help",
29558
+ onClick: onClose,
29559
+ style: { border: 0, background: "transparent", color: "inherit", cursor: "pointer", fontSize: 24, lineHeight: 1, padding: 4 },
29560
+ children: "\xD7"
29561
+ }
29562
+ )
29563
+ ] }),
29564
+ /* @__PURE__ */ jsx(
29565
+ "input",
29566
+ {
29567
+ ref: searchRef,
29568
+ type: "search",
29569
+ "aria-label": "Search help",
29570
+ placeholder: "Search tools, lines, columns, shortcuts\u2026",
29571
+ value: query,
29572
+ onChange: (event) => setQuery(event.target.value),
29573
+ style: {
29574
+ width: "100%",
29575
+ boxSizing: "border-box",
29576
+ marginTop: 14,
29577
+ padding: "10px 12px",
29578
+ border: "1px solid var(--dxw-toolbar-border, #c7cbd1)",
29579
+ borderRadius: 8,
29580
+ background: "var(--dxw-popover-bg, #fff)",
29581
+ color: "inherit",
29582
+ font: "14px system-ui, sans-serif",
29583
+ outlineColor: "var(--dxw-accent, #1a73e8)"
29584
+ }
29585
+ }
29586
+ ),
29587
+ /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": "Help sections", style: { display: "flex", gap: 6, marginTop: 12 }, children: ["guides", "shortcuts"].map((name) => /* @__PURE__ */ jsx(
29588
+ "button",
29589
+ {
29590
+ type: "button",
29591
+ role: "tab",
29592
+ "aria-selected": tab === name,
29593
+ onClick: () => setTab(name),
29594
+ style: {
29595
+ border: 0,
29596
+ borderRadius: 7,
29597
+ padding: "7px 12px",
29598
+ background: tab === name ? "var(--dxw-tab-active-bg, #e8f0fe)" : "transparent",
29599
+ color: tab === name ? "var(--dxw-accent, #1a73e8)" : "inherit",
29600
+ font: "600 13px system-ui, sans-serif",
29601
+ cursor: "pointer",
29602
+ textTransform: "capitalize"
29603
+ },
29604
+ children: name === "guides" ? "Guides" : "Shortcuts"
29605
+ },
29606
+ name
29607
+ )) })
29608
+ ] }),
29609
+ /* @__PURE__ */ jsxs("div", { style: { overflow: "auto", padding: "18px 20px 24px" }, children: [
29610
+ tab === "guides" && guideGroups.map((group) => /* @__PURE__ */ jsxs("section", { style: { marginBottom: 24 }, children: [
29611
+ /* @__PURE__ */ jsx("h3", { style: { margin: "0 0 10px", fontSize: 15 }, children: group.title }),
29612
+ /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 260px), 1fr))", gap: 10 }, children: group.items.map((item) => /* @__PURE__ */ jsxs("article", { style: { ...panel, padding: 14, background: "var(--dxw-help-card-bg, #f8fafd)" }, children: [
29613
+ /* @__PURE__ */ jsx("h4", { style: { margin: "0 0 6px", fontSize: 14 }, children: item.title }),
29614
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, color: "var(--dxw-toolbar-muted, #5f6368)", fontSize: 12.5, lineHeight: 1.45 }, children: item.description }),
29615
+ item.steps && /* @__PURE__ */ jsx("ol", { style: { margin: "9px 0 0", paddingLeft: 19, color: "var(--dxw-toolbar-muted, #5f6368)", fontSize: 12.5, lineHeight: 1.5 }, children: item.steps.map((step) => /* @__PURE__ */ jsx("li", { children: step }, step)) })
29616
+ ] }, item.title)) })
29617
+ ] }, group.title)),
29618
+ tab === "shortcuts" && shortcutGroups.map((group) => /* @__PURE__ */ jsxs("section", { style: { marginBottom: 24 }, children: [
29619
+ /* @__PURE__ */ jsx("h3", { style: { margin: "0 0 8px", fontSize: 15 }, children: group.title }),
29620
+ /* @__PURE__ */ jsx("div", { style: { ...panel, overflow: "hidden" }, children: group.items.map((item, index) => /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "minmax(180px, 1fr) minmax(150px, auto)", gap: 16, alignItems: "center", padding: "10px 12px", borderTop: index ? "1px solid var(--dxw-toolbar-border, #e6e8eb)" : 0 }, children: [
29621
+ /* @__PURE__ */ jsxs("div", { children: [
29622
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 13 }, children: item.action }),
29623
+ item.detail && /* @__PURE__ */ jsx("div", { style: { color: "var(--dxw-toolbar-muted, #5f6368)", fontSize: 11.5, marginTop: 2 }, children: item.detail })
29624
+ ] }),
29625
+ /* @__PURE__ */ jsx("kbd", { style: { justifySelf: "end", padding: "4px 7px", border: "1px solid var(--dxw-toolbar-border, #c7cbd1)", borderBottomWidth: 2, borderRadius: 5, background: "var(--dxw-help-key-bg, #fff)", font: "12px ui-monospace, SFMono-Regular, Menlo, monospace", whiteSpace: "nowrap" }, children: item.keys(apple) })
29626
+ ] }, item.action)) })
29627
+ ] }, group.title)),
29628
+ (tab === "guides" ? guideGroups.length : shortcutGroups.length) === 0 && /* @__PURE__ */ jsxs("p", { role: "status", style: { color: "var(--dxw-toolbar-muted, #5f6368)", textAlign: "center", padding: 36 }, children: [
29629
+ "No help topics match \u201C",
29630
+ query,
29631
+ "\u201D."
29632
+ ] })
29633
+ ] })
29634
+ ]
29635
+ }
29636
+ )
29637
+ }
29638
+ ),
29639
+ document.body
29640
+ );
29641
+ }
29642
+
29643
+ // src/toolbar.tsx
29644
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
28764
29645
  var T = {
28765
29646
  bg: "var(--dxw-toolbar-bg, #f9fbfd)",
28766
29647
  fg: "var(--dxw-toolbar-fg, #3c4043)",
@@ -28867,10 +29748,11 @@ var PAGE_SIZES = [
28867
29748
  { value: "a6", label: "A6", description: '4.13" \xD7 5.83"', width: 4.13, height: 5.83 },
28868
29749
  { value: "envelope10", label: "Envelope #10", description: '4.13" \xD7 9.5"', width: 4.13, height: 9.5 }
28869
29750
  ];
28870
- function Btn({ label, title, active, onClick }) {
28871
- return /* @__PURE__ */ jsx(
29751
+ function Btn({ label, title, active, onClick, buttonRef }) {
29752
+ return /* @__PURE__ */ jsx2(
28872
29753
  "button",
28873
29754
  {
29755
+ ref: buttonRef,
28874
29756
  title,
28875
29757
  style: btnStyle(!!active),
28876
29758
  onMouseDown: (e) => e.preventDefault(),
@@ -28882,19 +29764,19 @@ function Btn({ label, title, active, onClick }) {
28882
29764
  );
28883
29765
  }
28884
29766
  function Sep() {
28885
- return /* @__PURE__ */ jsx("span", { style: { width: 1, height: 18, background: T.border, margin: "0 4px", flexShrink: 0 } });
29767
+ return /* @__PURE__ */ jsx2("span", { style: { width: 1, height: 18, background: T.border, margin: "0 4px", flexShrink: 0 } });
28886
29768
  }
28887
29769
  function OverflowIcon() {
28888
- return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "currentColor", children: [
28889
- /* @__PURE__ */ jsx("circle", { cx: "8", cy: "3", r: "1.4" }),
28890
- /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "1.4" }),
28891
- /* @__PURE__ */ jsx("circle", { cx: "8", cy: "13", r: "1.4" })
29770
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "currentColor", children: [
29771
+ /* @__PURE__ */ jsx2("circle", { cx: "8", cy: "3", r: "1.4" }),
29772
+ /* @__PURE__ */ jsx2("circle", { cx: "8", cy: "8", r: "1.4" }),
29773
+ /* @__PURE__ */ jsx2("circle", { cx: "8", cy: "13", r: "1.4" })
28892
29774
  ] });
28893
29775
  }
28894
29776
  function OverflowMenu({ children: children2 }) {
28895
- const [open, setOpen] = useState(false);
28896
- const rootRef = useRef(null);
28897
- useEffect(() => {
29777
+ const [open, setOpen] = useState2(false);
29778
+ const rootRef = useRef2(null);
29779
+ useEffect2(() => {
28898
29780
  if (!open) return;
28899
29781
  const close = (e) => {
28900
29782
  if (!rootRef.current?.contains(e.target)) setOpen(false);
@@ -28902,8 +29784,8 @@ function OverflowMenu({ children: children2 }) {
28902
29784
  document.addEventListener("mousedown", close);
28903
29785
  return () => document.removeEventListener("mousedown", close);
28904
29786
  }, [open]);
28905
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-flex", marginLeft: "auto" }, children: [
28906
- /* @__PURE__ */ jsx(
29787
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-flex", marginLeft: "auto" }, children: [
29788
+ /* @__PURE__ */ jsx2(
28907
29789
  "button",
28908
29790
  {
28909
29791
  title: "More tools",
@@ -28911,10 +29793,10 @@ function OverflowMenu({ children: children2 }) {
28911
29793
  style: btnStyle(open),
28912
29794
  onMouseDown: (e) => e.preventDefault(),
28913
29795
  onClick: () => setOpen(!open),
28914
- children: /* @__PURE__ */ jsx(OverflowIcon, {})
29796
+ children: /* @__PURE__ */ jsx2(OverflowIcon, {})
28915
29797
  }
28916
29798
  ),
28917
- open && /* @__PURE__ */ jsx(
29799
+ open && /* @__PURE__ */ jsx2(
28918
29800
  "div",
28919
29801
  {
28920
29802
  "data-dxw-overflow-menu": "",
@@ -28942,16 +29824,16 @@ function OverflowMenu({ children: children2 }) {
28942
29824
  }
28943
29825
  var icon = { width: 16, height: 16, display: "block" };
28944
29826
  function ImageIcon() {
28945
- return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
28946
- /* @__PURE__ */ jsx("rect", { x: "1.5", y: "2.5", width: "13", height: "11", rx: "1" }),
28947
- /* @__PURE__ */ jsx("circle", { cx: "5.2", cy: "6", r: "1.2", fill: "currentColor", stroke: "none" }),
28948
- /* @__PURE__ */ jsx("path", { d: "M2.5 12l3.5-4 2.8 3 2-2.4 2.7 3.4" })
29827
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
29828
+ /* @__PURE__ */ jsx2("rect", { x: "1.5", y: "2.5", width: "13", height: "11", rx: "1" }),
29829
+ /* @__PURE__ */ jsx2("circle", { cx: "5.2", cy: "6", r: "1.2", fill: "currentColor", stroke: "none" }),
29830
+ /* @__PURE__ */ jsx2("path", { d: "M2.5 12l3.5-4 2.8 3 2-2.4 2.7 3.4" })
28949
29831
  ] });
28950
29832
  }
28951
29833
  function HighlightIcon({ color }) {
28952
- return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", children: [
28953
- /* @__PURE__ */ jsx("path", { d: "M3 9.5L9.5 3l3.5 3.5L6.5 13H4.5L3 11.5v-2z", fill: "none", stroke: "currentColor", strokeWidth: "1.3" }),
28954
- /* @__PURE__ */ jsx("rect", { x: "2", y: "13.5", width: "12", height: "2.5", rx: "0.5", fill: color })
29834
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", children: [
29835
+ /* @__PURE__ */ jsx2("path", { d: "M3 9.5L9.5 3l3.5 3.5L6.5 13H4.5L3 11.5v-2z", fill: "none", stroke: "currentColor", strokeWidth: "1.3" }),
29836
+ /* @__PURE__ */ jsx2("rect", { x: "2", y: "13.5", width: "12", height: "2.5", rx: "0.5", fill: color })
28955
29837
  ] });
28956
29838
  }
28957
29839
  function ToolbarMenuSelect({
@@ -28967,12 +29849,12 @@ function ToolbarMenuSelect({
28967
29849
  className,
28968
29850
  style
28969
29851
  }) {
28970
- const [open, setOpen] = useState(false);
28971
- const [position, setPosition] = useState({ left: 8, top: 8, width: menuWidth ?? 180, maxHeight: 320 });
28972
- const rootRef = useRef(null);
28973
- const triggerRef = useRef(null);
28974
- const menuRef = useRef(null);
28975
- const keyboardOpen = useRef(null);
29852
+ const [open, setOpen] = useState2(false);
29853
+ const [position, setPosition] = useState2({ left: 8, top: 8, width: menuWidth ?? 180, maxHeight: 320 });
29854
+ const rootRef = useRef2(null);
29855
+ const triggerRef = useRef2(null);
29856
+ const menuRef = useRef2(null);
29857
+ const keyboardOpen = useRef2(null);
28976
29858
  const id = useId();
28977
29859
  const selected = options.find((option) => option.value === value);
28978
29860
  useLayoutEffect(() => {
@@ -29055,7 +29937,7 @@ function ToolbarMenuSelect({
29055
29937
  items[next]?.focus({ preventScroll: true });
29056
29938
  };
29057
29939
  let previousGroup;
29058
- return /* @__PURE__ */ jsxs(
29940
+ return /* @__PURE__ */ jsxs2(
29059
29941
  "span",
29060
29942
  {
29061
29943
  ref: rootRef,
@@ -29063,7 +29945,7 @@ function ToolbarMenuSelect({
29063
29945
  "data-dxw-menu-select": "",
29064
29946
  style: { position: "relative", display: "inline-flex", width },
29065
29947
  children: [
29066
- /* @__PURE__ */ jsxs(
29948
+ /* @__PURE__ */ jsxs2(
29067
29949
  "select",
29068
29950
  {
29069
29951
  tabIndex: -1,
@@ -29082,12 +29964,12 @@ function ToolbarMenuSelect({
29082
29964
  pointerEvents: "none"
29083
29965
  },
29084
29966
  children: [
29085
- !options.some((option) => option.value === value) && /* @__PURE__ */ jsx("option", { value: "", children: String(placeholder) }),
29086
- options.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, disabled: option.disabled, children: String(option.label) }, option.value))
29967
+ !options.some((option) => option.value === value) && /* @__PURE__ */ jsx2("option", { value: "", children: String(placeholder) }),
29968
+ options.map((option) => /* @__PURE__ */ jsx2("option", { value: option.value, disabled: option.disabled, children: String(option.label) }, option.value))
29087
29969
  ]
29088
29970
  }
29089
29971
  ),
29090
- /* @__PURE__ */ jsxs(
29972
+ /* @__PURE__ */ jsxs2(
29091
29973
  "button",
29092
29974
  {
29093
29975
  ref: triggerRef,
@@ -29126,12 +30008,12 @@ function ToolbarMenuSelect({
29126
30008
  ...style
29127
30009
  },
29128
30010
  children: [
29129
- /* @__PURE__ */ jsx("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontFamily: selected?.fontFamily }, children: selected?.label ?? placeholder }),
29130
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "dxw-menu-select-chevron", style: { flexShrink: 0, fontSize: 10 }, children: "\u2304" })
30011
+ /* @__PURE__ */ jsx2("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontFamily: selected?.fontFamily }, children: selected?.label ?? placeholder }),
30012
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", className: "dxw-menu-select-chevron", style: { flexShrink: 0, fontSize: 10 }, children: "\u2304" })
29131
30013
  ]
29132
30014
  }
29133
30015
  ),
29134
- open && /* @__PURE__ */ jsx(
30016
+ open && /* @__PURE__ */ jsx2(
29135
30017
  "div",
29136
30018
  {
29137
30019
  ref: menuRef,
@@ -29162,9 +30044,9 @@ function ToolbarMenuSelect({
29162
30044
  const groupChanged = option.group !== previousGroup;
29163
30045
  previousGroup = option.group;
29164
30046
  const active = option.value === value;
29165
- return /* @__PURE__ */ jsxs(Fragment, { children: [
29166
- groupChanged && option.group && /* @__PURE__ */ jsx("div", { className: "dxw-menu-select-group", style: { padding: "6px 8px 3px", color: T.muted, font: "600 10.5px system-ui, sans-serif" }, children: option.group }),
29167
- /* @__PURE__ */ jsxs(
30047
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
30048
+ groupChanged && option.group && /* @__PURE__ */ jsx2("div", { className: "dxw-menu-select-group", style: { padding: "6px 8px 3px", color: T.muted, font: "600 10.5px system-ui, sans-serif" }, children: option.group }),
30049
+ /* @__PURE__ */ jsxs2(
29168
30050
  "button",
29169
30051
  {
29170
30052
  type: "button",
@@ -29199,8 +30081,8 @@ function ToolbarMenuSelect({
29199
30081
  if (!active) event.currentTarget.style.background = "transparent";
29200
30082
  },
29201
30083
  children: [
29202
- /* @__PURE__ */ jsx("span", { style: { flex: 1 }, children: option.label }),
29203
- active && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { color: T.accent, fontWeight: 700 }, children: "\u2713" })
30084
+ /* @__PURE__ */ jsx2("span", { style: { flex: 1 }, children: option.label }),
30085
+ active && /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", style: { color: T.accent, fontWeight: 700 }, children: "\u2713" })
29204
30086
  ]
29205
30087
  }
29206
30088
  )
@@ -29219,7 +30101,7 @@ function ActionMenu({
29219
30101
  onPick,
29220
30102
  width
29221
30103
  }) {
29222
- return /* @__PURE__ */ jsx(
30104
+ return /* @__PURE__ */ jsx2(
29223
30105
  ToolbarMenuSelect,
29224
30106
  {
29225
30107
  title,
@@ -29238,9 +30120,9 @@ function ActionMenu({
29238
30120
  );
29239
30121
  }
29240
30122
  function HighlightMenu({ current, onPick }) {
29241
- const [open, setOpen] = useState(false);
29242
- const rootRef = useRef(null);
29243
- useEffect(() => {
30123
+ const [open, setOpen] = useState2(false);
30124
+ const rootRef = useRef2(null);
30125
+ useEffect2(() => {
29244
30126
  if (!open) return;
29245
30127
  const close = (e) => {
29246
30128
  if (!rootRef.current?.contains(e.target)) setOpen(false);
@@ -29248,18 +30130,18 @@ function HighlightMenu({ current, onPick }) {
29248
30130
  document.addEventListener("mousedown", close);
29249
30131
  return () => document.removeEventListener("mousedown", close);
29250
30132
  }, [open]);
29251
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
29252
- /* @__PURE__ */ jsx(
30133
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30134
+ /* @__PURE__ */ jsx2(
29253
30135
  "button",
29254
30136
  {
29255
30137
  title: "Highlight color",
29256
30138
  style: btnStyle(open),
29257
30139
  onMouseDown: (e) => e.preventDefault(),
29258
30140
  onClick: () => setOpen(!open),
29259
- children: /* @__PURE__ */ jsx(HighlightIcon, { color: current ?? "#ffff00" })
30141
+ children: /* @__PURE__ */ jsx2(HighlightIcon, { color: current ?? "#ffff00" })
29260
30142
  }
29261
30143
  ),
29262
- open && /* @__PURE__ */ jsxs(
30144
+ open && /* @__PURE__ */ jsxs2(
29263
30145
  "div",
29264
30146
  {
29265
30147
  onMouseDown: (e) => e.preventDefault(),
@@ -29278,7 +30160,7 @@ function HighlightMenu({ current, onPick }) {
29278
30160
  alignItems: "center"
29279
30161
  },
29280
30162
  children: [
29281
- HIGHLIGHTS.map((h) => /* @__PURE__ */ jsx(
30163
+ HIGHLIGHTS.map((h) => /* @__PURE__ */ jsx2(
29282
30164
  "div",
29283
30165
  {
29284
30166
  title: h.name,
@@ -29290,7 +30172,7 @@ function HighlightMenu({ current, onPick }) {
29290
30172
  },
29291
30173
  h.name
29292
30174
  )),
29293
- /* @__PURE__ */ jsx(
30175
+ /* @__PURE__ */ jsx2(
29294
30176
  "div",
29295
30177
  {
29296
30178
  title: "No highlight",
@@ -29359,12 +30241,12 @@ function ColorMenu({
29359
30241
  trigger,
29360
30242
  onPick
29361
30243
  }) {
29362
- const [open, setOpen] = useState(false);
29363
- const [custom, setCustom] = useState(current);
29364
- const [position, setPosition] = useState({ left: 8, top: 8 });
29365
- const rootRef = useRef(null);
29366
- const triggerRef = useRef(null);
29367
- const menuRef = useRef(null);
30244
+ const [open, setOpen] = useState2(false);
30245
+ const [custom, setCustom] = useState2(current);
30246
+ const [position, setPosition] = useState2({ left: 8, top: 8 });
30247
+ const rootRef = useRef2(null);
30248
+ const triggerRef = useRef2(null);
30249
+ const menuRef = useRef2(null);
29368
30250
  const valid = normalizedColor(custom);
29369
30251
  useLayoutEffect(() => {
29370
30252
  if (!open) return;
@@ -29404,8 +30286,8 @@ function ColorMenu({
29404
30286
  onPick(value);
29405
30287
  setOpen(false);
29406
30288
  };
29407
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, className: "dxw-color-control", style: { position: "relative", display: "inline-flex" }, children: [
29408
- /* @__PURE__ */ jsx(
30289
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, className: "dxw-color-control", style: { position: "relative", display: "inline-flex" }, children: [
30290
+ /* @__PURE__ */ jsx2(
29409
30291
  "button",
29410
30292
  {
29411
30293
  ref: triggerRef,
@@ -29421,7 +30303,7 @@ function ColorMenu({
29421
30303
  children: trigger
29422
30304
  }
29423
30305
  ),
29424
- open && /* @__PURE__ */ jsxs(
30306
+ open && /* @__PURE__ */ jsxs2(
29425
30307
  "div",
29426
30308
  {
29427
30309
  ref: menuRef,
@@ -29444,7 +30326,7 @@ function ColorMenu({
29444
30326
  boxShadow: T.popoverShadow
29445
30327
  },
29446
30328
  children: [
29447
- /* @__PURE__ */ jsx("div", { className: "dxw-color-swatches", style: { display: "grid", gridTemplateColumns: "repeat(8, 1fr)", gap: 4 }, children: COLOR_SWATCHES.map((color) => /* @__PURE__ */ jsx(
30329
+ /* @__PURE__ */ jsx2("div", { className: "dxw-color-swatches", style: { display: "grid", gridTemplateColumns: "repeat(8, 1fr)", gap: 4 }, children: COLOR_SWATCHES.map((color) => /* @__PURE__ */ jsx2(
29448
30330
  "button",
29449
30331
  {
29450
30332
  type: "button",
@@ -29466,9 +30348,9 @@ function ColorMenu({
29466
30348
  },
29467
30349
  color
29468
30350
  )) }),
29469
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, marginTop: 8 }, children: [
29470
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { width: 24, height: 24, borderRadius: 4, border: `1px solid ${T.border}`, background: valid ?? current, flexShrink: 0 } }),
29471
- /* @__PURE__ */ jsx(
30351
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: 6, marginTop: 8 }, children: [
30352
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", style: { width: 24, height: 24, borderRadius: 4, border: `1px solid ${T.border}`, background: valid ?? current, flexShrink: 0 } }),
30353
+ /* @__PURE__ */ jsx2(
29472
30354
  "input",
29473
30355
  {
29474
30356
  "aria-label": "Custom hex color",
@@ -29483,7 +30365,7 @@ function ColorMenu({
29483
30365
  style: { minWidth: 0, flex: 1, height: 28, boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 5, padding: "3px 6px", color: T.fg, background: T.popoverBg }
29484
30366
  }
29485
30367
  ),
29486
- /* @__PURE__ */ jsx("button", { type: "button", disabled: !valid, onClick: () => valid && pick(valid), style: pillBtn, children: "Apply" })
30368
+ /* @__PURE__ */ jsx2("button", { type: "button", disabled: !valid, onClick: () => valid && pick(valid), style: pillBtn, children: "Apply" })
29487
30369
  ] })
29488
30370
  ]
29489
30371
  }
@@ -29491,46 +30373,46 @@ function ColorMenu({
29491
30373
  ] });
29492
30374
  }
29493
30375
  function BulletListIcon() {
29494
- return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
29495
- /* @__PURE__ */ jsx("circle", { cx: "3", cy: "4", r: "1.1", fill: "currentColor", stroke: "none" }),
29496
- /* @__PURE__ */ jsx("circle", { cx: "3", cy: "8", r: "1.1", fill: "currentColor", stroke: "none" }),
29497
- /* @__PURE__ */ jsx("circle", { cx: "3", cy: "12", r: "1.1", fill: "currentColor", stroke: "none" }),
29498
- /* @__PURE__ */ jsx("path", { d: "M6.5 4h8M6.5 8h8M6.5 12h8", strokeLinecap: "round" })
30376
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30377
+ /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "4", r: "1.1", fill: "currentColor", stroke: "none" }),
30378
+ /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "8", r: "1.1", fill: "currentColor", stroke: "none" }),
30379
+ /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "12", r: "1.1", fill: "currentColor", stroke: "none" }),
30380
+ /* @__PURE__ */ jsx2("path", { d: "M6.5 4h8M6.5 8h8M6.5 12h8", strokeLinecap: "round" })
29499
30381
  ] });
29500
30382
  }
29501
30383
  function NumberListIcon() {
29502
- return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
29503
- /* @__PURE__ */ jsx("text", { x: "1", y: "5.6", fontSize: "5.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "1" }),
29504
- /* @__PURE__ */ jsx("text", { x: "1", y: "9.9", fontSize: "5.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "2" }),
29505
- /* @__PURE__ */ jsx("text", { x: "1", y: "14.2", fontSize: "5.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "3" }),
29506
- /* @__PURE__ */ jsx("path", { d: "M6.5 4h8M6.5 8h8M6.5 12h8", strokeLinecap: "round" })
30384
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30385
+ /* @__PURE__ */ jsx2("text", { x: "1", y: "5.6", fontSize: "5.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "1" }),
30386
+ /* @__PURE__ */ jsx2("text", { x: "1", y: "9.9", fontSize: "5.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "2" }),
30387
+ /* @__PURE__ */ jsx2("text", { x: "1", y: "14.2", fontSize: "5.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "3" }),
30388
+ /* @__PURE__ */ jsx2("path", { d: "M6.5 4h8M6.5 8h8M6.5 12h8", strokeLinecap: "round" })
29507
30389
  ] });
29508
30390
  }
29509
30391
  function LinkIcon() {
29510
- return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
29511
- /* @__PURE__ */ jsx("path", { d: "M6.5 9.5l3-3", strokeLinecap: "round" }),
29512
- /* @__PURE__ */ jsx("path", { d: "M7.5 4.5l1.2-1.2a2.6 2.6 0 013.7 3.7L11.2 8.2", strokeLinecap: "round" }),
29513
- /* @__PURE__ */ jsx("path", { d: "M8.5 11.5l-1.2 1.2a2.6 2.6 0 01-3.7-3.7l1.2-1.2", strokeLinecap: "round" })
30392
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30393
+ /* @__PURE__ */ jsx2("path", { d: "M6.5 9.5l3-3", strokeLinecap: "round" }),
30394
+ /* @__PURE__ */ jsx2("path", { d: "M7.5 4.5l1.2-1.2a2.6 2.6 0 013.7 3.7L11.2 8.2", strokeLinecap: "round" }),
30395
+ /* @__PURE__ */ jsx2("path", { d: "M8.5 11.5l-1.2 1.2a2.6 2.6 0 01-3.7-3.7l1.2-1.2", strokeLinecap: "round" })
29514
30396
  ] });
29515
30397
  }
29516
30398
  function ClearFormatIcon() {
29517
- return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
29518
- /* @__PURE__ */ jsx("path", { d: "M5 3h8M9 3l-2.5 9", strokeLinecap: "round" }),
29519
- /* @__PURE__ */ jsx("path", { d: "M3 13.5l3.5-3.5M3 10l3.5 3.5", strokeLinecap: "round" })
30399
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30400
+ /* @__PURE__ */ jsx2("path", { d: "M5 3h8M9 3l-2.5 9", strokeLinecap: "round" }),
30401
+ /* @__PURE__ */ jsx2("path", { d: "M3 13.5l3.5-3.5M3 10l3.5 3.5", strokeLinecap: "round" })
29520
30402
  ] });
29521
30403
  }
29522
30404
  function IndentIcon({ dir }) {
29523
- return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
29524
- /* @__PURE__ */ jsx("path", { d: "M2 3h12M8 6.5h6M8 9.5h6M2 13h12", strokeLinecap: "round" }),
29525
- dir === 1 ? /* @__PURE__ */ jsx("path", { d: "M2.5 6l3 2-3 2z", fill: "currentColor", stroke: "none" }) : /* @__PURE__ */ jsx("path", { d: "M5.5 6l-3 2 3 2z", fill: "currentColor", stroke: "none" })
30405
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30406
+ /* @__PURE__ */ jsx2("path", { d: "M2 3h12M8 6.5h6M8 9.5h6M2 13h12", strokeLinecap: "round" }),
30407
+ dir === 1 ? /* @__PURE__ */ jsx2("path", { d: "M2.5 6l3 2-3 2z", fill: "currentColor", stroke: "none" }) : /* @__PURE__ */ jsx2("path", { d: "M5.5 6l-3 2 3 2z", fill: "currentColor", stroke: "none" })
29526
30408
  ] });
29527
30409
  }
29528
30410
  function LinkMenu({ api }) {
29529
- const [open, setOpen] = useState(false);
29530
- const [url, setUrl] = useState("");
29531
- const rootRef = useRef(null);
29532
- const inputRef = useRef(null);
29533
- useEffect(() => {
30411
+ const [open, setOpen] = useState2(false);
30412
+ const [url, setUrl] = useState2("");
30413
+ const rootRef = useRef2(null);
30414
+ const inputRef = useRef2(null);
30415
+ useEffect2(() => {
29534
30416
  if (!open) return;
29535
30417
  setUrl(api?.getLinkAt() ?? "");
29536
30418
  inputRef.current?.focus();
@@ -29545,9 +30427,9 @@ function LinkMenu({ api }) {
29545
30427
  if (v) api?.setLink(/^[a-z][a-z0-9+.-]*:/i.test(v) ? v : `https://${v}`);
29546
30428
  setOpen(false);
29547
30429
  };
29548
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
29549
- /* @__PURE__ */ jsx("button", { title: "Insert link", style: btnStyle(open), onMouseDown: (e) => e.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsx(LinkIcon, {}) }),
29550
- open && /* @__PURE__ */ jsxs(
30430
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30431
+ /* @__PURE__ */ jsx2("button", { title: "Insert link", style: btnStyle(open), onMouseDown: (e) => e.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsx2(LinkIcon, {}) }),
30432
+ open && /* @__PURE__ */ jsxs2(
29551
30433
  "div",
29552
30434
  {
29553
30435
  style: {
@@ -29566,7 +30448,7 @@ function LinkMenu({ api }) {
29566
30448
  alignItems: "center"
29567
30449
  },
29568
30450
  children: [
29569
- /* @__PURE__ */ jsx(
30451
+ /* @__PURE__ */ jsx2(
29570
30452
  "input",
29571
30453
  {
29572
30454
  ref: inputRef,
@@ -29577,8 +30459,8 @@ function LinkMenu({ api }) {
29577
30459
  style: { flex: 1, border: `1px solid ${T.border}`, borderRadius: 6, padding: "5px 8px", font: "13px system-ui, sans-serif", outline: "none" }
29578
30460
  }
29579
30461
  ),
29580
- /* @__PURE__ */ jsx("button", { style: pillBtn, disabled: !url.trim(), onClick: submit, children: "Apply" }),
29581
- api?.getLinkAt() && /* @__PURE__ */ jsx(
30462
+ /* @__PURE__ */ jsx2("button", { style: pillBtn, disabled: !url.trim(), onClick: submit, children: "Apply" }),
30463
+ api?.getLinkAt() && /* @__PURE__ */ jsx2(
29582
30464
  "button",
29583
30465
  {
29584
30466
  title: "Remove link",
@@ -29596,25 +30478,25 @@ function LinkMenu({ api }) {
29596
30478
  ] });
29597
30479
  }
29598
30480
  function FootnoteIcon() {
29599
- return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
29600
- /* @__PURE__ */ jsx("path", { d: "M2.5 13V3.5M2.5 3.5h7", strokeLinecap: "round" }),
29601
- /* @__PURE__ */ jsx("text", { x: "10.2", y: "6.6", fontSize: "6.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "1" }),
29602
- /* @__PURE__ */ jsx("path", { d: "M2.5 13h11", strokeLinecap: "round", strokeDasharray: "1.5 1.6" })
30481
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30482
+ /* @__PURE__ */ jsx2("path", { d: "M2.5 13V3.5M2.5 3.5h7", strokeLinecap: "round" }),
30483
+ /* @__PURE__ */ jsx2("text", { x: "10.2", y: "6.6", fontSize: "6.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "1" }),
30484
+ /* @__PURE__ */ jsx2("path", { d: "M2.5 13h11", strokeLinecap: "round", strokeDasharray: "1.5 1.6" })
29603
30485
  ] });
29604
30486
  }
29605
30487
  function CommentIcon() {
29606
- return /* @__PURE__ */ jsxs("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
29607
- /* @__PURE__ */ jsx("path", { d: "M1.5 3.5h13v8h-7l-3 3v-3h-3z", strokeLinejoin: "round" }),
29608
- /* @__PURE__ */ jsx("path", { d: "M8 5.5v4M6 7.5h4", strokeLinecap: "round" })
30488
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30489
+ /* @__PURE__ */ jsx2("path", { d: "M1.5 3.5h13v8h-7l-3 3v-3h-3z", strokeLinejoin: "round" }),
30490
+ /* @__PURE__ */ jsx2("path", { d: "M8 5.5v4M6 7.5h4", strokeLinecap: "round" })
29609
30491
  ] });
29610
30492
  }
29611
30493
  function FootnoteMenu({ api }) {
29612
- const [open, setOpen] = useState(false);
29613
- const [text, setText] = useState("");
29614
- const [hint, setHint] = useState("");
29615
- const rootRef = useRef(null);
29616
- const inputRef = useRef(null);
29617
- useEffect(() => {
30494
+ const [open, setOpen] = useState2(false);
30495
+ const [text, setText] = useState2("");
30496
+ const [hint, setHint] = useState2("");
30497
+ const rootRef = useRef2(null);
30498
+ const inputRef = useRef2(null);
30499
+ useEffect2(() => {
29618
30500
  if (!open) return;
29619
30501
  inputRef.current?.focus();
29620
30502
  const close = (e) => {
@@ -29632,9 +30514,9 @@ function FootnoteMenu({ api }) {
29632
30514
  setHint("Click into the text first so the reference has a place to go.");
29633
30515
  }
29634
30516
  };
29635
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
29636
- /* @__PURE__ */ jsx("button", { title: "Insert footnote (at the caret)", style: btnStyle(open), onMouseDown: (e) => e.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsx(FootnoteIcon, {}) }),
29637
- open && /* @__PURE__ */ jsxs(
30517
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30518
+ /* @__PURE__ */ jsx2("button", { title: "Insert footnote (at the caret)", style: btnStyle(open), onMouseDown: (e) => e.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsx2(FootnoteIcon, {}) }),
30519
+ open && /* @__PURE__ */ jsxs2(
29638
30520
  "div",
29639
30521
  {
29640
30522
  style: {
@@ -29650,7 +30532,7 @@ function FootnoteMenu({ api }) {
29650
30532
  width: 240
29651
30533
  },
29652
30534
  children: [
29653
- /* @__PURE__ */ jsx(
30535
+ /* @__PURE__ */ jsx2(
29654
30536
  "textarea",
29655
30537
  {
29656
30538
  ref: inputRef,
@@ -29676,10 +30558,10 @@ function FootnoteMenu({ api }) {
29676
30558
  }
29677
30559
  }
29678
30560
  ),
29679
- hint && /* @__PURE__ */ jsx("div", { style: { color: "#c5221f", fontSize: 12, marginTop: 4 }, children: hint }),
29680
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 6 }, children: [
29681
- /* @__PURE__ */ jsx("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => setOpen(false), children: "Cancel" }),
29682
- /* @__PURE__ */ jsx("button", { style: pillBtn, disabled: !text.trim(), onClick: submit, children: "Insert" })
30561
+ hint && /* @__PURE__ */ jsx2("div", { style: { color: "#c5221f", fontSize: 12, marginTop: 4 }, children: hint }),
30562
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 6 }, children: [
30563
+ /* @__PURE__ */ jsx2("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => setOpen(false), children: "Cancel" }),
30564
+ /* @__PURE__ */ jsx2("button", { style: pillBtn, disabled: !text.trim(), onClick: submit, children: "Insert" })
29683
30565
  ] })
29684
30566
  ]
29685
30567
  }
@@ -29687,11 +30569,11 @@ function FootnoteMenu({ api }) {
29687
30569
  ] });
29688
30570
  }
29689
30571
  function CommentMenu({ api }) {
29690
- const [open, setOpen] = useState(false);
29691
- const [text, setText] = useState("");
29692
- const rootRef = useRef(null);
29693
- const inputRef = useRef(null);
29694
- useEffect(() => {
30572
+ const [open, setOpen] = useState2(false);
30573
+ const [text, setText] = useState2("");
30574
+ const rootRef = useRef2(null);
30575
+ const inputRef = useRef2(null);
30576
+ useEffect2(() => {
29695
30577
  if (!open) return;
29696
30578
  inputRef.current?.focus();
29697
30579
  const close = (e) => {
@@ -29706,18 +30588,18 @@ function CommentMenu({ api }) {
29706
30588
  setOpen(false);
29707
30589
  }
29708
30590
  };
29709
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
29710
- /* @__PURE__ */ jsx(
30591
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30592
+ /* @__PURE__ */ jsx2(
29711
30593
  "button",
29712
30594
  {
29713
30595
  title: "Add comment (select text first)",
29714
30596
  style: btnStyle(open),
29715
30597
  onMouseDown: (e) => e.preventDefault(),
29716
30598
  onClick: () => setOpen(!open),
29717
- children: /* @__PURE__ */ jsx(CommentIcon, {})
30599
+ children: /* @__PURE__ */ jsx2(CommentIcon, {})
29718
30600
  }
29719
30601
  ),
29720
- open && /* @__PURE__ */ jsxs(
30602
+ open && /* @__PURE__ */ jsxs2(
29721
30603
  "div",
29722
30604
  {
29723
30605
  style: {
@@ -29733,7 +30615,7 @@ function CommentMenu({ api }) {
29733
30615
  width: 240
29734
30616
  },
29735
30617
  children: [
29736
- /* @__PURE__ */ jsx(
30618
+ /* @__PURE__ */ jsx2(
29737
30619
  "textarea",
29738
30620
  {
29739
30621
  ref: inputRef,
@@ -29759,9 +30641,9 @@ function CommentMenu({ api }) {
29759
30641
  }
29760
30642
  }
29761
30643
  ),
29762
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 6 }, children: [
29763
- /* @__PURE__ */ jsx("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => setOpen(false), children: "Cancel" }),
29764
- /* @__PURE__ */ jsx("button", { style: pillBtn, disabled: !text.trim(), onClick: submit, children: "Comment" })
30644
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 6 }, children: [
30645
+ /* @__PURE__ */ jsx2("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => setOpen(false), children: "Cancel" }),
30646
+ /* @__PURE__ */ jsx2("button", { style: pillBtn, disabled: !text.trim(), onClick: submit, children: "Comment" })
29765
30647
  ] })
29766
30648
  ]
29767
30649
  }
@@ -29778,12 +30660,12 @@ var pillBtn = {
29778
30660
  color: T.accentFg
29779
30661
  };
29780
30662
  function BookmarkMenu({ api }) {
29781
- const [open, setOpen] = useState(false);
29782
- const [name, setName] = useState("");
29783
- const [error, setError] = useState("");
29784
- const rootRef = useRef(null);
29785
- const inputRef = useRef(null);
29786
- useEffect(() => {
30663
+ const [open, setOpen] = useState2(false);
30664
+ const [name, setName] = useState2("");
30665
+ const [error, setError] = useState2("");
30666
+ const rootRef = useRef2(null);
30667
+ const inputRef = useRef2(null);
30668
+ useEffect2(() => {
29787
30669
  if (!open) return;
29788
30670
  inputRef.current?.focus();
29789
30671
  const close = (event) => {
@@ -29806,11 +30688,11 @@ function BookmarkMenu({ api }) {
29806
30688
  setError("");
29807
30689
  setOpen(false);
29808
30690
  };
29809
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
29810
- /* @__PURE__ */ jsx("button", { title: "Insert bookmark", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Bookmark" }),
29811
- open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, left: 0, zIndex: 100, width: 280, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
29812
- /* @__PURE__ */ jsx("div", { style: { font: "600 12px system-ui, sans-serif", marginBottom: 6, color: T.fg }, children: "Bookmark name" }),
29813
- /* @__PURE__ */ jsx(
30691
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30692
+ /* @__PURE__ */ jsx2("button", { title: "Insert bookmark", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Bookmark" }),
30693
+ open && /* @__PURE__ */ jsxs2("div", { style: { position: "absolute", top: 28, left: 0, zIndex: 100, width: 280, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30694
+ /* @__PURE__ */ jsx2("div", { style: { font: "600 12px system-ui, sans-serif", marginBottom: 6, color: T.fg }, children: "Bookmark name" }),
30695
+ /* @__PURE__ */ jsx2(
29814
30696
  "input",
29815
30697
  {
29816
30698
  ref: inputRef,
@@ -29824,21 +30706,21 @@ function BookmarkMenu({ api }) {
29824
30706
  style: { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "5px 8px", font: "13px system-ui, sans-serif", outline: "none" }
29825
30707
  }
29826
30708
  ),
29827
- error && /* @__PURE__ */ jsx("div", { style: { color: "#c5221f", fontSize: 11.5, marginTop: 5 }, children: error }),
29828
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 8 }, children: [
29829
- /* @__PURE__ */ jsx("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => setOpen(false), children: "Cancel" }),
29830
- /* @__PURE__ */ jsx("button", { style: pillBtn, disabled: !name.trim(), onClick: submit, children: "Add" })
30709
+ error && /* @__PURE__ */ jsx2("div", { style: { color: "#c5221f", fontSize: 11.5, marginTop: 5 }, children: error }),
30710
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 8 }, children: [
30711
+ /* @__PURE__ */ jsx2("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => setOpen(false), children: "Cancel" }),
30712
+ /* @__PURE__ */ jsx2("button", { style: pillBtn, disabled: !name.trim(), onClick: submit, children: "Add" })
29831
30713
  ] })
29832
30714
  ] })
29833
30715
  ] });
29834
30716
  }
29835
30717
  function CrossReferenceMenu({ api }) {
29836
- const [open, setOpen] = useState(false);
29837
- const [bookmark, setBookmark] = useState("");
29838
- const rootRef = useRef(null);
30718
+ const [open, setOpen] = useState2(false);
30719
+ const [bookmark, setBookmark] = useState2("");
30720
+ const rootRef = useRef2(null);
29839
30721
  const bookmarks = open ? api?.listBookmarks() ?? [] : [];
29840
30722
  const selected = bookmarks.includes(bookmark) ? bookmark : bookmarks[0] ?? "";
29841
- useEffect(() => {
30723
+ useEffect2(() => {
29842
30724
  if (!open) return;
29843
30725
  const close = (event) => {
29844
30726
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -29849,10 +30731,10 @@ function CrossReferenceMenu({ api }) {
29849
30731
  const insert = (kind) => {
29850
30732
  if (selected && api?.insertCrossReference(selected, kind)) setOpen(false);
29851
30733
  };
29852
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
29853
- /* @__PURE__ */ jsx("button", { title: "Insert cross-reference", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Cross-reference" }),
29854
- open && /* @__PURE__ */ jsx("div", { style: { position: "absolute", top: 28, left: 0, zIndex: 100, width: 260, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: bookmarks.length === 0 ? /* @__PURE__ */ jsx("div", { style: { color: T.muted, fontSize: 12 }, children: "Add a bookmark first, then reference its text or page." }) : /* @__PURE__ */ jsxs(Fragment2, { children: [
29855
- /* @__PURE__ */ jsx(
30734
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30735
+ /* @__PURE__ */ jsx2("button", { title: "Insert cross-reference", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Cross-reference" }),
30736
+ open && /* @__PURE__ */ jsx2("div", { style: { position: "absolute", top: 28, left: 0, zIndex: 100, width: 260, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: bookmarks.length === 0 ? /* @__PURE__ */ jsx2("div", { style: { color: T.muted, fontSize: 12 }, children: "Add a bookmark first, then reference its text or page." }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
30737
+ /* @__PURE__ */ jsx2(
29856
30738
  ToolbarMenuSelect,
29857
30739
  {
29858
30740
  value: selected,
@@ -29864,20 +30746,20 @@ function CrossReferenceMenu({ api }) {
29864
30746
  style: { borderColor: T.border }
29865
30747
  }
29866
30748
  ),
29867
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 8 }, children: [
29868
- /* @__PURE__ */ jsx("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => insert("page"), children: "Page number" }),
29869
- /* @__PURE__ */ jsx("button", { style: pillBtn, onClick: () => insert("text"), children: "Bookmark text" })
30749
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 8 }, children: [
30750
+ /* @__PURE__ */ jsx2("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => insert("page"), children: "Page number" }),
30751
+ /* @__PURE__ */ jsx2("button", { style: pillBtn, onClick: () => insert("text"), children: "Bookmark text" })
29870
30752
  ] })
29871
30753
  ] }) })
29872
30754
  ] });
29873
30755
  }
29874
30756
  function EquationMenu({ api }) {
29875
- const [open, setOpen] = useState(false);
29876
- const [linear, setLinear] = useState("x={-b\xB1\u221A{b^2-4ac}}/{2a}");
29877
- const [error, setError] = useState("");
29878
- const rootRef = useRef(null);
29879
- const inputRef = useRef(null);
29880
- useEffect(() => {
30757
+ const [open, setOpen] = useState2(false);
30758
+ const [linear, setLinear] = useState2("x={-b\xB1\u221A{b^2-4ac}}/{2a}");
30759
+ const [error, setError] = useState2("");
30760
+ const rootRef = useRef2(null);
30761
+ const inputRef = useRef2(null);
30762
+ useEffect2(() => {
29881
30763
  if (!open) return;
29882
30764
  inputRef.current?.focus();
29883
30765
  const close = (event) => {
@@ -29894,14 +30776,14 @@ function EquationMenu({ api }) {
29894
30776
  setError("Place the caret in editable text and enter a valid equation.");
29895
30777
  }
29896
30778
  };
29897
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
29898
- /* @__PURE__ */ jsxs("button", { title: "Insert equation", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: [
29899
- /* @__PURE__ */ jsx("span", { style: { fontFamily: "'Cambria Math', serif", fontSize: 18 }, children: "\u03C0" }),
29900
- /* @__PURE__ */ jsx("span", { style: { marginLeft: 5 }, children: "Equation" })
30779
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30780
+ /* @__PURE__ */ jsxs2("button", { title: "Insert equation", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: [
30781
+ /* @__PURE__ */ jsx2("span", { style: { fontFamily: "'Cambria Math', serif", fontSize: 18 }, children: "\u03C0" }),
30782
+ /* @__PURE__ */ jsx2("span", { style: { marginLeft: 5 }, children: "Equation" })
29901
30783
  ] }),
29902
- open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 340, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
29903
- /* @__PURE__ */ jsx("div", { style: { font: "600 12px system-ui, sans-serif", marginBottom: 5, color: T.fg }, children: "Linear equation" }),
29904
- /* @__PURE__ */ jsx(
30784
+ open && /* @__PURE__ */ jsxs2("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 340, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30785
+ /* @__PURE__ */ jsx2("div", { style: { font: "600 12px system-ui, sans-serif", marginBottom: 5, color: T.fg }, children: "Linear equation" }),
30786
+ /* @__PURE__ */ jsx2(
29905
30787
  "input",
29906
30788
  {
29907
30789
  ref: inputRef,
@@ -29915,18 +30797,18 @@ function EquationMenu({ api }) {
29915
30797
  style: { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 8px", font: "15px 'Cambria Math', serif", outline: "none" }
29916
30798
  }
29917
30799
  ),
29918
- /* @__PURE__ */ jsx("div", { style: { color: T.muted, fontSize: 11.5, marginTop: 5 }, children: "Use ^, _, /, \u221A{\u2026}, \u222B, matrices [a&b;c&d], and grouped {\u2026} expressions." }),
29919
- error && /* @__PURE__ */ jsx("div", { style: { color: "#c5221f", fontSize: 11.5, marginTop: 5 }, children: error }),
29920
- /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 8 }, children: /* @__PURE__ */ jsx("button", { style: pillBtn, disabled: !linear.trim(), onClick: submit, children: "Insert" }) })
30800
+ /* @__PURE__ */ jsx2("div", { style: { color: T.muted, fontSize: 11.5, marginTop: 5 }, children: "Use ^, _, /, \u221A{\u2026}, \u222B, matrices [a&b;c&d], and grouped {\u2026} expressions." }),
30801
+ error && /* @__PURE__ */ jsx2("div", { style: { color: "#c5221f", fontSize: 11.5, marginTop: 5 }, children: error }),
30802
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 8 }, children: /* @__PURE__ */ jsx2("button", { style: pillBtn, disabled: !linear.trim(), onClick: submit, children: "Insert" }) })
29921
30803
  ] })
29922
30804
  ] });
29923
30805
  }
29924
30806
  var SYMBOLS = ["\u03A9", "\xB1", "\xD7", "\xF7", "\u2264", "\u2265", "\u2260", "\u2248", "\u221E", "\u2211", "\u221A", "\u222B", "\u2192", "\u2194", "\xA9", "\xAE", "\u2122", "\u20AC", "\xA3", "\xA5", "\u2713", "\u2022", "\xA7", "\xB6"];
29925
30807
  function SymbolMenu({ api }) {
29926
- const [open, setOpen] = useState(false);
29927
- const [custom, setCustom] = useState("");
29928
- const rootRef = useRef(null);
29929
- useEffect(() => {
30808
+ const [open, setOpen] = useState2(false);
30809
+ const [custom, setCustom] = useState2("");
30810
+ const rootRef = useRef2(null);
30811
+ useEffect2(() => {
29930
30812
  if (!open) return;
29931
30813
  const close = (event) => {
29932
30814
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -29942,19 +30824,19 @@ function SymbolMenu({ api }) {
29942
30824
  setOpen(false);
29943
30825
  }
29944
30826
  };
29945
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
29946
- /* @__PURE__ */ jsx("button", { title: "Insert advanced symbol", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsxs("span", { style: { fontFamily: "serif", fontSize: 14 }, children: [
30827
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30828
+ /* @__PURE__ */ jsx2("button", { title: "Insert advanced symbol", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsxs2("span", { style: { fontFamily: "serif", fontSize: 14 }, children: [
29947
30829
  "\u03A9 ",
29948
- /* @__PURE__ */ jsx("span", { style: { fontFamily: "system-ui, sans-serif", fontSize: 12 }, children: "Advanced Symbol" })
30830
+ /* @__PURE__ */ jsx2("span", { style: { fontFamily: "system-ui, sans-serif", fontSize: 12 }, children: "Advanced Symbol" })
29949
30831
  ] }) }),
29950
- open && /* @__PURE__ */ jsxs("div", { style: { position: "fixed", top: anchor?.bottom ?? 28, left: popoverLeft, zIndex: 100, width: 264, padding: 8, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
29951
- /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(6, 32px)", gap: 5 }, children: SYMBOLS.map((symbol) => /* @__PURE__ */ jsx("button", { title: `Insert ${symbol}`, onMouseDown: (event) => event.preventDefault(), onClick: () => {
30832
+ open && /* @__PURE__ */ jsxs2("div", { style: { position: "fixed", top: anchor?.bottom ?? 28, left: popoverLeft, zIndex: 100, width: 264, padding: 8, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30833
+ /* @__PURE__ */ jsx2("div", { style: { display: "grid", gridTemplateColumns: "repeat(6, 32px)", gap: 5 }, children: SYMBOLS.map((symbol) => /* @__PURE__ */ jsx2("button", { title: `Insert ${symbol}`, onMouseDown: (event) => event.preventDefault(), onClick: () => {
29952
30834
  if (api?.insertSymbol(symbol)) setOpen(false);
29953
30835
  }, style: { width: 32, height: 30, border: `1px solid ${T.border}`, borderRadius: 5, background: T.popoverBg, color: T.fg, cursor: "pointer", font: "17px 'Cambria Math', serif" }, children: symbol }, symbol)) }),
29954
- /* @__PURE__ */ jsxs("div", { style: { borderTop: `1px solid ${T.border}`, marginTop: 8, paddingTop: 8 }, children: [
29955
- /* @__PURE__ */ jsx("label", { style: { display: "block", color: T.muted, font: "11.5px system-ui, sans-serif", marginBottom: 4 }, htmlFor: "dxw-advanced-symbol", children: "Any Unicode symbol" }),
29956
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 6 }, children: [
29957
- /* @__PURE__ */ jsx(
30836
+ /* @__PURE__ */ jsxs2("div", { style: { borderTop: `1px solid ${T.border}`, marginTop: 8, paddingTop: 8 }, children: [
30837
+ /* @__PURE__ */ jsx2("label", { style: { display: "block", color: T.muted, font: "11.5px system-ui, sans-serif", marginBottom: 4 }, htmlFor: "dxw-advanced-symbol", children: "Any Unicode symbol" }),
30838
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: 6 }, children: [
30839
+ /* @__PURE__ */ jsx2(
29958
30840
  "input",
29959
30841
  {
29960
30842
  id: "dxw-advanced-symbol",
@@ -29966,7 +30848,7 @@ function SymbolMenu({ api }) {
29966
30848
  style: { minWidth: 0, flex: 1, border: `1px solid ${T.border}`, borderRadius: 5, padding: "5px 7px", background: T.popoverBg, color: T.fg, font: "15px 'Cambria Math', serif" }
29967
30849
  }
29968
30850
  ),
29969
- /* @__PURE__ */ jsx("button", { type: "button", disabled: !custom, onClick: insertCustom, style: pillBtn, children: "Insert" })
30851
+ /* @__PURE__ */ jsx2("button", { type: "button", disabled: !custom, onClick: insertCustom, style: pillBtn, children: "Insert" })
29970
30852
  ] })
29971
30853
  ] })
29972
30854
  ] })
@@ -29981,10 +30863,10 @@ var SHAPES = [
29981
30863
  ["textBox", "Text box", "T"]
29982
30864
  ];
29983
30865
  function ShapeMenu({ api }) {
29984
- const [open, setOpen] = useState(false);
29985
- const [text, setText] = useState("");
29986
- const rootRef = useRef(null);
29987
- useEffect(() => {
30866
+ const [open, setOpen] = useState2(false);
30867
+ const [text, setText] = useState2("");
30868
+ const rootRef = useRef2(null);
30869
+ useEffect2(() => {
29988
30870
  if (!open) return;
29989
30871
  const close = (event) => {
29990
30872
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -29998,10 +30880,10 @@ function ShapeMenu({ api }) {
29998
30880
  setOpen(false);
29999
30881
  }
30000
30882
  };
30001
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30002
- /* @__PURE__ */ jsx("button", { title: "Insert shape", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsx("span", { style: { fontSize: 17 }, children: "\u25C7" }) }),
30003
- open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 250, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30004
- /* @__PURE__ */ jsx(
30883
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30884
+ /* @__PURE__ */ jsx2("button", { title: "Insert shape", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsx2("span", { style: { fontSize: 17 }, children: "\u25C7" }) }),
30885
+ open && /* @__PURE__ */ jsxs2("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 250, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30886
+ /* @__PURE__ */ jsx2(
30005
30887
  "input",
30006
30888
  {
30007
30889
  "aria-label": "Shape text",
@@ -30011,18 +30893,18 @@ function ShapeMenu({ api }) {
30011
30893
  style: { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "5px 8px", font: "13px system-ui, sans-serif", outline: "none" }
30012
30894
  }
30013
30895
  ),
30014
- /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 6, marginTop: 8 }, children: SHAPES.map(([preset, label, glyph]) => /* @__PURE__ */ jsxs("button", { title: `Insert ${label}`, onClick: () => insert(preset), style: { minHeight: 48, border: `1px solid ${T.border}`, borderRadius: 6, background: T.popoverBg, color: T.fg, cursor: "pointer", font: "12px system-ui, sans-serif" }, children: [
30015
- /* @__PURE__ */ jsx("span", { style: { display: "block", fontSize: 20, lineHeight: 1 }, children: glyph }),
30016
- /* @__PURE__ */ jsx("span", { children: label })
30896
+ /* @__PURE__ */ jsx2("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 6, marginTop: 8 }, children: SHAPES.map(([preset, label, glyph]) => /* @__PURE__ */ jsxs2("button", { title: `Insert ${label}`, onClick: () => insert(preset), style: { minHeight: 48, border: `1px solid ${T.border}`, borderRadius: 6, background: T.popoverBg, color: T.fg, cursor: "pointer", font: "12px system-ui, sans-serif" }, children: [
30897
+ /* @__PURE__ */ jsx2("span", { style: { display: "block", fontSize: 20, lineHeight: 1 }, children: glyph }),
30898
+ /* @__PURE__ */ jsx2("span", { children: label })
30017
30899
  ] }, preset)) })
30018
30900
  ] })
30019
30901
  ] });
30020
30902
  }
30021
30903
  function TextBoxMenu({ api }) {
30022
- const [open, setOpen] = useState(false);
30023
- const [text, setText] = useState("");
30024
- const rootRef = useRef(null);
30025
- useEffect(() => {
30904
+ const [open, setOpen] = useState2(false);
30905
+ const [text, setText] = useState2("");
30906
+ const rootRef = useRef2(null);
30907
+ useEffect2(() => {
30026
30908
  if (!open) return;
30027
30909
  const close = (event) => {
30028
30910
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30036,11 +30918,11 @@ function TextBoxMenu({ api }) {
30036
30918
  setOpen(false);
30037
30919
  }
30038
30920
  };
30039
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30040
- /* @__PURE__ */ jsx("button", { title: "Insert text box", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Text Box" }),
30041
- open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 240, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30042
- /* @__PURE__ */ jsx("label", { htmlFor: "dxw-text-box-text", style: { display: "block", color: T.muted, font: "11.5px system-ui, sans-serif", marginBottom: 4 }, children: "Initial text" }),
30043
- /* @__PURE__ */ jsx(
30921
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30922
+ /* @__PURE__ */ jsx2("button", { title: "Insert text box", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Text Box" }),
30923
+ open && /* @__PURE__ */ jsxs2("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 240, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30924
+ /* @__PURE__ */ jsx2("label", { htmlFor: "dxw-text-box-text", style: { display: "block", color: T.muted, font: "11.5px system-ui, sans-serif", marginBottom: 4 }, children: "Initial text" }),
30925
+ /* @__PURE__ */ jsx2(
30044
30926
  "input",
30045
30927
  {
30046
30928
  id: "dxw-text-box-text",
@@ -30052,7 +30934,7 @@ function TextBoxMenu({ api }) {
30052
30934
  style: { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "5px 8px", font: "13px system-ui, sans-serif", outline: "none" }
30053
30935
  }
30054
30936
  ),
30055
- /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 8 }, children: /* @__PURE__ */ jsx("button", { type: "button", onClick: insert, style: pillBtn, children: "Insert" }) })
30937
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 8 }, children: /* @__PURE__ */ jsx2("button", { type: "button", onClick: insert, style: pillBtn, children: "Insert" }) })
30056
30938
  ] })
30057
30939
  ] });
30058
30940
  }
@@ -30064,10 +30946,10 @@ var WORD_ART = [
30064
30946
  ["chevron", "Chevron", "\u2303"]
30065
30947
  ];
30066
30948
  function WordArtMenu({ api }) {
30067
- const [open, setOpen] = useState(false);
30068
- const [text, setText] = useState("Your text here");
30069
- const rootRef = useRef(null);
30070
- useEffect(() => {
30949
+ const [open, setOpen] = useState2(false);
30950
+ const [text, setText] = useState2("Your text here");
30951
+ const rootRef = useRef2(null);
30952
+ useEffect2(() => {
30071
30953
  if (!open) return;
30072
30954
  const close = (event) => {
30073
30955
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30075,10 +30957,10 @@ function WordArtMenu({ api }) {
30075
30957
  document.addEventListener("mousedown", close);
30076
30958
  return () => document.removeEventListener("mousedown", close);
30077
30959
  }, [open]);
30078
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30079
- /* @__PURE__ */ jsx("button", { title: "Insert WordArt", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsx("span", { style: { color: "#2e74b5", fontSize: 17, fontStyle: "italic", fontWeight: 700 }, children: "A" }) }),
30080
- open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 270, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30081
- /* @__PURE__ */ jsx(
30960
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30961
+ /* @__PURE__ */ jsx2("button", { title: "Insert WordArt", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsx2("span", { style: { color: "#2e74b5", fontSize: 17, fontStyle: "italic", fontWeight: 700 }, children: "A" }) }),
30962
+ open && /* @__PURE__ */ jsxs2("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 270, padding: 10, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30963
+ /* @__PURE__ */ jsx2(
30082
30964
  "input",
30083
30965
  {
30084
30966
  "aria-label": "WordArt text",
@@ -30087,7 +30969,7 @@ function WordArtMenu({ api }) {
30087
30969
  style: { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "5px 8px", font: "13px system-ui, sans-serif", outline: "none" }
30088
30970
  }
30089
30971
  ),
30090
- /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 6, marginTop: 8 }, children: WORD_ART.map(([preset, label, glyph]) => /* @__PURE__ */ jsxs(
30972
+ /* @__PURE__ */ jsx2("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 6, marginTop: 8 }, children: WORD_ART.map(([preset, label, glyph]) => /* @__PURE__ */ jsxs2(
30091
30973
  "button",
30092
30974
  {
30093
30975
  title: `Insert WordArt ${label}`,
@@ -30097,8 +30979,8 @@ function WordArtMenu({ api }) {
30097
30979
  },
30098
30980
  style: { minHeight: 48, border: `1px solid ${T.border}`, borderRadius: 6, background: T.popoverBg, color: "#2e74b5", cursor: text ? "pointer" : "default", font: "600 12px system-ui, sans-serif" },
30099
30981
  children: [
30100
- /* @__PURE__ */ jsx("span", { style: { display: "block", fontSize: 19, lineHeight: 1.2 }, children: glyph }),
30101
- /* @__PURE__ */ jsx("span", { children: label })
30982
+ /* @__PURE__ */ jsx2("span", { style: { display: "block", fontSize: 19, lineHeight: 1.2 }, children: glyph }),
30983
+ /* @__PURE__ */ jsx2("span", { children: label })
30102
30984
  ]
30103
30985
  },
30104
30986
  preset
@@ -30107,14 +30989,14 @@ function WordArtMenu({ api }) {
30107
30989
  ] });
30108
30990
  }
30109
30991
  function ChartMenu({ api }) {
30110
- const [open, setOpen] = useState(false);
30111
- const [type, setType] = useState("column");
30112
- const [title, setTitle] = useState("Quarterly sales");
30113
- const [categories, setCategories] = useState("Q1, Q2, Q3, Q4");
30114
- const [series, setSeries] = useState("Revenue: 12, 19, 15, 24\nCosts: 8, 11, 10, 14");
30115
- const [error, setError] = useState("");
30116
- const rootRef = useRef(null);
30117
- useEffect(() => {
30992
+ const [open, setOpen] = useState2(false);
30993
+ const [type, setType] = useState2("column");
30994
+ const [title, setTitle] = useState2("Quarterly sales");
30995
+ const [categories, setCategories] = useState2("Q1, Q2, Q3, Q4");
30996
+ const [series, setSeries] = useState2("Revenue: 12, 19, 15, 24\nCosts: 8, 11, 10, 14");
30997
+ const [error, setError] = useState2("");
30998
+ const rootRef = useRef2(null);
30999
+ useEffect2(() => {
30118
31000
  if (!open) return;
30119
31001
  const close = (event) => {
30120
31002
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30142,10 +31024,10 @@ function ChartMenu({ api }) {
30142
31024
  }
30143
31025
  };
30144
31026
  const fieldStyle = { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 8px", font: "13px system-ui, sans-serif", color: T.fg, background: T.popoverBg };
30145
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30146
- /* @__PURE__ */ jsx("button", { title: "Insert or edit chart", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Chart" }),
30147
- open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 320, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30148
- /* @__PURE__ */ jsx(
31027
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31028
+ /* @__PURE__ */ jsx2("button", { title: "Insert or edit chart", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Chart" }),
31029
+ open && /* @__PURE__ */ jsxs2("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 320, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
31030
+ /* @__PURE__ */ jsx2(
30149
31031
  ToolbarMenuSelect,
30150
31032
  {
30151
31033
  value: type,
@@ -30162,21 +31044,21 @@ function ChartMenu({ api }) {
30162
31044
  style: fieldStyle
30163
31045
  }
30164
31046
  ),
30165
- /* @__PURE__ */ jsx("input", { "aria-label": "Chart title", value: title, onChange: (event) => setTitle(event.target.value), placeholder: "Chart title", style: fieldStyle }),
30166
- /* @__PURE__ */ jsx("input", { "aria-label": "Chart categories", value: categories, onChange: (event) => setCategories(event.target.value), placeholder: "Q1, Q2, Q3, Q4", style: fieldStyle }),
30167
- /* @__PURE__ */ jsx("textarea", { "aria-label": "Chart series", rows: 3, value: series, onChange: (event) => setSeries(event.target.value), style: { ...fieldStyle, resize: "vertical" } }),
30168
- /* @__PURE__ */ jsx("div", { style: { color: T.muted, font: "11.5px system-ui, sans-serif" }, children: "Each series: Name: value, value, value" }),
30169
- error && /* @__PURE__ */ jsx("div", { role: "alert", style: { color: "#c5221f", font: "11.5px system-ui, sans-serif" }, children: error }),
30170
- /* @__PURE__ */ jsx("button", { onClick: submit, style: { border: 0, borderRadius: 6, padding: "7px 10px", background: T.accent, color: T.accentFg, cursor: "pointer", font: "600 12px system-ui, sans-serif" }, children: "Insert or update chart" })
31047
+ /* @__PURE__ */ jsx2("input", { "aria-label": "Chart title", value: title, onChange: (event) => setTitle(event.target.value), placeholder: "Chart title", style: fieldStyle }),
31048
+ /* @__PURE__ */ jsx2("input", { "aria-label": "Chart categories", value: categories, onChange: (event) => setCategories(event.target.value), placeholder: "Q1, Q2, Q3, Q4", style: fieldStyle }),
31049
+ /* @__PURE__ */ jsx2("textarea", { "aria-label": "Chart series", rows: 3, value: series, onChange: (event) => setSeries(event.target.value), style: { ...fieldStyle, resize: "vertical" } }),
31050
+ /* @__PURE__ */ jsx2("div", { style: { color: T.muted, font: "11.5px system-ui, sans-serif" }, children: "Each series: Name: value, value, value" }),
31051
+ error && /* @__PURE__ */ jsx2("div", { role: "alert", style: { color: "#c5221f", font: "11.5px system-ui, sans-serif" }, children: error }),
31052
+ /* @__PURE__ */ jsx2("button", { onClick: submit, style: { border: 0, borderRadius: 6, padding: "7px 10px", background: T.accent, color: T.accentFg, cursor: "pointer", font: "600 12px system-ui, sans-serif" }, children: "Insert or update chart" })
30171
31053
  ] })
30172
31054
  ] });
30173
31055
  }
30174
31056
  function SmartArtMenu({ api }) {
30175
- const [open, setOpen] = useState(false);
30176
- const [layout, setLayout] = useState("process");
30177
- const [items, setItems] = useState("Discover\nDesign\nDeliver");
30178
- const rootRef = useRef(null);
30179
- useEffect(() => {
31057
+ const [open, setOpen] = useState2(false);
31058
+ const [layout, setLayout] = useState2("process");
31059
+ const [items, setItems] = useState2("Discover\nDesign\nDeliver");
31060
+ const rootRef = useRef2(null);
31061
+ useEffect2(() => {
30180
31062
  if (!open) return;
30181
31063
  const close = (event) => {
30182
31064
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30191,10 +31073,10 @@ function SmartArtMenu({ api }) {
30191
31073
  if (api?.updateSelectedSmartArt(data) || api?.insertSmartArt(data)) setOpen(false);
30192
31074
  };
30193
31075
  const fieldStyle = { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 8px", font: "13px system-ui, sans-serif", color: T.fg, background: T.popoverBg };
30194
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30195
- /* @__PURE__ */ jsx("button", { title: "Insert or edit SmartArt", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "SmartArt" }),
30196
- open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 280, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30197
- /* @__PURE__ */ jsx(
31076
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31077
+ /* @__PURE__ */ jsx2("button", { title: "Insert or edit SmartArt", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "SmartArt" }),
31078
+ open && /* @__PURE__ */ jsxs2("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 280, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
31079
+ /* @__PURE__ */ jsx2(
30198
31080
  ToolbarMenuSelect,
30199
31081
  {
30200
31082
  value: layout,
@@ -30211,17 +31093,17 @@ function SmartArtMenu({ api }) {
30211
31093
  style: fieldStyle
30212
31094
  }
30213
31095
  ),
30214
- /* @__PURE__ */ jsx("textarea", { "aria-label": "SmartArt items", rows: 5, value: items, onChange: (event) => setItems(event.target.value), style: { ...fieldStyle, resize: "vertical" } }),
30215
- /* @__PURE__ */ jsx("div", { style: { color: T.muted, font: "11.5px system-ui, sans-serif" }, children: "One diagram item per line." }),
30216
- /* @__PURE__ */ jsx("button", { disabled: !items.trim(), onClick: submit, style: { border: 0, borderRadius: 6, padding: "7px 10px", background: items.trim() ? T.accent : T.border, color: T.accentFg, cursor: items.trim() ? "pointer" : "default", font: "600 12px system-ui, sans-serif" }, children: "Insert or update SmartArt" })
31096
+ /* @__PURE__ */ jsx2("textarea", { "aria-label": "SmartArt items", rows: 5, value: items, onChange: (event) => setItems(event.target.value), style: { ...fieldStyle, resize: "vertical" } }),
31097
+ /* @__PURE__ */ jsx2("div", { style: { color: T.muted, font: "11.5px system-ui, sans-serif" }, children: "One diagram item per line." }),
31098
+ /* @__PURE__ */ jsx2("button", { disabled: !items.trim(), onClick: submit, style: { border: 0, borderRadius: 6, padding: "7px 10px", background: items.trim() ? T.accent : T.border, color: T.accentFg, cursor: items.trim() ? "pointer" : "default", font: "600 12px system-ui, sans-serif" }, children: "Insert or update SmartArt" })
30217
31099
  ] })
30218
31100
  ] });
30219
31101
  }
30220
31102
  function MediaMenu({ api }) {
30221
- const [open, setOpen] = useState(false);
30222
- const [url, setUrl] = useState("");
30223
- const rootRef = useRef(null);
30224
- useEffect(() => {
31103
+ const [open, setOpen] = useState2(false);
31104
+ const [url, setUrl] = useState2("");
31105
+ const rootRef = useRef2(null);
31106
+ useEffect2(() => {
30225
31107
  if (!open) return;
30226
31108
  const close = (event) => {
30227
31109
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30229,11 +31111,11 @@ function MediaMenu({ api }) {
30229
31111
  document.addEventListener("mousedown", close);
30230
31112
  return () => document.removeEventListener("mousedown", close);
30231
31113
  }, [open]);
30232
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30233
- /* @__PURE__ */ jsx("button", { title: "Insert online video", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Media" }),
30234
- open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 300, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30235
- /* @__PURE__ */ jsx("input", { "aria-label": "Online video URL", value: url, onChange: (event) => setUrl(event.target.value), placeholder: "https://www.youtube.com/watch?v=\u2026", style: { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 8px", font: "13px system-ui, sans-serif", color: T.fg, background: T.popoverBg } }),
30236
- /* @__PURE__ */ jsx(
31114
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31115
+ /* @__PURE__ */ jsx2("button", { title: "Insert online video", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Media" }),
31116
+ open && /* @__PURE__ */ jsxs2("div", { style: { position: "absolute", top: 28, right: 0, zIndex: 100, width: 300, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
31117
+ /* @__PURE__ */ jsx2("input", { "aria-label": "Online video URL", value: url, onChange: (event) => setUrl(event.target.value), placeholder: "https://www.youtube.com/watch?v=\u2026", style: { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 8px", font: "13px system-ui, sans-serif", color: T.fg, background: T.popoverBg } }),
31118
+ /* @__PURE__ */ jsx2(
30237
31119
  "button",
30238
31120
  {
30239
31121
  disabled: !url.trim(),
@@ -30246,62 +31128,70 @@ function MediaMenu({ api }) {
30246
31128
  ] });
30247
31129
  }
30248
31130
  function DrawTab({ api }) {
30249
- const [color, setColor] = useState("#202124");
30250
- const [width, setWidth] = useState(2);
31131
+ const [pen, setPen] = useState2({ color: "#202124", width: 2 });
31132
+ const [highlighter, setHighlighter] = useState2({ color: "#F9D949", width: 12 });
30251
31133
  const kindOf = (tool) => tool ? tool.kind === "eraser" ? "eraser" : tool.kind === "lasso" ? "lasso" : tool.kind === "highlighter" ? "highlighter" : "pen" : "select";
30252
- const [active, setActive] = useState(kindOf(api?.getDrawingTool() ?? null));
30253
- useEffect(() => {
30254
- const update = (event) => setActive(kindOf(event.detail));
31134
+ const [active, setActive] = useState2(kindOf(api?.getDrawingTool() ?? null));
31135
+ useEffect2(() => {
31136
+ const update = (event) => {
31137
+ const tool = event.detail;
31138
+ setActive(kindOf(tool));
31139
+ if (tool?.kind === "highlighter") setHighlighter({ color: tool.color, width: tool.width });
31140
+ else if (tool?.kind === "pen") setPen({ color: tool.color, width: tool.width });
31141
+ };
30255
31142
  document.addEventListener("dxw-drawing-tool", update);
30256
31143
  return () => document.removeEventListener("dxw-drawing-tool", update);
30257
31144
  }, []);
30258
- useEffect(() => () => api?.setDrawingTool(null), [api]);
30259
- const activate = (kind, nextColor = color, nextWidth = width) => {
30260
- setColor(nextColor);
30261
- setWidth(nextWidth);
30262
- api?.setDrawingTool({ kind, color: nextColor, width: nextWidth });
31145
+ useEffect2(() => () => api?.setDrawingTool(null), [api]);
31146
+ const activate = (kind, patch) => {
31147
+ const next = { ...kind === "highlighter" ? highlighter : pen, ...patch };
31148
+ if (kind === "highlighter") setHighlighter(next);
31149
+ else setPen(next);
31150
+ api?.setDrawingTool({ kind, color: next.color, width: next.width });
30263
31151
  };
30264
- return /* @__PURE__ */ jsxs(Fragment2, { children: [
30265
- /* @__PURE__ */ jsx(Btn, { label: "Select", title: "Select objects", active: active === "select", onClick: () => api?.setDrawingTool(null) }),
30266
- /* @__PURE__ */ jsx(Btn, { label: "Pen", title: "Draw with pen", active: active === "pen", onClick: () => activate("pen") }),
30267
- /* @__PURE__ */ jsx(Btn, { label: "Highlighter", title: "Draw with highlighter", active: active === "highlighter", onClick: () => activate("highlighter", "#F9D949", 12) }),
30268
- /* @__PURE__ */ jsx(Btn, { label: "Eraser", title: "Stroke eraser", active: active === "eraser", onClick: () => api?.setDrawingTool({ kind: "eraser", size: 14 }) }),
30269
- /* @__PURE__ */ jsx(Btn, { label: "Lasso", title: "Lasso ink", active: active === "lasso", onClick: () => api?.setDrawingTool({ kind: "lasso" }) }),
30270
- /* @__PURE__ */ jsx(Sep, {}),
30271
- /* @__PURE__ */ jsx(
31152
+ const inkKind = active === "highlighter" ? "highlighter" : "pen";
31153
+ const ink = inkKind === "highlighter" ? highlighter : pen;
31154
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
31155
+ /* @__PURE__ */ jsx2(Btn, { label: "Select", title: "Select objects", active: active === "select", onClick: () => api?.setDrawingTool(null) }),
31156
+ /* @__PURE__ */ jsx2(Btn, { label: "Pen", title: "Draw with pen", active: active === "pen", onClick: () => activate("pen") }),
31157
+ /* @__PURE__ */ jsx2(Btn, { label: "Highlighter", title: "Draw with highlighter", active: active === "highlighter", onClick: () => activate("highlighter") }),
31158
+ /* @__PURE__ */ jsx2(Btn, { label: "Eraser", title: "Stroke eraser", active: active === "eraser", onClick: () => api?.setDrawingTool({ kind: "eraser", size: 14 }) }),
31159
+ /* @__PURE__ */ jsx2(Btn, { label: "Lasso", title: "Lasso ink", active: active === "lasso", onClick: () => api?.setDrawingTool({ kind: "lasso" }) }),
31160
+ /* @__PURE__ */ jsx2(Sep, {}),
31161
+ /* @__PURE__ */ jsx2(
30272
31162
  ColorMenu,
30273
31163
  {
30274
- current: color,
30275
- title: "Pen color",
30276
- trigger: /* @__PURE__ */ jsxs(Fragment2, { children: [
30277
- /* @__PURE__ */ jsx("span", { style: { font: "12px system-ui, sans-serif" }, children: "Color" }),
30278
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { width: 18, height: 18, borderRadius: 4, border: `1px solid ${T.border}`, background: color } })
31164
+ current: ink.color,
31165
+ title: inkKind === "highlighter" ? "Highlighter color" : "Pen color",
31166
+ trigger: /* @__PURE__ */ jsxs2(Fragment2, { children: [
31167
+ /* @__PURE__ */ jsx2("span", { style: { font: "12px system-ui, sans-serif" }, children: "Color" }),
31168
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", style: { width: 18, height: 18, borderRadius: 4, border: `1px solid ${T.border}`, background: ink.color } })
30279
31169
  ] }),
30280
- onPick: (value) => activate(active === "highlighter" ? "highlighter" : "pen", value, width)
31170
+ onPick: (value) => activate(inkKind, { color: value })
30281
31171
  }
30282
31172
  ),
30283
- /* @__PURE__ */ jsx(
31173
+ /* @__PURE__ */ jsx2(
30284
31174
  ActionMenu,
30285
31175
  {
30286
- label: `${width} px`,
30287
- title: "Pen width",
31176
+ label: `${ink.width} px`,
31177
+ title: inkKind === "highlighter" ? "Highlighter width" : "Pen width",
30288
31178
  width: 70,
30289
31179
  groups: [{ items: [["1", "1 px"], ["2", "2 px"], ["4", "4 px"], ["8", "8 px"], ["12", "12 px"]] }],
30290
- onPick: (value) => activate(active === "highlighter" ? "highlighter" : "pen", color, Number(value))
31180
+ onPick: (value) => activate(inkKind, { width: Number(value) })
30291
31181
  }
30292
31182
  )
30293
31183
  ] });
30294
31184
  }
30295
31185
  function ScreenshotButton({ api }) {
30296
- const [status, setStatus] = useState("");
31186
+ const [status, setStatus] = useState2("");
30297
31187
  const capture = async () => {
30298
31188
  setStatus("Capturing screenshot\u2026");
30299
31189
  const result = await api?.insertScreenshot();
30300
31190
  setStatus(result === "inserted" ? "Screenshot inserted." : result === "unsupported" ? "Screen capture is not supported in this browser." : result === "cancelled" ? "Screen capture was cancelled or denied." : result === "no-caret" ? "Click in the document before inserting a screenshot." : "Screenshot failed. Please try again.");
30301
31191
  };
30302
- return /* @__PURE__ */ jsxs("span", { style: { position: "relative", display: "inline-flex" }, children: [
30303
- /* @__PURE__ */ jsx(Btn, { label: "Screenshot", title: "Capture and insert a screen, window, or tab", onClick: () => void capture() }),
30304
- status && /* @__PURE__ */ jsx(
31192
+ return /* @__PURE__ */ jsxs2("span", { style: { position: "relative", display: "inline-flex" }, children: [
31193
+ /* @__PURE__ */ jsx2(Btn, { label: "Screenshot", title: "Capture and insert a screen, window, or tab", onClick: () => void capture() }),
31194
+ status && /* @__PURE__ */ jsx2(
30305
31195
  "span",
30306
31196
  {
30307
31197
  role: status === "Screenshot inserted." ? "status" : "alert",
@@ -30313,12 +31203,12 @@ function ScreenshotButton({ api }) {
30313
31203
  ] });
30314
31204
  }
30315
31205
  function CoverPageMenu({ api }) {
30316
- const [open, setOpen] = useState(false);
30317
- const [title, setTitle] = useState("");
30318
- const [subtitle, setSubtitle] = useState("");
30319
- const [author, setAuthor] = useState("");
30320
- const rootRef = useRef(null);
30321
- useEffect(() => {
31206
+ const [open, setOpen] = useState2(false);
31207
+ const [title, setTitle] = useState2("");
31208
+ const [subtitle, setSubtitle] = useState2("");
31209
+ const [author, setAuthor] = useState2("");
31210
+ const rootRef = useRef2(null);
31211
+ useEffect2(() => {
30322
31212
  if (!open) return;
30323
31213
  const close = (event) => {
30324
31214
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30333,7 +31223,7 @@ function CoverPageMenu({ api }) {
30333
31223
  setSubtitle("");
30334
31224
  setAuthor("");
30335
31225
  };
30336
- const input = (label, value, set) => /* @__PURE__ */ jsx(
31226
+ const input = (label, value, set) => /* @__PURE__ */ jsx2(
30337
31227
  "input",
30338
31228
  {
30339
31229
  "aria-label": label,
@@ -30343,21 +31233,21 @@ function CoverPageMenu({ api }) {
30343
31233
  style: { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 8px", font: "13px system-ui, sans-serif" }
30344
31234
  }
30345
31235
  );
30346
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30347
- /* @__PURE__ */ jsx("button", { title: "Insert cover page", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Cover page" }),
30348
- open && /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: 30, left: 0, zIndex: 100, width: 260, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
31236
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31237
+ /* @__PURE__ */ jsx2("button", { title: "Insert cover page", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Cover page" }),
31238
+ open && /* @__PURE__ */ jsxs2("div", { style: { position: "absolute", top: 30, left: 0, zIndex: 100, width: 260, padding: 10, display: "grid", gap: 7, background: T.popoverBg, border: `1px solid ${T.border}`, borderRadius: 8, boxShadow: T.popoverShadow }, children: [
30349
31239
  input("Cover title", title, setTitle),
30350
31240
  input("Cover subtitle", subtitle, setSubtitle),
30351
31241
  input("Cover author", author, setAuthor),
30352
- /* @__PURE__ */ jsx("button", { disabled: !title.trim(), onClick: insert, style: { border: 0, borderRadius: 6, padding: "7px 10px", background: title.trim() ? T.accent : T.border, color: T.accentFg, cursor: title.trim() ? "pointer" : "default", font: "600 12px system-ui, sans-serif" }, children: "Insert cover" })
31242
+ /* @__PURE__ */ jsx2("button", { disabled: !title.trim(), onClick: insert, style: { border: 0, borderRadius: 6, padding: "7px 10px", background: title.trim() ? T.accent : T.border, color: T.accentFg, cursor: title.trim() ? "pointer" : "default", font: "600 12px system-ui, sans-serif" }, children: "Insert cover" })
30353
31243
  ] })
30354
31244
  ] });
30355
31245
  }
30356
31246
  function TableMenu({ api }) {
30357
- const [open, setOpen] = useState(false);
30358
- const [hover, setHover] = useState({ r: 0, c: 0 });
30359
- const rootRef = useRef(null);
30360
- useEffect(() => {
31247
+ const [open, setOpen] = useState2(false);
31248
+ const [hover, setHover] = useState2({ r: 0, c: 0 });
31249
+ const rootRef = useRef2(null);
31250
+ useEffect2(() => {
30361
31251
  if (!open) return;
30362
31252
  const close = (e) => {
30363
31253
  if (!rootRef.current?.contains(e.target)) setOpen(false);
@@ -30382,8 +31272,8 @@ function TableMenu({ api }) {
30382
31272
  ["deleteTable", "Delete table"]
30383
31273
  ];
30384
31274
  const CELL_FILLS = ["FFF2CC", "D9E2F3", "E2EFDA", "FCE4EC", "F1F3F4"];
30385
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30386
- /* @__PURE__ */ jsx(
31275
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31276
+ /* @__PURE__ */ jsx2(
30387
31277
  "button",
30388
31278
  {
30389
31279
  title: "Table",
@@ -30393,7 +31283,7 @@ function TableMenu({ api }) {
30393
31283
  children: "Table \u25BE"
30394
31284
  }
30395
31285
  ),
30396
- open && /* @__PURE__ */ jsxs(
31286
+ open && /* @__PURE__ */ jsxs2(
30397
31287
  "div",
30398
31288
  {
30399
31289
  style: {
@@ -30410,12 +31300,12 @@ function TableMenu({ api }) {
30410
31300
  },
30411
31301
  onMouseDown: (e) => e.preventDefault(),
30412
31302
  children: [
30413
- /* @__PURE__ */ jsx("div", { style: { fontSize: 12, color: T.muted, marginBottom: 4 }, children: hover.r > 0 ? `${hover.r} \xD7 ${hover.c}` : "Insert table" }),
30414
- /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: `repeat(${COLS}, 16px)`, gap: 2 }, children: Array.from({ length: ROWS * COLS }, (_, i) => {
31303
+ /* @__PURE__ */ jsx2("div", { style: { fontSize: 12, color: T.muted, marginBottom: 4 }, children: hover.r > 0 ? `${hover.r} \xD7 ${hover.c}` : "Insert table" }),
31304
+ /* @__PURE__ */ jsx2("div", { style: { display: "grid", gridTemplateColumns: `repeat(${COLS}, 16px)`, gap: 2 }, children: Array.from({ length: ROWS * COLS }, (_, i) => {
30415
31305
  const r = Math.floor(i / COLS) + 1;
30416
31306
  const c = i % COLS + 1;
30417
31307
  const lit = r <= hover.r && c <= hover.c;
30418
- return /* @__PURE__ */ jsx(
31308
+ return /* @__PURE__ */ jsx2(
30419
31309
  "div",
30420
31310
  {
30421
31311
  onMouseEnter: () => setHover({ r, c }),
@@ -30436,8 +31326,8 @@ function TableMenu({ api }) {
30436
31326
  i
30437
31327
  );
30438
31328
  }) }),
30439
- /* @__PURE__ */ jsxs("div", { style: { borderTop: "1px solid #eee", marginTop: 8, paddingTop: 4 }, children: [
30440
- ops.map(([op, label]) => /* @__PURE__ */ jsx(
31329
+ /* @__PURE__ */ jsxs2("div", { style: { borderTop: "1px solid #eee", marginTop: 8, paddingTop: 4 }, children: [
31330
+ ops.map(([op, label]) => /* @__PURE__ */ jsx2(
30441
31331
  "div",
30442
31332
  {
30443
31333
  onClick: () => {
@@ -30455,9 +31345,9 @@ function TableMenu({ api }) {
30455
31345
  },
30456
31346
  op
30457
31347
  )),
30458
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 4, alignItems: "center", padding: "4px 6px" }, children: [
30459
- /* @__PURE__ */ jsx("span", { style: { fontSize: 12, color: T.muted, marginRight: 2 }, children: "Cell fill" }),
30460
- CELL_FILLS.map((f) => /* @__PURE__ */ jsx(
31348
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: 4, alignItems: "center", padding: "4px 6px" }, children: [
31349
+ /* @__PURE__ */ jsx2("span", { style: { fontSize: 12, color: T.muted, marginRight: 2 }, children: "Cell fill" }),
31350
+ CELL_FILLS.map((f) => /* @__PURE__ */ jsx2(
30461
31351
  "div",
30462
31352
  {
30463
31353
  title: `#${f}`,
@@ -30469,7 +31359,7 @@ function TableMenu({ api }) {
30469
31359
  },
30470
31360
  f
30471
31361
  )),
30472
- /* @__PURE__ */ jsx(
31362
+ /* @__PURE__ */ jsx2(
30473
31363
  "div",
30474
31364
  {
30475
31365
  title: "No fill",
@@ -30501,6 +31391,7 @@ function PagePreview({
30501
31391
  margins,
30502
31392
  mirrored,
30503
31393
  columns,
31394
+ columnSeparator,
30504
31395
  border,
30505
31396
  lineNumbers
30506
31397
  }) {
@@ -30513,14 +31404,14 @@ function PagePreview({
30513
31404
  const inset = margins ?? [0.8, 0.8, 0.8, 0.8];
30514
31405
  const borderWidth = border === "thick" ? 2 : border === "none" ? 0 : 1;
30515
31406
  const borderColor = border === "accent" ? T.accent : T.muted;
30516
- return /* @__PURE__ */ jsx(
31407
+ return /* @__PURE__ */ jsx2(
30517
31408
  "span",
30518
31409
  {
30519
31410
  "aria-hidden": "true",
30520
31411
  className: "dxw-layout-preview",
30521
31412
  "data-dxw-layout-preview": kind,
30522
31413
  style: { width: 52, height: 46, display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 3, flex: "0 0 52px" },
30523
- children: Array.from({ length: papers }, (_, paper) => /* @__PURE__ */ jsxs(
31414
+ children: Array.from({ length: papers }, (_, paper) => /* @__PURE__ */ jsxs2(
30524
31415
  "span",
30525
31416
  {
30526
31417
  className: "dxw-layout-preview-page",
@@ -30534,7 +31425,7 @@ function PagePreview({
30534
31425
  border: `${Math.max(1, borderWidth)}px solid ${borderWidth ? borderColor : T.border}`
30535
31426
  },
30536
31427
  children: [
30537
- kind === "margins" && /* @__PURE__ */ jsx("span", { style: {
31428
+ kind === "margins" && /* @__PURE__ */ jsx2("span", { style: {
30538
31429
  position: "absolute",
30539
31430
  top: `${Math.min(35, inset[0] * 18)}%`,
30540
31431
  right: `${Math.min(35, (mirrored && paper === 0 ? inset[3] : inset[1]) * 15)}%`,
@@ -30543,19 +31434,22 @@ function PagePreview({
30543
31434
  border: `1px solid ${T.accent}`,
30544
31435
  boxSizing: "border-box"
30545
31436
  } }),
30546
- !!columns && /* @__PURE__ */ jsx("span", { style: { position: "absolute", inset: "5px 3px", display: "flex", gap: 2 }, children: Array.from({ length: columns }, (_2, column) => /* @__PURE__ */ jsx("span", { style: { flex: 1, background: `repeating-linear-gradient(to bottom, ${T.muted} 0 1px, transparent 1px 4px)` } }, column)) }),
30547
- border === "none" && /* @__PURE__ */ jsx("span", { style: { position: "absolute", inset: 4, border: `1px dashed ${T.border}` } }),
30548
- lineNumbers && /* @__PURE__ */ jsxs("span", { style: { position: "absolute", inset: "4px 3px", display: "grid", gridTemplateColumns: "8px 1fr", gap: 2 }, children: [
30549
- /* @__PURE__ */ jsxs("span", { style: { fontSize: 5, lineHeight: "6px", color: T.accent }, children: [
31437
+ !!columns && /* @__PURE__ */ jsxs2("span", { style: { position: "absolute", inset: "5px 3px", display: "flex", gap: 2 }, children: [
31438
+ Array.from({ length: columns }, (_2, column) => /* @__PURE__ */ jsx2("span", { style: { flex: 1, background: `repeating-linear-gradient(to bottom, ${T.muted} 0 1px, transparent 1px 4px)` } }, column)),
31439
+ columnSeparator && /* @__PURE__ */ jsx2("span", { style: { position: "absolute", left: "50%", top: 0, bottom: 0, width: 1, background: T.muted } })
31440
+ ] }),
31441
+ border === "none" && /* @__PURE__ */ jsx2("span", { style: { position: "absolute", inset: 4, border: `1px dashed ${T.border}` } }),
31442
+ lineNumbers && /* @__PURE__ */ jsxs2("span", { style: { position: "absolute", inset: "4px 3px", display: "grid", gridTemplateColumns: "8px 1fr", gap: 2 }, children: [
31443
+ /* @__PURE__ */ jsxs2("span", { style: { fontSize: 5, lineHeight: "6px", color: T.accent }, children: [
30550
31444
  "1",
30551
- /* @__PURE__ */ jsx("br", {}),
31445
+ /* @__PURE__ */ jsx2("br", {}),
30552
31446
  "2",
30553
- /* @__PURE__ */ jsx("br", {}),
31447
+ /* @__PURE__ */ jsx2("br", {}),
30554
31448
  "3",
30555
- /* @__PURE__ */ jsx("br", {}),
31449
+ /* @__PURE__ */ jsx2("br", {}),
30556
31450
  "4"
30557
31451
  ] }),
30558
- /* @__PURE__ */ jsx("span", { style: { background: `repeating-linear-gradient(to bottom, ${T.muted} 0 1px, transparent 1px 6px)` } })
31452
+ /* @__PURE__ */ jsx2("span", { style: { background: `repeating-linear-gradient(to bottom, ${T.muted} 0 1px, transparent 1px 6px)` } })
30559
31453
  ] })
30560
31454
  ]
30561
31455
  },
@@ -30573,11 +31467,11 @@ function LayoutMenu({
30573
31467
  onPick
30574
31468
  }) {
30575
31469
  const id = useId();
30576
- const triggerRef = useRef(null);
30577
- const menuRef = useRef(null);
30578
- const keyboardOpen = useRef(null);
30579
- const [position, setPosition] = useState({ left: 8, top: 8, maxHeight: 480 });
30580
- const [portalTokens, setPortalTokens] = useState({});
31470
+ const triggerRef = useRef2(null);
31471
+ const menuRef = useRef2(null);
31472
+ const keyboardOpen = useRef2(null);
31473
+ const [position, setPosition] = useState2({ left: 8, top: 8, maxHeight: 480 });
31474
+ const [portalTokens, setPortalTokens] = useState2({});
30581
31475
  useLayoutEffect(() => {
30582
31476
  if (!open) return;
30583
31477
  const update = () => {
@@ -30670,8 +31564,8 @@ function LayoutMenu({
30670
31564
  event.stopPropagation();
30671
31565
  items[next]?.focus({ preventScroll: true });
30672
31566
  };
30673
- return /* @__PURE__ */ jsxs("span", { className: "dxw-layout-control", style: { display: "inline-flex", minWidth: 0 }, children: [
30674
- /* @__PURE__ */ jsxs(
31567
+ return /* @__PURE__ */ jsxs2("span", { className: "dxw-layout-control", style: { display: "inline-flex", minWidth: 0 }, children: [
31568
+ /* @__PURE__ */ jsxs2(
30675
31569
  "button",
30676
31570
  {
30677
31571
  ref: triggerRef,
@@ -30705,13 +31599,13 @@ function LayoutMenu({
30705
31599
  fontWeight: 500
30706
31600
  },
30707
31601
  children: [
30708
- /* @__PURE__ */ jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: label }),
30709
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { fontSize: 10 }, children: "\u2304" })
31602
+ /* @__PURE__ */ jsx2("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: label }),
31603
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", style: { fontSize: 10 }, children: "\u2304" })
30710
31604
  ]
30711
31605
  }
30712
31606
  ),
30713
- open && createPortal(
30714
- /* @__PURE__ */ jsx(
31607
+ open && createPortal2(
31608
+ /* @__PURE__ */ jsx2(
30715
31609
  "div",
30716
31610
  {
30717
31611
  ref: menuRef,
@@ -30739,7 +31633,7 @@ function LayoutMenu({
30739
31633
  boxShadow: T.popoverShadow,
30740
31634
  padding: 6
30741
31635
  },
30742
- children: options.map((option) => /* @__PURE__ */ jsxs(
31636
+ children: options.map((option) => /* @__PURE__ */ jsxs2(
30743
31637
  "button",
30744
31638
  {
30745
31639
  type: "button",
@@ -30771,9 +31665,9 @@ function LayoutMenu({
30771
31665
  onMouseLeave: (event) => event.currentTarget.style.background = "transparent",
30772
31666
  children: [
30773
31667
  option.preview,
30774
- /* @__PURE__ */ jsxs("span", { style: { minWidth: 0 }, children: [
30775
- /* @__PURE__ */ jsx("span", { style: { display: "block", fontSize: 13, fontWeight: 550 }, children: option.label }),
30776
- option.description && /* @__PURE__ */ jsx("span", { style: { display: "block", fontSize: 11, color: T.muted, marginTop: 1 }, children: option.description })
31668
+ /* @__PURE__ */ jsxs2("span", { style: { minWidth: 0 }, children: [
31669
+ /* @__PURE__ */ jsx2("span", { style: { display: "block", fontSize: 13, fontWeight: 550 }, children: option.label }),
31670
+ option.description && /* @__PURE__ */ jsx2("span", { style: { display: "block", fontSize: 11, color: T.muted, marginTop: 1 }, children: option.description })
30777
31671
  ] })
30778
31672
  ]
30779
31673
  },
@@ -30791,11 +31685,11 @@ function MarginMenu({
30791
31685
  open,
30792
31686
  onOpenChange
30793
31687
  }) {
30794
- const [customOpen, setCustomOpen] = useState(false);
30795
- const [values, setValues] = useState({ top: "1", bottom: "1", left: "1", right: "1" });
30796
- const rootRef = useRef(null);
30797
- const [dialogPosition, setDialogPosition] = useState({ left: 8, top: 8 });
30798
- useEffect(() => {
31688
+ const [customOpen, setCustomOpen] = useState2(false);
31689
+ const [values, setValues] = useState2({ top: "1", bottom: "1", left: "1", right: "1" });
31690
+ const rootRef = useRef2(null);
31691
+ const [dialogPosition, setDialogPosition] = useState2({ left: 8, top: 8 });
31692
+ useEffect2(() => {
30799
31693
  if (!customOpen) return;
30800
31694
  const positionDialog = () => {
30801
31695
  const trigger = rootRef.current?.querySelector("[data-dxw-layout-menu-trigger]");
@@ -30851,9 +31745,9 @@ function MarginMenu({
30851
31745
  });
30852
31746
  setCustomOpen(false);
30853
31747
  };
30854
- const field = (side, label) => /* @__PURE__ */ jsxs("label", { style: { display: "grid", gridTemplateColumns: "54px 1fr", gap: 8, alignItems: "center", fontSize: 12 }, children: [
30855
- /* @__PURE__ */ jsx("span", { children: label }),
30856
- /* @__PURE__ */ jsx(
31748
+ const field = (side, label) => /* @__PURE__ */ jsxs2("label", { style: { display: "grid", gridTemplateColumns: "54px 1fr", gap: 8, alignItems: "center", fontSize: 12 }, children: [
31749
+ /* @__PURE__ */ jsx2("span", { children: label }),
31750
+ /* @__PURE__ */ jsx2(
30857
31751
  "input",
30858
31752
  {
30859
31753
  "aria-label": `${label} margin (inches)`,
@@ -30871,8 +31765,8 @@ function MarginMenu({
30871
31765
  }
30872
31766
  )
30873
31767
  ] });
30874
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-flex" }, children: [
30875
- /* @__PURE__ */ jsx(
31768
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-flex" }, children: [
31769
+ /* @__PURE__ */ jsx2(
30876
31770
  LayoutMenu,
30877
31771
  {
30878
31772
  name: "margins",
@@ -30881,16 +31775,16 @@ function MarginMenu({
30881
31775
  onOpenChange,
30882
31776
  onPick: pick,
30883
31777
  options: [
30884
- { value: "m:normal", label: "Normal", description: '1" on every side', preview: /* @__PURE__ */ jsx(PagePreview, { kind: "margins", margins: [1, 1, 1, 1] }) },
30885
- { value: "m:narrow", label: "Narrow", description: '0.5" on every side', preview: /* @__PURE__ */ jsx(PagePreview, { kind: "margins", margins: [0.5, 0.5, 0.5, 0.5] }) },
30886
- { value: "m:moderate", label: "Moderate", description: '1" top/bottom, 0.75" left/right', preview: /* @__PURE__ */ jsx(PagePreview, { kind: "margins", margins: [1, 0.75, 1, 0.75] }) },
30887
- { value: "m:wide", label: "Wide", description: '1" top/bottom, 2" left/right', preview: /* @__PURE__ */ jsx(PagePreview, { kind: "margins", margins: [1, 2, 1, 2] }) },
30888
- { value: "m:mirrored", label: "Mirrored", description: 'Facing pages; inside margin 1.25"', preview: /* @__PURE__ */ jsx(PagePreview, { kind: "margins", margins: [1, 1, 1, 1.25], mirrored: true }) },
30889
- { value: "m:custom", label: "Custom Margins\u2026", description: "Set each side in inches", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "margins", margins: [0.7, 1.2, 0.7, 1.2] }) }
31778
+ { value: "m:normal", label: "Normal", description: '1" on every side', preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "margins", margins: [1, 1, 1, 1] }) },
31779
+ { value: "m:narrow", label: "Narrow", description: '0.5" on every side', preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "margins", margins: [0.5, 0.5, 0.5, 0.5] }) },
31780
+ { value: "m:moderate", label: "Moderate", description: '1" top/bottom, 0.75" left/right', preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "margins", margins: [1, 0.75, 1, 0.75] }) },
31781
+ { value: "m:wide", label: "Wide", description: '1" top/bottom, 2" left/right', preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "margins", margins: [1, 2, 1, 2] }) },
31782
+ { value: "m:mirrored", label: "Mirrored", description: 'Facing pages; inside margin 1.25"', preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "margins", margins: [1, 1, 1, 1.25], mirrored: true }) },
31783
+ { value: "m:custom", label: "Custom Margins\u2026", description: "Set each side in inches", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "margins", margins: [0.7, 1.2, 0.7, 1.2] }) }
30890
31784
  ]
30891
31785
  }
30892
31786
  ),
30893
- customOpen && /* @__PURE__ */ jsxs(
31787
+ customOpen && /* @__PURE__ */ jsxs2(
30894
31788
  "div",
30895
31789
  {
30896
31790
  role: "dialog",
@@ -30912,19 +31806,19 @@ function MarginMenu({
30912
31806
  gap: 7
30913
31807
  },
30914
31808
  children: [
30915
- /* @__PURE__ */ jsx("strong", { style: { fontSize: 13 }, children: "Custom Margins" }),
31809
+ /* @__PURE__ */ jsx2("strong", { style: { fontSize: 13 }, children: "Custom Margins" }),
30916
31810
  field("top", "Top"),
30917
31811
  field("bottom", "Bottom"),
30918
31812
  field("left", "Left"),
30919
31813
  field("right", "Right"),
30920
- /* @__PURE__ */ jsxs("span", { style: { color: T.muted, fontSize: 11 }, children: [
31814
+ /* @__PURE__ */ jsxs2("span", { style: { color: T.muted, fontSize: 11 }, children: [
30921
31815
  "Applies to ",
30922
31816
  scope === "section" ? "this section" : "the whole document",
30923
31817
  " and turns mirrored margins off for the whole document."
30924
31818
  ] }),
30925
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6 }, children: [
30926
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setCustomOpen(false), style: { ...pillBtn, background: T.popoverBg, color: T.fg }, children: "Cancel" }),
30927
- /* @__PURE__ */ jsx("button", { type: "button", onClick: applyCustom, disabled: !valid, style: pillBtn, children: "Apply" })
31819
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6 }, children: [
31820
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => setCustomOpen(false), style: { ...pillBtn, background: T.popoverBg, color: T.fg }, children: "Cancel" }),
31821
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: applyCustom, disabled: !valid, style: pillBtn, children: "Apply" })
30928
31822
  ] })
30929
31823
  ]
30930
31824
  }
@@ -30937,11 +31831,11 @@ function PageSizeMenu({
30937
31831
  open,
30938
31832
  onOpenChange
30939
31833
  }) {
30940
- const [customOpen, setCustomOpen] = useState(false);
30941
- const [values, setValues] = useState({ width: "8.5", height: "11" });
30942
- const rootRef = useRef(null);
30943
- const [dialogPosition, setDialogPosition] = useState({ left: 8, top: 8 });
30944
- useEffect(() => {
31834
+ const [customOpen, setCustomOpen] = useState2(false);
31835
+ const [values, setValues] = useState2({ width: "8.5", height: "11" });
31836
+ const rootRef = useRef2(null);
31837
+ const [dialogPosition, setDialogPosition] = useState2({ left: 8, top: 8 });
31838
+ useEffect2(() => {
30945
31839
  if (!customOpen) return;
30946
31840
  const positionDialog = () => {
30947
31841
  const trigger = rootRef.current?.querySelector("[data-dxw-layout-menu-trigger]");
@@ -30977,9 +31871,9 @@ function PageSizeMenu({
30977
31871
  onApply({ size: { width: Number(values.width), height: Number(values.height) } });
30978
31872
  setCustomOpen(false);
30979
31873
  };
30980
- const field = (side, label) => /* @__PURE__ */ jsxs("label", { style: { display: "grid", gridTemplateColumns: "54px 1fr", gap: 8, alignItems: "center", fontSize: 12 }, children: [
30981
- /* @__PURE__ */ jsx("span", { children: label }),
30982
- /* @__PURE__ */ jsx(
31874
+ const field = (side, label) => /* @__PURE__ */ jsxs2("label", { style: { display: "grid", gridTemplateColumns: "54px 1fr", gap: 8, alignItems: "center", fontSize: 12 }, children: [
31875
+ /* @__PURE__ */ jsx2("span", { children: label }),
31876
+ /* @__PURE__ */ jsx2(
30983
31877
  "input",
30984
31878
  {
30985
31879
  "aria-label": `Page ${side} (inches)`,
@@ -30997,8 +31891,8 @@ function PageSizeMenu({
30997
31891
  }
30998
31892
  )
30999
31893
  ] });
31000
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-flex" }, children: [
31001
- /* @__PURE__ */ jsx(
31894
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-flex" }, children: [
31895
+ /* @__PURE__ */ jsx2(
31002
31896
  LayoutMenu,
31003
31897
  {
31004
31898
  name: "size",
@@ -31010,9 +31904,9 @@ function PageSizeMenu({
31010
31904
  value: size.value,
31011
31905
  label: size.label,
31012
31906
  description: size.description,
31013
- preview: /* @__PURE__ */ jsx(PagePreview, { kind: "size", width: size.width, height: size.height })
31907
+ preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "size", width: size.width, height: size.height })
31014
31908
  })),
31015
- { value: "custom", label: "Custom Paper Size\u2026", description: "Set width and height in inches", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "size", width: 7.5, height: 10 }) }
31909
+ { value: "custom", label: "Custom Paper Size\u2026", description: "Set width and height in inches", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "size", width: 7.5, height: 10 }) }
31016
31910
  ],
31017
31911
  onPick: (value) => {
31018
31912
  if (value === "custom") {
@@ -31025,7 +31919,7 @@ function PageSizeMenu({
31025
31919
  }
31026
31920
  }
31027
31921
  ),
31028
- customOpen && /* @__PURE__ */ jsxs(
31922
+ customOpen && /* @__PURE__ */ jsxs2(
31029
31923
  "div",
31030
31924
  {
31031
31925
  role: "dialog",
@@ -31047,17 +31941,17 @@ function PageSizeMenu({
31047
31941
  gap: 7
31048
31942
  },
31049
31943
  children: [
31050
- /* @__PURE__ */ jsx("strong", { style: { fontSize: 13 }, children: "Custom Paper Size" }),
31944
+ /* @__PURE__ */ jsx2("strong", { style: { fontSize: 13 }, children: "Custom Paper Size" }),
31051
31945
  field("width", "Width"),
31052
31946
  field("height", "Height"),
31053
- /* @__PURE__ */ jsxs("span", { style: { color: T.muted, fontSize: 11 }, children: [
31947
+ /* @__PURE__ */ jsxs2("span", { style: { color: T.muted, fontSize: 11 }, children: [
31054
31948
  "Applies to ",
31055
31949
  scope === "section" ? "this section" : "the whole document",
31056
31950
  "."
31057
31951
  ] }),
31058
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6 }, children: [
31059
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setCustomOpen(false), style: { ...pillBtn, background: T.popoverBg, color: T.fg }, children: "Cancel" }),
31060
- /* @__PURE__ */ jsx("button", { type: "button", onClick: applyCustom, disabled: !valid, style: pillBtn, children: "Apply" })
31952
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6 }, children: [
31953
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => setCustomOpen(false), style: { ...pillBtn, background: T.popoverBg, color: T.fg }, children: "Cancel" }),
31954
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: applyCustom, disabled: !valid, style: pillBtn, children: "Apply" })
31061
31955
  ] })
31062
31956
  ]
31063
31957
  }
@@ -31065,80 +31959,111 @@ function PageSizeMenu({
31065
31959
  ] });
31066
31960
  }
31067
31961
  function LayoutTab({ api, showArrange }) {
31068
- const [scope, setScope] = useState("document");
31069
- const [openMenu, setOpenMenu] = useState(null);
31070
- const rootRef = useRef(null);
31962
+ const [scope, setScope] = useState2("document");
31963
+ const [section, setSection] = useState2(null);
31964
+ const [objectSelected, setObjectSelected] = useState2(false);
31965
+ const [openMenu, setOpenMenu] = useState2(null);
31966
+ const rootRef = useRef2(null);
31967
+ useEffect2(() => {
31968
+ const refresh = () => {
31969
+ setSection(api?.getSectionContext() ?? null);
31970
+ setObjectSelected(api?.hasSelectedObject() ?? false);
31971
+ };
31972
+ refresh();
31973
+ document.addEventListener("dxw-selection", refresh);
31974
+ document.addEventListener("dxw-object-selection", refresh);
31975
+ return () => {
31976
+ document.removeEventListener("dxw-selection", refresh);
31977
+ document.removeEventListener("dxw-object-selection", refresh);
31978
+ };
31979
+ }, [api]);
31071
31980
  const set = (patch) => api?.setPageLayout(patch, scope);
31072
31981
  const setLn = (patch) => api?.setLineNumbering(patch, scope);
31073
31982
  const menuState = (name) => ({
31074
31983
  open: openMenu === name,
31075
31984
  onOpenChange: (open) => setOpenMenu(open ? name : null)
31076
31985
  });
31077
- return /* @__PURE__ */ jsxs(
31986
+ return /* @__PURE__ */ jsxs2(
31078
31987
  "span",
31079
31988
  {
31080
31989
  ref: rootRef,
31081
31990
  className: "dxw-layout-ribbon",
31082
31991
  "data-dxw-layout-ribbon": "",
31083
- style: { display: "flex", flex: "1 1 640px", minWidth: 0, alignItems: "center", flexWrap: "wrap", gap: 2 },
31992
+ style: {
31993
+ display: "flex",
31994
+ flex: "0 0 100%",
31995
+ order: 2,
31996
+ minWidth: 0,
31997
+ boxSizing: "border-box",
31998
+ alignItems: "center",
31999
+ flexWrap: "wrap",
32000
+ gap: 2,
32001
+ paddingTop: 4,
32002
+ marginTop: 2,
32003
+ borderTop: `1px solid ${T.border}`
32004
+ },
31084
32005
  children: [
31085
- /* @__PURE__ */ jsx(
32006
+ /* @__PURE__ */ jsx2(
31086
32007
  ToolbarMenuSelect,
31087
32008
  {
31088
32009
  title: "Apply layout changes to",
31089
32010
  ariaLabel: "Apply layout changes to",
31090
32011
  value: scope,
31091
- width: 118,
31092
- menuWidth: 170,
32012
+ width: section ? 160 : 142,
32013
+ menuWidth: 205,
31093
32014
  options: [
31094
32015
  { value: "document", label: "Whole document" },
31095
- { value: "section", label: "This section" }
32016
+ {
32017
+ value: "section",
32018
+ label: section ? `This section \xB7 ${section.index} of ${section.count}` : "This section"
32019
+ }
31096
32020
  ],
31097
32021
  onChange: (value) => setScope(value),
31098
32022
  style: { maxWidth: "100%" }
31099
32023
  }
31100
32024
  ),
31101
- /* @__PURE__ */ jsx(Sep, {}),
31102
- /* @__PURE__ */ jsx(MarginMenu, { scope, onApply: set, ...menuState("margins") }),
31103
- /* @__PURE__ */ jsx(
32025
+ /* @__PURE__ */ jsx2(Sep, {}),
32026
+ /* @__PURE__ */ jsx2(MarginMenu, { scope, onApply: set, ...menuState("margins") }),
32027
+ /* @__PURE__ */ jsx2(
31104
32028
  LayoutMenu,
31105
32029
  {
31106
32030
  name: "orientation",
31107
32031
  label: "Orientation",
31108
32032
  ...menuState("orientation"),
31109
32033
  options: [
31110
- { value: "portrait", label: "Portrait", description: "Vertical page", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "orientation" }) },
31111
- { value: "landscape", label: "Landscape", description: "Horizontal page", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "orientation", width: 11, height: 8.5 }) }
32034
+ { value: "portrait", label: "Portrait", description: "Vertical page", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "orientation" }) },
32035
+ { value: "landscape", label: "Landscape", description: "Horizontal page", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "orientation", width: 11, height: 8.5 }) }
31112
32036
  ],
31113
32037
  onPick: (value) => set({ orientation: value })
31114
32038
  }
31115
32039
  ),
31116
- /* @__PURE__ */ jsx(PageSizeMenu, { scope, onApply: set, ...menuState("size") }),
31117
- /* @__PURE__ */ jsx(
32040
+ /* @__PURE__ */ jsx2(PageSizeMenu, { scope, onApply: set, ...menuState("size") }),
32041
+ /* @__PURE__ */ jsx2(
31118
32042
  LayoutMenu,
31119
32043
  {
31120
32044
  name: "columns",
31121
- label: "Columns",
32045
+ label: "Columns & divider",
31122
32046
  ...menuState("columns"),
31123
32047
  options: [
31124
- { value: "1", label: "One", description: "Single text column", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "columns", columns: 1 }) },
31125
- { value: "2", label: "Two", description: "Two equal columns", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "columns", columns: 2 }) },
31126
- { value: "3", label: "Three", description: "Three equal columns", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "columns", columns: 3 }) }
32048
+ { value: "1", label: "One", description: "Single text column", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "columns", columns: 1 }) },
32049
+ { value: "2", label: "Two", description: "Two equal columns", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "columns", columns: 2 }) },
32050
+ { value: "2-divider", label: "Two + divider line", description: "Two columns with Word's automatic vertical line between them", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "columns", columns: 2, columnSeparator: true }) },
32051
+ { value: "3", label: "Three", description: "Three equal columns", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "columns", columns: 3 }) }
31127
32052
  ],
31128
- onPick: (value) => set({ columns: parseInt(value, 10) })
32053
+ onPick: (value) => set({ columns: parseInt(value, 10), columnSeparator: value === "2-divider" })
31129
32054
  }
31130
32055
  ),
31131
- /* @__PURE__ */ jsx(
32056
+ /* @__PURE__ */ jsx2(
31132
32057
  LayoutMenu,
31133
32058
  {
31134
32059
  name: "page-border",
31135
32060
  label: "Page border",
31136
32061
  ...menuState("page-border"),
31137
32062
  options: [
31138
- { value: "none", label: "None", description: "No page border", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "page-border", border: "none" }) },
31139
- { value: "thin", label: "Thin box", description: "\xBD pt solid line", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "page-border", border: "thin" }) },
31140
- { value: "thick", label: "Thick box", description: "1\xBD pt solid line", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "page-border", border: "thick" }) },
31141
- { value: "accent", label: "Accent box", description: "Blue 1 pt line", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "page-border", border: "accent" }) }
32063
+ { value: "none", label: "None", description: "No page border", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "page-border", border: "none" }) },
32064
+ { value: "thin", label: "Thin box", description: "\xBD pt solid line", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "page-border", border: "thin" }) },
32065
+ { value: "thick", label: "Thick box", description: "1\xBD pt solid line", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "page-border", border: "thick" }) },
32066
+ { value: "accent", label: "Accent box", description: "Blue 1 pt line", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "page-border", border: "accent" }) }
31142
32067
  ],
31143
32068
  onPick: (value) => {
31144
32069
  if (value === "none") set({ pageBorders: null });
@@ -31148,19 +32073,19 @@ function LayoutTab({ api, showArrange }) {
31148
32073
  }
31149
32074
  }
31150
32075
  ),
31151
- /* @__PURE__ */ jsx(
32076
+ /* @__PURE__ */ jsx2(
31152
32077
  LayoutMenu,
31153
32078
  {
31154
32079
  name: "line-numbers",
31155
32080
  label: "Line numbers",
31156
32081
  ...menuState("line-numbers"),
31157
32082
  options: [
31158
- { value: "off", label: "None", description: "Hide line numbers", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "line-numbers" }) },
31159
- { value: "continuous", label: "Continuous", description: "Number every line continuously", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
31160
- { value: "eachPage", label: "Restart each page", description: "Start at 1 on every page", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
31161
- { value: "eachSection", label: "Restart each section", description: "Start at 1 in each section", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
31162
- { value: "by5", label: "Count by 5", description: "Show every fifth line", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
31163
- { value: "by10", label: "Count by 10", description: "Show every tenth line", preview: /* @__PURE__ */ jsx(PagePreview, { kind: "line-numbers", lineNumbers: true }) }
32083
+ { value: "off", label: "None", description: "Hide line numbers", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers" }) },
32084
+ { value: "continuous", label: "Continuous", description: "Number every line continuously", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
32085
+ { value: "eachPage", label: "Restart each page", description: "Start at 1 on every page", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
32086
+ { value: "eachSection", label: "Restart each section", description: "Start at 1 in each section", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
32087
+ { value: "by5", label: "Count by 5", description: "Show every fifth line", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
32088
+ { value: "by10", label: "Count by 10", description: "Show every tenth line", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers", lineNumbers: true }) }
31164
32089
  ],
31165
32090
  onPick: (value) => {
31166
32091
  if (value === "off") setLn({ enabled: false });
@@ -31172,9 +32097,9 @@ function LayoutTab({ api, showArrange }) {
31172
32097
  }
31173
32098
  }
31174
32099
  ),
31175
- showArrange && /* @__PURE__ */ jsxs(Fragment2, { children: [
31176
- /* @__PURE__ */ jsx(Sep, {}),
31177
- /* @__PURE__ */ jsx(
32100
+ showArrange && objectSelected && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32101
+ /* @__PURE__ */ jsx2(Sep, {}),
32102
+ /* @__PURE__ */ jsx2(
31178
32103
  ActionMenu,
31179
32104
  {
31180
32105
  label: "Align",
@@ -31187,7 +32112,7 @@ function LayoutTab({ api, showArrange }) {
31187
32112
  onPick: (value) => api?.arrangeObject(value)
31188
32113
  }
31189
32114
  ),
31190
- /* @__PURE__ */ jsx(
32115
+ /* @__PURE__ */ jsx2(
31191
32116
  ActionMenu,
31192
32117
  {
31193
32118
  label: "Rotate",
@@ -31197,7 +32122,7 @@ function LayoutTab({ api, showArrange }) {
31197
32122
  onPick: (value) => api?.arrangeObject(value)
31198
32123
  }
31199
32124
  ),
31200
- /* @__PURE__ */ jsx(
32125
+ /* @__PURE__ */ jsx2(
31201
32126
  ActionMenu,
31202
32127
  {
31203
32128
  label: "Arrange",
@@ -31221,12 +32146,17 @@ function DocxToolbar({
31221
32146
  style
31222
32147
  }) {
31223
32148
  const on = (k) => features?.[k] !== false;
31224
- const [tab, setTab] = useState("home");
31225
- const iconInput = useRef(null);
31226
- const modelInput = useRef(null);
31227
- const objectInput = useRef(null);
31228
- const [tip, setTip] = useState(null);
31229
- const tipTimer = useRef(null);
32149
+ const [tab, setTab] = useState2("home");
32150
+ const [helpOpen, setHelpOpen] = useState2(false);
32151
+ const apple = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform);
32152
+ const shortcut = (key) => apple ? `\u2318${key}` : `Ctrl+${key}`;
32153
+ const closeHelp = useCallback(() => setHelpOpen(false), []);
32154
+ const iconInput = useRef2(null);
32155
+ const modelInput = useRef2(null);
32156
+ const objectInput = useRef2(null);
32157
+ const helpTrigger = useRef2(null);
32158
+ const [tip, setTip] = useState2(null);
32159
+ const tipTimer = useRef2(null);
31230
32160
  const onTipOver = useCallback((e) => {
31231
32161
  const el16 = e.target.closest("[title], [data-tip]");
31232
32162
  if (!el16) return;
@@ -31247,14 +32177,25 @@ function DocxToolbar({
31247
32177
  if (tipTimer.current) clearTimeout(tipTimer.current);
31248
32178
  setTip(null);
31249
32179
  }, []);
31250
- const [fmt, setFmt] = useState(null);
31251
- const [curStyle, setCurStyle] = useState(null);
31252
- const [listKind, setListKind] = useState(null);
31253
- const savedRange = useRef(null);
31254
- const imageInput = useRef(null);
31255
- const rootRef = useRef(null);
31256
- const [tier, setTier] = useState(0);
31257
- useEffect(() => {
32180
+ const [fmt, setFmt] = useState2(null);
32181
+ const [curStyle, setCurStyle] = useState2(null);
32182
+ const [listKind, setListKind] = useState2(null);
32183
+ const savedRange = useRef2(null);
32184
+ const imageInput = useRef2(null);
32185
+ const rootRef = useRef2(null);
32186
+ const [tier, setTier] = useState2(0);
32187
+ useEffect2(() => {
32188
+ if (!on("help")) return;
32189
+ const keydown = (event) => {
32190
+ if (event.key === "F1" || (event.metaKey || event.ctrlKey) && event.key === "/") {
32191
+ event.preventDefault();
32192
+ setHelpOpen(true);
32193
+ }
32194
+ };
32195
+ document.addEventListener("keydown", keydown);
32196
+ return () => document.removeEventListener("keydown", keydown);
32197
+ }, [features]);
32198
+ useEffect2(() => {
31258
32199
  const el16 = rootRef.current;
31259
32200
  if (!el16 || typeof ResizeObserver === "undefined") return;
31260
32201
  const measure = () => {
@@ -31279,7 +32220,7 @@ function DocxToolbar({
31279
32220
  setCurStyle(api?.getParagraphStyleId?.() ?? null);
31280
32221
  setListKind(api?.getListType?.() ?? null);
31281
32222
  }, [api]);
31282
- useEffect(() => {
32223
+ useEffect2(() => {
31283
32224
  document.addEventListener("selectionchange", refresh);
31284
32225
  document.addEventListener("dxw-selection", refresh);
31285
32226
  return () => {
@@ -31307,22 +32248,22 @@ function DocxToolbar({
31307
32248
  if (on("history"))
31308
32249
  groups.push({
31309
32250
  key: "history",
31310
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31311
- /* @__PURE__ */ jsx(Btn, { label: "\u21B6", title: "Undo (\u2318Z)", onClick: () => {
32251
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32252
+ /* @__PURE__ */ jsx2(Btn, { label: "\u21B6", title: "Undo (\u2318Z)", onClick: () => {
31312
32253
  api?.undo();
31313
32254
  refresh();
31314
32255
  } }),
31315
- /* @__PURE__ */ jsx(Btn, { label: "\u21B7", title: "Redo (\u21E7\u2318Z)", onClick: () => {
32256
+ /* @__PURE__ */ jsx2(Btn, { label: "\u21B7", title: "Redo (\u21E7\u2318Z)", onClick: () => {
31316
32257
  api?.redo();
31317
32258
  refresh();
31318
32259
  } }),
31319
- /* @__PURE__ */ jsx(Sep, {})
32260
+ /* @__PURE__ */ jsx2(Sep, {})
31320
32261
  ] })
31321
32262
  });
31322
32263
  if (on("styles"))
31323
32264
  groups.push({
31324
32265
  key: "styles",
31325
- node: /* @__PURE__ */ jsx(
32266
+ node: /* @__PURE__ */ jsx2(
31326
32267
  ToolbarMenuSelect,
31327
32268
  {
31328
32269
  title: "Paragraph style",
@@ -31346,7 +32287,7 @@ function DocxToolbar({
31346
32287
  if (on("font"))
31347
32288
  groups.push({
31348
32289
  key: "font",
31349
- node: /* @__PURE__ */ jsx(
32290
+ node: /* @__PURE__ */ jsx2(
31350
32291
  ToolbarMenuSelect,
31351
32292
  {
31352
32293
  title: "Font",
@@ -31366,8 +32307,8 @@ function DocxToolbar({
31366
32307
  if (on("size"))
31367
32308
  groups.push({
31368
32309
  key: "size",
31369
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31370
- /* @__PURE__ */ jsx(
32310
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32311
+ /* @__PURE__ */ jsx2(
31371
32312
  ToolbarMenuSelect,
31372
32313
  {
31373
32314
  title: "Font size",
@@ -31379,43 +32320,43 @@ function DocxToolbar({
31379
32320
  onChange: (value) => value && apply({ fontSizePt: parseFloat(value) })
31380
32321
  }
31381
32322
  ),
31382
- /* @__PURE__ */ jsx(Sep, {})
32323
+ /* @__PURE__ */ jsx2(Sep, {})
31383
32324
  ] })
31384
32325
  });
31385
32326
  if (on("format"))
31386
32327
  groups.push({
31387
32328
  key: "format",
31388
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31389
- /* @__PURE__ */ jsx(Btn, { label: /* @__PURE__ */ jsx("b", { children: "B" }), title: "Bold (\u2318B)", active: !!fmt?.bold, onClick: () => apply({ bold: !fmt?.bold }) }),
31390
- /* @__PURE__ */ jsx(Btn, { label: /* @__PURE__ */ jsx("i", { children: "I" }), title: "Italic", active: !!fmt?.italic, onClick: () => apply({ italic: !fmt?.italic }) }),
31391
- /* @__PURE__ */ jsx(Btn, { label: /* @__PURE__ */ jsx("u", { children: "U" }), title: "Underline", active: !!fmt?.underline, onClick: () => apply({ underline: !fmt?.underline }) }),
31392
- /* @__PURE__ */ jsx(Btn, { label: /* @__PURE__ */ jsx("s", { children: "S" }), title: "Strikethrough", active: !!fmt?.strike, onClick: () => apply({ strike: !fmt?.strike }) }),
31393
- /* @__PURE__ */ jsx(
32329
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32330
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2("b", { children: "B" }), title: "Bold (\u2318B)", active: !!fmt?.bold, onClick: () => apply({ bold: !fmt?.bold }) }),
32331
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2("i", { children: "I" }), title: "Italic", active: !!fmt?.italic, onClick: () => apply({ italic: !fmt?.italic }) }),
32332
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2("u", { children: "U" }), title: "Underline", active: !!fmt?.underline, onClick: () => apply({ underline: !fmt?.underline }) }),
32333
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2("s", { children: "S" }), title: "Strikethrough", active: !!fmt?.strike, onClick: () => apply({ strike: !fmt?.strike }) }),
32334
+ /* @__PURE__ */ jsx2(
31394
32335
  Btn,
31395
32336
  {
31396
- label: /* @__PURE__ */ jsxs("span", { style: { fontSize: 12 }, children: [
32337
+ label: /* @__PURE__ */ jsxs2("span", { style: { fontSize: 12 }, children: [
31397
32338
  "x",
31398
- /* @__PURE__ */ jsx("sup", { style: { fontSize: 9 }, children: "2" })
32339
+ /* @__PURE__ */ jsx2("sup", { style: { fontSize: 9 }, children: "2" })
31399
32340
  ] }),
31400
32341
  title: "Superscript",
31401
32342
  active: fmt?.verticalAlign === "superscript",
31402
32343
  onClick: () => apply({ verticalAlign: fmt?.verticalAlign === "superscript" ? null : "superscript" })
31403
32344
  }
31404
32345
  ),
31405
- /* @__PURE__ */ jsx(
32346
+ /* @__PURE__ */ jsx2(
31406
32347
  Btn,
31407
32348
  {
31408
- label: /* @__PURE__ */ jsxs("span", { style: { fontSize: 12 }, children: [
32349
+ label: /* @__PURE__ */ jsxs2("span", { style: { fontSize: 12 }, children: [
31409
32350
  "x",
31410
- /* @__PURE__ */ jsx("sub", { style: { fontSize: 9 }, children: "2" })
32351
+ /* @__PURE__ */ jsx2("sub", { style: { fontSize: 9 }, children: "2" })
31411
32352
  ] }),
31412
32353
  title: "Subscript",
31413
32354
  active: fmt?.verticalAlign === "subscript",
31414
32355
  onClick: () => apply({ verticalAlign: fmt?.verticalAlign === "subscript" ? null : "subscript" })
31415
32356
  }
31416
32357
  ),
31417
- /* @__PURE__ */ jsx(Btn, { label: /* @__PURE__ */ jsx(ClearFormatIcon, {}), title: "Clear formatting", onClick: () => apply({ clear: true }) }),
31418
- /* @__PURE__ */ jsx(
32358
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2(ClearFormatIcon, {}), title: "Clear formatting", onClick: () => apply({ clear: true }) }),
32359
+ /* @__PURE__ */ jsx2(
31419
32360
  ActionMenu,
31420
32361
  {
31421
32362
  label: "Aa",
@@ -31433,12 +32374,12 @@ function DocxToolbar({
31433
32374
  if (on("color"))
31434
32375
  groups.push({
31435
32376
  key: "color",
31436
- node: /* @__PURE__ */ jsx(
32377
+ node: /* @__PURE__ */ jsx2(
31437
32378
  ColorMenu,
31438
32379
  {
31439
32380
  current: fmt?.color && fmt.color !== "auto" ? fmt.color : "#000000",
31440
32381
  title: "Text color",
31441
- trigger: /* @__PURE__ */ jsx("span", { style: { fontSize: 13, borderBottom: `3px solid ${fmt?.color && fmt.color !== "auto" ? fmt.color : "#000"}`, padding: "0 3px", color: T.fg }, children: "A" }),
32382
+ trigger: /* @__PURE__ */ jsx2("span", { style: { fontSize: 13, borderBottom: `3px solid ${fmt?.color && fmt.color !== "auto" ? fmt.color : "#000"}`, padding: "0 3px", color: T.fg }, children: "A" }),
31442
32383
  onPick: (value) => apply({ color: value })
31443
32384
  }
31444
32385
  )
@@ -31446,34 +32387,34 @@ function DocxToolbar({
31446
32387
  if (on("highlight"))
31447
32388
  groups.push({
31448
32389
  key: "highlight",
31449
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31450
- /* @__PURE__ */ jsx(HighlightMenu, { current: fmt?.highlight, onPick: (v) => apply({ highlight: v }) }),
31451
- /* @__PURE__ */ jsx(Sep, {})
32390
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32391
+ /* @__PURE__ */ jsx2(HighlightMenu, { current: fmt?.highlight, onPick: (v) => apply({ highlight: v }) }),
32392
+ /* @__PURE__ */ jsx2(Sep, {})
31452
32393
  ] })
31453
32394
  });
31454
32395
  if (on("alignment"))
31455
32396
  groups.push({
31456
32397
  key: "alignment",
31457
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31458
- /* @__PURE__ */ jsx(Btn, { label: "\u2261", title: "Align left", onClick: () => api?.setAlignment("left") }),
31459
- /* @__PURE__ */ jsx(Btn, { label: "\u2263", title: "Center", onClick: () => api?.setAlignment("center") }),
31460
- /* @__PURE__ */ jsx(Btn, { label: "\u2262", title: "Align right", onClick: () => api?.setAlignment("right") }),
31461
- /* @__PURE__ */ jsx(Btn, { label: "\u2630", title: "Justify", onClick: () => api?.setAlignment("justify") }),
31462
- /* @__PURE__ */ jsx(Sep, {})
32398
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32399
+ /* @__PURE__ */ jsx2(Btn, { label: "\u2261", title: "Align left", onClick: () => api?.setAlignment("left") }),
32400
+ /* @__PURE__ */ jsx2(Btn, { label: "\u2263", title: "Center", onClick: () => api?.setAlignment("center") }),
32401
+ /* @__PURE__ */ jsx2(Btn, { label: "\u2262", title: "Align right", onClick: () => api?.setAlignment("right") }),
32402
+ /* @__PURE__ */ jsx2(Btn, { label: "\u2630", title: "Justify", onClick: () => api?.setAlignment("justify") }),
32403
+ /* @__PURE__ */ jsx2(Sep, {})
31463
32404
  ] })
31464
32405
  });
31465
32406
  if (on("indent"))
31466
32407
  groups.push({
31467
32408
  key: "indent",
31468
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31469
- /* @__PURE__ */ jsx(Btn, { label: /* @__PURE__ */ jsx(IndentIcon, { dir: -1 }), title: "Decrease indent", onClick: () => api?.adjustIndent(-1) }),
31470
- /* @__PURE__ */ jsx(Btn, { label: /* @__PURE__ */ jsx(IndentIcon, { dir: 1 }), title: "Increase indent", onClick: () => api?.adjustIndent(1) })
32409
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32410
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2(IndentIcon, { dir: -1 }), title: "Decrease indent", onClick: () => api?.adjustIndent(-1) }),
32411
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2(IndentIcon, { dir: 1 }), title: "Increase indent", onClick: () => api?.adjustIndent(1) })
31471
32412
  ] })
31472
32413
  });
31473
32414
  if (on("spacing"))
31474
32415
  groups.push({
31475
32416
  key: "spacing",
31476
- node: /* @__PURE__ */ jsx(
32417
+ node: /* @__PURE__ */ jsx2(
31477
32418
  ActionMenu,
31478
32419
  {
31479
32420
  label: "\u2195",
@@ -31481,14 +32422,30 @@ function DocxToolbar({
31481
32422
  width: 44,
31482
32423
  groups: [
31483
32424
  { label: "Line spacing", items: [["l:1", "Single"], ["l:1.15", "1.15"], ["l:1.5", "1.5"], ["l:2", "Double"]] },
32425
+ { label: "Exact line height", items: [["e:12", "Exactly 12 pt"], ["e:18", "Exactly 18 pt"], ["e:24", "Exactly 24 pt"], ["e:custom", "Custom exact height\u2026"]] },
31484
32426
  { label: "Paragraph", items: [["b:add", "Add space before"], ["b:none", "Remove space before"], ["a:add", "Add space after"], ["a:none", "Remove space after"]] }
31485
32427
  ],
31486
32428
  onPick: (v) => {
31487
32429
  if (v.startsWith("l:")) api?.setParagraphSpacing({ lineMultiple: parseFloat(v.slice(2)) });
32430
+ else if (v === "e:custom") {
32431
+ const anchor = rootRef.current;
32432
+ if (!anchor) return;
32433
+ void requestTextInputDialog(anchor, {
32434
+ title: "Exact line height",
32435
+ label: "Line height (points)",
32436
+ value: "24",
32437
+ placeholder: "24",
32438
+ submitLabel: "Apply"
32439
+ }).then((next) => {
32440
+ if (next === null) return;
32441
+ const points = Number(next.trim());
32442
+ if (Number.isFinite(points) && points > 0) api?.setParagraphSpacing({ exactLinePt: points });
32443
+ });
32444
+ } else if (v.startsWith("e:")) api?.setParagraphSpacing({ exactLinePt: parseFloat(v.slice(2)) });
31488
32445
  else if (v === "b:add") api?.setParagraphSpacing({ beforePt: 10 });
31489
- else if (v === "b:none") api?.setParagraphSpacing({ beforePt: null });
32446
+ else if (v === "b:none") api?.setParagraphSpacing({ beforePt: 0 });
31490
32447
  else if (v === "a:add") api?.setParagraphSpacing({ afterPt: 10 });
31491
- else if (v === "a:none") api?.setParagraphSpacing({ afterPt: null });
32448
+ else if (v === "a:none") api?.setParagraphSpacing({ afterPt: 0 });
31492
32449
  }
31493
32450
  }
31494
32451
  )
@@ -31496,11 +32453,11 @@ function DocxToolbar({
31496
32453
  if (on("lists"))
31497
32454
  groups.push({
31498
32455
  key: "lists",
31499
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31500
- /* @__PURE__ */ jsx(
32456
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32457
+ /* @__PURE__ */ jsx2(
31501
32458
  Btn,
31502
32459
  {
31503
- label: /* @__PURE__ */ jsx(BulletListIcon, {}),
32460
+ label: /* @__PURE__ */ jsx2(BulletListIcon, {}),
31504
32461
  title: "Bulleted list",
31505
32462
  active: listKind === "bullet",
31506
32463
  onClick: () => {
@@ -31509,10 +32466,10 @@ function DocxToolbar({
31509
32466
  }
31510
32467
  }
31511
32468
  ),
31512
- /* @__PURE__ */ jsx(
32469
+ /* @__PURE__ */ jsx2(
31513
32470
  Btn,
31514
32471
  {
31515
- label: /* @__PURE__ */ jsx(NumberListIcon, {}),
32472
+ label: /* @__PURE__ */ jsx2(NumberListIcon, {}),
31516
32473
  title: "Numbered list",
31517
32474
  active: listKind === "number",
31518
32475
  onClick: () => {
@@ -31521,18 +32478,18 @@ function DocxToolbar({
31521
32478
  }
31522
32479
  }
31523
32480
  ),
31524
- /* @__PURE__ */ jsx(Sep, {})
32481
+ /* @__PURE__ */ jsx2(Sep, {})
31525
32482
  ] })
31526
32483
  });
31527
32484
  const overflowKeys = tier === 0 ? /* @__PURE__ */ new Set() : tier === 1 ? /* @__PURE__ */ new Set(["styles", "indent", "spacing"]) : /* @__PURE__ */ new Set(["styles", "font", "size", "color", "highlight", "alignment", "indent", "spacing"]);
31528
32485
  const inline = groups.filter((g) => !overflowKeys.has(g.key));
31529
32486
  const overflow = groups.filter((g) => overflowKeys.has(g.key));
31530
- return /* @__PURE__ */ jsxs(Fragment2, { children: [
31531
- inline.map((g) => /* @__PURE__ */ jsx(Fragment, { children: g.node }, g.key)),
31532
- overflow.length > 0 && /* @__PURE__ */ jsx(OverflowMenu, { children: overflow.map((g) => /* @__PURE__ */ jsx(Fragment, { children: g.node }, g.key)) })
32487
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
32488
+ inline.map((g) => /* @__PURE__ */ jsx2(Fragment, { children: g.node }, g.key)),
32489
+ overflow.length > 0 && /* @__PURE__ */ jsx2(OverflowMenu, { children: overflow.map((g) => /* @__PURE__ */ jsx2(Fragment, { children: g.node }, g.key)) })
31533
32490
  ] });
31534
32491
  };
31535
- return /* @__PURE__ */ jsxs(
32492
+ return /* @__PURE__ */ jsxs2(
31536
32493
  "div",
31537
32494
  {
31538
32495
  ref: rootRef,
@@ -31559,7 +32516,7 @@ function DocxToolbar({
31559
32516
  ...style
31560
32517
  },
31561
32518
  children: [
31562
- tip && /* @__PURE__ */ jsx(
32519
+ tip && /* @__PURE__ */ jsx2(
31563
32520
  "div",
31564
32521
  {
31565
32522
  style: {
@@ -31580,55 +32537,80 @@ function DocxToolbar({
31580
32537
  children: tip.text
31581
32538
  }
31582
32539
  ),
31583
- mode === "advanced" && /* @__PURE__ */ jsxs(Fragment2, { children: [
31584
- /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 2, marginRight: 8 }, children: ["home", "insert", "draw", "layout"].filter((t) => (t !== "draw" || on("drawing")) && (t !== "layout" || on("layout"))).map((t) => /* @__PURE__ */ jsx(
31585
- "button",
31586
- {
31587
- "data-tab": t,
31588
- onMouseDown: (e) => e.preventDefault(),
31589
- onClick: () => setTab(t),
31590
- style: {
31591
- border: "none",
31592
- background: tab === t ? T.tabActiveBg : "transparent",
31593
- color: tab === t ? T.accent : T.fg,
31594
- font: "600 12.5px system-ui, sans-serif",
31595
- padding: "5px 10px",
31596
- borderRadius: 6,
31597
- cursor: "pointer",
31598
- textTransform: "capitalize"
32540
+ mode === "advanced" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32541
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: 2, marginRight: 8 }, children: [
32542
+ ["home", "insert", "draw", "layout"].filter((t) => (t !== "draw" || on("drawing")) && (t !== "layout" || on("layout"))).map((t) => /* @__PURE__ */ jsx2(
32543
+ "button",
32544
+ {
32545
+ "data-tab": t,
32546
+ onMouseDown: (e) => e.preventDefault(),
32547
+ onClick: () => setTab(t),
32548
+ style: {
32549
+ border: "none",
32550
+ background: tab === t ? T.tabActiveBg : "transparent",
32551
+ color: tab === t ? T.accent : T.fg,
32552
+ font: "600 12.5px system-ui, sans-serif",
32553
+ padding: "5px 10px",
32554
+ borderRadius: 6,
32555
+ cursor: "pointer",
32556
+ textTransform: "capitalize"
32557
+ },
32558
+ children: t
31599
32559
  },
31600
- children: t
31601
- },
31602
- t
31603
- )) }),
31604
- /* @__PURE__ */ jsx(Sep, {})
32560
+ t
32561
+ )),
32562
+ on("help") && /* @__PURE__ */ jsx2(
32563
+ "button",
32564
+ {
32565
+ ref: helpTrigger,
32566
+ type: "button",
32567
+ title: `Help and keyboard shortcuts (${shortcut("/")})`,
32568
+ "aria-haspopup": "dialog",
32569
+ "aria-expanded": helpOpen,
32570
+ "data-dxw-help-trigger": "",
32571
+ onMouseDown: (event) => event.preventDefault(),
32572
+ onClick: () => setHelpOpen(true),
32573
+ style: {
32574
+ border: "none",
32575
+ background: "transparent",
32576
+ color: T.fg,
32577
+ font: "600 12.5px system-ui, sans-serif",
32578
+ padding: "5px 10px",
32579
+ borderRadius: 6,
32580
+ cursor: "pointer"
32581
+ },
32582
+ children: "Help"
32583
+ }
32584
+ )
32585
+ ] }),
32586
+ /* @__PURE__ */ jsx2(Sep, {})
31605
32587
  ] }),
31606
32588
  (mode === "simple" || tab === "home") && renderHome(),
31607
- mode === "advanced" && tab === "insert" && /* @__PURE__ */ jsxs(Fragment2, { children: [
31608
- on("coverPage") && /* @__PURE__ */ jsx(CoverPageMenu, { api }),
31609
- on("table") && /* @__PURE__ */ jsx(TableMenu, { api }),
31610
- on("image") && /* @__PURE__ */ jsx(Btn, { label: /* @__PURE__ */ jsx(ImageIcon, {}), title: "Insert image", onClick: () => imageInput.current?.click() }),
31611
- on("icon") && /* @__PURE__ */ jsx(Btn, { label: "Icons", title: "Insert SVG icon", onClick: () => iconInput.current?.click() }),
31612
- on("screenshot") && /* @__PURE__ */ jsx(ScreenshotButton, { api }),
31613
- tier === 0 ? /* @__PURE__ */ jsxs(Fragment2, { children: [
31614
- on("model3D") && /* @__PURE__ */ jsx(Btn, { label: "3D Models", title: "Insert a GLB 3D model", onClick: () => modelInput.current?.click() }),
31615
- on("smartArt") && /* @__PURE__ */ jsx(SmartArtMenu, { api }),
31616
- on("chart") && /* @__PURE__ */ jsx(ChartMenu, { api }),
31617
- on("media") && /* @__PURE__ */ jsx(MediaMenu, { api }),
31618
- on("shape") && /* @__PURE__ */ jsx(ShapeMenu, { api }),
31619
- on("textBox") && /* @__PURE__ */ jsx(TextBoxMenu, { api }),
31620
- on("wordArt") && /* @__PURE__ */ jsx(WordArtMenu, { api }),
31621
- on("link") && /* @__PURE__ */ jsx(LinkMenu, { api }),
31622
- on("comment") && /* @__PURE__ */ jsx(CommentMenu, { api }),
31623
- on("footnote") && /* @__PURE__ */ jsx(FootnoteMenu, { api }),
31624
- on("bookmark") && /* @__PURE__ */ jsx(BookmarkMenu, { api }),
31625
- on("crossReference") && /* @__PURE__ */ jsx(CrossReferenceMenu, { api }),
31626
- on("headerFooter") && /* @__PURE__ */ jsxs(Fragment2, { children: [
31627
- /* @__PURE__ */ jsx(Btn, { label: "Header", title: "Edit header", onClick: () => api?.openHeaderFooter("header") }),
31628
- /* @__PURE__ */ jsx(Btn, { label: "Footer", title: "Edit footer", onClick: () => api?.openHeaderFooter("footer") })
32589
+ mode === "advanced" && tab === "insert" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32590
+ on("coverPage") && /* @__PURE__ */ jsx2(CoverPageMenu, { api }),
32591
+ on("table") && /* @__PURE__ */ jsx2(TableMenu, { api }),
32592
+ on("image") && /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2(ImageIcon, {}), title: "Insert image", onClick: () => imageInput.current?.click() }),
32593
+ on("icon") && /* @__PURE__ */ jsx2(Btn, { label: "Icons", title: "Insert SVG icon", onClick: () => iconInput.current?.click() }),
32594
+ on("screenshot") && /* @__PURE__ */ jsx2(ScreenshotButton, { api }),
32595
+ tier === 0 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
32596
+ on("model3D") && /* @__PURE__ */ jsx2(Btn, { label: "3D Models", title: "Insert a GLB 3D model", onClick: () => modelInput.current?.click() }),
32597
+ on("smartArt") && /* @__PURE__ */ jsx2(SmartArtMenu, { api }),
32598
+ on("chart") && /* @__PURE__ */ jsx2(ChartMenu, { api }),
32599
+ on("media") && /* @__PURE__ */ jsx2(MediaMenu, { api }),
32600
+ on("shape") && /* @__PURE__ */ jsx2(ShapeMenu, { api }),
32601
+ on("textBox") && /* @__PURE__ */ jsx2(TextBoxMenu, { api }),
32602
+ on("wordArt") && /* @__PURE__ */ jsx2(WordArtMenu, { api }),
32603
+ on("link") && /* @__PURE__ */ jsx2(LinkMenu, { api }),
32604
+ on("comment") && /* @__PURE__ */ jsx2(CommentMenu, { api }),
32605
+ on("footnote") && /* @__PURE__ */ jsx2(FootnoteMenu, { api }),
32606
+ on("bookmark") && /* @__PURE__ */ jsx2(BookmarkMenu, { api }),
32607
+ on("crossReference") && /* @__PURE__ */ jsx2(CrossReferenceMenu, { api }),
32608
+ on("headerFooter") && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32609
+ /* @__PURE__ */ jsx2(Btn, { label: "Header", title: "Edit header", onClick: () => api?.openHeaderFooter("header") }),
32610
+ /* @__PURE__ */ jsx2(Btn, { label: "Footer", title: "Edit footer", onClick: () => api?.openHeaderFooter("footer") })
31629
32611
  ] }),
31630
- /* @__PURE__ */ jsx(Sep, {}),
31631
- on("pageNumber") && /* @__PURE__ */ jsx(
32612
+ /* @__PURE__ */ jsx2(Sep, {}),
32613
+ on("pageNumber") && /* @__PURE__ */ jsx2(
31632
32614
  ActionMenu,
31633
32615
  {
31634
32616
  label: "Page number",
@@ -31641,9 +32623,9 @@ function DocxToolbar({
31641
32623
  }
31642
32624
  }
31643
32625
  ),
31644
- on("break") && /* @__PURE__ */ jsxs(Fragment2, { children: [
31645
- /* @__PURE__ */ jsx(Btn, { label: "Blank page", title: "Insert blank page", onClick: () => api?.insertBlankPage() }),
31646
- /* @__PURE__ */ jsx(
32626
+ on("break") && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32627
+ /* @__PURE__ */ jsx2(Btn, { label: "Blank page", title: "Insert blank page", onClick: () => api?.insertBlankPage() }),
32628
+ /* @__PURE__ */ jsx2(
31647
32629
  ActionMenu,
31648
32630
  {
31649
32631
  label: "Break",
@@ -31662,7 +32644,7 @@ function DocxToolbar({
31662
32644
  }
31663
32645
  )
31664
32646
  ] }),
31665
- on("dateTime") && /* @__PURE__ */ jsx(
32647
+ on("dateTime") && /* @__PURE__ */ jsx2(
31666
32648
  ActionMenu,
31667
32649
  {
31668
32650
  label: "Date & time",
@@ -31681,7 +32663,7 @@ function DocxToolbar({
31681
32663
  }
31682
32664
  }
31683
32665
  ),
31684
- on("field") && /* @__PURE__ */ jsx(
32666
+ on("field") && /* @__PURE__ */ jsx2(
31685
32667
  ActionMenu,
31686
32668
  {
31687
32669
  label: "Field",
@@ -31691,9 +32673,9 @@ function DocxToolbar({
31691
32673
  onPick: (value) => api?.insertField(`${value} \\* MERGEFORMAT`)
31692
32674
  }
31693
32675
  ),
31694
- on("equation") && /* @__PURE__ */ jsx(EquationMenu, { api }),
31695
- on("symbol") && /* @__PURE__ */ jsx(SymbolMenu, { api }),
31696
- on("dropCap") && /* @__PURE__ */ jsx(
32676
+ on("equation") && /* @__PURE__ */ jsx2(EquationMenu, { api }),
32677
+ on("symbol") && /* @__PURE__ */ jsx2(SymbolMenu, { api }),
32678
+ on("dropCap") && /* @__PURE__ */ jsx2(
31697
32679
  ActionMenu,
31698
32680
  {
31699
32681
  label: "Drop cap",
@@ -31703,25 +32685,25 @@ function DocxToolbar({
31703
32685
  onPick: (value) => api?.setDropCap(value === "none" ? null : value)
31704
32686
  }
31705
32687
  ),
31706
- on("object") && /* @__PURE__ */ jsx(Btn, { label: "Object", title: "Embed a file in this document", onClick: () => objectInput.current?.click() })
31707
- ] }) : /* @__PURE__ */ jsxs(OverflowMenu, { children: [
31708
- on("model3D") && /* @__PURE__ */ jsx(Btn, { label: "3D Models", title: "Insert a GLB 3D model", onClick: () => modelInput.current?.click() }),
31709
- on("smartArt") && /* @__PURE__ */ jsx(SmartArtMenu, { api }),
31710
- on("chart") && /* @__PURE__ */ jsx(ChartMenu, { api }),
31711
- on("media") && /* @__PURE__ */ jsx(MediaMenu, { api }),
31712
- on("shape") && /* @__PURE__ */ jsx(ShapeMenu, { api }),
31713
- on("textBox") && /* @__PURE__ */ jsx(TextBoxMenu, { api }),
31714
- on("wordArt") && /* @__PURE__ */ jsx(WordArtMenu, { api }),
31715
- on("link") && /* @__PURE__ */ jsx(LinkMenu, { api }),
31716
- on("comment") && /* @__PURE__ */ jsx(CommentMenu, { api }),
31717
- on("footnote") && /* @__PURE__ */ jsx(FootnoteMenu, { api }),
31718
- on("bookmark") && /* @__PURE__ */ jsx(BookmarkMenu, { api }),
31719
- on("crossReference") && /* @__PURE__ */ jsx(CrossReferenceMenu, { api }),
31720
- on("headerFooter") && /* @__PURE__ */ jsxs(Fragment2, { children: [
31721
- /* @__PURE__ */ jsx(Btn, { label: "Header", title: "Edit header", onClick: () => api?.openHeaderFooter("header") }),
31722
- /* @__PURE__ */ jsx(Btn, { label: "Footer", title: "Edit footer", onClick: () => api?.openHeaderFooter("footer") })
32688
+ on("object") && /* @__PURE__ */ jsx2(Btn, { label: "Object", title: "Embed a file in this document", onClick: () => objectInput.current?.click() })
32689
+ ] }) : /* @__PURE__ */ jsxs2(OverflowMenu, { children: [
32690
+ on("model3D") && /* @__PURE__ */ jsx2(Btn, { label: "3D Models", title: "Insert a GLB 3D model", onClick: () => modelInput.current?.click() }),
32691
+ on("smartArt") && /* @__PURE__ */ jsx2(SmartArtMenu, { api }),
32692
+ on("chart") && /* @__PURE__ */ jsx2(ChartMenu, { api }),
32693
+ on("media") && /* @__PURE__ */ jsx2(MediaMenu, { api }),
32694
+ on("shape") && /* @__PURE__ */ jsx2(ShapeMenu, { api }),
32695
+ on("textBox") && /* @__PURE__ */ jsx2(TextBoxMenu, { api }),
32696
+ on("wordArt") && /* @__PURE__ */ jsx2(WordArtMenu, { api }),
32697
+ on("link") && /* @__PURE__ */ jsx2(LinkMenu, { api }),
32698
+ on("comment") && /* @__PURE__ */ jsx2(CommentMenu, { api }),
32699
+ on("footnote") && /* @__PURE__ */ jsx2(FootnoteMenu, { api }),
32700
+ on("bookmark") && /* @__PURE__ */ jsx2(BookmarkMenu, { api }),
32701
+ on("crossReference") && /* @__PURE__ */ jsx2(CrossReferenceMenu, { api }),
32702
+ on("headerFooter") && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32703
+ /* @__PURE__ */ jsx2(Btn, { label: "Header", title: "Edit header", onClick: () => api?.openHeaderFooter("header") }),
32704
+ /* @__PURE__ */ jsx2(Btn, { label: "Footer", title: "Edit footer", onClick: () => api?.openHeaderFooter("footer") })
31723
32705
  ] }),
31724
- on("pageNumber") && /* @__PURE__ */ jsx(
32706
+ on("pageNumber") && /* @__PURE__ */ jsx2(
31725
32707
  ActionMenu,
31726
32708
  {
31727
32709
  label: "Page number",
@@ -31734,9 +32716,9 @@ function DocxToolbar({
31734
32716
  }
31735
32717
  }
31736
32718
  ),
31737
- on("break") && /* @__PURE__ */ jsxs(Fragment2, { children: [
31738
- /* @__PURE__ */ jsx(Btn, { label: "Blank page", title: "Insert blank page", onClick: () => api?.insertBlankPage() }),
31739
- /* @__PURE__ */ jsx(
32719
+ on("break") && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32720
+ /* @__PURE__ */ jsx2(Btn, { label: "Blank page", title: "Insert blank page", onClick: () => api?.insertBlankPage() }),
32721
+ /* @__PURE__ */ jsx2(
31740
32722
  ActionMenu,
31741
32723
  {
31742
32724
  label: "Break",
@@ -31755,7 +32737,7 @@ function DocxToolbar({
31755
32737
  }
31756
32738
  )
31757
32739
  ] }),
31758
- on("dateTime") && /* @__PURE__ */ jsx(
32740
+ on("dateTime") && /* @__PURE__ */ jsx2(
31759
32741
  ActionMenu,
31760
32742
  {
31761
32743
  label: "Date & time",
@@ -31774,15 +32756,15 @@ function DocxToolbar({
31774
32756
  }
31775
32757
  }
31776
32758
  ),
31777
- on("field") && /* @__PURE__ */ jsx(ActionMenu, { label: "Field", title: "Insert a Word field", width: 68, groups: [{ items: [["PAGE", "Current page"], ["NUMPAGES", "Number of pages"], ["DATE", "Current date"], ["TIME", "Current time"]] }], onPick: (value) => api?.insertField(`${value} \\* MERGEFORMAT`) }),
31778
- on("equation") && /* @__PURE__ */ jsx(EquationMenu, { api }),
31779
- on("symbol") && /* @__PURE__ */ jsx(SymbolMenu, { api }),
31780
- on("dropCap") && /* @__PURE__ */ jsx(ActionMenu, { label: "Drop cap", title: "Drop cap", width: 84, groups: [{ items: [["drop", "Dropped"], ["margin", "In margin"], ["none", "None"]] }], onPick: (value) => api?.setDropCap(value === "none" ? null : value) }),
31781
- on("object") && /* @__PURE__ */ jsx(Btn, { label: "Object", title: "Embed a file in this document", onClick: () => objectInput.current?.click() })
32759
+ on("field") && /* @__PURE__ */ jsx2(ActionMenu, { label: "Field", title: "Insert a Word field", width: 68, groups: [{ items: [["PAGE", "Current page"], ["NUMPAGES", "Number of pages"], ["DATE", "Current date"], ["TIME", "Current time"]] }], onPick: (value) => api?.insertField(`${value} \\* MERGEFORMAT`) }),
32760
+ on("equation") && /* @__PURE__ */ jsx2(EquationMenu, { api }),
32761
+ on("symbol") && /* @__PURE__ */ jsx2(SymbolMenu, { api }),
32762
+ on("dropCap") && /* @__PURE__ */ jsx2(ActionMenu, { label: "Drop cap", title: "Drop cap", width: 84, groups: [{ items: [["drop", "Dropped"], ["margin", "In margin"], ["none", "None"]] }], onPick: (value) => api?.setDropCap(value === "none" ? null : value) }),
32763
+ on("object") && /* @__PURE__ */ jsx2(Btn, { label: "Object", title: "Embed a file in this document", onClick: () => objectInput.current?.click() })
31782
32764
  ] })
31783
32765
  ] }),
31784
- mode === "advanced" && tab === "draw" && on("drawing") && /* @__PURE__ */ jsx(DrawTab, { api }),
31785
- /* @__PURE__ */ jsx(
32766
+ mode === "advanced" && tab === "draw" && on("drawing") && /* @__PURE__ */ jsx2(DrawTab, { api }),
32767
+ /* @__PURE__ */ jsx2(
31786
32768
  "input",
31787
32769
  {
31788
32770
  ref: imageInput,
@@ -31796,7 +32778,7 @@ function DocxToolbar({
31796
32778
  }
31797
32779
  }
31798
32780
  ),
31799
- /* @__PURE__ */ jsx(
32781
+ /* @__PURE__ */ jsx2(
31800
32782
  "input",
31801
32783
  {
31802
32784
  ref: iconInput,
@@ -31810,7 +32792,7 @@ function DocxToolbar({
31810
32792
  }
31811
32793
  }
31812
32794
  ),
31813
- /* @__PURE__ */ jsx(
32795
+ /* @__PURE__ */ jsx2(
31814
32796
  "input",
31815
32797
  {
31816
32798
  ref: modelInput,
@@ -31825,7 +32807,7 @@ function DocxToolbar({
31825
32807
  }
31826
32808
  }
31827
32809
  ),
31828
- /* @__PURE__ */ jsx(
32810
+ /* @__PURE__ */ jsx2(
31829
32811
  "input",
31830
32812
  {
31831
32813
  ref: objectInput,
@@ -31839,18 +32821,20 @@ function DocxToolbar({
31839
32821
  }
31840
32822
  }
31841
32823
  ),
31842
- mode === "advanced" && tab === "layout" && on("layout") && /* @__PURE__ */ jsx(LayoutTab, { api, showArrange: on("arrange") }),
31843
- on("download") && onSave && /* @__PURE__ */ jsxs(Fragment2, { children: [
31844
- /* @__PURE__ */ jsx("span", { style: { flex: 1 } }),
31845
- /* @__PURE__ */ jsx(Btn, { label: "Download", title: "Save edited .docx", onClick: () => api && onSave(api.save()) })
31846
- ] })
32824
+ mode === "advanced" && tab === "layout" && on("layout") && /* @__PURE__ */ jsx2(LayoutTab, { api, showArrange: on("arrange") }),
32825
+ mode === "simple" && on("help") && /* @__PURE__ */ jsx2("span", { style: { marginLeft: "auto" }, children: /* @__PURE__ */ jsx2(Btn, { buttonRef: helpTrigger, label: "Help", title: `Help and keyboard shortcuts (${shortcut("/")})`, onClick: () => setHelpOpen(true) }) }),
32826
+ on("download") && onSave && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32827
+ /* @__PURE__ */ jsx2("span", { style: { flex: 1 } }),
32828
+ /* @__PURE__ */ jsx2(Btn, { label: "Download", title: "Save edited .docx", onClick: () => api && onSave(api.save()) })
32829
+ ] }),
32830
+ /* @__PURE__ */ jsx2(HelpGuide, { open: helpOpen, onClose: closeHelp, returnFocus: helpTrigger })
31847
32831
  ]
31848
32832
  }
31849
32833
  );
31850
32834
  }
31851
32835
 
31852
32836
  // src/index.tsx
31853
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
32837
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
31854
32838
  async function objectPoster(title, subtitle, glyph) {
31855
32839
  const canvas = document.createElement("canvas");
31856
32840
  canvas.width = 640;
@@ -31894,6 +32878,7 @@ function DocxView({
31894
32878
  className,
31895
32879
  style,
31896
32880
  onLoad,
32881
+ onPageCountChange,
31897
32882
  onReady,
31898
32883
  onError,
31899
32884
  commentAuthor = "You",
@@ -31901,17 +32886,19 @@ function DocxView({
31901
32886
  revisions = "final",
31902
32887
  onMissingFonts
31903
32888
  }) {
31904
- const containerRef = useRef2(null);
31905
- const [error, setError] = useState2(null);
31906
- const [layoutBusy, setLayoutBusy] = useState2(false);
31907
- const [fitZoom, setFitZoom] = useState2(null);
31908
- const [narrow, setNarrow] = useState2(false);
31909
- const basePageWidthRef = useRef2(816);
32889
+ const containerRef = useRef3(null);
32890
+ const [error, setError] = useState3(null);
32891
+ const [layoutBusy, setLayoutBusy] = useState3(false);
32892
+ const [fitZoom, setFitZoom] = useState3(null);
32893
+ const [narrow, setNarrow] = useState3(false);
32894
+ const basePageWidthRef = useRef3(816);
31910
32895
  const effectiveZoom = fitWidth && fitZoom != null ? Math.min(zoom, fitZoom) : zoom;
31911
- const effZoomRef = useRef2(effectiveZoom);
32896
+ const effZoomRef = useRef3(effectiveZoom);
31912
32897
  effZoomRef.current = effectiveZoom;
31913
- const applyZoomRef = useRef2(null);
31914
- useEffect2(() => {
32898
+ const applyZoomRef = useRef3(null);
32899
+ const onPageCountChangeRef = useRef3(onPageCountChange);
32900
+ onPageCountChangeRef.current = onPageCountChange;
32901
+ useEffect3(() => {
31915
32902
  if (editable && typeof window !== "undefined" && !customElements.get("model-viewer")) {
31916
32903
  void import("@google/model-viewer");
31917
32904
  }
@@ -31925,7 +32912,7 @@ function DocxView({
31925
32912
  setFitZoom((cw - gutter) / basePageWidthRef.current);
31926
32913
  setNarrow(cw <= narrowWidth);
31927
32914
  }, [narrowWidth]);
31928
- useEffect2(() => {
32915
+ useEffect3(() => {
31929
32916
  const c = containerRef.current;
31930
32917
  if (!c || typeof ResizeObserver === "undefined") return;
31931
32918
  const ro = new ResizeObserver(() => recomputeFit());
@@ -31933,13 +32920,13 @@ function DocxView({
31933
32920
  recomputeFit();
31934
32921
  return () => ro.disconnect();
31935
32922
  }, [recomputeFit]);
31936
- useEffect2(() => {
32923
+ useEffect3(() => {
31937
32924
  applyZoomRef.current?.(effectiveZoom);
31938
32925
  }, [effectiveZoom]);
31939
- useEffect2(() => {
32926
+ useEffect3(() => {
31940
32927
  containerRef.current?.classList.toggle("dxw-narrow", narrow);
31941
32928
  }, [narrow]);
31942
- useEffect2(() => {
32929
+ useEffect3(() => {
31943
32930
  const c = containerRef.current;
31944
32931
  if (!c) return;
31945
32932
  const onTap = (e) => {
@@ -31959,17 +32946,17 @@ function DocxView({
31959
32946
  c.addEventListener("click", onTap);
31960
32947
  return () => c.removeEventListener("click", onTap);
31961
32948
  }, []);
31962
- const [hfMode, setHfMode] = useState2(false);
31963
- const apiRef = useRef2(null);
31964
- const docCacheRef = useRef2(null);
31965
- useEffect2(() => {
32949
+ const [hfMode, setHfMode] = useState3(false);
32950
+ const apiRef = useRef3(null);
32951
+ const docCacheRef = useRef3(null);
32952
+ useEffect3(() => {
31966
32953
  const c = containerRef.current;
31967
32954
  if (!c) return;
31968
32955
  const onHf = (e) => setHfMode(!!e.detail?.active);
31969
32956
  c.addEventListener("dxw-hfmode", onHf);
31970
32957
  return () => c.removeEventListener("dxw-hfmode", onHf);
31971
32958
  }, []);
31972
- useEffect2(() => {
32959
+ useEffect3(() => {
31973
32960
  let cancelled = false;
31974
32961
  let handle = null;
31975
32962
  let editor = null;
@@ -32033,6 +33020,7 @@ function DocxView({
32033
33020
  totalPages: layout.totalPages
32034
33021
  };
32035
33022
  }
33023
+ if (pages !== layout.totalPages) onPageCountChangeRef.current?.(layout.totalPages);
32036
33024
  pages = layout.totalPages;
32037
33025
  return layout.totalPages;
32038
33026
  };
@@ -32446,6 +33434,7 @@ function DocxView({
32446
33434
  setDrawingTool: (tool) => editor?.setDrawingTool(tool),
32447
33435
  getDrawingTool: () => editor?.getDrawingTool() ?? null,
32448
33436
  arrangeObject: (action) => editor?.arrangeSelectedObject(action) ?? false,
33437
+ hasSelectedObject: () => editor?.hasSelectedObject() ?? false,
32449
33438
  addComment: (text) => {
32450
33439
  const segs = editor?.getSelectionSegments() ?? [];
32451
33440
  const segments = segs.length > 0 ? segs : handle ? selectionToSegments(handle.bindings) : [];
@@ -32561,7 +33550,7 @@ function DocxView({
32561
33550
  history.checkpoint();
32562
33551
  const done = kind === "page" || kind === "column" ? insertBreakAt(doc, target.t, target.offset, kind) : insertSectionBreak(doc, target.t, kind === "sectionNextPage" ? "nextPage" : "continuous");
32563
33552
  if (done) pages = rerender(doc);
32564
- return done;
33553
+ return !!done;
32565
33554
  },
32566
33555
  insertBlankPage: () => {
32567
33556
  const target = insertionTarget();
@@ -32586,6 +33575,10 @@ function DocxView({
32586
33575
  }
32587
33576
  if (setPageLayout(doc, patch, target)) pages = rerender(doc);
32588
33577
  },
33578
+ getSectionContext: () => {
33579
+ const t = editor?.getCaretTarget()?.t ?? editor?.getSelectionSegments()?.[0]?.t;
33580
+ return t ? sectionContextAt(doc, t) : null;
33581
+ },
32589
33582
  setLineNumbering: (patch, scope) => {
32590
33583
  history.checkpoint();
32591
33584
  let target;
@@ -32779,7 +33772,7 @@ function DocxView({
32779
33772
  handle = null;
32780
33773
  };
32781
33774
  }, [source, editable, commentAuthor, showComments, revisions]);
32782
- const hotBtn = (label, title, onClick) => /* @__PURE__ */ jsx2(
33775
+ const hotBtn = (label, title, onClick) => /* @__PURE__ */ jsx3(
32783
33776
  "button",
32784
33777
  {
32785
33778
  title,
@@ -32798,71 +33791,105 @@ function DocxView({
32798
33791
  children: label
32799
33792
  }
32800
33793
  );
32801
- return /* @__PURE__ */ jsxs2("div", { style: { position: "relative", ...style?.height ? { height: style.height } : {} }, children: [
32802
- /* @__PURE__ */ jsx2(
32803
- "div",
32804
- {
32805
- ref: containerRef,
32806
- className,
32807
- style: { background: "var(--dxw-canvas-bg, #e8eaed)", overflow: "auto", height: "100%", ...style },
32808
- children: error && /* @__PURE__ */ jsxs2("div", { style: { padding: 16, color: "#b00020", fontFamily: "system-ui" }, children: [
32809
- "Failed to render document: ",
32810
- error.message
32811
- ] })
32812
- }
32813
- ),
32814
- layoutBusy && /* @__PURE__ */ jsx2(
32815
- "div",
32816
- {
32817
- "data-dxw-layout-status": "",
32818
- "aria-live": "polite",
32819
- style: {
32820
- position: "absolute",
32821
- top: 10,
32822
- right: 12,
32823
- zIndex: 45,
32824
- padding: "5px 10px",
32825
- borderRadius: 14,
32826
- background: "rgba(32,33,36,.88)",
32827
- color: "#fff",
32828
- font: "12px system-ui,sans-serif",
32829
- pointerEvents: "none"
32830
- },
32831
- children: "Repaginating\u2026"
32832
- }
32833
- ),
32834
- editable && hfMode && /* @__PURE__ */ jsxs2(
32835
- "div",
32836
- {
32837
- "data-dxw-hf-hotbar": "",
32838
- style: {
32839
- position: "absolute",
32840
- top: 10,
32841
- left: "50%",
32842
- transform: "translateX(-50%)",
32843
- display: "flex",
32844
- gap: 6,
32845
- zIndex: 40,
32846
- background: "rgba(249,251,253,.96)",
32847
- border: "1px solid #dadce0",
32848
- borderRadius: 18,
32849
- padding: "5px 8px",
32850
- boxShadow: "0 2px 10px rgba(0,0,0,.15)",
32851
- alignItems: "center"
32852
- },
32853
- children: [
32854
- /* @__PURE__ */ jsx2("span", { style: { font: "600 11.5px system-ui, sans-serif", color: "#5f6368", padding: "0 4px" }, children: "Header & footer \xB7 repeats on pages" }),
32855
- hotBtn("Line", "Insert a reusable line in the repeating page layer", () => apiRef.current?.insertShape("line")),
32856
- hotBtn("Page number", "Insert a dynamic page number at the caret", () => apiRef.current?.insertPageNumber("page")),
32857
- hotBtn("Page X of Y", "Insert 'Page X of Y' at the caret", () => apiRef.current?.insertPageNumber("pageOfTotal")),
32858
- hotBtn("Close", "Return to the document body", () => {
32859
- apiRef.current?.closeHeaderFooter();
32860
- setHfMode(false);
32861
- })
32862
- ]
32863
- }
32864
- )
32865
- ] });
33794
+ return /* @__PURE__ */ jsxs3(
33795
+ "div",
33796
+ {
33797
+ style: {
33798
+ position: "relative",
33799
+ display: "flex",
33800
+ flexDirection: "column",
33801
+ minHeight: 0,
33802
+ ...style?.height ? { height: style.height } : {}
33803
+ },
33804
+ children: [
33805
+ editable && hfMode && /* @__PURE__ */ jsx3(
33806
+ "div",
33807
+ {
33808
+ "data-dxw-editor-context-row": "",
33809
+ style: {
33810
+ flex: "0 0 52px",
33811
+ display: "flex",
33812
+ alignItems: "center",
33813
+ justifyContent: "center",
33814
+ background: "var(--dxw-canvas-bg, #e8eaed)",
33815
+ position: "relative",
33816
+ zIndex: 40,
33817
+ pointerEvents: "none"
33818
+ },
33819
+ children: /* @__PURE__ */ jsxs3(
33820
+ "div",
33821
+ {
33822
+ "data-dxw-hf-hotbar": "",
33823
+ style: {
33824
+ display: "flex",
33825
+ gap: 6,
33826
+ background: "rgba(249,251,253,.96)",
33827
+ border: "1px solid #dadce0",
33828
+ borderRadius: 18,
33829
+ padding: "5px 8px",
33830
+ boxShadow: "0 2px 10px rgba(0,0,0,.15)",
33831
+ alignItems: "center",
33832
+ pointerEvents: "auto"
33833
+ },
33834
+ children: [
33835
+ /* @__PURE__ */ jsx3("span", { style: { font: "600 11.5px system-ui, sans-serif", color: "#5f6368", padding: "0 4px" }, children: "Header & footer \xB7 repeats on pages" }),
33836
+ hotBtn("Page number", "Insert a dynamic page number at the caret", () => apiRef.current?.insertPageNumber("page")),
33837
+ hotBtn("Page X of Y", "Insert 'Page X of Y' at the caret", () => apiRef.current?.insertPageNumber("pageOfTotal")),
33838
+ hotBtn("Close", "Return to the document body", () => {
33839
+ apiRef.current?.closeHeaderFooter();
33840
+ setHfMode(false);
33841
+ })
33842
+ ]
33843
+ }
33844
+ )
33845
+ }
33846
+ ),
33847
+ /* @__PURE__ */ jsx3(
33848
+ "div",
33849
+ {
33850
+ ref: containerRef,
33851
+ className,
33852
+ style: {
33853
+ background: "var(--dxw-canvas-bg, #e8eaed)",
33854
+ overflow: "auto",
33855
+ height: "100%",
33856
+ ...style,
33857
+ ...editable ? {
33858
+ height: "auto",
33859
+ flex: "1 1 auto",
33860
+ minHeight: 0,
33861
+ boxSizing: "border-box"
33862
+ } : {}
33863
+ },
33864
+ children: error && /* @__PURE__ */ jsxs3("div", { style: { padding: 16, color: "#b00020", fontFamily: "system-ui" }, children: [
33865
+ "Failed to render document: ",
33866
+ error.message
33867
+ ] })
33868
+ }
33869
+ ),
33870
+ layoutBusy && /* @__PURE__ */ jsx3(
33871
+ "div",
33872
+ {
33873
+ "data-dxw-layout-status": "",
33874
+ "aria-live": "polite",
33875
+ style: {
33876
+ position: "absolute",
33877
+ top: editable ? 62 : 10,
33878
+ right: 12,
33879
+ zIndex: 45,
33880
+ padding: "5px 10px",
33881
+ borderRadius: 14,
33882
+ background: "rgba(32,33,36,.88)",
33883
+ color: "#fff",
33884
+ font: "12px system-ui,sans-serif",
33885
+ pointerEvents: "none"
33886
+ },
33887
+ children: "Repaginating\u2026"
33888
+ }
33889
+ )
33890
+ ]
33891
+ }
33892
+ );
32866
33893
  }
32867
33894
  export {
32868
33895
  DocxDocument,