@windoc/react 0.2.6 → 0.2.8

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
@@ -182,7 +182,7 @@ var import_react3 = require("react");
182
182
  var import_jsx_runtime5 = require("react/jsx-runtime");
183
183
  function ColumnTool() {
184
184
  const { editorRef } = useEditor();
185
- const [isOpen, setIsOpen] = (0, import_react3.useState)(false);
185
+ const optionsRef = (0, import_react3.useRef)(null);
186
186
  const [currentColumns, setCurrentColumns] = (0, import_react3.useState)(1);
187
187
  const [gap, setGap] = (0, import_react3.useState)(20);
188
188
  const handleColumn = (col) => {
@@ -194,9 +194,9 @@ function ColumnTool() {
194
194
  setGap(clampedValue);
195
195
  editorRef.current?.command.executeColumnGap(clampedValue);
196
196
  };
197
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "menu-item__column", onClick: () => setIsOpen(!isOpen), children: [
197
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "menu-item__column", onClick: () => optionsRef.current?.classList.toggle("visible"), children: [
198
198
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "select", title: "Column Layout", children: currentColumns === 1 ? "1 Column" : `${currentColumns} Columns` }),
199
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "options" + (isOpen ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { onClick: (e) => e.stopPropagation(), children: [
199
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "options", ref: optionsRef, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { onClick: (e) => e.stopPropagation(), children: [
200
200
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("ul", { children: [
201
201
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { onClick: () => handleColumn(1), children: "1 Column" }),
202
202
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { onClick: () => handleColumn(2), children: "2 Columns" })
@@ -285,15 +285,15 @@ var LEVELS = [
285
285
  ];
286
286
  function TitleTool() {
287
287
  const { editorRef, rangeStyle } = useEditor();
288
- const [isOpen, setIsOpen] = (0, import_react5.useState)(false);
288
+ const optionsRef = (0, import_react5.useRef)(null);
289
289
  const activeLevel = rangeStyle?.level || null;
290
290
  const activeLabel = LEVELS.find((l) => l.level === activeLevel)?.label || "Body";
291
291
  const handleTitle = (level) => {
292
292
  editorRef.current?.command.executeTitle(level);
293
293
  };
294
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "menu-item__title", onClick: () => setIsOpen(!isOpen), children: [
294
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "menu-item__title", onClick: () => optionsRef.current?.classList.toggle("visible"), children: [
295
295
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "select", title: "Toggle Heading", children: activeLabel }),
296
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "options" + (isOpen ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { children: LEVELS.map(({ level, label }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
296
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "options", ref: optionsRef, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { children: LEVELS.map(({ level, label }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
297
297
  "li",
298
298
  {
299
299
  className: activeLevel === level ? "active" : "",
@@ -310,20 +310,26 @@ function TitleTool() {
310
310
  var import_react6 = require("react");
311
311
  var import_jsx_runtime8 = require("react/jsx-runtime");
312
312
  var FONTS = [
313
- { family: "Arial", label: "Sans Serif" },
314
- { family: "Times New Roman", label: "Serif" }
313
+ { family: "Arial", label: "Arial" },
314
+ { family: "Times New Roman", label: "Times New Roman" },
315
+ { family: "Georgia", label: "Georgia" },
316
+ { family: "Verdana", label: "Verdana" },
317
+ { family: "Trebuchet MS", label: "Trebuchet MS" },
318
+ { family: "Courier New", label: "Courier New" },
319
+ { family: "Comic Sans MS", label: "Comic Sans MS" },
320
+ { family: "Impact", label: "Impact" }
315
321
  ];
316
322
  function FontTool() {
317
323
  const { editorRef, rangeStyle } = useEditor();
318
- const [isOpen, setIsOpen] = (0, import_react6.useState)(false);
324
+ const optionsRef = (0, import_react6.useRef)(null);
319
325
  const activeFont = rangeStyle?.font || "Arial";
320
326
  const activeLabel = FONTS.find((f) => f.family === activeFont)?.label || activeFont;
321
327
  const handleFont = (family) => {
322
328
  editorRef.current?.command.executeFont(family);
323
329
  };
324
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "menu-item__font", onClick: () => setIsOpen(!isOpen), children: [
330
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "menu-item__font", onClick: () => optionsRef.current?.classList.toggle("visible"), children: [
325
331
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "select", title: "Font", children: activeLabel }),
326
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "options" + (isOpen ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { children: FONTS.map(({ family, label }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
332
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "options", ref: optionsRef, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { children: FONTS.map(({ family, label }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
327
333
  "li",
328
334
  {
329
335
  "data-family": family,
@@ -343,14 +349,14 @@ var import_jsx_runtime9 = require("react/jsx-runtime");
343
349
  var SIZES = [56, 48, 34, 32, 29, 24, 21, 20, 18, 16, 14, 12, 10, 8];
344
350
  function FontSizeTool() {
345
351
  const { editorRef, rangeStyle } = useEditor();
346
- const [isOpen, setIsOpen] = (0, import_react7.useState)(false);
352
+ const optionsRef = (0, import_react7.useRef)(null);
347
353
  const activeSize = rangeStyle?.size ?? 16;
348
354
  const handleSize = (size) => {
349
355
  editorRef.current?.command.executeSize(size);
350
356
  };
351
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "menu-item__size", onClick: () => setIsOpen(!isOpen), children: [
357
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "menu-item__size", onClick: () => optionsRef.current?.classList.toggle("visible"), children: [
352
358
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "select", title: "Font Size", children: activeSize }),
353
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "options" + (isOpen ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ul", { children: SIZES.map((size) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
359
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "options", ref: optionsRef, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ul", { children: SIZES.map((size) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
354
360
  "li",
355
361
  {
356
362
  className: activeSize === size ? "active" : "",
@@ -368,15 +374,15 @@ var import_jsx_runtime10 = require("react/jsx-runtime");
368
374
  var LINE_HEIGHTS = ["1.0", "1.15", "1.5", "2.0", "2.5"];
369
375
  function LineHeightTool() {
370
376
  const { editorRef, rangeStyle } = useEditor();
371
- const [isOpen, setIsOpen] = (0, import_react8.useState)(false);
377
+ const optionsRef = (0, import_react8.useRef)(null);
372
378
  const activeMargin = rangeStyle?.rowMargin ?? 1;
373
379
  const activeLabel = Number.isInteger(activeMargin) ? `${activeMargin}.0` : String(activeMargin);
374
380
  const handleLineHeight = (value) => {
375
381
  editorRef.current?.command.executeRowMargin(Number(value));
376
382
  };
377
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "menu-item__line-height", onClick: () => setIsOpen(!isOpen), children: [
383
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "menu-item__line-height", onClick: () => optionsRef.current?.classList.toggle("visible"), children: [
378
384
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "select", title: "Line Height", children: activeLabel }),
379
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "options" + (isOpen ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("ul", { children: LINE_HEIGHTS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
385
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "options", ref: optionsRef, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("ul", { children: LINE_HEIGHTS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
380
386
  "li",
381
387
  {
382
388
  className: String(activeMargin) === h || activeLabel === h ? "active" : "",
@@ -404,7 +410,7 @@ var COLOR_PALETTE = [
404
410
  ];
405
411
  function ColorTool() {
406
412
  const { editorRef, rangeStyle } = useEditor();
407
- const [visible, setVisible] = (0, import_react9.useState)(false);
413
+ const dropdownRef = (0, import_react9.useRef)(null);
408
414
  const activeColor = rangeStyle?.color || "#000000";
409
415
  const handleColor = (color) => {
410
416
  editorRef.current?.command.executeColor(color);
@@ -412,11 +418,11 @@ function ColorTool() {
412
418
  const handleReset = () => {
413
419
  editorRef.current?.command.executeColor(null);
414
420
  };
415
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "menu-item__color", title: "Font Color", onClick: () => setVisible(!visible), children: [
421
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "menu-item__color", title: "Font Color", onClick: () => dropdownRef.current?.classList.toggle("visible"), children: [
416
422
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.Baseline, { size: 16 }),
417
423
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { backgroundColor: activeColor } }),
418
424
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { id: "color", type: "color", readOnly: true, tabIndex: -1 }),
419
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "color-palette-dropdown" + (visible ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { onClick: (e) => e.stopPropagation(), children: [
425
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "color-palette-dropdown", ref: dropdownRef, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { onClick: (e) => e.stopPropagation(), children: [
420
426
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("button", { className: "color-palette-reset", onClick: handleReset, children: [
421
427
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.RotateCcw, { size: 12 }),
422
428
  "Reset"
@@ -451,7 +457,7 @@ var HIGHLIGHT_PALETTE = [
451
457
  ];
452
458
  function HighlightTool() {
453
459
  const { editorRef, rangeStyle } = useEditor();
454
- const [visible, setVisible] = (0, import_react10.useState)(false);
460
+ const dropdownRef = (0, import_react10.useRef)(null);
455
461
  const activeColor = rangeStyle?.highlight || "";
456
462
  const handleColor = (color) => {
457
463
  editorRef.current?.command.executeHighlight(color);
@@ -459,11 +465,11 @@ function HighlightTool() {
459
465
  const handleReset = () => {
460
466
  editorRef.current?.command.executeHighlight(null);
461
467
  };
462
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "menu-item__highlight", title: "Highlight", onClick: () => setVisible(!visible), children: [
468
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "menu-item__highlight", title: "Highlight", onClick: () => dropdownRef.current?.classList.toggle("visible"), children: [
463
469
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Highlighter, { size: 16 }),
464
470
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { backgroundColor: activeColor || "#ffff00" } }),
465
471
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { id: "highlight", type: "color", readOnly: true, tabIndex: -1 }),
466
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "color-palette-dropdown" + (visible ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { onClick: (e) => e.stopPropagation(), children: [
472
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "color-palette-dropdown", ref: dropdownRef, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { onClick: (e) => e.stopPropagation(), children: [
467
473
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { className: "color-palette-reset", onClick: handleReset, children: [
468
474
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.RotateCcw, { size: 12 }),
469
475
  "None"
@@ -507,12 +513,12 @@ var import_jsx_runtime15 = require("react/jsx-runtime");
507
513
  var STYLES = ["solid", "double", "dashed", "dotted", "wavy"];
508
514
  function UnderlineTool() {
509
515
  const { editorRef, isApple, rangeStyle } = useEditor();
510
- const [isOpen, setIsOpen] = (0, import_react11.useState)(false);
516
+ const optionsRef = (0, import_react11.useRef)(null);
511
517
  const isActive = rangeStyle?.underline === true;
512
518
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: `menu-item__underline ${isActive ? "active" : ""}`, title: `Underline(${isApple ? "\u2318" : "Ctrl"}+U)`, children: [
513
519
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Underline, { size: 16, onClick: () => editorRef.current?.command.executeUnderline(), style: { cursor: "pointer" } }),
514
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "select", onClick: () => setIsOpen(!isOpen) }),
515
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "options" + (isOpen ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ul", { children: STYLES.map((style) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("li", { "data-decoration-style": style, onClick: () => {
520
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "select", onClick: () => optionsRef.current?.classList.toggle("visible") }),
521
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "options", ref: optionsRef, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ul", { children: STYLES.map((style) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("li", { "data-decoration-style": style, onClick: () => {
516
522
  editorRef.current?.command.executeUnderline({ style });
517
523
  }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("i", {}) }, style)) }) })
518
524
  ] });
@@ -599,7 +605,7 @@ function PresetCell({ option, onClick }) {
599
605
  }
600
606
  function ListTool() {
601
607
  const { editorRef, isApple, rangeStyle } = useEditor();
602
- const [isOpen, setIsOpen] = (0, import_react12.useState)(false);
608
+ const optionsRef = (0, import_react12.useRef)(null);
603
609
  const isActive = !!rangeStyle?.listType;
604
610
  const handleList = (type, style) => {
605
611
  editorRef.current?.command.executeList(type, style);
@@ -617,8 +623,8 @@ function ListTool() {
617
623
  editorRef.current?.command.executeListOutdent();
618
624
  };
619
625
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `menu-item__list ${isActive ? "active" : ""}`, title: `List(${isApple ? "\u2318" : "Ctrl"}+Shift+U)`, children: [
620
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.List, { size: 16, onClick: () => setIsOpen(!isOpen), style: { cursor: "pointer" } }),
621
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "options" + (isOpen ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { padding: "8px", width: "320px" }, children: [
626
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.List, { size: 16, onClick: () => optionsRef.current?.classList.toggle("visible"), style: { cursor: "pointer" } }),
627
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "options", ref: optionsRef, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { padding: "8px", width: "320px" }, children: [
622
628
  /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: "4px", marginBottom: "8px" }, children: [
623
629
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
624
630
  "button",
@@ -709,15 +715,15 @@ var LINE_WIDTHS = [
709
715
  ];
710
716
  function SeparatorTool() {
711
717
  const { editorRef } = useEditor();
712
- const [isOpen, setIsOpen] = (0, import_react13.useState)(false);
718
+ const optionsRef = (0, import_react13.useRef)(null);
713
719
  const [selectedWidth, setSelectedWidth] = (0, import_react13.useState)(1);
714
720
  const lineColor = "#344054";
715
721
  const handleSeparator = (dashArray) => {
716
722
  editorRef.current?.command.executeSeparator(dashArray, { lineWidth: selectedWidth });
717
723
  };
718
724
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "menu-item__separator", title: "Separator", children: [
719
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react16.Minus, { size: 16, onClick: () => setIsOpen(!isOpen), style: { cursor: "pointer" } }),
720
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "options" + (isOpen ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { padding: "8px 10px 10px", width: "200px" }, children: [
725
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react16.Minus, { size: 16, onClick: () => optionsRef.current?.classList.toggle("visible"), style: { cursor: "pointer" } }),
726
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "options", ref: optionsRef, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { padding: "8px 10px 10px", width: "200px" }, children: [
721
727
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("ul", { style: { margin: 0, padding: 0, listStyle: "none" }, children: DASH_STYLES.map(({ label, dashArray }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
722
728
  "li",
723
729
  {
@@ -775,7 +781,7 @@ var import_react14 = require("react");
775
781
  var import_jsx_runtime24 = require("react/jsx-runtime");
776
782
  function InsertElementTool() {
777
783
  const { editorRef } = useEditor();
778
- const [isOpen, setIsOpen] = (0, import_react14.useState)(false);
784
+ const optionsRef = (0, import_react14.useRef)(null);
779
785
  const handleHeader = () => {
780
786
  if (!editorRef.current) return;
781
787
  const options = editorRef.current.command.getOptions();
@@ -785,9 +791,9 @@ function InsertElementTool() {
785
791
  }
786
792
  editorRef.current.command.executeSetZone("header");
787
793
  };
788
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "menu-item__insert-element", onClick: () => setIsOpen(!isOpen), children: [
794
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "menu-item__insert-element", onClick: () => optionsRef.current?.classList.toggle("visible"), children: [
789
795
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("i", { title: "Insert Element" }),
790
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "options" + (isOpen ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("ul", { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { onClick: handleHeader, children: "Add Header" }) }) })
796
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "options", ref: optionsRef, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("ul", { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { onClick: handleHeader, children: "Add Header" }) }) })
791
797
  ] });
792
798
  }
793
799
 
@@ -796,7 +802,7 @@ var import_react15 = require("react");
796
802
  var import_jsx_runtime25 = require("react/jsx-runtime");
797
803
  function PageBreakTool() {
798
804
  const { editorRef } = useEditor();
799
- const [isOpen, setIsOpen] = (0, import_react15.useState)(false);
805
+ const optionsRef = (0, import_react15.useRef)(null);
800
806
  const handlePageBreak = () => {
801
807
  editorRef.current?.command.executePageBreak();
802
808
  };
@@ -807,10 +813,10 @@ function PageBreakTool() {
807
813
  "div",
808
814
  {
809
815
  className: "menu-item__page-break",
810
- onClick: () => setIsOpen(!isOpen),
816
+ onClick: () => optionsRef.current?.classList.toggle("visible"),
811
817
  children: [
812
818
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("i", { title: "Break" }),
813
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "options" + (isOpen ? " visible" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("ul", { children: [
819
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "options", ref: optionsRef, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("ul", { children: [
814
820
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { onClick: handlePageBreak, children: "Page Break" }),
815
821
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { onClick: handleColumnBreak, children: "Column Break" })
816
822
  ] }) })
@@ -1029,6 +1035,7 @@ function PaperDirectionTool() {
1029
1035
  }
1030
1036
 
1031
1037
  // src/footer/PaperMarginTool.tsx
1038
+ var import_core = require("@windoc/core");
1032
1039
  var import_jsx_runtime36 = require("react/jsx-runtime");
1033
1040
  function PaperMarginTool() {
1034
1041
  const { editorRef } = useEditor();
@@ -1039,10 +1046,10 @@ function PaperMarginTool() {
1039
1046
  new Dialog({
1040
1047
  title: "Page Margins",
1041
1048
  data: [
1042
- { type: "text", label: "Top Margin", name: "top", required: true, value: `${topMargin}`, placeholder: "Please enter top margin" },
1043
- { type: "text", label: "Bottom Margin", name: "bottom", required: true, value: `${bottomMargin}`, placeholder: "Please enter bottom margin" },
1044
- { type: "text", label: "Left Margin", name: "left", required: true, value: `${leftMargin}`, placeholder: "Please enter left margin" },
1045
- { type: "text", label: "Right Margin", name: "right", required: true, value: `${rightMargin}`, placeholder: "Please enter right margin" }
1049
+ { type: "text", label: "Top Margin (cm)", name: "top", required: true, value: `${(0, import_core.pxToCm)(topMargin)}`, placeholder: "e.g. 2.54" },
1050
+ { type: "text", label: "Bottom Margin (cm)", name: "bottom", required: true, value: `${(0, import_core.pxToCm)(bottomMargin)}`, placeholder: "e.g. 2.54" },
1051
+ { type: "text", label: "Left Margin (cm)", name: "left", required: true, value: `${(0, import_core.pxToCm)(leftMargin)}`, placeholder: "e.g. 2.54" },
1052
+ { type: "text", label: "Right Margin (cm)", name: "right", required: true, value: `${(0, import_core.pxToCm)(rightMargin)}`, placeholder: "e.g. 2.54" }
1046
1053
  ],
1047
1054
  onConfirm: (payload) => {
1048
1055
  const top = payload.find((p) => p.name === "top")?.value;
@@ -1054,10 +1061,10 @@ function PaperMarginTool() {
1054
1061
  const right = payload.find((p) => p.name === "right")?.value;
1055
1062
  if (!right) return;
1056
1063
  editorRef.current?.command.executeSetPaperMargin([
1057
- Number(top),
1058
- Number(right),
1059
- Number(bottom),
1060
- Number(left)
1064
+ (0, import_core.cmToPx)(Number(top)),
1065
+ (0, import_core.cmToPx)(Number(right)),
1066
+ (0, import_core.cmToPx)(Number(bottom)),
1067
+ (0, import_core.cmToPx)(Number(left))
1061
1068
  ]);
1062
1069
  }
1063
1070
  });
@@ -1220,85 +1227,95 @@ function WatermarkFooterTool() {
1220
1227
  };
1221
1228
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "watermark-footer", ref: containerRef, onClick: () => setVisible(!visible), children: [
1222
1229
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("i", { title: "Watermark" }),
1223
- visible && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "watermark-footer-panel", ref: panelRef, onClick: (e) => e.stopPropagation(), children: [
1224
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-tabs", children: [
1225
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: `wm-panel-tab ${tab === "text" ? "active" : ""}`, onClick: () => setTab("text"), children: "Text" }),
1226
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: `wm-panel-tab ${tab === "image" ? "active" : ""}`, onClick: () => setTab("image"), children: "Image" })
1227
- ] }),
1228
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-body", children: [
1229
- tab === "text" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
1230
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1231
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "Text" }),
1232
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "text", value: text, onChange: (e) => setText(e.target.value), placeholder: "Watermark text" })
1230
+ visible && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
1231
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "wm-panel-mask", onClick: (e) => {
1232
+ e.stopPropagation();
1233
+ setVisible(false);
1234
+ } }),
1235
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "watermark-footer-panel", ref: panelRef, onClick: (e) => e.stopPropagation(), children: [
1236
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-title", children: [
1237
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: "Watermark" }),
1238
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("i", { onClick: () => setVisible(false) })
1239
+ ] }),
1240
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-tabs", children: [
1241
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: `wm-panel-tab ${tab === "text" ? "active" : ""}`, onClick: () => setTab("text"), children: "Text" }),
1242
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: `wm-panel-tab ${tab === "image" ? "active" : ""}`, onClick: () => setTab("image"), children: "Image" })
1243
+ ] }),
1244
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-body", children: [
1245
+ tab === "text" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
1246
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1247
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "Text" }),
1248
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "text", value: text, onChange: (e) => setText(e.target.value), placeholder: "Watermark text" })
1249
+ ] }),
1250
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1251
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "Font" }),
1252
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("select", { value: font, onChange: (e) => setFont(e.target.value), children: FONTS2.map((f) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("option", { value: f.family, children: f.label }, f.family)) })
1253
+ ] }),
1254
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1255
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "Color" }),
1256
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "wm-panel-colors", children: COLOR_PALETTE2.flat().map((c) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
1257
+ "div",
1258
+ {
1259
+ className: `wm-panel-color ${color.toLowerCase() === c.toLowerCase() ? "active" : ""}`,
1260
+ style: { backgroundColor: c },
1261
+ onClick: () => setColor(c)
1262
+ },
1263
+ c
1264
+ )) })
1265
+ ] })
1266
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
1267
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1268
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "Image" }),
1269
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
1270
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: "wm-panel-upload", onClick: () => fileInputRef.current?.click(), children: "Choose File" }),
1271
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: "none" }, onChange: handleFileUpload }),
1272
+ imageData && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { style: { fontSize: "11px", color: "#667085" }, children: "Loaded" })
1273
+ ] })
1274
+ ] }),
1275
+ imageData && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "wm-panel-field", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "wm-panel-preview", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("img", { src: imageData, alt: "preview", style: { maxWidth: "100%", maxHeight: "48px", objectFit: "contain" } }) }) }),
1276
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field-row", children: [
1277
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field wm-panel-field-half", children: [
1278
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "W" }),
1279
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "number", value: imgWidth, min: 10, onChange: (e) => setImgWidth(Number(e.target.value)) })
1280
+ ] }),
1281
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field wm-panel-field-half", children: [
1282
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "H" }),
1283
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "number", value: imgHeight, min: 10, onChange: (e) => setImgHeight(Number(e.target.value)) })
1284
+ ] })
1285
+ ] })
1233
1286
  ] }),
1234
1287
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1235
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "Font" }),
1236
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("select", { value: font, onChange: (e) => setFont(e.target.value), children: FONTS2.map((f) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("option", { value: f.family, children: f.label }, f.family)) })
1288
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { children: [
1289
+ "Opacity ",
1290
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "wm-panel-value", children: [
1291
+ opacity,
1292
+ "%"
1293
+ ] })
1294
+ ] }),
1295
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "range", min: 0, max: 100, value: opacity, onChange: (e) => setOpacity(Number(e.target.value)), className: "wm-panel-slider" })
1237
1296
  ] }),
1238
1297
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1239
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "Color" }),
1240
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "wm-panel-colors", children: COLOR_PALETTE2.flat().map((c) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
1241
- "div",
1242
- {
1243
- className: `wm-panel-color ${color.toLowerCase() === c.toLowerCase() ? "active" : ""}`,
1244
- style: { backgroundColor: c },
1245
- onClick: () => setColor(c)
1246
- },
1247
- c
1248
- )) })
1249
- ] })
1250
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
1251
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1252
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "Image" }),
1253
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
1254
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: "wm-panel-upload", onClick: () => fileInputRef.current?.click(), children: "Choose File" }),
1255
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: "none" }, onChange: handleFileUpload }),
1256
- imageData && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { style: { fontSize: "11px", color: "#667085" }, children: "Loaded" })
1257
- ] })
1258
- ] }),
1259
- imageData && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "wm-panel-field", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "wm-panel-preview", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("img", { src: imageData, alt: "preview", style: { maxWidth: "100%", maxHeight: "48px", objectFit: "contain" } }) }) }),
1260
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field-row", children: [
1261
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field wm-panel-field-half", children: [
1262
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "W" }),
1263
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "number", value: imgWidth, min: 10, onChange: (e) => setImgWidth(Number(e.target.value)) })
1298
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { children: [
1299
+ "Rotation ",
1300
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "wm-panel-value", children: [
1301
+ rotation,
1302
+ "\xB0"
1303
+ ] })
1264
1304
  ] }),
1265
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field wm-panel-field-half", children: [
1266
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "H" }),
1267
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "number", value: imgHeight, min: 10, onChange: (e) => setImgHeight(Number(e.target.value)) })
1268
- ] })
1269
- ] })
1270
- ] }),
1271
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1272
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { children: [
1273
- "Opacity ",
1274
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "wm-panel-value", children: [
1275
- opacity,
1276
- "%"
1277
- ] })
1305
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "range", min: -90, max: 90, value: rotation, onChange: (e) => setRotation(Number(e.target.value)), className: "wm-panel-slider" })
1278
1306
  ] }),
1279
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "range", min: 0, max: 100, value: opacity, onChange: (e) => setOpacity(Number(e.target.value)), className: "wm-panel-slider" })
1280
- ] }),
1281
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1282
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { children: [
1283
- "Rotation ",
1284
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "wm-panel-value", children: [
1285
- rotation,
1286
- "\xB0"
1307
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1308
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "Position" }),
1309
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-toggle", children: [
1310
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: !inFront ? "active" : "", onClick: () => setInFront(false), children: "Behind" }),
1311
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: inFront ? "active" : "", onClick: () => setInFront(true), children: "In Front" })
1287
1312
  ] })
1288
- ] }),
1289
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "range", min: -90, max: 90, value: rotation, onChange: (e) => setRotation(Number(e.target.value)), className: "wm-panel-slider" })
1290
- ] }),
1291
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-field", children: [
1292
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { children: "Position" }),
1293
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-toggle", children: [
1294
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: !inFront ? "active" : "", onClick: () => setInFront(false), children: "Behind" }),
1295
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: inFront ? "active" : "", onClick: () => setInFront(true), children: "In Front" })
1296
1313
  ] })
1314
+ ] }),
1315
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-actions", children: [
1316
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: "wm-panel-btn-delete", onClick: handleDelete, children: "Remove" }),
1317
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: "wm-panel-btn-apply", onClick: handleApply, children: "Apply" })
1297
1318
  ] })
1298
- ] }),
1299
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "wm-panel-actions", children: [
1300
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: "wm-panel-btn-delete", onClick: handleDelete, children: "Remove" }),
1301
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { className: "wm-panel-btn-apply", onClick: handleApply, children: "Apply" })
1302
1319
  ] })
1303
1320
  ] })
1304
1321
  ] });
@@ -1501,7 +1518,9 @@ function EditorInner({
1501
1518
  ]);
1502
1519
  const closeDropdowns = (evt) => {
1503
1520
  const visibleDom = document.querySelector(".visible");
1504
- if (!visibleDom || visibleDom.contains(evt.target)) return;
1521
+ if (!visibleDom) return;
1522
+ const parent = visibleDom.parentElement;
1523
+ if (parent && parent.contains(evt.target)) return;
1505
1524
  visibleDom.classList.remove("visible");
1506
1525
  };
1507
1526
  window.addEventListener("click", closeDropdowns, { capture: true });