themed-markdown 0.1.91 → 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";
@@ -2703,7 +3024,7 @@ var extractTextFromChildren = (children) => {
2703
3024
  }
2704
3025
  return "";
2705
3026
  };
2706
- var LinkWithLoadingIndicator = ({ href, children, onClick, className }) => {
3027
+ var LinkWithLoadingIndicator = ({ href, children, onClick, className, style }) => {
2707
3028
  const handleClick = (e) => {
2708
3029
  if (onClick) {
2709
3030
  e.preventDefault();
@@ -2714,13 +3035,14 @@ var LinkWithLoadingIndicator = ({ href, children, onClick, className }) => {
2714
3035
  href,
2715
3036
  onClick: handleClick,
2716
3037
  className,
3038
+ style,
2717
3039
  target: "_blank",
2718
3040
  rel: "noopener noreferrer"
2719
3041
  }, children);
2720
3042
  };
2721
3043
  // industryMarkdown/components/IndustryBashCommandDropdown.tsx
2722
3044
  import { Play, ChevronDown } from "lucide-react";
2723
- 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";
2724
3046
  var IndustryBashCommandDropdown = ({
2725
3047
  commands,
2726
3048
  allCommands,
@@ -2729,11 +3051,11 @@ var IndustryBashCommandDropdown = ({
2729
3051
  slideIdPrefix: _slideIdPrefix,
2730
3052
  theme: themeOverride
2731
3053
  }) => {
2732
- const [isOpen, setIsOpen] = useState6(false);
2733
- const [isRunning, setIsRunning] = useState6(false);
2734
- const dropdownRef = useRef4(null);
3054
+ const [isOpen, setIsOpen] = useState7(false);
3055
+ const [isRunning, setIsRunning] = useState7(false);
3056
+ const dropdownRef = useRef5(null);
2735
3057
  const theme2 = themeOverride ?? theme;
2736
- useEffect5(() => {
3058
+ useEffect6(() => {
2737
3059
  const handleClickOutside = (event) => {
2738
3060
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
2739
3061
  setIsOpen(false);
@@ -2852,7 +3174,7 @@ var IndustryBashCommandDropdown = ({
2852
3174
  e.currentTarget.style.backgroundColor = theme2.colors.muted;
2853
3175
  }
2854
3176
  }, "\uD83D\uDE80 Run all (", commands.length, " commands)"), commands.map((cmd, index) => {
2855
- const [isHovered, setIsHovered] = useState6(false);
3177
+ const [isHovered, setIsHovered] = useState7(false);
2856
3178
  return /* @__PURE__ */ React8.createElement("div", {
2857
3179
  key: index,
2858
3180
  style: dropdownItemStyle(isHovered),
@@ -2908,8 +3230,8 @@ var OptimizedMarkdownMedia = React9.memo(({
2908
3230
  const transformedSrc = useMemo2(() => {
2909
3231
  return transformImageUrl(src, repositoryInfo);
2910
3232
  }, [src, repositoryInfo]);
2911
- const [hasErrored, setHasErrored] = useState7(() => failedImageCache.has(transformedSrc));
2912
- const retryCount = useRef5(0);
3233
+ const [hasErrored, setHasErrored] = useState8(() => failedImageCache.has(transformedSrc));
3234
+ const retryCount = useRef6(0);
2913
3235
  const mediaStyle = useMemo2(() => ({
2914
3236
  maxWidth: "100%",
2915
3237
  height: "auto",
@@ -3013,8 +3335,24 @@ var createIndustryMarkdownComponents = ({
3013
3335
  slideHeaderMarginTopOverride,
3014
3336
  index,
3015
3337
  repositoryInfo,
3016
- editable = false
3338
+ editable = false,
3339
+ selectableBlocks = false,
3340
+ onDeleteListItem
3017
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
+ };
3018
3356
  const getLuminance = (hex) => {
3019
3357
  const rgb = hex.replace("#", "").match(/.{2}/g);
3020
3358
  if (!rgb)
@@ -3028,7 +3366,7 @@ var createIndustryMarkdownComponents = ({
3028
3366
  headerStyles.marginTop = slideHeaderMarginTopOverride ? `${slideHeaderMarginTopOverride}px` : 0;
3029
3367
  }
3030
3368
  return {
3031
- h1: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h1", {
3369
+ h1: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h1", {
3032
3370
  style: {
3033
3371
  color: theme2.colors.text,
3034
3372
  fontSize: theme2.fontSizes[5],
@@ -3041,9 +3379,10 @@ var createIndustryMarkdownComponents = ({
3041
3379
  borderBottom: `1px solid ${theme2.colors.border}`,
3042
3380
  ...headerStyles
3043
3381
  },
3044
- ...props
3382
+ ...props,
3383
+ ...blockMeta(node)
3045
3384
  }, children),
3046
- h2: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h2", {
3385
+ h2: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h2", {
3047
3386
  style: {
3048
3387
  color: theme2.colors.text,
3049
3388
  fontSize: theme2.fontSizes[4],
@@ -3056,9 +3395,10 @@ var createIndustryMarkdownComponents = ({
3056
3395
  borderBottom: `1px solid ${theme2.colors.border}`,
3057
3396
  ...headerStyles
3058
3397
  },
3059
- ...props
3398
+ ...props,
3399
+ ...blockMeta(node)
3060
3400
  }, children),
3061
- h3: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h3", {
3401
+ h3: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h3", {
3062
3402
  style: {
3063
3403
  color: theme2.colors.text,
3064
3404
  fontSize: theme2.fontSizes[3],
@@ -3068,9 +3408,10 @@ var createIndustryMarkdownComponents = ({
3068
3408
  marginBottom: theme2.space[3],
3069
3409
  fontFamily: theme2.fonts.heading
3070
3410
  },
3071
- ...props
3411
+ ...props,
3412
+ ...blockMeta(node)
3072
3413
  }, children),
3073
- h4: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h4", {
3414
+ h4: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h4", {
3074
3415
  style: {
3075
3416
  color: theme2.colors.text,
3076
3417
  fontSize: theme2.fontSizes[2],
@@ -3080,9 +3421,10 @@ var createIndustryMarkdownComponents = ({
3080
3421
  marginBottom: theme2.space[2],
3081
3422
  fontFamily: theme2.fonts.heading
3082
3423
  },
3083
- ...props
3424
+ ...props,
3425
+ ...blockMeta(node)
3084
3426
  }, children),
3085
- h5: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h5", {
3427
+ h5: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h5", {
3086
3428
  style: {
3087
3429
  color: theme2.colors.text,
3088
3430
  fontSize: theme2.fontSizes[1],
@@ -3092,9 +3434,10 @@ var createIndustryMarkdownComponents = ({
3092
3434
  marginBottom: theme2.space[1],
3093
3435
  fontFamily: theme2.fonts.heading
3094
3436
  },
3095
- ...props
3437
+ ...props,
3438
+ ...blockMeta(node)
3096
3439
  }, children),
3097
- h6: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("h6", {
3440
+ h6: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("h6", {
3098
3441
  style: {
3099
3442
  color: theme2.colors.text,
3100
3443
  fontSize: theme2.fontSizes[1],
@@ -3104,9 +3447,10 @@ var createIndustryMarkdownComponents = ({
3104
3447
  marginBottom: theme2.space[1],
3105
3448
  fontFamily: theme2.fonts.heading
3106
3449
  },
3107
- ...props
3450
+ ...props,
3451
+ ...blockMeta(node)
3108
3452
  }, children),
3109
- p: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("p", {
3453
+ p: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("p", {
3110
3454
  style: {
3111
3455
  color: theme2.colors.text,
3112
3456
  fontSize: theme2.fontSizes[2],
@@ -3114,9 +3458,10 @@ var createIndustryMarkdownComponents = ({
3114
3458
  marginBottom: theme2.space[3],
3115
3459
  fontFamily: theme2.fonts.body
3116
3460
  },
3117
- ...props
3461
+ ...props,
3462
+ ...blockMeta(node)
3118
3463
  }, children),
3119
- ul: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("ul", {
3464
+ ul: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("ul", {
3120
3465
  style: {
3121
3466
  color: theme2.colors.text,
3122
3467
  fontSize: theme2.fontSizes[2],
@@ -3126,9 +3471,10 @@ var createIndustryMarkdownComponents = ({
3126
3471
  listStyleType: "disc",
3127
3472
  fontFamily: theme2.fonts.body
3128
3473
  },
3129
- ...props
3474
+ ...props,
3475
+ ...blockMeta(node)
3130
3476
  }, children),
3131
- ol: ({ children, ...props }) => /* @__PURE__ */ React9.createElement("ol", {
3477
+ ol: ({ children, node, ...props }) => /* @__PURE__ */ React9.createElement("ol", {
3132
3478
  style: {
3133
3479
  color: theme2.colors.text,
3134
3480
  fontSize: theme2.fontSizes[2],
@@ -3138,9 +3484,10 @@ var createIndustryMarkdownComponents = ({
3138
3484
  listStyleType: "decimal",
3139
3485
  fontFamily: theme2.fonts.body
3140
3486
  },
3141
- ...props
3487
+ ...props,
3488
+ ...blockMeta(node)
3142
3489
  }, children),
3143
- li: ({ children, ...props }) => {
3490
+ li: ({ children, node, ...props }) => {
3144
3491
  const isTaskListItem = Array.isArray(children) && children.length > 0 && React9.isValidElement(children[0]) && children[0]?.props?.type === "checkbox";
3145
3492
  if (isTaskListItem) {
3146
3493
  const checkbox = children[0];
@@ -3155,7 +3502,7 @@ var createIndustryMarkdownComponents = ({
3155
3502
  }
3156
3503
  });
3157
3504
  const checked = checkbox?.props?.checked || false;
3158
- const lineNumber = props.sourcePosition?.start?.line || props.node?.position?.start?.line || 1;
3505
+ const lineNumber = props.sourcePosition?.start?.line || node?.position?.start?.line || 1;
3159
3506
  const id = `${slideIdPrefix}-checkbox-${lineNumber}`;
3160
3507
  const isChecked = checkedItems[id] ?? checked;
3161
3508
  const handleChange = (e) => {
@@ -3203,6 +3550,37 @@ var createIndustryMarkdownComponents = ({
3203
3550
  }
3204
3551
  }, labelContent.length > 0 ? labelContent : null)), nestedListElements.length > 0 ? nestedListElements : null);
3205
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
+ }
3206
3584
  return /* @__PURE__ */ React9.createElement("li", {
3207
3585
  style: {
3208
3586
  marginBottom: theme2.space[2],
@@ -3210,16 +3588,39 @@ var createIndustryMarkdownComponents = ({
3210
3588
  color: theme2.colors.text,
3211
3589
  lineHeight: theme2.lineHeights.relaxed
3212
3590
  },
3213
- ...props
3591
+ ...props,
3592
+ ...blockMeta(node)
3214
3593
  }, children);
3215
3594
  },
3216
- 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", {
3217
3617
  style: {
3218
3618
  overflowX: "auto",
3219
3619
  marginBottom: theme2.space[4],
3220
3620
  borderRadius: theme2.radii[2],
3221
3621
  border: `1px solid ${theme2.colors.border}`
3222
- }
3622
+ },
3623
+ ...blockMeta(node)
3223
3624
  }, /* @__PURE__ */ React9.createElement("table", {
3224
3625
  style: {
3225
3626
  width: "100%",
@@ -3256,7 +3657,8 @@ var createIndustryMarkdownComponents = ({
3256
3657
  a: ({ children, href, ...props }) => /* @__PURE__ */ React9.createElement(LinkWithLoadingIndicator, {
3257
3658
  href: href || "",
3258
3659
  onClick: onLinkClick ? (h, e) => onLinkClick(h, e) : undefined,
3259
- className: props.className
3660
+ className: props.className,
3661
+ style: { color: theme2.colors.primary, textDecoration: "underline" }
3260
3662
  }, children),
3261
3663
  img: ({ src, alt, ...props }) => /* @__PURE__ */ React9.createElement(OptimizedMarkdownMedia, {
3262
3664
  src: src || "",
@@ -3304,7 +3706,7 @@ var createIndustryMarkdownComponents = ({
3304
3706
  const codeString = extractTextFromChildren(children);
3305
3707
  const matchLang = /language-(\w+)/.exec(className || "");
3306
3708
  const language = matchLang ? matchLang[1] : null;
3307
- const [copied, setCopied] = useState7(false);
3709
+ const [copied, setCopied] = useState8(false);
3308
3710
  let isInline;
3309
3711
  let isCodeBlock;
3310
3712
  const hasNewlines = codeString.includes(`
@@ -3370,7 +3772,8 @@ var createIndustryMarkdownComponents = ({
3370
3772
  fontSize: theme2.fontSizes[0]
3371
3773
  };
3372
3774
  return /* @__PURE__ */ React9.createElement("div", {
3373
- style: containerStyle
3775
+ style: containerStyle,
3776
+ ...blockMeta(node)
3374
3777
  }, /* @__PURE__ */ React9.createElement("div", {
3375
3778
  style: headerStyle
3376
3779
  }, /* @__PURE__ */ React9.createElement("span", {
@@ -3529,11 +3932,11 @@ var createIndustryMarkdownComponents = ({
3529
3932
  };
3530
3933
 
3531
3934
  // industryMarkdown/components/IndustryMermaidModal.tsx
3532
- import React11, { useEffect as useEffect7, useRef as useRef7 } from "react";
3935
+ import React11, { useEffect as useEffect8, useRef as useRef8 } from "react";
3533
3936
  import { createPortal } from "react-dom";
3534
3937
 
3535
3938
  // industryMarkdown/components/IndustryZoomableMermaidDiagram.tsx
3536
- 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";
3537
3940
  import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
3538
3941
  function IndustryZoomableMermaidDiagram({
3539
3942
  code,
@@ -3543,13 +3946,13 @@ function IndustryZoomableMermaidDiagram({
3543
3946
  padding = 0.9
3544
3947
  }) {
3545
3948
  const theme2 = themeOverride ?? theme;
3546
- const [calculatedScale, setCalculatedScale] = useState8(1);
3547
- const [hasInitialized, setHasInitialized] = useState8(false);
3548
- const containerRef = useRef6(null);
3549
- const diagramRef = useRef6(null);
3550
- const [isCalculating, setIsCalculating] = useState8(true);
3551
- const transformRef = useRef6(null);
3552
- 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(() => {
3553
3956
  if (!containerRef.current || !diagramRef.current)
3554
3957
  return;
3555
3958
  const calculateOptimalScale = () => {
@@ -3613,7 +4016,7 @@ function IndustryZoomableMermaidDiagram({
3613
4016
  resizeObserver.disconnect();
3614
4017
  };
3615
4018
  }, [code, fitStrategy, padding]);
3616
- useEffect6(() => {
4019
+ useEffect7(() => {
3617
4020
  if (hasInitialized && transformRef.current) {
3618
4021
  const { centerView } = transformRef.current;
3619
4022
  centerView(calculatedScale, 0, "easeOut");
@@ -3723,8 +4126,8 @@ function IndustryMermaidModal({
3723
4126
  mermaidCode,
3724
4127
  theme: theme2
3725
4128
  }) {
3726
- const modalRef = useRef7(null);
3727
- useEffect7(() => {
4129
+ const modalRef = useRef8(null);
4130
+ useEffect8(() => {
3728
4131
  const handleEscape = (event) => {
3729
4132
  if (event.key === "Escape") {
3730
4133
  onClose();
@@ -3826,7 +4229,7 @@ function IndustryMermaidModal({
3826
4229
  }
3827
4230
 
3828
4231
  // industryMarkdown/components/IndustryPlaceholderModal.tsx
3829
- import React12, { useState as useState9 } from "react";
4232
+ import React12, { useState as useState10 } from "react";
3830
4233
  function IndustryPlaceholderModal({
3831
4234
  isOpen,
3832
4235
  onClose,
@@ -3835,7 +4238,7 @@ function IndustryPlaceholderModal({
3835
4238
  onCopy,
3836
4239
  theme: theme2
3837
4240
  }) {
3838
- const [values, setValues] = useState9({});
4241
+ const [values, setValues] = useState10({});
3839
4242
  if (!isOpen)
3840
4243
  return null;
3841
4244
  const handleSubmit = (e) => {
@@ -4242,6 +4645,52 @@ var annotationCSS = `
4242
4645
  cursor: pointer;
4243
4646
  }
4244
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
+ `;
4245
4694
  var fontTransitionCSS = `
4246
4695
  .markdown-slide * {
4247
4696
  transition: font-size 0.2s ease-in-out;
@@ -4305,6 +4754,12 @@ var injectStyles = () => {
4305
4754
  annotationStyle.textContent = annotationCSS;
4306
4755
  document.head.appendChild(annotationStyle);
4307
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
+ }
4308
4763
  stylesInjected = true;
4309
4764
  }
4310
4765
  };
@@ -4336,6 +4791,10 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4336
4791
  keyboardScrollConfig,
4337
4792
  repositoryInfo,
4338
4793
  editable = false,
4794
+ selectableBlocks = false,
4795
+ deletionMode = "block",
4796
+ onContentChange,
4797
+ onDeleteBlocks,
4339
4798
  annotations,
4340
4799
  activeAnnotationId,
4341
4800
  renderAnnotation,
@@ -4343,9 +4802,9 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4343
4802
  onAnnotationClick,
4344
4803
  annotationStyle
4345
4804
  }) {
4346
- const slideRef = useRef8(null);
4347
- const scrollPositionsRef = useRef8(new Map);
4348
- const [measuredContainerWidth, setMeasuredContainerWidth] = useState10(null);
4805
+ const slideRef = useRef9(null);
4806
+ const scrollPositionsRef = useRef9(new Map);
4807
+ const [measuredContainerWidth, setMeasuredContainerWidth] = useState11(null);
4349
4808
  const chunks = useMemo3(() => {
4350
4809
  if (typeof content !== "string")
4351
4810
  return [];
@@ -4356,16 +4815,16 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4356
4815
  return [];
4357
4816
  }
4358
4817
  }, [content, slideIdPrefix]);
4359
- const [checkedItems, setCheckedItems] = useState10({});
4818
+ const [checkedItems, setCheckedItems] = useState11({});
4360
4819
  const { htmlModalOpen, htmlModalContent, openHtmlModal, closeHtmlModal } = useIndustryHtmlModal();
4361
- const [mermaidModalOpen, setMermaidModalOpen] = useState10(false);
4362
- const [mermaidModalCode, setMermaidModalCode] = useState10("");
4363
- const [placeholderModalOpen, setPlaceholderModalOpen] = useState10(false);
4364
- const [placeholderModalData, setPlaceholderModalData] = useState10(null);
4365
- 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(() => {
4366
4825
  injectStyles();
4367
4826
  }, []);
4368
- useEffect8(() => {
4827
+ useEffect9(() => {
4369
4828
  if (containerWidth !== undefined) {
4370
4829
  return;
4371
4830
  }
@@ -4424,7 +4883,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4424
4883
  ...keyboardScrollConfig?.keys
4425
4884
  }
4426
4885
  };
4427
- const handleKeyDown = useCallback2((event) => {
4886
+ const handleKeyDown = useCallback3((event) => {
4428
4887
  if (!enableKeyboardScrolling) {
4429
4888
  return;
4430
4889
  }
@@ -4534,7 +4993,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4534
4993
  }, scrollConfig.smoothScroll ? 100 : 0);
4535
4994
  }
4536
4995
  }, [enableKeyboardScrolling, isVisible, slideIndex, scrollConfig]);
4537
- useEffect8(() => {
4996
+ useEffect9(() => {
4538
4997
  if (autoFocusOnVisible && isVisible && slideRef.current) {
4539
4998
  slideRef.current.focus({ preventScroll: true });
4540
4999
  }
@@ -4599,7 +5058,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4599
5058
  additionalPadding,
4600
5059
  disableBasePadding
4601
5060
  ]);
4602
- useEffect8(() => {
5061
+ useEffect9(() => {
4603
5062
  const slideElement = slideRef.current;
4604
5063
  if (slideElement) {
4605
5064
  const handleScroll = () => {
@@ -4686,7 +5145,17 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4686
5145
  }
4687
5146
  }), []);
4688
5147
  const rootMargin = isVisible ? "0px" : "100px";
4689
- 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) => {
4690
5159
  const baseComponents = createIndustryMarkdownComponents({
4691
5160
  theme: theme2,
4692
5161
  slideIdPrefix,
@@ -4702,7 +5171,9 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4702
5171
  slideHeaderMarginTopOverride,
4703
5172
  index: chunkIndex,
4704
5173
  repositoryInfo,
4705
- editable
5174
+ editable,
5175
+ selectableBlocks,
5176
+ onDeleteListItem: blockDeletionEnabled ? handleDeleteListItem : undefined
4706
5177
  });
4707
5178
  if (searchQuery) {
4708
5179
  return {
@@ -4736,8 +5207,24 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4736
5207
  slideHeaderMarginTopOverride,
4737
5208
  repositoryInfo,
4738
5209
  searchQuery,
4739
- editable
5210
+ editable,
5211
+ selectableBlocks,
5212
+ blockDeletionEnabled,
5213
+ handleDeleteListItem
4740
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]);
4741
5228
  const renderedChunks = useMemo3(() => {
4742
5229
  if (chunks.length === 0) {
4743
5230
  return /* @__PURE__ */ React13.createElement("div", {
@@ -4755,12 +5242,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4755
5242
  return /* @__PURE__ */ React13.createElement(ReactMarkdown, {
4756
5243
  key: `${chunk.id}-${JSON.stringify(theme2.colors.accent)}`,
4757
5244
  remarkPlugins: [remarkGfm],
4758
- rehypePlugins: [
4759
- rehypeRaw,
4760
- [rehypeSanitize, sanitizeSchema],
4761
- rehypeSlug,
4762
- rehypeHighlight
4763
- ],
5245
+ rehypePlugins,
4764
5246
  components: getMarkdownComponents(index)
4765
5247
  }, processedContent);
4766
5248
  }
@@ -4788,7 +5270,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4788
5270
  content,
4789
5271
  searchQuery,
4790
5272
  theme2,
4791
- sanitizeSchema,
5273
+ rehypePlugins,
4792
5274
  getMarkdownComponents,
4793
5275
  rootMargin,
4794
5276
  onCopyMermaidError,
@@ -4801,6 +5283,27 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4801
5283
  onSelectionChange,
4802
5284
  onAnnotationClick
4803
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]);
4804
5307
  const annotationCSSVars = {};
4805
5308
  if (annotationStyle?.backgroundColor) {
4806
5309
  annotationCSSVars["--industry-md-annotation-bg"] = annotationStyle.backgroundColor;
@@ -4835,7 +5338,37 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4835
5338
  }
4836
5339
  }, renderedChunks, renderAnnotation && annotationMounts.filter((mount) => mount.resolved).map((mount) => createPortal2(/* @__PURE__ */ React13.createElement(React13.Fragment, {
4837
5340
  key: mount.annotation.id
4838
- }, 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, {
4839
5372
  isOpen: htmlModalOpen,
4840
5373
  onClose: closeHtmlModal,
4841
5374
  htmlContent: htmlModalContent,
@@ -4856,7 +5389,7 @@ var IndustryMarkdownSlide = React13.memo(function IndustryMarkdownSlide2({
4856
5389
  });
4857
5390
  // industryMarkdown/components/SlidePresentation.tsx
4858
5391
  import { AnimatedResizableLayout } from "@principal-ade/panels";
4859
- 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";
4860
5393
 
4861
5394
  // industryMarkdown/utils/extractSlideTitles.ts
4862
5395
  function extractSlideTitle2(content, slideIndex) {
@@ -5127,7 +5660,7 @@ var SlideNavigationHeader = ({
5127
5660
 
5128
5661
  // industryMarkdown/components/SlideSearchBar.tsx
5129
5662
  import { Search, X as X2 } from "lucide-react";
5130
- import React16, { useRef as useRef9, useEffect as useEffect9 } from "react";
5663
+ import React16, { useRef as useRef10, useEffect as useEffect10 } from "react";
5131
5664
  var SlideSearchBar = ({
5132
5665
  showSearch,
5133
5666
  searchQuery,
@@ -5141,8 +5674,8 @@ var SlideSearchBar = ({
5141
5674
  onClose,
5142
5675
  onClear
5143
5676
  }) => {
5144
- const searchInputRef = useRef9(null);
5145
- useEffect9(() => {
5677
+ const searchInputRef = useRef10(null);
5678
+ useEffect10(() => {
5146
5679
  if (showSearch && searchInputRef.current) {
5147
5680
  searchInputRef.current.focus();
5148
5681
  }
@@ -5344,8 +5877,8 @@ var SlidePresentation = ({
5344
5877
  fontSizeScale,
5345
5878
  theme: theme2
5346
5879
  }) => {
5347
- const [isMobile, setIsMobile] = useState11(false);
5348
- useEffect10(() => {
5880
+ const [isMobile, setIsMobile] = useState12(false);
5881
+ useEffect11(() => {
5349
5882
  const checkMobile = () => {
5350
5883
  setIsMobile(/iPhone|iPad|iPod|Android/i.test(navigator.userAgent) || window.innerWidth < 768);
5351
5884
  };
@@ -5355,17 +5888,17 @@ var SlidePresentation = ({
5355
5888
  }, []);
5356
5889
  const effectiveTocDisplayMode = isMobile ? "overlay" : tocDisplayMode;
5357
5890
  const defaultTocOpen = initialTocOpen ?? effectiveTocDisplayMode === "sidebar";
5358
- const [currentSlide, setCurrentSlide] = useState11(initialSlide);
5359
- const [isFullscreen, setIsFullscreen] = useState11(false);
5360
- const [showTOC, setShowTOC] = useState11(defaultTocOpen);
5361
- const [showSearch, setShowSearch] = useState11(false);
5362
- const [searchQuery, setSearchQuery] = useState11("");
5363
- const [searchResults, setSearchResults] = useState11([]);
5364
- const [currentSearchResult, setCurrentSearchResult] = useState11(-1);
5365
- const [searchStartSlide, setSearchStartSlide] = useState11(0);
5366
- 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);
5367
5900
  const slideTitles = extractAllSlideTitles(slides);
5368
- const navigateToSlide = useCallback3((slideIndex) => {
5901
+ const navigateToSlide = useCallback4((slideIndex) => {
5369
5902
  if (slideIndex >= 0 && slideIndex < slides.length) {
5370
5903
  setCurrentSlide(slideIndex);
5371
5904
  onSlideChange?.(slideIndex);
@@ -5374,7 +5907,7 @@ var SlidePresentation = ({
5374
5907
  }
5375
5908
  }
5376
5909
  }, [slides.length, onSlideChange, effectiveTocDisplayMode]);
5377
- useEffect10(() => {
5910
+ useEffect11(() => {
5378
5911
  if (!searchQuery.trim()) {
5379
5912
  setSearchResults([]);
5380
5913
  setCurrentSearchResult(-1);
@@ -5392,7 +5925,7 @@ var SlidePresentation = ({
5392
5925
  setSearchResults(results);
5393
5926
  setCurrentSearchResult(-1);
5394
5927
  }, [searchQuery, slides]);
5395
- const navigateToSearchResult = useCallback3((resultIndex) => {
5928
+ const navigateToSearchResult = useCallback4((resultIndex) => {
5396
5929
  if (searchResults.length === 0)
5397
5930
  return;
5398
5931
  let newIndex = resultIndex;
@@ -5407,22 +5940,22 @@ var SlidePresentation = ({
5407
5940
  navigateToSlide(targetSlide);
5408
5941
  }
5409
5942
  }, [searchResults, navigateToSlide, currentSlide, currentSearchResult]);
5410
- const closeSearch = useCallback3(() => {
5943
+ const closeSearch = useCallback4(() => {
5411
5944
  setShowSearch(false);
5412
5945
  }, []);
5413
- const clearSearch = useCallback3(() => {
5946
+ const clearSearch = useCallback4(() => {
5414
5947
  setSearchQuery("");
5415
5948
  setSearchResults([]);
5416
5949
  setCurrentSearchResult(-1);
5417
5950
  setSearchStartSlide(0);
5418
5951
  }, []);
5419
- const goToPreviousSlide = useCallback3(() => {
5952
+ const goToPreviousSlide = useCallback4(() => {
5420
5953
  navigateToSlide(currentSlide - 1);
5421
5954
  }, [currentSlide, navigateToSlide]);
5422
- const goToNextSlide = useCallback3(() => {
5955
+ const goToNextSlide = useCallback4(() => {
5423
5956
  navigateToSlide(currentSlide + 1);
5424
5957
  }, [currentSlide, navigateToSlide]);
5425
- const toggleFullscreen = useCallback3(() => {
5958
+ const toggleFullscreen = useCallback4(() => {
5426
5959
  if (!containerRef.current)
5427
5960
  return;
5428
5961
  if (!isFullscreen) {
@@ -5433,7 +5966,7 @@ var SlidePresentation = ({
5433
5966
  setIsFullscreen(false);
5434
5967
  }
5435
5968
  }, [isFullscreen]);
5436
- useEffect10(() => {
5969
+ useEffect11(() => {
5437
5970
  const handleKeyDown = (event) => {
5438
5971
  if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) {
5439
5972
  if (showSearch && (event.key === "Tab" || event.key === "Enter" || event.key === "Escape")) {} else {
@@ -5551,7 +6084,7 @@ var SlidePresentation = ({
5551
6084
  currentSearchResult,
5552
6085
  tocDisplayMode
5553
6086
  ]);
5554
- useEffect10(() => {
6087
+ useEffect11(() => {
5555
6088
  if (currentSlide >= slides.length && slides.length > 0) {
5556
6089
  setCurrentSlide(slides.length - 1);
5557
6090
  }
@@ -6012,7 +6545,7 @@ var SlidePresentation = ({
6012
6545
  };
6013
6546
  // industryMarkdown/components/SlidePresentationBook.tsx
6014
6547
  import { AnimatedResizableLayout as AnimatedResizableLayout2 } from "@principal-ade/panels";
6015
- 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";
6016
6549
  var SlidePresentationBook = ({
6017
6550
  slides,
6018
6551
  initialSlide = 0,
@@ -6042,8 +6575,8 @@ var SlidePresentationBook = ({
6042
6575
  repositoryInfo,
6043
6576
  width
6044
6577
  }) => {
6045
- const [isMobile, setIsMobile] = useState12(false);
6046
- useEffect11(() => {
6578
+ const [isMobile, setIsMobile] = useState13(false);
6579
+ useEffect12(() => {
6047
6580
  const checkMobile = () => {
6048
6581
  setIsMobile(/iPhone|iPad|iPod|Android/i.test(navigator.userAgent) || window.innerWidth < 768);
6049
6582
  };
@@ -6054,20 +6587,20 @@ var SlidePresentationBook = ({
6054
6587
  const effectiveTocDisplayMode = isMobile && viewMode === "single" ? "overlay" : tocDisplayMode ?? (viewMode === "single" ? "sidebar" : "overlay");
6055
6588
  const defaultTocOpen = initialTocOpen ?? false;
6056
6589
  const adjustedInitialSlide = viewMode === "book" ? Math.floor(initialSlide / 2) * 2 : initialSlide;
6057
- const [currentSlide, setCurrentSlide] = useState12(adjustedInitialSlide);
6058
- const [isFullscreen, setIsFullscreen] = useState12(false);
6059
- const [showTOC, setShowTOC] = useState12(defaultTocOpen);
6060
- const [showSearch, setShowSearch] = useState12(false);
6061
- const [searchQuery, setSearchQuery] = useState12("");
6062
- const [searchResults, setSearchResults] = useState12([]);
6063
- const [currentSearchResult, setCurrentSearchResult] = useState12(-1);
6064
- const [searchStartSlide, setSearchStartSlide] = useState12(0);
6065
- const [collapsedSide, setCollapsedSide] = useState12(null);
6066
- const [lastInteractedSide, setLastInteractedSide] = useState12("left");
6067
- 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);
6068
6601
  const slideTitles = extractAllSlideTitles(slides);
6069
6602
  const stepSize = viewMode === "book" ? 2 : 1;
6070
- const navigateToSlide = useCallback4((slideIndex) => {
6603
+ const navigateToSlide = useCallback5((slideIndex) => {
6071
6604
  const targetSlide = viewMode === "book" ? Math.floor(slideIndex / 2) * 2 : slideIndex;
6072
6605
  if (targetSlide >= 0 && targetSlide < slides.length) {
6073
6606
  setCurrentSlide(targetSlide);
@@ -6077,7 +6610,7 @@ var SlidePresentationBook = ({
6077
6610
  }
6078
6611
  }
6079
6612
  }, [slides.length, onSlideChange, viewMode, effectiveTocDisplayMode]);
6080
- useEffect11(() => {
6613
+ useEffect12(() => {
6081
6614
  if (!searchQuery.trim()) {
6082
6615
  setSearchResults([]);
6083
6616
  setCurrentSearchResult(-1);
@@ -6095,7 +6628,7 @@ var SlidePresentationBook = ({
6095
6628
  setSearchResults(results);
6096
6629
  setCurrentSearchResult(-1);
6097
6630
  }, [searchQuery, slides]);
6098
- const navigateToSearchResult = useCallback4((resultIndex) => {
6631
+ const navigateToSearchResult = useCallback5((resultIndex) => {
6099
6632
  if (searchResults.length === 0)
6100
6633
  return;
6101
6634
  let newIndex = resultIndex;
@@ -6110,22 +6643,22 @@ var SlidePresentationBook = ({
6110
6643
  navigateToSlide(targetSlide);
6111
6644
  }
6112
6645
  }, [searchResults, navigateToSlide, currentSlide, currentSearchResult]);
6113
- const closeSearch = useCallback4(() => {
6646
+ const closeSearch = useCallback5(() => {
6114
6647
  setShowSearch(false);
6115
6648
  }, []);
6116
- const clearSearch = useCallback4(() => {
6649
+ const clearSearch = useCallback5(() => {
6117
6650
  setSearchQuery("");
6118
6651
  setSearchResults([]);
6119
6652
  setCurrentSearchResult(-1);
6120
6653
  setSearchStartSlide(0);
6121
6654
  }, []);
6122
- const goToPreviousSlide = useCallback4(() => {
6655
+ const goToPreviousSlide = useCallback5(() => {
6123
6656
  navigateToSlide(currentSlide - stepSize);
6124
6657
  }, [currentSlide, navigateToSlide, stepSize]);
6125
- const goToNextSlide = useCallback4(() => {
6658
+ const goToNextSlide = useCallback5(() => {
6126
6659
  navigateToSlide(currentSlide + stepSize);
6127
6660
  }, [currentSlide, navigateToSlide, stepSize]);
6128
- const handleCollapseLeft = useCallback4(() => {
6661
+ const handleCollapseLeft = useCallback5(() => {
6129
6662
  if (collapsedSide === "left") {
6130
6663
  setCollapsedSide(null);
6131
6664
  } else if (collapsedSide === "right") {
@@ -6135,7 +6668,7 @@ var SlidePresentationBook = ({
6135
6668
  setCollapsedSide("right");
6136
6669
  }
6137
6670
  }, [collapsedSide]);
6138
- const handleCollapseRight = useCallback4(() => {
6671
+ const handleCollapseRight = useCallback5(() => {
6139
6672
  if (collapsedSide === "right") {
6140
6673
  setCollapsedSide(null);
6141
6674
  } else if (collapsedSide === "left") {
@@ -6145,7 +6678,7 @@ var SlidePresentationBook = ({
6145
6678
  setCollapsedSide("left");
6146
6679
  }
6147
6680
  }, [collapsedSide]);
6148
- const toggleFullscreen = useCallback4(() => {
6681
+ const toggleFullscreen = useCallback5(() => {
6149
6682
  if (!containerRef.current)
6150
6683
  return;
6151
6684
  if (!isFullscreen) {
@@ -6156,7 +6689,7 @@ var SlidePresentationBook = ({
6156
6689
  setIsFullscreen(false);
6157
6690
  }
6158
6691
  }, [isFullscreen]);
6159
- useEffect11(() => {
6692
+ useEffect12(() => {
6160
6693
  const handleKeyDown = (event) => {
6161
6694
  if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) {
6162
6695
  if (showSearch && (event.key === "Tab" || event.key === "Enter" || event.key === "Escape")) {} else {
@@ -6275,7 +6808,7 @@ var SlidePresentationBook = ({
6275
6808
  searchResults,
6276
6809
  effectiveTocDisplayMode
6277
6810
  ]);
6278
- useEffect11(() => {
6811
+ useEffect12(() => {
6279
6812
  if (currentSlide >= slides.length && slides.length > 0) {
6280
6813
  setCurrentSlide(slides.length - 1);
6281
6814
  }
@@ -6938,7 +7471,7 @@ var SlidePresentationBook = ({
6938
7471
  }));
6939
7472
  };
6940
7473
  // industryMarkdown/components/DocumentView.tsx
6941
- import React19, { useRef as useRef12 } from "react";
7474
+ import React19, { useRef as useRef13 } from "react";
6942
7475
  var DocumentView = ({
6943
7476
  content,
6944
7477
  onCheckboxChange,
@@ -6963,7 +7496,7 @@ var DocumentView = ({
6963
7496
  onAnnotationClick,
6964
7497
  annotationStyle
6965
7498
  }) => {
6966
- const containerRef = useRef12(null);
7499
+ const containerRef = useRef13(null);
6967
7500
  const backgroundColor = transparentBackground ? "transparent" : theme2.colors.background;
6968
7501
  return /* @__PURE__ */ React19.createElement("div", {
6969
7502
  ref: containerRef,
@@ -7427,6 +7960,9 @@ export {
7427
7960
  createPresentationWithErrorMessage,
7428
7961
  createIndustryMarkdownComponents,
7429
7962
  createGithubFileSource,
7963
+ computeTextDeletion,
7964
+ computeDeletion,
7965
+ computeChunkOffsets,
7430
7966
  ThemeProvider,
7431
7967
  SlideSearchBar,
7432
7968
  SlidePresentationBook,