themed-markdown 0.1.92 → 0.1.93

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.mjs CHANGED
@@ -1053,7 +1053,8 @@ function resetFontScale(theme2) {
1053
1053
 
1054
1054
  // industryMarkdown/components/IndustryMarkdownSlide.tsx
1055
1055
  import { defaultSchema } from "hast-util-sanitize";
1056
- import React13, { useRef as useRef8, useEffect as useEffect8, useLayoutEffect as useLayoutEffect2, useState as useState10, useMemo as useMemo3, useCallback as useCallback2 } from "react";
1056
+ import { Trash2 } from "lucide-react";
1057
+ import React13, { useRef as useRef9, useEffect as useEffect9, useLayoutEffect as useLayoutEffect2, useState as useState11, useMemo as useMemo3, useCallback as useCallback3 } from "react";
1057
1058
  import { createPortal as createPortal2 } from "react-dom";
1058
1059
  import ReactMarkdown from "react-markdown";
1059
1060
  import rehypeHighlight from "rehype-highlight";
@@ -1062,6 +1063,110 @@ import rehypeSanitize from "rehype-sanitize";
1062
1063
  import rehypeSlug from "rehype-slug";
1063
1064
  import remarkGfm from "remark-gfm";
1064
1065
 
1066
+ // industryMarkdown/utils/blockDeletion.ts
1067
+ function lineStartOffset(text, line) {
1068
+ if (line <= 1)
1069
+ return 0;
1070
+ let offset = 0;
1071
+ let current = 1;
1072
+ while (current < line) {
1073
+ const nl = text.indexOf(`
1074
+ `, offset);
1075
+ if (nl === -1)
1076
+ return text.length;
1077
+ offset = nl + 1;
1078
+ current += 1;
1079
+ }
1080
+ return offset;
1081
+ }
1082
+ function lineEndOffset(text, line) {
1083
+ const start = lineStartOffset(text, line);
1084
+ const nl = text.indexOf(`
1085
+ `, start);
1086
+ return nl === -1 ? text.length : nl;
1087
+ }
1088
+ function computeChunkOffsets(content, chunks) {
1089
+ const offsets = [];
1090
+ let cursor = 0;
1091
+ for (const chunk of chunks) {
1092
+ if (!chunk.content) {
1093
+ offsets.push(-1);
1094
+ continue;
1095
+ }
1096
+ const idx = content.indexOf(chunk.content, cursor);
1097
+ offsets.push(idx);
1098
+ if (idx !== -1) {
1099
+ cursor = idx + chunk.content.length;
1100
+ }
1101
+ }
1102
+ return offsets;
1103
+ }
1104
+ function computeDeletion(content, chunks, targets) {
1105
+ const offsets = computeChunkOffsets(content, chunks);
1106
+ const ranges = [];
1107
+ for (const target of targets) {
1108
+ const base = offsets[target.chunkIndex];
1109
+ const chunk = chunks[target.chunkIndex];
1110
+ if (base === undefined || base < 0 || !chunk)
1111
+ continue;
1112
+ const chunkText = chunk.content;
1113
+ const startRel = lineStartOffset(chunkText, target.startLine);
1114
+ let endRel = lineEndOffset(chunkText, target.endLine);
1115
+ if (chunkText[endRel] === `
1116
+ `)
1117
+ endRel += 1;
1118
+ if (endRel < chunkText.length) {
1119
+ const nextNl = chunkText.indexOf(`
1120
+ `, endRel);
1121
+ const followingLineEnd = nextNl === -1 ? chunkText.length : nextNl;
1122
+ if (chunkText.slice(endRel, followingLineEnd).trim() === "") {
1123
+ endRel = nextNl === -1 ? chunkText.length : nextNl + 1;
1124
+ }
1125
+ }
1126
+ ranges.push({ start: base + startRel, end: base + endRel });
1127
+ }
1128
+ ranges.sort((a, b) => a.start - b.start);
1129
+ const merged = [];
1130
+ for (const range of ranges) {
1131
+ const last = merged[merged.length - 1];
1132
+ if (last && range.start <= last.end) {
1133
+ last.end = Math.max(last.end, range.end);
1134
+ } else {
1135
+ merged.push({ ...range });
1136
+ }
1137
+ }
1138
+ let newContent = "";
1139
+ let removedText = "";
1140
+ let cursor = 0;
1141
+ for (const range of merged) {
1142
+ newContent += content.slice(cursor, range.start);
1143
+ removedText += content.slice(range.start, range.end);
1144
+ cursor = range.end;
1145
+ }
1146
+ newContent += content.slice(cursor);
1147
+ return { newContent, removedText, ranges: merged };
1148
+ }
1149
+ function computeTextDeletion(content, chunks, chunkIndex, startOffset, endOffset) {
1150
+ const empty = { newContent: content, removedText: "", ranges: [] };
1151
+ const chunk = chunks[chunkIndex];
1152
+ if (!chunk)
1153
+ return empty;
1154
+ const base = computeChunkOffsets(content, chunks)[chunkIndex];
1155
+ if (base === undefined || base < 0)
1156
+ return empty;
1157
+ const start = Math.min(startOffset, endOffset);
1158
+ const end = Math.max(startOffset, endOffset);
1159
+ if (start === end)
1160
+ return empty;
1161
+ const absStart = base + start;
1162
+ const absEnd = base + end;
1163
+ return {
1164
+ newContent: content.slice(0, absStart) + content.slice(absEnd),
1165
+ removedText: content.slice(absStart, absEnd),
1166
+ ranges: [{ start: absStart, end: absEnd }]
1167
+ };
1168
+ }
1169
+
1065
1170
  // industryMarkdown/utils/highlightSearchMatches.ts
1066
1171
  function highlightSearchMatches(content, searchQuery) {
1067
1172
  if (!searchQuery || !searchQuery.trim()) {
@@ -1644,6 +1749,42 @@ function parseSkillMarkdown(content) {
1644
1749
  // industryMarkdown/utils/markdownUtils.ts
1645
1750
  var parseMarkdownChunks2 = parseMarkdownChunks;
1646
1751
 
1752
+ // industryMarkdown/utils/rehypeSourcePositions.ts
1753
+ var SKIP_TAGS = new Set(["pre", "code"]);
1754
+ function isText(node) {
1755
+ return node.type === "text";
1756
+ }
1757
+ function rehypeSourcePositions() {
1758
+ return (tree) => {
1759
+ const visit = (node) => {
1760
+ const children = node.children;
1761
+ if (!children)
1762
+ return;
1763
+ if (node.type === "element" && SKIP_TAGS.has(node.tagName))
1764
+ return;
1765
+ const out = [];
1766
+ for (const child of children) {
1767
+ const startOffset = isText(child) ? child.position?.start?.offset : undefined;
1768
+ const endOffset = isText(child) ? child.position?.end?.offset : undefined;
1769
+ if (isText(child) && typeof startOffset === "number" && typeof endOffset === "number" && child.value.trim() !== "") {
1770
+ out.push({
1771
+ type: "element",
1772
+ tagName: "span",
1773
+ properties: { dataSrcStart: startOffset, dataSrcEnd: endOffset },
1774
+ children: [child],
1775
+ position: child.position
1776
+ });
1777
+ } else {
1778
+ visit(child);
1779
+ out.push(child);
1780
+ }
1781
+ }
1782
+ node.children = out;
1783
+ };
1784
+ visit(tree);
1785
+ };
1786
+ }
1787
+
1647
1788
  // industryMarkdown/utils/useAnnotations.ts
1648
1789
  import { useEffect as useEffect2, useLayoutEffect, useMemo, useRef, useState as useState2 } from "react";
1649
1790
 
@@ -2042,16 +2183,196 @@ function useAnnotations({
2042
2183
  return mounts;
2043
2184
  }
2044
2185
 
2186
+ // industryMarkdown/utils/useBlockSelection.ts
2187
+ import { useCallback, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
2188
+ var BLOCK_SELECTED_ATTR = "data-md-selected";
2189
+ function parseTarget(el) {
2190
+ const chunk = el.getAttribute("data-md-chunk");
2191
+ const start = el.getAttribute("data-md-start");
2192
+ const end = el.getAttribute("data-md-end");
2193
+ if (chunk === null || start === null || end === null)
2194
+ return null;
2195
+ const chunkIndex = Number(chunk);
2196
+ const startLine = Number(start);
2197
+ const endLine = Number(end);
2198
+ if ([chunkIndex, startLine, endLine].some(Number.isNaN))
2199
+ return null;
2200
+ return { chunkIndex, startLine, endLine };
2201
+ }
2202
+ function firstTextNode(node) {
2203
+ if (node.nodeType === Node.TEXT_NODE)
2204
+ return node;
2205
+ const walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT);
2206
+ return walker.nextNode();
2207
+ }
2208
+ function lastTextNode(node) {
2209
+ if (node.nodeType === Node.TEXT_NODE)
2210
+ return node;
2211
+ const walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT);
2212
+ let last = null;
2213
+ let current = walker.nextNode();
2214
+ while (current) {
2215
+ last = current;
2216
+ current = walker.nextNode();
2217
+ }
2218
+ return last;
2219
+ }
2220
+ function resolveBoundary(container, offset, preferEnd) {
2221
+ if (container.nodeType === Node.TEXT_NODE) {
2222
+ return { textNode: container, local: offset };
2223
+ }
2224
+ if (container.nodeType !== Node.ELEMENT_NODE)
2225
+ return null;
2226
+ const children = container.childNodes;
2227
+ const before = children[offset - 1];
2228
+ const after = children[offset];
2229
+ if (preferEnd) {
2230
+ const beforeText = before && lastTextNode(before);
2231
+ if (beforeText)
2232
+ return { textNode: beforeText, local: beforeText.length };
2233
+ const afterText = after && firstTextNode(after);
2234
+ if (afterText)
2235
+ return { textNode: afterText, local: 0 };
2236
+ } else {
2237
+ const afterText = after && firstTextNode(after);
2238
+ if (afterText)
2239
+ return { textNode: afterText, local: 0 };
2240
+ const beforeText = before && lastTextNode(before);
2241
+ if (beforeText)
2242
+ return { textNode: beforeText, local: beforeText.length };
2243
+ }
2244
+ return null;
2245
+ }
2246
+ function boundaryToSource(textNode, local) {
2247
+ const wrapper = textNode.parentElement?.closest("[data-src-start]");
2248
+ if (!wrapper)
2249
+ return null;
2250
+ const srcStart = Number(wrapper.getAttribute("data-src-start"));
2251
+ if (Number.isNaN(srcStart))
2252
+ return null;
2253
+ const chunkEl = wrapper.closest("[data-md-chunk]");
2254
+ const chunkIndex = chunkEl ? Number(chunkEl.getAttribute("data-md-chunk")) : NaN;
2255
+ if (Number.isNaN(chunkIndex))
2256
+ return null;
2257
+ return { chunkIndex, offset: srcStart + local };
2258
+ }
2259
+ function resolveTextRange(range) {
2260
+ const startB = resolveBoundary(range.startContainer, range.startOffset, false);
2261
+ const endB = resolveBoundary(range.endContainer, range.endOffset, true);
2262
+ if (!startB || !endB)
2263
+ return null;
2264
+ const startSrc = boundaryToSource(startB.textNode, startB.local);
2265
+ const endSrc = boundaryToSource(endB.textNode, endB.local);
2266
+ if (!startSrc || !endSrc)
2267
+ return null;
2268
+ if (startSrc.chunkIndex !== endSrc.chunkIndex)
2269
+ return null;
2270
+ const startOffset = Math.min(startSrc.offset, endSrc.offset);
2271
+ const endOffset = Math.max(startSrc.offset, endSrc.offset);
2272
+ if (startOffset === endOffset)
2273
+ return null;
2274
+ return { chunkIndex: startSrc.chunkIndex, startOffset, endOffset };
2275
+ }
2276
+ function useBlockSelection({
2277
+ rootRef,
2278
+ enabled,
2279
+ mode
2280
+ }) {
2281
+ const [selection, setSelection] = useState3(null);
2282
+ const selectedEls = useRef2([]);
2283
+ const clearOutline = useCallback(() => {
2284
+ selectedEls.current.forEach((el) => el.removeAttribute(BLOCK_SELECTED_ATTR));
2285
+ selectedEls.current = [];
2286
+ }, []);
2287
+ const clear = useCallback(() => {
2288
+ clearOutline();
2289
+ setSelection(null);
2290
+ }, [clearOutline]);
2291
+ useEffect3(() => {
2292
+ if (!enabled) {
2293
+ clear();
2294
+ return;
2295
+ }
2296
+ const root = rootRef.current;
2297
+ if (!root)
2298
+ return;
2299
+ const anchorFor = (range) => {
2300
+ const rootRect = root.getBoundingClientRect();
2301
+ const rangeRect = range.getBoundingClientRect();
2302
+ return {
2303
+ top: rangeRect.top - rootRect.top + root.scrollTop,
2304
+ left: rangeRect.right - rootRect.left + root.scrollLeft
2305
+ };
2306
+ };
2307
+ const resolveBlock = (sel, range) => {
2308
+ const tagged = Array.from(root.querySelectorAll(`[data-md-start]`));
2309
+ const matched = tagged.filter((el) => sel.containsNode(el, true));
2310
+ if (matched.length === 0)
2311
+ return false;
2312
+ const topLevel = matched.filter((el) => !matched.some((other) => other !== el && other.contains(el)));
2313
+ const targets = [];
2314
+ topLevel.forEach((el) => {
2315
+ const target = parseTarget(el);
2316
+ if (target)
2317
+ targets.push(target);
2318
+ });
2319
+ if (targets.length === 0)
2320
+ return false;
2321
+ clearOutline();
2322
+ topLevel.forEach((el) => el.setAttribute(BLOCK_SELECTED_ATTR, "true"));
2323
+ selectedEls.current = topLevel;
2324
+ setSelection({ kind: "block", targets, anchor: anchorFor(range) });
2325
+ return true;
2326
+ };
2327
+ const resolve = () => {
2328
+ const sel = document.getSelection();
2329
+ if (!sel || sel.rangeCount === 0 || sel.isCollapsed) {
2330
+ clear();
2331
+ return;
2332
+ }
2333
+ const range = sel.getRangeAt(0);
2334
+ if (!root.contains(range.commonAncestorContainer)) {
2335
+ clear();
2336
+ return;
2337
+ }
2338
+ if (mode === "text") {
2339
+ const text = resolveTextRange(range);
2340
+ if (text) {
2341
+ clearOutline();
2342
+ setSelection({ kind: "text", ...text, anchor: anchorFor(range) });
2343
+ return;
2344
+ }
2345
+ }
2346
+ if (!resolveBlock(sel, range)) {
2347
+ clear();
2348
+ }
2349
+ };
2350
+ const handleMouseUp = () => window.setTimeout(resolve, 0);
2351
+ const handleKeyUp = (event) => {
2352
+ if (["Shift", "Meta", "Control", "Alt"].includes(event.key))
2353
+ return;
2354
+ window.setTimeout(resolve, 0);
2355
+ };
2356
+ document.addEventListener("mouseup", handleMouseUp);
2357
+ document.addEventListener("keyup", handleKeyUp);
2358
+ return () => {
2359
+ document.removeEventListener("mouseup", handleMouseUp);
2360
+ document.removeEventListener("keyup", handleKeyUp);
2361
+ };
2362
+ }, [enabled, mode, rootRef, clear, clearOutline]);
2363
+ return { selection, clear };
2364
+ }
2365
+
2045
2366
  // industryMarkdown/components/IndustryHtmlModal.tsx
2046
- import React3, { useCallback, useState as useState3 } from "react";
2367
+ import React3, { useCallback as useCallback2, useState as useState4 } from "react";
2047
2368
  var useIndustryHtmlModal = () => {
2048
- const [htmlModalOpen, setHtmlModalOpen] = useState3(false);
2049
- const [htmlModalContent, setHtmlModalContent] = useState3("");
2050
- const openHtmlModal = useCallback((content) => {
2369
+ const [htmlModalOpen, setHtmlModalOpen] = useState4(false);
2370
+ const [htmlModalContent, setHtmlModalContent] = useState4("");
2371
+ const openHtmlModal = useCallback2((content) => {
2051
2372
  setHtmlModalContent(content);
2052
2373
  setHtmlModalOpen(true);
2053
2374
  }, []);
2054
- const closeHtmlModal = useCallback(() => {
2375
+ const closeHtmlModal = useCallback2(() => {
2055
2376
  setHtmlModalOpen(false);
2056
2377
  }, []);
2057
2378
  return { htmlModalOpen, htmlModalContent, openHtmlModal, closeHtmlModal };
@@ -2157,11 +2478,11 @@ function IndustryHtmlModal({ isOpen, onClose, htmlContent, theme: theme2 }) {
2157
2478
 
2158
2479
  // industryMarkdown/components/IndustryLazyMermaidDiagram.tsx
2159
2480
  import { MoveRight } from "lucide-react";
2160
- import React6, { useEffect as useEffect4, useRef as useRef3, useState as useState5 } from "react";
2481
+ import React6, { useEffect as useEffect5, useRef as useRef4, useState as useState6 } from "react";
2161
2482
 
2162
2483
  // industryMarkdown/components/IndustryMermaidDiagram.tsx
2163
2484
  import { Expand, Copy, Check } from "lucide-react";
2164
- import React5, { useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
2485
+ import React5, { useEffect as useEffect4, useRef as useRef3, useState as useState5 } from "react";
2165
2486
  var getMermaidSync = () => {
2166
2487
  if (typeof window !== "undefined") {
2167
2488
  const mermaid = window.mermaid;
@@ -2183,12 +2504,12 @@ function IndustryMermaidDiagram({
2183
2504
  onExpandClick
2184
2505
  }) {
2185
2506
  const theme2 = themeOverride ?? theme;
2186
- const [errorDetails, setErrorDetails] = useState4(null);
2187
- const [isIntersecting, setIsIntersecting] = useState4(false);
2188
- const [hasRendered, setHasRendered] = useState4(false);
2189
- const [containerElement, setContainerElement] = useState4(null);
2190
- const [copiedError, setCopiedError] = useState4(false);
2191
- const observerRef = useRef2(null);
2507
+ const [errorDetails, setErrorDetails] = useState5(null);
2508
+ const [isIntersecting, setIsIntersecting] = useState5(false);
2509
+ const [hasRendered, setHasRendered] = useState5(false);
2510
+ const [containerElement, setContainerElement] = useState5(null);
2511
+ const [copiedError, setCopiedError] = useState5(false);
2512
+ const observerRef = useRef3(null);
2192
2513
  const containerRef = React5.useCallback((node) => {
2193
2514
  setContainerElement(node);
2194
2515
  if (observerRef.current) {
@@ -2213,14 +2534,14 @@ function IndustryMermaidDiagram({
2213
2534
  observerRef.current.observe(node);
2214
2535
  }
2215
2536
  }, [rootMargin, hasRendered, isModalMode]);
2216
- useEffect3(() => {
2537
+ useEffect4(() => {
2217
2538
  return () => {
2218
2539
  if (observerRef.current) {
2219
2540
  observerRef.current.disconnect();
2220
2541
  }
2221
2542
  };
2222
2543
  }, []);
2223
- useEffect3(() => {
2544
+ useEffect4(() => {
2224
2545
  if (!hasRendered)
2225
2546
  return;
2226
2547
  const renderDiagram = async () => {
@@ -2555,15 +2876,15 @@ function IndustryLazyMermaidDiagram({
2555
2876
  onExpandClick
2556
2877
  }) {
2557
2878
  const theme2 = themeOverride ?? theme;
2558
- const [isIntersecting, setIsIntersecting] = useState5(false);
2559
- const [hasRendered, setHasRendered] = useState5(false);
2560
- const [isMounted, setIsMounted] = useState5(false);
2561
- const [hasError, setHasError] = useState5(false);
2562
- const containerRef = useRef3(null);
2563
- useEffect4(() => {
2879
+ const [isIntersecting, setIsIntersecting] = useState6(false);
2880
+ const [hasRendered, setHasRendered] = useState6(false);
2881
+ const [isMounted, setIsMounted] = useState6(false);
2882
+ const [hasError, setHasError] = useState6(false);
2883
+ const containerRef = useRef4(null);
2884
+ useEffect5(() => {
2564
2885
  setIsMounted(true);
2565
2886
  }, []);
2566
- useEffect4(() => {
2887
+ useEffect5(() => {
2567
2888
  if (!isMounted)
2568
2889
  return;
2569
2890
  if (typeof IntersectionObserver === "undefined") {
@@ -2684,7 +3005,7 @@ function IndustryLazyMermaidDiagram({
2684
3005
 
2685
3006
  // industryMarkdown/components/IndustryMarkdownComponents.tsx
2686
3007
  import { Copy as Copy2, Monitor, FileText, Check as Check2 } from "lucide-react";
2687
- import React9, { useMemo as useMemo2, useState as useState7, useRef as useRef5 } from "react";
3008
+ import React9, { useMemo as useMemo2, useState as useState8, useRef as useRef6 } from "react";
2688
3009
 
2689
3010
  // industryMarkdown/utils/componentUtils.tsx
2690
3011
  import React7 from "react";
@@ -2721,7 +3042,7 @@ var LinkWithLoadingIndicator = ({ href, children, onClick, className, style }) =
2721
3042
  };
2722
3043
  // industryMarkdown/components/IndustryBashCommandDropdown.tsx
2723
3044
  import { Play, ChevronDown } from "lucide-react";
2724
- import React8, { useState as useState6, useRef as useRef4, useEffect as useEffect5 } from "react";
3045
+ import React8, { useState as useState7, useRef as useRef5, useEffect as useEffect6 } from "react";
2725
3046
  var IndustryBashCommandDropdown = ({
2726
3047
  commands,
2727
3048
  allCommands,
@@ -2730,11 +3051,11 @@ var IndustryBashCommandDropdown = ({
2730
3051
  slideIdPrefix: _slideIdPrefix,
2731
3052
  theme: themeOverride
2732
3053
  }) => {
2733
- const [isOpen, setIsOpen] = useState6(false);
2734
- const [isRunning, setIsRunning] = useState6(false);
2735
- const dropdownRef = useRef4(null);
3054
+ const [isOpen, setIsOpen] = useState7(false);
3055
+ const [isRunning, setIsRunning] = useState7(false);
3056
+ const dropdownRef = useRef5(null);
2736
3057
  const theme2 = themeOverride ?? theme;
2737
- useEffect5(() => {
3058
+ useEffect6(() => {
2738
3059
  const handleClickOutside = (event) => {
2739
3060
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
2740
3061
  setIsOpen(false);
@@ -2853,7 +3174,7 @@ var IndustryBashCommandDropdown = ({
2853
3174
  e.currentTarget.style.backgroundColor = theme2.colors.muted;
2854
3175
  }
2855
3176
  }, "\uD83D\uDE80 Run all (", commands.length, " commands)"), commands.map((cmd, index) => {
2856
- const [isHovered, setIsHovered] = useState6(false);
3177
+ const [isHovered, setIsHovered] = useState7(false);
2857
3178
  return /* @__PURE__ */ React8.createElement("div", {
2858
3179
  key: index,
2859
3180
  style: dropdownItemStyle(isHovered),
@@ -2909,8 +3230,8 @@ var OptimizedMarkdownMedia = React9.memo(({
2909
3230
  const transformedSrc = useMemo2(() => {
2910
3231
  return transformImageUrl(src, repositoryInfo);
2911
3232
  }, [src, repositoryInfo]);
2912
- const [hasErrored, setHasErrored] = useState7(() => failedImageCache.has(transformedSrc));
2913
- const retryCount = useRef5(0);
3233
+ const [hasErrored, setHasErrored] = useState8(() => failedImageCache.has(transformedSrc));
3234
+ const retryCount = useRef6(0);
2914
3235
  const mediaStyle = useMemo2(() => ({
2915
3236
  maxWidth: "100%",
2916
3237
  height: "auto",
@@ -3014,8 +3335,24 @@ var createIndustryMarkdownComponents = ({
3014
3335
  slideHeaderMarginTopOverride,
3015
3336
  index,
3016
3337
  repositoryInfo,
3017
- editable = false
3338
+ editable = false,
3339
+ selectableBlocks = false,
3340
+ onDeleteListItem
3018
3341
  }) => {
3342
+ const blockMeta = (node) => {
3343
+ if (!selectableBlocks)
3344
+ return {};
3345
+ const position = node?.position;
3346
+ const startLine = position?.start?.line;
3347
+ const endLine = position?.end?.line;
3348
+ if (typeof startLine !== "number" || typeof endLine !== "number")
3349
+ return {};
3350
+ return {
3351
+ "data-md-chunk": index,
3352
+ "data-md-start": startLine,
3353
+ "data-md-end": endLine
3354
+ };
3355
+ };
3019
3356
  const getLuminance = (hex) => {
3020
3357
  const rgb = hex.replace("#", "").match(/.{2}/g);
3021
3358
  if (!rgb)
@@ -3029,7 +3366,7 @@ var createIndustryMarkdownComponents = ({
3029
3366
  headerStyles.marginTop = slideHeaderMarginTopOverride ? `${slideHeaderMarginTopOverride}px` : 0;
3030
3367
  }
3031
3368
  return {
3032
- h1: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h1", {
3369
+ h1: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h1", {
3033
3370
  style: {
3034
3371
  color: theme2.colors.text,
3035
3372
  fontSize: theme2.fontSizes[5],
@@ -3042,9 +3379,10 @@ var createIndustryMarkdownComponents = ({
3042
3379
  borderBottom: `1px solid ${theme2.colors.border}`,
3043
3380
  ...headerStyles
3044
3381
  },
3045
- ...props
3382
+ ...props,
3383
+ ...blockMeta(node)
3046
3384
  }, children),
3047
- h2: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h2", {
3385
+ h2: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h2", {
3048
3386
  style: {
3049
3387
  color: theme2.colors.text,
3050
3388
  fontSize: theme2.fontSizes[4],
@@ -3057,9 +3395,10 @@ var createIndustryMarkdownComponents = ({
3057
3395
  borderBottom: `1px solid ${theme2.colors.border}`,
3058
3396
  ...headerStyles
3059
3397
  },
3060
- ...props
3398
+ ...props,
3399
+ ...blockMeta(node)
3061
3400
  }, children),
3062
- h3: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h3", {
3401
+ h3: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h3", {
3063
3402
  style: {
3064
3403
  color: theme2.colors.text,
3065
3404
  fontSize: theme2.fontSizes[3],
@@ -3069,9 +3408,10 @@ var createIndustryMarkdownComponents = ({
3069
3408
  marginBottom: theme2.space[3],
3070
3409
  fontFamily: theme2.fonts.heading
3071
3410
  },
3072
- ...props
3411
+ ...props,
3412
+ ...blockMeta(node)
3073
3413
  }, children),
3074
- h4: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h4", {
3414
+ h4: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h4", {
3075
3415
  style: {
3076
3416
  color: theme2.colors.text,
3077
3417
  fontSize: theme2.fontSizes[2],
@@ -3081,9 +3421,10 @@ var createIndustryMarkdownComponents = ({
3081
3421
  marginBottom: theme2.space[2],
3082
3422
  fontFamily: theme2.fonts.heading
3083
3423
  },
3084
- ...props
3424
+ ...props,
3425
+ ...blockMeta(node)
3085
3426
  }, children),
3086
- h5: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h5", {
3427
+ h5: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h5", {
3087
3428
  style: {
3088
3429
  color: theme2.colors.text,
3089
3430
  fontSize: theme2.fontSizes[1],
@@ -3093,9 +3434,10 @@ var createIndustryMarkdownComponents = ({
3093
3434
  marginBottom: theme2.space[1],
3094
3435
  fontFamily: theme2.fonts.heading
3095
3436
  },
3096
- ...props
3437
+ ...props,
3438
+ ...blockMeta(node)
3097
3439
  }, children),
3098
- h6: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h6", {
3440
+ h6: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h6", {
3099
3441
  style: {
3100
3442
  color: theme2.colors.text,
3101
3443
  fontSize: theme2.fontSizes[1],
@@ -3105,9 +3447,10 @@ var createIndustryMarkdownComponents = ({
3105
3447
  marginBottom: theme2.space[1],
3106
3448
  fontFamily: theme2.fonts.heading
3107
3449
  },
3108
- ...props
3450
+ ...props,
3451
+ ...blockMeta(node)
3109
3452
  }, children),
3110
- p: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("p", {
3453
+ p: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("p", {
3111
3454
  style: {
3112
3455
  color: theme2.colors.text,
3113
3456
  fontSize: theme2.fontSizes[2],
@@ -3115,9 +3458,10 @@ var createIndustryMarkdownComponents = ({
3115
3458
  marginBottom: theme2.space[3],
3116
3459
  fontFamily: theme2.fonts.body
3117
3460
  },
3118
- ...props
3461
+ ...props,
3462
+ ...blockMeta(node)
3119
3463
  }, children),
3120
- ul: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("ul", {
3464
+ ul: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("ul", {
3121
3465
  style: {
3122
3466
  color: theme2.colors.text,
3123
3467
  fontSize: theme2.fontSizes[2],
@@ -3127,9 +3471,10 @@ var createIndustryMarkdownComponents = ({
3127
3471
  listStyleType: "disc",
3128
3472
  fontFamily: theme2.fonts.body
3129
3473
  },
3130
- ...props
3474
+ ...props,
3475
+ ...blockMeta(node)
3131
3476
  }, children),
3132
- ol: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("ol", {
3477
+ ol: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("ol", {
3133
3478
  style: {
3134
3479
  color: theme2.colors.text,
3135
3480
  fontSize: theme2.fontSizes[2],
@@ -3139,9 +3484,10 @@ var createIndustryMarkdownComponents = ({
3139
3484
  listStyleType: "decimal",
3140
3485
  fontFamily: theme2.fonts.body
3141
3486
  },
3142
- ...props
3487
+ ...props,
3488
+ ...blockMeta(node)
3143
3489
  }, children),
3144
- li: ({ children, ...props }) => {
3490
+ li: ({ children, node, ...props }) => {
3145
3491
  const isTaskListItem = Array.isArray(children) && children.length > 0 && React9.isValidElement(children[0]) && children[0]?.props?.type === "checkbox";
3146
3492
  if (isTaskListItem) {
3147
3493
  const checkbox = children[0];
@@ -3156,7 +3502,7 @@ var createIndustryMarkdownComponents = ({
3156
3502
  }
3157
3503
  });
3158
3504
  const checked = checkbox?.props?.checked || false;
3159
- const lineNumber = props.sourcePosition?.start?.line || props.node?.position?.start?.line || 1;
3505
+ const lineNumber = props.sourcePosition?.start?.line || node?.position?.start?.line || 1;
3160
3506
  const id = `${slideIdPrefix}-checkbox-${lineNumber}`;
3161
3507
  const isChecked = checkedItems[id] ?? checked;
3162
3508
  const handleChange = (e) => {
@@ -3204,6 +3550,37 @@ var createIndustryMarkdownComponents = ({
3204
3550
  }
3205
3551
  }, labelContent.length > 0 ? labelContent : null)), nestedListElements.length > 0 ? nestedListElements : null);
3206
3552
  }
3553
+ const position = node?.position;
3554
+ const itemStart = position?.start?.line;
3555
+ const itemEnd = position?.end?.line;
3556
+ const deletable = selectableBlocks && !!onDeleteListItem && typeof itemStart === "number" && typeof itemEnd === "number";
3557
+ if (deletable) {
3558
+ return /* @__PURE__ */ React9.createElement("li", {
3559
+ className: "md-del-li",
3560
+ style: {
3561
+ marginBottom: theme2.space[2],
3562
+ paddingTop: theme2.space[1],
3563
+ color: theme2.colors.text,
3564
+ lineHeight: theme2.lineHeights.relaxed,
3565
+ display: "flex",
3566
+ alignItems: "flex-start"
3567
+ },
3568
+ ...props,
3569
+ ...blockMeta(node)
3570
+ }, /* @__PURE__ */ React9.createElement("button", {
3571
+ type: "button",
3572
+ className: "md-del-marker",
3573
+ "aria-label": "Delete list item",
3574
+ title: "Delete this item",
3575
+ onClick: (e) => {
3576
+ e.preventDefault();
3577
+ e.stopPropagation();
3578
+ onDeleteListItem(index, itemStart, itemEnd);
3579
+ }
3580
+ }), /* @__PURE__ */ React9.createElement("div", {
3581
+ style: { flex: 1, minWidth: 0 }
3582
+ }, children));
3583
+ }
3207
3584
  return /* @__PURE__ */ React9.createElement("li", {
3208
3585
  style: {
3209
3586
  marginBottom: theme2.space[2],
@@ -3211,16 +3588,39 @@ var createIndustryMarkdownComponents = ({
3211
3588
  color: theme2.colors.text,
3212
3589
  lineHeight: theme2.lineHeights.relaxed
3213
3590
  },
3214
- ...props
3591
+ ...props,
3592
+ ...blockMeta(node)
3215
3593
  }, children);
3216
3594
  },
3217
- table: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("div", {
3595
+ blockquote: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("blockquote", {
3596
+ style: {
3597
+ margin: `0 0 ${theme2.space[3]}px 0`,
3598
+ padding: `${theme2.space[2]}px ${theme2.space[4]}px`,
3599
+ borderLeft: `4px solid ${theme2.colors.border}`,
3600
+ color: theme2.colors.textSecondary,
3601
+ fontStyle: "italic",
3602
+ fontFamily: theme2.fonts.body
3603
+ },
3604
+ ...props,
3605
+ ...blockMeta(node)
3606
+ }, children),
3607
+ hr: ({ node, ...props }) => /* @__PURE__ */ React9.createElement("hr", {
3608
+ style: {
3609
+ border: "none",
3610
+ borderTop: `1px solid ${theme2.colors.border}`,
3611
+ margin: `${theme2.space[4]}px 0`
3612
+ },
3613
+ ...props,
3614
+ ...blockMeta(node)
3615
+ }),
3616
+ table: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("div", {
3218
3617
  style: {
3219
3618
  overflowX: "auto",
3220
3619
  marginBottom: theme2.space[4],
3221
3620
  borderRadius: theme2.radii[2],
3222
3621
  border: `1px solid ${theme2.colors.border}`
3223
- }
3622
+ },
3623
+ ...blockMeta(node)
3224
3624
  }, /* @__PURE__ */ React9.createElement("table", {
3225
3625
  style: {
3226
3626
  width: "100%",
@@ -3306,7 +3706,7 @@ var createIndustryMarkdownComponents = ({
3306
3706
  const codeString = extractTextFromChildren(children);
3307
3707
  const matchLang = /language-(\w+)/.exec(className || "");
3308
3708
  const language = matchLang ? matchLang[1] : null;
3309
- const [copied, setCopied] = useState7(false);
3709
+ const [copied, setCopied] = useState8(false);
3310
3710
  let isInline;
3311
3711
  let isCodeBlock;
3312
3712
  const hasNewlines = codeString.includes(`
@@ -3372,7 +3772,8 @@ var createIndustryMarkdownComponents = ({
3372
3772
  fontSize: theme2.fontSizes[0]
3373
3773
  };
3374
3774
  return /* @__PURE__ */ React9.createElement("div", {
3375
- style: containerStyle
3775
+ style: containerStyle,
3776
+ ...blockMeta(node)
3376
3777
  }, /* @__PURE__ */ React9.createElement("div", {
3377
3778
  style: headerStyle
3378
3779
  }, /* @__PURE__ */ React9.createElement("span", {
@@ -3531,11 +3932,11 @@ var createIndustryMarkdownComponents = ({
3531
3932
  };
3532
3933
 
3533
3934
  // industryMarkdown/components/IndustryMermaidModal.tsx
3534
- import React11, { useEffect as useEffect7, useRef as useRef7 } from "react";
3935
+ import React11, { useEffect as useEffect8, useRef as useRef8 } from "react";
3535
3936
  import { createPortal } from "react-dom";
3536
3937
 
3537
3938
  // industryMarkdown/components/IndustryZoomableMermaidDiagram.tsx
3538
- import React10, { useEffect as useEffect6, useRef as useRef6, useState as useState8 } from "react";
3939
+ import React10, { useEffect as useEffect7, useRef as useRef7, useState as useState9 } from "react";
3539
3940
  import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
3540
3941
  function IndustryZoomableMermaidDiagram({
3541
3942
  code,
@@ -3545,13 +3946,13 @@ function IndustryZoomableMermaidDiagram({
3545
3946
  padding = 0.9
3546
3947
  }) {
3547
3948
  const theme2 = themeOverride ?? theme;
3548
- const [calculatedScale, setCalculatedScale] = useState8(1);
3549
- const [hasInitialized, setHasInitialized] = useState8(false);
3550
- const containerRef = useRef6(null);
3551
- const diagramRef = useRef6(null);
3552
- const [isCalculating, setIsCalculating] = useState8(true);
3553
- const transformRef = useRef6(null);
3554
- useEffect6(() => {
3949
+ const [calculatedScale, setCalculatedScale] = useState9(1);
3950
+ const [hasInitialized, setHasInitialized] = useState9(false);
3951
+ const containerRef = useRef7(null);
3952
+ const diagramRef = useRef7(null);
3953
+ const [isCalculating, setIsCalculating] = useState9(true);
3954
+ const transformRef = useRef7(null);
3955
+ useEffect7(() => {
3555
3956
  if (!containerRef.current || !diagramRef.current)
3556
3957
  return;
3557
3958
  const calculateOptimalScale = () => {
@@ -3615,7 +4016,7 @@ function IndustryZoomableMermaidDiagram({
3615
4016
  resizeObserver.disconnect();
3616
4017
  };
3617
4018
  }, [code, fitStrategy, padding]);
3618
- useEffect6(() => {
4019
+ useEffect7(() => {
3619
4020
  if (hasInitialized && transformRef.current) {
3620
4021
  const { centerView } = transformRef.current;
3621
4022
  centerView(calculatedScale, 0, "easeOut");
@@ -3725,8 +4126,8 @@ function IndustryMermaidModal({
3725
4126
  mermaidCode,
3726
4127
  theme: theme2
3727
4128
  }) {
3728
- const modalRef = useRef7(null);
3729
- useEffect7(() => {
4129
+ const modalRef = useRef8(null);
4130
+ useEffect8(() => {
3730
4131
  const handleEscape = (event) => {
3731
4132
  if (event.key === "Escape") {
3732
4133
  onClose();
@@ -3828,7 +4229,7 @@ function IndustryMermaidModal({
3828
4229
  }
3829
4230
 
3830
4231
  // industryMarkdown/components/IndustryPlaceholderModal.tsx
3831
- import React12, { useState as useState9 } from "react";
4232
+ import React12, { useState as useState10 } from "react";
3832
4233
  function IndustryPlaceholderModal({
3833
4234
  isOpen,
3834
4235
  onClose,
@@ -3837,7 +4238,7 @@ function IndustryPlaceholderModal({
3837
4238
  onCopy,
3838
4239
  theme: theme2
3839
4240
  }) {
3840
- const [values, setValues] = useState9({});
4241
+ const [values, setValues] = useState10({});
3841
4242
  if (!isOpen)
3842
4243
  return null;
3843
4244
  const handleSubmit = (e) => {
@@ -4244,6 +4645,52 @@ var annotationCSS = `
4244
4645
  cursor: pointer;
4245
4646
  }
4246
4647
  `;
4648
+ var blockSelectionCSS = `
4649
+ .markdown-slide [data-md-selected] {
4650
+ outline: 2px solid var(--industry-md-delete-outline, rgba(220, 38, 38, 0.7));
4651
+ outline-offset: 2px;
4652
+ border-radius: 3px;
4653
+ background-color: var(--industry-md-delete-bg, rgba(220, 38, 38, 0.08));
4654
+ }
4655
+
4656
+ /* Clickable list-item markers (bullet / number) for per-item deletion. */
4657
+ .markdown-slide li.md-del-li {
4658
+ list-style: none;
4659
+ }
4660
+ .markdown-slide .md-del-marker {
4661
+ flex: 0 0 auto;
4662
+ width: 1.5em;
4663
+ margin-right: 0.35em;
4664
+ padding: 0;
4665
+ box-sizing: border-box;
4666
+ appearance: none;
4667
+ background: transparent;
4668
+ border: none;
4669
+ color: inherit;
4670
+ font: inherit;
4671
+ line-height: inherit;
4672
+ text-align: right;
4673
+ cursor: pointer;
4674
+ user-select: none;
4675
+ transition: color 0.15s ease;
4676
+ }
4677
+ .markdown-slide ul .md-del-marker::before {
4678
+ content: "\\2022"; /* • */
4679
+ }
4680
+ .markdown-slide ol {
4681
+ counter-reset: md-del-counter;
4682
+ }
4683
+ .markdown-slide ol > li > .md-del-marker::before {
4684
+ counter-increment: md-del-counter;
4685
+ content: counter(md-del-counter) ".";
4686
+ }
4687
+ .markdown-slide .md-del-marker:hover {
4688
+ color: var(--industry-md-delete-outline, #dc2626);
4689
+ }
4690
+ .markdown-slide .md-del-marker:hover::before {
4691
+ content: "\\2715"; /* ✕ */
4692
+ }
4693
+ `;
4247
4694
  var fontTransitionCSS = `
4248
4695
  .markdown-slide * {
4249
4696
  transition: font-size 0.2s ease-in-out;
@@ -4307,6 +4754,12 @@ var injectStyles = () => {
4307
4754
  annotationStyle.textContent = annotationCSS;
4308
4755
  document.head.appendChild(annotationStyle);
4309
4756
  }
4757
+ if (!document.getElementById("markdown-slide-block-selection")) {
4758
+ const blockSelectionStyle = document.createElement("style");
4759
+ blockSelectionStyle.id = "markdown-slide-block-selection";
4760
+ blockSelectionStyle.textContent = blockSelectionCSS;
4761
+ document.head.appendChild(blockSelectionStyle);
4762
+ }
4310
4763
  stylesInjected = true;
4311
4764
  }
4312
4765
  };
@@ -4338,6 +4791,10 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4338
4791
  keyboardScrollConfig,
4339
4792
  repositoryInfo,
4340
4793
  editable = false,
4794
+ selectableBlocks = false,
4795
+ deletionMode = "block",
4796
+ onContentChange,
4797
+ onDeleteBlocks,
4341
4798
  annotations,
4342
4799
  activeAnnotationId,
4343
4800
  renderAnnotation,
@@ -4345,9 +4802,9 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4345
4802
  onAnnotationClick,
4346
4803
  annotationStyle
4347
4804
  }) {
4348
- const slideRef = useRef8(null);
4349
- const scrollPositionsRef = useRef8(new Map);
4350
- const [measuredContainerWidth, setMeasuredContainerWidth] = useState10(null);
4805
+ const slideRef = useRef9(null);
4806
+ const scrollPositionsRef = useRef9(new Map);
4807
+ const [measuredContainerWidth, setMeasuredContainerWidth] = useState11(null);
4351
4808
  const chunks = useMemo3(() => {
4352
4809
  if (typeof content !== "string")
4353
4810
  return [];
@@ -4358,16 +4815,16 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4358
4815
  return [];
4359
4816
  }
4360
4817
  }, [content, slideIdPrefix]);
4361
- const [checkedItems, setCheckedItems] = useState10({});
4818
+ const [checkedItems, setCheckedItems] = useState11({});
4362
4819
  const { htmlModalOpen, htmlModalContent, openHtmlModal, closeHtmlModal } = useIndustryHtmlModal();
4363
- const [mermaidModalOpen, setMermaidModalOpen] = useState10(false);
4364
- const [mermaidModalCode, setMermaidModalCode] = useState10("");
4365
- const [placeholderModalOpen, setPlaceholderModalOpen] = useState10(false);
4366
- const [placeholderModalData, setPlaceholderModalData] = useState10(null);
4367
- useEffect8(() => {
4820
+ const [mermaidModalOpen, setMermaidModalOpen] = useState11(false);
4821
+ const [mermaidModalCode, setMermaidModalCode] = useState11("");
4822
+ const [placeholderModalOpen, setPlaceholderModalOpen] = useState11(false);
4823
+ const [placeholderModalData, setPlaceholderModalData] = useState11(null);
4824
+ useEffect9(() => {
4368
4825
  injectStyles();
4369
4826
  }, []);
4370
- useEffect8(() => {
4827
+ useEffect9(() => {
4371
4828
  if (containerWidth !== undefined) {
4372
4829
  return;
4373
4830
  }
@@ -4426,7 +4883,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4426
4883
  ...keyboardScrollConfig?.keys
4427
4884
  }
4428
4885
  };
4429
- const handleKeyDown = useCallback2((event) => {
4886
+ const handleKeyDown = useCallback3((event) => {
4430
4887
  if (!enableKeyboardScrolling) {
4431
4888
  return;
4432
4889
  }
@@ -4536,7 +4993,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4536
4993
  }, scrollConfig.smoothScroll ? 100 : 0);
4537
4994
  }
4538
4995
  }, [enableKeyboardScrolling, isVisible, slideIndex, scrollConfig]);
4539
- useEffect8(() => {
4996
+ useEffect9(() => {
4540
4997
  if (autoFocusOnVisible && isVisible && slideRef.current) {
4541
4998
  slideRef.current.focus({ preventScroll: true });
4542
4999
  }
@@ -4601,7 +5058,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4601
5058
  additionalPadding,
4602
5059
  disableBasePadding
4603
5060
  ]);
4604
- useEffect8(() => {
5061
+ useEffect9(() => {
4605
5062
  const slideElement = slideRef.current;
4606
5063
  if (slideElement) {
4607
5064
  const handleScroll = () => {
@@ -4688,7 +5145,17 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4688
5145
  }
4689
5146
  }), []);
4690
5147
  const rootMargin = isVisible ? "0px" : "100px";
4691
- const getMarkdownComponents = useCallback2((chunkIndex) => {
5148
+ const hasDeleteHandler = !!onContentChange || !!onDeleteBlocks;
5149
+ const blockDeletionEnabled = selectableBlocks && hasDeleteHandler;
5150
+ const handleDeleteListItem = useCallback3((chunkIndex, startLine, endLine) => {
5151
+ const targets = [{ chunkIndex, startLine, endLine }];
5152
+ const { newContent, removedText } = computeDeletion(content, chunks, targets);
5153
+ if (newContent === content)
5154
+ return;
5155
+ onContentChange?.(newContent);
5156
+ onDeleteBlocks?.({ newContent, removedText, targets });
5157
+ }, [content, chunks, onContentChange, onDeleteBlocks]);
5158
+ const getMarkdownComponents = useCallback3((chunkIndex) => {
4692
5159
  const baseComponents = createIndustryMarkdownComponents({
4693
5160
  theme: theme2,
4694
5161
  slideIdPrefix,
@@ -4704,7 +5171,9 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4704
5171
  slideHeaderMarginTopOverride,
4705
5172
  index: chunkIndex,
4706
5173
  repositoryInfo,
4707
- editable
5174
+ editable,
5175
+ selectableBlocks,
5176
+ onDeleteListItem: blockDeletionEnabled ? handleDeleteListItem : undefined
4708
5177
  });
4709
5178
  if (searchQuery) {
4710
5179
  return {
@@ -4738,8 +5207,24 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4738
5207
  slideHeaderMarginTopOverride,
4739
5208
  repositoryInfo,
4740
5209
  searchQuery,
4741
- editable
5210
+ editable,
5211
+ selectableBlocks,
5212
+ blockDeletionEnabled,
5213
+ handleDeleteListItem
4742
5214
  ]);
5215
+ const sourcePositionsEnabled = blockDeletionEnabled && deletionMode === "text" && !searchQuery;
5216
+ const rehypePlugins = useMemo3(() => {
5217
+ const plugins = [
5218
+ rehypeRaw,
5219
+ [rehypeSanitize, sanitizeSchema],
5220
+ rehypeSlug,
5221
+ rehypeHighlight
5222
+ ];
5223
+ if (sourcePositionsEnabled) {
5224
+ plugins.push(rehypeSourcePositions);
5225
+ }
5226
+ return plugins;
5227
+ }, [sanitizeSchema, sourcePositionsEnabled]);
4743
5228
  const renderedChunks = useMemo3(() => {
4744
5229
  if (chunks.length === 0) {
4745
5230
  return /* @__PURE__ */ React13.createElement("div", {
@@ -4757,12 +5242,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4757
5242
  return /* @__PURE__ */ React13.createElement(ReactMarkdown, {
4758
5243
  key: `${chunk.id}-${JSON.stringify(theme2.colors.accent)}`,
4759
5244
  remarkPlugins: [remarkGfm],
4760
- rehypePlugins: [
4761
- rehypeRaw,
4762
- [rehypeSanitize, sanitizeSchema],
4763
- rehypeSlug,
4764
- rehypeHighlight
4765
- ],
5245
+ rehypePlugins,
4766
5246
  components: getMarkdownComponents(index)
4767
5247
  }, processedContent);
4768
5248
  }
@@ -4790,7 +5270,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4790
5270
  content,
4791
5271
  searchQuery,
4792
5272
  theme2,
4793
- sanitizeSchema,
5273
+ rehypePlugins,
4794
5274
  getMarkdownComponents,
4795
5275
  rootMargin,
4796
5276
  onCopyMermaidError,
@@ -4803,6 +5283,27 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4803
5283
  onSelectionChange,
4804
5284
  onAnnotationClick
4805
5285
  });
5286
+ const { selection: blockSelection, clear: clearBlockSelection } = useBlockSelection({
5287
+ rootRef: slideRef,
5288
+ enabled: blockDeletionEnabled,
5289
+ mode: deletionMode
5290
+ });
5291
+ const handleDeleteSelection = useCallback3(() => {
5292
+ if (!blockSelection)
5293
+ return;
5294
+ const result = blockSelection.kind === "text" ? computeTextDeletion(content, chunks, blockSelection.chunkIndex, blockSelection.startOffset, blockSelection.endOffset) : computeDeletion(content, chunks, blockSelection.targets);
5295
+ if (result.newContent === content) {
5296
+ clearBlockSelection();
5297
+ return;
5298
+ }
5299
+ onContentChange?.(result.newContent);
5300
+ onDeleteBlocks?.({
5301
+ newContent: result.newContent,
5302
+ removedText: result.removedText,
5303
+ targets: blockSelection.kind === "block" ? blockSelection.targets : []
5304
+ });
5305
+ clearBlockSelection();
5306
+ }, [blockSelection, content, chunks, onContentChange, onDeleteBlocks, clearBlockSelection]);
4806
5307
  const annotationCSSVars = {};
4807
5308
  if (annotationStyle?.backgroundColor) {
4808
5309
  annotationCSSVars["--industry-md-annotation-bg"] = annotationStyle.backgroundColor;
@@ -4837,7 +5338,37 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4837
5338
  }
4838
5339
  }, renderedChunks, renderAnnotation && annotationMounts.filter((mount) => mount.resolved).map((mount) => createPortal2(/* @__PURE__ */ React13.createElement(React13.Fragment, {
4839
5340
  key: mount.annotation.id
4840
- }, renderAnnotation(mount.annotation)), mount.host)), /* @__PURE__ */ React13.createElement(IndustryHtmlModal, {
5341
+ }, renderAnnotation(mount.annotation)), mount.host)), blockDeletionEnabled && blockSelection && /* @__PURE__ */ React13.createElement("button", {
5342
+ type: "button",
5343
+ "aria-label": "Delete selected block",
5344
+ title: "Delete selected block",
5345
+ onMouseDown: (e) => e.preventDefault(),
5346
+ onClick: (e) => {
5347
+ e.stopPropagation();
5348
+ handleDeleteSelection();
5349
+ },
5350
+ style: {
5351
+ position: "absolute",
5352
+ top: blockSelection.anchor.top,
5353
+ left: blockSelection.anchor.left,
5354
+ transform: "translate(4px, -100%)",
5355
+ zIndex: 20,
5356
+ display: "flex",
5357
+ alignItems: "center",
5358
+ gap: theme2.space[1],
5359
+ padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
5360
+ backgroundColor: theme2.colors.error || "#dc2626",
5361
+ color: "#fff",
5362
+ border: "none",
5363
+ borderRadius: theme2.radii[1],
5364
+ fontSize: theme2.fontSizes[0],
5365
+ fontFamily: theme2.fonts.body,
5366
+ cursor: "pointer",
5367
+ boxShadow: theme2.shadows?.[2] ?? "0 2px 8px rgba(0,0,0,0.25)"
5368
+ }
5369
+ }, /* @__PURE__ */ React13.createElement(Trash2, {
5370
+ size: 14
5371
+ }), "Delete"), /* @__PURE__ */ React13.createElement(IndustryHtmlModal, {
4841
5372
  isOpen: htmlModalOpen,
4842
5373
  onClose: closeHtmlModal,
4843
5374
  htmlContent: htmlModalContent,
@@ -4858,7 +5389,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4858
5389
  });
4859
5390
  // industryMarkdown/components/SlidePresentation.tsx
4860
5391
  import { AnimatedResizableLayout } from "@principal-ade/panels";
4861
- import React17, { useState as useState11, useCallback as useCallback3, useRef as useRef10, useEffect as useEffect10 } from "react";
5392
+ import React17, { useState as useState12, useCallback as useCallback4, useRef as useRef11, useEffect as useEffect11 } from "react";
4862
5393
 
4863
5394
  // industryMarkdown/utils/extractSlideTitles.ts
4864
5395
  function extractSlideTitle2(content, slideIndex) {
@@ -5129,7 +5660,7 @@ var SlideNavigationHeader = ({
5129
5660
 
5130
5661
  // industryMarkdown/components/SlideSearchBar.tsx
5131
5662
  import { Search, X as X2 } from "lucide-react";
5132
- import React16, { useRef as useRef9, useEffect as useEffect9 } from "react";
5663
+ import React16, { useRef as useRef10, useEffect as useEffect10 } from "react";
5133
5664
  var SlideSearchBar = ({
5134
5665
  showSearch,
5135
5666
  searchQuery,
@@ -5143,8 +5674,8 @@ var SlideSearchBar = ({
5143
5674
  onClose,
5144
5675
  onClear
5145
5676
  }) => {
5146
- const searchInputRef = useRef9(null);
5147
- useEffect9(() => {
5677
+ const searchInputRef = useRef10(null);
5678
+ useEffect10(() => {
5148
5679
  if (showSearch && searchInputRef.current) {
5149
5680
  searchInputRef.current.focus();
5150
5681
  }
@@ -5346,8 +5877,8 @@ var SlidePresentation = ({
5346
5877
  fontSizeScale,
5347
5878
  theme: theme2
5348
5879
  }) => {
5349
- const [isMobile, setIsMobile] = useState11(false);
5350
- useEffect10(() => {
5880
+ const [isMobile, setIsMobile] = useState12(false);
5881
+ useEffect11(() => {
5351
5882
  const checkMobile = () => {
5352
5883
  setIsMobile(/iPhone|iPad|iPod|Android/i.test(navigator.userAgent) || window.innerWidth < 768);
5353
5884
  };
@@ -5357,17 +5888,17 @@ var SlidePresentation = ({
5357
5888
  }, []);
5358
5889
  const effectiveTocDisplayMode = isMobile ? "overlay" : tocDisplayMode;
5359
5890
  const defaultTocOpen = initialTocOpen ?? effectiveTocDisplayMode === "sidebar";
5360
- const [currentSlide, setCurrentSlide] = useState11(initialSlide);
5361
- const [isFullscreen, setIsFullscreen] = useState11(false);
5362
- const [showTOC, setShowTOC] = useState11(defaultTocOpen);
5363
- const [showSearch, setShowSearch] = useState11(false);
5364
- const [searchQuery, setSearchQuery] = useState11("");
5365
- const [searchResults, setSearchResults] = useState11([]);
5366
- const [currentSearchResult, setCurrentSearchResult] = useState11(-1);
5367
- const [searchStartSlide, setSearchStartSlide] = useState11(0);
5368
- const containerRef = useRef10(null);
5891
+ const [currentSlide, setCurrentSlide] = useState12(initialSlide);
5892
+ const [isFullscreen, setIsFullscreen] = useState12(false);
5893
+ const [showTOC, setShowTOC] = useState12(defaultTocOpen);
5894
+ const [showSearch, setShowSearch] = useState12(false);
5895
+ const [searchQuery, setSearchQuery] = useState12("");
5896
+ const [searchResults, setSearchResults] = useState12([]);
5897
+ const [currentSearchResult, setCurrentSearchResult] = useState12(-1);
5898
+ const [searchStartSlide, setSearchStartSlide] = useState12(0);
5899
+ const containerRef = useRef11(null);
5369
5900
  const slideTitles = extractAllSlideTitles(slides);
5370
- const navigateToSlide = useCallback3((slideIndex) => {
5901
+ const navigateToSlide = useCallback4((slideIndex) => {
5371
5902
  if (slideIndex >= 0 && slideIndex < slides.length) {
5372
5903
  setCurrentSlide(slideIndex);
5373
5904
  onSlideChange?.(slideIndex);
@@ -5376,7 +5907,7 @@ var SlidePresentation = ({
5376
5907
  }
5377
5908
  }
5378
5909
  }, [slides.length, onSlideChange, effectiveTocDisplayMode]);
5379
- useEffect10(() => {
5910
+ useEffect11(() => {
5380
5911
  if (!searchQuery.trim()) {
5381
5912
  setSearchResults([]);
5382
5913
  setCurrentSearchResult(-1);
@@ -5394,7 +5925,7 @@ var SlidePresentation = ({
5394
5925
  setSearchResults(results);
5395
5926
  setCurrentSearchResult(-1);
5396
5927
  }, [searchQuery, slides]);
5397
- const navigateToSearchResult = useCallback3((resultIndex) => {
5928
+ const navigateToSearchResult = useCallback4((resultIndex) => {
5398
5929
  if (searchResults.length === 0)
5399
5930
  return;
5400
5931
  let newIndex = resultIndex;
@@ -5409,22 +5940,22 @@ var SlidePresentation = ({
5409
5940
  navigateToSlide(targetSlide);
5410
5941
  }
5411
5942
  }, [searchResults, navigateToSlide, currentSlide, currentSearchResult]);
5412
- const closeSearch = useCallback3(() => {
5943
+ const closeSearch = useCallback4(() => {
5413
5944
  setShowSearch(false);
5414
5945
  }, []);
5415
- const clearSearch = useCallback3(() => {
5946
+ const clearSearch = useCallback4(() => {
5416
5947
  setSearchQuery("");
5417
5948
  setSearchResults([]);
5418
5949
  setCurrentSearchResult(-1);
5419
5950
  setSearchStartSlide(0);
5420
5951
  }, []);
5421
- const goToPreviousSlide = useCallback3(() => {
5952
+ const goToPreviousSlide = useCallback4(() => {
5422
5953
  navigateToSlide(currentSlide - 1);
5423
5954
  }, [currentSlide, navigateToSlide]);
5424
- const goToNextSlide = useCallback3(() => {
5955
+ const goToNextSlide = useCallback4(() => {
5425
5956
  navigateToSlide(currentSlide + 1);
5426
5957
  }, [currentSlide, navigateToSlide]);
5427
- const toggleFullscreen = useCallback3(() => {
5958
+ const toggleFullscreen = useCallback4(() => {
5428
5959
  if (!containerRef.current)
5429
5960
  return;
5430
5961
  if (!isFullscreen) {
@@ -5435,7 +5966,7 @@ var SlidePresentation = ({
5435
5966
  setIsFullscreen(false);
5436
5967
  }
5437
5968
  }, [isFullscreen]);
5438
- useEffect10(() => {
5969
+ useEffect11(() => {
5439
5970
  const handleKeyDown = (event) => {
5440
5971
  if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) {
5441
5972
  if (showSearch && (event.key === "Tab" || event.key === "Enter" || event.key === "Escape")) {} else {
@@ -5553,7 +6084,7 @@ var SlidePresentation = ({
5553
6084
  currentSearchResult,
5554
6085
  tocDisplayMode
5555
6086
  ]);
5556
- useEffect10(() => {
6087
+ useEffect11(() => {
5557
6088
  if (currentSlide >= slides.length && slides.length > 0) {
5558
6089
  setCurrentSlide(slides.length - 1);
5559
6090
  }
@@ -6014,7 +6545,7 @@ var SlidePresentation = ({
6014
6545
  };
6015
6546
  // industryMarkdown/components/SlidePresentationBook.tsx
6016
6547
  import { AnimatedResizableLayout as AnimatedResizableLayout2 } from "@principal-ade/panels";
6017
- import React18, { useState as useState12, useCallback as useCallback4, useRef as useRef11, useEffect as useEffect11 } from "react";
6548
+ import React18, { useState as useState13, useCallback as useCallback5, useRef as useRef12, useEffect as useEffect12 } from "react";
6018
6549
  var SlidePresentationBook = ({
6019
6550
  slides,
6020
6551
  initialSlide = 0,
@@ -6044,8 +6575,8 @@ var SlidePresentationBook = ({
6044
6575
  repositoryInfo,
6045
6576
  width
6046
6577
  }) => {
6047
- const [isMobile, setIsMobile] = useState12(false);
6048
- useEffect11(() => {
6578
+ const [isMobile, setIsMobile] = useState13(false);
6579
+ useEffect12(() => {
6049
6580
  const checkMobile = () => {
6050
6581
  setIsMobile(/iPhone|iPad|iPod|Android/i.test(navigator.userAgent) || window.innerWidth < 768);
6051
6582
  };
@@ -6056,20 +6587,20 @@ var SlidePresentationBook = ({
6056
6587
  const effectiveTocDisplayMode = isMobile && viewMode === "single" ? "overlay" : tocDisplayMode ?? (viewMode === "single" ? "sidebar" : "overlay");
6057
6588
  const defaultTocOpen = initialTocOpen ?? false;
6058
6589
  const adjustedInitialSlide = viewMode === "book" ? Math.floor(initialSlide / 2) * 2 : initialSlide;
6059
- const [currentSlide, setCurrentSlide] = useState12(adjustedInitialSlide);
6060
- const [isFullscreen, setIsFullscreen] = useState12(false);
6061
- const [showTOC, setShowTOC] = useState12(defaultTocOpen);
6062
- const [showSearch, setShowSearch] = useState12(false);
6063
- const [searchQuery, setSearchQuery] = useState12("");
6064
- const [searchResults, setSearchResults] = useState12([]);
6065
- const [currentSearchResult, setCurrentSearchResult] = useState12(-1);
6066
- const [searchStartSlide, setSearchStartSlide] = useState12(0);
6067
- const [collapsedSide, setCollapsedSide] = useState12(null);
6068
- const [lastInteractedSide, setLastInteractedSide] = useState12("left");
6069
- const containerRef = useRef11(null);
6590
+ const [currentSlide, setCurrentSlide] = useState13(adjustedInitialSlide);
6591
+ const [isFullscreen, setIsFullscreen] = useState13(false);
6592
+ const [showTOC, setShowTOC] = useState13(defaultTocOpen);
6593
+ const [showSearch, setShowSearch] = useState13(false);
6594
+ const [searchQuery, setSearchQuery] = useState13("");
6595
+ const [searchResults, setSearchResults] = useState13([]);
6596
+ const [currentSearchResult, setCurrentSearchResult] = useState13(-1);
6597
+ const [searchStartSlide, setSearchStartSlide] = useState13(0);
6598
+ const [collapsedSide, setCollapsedSide] = useState13(null);
6599
+ const [lastInteractedSide, setLastInteractedSide] = useState13("left");
6600
+ const containerRef = useRef12(null);
6070
6601
  const slideTitles = extractAllSlideTitles(slides);
6071
6602
  const stepSize = viewMode === "book" ? 2 : 1;
6072
- const navigateToSlide = useCallback4((slideIndex) => {
6603
+ const navigateToSlide = useCallback5((slideIndex) => {
6073
6604
  const targetSlide = viewMode === "book" ? Math.floor(slideIndex / 2) * 2 : slideIndex;
6074
6605
  if (targetSlide >= 0 && targetSlide < slides.length) {
6075
6606
  setCurrentSlide(targetSlide);
@@ -6079,7 +6610,7 @@ var SlidePresentationBook = ({
6079
6610
  }
6080
6611
  }
6081
6612
  }, [slides.length, onSlideChange, viewMode, effectiveTocDisplayMode]);
6082
- useEffect11(() => {
6613
+ useEffect12(() => {
6083
6614
  if (!searchQuery.trim()) {
6084
6615
  setSearchResults([]);
6085
6616
  setCurrentSearchResult(-1);
@@ -6097,7 +6628,7 @@ var SlidePresentationBook = ({
6097
6628
  setSearchResults(results);
6098
6629
  setCurrentSearchResult(-1);
6099
6630
  }, [searchQuery, slides]);
6100
- const navigateToSearchResult = useCallback4((resultIndex) => {
6631
+ const navigateToSearchResult = useCallback5((resultIndex) => {
6101
6632
  if (searchResults.length === 0)
6102
6633
  return;
6103
6634
  let newIndex = resultIndex;
@@ -6112,22 +6643,22 @@ var SlidePresentationBook = ({
6112
6643
  navigateToSlide(targetSlide);
6113
6644
  }
6114
6645
  }, [searchResults, navigateToSlide, currentSlide, currentSearchResult]);
6115
- const closeSearch = useCallback4(() => {
6646
+ const closeSearch = useCallback5(() => {
6116
6647
  setShowSearch(false);
6117
6648
  }, []);
6118
- const clearSearch = useCallback4(() => {
6649
+ const clearSearch = useCallback5(() => {
6119
6650
  setSearchQuery("");
6120
6651
  setSearchResults([]);
6121
6652
  setCurrentSearchResult(-1);
6122
6653
  setSearchStartSlide(0);
6123
6654
  }, []);
6124
- const goToPreviousSlide = useCallback4(() => {
6655
+ const goToPreviousSlide = useCallback5(() => {
6125
6656
  navigateToSlide(currentSlide - stepSize);
6126
6657
  }, [currentSlide, navigateToSlide, stepSize]);
6127
- const goToNextSlide = useCallback4(() => {
6658
+ const goToNextSlide = useCallback5(() => {
6128
6659
  navigateToSlide(currentSlide + stepSize);
6129
6660
  }, [currentSlide, navigateToSlide, stepSize]);
6130
- const handleCollapseLeft = useCallback4(() => {
6661
+ const handleCollapseLeft = useCallback5(() => {
6131
6662
  if (collapsedSide === "left") {
6132
6663
  setCollapsedSide(null);
6133
6664
  } else if (collapsedSide === "right") {
@@ -6137,7 +6668,7 @@ var SlidePresentationBook = ({
6137
6668
  setCollapsedSide("right");
6138
6669
  }
6139
6670
  }, [collapsedSide]);
6140
- const handleCollapseRight = useCallback4(() => {
6671
+ const handleCollapseRight = useCallback5(() => {
6141
6672
  if (collapsedSide === "right") {
6142
6673
  setCollapsedSide(null);
6143
6674
  } else if (collapsedSide === "left") {
@@ -6147,7 +6678,7 @@ var SlidePresentationBook = ({
6147
6678
  setCollapsedSide("left");
6148
6679
  }
6149
6680
  }, [collapsedSide]);
6150
- const toggleFullscreen = useCallback4(() => {
6681
+ const toggleFullscreen = useCallback5(() => {
6151
6682
  if (!containerRef.current)
6152
6683
  return;
6153
6684
  if (!isFullscreen) {
@@ -6158,7 +6689,7 @@ var SlidePresentationBook = ({
6158
6689
  setIsFullscreen(false);
6159
6690
  }
6160
6691
  }, [isFullscreen]);
6161
- useEffect11(() => {
6692
+ useEffect12(() => {
6162
6693
  const handleKeyDown = (event) => {
6163
6694
  if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) {
6164
6695
  if (showSearch && (event.key === "Tab" || event.key === "Enter" || event.key === "Escape")) {} else {
@@ -6277,7 +6808,7 @@ var SlidePresentationBook = ({
6277
6808
  searchResults,
6278
6809
  effectiveTocDisplayMode
6279
6810
  ]);
6280
- useEffect11(() => {
6811
+ useEffect12(() => {
6281
6812
  if (currentSlide >= slides.length && slides.length > 0) {
6282
6813
  setCurrentSlide(slides.length - 1);
6283
6814
  }
@@ -6940,7 +7471,7 @@ var SlidePresentationBook = ({
6940
7471
  }));
6941
7472
  };
6942
7473
  // industryMarkdown/components/DocumentView.tsx
6943
- import React19, { useRef as useRef12 } from "react";
7474
+ import React19, { useRef as useRef13 } from "react";
6944
7475
  var DocumentView = ({
6945
7476
  content,
6946
7477
  onCheckboxChange,
@@ -6965,7 +7496,7 @@ var DocumentView = ({
6965
7496
  onAnnotationClick,
6966
7497
  annotationStyle
6967
7498
  }) => {
6968
- const containerRef = useRef12(null);
7499
+ const containerRef = useRef13(null);
6969
7500
  const backgroundColor = transparentBackground ? "transparent" : theme2.colors.background;
6970
7501
  return /* @__PURE__ */ React19.createElement("div", {
6971
7502
  ref: containerRef,
@@ -7429,6 +7960,9 @@ export {
7429
7960
  createPresentationWithErrorMessage,
7430
7961
  createIndustryMarkdownComponents,
7431
7962
  createGithubFileSource,
7963
+ computeTextDeletion,
7964
+ computeDeletion,
7965
+ computeChunkOffsets,
7432
7966
  ThemeProvider,
7433
7967
  SlideSearchBar,
7434
7968
  SlidePresentationBook,