@thanh01.pmt/presentation-kit 0.2.8 → 0.2.10

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.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkVLAPHJOC_cjs = require('./chunk-VLAPHJOC.cjs');
4
- var chunkIGCFC6GI_cjs = require('./chunk-IGCFC6GI.cjs');
3
+ var chunkTGI6YSZP_cjs = require('./chunk-TGI6YSZP.cjs');
4
+ var chunk3Q4RMZVQ_cjs = require('./chunk-3Q4RMZVQ.cjs');
5
5
 
6
6
  // src/engine.ts
7
7
  function createEngine(config = {}) {
@@ -18,14 +18,14 @@ function createEngine(config = {}) {
18
18
  }
19
19
  return {
20
20
  render: (markdown, options) => {
21
- return chunkVLAPHJOC_cjs.renderSlide(markdown, mergeOptions(options));
21
+ return chunkTGI6YSZP_cjs.renderSlide(markdown, mergeOptions(options));
22
22
  },
23
23
  renderAsync: async (markdown, options) => {
24
- return chunkVLAPHJOC_cjs.renderSlideAsync(markdown, mergeOptions(options));
24
+ return chunkTGI6YSZP_cjs.renderSlideAsync(markdown, mergeOptions(options));
25
25
  },
26
26
  getThemeCss: (theme, containerId) => {
27
- const resolved = chunkVLAPHJOC_cjs.resolveTheme(theme);
28
- return chunkVLAPHJOC_cjs.generateScopedCss2(resolved, containerId);
27
+ const resolved = chunkTGI6YSZP_cjs.resolveTheme(theme);
28
+ return chunkTGI6YSZP_cjs.generateScopedCss2(resolved, containerId);
29
29
  }
30
30
  };
31
31
  }
@@ -101,8 +101,8 @@ async function convertMarkdownToPptx(markdown, options) {
101
101
  pptx.layout = "LAYOUT_WIDE";
102
102
  if (options?.title) pptx.title = options.title;
103
103
  if (options?.author) pptx.author = options.author;
104
- const renderResult = chunkVLAPHJOC_cjs.renderSlide(markdown);
105
- const { slides } = chunkIGCFC6GI_cjs.splitMarkdownSlides(markdown);
104
+ const renderResult = chunkTGI6YSZP_cjs.renderSlide(markdown);
105
+ const { slides } = chunk3Q4RMZVQ_cjs.splitMarkdownSlides(markdown);
106
106
  const isDark = options?.theme !== "light";
107
107
  const defaultBg = isDark ? "14151B" : "FFFFFF";
108
108
  const defaultText = isDark ? "F1F5F9" : "1E293B";
@@ -201,143 +201,147 @@ async function convertMarkdownToPptx(markdown, options) {
201
201
 
202
202
  Object.defineProperty(exports, "convertTextArrows", {
203
203
  enumerable: true,
204
- get: function () { return chunkVLAPHJOC_cjs.convertTextArrows; }
204
+ get: function () { return chunkTGI6YSZP_cjs.convertTextArrows; }
205
205
  });
206
206
  Object.defineProperty(exports, "countSlides", {
207
207
  enumerable: true,
208
- get: function () { return chunkVLAPHJOC_cjs.countSlides; }
208
+ get: function () { return chunkTGI6YSZP_cjs.countSlides; }
209
209
  });
210
210
  Object.defineProperty(exports, "darkThemeTokens", {
211
211
  enumerable: true,
212
- get: function () { return chunkVLAPHJOC_cjs.darkThemeTokens; }
212
+ get: function () { return chunkTGI6YSZP_cjs.darkThemeTokens; }
213
213
  });
214
214
  Object.defineProperty(exports, "defineTheme", {
215
215
  enumerable: true,
216
- get: function () { return chunkVLAPHJOC_cjs.defineTheme; }
216
+ get: function () { return chunkTGI6YSZP_cjs.defineTheme; }
217
217
  });
218
218
  Object.defineProperty(exports, "detectMermaidBlocks", {
219
219
  enumerable: true,
220
- get: function () { return chunkVLAPHJOC_cjs.detectMermaidBlocks; }
220
+ get: function () { return chunkTGI6YSZP_cjs.detectMermaidBlocks; }
221
221
  });
222
222
  Object.defineProperty(exports, "extractLayoutsAndNotes", {
223
223
  enumerable: true,
224
- get: function () { return chunkVLAPHJOC_cjs.extractLayoutsAndNotes; }
224
+ get: function () { return chunkTGI6YSZP_cjs.extractLayoutsAndNotes; }
225
225
  });
226
226
  Object.defineProperty(exports, "extractMarpSource", {
227
227
  enumerable: true,
228
- get: function () { return chunkVLAPHJOC_cjs.extractMarpSource; }
228
+ get: function () { return chunkTGI6YSZP_cjs.extractMarpSource; }
229
229
  });
230
230
  Object.defineProperty(exports, "extractMaxClicks", {
231
231
  enumerable: true,
232
- get: function () { return chunkVLAPHJOC_cjs.extractMaxClicks; }
232
+ get: function () { return chunkTGI6YSZP_cjs.extractMaxClicks; }
233
233
  });
234
234
  Object.defineProperty(exports, "filterPresenterNotes", {
235
235
  enumerable: true,
236
- get: function () { return chunkVLAPHJOC_cjs.filterPresenterNotes; }
236
+ get: function () { return chunkTGI6YSZP_cjs.filterPresenterNotes; }
237
237
  });
238
238
  Object.defineProperty(exports, "generateClickCss", {
239
239
  enumerable: true,
240
- get: function () { return chunkVLAPHJOC_cjs.generateClickCss; }
240
+ get: function () { return chunkTGI6YSZP_cjs.generateClickCss; }
241
241
  });
242
242
  Object.defineProperty(exports, "generateLayoutCss", {
243
243
  enumerable: true,
244
- get: function () { return chunkVLAPHJOC_cjs.generateLayoutCss; }
244
+ get: function () { return chunkTGI6YSZP_cjs.generateLayoutCss; }
245
245
  });
246
246
  Object.defineProperty(exports, "generateScopedCss", {
247
247
  enumerable: true,
248
- get: function () { return chunkVLAPHJOC_cjs.generateScopedCss2; }
248
+ get: function () { return chunkTGI6YSZP_cjs.generateScopedCss2; }
249
249
  });
250
250
  Object.defineProperty(exports, "generateScopedCssFromTokens", {
251
251
  enumerable: true,
252
- get: function () { return chunkVLAPHJOC_cjs.generateScopedCss; }
252
+ get: function () { return chunkTGI6YSZP_cjs.generateScopedCss; }
253
253
  });
254
254
  Object.defineProperty(exports, "getHighlighter", {
255
255
  enumerable: true,
256
- get: function () { return chunkVLAPHJOC_cjs.getHighlighter; }
256
+ get: function () { return chunkTGI6YSZP_cjs.getHighlighter; }
257
257
  });
258
258
  Object.defineProperty(exports, "getThemeTokens", {
259
259
  enumerable: true,
260
- get: function () { return chunkVLAPHJOC_cjs.getThemeTokens; }
260
+ get: function () { return chunkTGI6YSZP_cjs.getThemeTokens; }
261
261
  });
262
262
  Object.defineProperty(exports, "highlightCodeBlocks", {
263
263
  enumerable: true,
264
- get: function () { return chunkVLAPHJOC_cjs.highlightCodeBlocks; }
264
+ get: function () { return chunkTGI6YSZP_cjs.highlightCodeBlocks; }
265
265
  });
266
266
  Object.defineProperty(exports, "isLayoutComment", {
267
267
  enumerable: true,
268
- get: function () { return chunkVLAPHJOC_cjs.isLayoutComment; }
268
+ get: function () { return chunkTGI6YSZP_cjs.isLayoutComment; }
269
269
  });
270
270
  Object.defineProperty(exports, "lightThemeTokens", {
271
271
  enumerable: true,
272
- get: function () { return chunkVLAPHJOC_cjs.lightThemeTokens; }
272
+ get: function () { return chunkTGI6YSZP_cjs.lightThemeTokens; }
273
273
  });
274
274
  Object.defineProperty(exports, "navyThemeTokens", {
275
275
  enumerable: true,
276
- get: function () { return chunkVLAPHJOC_cjs.navyThemeTokens; }
276
+ get: function () { return chunkTGI6YSZP_cjs.navyThemeTokens; }
277
277
  });
278
278
  Object.defineProperty(exports, "parseLayoutFromComment", {
279
279
  enumerable: true,
280
- get: function () { return chunkVLAPHJOC_cjs.parseLayoutFromComment; }
280
+ get: function () { return chunkTGI6YSZP_cjs.parseLayoutFromComment; }
281
281
  });
282
282
  Object.defineProperty(exports, "postprocessClicks", {
283
283
  enumerable: true,
284
- get: function () { return chunkVLAPHJOC_cjs.postprocessClicks; }
284
+ get: function () { return chunkTGI6YSZP_cjs.postprocessClicks; }
285
285
  });
286
286
  Object.defineProperty(exports, "preprocessClicks", {
287
287
  enumerable: true,
288
- get: function () { return chunkVLAPHJOC_cjs.preprocessClicks; }
288
+ get: function () { return chunkTGI6YSZP_cjs.preprocessClicks; }
289
289
  });
290
290
  Object.defineProperty(exports, "renderMarp", {
291
291
  enumerable: true,
292
- get: function () { return chunkVLAPHJOC_cjs.renderMarp; }
292
+ get: function () { return chunkTGI6YSZP_cjs.renderMarp; }
293
293
  });
294
294
  Object.defineProperty(exports, "renderMermaidDiagrams", {
295
295
  enumerable: true,
296
- get: function () { return chunkVLAPHJOC_cjs.renderMermaidDiagrams; }
296
+ get: function () { return chunkTGI6YSZP_cjs.renderMermaidDiagrams; }
297
297
  });
298
298
  Object.defineProperty(exports, "renderSlide", {
299
299
  enumerable: true,
300
- get: function () { return chunkVLAPHJOC_cjs.renderSlide; }
300
+ get: function () { return chunkTGI6YSZP_cjs.renderSlide; }
301
301
  });
302
302
  Object.defineProperty(exports, "renderSlideAsync", {
303
303
  enumerable: true,
304
- get: function () { return chunkVLAPHJOC_cjs.renderSlideAsync; }
304
+ get: function () { return chunkTGI6YSZP_cjs.renderSlideAsync; }
305
305
  });
306
306
  Object.defineProperty(exports, "resolveTheme", {
307
307
  enumerable: true,
308
- get: function () { return chunkVLAPHJOC_cjs.resolveTheme; }
308
+ get: function () { return chunkTGI6YSZP_cjs.resolveTheme; }
309
309
  });
310
310
  Object.defineProperty(exports, "sanitizeMermaidCode", {
311
311
  enumerable: true,
312
- get: function () { return chunkVLAPHJOC_cjs.sanitizeMermaidCode; }
312
+ get: function () { return chunkTGI6YSZP_cjs.sanitizeMermaidCode; }
313
313
  });
314
314
  Object.defineProperty(exports, "SLIDE_LAYOUT_PRESETS", {
315
315
  enumerable: true,
316
- get: function () { return chunkIGCFC6GI_cjs.SLIDE_LAYOUT_PRESETS; }
316
+ get: function () { return chunk3Q4RMZVQ_cjs.SLIDE_LAYOUT_PRESETS; }
317
317
  });
318
318
  Object.defineProperty(exports, "getSlideLayoutPresetById", {
319
319
  enumerable: true,
320
- get: function () { return chunkIGCFC6GI_cjs.getSlideLayoutPresetById; }
320
+ get: function () { return chunk3Q4RMZVQ_cjs.getSlideLayoutPresetById; }
321
321
  });
322
322
  Object.defineProperty(exports, "getSlideLayoutPresetsByCategory", {
323
323
  enumerable: true,
324
- get: function () { return chunkIGCFC6GI_cjs.getSlideLayoutPresetsByCategory; }
324
+ get: function () { return chunk3Q4RMZVQ_cjs.getSlideLayoutPresetsByCategory; }
325
+ });
326
+ Object.defineProperty(exports, "removeSlideElementFromMarkdown", {
327
+ enumerable: true,
328
+ get: function () { return chunk3Q4RMZVQ_cjs.removeSlideElementFromMarkdown; }
325
329
  });
326
330
  Object.defineProperty(exports, "serializeLayoutToComment", {
327
331
  enumerable: true,
328
- get: function () { return chunkIGCFC6GI_cjs.serializeLayoutToComment; }
332
+ get: function () { return chunk3Q4RMZVQ_cjs.serializeLayoutToComment; }
329
333
  });
330
334
  Object.defineProperty(exports, "splitMarkdownSlides", {
331
335
  enumerable: true,
332
- get: function () { return chunkIGCFC6GI_cjs.splitMarkdownSlides; }
336
+ get: function () { return chunk3Q4RMZVQ_cjs.splitMarkdownSlides; }
333
337
  });
334
338
  Object.defineProperty(exports, "updateSlideLayoutInMarkdown", {
335
339
  enumerable: true,
336
- get: function () { return chunkIGCFC6GI_cjs.updateSlideLayoutInMarkdown; }
340
+ get: function () { return chunk3Q4RMZVQ_cjs.updateSlideLayoutInMarkdown; }
337
341
  });
338
342
  Object.defineProperty(exports, "updateSlideTextInMarkdown", {
339
343
  enumerable: true,
340
- get: function () { return chunkIGCFC6GI_cjs.updateSlideTextInMarkdown; }
344
+ get: function () { return chunk3Q4RMZVQ_cjs.updateSlideTextInMarkdown; }
341
345
  });
342
346
  exports.cleanHexColor = cleanHexColor;
343
347
  exports.convertMarkdownToPptx = convertMarkdownToPptx;
package/dist/index.d.cts CHANGED
@@ -110,6 +110,14 @@ declare function updateSlideLayoutInMarkdown(markdown: string, slideIndex: numbe
110
110
  * Replaces oldText with newText within the given slideIndex.
111
111
  */
112
112
  declare function updateSlideTextInMarkdown(markdown: string, slideIndex: number, oldText: string, newText: string): string;
113
+ /**
114
+ * Remove an element (line) and its layout box from a specific slide's markdown.
115
+ */
116
+ declare function removeSlideElementFromMarkdown(markdown: string, slideIndex: number, options: {
117
+ content?: string;
118
+ boxId?: string;
119
+ target?: string;
120
+ }): string;
113
121
 
114
122
  /**
115
123
  * Generate scoped CSS for per-slide layout overrides.
@@ -155,4 +163,4 @@ declare function convertTextArrows(text: string): string;
155
163
  */
156
164
  declare function extractMarpSource(raw: string): string;
157
165
 
158
- export { MermaidBlock, type PptxExportOptions, SlideEngine, SlideEngineConfig, SlideLayoutData, ThemeTokens, cleanHexColor, convertMarkdownToPptx, convertTextArrows, createEngine, darkThemeTokens, detectMermaidBlocks, extractLayoutsAndNotes, extractMarpSource, filterPresenterNotes, generateLayoutCss, generateScopedCss as generateScopedCssFromTokens, getHighlighter, highlightCodeBlocks, isLayoutComment, lightThemeTokens, navyThemeTokens, parseFontSizeToPt, parseLayoutFromComment, renderMermaidDiagrams, sanitizeMermaidCode, serializeLayoutToComment, splitMarkdownSlides, updateSlideLayoutInMarkdown, updateSlideTextInMarkdown };
166
+ export { MermaidBlock, type PptxExportOptions, SlideEngine, SlideEngineConfig, SlideLayoutData, ThemeTokens, cleanHexColor, convertMarkdownToPptx, convertTextArrows, createEngine, darkThemeTokens, detectMermaidBlocks, extractLayoutsAndNotes, extractMarpSource, filterPresenterNotes, generateLayoutCss, generateScopedCss as generateScopedCssFromTokens, getHighlighter, highlightCodeBlocks, isLayoutComment, lightThemeTokens, navyThemeTokens, parseFontSizeToPt, parseLayoutFromComment, removeSlideElementFromMarkdown, renderMermaidDiagrams, sanitizeMermaidCode, serializeLayoutToComment, splitMarkdownSlides, updateSlideLayoutInMarkdown, updateSlideTextInMarkdown };
package/dist/index.d.ts CHANGED
@@ -110,6 +110,14 @@ declare function updateSlideLayoutInMarkdown(markdown: string, slideIndex: numbe
110
110
  * Replaces oldText with newText within the given slideIndex.
111
111
  */
112
112
  declare function updateSlideTextInMarkdown(markdown: string, slideIndex: number, oldText: string, newText: string): string;
113
+ /**
114
+ * Remove an element (line) and its layout box from a specific slide's markdown.
115
+ */
116
+ declare function removeSlideElementFromMarkdown(markdown: string, slideIndex: number, options: {
117
+ content?: string;
118
+ boxId?: string;
119
+ target?: string;
120
+ }): string;
113
121
 
114
122
  /**
115
123
  * Generate scoped CSS for per-slide layout overrides.
@@ -155,4 +163,4 @@ declare function convertTextArrows(text: string): string;
155
163
  */
156
164
  declare function extractMarpSource(raw: string): string;
157
165
 
158
- export { MermaidBlock, type PptxExportOptions, SlideEngine, SlideEngineConfig, SlideLayoutData, ThemeTokens, cleanHexColor, convertMarkdownToPptx, convertTextArrows, createEngine, darkThemeTokens, detectMermaidBlocks, extractLayoutsAndNotes, extractMarpSource, filterPresenterNotes, generateLayoutCss, generateScopedCss as generateScopedCssFromTokens, getHighlighter, highlightCodeBlocks, isLayoutComment, lightThemeTokens, navyThemeTokens, parseFontSizeToPt, parseLayoutFromComment, renderMermaidDiagrams, sanitizeMermaidCode, serializeLayoutToComment, splitMarkdownSlides, updateSlideLayoutInMarkdown, updateSlideTextInMarkdown };
166
+ export { MermaidBlock, type PptxExportOptions, SlideEngine, SlideEngineConfig, SlideLayoutData, ThemeTokens, cleanHexColor, convertMarkdownToPptx, convertTextArrows, createEngine, darkThemeTokens, detectMermaidBlocks, extractLayoutsAndNotes, extractMarpSource, filterPresenterNotes, generateLayoutCss, generateScopedCss as generateScopedCssFromTokens, getHighlighter, highlightCodeBlocks, isLayoutComment, lightThemeTokens, navyThemeTokens, parseFontSizeToPt, parseLayoutFromComment, removeSlideElementFromMarkdown, renderMermaidDiagrams, sanitizeMermaidCode, serializeLayoutToComment, splitMarkdownSlides, updateSlideLayoutInMarkdown, updateSlideTextInMarkdown };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { resolveTheme, generateScopedCss2, renderSlideAsync, renderSlide } from './chunk-JOW4QWKF.js';
2
- export { convertTextArrows, countSlides, darkThemeTokens, defineTheme, detectMermaidBlocks, extractLayoutsAndNotes, extractMarpSource, extractMaxClicks, filterPresenterNotes, generateClickCss, generateLayoutCss, generateScopedCss2 as generateScopedCss, generateScopedCss as generateScopedCssFromTokens, getHighlighter, getThemeTokens, highlightCodeBlocks, isLayoutComment, lightThemeTokens, navyThemeTokens, parseLayoutFromComment, postprocessClicks, preprocessClicks, renderMarp, renderMermaidDiagrams, renderSlide, renderSlideAsync, resolveTheme, sanitizeMermaidCode } from './chunk-JOW4QWKF.js';
3
- import { splitMarkdownSlides } from './chunk-26ZVUVXF.js';
4
- export { SLIDE_LAYOUT_PRESETS, getSlideLayoutPresetById, getSlideLayoutPresetsByCategory, serializeLayoutToComment, splitMarkdownSlides, updateSlideLayoutInMarkdown, updateSlideTextInMarkdown } from './chunk-26ZVUVXF.js';
1
+ import { resolveTheme, generateScopedCss2, renderSlideAsync, renderSlide } from './chunk-NYLDRVHZ.js';
2
+ export { convertTextArrows, countSlides, darkThemeTokens, defineTheme, detectMermaidBlocks, extractLayoutsAndNotes, extractMarpSource, extractMaxClicks, filterPresenterNotes, generateClickCss, generateLayoutCss, generateScopedCss2 as generateScopedCss, generateScopedCss as generateScopedCssFromTokens, getHighlighter, getThemeTokens, highlightCodeBlocks, isLayoutComment, lightThemeTokens, navyThemeTokens, parseLayoutFromComment, postprocessClicks, preprocessClicks, renderMarp, renderMermaidDiagrams, renderSlide, renderSlideAsync, resolveTheme, sanitizeMermaidCode } from './chunk-NYLDRVHZ.js';
3
+ import { splitMarkdownSlides } from './chunk-V6X7D44H.js';
4
+ export { SLIDE_LAYOUT_PRESETS, getSlideLayoutPresetById, getSlideLayoutPresetsByCategory, removeSlideElementFromMarkdown, serializeLayoutToComment, splitMarkdownSlides, updateSlideLayoutInMarkdown, updateSlideTextInMarkdown } from './chunk-V6X7D44H.js';
5
5
 
6
6
  // src/engine.ts
7
7
  function createEngine(config = {}) {
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkVLAPHJOC_cjs = require('../chunk-VLAPHJOC.cjs');
4
- var chunkIGCFC6GI_cjs = require('../chunk-IGCFC6GI.cjs');
3
+ var chunkTGI6YSZP_cjs = require('../chunk-TGI6YSZP.cjs');
4
+ var chunk3Q4RMZVQ_cjs = require('../chunk-3Q4RMZVQ.cjs');
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
 
@@ -21,7 +21,7 @@ function useSlideState(options) {
21
21
  const result = react.useMemo(() => {
22
22
  if (!markdown || !markdown.trim()) return null;
23
23
  renderCountRef.current++;
24
- return chunkVLAPHJOC_cjs.renderSlide(markdown, {
24
+ return chunkTGI6YSZP_cjs.renderSlide(markdown, {
25
25
  theme,
26
26
  enableMermaid: true,
27
27
  enableClicks,
@@ -585,23 +585,38 @@ function SlideDesignOverlay({
585
585
  layout,
586
586
  onLayoutChange,
587
587
  onSave,
588
+ onDeleteBox,
589
+ onAddBox,
588
590
  onClose,
589
591
  isActive,
590
- theme = "dark"
592
+ theme = "dark",
593
+ selectedBoxId,
594
+ onSelectBoxId
591
595
  }) {
592
596
  if (!isActive) return null;
593
597
  const [boxes, setBoxes] = react.useState(layout?.boxes ?? []);
594
- const [selectedId, setSelectedId] = react.useState(null);
598
+ const [selectedId, setSelectedIdState] = react.useState(selectedBoxId ?? null);
595
599
  const [editingId, setEditingId] = react.useState(null);
596
600
  const containerRef = react.useRef(null);
601
+ const setSelectedId = react.useCallback((id) => {
602
+ setSelectedIdState(id);
603
+ if (onSelectBoxId) onSelectBoxId(id);
604
+ }, [onSelectBoxId]);
605
+ react.useEffect(() => {
606
+ if (selectedBoxId !== void 0) {
607
+ setSelectedIdState(selectedBoxId);
608
+ }
609
+ }, [selectedBoxId]);
597
610
  react.useEffect(() => {
598
611
  setBoxes(layout?.boxes ?? []);
599
612
  }, [layout, slideIndex]);
600
613
  const selectedBox = boxes.find((b) => b.id === selectedId) ?? null;
614
+ const hasMovedRef = react.useRef(false);
601
615
  const [dragging, setDragging] = react.useState(null);
602
616
  const handleMouseDown = (e, box, type) => {
603
617
  e.preventDefault();
604
618
  e.stopPropagation();
619
+ hasMovedRef.current = false;
605
620
  setSelectedId(box.id);
606
621
  setDragging({
607
622
  type,
@@ -618,6 +633,9 @@ function SlideDesignOverlay({
618
633
  const scaleY = 720 / rect.height;
619
634
  const dx = (e.clientX - dragging.startX) * scaleX;
620
635
  const dy = (e.clientY - dragging.startY) * scaleY;
636
+ if (Math.abs(dx) > 1 || Math.abs(dy) > 1) {
637
+ hasMovedRef.current = true;
638
+ }
621
639
  const [origX, origY, origW, origH] = dragging.startPos;
622
640
  setBoxes((prev) => {
623
641
  const updated = prev.map((b) => {
@@ -629,30 +647,38 @@ function SlideDesignOverlay({
629
647
  newY = Math.round(Math.max(0, Math.min(720 - origH, origY + dy)));
630
648
  break;
631
649
  case "se":
632
- newW = Math.round(Math.max(100, Math.min(1280 - origX, origW + dx)));
633
- newH = Math.round(Math.max(40, Math.min(720 - origY, origH + dy)));
650
+ newW = Math.round(Math.max(60, Math.min(1280 - origX, origW + dx)));
651
+ newH = Math.round(Math.max(30, Math.min(720 - origY, origH + dy)));
634
652
  break;
635
653
  case "e":
636
- newW = Math.round(Math.max(100, Math.min(1280 - origX, origW + dx)));
654
+ newW = Math.round(Math.max(60, Math.min(1280 - origX, origW + dx)));
637
655
  break;
638
656
  case "s":
639
- newH = Math.round(Math.max(40, Math.min(720 - origY, origH + dy)));
657
+ newH = Math.round(Math.max(30, Math.min(720 - origY, origH + dy)));
640
658
  break;
641
659
  case "sw":
642
- newW = Math.round(Math.max(100, origW - dx));
643
- newX = Math.round(Math.min(origX + origW - 100, origX + dx));
644
- newH = Math.round(Math.max(40, origH + dy));
660
+ newW = Math.round(Math.max(60, origW - dx));
661
+ newX = Math.round(Math.min(origX + origW - 60, origX + dx));
662
+ newH = Math.round(Math.max(30, origH + dy));
645
663
  break;
646
664
  case "ne":
647
- newW = Math.round(Math.max(100, origW + dx));
648
- newH = Math.round(Math.max(40, origH - dy));
649
- newY = Math.round(Math.min(origY + origH - 40, origY + dy));
665
+ newW = Math.round(Math.max(60, origW + dx));
666
+ newH = Math.round(Math.max(30, origH - dy));
667
+ newY = Math.round(Math.min(origY + origH - 30, origY + dy));
650
668
  break;
651
669
  case "nw":
652
- newW = Math.round(Math.max(100, origW - dx));
653
- newX = Math.round(Math.min(origX + origW - 100, origX + dx));
654
- newH = Math.round(Math.max(40, origH - dy));
655
- newY = Math.round(Math.min(origY + origH - 40, origY + dy));
670
+ newW = Math.round(Math.max(60, origW - dx));
671
+ newX = Math.round(Math.min(origX + origW - 60, origX + dx));
672
+ newH = Math.round(Math.max(30, origH - dy));
673
+ newY = Math.round(Math.min(origY + origH - 30, origY + dy));
674
+ break;
675
+ case "n":
676
+ newH = Math.round(Math.max(30, origH - dy));
677
+ newY = Math.round(Math.min(origY + origH - 30, origY + dy));
678
+ break;
679
+ case "w":
680
+ newW = Math.round(Math.max(60, origW - dx));
681
+ newX = Math.round(Math.min(origX + origW - 60, origX + dx));
656
682
  break;
657
683
  }
658
684
  return { ...b, pos: [newX, newY, newW, newH] };
@@ -662,8 +688,12 @@ function SlideDesignOverlay({
662
688
  });
663
689
  }, [dragging, onLayoutChange]);
664
690
  const handleMouseUp = react.useCallback(() => {
691
+ if (dragging && hasMovedRef.current && onSave) {
692
+ onSave({ boxes });
693
+ }
694
+ hasMovedRef.current = false;
665
695
  setDragging(null);
666
- }, []);
696
+ }, [dragging, boxes, onSave]);
667
697
  react.useEffect(() => {
668
698
  if (dragging) {
669
699
  window.addEventListener("mousemove", handleMouseMove);
@@ -674,6 +704,33 @@ function SlideDesignOverlay({
674
704
  };
675
705
  }
676
706
  }, [dragging, handleMouseMove, handleMouseUp]);
707
+ const removeSelectedBox = react.useCallback(() => {
708
+ if (!selectedId) return;
709
+ const boxToRemove = boxes.find((b) => b.id === selectedId);
710
+ setBoxes((prev) => {
711
+ const updated = prev.filter((b) => b.id !== selectedId);
712
+ onLayoutChange({ boxes: updated });
713
+ if (onSave) onSave({ boxes: updated });
714
+ return updated;
715
+ });
716
+ setSelectedId(null);
717
+ if (boxToRemove && onDeleteBox) {
718
+ onDeleteBox(boxToRemove);
719
+ }
720
+ }, [selectedId, boxes, onLayoutChange, onSave, onDeleteBox, setSelectedId]);
721
+ react.useEffect(() => {
722
+ const handleKeyDown = (e) => {
723
+ if (editingId) return;
724
+ if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;
725
+ if ((e.key === "Delete" || e.key === "Backspace") && selectedId) {
726
+ e.preventDefault();
727
+ e.stopPropagation();
728
+ removeSelectedBox();
729
+ }
730
+ };
731
+ window.addEventListener("keydown", handleKeyDown);
732
+ return () => window.removeEventListener("keydown", handleKeyDown);
733
+ }, [selectedId, editingId, removeSelectedBox]);
677
734
  const addNewBox = (targetTag) => {
678
735
  const isH1 = targetTag === "h1";
679
736
  const newId = `box-${Date.now().toString(36)}`;
@@ -691,6 +748,9 @@ function SlideDesignOverlay({
691
748
  setSelectedId(newId);
692
749
  setEditingId(newId);
693
750
  onLayoutChange({ boxes: updated });
751
+ if (onAddBox) {
752
+ onAddBox(newBox);
753
+ }
694
754
  };
695
755
  const updateSelectedBox = (partial) => {
696
756
  if (!selectedId) return;
@@ -700,15 +760,6 @@ function SlideDesignOverlay({
700
760
  return updated;
701
761
  });
702
762
  };
703
- const removeSelectedBox = () => {
704
- if (!selectedId) return;
705
- setBoxes((prev) => {
706
- const updated = prev.filter((b) => b.id !== selectedId);
707
- onLayoutChange({ boxes: updated });
708
- return updated;
709
- });
710
- setSelectedId(null);
711
- };
712
763
  const isLight = theme === "light";
713
764
  const isNavy = theme === "navy";
714
765
  const toolbarBg = isLight ? "rgba(255, 255, 255, 0.96)" : isNavy ? "rgba(11, 19, 43, 0.95)" : "rgba(24, 25, 32, 0.95)";
@@ -778,7 +829,7 @@ function SlideDesignOverlay({
778
829
  "select",
779
830
  {
780
831
  onChange: (e) => {
781
- const preset = chunkIGCFC6GI_cjs.SLIDE_LAYOUT_PRESETS.find((p) => p.id === e.target.value);
832
+ const preset = chunk3Q4RMZVQ_cjs.SLIDE_LAYOUT_PRESETS.find((p) => p.id === e.target.value);
782
833
  if (preset) {
783
834
  const clonedBoxes = JSON.parse(JSON.stringify(preset.layout.boxes));
784
835
  setBoxes(clonedBoxes);
@@ -798,7 +849,7 @@ function SlideDesignOverlay({
798
849
  title: "\xC1p d\u1EE5ng m\u1EABu b\u1ED1 c\u1EE5c c\xF3 s\u1EB5n",
799
850
  children: [
800
851
  /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, style: { backgroundColor: isLight ? "#ffffff" : "#1e1f29", color: subtextColor }, children: "M\u1EABu b\u1ED1 c\u1EE5c (Presets)..." }),
801
- chunkIGCFC6GI_cjs.SLIDE_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.id, style: { backgroundColor: isLight ? "#ffffff" : "#1e1f29", color: isLight ? "#0f172a" : "#f8fafc" }, children: p.name }, p.id))
852
+ chunk3Q4RMZVQ_cjs.SLIDE_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.id, style: { backgroundColor: isLight ? "#ffffff" : "#1e1f29", color: isLight ? "#0f172a" : "#f8fafc" }, children: p.name }, p.id))
802
853
  ]
803
854
  }
804
855
  ),
@@ -869,8 +920,9 @@ function SlideDesignOverlay({
869
920
  style: {
870
921
  width: "100%",
871
922
  height: "100%",
872
- background: "transparent",
873
- border: "none",
923
+ backgroundColor: isLight ? "#ffffff" : isNavy ? "#0b132b" : "#181920",
924
+ border: isLight ? "1px solid #0284c7" : "1px solid #38bdf8",
925
+ borderRadius: "4px",
874
926
  outline: "none",
875
927
  resize: "none",
876
928
  fontSize: box.fontSize ?? (box.target === "h1" ? "2.2rem" : "1.1rem"),
@@ -879,8 +931,9 @@ function SlideDesignOverlay({
879
931
  fontFamily: "Inter, sans-serif",
880
932
  fontWeight: box.target === "h1" ? 700 : 400,
881
933
  lineHeight: 1.25,
882
- padding: 0,
883
- margin: 0
934
+ padding: "4px 6px",
935
+ margin: 0,
936
+ boxShadow: "0 4px 16px rgba(0,0,0,0.25)"
884
937
  }
885
938
  }
886
939
  ) : /* @__PURE__ */ jsxRuntime.jsx(
@@ -894,20 +947,9 @@ function SlideDesignOverlay({
894
947
  style: {
895
948
  width: "100%",
896
949
  height: "100%",
897
- fontSize: box.fontSize ?? (box.target === "h1" ? "2.2rem" : "1.1rem"),
898
- color: box.color ?? (isLight ? "#0f172a" : "#f8fafc"),
899
- textAlign: box.textAlign ?? "left",
900
- fontFamily: "Inter, sans-serif",
901
- fontWeight: box.target === "h1" ? 700 : 400,
902
- lineHeight: 1.25,
903
- wordBreak: "break-word",
904
- userSelect: "none",
905
- cursor: "pointer",
906
- display: "flex",
907
- alignItems: "center"
950
+ cursor: "pointer"
908
951
  },
909
- title: "Click \u0111\xFAp \u0111\u1EC3 s\u1EEDa ch\u1EEF",
910
- children: box.content ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: box.content }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { opacity: 0.45, fontStyle: "italic", fontSize: "12px" }, children: box.target === "h1" ? "Ti\xEAu \u0111\u1EC1 (Click \u0111\xFAp \u0111\u1EC3 s\u1EEDa)..." : "N\u1ED9i dung (Click \u0111\xFAp \u0111\u1EC3 s\u1EEDa)..." })
952
+ title: "Click \u0111\xFAp \u0111\u1EC3 s\u1EEDa ch\u1EEF"
911
953
  }
912
954
  )
913
955
  }
@@ -940,12 +982,14 @@ function SlideDesignOverlay({
940
982
  }
941
983
  ),
942
984
  isSelected && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
943
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("se", isLight), onMouseDown: (e) => handleMouseDown(e, box, "se") }),
944
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("e", isLight), onMouseDown: (e) => handleMouseDown(e, box, "e") }),
945
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("s", isLight), onMouseDown: (e) => handleMouseDown(e, box, "s") }),
946
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("sw", isLight), onMouseDown: (e) => handleMouseDown(e, box, "sw") }),
947
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("ne", isLight), onMouseDown: (e) => handleMouseDown(e, box, "ne") }),
948
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("nw", isLight), onMouseDown: (e) => handleMouseDown(e, box, "nw") })
985
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("nw", isLight), onMouseDown: (e) => handleMouseDown(e, box, "nw"), title: "K\xE9o g\xF3c tr\xEAn-tr\xE1i" }),
986
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("n", isLight), onMouseDown: (e) => handleMouseDown(e, box, "n"), title: "K\xE9o c\u1EA1nh tr\xEAn" }),
987
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("ne", isLight), onMouseDown: (e) => handleMouseDown(e, box, "ne"), title: "K\xE9o g\xF3c tr\xEAn-ph\u1EA3i" }),
988
+ /* @__PURE__ */ jsxRuntime.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)" }),
989
+ /* @__PURE__ */ jsxRuntime.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)" }),
990
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("s", isLight), onMouseDown: (e) => handleMouseDown(e, box, "s"), title: "K\xE9o c\u1EA1nh d\u01B0\u1EDBi" }),
991
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle("sw", isLight), onMouseDown: (e) => handleMouseDown(e, box, "sw"), title: "K\xE9o g\xF3c d\u01B0\u1EDBi-tr\xE1i" }),
992
+ /* @__PURE__ */ jsxRuntime.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)" })
949
993
  ] })
950
994
  ]
951
995
  },
@@ -1029,7 +1073,7 @@ function SlideDesignOverlay({
1029
1073
  /* @__PURE__ */ jsxRuntime.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" } })
1030
1074
  ] }),
1031
1075
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", gap: "2px", whiteSpace: "nowrap" }, children: ["left", "center", "right"].map((align) => /* @__PURE__ */ jsxRuntime.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)) }),
1032
- /* @__PURE__ */ jsxRuntime.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" })
1076
+ /* @__PURE__ */ jsxRuntime.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)" })
1033
1077
  ]
1034
1078
  }
1035
1079
  )
@@ -1062,6 +1106,10 @@ function handleStyle(pos, isLight = false) {
1062
1106
  return { ...base, right: `-${size / 2}px`, top: `-${size / 2}px`, cursor: "ne-resize" };
1063
1107
  case "nw":
1064
1108
  return { ...base, left: `-${size / 2}px`, top: `-${size / 2}px`, cursor: "nw-resize" };
1109
+ case "n":
1110
+ return { ...base, top: `-${size / 2}px`, left: `calc(50% - ${size / 2}px)`, cursor: "n-resize" };
1111
+ case "w":
1112
+ return { ...base, left: `-${size / 2}px`, top: `calc(50% - ${size / 2}px)`, cursor: "w-resize" };
1065
1113
  }
1066
1114
  }
1067
1115
  var DEFAULT_THEME_OPTIONS = [
@@ -1197,7 +1245,7 @@ function SlideViewer({
1197
1245
  containers.forEach((container) => {
1198
1246
  if (container instanceof HTMLElement) {
1199
1247
  const themeName2 = typeof theme === "string" ? theme : "dark";
1200
- chunkVLAPHJOC_cjs.renderMermaidDiagrams(container, themeName2).catch(() => {
1248
+ chunkTGI6YSZP_cjs.renderMermaidDiagrams(container, themeName2).catch(() => {
1201
1249
  });
1202
1250
  }
1203
1251
  });
@@ -1414,7 +1462,7 @@ function SlideViewer({
1414
1462
  onSave: (layout) => {
1415
1463
  setLiveLayout(layout);
1416
1464
  if (onSaveMarkdown) {
1417
- const updated = chunkIGCFC6GI_cjs.updateSlideLayoutInMarkdown(markdown, currentIndex, layout);
1465
+ const updated = chunk3Q4RMZVQ_cjs.updateSlideLayoutInMarkdown(markdown, currentIndex, layout);
1418
1466
  onSaveMarkdown(updated);
1419
1467
  }
1420
1468
  },
@@ -1450,35 +1498,35 @@ function SlideViewer({
1450
1498
 
1451
1499
  Object.defineProperty(exports, "defineTheme", {
1452
1500
  enumerable: true,
1453
- get: function () { return chunkVLAPHJOC_cjs.defineTheme; }
1501
+ get: function () { return chunkTGI6YSZP_cjs.defineTheme; }
1454
1502
  });
1455
1503
  Object.defineProperty(exports, "extractMaxClicks", {
1456
1504
  enumerable: true,
1457
- get: function () { return chunkVLAPHJOC_cjs.extractMaxClicks; }
1505
+ get: function () { return chunkTGI6YSZP_cjs.extractMaxClicks; }
1458
1506
  });
1459
1507
  Object.defineProperty(exports, "generateClickCss", {
1460
1508
  enumerable: true,
1461
- get: function () { return chunkVLAPHJOC_cjs.generateClickCss; }
1509
+ get: function () { return chunkTGI6YSZP_cjs.generateClickCss; }
1462
1510
  });
1463
1511
  Object.defineProperty(exports, "postprocessClicks", {
1464
1512
  enumerable: true,
1465
- get: function () { return chunkVLAPHJOC_cjs.postprocessClicks; }
1513
+ get: function () { return chunkTGI6YSZP_cjs.postprocessClicks; }
1466
1514
  });
1467
1515
  Object.defineProperty(exports, "preprocessClicks", {
1468
1516
  enumerable: true,
1469
- get: function () { return chunkVLAPHJOC_cjs.preprocessClicks; }
1517
+ get: function () { return chunkTGI6YSZP_cjs.preprocessClicks; }
1470
1518
  });
1471
1519
  Object.defineProperty(exports, "renderSlide", {
1472
1520
  enumerable: true,
1473
- get: function () { return chunkVLAPHJOC_cjs.renderSlide; }
1521
+ get: function () { return chunkTGI6YSZP_cjs.renderSlide; }
1474
1522
  });
1475
1523
  Object.defineProperty(exports, "renderSlideAsync", {
1476
1524
  enumerable: true,
1477
- get: function () { return chunkVLAPHJOC_cjs.renderSlideAsync; }
1525
+ get: function () { return chunkTGI6YSZP_cjs.renderSlideAsync; }
1478
1526
  });
1479
1527
  Object.defineProperty(exports, "resolveTheme", {
1480
1528
  enumerable: true,
1481
- get: function () { return chunkVLAPHJOC_cjs.resolveTheme; }
1529
+ get: function () { return chunkTGI6YSZP_cjs.resolveTheme; }
1482
1530
  });
1483
1531
  exports.DeckView = DeckView;
1484
1532
  exports.NavigationBar = NavigationBar;