@thanh01.pmt/presentation-kit 0.2.8 → 0.2.9

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.
@@ -1,5 +1,5 @@
1
1
  import React$1 from 'react';
2
- import { B as BuiltInTheme, c as SlideTheme, e as SlideRenderResult, b as SlideLayoutData } from '../types-C1121XLt.cjs';
2
+ import { B as BuiltInTheme, c as SlideTheme, e as SlideRenderResult, b as SlideLayoutData, L as LayoutBoxConfig } from '../types-C1121XLt.cjs';
3
3
  export { M as MermaidBlock, f as SlideRenderAsyncResult, d as SlideRenderOptions, T as ThemeTokens } from '../types-C1121XLt.cjs';
4
4
  export { l as ClickCssOptions, k as ClickPostprocessResult, C as ClickPreprocessResult, d as defineTheme, i as extractMaxClicks, j as generateClickCss, h as postprocessClicks, p as preprocessClicks, r as renderSlide, a as renderSlideAsync, e as resolveTheme } from '../click-css-BP9oqy_1.cjs';
5
5
 
@@ -256,16 +256,24 @@ interface SlideDesignOverlayProps {
256
256
  layout: SlideLayoutData | null;
257
257
  /** Callback when layout changes in real-time */
258
258
  onLayoutChange: (layout: SlideLayoutData) => void;
259
- /** Callback when user explicitly clicks Save */
259
+ /** Callback when user explicitly clicks Save or finishes drag/resize */
260
260
  onSave?: (layout: SlideLayoutData) => void;
261
+ /** Callback when an item is deleted */
262
+ onDeleteBox?: (box: LayoutBoxConfig) => void;
263
+ /** Callback when a new box is added */
264
+ onAddBox?: (box: LayoutBoxConfig) => void;
261
265
  /** Callback when user cancels or closes design mode */
262
266
  onClose?: () => void;
263
267
  /** Whether design mode is active */
264
268
  isActive: boolean;
265
269
  /** Active theme (dark, light, navy) */
266
270
  theme?: BuiltInTheme;
271
+ /** External selected box ID control */
272
+ selectedBoxId?: string | null;
273
+ /** Callback when box selection changes */
274
+ onSelectBoxId?: (id: string | null) => void;
267
275
  }
268
- declare function SlideDesignOverlay({ slideIndex, layout, onLayoutChange, onSave, onClose, isActive, theme, }: SlideDesignOverlayProps): React$1.JSX.Element | null;
276
+ declare function SlideDesignOverlay({ slideIndex, layout, onLayoutChange, onSave, onDeleteBox, onAddBox, onClose, isActive, theme, selectedBoxId, onSelectBoxId, }: SlideDesignOverlayProps): React$1.JSX.Element | null;
269
277
 
270
278
  interface UseSlideStateOptions {
271
279
  markdown: string;
@@ -1,5 +1,5 @@
1
1
  import React$1 from 'react';
2
- import { B as BuiltInTheme, c as SlideTheme, e as SlideRenderResult, b as SlideLayoutData } from '../types-C1121XLt.js';
2
+ import { B as BuiltInTheme, c as SlideTheme, e as SlideRenderResult, b as SlideLayoutData, L as LayoutBoxConfig } from '../types-C1121XLt.js';
3
3
  export { M as MermaidBlock, f as SlideRenderAsyncResult, d as SlideRenderOptions, T as ThemeTokens } from '../types-C1121XLt.js';
4
4
  export { l as ClickCssOptions, k as ClickPostprocessResult, C as ClickPreprocessResult, d as defineTheme, i as extractMaxClicks, j as generateClickCss, h as postprocessClicks, p as preprocessClicks, r as renderSlide, a as renderSlideAsync, e as resolveTheme } from '../click-css-BbhqdtGr.js';
5
5
 
@@ -256,16 +256,24 @@ interface SlideDesignOverlayProps {
256
256
  layout: SlideLayoutData | null;
257
257
  /** Callback when layout changes in real-time */
258
258
  onLayoutChange: (layout: SlideLayoutData) => void;
259
- /** Callback when user explicitly clicks Save */
259
+ /** Callback when user explicitly clicks Save or finishes drag/resize */
260
260
  onSave?: (layout: SlideLayoutData) => void;
261
+ /** Callback when an item is deleted */
262
+ onDeleteBox?: (box: LayoutBoxConfig) => void;
263
+ /** Callback when a new box is added */
264
+ onAddBox?: (box: LayoutBoxConfig) => void;
261
265
  /** Callback when user cancels or closes design mode */
262
266
  onClose?: () => void;
263
267
  /** Whether design mode is active */
264
268
  isActive: boolean;
265
269
  /** Active theme (dark, light, navy) */
266
270
  theme?: BuiltInTheme;
271
+ /** External selected box ID control */
272
+ selectedBoxId?: string | null;
273
+ /** Callback when box selection changes */
274
+ onSelectBoxId?: (id: string | null) => void;
267
275
  }
268
- declare function SlideDesignOverlay({ slideIndex, layout, onLayoutChange, onSave, onClose, isActive, theme, }: SlideDesignOverlayProps): React$1.JSX.Element | null;
276
+ declare function SlideDesignOverlay({ slideIndex, layout, onLayoutChange, onSave, onDeleteBox, onAddBox, onClose, isActive, theme, selectedBoxId, onSelectBoxId, }: SlideDesignOverlayProps): React$1.JSX.Element | null;
269
277
 
270
278
  interface UseSlideStateOptions {
271
279
  markdown: string;
@@ -1,6 +1,6 @@
1
- import { renderSlide, renderMermaidDiagrams } from '../chunk-JOW4QWKF.js';
2
- export { defineTheme, extractMaxClicks, generateClickCss, postprocessClicks, preprocessClicks, renderSlide, renderSlideAsync, resolveTheme } from '../chunk-JOW4QWKF.js';
3
- import { SLIDE_LAYOUT_PRESETS, updateSlideLayoutInMarkdown } from '../chunk-26ZVUVXF.js';
1
+ import { renderSlide, renderMermaidDiagrams } from '../chunk-NYLDRVHZ.js';
2
+ export { defineTheme, extractMaxClicks, generateClickCss, postprocessClicks, preprocessClicks, renderSlide, renderSlideAsync, resolveTheme } from '../chunk-NYLDRVHZ.js';
3
+ import { SLIDE_LAYOUT_PRESETS, updateSlideLayoutInMarkdown } from '../chunk-ZPASRL75.js';
4
4
  import { useState, useRef, useMemo, useEffect, useCallback } from 'react';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
 
@@ -584,15 +584,28 @@ function SlideDesignOverlay({
584
584
  layout,
585
585
  onLayoutChange,
586
586
  onSave,
587
+ onDeleteBox,
588
+ onAddBox,
587
589
  onClose,
588
590
  isActive,
589
- theme = "dark"
591
+ theme = "dark",
592
+ selectedBoxId,
593
+ onSelectBoxId
590
594
  }) {
591
595
  if (!isActive) return null;
592
596
  const [boxes, setBoxes] = useState(layout?.boxes ?? []);
593
- const [selectedId, setSelectedId] = useState(null);
597
+ const [selectedId, setSelectedIdState] = useState(selectedBoxId ?? null);
594
598
  const [editingId, setEditingId] = useState(null);
595
599
  const containerRef = useRef(null);
600
+ const setSelectedId = useCallback((id) => {
601
+ setSelectedIdState(id);
602
+ if (onSelectBoxId) onSelectBoxId(id);
603
+ }, [onSelectBoxId]);
604
+ useEffect(() => {
605
+ if (selectedBoxId !== void 0) {
606
+ setSelectedIdState(selectedBoxId);
607
+ }
608
+ }, [selectedBoxId]);
596
609
  useEffect(() => {
597
610
  setBoxes(layout?.boxes ?? []);
598
611
  }, [layout, slideIndex]);
@@ -628,30 +641,38 @@ function SlideDesignOverlay({
628
641
  newY = Math.round(Math.max(0, Math.min(720 - origH, origY + dy)));
629
642
  break;
630
643
  case "se":
631
- newW = Math.round(Math.max(100, Math.min(1280 - origX, origW + dx)));
632
- newH = Math.round(Math.max(40, Math.min(720 - origY, origH + dy)));
644
+ newW = Math.round(Math.max(60, Math.min(1280 - origX, origW + dx)));
645
+ newH = Math.round(Math.max(30, Math.min(720 - origY, origH + dy)));
633
646
  break;
634
647
  case "e":
635
- newW = Math.round(Math.max(100, Math.min(1280 - origX, origW + dx)));
648
+ newW = Math.round(Math.max(60, Math.min(1280 - origX, origW + dx)));
636
649
  break;
637
650
  case "s":
638
- newH = Math.round(Math.max(40, Math.min(720 - origY, origH + dy)));
651
+ newH = Math.round(Math.max(30, Math.min(720 - origY, origH + dy)));
639
652
  break;
640
653
  case "sw":
641
- newW = Math.round(Math.max(100, origW - dx));
642
- newX = Math.round(Math.min(origX + origW - 100, origX + dx));
643
- newH = Math.round(Math.max(40, origH + dy));
654
+ newW = Math.round(Math.max(60, origW - dx));
655
+ newX = Math.round(Math.min(origX + origW - 60, origX + dx));
656
+ newH = Math.round(Math.max(30, origH + dy));
644
657
  break;
645
658
  case "ne":
646
- newW = Math.round(Math.max(100, origW + dx));
647
- newH = Math.round(Math.max(40, origH - dy));
648
- newY = Math.round(Math.min(origY + origH - 40, origY + dy));
659
+ newW = Math.round(Math.max(60, origW + dx));
660
+ newH = Math.round(Math.max(30, origH - dy));
661
+ newY = Math.round(Math.min(origY + origH - 30, origY + dy));
649
662
  break;
650
663
  case "nw":
651
- newW = Math.round(Math.max(100, origW - dx));
652
- newX = Math.round(Math.min(origX + origW - 100, origX + dx));
653
- newH = Math.round(Math.max(40, origH - dy));
654
- newY = Math.round(Math.min(origY + origH - 40, origY + dy));
664
+ newW = Math.round(Math.max(60, origW - dx));
665
+ newX = Math.round(Math.min(origX + origW - 60, origX + dx));
666
+ newH = Math.round(Math.max(30, origH - dy));
667
+ newY = Math.round(Math.min(origY + origH - 30, origY + dy));
668
+ break;
669
+ case "n":
670
+ newH = Math.round(Math.max(30, origH - dy));
671
+ newY = Math.round(Math.min(origY + origH - 30, origY + dy));
672
+ break;
673
+ case "w":
674
+ newW = Math.round(Math.max(60, origW - dx));
675
+ newX = Math.round(Math.min(origX + origW - 60, origX + dx));
655
676
  break;
656
677
  }
657
678
  return { ...b, pos: [newX, newY, newW, newH] };
@@ -661,8 +682,11 @@ function SlideDesignOverlay({
661
682
  });
662
683
  }, [dragging, onLayoutChange]);
663
684
  const handleMouseUp = useCallback(() => {
685
+ if (dragging && onSave) {
686
+ onSave({ boxes });
687
+ }
664
688
  setDragging(null);
665
- }, []);
689
+ }, [dragging, boxes, onSave]);
666
690
  useEffect(() => {
667
691
  if (dragging) {
668
692
  window.addEventListener("mousemove", handleMouseMove);
@@ -673,6 +697,33 @@ function SlideDesignOverlay({
673
697
  };
674
698
  }
675
699
  }, [dragging, handleMouseMove, handleMouseUp]);
700
+ const removeSelectedBox = useCallback(() => {
701
+ if (!selectedId) return;
702
+ const boxToRemove = boxes.find((b) => b.id === selectedId);
703
+ setBoxes((prev) => {
704
+ const updated = prev.filter((b) => b.id !== selectedId);
705
+ onLayoutChange({ boxes: updated });
706
+ if (onSave) onSave({ boxes: updated });
707
+ return updated;
708
+ });
709
+ setSelectedId(null);
710
+ if (boxToRemove && onDeleteBox) {
711
+ onDeleteBox(boxToRemove);
712
+ }
713
+ }, [selectedId, boxes, onLayoutChange, onSave, onDeleteBox, setSelectedId]);
714
+ useEffect(() => {
715
+ const handleKeyDown = (e) => {
716
+ if (editingId) return;
717
+ if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;
718
+ if ((e.key === "Delete" || e.key === "Backspace") && selectedId) {
719
+ e.preventDefault();
720
+ e.stopPropagation();
721
+ removeSelectedBox();
722
+ }
723
+ };
724
+ window.addEventListener("keydown", handleKeyDown);
725
+ return () => window.removeEventListener("keydown", handleKeyDown);
726
+ }, [selectedId, editingId, removeSelectedBox]);
676
727
  const addNewBox = (targetTag) => {
677
728
  const isH1 = targetTag === "h1";
678
729
  const newId = `box-${Date.now().toString(36)}`;
@@ -690,6 +741,9 @@ function SlideDesignOverlay({
690
741
  setSelectedId(newId);
691
742
  setEditingId(newId);
692
743
  onLayoutChange({ boxes: updated });
744
+ if (onAddBox) {
745
+ onAddBox(newBox);
746
+ }
693
747
  };
694
748
  const updateSelectedBox = (partial) => {
695
749
  if (!selectedId) return;
@@ -699,15 +753,6 @@ function SlideDesignOverlay({
699
753
  return updated;
700
754
  });
701
755
  };
702
- const removeSelectedBox = () => {
703
- if (!selectedId) return;
704
- setBoxes((prev) => {
705
- const updated = prev.filter((b) => b.id !== selectedId);
706
- onLayoutChange({ boxes: updated });
707
- return updated;
708
- });
709
- setSelectedId(null);
710
- };
711
756
  const isLight = theme === "light";
712
757
  const isNavy = theme === "navy";
713
758
  const toolbarBg = isLight ? "rgba(255, 255, 255, 0.96)" : isNavy ? "rgba(11, 19, 43, 0.95)" : "rgba(24, 25, 32, 0.95)";
@@ -939,12 +984,14 @@ function SlideDesignOverlay({
939
984
  }
940
985
  ),
941
986
  isSelected && /* @__PURE__ */ jsxs(Fragment, { children: [
942
- /* @__PURE__ */ jsx("div", { style: handleStyle("se", isLight), onMouseDown: (e) => handleMouseDown(e, box, "se") }),
943
- /* @__PURE__ */ jsx("div", { style: handleStyle("e", isLight), onMouseDown: (e) => handleMouseDown(e, box, "e") }),
944
- /* @__PURE__ */ jsx("div", { style: handleStyle("s", isLight), onMouseDown: (e) => handleMouseDown(e, box, "s") }),
945
- /* @__PURE__ */ jsx("div", { style: handleStyle("sw", isLight), onMouseDown: (e) => handleMouseDown(e, box, "sw") }),
946
- /* @__PURE__ */ jsx("div", { style: handleStyle("ne", isLight), onMouseDown: (e) => handleMouseDown(e, box, "ne") }),
947
- /* @__PURE__ */ jsx("div", { style: handleStyle("nw", isLight), onMouseDown: (e) => handleMouseDown(e, box, "nw") })
987
+ /* @__PURE__ */ jsx("div", { style: handleStyle("nw", isLight), onMouseDown: (e) => handleMouseDown(e, box, "nw"), title: "K\xE9o g\xF3c tr\xEAn-tr\xE1i" }),
988
+ /* @__PURE__ */ jsx("div", { style: handleStyle("n", isLight), onMouseDown: (e) => handleMouseDown(e, box, "n"), title: "K\xE9o c\u1EA1nh tr\xEAn" }),
989
+ /* @__PURE__ */ jsx("div", { style: handleStyle("ne", isLight), onMouseDown: (e) => handleMouseDown(e, box, "ne"), title: "K\xE9o g\xF3c tr\xEAn-ph\u1EA3i" }),
990
+ /* @__PURE__ */ jsx("div", { style: handleStyle("e", isLight), onMouseDown: (e) => handleMouseDown(e, box, "e"), title: "K\xE9o c\u1EA1nh ph\u1EA3i (Ch\u1EC9nh \u0111\u1ED9 r\u1ED9ng / wrap text)" }),
991
+ /* @__PURE__ */ jsx("div", { style: handleStyle("se", isLight), onMouseDown: (e) => handleMouseDown(e, box, "se"), title: "K\xE9o g\xF3c d\u01B0\u1EDBi-ph\u1EA3i (Ch\u1EC9nh k\xEDch th\u01B0\u1EDBc / wrap text)" }),
992
+ /* @__PURE__ */ jsx("div", { style: handleStyle("s", isLight), onMouseDown: (e) => handleMouseDown(e, box, "s"), title: "K\xE9o c\u1EA1nh d\u01B0\u1EDBi" }),
993
+ /* @__PURE__ */ jsx("div", { style: handleStyle("sw", isLight), onMouseDown: (e) => handleMouseDown(e, box, "sw"), title: "K\xE9o g\xF3c d\u01B0\u1EDBi-tr\xE1i" }),
994
+ /* @__PURE__ */ jsx("div", { style: handleStyle("w", isLight), onMouseDown: (e) => handleMouseDown(e, box, "w"), title: "K\xE9o c\u1EA1nh tr\xE1i (Ch\u1EC9nh \u0111\u1ED9 r\u1ED9ng / wrap text)" })
948
995
  ] })
949
996
  ]
950
997
  },
@@ -1028,7 +1075,7 @@ function SlideDesignOverlay({
1028
1075
  /* @__PURE__ */ jsx("input", { type: "color", value: selectedBox.color ?? (isLight ? "#0f172a" : "#38bdf8"), onChange: (e) => updateSelectedBox({ color: e.target.value }), style: { width: "22px", height: "22px", padding: "0", border: "none", borderRadius: "4px", cursor: "pointer", backgroundColor: "transparent" } })
1029
1076
  ] }),
1030
1077
  /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", gap: "2px", whiteSpace: "nowrap" }, children: ["left", "center", "right"].map((align) => /* @__PURE__ */ jsx("button", { type: "button", onClick: () => updateSelectedBox({ textAlign: align }), style: { ...btnStyle, backgroundColor: selectedBox.textAlign === align ? "#0284c7" : isLight ? "rgba(0,0,0,0.05)" : "rgba(255,255,255,0.05)", color: selectedBox.textAlign === align ? "#ffffff" : isLight ? "#0f172a" : "#e2e8f0", textTransform: "capitalize", fontSize: "11px", padding: "2px 6px", height: "22px" }, children: align }, align)) }),
1031
- /* @__PURE__ */ jsx("button", { type: "button", onClick: removeSelectedBox, style: { ...btnStyle, backgroundColor: isLight ? "rgba(239, 68, 68, 0.1)" : "rgba(239, 68, 68, 0.2)", color: isLight ? "#dc2626" : "#f87171", border: isLight ? "1px solid rgba(239, 68, 68, 0.3)" : "1px solid rgba(239, 68, 68, 0.4)", fontWeight: 500, height: "22px", padding: "0 8px" }, title: "X\xF3a \u0111\u1ECBnh v\u1ECB t\u1EF1 do c\u1EE7a khung n\xE0y", children: "X\xF3a v\u1ECB tr\xED" })
1078
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: removeSelectedBox, style: { ...btnStyle, backgroundColor: isLight ? "rgba(239, 68, 68, 0.1)" : "rgba(239, 68, 68, 0.2)", color: isLight ? "#dc2626" : "#f87171", border: isLight ? "1px solid rgba(239, 68, 68, 0.3)" : "1px solid rgba(239, 68, 68, 0.4)", fontWeight: 500, height: "22px", padding: "0 8px" }, title: "X\xF3a ph\u1EA7n t\u1EED (ho\u1EB7c nh\u1EA5n Delete tr\xEAn b\xE0n ph\xEDm)", children: "X\xF3a ph\u1EA7n t\u1EED (Del)" })
1032
1079
  ]
1033
1080
  }
1034
1081
  )
@@ -1061,6 +1108,10 @@ function handleStyle(pos, isLight = false) {
1061
1108
  return { ...base, right: `-${size / 2}px`, top: `-${size / 2}px`, cursor: "ne-resize" };
1062
1109
  case "nw":
1063
1110
  return { ...base, left: `-${size / 2}px`, top: `-${size / 2}px`, cursor: "nw-resize" };
1111
+ case "n":
1112
+ return { ...base, top: `-${size / 2}px`, left: `calc(50% - ${size / 2}px)`, cursor: "n-resize" };
1113
+ case "w":
1114
+ return { ...base, left: `-${size / 2}px`, top: `calc(50% - ${size / 2}px)`, cursor: "w-resize" };
1064
1115
  }
1065
1116
  }
1066
1117
  var DEFAULT_THEME_OPTIONS = [