wordinweb 0.1.13 → 0.1.15

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);
@@ -6906,7 +6906,95 @@ var DocxDocument = class _DocxDocument {
6906
6906
  const xml = serializeXml(root, true);
6907
6907
  if (xml !== this.originalModeledXml.get(part)) files[part] = strToU82(xml);
6908
6908
  }
6909
+ /**
6910
+ * Canonicalize producer shorthand that Google Docs otherwise interprets as
6911
+ * a fixed, few-twip table. Word treats `tblW="100%"` plus a placeholder
6912
+ * grid as autofit; Google needs the standard pct value and a usable cached
6913
+ * grid. The cached widths follow the same content-dominant shape and do not
6914
+ * change Word's autofit result.
6915
+ */
6916
+ normalizePercentageTableGrids() {
6917
+ const setAttr = (element, name, value) => {
6918
+ const key = Object.keys(element.attrs).find((item) => localName(item) === name);
6919
+ element.attrs[key ?? `${element.name.includes(":") ? element.name.split(":")[0] + ":" : ""}${name}`] = value;
6920
+ };
6921
+ const textLength = (blocks) => {
6922
+ let length = 0;
6923
+ for (const block of blocks) {
6924
+ if (block.type === "table") {
6925
+ for (const row of block.rows) {
6926
+ for (const cell of row.cells) length += textLength(cell.blocks);
6927
+ }
6928
+ continue;
6929
+ }
6930
+ for (const item of block.children) {
6931
+ const runs = item.type === "run" ? [item] : item.runs;
6932
+ for (const run of runs) {
6933
+ for (const content of run.content) {
6934
+ if (content.kind === "text") length += content.text.length;
6935
+ else if (content.kind === "tab") length += 4;
6936
+ }
6937
+ }
6938
+ }
6939
+ }
6940
+ return length;
6941
+ };
6942
+ const normalize = (table2, available) => {
6943
+ const source = table2.src;
6944
+ if (!source) return;
6945
+ const tableProps = child(source, "tblPr");
6946
+ const tableWidth = child(tableProps, "tblW");
6947
+ const rawWidth = attr(tableWidth, "w")?.trim();
6948
+ if (attr(tableWidth, "type") !== "pct" || !rawWidth?.endsWith("%")) return;
6949
+ const percent = Number.parseFloat(rawWidth);
6950
+ if (!Number.isFinite(percent) || percent <= 0) return;
6951
+ setAttr(tableWidth, "w", String(Math.round(percent * 50)));
6952
+ const grid = child(source, "tblGrid");
6953
+ const columns = children(grid, "gridCol");
6954
+ if (columns.length === 0) return;
6955
+ const target = Math.round(pxToTwips(available) * percent / 100);
6956
+ const authoredTotal = columns.reduce((sum2, column) => sum2 + (intAttr(column, "w") ?? 0), 0);
6957
+ if (target <= 0 || authoredTotal >= target * 0.1) return;
6958
+ const floor = 600;
6959
+ const widths = new Array(columns.length).fill(floor);
6960
+ for (const row of table2.rows) {
6961
+ let column = 0;
6962
+ for (const cell of row.cells) {
6963
+ const span = Math.max(1, Math.min(cell.props.gridSpan, columns.length - column));
6964
+ const demand = Math.max(floor * span, textLength(cell.blocks) * 100 + 300);
6965
+ for (let offset = 0; offset < span; offset++) {
6966
+ widths[column + offset] = Math.max(widths[column + offset], demand / span);
6967
+ }
6968
+ column += cell.props.gridSpan;
6969
+ if (column >= columns.length) break;
6970
+ }
6971
+ }
6972
+ const dominant = widths.indexOf(Math.max(...widths));
6973
+ const total = widths.reduce((sum2, width) => sum2 + width, 0);
6974
+ if (total < target) {
6975
+ widths[dominant] += target - total;
6976
+ } else if (total > target) {
6977
+ const slack = widths.reduce((sum2, width) => sum2 + Math.max(0, width - floor), 0);
6978
+ const scale = slack > 0 ? Math.min(1, (total - target) / slack) : 0;
6979
+ for (let index = 0; index < widths.length; index++) {
6980
+ widths[index] -= Math.max(0, widths[index] - floor) * scale;
6981
+ }
6982
+ }
6983
+ const rounded = widths.map(Math.round);
6984
+ rounded[dominant] += target - rounded.reduce((sum2, width) => sum2 + width, 0);
6985
+ columns.forEach((column, index) => setAttr(column, "w", String(rounded[index])));
6986
+ };
6987
+ for (const section of this.sections) {
6988
+ const contentWidth = section.props.pageWidth - section.props.marginLeft - section.props.marginRight - section.props.gutter;
6989
+ const columnCount = Math.max(1, section.props.columns.count);
6990
+ const available = section.props.columns.widths?.[0] ?? (contentWidth - section.props.columns.space * (columnCount - 1)) / columnCount;
6991
+ for (const block of section.blocks) {
6992
+ if (block.type === "table") normalize(block, available);
6993
+ }
6994
+ }
6995
+ }
6909
6996
  save() {
6997
+ this.normalizePercentageTableGrids();
6910
6998
  const files = { ...this.pkg.raw() };
6911
6999
  if (files["docProps/custom.xml"] && this.contentTypesRoot && !this.contentTypesRoot.children.some(
6912
7000
  (item) => localName(item.name) === "Override" && item.attrs.PartName === "/docProps/custom.xml"
@@ -11327,7 +11415,12 @@ function laidOutPage(p) {
11327
11415
  items: p.items,
11328
11416
  bodyTop: p.bodyTop,
11329
11417
  bodyBottom: p.bodyBottom,
11330
- hfStart: p.hfStart ?? p.items.length
11418
+ hfStart: p.hfStart ?? p.items.length,
11419
+ columnBands: p.bands.map((band) => ({
11420
+ top: band.top,
11421
+ colXs: [...band.colXs],
11422
+ colWidths: [...band.colWidths]
11423
+ }))
11331
11424
  };
11332
11425
  }
11333
11426
  var PAGE_FMT = {
@@ -14961,19 +15054,19 @@ var Engine = class {
14961
15054
  for (const pth of shape.paths) {
14962
15055
  const x = ox + pth.x - fx;
14963
15056
  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 });
15057
+ 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
15058
  }
14966
15059
  for (const l of shape.lines) {
14967
15060
  const x1 = ox + l.x1 - fx;
14968
15061
  const y1 = oy + l.y1 - fy;
14969
15062
  const x2 = ox + l.x2 - fx;
14970
15063
  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 });
15064
+ 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
15065
  }
14973
15066
  for (const img of shape.images) {
14974
15067
  const x = ox + img.x - fx;
14975
15068
  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 });
15069
+ 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
15070
  }
14978
15071
  if (shape.srcDrawing) {
14979
15072
  page.items.push({
@@ -14986,6 +15079,7 @@ var Engine = class {
14986
15079
  anchored: true,
14987
15080
  ink: shape.ink,
14988
15081
  belowText: !shape.behind,
15082
+ behind: shape.behind,
14989
15083
  ...rotate ? { rotate: rotate(ox - fx, oy - fy) } : {},
14990
15084
  z: shape.z
14991
15085
  });
@@ -15125,6 +15219,7 @@ var Engine = class {
15125
15219
  y2,
15126
15220
  border: b,
15127
15221
  ...rotate ? { rotate: rotate(Math.min(x1, x2), Math.min(y1, y2)) } : {},
15222
+ ...behind ? { behind: true } : {},
15128
15223
  ...front ? { front: true } : {},
15129
15224
  z: shape.z
15130
15225
  });
@@ -15145,7 +15240,7 @@ var Engine = class {
15145
15240
  const texts = inner.items.filter((it) => it.kind === "text");
15146
15241
  const str = texts.map((it) => it.text).join("").replace(/\s+/g, " ").trim();
15147
15242
  if (str) {
15148
- if (front && shape.srcDrawing) {
15243
+ if (shape.srcDrawing) {
15149
15244
  page.items.push({
15150
15245
  kind: "drawingHit",
15151
15246
  x: ox - fx,
@@ -15155,8 +15250,9 @@ var Engine = class {
15155
15250
  src: shape.srcDrawing,
15156
15251
  anchored: true,
15157
15252
  belowText: true,
15253
+ ...behind ? { behind: true } : {},
15158
15254
  ...rotate ? { rotate: rotate(ox - fx, oy - fy) } : {},
15159
- z: shape.z
15255
+ z: shape.wordArt ? (shape.z ?? 0) + 1 : shape.z
15160
15256
  });
15161
15257
  }
15162
15258
  const f = texts[0].font;
@@ -15194,7 +15290,7 @@ var Engine = class {
15194
15290
  this.textboxChains.set(shape.chainId, { blocks: storyBlocks, consumedY: cut });
15195
15291
  }
15196
15292
  const independentStory = !!shape.textboxStory && !shape.wordArt;
15197
- if (front && shape.srcDrawing) {
15293
+ if (shape.srcDrawing) {
15198
15294
  page.items.push({
15199
15295
  kind: "drawingHit",
15200
15296
  x: ox - fx,
@@ -15204,9 +15300,10 @@ var Engine = class {
15204
15300
  src: shape.srcDrawing,
15205
15301
  anchored: true,
15206
15302
  belowText: !shape.wordArt,
15303
+ ...behind ? { behind: true } : {},
15207
15304
  ...independentStory ? { textboxStory: true } : {},
15208
15305
  ...rotate ? { rotate: rotate(ox - fx, oy - fy) } : {},
15209
- z: shape.z
15306
+ z: shape.wordArt ? (shape.z ?? 0) + 1 : shape.z
15210
15307
  });
15211
15308
  }
15212
15309
  for (const it of inner.items) {
@@ -15223,7 +15320,7 @@ var Engine = class {
15223
15320
  } else if (rotate && it.kind === "edge") {
15224
15321
  it.rotate = rotate(Math.min(it.x1, it.x2), Math.min(it.y1, it.y2));
15225
15322
  }
15226
- if (behind && (it.kind === "text" || it.kind === "rect")) it.behind = true;
15323
+ if (behind && (it.kind === "text" || it.kind === "rect" || it.kind === "edge" || it.kind === "image" || it.kind === "path" || it.kind === "drawingHit")) it.behind = true;
15227
15324
  if (front && (it.kind === "text" || it.kind === "rect" || it.kind === "edge")) it.front = true;
15228
15325
  if (it.kind === "text" || it.kind === "rect" || it.kind === "edge" || it.kind === "image" || it.kind === "path" || it.kind === "drawingHit") it.z = shape.z;
15229
15326
  page.items.push(it);
@@ -17571,7 +17668,7 @@ function itemEq(a, b, depth) {
17571
17668
  }
17572
17669
  function pageEq(a, b) {
17573
17670
  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) {
17671
+ 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
17672
  return false;
17576
17673
  }
17577
17674
  for (let i = 0; i < a.items.length; i++) {
@@ -17715,6 +17812,7 @@ function renderPageShell(page, zoom, options) {
17715
17812
  }
17716
17813
  el16.dataset.bodyTop = String(page.bodyTop);
17717
17814
  el16.dataset.bodyBottom = String(page.bodyBottom);
17815
+ el16.dataset.columnBands = JSON.stringify(page.columnBands);
17718
17816
  return el16;
17719
17817
  }
17720
17818
  function renderEmptyPageRecord(page, zoom, options) {
@@ -18398,6 +18496,7 @@ function ensureStylesheet() {
18398
18496
  .dxw-body-mode .dxw-page span[data-dxw-hf]:not([data-dxw-textbox-story]),
18399
18497
  .dxw-body-mode .dxw-page a[data-dxw-hf]:not([data-dxw-textbox-story]),
18400
18498
  .dxw-body-mode .dxw-page img[data-dxw-hf] { opacity: .55; }
18499
+ .dxw-body-mode .dxw-page [data-dxw-drawing][data-dxw-hf]:not([data-dxw-textbox-story-object]) { pointer-events: none; }
18401
18500
  .dxw-comment-hl { background: var(--dxw-comment-hl, rgba(255, 200, 90, .38)); }
18402
18501
  .dxw-comment-hl.dxw-hot { background: var(--dxw-comment-hl-active, rgba(255, 170, 0, .55)); }
18403
18502
  .dxw-comment-card {
@@ -18655,7 +18754,7 @@ function renderItem(doc, item, urls, interactive) {
18655
18754
  hit.style.width = `${item.width}px`;
18656
18755
  hit.style.height = `${item.height}px`;
18657
18756
  hit.style.cursor = "move";
18658
- hit.style.zIndex = item.z !== void 0 ? String(item.z) : item.belowText ? "1" : "6";
18757
+ hit.style.zIndex = item.behind ? "-1" : item.z !== void 0 ? String(item.z) : item.belowText ? "1" : "6";
18659
18758
  if (item.rotate) {
18660
18759
  hit.style.transform = `rotate(${item.rotate.deg}deg)`;
18661
18760
  hit.style.transformOrigin = `${item.rotate.ox}px ${item.rotate.oy}px`;
@@ -18969,7 +19068,7 @@ function renderItem(doc, item, urls, interactive) {
18969
19068
  return node;
18970
19069
  }
18971
19070
  case "text":
18972
- return renderText(item);
19071
+ return renderText(item, interactive);
18973
19072
  case "wordart":
18974
19073
  return renderWordArt(item);
18975
19074
  case "warptext":
@@ -19234,7 +19333,7 @@ function renderWarpText(item) {
19234
19333
  svg.appendChild(text);
19235
19334
  return svg;
19236
19335
  }
19237
- function renderText(item) {
19336
+ function renderText(item, interactive) {
19238
19337
  const tag = item.href ? "a" : "span";
19239
19338
  const el16 = document.createElement(tag);
19240
19339
  el16.style.position = "absolute";
@@ -19325,9 +19424,22 @@ function renderText(item) {
19325
19424
  el16.style.cursor = "pointer";
19326
19425
  }
19327
19426
  if (item.href) {
19328
- el16.href = item.href;
19329
- el16.target = "_blank";
19330
- el16.rel = "noreferrer noopener";
19427
+ const anchor = el16;
19428
+ anchor.href = item.href;
19429
+ anchor.target = "_blank";
19430
+ anchor.rel = "noreferrer noopener";
19431
+ anchor.title = item.href;
19432
+ if (interactive) {
19433
+ anchor.addEventListener("mouseup", (event) => {
19434
+ if (event.metaKey || event.ctrlKey) event.stopPropagation();
19435
+ });
19436
+ anchor.addEventListener("click", (event) => {
19437
+ event.preventDefault();
19438
+ if (event.metaKey || event.ctrlKey) {
19439
+ window.open(anchor.href, "_blank", "noopener,noreferrer");
19440
+ }
19441
+ });
19442
+ }
19331
19443
  if (!props.color) el16.style.color = "#0563c1";
19332
19444
  }
19333
19445
  if (item.rotate) {
@@ -19653,7 +19765,11 @@ function setPageLayout(doc, patch, target) {
19653
19765
  if (patch.columns !== void 0) {
19654
19766
  sectPr.children = sectPr.children.filter((c) => localName(c.name) !== "cols");
19655
19767
  if (patch.columns > 1) {
19656
- const cols = el2(`${w}cols`, { [`${w}num`]: String(patch.columns), [`${w}space`]: "720" });
19768
+ const cols = el2(`${w}cols`, {
19769
+ [`${w}num`]: String(patch.columns),
19770
+ [`${w}space`]: "720",
19771
+ ...patch.columnSeparator ? { [`${w}sep`]: "1" } : {}
19772
+ });
19657
19773
  const idx = sectPr.children.indexOf(pgMar);
19658
19774
  sectPr.children.splice(idx + 1, 0, cols);
19659
19775
  }
@@ -20638,12 +20754,26 @@ function resizeDrawing(doc, drawingEl, widthPx, heightPx) {
20638
20754
  const EMU = 9525;
20639
20755
  const cx = String(Math.max(Math.round(widthPx * EMU), EMU));
20640
20756
  const cy = String(Math.max(Math.round(heightPx * EMU), EMU));
20757
+ let lineExtent;
20758
+ const findLineExtent = (node) => {
20759
+ if (lineExtent) return;
20760
+ if (localName(node.name) === "spPr") {
20761
+ const preset = attr(child(node, "prstGeom"), "prst") ?? "";
20762
+ if (preset === "line" || preset.startsWith("straightConnector")) {
20763
+ lineExtent = child(child(node, "xfrm"), "ext");
20764
+ return;
20765
+ }
20766
+ }
20767
+ for (const childNode of node.children) findLineExtent(childNode);
20768
+ };
20769
+ findLineExtent(drawingEl);
20770
+ const keepHorizontal = lineExtent ? parseInt(lineExtent.attrs[Object.keys(lineExtent.attrs).find((key) => localName(key) === "cy") ?? "cy"] ?? "0", 10) === 0 : false;
20641
20771
  let touched = false;
20642
20772
  const setExt = (el16) => {
20643
20773
  const cxKey = Object.keys(el16.attrs).find((k) => localName(k) === "cx") ?? "cx";
20644
20774
  const cyKey = Object.keys(el16.attrs).find((k) => localName(k) === "cy") ?? "cy";
20645
20775
  el16.attrs[cxKey] = cx;
20646
- el16.attrs[cyKey] = cy;
20776
+ el16.attrs[cyKey] = el16 === lineExtent && keepHorizontal ? "0" : cy;
20647
20777
  touched = true;
20648
20778
  };
20649
20779
  const walk2 = (el16, insideGroup) => {
@@ -20919,10 +21049,23 @@ function sectPrAt(doc, t) {
20919
21049
  }
20920
21050
  return seen ? bodySectPr : bodySectPr;
20921
21051
  }
21052
+ function sectionContextAt(doc, t) {
21053
+ const body = bodyOf(doc);
21054
+ const target = sectPrAt(doc, t);
21055
+ if (!body || !target) return null;
21056
+ const sections = [];
21057
+ const visit = (node) => {
21058
+ if (localName(node.name) === "sectPr") sections.push(node);
21059
+ else for (const child4 of node.children) visit(child4);
21060
+ };
21061
+ visit(body);
21062
+ const index = sections.indexOf(target);
21063
+ return index < 0 ? null : { index: index + 1, count: sections.length };
21064
+ }
20922
21065
  function insertBreakAt(doc, t, offset, kind) {
20923
21066
  const rEl = doc.findParentOf(t);
20924
21067
  const pEl = rEl && doc.findParentOf(rEl);
20925
- if (!rEl || !pEl || localName(rEl.name) !== "r") return false;
21068
+ if (!rEl || !pEl || localName(rEl.name) !== "r") return null;
20926
21069
  const rw = rEl.name.includes(":") ? rEl.name.slice(0, rEl.name.indexOf(":") + 1) : "";
20927
21070
  const rPr = rEl.children.find((c) => localName(c.name) === "rPr");
20928
21071
  const brRun = el4(`${rw}r`, {}, [
@@ -20930,8 +21073,11 @@ function insertBreakAt(doc, t, offset, kind) {
20930
21073
  el4(`${rw}br`, { [`${rw}type`]: kind })
20931
21074
  ]);
20932
21075
  const rIdx = pEl.children.indexOf(rEl);
21076
+ let destination = t;
20933
21077
  if (offset >= t.text.length) {
20934
- pEl.children.splice(rIdx + 1, 0, brRun);
21078
+ destination = el4(`${rw}t`, { "xml:space": "preserve" }, [], "");
21079
+ const tail = el4(`${rw}r`, {}, [...rPr ? [cloneDeep(rPr)] : [], destination]);
21080
+ pEl.children.splice(rIdx + 1, 0, brRun, tail);
20935
21081
  } else if (offset <= 0) {
20936
21082
  pEl.children.splice(rIdx, 0, brRun);
20937
21083
  } else {
@@ -20939,9 +21085,10 @@ function insertBreakAt(doc, t, offset, kind) {
20939
21085
  t.text = t.text.slice(0, offset);
20940
21086
  const tail = el4(`${rw}r`, {}, [...rPr ? [cloneDeep(rPr)] : [], tailT]);
20941
21087
  pEl.children.splice(rIdx + 1, 0, brRun, tail);
21088
+ destination = tailT;
20942
21089
  }
20943
21090
  doc.refresh();
20944
- return true;
21091
+ return { t: destination, offset: 0 };
20945
21092
  }
20946
21093
  function insertBlankPageAt(doc, t, offset) {
20947
21094
  const rEl = doc.findParentOf(t);
@@ -21626,13 +21773,14 @@ function insertShapeAt(doc, caretT, preset, text = "") {
21626
21773
  const height = isLine ? 2 : preset === "textBox" ? 72 : 96;
21627
21774
  const cx = String(Math.round(width * EMU_PER_PX4));
21628
21775
  const cy = String(Math.round(height * EMU_PER_PX4));
21776
+ const shapeCy = isLine ? "0" : cy;
21629
21777
  const geometry = preset === "roundedRectangle" ? "roundRect" : preset === "rectangle" || preset === "textBox" ? "rect" : preset;
21630
21778
  const isTextBox = preset === "textBox";
21631
21779
  const shapeName = isLine ? `Line ${id}` : isTextBox ? `Text Box ${id}` : `Shape ${id}`;
21632
21780
  const spPr = [
21633
21781
  el6("a:xfrm", {}, [
21634
21782
  el6("a:off", { x: "0", y: "0" }),
21635
- el6("a:ext", { cx, cy })
21783
+ el6("a:ext", { cx, cy: shapeCy })
21636
21784
  ]),
21637
21785
  el6("a:prstGeom", { prst: geometry }, [el6("a:avLst")]),
21638
21786
  isTextBox || isLine ? el6("a:noFill") : el6("a:solidFill", {}, [el6("a:srgbClr", { val: "4472C4" })]),
@@ -21734,6 +21882,10 @@ function insertWordArtAt(doc, caretT, text, preset = "plain") {
21734
21882
  function isDrawingWordArt(drawing) {
21735
21883
  return (descendant3(drawing, "docPr")?.attrs.name ?? "").startsWith("WordArt ");
21736
21884
  }
21885
+ function isDrawingLine(drawing) {
21886
+ const preset = descendant3(drawing, "prstGeom")?.attrs.prst ?? "";
21887
+ return preset === "line" || preset.startsWith("straightConnector");
21888
+ }
21737
21889
  function drawingWordArtText(drawing) {
21738
21890
  return isDrawingWordArt(drawing) ? descendant3(drawing, "t")?.text ?? "" : "";
21739
21891
  }
@@ -21746,15 +21898,42 @@ function setDrawingWordArtText(doc, drawing, text) {
21746
21898
  return true;
21747
21899
  }
21748
21900
  function drawingLineStyle(drawing) {
21901
+ const spPr = descendant3(drawing, "spPr");
21902
+ if (!spPr) return null;
21749
21903
  const line2 = descendant3(drawing, "ln");
21750
- if (!line2) return null;
21904
+ if (!line2) return { color: "#000000", width: 0.75 };
21751
21905
  const color = descendant3(line2, "srgbClr")?.attrs.val ?? "000000";
21752
21906
  const width = Math.max((parseInt(line2.attrs.w ?? "0", 10) || 0) / EMU_PER_PX4, 0.75);
21753
21907
  return { color: `#${color.toUpperCase()}`, width };
21754
21908
  }
21909
+ function drawingFillColor(drawing) {
21910
+ const spPr = descendant3(drawing, "spPr");
21911
+ if (!spPr || spPr.children.some((child4) => localName(child4.name) === "noFill")) return null;
21912
+ const solidFill = spPr.children.find((child4) => localName(child4.name) === "solidFill");
21913
+ const color = solidFill ? descendant3(solidFill, "srgbClr")?.attrs.val : void 0;
21914
+ return color ? `#${color.toUpperCase()}` : null;
21915
+ }
21916
+ function setDrawingFill(doc, drawing, color) {
21917
+ const spPr = descendant3(drawing, "spPr");
21918
+ if (!spPr) return false;
21919
+ spPr.children = spPr.children.filter((child4) => {
21920
+ const name = localName(child4.name);
21921
+ return name !== "solidFill" && name !== "noFill";
21922
+ });
21923
+ const fill = color ? el6("a:solidFill", {}, [el6("a:srgbClr", { val: color.replace(/^#/, "").toUpperCase() })]) : el6("a:noFill");
21924
+ const lineIndex = spPr.children.findIndex((child4) => localName(child4.name) === "ln");
21925
+ spPr.children.splice(lineIndex === -1 ? spPr.children.length : lineIndex, 0, fill);
21926
+ doc.refresh();
21927
+ return true;
21928
+ }
21755
21929
  function setDrawingLineStyle(doc, drawing, color, widthPx) {
21756
- const line2 = descendant3(drawing, "ln");
21757
- if (!line2) return false;
21930
+ const spPr = descendant3(drawing, "spPr");
21931
+ if (!spPr) return false;
21932
+ let line2 = spPr.children.find((child4) => localName(child4.name) === "ln");
21933
+ if (!line2) {
21934
+ line2 = el6("a:ln");
21935
+ spPr.children.push(line2);
21936
+ }
21758
21937
  line2.attrs.w = String(Math.max(1, Math.round(widthPx * EMU_PER_PX4)));
21759
21938
  line2.children = line2.children.filter((child4) => {
21760
21939
  const name = localName(child4.name);
@@ -23194,7 +23373,14 @@ function emptyParagraphLike(el16) {
23194
23373
  };
23195
23374
  }
23196
23375
  function removeDrawingRun(doc, src) {
23197
- let run = doc.findParentOf(src);
23376
+ let drawing = src;
23377
+ while (drawing) {
23378
+ const name = localName(drawing.name);
23379
+ if (name === "drawing" || name === "pict" || name === "object" || name === "AlternateContent") break;
23380
+ drawing = doc.findParentOf(drawing);
23381
+ }
23382
+ if (!drawing) return false;
23383
+ let run = doc.findParentOf(drawing);
23198
23384
  while (run && localName(run.name) !== "r") run = doc.findParentOf(run);
23199
23385
  const parent = run ? doc.findParentOf(run) : void 0;
23200
23386
  if (!run || !parent) return false;
@@ -23516,7 +23702,7 @@ var _DocxEditor = class _DocxEditor {
23516
23702
  this.focusText();
23517
23703
  return;
23518
23704
  }
23519
- if (this.imageOverlay?.contains(e.target)) return;
23705
+ if (this.imageOverlay?.contains(e.target) || this.imageToolbar?.contains(e.target)) return;
23520
23706
  if (this.wordArtOverlay?.contains(e.target)) return;
23521
23707
  if (this.wordArtTextEditor?.input.contains(e.target)) return;
23522
23708
  if (this.selectedInkGroup?.overlay.contains(e.target)) return;
@@ -23541,6 +23727,9 @@ var _DocxEditor = class _DocxEditor {
23541
23727
  }
23542
23728
  const onGlyph = this.caretFromPoint(e.clientX, e.clientY);
23543
23729
  let caret = onGlyph ?? this.nearestCaret(e.clientX, e.clientY);
23730
+ if (!onGlyph && !this.inHeaderFooter && e.detail === 1 && !e.shiftKey) {
23731
+ caret = this.extendCaretAfterPageTable(e.clientX, e.clientY) ?? caret;
23732
+ }
23544
23733
  let region = caret ? this.regionOf(caret.t) : "body";
23545
23734
  const storyObject = e.target?.closest?.(
23546
23735
  "[data-dxw-textbox-story-object]"
@@ -23617,7 +23806,8 @@ var _DocxEditor = class _DocxEditor {
23617
23806
  this.hfPage = null;
23618
23807
  }
23619
23808
  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;
23809
+ const columnCaret = this.extendCaretIntoLaterColumn(caret, e.clientX, e.clientY);
23810
+ 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
23811
  }
23622
23812
  if (caret && e.shiftKey) {
23623
23813
  const anchor = this.anchorPoint();
@@ -23677,7 +23867,7 @@ var _DocxEditor = class _DocxEditor {
23677
23867
  menu.setAttribute("role", "menu");
23678
23868
  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
23869
  const isApplePlatform = /Mac|iPhone|iPad/.test(navigator.platform);
23680
- const mod = isApplePlatform ? "\u2318" : "Ctrl+";
23870
+ const mod2 = isApplePlatform ? "\u2318" : "Ctrl+";
23681
23871
  const item = (label, shortcut, disabled, action) => {
23682
23872
  const button = document.createElement("button");
23683
23873
  button.type = "button";
@@ -23712,35 +23902,35 @@ var _DocxEditor = class _DocxEditor {
23712
23902
  const selectedText = selectionTextLogical(this.host.doc, this.getSelectionSegments());
23713
23903
  const clipboard = navigator.clipboard;
23714
23904
  const copy = () => clipboard.writeText(selectedText);
23715
- item("Copy", `${mod}C`, !selectedText || !clipboard?.writeText, () => void copy());
23716
- item("Cut", `${mod}X`, !selectedText || !clipboard?.writeText, () => {
23905
+ item("Copy", `${mod2}C`, !selectedText || !clipboard?.writeText, () => void copy());
23906
+ item("Cut", `${mod2}X`, !selectedText || !clipboard?.writeText, () => {
23717
23907
  void copy().then(() => {
23718
23908
  this.host.history?.checkpoint();
23719
23909
  this.removeSelectedText();
23720
23910
  this.commit();
23721
23911
  });
23722
23912
  });
23723
- item("Paste", `${mod}V`, !clipboard?.readText, () => {
23913
+ item("Paste", `${mod2}V`, !clipboard?.readText, () => {
23724
23914
  void clipboard.readText().then((text) => {
23725
23915
  if (text) this.insertText(text);
23726
23916
  });
23727
23917
  });
23728
23918
  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"));
23919
+ item("Bold", `${mod2}B`, !selectedText, () => this.host.onFormatShortcut?.("bold"));
23920
+ item("Italic", `${mod2}I`, !selectedText, () => this.host.onFormatShortcut?.("italic"));
23921
+ item("Underline", `${mod2}U`, !selectedText, () => this.host.onFormatShortcut?.("underline"));
23732
23922
  separator();
23733
- item("Link\u2026", `${mod}K`, !selectedText, () => this.host.onTextCommand?.("link"));
23923
+ item("Link\u2026", `${mod2}K`, !selectedText, () => this.host.onTextCommand?.("link"));
23734
23924
  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"));
23925
+ item("Bulleted list", `${mod2}Shift+L`, false, () => this.host.onTextCommand?.("bullet"));
23926
+ item("Numbered list", `${mod2}Shift+7`, false, () => this.host.onTextCommand?.("number"));
23737
23927
  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"));
23928
+ item("Align left", `${mod2}L`, false, () => this.host.onTextCommand?.("alignLeft"));
23929
+ item("Center", `${mod2}E`, false, () => this.host.onTextCommand?.("alignCenter"));
23930
+ item("Align right", `${mod2}R`, false, () => this.host.onTextCommand?.("alignRight"));
23931
+ item("Justify", `${mod2}J`, false, () => this.host.onTextCommand?.("justify"));
23742
23932
  separator();
23743
- item("Select all", `${mod}A`, false, () => this.selectAll());
23933
+ item("Select all", `${mod2}A`, false, () => this.selectAll());
23744
23934
  document.body.appendChild(menu);
23745
23935
  const rect = menu.getBoundingClientRect();
23746
23936
  menu.style.left = `${Math.max(6, Math.min(event.clientX, window.innerWidth - rect.width - 6))}px`;
@@ -23839,7 +24029,11 @@ var _DocxEditor = class _DocxEditor {
23839
24029
  if (e.key === "Enter" && (e.metaKey || e.ctrlKey) && this.caret) {
23840
24030
  e.preventDefault();
23841
24031
  this.host.history?.checkpoint();
23842
- if (insertBreakAt(this.host.doc, this.caret.t, this.caret.offset, "page")) this.commit();
24032
+ const destination = insertBreakAt(this.host.doc, this.caret.t, this.caret.offset, e.shiftKey ? "column" : "page");
24033
+ if (destination) {
24034
+ this.caret = { ...this.caret, ...destination };
24035
+ this.commit();
24036
+ }
23843
24037
  return;
23844
24038
  }
23845
24039
  if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "z") {
@@ -24611,6 +24805,13 @@ var _DocxEditor = class _DocxEditor {
24611
24805
  getSelectedDrawingSource() {
24612
24806
  return this.selectedImage?.src ?? null;
24613
24807
  }
24808
+ /** Whether Layout's contextual object commands currently have a target. */
24809
+ hasSelectedObject() {
24810
+ return this.selectedImage !== null || this.selectedInkGroup !== null;
24811
+ }
24812
+ notifyObjectSelection() {
24813
+ document.dispatchEvent(new CustomEvent("dxw-object-selection", { detail: this.hasSelectedObject() }));
24814
+ }
24614
24815
  /** Restore an object selection after a render replaced its DOM element. */
24615
24816
  reselectDrawing(src) {
24616
24817
  this.reselectImage(src);
@@ -25235,8 +25436,10 @@ var _DocxEditor = class _DocxEditor {
25235
25436
  return setImageWrap(this.host.doc, drawingEl, "square", { x, y: 0 });
25236
25437
  }
25237
25438
  deselectInkGroup() {
25439
+ const changed = this.selectedInkGroup !== null;
25238
25440
  this.selectedInkGroup?.overlay.remove();
25239
25441
  this.selectedInkGroup = null;
25442
+ if (changed) this.notifyObjectSelection();
25240
25443
  }
25241
25444
  selectInkGroup(bindings) {
25242
25445
  this.deselectInkGroup();
@@ -25254,6 +25457,7 @@ var _DocxEditor = class _DocxEditor {
25254
25457
  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
25458
  surface.appendChild(overlay);
25256
25459
  this.selectedInkGroup = { sources, bindings, overlay };
25460
+ this.notifyObjectSelection();
25257
25461
  this.hideCaret();
25258
25462
  this.focusText();
25259
25463
  }
@@ -25351,12 +25555,14 @@ var _DocxEditor = class _DocxEditor {
25351
25555
  return true;
25352
25556
  }
25353
25557
  deselectImage() {
25558
+ const changed = this.selectedImage !== null;
25354
25559
  this.wordArtTextEditor?.finish(true, false);
25355
25560
  this.imageOverlay?.remove();
25356
25561
  this.imageToolbar?.remove();
25357
25562
  this.imageOverlay = null;
25358
25563
  this.imageToolbar = null;
25359
25564
  this.selectedImage = null;
25565
+ if (changed) this.notifyObjectSelection();
25360
25566
  }
25361
25567
  /** Re-select the same drawing after a re-render replaced its element.
25362
25568
  * A header/footer drawing paints one instance per page from the same src;
@@ -25397,13 +25603,32 @@ var _DocxEditor = class _DocxEditor {
25397
25603
  overlay.style.boxSizing = "border-box";
25398
25604
  overlay.style.pointerEvents = "none";
25399
25605
  overlay.style.zIndex = "2147483647";
25606
+ const line2 = kind === "drawing" && isDrawingLine(src);
25607
+ if (line2) {
25608
+ const move = document.createElement("div");
25609
+ move.dataset.dxwObjectMove = "1";
25610
+ move.title = "Drag to move line";
25611
+ move.style.cssText = "position:absolute;left:5px;right:5px;top:calc(50% - 7px);height:14px;pointer-events:auto;cursor:move;";
25612
+ overlay.appendChild(move);
25613
+ }
25400
25614
  for (const [dir, fx, fy] of _DocxEditor.HANDLE_DIRS) {
25615
+ if (line2 && dir !== "e" && dir !== "w") continue;
25401
25616
  const h = document.createElement("div");
25402
25617
  const corner = dir.length === 2;
25403
25618
  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
25619
  h.dataset.dxwImgHandle = dir;
25405
25620
  overlay.appendChild(h);
25406
25621
  }
25622
+ if (el16.dataset.dxwModel3d) {
25623
+ const move = document.createElement("button");
25624
+ move.type = "button";
25625
+ move.dataset.dxwObjectMove = "1";
25626
+ move.title = "Drag to move 3D object";
25627
+ move.setAttribute("aria-label", "Move 3D object");
25628
+ move.textContent = "Move";
25629
+ 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);";
25630
+ overlay.appendChild(move);
25631
+ }
25407
25632
  const bar = document.createElement("div");
25408
25633
  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
25634
  const isFloating = isFloatingDrawing(src);
@@ -25507,6 +25732,42 @@ var _DocxEditor = class _DocxEditor {
25507
25732
  });
25508
25733
  });
25509
25734
  if (kind === "drawing") {
25735
+ extra("Rotate", "Set rotation (degrees)", () => {
25736
+ void requestTextInputDialog(this.host.container, {
25737
+ title: "Rotation",
25738
+ label: "Degrees clockwise",
25739
+ value: String(drawingRotation(src)),
25740
+ placeholder: "90"
25741
+ }).then((next) => {
25742
+ if (next === null) return;
25743
+ const degrees = parseFloat(next);
25744
+ if (!Number.isFinite(degrees)) return;
25745
+ this.host.history?.checkpoint();
25746
+ if (setDrawingRotation(this.host.doc, src, degrees)) {
25747
+ this.host.rerender(void 0, "global");
25748
+ this.reselectImage(src);
25749
+ }
25750
+ });
25751
+ });
25752
+ if (!isDrawingLine(src)) {
25753
+ extra("Fill", "Shape fill color", () => {
25754
+ void requestTextInputDialog(this.host.container, {
25755
+ title: "Fill",
25756
+ label: "Color or none",
25757
+ value: drawingFillColor(src) ?? "none",
25758
+ placeholder: "#4472C4 or none"
25759
+ }).then((next) => {
25760
+ if (next === null) return;
25761
+ const color = /^\s*none\s*$/i.test(next) ? null : /^\s*#?([0-9a-f]{6})\s*$/i.exec(next)?.[1];
25762
+ if (color === void 0) return;
25763
+ this.host.history?.checkpoint();
25764
+ if (setDrawingFill(this.host.doc, src, color ? `#${color}` : null)) {
25765
+ this.host.rerender();
25766
+ this.reselectImage(src);
25767
+ }
25768
+ });
25769
+ });
25770
+ }
25510
25771
  extra("Outline", "Outline color and weight", () => {
25511
25772
  const style = drawingLineStyle(src);
25512
25773
  if (!style) return;
@@ -25525,10 +25786,11 @@ var _DocxEditor = class _DocxEditor {
25525
25786
  }
25526
25787
  });
25527
25788
  });
25789
+ extra("Delete", "Delete shape", () => this.deleteSelectedImage());
25528
25790
  }
25529
25791
  const drawingBinding = kind === "drawing" ? this.host.getHandle()?.drawings.find((binding) => binding.item.src === src) : void 0;
25530
25792
  if (drawingBinding?.item.textboxStory && !isDrawingWordArt(src)) {
25531
- extra("Edit text", "Edit shape text", () => {
25793
+ extra("Edit text", "Edit shape text with the Home font controls", () => {
25532
25794
  const rect = drawingBinding.el.getBoundingClientRect();
25533
25795
  this.enterTextboxStory(src, rect.left + rect.width / 2, rect.top + rect.height / 2);
25534
25796
  });
@@ -25578,6 +25840,7 @@ var _DocxEditor = class _DocxEditor {
25578
25840
  bar.style.left = `${left}px`;
25579
25841
  this.imageOverlay = overlay;
25580
25842
  this.imageToolbar = bar;
25843
+ this.notifyObjectSelection();
25581
25844
  this.focusText();
25582
25845
  }
25583
25846
  deleteSelectedImage() {
@@ -25586,7 +25849,7 @@ var _DocxEditor = class _DocxEditor {
25586
25849
  this.host.history?.checkpoint();
25587
25850
  if (removeDrawingRun(this.host.doc, src)) {
25588
25851
  this.host.doc.refresh();
25589
- this.host.rerender();
25852
+ this.host.rerender(void 0, "global");
25590
25853
  }
25591
25854
  this.deselectImage();
25592
25855
  }
@@ -25774,12 +26037,18 @@ var _DocxEditor = class _DocxEditor {
25774
26037
  /** Handle mousedown on images / their resize handle. Returns true if consumed. */
25775
26038
  startImageInteraction(e, target) {
25776
26039
  const zoom = this.host.zoom ?? 1;
26040
+ const objectMove = target.closest?.("[data-dxw-object-move]");
26041
+ if (this.imageToolbar?.contains(target)) {
26042
+ this.suppressNextMouseUp = true;
26043
+ return true;
26044
+ }
25777
26045
  if (target.closest?.("[data-dxw-model3d-viewer]")) return true;
25778
26046
  if (target.dataset.dxwImgHandle && this.selectedImage) {
25779
26047
  e.preventDefault();
25780
26048
  e.stopPropagation();
25781
26049
  const dir = target.dataset.dxwImgHandle;
25782
26050
  const { el: el16, src } = this.selectedImage;
26051
+ const line2 = this.selectedImage.kind === "drawing" && isDrawingLine(src);
25783
26052
  const nearPt = { x: el16.getBoundingClientRect().left, y: el16.getBoundingClientRect().top };
25784
26053
  const w0 = parseFloat(el16.style.width);
25785
26054
  const h0 = parseFloat(el16.style.height);
@@ -25806,7 +26075,7 @@ var _DocxEditor = class _DocxEditor {
25806
26075
  h = h0 * scale;
25807
26076
  }
25808
26077
  w = Math.max(8, w);
25809
- h = Math.max(8, h);
26078
+ h = line2 ? h0 : Math.max(8, h);
25810
26079
  apply(el16);
25811
26080
  if (this.imageOverlay) apply(this.imageOverlay);
25812
26081
  };
@@ -25841,8 +26110,8 @@ var _DocxEditor = class _DocxEditor {
25841
26110
  }
25842
26111
  const mathTarget = target.closest?.("[data-dxw-math]");
25843
26112
  if (mathTarget) {
25844
- const handle = this.host.getHandle();
25845
- const mathBinding = handle?.bindings.find((b) => b.el === mathTarget);
26113
+ const handle2 = this.host.getHandle();
26114
+ const mathBinding = handle2?.bindings.find((b) => b.el === mathTarget);
25846
26115
  const oMathEl = mathBinding?.item.mathSrc;
25847
26116
  if (oMathEl) {
25848
26117
  e.preventDefault();
@@ -25869,9 +26138,21 @@ var _DocxEditor = class _DocxEditor {
25869
26138
  return true;
25870
26139
  }
25871
26140
  }
25872
- if (target.dataset.dxwDrawing) {
25873
- const handle = this.host.getHandle();
25874
- const binding = handle?.drawings.find((b) => b.el === target);
26141
+ const drawingTarget = objectMove && this.selectedImage?.kind === "drawing" ? this.selectedImage.el : target.closest?.("[data-dxw-drawing]");
26142
+ const handle = this.host.getHandle();
26143
+ let drawingBinding = drawingTarget ? handle?.drawings.find((b) => b.el === drawingTarget) : void 0;
26144
+ if (!drawingBinding && !target.closest("button")) {
26145
+ const pointCaret2 = this.caretFromPoint(e.clientX, e.clientY);
26146
+ if (!pointCaret2 || !this.inActiveRegion(pointCaret2.t)) {
26147
+ drawingBinding = handle?.drawings.find((candidate) => {
26148
+ if (!candidate.item.behind) return false;
26149
+ const rect = candidate.el.getBoundingClientRect();
26150
+ return e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
26151
+ });
26152
+ }
26153
+ }
26154
+ if (drawingBinding) {
26155
+ const binding = drawingBinding;
25875
26156
  if (!binding) return false;
25876
26157
  const textboxStory = binding.item.textboxStory === true;
25877
26158
  if (!textboxStory && this.regionOf(binding.item.src) === "hf" !== this.inHeaderFooter) return false;
@@ -25891,11 +26172,41 @@ var _DocxEditor = class _DocxEditor {
25891
26172
  }
25892
26173
  const startX = e.clientX;
25893
26174
  const startY = e.clientY;
26175
+ const el16 = binding.el;
26176
+ const left0 = parseFloat(el16.style.left) || 0;
26177
+ const top0 = parseFloat(el16.style.top) || 0;
25894
26178
  const rect0 = binding.el.getBoundingClientRect();
25895
26179
  let moved = false;
26180
+ let toolbarLeft0 = 0;
26181
+ let toolbarTop0 = 0;
25896
26182
  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);
26183
+ if (!moved && Math.hypot(me.clientX - startX, me.clientY - startY) > 5) {
26184
+ moved = true;
26185
+ if (binding.item.anchored) {
26186
+ if (this.selectedImage?.src !== binding.item.src) {
26187
+ this.selectImage(el16, binding.item.src, void 0, "drawing");
26188
+ }
26189
+ toolbarLeft0 = parseFloat(this.imageToolbar?.style.left ?? "") || 0;
26190
+ toolbarTop0 = parseFloat(this.imageToolbar?.style.top ?? "") || 0;
26191
+ }
26192
+ }
26193
+ if (!moved) return;
26194
+ if (binding.item.anchored) {
26195
+ const dx = (me.clientX - startX) / zoom;
26196
+ const dy = (me.clientY - startY) / zoom;
26197
+ el16.style.left = `${left0 + dx}px`;
26198
+ el16.style.top = `${top0 + dy}px`;
26199
+ if (this.imageOverlay) {
26200
+ this.imageOverlay.style.left = `${left0 + dx}px`;
26201
+ this.imageOverlay.style.top = `${top0 + dy}px`;
26202
+ }
26203
+ if (this.imageToolbar) {
26204
+ this.imageToolbar.style.left = `${toolbarLeft0 + dx}px`;
26205
+ this.imageToolbar.style.top = `${toolbarTop0 + dy}px`;
26206
+ }
26207
+ } else {
26208
+ this.showDropIndicator(me.clientX, me.clientY);
26209
+ }
25899
26210
  };
25900
26211
  const onUp = (me) => {
25901
26212
  document.removeEventListener("mousemove", onMove);
@@ -25903,15 +26214,31 @@ var _DocxEditor = class _DocxEditor {
25903
26214
  this.hideDropIndicator();
25904
26215
  this.suppressNextMouseUp = false;
25905
26216
  if (!moved) {
25906
- this.selectImage(target, binding.item.src, void 0, "drawing");
26217
+ this.selectImage(binding.el, binding.item.src, void 0, "drawing");
25907
26218
  return;
25908
26219
  }
25909
26220
  if (binding.item.anchored) {
25910
26221
  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)) {
26222
+ const dxClient = me.clientX - startX;
26223
+ const dyClient = me.clientY - startY;
26224
+ const want = { x: rect0.left + dxClient, y: rect0.top + dyClient };
26225
+ const pageRect = el16.closest(".dxw-page")?.getBoundingClientRect();
26226
+ const centerX = want.x + rect0.width / 2;
26227
+ const centerY = want.y + rect0.height / 2;
26228
+ const staysOnPage = !!pageRect && centerX >= pageRect.left && centerX <= pageRect.right && centerY >= pageRect.top && centerY <= pageRect.bottom;
26229
+ el16.style.left = `${left0}px`;
26230
+ el16.style.top = `${top0}px`;
26231
+ const changed = staysOnPage ? setFloatingPagePosition(
26232
+ this.host.doc,
26233
+ binding.item.src,
26234
+ left0 + dxClient / zoom,
26235
+ top0 + dyClient / zoom
26236
+ ) : this.moveFloatingDrawing(binding, dxClient, dyClient);
26237
+ if (changed) {
25913
26238
  this.host.rerender();
25914
26239
  this.reselectImage(binding.item.src, want);
26240
+ } else {
26241
+ this.reselectImage(binding.item.src, { x: rect0.left, y: rect0.top });
25915
26242
  }
25916
26243
  return;
25917
26244
  }
@@ -25930,12 +26257,18 @@ var _DocxEditor = class _DocxEditor {
25930
26257
  return true;
25931
26258
  }
25932
26259
  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) => {
26260
+ const pointCaret = this.caretFromPoint(e.clientX, e.clientY);
26261
+ if (objectMove && this.selectedImage?.kind === "image") {
26262
+ const selected = this.selectedImage;
26263
+ imageBinding = this.host.getHandle()?.images.find(
26264
+ (binding) => binding.el === selected.el && binding.item.src === selected.src
26265
+ );
26266
+ } else if (target.tagName === "IMG") {
26267
+ const handle2 = this.host.getHandle();
26268
+ imageBinding = handle2?.images.find((b) => b.el === target || b.el.contains(target));
26269
+ } else if (!target.closest("button") && !target.dataset.dxwImgHandle && !this.imageOverlay?.contains(target) && (!pointCaret || !this.inActiveRegion(pointCaret.t))) {
26270
+ const handle2 = this.host.getHandle();
26271
+ imageBinding = handle2?.images.find((b) => {
25939
26272
  if (!b.item.behind) return false;
25940
26273
  const r = b.el.getBoundingClientRect();
25941
26274
  return e.clientX >= r.left && e.clientX <= r.right && e.clientY >= r.top && e.clientY <= r.bottom;
@@ -25950,30 +26283,37 @@ var _DocxEditor = class _DocxEditor {
25950
26283
  const startX = e.clientX;
25951
26284
  const startY = e.clientY;
25952
26285
  const floating = isFloatingDrawing(binding.item.src);
26286
+ const moveAsObject = !!objectMove;
25953
26287
  const el16 = binding.el;
25954
26288
  const left0 = parseFloat(el16.style.left) || 0;
25955
26289
  const top0 = parseFloat(el16.style.top) || 0;
25956
26290
  const rect0 = el16.getBoundingClientRect();
25957
26291
  let moved = false;
25958
26292
  let ghost = null;
26293
+ let toolbarLeft0 = parseFloat(this.imageToolbar?.style.left ?? "") || 0;
26294
+ let toolbarTop0 = parseFloat(this.imageToolbar?.style.top ?? "") || 0;
25959
26295
  const grabX = e.clientX - el16.getBoundingClientRect().left;
25960
26296
  const grabY = e.clientY - el16.getBoundingClientRect().top;
25961
26297
  const onMove = (me) => {
25962
26298
  if (!moved && Math.hypot(me.clientX - startX, me.clientY - startY) > 5) {
25963
26299
  moved = true;
25964
- if (!floating) {
26300
+ if (!floating && !moveAsObject) {
25965
26301
  ghost = el16.cloneNode(true);
25966
26302
  ghost.style.position = "fixed";
25967
26303
  ghost.style.opacity = "0.5";
25968
26304
  ghost.style.pointerEvents = "none";
25969
26305
  ghost.style.zIndex = "1000";
25970
26306
  document.body.appendChild(ghost);
25971
- } else if (this.imageOverlay === null) {
26307
+ } else if (this.selectedImage?.src !== binding.item.src) {
25972
26308
  this.selectImage(el16, binding.item.src, binding.item);
25973
26309
  }
26310
+ if (floating || moveAsObject) {
26311
+ toolbarLeft0 = parseFloat(this.imageToolbar?.style.left ?? "") || 0;
26312
+ toolbarTop0 = parseFloat(this.imageToolbar?.style.top ?? "") || 0;
26313
+ }
25974
26314
  }
25975
26315
  if (!moved) return;
25976
- if (floating) {
26316
+ if (floating || moveAsObject) {
25977
26317
  const nl = left0 + (me.clientX - startX) / zoom;
25978
26318
  const nt = top0 + (me.clientY - startY) / zoom;
25979
26319
  el16.style.left = `${nl}px`;
@@ -25982,6 +26322,10 @@ var _DocxEditor = class _DocxEditor {
25982
26322
  this.imageOverlay.style.left = `${nl}px`;
25983
26323
  this.imageOverlay.style.top = `${nt}px`;
25984
26324
  }
26325
+ if (this.imageToolbar) {
26326
+ this.imageToolbar.style.left = `${toolbarLeft0 + (me.clientX - startX) / zoom}px`;
26327
+ this.imageToolbar.style.top = `${toolbarTop0 + (me.clientY - startY) / zoom}px`;
26328
+ }
25985
26329
  } else if (ghost) {
25986
26330
  ghost.style.left = `${me.clientX - grabX}px`;
25987
26331
  ghost.style.top = `${me.clientY - grabY}px`;
@@ -26049,6 +26393,18 @@ var _DocxEditor = class _DocxEditor {
26049
26393
  el16.style.top = `${top0}px`;
26050
26394
  this.reselectImage(src, { x: rect0.left, y: rect0.top });
26051
26395
  }
26396
+ } else if (moveAsObject) {
26397
+ const src = binding.item.src;
26398
+ const dx = (me.clientX - startX) / zoom;
26399
+ const dy = (me.clientY - startY) / zoom;
26400
+ const want = { x: rect0.left + me.clientX - startX, y: rect0.top + me.clientY - startY };
26401
+ el16.style.left = `${left0}px`;
26402
+ el16.style.top = `${top0}px`;
26403
+ setImageWrap(this.host.doc, src, "square", { x: 0, y: 0 });
26404
+ if (setFloatingPagePosition(this.host.doc, src, binding.item.x + dx, binding.item.y + dy)) {
26405
+ this.host.rerender();
26406
+ this.reselectImage(src, want);
26407
+ }
26052
26408
  } else {
26053
26409
  const imgRegion = this.regionOf(binding.item.src);
26054
26410
  let dest = this.caretFromPoint(me.clientX, me.clientY) ?? this.nearestCaret(me.clientX, me.clientY);
@@ -26482,6 +26838,154 @@ var _DocxEditor = class _DocxEditor {
26482
26838
  bias: logicalAfter && item.text.length > 0 ? "end" : void 0
26483
26839
  };
26484
26840
  }
26841
+ columnAtPoint(page, x, y) {
26842
+ const bands = JSON.parse(page.dataset.columnBands ?? "[]");
26843
+ let band = bands[0];
26844
+ for (const candidate of bands) {
26845
+ if (candidate.top <= y + 0.01) band = candidate;
26846
+ else break;
26847
+ }
26848
+ if (!band || band.colXs.length < 2) return null;
26849
+ let best = 0;
26850
+ let bestDistance = Infinity;
26851
+ for (let i = 0; i < band.colXs.length; i++) {
26852
+ const left = band.colXs[i];
26853
+ const right = left + band.colWidths[i];
26854
+ const distance = x < left ? left - x : x > right ? x - right : 0;
26855
+ if (distance < bestDistance) {
26856
+ best = i;
26857
+ bestDistance = distance;
26858
+ }
26859
+ }
26860
+ return {
26861
+ index: best,
26862
+ left: band.colXs[best],
26863
+ right: band.colXs[best] + band.colWidths[best]
26864
+ };
26865
+ }
26866
+ /** Word columns are one text flow. Clicking an empty later column inserts
26867
+ * the column break that Word otherwise exposes through Layout > Breaks, then
26868
+ * keeps click-and-type's vertical placement inside that column. */
26869
+ extendCaretIntoLaterColumn(caret, x, y) {
26870
+ const handle = this.host.getHandle();
26871
+ const page = document.elementFromPoint(x, y)?.closest(".dxw-page");
26872
+ const surface = page?.firstElementChild;
26873
+ if (!handle || !page || !surface) return null;
26874
+ const rect = surface.getBoundingClientRect();
26875
+ const zoom = this.host.zoom ?? 1;
26876
+ const lx = (x - rect.left) / zoom;
26877
+ const ly = (y - rect.top) / zoom;
26878
+ const targetColumn = this.columnAtPoint(page, lx, ly);
26879
+ if (!targetColumn) return null;
26880
+ const binding = handle.bindings.filter(
26881
+ (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
26882
+ ).sort((a, b) => Math.abs(a.item.lineTop - ly) - Math.abs(b.item.lineTop - ly))[0];
26883
+ if (!binding) return null;
26884
+ const sourceColumn = this.columnAtPoint(
26885
+ page,
26886
+ binding.item.x + Math.max(1, binding.item.width) / 2,
26887
+ binding.item.lineTop
26888
+ );
26889
+ if (!sourceColumn || targetColumn.index <= sourceColumn.index) return null;
26890
+ const rEl = this.host.doc.findParentOf(caret.t);
26891
+ const pEl = rEl && this.host.doc.findParentOf(rEl);
26892
+ if (!rEl || !pEl || localName(rEl.name) !== "r" || localName(pEl.name) !== "p") return null;
26893
+ const prefix = rEl.name.includes(":") ? rEl.name.slice(0, rEl.name.indexOf(":") + 1) : "";
26894
+ const rPr = rEl.children.find((child4) => localName(child4.name) === "rPr");
26895
+ const breakRuns = [];
26896
+ for (let i = sourceColumn.index; i < targetColumn.index; i++) {
26897
+ breakRuns.push({
26898
+ name: `${prefix}r`,
26899
+ attrs: {},
26900
+ children: [
26901
+ ...rPr ? [cloneXml(rPr)] : [],
26902
+ { name: `${prefix}br`, attrs: { [`${prefix}type`]: "column" }, children: [], text: "" }
26903
+ ],
26904
+ text: ""
26905
+ });
26906
+ }
26907
+ const runIndex = pEl.children.indexOf(rEl);
26908
+ const oldText = caret.t.text;
26909
+ let targetText = caret.t;
26910
+ this.host.history?.checkpoint();
26911
+ if (caret.offset <= 0) {
26912
+ pEl.children.splice(runIndex, 0, ...breakRuns);
26913
+ } else {
26914
+ const tailText = {
26915
+ name: caret.t.name,
26916
+ attrs: { ...caret.t.attrs, "xml:space": "preserve" },
26917
+ children: [],
26918
+ text: oldText.slice(caret.offset)
26919
+ };
26920
+ const tailRun = {
26921
+ name: rEl.name,
26922
+ attrs: {},
26923
+ children: [...rPr ? [cloneXml(rPr)] : [], tailText],
26924
+ text: ""
26925
+ };
26926
+ caret.t.text = oldText.slice(0, caret.offset);
26927
+ pEl.children.splice(runIndex + 1, 0, ...breakRuns, tailRun);
26928
+ targetText = tailText;
26929
+ }
26930
+ this.caret = { t: targetText, run: caret.run, offset: 0 };
26931
+ this.pendingClickTypeCheckpoint = true;
26932
+ this.commit(false, "global");
26933
+ return this.nearestCaret(x, y, "body") ?? this.caret;
26934
+ }
26935
+ /** A table can end partway through an intermediate page while the next body
26936
+ * block starts on a later page. Word still lets the user click the open body
26937
+ * area below that table. Materialize ordinary empty paragraphs between the
26938
+ * table and the following block so the requested line becomes editable. */
26939
+ extendCaretAfterPageTable(x, y) {
26940
+ const handle = this.host.getHandle();
26941
+ const page = document.elementFromPoint(x, y)?.closest(".dxw-page");
26942
+ const surface = page?.firstElementChild;
26943
+ if (!handle || !page || !surface) return null;
26944
+ const rect = surface.getBoundingClientRect();
26945
+ const zoom = this.host.zoom ?? 1;
26946
+ const lx = (x - rect.left) / zoom;
26947
+ const ly = (y - rect.top) / zoom;
26948
+ const bodyTop = parseFloat(page.dataset.bodyTop ?? "0");
26949
+ const bodyBottom = parseFloat(page.dataset.bodyBottom ?? "0");
26950
+ if (ly < bodyTop || ly > bodyBottom) return null;
26951
+ if (this.nearestCaret(x, y, "body")) return null;
26952
+ const table2 = handle.grips.filter((grip) => {
26953
+ if (grip.item.axis !== "move" || grip.el.parentElement !== surface) return false;
26954
+ if (ly <= grip.item.y2 + 1 || lx < grip.item.x || lx > (grip.item.x2 ?? grip.item.x)) return false;
26955
+ const parent2 = this.host.doc.findParentOf(grip.item.tbl);
26956
+ if (!parent2 || localName(parent2.name) !== "body") return false;
26957
+ const tblPr = grip.item.tbl.children.find((child4) => localName(child4.name) === "tblPr");
26958
+ return tblPr?.children.some((child4) => localName(child4.name) === "tblpPr") !== true;
26959
+ }).sort((a, b) => b.item.y2 - a.item.y2)[0];
26960
+ if (!table2) return null;
26961
+ const parent = this.host.doc.findParentOf(table2.item.tbl);
26962
+ const nearby = handle.bindings.filter(
26963
+ (binding2) => binding2.el.parentElement === surface && binding2.item.src?.t && this.regionOf(binding2.item.src.t) === "body" && binding2.item.lineTop <= table2.item.y2 + 1
26964
+ ).sort((a, b) => b.item.lineTop - a.item.lineTop)[0];
26965
+ const lineHeight = Math.max(1, nearby?.item.lineHeight ?? 16);
26966
+ const lineCount = Math.max(1, Math.round((ly - table2.item.y2) / lineHeight) + 1);
26967
+ const w = table2.item.tbl.name.includes(":") ? table2.item.tbl.name.slice(0, table2.item.tbl.name.indexOf(":") + 1) : "";
26968
+ const paragraphs = [];
26969
+ let targetText = null;
26970
+ for (let i = 0; i < lineCount; i++) {
26971
+ const created = emptyParagraphLike(table2.item.tbl);
26972
+ if (i === 0) {
26973
+ created.paragraph.children.unshift({ name: `${w}pPr`, attrs: {}, children: [], text: "" });
26974
+ }
26975
+ paragraphs.push(created.paragraph);
26976
+ targetText = created.text;
26977
+ }
26978
+ this.host.history?.checkpoint();
26979
+ parent.children.splice(parent.children.indexOf(table2.item.tbl) + 1, 0, ...paragraphs);
26980
+ this.pendingClickTypeCheckpoint = true;
26981
+ this.host.doc.refresh();
26982
+ this.host.rerender(void 0, "global");
26983
+ const binding = targetText ? this.host.getHandle()?.bindingsByText.get(targetText)?.[0] : void 0;
26984
+ if (!targetText || !binding?.item.src) return null;
26985
+ this.caret = { t: targetText, run: binding.item.src.run, offset: 0 };
26986
+ this.focusText();
26987
+ return this.caret;
26988
+ }
26485
26989
  /** Materialize Word's click-and-type position below a moved floating table. */
26486
26990
  extendCaretBelowFloatingTable(caret, x, y) {
26487
26991
  const handle = this.host.getHandle();
@@ -26545,7 +27049,7 @@ var _DocxEditor = class _DocxEditor {
26545
27049
  /** Word-style click-and-type: clicking below the final body line on a page
26546
27050
  * creates the intervening empty paragraphs so vertical arrows visit every
26547
27051
  * visible line instead of jumping across synthetic paragraph spacing. */
26548
- extendCaretIntoBodyWhitespace(caret, x, y) {
27052
+ extendCaretIntoBodyWhitespace(caret, x, y, checkpoint = true) {
26549
27053
  const handle = this.host.getHandle();
26550
27054
  const page = document.elementFromPoint(x, y)?.closest(".dxw-page");
26551
27055
  const surface = page?.firstElementChild;
@@ -26570,7 +27074,7 @@ var _DocxEditor = class _DocxEditor {
26570
27074
  );
26571
27075
  if (hasLaterLine) return null;
26572
27076
  const lineCount = Math.max(1, Math.round((ly - binding.item.lineTop) / lineHeight));
26573
- this.host.history?.checkpoint();
27077
+ if (checkpoint) this.host.history?.checkpoint();
26574
27078
  this.caret = {
26575
27079
  t: endText,
26576
27080
  run: binding.item.src.run,
@@ -26661,7 +27165,7 @@ var _DocxEditor = class _DocxEditor {
26661
27165
  const binding = this.host.getHandle()?.bindings.find((b) => b.el === el16 || el16 !== null && b.el === el16.parentElement);
26662
27166
  if (!binding?.item.src?.t) return null;
26663
27167
  const r = binding.el.getBoundingClientRect();
26664
- if (y < r.top - 4 || y > r.bottom + 4) return null;
27168
+ if (x < r.left - 4 || x > r.right + 4 || y < r.top - 4 || y > r.bottom + 4) return null;
26665
27169
  const local = Math.min(offset, binding.item.text.length);
26666
27170
  return {
26667
27171
  t: binding.item.src.t,
@@ -28187,7 +28691,10 @@ function setParagraphSpacing(doc, targets, patch) {
28187
28691
  sp = { name: `${w}spacing`, attrs: {}, children: [], text: "" };
28188
28692
  pPr.children.push(sp);
28189
28693
  }
28190
- if (patch.lineMultiple !== void 0) {
28694
+ if (patch.exactLinePt !== void 0) {
28695
+ sp.attrs[attrKey(sp, "line", w)] = String(Math.round(patch.exactLinePt * 20));
28696
+ sp.attrs[attrKey(sp, "lineRule", w)] = "exact";
28697
+ } else if (patch.lineMultiple !== void 0) {
28191
28698
  sp.attrs[attrKey(sp, "line", w)] = String(Math.round(patch.lineMultiple * 240));
28192
28699
  sp.attrs[attrKey(sp, "lineRule", w)] = "auto";
28193
28700
  }
@@ -28758,81 +29265,543 @@ function detectMissingFonts(layout) {
28758
29265
  }
28759
29266
 
28760
29267
  // src/toolbar.tsx
28761
- import { Fragment, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
29268
+ import { Fragment, useCallback, useEffect as useEffect2, useId, useLayoutEffect, useRef as useRef2, useState as useState2 } from "react";
29269
+ import { createPortal as createPortal2 } from "react-dom";
29270
+
29271
+ // src/help.tsx
29272
+ import { useEffect, useMemo, useRef, useState } from "react";
28762
29273
  import { createPortal } from "react-dom";
28763
- import { Fragment as Fragment2, jsx, jsxs } from "react/jsx-runtime";
28764
- var T = {
28765
- bg: "var(--dxw-toolbar-bg, #f9fbfd)",
28766
- fg: "var(--dxw-toolbar-fg, #3c4043)",
28767
- border: "var(--dxw-toolbar-border, #dadce0)",
28768
- muted: "var(--dxw-toolbar-muted, #5f6368)",
28769
- accent: "var(--dxw-accent, #1a73e8)",
28770
- accentFg: "var(--dxw-accent-fg, #fff)",
28771
- activeBg: "var(--dxw-btn-active-bg, #dfe7f5)",
28772
- hoverBg: "var(--dxw-btn-hover-bg, #f1f3f4)",
28773
- tabActiveBg: "var(--dxw-tab-active-bg, #e8f0fe)",
28774
- popoverBg: "var(--dxw-popover-bg, #fff)",
28775
- popoverShadow: "var(--dxw-popover-shadow, 0 4px 16px rgba(0,0,0,.15))"
28776
- };
28777
- var FONT_CANDIDATES = [
28778
- "Arial",
28779
- "Arial Black",
28780
- "Arial Narrow",
28781
- "Avenir",
28782
- "Avenir Next",
28783
- "Baskerville",
28784
- "Bookman Old Style",
28785
- "Brush Script MT",
28786
- "Calibri",
28787
- "Cambria",
28788
- "Century Gothic",
28789
- "Chalkboard",
28790
- "Charter",
28791
- "Comic Sans MS",
28792
- "Copperplate",
28793
- "Courier New",
28794
- "Didot",
28795
- "Futura",
28796
- "Garamond",
28797
- "Georgia",
28798
- "Gill Sans",
28799
- "Helvetica",
28800
- "Helvetica Neue",
28801
- "Hoefler Text",
28802
- "Impact",
28803
- "Lucida Grande",
28804
- "Menlo",
28805
- "Monaco",
28806
- "Optima",
28807
- "Palatino",
28808
- "Rockwell",
28809
- "Seravek",
28810
- "Tahoma",
28811
- "Times New Roman",
28812
- "Trebuchet MS",
28813
- "Verdana"
28814
- ];
28815
- var availableFonts = null;
28816
- function detectFonts() {
28817
- if (availableFonts) return availableFonts;
28818
- try {
28819
- const canvas = document.createElement("canvas");
28820
- const ctx = canvas.getContext("2d");
28821
- const probe = "mmmwwwlliiWQ@";
28822
- const widthIn = (family) => {
28823
- ctx.font = `16px ${family.includes(" ") ? `"${family}"` : family}, monospace`;
28824
- return ctx.measureText(probe).width;
28825
- };
28826
- ctx.font = "16px monospace";
28827
- const base = ctx.measureText(probe).width;
28828
- const always = /* @__PURE__ */ new Set(["Calibri", "Cambria"]);
28829
- availableFonts = FONT_CANDIDATES.filter((f) => always.has(f) || Math.abs(widthIn(f) - base) > 0.5);
28830
- } catch {
28831
- availableFonts = FONT_CANDIDATES;
28832
- }
28833
- return availableFonts;
28834
- }
28835
- var SIZES = [8, 9, 10, 10.5, 11, 12, 14, 16, 18, 20, 24, 28, 36, 48];
29274
+ import { jsx, jsxs } from "react/jsx-runtime";
29275
+ var GUIDE_GROUPS = [
29276
+ {
29277
+ title: "Start editing",
29278
+ items: [
29279
+ {
29280
+ title: "Type and select text",
29281
+ 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."
29282
+ },
29283
+ {
29284
+ title: "Right-click text",
29285
+ description: "The text menu includes cut, copy, paste, formatting, links, comments, lists, alignment, and Select all. Selection-dependent actions become available after selecting text."
29286
+ },
29287
+ {
29288
+ title: "Move through the document",
29289
+ 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."
29290
+ },
29291
+ {
29292
+ title: "Save your work",
29293
+ description: "Use Download to save the edited DOCX. Hosts can also persist drafts from the editor's saved DOCX bytes."
29294
+ }
29295
+ ]
29296
+ },
29297
+ {
29298
+ title: "Demo workspace",
29299
+ items: [
29300
+ {
29301
+ title: "Open or upload a document",
29302
+ description: "Choose a sample from Try a template or use Upload .docx to edit a local Word file in the browser."
29303
+ },
29304
+ {
29305
+ title: "Zoom, review, and author",
29306
+ 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."
29307
+ },
29308
+ {
29309
+ title: "Find and replace",
29310
+ description: "Press Cmd/Ctrl+F in the demo to open Find. Step through matches, replace the current match, or replace every match."
29311
+ },
29312
+ {
29313
+ title: "Save, download, print",
29314
+ description: "Save keeps the demo workspace in this browser, Download writes a DOCX file, and Print opens the browser's print or PDF workflow."
29315
+ }
29316
+ ]
29317
+ },
29318
+ {
29319
+ title: "Home tools",
29320
+ items: [
29321
+ {
29322
+ title: "Undo and redo",
29323
+ description: "Reverse or restore text, formatting, layout, and object edits with the arrow buttons or keyboard shortcuts."
29324
+ },
29325
+ {
29326
+ title: "Styles, font, and size",
29327
+ description: "Apply document paragraph styles, choose an available typeface, and set the selected text size."
29328
+ },
29329
+ {
29330
+ title: "Character formatting",
29331
+ description: "Bold, italicize, underline, strike, superscript, subscript, change case, clear formatting, or change text and highlight colors."
29332
+ },
29333
+ {
29334
+ title: "Paragraph formatting",
29335
+ description: "Align text, adjust indentation, and set line or paragraph spacing. These controls apply to the selected paragraphs or the paragraph containing the caret."
29336
+ },
29337
+ {
29338
+ title: "Lists",
29339
+ description: "Start or remove bulleted and numbered lists. Tab changes the level of the current list item; Shift+Tab promotes it."
29340
+ }
29341
+ ]
29342
+ },
29343
+ {
29344
+ title: "Insert tools",
29345
+ items: [
29346
+ {
29347
+ title: "Pages, breaks, and sections",
29348
+ description: "Insert a cover page, full blank page, page break, column break, or next-page/continuous section break at the caret."
29349
+ },
29350
+ {
29351
+ title: "Tables",
29352
+ 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."
29353
+ },
29354
+ {
29355
+ title: "Images, icons, and screenshots",
29356
+ 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."
29357
+ },
29358
+ {
29359
+ title: "3D models",
29360
+ 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."
29361
+ },
29362
+ {
29363
+ title: "Shapes and lines",
29364
+ 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."
29365
+ },
29366
+ {
29367
+ title: "Text boxes and WordArt",
29368
+ 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."
29369
+ },
29370
+ {
29371
+ title: "Charts and SmartArt",
29372
+ 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."
29373
+ },
29374
+ {
29375
+ title: "Links, comments, and notes",
29376
+ description: "Select text before adding a hyperlink or comment. Footnotes insert at the caret and remain editable in the note area."
29377
+ },
29378
+ {
29379
+ title: "Bookmarks and cross-references",
29380
+ description: "Create a named bookmark at a selection, then insert a live text or page reference to that bookmark elsewhere."
29381
+ },
29382
+ {
29383
+ title: "Headers, footers, and page numbers",
29384
+ 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."
29385
+ },
29386
+ {
29387
+ title: "Dates, fields, symbols, and drop caps",
29388
+ description: "Insert updating date/time and page fields, Unicode or custom symbols, and dropped or margin capitals at the caret."
29389
+ },
29390
+ {
29391
+ title: "Equations",
29392
+ 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."
29393
+ },
29394
+ {
29395
+ title: "Media and embedded files",
29396
+ description: "Insert online-video metadata with a browser-safe poster, or embed another file in the DOCX package."
29397
+ }
29398
+ ]
29399
+ },
29400
+ {
29401
+ title: "Draw tools",
29402
+ items: [
29403
+ {
29404
+ title: "Pen and highlighter",
29405
+ description: "Choose Pen or Highlighter, then drag on a page. Set color and width before drawing. Escape or Select returns to normal editing."
29406
+ },
29407
+ {
29408
+ title: "Erase and select ink",
29409
+ 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."
29410
+ }
29411
+ ]
29412
+ },
29413
+ {
29414
+ title: "Layout tools",
29415
+ items: [
29416
+ {
29417
+ title: "Document or section scope",
29418
+ description: "Choose Whole document for a global change or This section when only the caret's current section should change."
29419
+ },
29420
+ {
29421
+ title: "Margins, orientation, and page size",
29422
+ description: "Choose presets or exact custom page dimensions and margins. Orientation swaps the page between portrait and landscape."
29423
+ },
29424
+ {
29425
+ title: "Columns",
29426
+ description: "Choose one, two, two with divider, or three columns. Insert a column break when text should begin in the next column immediately."
29427
+ },
29428
+ {
29429
+ title: "Page borders and line numbers",
29430
+ description: "Apply a repeating page border and enable continuous, per-page, per-section, or interval-based line numbering."
29431
+ },
29432
+ {
29433
+ title: "Arrange selected objects",
29434
+ 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."
29435
+ }
29436
+ ]
29437
+ },
29438
+ {
29439
+ title: "Object controls",
29440
+ items: [
29441
+ {
29442
+ title: "Move, resize, rotate, and delete",
29443
+ 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."
29444
+ },
29445
+ {
29446
+ title: "Text wrapping and layering",
29447
+ 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."
29448
+ },
29449
+ {
29450
+ title: "Exact object properties",
29451
+ 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."
29452
+ }
29453
+ ]
29454
+ },
29455
+ {
29456
+ title: "Special-case recipes",
29457
+ items: [
29458
+ {
29459
+ title: "California pleading paper",
29460
+ 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.",
29461
+ steps: [
29462
+ "Open Insert \u2192 Header, then insert a text box in the repeating header layer.",
29463
+ "Enter 1 through 28 as separate paragraphs and select all of those numbered paragraphs.",
29464
+ "Open Home \u2192 Line & paragraph spacing \u2192 Exactly 24 pt, then choose Remove space before and Remove space after.",
29465
+ "Use Insert \u2192 Shape \u2192 Line for each vertical rule, rotate and position it in the same repeating header layer.",
29466
+ "Choose Close to return to body text."
29467
+ ]
29468
+ },
29469
+ {
29470
+ title: "Magazine columns with a middle rule",
29471
+ description: "Use the document's native column divider so the rule tracks layout automatically.",
29472
+ steps: [
29473
+ "Open Layout \u2192 Columns & divider \u2192 Two + divider line.",
29474
+ "Type normally to flow from the first column into the second.",
29475
+ "Use Insert \u2192 Break \u2192 Column break to move to the second column early."
29476
+ ]
29477
+ },
29478
+ {
29479
+ title: "Resume horizontal rule",
29480
+ description: "Use a body line when the rule belongs to one location in the document.",
29481
+ steps: [
29482
+ "Place the caret near the intended rule and choose Insert \u2192 Shape \u2192 Line.",
29483
+ "Drag to position and size it; use Position for exact placement.",
29484
+ "Choose Inline, Wrap, In front, or Behind according to how nearby text should flow."
29485
+ ]
29486
+ },
29487
+ {
29488
+ title: "Repeating page art",
29489
+ 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."
29490
+ },
29491
+ {
29492
+ title: "Border around every page",
29493
+ description: "Choose Layout \u2192 Page border for a true page border. Use header shapes when the design needs custom partial rules or ornaments."
29494
+ }
29495
+ ]
29496
+ }
29497
+ ];
29498
+ var mod = (apple, key) => apple ? `\u2318${key}` : `Ctrl+${key}`;
29499
+ var modShift = (apple, key) => apple ? `\u21E7\u2318${key}` : `Ctrl+Shift+${key}`;
29500
+ var SHORTCUT_GROUPS = [
29501
+ {
29502
+ title: "History and clipboard",
29503
+ items: [
29504
+ { action: "Undo", keys: (apple) => mod(apple, "Z") },
29505
+ { action: "Redo", keys: (apple) => apple ? "\u21E7\u2318Z" : "Ctrl+Y or Ctrl+Shift+Z" },
29506
+ { action: "Cut", keys: (apple) => mod(apple, "X") },
29507
+ { action: "Copy", keys: (apple) => mod(apple, "C") },
29508
+ { action: "Paste", keys: (apple) => mod(apple, "V") },
29509
+ { action: "Select all in the active story", keys: (apple) => mod(apple, "A") },
29510
+ { action: "Find and replace in the demo", keys: (apple) => mod(apple, "F") }
29511
+ ]
29512
+ },
29513
+ {
29514
+ title: "Text and paragraphs",
29515
+ items: [
29516
+ { action: "Bold", keys: (apple) => mod(apple, "B"), detail: "Requires selected text." },
29517
+ { action: "Italic", keys: (apple) => mod(apple, "I"), detail: "Requires selected text." },
29518
+ { action: "Underline", keys: (apple) => mod(apple, "U"), detail: "Requires selected text." },
29519
+ { action: "Insert or edit link", keys: (apple) => mod(apple, "K"), detail: "Requires selected text." },
29520
+ { action: "New comment", keys: (apple) => apple ? "\u2318\u2325A" : "Ctrl+Alt+M", detail: "Requires selected text." },
29521
+ { action: "Bulleted list", keys: (apple) => modShift(apple, "L") },
29522
+ { action: "Numbered list", keys: (apple) => modShift(apple, "7") },
29523
+ { action: "Align left", keys: (apple) => mod(apple, "L") },
29524
+ { action: "Center", keys: (apple) => mod(apple, "E") },
29525
+ { action: "Align right", keys: (apple) => mod(apple, "R") },
29526
+ { action: "Justify", keys: (apple) => mod(apple, "J") },
29527
+ { action: "Heading 1\u20136", keys: (apple) => apple ? "\u2318\u23251\u20136" : "Ctrl+Alt+1\u20136" },
29528
+ { action: "Normal paragraph", keys: (apple) => apple ? "\u2318\u23250" : "Ctrl+Alt+0" }
29529
+ ]
29530
+ },
29531
+ {
29532
+ title: "Structure and navigation",
29533
+ items: [
29534
+ { action: "Page break", keys: (apple) => mod(apple, "Enter") },
29535
+ { action: "Column break", keys: (apple) => modShift(apple, "Enter") },
29536
+ { action: "Move by character or visual line", keys: () => "Arrow keys" },
29537
+ { action: "Select by character or visual line", keys: () => "Shift+Arrow keys" },
29538
+ { action: "Move to visual line edge", keys: () => "Home / End" },
29539
+ { action: "Select to visual line edge", keys: () => "Shift+Home / Shift+End" },
29540
+ { action: "Move to line edge or adjacent paragraph", keys: (apple) => apple ? "\u2318+Arrow keys" : "Ctrl+Arrow keys" },
29541
+ { action: "Extend to line edge or adjacent paragraph", keys: (apple) => apple ? "\u21E7\u2318+Arrow keys" : "Ctrl+Shift+Arrow keys" },
29542
+ { action: "Next or previous table cell", keys: () => "Tab / Shift+Tab" },
29543
+ { action: "Change list level", keys: () => "Tab / Shift+Tab" }
29544
+ ]
29545
+ },
29546
+ {
29547
+ title: "Objects and editing modes",
29548
+ items: [
29549
+ { action: "Nudge selected floating object or ink", keys: () => "Arrow keys", detail: "Moves one pixel." },
29550
+ { action: "Nudge selected object farther", keys: () => "Shift+Arrow keys", detail: "Moves ten pixels." },
29551
+ { action: "Delete selected object", keys: () => "Delete / Backspace" },
29552
+ { action: "Leave drawing, text-box, header/footer, or object selection", keys: () => "Escape" },
29553
+ { action: "Open this help guide", keys: (apple) => `${mod(apple, "/")} or F1` }
29554
+ ]
29555
+ }
29556
+ ];
29557
+ var panel = {
29558
+ background: "var(--dxw-popover-bg, #fff)",
29559
+ color: "var(--dxw-toolbar-fg, #3c4043)",
29560
+ border: "1px solid var(--dxw-toolbar-border, #dadce0)",
29561
+ borderRadius: 12
29562
+ };
29563
+ function HelpGuide({ open, onClose, returnFocus }) {
29564
+ const [tab, setTab] = useState("guides");
29565
+ const [query, setQuery] = useState("");
29566
+ const searchRef = useRef(null);
29567
+ const previousFocus = useRef(null);
29568
+ const apple = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform);
29569
+ useEffect(() => {
29570
+ if (!open) return;
29571
+ previousFocus.current = document.activeElement;
29572
+ const frame = requestAnimationFrame(() => searchRef.current?.focus());
29573
+ const keydown = (event) => {
29574
+ if (event.key === "Escape") {
29575
+ event.preventDefault();
29576
+ onClose();
29577
+ }
29578
+ };
29579
+ document.addEventListener("keydown", keydown);
29580
+ return () => {
29581
+ cancelAnimationFrame(frame);
29582
+ document.removeEventListener("keydown", keydown);
29583
+ requestAnimationFrame(() => (returnFocus?.current ?? previousFocus.current)?.focus({ preventScroll: true }));
29584
+ };
29585
+ }, [open, onClose, returnFocus]);
29586
+ const needle = query.trim().toLowerCase();
29587
+ const guideGroups = useMemo(() => GUIDE_GROUPS.map((group) => ({
29588
+ ...group,
29589
+ items: group.items.filter(
29590
+ (item) => !needle || `${group.title} ${item.title} ${item.description} ${(item.steps ?? []).join(" ")}`.toLowerCase().includes(needle)
29591
+ )
29592
+ })).filter((group) => group.items.length > 0), [needle]);
29593
+ const shortcutGroups = useMemo(() => SHORTCUT_GROUPS.map((group) => ({
29594
+ ...group,
29595
+ items: group.items.filter(
29596
+ (item) => !needle || `${group.title} ${item.action} ${item.keys(apple)} ${item.detail ?? ""}`.toLowerCase().includes(needle)
29597
+ )
29598
+ })).filter((group) => group.items.length > 0), [apple, needle]);
29599
+ if (!open) return null;
29600
+ return createPortal(
29601
+ /* @__PURE__ */ jsx(
29602
+ "div",
29603
+ {
29604
+ "data-dxw-help-backdrop": "",
29605
+ onMouseDown: (event) => {
29606
+ if (event.target === event.currentTarget) onClose();
29607
+ },
29608
+ style: {
29609
+ position: "fixed",
29610
+ inset: 0,
29611
+ zIndex: 1e4,
29612
+ display: "grid",
29613
+ placeItems: "center",
29614
+ padding: 18,
29615
+ background: "rgba(32,33,36,.48)",
29616
+ fontFamily: "system-ui, sans-serif"
29617
+ },
29618
+ children: /* @__PURE__ */ jsxs(
29619
+ "div",
29620
+ {
29621
+ role: "dialog",
29622
+ "aria-modal": "true",
29623
+ "aria-labelledby": "dxw-help-title",
29624
+ "data-dxw-help-dialog": "",
29625
+ style: {
29626
+ ...panel,
29627
+ width: "min(980px, calc(100vw - 36px))",
29628
+ maxHeight: "min(820px, calc(100vh - 36px))",
29629
+ display: "flex",
29630
+ flexDirection: "column",
29631
+ overflow: "hidden",
29632
+ boxShadow: "0 18px 60px rgba(0,0,0,.28)"
29633
+ },
29634
+ children: [
29635
+ /* @__PURE__ */ jsxs("header", { style: { padding: "18px 20px 14px", borderBottom: "1px solid var(--dxw-toolbar-border, #dadce0)" }, children: [
29636
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "flex-start", gap: 16 }, children: [
29637
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1 }, children: [
29638
+ /* @__PURE__ */ jsx("h2", { id: "dxw-help-title", style: { margin: 0, fontSize: 22, color: "var(--dxw-toolbar-fg, #202124)" }, children: "WordInWeb help" }),
29639
+ /* @__PURE__ */ jsx("p", { style: { margin: "4px 0 0", color: "var(--dxw-toolbar-muted, #5f6368)", fontSize: 13 }, children: "Tool guides, editing recipes, and keyboard shortcuts." })
29640
+ ] }),
29641
+ /* @__PURE__ */ jsx(
29642
+ "button",
29643
+ {
29644
+ type: "button",
29645
+ "aria-label": "Close help",
29646
+ onClick: onClose,
29647
+ style: { border: 0, background: "transparent", color: "inherit", cursor: "pointer", fontSize: 24, lineHeight: 1, padding: 4 },
29648
+ children: "\xD7"
29649
+ }
29650
+ )
29651
+ ] }),
29652
+ /* @__PURE__ */ jsx(
29653
+ "input",
29654
+ {
29655
+ ref: searchRef,
29656
+ type: "search",
29657
+ "aria-label": "Search help",
29658
+ placeholder: "Search tools, lines, columns, shortcuts\u2026",
29659
+ value: query,
29660
+ onChange: (event) => setQuery(event.target.value),
29661
+ style: {
29662
+ width: "100%",
29663
+ boxSizing: "border-box",
29664
+ marginTop: 14,
29665
+ padding: "10px 12px",
29666
+ border: "1px solid var(--dxw-toolbar-border, #c7cbd1)",
29667
+ borderRadius: 8,
29668
+ background: "var(--dxw-popover-bg, #fff)",
29669
+ color: "inherit",
29670
+ font: "14px system-ui, sans-serif",
29671
+ outlineColor: "var(--dxw-accent, #1a73e8)"
29672
+ }
29673
+ }
29674
+ ),
29675
+ /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": "Help sections", style: { display: "flex", gap: 6, marginTop: 12 }, children: ["guides", "shortcuts"].map((name) => /* @__PURE__ */ jsx(
29676
+ "button",
29677
+ {
29678
+ type: "button",
29679
+ role: "tab",
29680
+ "aria-selected": tab === name,
29681
+ onClick: () => setTab(name),
29682
+ style: {
29683
+ border: 0,
29684
+ borderRadius: 7,
29685
+ padding: "7px 12px",
29686
+ background: tab === name ? "var(--dxw-tab-active-bg, #e8f0fe)" : "transparent",
29687
+ color: tab === name ? "var(--dxw-accent, #1a73e8)" : "inherit",
29688
+ font: "600 13px system-ui, sans-serif",
29689
+ cursor: "pointer",
29690
+ textTransform: "capitalize"
29691
+ },
29692
+ children: name === "guides" ? "Guides" : "Shortcuts"
29693
+ },
29694
+ name
29695
+ )) })
29696
+ ] }),
29697
+ /* @__PURE__ */ jsxs("div", { style: { overflow: "auto", padding: "18px 20px 24px" }, children: [
29698
+ tab === "guides" && guideGroups.map((group) => /* @__PURE__ */ jsxs("section", { style: { marginBottom: 24 }, children: [
29699
+ /* @__PURE__ */ jsx("h3", { style: { margin: "0 0 10px", fontSize: 15 }, children: group.title }),
29700
+ /* @__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: [
29701
+ /* @__PURE__ */ jsx("h4", { style: { margin: "0 0 6px", fontSize: 14 }, children: item.title }),
29702
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, color: "var(--dxw-toolbar-muted, #5f6368)", fontSize: 12.5, lineHeight: 1.45 }, children: item.description }),
29703
+ 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)) })
29704
+ ] }, item.title)) })
29705
+ ] }, group.title)),
29706
+ tab === "shortcuts" && shortcutGroups.map((group) => /* @__PURE__ */ jsxs("section", { style: { marginBottom: 24 }, children: [
29707
+ /* @__PURE__ */ jsx("h3", { style: { margin: "0 0 8px", fontSize: 15 }, children: group.title }),
29708
+ /* @__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: [
29709
+ /* @__PURE__ */ jsxs("div", { children: [
29710
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 13 }, children: item.action }),
29711
+ item.detail && /* @__PURE__ */ jsx("div", { style: { color: "var(--dxw-toolbar-muted, #5f6368)", fontSize: 11.5, marginTop: 2 }, children: item.detail })
29712
+ ] }),
29713
+ /* @__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) })
29714
+ ] }, item.action)) })
29715
+ ] }, group.title)),
29716
+ (tab === "guides" ? guideGroups.length : shortcutGroups.length) === 0 && /* @__PURE__ */ jsxs("p", { role: "status", style: { color: "var(--dxw-toolbar-muted, #5f6368)", textAlign: "center", padding: 36 }, children: [
29717
+ "No help topics match \u201C",
29718
+ query,
29719
+ "\u201D."
29720
+ ] })
29721
+ ] })
29722
+ ]
29723
+ }
29724
+ )
29725
+ }
29726
+ ),
29727
+ document.body
29728
+ );
29729
+ }
29730
+
29731
+ // src/toolbar.tsx
29732
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
29733
+ var T = {
29734
+ bg: "var(--dxw-toolbar-bg, #f9fbfd)",
29735
+ fg: "var(--dxw-toolbar-fg, #3c4043)",
29736
+ border: "var(--dxw-toolbar-border, #dadce0)",
29737
+ muted: "var(--dxw-toolbar-muted, #5f6368)",
29738
+ accent: "var(--dxw-accent, #1a73e8)",
29739
+ accentFg: "var(--dxw-accent-fg, #fff)",
29740
+ activeBg: "var(--dxw-btn-active-bg, #dfe7f5)",
29741
+ hoverBg: "var(--dxw-btn-hover-bg, #f1f3f4)",
29742
+ tabActiveBg: "var(--dxw-tab-active-bg, #e8f0fe)",
29743
+ popoverBg: "var(--dxw-popover-bg, #fff)",
29744
+ popoverShadow: "var(--dxw-popover-shadow, 0 4px 16px rgba(0,0,0,.15))"
29745
+ };
29746
+ var FONT_CANDIDATES = [
29747
+ "Arial",
29748
+ "Arial Black",
29749
+ "Arial Narrow",
29750
+ "Avenir",
29751
+ "Avenir Next",
29752
+ "Baskerville",
29753
+ "Bookman Old Style",
29754
+ "Brush Script MT",
29755
+ "Calibri",
29756
+ "Cambria",
29757
+ "Century Gothic",
29758
+ "Chalkboard",
29759
+ "Charter",
29760
+ "Comic Sans MS",
29761
+ "Copperplate",
29762
+ "Courier New",
29763
+ "Didot",
29764
+ "Futura",
29765
+ "Garamond",
29766
+ "Georgia",
29767
+ "Gill Sans",
29768
+ "Helvetica",
29769
+ "Helvetica Neue",
29770
+ "Hoefler Text",
29771
+ "Impact",
29772
+ "Lucida Grande",
29773
+ "Menlo",
29774
+ "Monaco",
29775
+ "Optima",
29776
+ "Palatino",
29777
+ "Rockwell",
29778
+ "Seravek",
29779
+ "Tahoma",
29780
+ "Times New Roman",
29781
+ "Trebuchet MS",
29782
+ "Verdana"
29783
+ ];
29784
+ var availableFonts = null;
29785
+ function detectFonts() {
29786
+ if (availableFonts) return availableFonts;
29787
+ try {
29788
+ const canvas = document.createElement("canvas");
29789
+ const ctx = canvas.getContext("2d");
29790
+ const probe = "mmmwwwlliiWQ@";
29791
+ const widthIn = (family) => {
29792
+ ctx.font = `16px ${family.includes(" ") ? `"${family}"` : family}, monospace`;
29793
+ return ctx.measureText(probe).width;
29794
+ };
29795
+ ctx.font = "16px monospace";
29796
+ const base = ctx.measureText(probe).width;
29797
+ const always = /* @__PURE__ */ new Set(["Calibri", "Cambria"]);
29798
+ availableFonts = FONT_CANDIDATES.filter((f) => always.has(f) || Math.abs(widthIn(f) - base) > 0.5);
29799
+ } catch {
29800
+ availableFonts = FONT_CANDIDATES;
29801
+ }
29802
+ return availableFonts;
29803
+ }
29804
+ var SIZES = [8, 9, 10, 10.5, 11, 12, 14, 16, 18, 20, 24, 28, 36, 48];
28836
29805
  var HIGHLIGHTS = [
28837
29806
  { name: "yellow", css: "#ffff00" },
28838
29807
  { name: "green", css: "#00ff00" },
@@ -28867,10 +29836,11 @@ var PAGE_SIZES = [
28867
29836
  { value: "a6", label: "A6", description: '4.13" \xD7 5.83"', width: 4.13, height: 5.83 },
28868
29837
  { value: "envelope10", label: "Envelope #10", description: '4.13" \xD7 9.5"', width: 4.13, height: 9.5 }
28869
29838
  ];
28870
- function Btn({ label, title, active, onClick }) {
28871
- return /* @__PURE__ */ jsx(
29839
+ function Btn({ label, title, active, onClick, buttonRef }) {
29840
+ return /* @__PURE__ */ jsx2(
28872
29841
  "button",
28873
29842
  {
29843
+ ref: buttonRef,
28874
29844
  title,
28875
29845
  style: btnStyle(!!active),
28876
29846
  onMouseDown: (e) => e.preventDefault(),
@@ -28882,19 +29852,19 @@ function Btn({ label, title, active, onClick }) {
28882
29852
  );
28883
29853
  }
28884
29854
  function Sep() {
28885
- return /* @__PURE__ */ jsx("span", { style: { width: 1, height: 18, background: T.border, margin: "0 4px", flexShrink: 0 } });
29855
+ return /* @__PURE__ */ jsx2("span", { style: { width: 1, height: 18, background: T.border, margin: "0 4px", flexShrink: 0 } });
28886
29856
  }
28887
29857
  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" })
29858
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "currentColor", children: [
29859
+ /* @__PURE__ */ jsx2("circle", { cx: "8", cy: "3", r: "1.4" }),
29860
+ /* @__PURE__ */ jsx2("circle", { cx: "8", cy: "8", r: "1.4" }),
29861
+ /* @__PURE__ */ jsx2("circle", { cx: "8", cy: "13", r: "1.4" })
28892
29862
  ] });
28893
29863
  }
28894
29864
  function OverflowMenu({ children: children2 }) {
28895
- const [open, setOpen] = useState(false);
28896
- const rootRef = useRef(null);
28897
- useEffect(() => {
29865
+ const [open, setOpen] = useState2(false);
29866
+ const rootRef = useRef2(null);
29867
+ useEffect2(() => {
28898
29868
  if (!open) return;
28899
29869
  const close = (e) => {
28900
29870
  if (!rootRef.current?.contains(e.target)) setOpen(false);
@@ -28902,8 +29872,8 @@ function OverflowMenu({ children: children2 }) {
28902
29872
  document.addEventListener("mousedown", close);
28903
29873
  return () => document.removeEventListener("mousedown", close);
28904
29874
  }, [open]);
28905
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-flex", marginLeft: "auto" }, children: [
28906
- /* @__PURE__ */ jsx(
29875
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-flex", marginLeft: "auto" }, children: [
29876
+ /* @__PURE__ */ jsx2(
28907
29877
  "button",
28908
29878
  {
28909
29879
  title: "More tools",
@@ -28911,10 +29881,10 @@ function OverflowMenu({ children: children2 }) {
28911
29881
  style: btnStyle(open),
28912
29882
  onMouseDown: (e) => e.preventDefault(),
28913
29883
  onClick: () => setOpen(!open),
28914
- children: /* @__PURE__ */ jsx(OverflowIcon, {})
29884
+ children: /* @__PURE__ */ jsx2(OverflowIcon, {})
28915
29885
  }
28916
29886
  ),
28917
- open && /* @__PURE__ */ jsx(
29887
+ open && /* @__PURE__ */ jsx2(
28918
29888
  "div",
28919
29889
  {
28920
29890
  "data-dxw-overflow-menu": "",
@@ -28942,16 +29912,16 @@ function OverflowMenu({ children: children2 }) {
28942
29912
  }
28943
29913
  var icon = { width: 16, height: 16, display: "block" };
28944
29914
  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" })
29915
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
29916
+ /* @__PURE__ */ jsx2("rect", { x: "1.5", y: "2.5", width: "13", height: "11", rx: "1" }),
29917
+ /* @__PURE__ */ jsx2("circle", { cx: "5.2", cy: "6", r: "1.2", fill: "currentColor", stroke: "none" }),
29918
+ /* @__PURE__ */ jsx2("path", { d: "M2.5 12l3.5-4 2.8 3 2-2.4 2.7 3.4" })
28949
29919
  ] });
28950
29920
  }
28951
29921
  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 })
29922
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", children: [
29923
+ /* @__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" }),
29924
+ /* @__PURE__ */ jsx2("rect", { x: "2", y: "13.5", width: "12", height: "2.5", rx: "0.5", fill: color })
28955
29925
  ] });
28956
29926
  }
28957
29927
  function ToolbarMenuSelect({
@@ -28967,12 +29937,12 @@ function ToolbarMenuSelect({
28967
29937
  className,
28968
29938
  style
28969
29939
  }) {
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);
29940
+ const [open, setOpen] = useState2(false);
29941
+ const [position, setPosition] = useState2({ left: 8, top: 8, width: menuWidth ?? 180, maxHeight: 320 });
29942
+ const rootRef = useRef2(null);
29943
+ const triggerRef = useRef2(null);
29944
+ const menuRef = useRef2(null);
29945
+ const keyboardOpen = useRef2(null);
28976
29946
  const id = useId();
28977
29947
  const selected = options.find((option) => option.value === value);
28978
29948
  useLayoutEffect(() => {
@@ -29055,7 +30025,7 @@ function ToolbarMenuSelect({
29055
30025
  items[next]?.focus({ preventScroll: true });
29056
30026
  };
29057
30027
  let previousGroup;
29058
- return /* @__PURE__ */ jsxs(
30028
+ return /* @__PURE__ */ jsxs2(
29059
30029
  "span",
29060
30030
  {
29061
30031
  ref: rootRef,
@@ -29063,7 +30033,7 @@ function ToolbarMenuSelect({
29063
30033
  "data-dxw-menu-select": "",
29064
30034
  style: { position: "relative", display: "inline-flex", width },
29065
30035
  children: [
29066
- /* @__PURE__ */ jsxs(
30036
+ /* @__PURE__ */ jsxs2(
29067
30037
  "select",
29068
30038
  {
29069
30039
  tabIndex: -1,
@@ -29082,12 +30052,12 @@ function ToolbarMenuSelect({
29082
30052
  pointerEvents: "none"
29083
30053
  },
29084
30054
  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))
30055
+ !options.some((option) => option.value === value) && /* @__PURE__ */ jsx2("option", { value: "", children: String(placeholder) }),
30056
+ options.map((option) => /* @__PURE__ */ jsx2("option", { value: option.value, disabled: option.disabled, children: String(option.label) }, option.value))
29087
30057
  ]
29088
30058
  }
29089
30059
  ),
29090
- /* @__PURE__ */ jsxs(
30060
+ /* @__PURE__ */ jsxs2(
29091
30061
  "button",
29092
30062
  {
29093
30063
  ref: triggerRef,
@@ -29126,12 +30096,12 @@ function ToolbarMenuSelect({
29126
30096
  ...style
29127
30097
  },
29128
30098
  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" })
30099
+ /* @__PURE__ */ jsx2("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontFamily: selected?.fontFamily }, children: selected?.label ?? placeholder }),
30100
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", className: "dxw-menu-select-chevron", style: { flexShrink: 0, fontSize: 10 }, children: "\u2304" })
29131
30101
  ]
29132
30102
  }
29133
30103
  ),
29134
- open && /* @__PURE__ */ jsx(
30104
+ open && /* @__PURE__ */ jsx2(
29135
30105
  "div",
29136
30106
  {
29137
30107
  ref: menuRef,
@@ -29162,9 +30132,9 @@ function ToolbarMenuSelect({
29162
30132
  const groupChanged = option.group !== previousGroup;
29163
30133
  previousGroup = option.group;
29164
30134
  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(
30135
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
30136
+ 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 }),
30137
+ /* @__PURE__ */ jsxs2(
29168
30138
  "button",
29169
30139
  {
29170
30140
  type: "button",
@@ -29199,8 +30169,8 @@ function ToolbarMenuSelect({
29199
30169
  if (!active) event.currentTarget.style.background = "transparent";
29200
30170
  },
29201
30171
  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" })
30172
+ /* @__PURE__ */ jsx2("span", { style: { flex: 1 }, children: option.label }),
30173
+ active && /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", style: { color: T.accent, fontWeight: 700 }, children: "\u2713" })
29204
30174
  ]
29205
30175
  }
29206
30176
  )
@@ -29219,7 +30189,7 @@ function ActionMenu({
29219
30189
  onPick,
29220
30190
  width
29221
30191
  }) {
29222
- return /* @__PURE__ */ jsx(
30192
+ return /* @__PURE__ */ jsx2(
29223
30193
  ToolbarMenuSelect,
29224
30194
  {
29225
30195
  title,
@@ -29238,9 +30208,9 @@ function ActionMenu({
29238
30208
  );
29239
30209
  }
29240
30210
  function HighlightMenu({ current, onPick }) {
29241
- const [open, setOpen] = useState(false);
29242
- const rootRef = useRef(null);
29243
- useEffect(() => {
30211
+ const [open, setOpen] = useState2(false);
30212
+ const rootRef = useRef2(null);
30213
+ useEffect2(() => {
29244
30214
  if (!open) return;
29245
30215
  const close = (e) => {
29246
30216
  if (!rootRef.current?.contains(e.target)) setOpen(false);
@@ -29248,18 +30218,18 @@ function HighlightMenu({ current, onPick }) {
29248
30218
  document.addEventListener("mousedown", close);
29249
30219
  return () => document.removeEventListener("mousedown", close);
29250
30220
  }, [open]);
29251
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
29252
- /* @__PURE__ */ jsx(
30221
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30222
+ /* @__PURE__ */ jsx2(
29253
30223
  "button",
29254
30224
  {
29255
30225
  title: "Highlight color",
29256
30226
  style: btnStyle(open),
29257
30227
  onMouseDown: (e) => e.preventDefault(),
29258
30228
  onClick: () => setOpen(!open),
29259
- children: /* @__PURE__ */ jsx(HighlightIcon, { color: current ?? "#ffff00" })
30229
+ children: /* @__PURE__ */ jsx2(HighlightIcon, { color: current ?? "#ffff00" })
29260
30230
  }
29261
30231
  ),
29262
- open && /* @__PURE__ */ jsxs(
30232
+ open && /* @__PURE__ */ jsxs2(
29263
30233
  "div",
29264
30234
  {
29265
30235
  onMouseDown: (e) => e.preventDefault(),
@@ -29278,7 +30248,7 @@ function HighlightMenu({ current, onPick }) {
29278
30248
  alignItems: "center"
29279
30249
  },
29280
30250
  children: [
29281
- HIGHLIGHTS.map((h) => /* @__PURE__ */ jsx(
30251
+ HIGHLIGHTS.map((h) => /* @__PURE__ */ jsx2(
29282
30252
  "div",
29283
30253
  {
29284
30254
  title: h.name,
@@ -29290,7 +30260,7 @@ function HighlightMenu({ current, onPick }) {
29290
30260
  },
29291
30261
  h.name
29292
30262
  )),
29293
- /* @__PURE__ */ jsx(
30263
+ /* @__PURE__ */ jsx2(
29294
30264
  "div",
29295
30265
  {
29296
30266
  title: "No highlight",
@@ -29359,12 +30329,12 @@ function ColorMenu({
29359
30329
  trigger,
29360
30330
  onPick
29361
30331
  }) {
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);
30332
+ const [open, setOpen] = useState2(false);
30333
+ const [custom, setCustom] = useState2(current);
30334
+ const [position, setPosition] = useState2({ left: 8, top: 8 });
30335
+ const rootRef = useRef2(null);
30336
+ const triggerRef = useRef2(null);
30337
+ const menuRef = useRef2(null);
29368
30338
  const valid = normalizedColor(custom);
29369
30339
  useLayoutEffect(() => {
29370
30340
  if (!open) return;
@@ -29404,8 +30374,8 @@ function ColorMenu({
29404
30374
  onPick(value);
29405
30375
  setOpen(false);
29406
30376
  };
29407
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, className: "dxw-color-control", style: { position: "relative", display: "inline-flex" }, children: [
29408
- /* @__PURE__ */ jsx(
30377
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, className: "dxw-color-control", style: { position: "relative", display: "inline-flex" }, children: [
30378
+ /* @__PURE__ */ jsx2(
29409
30379
  "button",
29410
30380
  {
29411
30381
  ref: triggerRef,
@@ -29421,7 +30391,7 @@ function ColorMenu({
29421
30391
  children: trigger
29422
30392
  }
29423
30393
  ),
29424
- open && /* @__PURE__ */ jsxs(
30394
+ open && /* @__PURE__ */ jsxs2(
29425
30395
  "div",
29426
30396
  {
29427
30397
  ref: menuRef,
@@ -29444,7 +30414,7 @@ function ColorMenu({
29444
30414
  boxShadow: T.popoverShadow
29445
30415
  },
29446
30416
  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(
30417
+ /* @__PURE__ */ jsx2("div", { className: "dxw-color-swatches", style: { display: "grid", gridTemplateColumns: "repeat(8, 1fr)", gap: 4 }, children: COLOR_SWATCHES.map((color) => /* @__PURE__ */ jsx2(
29448
30418
  "button",
29449
30419
  {
29450
30420
  type: "button",
@@ -29466,9 +30436,9 @@ function ColorMenu({
29466
30436
  },
29467
30437
  color
29468
30438
  )) }),
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(
30439
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: 6, marginTop: 8 }, children: [
30440
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", style: { width: 24, height: 24, borderRadius: 4, border: `1px solid ${T.border}`, background: valid ?? current, flexShrink: 0 } }),
30441
+ /* @__PURE__ */ jsx2(
29472
30442
  "input",
29473
30443
  {
29474
30444
  "aria-label": "Custom hex color",
@@ -29483,7 +30453,7 @@ function ColorMenu({
29483
30453
  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
30454
  }
29485
30455
  ),
29486
- /* @__PURE__ */ jsx("button", { type: "button", disabled: !valid, onClick: () => valid && pick(valid), style: pillBtn, children: "Apply" })
30456
+ /* @__PURE__ */ jsx2("button", { type: "button", disabled: !valid, onClick: () => valid && pick(valid), style: pillBtn, children: "Apply" })
29487
30457
  ] })
29488
30458
  ]
29489
30459
  }
@@ -29491,46 +30461,46 @@ function ColorMenu({
29491
30461
  ] });
29492
30462
  }
29493
30463
  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" })
30464
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30465
+ /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "4", r: "1.1", fill: "currentColor", stroke: "none" }),
30466
+ /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "8", r: "1.1", fill: "currentColor", stroke: "none" }),
30467
+ /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "12", r: "1.1", fill: "currentColor", stroke: "none" }),
30468
+ /* @__PURE__ */ jsx2("path", { d: "M6.5 4h8M6.5 8h8M6.5 12h8", strokeLinecap: "round" })
29499
30469
  ] });
29500
30470
  }
29501
30471
  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" })
30472
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30473
+ /* @__PURE__ */ jsx2("text", { x: "1", y: "5.6", fontSize: "5.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "1" }),
30474
+ /* @__PURE__ */ jsx2("text", { x: "1", y: "9.9", fontSize: "5.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "2" }),
30475
+ /* @__PURE__ */ jsx2("text", { x: "1", y: "14.2", fontSize: "5.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "3" }),
30476
+ /* @__PURE__ */ jsx2("path", { d: "M6.5 4h8M6.5 8h8M6.5 12h8", strokeLinecap: "round" })
29507
30477
  ] });
29508
30478
  }
29509
30479
  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" })
30480
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30481
+ /* @__PURE__ */ jsx2("path", { d: "M6.5 9.5l3-3", strokeLinecap: "round" }),
30482
+ /* @__PURE__ */ jsx2("path", { d: "M7.5 4.5l1.2-1.2a2.6 2.6 0 013.7 3.7L11.2 8.2", strokeLinecap: "round" }),
30483
+ /* @__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
30484
  ] });
29515
30485
  }
29516
30486
  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" })
30487
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30488
+ /* @__PURE__ */ jsx2("path", { d: "M5 3h8M9 3l-2.5 9", strokeLinecap: "round" }),
30489
+ /* @__PURE__ */ jsx2("path", { d: "M3 13.5l3.5-3.5M3 10l3.5 3.5", strokeLinecap: "round" })
29520
30490
  ] });
29521
30491
  }
29522
30492
  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" })
30493
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30494
+ /* @__PURE__ */ jsx2("path", { d: "M2 3h12M8 6.5h6M8 9.5h6M2 13h12", strokeLinecap: "round" }),
30495
+ 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
30496
  ] });
29527
30497
  }
29528
30498
  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(() => {
30499
+ const [open, setOpen] = useState2(false);
30500
+ const [url, setUrl] = useState2("");
30501
+ const rootRef = useRef2(null);
30502
+ const inputRef = useRef2(null);
30503
+ useEffect2(() => {
29534
30504
  if (!open) return;
29535
30505
  setUrl(api?.getLinkAt() ?? "");
29536
30506
  inputRef.current?.focus();
@@ -29545,9 +30515,9 @@ function LinkMenu({ api }) {
29545
30515
  if (v) api?.setLink(/^[a-z][a-z0-9+.-]*:/i.test(v) ? v : `https://${v}`);
29546
30516
  setOpen(false);
29547
30517
  };
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(
30518
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30519
+ /* @__PURE__ */ jsx2("button", { title: "Insert link", style: btnStyle(open), onMouseDown: (e) => e.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsx2(LinkIcon, {}) }),
30520
+ open && /* @__PURE__ */ jsxs2(
29551
30521
  "div",
29552
30522
  {
29553
30523
  style: {
@@ -29566,7 +30536,7 @@ function LinkMenu({ api }) {
29566
30536
  alignItems: "center"
29567
30537
  },
29568
30538
  children: [
29569
- /* @__PURE__ */ jsx(
30539
+ /* @__PURE__ */ jsx2(
29570
30540
  "input",
29571
30541
  {
29572
30542
  ref: inputRef,
@@ -29577,8 +30547,8 @@ function LinkMenu({ api }) {
29577
30547
  style: { flex: 1, border: `1px solid ${T.border}`, borderRadius: 6, padding: "5px 8px", font: "13px system-ui, sans-serif", outline: "none" }
29578
30548
  }
29579
30549
  ),
29580
- /* @__PURE__ */ jsx("button", { style: pillBtn, disabled: !url.trim(), onClick: submit, children: "Apply" }),
29581
- api?.getLinkAt() && /* @__PURE__ */ jsx(
30550
+ /* @__PURE__ */ jsx2("button", { style: pillBtn, disabled: !url.trim(), onClick: submit, children: "Apply" }),
30551
+ api?.getLinkAt() && /* @__PURE__ */ jsx2(
29582
30552
  "button",
29583
30553
  {
29584
30554
  title: "Remove link",
@@ -29596,25 +30566,25 @@ function LinkMenu({ api }) {
29596
30566
  ] });
29597
30567
  }
29598
30568
  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" })
30569
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30570
+ /* @__PURE__ */ jsx2("path", { d: "M2.5 13V3.5M2.5 3.5h7", strokeLinecap: "round" }),
30571
+ /* @__PURE__ */ jsx2("text", { x: "10.2", y: "6.6", fontSize: "6.4", fill: "currentColor", stroke: "none", fontFamily: "system-ui", children: "1" }),
30572
+ /* @__PURE__ */ jsx2("path", { d: "M2.5 13h11", strokeLinecap: "round", strokeDasharray: "1.5 1.6" })
29603
30573
  ] });
29604
30574
  }
29605
30575
  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" })
30576
+ return /* @__PURE__ */ jsxs2("svg", { style: icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
30577
+ /* @__PURE__ */ jsx2("path", { d: "M1.5 3.5h13v8h-7l-3 3v-3h-3z", strokeLinejoin: "round" }),
30578
+ /* @__PURE__ */ jsx2("path", { d: "M8 5.5v4M6 7.5h4", strokeLinecap: "round" })
29609
30579
  ] });
29610
30580
  }
29611
30581
  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(() => {
30582
+ const [open, setOpen] = useState2(false);
30583
+ const [text, setText] = useState2("");
30584
+ const [hint, setHint] = useState2("");
30585
+ const rootRef = useRef2(null);
30586
+ const inputRef = useRef2(null);
30587
+ useEffect2(() => {
29618
30588
  if (!open) return;
29619
30589
  inputRef.current?.focus();
29620
30590
  const close = (e) => {
@@ -29632,9 +30602,9 @@ function FootnoteMenu({ api }) {
29632
30602
  setHint("Click into the text first so the reference has a place to go.");
29633
30603
  }
29634
30604
  };
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(
30605
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30606
+ /* @__PURE__ */ jsx2("button", { title: "Insert footnote (at the caret)", style: btnStyle(open), onMouseDown: (e) => e.preventDefault(), onClick: () => setOpen(!open), children: /* @__PURE__ */ jsx2(FootnoteIcon, {}) }),
30607
+ open && /* @__PURE__ */ jsxs2(
29638
30608
  "div",
29639
30609
  {
29640
30610
  style: {
@@ -29650,7 +30620,7 @@ function FootnoteMenu({ api }) {
29650
30620
  width: 240
29651
30621
  },
29652
30622
  children: [
29653
- /* @__PURE__ */ jsx(
30623
+ /* @__PURE__ */ jsx2(
29654
30624
  "textarea",
29655
30625
  {
29656
30626
  ref: inputRef,
@@ -29676,10 +30646,10 @@ function FootnoteMenu({ api }) {
29676
30646
  }
29677
30647
  }
29678
30648
  ),
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" })
30649
+ hint && /* @__PURE__ */ jsx2("div", { style: { color: "#c5221f", fontSize: 12, marginTop: 4 }, children: hint }),
30650
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 6 }, children: [
30651
+ /* @__PURE__ */ jsx2("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => setOpen(false), children: "Cancel" }),
30652
+ /* @__PURE__ */ jsx2("button", { style: pillBtn, disabled: !text.trim(), onClick: submit, children: "Insert" })
29683
30653
  ] })
29684
30654
  ]
29685
30655
  }
@@ -29687,11 +30657,11 @@ function FootnoteMenu({ api }) {
29687
30657
  ] });
29688
30658
  }
29689
30659
  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(() => {
30660
+ const [open, setOpen] = useState2(false);
30661
+ const [text, setText] = useState2("");
30662
+ const rootRef = useRef2(null);
30663
+ const inputRef = useRef2(null);
30664
+ useEffect2(() => {
29695
30665
  if (!open) return;
29696
30666
  inputRef.current?.focus();
29697
30667
  const close = (e) => {
@@ -29706,18 +30676,18 @@ function CommentMenu({ api }) {
29706
30676
  setOpen(false);
29707
30677
  }
29708
30678
  };
29709
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
29710
- /* @__PURE__ */ jsx(
30679
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30680
+ /* @__PURE__ */ jsx2(
29711
30681
  "button",
29712
30682
  {
29713
30683
  title: "Add comment (select text first)",
29714
30684
  style: btnStyle(open),
29715
30685
  onMouseDown: (e) => e.preventDefault(),
29716
30686
  onClick: () => setOpen(!open),
29717
- children: /* @__PURE__ */ jsx(CommentIcon, {})
30687
+ children: /* @__PURE__ */ jsx2(CommentIcon, {})
29718
30688
  }
29719
30689
  ),
29720
- open && /* @__PURE__ */ jsxs(
30690
+ open && /* @__PURE__ */ jsxs2(
29721
30691
  "div",
29722
30692
  {
29723
30693
  style: {
@@ -29733,7 +30703,7 @@ function CommentMenu({ api }) {
29733
30703
  width: 240
29734
30704
  },
29735
30705
  children: [
29736
- /* @__PURE__ */ jsx(
30706
+ /* @__PURE__ */ jsx2(
29737
30707
  "textarea",
29738
30708
  {
29739
30709
  ref: inputRef,
@@ -29759,9 +30729,9 @@ function CommentMenu({ api }) {
29759
30729
  }
29760
30730
  }
29761
30731
  ),
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" })
30732
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 6 }, children: [
30733
+ /* @__PURE__ */ jsx2("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => setOpen(false), children: "Cancel" }),
30734
+ /* @__PURE__ */ jsx2("button", { style: pillBtn, disabled: !text.trim(), onClick: submit, children: "Comment" })
29765
30735
  ] })
29766
30736
  ]
29767
30737
  }
@@ -29778,12 +30748,12 @@ var pillBtn = {
29778
30748
  color: T.accentFg
29779
30749
  };
29780
30750
  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(() => {
30751
+ const [open, setOpen] = useState2(false);
30752
+ const [name, setName] = useState2("");
30753
+ const [error, setError] = useState2("");
30754
+ const rootRef = useRef2(null);
30755
+ const inputRef = useRef2(null);
30756
+ useEffect2(() => {
29787
30757
  if (!open) return;
29788
30758
  inputRef.current?.focus();
29789
30759
  const close = (event) => {
@@ -29806,11 +30776,11 @@ function BookmarkMenu({ api }) {
29806
30776
  setError("");
29807
30777
  setOpen(false);
29808
30778
  };
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(
30779
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30780
+ /* @__PURE__ */ jsx2("button", { title: "Insert bookmark", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Bookmark" }),
30781
+ 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: [
30782
+ /* @__PURE__ */ jsx2("div", { style: { font: "600 12px system-ui, sans-serif", marginBottom: 6, color: T.fg }, children: "Bookmark name" }),
30783
+ /* @__PURE__ */ jsx2(
29814
30784
  "input",
29815
30785
  {
29816
30786
  ref: inputRef,
@@ -29824,21 +30794,21 @@ function BookmarkMenu({ api }) {
29824
30794
  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
30795
  }
29826
30796
  ),
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" })
30797
+ error && /* @__PURE__ */ jsx2("div", { style: { color: "#c5221f", fontSize: 11.5, marginTop: 5 }, children: error }),
30798
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 8 }, children: [
30799
+ /* @__PURE__ */ jsx2("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => setOpen(false), children: "Cancel" }),
30800
+ /* @__PURE__ */ jsx2("button", { style: pillBtn, disabled: !name.trim(), onClick: submit, children: "Add" })
29831
30801
  ] })
29832
30802
  ] })
29833
30803
  ] });
29834
30804
  }
29835
30805
  function CrossReferenceMenu({ api }) {
29836
- const [open, setOpen] = useState(false);
29837
- const [bookmark, setBookmark] = useState("");
29838
- const rootRef = useRef(null);
30806
+ const [open, setOpen] = useState2(false);
30807
+ const [bookmark, setBookmark] = useState2("");
30808
+ const rootRef = useRef2(null);
29839
30809
  const bookmarks = open ? api?.listBookmarks() ?? [] : [];
29840
30810
  const selected = bookmarks.includes(bookmark) ? bookmark : bookmarks[0] ?? "";
29841
- useEffect(() => {
30811
+ useEffect2(() => {
29842
30812
  if (!open) return;
29843
30813
  const close = (event) => {
29844
30814
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -29849,10 +30819,10 @@ function CrossReferenceMenu({ api }) {
29849
30819
  const insert = (kind) => {
29850
30820
  if (selected && api?.insertCrossReference(selected, kind)) setOpen(false);
29851
30821
  };
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(
30822
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30823
+ /* @__PURE__ */ jsx2("button", { title: "Insert cross-reference", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Cross-reference" }),
30824
+ 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: [
30825
+ /* @__PURE__ */ jsx2(
29856
30826
  ToolbarMenuSelect,
29857
30827
  {
29858
30828
  value: selected,
@@ -29864,20 +30834,20 @@ function CrossReferenceMenu({ api }) {
29864
30834
  style: { borderColor: T.border }
29865
30835
  }
29866
30836
  ),
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" })
30837
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 8 }, children: [
30838
+ /* @__PURE__ */ jsx2("button", { style: { ...pillBtn, background: T.popoverBg, color: T.fg }, onClick: () => insert("page"), children: "Page number" }),
30839
+ /* @__PURE__ */ jsx2("button", { style: pillBtn, onClick: () => insert("text"), children: "Bookmark text" })
29870
30840
  ] })
29871
30841
  ] }) })
29872
30842
  ] });
29873
30843
  }
29874
30844
  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(() => {
30845
+ const [open, setOpen] = useState2(false);
30846
+ const [linear, setLinear] = useState2("x={-b\xB1\u221A{b^2-4ac}}/{2a}");
30847
+ const [error, setError] = useState2("");
30848
+ const rootRef = useRef2(null);
30849
+ const inputRef = useRef2(null);
30850
+ useEffect2(() => {
29881
30851
  if (!open) return;
29882
30852
  inputRef.current?.focus();
29883
30853
  const close = (event) => {
@@ -29894,14 +30864,14 @@ function EquationMenu({ api }) {
29894
30864
  setError("Place the caret in editable text and enter a valid equation.");
29895
30865
  }
29896
30866
  };
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" })
30867
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30868
+ /* @__PURE__ */ jsxs2("button", { title: "Insert equation", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: [
30869
+ /* @__PURE__ */ jsx2("span", { style: { fontFamily: "'Cambria Math', serif", fontSize: 18 }, children: "\u03C0" }),
30870
+ /* @__PURE__ */ jsx2("span", { style: { marginLeft: 5 }, children: "Equation" })
29901
30871
  ] }),
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(
30872
+ 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: [
30873
+ /* @__PURE__ */ jsx2("div", { style: { font: "600 12px system-ui, sans-serif", marginBottom: 5, color: T.fg }, children: "Linear equation" }),
30874
+ /* @__PURE__ */ jsx2(
29905
30875
  "input",
29906
30876
  {
29907
30877
  ref: inputRef,
@@ -29915,18 +30885,18 @@ function EquationMenu({ api }) {
29915
30885
  style: { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 8px", font: "15px 'Cambria Math', serif", outline: "none" }
29916
30886
  }
29917
30887
  ),
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" }) })
30888
+ /* @__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." }),
30889
+ error && /* @__PURE__ */ jsx2("div", { style: { color: "#c5221f", fontSize: 11.5, marginTop: 5 }, children: error }),
30890
+ /* @__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
30891
  ] })
29922
30892
  ] });
29923
30893
  }
29924
30894
  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
30895
  function SymbolMenu({ api }) {
29926
- const [open, setOpen] = useState(false);
29927
- const [custom, setCustom] = useState("");
29928
- const rootRef = useRef(null);
29929
- useEffect(() => {
30896
+ const [open, setOpen] = useState2(false);
30897
+ const [custom, setCustom] = useState2("");
30898
+ const rootRef = useRef2(null);
30899
+ useEffect2(() => {
29930
30900
  if (!open) return;
29931
30901
  const close = (event) => {
29932
30902
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -29942,19 +30912,19 @@ function SymbolMenu({ api }) {
29942
30912
  setOpen(false);
29943
30913
  }
29944
30914
  };
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: [
30915
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30916
+ /* @__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
30917
  "\u03A9 ",
29948
- /* @__PURE__ */ jsx("span", { style: { fontFamily: "system-ui, sans-serif", fontSize: 12 }, children: "Advanced Symbol" })
30918
+ /* @__PURE__ */ jsx2("span", { style: { fontFamily: "system-ui, sans-serif", fontSize: 12 }, children: "Advanced Symbol" })
29949
30919
  ] }) }),
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: () => {
30920
+ 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: [
30921
+ /* @__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
30922
  if (api?.insertSymbol(symbol)) setOpen(false);
29953
30923
  }, 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(
30924
+ /* @__PURE__ */ jsxs2("div", { style: { borderTop: `1px solid ${T.border}`, marginTop: 8, paddingTop: 8 }, children: [
30925
+ /* @__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" }),
30926
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: 6 }, children: [
30927
+ /* @__PURE__ */ jsx2(
29958
30928
  "input",
29959
30929
  {
29960
30930
  id: "dxw-advanced-symbol",
@@ -29966,7 +30936,7 @@ function SymbolMenu({ api }) {
29966
30936
  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
30937
  }
29968
30938
  ),
29969
- /* @__PURE__ */ jsx("button", { type: "button", disabled: !custom, onClick: insertCustom, style: pillBtn, children: "Insert" })
30939
+ /* @__PURE__ */ jsx2("button", { type: "button", disabled: !custom, onClick: insertCustom, style: pillBtn, children: "Insert" })
29970
30940
  ] })
29971
30941
  ] })
29972
30942
  ] })
@@ -29981,10 +30951,10 @@ var SHAPES = [
29981
30951
  ["textBox", "Text box", "T"]
29982
30952
  ];
29983
30953
  function ShapeMenu({ api }) {
29984
- const [open, setOpen] = useState(false);
29985
- const [text, setText] = useState("");
29986
- const rootRef = useRef(null);
29987
- useEffect(() => {
30954
+ const [open, setOpen] = useState2(false);
30955
+ const [text, setText] = useState2("");
30956
+ const rootRef = useRef2(null);
30957
+ useEffect2(() => {
29988
30958
  if (!open) return;
29989
30959
  const close = (event) => {
29990
30960
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -29998,10 +30968,10 @@ function ShapeMenu({ api }) {
29998
30968
  setOpen(false);
29999
30969
  }
30000
30970
  };
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(
30971
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
30972
+ /* @__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" }) }),
30973
+ 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: [
30974
+ /* @__PURE__ */ jsx2(
30005
30975
  "input",
30006
30976
  {
30007
30977
  "aria-label": "Shape text",
@@ -30011,18 +30981,18 @@ function ShapeMenu({ api }) {
30011
30981
  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
30982
  }
30013
30983
  ),
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 })
30984
+ /* @__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: [
30985
+ /* @__PURE__ */ jsx2("span", { style: { display: "block", fontSize: 20, lineHeight: 1 }, children: glyph }),
30986
+ /* @__PURE__ */ jsx2("span", { children: label })
30017
30987
  ] }, preset)) })
30018
30988
  ] })
30019
30989
  ] });
30020
30990
  }
30021
30991
  function TextBoxMenu({ api }) {
30022
- const [open, setOpen] = useState(false);
30023
- const [text, setText] = useState("");
30024
- const rootRef = useRef(null);
30025
- useEffect(() => {
30992
+ const [open, setOpen] = useState2(false);
30993
+ const [text, setText] = useState2("");
30994
+ const rootRef = useRef2(null);
30995
+ useEffect2(() => {
30026
30996
  if (!open) return;
30027
30997
  const close = (event) => {
30028
30998
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30036,11 +31006,11 @@ function TextBoxMenu({ api }) {
30036
31006
  setOpen(false);
30037
31007
  }
30038
31008
  };
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(
31009
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31010
+ /* @__PURE__ */ jsx2("button", { title: "Insert text box", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Text Box" }),
31011
+ 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: [
31012
+ /* @__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" }),
31013
+ /* @__PURE__ */ jsx2(
30044
31014
  "input",
30045
31015
  {
30046
31016
  id: "dxw-text-box-text",
@@ -30052,7 +31022,7 @@ function TextBoxMenu({ api }) {
30052
31022
  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
31023
  }
30054
31024
  ),
30055
- /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 8 }, children: /* @__PURE__ */ jsx("button", { type: "button", onClick: insert, style: pillBtn, children: "Insert" }) })
31025
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 8 }, children: /* @__PURE__ */ jsx2("button", { type: "button", onClick: insert, style: pillBtn, children: "Insert" }) })
30056
31026
  ] })
30057
31027
  ] });
30058
31028
  }
@@ -30064,10 +31034,10 @@ var WORD_ART = [
30064
31034
  ["chevron", "Chevron", "\u2303"]
30065
31035
  ];
30066
31036
  function WordArtMenu({ api }) {
30067
- const [open, setOpen] = useState(false);
30068
- const [text, setText] = useState("Your text here");
30069
- const rootRef = useRef(null);
30070
- useEffect(() => {
31037
+ const [open, setOpen] = useState2(false);
31038
+ const [text, setText] = useState2("Your text here");
31039
+ const rootRef = useRef2(null);
31040
+ useEffect2(() => {
30071
31041
  if (!open) return;
30072
31042
  const close = (event) => {
30073
31043
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30075,10 +31045,10 @@ function WordArtMenu({ api }) {
30075
31045
  document.addEventListener("mousedown", close);
30076
31046
  return () => document.removeEventListener("mousedown", close);
30077
31047
  }, [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(
31048
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31049
+ /* @__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" }) }),
31050
+ 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: [
31051
+ /* @__PURE__ */ jsx2(
30082
31052
  "input",
30083
31053
  {
30084
31054
  "aria-label": "WordArt text",
@@ -30087,7 +31057,7 @@ function WordArtMenu({ api }) {
30087
31057
  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
31058
  }
30089
31059
  ),
30090
- /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 6, marginTop: 8 }, children: WORD_ART.map(([preset, label, glyph]) => /* @__PURE__ */ jsxs(
31060
+ /* @__PURE__ */ jsx2("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 6, marginTop: 8 }, children: WORD_ART.map(([preset, label, glyph]) => /* @__PURE__ */ jsxs2(
30091
31061
  "button",
30092
31062
  {
30093
31063
  title: `Insert WordArt ${label}`,
@@ -30097,8 +31067,8 @@ function WordArtMenu({ api }) {
30097
31067
  },
30098
31068
  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
31069
  children: [
30100
- /* @__PURE__ */ jsx("span", { style: { display: "block", fontSize: 19, lineHeight: 1.2 }, children: glyph }),
30101
- /* @__PURE__ */ jsx("span", { children: label })
31070
+ /* @__PURE__ */ jsx2("span", { style: { display: "block", fontSize: 19, lineHeight: 1.2 }, children: glyph }),
31071
+ /* @__PURE__ */ jsx2("span", { children: label })
30102
31072
  ]
30103
31073
  },
30104
31074
  preset
@@ -30107,14 +31077,14 @@ function WordArtMenu({ api }) {
30107
31077
  ] });
30108
31078
  }
30109
31079
  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(() => {
31080
+ const [open, setOpen] = useState2(false);
31081
+ const [type, setType] = useState2("column");
31082
+ const [title, setTitle] = useState2("Quarterly sales");
31083
+ const [categories, setCategories] = useState2("Q1, Q2, Q3, Q4");
31084
+ const [series, setSeries] = useState2("Revenue: 12, 19, 15, 24\nCosts: 8, 11, 10, 14");
31085
+ const [error, setError] = useState2("");
31086
+ const rootRef = useRef2(null);
31087
+ useEffect2(() => {
30118
31088
  if (!open) return;
30119
31089
  const close = (event) => {
30120
31090
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30142,10 +31112,10 @@ function ChartMenu({ api }) {
30142
31112
  }
30143
31113
  };
30144
31114
  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(
31115
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31116
+ /* @__PURE__ */ jsx2("button", { title: "Insert or edit chart", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Chart" }),
31117
+ 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: [
31118
+ /* @__PURE__ */ jsx2(
30149
31119
  ToolbarMenuSelect,
30150
31120
  {
30151
31121
  value: type,
@@ -30162,21 +31132,21 @@ function ChartMenu({ api }) {
30162
31132
  style: fieldStyle
30163
31133
  }
30164
31134
  ),
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" })
31135
+ /* @__PURE__ */ jsx2("input", { "aria-label": "Chart title", value: title, onChange: (event) => setTitle(event.target.value), placeholder: "Chart title", style: fieldStyle }),
31136
+ /* @__PURE__ */ jsx2("input", { "aria-label": "Chart categories", value: categories, onChange: (event) => setCategories(event.target.value), placeholder: "Q1, Q2, Q3, Q4", style: fieldStyle }),
31137
+ /* @__PURE__ */ jsx2("textarea", { "aria-label": "Chart series", rows: 3, value: series, onChange: (event) => setSeries(event.target.value), style: { ...fieldStyle, resize: "vertical" } }),
31138
+ /* @__PURE__ */ jsx2("div", { style: { color: T.muted, font: "11.5px system-ui, sans-serif" }, children: "Each series: Name: value, value, value" }),
31139
+ error && /* @__PURE__ */ jsx2("div", { role: "alert", style: { color: "#c5221f", font: "11.5px system-ui, sans-serif" }, children: error }),
31140
+ /* @__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
31141
  ] })
30172
31142
  ] });
30173
31143
  }
30174
31144
  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(() => {
31145
+ const [open, setOpen] = useState2(false);
31146
+ const [layout, setLayout] = useState2("process");
31147
+ const [items, setItems] = useState2("Discover\nDesign\nDeliver");
31148
+ const rootRef = useRef2(null);
31149
+ useEffect2(() => {
30180
31150
  if (!open) return;
30181
31151
  const close = (event) => {
30182
31152
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30191,10 +31161,10 @@ function SmartArtMenu({ api }) {
30191
31161
  if (api?.updateSelectedSmartArt(data) || api?.insertSmartArt(data)) setOpen(false);
30192
31162
  };
30193
31163
  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(
31164
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31165
+ /* @__PURE__ */ jsx2("button", { title: "Insert or edit SmartArt", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "SmartArt" }),
31166
+ 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: [
31167
+ /* @__PURE__ */ jsx2(
30198
31168
  ToolbarMenuSelect,
30199
31169
  {
30200
31170
  value: layout,
@@ -30211,17 +31181,17 @@ function SmartArtMenu({ api }) {
30211
31181
  style: fieldStyle
30212
31182
  }
30213
31183
  ),
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" })
31184
+ /* @__PURE__ */ jsx2("textarea", { "aria-label": "SmartArt items", rows: 5, value: items, onChange: (event) => setItems(event.target.value), style: { ...fieldStyle, resize: "vertical" } }),
31185
+ /* @__PURE__ */ jsx2("div", { style: { color: T.muted, font: "11.5px system-ui, sans-serif" }, children: "One diagram item per line." }),
31186
+ /* @__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
31187
  ] })
30218
31188
  ] });
30219
31189
  }
30220
31190
  function MediaMenu({ api }) {
30221
- const [open, setOpen] = useState(false);
30222
- const [url, setUrl] = useState("");
30223
- const rootRef = useRef(null);
30224
- useEffect(() => {
31191
+ const [open, setOpen] = useState2(false);
31192
+ const [url, setUrl] = useState2("");
31193
+ const rootRef = useRef2(null);
31194
+ useEffect2(() => {
30225
31195
  if (!open) return;
30226
31196
  const close = (event) => {
30227
31197
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30229,11 +31199,11 @@ function MediaMenu({ api }) {
30229
31199
  document.addEventListener("mousedown", close);
30230
31200
  return () => document.removeEventListener("mousedown", close);
30231
31201
  }, [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(
31202
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31203
+ /* @__PURE__ */ jsx2("button", { title: "Insert online video", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Media" }),
31204
+ 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: [
31205
+ /* @__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 } }),
31206
+ /* @__PURE__ */ jsx2(
30237
31207
  "button",
30238
31208
  {
30239
31209
  disabled: !url.trim(),
@@ -30246,62 +31216,70 @@ function MediaMenu({ api }) {
30246
31216
  ] });
30247
31217
  }
30248
31218
  function DrawTab({ api }) {
30249
- const [color, setColor] = useState("#202124");
30250
- const [width, setWidth] = useState(2);
31219
+ const [pen, setPen] = useState2({ color: "#202124", width: 2 });
31220
+ const [highlighter, setHighlighter] = useState2({ color: "#F9D949", width: 12 });
30251
31221
  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));
31222
+ const [active, setActive] = useState2(kindOf(api?.getDrawingTool() ?? null));
31223
+ useEffect2(() => {
31224
+ const update = (event) => {
31225
+ const tool = event.detail;
31226
+ setActive(kindOf(tool));
31227
+ if (tool?.kind === "highlighter") setHighlighter({ color: tool.color, width: tool.width });
31228
+ else if (tool?.kind === "pen") setPen({ color: tool.color, width: tool.width });
31229
+ };
30255
31230
  document.addEventListener("dxw-drawing-tool", update);
30256
31231
  return () => document.removeEventListener("dxw-drawing-tool", update);
30257
31232
  }, []);
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 });
31233
+ useEffect2(() => () => api?.setDrawingTool(null), [api]);
31234
+ const activate = (kind, patch) => {
31235
+ const next = { ...kind === "highlighter" ? highlighter : pen, ...patch };
31236
+ if (kind === "highlighter") setHighlighter(next);
31237
+ else setPen(next);
31238
+ api?.setDrawingTool({ kind, color: next.color, width: next.width });
30263
31239
  };
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(
31240
+ const inkKind = active === "highlighter" ? "highlighter" : "pen";
31241
+ const ink = inkKind === "highlighter" ? highlighter : pen;
31242
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
31243
+ /* @__PURE__ */ jsx2(Btn, { label: "Select", title: "Select objects", active: active === "select", onClick: () => api?.setDrawingTool(null) }),
31244
+ /* @__PURE__ */ jsx2(Btn, { label: "Pen", title: "Draw with pen", active: active === "pen", onClick: () => activate("pen") }),
31245
+ /* @__PURE__ */ jsx2(Btn, { label: "Highlighter", title: "Draw with highlighter", active: active === "highlighter", onClick: () => activate("highlighter") }),
31246
+ /* @__PURE__ */ jsx2(Btn, { label: "Eraser", title: "Stroke eraser", active: active === "eraser", onClick: () => api?.setDrawingTool({ kind: "eraser", size: 14 }) }),
31247
+ /* @__PURE__ */ jsx2(Btn, { label: "Lasso", title: "Lasso ink", active: active === "lasso", onClick: () => api?.setDrawingTool({ kind: "lasso" }) }),
31248
+ /* @__PURE__ */ jsx2(Sep, {}),
31249
+ /* @__PURE__ */ jsx2(
30272
31250
  ColorMenu,
30273
31251
  {
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 } })
31252
+ current: ink.color,
31253
+ title: inkKind === "highlighter" ? "Highlighter color" : "Pen color",
31254
+ trigger: /* @__PURE__ */ jsxs2(Fragment2, { children: [
31255
+ /* @__PURE__ */ jsx2("span", { style: { font: "12px system-ui, sans-serif" }, children: "Color" }),
31256
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", style: { width: 18, height: 18, borderRadius: 4, border: `1px solid ${T.border}`, background: ink.color } })
30279
31257
  ] }),
30280
- onPick: (value) => activate(active === "highlighter" ? "highlighter" : "pen", value, width)
31258
+ onPick: (value) => activate(inkKind, { color: value })
30281
31259
  }
30282
31260
  ),
30283
- /* @__PURE__ */ jsx(
31261
+ /* @__PURE__ */ jsx2(
30284
31262
  ActionMenu,
30285
31263
  {
30286
- label: `${width} px`,
30287
- title: "Pen width",
31264
+ label: `${ink.width} px`,
31265
+ title: inkKind === "highlighter" ? "Highlighter width" : "Pen width",
30288
31266
  width: 70,
30289
31267
  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))
31268
+ onPick: (value) => activate(inkKind, { width: Number(value) })
30291
31269
  }
30292
31270
  )
30293
31271
  ] });
30294
31272
  }
30295
31273
  function ScreenshotButton({ api }) {
30296
- const [status, setStatus] = useState("");
31274
+ const [status, setStatus] = useState2("");
30297
31275
  const capture = async () => {
30298
31276
  setStatus("Capturing screenshot\u2026");
30299
31277
  const result = await api?.insertScreenshot();
30300
31278
  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
31279
  };
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(
31280
+ return /* @__PURE__ */ jsxs2("span", { style: { position: "relative", display: "inline-flex" }, children: [
31281
+ /* @__PURE__ */ jsx2(Btn, { label: "Screenshot", title: "Capture and insert a screen, window, or tab", onClick: () => void capture() }),
31282
+ status && /* @__PURE__ */ jsx2(
30305
31283
  "span",
30306
31284
  {
30307
31285
  role: status === "Screenshot inserted." ? "status" : "alert",
@@ -30313,12 +31291,12 @@ function ScreenshotButton({ api }) {
30313
31291
  ] });
30314
31292
  }
30315
31293
  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(() => {
31294
+ const [open, setOpen] = useState2(false);
31295
+ const [title, setTitle] = useState2("");
31296
+ const [subtitle, setSubtitle] = useState2("");
31297
+ const [author, setAuthor] = useState2("");
31298
+ const rootRef = useRef2(null);
31299
+ useEffect2(() => {
30322
31300
  if (!open) return;
30323
31301
  const close = (event) => {
30324
31302
  if (!rootRef.current?.contains(event.target)) setOpen(false);
@@ -30333,7 +31311,7 @@ function CoverPageMenu({ api }) {
30333
31311
  setSubtitle("");
30334
31312
  setAuthor("");
30335
31313
  };
30336
- const input = (label, value, set) => /* @__PURE__ */ jsx(
31314
+ const input = (label, value, set) => /* @__PURE__ */ jsx2(
30337
31315
  "input",
30338
31316
  {
30339
31317
  "aria-label": label,
@@ -30343,21 +31321,21 @@ function CoverPageMenu({ api }) {
30343
31321
  style: { width: "100%", boxSizing: "border-box", border: `1px solid ${T.border}`, borderRadius: 6, padding: "6px 8px", font: "13px system-ui, sans-serif" }
30344
31322
  }
30345
31323
  );
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: [
31324
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31325
+ /* @__PURE__ */ jsx2("button", { title: "Insert cover page", style: btnStyle(open), onMouseDown: (event) => event.preventDefault(), onClick: () => setOpen(!open), children: "Cover page" }),
31326
+ 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
31327
  input("Cover title", title, setTitle),
30350
31328
  input("Cover subtitle", subtitle, setSubtitle),
30351
31329
  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" })
31330
+ /* @__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
31331
  ] })
30354
31332
  ] });
30355
31333
  }
30356
31334
  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(() => {
31335
+ const [open, setOpen] = useState2(false);
31336
+ const [hover, setHover] = useState2({ r: 0, c: 0 });
31337
+ const rootRef = useRef2(null);
31338
+ useEffect2(() => {
30361
31339
  if (!open) return;
30362
31340
  const close = (e) => {
30363
31341
  if (!rootRef.current?.contains(e.target)) setOpen(false);
@@ -30382,8 +31360,8 @@ function TableMenu({ api }) {
30382
31360
  ["deleteTable", "Delete table"]
30383
31361
  ];
30384
31362
  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(
31363
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-block" }, children: [
31364
+ /* @__PURE__ */ jsx2(
30387
31365
  "button",
30388
31366
  {
30389
31367
  title: "Table",
@@ -30393,7 +31371,7 @@ function TableMenu({ api }) {
30393
31371
  children: "Table \u25BE"
30394
31372
  }
30395
31373
  ),
30396
- open && /* @__PURE__ */ jsxs(
31374
+ open && /* @__PURE__ */ jsxs2(
30397
31375
  "div",
30398
31376
  {
30399
31377
  style: {
@@ -30410,12 +31388,12 @@ function TableMenu({ api }) {
30410
31388
  },
30411
31389
  onMouseDown: (e) => e.preventDefault(),
30412
31390
  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) => {
31391
+ /* @__PURE__ */ jsx2("div", { style: { fontSize: 12, color: T.muted, marginBottom: 4 }, children: hover.r > 0 ? `${hover.r} \xD7 ${hover.c}` : "Insert table" }),
31392
+ /* @__PURE__ */ jsx2("div", { style: { display: "grid", gridTemplateColumns: `repeat(${COLS}, 16px)`, gap: 2 }, children: Array.from({ length: ROWS * COLS }, (_, i) => {
30415
31393
  const r = Math.floor(i / COLS) + 1;
30416
31394
  const c = i % COLS + 1;
30417
31395
  const lit = r <= hover.r && c <= hover.c;
30418
- return /* @__PURE__ */ jsx(
31396
+ return /* @__PURE__ */ jsx2(
30419
31397
  "div",
30420
31398
  {
30421
31399
  onMouseEnter: () => setHover({ r, c }),
@@ -30436,8 +31414,8 @@ function TableMenu({ api }) {
30436
31414
  i
30437
31415
  );
30438
31416
  }) }),
30439
- /* @__PURE__ */ jsxs("div", { style: { borderTop: "1px solid #eee", marginTop: 8, paddingTop: 4 }, children: [
30440
- ops.map(([op, label]) => /* @__PURE__ */ jsx(
31417
+ /* @__PURE__ */ jsxs2("div", { style: { borderTop: "1px solid #eee", marginTop: 8, paddingTop: 4 }, children: [
31418
+ ops.map(([op, label]) => /* @__PURE__ */ jsx2(
30441
31419
  "div",
30442
31420
  {
30443
31421
  onClick: () => {
@@ -30455,9 +31433,9 @@ function TableMenu({ api }) {
30455
31433
  },
30456
31434
  op
30457
31435
  )),
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(
31436
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: 4, alignItems: "center", padding: "4px 6px" }, children: [
31437
+ /* @__PURE__ */ jsx2("span", { style: { fontSize: 12, color: T.muted, marginRight: 2 }, children: "Cell fill" }),
31438
+ CELL_FILLS.map((f) => /* @__PURE__ */ jsx2(
30461
31439
  "div",
30462
31440
  {
30463
31441
  title: `#${f}`,
@@ -30469,7 +31447,7 @@ function TableMenu({ api }) {
30469
31447
  },
30470
31448
  f
30471
31449
  )),
30472
- /* @__PURE__ */ jsx(
31450
+ /* @__PURE__ */ jsx2(
30473
31451
  "div",
30474
31452
  {
30475
31453
  title: "No fill",
@@ -30501,6 +31479,7 @@ function PagePreview({
30501
31479
  margins,
30502
31480
  mirrored,
30503
31481
  columns,
31482
+ columnSeparator,
30504
31483
  border,
30505
31484
  lineNumbers
30506
31485
  }) {
@@ -30513,14 +31492,14 @@ function PagePreview({
30513
31492
  const inset = margins ?? [0.8, 0.8, 0.8, 0.8];
30514
31493
  const borderWidth = border === "thick" ? 2 : border === "none" ? 0 : 1;
30515
31494
  const borderColor = border === "accent" ? T.accent : T.muted;
30516
- return /* @__PURE__ */ jsx(
31495
+ return /* @__PURE__ */ jsx2(
30517
31496
  "span",
30518
31497
  {
30519
31498
  "aria-hidden": "true",
30520
31499
  className: "dxw-layout-preview",
30521
31500
  "data-dxw-layout-preview": kind,
30522
31501
  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(
31502
+ children: Array.from({ length: papers }, (_, paper) => /* @__PURE__ */ jsxs2(
30524
31503
  "span",
30525
31504
  {
30526
31505
  className: "dxw-layout-preview-page",
@@ -30534,7 +31513,7 @@ function PagePreview({
30534
31513
  border: `${Math.max(1, borderWidth)}px solid ${borderWidth ? borderColor : T.border}`
30535
31514
  },
30536
31515
  children: [
30537
- kind === "margins" && /* @__PURE__ */ jsx("span", { style: {
31516
+ kind === "margins" && /* @__PURE__ */ jsx2("span", { style: {
30538
31517
  position: "absolute",
30539
31518
  top: `${Math.min(35, inset[0] * 18)}%`,
30540
31519
  right: `${Math.min(35, (mirrored && paper === 0 ? inset[3] : inset[1]) * 15)}%`,
@@ -30543,19 +31522,22 @@ function PagePreview({
30543
31522
  border: `1px solid ${T.accent}`,
30544
31523
  boxSizing: "border-box"
30545
31524
  } }),
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: [
31525
+ !!columns && /* @__PURE__ */ jsxs2("span", { style: { position: "absolute", inset: "5px 3px", display: "flex", gap: 2 }, children: [
31526
+ 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)),
31527
+ columnSeparator && /* @__PURE__ */ jsx2("span", { style: { position: "absolute", left: "50%", top: 0, bottom: 0, width: 1, background: T.muted } })
31528
+ ] }),
31529
+ border === "none" && /* @__PURE__ */ jsx2("span", { style: { position: "absolute", inset: 4, border: `1px dashed ${T.border}` } }),
31530
+ lineNumbers && /* @__PURE__ */ jsxs2("span", { style: { position: "absolute", inset: "4px 3px", display: "grid", gridTemplateColumns: "8px 1fr", gap: 2 }, children: [
31531
+ /* @__PURE__ */ jsxs2("span", { style: { fontSize: 5, lineHeight: "6px", color: T.accent }, children: [
30550
31532
  "1",
30551
- /* @__PURE__ */ jsx("br", {}),
31533
+ /* @__PURE__ */ jsx2("br", {}),
30552
31534
  "2",
30553
- /* @__PURE__ */ jsx("br", {}),
31535
+ /* @__PURE__ */ jsx2("br", {}),
30554
31536
  "3",
30555
- /* @__PURE__ */ jsx("br", {}),
31537
+ /* @__PURE__ */ jsx2("br", {}),
30556
31538
  "4"
30557
31539
  ] }),
30558
- /* @__PURE__ */ jsx("span", { style: { background: `repeating-linear-gradient(to bottom, ${T.muted} 0 1px, transparent 1px 6px)` } })
31540
+ /* @__PURE__ */ jsx2("span", { style: { background: `repeating-linear-gradient(to bottom, ${T.muted} 0 1px, transparent 1px 6px)` } })
30559
31541
  ] })
30560
31542
  ]
30561
31543
  },
@@ -30573,11 +31555,11 @@ function LayoutMenu({
30573
31555
  onPick
30574
31556
  }) {
30575
31557
  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({});
31558
+ const triggerRef = useRef2(null);
31559
+ const menuRef = useRef2(null);
31560
+ const keyboardOpen = useRef2(null);
31561
+ const [position, setPosition] = useState2({ left: 8, top: 8, maxHeight: 480 });
31562
+ const [portalTokens, setPortalTokens] = useState2({});
30581
31563
  useLayoutEffect(() => {
30582
31564
  if (!open) return;
30583
31565
  const update = () => {
@@ -30670,8 +31652,8 @@ function LayoutMenu({
30670
31652
  event.stopPropagation();
30671
31653
  items[next]?.focus({ preventScroll: true });
30672
31654
  };
30673
- return /* @__PURE__ */ jsxs("span", { className: "dxw-layout-control", style: { display: "inline-flex", minWidth: 0 }, children: [
30674
- /* @__PURE__ */ jsxs(
31655
+ return /* @__PURE__ */ jsxs2("span", { className: "dxw-layout-control", style: { display: "inline-flex", minWidth: 0 }, children: [
31656
+ /* @__PURE__ */ jsxs2(
30675
31657
  "button",
30676
31658
  {
30677
31659
  ref: triggerRef,
@@ -30705,13 +31687,13 @@ function LayoutMenu({
30705
31687
  fontWeight: 500
30706
31688
  },
30707
31689
  children: [
30708
- /* @__PURE__ */ jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: label }),
30709
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { fontSize: 10 }, children: "\u2304" })
31690
+ /* @__PURE__ */ jsx2("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: label }),
31691
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", style: { fontSize: 10 }, children: "\u2304" })
30710
31692
  ]
30711
31693
  }
30712
31694
  ),
30713
- open && createPortal(
30714
- /* @__PURE__ */ jsx(
31695
+ open && createPortal2(
31696
+ /* @__PURE__ */ jsx2(
30715
31697
  "div",
30716
31698
  {
30717
31699
  ref: menuRef,
@@ -30739,7 +31721,7 @@ function LayoutMenu({
30739
31721
  boxShadow: T.popoverShadow,
30740
31722
  padding: 6
30741
31723
  },
30742
- children: options.map((option) => /* @__PURE__ */ jsxs(
31724
+ children: options.map((option) => /* @__PURE__ */ jsxs2(
30743
31725
  "button",
30744
31726
  {
30745
31727
  type: "button",
@@ -30771,9 +31753,9 @@ function LayoutMenu({
30771
31753
  onMouseLeave: (event) => event.currentTarget.style.background = "transparent",
30772
31754
  children: [
30773
31755
  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 })
31756
+ /* @__PURE__ */ jsxs2("span", { style: { minWidth: 0 }, children: [
31757
+ /* @__PURE__ */ jsx2("span", { style: { display: "block", fontSize: 13, fontWeight: 550 }, children: option.label }),
31758
+ option.description && /* @__PURE__ */ jsx2("span", { style: { display: "block", fontSize: 11, color: T.muted, marginTop: 1 }, children: option.description })
30777
31759
  ] })
30778
31760
  ]
30779
31761
  },
@@ -30791,11 +31773,11 @@ function MarginMenu({
30791
31773
  open,
30792
31774
  onOpenChange
30793
31775
  }) {
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(() => {
31776
+ const [customOpen, setCustomOpen] = useState2(false);
31777
+ const [values, setValues] = useState2({ top: "1", bottom: "1", left: "1", right: "1" });
31778
+ const rootRef = useRef2(null);
31779
+ const [dialogPosition, setDialogPosition] = useState2({ left: 8, top: 8 });
31780
+ useEffect2(() => {
30799
31781
  if (!customOpen) return;
30800
31782
  const positionDialog = () => {
30801
31783
  const trigger = rootRef.current?.querySelector("[data-dxw-layout-menu-trigger]");
@@ -30851,9 +31833,9 @@ function MarginMenu({
30851
31833
  });
30852
31834
  setCustomOpen(false);
30853
31835
  };
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(
31836
+ const field = (side, label) => /* @__PURE__ */ jsxs2("label", { style: { display: "grid", gridTemplateColumns: "54px 1fr", gap: 8, alignItems: "center", fontSize: 12 }, children: [
31837
+ /* @__PURE__ */ jsx2("span", { children: label }),
31838
+ /* @__PURE__ */ jsx2(
30857
31839
  "input",
30858
31840
  {
30859
31841
  "aria-label": `${label} margin (inches)`,
@@ -30871,8 +31853,8 @@ function MarginMenu({
30871
31853
  }
30872
31854
  )
30873
31855
  ] });
30874
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-flex" }, children: [
30875
- /* @__PURE__ */ jsx(
31856
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-flex" }, children: [
31857
+ /* @__PURE__ */ jsx2(
30876
31858
  LayoutMenu,
30877
31859
  {
30878
31860
  name: "margins",
@@ -30881,16 +31863,16 @@ function MarginMenu({
30881
31863
  onOpenChange,
30882
31864
  onPick: pick,
30883
31865
  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] }) }
31866
+ { value: "m:normal", label: "Normal", description: '1" on every side', preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "margins", margins: [1, 1, 1, 1] }) },
31867
+ { 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] }) },
31868
+ { 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] }) },
31869
+ { value: "m:wide", label: "Wide", description: '1" top/bottom, 2" left/right', preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "margins", margins: [1, 2, 1, 2] }) },
31870
+ { 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 }) },
31871
+ { 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
31872
  ]
30891
31873
  }
30892
31874
  ),
30893
- customOpen && /* @__PURE__ */ jsxs(
31875
+ customOpen && /* @__PURE__ */ jsxs2(
30894
31876
  "div",
30895
31877
  {
30896
31878
  role: "dialog",
@@ -30912,19 +31894,19 @@ function MarginMenu({
30912
31894
  gap: 7
30913
31895
  },
30914
31896
  children: [
30915
- /* @__PURE__ */ jsx("strong", { style: { fontSize: 13 }, children: "Custom Margins" }),
31897
+ /* @__PURE__ */ jsx2("strong", { style: { fontSize: 13 }, children: "Custom Margins" }),
30916
31898
  field("top", "Top"),
30917
31899
  field("bottom", "Bottom"),
30918
31900
  field("left", "Left"),
30919
31901
  field("right", "Right"),
30920
- /* @__PURE__ */ jsxs("span", { style: { color: T.muted, fontSize: 11 }, children: [
31902
+ /* @__PURE__ */ jsxs2("span", { style: { color: T.muted, fontSize: 11 }, children: [
30921
31903
  "Applies to ",
30922
31904
  scope === "section" ? "this section" : "the whole document",
30923
31905
  " and turns mirrored margins off for the whole document."
30924
31906
  ] }),
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" })
31907
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6 }, children: [
31908
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => setCustomOpen(false), style: { ...pillBtn, background: T.popoverBg, color: T.fg }, children: "Cancel" }),
31909
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: applyCustom, disabled: !valid, style: pillBtn, children: "Apply" })
30928
31910
  ] })
30929
31911
  ]
30930
31912
  }
@@ -30937,11 +31919,11 @@ function PageSizeMenu({
30937
31919
  open,
30938
31920
  onOpenChange
30939
31921
  }) {
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(() => {
31922
+ const [customOpen, setCustomOpen] = useState2(false);
31923
+ const [values, setValues] = useState2({ width: "8.5", height: "11" });
31924
+ const rootRef = useRef2(null);
31925
+ const [dialogPosition, setDialogPosition] = useState2({ left: 8, top: 8 });
31926
+ useEffect2(() => {
30945
31927
  if (!customOpen) return;
30946
31928
  const positionDialog = () => {
30947
31929
  const trigger = rootRef.current?.querySelector("[data-dxw-layout-menu-trigger]");
@@ -30977,9 +31959,9 @@ function PageSizeMenu({
30977
31959
  onApply({ size: { width: Number(values.width), height: Number(values.height) } });
30978
31960
  setCustomOpen(false);
30979
31961
  };
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(
31962
+ const field = (side, label) => /* @__PURE__ */ jsxs2("label", { style: { display: "grid", gridTemplateColumns: "54px 1fr", gap: 8, alignItems: "center", fontSize: 12 }, children: [
31963
+ /* @__PURE__ */ jsx2("span", { children: label }),
31964
+ /* @__PURE__ */ jsx2(
30983
31965
  "input",
30984
31966
  {
30985
31967
  "aria-label": `Page ${side} (inches)`,
@@ -30997,8 +31979,8 @@ function PageSizeMenu({
30997
31979
  }
30998
31980
  )
30999
31981
  ] });
31000
- return /* @__PURE__ */ jsxs("span", { ref: rootRef, style: { position: "relative", display: "inline-flex" }, children: [
31001
- /* @__PURE__ */ jsx(
31982
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, style: { position: "relative", display: "inline-flex" }, children: [
31983
+ /* @__PURE__ */ jsx2(
31002
31984
  LayoutMenu,
31003
31985
  {
31004
31986
  name: "size",
@@ -31010,9 +31992,9 @@ function PageSizeMenu({
31010
31992
  value: size.value,
31011
31993
  label: size.label,
31012
31994
  description: size.description,
31013
- preview: /* @__PURE__ */ jsx(PagePreview, { kind: "size", width: size.width, height: size.height })
31995
+ preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "size", width: size.width, height: size.height })
31014
31996
  })),
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 }) }
31997
+ { 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
31998
  ],
31017
31999
  onPick: (value) => {
31018
32000
  if (value === "custom") {
@@ -31025,7 +32007,7 @@ function PageSizeMenu({
31025
32007
  }
31026
32008
  }
31027
32009
  ),
31028
- customOpen && /* @__PURE__ */ jsxs(
32010
+ customOpen && /* @__PURE__ */ jsxs2(
31029
32011
  "div",
31030
32012
  {
31031
32013
  role: "dialog",
@@ -31047,17 +32029,17 @@ function PageSizeMenu({
31047
32029
  gap: 7
31048
32030
  },
31049
32031
  children: [
31050
- /* @__PURE__ */ jsx("strong", { style: { fontSize: 13 }, children: "Custom Paper Size" }),
32032
+ /* @__PURE__ */ jsx2("strong", { style: { fontSize: 13 }, children: "Custom Paper Size" }),
31051
32033
  field("width", "Width"),
31052
32034
  field("height", "Height"),
31053
- /* @__PURE__ */ jsxs("span", { style: { color: T.muted, fontSize: 11 }, children: [
32035
+ /* @__PURE__ */ jsxs2("span", { style: { color: T.muted, fontSize: 11 }, children: [
31054
32036
  "Applies to ",
31055
32037
  scope === "section" ? "this section" : "the whole document",
31056
32038
  "."
31057
32039
  ] }),
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" })
32040
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6 }, children: [
32041
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => setCustomOpen(false), style: { ...pillBtn, background: T.popoverBg, color: T.fg }, children: "Cancel" }),
32042
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: applyCustom, disabled: !valid, style: pillBtn, children: "Apply" })
31061
32043
  ] })
31062
32044
  ]
31063
32045
  }
@@ -31065,80 +32047,111 @@ function PageSizeMenu({
31065
32047
  ] });
31066
32048
  }
31067
32049
  function LayoutTab({ api, showArrange }) {
31068
- const [scope, setScope] = useState("document");
31069
- const [openMenu, setOpenMenu] = useState(null);
31070
- const rootRef = useRef(null);
32050
+ const [scope, setScope] = useState2("document");
32051
+ const [section, setSection] = useState2(null);
32052
+ const [objectSelected, setObjectSelected] = useState2(false);
32053
+ const [openMenu, setOpenMenu] = useState2(null);
32054
+ const rootRef = useRef2(null);
32055
+ useEffect2(() => {
32056
+ const refresh = () => {
32057
+ setSection(api?.getSectionContext() ?? null);
32058
+ setObjectSelected(api?.hasSelectedObject() ?? false);
32059
+ };
32060
+ refresh();
32061
+ document.addEventListener("dxw-selection", refresh);
32062
+ document.addEventListener("dxw-object-selection", refresh);
32063
+ return () => {
32064
+ document.removeEventListener("dxw-selection", refresh);
32065
+ document.removeEventListener("dxw-object-selection", refresh);
32066
+ };
32067
+ }, [api]);
31071
32068
  const set = (patch) => api?.setPageLayout(patch, scope);
31072
32069
  const setLn = (patch) => api?.setLineNumbering(patch, scope);
31073
32070
  const menuState = (name) => ({
31074
32071
  open: openMenu === name,
31075
32072
  onOpenChange: (open) => setOpenMenu(open ? name : null)
31076
32073
  });
31077
- return /* @__PURE__ */ jsxs(
32074
+ return /* @__PURE__ */ jsxs2(
31078
32075
  "span",
31079
32076
  {
31080
32077
  ref: rootRef,
31081
32078
  className: "dxw-layout-ribbon",
31082
32079
  "data-dxw-layout-ribbon": "",
31083
- style: { display: "flex", flex: "1 1 640px", minWidth: 0, alignItems: "center", flexWrap: "wrap", gap: 2 },
32080
+ style: {
32081
+ display: "flex",
32082
+ flex: "0 0 100%",
32083
+ order: 2,
32084
+ minWidth: 0,
32085
+ boxSizing: "border-box",
32086
+ alignItems: "center",
32087
+ flexWrap: "wrap",
32088
+ gap: 2,
32089
+ paddingTop: 4,
32090
+ marginTop: 2,
32091
+ borderTop: `1px solid ${T.border}`
32092
+ },
31084
32093
  children: [
31085
- /* @__PURE__ */ jsx(
32094
+ /* @__PURE__ */ jsx2(
31086
32095
  ToolbarMenuSelect,
31087
32096
  {
31088
32097
  title: "Apply layout changes to",
31089
32098
  ariaLabel: "Apply layout changes to",
31090
32099
  value: scope,
31091
- width: 118,
31092
- menuWidth: 170,
32100
+ width: section ? 160 : 142,
32101
+ menuWidth: 205,
31093
32102
  options: [
31094
32103
  { value: "document", label: "Whole document" },
31095
- { value: "section", label: "This section" }
32104
+ {
32105
+ value: "section",
32106
+ label: section ? `This section \xB7 ${section.index} of ${section.count}` : "This section"
32107
+ }
31096
32108
  ],
31097
32109
  onChange: (value) => setScope(value),
31098
32110
  style: { maxWidth: "100%" }
31099
32111
  }
31100
32112
  ),
31101
- /* @__PURE__ */ jsx(Sep, {}),
31102
- /* @__PURE__ */ jsx(MarginMenu, { scope, onApply: set, ...menuState("margins") }),
31103
- /* @__PURE__ */ jsx(
32113
+ /* @__PURE__ */ jsx2(Sep, {}),
32114
+ /* @__PURE__ */ jsx2(MarginMenu, { scope, onApply: set, ...menuState("margins") }),
32115
+ /* @__PURE__ */ jsx2(
31104
32116
  LayoutMenu,
31105
32117
  {
31106
32118
  name: "orientation",
31107
32119
  label: "Orientation",
31108
32120
  ...menuState("orientation"),
31109
32121
  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 }) }
32122
+ { value: "portrait", label: "Portrait", description: "Vertical page", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "orientation" }) },
32123
+ { value: "landscape", label: "Landscape", description: "Horizontal page", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "orientation", width: 11, height: 8.5 }) }
31112
32124
  ],
31113
32125
  onPick: (value) => set({ orientation: value })
31114
32126
  }
31115
32127
  ),
31116
- /* @__PURE__ */ jsx(PageSizeMenu, { scope, onApply: set, ...menuState("size") }),
31117
- /* @__PURE__ */ jsx(
32128
+ /* @__PURE__ */ jsx2(PageSizeMenu, { scope, onApply: set, ...menuState("size") }),
32129
+ /* @__PURE__ */ jsx2(
31118
32130
  LayoutMenu,
31119
32131
  {
31120
32132
  name: "columns",
31121
- label: "Columns",
32133
+ label: "Columns & divider",
31122
32134
  ...menuState("columns"),
31123
32135
  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 }) }
32136
+ { value: "1", label: "One", description: "Single text column", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "columns", columns: 1 }) },
32137
+ { value: "2", label: "Two", description: "Two equal columns", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "columns", columns: 2 }) },
32138
+ { 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 }) },
32139
+ { value: "3", label: "Three", description: "Three equal columns", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "columns", columns: 3 }) }
31127
32140
  ],
31128
- onPick: (value) => set({ columns: parseInt(value, 10) })
32141
+ onPick: (value) => set({ columns: parseInt(value, 10), columnSeparator: value === "2-divider" })
31129
32142
  }
31130
32143
  ),
31131
- /* @__PURE__ */ jsx(
32144
+ /* @__PURE__ */ jsx2(
31132
32145
  LayoutMenu,
31133
32146
  {
31134
32147
  name: "page-border",
31135
32148
  label: "Page border",
31136
32149
  ...menuState("page-border"),
31137
32150
  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" }) }
32151
+ { value: "none", label: "None", description: "No page border", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "page-border", border: "none" }) },
32152
+ { value: "thin", label: "Thin box", description: "\xBD pt solid line", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "page-border", border: "thin" }) },
32153
+ { value: "thick", label: "Thick box", description: "1\xBD pt solid line", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "page-border", border: "thick" }) },
32154
+ { value: "accent", label: "Accent box", description: "Blue 1 pt line", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "page-border", border: "accent" }) }
31142
32155
  ],
31143
32156
  onPick: (value) => {
31144
32157
  if (value === "none") set({ pageBorders: null });
@@ -31148,19 +32161,19 @@ function LayoutTab({ api, showArrange }) {
31148
32161
  }
31149
32162
  }
31150
32163
  ),
31151
- /* @__PURE__ */ jsx(
32164
+ /* @__PURE__ */ jsx2(
31152
32165
  LayoutMenu,
31153
32166
  {
31154
32167
  name: "line-numbers",
31155
32168
  label: "Line numbers",
31156
32169
  ...menuState("line-numbers"),
31157
32170
  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 }) }
32171
+ { value: "off", label: "None", description: "Hide line numbers", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers" }) },
32172
+ { value: "continuous", label: "Continuous", description: "Number every line continuously", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
32173
+ { value: "eachPage", label: "Restart each page", description: "Start at 1 on every page", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
32174
+ { value: "eachSection", label: "Restart each section", description: "Start at 1 in each section", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
32175
+ { value: "by5", label: "Count by 5", description: "Show every fifth line", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers", lineNumbers: true }) },
32176
+ { value: "by10", label: "Count by 10", description: "Show every tenth line", preview: /* @__PURE__ */ jsx2(PagePreview, { kind: "line-numbers", lineNumbers: true }) }
31164
32177
  ],
31165
32178
  onPick: (value) => {
31166
32179
  if (value === "off") setLn({ enabled: false });
@@ -31172,9 +32185,9 @@ function LayoutTab({ api, showArrange }) {
31172
32185
  }
31173
32186
  }
31174
32187
  ),
31175
- showArrange && /* @__PURE__ */ jsxs(Fragment2, { children: [
31176
- /* @__PURE__ */ jsx(Sep, {}),
31177
- /* @__PURE__ */ jsx(
32188
+ showArrange && objectSelected && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32189
+ /* @__PURE__ */ jsx2(Sep, {}),
32190
+ /* @__PURE__ */ jsx2(
31178
32191
  ActionMenu,
31179
32192
  {
31180
32193
  label: "Align",
@@ -31187,7 +32200,7 @@ function LayoutTab({ api, showArrange }) {
31187
32200
  onPick: (value) => api?.arrangeObject(value)
31188
32201
  }
31189
32202
  ),
31190
- /* @__PURE__ */ jsx(
32203
+ /* @__PURE__ */ jsx2(
31191
32204
  ActionMenu,
31192
32205
  {
31193
32206
  label: "Rotate",
@@ -31197,7 +32210,7 @@ function LayoutTab({ api, showArrange }) {
31197
32210
  onPick: (value) => api?.arrangeObject(value)
31198
32211
  }
31199
32212
  ),
31200
- /* @__PURE__ */ jsx(
32213
+ /* @__PURE__ */ jsx2(
31201
32214
  ActionMenu,
31202
32215
  {
31203
32216
  label: "Arrange",
@@ -31221,12 +32234,17 @@ function DocxToolbar({
31221
32234
  style
31222
32235
  }) {
31223
32236
  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);
32237
+ const [tab, setTab] = useState2("home");
32238
+ const [helpOpen, setHelpOpen] = useState2(false);
32239
+ const apple = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform);
32240
+ const shortcut = (key) => apple ? `\u2318${key}` : `Ctrl+${key}`;
32241
+ const closeHelp = useCallback(() => setHelpOpen(false), []);
32242
+ const iconInput = useRef2(null);
32243
+ const modelInput = useRef2(null);
32244
+ const objectInput = useRef2(null);
32245
+ const helpTrigger = useRef2(null);
32246
+ const [tip, setTip] = useState2(null);
32247
+ const tipTimer = useRef2(null);
31230
32248
  const onTipOver = useCallback((e) => {
31231
32249
  const el16 = e.target.closest("[title], [data-tip]");
31232
32250
  if (!el16) return;
@@ -31247,14 +32265,25 @@ function DocxToolbar({
31247
32265
  if (tipTimer.current) clearTimeout(tipTimer.current);
31248
32266
  setTip(null);
31249
32267
  }, []);
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(() => {
32268
+ const [fmt, setFmt] = useState2(null);
32269
+ const [curStyle, setCurStyle] = useState2(null);
32270
+ const [listKind, setListKind] = useState2(null);
32271
+ const savedRange = useRef2(null);
32272
+ const imageInput = useRef2(null);
32273
+ const rootRef = useRef2(null);
32274
+ const [tier, setTier] = useState2(0);
32275
+ useEffect2(() => {
32276
+ if (!on("help")) return;
32277
+ const keydown = (event) => {
32278
+ if (event.key === "F1" || (event.metaKey || event.ctrlKey) && event.key === "/") {
32279
+ event.preventDefault();
32280
+ setHelpOpen(true);
32281
+ }
32282
+ };
32283
+ document.addEventListener("keydown", keydown);
32284
+ return () => document.removeEventListener("keydown", keydown);
32285
+ }, [features]);
32286
+ useEffect2(() => {
31258
32287
  const el16 = rootRef.current;
31259
32288
  if (!el16 || typeof ResizeObserver === "undefined") return;
31260
32289
  const measure = () => {
@@ -31279,7 +32308,7 @@ function DocxToolbar({
31279
32308
  setCurStyle(api?.getParagraphStyleId?.() ?? null);
31280
32309
  setListKind(api?.getListType?.() ?? null);
31281
32310
  }, [api]);
31282
- useEffect(() => {
32311
+ useEffect2(() => {
31283
32312
  document.addEventListener("selectionchange", refresh);
31284
32313
  document.addEventListener("dxw-selection", refresh);
31285
32314
  return () => {
@@ -31307,22 +32336,22 @@ function DocxToolbar({
31307
32336
  if (on("history"))
31308
32337
  groups.push({
31309
32338
  key: "history",
31310
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31311
- /* @__PURE__ */ jsx(Btn, { label: "\u21B6", title: "Undo (\u2318Z)", onClick: () => {
32339
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32340
+ /* @__PURE__ */ jsx2(Btn, { label: "\u21B6", title: "Undo (\u2318Z)", onClick: () => {
31312
32341
  api?.undo();
31313
32342
  refresh();
31314
32343
  } }),
31315
- /* @__PURE__ */ jsx(Btn, { label: "\u21B7", title: "Redo (\u21E7\u2318Z)", onClick: () => {
32344
+ /* @__PURE__ */ jsx2(Btn, { label: "\u21B7", title: "Redo (\u21E7\u2318Z)", onClick: () => {
31316
32345
  api?.redo();
31317
32346
  refresh();
31318
32347
  } }),
31319
- /* @__PURE__ */ jsx(Sep, {})
32348
+ /* @__PURE__ */ jsx2(Sep, {})
31320
32349
  ] })
31321
32350
  });
31322
32351
  if (on("styles"))
31323
32352
  groups.push({
31324
32353
  key: "styles",
31325
- node: /* @__PURE__ */ jsx(
32354
+ node: /* @__PURE__ */ jsx2(
31326
32355
  ToolbarMenuSelect,
31327
32356
  {
31328
32357
  title: "Paragraph style",
@@ -31346,7 +32375,7 @@ function DocxToolbar({
31346
32375
  if (on("font"))
31347
32376
  groups.push({
31348
32377
  key: "font",
31349
- node: /* @__PURE__ */ jsx(
32378
+ node: /* @__PURE__ */ jsx2(
31350
32379
  ToolbarMenuSelect,
31351
32380
  {
31352
32381
  title: "Font",
@@ -31366,8 +32395,8 @@ function DocxToolbar({
31366
32395
  if (on("size"))
31367
32396
  groups.push({
31368
32397
  key: "size",
31369
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31370
- /* @__PURE__ */ jsx(
32398
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32399
+ /* @__PURE__ */ jsx2(
31371
32400
  ToolbarMenuSelect,
31372
32401
  {
31373
32402
  title: "Font size",
@@ -31379,43 +32408,43 @@ function DocxToolbar({
31379
32408
  onChange: (value) => value && apply({ fontSizePt: parseFloat(value) })
31380
32409
  }
31381
32410
  ),
31382
- /* @__PURE__ */ jsx(Sep, {})
32411
+ /* @__PURE__ */ jsx2(Sep, {})
31383
32412
  ] })
31384
32413
  });
31385
32414
  if (on("format"))
31386
32415
  groups.push({
31387
32416
  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(
32417
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32418
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2("b", { children: "B" }), title: "Bold (\u2318B)", active: !!fmt?.bold, onClick: () => apply({ bold: !fmt?.bold }) }),
32419
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2("i", { children: "I" }), title: "Italic", active: !!fmt?.italic, onClick: () => apply({ italic: !fmt?.italic }) }),
32420
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2("u", { children: "U" }), title: "Underline", active: !!fmt?.underline, onClick: () => apply({ underline: !fmt?.underline }) }),
32421
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2("s", { children: "S" }), title: "Strikethrough", active: !!fmt?.strike, onClick: () => apply({ strike: !fmt?.strike }) }),
32422
+ /* @__PURE__ */ jsx2(
31394
32423
  Btn,
31395
32424
  {
31396
- label: /* @__PURE__ */ jsxs("span", { style: { fontSize: 12 }, children: [
32425
+ label: /* @__PURE__ */ jsxs2("span", { style: { fontSize: 12 }, children: [
31397
32426
  "x",
31398
- /* @__PURE__ */ jsx("sup", { style: { fontSize: 9 }, children: "2" })
32427
+ /* @__PURE__ */ jsx2("sup", { style: { fontSize: 9 }, children: "2" })
31399
32428
  ] }),
31400
32429
  title: "Superscript",
31401
32430
  active: fmt?.verticalAlign === "superscript",
31402
32431
  onClick: () => apply({ verticalAlign: fmt?.verticalAlign === "superscript" ? null : "superscript" })
31403
32432
  }
31404
32433
  ),
31405
- /* @__PURE__ */ jsx(
32434
+ /* @__PURE__ */ jsx2(
31406
32435
  Btn,
31407
32436
  {
31408
- label: /* @__PURE__ */ jsxs("span", { style: { fontSize: 12 }, children: [
32437
+ label: /* @__PURE__ */ jsxs2("span", { style: { fontSize: 12 }, children: [
31409
32438
  "x",
31410
- /* @__PURE__ */ jsx("sub", { style: { fontSize: 9 }, children: "2" })
32439
+ /* @__PURE__ */ jsx2("sub", { style: { fontSize: 9 }, children: "2" })
31411
32440
  ] }),
31412
32441
  title: "Subscript",
31413
32442
  active: fmt?.verticalAlign === "subscript",
31414
32443
  onClick: () => apply({ verticalAlign: fmt?.verticalAlign === "subscript" ? null : "subscript" })
31415
32444
  }
31416
32445
  ),
31417
- /* @__PURE__ */ jsx(Btn, { label: /* @__PURE__ */ jsx(ClearFormatIcon, {}), title: "Clear formatting", onClick: () => apply({ clear: true }) }),
31418
- /* @__PURE__ */ jsx(
32446
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2(ClearFormatIcon, {}), title: "Clear formatting", onClick: () => apply({ clear: true }) }),
32447
+ /* @__PURE__ */ jsx2(
31419
32448
  ActionMenu,
31420
32449
  {
31421
32450
  label: "Aa",
@@ -31433,12 +32462,12 @@ function DocxToolbar({
31433
32462
  if (on("color"))
31434
32463
  groups.push({
31435
32464
  key: "color",
31436
- node: /* @__PURE__ */ jsx(
32465
+ node: /* @__PURE__ */ jsx2(
31437
32466
  ColorMenu,
31438
32467
  {
31439
32468
  current: fmt?.color && fmt.color !== "auto" ? fmt.color : "#000000",
31440
32469
  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" }),
32470
+ 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
32471
  onPick: (value) => apply({ color: value })
31443
32472
  }
31444
32473
  )
@@ -31446,34 +32475,34 @@ function DocxToolbar({
31446
32475
  if (on("highlight"))
31447
32476
  groups.push({
31448
32477
  key: "highlight",
31449
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31450
- /* @__PURE__ */ jsx(HighlightMenu, { current: fmt?.highlight, onPick: (v) => apply({ highlight: v }) }),
31451
- /* @__PURE__ */ jsx(Sep, {})
32478
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32479
+ /* @__PURE__ */ jsx2(HighlightMenu, { current: fmt?.highlight, onPick: (v) => apply({ highlight: v }) }),
32480
+ /* @__PURE__ */ jsx2(Sep, {})
31452
32481
  ] })
31453
32482
  });
31454
32483
  if (on("alignment"))
31455
32484
  groups.push({
31456
32485
  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, {})
32486
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32487
+ /* @__PURE__ */ jsx2(Btn, { label: "\u2261", title: "Align left", onClick: () => api?.setAlignment("left") }),
32488
+ /* @__PURE__ */ jsx2(Btn, { label: "\u2263", title: "Center", onClick: () => api?.setAlignment("center") }),
32489
+ /* @__PURE__ */ jsx2(Btn, { label: "\u2262", title: "Align right", onClick: () => api?.setAlignment("right") }),
32490
+ /* @__PURE__ */ jsx2(Btn, { label: "\u2630", title: "Justify", onClick: () => api?.setAlignment("justify") }),
32491
+ /* @__PURE__ */ jsx2(Sep, {})
31463
32492
  ] })
31464
32493
  });
31465
32494
  if (on("indent"))
31466
32495
  groups.push({
31467
32496
  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) })
32497
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32498
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2(IndentIcon, { dir: -1 }), title: "Decrease indent", onClick: () => api?.adjustIndent(-1) }),
32499
+ /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2(IndentIcon, { dir: 1 }), title: "Increase indent", onClick: () => api?.adjustIndent(1) })
31471
32500
  ] })
31472
32501
  });
31473
32502
  if (on("spacing"))
31474
32503
  groups.push({
31475
32504
  key: "spacing",
31476
- node: /* @__PURE__ */ jsx(
32505
+ node: /* @__PURE__ */ jsx2(
31477
32506
  ActionMenu,
31478
32507
  {
31479
32508
  label: "\u2195",
@@ -31481,14 +32510,30 @@ function DocxToolbar({
31481
32510
  width: 44,
31482
32511
  groups: [
31483
32512
  { label: "Line spacing", items: [["l:1", "Single"], ["l:1.15", "1.15"], ["l:1.5", "1.5"], ["l:2", "Double"]] },
32513
+ { 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
32514
  { label: "Paragraph", items: [["b:add", "Add space before"], ["b:none", "Remove space before"], ["a:add", "Add space after"], ["a:none", "Remove space after"]] }
31485
32515
  ],
31486
32516
  onPick: (v) => {
31487
32517
  if (v.startsWith("l:")) api?.setParagraphSpacing({ lineMultiple: parseFloat(v.slice(2)) });
32518
+ else if (v === "e:custom") {
32519
+ const anchor = rootRef.current;
32520
+ if (!anchor) return;
32521
+ void requestTextInputDialog(anchor, {
32522
+ title: "Exact line height",
32523
+ label: "Line height (points)",
32524
+ value: "24",
32525
+ placeholder: "24",
32526
+ submitLabel: "Apply"
32527
+ }).then((next) => {
32528
+ if (next === null) return;
32529
+ const points = Number(next.trim());
32530
+ if (Number.isFinite(points) && points > 0) api?.setParagraphSpacing({ exactLinePt: points });
32531
+ });
32532
+ } else if (v.startsWith("e:")) api?.setParagraphSpacing({ exactLinePt: parseFloat(v.slice(2)) });
31488
32533
  else if (v === "b:add") api?.setParagraphSpacing({ beforePt: 10 });
31489
- else if (v === "b:none") api?.setParagraphSpacing({ beforePt: null });
32534
+ else if (v === "b:none") api?.setParagraphSpacing({ beforePt: 0 });
31490
32535
  else if (v === "a:add") api?.setParagraphSpacing({ afterPt: 10 });
31491
- else if (v === "a:none") api?.setParagraphSpacing({ afterPt: null });
32536
+ else if (v === "a:none") api?.setParagraphSpacing({ afterPt: 0 });
31492
32537
  }
31493
32538
  }
31494
32539
  )
@@ -31496,11 +32541,11 @@ function DocxToolbar({
31496
32541
  if (on("lists"))
31497
32542
  groups.push({
31498
32543
  key: "lists",
31499
- node: /* @__PURE__ */ jsxs(Fragment2, { children: [
31500
- /* @__PURE__ */ jsx(
32544
+ node: /* @__PURE__ */ jsxs2(Fragment2, { children: [
32545
+ /* @__PURE__ */ jsx2(
31501
32546
  Btn,
31502
32547
  {
31503
- label: /* @__PURE__ */ jsx(BulletListIcon, {}),
32548
+ label: /* @__PURE__ */ jsx2(BulletListIcon, {}),
31504
32549
  title: "Bulleted list",
31505
32550
  active: listKind === "bullet",
31506
32551
  onClick: () => {
@@ -31509,10 +32554,10 @@ function DocxToolbar({
31509
32554
  }
31510
32555
  }
31511
32556
  ),
31512
- /* @__PURE__ */ jsx(
32557
+ /* @__PURE__ */ jsx2(
31513
32558
  Btn,
31514
32559
  {
31515
- label: /* @__PURE__ */ jsx(NumberListIcon, {}),
32560
+ label: /* @__PURE__ */ jsx2(NumberListIcon, {}),
31516
32561
  title: "Numbered list",
31517
32562
  active: listKind === "number",
31518
32563
  onClick: () => {
@@ -31521,18 +32566,18 @@ function DocxToolbar({
31521
32566
  }
31522
32567
  }
31523
32568
  ),
31524
- /* @__PURE__ */ jsx(Sep, {})
32569
+ /* @__PURE__ */ jsx2(Sep, {})
31525
32570
  ] })
31526
32571
  });
31527
32572
  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
32573
  const inline = groups.filter((g) => !overflowKeys.has(g.key));
31529
32574
  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)) })
32575
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
32576
+ inline.map((g) => /* @__PURE__ */ jsx2(Fragment, { children: g.node }, g.key)),
32577
+ overflow.length > 0 && /* @__PURE__ */ jsx2(OverflowMenu, { children: overflow.map((g) => /* @__PURE__ */ jsx2(Fragment, { children: g.node }, g.key)) })
31533
32578
  ] });
31534
32579
  };
31535
- return /* @__PURE__ */ jsxs(
32580
+ return /* @__PURE__ */ jsxs2(
31536
32581
  "div",
31537
32582
  {
31538
32583
  ref: rootRef,
@@ -31559,7 +32604,7 @@ function DocxToolbar({
31559
32604
  ...style
31560
32605
  },
31561
32606
  children: [
31562
- tip && /* @__PURE__ */ jsx(
32607
+ tip && /* @__PURE__ */ jsx2(
31563
32608
  "div",
31564
32609
  {
31565
32610
  style: {
@@ -31580,55 +32625,80 @@ function DocxToolbar({
31580
32625
  children: tip.text
31581
32626
  }
31582
32627
  ),
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"
32628
+ mode === "advanced" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32629
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: 2, marginRight: 8 }, children: [
32630
+ ["home", "insert", "draw", "layout"].filter((t) => (t !== "draw" || on("drawing")) && (t !== "layout" || on("layout"))).map((t) => /* @__PURE__ */ jsx2(
32631
+ "button",
32632
+ {
32633
+ "data-tab": t,
32634
+ onMouseDown: (e) => e.preventDefault(),
32635
+ onClick: () => setTab(t),
32636
+ style: {
32637
+ border: "none",
32638
+ background: tab === t ? T.tabActiveBg : "transparent",
32639
+ color: tab === t ? T.accent : T.fg,
32640
+ font: "600 12.5px system-ui, sans-serif",
32641
+ padding: "5px 10px",
32642
+ borderRadius: 6,
32643
+ cursor: "pointer",
32644
+ textTransform: "capitalize"
32645
+ },
32646
+ children: t
31599
32647
  },
31600
- children: t
31601
- },
31602
- t
31603
- )) }),
31604
- /* @__PURE__ */ jsx(Sep, {})
32648
+ t
32649
+ )),
32650
+ on("help") && /* @__PURE__ */ jsx2(
32651
+ "button",
32652
+ {
32653
+ ref: helpTrigger,
32654
+ type: "button",
32655
+ title: `Help and keyboard shortcuts (${shortcut("/")})`,
32656
+ "aria-haspopup": "dialog",
32657
+ "aria-expanded": helpOpen,
32658
+ "data-dxw-help-trigger": "",
32659
+ onMouseDown: (event) => event.preventDefault(),
32660
+ onClick: () => setHelpOpen(true),
32661
+ style: {
32662
+ border: "none",
32663
+ background: "transparent",
32664
+ color: T.fg,
32665
+ font: "600 12.5px system-ui, sans-serif",
32666
+ padding: "5px 10px",
32667
+ borderRadius: 6,
32668
+ cursor: "pointer"
32669
+ },
32670
+ children: "Help"
32671
+ }
32672
+ )
32673
+ ] }),
32674
+ /* @__PURE__ */ jsx2(Sep, {})
31605
32675
  ] }),
31606
32676
  (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") })
32677
+ mode === "advanced" && tab === "insert" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32678
+ on("coverPage") && /* @__PURE__ */ jsx2(CoverPageMenu, { api }),
32679
+ on("table") && /* @__PURE__ */ jsx2(TableMenu, { api }),
32680
+ on("image") && /* @__PURE__ */ jsx2(Btn, { label: /* @__PURE__ */ jsx2(ImageIcon, {}), title: "Insert image", onClick: () => imageInput.current?.click() }),
32681
+ on("icon") && /* @__PURE__ */ jsx2(Btn, { label: "Icons", title: "Insert SVG icon", onClick: () => iconInput.current?.click() }),
32682
+ on("screenshot") && /* @__PURE__ */ jsx2(ScreenshotButton, { api }),
32683
+ tier === 0 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
32684
+ on("model3D") && /* @__PURE__ */ jsx2(Btn, { label: "3D Models", title: "Insert a GLB 3D model", onClick: () => modelInput.current?.click() }),
32685
+ on("smartArt") && /* @__PURE__ */ jsx2(SmartArtMenu, { api }),
32686
+ on("chart") && /* @__PURE__ */ jsx2(ChartMenu, { api }),
32687
+ on("media") && /* @__PURE__ */ jsx2(MediaMenu, { api }),
32688
+ on("shape") && /* @__PURE__ */ jsx2(ShapeMenu, { api }),
32689
+ on("textBox") && /* @__PURE__ */ jsx2(TextBoxMenu, { api }),
32690
+ on("wordArt") && /* @__PURE__ */ jsx2(WordArtMenu, { api }),
32691
+ on("link") && /* @__PURE__ */ jsx2(LinkMenu, { api }),
32692
+ on("comment") && /* @__PURE__ */ jsx2(CommentMenu, { api }),
32693
+ on("footnote") && /* @__PURE__ */ jsx2(FootnoteMenu, { api }),
32694
+ on("bookmark") && /* @__PURE__ */ jsx2(BookmarkMenu, { api }),
32695
+ on("crossReference") && /* @__PURE__ */ jsx2(CrossReferenceMenu, { api }),
32696
+ on("headerFooter") && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32697
+ /* @__PURE__ */ jsx2(Btn, { label: "Header", title: "Edit header", onClick: () => api?.openHeaderFooter("header") }),
32698
+ /* @__PURE__ */ jsx2(Btn, { label: "Footer", title: "Edit footer", onClick: () => api?.openHeaderFooter("footer") })
31629
32699
  ] }),
31630
- /* @__PURE__ */ jsx(Sep, {}),
31631
- on("pageNumber") && /* @__PURE__ */ jsx(
32700
+ /* @__PURE__ */ jsx2(Sep, {}),
32701
+ on("pageNumber") && /* @__PURE__ */ jsx2(
31632
32702
  ActionMenu,
31633
32703
  {
31634
32704
  label: "Page number",
@@ -31641,9 +32711,9 @@ function DocxToolbar({
31641
32711
  }
31642
32712
  }
31643
32713
  ),
31644
- on("break") && /* @__PURE__ */ jsxs(Fragment2, { children: [
31645
- /* @__PURE__ */ jsx(Btn, { label: "Blank page", title: "Insert blank page", onClick: () => api?.insertBlankPage() }),
31646
- /* @__PURE__ */ jsx(
32714
+ on("break") && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32715
+ /* @__PURE__ */ jsx2(Btn, { label: "Blank page", title: "Insert blank page", onClick: () => api?.insertBlankPage() }),
32716
+ /* @__PURE__ */ jsx2(
31647
32717
  ActionMenu,
31648
32718
  {
31649
32719
  label: "Break",
@@ -31662,7 +32732,7 @@ function DocxToolbar({
31662
32732
  }
31663
32733
  )
31664
32734
  ] }),
31665
- on("dateTime") && /* @__PURE__ */ jsx(
32735
+ on("dateTime") && /* @__PURE__ */ jsx2(
31666
32736
  ActionMenu,
31667
32737
  {
31668
32738
  label: "Date & time",
@@ -31681,7 +32751,7 @@ function DocxToolbar({
31681
32751
  }
31682
32752
  }
31683
32753
  ),
31684
- on("field") && /* @__PURE__ */ jsx(
32754
+ on("field") && /* @__PURE__ */ jsx2(
31685
32755
  ActionMenu,
31686
32756
  {
31687
32757
  label: "Field",
@@ -31691,9 +32761,9 @@ function DocxToolbar({
31691
32761
  onPick: (value) => api?.insertField(`${value} \\* MERGEFORMAT`)
31692
32762
  }
31693
32763
  ),
31694
- on("equation") && /* @__PURE__ */ jsx(EquationMenu, { api }),
31695
- on("symbol") && /* @__PURE__ */ jsx(SymbolMenu, { api }),
31696
- on("dropCap") && /* @__PURE__ */ jsx(
32764
+ on("equation") && /* @__PURE__ */ jsx2(EquationMenu, { api }),
32765
+ on("symbol") && /* @__PURE__ */ jsx2(SymbolMenu, { api }),
32766
+ on("dropCap") && /* @__PURE__ */ jsx2(
31697
32767
  ActionMenu,
31698
32768
  {
31699
32769
  label: "Drop cap",
@@ -31703,25 +32773,25 @@ function DocxToolbar({
31703
32773
  onPick: (value) => api?.setDropCap(value === "none" ? null : value)
31704
32774
  }
31705
32775
  ),
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") })
32776
+ on("object") && /* @__PURE__ */ jsx2(Btn, { label: "Object", title: "Embed a file in this document", onClick: () => objectInput.current?.click() })
32777
+ ] }) : /* @__PURE__ */ jsxs2(OverflowMenu, { children: [
32778
+ on("model3D") && /* @__PURE__ */ jsx2(Btn, { label: "3D Models", title: "Insert a GLB 3D model", onClick: () => modelInput.current?.click() }),
32779
+ on("smartArt") && /* @__PURE__ */ jsx2(SmartArtMenu, { api }),
32780
+ on("chart") && /* @__PURE__ */ jsx2(ChartMenu, { api }),
32781
+ on("media") && /* @__PURE__ */ jsx2(MediaMenu, { api }),
32782
+ on("shape") && /* @__PURE__ */ jsx2(ShapeMenu, { api }),
32783
+ on("textBox") && /* @__PURE__ */ jsx2(TextBoxMenu, { api }),
32784
+ on("wordArt") && /* @__PURE__ */ jsx2(WordArtMenu, { api }),
32785
+ on("link") && /* @__PURE__ */ jsx2(LinkMenu, { api }),
32786
+ on("comment") && /* @__PURE__ */ jsx2(CommentMenu, { api }),
32787
+ on("footnote") && /* @__PURE__ */ jsx2(FootnoteMenu, { api }),
32788
+ on("bookmark") && /* @__PURE__ */ jsx2(BookmarkMenu, { api }),
32789
+ on("crossReference") && /* @__PURE__ */ jsx2(CrossReferenceMenu, { api }),
32790
+ on("headerFooter") && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32791
+ /* @__PURE__ */ jsx2(Btn, { label: "Header", title: "Edit header", onClick: () => api?.openHeaderFooter("header") }),
32792
+ /* @__PURE__ */ jsx2(Btn, { label: "Footer", title: "Edit footer", onClick: () => api?.openHeaderFooter("footer") })
31723
32793
  ] }),
31724
- on("pageNumber") && /* @__PURE__ */ jsx(
32794
+ on("pageNumber") && /* @__PURE__ */ jsx2(
31725
32795
  ActionMenu,
31726
32796
  {
31727
32797
  label: "Page number",
@@ -31734,9 +32804,9 @@ function DocxToolbar({
31734
32804
  }
31735
32805
  }
31736
32806
  ),
31737
- on("break") && /* @__PURE__ */ jsxs(Fragment2, { children: [
31738
- /* @__PURE__ */ jsx(Btn, { label: "Blank page", title: "Insert blank page", onClick: () => api?.insertBlankPage() }),
31739
- /* @__PURE__ */ jsx(
32807
+ on("break") && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32808
+ /* @__PURE__ */ jsx2(Btn, { label: "Blank page", title: "Insert blank page", onClick: () => api?.insertBlankPage() }),
32809
+ /* @__PURE__ */ jsx2(
31740
32810
  ActionMenu,
31741
32811
  {
31742
32812
  label: "Break",
@@ -31755,7 +32825,7 @@ function DocxToolbar({
31755
32825
  }
31756
32826
  )
31757
32827
  ] }),
31758
- on("dateTime") && /* @__PURE__ */ jsx(
32828
+ on("dateTime") && /* @__PURE__ */ jsx2(
31759
32829
  ActionMenu,
31760
32830
  {
31761
32831
  label: "Date & time",
@@ -31774,15 +32844,15 @@ function DocxToolbar({
31774
32844
  }
31775
32845
  }
31776
32846
  ),
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() })
32847
+ 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`) }),
32848
+ on("equation") && /* @__PURE__ */ jsx2(EquationMenu, { api }),
32849
+ on("symbol") && /* @__PURE__ */ jsx2(SymbolMenu, { api }),
32850
+ 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) }),
32851
+ on("object") && /* @__PURE__ */ jsx2(Btn, { label: "Object", title: "Embed a file in this document", onClick: () => objectInput.current?.click() })
31782
32852
  ] })
31783
32853
  ] }),
31784
- mode === "advanced" && tab === "draw" && on("drawing") && /* @__PURE__ */ jsx(DrawTab, { api }),
31785
- /* @__PURE__ */ jsx(
32854
+ mode === "advanced" && tab === "draw" && on("drawing") && /* @__PURE__ */ jsx2(DrawTab, { api }),
32855
+ /* @__PURE__ */ jsx2(
31786
32856
  "input",
31787
32857
  {
31788
32858
  ref: imageInput,
@@ -31796,7 +32866,7 @@ function DocxToolbar({
31796
32866
  }
31797
32867
  }
31798
32868
  ),
31799
- /* @__PURE__ */ jsx(
32869
+ /* @__PURE__ */ jsx2(
31800
32870
  "input",
31801
32871
  {
31802
32872
  ref: iconInput,
@@ -31810,7 +32880,7 @@ function DocxToolbar({
31810
32880
  }
31811
32881
  }
31812
32882
  ),
31813
- /* @__PURE__ */ jsx(
32883
+ /* @__PURE__ */ jsx2(
31814
32884
  "input",
31815
32885
  {
31816
32886
  ref: modelInput,
@@ -31825,7 +32895,7 @@ function DocxToolbar({
31825
32895
  }
31826
32896
  }
31827
32897
  ),
31828
- /* @__PURE__ */ jsx(
32898
+ /* @__PURE__ */ jsx2(
31829
32899
  "input",
31830
32900
  {
31831
32901
  ref: objectInput,
@@ -31839,18 +32909,20 @@ function DocxToolbar({
31839
32909
  }
31840
32910
  }
31841
32911
  ),
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
- ] })
32912
+ mode === "advanced" && tab === "layout" && on("layout") && /* @__PURE__ */ jsx2(LayoutTab, { api, showArrange: on("arrange") }),
32913
+ 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) }) }),
32914
+ on("download") && onSave && /* @__PURE__ */ jsxs2(Fragment2, { children: [
32915
+ /* @__PURE__ */ jsx2("span", { style: { flex: 1 } }),
32916
+ /* @__PURE__ */ jsx2(Btn, { label: "Download", title: "Save edited .docx", onClick: () => api && onSave(api.save()) })
32917
+ ] }),
32918
+ /* @__PURE__ */ jsx2(HelpGuide, { open: helpOpen, onClose: closeHelp, returnFocus: helpTrigger })
31847
32919
  ]
31848
32920
  }
31849
32921
  );
31850
32922
  }
31851
32923
 
31852
32924
  // src/index.tsx
31853
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
32925
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
31854
32926
  async function objectPoster(title, subtitle, glyph) {
31855
32927
  const canvas = document.createElement("canvas");
31856
32928
  canvas.width = 640;
@@ -31894,6 +32966,7 @@ function DocxView({
31894
32966
  className,
31895
32967
  style,
31896
32968
  onLoad,
32969
+ onPageCountChange,
31897
32970
  onReady,
31898
32971
  onError,
31899
32972
  commentAuthor = "You",
@@ -31901,17 +32974,19 @@ function DocxView({
31901
32974
  revisions = "final",
31902
32975
  onMissingFonts
31903
32976
  }) {
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);
32977
+ const containerRef = useRef3(null);
32978
+ const [error, setError] = useState3(null);
32979
+ const [layoutBusy, setLayoutBusy] = useState3(false);
32980
+ const [fitZoom, setFitZoom] = useState3(null);
32981
+ const [narrow, setNarrow] = useState3(false);
32982
+ const basePageWidthRef = useRef3(816);
31910
32983
  const effectiveZoom = fitWidth && fitZoom != null ? Math.min(zoom, fitZoom) : zoom;
31911
- const effZoomRef = useRef2(effectiveZoom);
32984
+ const effZoomRef = useRef3(effectiveZoom);
31912
32985
  effZoomRef.current = effectiveZoom;
31913
- const applyZoomRef = useRef2(null);
31914
- useEffect2(() => {
32986
+ const applyZoomRef = useRef3(null);
32987
+ const onPageCountChangeRef = useRef3(onPageCountChange);
32988
+ onPageCountChangeRef.current = onPageCountChange;
32989
+ useEffect3(() => {
31915
32990
  if (editable && typeof window !== "undefined" && !customElements.get("model-viewer")) {
31916
32991
  void import("@google/model-viewer");
31917
32992
  }
@@ -31925,7 +33000,7 @@ function DocxView({
31925
33000
  setFitZoom((cw - gutter) / basePageWidthRef.current);
31926
33001
  setNarrow(cw <= narrowWidth);
31927
33002
  }, [narrowWidth]);
31928
- useEffect2(() => {
33003
+ useEffect3(() => {
31929
33004
  const c = containerRef.current;
31930
33005
  if (!c || typeof ResizeObserver === "undefined") return;
31931
33006
  const ro = new ResizeObserver(() => recomputeFit());
@@ -31933,13 +33008,13 @@ function DocxView({
31933
33008
  recomputeFit();
31934
33009
  return () => ro.disconnect();
31935
33010
  }, [recomputeFit]);
31936
- useEffect2(() => {
33011
+ useEffect3(() => {
31937
33012
  applyZoomRef.current?.(effectiveZoom);
31938
33013
  }, [effectiveZoom]);
31939
- useEffect2(() => {
33014
+ useEffect3(() => {
31940
33015
  containerRef.current?.classList.toggle("dxw-narrow", narrow);
31941
33016
  }, [narrow]);
31942
- useEffect2(() => {
33017
+ useEffect3(() => {
31943
33018
  const c = containerRef.current;
31944
33019
  if (!c) return;
31945
33020
  const onTap = (e) => {
@@ -31959,17 +33034,17 @@ function DocxView({
31959
33034
  c.addEventListener("click", onTap);
31960
33035
  return () => c.removeEventListener("click", onTap);
31961
33036
  }, []);
31962
- const [hfMode, setHfMode] = useState2(false);
31963
- const apiRef = useRef2(null);
31964
- const docCacheRef = useRef2(null);
31965
- useEffect2(() => {
33037
+ const [hfMode, setHfMode] = useState3(false);
33038
+ const apiRef = useRef3(null);
33039
+ const docCacheRef = useRef3(null);
33040
+ useEffect3(() => {
31966
33041
  const c = containerRef.current;
31967
33042
  if (!c) return;
31968
33043
  const onHf = (e) => setHfMode(!!e.detail?.active);
31969
33044
  c.addEventListener("dxw-hfmode", onHf);
31970
33045
  return () => c.removeEventListener("dxw-hfmode", onHf);
31971
33046
  }, []);
31972
- useEffect2(() => {
33047
+ useEffect3(() => {
31973
33048
  let cancelled = false;
31974
33049
  let handle = null;
31975
33050
  let editor = null;
@@ -32033,6 +33108,7 @@ function DocxView({
32033
33108
  totalPages: layout.totalPages
32034
33109
  };
32035
33110
  }
33111
+ if (pages !== layout.totalPages) onPageCountChangeRef.current?.(layout.totalPages);
32036
33112
  pages = layout.totalPages;
32037
33113
  return layout.totalPages;
32038
33114
  };
@@ -32446,6 +33522,7 @@ function DocxView({
32446
33522
  setDrawingTool: (tool) => editor?.setDrawingTool(tool),
32447
33523
  getDrawingTool: () => editor?.getDrawingTool() ?? null,
32448
33524
  arrangeObject: (action) => editor?.arrangeSelectedObject(action) ?? false,
33525
+ hasSelectedObject: () => editor?.hasSelectedObject() ?? false,
32449
33526
  addComment: (text) => {
32450
33527
  const segs = editor?.getSelectionSegments() ?? [];
32451
33528
  const segments = segs.length > 0 ? segs : handle ? selectionToSegments(handle.bindings) : [];
@@ -32561,7 +33638,7 @@ function DocxView({
32561
33638
  history.checkpoint();
32562
33639
  const done = kind === "page" || kind === "column" ? insertBreakAt(doc, target.t, target.offset, kind) : insertSectionBreak(doc, target.t, kind === "sectionNextPage" ? "nextPage" : "continuous");
32563
33640
  if (done) pages = rerender(doc);
32564
- return done;
33641
+ return !!done;
32565
33642
  },
32566
33643
  insertBlankPage: () => {
32567
33644
  const target = insertionTarget();
@@ -32586,6 +33663,10 @@ function DocxView({
32586
33663
  }
32587
33664
  if (setPageLayout(doc, patch, target)) pages = rerender(doc);
32588
33665
  },
33666
+ getSectionContext: () => {
33667
+ const t = editor?.getCaretTarget()?.t ?? editor?.getSelectionSegments()?.[0]?.t;
33668
+ return t ? sectionContextAt(doc, t) : null;
33669
+ },
32589
33670
  setLineNumbering: (patch, scope) => {
32590
33671
  history.checkpoint();
32591
33672
  let target;
@@ -32779,7 +33860,7 @@ function DocxView({
32779
33860
  handle = null;
32780
33861
  };
32781
33862
  }, [source, editable, commentAuthor, showComments, revisions]);
32782
- const hotBtn = (label, title, onClick) => /* @__PURE__ */ jsx2(
33863
+ const hotBtn = (label, title, onClick) => /* @__PURE__ */ jsx3(
32783
33864
  "button",
32784
33865
  {
32785
33866
  title,
@@ -32798,71 +33879,105 @@ function DocxView({
32798
33879
  children: label
32799
33880
  }
32800
33881
  );
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
- ] });
33882
+ return /* @__PURE__ */ jsxs3(
33883
+ "div",
33884
+ {
33885
+ style: {
33886
+ position: "relative",
33887
+ display: "flex",
33888
+ flexDirection: "column",
33889
+ minHeight: 0,
33890
+ ...style?.height ? { height: style.height } : {}
33891
+ },
33892
+ children: [
33893
+ editable && hfMode && /* @__PURE__ */ jsx3(
33894
+ "div",
33895
+ {
33896
+ "data-dxw-editor-context-row": "",
33897
+ style: {
33898
+ flex: "0 0 52px",
33899
+ display: "flex",
33900
+ alignItems: "center",
33901
+ justifyContent: "center",
33902
+ background: "var(--dxw-canvas-bg, #e8eaed)",
33903
+ position: "relative",
33904
+ zIndex: 40,
33905
+ pointerEvents: "none"
33906
+ },
33907
+ children: /* @__PURE__ */ jsxs3(
33908
+ "div",
33909
+ {
33910
+ "data-dxw-hf-hotbar": "",
33911
+ style: {
33912
+ display: "flex",
33913
+ gap: 6,
33914
+ background: "rgba(249,251,253,.96)",
33915
+ border: "1px solid #dadce0",
33916
+ borderRadius: 18,
33917
+ padding: "5px 8px",
33918
+ boxShadow: "0 2px 10px rgba(0,0,0,.15)",
33919
+ alignItems: "center",
33920
+ pointerEvents: "auto"
33921
+ },
33922
+ children: [
33923
+ /* @__PURE__ */ jsx3("span", { style: { font: "600 11.5px system-ui, sans-serif", color: "#5f6368", padding: "0 4px" }, children: "Header & footer \xB7 repeats on pages" }),
33924
+ hotBtn("Page number", "Insert a dynamic page number at the caret", () => apiRef.current?.insertPageNumber("page")),
33925
+ hotBtn("Page X of Y", "Insert 'Page X of Y' at the caret", () => apiRef.current?.insertPageNumber("pageOfTotal")),
33926
+ hotBtn("Close", "Return to the document body", () => {
33927
+ apiRef.current?.closeHeaderFooter();
33928
+ setHfMode(false);
33929
+ })
33930
+ ]
33931
+ }
33932
+ )
33933
+ }
33934
+ ),
33935
+ /* @__PURE__ */ jsx3(
33936
+ "div",
33937
+ {
33938
+ ref: containerRef,
33939
+ className,
33940
+ style: {
33941
+ background: "var(--dxw-canvas-bg, #e8eaed)",
33942
+ overflow: "auto",
33943
+ height: "100%",
33944
+ ...style,
33945
+ ...editable ? {
33946
+ height: "auto",
33947
+ flex: "1 1 auto",
33948
+ minHeight: 0,
33949
+ boxSizing: "border-box"
33950
+ } : {}
33951
+ },
33952
+ children: error && /* @__PURE__ */ jsxs3("div", { style: { padding: 16, color: "#b00020", fontFamily: "system-ui" }, children: [
33953
+ "Failed to render document: ",
33954
+ error.message
33955
+ ] })
33956
+ }
33957
+ ),
33958
+ layoutBusy && /* @__PURE__ */ jsx3(
33959
+ "div",
33960
+ {
33961
+ "data-dxw-layout-status": "",
33962
+ "aria-live": "polite",
33963
+ style: {
33964
+ position: "absolute",
33965
+ top: editable ? 62 : 10,
33966
+ right: 12,
33967
+ zIndex: 45,
33968
+ padding: "5px 10px",
33969
+ borderRadius: 14,
33970
+ background: "rgba(32,33,36,.88)",
33971
+ color: "#fff",
33972
+ font: "12px system-ui,sans-serif",
33973
+ pointerEvents: "none"
33974
+ },
33975
+ children: "Repaginating\u2026"
33976
+ }
33977
+ )
33978
+ ]
33979
+ }
33980
+ );
32866
33981
  }
32867
33982
  export {
32868
33983
  DocxDocument,