themed-markdown 0.1.13 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js DELETED
@@ -1,3804 +0,0 @@
1
- var __create = Object.create;
2
- var __getProtoOf = Object.getPrototypeOf;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __toESM = (mod, isNodeMode, target) => {
8
- target = mod != null ? __create(__getProtoOf(mod)) : {};
9
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
- for (let key of __getOwnPropNames(mod))
11
- if (!__hasOwnProp.call(to, key))
12
- __defProp(to, key, {
13
- get: () => mod[key],
14
- enumerable: true
15
- });
16
- return to;
17
- };
18
- var __moduleCache = /* @__PURE__ */ new WeakMap;
19
- var __toCommonJS = (from) => {
20
- var entry = __moduleCache.get(from), desc;
21
- if (entry)
22
- return entry;
23
- entry = __defProp({}, "__esModule", { value: true });
24
- if (from && typeof from === "object" || typeof from === "function")
25
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
26
- get: () => from[key],
27
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
28
- }));
29
- __moduleCache.set(from, entry);
30
- return entry;
31
- };
32
- var __export = (target, all) => {
33
- for (var name in all)
34
- __defProp(target, name, {
35
- get: all[name],
36
- enumerable: true,
37
- configurable: true,
38
- set: (newValue) => all[name] = () => newValue
39
- });
40
- };
41
-
42
- // index.ts
43
- var exports_themed_markdown = {};
44
- __export(exports_themed_markdown, {
45
- withTheme: () => withTheme,
46
- useTheme: () => useTheme,
47
- useIndustryHtmlModal: () => useIndustryHtmlModal,
48
- updateSlideTitle: () => updateSlideTitle,
49
- updateSlideContent: () => updateSlideContent,
50
- updatePresentationSlide: () => updatePresentationSlide,
51
- serializePresentationToMarkdown: () => serializePresentationToMarkdown,
52
- scaleThemeFonts: () => scaleThemeFonts,
53
- resetFontScale: () => resetFontScale,
54
- reconstructMarkdownContent: () => reconstructMarkdownContent,
55
- parseMarkdownIntoPresentationFromSource: () => parseMarkdownIntoPresentationFromSource,
56
- parseMarkdownIntoPresentation: () => parseMarkdownIntoPresentation,
57
- parseMarkdownChunks: () => parseMarkdownChunks,
58
- increaseFontScale: () => increaseFontScale,
59
- getThemeWithMode: () => getThemeWithMode,
60
- getAllSlideTitles: () => getAllSlideTitles,
61
- findSlideIndexByTitle: () => findSlideIndexByTitle,
62
- findSlideByTitle: () => findSlideByTitle,
63
- extractSlideTitle: () => extractSlideTitle,
64
- defaultTheme: () => theme,
65
- decreaseFontScale: () => decreaseFontScale,
66
- createPresentationWithErrorMessage: () => createPresentationWithErrorMessage,
67
- createIndustryMarkdownComponents: () => createIndustryMarkdownComponents,
68
- createGithubFileSource: () => createGithubFileSource,
69
- ThemeProvider: () => ThemeProvider,
70
- SlidePresentation: () => SlidePresentation,
71
- IndustryZoomableMermaidDiagram: () => IndustryZoomableMermaidDiagram,
72
- IndustryPlaceholderModal: () => IndustryPlaceholderModal,
73
- IndustryMermaidModal: () => IndustryMermaidModal,
74
- IndustryMarkdownSlide: () => IndustryMarkdownSlide,
75
- IndustryLazyMermaidDiagram: () => IndustryLazyMermaidDiagram,
76
- IndustryHtmlModal: () => IndustryHtmlModal,
77
- IndustryEditableMarkdownSlide: () => IndustryEditableMarkdownSlide,
78
- DocumentView: () => DocumentView
79
- });
80
- module.exports = __toCommonJS(exports_themed_markdown);
81
-
82
- // industryMarkdown/components/IndustryMarkdownSlide.tsx
83
- var import_hast_util_sanitize = require("hast-util-sanitize");
84
- var import_react11 = __toESM(require("react"));
85
- var import_react_markdown = __toESM(require("react-markdown"));
86
- var import_rehype_highlight = __toESM(require("rehype-highlight"));
87
- var import_rehype_raw = __toESM(require("rehype-raw"));
88
- var import_rehype_sanitize = __toESM(require("rehype-sanitize"));
89
- var import_rehype_slug = __toESM(require("rehype-slug"));
90
- var import_remark_gfm = __toESM(require("remark-gfm"));
91
-
92
- // industryTheme/ThemeProvider.tsx
93
- var import_react = __toESM(require("react"));
94
- var ThemeContext;
95
- var getThemeContext = () => {
96
- if (typeof window !== "undefined") {
97
- const globalWindow = window;
98
- if (!globalWindow.__principlemd_theme_context__) {
99
- globalWindow.__principlemd_theme_context__ = import_react.createContext(undefined);
100
- }
101
- return globalWindow.__principlemd_theme_context__;
102
- } else {
103
- if (!ThemeContext) {
104
- ThemeContext = import_react.createContext(undefined);
105
- }
106
- return ThemeContext;
107
- }
108
- };
109
- var ThemeContextSingleton = getThemeContext();
110
- var useTheme = () => {
111
- const context = import_react.useContext(ThemeContextSingleton);
112
- if (!context) {
113
- throw new Error("useTheme must be used within a ThemeProvider");
114
- }
115
- return context;
116
- };
117
- var getThemeWithMode = (baseTheme, colorMode) => {
118
- if (colorMode === "light") {
119
- return baseTheme;
120
- }
121
- const darkModeColors = baseTheme.colors.modes.dark;
122
- return {
123
- ...baseTheme,
124
- colors: {
125
- ...baseTheme.colors,
126
- ...darkModeColors
127
- }
128
- };
129
- };
130
- var ThemeProvider = ({
131
- children,
132
- theme: customTheme = theme,
133
- initialColorMode = "dark"
134
- }) => {
135
- const [colorMode, setColorMode] = import_react.useState(initialColorMode);
136
- import_react.useEffect(() => {
137
- const savedMode = localStorage.getItem("principlemd-color-mode");
138
- if (savedMode === "light" || savedMode === "dark") {
139
- setColorMode(savedMode);
140
- } else {
141
- const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
142
- setColorMode(prefersDark ? "dark" : "light");
143
- }
144
- }, []);
145
- import_react.useEffect(() => {
146
- localStorage.setItem("principlemd-color-mode", colorMode);
147
- }, [colorMode]);
148
- const toggleColorMode = () => {
149
- setColorMode((prev) => prev === "light" ? "dark" : "light");
150
- };
151
- const themeWithMode = getThemeWithMode(customTheme, colorMode);
152
- const value = {
153
- theme: themeWithMode,
154
- colorMode,
155
- setColorMode,
156
- toggleColorMode
157
- };
158
- return /* @__PURE__ */ import_react.default.createElement(ThemeContextSingleton.Provider, {
159
- value
160
- }, children);
161
- };
162
- var withTheme = (Component) => {
163
- return (props) => {
164
- const { theme: theme2 } = useTheme();
165
- return /* @__PURE__ */ import_react.default.createElement(Component, {
166
- ...props,
167
- theme: theme2
168
- });
169
- };
170
- };
171
-
172
- // industryTheme/index.ts
173
- var theme = {
174
- space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
175
- fonts: {
176
- body: '"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
177
- heading: '"Crimson Text", "Georgia", "Times New Roman", serif',
178
- monospace: '"Fira Code", "SF Mono", Monaco, Inconsolata, monospace'
179
- },
180
- fontSizes: [12, 14, 16, 18, 20, 24, 32, 48, 64, 96],
181
- fontScale: 1,
182
- fontWeights: {
183
- body: 400,
184
- heading: 600,
185
- bold: 700,
186
- light: 300,
187
- medium: 500,
188
- semibold: 600
189
- },
190
- lineHeights: {
191
- body: 1.5,
192
- heading: 1.2,
193
- tight: 1.25,
194
- relaxed: 1.75
195
- },
196
- breakpoints: ["640px", "768px", "1024px", "1280px"],
197
- sizes: [16, 32, 64, 128, 256, 512, 768, 1024, 1536],
198
- radii: [0, 2, 4, 6, 8, 12, 16, 24],
199
- shadows: [
200
- "none",
201
- "0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)",
202
- "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
203
- "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
204
- "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
205
- "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
206
- ],
207
- zIndices: [0, 1, 10, 20, 30, 40, 50],
208
- colors: {
209
- text: "#f1e8dc",
210
- background: "#1a1f2e",
211
- primary: "#d4a574",
212
- secondary: "#e0b584",
213
- accent: "#c9b8a3",
214
- highlight: "rgba(212, 165, 116, 0.15)",
215
- muted: "#8b7968",
216
- success: "#5c8a72",
217
- warning: "#d4a574",
218
- error: "#a85751",
219
- info: "#d4a574",
220
- border: "rgba(212, 165, 116, 0.2)",
221
- backgroundSecondary: "#212738",
222
- backgroundTertiary: "#2d3446",
223
- backgroundLight: "rgba(212, 165, 116, 0.08)",
224
- backgroundHover: "rgba(212, 165, 116, 0.15)",
225
- surface: "#212738",
226
- textSecondary: "#c9b8a3",
227
- textTertiary: "#8b7968",
228
- textMuted: "#8b7968",
229
- modes: {
230
- dark: {
231
- text: "#f1e8dc",
232
- background: "#1a1f2e",
233
- primary: "#d4a574",
234
- secondary: "#e0b584",
235
- accent: "#c9b8a3",
236
- highlight: "rgba(212, 165, 116, 0.15)",
237
- muted: "#8b7968",
238
- success: "#5c8a72",
239
- warning: "#d4a574",
240
- error: "#a85751",
241
- info: "#d4a574",
242
- border: "rgba(212, 165, 116, 0.2)",
243
- backgroundSecondary: "#212738",
244
- backgroundTertiary: "#2d3446",
245
- backgroundLight: "rgba(212, 165, 116, 0.08)",
246
- backgroundHover: "rgba(212, 165, 116, 0.15)",
247
- surface: "#212738",
248
- textSecondary: "#c9b8a3",
249
- textTertiary: "#8b7968",
250
- textMuted: "#8b7968"
251
- }
252
- }
253
- },
254
- buttons: {
255
- primary: {
256
- color: "background",
257
- bg: "primary",
258
- "&:hover": {
259
- bg: "secondary"
260
- }
261
- },
262
- secondary: {
263
- color: "text",
264
- bg: "muted",
265
- "&:hover": {
266
- bg: "backgroundSecondary"
267
- }
268
- },
269
- ghost: {
270
- color: "primary",
271
- bg: "transparent",
272
- "&:hover": {
273
- bg: "muted"
274
- }
275
- }
276
- },
277
- text: {
278
- heading: {
279
- fontFamily: "heading",
280
- fontWeight: "heading",
281
- lineHeight: "heading"
282
- },
283
- body: {
284
- fontFamily: "body",
285
- fontWeight: "body",
286
- lineHeight: "body"
287
- },
288
- caption: {
289
- fontSize: 1,
290
- color: "textSecondary"
291
- }
292
- },
293
- cards: {
294
- primary: {
295
- bg: "background",
296
- border: "1px solid",
297
- borderColor: "border",
298
- borderRadius: 2
299
- },
300
- secondary: {
301
- bg: "backgroundSecondary",
302
- border: "1px solid",
303
- borderColor: "border",
304
- borderRadius: 2
305
- }
306
- }
307
- };
308
- function scaleThemeFonts(theme2, scale) {
309
- const currentScale = theme2.fontScale || 1;
310
- const effectiveScale = scale / currentScale;
311
- return {
312
- ...theme2,
313
- fontSizes: theme2.fontSizes.map((size) => Math.round(size * effectiveScale)),
314
- fontScale: scale
315
- };
316
- }
317
- function increaseFontScale(theme2) {
318
- const currentScale = theme2.fontScale || 1;
319
- const newScale = Math.min(currentScale * 1.1, 2);
320
- return scaleThemeFonts(theme2, newScale);
321
- }
322
- function decreaseFontScale(theme2) {
323
- const currentScale = theme2.fontScale || 1;
324
- const newScale = Math.max(currentScale * 0.9, 0.5);
325
- return scaleThemeFonts(theme2, newScale);
326
- }
327
- function resetFontScale(theme2) {
328
- return scaleThemeFonts(theme2, 1);
329
- }
330
-
331
- // industryMarkdown/utils/markdownUtils.ts
332
- function hashMarkdownString(str) {
333
- let hash = 0;
334
- for (let i = 0;i < str.length; i++) {
335
- const char = str.charCodeAt(i);
336
- hash = (hash << 5) - hash + char;
337
- hash = hash & hash;
338
- }
339
- return Math.abs(hash).toString(36);
340
- }
341
- function parseMarkdownChunks(markdownContent, idPrefix) {
342
- try {
343
- if (typeof markdownContent !== "string") {
344
- throw new Error("Invalid markdown content provided for slide");
345
- }
346
- if (!markdownContent || markdownContent.trim() === "") {
347
- return [];
348
- }
349
- const chunks = [];
350
- const mermaidRegex = /^```mermaid\n([\s\S]*?)\n^```$/gm;
351
- let lastIndex = 0;
352
- let match;
353
- let partCounter = 0;
354
- while ((match = mermaidRegex.exec(markdownContent)) !== null) {
355
- partCounter++;
356
- if (match.index > lastIndex) {
357
- const mdContent = markdownContent.substring(lastIndex, match.index);
358
- if (mdContent.trim()) {
359
- chunks.push({
360
- type: "markdown_chunk",
361
- content: mdContent,
362
- id: `${idPrefix}-md-${partCounter}-${hashMarkdownString(mdContent)}`
363
- });
364
- }
365
- }
366
- partCounter++;
367
- const mermaidCode = match[1].trim();
368
- chunks.push({
369
- type: "mermaid_chunk",
370
- code: mermaidCode,
371
- id: `${idPrefix}-mermaid-${partCounter}-${hashMarkdownString(mermaidCode)}`
372
- });
373
- lastIndex = match.index + match[0].length;
374
- }
375
- if (lastIndex < markdownContent.length) {
376
- partCounter++;
377
- const remainingMdContent = markdownContent.substring(lastIndex);
378
- if (remainingMdContent.trim()) {
379
- chunks.push({
380
- type: "markdown_chunk",
381
- content: remainingMdContent,
382
- id: `${idPrefix}-md-${partCounter}-${hashMarkdownString(remainingMdContent)}`
383
- });
384
- }
385
- }
386
- if (chunks.length === 0 && markdownContent.trim()) {
387
- chunks.push({
388
- type: "markdown_chunk",
389
- content: markdownContent,
390
- id: `${idPrefix}-md-only-${hashMarkdownString(markdownContent)}`
391
- });
392
- }
393
- return chunks;
394
- } catch (error) {
395
- console.error("Error in parseMarkdownChunks:", error);
396
- return markdownContent ? [
397
- {
398
- type: "markdown_chunk",
399
- content: markdownContent,
400
- id: `${idPrefix}-md-error-fallback-${hashMarkdownString(markdownContent)}`
401
- }
402
- ] : [];
403
- }
404
- }
405
-
406
- // industryMarkdown/components/IndustryHtmlModal.tsx
407
- var import_react2 = __toESM(require("react"));
408
- var useIndustryHtmlModal = () => {
409
- const [htmlModalOpen, setHtmlModalOpen] = import_react2.useState(false);
410
- const [htmlModalContent, setHtmlModalContent] = import_react2.useState("");
411
- const openHtmlModal = (content) => {
412
- setHtmlModalContent(content);
413
- setHtmlModalOpen(true);
414
- };
415
- const closeHtmlModal = () => {
416
- setHtmlModalOpen(false);
417
- };
418
- return { htmlModalOpen, htmlModalContent, openHtmlModal, closeHtmlModal };
419
- };
420
- function IndustryHtmlModal({ isOpen, onClose, htmlContent, theme: theme2 }) {
421
- if (!isOpen)
422
- return null;
423
- const overlayStyle = {
424
- position: "fixed",
425
- top: 0,
426
- left: 0,
427
- right: 0,
428
- bottom: 0,
429
- backgroundColor: "rgba(0, 0, 0, 0.8)",
430
- display: "flex",
431
- alignItems: "center",
432
- justifyContent: "center",
433
- zIndex: 50,
434
- padding: theme2.space[6]
435
- };
436
- const modalStyle = {
437
- backgroundColor: theme2.colors.background,
438
- borderRadius: theme2.radii[3],
439
- maxWidth: "900px",
440
- maxHeight: "90vh",
441
- overflow: "hidden",
442
- display: "flex",
443
- flexDirection: "column",
444
- border: `1px solid ${theme2.colors.border}`,
445
- boxShadow: theme2.shadows[4]
446
- };
447
- const headerStyle = {
448
- padding: theme2.space[4],
449
- borderBottom: `1px solid ${theme2.colors.border}`,
450
- display: "flex",
451
- justifyContent: "space-between",
452
- alignItems: "center",
453
- backgroundColor: theme2.colors.backgroundSecondary
454
- };
455
- const contentStyle = {
456
- padding: theme2.space[5],
457
- overflow: "auto",
458
- flex: 1,
459
- backgroundColor: theme2.colors.background,
460
- color: theme2.colors.text
461
- };
462
- const titleStyle = {
463
- margin: 0,
464
- color: theme2.colors.text,
465
- fontSize: theme2.fontSizes[3],
466
- fontWeight: theme2.fontWeights.semibold,
467
- fontFamily: theme2.fonts.heading
468
- };
469
- const closeButtonStyle = {
470
- background: "transparent",
471
- border: "none",
472
- fontSize: theme2.fontSizes[5],
473
- cursor: "pointer",
474
- color: theme2.colors.textSecondary,
475
- padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
476
- borderRadius: theme2.radii[1],
477
- transition: "all 0.2s ease",
478
- display: "flex",
479
- alignItems: "center",
480
- justifyContent: "center",
481
- width: "32px",
482
- height: "32px"
483
- };
484
- const handleCloseButtonHover = (e) => {
485
- e.currentTarget.style.backgroundColor = theme2.colors.backgroundTertiary;
486
- e.currentTarget.style.color = theme2.colors.text;
487
- };
488
- const handleCloseButtonLeave = (e) => {
489
- e.currentTarget.style.backgroundColor = "transparent";
490
- e.currentTarget.style.color = theme2.colors.textSecondary;
491
- };
492
- return /* @__PURE__ */ import_react2.default.createElement("div", {
493
- style: overlayStyle,
494
- onClick: onClose
495
- }, /* @__PURE__ */ import_react2.default.createElement("div", {
496
- style: modalStyle,
497
- onClick: (e) => e.stopPropagation()
498
- }, /* @__PURE__ */ import_react2.default.createElement("div", {
499
- style: headerStyle
500
- }, /* @__PURE__ */ import_react2.default.createElement("h3", {
501
- style: titleStyle
502
- }, "HTML Preview"), /* @__PURE__ */ import_react2.default.createElement("button", {
503
- onClick: (e) => {
504
- e.stopPropagation();
505
- onClose();
506
- },
507
- style: closeButtonStyle,
508
- onMouseEnter: handleCloseButtonHover,
509
- onMouseLeave: handleCloseButtonLeave,
510
- title: "Close",
511
- "aria-label": "Close modal"
512
- }, "×")), /* @__PURE__ */ import_react2.default.createElement("div", {
513
- style: contentStyle
514
- }, /* @__PURE__ */ import_react2.default.createElement("div", {
515
- dangerouslySetInnerHTML: { __html: htmlContent }
516
- }))));
517
- }
518
-
519
- // industryMarkdown/components/IndustryLazyMermaidDiagram.tsx
520
- var import_lucide_react2 = require("lucide-react");
521
- var import_react4 = __toESM(require("react"));
522
-
523
- // industryMarkdown/components/IndustryMermaidDiagram.tsx
524
- var import_lucide_react = require("lucide-react");
525
- var import_react3 = __toESM(require("react"));
526
- var getMermaidSync = () => {
527
- if (typeof window !== "undefined") {
528
- const mermaid = window.mermaid;
529
- if (mermaid) {
530
- return mermaid;
531
- }
532
- }
533
- return null;
534
- };
535
- function IndustryMermaidDiagram({
536
- code,
537
- id,
538
- theme: themeOverride,
539
- onCopyError,
540
- onError,
541
- rootMargin = "200px",
542
- isModalMode = false
543
- }) {
544
- const theme2 = themeOverride || theme;
545
- const [errorDetails, setErrorDetails] = import_react3.useState(null);
546
- const [isIntersecting, setIsIntersecting] = import_react3.useState(false);
547
- const [hasRendered, setHasRendered] = import_react3.useState(false);
548
- const [containerElement, setContainerElement] = import_react3.useState(null);
549
- const [zoomLevel, setZoomLevel] = import_react3.useState(1);
550
- const observerRef = import_react3.useRef(null);
551
- const containerRef = import_react3.default.useCallback((node) => {
552
- setContainerElement(node);
553
- if (observerRef.current) {
554
- observerRef.current.disconnect();
555
- observerRef.current = null;
556
- }
557
- if (node && !hasRendered) {
558
- if (isModalMode || typeof IntersectionObserver === "undefined") {
559
- setIsIntersecting(true);
560
- setHasRendered(true);
561
- return;
562
- }
563
- observerRef.current = new IntersectionObserver(([entry]) => {
564
- setIsIntersecting(entry.isIntersecting);
565
- if (entry.isIntersecting && !hasRendered) {
566
- setHasRendered(true);
567
- }
568
- }, {
569
- rootMargin,
570
- threshold: 0.01
571
- });
572
- observerRef.current.observe(node);
573
- }
574
- }, [rootMargin, hasRendered, isModalMode]);
575
- import_react3.useEffect(() => {
576
- return () => {
577
- if (observerRef.current) {
578
- observerRef.current.disconnect();
579
- }
580
- };
581
- }, []);
582
- import_react3.useEffect(() => {
583
- if (!hasRendered)
584
- return;
585
- const renderDiagram = async () => {
586
- const mermaid = getMermaidSync();
587
- if (!mermaid || !containerElement)
588
- return;
589
- try {
590
- const diagramBackground = theme2.colors.backgroundSecondary || theme2.colors.muted || theme2.colors.background;
591
- const nodeBackground = theme2.colors.backgroundTertiary || theme2.colors.backgroundSecondary || theme2.colors.primary + "22";
592
- mermaid.initialize({
593
- startOnLoad: false,
594
- theme: "base",
595
- themeVariables: {
596
- primaryColor: nodeBackground,
597
- primaryTextColor: theme2.colors.text,
598
- primaryBorderColor: theme2.colors.border,
599
- lineColor: theme2.colors.border,
600
- secondaryColor: theme2.colors.secondary + "44",
601
- tertiaryColor: theme2.colors.accent + "44",
602
- background: diagramBackground,
603
- mainBkg: nodeBackground,
604
- secondBkg: theme2.colors.backgroundSecondary || theme2.colors.muted,
605
- tertiaryBkg: theme2.colors.backgroundTertiary || theme2.colors.accent + "22",
606
- secondaryBorderColor: theme2.colors.border,
607
- tertiaryBorderColor: theme2.colors.accent,
608
- textColor: theme2.colors.text,
609
- labelTextColor: theme2.colors.text,
610
- altBackground: theme2.colors.muted,
611
- errorBkgColor: theme2.colors.error + "33",
612
- errorTextColor: theme2.colors.error
613
- },
614
- securityLevel: "loose",
615
- logLevel: "error"
616
- });
617
- containerElement.innerHTML = "";
618
- const elementId = `mermaid-${id}-${Date.now()}`;
619
- const graphDiv = document.createElement("div");
620
- graphDiv.id = elementId;
621
- graphDiv.textContent = code;
622
- containerElement.appendChild(graphDiv);
623
- await mermaid.run({
624
- nodes: [graphDiv]
625
- });
626
- const svgElement = graphDiv.querySelector("svg");
627
- if (svgElement) {
628
- svgElement.style.maxWidth = "none";
629
- svgElement.style.maxHeight = "none";
630
- svgElement.style.width = "auto";
631
- svgElement.style.height = "auto";
632
- svgElement.style.display = "block";
633
- svgElement.style.margin = "0 auto";
634
- if (isModalMode) {
635
- svgElement.style.width = "auto";
636
- svgElement.style.height = "auto";
637
- const viewBox = svgElement.getAttribute("viewBox");
638
- if (viewBox) {
639
- const [, , width, height] = viewBox.split(" ").map(Number);
640
- if (width && height) {
641
- svgElement.setAttribute("width", width.toString());
642
- svgElement.setAttribute("height", height.toString());
643
- }
644
- }
645
- } else {
646
- svgElement.style.maxHeight = "360px";
647
- svgElement.style.width = "auto";
648
- svgElement.style.maxWidth = "none";
649
- }
650
- } else {
651
- console.warn("No SVG element found after mermaid render");
652
- }
653
- setErrorDetails(null);
654
- if (onError)
655
- onError(false);
656
- } catch (err) {
657
- console.error("Mermaid rendering error:", err);
658
- const errorMessage = err instanceof Error ? err.message : "Failed to render diagram";
659
- setErrorDetails({ code, message: errorMessage });
660
- if (onError)
661
- onError(true);
662
- if (containerElement) {
663
- containerElement.innerHTML = `
664
- <div style="
665
- padding: ${theme2.space[4]}px;
666
- background: ${theme2.colors.error}22;
667
- border: 1px solid ${theme2.colors.error};
668
- border-radius: ${theme2.radii[2]}px;
669
- color: ${theme2.colors.text};
670
- font-family: ${theme2.fonts.monospace};
671
- font-size: ${theme2.fontSizes[1]}px;
672
- ">
673
- <div style="font-weight: ${theme2.fontWeights.bold}; margin-bottom: ${theme2.space[2]}px;">
674
- Failed to render Mermaid diagram
675
- </div>
676
- <div style="font-size: ${theme2.fontSizes[0]}px; opacity: 0.8;">
677
- ${errorMessage}
678
- </div>
679
- </div>
680
- `;
681
- }
682
- }
683
- };
684
- renderDiagram();
685
- }, [hasRendered, code, id, theme2, containerElement, onError, isModalMode]);
686
- import_react3.useEffect(() => {
687
- if (!containerElement || !hasRendered)
688
- return;
689
- const svgElement = containerElement.querySelector("svg");
690
- if (svgElement) {
691
- if (zoomLevel !== 1) {
692
- svgElement.style.transform = `scale(${zoomLevel})`;
693
- svgElement.style.transformOrigin = "top center";
694
- const containerRect = containerElement.getBoundingClientRect();
695
- const svgRect = svgElement.getBoundingClientRect();
696
- if (svgRect.width < containerRect.width) {
697
- svgElement.style.margin = "0 auto";
698
- }
699
- } else {
700
- svgElement.style.transform = "";
701
- svgElement.style.transformOrigin = "";
702
- svgElement.style.margin = "0 auto";
703
- if (!isModalMode) {
704
- svgElement.style.maxHeight = "360px";
705
- svgElement.style.width = "auto";
706
- svgElement.style.maxWidth = "none";
707
- }
708
- }
709
- }
710
- }, [zoomLevel, containerElement, hasRendered, isModalMode]);
711
- import_react3.useEffect(() => {
712
- if (errorDetails && onCopyError) {
713
- const handleKeyDown = (e) => {
714
- if ((e.ctrlKey || e.metaKey) && e.key === "c" && window.getSelection()?.toString()) {
715
- onCopyError(errorDetails.code, errorDetails.message);
716
- }
717
- };
718
- if (containerElement) {
719
- containerElement.addEventListener("keydown", handleKeyDown);
720
- return () => {
721
- containerElement.removeEventListener("keydown", handleKeyDown);
722
- };
723
- }
724
- }
725
- return;
726
- }, [errorDetails, onCopyError, containerElement]);
727
- const containerStyle = isModalMode ? {
728
- position: "relative",
729
- width: "fit-content",
730
- height: "fit-content",
731
- display: "block",
732
- backgroundColor: "transparent",
733
- border: "none",
734
- borderRadius: 0,
735
- padding: 0,
736
- margin: 0,
737
- overflow: "visible"
738
- } : {
739
- position: "relative",
740
- width: "100%",
741
- minHeight: "200px",
742
- maxHeight: "400px",
743
- display: "block",
744
- backgroundColor: hasRendered ? "transparent" : theme2.colors.backgroundSecondary,
745
- border: hasRendered ? `1px solid ${theme2.colors.border}` : `1px solid ${theme2.colors.border}`,
746
- borderRadius: theme2.radii[2],
747
- padding: hasRendered ? theme2.space[3] : theme2.space[4],
748
- margin: `${theme2.space[4]}px 0`,
749
- overflowX: hasRendered ? "auto" : "visible",
750
- overflowY: hasRendered ? "auto" : "visible"
751
- };
752
- const placeholderStyle = {
753
- textAlign: "center",
754
- color: theme2.colors.textSecondary,
755
- fontSize: theme2.fontSizes[2],
756
- fontFamily: theme2.fonts.body
757
- };
758
- return isModalMode ? /* @__PURE__ */ import_react3.default.createElement("div", {
759
- ref: containerRef,
760
- style: containerStyle,
761
- className: "mermaid-container"
762
- }, !hasRendered && /* @__PURE__ */ import_react3.default.createElement("div", {
763
- style: placeholderStyle
764
- }, /* @__PURE__ */ import_react3.default.createElement("div", null, "\uD83D\uDCCA Mermaid Diagram"), /* @__PURE__ */ import_react3.default.createElement("div", {
765
- style: { fontSize: theme2.fontSizes[1], marginTop: theme2.space[2], opacity: 0.7 }
766
- }, "Loading..."))) : /* @__PURE__ */ import_react3.default.createElement("div", {
767
- style: { position: "relative" }
768
- }, hasRendered && /* @__PURE__ */ import_react3.default.createElement("div", {
769
- style: {
770
- position: "absolute",
771
- top: theme2.space[2],
772
- right: theme2.space[2],
773
- zIndex: 10,
774
- display: "flex",
775
- gap: theme2.space[1]
776
- }
777
- }, /* @__PURE__ */ import_react3.default.createElement("button", {
778
- onClick: () => setZoomLevel(Math.min(3, zoomLevel + 0.25)),
779
- disabled: zoomLevel >= 3,
780
- style: {
781
- padding: theme2.space[1],
782
- backgroundColor: theme2.colors.backgroundSecondary,
783
- border: `1px solid ${theme2.colors.border}`,
784
- borderRadius: theme2.radii[1],
785
- color: theme2.colors.text,
786
- cursor: zoomLevel >= 3 ? "not-allowed" : "pointer",
787
- display: "flex",
788
- alignItems: "center",
789
- justifyContent: "center",
790
- width: "28px",
791
- height: "28px",
792
- opacity: zoomLevel >= 3 ? 0.5 : 1
793
- },
794
- title: "Zoom In"
795
- }, /* @__PURE__ */ import_react3.default.createElement(import_lucide_react.ZoomIn, {
796
- size: 14
797
- })), /* @__PURE__ */ import_react3.default.createElement("button", {
798
- onClick: () => setZoomLevel(Math.max(0.5, zoomLevel - 0.25)),
799
- disabled: zoomLevel <= 0.5,
800
- style: {
801
- padding: theme2.space[1],
802
- backgroundColor: theme2.colors.backgroundSecondary,
803
- border: `1px solid ${theme2.colors.border}`,
804
- borderRadius: theme2.radii[1],
805
- color: theme2.colors.text,
806
- cursor: zoomLevel <= 0.5 ? "not-allowed" : "pointer",
807
- display: "flex",
808
- alignItems: "center",
809
- justifyContent: "center",
810
- width: "28px",
811
- height: "28px",
812
- opacity: zoomLevel <= 0.5 ? 0.5 : 1
813
- },
814
- title: "Zoom Out"
815
- }, /* @__PURE__ */ import_react3.default.createElement(import_lucide_react.ZoomOut, {
816
- size: 14
817
- })), /* @__PURE__ */ import_react3.default.createElement("button", {
818
- onClick: () => setZoomLevel(1),
819
- disabled: zoomLevel === 1,
820
- style: {
821
- padding: theme2.space[1],
822
- backgroundColor: theme2.colors.backgroundSecondary,
823
- border: `1px solid ${theme2.colors.border}`,
824
- borderRadius: theme2.radii[1],
825
- color: theme2.colors.text,
826
- cursor: zoomLevel === 1 ? "not-allowed" : "pointer",
827
- display: "flex",
828
- alignItems: "center",
829
- justifyContent: "center",
830
- width: "28px",
831
- height: "28px",
832
- opacity: zoomLevel === 1 ? 0.5 : 1
833
- },
834
- title: "Reset Zoom"
835
- }, /* @__PURE__ */ import_react3.default.createElement(import_lucide_react.RotateCcw, {
836
- size: 14
837
- }))), /* @__PURE__ */ import_react3.default.createElement("div", {
838
- ref: containerRef,
839
- style: containerStyle,
840
- className: "mermaid-container"
841
- }, !hasRendered && /* @__PURE__ */ import_react3.default.createElement("div", {
842
- style: placeholderStyle
843
- }, /* @__PURE__ */ import_react3.default.createElement("div", null, "\uD83D\uDCCA Mermaid Diagram"), /* @__PURE__ */ import_react3.default.createElement("div", {
844
- style: { fontSize: theme2.fontSizes[1], marginTop: theme2.space[2], opacity: 0.7 }
845
- }, isIntersecting ? "Loading..." : "Scroll to view"))));
846
- }
847
-
848
- // industryMarkdown/components/IndustryLazyMermaidDiagram.tsx
849
- function IndustryLazyMermaidDiagram({
850
- code,
851
- id,
852
- onCopyError,
853
- rootMargin = "200px",
854
- onShowInPanel,
855
- theme: theme2 = theme
856
- }) {
857
- const [isIntersecting, setIsIntersecting] = import_react4.useState(false);
858
- const [hasRendered, setHasRendered] = import_react4.useState(false);
859
- const [isMounted, setIsMounted] = import_react4.useState(false);
860
- const [hasError, setHasError] = import_react4.useState(false);
861
- const containerRef = import_react4.useRef(null);
862
- import_react4.useEffect(() => {
863
- setIsMounted(true);
864
- }, []);
865
- import_react4.useEffect(() => {
866
- if (!isMounted)
867
- return;
868
- if (typeof IntersectionObserver === "undefined") {
869
- setIsIntersecting(true);
870
- setHasRendered(true);
871
- return;
872
- }
873
- const observer = new IntersectionObserver(([entry]) => {
874
- setIsIntersecting(entry.isIntersecting);
875
- if (entry.isIntersecting && !hasRendered) {
876
- setHasRendered(true);
877
- }
878
- }, {
879
- rootMargin,
880
- threshold: 0.01
881
- });
882
- const currentElement = containerRef.current;
883
- if (currentElement && observer) {
884
- observer.observe(currentElement);
885
- }
886
- return () => {
887
- if (currentElement && observer) {
888
- observer.unobserve(currentElement);
889
- }
890
- };
891
- }, [rootMargin, hasRendered, isMounted]);
892
- const getPlaceholderStyle = () => {
893
- return {
894
- position: "relative",
895
- margin: `${theme2.space[4]}px 0`,
896
- padding: theme2.space[5],
897
- border: `1px solid ${theme2.colors.border}`,
898
- borderRadius: theme2.radii[2],
899
- backgroundColor: theme2.colors.backgroundSecondary,
900
- minHeight: "200px",
901
- display: "flex",
902
- justifyContent: "center",
903
- alignItems: "center"
904
- };
905
- };
906
- const getTextStyle = () => {
907
- return {
908
- textAlign: "center",
909
- fontSize: theme2.fontSizes[2],
910
- color: theme2.colors.textSecondary,
911
- fontFamily: theme2.fonts.monospace
912
- };
913
- };
914
- const getSecondaryTextStyle = () => {
915
- return {
916
- fontSize: theme2.fontSizes[1],
917
- marginTop: theme2.space[2],
918
- color: theme2.colors.textTertiary
919
- };
920
- };
921
- if (!isMounted) {
922
- return /* @__PURE__ */ import_react4.default.createElement("div", {
923
- style: getPlaceholderStyle()
924
- }, /* @__PURE__ */ import_react4.default.createElement("div", {
925
- style: getTextStyle()
926
- }, /* @__PURE__ */ import_react4.default.createElement("div", null, "\uD83D\uDCCA Mermaid Diagram"), /* @__PURE__ */ import_react4.default.createElement("div", {
927
- style: getSecondaryTextStyle()
928
- }, "Loading...")));
929
- }
930
- return /* @__PURE__ */ import_react4.default.createElement("div", {
931
- ref: containerRef,
932
- style: { position: "relative" }
933
- }, hasRendered && onShowInPanel && !hasError && /* @__PURE__ */ import_react4.default.createElement("button", {
934
- onClick: (e) => {
935
- e.stopPropagation();
936
- const titleMatch = code.match(/^(?:%%\s*(.+)|(\w+)\s)/m);
937
- const title = titleMatch?.[1] || titleMatch?.[2] || "Diagram from Markdown";
938
- onShowInPanel(code, title);
939
- },
940
- style: {
941
- position: "absolute",
942
- top: theme2.space[2],
943
- right: theme2.space[2],
944
- padding: `${theme2.space[2]}px ${theme2.space[3]}px`,
945
- backgroundColor: theme2.colors.background,
946
- color: theme2.colors.text,
947
- border: `1px solid ${theme2.colors.border}`,
948
- borderRadius: theme2.radii[1],
949
- fontSize: theme2.fontSizes[1],
950
- fontWeight: theme2.fontWeights.medium,
951
- cursor: "pointer",
952
- zIndex: 10,
953
- fontFamily: theme2.fonts.body,
954
- transition: "all 0.2s ease",
955
- display: "flex",
956
- alignItems: "center",
957
- gap: theme2.space[1]
958
- },
959
- onMouseEnter: (e) => {
960
- e.currentTarget.style.backgroundColor = theme2.colors.backgroundSecondary;
961
- },
962
- onMouseLeave: (e) => {
963
- e.currentTarget.style.backgroundColor = theme2.colors.background;
964
- },
965
- title: "Show in diagram panel"
966
- }, /* @__PURE__ */ import_react4.default.createElement(import_lucide_react2.MoveRight, {
967
- size: 14
968
- })), hasRendered ? /* @__PURE__ */ import_react4.default.createElement(IndustryMermaidDiagram, {
969
- code,
970
- id,
971
- onCopyError,
972
- onError: setHasError,
973
- theme: theme2
974
- }) : /* @__PURE__ */ import_react4.default.createElement("div", {
975
- style: getPlaceholderStyle()
976
- }, /* @__PURE__ */ import_react4.default.createElement("div", {
977
- style: getTextStyle()
978
- }, /* @__PURE__ */ import_react4.default.createElement("div", null, "\uD83D\uDCCA Mermaid Diagram"), /* @__PURE__ */ import_react4.default.createElement("div", {
979
- style: getSecondaryTextStyle()
980
- }, isIntersecting ? "Loading..." : "Scroll to view"))));
981
- }
982
-
983
- // industryMarkdown/components/IndustryMarkdownComponents.tsx
984
- var import_lucide_react4 = require("lucide-react");
985
- var import_react7 = __toESM(require("react"));
986
-
987
- // industryMarkdown/utils/bashCommandParser.ts
988
- function parseBashCommands(codeString) {
989
- const lines = codeString.split(`
990
- `);
991
- const commands = [];
992
- let currentCommand = "";
993
- let commandStartLine = 0;
994
- let currentDescription = "";
995
- for (let i = 0;i < lines.length; i++) {
996
- const line = lines[i].trim();
997
- if (!line) {
998
- if (currentCommand) {
999
- commands.push({
1000
- command: currentCommand.trim(),
1001
- description: currentDescription || undefined,
1002
- line: commandStartLine + 1
1003
- });
1004
- currentCommand = "";
1005
- currentDescription = "";
1006
- }
1007
- continue;
1008
- }
1009
- if (line.startsWith("#")) {
1010
- if (!currentCommand) {
1011
- currentDescription = line.substring(1).trim();
1012
- }
1013
- continue;
1014
- }
1015
- if (line.endsWith("\\")) {
1016
- if (!currentCommand) {
1017
- commandStartLine = i;
1018
- }
1019
- currentCommand += line.slice(0, -1) + " ";
1020
- continue;
1021
- }
1022
- const isPipeContinuation = line.startsWith("|") || line.startsWith("&&") || line.startsWith("||");
1023
- const previousLineEndsWithOperator = currentCommand && (currentCommand.trim().endsWith("|") || currentCommand.trim().endsWith("&&") || currentCommand.trim().endsWith("||") || currentCommand.trim().endsWith(";"));
1024
- if (currentCommand && (isPipeContinuation || previousLineEndsWithOperator)) {
1025
- currentCommand += (currentCommand.endsWith(" ") ? "" : " ") + line;
1026
- continue;
1027
- }
1028
- if (currentCommand) {
1029
- commands.push({
1030
- command: currentCommand.trim(),
1031
- description: currentDescription || undefined,
1032
- line: commandStartLine + 1
1033
- });
1034
- currentDescription = "";
1035
- }
1036
- commandStartLine = i;
1037
- currentCommand = line;
1038
- }
1039
- if (currentCommand) {
1040
- commands.push({
1041
- command: currentCommand.trim(),
1042
- description: currentDescription || undefined,
1043
- line: commandStartLine + 1
1044
- });
1045
- }
1046
- return commands.filter((cmd) => cmd.command.length > 0);
1047
- }
1048
- function getCommandDisplayName(command, maxLength = 50) {
1049
- if (command.description) {
1050
- return command.description.length <= maxLength ? command.description : command.description.substring(0, maxLength - 3) + "...";
1051
- }
1052
- const cmdText = command.command;
1053
- if (cmdText.length <= maxLength) {
1054
- return cmdText;
1055
- }
1056
- return cmdText.substring(0, maxLength - 3) + "...";
1057
- }
1058
-
1059
- // industryMarkdown/utils/componentUtils.tsx
1060
- var import_react5 = __toESM(require("react"));
1061
- var extractTextFromChildren = (children) => {
1062
- if (typeof children === "string") {
1063
- return children;
1064
- }
1065
- if (Array.isArray(children)) {
1066
- return children.map(extractTextFromChildren).join("");
1067
- }
1068
- if (import_react5.default.isValidElement(children)) {
1069
- const props = children.props;
1070
- if (props.children) {
1071
- return extractTextFromChildren(props.children);
1072
- }
1073
- }
1074
- return "";
1075
- };
1076
- var LinkWithLoadingIndicator = ({ href, children, onClick, className }) => {
1077
- const handleClick = (e) => {
1078
- if (onClick) {
1079
- e.preventDefault();
1080
- onClick(href, e);
1081
- }
1082
- };
1083
- return /* @__PURE__ */ import_react5.default.createElement("a", {
1084
- href,
1085
- onClick: handleClick,
1086
- className,
1087
- target: "_blank",
1088
- rel: "noopener noreferrer"
1089
- }, children);
1090
- };
1091
-
1092
- // industryMarkdown/utils/imageUrlUtils.ts
1093
- function isRelativeUrl(url) {
1094
- if (url.startsWith("http://") || url.startsWith("https://")) {
1095
- return false;
1096
- }
1097
- if (url.startsWith("//")) {
1098
- return false;
1099
- }
1100
- if (url.startsWith("data:")) {
1101
- return false;
1102
- }
1103
- if (url.startsWith("blob:")) {
1104
- return false;
1105
- }
1106
- return true;
1107
- }
1108
- function transformImageUrl(src, repositoryInfo) {
1109
- if (!repositoryInfo || !isRelativeUrl(src)) {
1110
- return src;
1111
- }
1112
- const { owner, repo, branch = "main", basePath = "" } = repositoryInfo;
1113
- let fullPath;
1114
- if (src.startsWith("/")) {
1115
- fullPath = src.substring(1);
1116
- } else {
1117
- let cleanPath = src;
1118
- if (cleanPath.startsWith("./")) {
1119
- cleanPath = cleanPath.substring(2);
1120
- }
1121
- if (cleanPath.startsWith("../")) {
1122
- console.warn("Relative parent directory navigation in image URLs is not fully supported:", src);
1123
- cleanPath = cleanPath.replace(/^(\.\.\/)+/, "");
1124
- }
1125
- if (basePath) {
1126
- const cleanBasePath = basePath.replace(/^\/+|\/+$/g, "");
1127
- fullPath = `${cleanBasePath}/${cleanPath}`;
1128
- } else {
1129
- fullPath = cleanPath;
1130
- }
1131
- }
1132
- const rawUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${fullPath}`;
1133
- return rawUrl;
1134
- }
1135
-
1136
- // industryMarkdown/components/IndustryBashCommandDropdown.tsx
1137
- var import_lucide_react3 = require("lucide-react");
1138
- var import_react6 = __toESM(require("react"));
1139
- var IndustryBashCommandDropdown = ({
1140
- commands,
1141
- allCommands,
1142
- onRunCommand,
1143
- darkMode: _darkMode,
1144
- slideIdPrefix: _slideIdPrefix,
1145
- theme: themeOverride
1146
- }) => {
1147
- const [isOpen, setIsOpen] = import_react6.useState(false);
1148
- const [isRunning, setIsRunning] = import_react6.useState(false);
1149
- const dropdownRef = import_react6.useRef(null);
1150
- const { theme: contextTheme } = useTheme();
1151
- const theme2 = themeOverride || contextTheme;
1152
- import_react6.useEffect(() => {
1153
- const handleClickOutside = (event) => {
1154
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1155
- setIsOpen(false);
1156
- }
1157
- };
1158
- document.addEventListener("mousedown", handleClickOutside);
1159
- return () => {
1160
- document.removeEventListener("mousedown", handleClickOutside);
1161
- };
1162
- }, []);
1163
- const handleRunCommand = async (command) => {
1164
- setIsRunning(true);
1165
- setIsOpen(false);
1166
- try {
1167
- await onRunCommand(command);
1168
- } finally {
1169
- setIsRunning(false);
1170
- }
1171
- };
1172
- const buttonStyle = {
1173
- padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
1174
- backgroundColor: isRunning ? theme2.colors.muted : theme2.colors.primary,
1175
- color: theme2.colors.background,
1176
- border: "none",
1177
- borderRadius: theme2.radii[1],
1178
- fontSize: theme2.fontSizes[1],
1179
- cursor: isRunning ? "not-allowed" : "pointer",
1180
- display: "flex",
1181
- alignItems: "center",
1182
- gap: theme2.space[2],
1183
- opacity: isRunning ? 0.6 : 1,
1184
- minWidth: "70px",
1185
- justifyContent: "center",
1186
- fontFamily: theme2.fonts.body,
1187
- fontWeight: theme2.fontWeights.medium,
1188
- transition: "all 0.2s ease"
1189
- };
1190
- const dropdownStyle = {
1191
- position: "absolute",
1192
- top: "100%",
1193
- right: "0",
1194
- backgroundColor: theme2.colors.background,
1195
- border: `1px solid ${theme2.colors.border}`,
1196
- borderRadius: theme2.radii[2],
1197
- boxShadow: theme2.shadows[2],
1198
- zIndex: 10,
1199
- minWidth: "200px",
1200
- maxWidth: "350px",
1201
- maxHeight: "300px",
1202
- overflow: "auto",
1203
- marginTop: theme2.space[1]
1204
- };
1205
- const dropdownItemStyle = (isHovered) => ({
1206
- padding: `${theme2.space[2]}px ${theme2.space[3]}px`,
1207
- cursor: "pointer",
1208
- backgroundColor: isHovered ? theme2.colors.backgroundSecondary : "transparent",
1209
- fontSize: theme2.fontSizes[1],
1210
- color: theme2.colors.text,
1211
- fontFamily: theme2.fonts.monospace,
1212
- whiteSpace: "pre-wrap",
1213
- wordBreak: "break-word",
1214
- transition: "background-color 0.2s ease"
1215
- });
1216
- const hasMultipleCommands = commands.length > 1;
1217
- const singleCommand = commands.length === 1 ? commands[0].command : allCommands;
1218
- return /* @__PURE__ */ import_react6.default.createElement("div", {
1219
- ref: dropdownRef,
1220
- style: { position: "relative", display: "inline-block" }
1221
- }, hasMultipleCommands ? /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement("button", {
1222
- onClick: () => setIsOpen(!isOpen),
1223
- disabled: isRunning,
1224
- style: buttonStyle,
1225
- onMouseEnter: (e) => {
1226
- if (!isRunning) {
1227
- e.currentTarget.style.backgroundColor = theme2.colors.secondary;
1228
- }
1229
- },
1230
- onMouseLeave: (e) => {
1231
- if (!isRunning) {
1232
- e.currentTarget.style.backgroundColor = theme2.colors.primary;
1233
- }
1234
- }
1235
- }, isRunning ? /* @__PURE__ */ import_react6.default.createElement("span", {
1236
- style: { fontSize: theme2.fontSizes[1] }
1237
- }, "...") : /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement(import_lucide_react3.Play, {
1238
- size: 14
1239
- }), "Run", /* @__PURE__ */ import_react6.default.createElement(import_lucide_react3.ChevronDown, {
1240
- size: 14
1241
- }))), isOpen && /* @__PURE__ */ import_react6.default.createElement("div", {
1242
- style: dropdownStyle
1243
- }, /* @__PURE__ */ import_react6.default.createElement("div", {
1244
- style: {
1245
- padding: `${theme2.space[2]}px ${theme2.space[3]}px`,
1246
- borderBottom: `1px solid ${theme2.colors.border}`,
1247
- fontWeight: theme2.fontWeights.semibold,
1248
- fontSize: theme2.fontSizes[1],
1249
- color: theme2.colors.textSecondary,
1250
- fontFamily: theme2.fonts.body
1251
- }
1252
- }, "Select command to run"), /* @__PURE__ */ import_react6.default.createElement("div", {
1253
- style: {
1254
- padding: `${theme2.space[2]}px ${theme2.space[3]}px`,
1255
- backgroundColor: theme2.colors.muted,
1256
- cursor: "pointer",
1257
- fontSize: theme2.fontSizes[1],
1258
- fontWeight: theme2.fontWeights.medium,
1259
- color: theme2.colors.text,
1260
- fontFamily: theme2.fonts.body,
1261
- transition: "background-color 0.2s ease"
1262
- },
1263
- onClick: () => handleRunCommand(allCommands),
1264
- onMouseEnter: (e) => {
1265
- e.currentTarget.style.backgroundColor = theme2.colors.backgroundSecondary;
1266
- },
1267
- onMouseLeave: (e) => {
1268
- e.currentTarget.style.backgroundColor = theme2.colors.muted;
1269
- }
1270
- }, "\uD83D\uDE80 Run all (", commands.length, " commands)"), commands.map((cmd, index) => {
1271
- const [isHovered, setIsHovered] = import_react6.useState(false);
1272
- return /* @__PURE__ */ import_react6.default.createElement("div", {
1273
- key: index,
1274
- style: dropdownItemStyle(isHovered),
1275
- onClick: () => handleRunCommand(cmd.command),
1276
- onMouseEnter: () => setIsHovered(true),
1277
- onMouseLeave: () => setIsHovered(false),
1278
- title: cmd.command
1279
- }, getCommandDisplayName(cmd));
1280
- }))) : /* @__PURE__ */ import_react6.default.createElement("button", {
1281
- onClick: () => handleRunCommand(singleCommand),
1282
- disabled: isRunning,
1283
- style: buttonStyle,
1284
- onMouseEnter: (e) => {
1285
- if (!isRunning) {
1286
- e.currentTarget.style.backgroundColor = theme2.colors.secondary;
1287
- }
1288
- },
1289
- onMouseLeave: (e) => {
1290
- if (!isRunning) {
1291
- e.currentTarget.style.backgroundColor = theme2.colors.primary;
1292
- }
1293
- }
1294
- }, isRunning ? /* @__PURE__ */ import_react6.default.createElement("span", {
1295
- style: { fontSize: theme2.fontSizes[1] }
1296
- }, "...") : /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement(import_lucide_react3.Play, {
1297
- size: 14
1298
- }), "Run")));
1299
- };
1300
-
1301
- // industryMarkdown/components/IndustryMarkdownComponents.tsx
1302
- var failedImageCache = new Set;
1303
- var OptimizedMarkdownImage = import_react7.default.memo(({
1304
- src,
1305
- alt,
1306
- repositoryInfo,
1307
- theme: theme2,
1308
- ...props
1309
- }) => {
1310
- const transformedSrc = import_react7.useMemo(() => {
1311
- return transformImageUrl(src, repositoryInfo);
1312
- }, [src, repositoryInfo]);
1313
- const [hasErrored, setHasErrored] = import_react7.useState(() => failedImageCache.has(transformedSrc));
1314
- const retryCount = import_react7.useRef(0);
1315
- const imageStyle = import_react7.useMemo(() => ({
1316
- maxWidth: "100%",
1317
- height: "auto",
1318
- display: "block",
1319
- margin: `${theme2.space[3]}px auto`,
1320
- borderRadius: theme2.radii[1],
1321
- boxShadow: theme2.shadows[2]
1322
- }), [theme2]);
1323
- const handleLoad = () => {
1324
- failedImageCache.delete(transformedSrc);
1325
- setHasErrored(false);
1326
- retryCount.current = 0;
1327
- };
1328
- const handleError = (e) => {
1329
- retryCount.current += 1;
1330
- failedImageCache.add(transformedSrc);
1331
- setHasErrored(true);
1332
- e.stopPropagation();
1333
- };
1334
- if (hasErrored) {
1335
- return /* @__PURE__ */ import_react7.default.createElement("span", {
1336
- style: {
1337
- ...imageStyle,
1338
- display: "inline-flex",
1339
- alignItems: "center",
1340
- justifyContent: "center",
1341
- backgroundColor: theme2.colors.backgroundSecondary,
1342
- color: theme2.colors.textSecondary,
1343
- border: `1px solid ${theme2.colors.border}`,
1344
- minHeight: "50px",
1345
- minWidth: "100px",
1346
- fontSize: theme2.fontSizes[0],
1347
- textAlign: "center",
1348
- padding: `${theme2.space[2]}px`
1349
- },
1350
- title: `Failed to load image: ${transformedSrc}`
1351
- }, "\uD83D\uDDBC️ Image unavailable", " ", alt && /* @__PURE__ */ import_react7.default.createElement("span", {
1352
- style: { fontSize: theme2.fontSizes[0], opacity: 0.7 }
1353
- }, "(", alt, ")"));
1354
- }
1355
- return /* @__PURE__ */ import_react7.default.createElement("img", {
1356
- src: transformedSrc,
1357
- alt,
1358
- style: imageStyle,
1359
- onLoad: handleLoad,
1360
- onError: handleError,
1361
- ...props
1362
- });
1363
- });
1364
- var createIndustryMarkdownComponents = ({
1365
- theme: theme2,
1366
- slideIdPrefix,
1367
- slideIndex,
1368
- onLinkClick,
1369
- onCheckboxChange,
1370
- checkedItems,
1371
- setCheckedItems,
1372
- openHtmlModal,
1373
- openPlaceholderModal,
1374
- handleRunBashCommand,
1375
- enableHtmlPopout,
1376
- slideHeaderMarginTopOverride,
1377
- index,
1378
- repositoryInfo
1379
- }) => {
1380
- const getLuminance = (hex) => {
1381
- const rgb = hex.replace("#", "").match(/.{2}/g);
1382
- if (!rgb)
1383
- return 1;
1384
- const [r, g, b] = rgb.map((x) => parseInt(x, 16) / 255);
1385
- return 0.2126 * r + 0.7152 * g + 0.0722 * b;
1386
- };
1387
- const darkMode = getLuminance(theme2.colors.background) < 0.5;
1388
- const headerStyles = {};
1389
- if (index === 0 && slideHeaderMarginTopOverride) {
1390
- headerStyles.marginTop = `${slideHeaderMarginTopOverride}px`;
1391
- }
1392
- return {
1393
- h1: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("h1", {
1394
- style: {
1395
- color: theme2.colors.text,
1396
- fontSize: theme2.fontSizes[5],
1397
- lineHeight: theme2.lineHeights.heading,
1398
- fontWeight: theme2.fontWeights.bold,
1399
- marginBottom: theme2.space[4],
1400
- fontFamily: theme2.fonts.heading,
1401
- ...headerStyles
1402
- },
1403
- ...props
1404
- }, children),
1405
- h2: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("h2", {
1406
- style: {
1407
- color: theme2.colors.text,
1408
- fontSize: theme2.fontSizes[4],
1409
- lineHeight: theme2.lineHeights.heading,
1410
- fontWeight: theme2.fontWeights.bold,
1411
- marginTop: theme2.space[4],
1412
- marginBottom: theme2.space[3],
1413
- fontFamily: theme2.fonts.heading,
1414
- ...headerStyles
1415
- },
1416
- ...props
1417
- }, children),
1418
- h3: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("h3", {
1419
- style: {
1420
- color: theme2.colors.text,
1421
- fontSize: theme2.fontSizes[3],
1422
- lineHeight: theme2.lineHeights.heading,
1423
- fontWeight: theme2.fontWeights.semibold,
1424
- marginTop: theme2.space[4],
1425
- marginBottom: theme2.space[3],
1426
- fontFamily: theme2.fonts.heading
1427
- },
1428
- ...props
1429
- }, children),
1430
- p: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("p", {
1431
- style: {
1432
- color: theme2.colors.text,
1433
- fontSize: theme2.fontSizes[2],
1434
- lineHeight: theme2.lineHeights.body,
1435
- marginBottom: theme2.space[3],
1436
- fontFamily: theme2.fonts.body
1437
- },
1438
- ...props
1439
- }, children),
1440
- ul: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("ul", {
1441
- style: {
1442
- color: theme2.colors.text,
1443
- fontSize: theme2.fontSizes[2],
1444
- lineHeight: theme2.lineHeights.body,
1445
- marginBottom: theme2.space[3],
1446
- paddingLeft: theme2.space[5],
1447
- listStyleType: "disc",
1448
- fontFamily: theme2.fonts.body
1449
- },
1450
- ...props
1451
- }, children),
1452
- ol: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("ol", {
1453
- style: {
1454
- color: theme2.colors.text,
1455
- fontSize: theme2.fontSizes[2],
1456
- lineHeight: theme2.lineHeights.body,
1457
- marginBottom: theme2.space[3],
1458
- paddingLeft: theme2.space[5],
1459
- listStyleType: "decimal",
1460
- fontFamily: theme2.fonts.body
1461
- },
1462
- ...props
1463
- }, children),
1464
- li: ({ children, ...props }) => {
1465
- const isTaskListItem = Array.isArray(children) && children.length > 0 && import_react7.default.isValidElement(children[0]) && children[0]?.props?.type === "checkbox";
1466
- if (isTaskListItem) {
1467
- const checkbox = children[0];
1468
- const remainingChildren = children.slice(1);
1469
- const labelContent = [];
1470
- const nestedListElements = [];
1471
- import_react7.default.Children.forEach(remainingChildren, (child) => {
1472
- if (import_react7.default.isValidElement(child) && (child.type === "ul" || child.type === "ol")) {
1473
- nestedListElements.push(child);
1474
- } else {
1475
- labelContent.push(child);
1476
- }
1477
- });
1478
- const checked = checkbox?.props?.checked || false;
1479
- const lineNumber = props.sourcePosition?.start?.line || props.node?.position?.start?.line || 1;
1480
- const id = `${slideIdPrefix}-checkbox-${lineNumber}`;
1481
- const isChecked = checkedItems[id] ?? checked;
1482
- const handleChange = (e) => {
1483
- e.stopPropagation();
1484
- const newChecked = e.target.checked;
1485
- setCheckedItems((prev) => ({
1486
- ...prev,
1487
- [id]: newChecked
1488
- }));
1489
- onCheckboxChange?.(slideIndex, lineNumber, newChecked);
1490
- };
1491
- return /* @__PURE__ */ import_react7.default.createElement("li", {
1492
- style: {
1493
- listStyle: "none",
1494
- marginLeft: `-${theme2.space[5]}px`,
1495
- marginBottom: theme2.space[3],
1496
- paddingTop: theme2.space[1],
1497
- color: theme2.colors.text,
1498
- fontSize: theme2.fontSizes[2]
1499
- },
1500
- ...props
1501
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
1502
- style: { display: "flex", alignItems: "flex-start" }
1503
- }, /* @__PURE__ */ import_react7.default.createElement("input", {
1504
- type: "checkbox",
1505
- checked: isChecked,
1506
- onChange: handleChange,
1507
- onClick: (e) => e.stopPropagation(),
1508
- style: {
1509
- marginRight: theme2.space[2],
1510
- marginTop: theme2.space[1],
1511
- width: "16px",
1512
- height: "16px",
1513
- cursor: "pointer"
1514
- },
1515
- id
1516
- }), /* @__PURE__ */ import_react7.default.createElement("label", {
1517
- htmlFor: id,
1518
- style: {
1519
- flex: 1,
1520
- cursor: "pointer",
1521
- textDecoration: isChecked ? "line-through" : "none",
1522
- opacity: isChecked ? 0.6 : 1,
1523
- lineHeight: theme2.lineHeights.relaxed
1524
- }
1525
- }, labelContent.length > 0 ? labelContent : null)), nestedListElements.length > 0 ? nestedListElements : null);
1526
- }
1527
- return /* @__PURE__ */ import_react7.default.createElement("li", {
1528
- style: {
1529
- marginBottom: theme2.space[2],
1530
- paddingTop: theme2.space[1],
1531
- color: theme2.colors.text,
1532
- lineHeight: theme2.lineHeights.relaxed
1533
- },
1534
- ...props
1535
- }, children);
1536
- },
1537
- table: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("div", {
1538
- style: {
1539
- overflowX: "auto",
1540
- marginBottom: theme2.space[4],
1541
- borderRadius: theme2.radii[2],
1542
- border: `1px solid ${theme2.colors.border}`
1543
- }
1544
- }, /* @__PURE__ */ import_react7.default.createElement("table", {
1545
- style: {
1546
- width: "100%",
1547
- borderCollapse: "collapse",
1548
- fontSize: theme2.fontSizes[1],
1549
- fontFamily: theme2.fonts.body
1550
- },
1551
- ...props
1552
- }, children)),
1553
- thead: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("thead", {
1554
- style: {
1555
- backgroundColor: theme2.colors.backgroundSecondary
1556
- },
1557
- ...props
1558
- }, children),
1559
- th: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("th", {
1560
- style: {
1561
- padding: theme2.space[3],
1562
- textAlign: "left",
1563
- fontWeight: theme2.fontWeights.semibold,
1564
- borderBottom: `2px solid ${theme2.colors.border}`,
1565
- color: theme2.colors.text
1566
- },
1567
- ...props
1568
- }, children),
1569
- td: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("td", {
1570
- style: {
1571
- padding: theme2.space[3],
1572
- borderBottom: `1px solid ${theme2.colors.border}`,
1573
- color: theme2.colors.text
1574
- },
1575
- ...props
1576
- }, children),
1577
- a: ({ children, href, ...props }) => /* @__PURE__ */ import_react7.default.createElement(LinkWithLoadingIndicator, {
1578
- href: href || "",
1579
- onClick: onLinkClick ? (h, e) => onLinkClick(h, e) : undefined,
1580
- className: props.className
1581
- }, children),
1582
- img: ({ src, alt, ...props }) => /* @__PURE__ */ import_react7.default.createElement(OptimizedMarkdownImage, {
1583
- src: src || "",
1584
- alt: alt || "",
1585
- repositoryInfo,
1586
- theme: theme2,
1587
- ...props
1588
- }),
1589
- picture: ({ children, ...props }) => /* @__PURE__ */ import_react7.default.createElement("picture", {
1590
- ...props
1591
- }, children),
1592
- source: ({ srcset, srcSet, ...props }) => {
1593
- const srcsetValue = srcset || srcSet;
1594
- const transformedSrcset = import_react7.useMemo(() => {
1595
- if (!srcsetValue || !repositoryInfo)
1596
- return srcsetValue;
1597
- return srcsetValue.split(",").map((src) => {
1598
- const trimmed = src.trim();
1599
- const parts = trimmed.split(/\s+/);
1600
- const url = parts[0];
1601
- const descriptors = parts.slice(1).join(" ");
1602
- const transformedUrl = transformImageUrl(url, repositoryInfo);
1603
- return descriptors ? `${transformedUrl} ${descriptors}` : transformedUrl;
1604
- }).join(", ");
1605
- }, [srcsetValue, repositoryInfo]);
1606
- return /* @__PURE__ */ import_react7.default.createElement("source", {
1607
- srcSet: transformedSrcset,
1608
- ...props
1609
- });
1610
- },
1611
- code: ({ node, className, children, ...props }) => {
1612
- const hasLanguageClass = className && (className.includes("language-") || className.includes("hljs"));
1613
- const codeString = extractTextFromChildren(children);
1614
- const matchLang = /language-(\w+)/.exec(className || "");
1615
- const language = matchLang ? matchLang[1] : null;
1616
- const [copied, setCopied] = import_react7.useState(false);
1617
- let isInline;
1618
- let isCodeBlock;
1619
- const hasNewlines = codeString.includes(`
1620
- `);
1621
- if (!className && !hasNewlines) {
1622
- isInline = true;
1623
- isCodeBlock = false;
1624
- } else if (hasNewlines) {
1625
- isInline = false;
1626
- isCodeBlock = true;
1627
- } else if (language === "text") {
1628
- isInline = true;
1629
- isCodeBlock = false;
1630
- } else {
1631
- isCodeBlock = hasLanguageClass || codeString.length > 50;
1632
- const nodeWithParent = node;
1633
- const isInsideParagraph = nodeWithParent?.parent?.tagName === "p" || nodeWithParent?.parent?.parent?.tagName === "p";
1634
- isInline = !isCodeBlock || isInsideParagraph;
1635
- }
1636
- if (!isInline) {
1637
- const language2 = matchLang ? matchLang[1] : "text";
1638
- const isExecutable = (language2 === "bash" || language2 === "sh" || language2 === "shell") && handleRunBashCommand;
1639
- const isHtml = (language2 === "html" || language2 === "htm") && enableHtmlPopout;
1640
- const isPrompt = language2 === "prompt";
1641
- const placeholderRegex = /\{\{([^}]+)\}\}/g;
1642
- const placeholders = isPrompt ? [...codeString.matchAll(placeholderRegex)].map((match) => match[1].trim()) : [];
1643
- const hasPlaceholders = placeholders.length > 0;
1644
- const bashCommands = isExecutable ? parseBashCommands(codeString) : [];
1645
- const containerStyle = isPrompt ? {
1646
- position: "relative",
1647
- margin: `${theme2.space[4]}px 0`,
1648
- backgroundColor: darkMode ? theme2.colors.backgroundTertiary : theme2.colors.highlight,
1649
- border: `2px solid ${theme2.colors.accent}`,
1650
- borderRadius: theme2.radii[2],
1651
- overflow: "visible",
1652
- boxShadow: theme2.shadows[2]
1653
- } : {
1654
- position: "relative",
1655
- margin: `${theme2.space[4]}px 0`,
1656
- backgroundColor: theme2.colors.backgroundSecondary,
1657
- borderRadius: theme2.radii[2],
1658
- overflow: "hidden",
1659
- border: `1px solid ${theme2.colors.border}`
1660
- };
1661
- const headerStyle = isPrompt ? {
1662
- display: "flex",
1663
- justifyContent: "space-between",
1664
- alignItems: "center",
1665
- padding: `${theme2.space[3]}px ${theme2.space[4]}px`,
1666
- backgroundColor: theme2.colors.muted,
1667
- borderBottom: `2px solid ${theme2.colors.accent}`,
1668
- fontSize: theme2.fontSizes[0],
1669
- color: theme2.colors.accent
1670
- } : {
1671
- display: "flex",
1672
- justifyContent: "space-between",
1673
- alignItems: "center",
1674
- padding: `${theme2.space[2]}px ${theme2.space[3]}px`,
1675
- backgroundColor: theme2.colors.backgroundTertiary,
1676
- borderBottom: `1px solid ${theme2.colors.border}`,
1677
- fontSize: theme2.fontSizes[0]
1678
- };
1679
- return /* @__PURE__ */ import_react7.default.createElement("div", {
1680
- style: containerStyle
1681
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
1682
- style: headerStyle
1683
- }, /* @__PURE__ */ import_react7.default.createElement("span", {
1684
- style: {
1685
- fontFamily: theme2.fonts.monospace,
1686
- fontWeight: isPrompt ? theme2.fontWeights.bold : theme2.fontWeights.body
1687
- }
1688
- }, isPrompt ? "\uD83D\uDCA1 Prompt" : language2), /* @__PURE__ */ import_react7.default.createElement("div", {
1689
- style: { display: "flex", gap: `${theme2.space[2]}px` }
1690
- }, /* @__PURE__ */ import_react7.default.createElement("button", {
1691
- onClick: (e) => {
1692
- e.stopPropagation();
1693
- navigator.clipboard.writeText(codeString).then(() => {
1694
- setCopied(true);
1695
- setTimeout(() => setCopied(false), 2000);
1696
- }).catch((err) => {
1697
- console.error("Failed to copy:", err);
1698
- });
1699
- },
1700
- style: {
1701
- padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
1702
- backgroundColor: copied ? theme2.colors.success + "22" : darkMode ? theme2.colors.backgroundTertiary : theme2.colors.backgroundSecondary,
1703
- color: copied ? theme2.colors.success : theme2.colors.textSecondary,
1704
- border: `1px solid ${copied ? theme2.colors.success : theme2.colors.border}`,
1705
- borderRadius: theme2.radii[1],
1706
- fontSize: theme2.fontSizes[0],
1707
- cursor: "pointer",
1708
- display: "flex",
1709
- alignItems: "center",
1710
- gap: `${theme2.space[1]}px`,
1711
- transition: "all 0.15s ease-in-out"
1712
- },
1713
- title: copied ? "Copied!" : "Copy code to clipboard"
1714
- }, copied ? /* @__PURE__ */ import_react7.default.createElement(import_lucide_react4.Check, {
1715
- size: 14
1716
- }) : /* @__PURE__ */ import_react7.default.createElement(import_lucide_react4.Copy, {
1717
- size: 14
1718
- }), copied ? "Copied!" : "Copy"), isExecutable && /* @__PURE__ */ import_react7.default.createElement(IndustryBashCommandDropdown, {
1719
- commands: bashCommands,
1720
- allCommands: codeString.trim(),
1721
- onRunCommand: async (command) => {
1722
- try {
1723
- await handleRunBashCommand(command, {
1724
- id: `${slideIdPrefix}-code-${Date.now()}`,
1725
- showInTerminal: true
1726
- });
1727
- } catch (error) {
1728
- console.error("Error running bash command:", error);
1729
- }
1730
- },
1731
- slideIdPrefix,
1732
- theme: theme2
1733
- }), isHtml && /* @__PURE__ */ import_react7.default.createElement("button", {
1734
- onClick: (e) => {
1735
- e.stopPropagation();
1736
- openHtmlModal(codeString);
1737
- },
1738
- style: {
1739
- padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
1740
- backgroundColor: theme2.colors.primary,
1741
- color: "white",
1742
- border: "none",
1743
- borderRadius: theme2.radii[1],
1744
- fontSize: theme2.fontSizes[0],
1745
- cursor: "pointer",
1746
- display: "flex",
1747
- alignItems: "center",
1748
- gap: `${theme2.space[1]}px`
1749
- },
1750
- title: "Render HTML in modal"
1751
- }, /* @__PURE__ */ import_react7.default.createElement(import_lucide_react4.Monitor, {
1752
- size: 14
1753
- }), "Render HTML"), isPrompt && openPlaceholderModal && hasPlaceholders && /* @__PURE__ */ import_react7.default.createElement("button", {
1754
- onClick: (e) => {
1755
- e.stopPropagation();
1756
- openPlaceholderModal(placeholders, codeString);
1757
- },
1758
- style: {
1759
- padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
1760
- backgroundColor: theme2.colors.accent,
1761
- color: "white",
1762
- border: "none",
1763
- borderRadius: theme2.radii[1],
1764
- fontSize: theme2.fontSizes[0],
1765
- cursor: "pointer",
1766
- display: "flex",
1767
- alignItems: "center",
1768
- gap: `${theme2.space[1]}px`
1769
- },
1770
- title: "Fill placeholders and copy"
1771
- }, /* @__PURE__ */ import_react7.default.createElement(import_lucide_react4.FileText, {
1772
- size: 14
1773
- }), "Fill & Copy (", placeholders.length, ")"))), isPrompt ? /* @__PURE__ */ import_react7.default.createElement("div", {
1774
- style: {
1775
- margin: 0,
1776
- padding: theme2.space[5],
1777
- backgroundColor: "transparent",
1778
- fontSize: theme2.fontSizes[1],
1779
- lineHeight: theme2.lineHeights.body,
1780
- fontFamily: theme2.fonts.body,
1781
- overflow: "auto",
1782
- color: theme2.colors.text
1783
- }
1784
- }, codeString.split(/(\{\{[^}]+\}\})/).map((part, index2) => {
1785
- if (part.match(/^\{\{[^}]+\}\}$/)) {
1786
- return /* @__PURE__ */ import_react7.default.createElement("span", {
1787
- key: index2,
1788
- style: {
1789
- backgroundColor: theme2.colors.highlight,
1790
- color: theme2.colors.primary,
1791
- padding: `${theme2.space[0]}px ${theme2.space[1]}px`,
1792
- borderRadius: theme2.radii[1],
1793
- fontWeight: theme2.fontWeights.semibold,
1794
- fontFamily: theme2.fonts.monospace,
1795
- fontSize: theme2.fontSizes[1]
1796
- }
1797
- }, part);
1798
- }
1799
- return part;
1800
- })) : /* @__PURE__ */ import_react7.default.createElement("pre", {
1801
- style: {
1802
- margin: 0,
1803
- padding: theme2.space[4],
1804
- backgroundColor: "transparent",
1805
- overflow: "auto",
1806
- fontSize: theme2.fontSizes[1],
1807
- lineHeight: 1.2,
1808
- fontFamily: theme2.fonts.monospace
1809
- }
1810
- }, /* @__PURE__ */ import_react7.default.createElement("code", {
1811
- className,
1812
- style: {
1813
- lineHeight: "inherit",
1814
- fontSize: "inherit",
1815
- fontFamily: "inherit",
1816
- display: "block"
1817
- },
1818
- ...props
1819
- }, children)));
1820
- }
1821
- return /* @__PURE__ */ import_react7.default.createElement("code", {
1822
- style: {
1823
- backgroundColor: theme2.colors.backgroundSecondary,
1824
- color: theme2.colors.text,
1825
- padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
1826
- borderRadius: theme2.radii[1],
1827
- fontSize: "0.875em",
1828
- fontFamily: theme2.fonts.monospace,
1829
- border: `1px solid ${theme2.colors.border}`,
1830
- "--text-color": theme2.colors.text
1831
- },
1832
- className: `inline-code ${className || ""}`,
1833
- ...props
1834
- }, children);
1835
- }
1836
- };
1837
- };
1838
-
1839
- // industryMarkdown/components/IndustryMermaidModal.tsx
1840
- var import_react9 = __toESM(require("react"));
1841
- var import_react_dom = __toESM(require("react-dom"));
1842
-
1843
- // industryMarkdown/components/IndustryZoomableMermaidDiagram.tsx
1844
- var import_react8 = __toESM(require("react"));
1845
- var import_react_zoom_pan_pinch = require("react-zoom-pan-pinch");
1846
- function IndustryZoomableMermaidDiagram({
1847
- code,
1848
- id,
1849
- theme: themeOverride,
1850
- fitStrategy = "contain",
1851
- padding = 0.85
1852
- }) {
1853
- const { theme: contextTheme } = useTheme();
1854
- const theme2 = themeOverride || contextTheme;
1855
- const [calculatedScale, setCalculatedScale] = import_react8.useState(0.8);
1856
- const containerRef = import_react8.useRef(null);
1857
- const diagramRef = import_react8.useRef(null);
1858
- const [isCalculating, setIsCalculating] = import_react8.useState(true);
1859
- import_react8.useEffect(() => {
1860
- if (!containerRef.current || !diagramRef.current)
1861
- return;
1862
- const calculateOptimalScale = () => {
1863
- const container = containerRef.current;
1864
- const diagram = diagramRef.current;
1865
- if (!container || !diagram)
1866
- return;
1867
- const svg = diagram.querySelector("svg");
1868
- if (!svg) {
1869
- setTimeout(calculateOptimalScale, 100);
1870
- return;
1871
- }
1872
- let svgWidth, svgHeight;
1873
- const viewBox = svg.getAttribute("viewBox");
1874
- if (viewBox) {
1875
- const [, , width, height] = viewBox.split(" ").map(Number);
1876
- svgWidth = width;
1877
- svgHeight = height;
1878
- } else {
1879
- const svgRect = svg.getBoundingClientRect();
1880
- svgWidth = svgRect.width / calculatedScale;
1881
- svgHeight = svgRect.height / calculatedScale;
1882
- }
1883
- const containerWidth = container.clientWidth;
1884
- const containerHeight = container.clientHeight;
1885
- if (svgWidth <= 0 || svgHeight <= 0 || containerWidth <= 0 || containerHeight <= 0) {
1886
- return;
1887
- }
1888
- let scale = 1;
1889
- switch (fitStrategy) {
1890
- case "width":
1891
- scale = containerWidth * padding / svgWidth;
1892
- break;
1893
- case "height":
1894
- scale = containerHeight * padding / svgHeight;
1895
- break;
1896
- case "contain":
1897
- default:
1898
- scale = Math.min(containerWidth * padding / svgWidth, containerHeight * padding / svgHeight);
1899
- break;
1900
- }
1901
- scale = Math.min(Math.max(scale, 0.3), 2);
1902
- setCalculatedScale(scale);
1903
- setIsCalculating(false);
1904
- };
1905
- const resizeObserver = new ResizeObserver(() => {
1906
- calculateOptimalScale();
1907
- });
1908
- resizeObserver.observe(containerRef.current);
1909
- setTimeout(calculateOptimalScale, 200);
1910
- return () => {
1911
- resizeObserver.disconnect();
1912
- };
1913
- }, [code, fitStrategy, padding]);
1914
- const buttonStyle = {
1915
- padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
1916
- marginRight: theme2.space[2],
1917
- backgroundColor: theme2.colors.background,
1918
- color: theme2.colors.text,
1919
- border: `1px solid ${theme2.colors.border}`,
1920
- borderRadius: theme2.radii[1],
1921
- fontSize: theme2.fontSizes[2],
1922
- fontWeight: theme2.fontWeights.medium,
1923
- cursor: "pointer",
1924
- transition: "all 0.2s ease",
1925
- fontFamily: theme2.fonts.body
1926
- };
1927
- const handleButtonHover = (e) => {
1928
- e.currentTarget.style.backgroundColor = theme2.colors.backgroundSecondary;
1929
- };
1930
- const handleButtonLeave = (e) => {
1931
- e.currentTarget.style.backgroundColor = theme2.colors.background;
1932
- };
1933
- return /* @__PURE__ */ import_react8.default.createElement("div", {
1934
- ref: containerRef,
1935
- style: { width: "100%", height: "100%", position: "relative" }
1936
- }, /* @__PURE__ */ import_react8.default.createElement(import_react_zoom_pan_pinch.TransformWrapper, {
1937
- limitToBounds: true,
1938
- doubleClick: { disabled: true },
1939
- minScale: 0.3,
1940
- maxScale: 10,
1941
- initialScale: calculatedScale,
1942
- initialPositionX: 0,
1943
- initialPositionY: 0,
1944
- centerOnInit: true,
1945
- centerZoomedOut: true,
1946
- alignmentAnimation: { disabled: true },
1947
- zoomAnimation: { disabled: false, size: 0.2 }
1948
- }, ({ centerView, instance }) => /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement("div", {
1949
- style: {
1950
- position: "absolute",
1951
- top: theme2.space[3],
1952
- right: theme2.space[3],
1953
- zIndex: 10,
1954
- display: "flex",
1955
- gap: theme2.space[2]
1956
- }
1957
- }, /* @__PURE__ */ import_react8.default.createElement("button", {
1958
- onClick: () => {
1959
- const { scale } = instance.transformState;
1960
- const newScale = Math.min(scale * 1.2, 10);
1961
- centerView(newScale, 200, "easeOut");
1962
- },
1963
- style: buttonStyle,
1964
- onMouseEnter: handleButtonHover,
1965
- onMouseLeave: handleButtonLeave,
1966
- title: "Zoom in"
1967
- }, "+"), /* @__PURE__ */ import_react8.default.createElement("button", {
1968
- onClick: () => {
1969
- const { scale } = instance.transformState;
1970
- const newScale = Math.max(scale * 0.833, 0.3);
1971
- centerView(newScale, 200, "easeOut");
1972
- },
1973
- style: buttonStyle,
1974
- onMouseEnter: handleButtonHover,
1975
- onMouseLeave: handleButtonLeave,
1976
- title: "Zoom out"
1977
- }, "−"), /* @__PURE__ */ import_react8.default.createElement("button", {
1978
- onClick: () => {
1979
- centerView(calculatedScale, 200, "easeOut");
1980
- },
1981
- style: buttonStyle,
1982
- onMouseEnter: handleButtonHover,
1983
- onMouseLeave: handleButtonLeave,
1984
- title: "Reset zoom"
1985
- }, "⟲"), isCalculating && /* @__PURE__ */ import_react8.default.createElement("span", {
1986
- style: {
1987
- padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
1988
- fontSize: theme2.fontSizes[1],
1989
- color: theme2.colors.textMuted,
1990
- fontFamily: theme2.fonts.body
1991
- }
1992
- }, "Optimizing view...")), /* @__PURE__ */ import_react8.default.createElement(import_react_zoom_pan_pinch.TransformComponent, {
1993
- wrapperStyle: {
1994
- width: "100%",
1995
- height: "100%",
1996
- overflow: "hidden"
1997
- },
1998
- contentStyle: {
1999
- width: "fit-content",
2000
- height: "fit-content",
2001
- display: "flex",
2002
- alignItems: "center",
2003
- justifyContent: "center",
2004
- minWidth: "100%",
2005
- minHeight: "100%"
2006
- }
2007
- }, /* @__PURE__ */ import_react8.default.createElement("div", {
2008
- ref: diagramRef,
2009
- style: {
2010
- display: "flex",
2011
- alignItems: "center",
2012
- justifyContent: "center",
2013
- width: "fit-content",
2014
- height: "fit-content",
2015
- minWidth: "100%",
2016
- minHeight: "100%"
2017
- }
2018
- }, /* @__PURE__ */ import_react8.default.createElement(IndustryMermaidDiagram, {
2019
- code,
2020
- id,
2021
- isModalMode: true
2022
- }))))));
2023
- }
2024
-
2025
- // industryMarkdown/components/IndustryMermaidModal.tsx
2026
- function IndustryMermaidModal({
2027
- isOpen,
2028
- onClose,
2029
- mermaidCode,
2030
- theme: theme2
2031
- }) {
2032
- const modalRef = import_react9.useRef(null);
2033
- import_react9.useEffect(() => {
2034
- const handleEscape = (event) => {
2035
- if (event.key === "Escape") {
2036
- onClose();
2037
- }
2038
- };
2039
- if (isOpen) {
2040
- document.addEventListener("keydown", handleEscape);
2041
- }
2042
- return () => {
2043
- document.removeEventListener("keydown", handleEscape);
2044
- };
2045
- }, [isOpen, onClose]);
2046
- const handleBackdropClick = (event) => {
2047
- if (modalRef.current && !modalRef.current.contains(event.target)) {
2048
- onClose();
2049
- }
2050
- };
2051
- if (!isOpen) {
2052
- return null;
2053
- }
2054
- const modalContent = /* @__PURE__ */ import_react9.default.createElement("div", {
2055
- onClick: handleBackdropClick,
2056
- style: {
2057
- position: "fixed",
2058
- top: 0,
2059
- left: 0,
2060
- right: 0,
2061
- bottom: 0,
2062
- backgroundColor: "rgba(0, 0, 0, 0.8)",
2063
- display: "flex",
2064
- alignItems: "center",
2065
- justifyContent: "center",
2066
- zIndex: 50,
2067
- padding: theme2.space[4]
2068
- }
2069
- }, /* @__PURE__ */ import_react9.default.createElement("div", {
2070
- ref: modalRef,
2071
- onClick: (e) => e.stopPropagation(),
2072
- style: {
2073
- position: "relative",
2074
- backgroundColor: theme2.colors.background,
2075
- borderRadius: theme2.radii[3],
2076
- padding: theme2.space[5],
2077
- width: "90vw",
2078
- height: "90vh",
2079
- display: "flex",
2080
- flexDirection: "column",
2081
- overflow: "hidden",
2082
- boxShadow: theme2.shadows[4]
2083
- }
2084
- }, /* @__PURE__ */ import_react9.default.createElement("button", {
2085
- onClick: onClose,
2086
- style: {
2087
- position: "absolute",
2088
- top: theme2.space[4],
2089
- right: theme2.space[4],
2090
- background: "none",
2091
- border: "none",
2092
- fontSize: theme2.fontSizes[5],
2093
- color: theme2.colors.textSecondary,
2094
- cursor: "pointer",
2095
- lineHeight: 1,
2096
- padding: `${theme2.space[1]}px`,
2097
- borderRadius: theme2.radii[1],
2098
- width: "32px",
2099
- height: "32px",
2100
- display: "flex",
2101
- alignItems: "center",
2102
- justifyContent: "center",
2103
- transition: "all 0.2s ease"
2104
- },
2105
- onMouseEnter: (e) => {
2106
- e.currentTarget.style.backgroundColor = theme2.colors.backgroundTertiary;
2107
- e.currentTarget.style.color = theme2.colors.text;
2108
- },
2109
- onMouseLeave: (e) => {
2110
- e.currentTarget.style.backgroundColor = "transparent";
2111
- e.currentTarget.style.color = theme2.colors.textSecondary;
2112
- },
2113
- "aria-label": "Close"
2114
- }, "×"), /* @__PURE__ */ import_react9.default.createElement("div", {
2115
- style: { flex: 1, overflow: "hidden", position: "relative" }
2116
- }, /* @__PURE__ */ import_react9.default.createElement(IndustryZoomableMermaidDiagram, {
2117
- id: "mermaid-modal-diagram",
2118
- code: mermaidCode,
2119
- theme: theme2
2120
- }))));
2121
- return import_react_dom.default.createPortal(modalContent, document.body);
2122
- }
2123
-
2124
- // industryMarkdown/components/IndustryPlaceholderModal.tsx
2125
- var import_react10 = __toESM(require("react"));
2126
- function IndustryPlaceholderModal({
2127
- isOpen,
2128
- onClose,
2129
- placeholders,
2130
- promptContent,
2131
- onCopy,
2132
- theme: theme2
2133
- }) {
2134
- const [values, setValues] = import_react10.useState({});
2135
- if (!isOpen)
2136
- return null;
2137
- const handleSubmit = (e) => {
2138
- e.preventDefault();
2139
- let filledPrompt = promptContent;
2140
- placeholders.forEach((placeholder) => {
2141
- const value = values[placeholder] || `{{${placeholder}}}`;
2142
- const regex = new RegExp(`\\{\\{${placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\}\\}`, "g");
2143
- filledPrompt = filledPrompt.replace(regex, value);
2144
- });
2145
- navigator.clipboard.writeText(filledPrompt).then(() => {
2146
- onCopy(filledPrompt);
2147
- onClose();
2148
- setValues({});
2149
- }).catch((err) => {
2150
- console.error("Failed to copy filled prompt:", err);
2151
- });
2152
- };
2153
- return /* @__PURE__ */ import_react10.default.createElement("div", {
2154
- style: {
2155
- position: "fixed",
2156
- top: 0,
2157
- left: 0,
2158
- right: 0,
2159
- bottom: 0,
2160
- backgroundColor: "rgba(0, 0, 0, 0.8)",
2161
- display: "flex",
2162
- alignItems: "center",
2163
- justifyContent: "center",
2164
- zIndex: 50,
2165
- padding: theme2.space[5]
2166
- },
2167
- onClick: onClose
2168
- }, /* @__PURE__ */ import_react10.default.createElement("div", {
2169
- style: {
2170
- backgroundColor: theme2.colors.background,
2171
- borderRadius: theme2.radii[3],
2172
- maxWidth: "600px",
2173
- width: "100%",
2174
- maxHeight: "80vh",
2175
- overflow: "hidden",
2176
- display: "flex",
2177
- flexDirection: "column",
2178
- border: `1px solid ${theme2.colors.border}`,
2179
- boxShadow: theme2.shadows[4]
2180
- },
2181
- onClick: (e) => e.stopPropagation()
2182
- }, /* @__PURE__ */ import_react10.default.createElement("div", {
2183
- style: {
2184
- padding: theme2.space[4],
2185
- borderBottom: `1px solid ${theme2.colors.border}`,
2186
- display: "flex",
2187
- justifyContent: "space-between",
2188
- alignItems: "center",
2189
- backgroundColor: theme2.colors.backgroundSecondary
2190
- }
2191
- }, /* @__PURE__ */ import_react10.default.createElement("h3", {
2192
- style: {
2193
- margin: 0,
2194
- color: theme2.colors.text,
2195
- fontSize: theme2.fontSizes[3],
2196
- fontWeight: theme2.fontWeights.semibold,
2197
- fontFamily: theme2.fonts.heading
2198
- }
2199
- }, "Fill Prompt Placeholders"), /* @__PURE__ */ import_react10.default.createElement("button", {
2200
- onClick: (e) => {
2201
- e.stopPropagation();
2202
- onClose();
2203
- },
2204
- style: {
2205
- background: "none",
2206
- border: "none",
2207
- fontSize: theme2.fontSizes[5],
2208
- cursor: "pointer",
2209
- color: theme2.colors.textSecondary,
2210
- padding: `${theme2.space[1]}px`,
2211
- borderRadius: theme2.radii[1],
2212
- display: "flex",
2213
- alignItems: "center",
2214
- justifyContent: "center",
2215
- width: "32px",
2216
- height: "32px",
2217
- transition: "all 0.2s ease"
2218
- },
2219
- onMouseEnter: (e) => {
2220
- e.currentTarget.style.backgroundColor = theme2.colors.backgroundTertiary;
2221
- e.currentTarget.style.color = theme2.colors.text;
2222
- },
2223
- onMouseLeave: (e) => {
2224
- e.currentTarget.style.backgroundColor = "transparent";
2225
- e.currentTarget.style.color = theme2.colors.textSecondary;
2226
- },
2227
- title: "Close",
2228
- "aria-label": "Close modal"
2229
- }, "×")), /* @__PURE__ */ import_react10.default.createElement("div", {
2230
- style: {
2231
- padding: theme2.space[5],
2232
- overflow: "auto",
2233
- flex: 1,
2234
- backgroundColor: theme2.colors.background
2235
- }
2236
- }, /* @__PURE__ */ import_react10.default.createElement("p", {
2237
- style: {
2238
- margin: `0 0 ${theme2.space[4]}px 0`,
2239
- color: theme2.colors.textSecondary,
2240
- fontSize: theme2.fontSizes[2],
2241
- lineHeight: theme2.lineHeights.body,
2242
- fontFamily: theme2.fonts.body
2243
- }
2244
- }, "Fill in the values for the placeholders below. The prompt will be copied to your clipboard with the values substituted."), /* @__PURE__ */ import_react10.default.createElement("form", {
2245
- onSubmit: handleSubmit
2246
- }, placeholders.map((placeholder, index) => /* @__PURE__ */ import_react10.default.createElement("div", {
2247
- key: index,
2248
- style: { marginBottom: theme2.space[4] }
2249
- }, /* @__PURE__ */ import_react10.default.createElement("label", {
2250
- style: {
2251
- display: "block",
2252
- marginBottom: theme2.space[2],
2253
- fontWeight: theme2.fontWeights.medium,
2254
- color: theme2.colors.text,
2255
- fontSize: theme2.fontSizes[1],
2256
- fontFamily: theme2.fonts.body
2257
- }
2258
- }, placeholder), /* @__PURE__ */ import_react10.default.createElement("input", {
2259
- type: "text",
2260
- value: values[placeholder] || "",
2261
- onChange: (e) => setValues((prev) => ({
2262
- ...prev,
2263
- [placeholder]: e.target.value
2264
- })),
2265
- style: {
2266
- width: "100%",
2267
- padding: `${theme2.space[3]}px`,
2268
- border: `1px solid ${theme2.colors.border}`,
2269
- borderRadius: theme2.radii[1],
2270
- fontSize: theme2.fontSizes[2],
2271
- backgroundColor: theme2.colors.background,
2272
- color: theme2.colors.text,
2273
- outline: "none",
2274
- fontFamily: theme2.fonts.body,
2275
- transition: "border-color 0.2s ease"
2276
- },
2277
- onFocus: (e) => {
2278
- e.currentTarget.style.borderColor = theme2.colors.primary;
2279
- },
2280
- onBlur: (e) => {
2281
- e.currentTarget.style.borderColor = theme2.colors.border;
2282
- },
2283
- placeholder: `Enter value for ${placeholder}`
2284
- }))), /* @__PURE__ */ import_react10.default.createElement("div", {
2285
- style: {
2286
- display: "flex",
2287
- gap: theme2.space[3],
2288
- justifyContent: "flex-end",
2289
- marginTop: theme2.space[5]
2290
- }
2291
- }, /* @__PURE__ */ import_react10.default.createElement("button", {
2292
- type: "button",
2293
- onClick: onClose,
2294
- style: {
2295
- padding: `${theme2.space[2]}px ${theme2.space[4]}px`,
2296
- borderRadius: theme2.radii[1],
2297
- fontSize: theme2.fontSizes[2],
2298
- fontWeight: theme2.fontWeights.medium,
2299
- cursor: "pointer",
2300
- border: `1px solid ${theme2.colors.border}`,
2301
- display: "flex",
2302
- alignItems: "center",
2303
- gap: theme2.space[2],
2304
- backgroundColor: theme2.colors.background,
2305
- color: theme2.colors.text,
2306
- fontFamily: theme2.fonts.body,
2307
- transition: "all 0.2s ease"
2308
- },
2309
- onMouseEnter: (e) => {
2310
- e.currentTarget.style.backgroundColor = theme2.colors.backgroundSecondary;
2311
- },
2312
- onMouseLeave: (e) => {
2313
- e.currentTarget.style.backgroundColor = theme2.colors.background;
2314
- }
2315
- }, "Cancel"), /* @__PURE__ */ import_react10.default.createElement("button", {
2316
- type: "submit",
2317
- style: {
2318
- padding: `${theme2.space[2]}px ${theme2.space[4]}px`,
2319
- borderRadius: theme2.radii[1],
2320
- fontSize: theme2.fontSizes[2],
2321
- fontWeight: theme2.fontWeights.medium,
2322
- cursor: "pointer",
2323
- border: "none",
2324
- display: "flex",
2325
- alignItems: "center",
2326
- gap: theme2.space[2],
2327
- backgroundColor: theme2.colors.primary,
2328
- color: "white",
2329
- fontFamily: theme2.fonts.body,
2330
- transition: "all 0.2s ease"
2331
- },
2332
- onMouseEnter: (e) => {
2333
- e.currentTarget.style.opacity = "0.9";
2334
- },
2335
- onMouseLeave: (e) => {
2336
- e.currentTarget.style.opacity = "1";
2337
- }
2338
- }, "Copy to Clipboard"))))));
2339
- }
2340
-
2341
- // industryMarkdown/components/IndustryMarkdownSlide.tsx
2342
- var highlightOverrides = `
2343
- .hljs,
2344
- .hljs-keyword,
2345
- .hljs-selector-tag,
2346
- .hljs-literal,
2347
- .hljs-strong,
2348
- .hljs-name,
2349
- .hljs-variable,
2350
- .hljs-number,
2351
- .hljs-string,
2352
- .hljs-comment,
2353
- .hljs-type,
2354
- .hljs-built_in,
2355
- .hljs-builtin-name,
2356
- .hljs-meta,
2357
- .hljs-tag,
2358
- .hljs-title,
2359
- .hljs-attr,
2360
- .hljs-attribute,
2361
- .hljs-addition,
2362
- .hljs-deletion,
2363
- .hljs-link,
2364
- .hljs-doctag,
2365
- .hljs-formula,
2366
- .hljs-section,
2367
- .hljs-selector-class,
2368
- .hljs-selector-attr,
2369
- .hljs-selector-pseudo,
2370
- .hljs-symbol,
2371
- .hljs-bullet,
2372
- .hljs-selector-id,
2373
- .hljs-emphasis,
2374
- .hljs-quote,
2375
- .hljs-template-variable,
2376
- .hljs-regexp,
2377
- .hljs-subst {
2378
- background-color: transparent !important;
2379
- }
2380
-
2381
- /* Ensure inline code has proper contrast */
2382
- .inline-code {
2383
- color: inherit !important;
2384
- }
2385
-
2386
- /* Prevent highlight.js from overriding inline code colors */
2387
- .inline-code.hljs,
2388
- .inline-code .hljs-keyword,
2389
- .inline-code .hljs-string,
2390
- .inline-code .hljs-number,
2391
- .inline-code .hljs-comment,
2392
- .inline-code .hljs-built_in,
2393
- .inline-code .hljs-literal {
2394
- color: inherit !important;
2395
- background-color: transparent !important;
2396
- }
2397
- `;
2398
- var fontTransitionCSS = `
2399
- .markdown-slide * {
2400
- transition: font-size 0.2s ease-in-out;
2401
- }
2402
-
2403
- /* Disable transitions and dynamic sizing on form elements to prevent flashing */
2404
- .markdown-slide input,
2405
- .markdown-slide label,
2406
- .markdown-slide button,
2407
- .markdown-slide input[type="checkbox"],
2408
- .markdown-slide input[type="radio"] {
2409
- transition: none !important;
2410
- font-size: inherit !important; /* Prevent dynamic font sizing from affecting form elements */
2411
- }
2412
-
2413
- /* Ensure checkbox labels maintain fixed sizing */
2414
- .markdown-slide label[for*="checkbox"] {
2415
- font-size: 1rem !important; /* Fixed size for checkbox labels */
2416
- }
2417
- `;
2418
- var stylesInjected = false;
2419
- var injectStyles = () => {
2420
- if (typeof document !== "undefined" && !stylesInjected) {
2421
- if (!document.getElementById("markdown-slide-highlight-overrides")) {
2422
- const highlightStyle = document.createElement("style");
2423
- highlightStyle.id = "markdown-slide-highlight-overrides";
2424
- highlightStyle.textContent = highlightOverrides;
2425
- document.head.appendChild(highlightStyle);
2426
- }
2427
- if (!document.getElementById("markdown-slide-font-transitions")) {
2428
- const transitionStyle = document.createElement("style");
2429
- transitionStyle.id = "markdown-slide-font-transitions";
2430
- transitionStyle.textContent = fontTransitionCSS;
2431
- document.head.appendChild(transitionStyle);
2432
- }
2433
- stylesInjected = true;
2434
- }
2435
- };
2436
- var IndustryMarkdownSlide = import_react11.default.memo(function IndustryMarkdownSlide2({
2437
- content,
2438
- slideIdPrefix,
2439
- slideIndex,
2440
- isVisible = false,
2441
- onLinkClick,
2442
- onCheckboxChange,
2443
- onCopyMermaidError,
2444
- onShowMermaidInPanel,
2445
- handleRunBashCommand,
2446
- handlePromptCopy,
2447
- enableHtmlPopout = true,
2448
- slideHeaderMarginTopOverride,
2449
- theme: themeOverride,
2450
- fontSizeScale = 1,
2451
- containerWidth,
2452
- minScreenWidth: _minScreenWidth,
2453
- maxScreenWidth: _maxScreenWidth,
2454
- enableKeyboardScrolling = true,
2455
- keyboardScrollConfig,
2456
- repositoryInfo
2457
- }) {
2458
- const slideRef = import_react11.useRef(null);
2459
- const scrollPositionRef = import_react11.useRef(0);
2460
- const [measuredContainerWidth, setMeasuredContainerWidth] = import_react11.useState(null);
2461
- let chunks = [];
2462
- try {
2463
- if (typeof content === "string") {
2464
- chunks = parseMarkdownChunks(content, slideIdPrefix);
2465
- } else {}
2466
- } catch (error) {
2467
- console.error("Error parsing markdown chunks:", error);
2468
- }
2469
- const [checkedItems, setCheckedItems] = import_react11.useState({});
2470
- const { htmlModalOpen, htmlModalContent, openHtmlModal, closeHtmlModal } = useIndustryHtmlModal();
2471
- const [mermaidModalOpen, setMermaidModalOpen] = import_react11.useState(false);
2472
- const [mermaidModalCode, setMermaidModalCode] = import_react11.useState("");
2473
- const [placeholderModalOpen, setPlaceholderModalOpen] = import_react11.useState(false);
2474
- const [placeholderModalData, setPlaceholderModalData] = import_react11.useState(null);
2475
- import_react11.useEffect(() => {
2476
- injectStyles();
2477
- }, []);
2478
- import_react11.useEffect(() => {
2479
- if (containerWidth !== undefined) {
2480
- return;
2481
- }
2482
- if (!slideRef.current) {
2483
- return;
2484
- }
2485
- const setupResizeObserver = () => {
2486
- const parentContainer = slideRef.current?.parentElement;
2487
- if (!parentContainer) {
2488
- return;
2489
- }
2490
- const resizeObserver2 = new ResizeObserver((entries) => {
2491
- for (const entry of entries) {
2492
- const { width } = entry.contentRect;
2493
- setMeasuredContainerWidth(width);
2494
- }
2495
- });
2496
- resizeObserver2.observe(parentContainer);
2497
- return resizeObserver2;
2498
- };
2499
- let resizeObserver = setupResizeObserver();
2500
- if (!resizeObserver) {
2501
- const timeoutId = setTimeout(() => {
2502
- resizeObserver = setupResizeObserver();
2503
- }, 100);
2504
- return () => {
2505
- clearTimeout(timeoutId);
2506
- if (resizeObserver) {
2507
- resizeObserver.disconnect();
2508
- }
2509
- };
2510
- }
2511
- return () => {
2512
- if (resizeObserver) {
2513
- resizeObserver.disconnect();
2514
- }
2515
- };
2516
- }, [containerWidth]);
2517
- const defaultScrollConfig = {
2518
- scrollAmount: 100,
2519
- pageScrollRatio: 0.8,
2520
- smoothScroll: true,
2521
- keys: {
2522
- scrollUp: ["ArrowUp"],
2523
- scrollDown: ["ArrowDown"],
2524
- pageUp: ["PageUp"],
2525
- pageDown: ["PageDown"]
2526
- },
2527
- enableDebugLogging: false
2528
- };
2529
- const scrollConfig = {
2530
- ...defaultScrollConfig,
2531
- ...keyboardScrollConfig,
2532
- keys: {
2533
- ...defaultScrollConfig.keys,
2534
- ...keyboardScrollConfig?.keys
2535
- }
2536
- };
2537
- const handleKeyDown = import_react11.useCallback((event) => {
2538
- if (!enableKeyboardScrolling) {
2539
- return;
2540
- }
2541
- if (!isVisible) {
2542
- if (scrollConfig.enableDebugLogging) {
2543
- console.log(`\uD83D\uDEAB Slide ${slideIndex} ignoring key press - not visible`);
2544
- }
2545
- return;
2546
- }
2547
- if (scrollConfig.enableDebugLogging) {
2548
- console.log(`\uD83D\uDD39 Slide ${slideIndex} key pressed:`, event.key, "Target:", event.target);
2549
- }
2550
- if (!slideRef.current) {
2551
- if (scrollConfig.enableDebugLogging) {
2552
- console.log("❌ slideRef.current is null");
2553
- }
2554
- return;
2555
- }
2556
- const container = slideRef.current;
2557
- const scrollInfo = {
2558
- scrollTop: container.scrollTop,
2559
- scrollHeight: container.scrollHeight,
2560
- clientHeight: container.clientHeight,
2561
- canScroll: container.scrollHeight > container.clientHeight,
2562
- maxScroll: container.scrollHeight - container.clientHeight
2563
- };
2564
- if (scrollConfig.enableDebugLogging) {
2565
- console.log(`\uD83D\uDCCA Slide ${slideIndex} Scroll Info:`, scrollInfo);
2566
- let parent = container.parentElement;
2567
- let level = 1;
2568
- while (parent && level <= 3) {
2569
- const parentScrollInfo = {
2570
- level,
2571
- tagName: parent.tagName,
2572
- className: parent.className,
2573
- scrollTop: parent.scrollTop,
2574
- scrollHeight: parent.scrollHeight,
2575
- clientHeight: parent.clientHeight,
2576
- canScroll: parent.scrollHeight > parent.clientHeight,
2577
- overflowY: getComputedStyle(parent).overflowY
2578
- };
2579
- console.log(`\uD83D\uDCCA Slide ${slideIndex} Parent ${level} Info:`, parentScrollInfo);
2580
- parent = parent.parentElement;
2581
- level++;
2582
- }
2583
- }
2584
- const isScrollDown = scrollConfig.keys.scrollDown.includes(event.key);
2585
- const isScrollUp = scrollConfig.keys.scrollUp.includes(event.key);
2586
- const isPageDown = scrollConfig.keys.pageDown.includes(event.key);
2587
- const isPageUp = scrollConfig.keys.pageUp.includes(event.key);
2588
- if (!isScrollDown && !isScrollUp && !isPageDown && !isPageUp) {
2589
- return;
2590
- }
2591
- let scrollTarget = container;
2592
- if (!scrollInfo.canScroll) {
2593
- let parent = container.parentElement;
2594
- while (parent) {
2595
- if (parent.scrollHeight > parent.clientHeight) {
2596
- if (scrollConfig.enableDebugLogging) {
2597
- console.log(`\uD83C\uDFAF Slide ${slideIndex} Found scrollable parent:`, parent.tagName, parent.className);
2598
- }
2599
- scrollTarget = parent;
2600
- break;
2601
- }
2602
- parent = parent.parentElement;
2603
- }
2604
- }
2605
- if (scrollTarget.scrollHeight <= scrollTarget.clientHeight) {
2606
- if (scrollConfig.enableDebugLogging) {
2607
- console.log(`⚠️ Slide ${slideIndex} Cannot scroll - content fits in container`);
2608
- }
2609
- return;
2610
- }
2611
- event.preventDefault();
2612
- event.stopPropagation();
2613
- let scrollAmount = 0;
2614
- if (isScrollDown) {
2615
- if (scrollConfig.enableDebugLogging) {
2616
- console.log(`⬇️ Slide ${slideIndex} Scroll down pressed`);
2617
- }
2618
- scrollAmount = scrollConfig.scrollAmount;
2619
- } else if (isScrollUp) {
2620
- if (scrollConfig.enableDebugLogging) {
2621
- console.log(`⬆️ Slide ${slideIndex} Scroll up pressed`);
2622
- }
2623
- scrollAmount = -scrollConfig.scrollAmount;
2624
- } else if (isPageDown) {
2625
- if (scrollConfig.enableDebugLogging) {
2626
- console.log(`\uD83D\uDCC4⬇️ Slide ${slideIndex} Page down pressed`);
2627
- }
2628
- scrollAmount = scrollTarget.clientHeight * scrollConfig.pageScrollRatio;
2629
- } else if (isPageUp) {
2630
- if (scrollConfig.enableDebugLogging) {
2631
- console.log(`\uD83D\uDCC4⬆️ Slide ${slideIndex} Page up pressed`);
2632
- }
2633
- scrollAmount = -scrollTarget.clientHeight * scrollConfig.pageScrollRatio;
2634
- }
2635
- const beforeScroll = scrollTarget.scrollTop;
2636
- scrollTarget.scrollBy({
2637
- top: scrollAmount,
2638
- behavior: scrollConfig.smoothScroll ? "smooth" : "auto"
2639
- });
2640
- if (scrollConfig.enableDebugLogging) {
2641
- setTimeout(() => {
2642
- const afterScroll = scrollTarget.scrollTop;
2643
- console.log(`\uD83D\uDCC8 Slide ${slideIndex} Scroll: ${beforeScroll} → ${afterScroll} (diff: ${afterScroll - beforeScroll})`);
2644
- }, scrollConfig.smoothScroll ? 100 : 0);
2645
- }
2646
- }, [enableKeyboardScrolling, isVisible, slideIndex, scrollConfig]);
2647
- import_react11.useEffect(() => {
2648
- if (isVisible && slideRef.current) {
2649
- console.log("\uD83C\uDFAF Auto-focusing slide container");
2650
- slideRef.current.focus();
2651
- }
2652
- }, [isVisible]);
2653
- const openPlaceholderModal = (placeholders, promptContent) => {
2654
- if (!handlePromptCopy)
2655
- return;
2656
- setPlaceholderModalData({ placeholders, promptContent });
2657
- setPlaceholderModalOpen(true);
2658
- };
2659
- const closePlaceholderModal = () => {
2660
- setPlaceholderModalOpen(false);
2661
- setPlaceholderModalData(null);
2662
- };
2663
- const closeMermaidModal = () => {
2664
- setMermaidModalOpen(false);
2665
- setMermaidModalCode("");
2666
- };
2667
- let industryTheme;
2668
- try {
2669
- const themeContext = useTheme();
2670
- industryTheme = themeContext.theme;
2671
- } catch {
2672
- industryTheme = undefined;
2673
- }
2674
- const baseTheme = themeOverride || industryTheme;
2675
- if (!baseTheme) {
2676
- throw new Error("IndustryMarkdownSlide: theme must be provided as a prop when ThemeProvider is not available");
2677
- }
2678
- const theme2 = import_react11.useMemo(() => {
2679
- if (fontSizeScale === 1)
2680
- return baseTheme;
2681
- return {
2682
- ...baseTheme,
2683
- fontSizes: baseTheme.fontSizes.map((size) => Math.round(size * fontSizeScale))
2684
- };
2685
- }, [baseTheme, fontSizeScale]);
2686
- const calculateSlidePadding = import_react11.useMemo(() => {
2687
- const effectiveContainerWidth = containerWidth ?? measuredContainerWidth ?? 800;
2688
- const paddingPercentage = 0.03;
2689
- const horizontalPadding = Math.max(5, Math.round(effectiveContainerWidth * paddingPercentage));
2690
- const verticalPadding = Math.max(5, Math.round(effectiveContainerWidth * (paddingPercentage - 0.015)));
2691
- const result = {
2692
- vertical: `${verticalPadding}px`,
2693
- horizontal: `${horizontalPadding}px`
2694
- };
2695
- return result;
2696
- }, [containerWidth, measuredContainerWidth]);
2697
- import_react11.useEffect(() => {
2698
- const slideElement = slideRef.current;
2699
- if (slideElement) {
2700
- const handleScroll = () => {
2701
- scrollPositionRef.current = slideElement.scrollTop || 0;
2702
- };
2703
- slideElement.addEventListener("scroll", handleScroll);
2704
- return () => {
2705
- slideElement.removeEventListener("scroll", handleScroll);
2706
- };
2707
- }
2708
- return;
2709
- }, []);
2710
- import_react11.useEffect(() => {
2711
- if (slideRef.current && scrollPositionRef.current) {
2712
- slideRef.current.scrollTop = scrollPositionRef.current;
2713
- }
2714
- }, [content]);
2715
- const sanitizeSchema = import_react11.useMemo(() => ({
2716
- ...import_hast_util_sanitize.defaultSchema,
2717
- tagNames: [...import_hast_util_sanitize.defaultSchema.tagNames || [], "picture", "source"],
2718
- attributes: {
2719
- ...import_hast_util_sanitize.defaultSchema.attributes,
2720
- code: [...import_hast_util_sanitize.defaultSchema.attributes?.code || [], "className", "style"],
2721
- span: [...import_hast_util_sanitize.defaultSchema.attributes?.span || [], "className", "style"],
2722
- pre: [...import_hast_util_sanitize.defaultSchema.attributes?.pre || [], "className", "style"],
2723
- div: [...import_hast_util_sanitize.defaultSchema.attributes?.div || [], "style", "className", "id"],
2724
- p: [...import_hast_util_sanitize.defaultSchema.attributes?.p || [], "style", "className", "id"],
2725
- h1: [...import_hast_util_sanitize.defaultSchema.attributes?.h1 || [], "style", "className", "id"],
2726
- h2: [...import_hast_util_sanitize.defaultSchema.attributes?.h2 || [], "style", "className", "id"],
2727
- h3: [...import_hast_util_sanitize.defaultSchema.attributes?.h3 || [], "style", "className", "id"],
2728
- h4: [...import_hast_util_sanitize.defaultSchema.attributes?.h4 || [], "style", "className", "id"],
2729
- h5: [...import_hast_util_sanitize.defaultSchema.attributes?.h5 || [], "style", "className", "id"],
2730
- h6: [...import_hast_util_sanitize.defaultSchema.attributes?.h6 || [], "style", "className", "id"],
2731
- strong: [...import_hast_util_sanitize.defaultSchema.attributes?.strong || [], "style", "className"],
2732
- em: [...import_hast_util_sanitize.defaultSchema.attributes?.em || [], "style", "className"],
2733
- ul: [...import_hast_util_sanitize.defaultSchema.attributes?.ul || [], "style", "className"],
2734
- ol: [...import_hast_util_sanitize.defaultSchema.attributes?.ol || [], "style", "className"],
2735
- li: [...import_hast_util_sanitize.defaultSchema.attributes?.li || [], "style", "className"],
2736
- a: [...import_hast_util_sanitize.defaultSchema.attributes?.a || [], "style", "className"],
2737
- img: [...import_hast_util_sanitize.defaultSchema.attributes?.img || [], "style", "className"],
2738
- picture: [...import_hast_util_sanitize.defaultSchema.attributes?.picture || [], "style", "className"],
2739
- source: [
2740
- ...import_hast_util_sanitize.defaultSchema.attributes?.source || [],
2741
- "srcSet",
2742
- "media",
2743
- "type",
2744
- "sizes",
2745
- "style",
2746
- "className"
2747
- ],
2748
- table: [...import_hast_util_sanitize.defaultSchema.attributes?.table || [], "style", "className"],
2749
- thead: [...import_hast_util_sanitize.defaultSchema.attributes?.thead || [], "style", "className"],
2750
- tbody: [...import_hast_util_sanitize.defaultSchema.attributes?.tbody || [], "style", "className"],
2751
- tr: [...import_hast_util_sanitize.defaultSchema.attributes?.tr || [], "style", "className"],
2752
- th: [...import_hast_util_sanitize.defaultSchema.attributes?.th || [], "style", "className"],
2753
- td: [...import_hast_util_sanitize.defaultSchema.attributes?.td || [], "style", "className"],
2754
- blockquote: [...import_hast_util_sanitize.defaultSchema.attributes?.blockquote || [], "style", "className"],
2755
- hr: [...import_hast_util_sanitize.defaultSchema.attributes?.hr || [], "style", "className"],
2756
- label: [...import_hast_util_sanitize.defaultSchema.attributes?.label || [], "style", "className", "for"],
2757
- input: [...import_hast_util_sanitize.defaultSchema.attributes?.input || [], "style", "className", "type", "placeholder", "value", "checked", "disabled"],
2758
- button: [...import_hast_util_sanitize.defaultSchema.attributes?.button || [], "style", "className", "type", "disabled"],
2759
- details: [...import_hast_util_sanitize.defaultSchema.attributes?.details || [], "style", "className", "open"],
2760
- summary: [...import_hast_util_sanitize.defaultSchema.attributes?.summary || [], "style", "className"],
2761
- footer: [...import_hast_util_sanitize.defaultSchema.attributes?.footer || [], "style", "className"],
2762
- header: [...import_hast_util_sanitize.defaultSchema.attributes?.header || [], "style", "className"],
2763
- section: [...import_hast_util_sanitize.defaultSchema.attributes?.section || [], "style", "className"]
2764
- }
2765
- }), []);
2766
- const rootMargin = isVisible ? "0px" : "100px";
2767
- const getMarkdownComponents = import_react11.useCallback((chunkIndex) => {
2768
- return createIndustryMarkdownComponents({
2769
- theme: theme2,
2770
- slideIdPrefix,
2771
- slideIndex,
2772
- onLinkClick,
2773
- onCheckboxChange,
2774
- checkedItems,
2775
- setCheckedItems,
2776
- openHtmlModal,
2777
- openPlaceholderModal: handlePromptCopy ? openPlaceholderModal : undefined,
2778
- handleRunBashCommand,
2779
- enableHtmlPopout,
2780
- slideHeaderMarginTopOverride,
2781
- index: chunkIndex,
2782
- repositoryInfo
2783
- });
2784
- }, [
2785
- theme2,
2786
- slideIdPrefix,
2787
- slideIndex,
2788
- onLinkClick,
2789
- onCheckboxChange,
2790
- checkedItems,
2791
- setCheckedItems,
2792
- openHtmlModal,
2793
- handlePromptCopy,
2794
- handleRunBashCommand,
2795
- enableHtmlPopout,
2796
- slideHeaderMarginTopOverride,
2797
- repositoryInfo
2798
- ]);
2799
- return /* @__PURE__ */ import_react11.default.createElement("div", {
2800
- className: "markdown-slide",
2801
- ref: slideRef,
2802
- style: {
2803
- height: "100%",
2804
- overflowY: "auto",
2805
- overflowX: "hidden",
2806
- position: "relative",
2807
- backgroundColor: theme2.colors.background,
2808
- color: theme2.colors.text,
2809
- fontFamily: theme2.fonts.body,
2810
- padding: `${calculateSlidePadding.horizontal}`,
2811
- outline: "none",
2812
- border: "2px solid transparent",
2813
- transition: "border-color 0.2s ease"
2814
- },
2815
- tabIndex: 0,
2816
- onKeyDown: handleKeyDown,
2817
- onClick: () => {
2818
- if (slideRef.current) {
2819
- slideRef.current.focus();
2820
- }
2821
- }
2822
- }, chunks.length === 0 ? /* @__PURE__ */ import_react11.default.createElement("div", {
2823
- style: {
2824
- padding: theme2.space[4],
2825
- textAlign: "center",
2826
- color: theme2.colors.muted,
2827
- fontSize: theme2.fontSizes[2]
2828
- }
2829
- }, "No content to display") : chunks.map((chunk, index) => {
2830
- if (chunk.type === "markdown_chunk") {
2831
- return /* @__PURE__ */ import_react11.default.createElement(import_react_markdown.default, {
2832
- key: chunk.id,
2833
- remarkPlugins: [import_remark_gfm.default],
2834
- rehypePlugins: [
2835
- import_rehype_raw.default,
2836
- [import_rehype_sanitize.default, sanitizeSchema],
2837
- import_rehype_slug.default,
2838
- import_rehype_highlight.default
2839
- ],
2840
- components: getMarkdownComponents(index)
2841
- }, chunk.content);
2842
- }
2843
- if (chunk.type === "mermaid_chunk") {
2844
- const mermaidProps = {
2845
- id: chunk.id,
2846
- code: chunk.code,
2847
- onCopyError: onCopyMermaidError,
2848
- rootMargin,
2849
- theme: theme2
2850
- };
2851
- if (onShowMermaidInPanel) {
2852
- mermaidProps.onShowInPanel = onShowMermaidInPanel;
2853
- }
2854
- return /* @__PURE__ */ import_react11.default.createElement(IndustryLazyMermaidDiagram, {
2855
- key: chunk.id,
2856
- ...mermaidProps
2857
- });
2858
- }
2859
- return null;
2860
- }), /* @__PURE__ */ import_react11.default.createElement(IndustryHtmlModal, {
2861
- isOpen: htmlModalOpen,
2862
- onClose: closeHtmlModal,
2863
- htmlContent: htmlModalContent,
2864
- theme: theme2
2865
- }), /* @__PURE__ */ import_react11.default.createElement(IndustryMermaidModal, {
2866
- isOpen: mermaidModalOpen,
2867
- onClose: closeMermaidModal,
2868
- mermaidCode: mermaidModalCode,
2869
- theme: theme2
2870
- }), handlePromptCopy && placeholderModalData && /* @__PURE__ */ import_react11.default.createElement(IndustryPlaceholderModal, {
2871
- isOpen: placeholderModalOpen,
2872
- onClose: closePlaceholderModal,
2873
- placeholders: placeholderModalData.placeholders,
2874
- promptContent: placeholderModalData.promptContent,
2875
- onCopy: handlePromptCopy,
2876
- theme: theme2
2877
- }));
2878
- });
2879
- // industryMarkdown/components/SlidePresentation.tsx
2880
- var import_lucide_react5 = require("lucide-react");
2881
- var import_react12 = __toESM(require("react"));
2882
- var SlidePresentation = ({
2883
- slides,
2884
- initialSlide = 0,
2885
- onSlideChange,
2886
- onCheckboxChange,
2887
- showNavigation = true,
2888
- showSlideCounter = true,
2889
- showFullscreenButton = false,
2890
- containerHeight = "100%",
2891
- slideIdPrefix = "slide",
2892
- enableHtmlPopout = true,
2893
- enableKeyboardScrolling = true,
2894
- onLinkClick,
2895
- handleRunBashCommand,
2896
- handlePromptCopy,
2897
- fontSizeScale
2898
- }) => {
2899
- const [currentSlide, setCurrentSlide] = import_react12.useState(initialSlide);
2900
- const [isFullscreen, setIsFullscreen] = import_react12.useState(false);
2901
- const containerRef = import_react12.useRef(null);
2902
- const { theme: theme2 } = useTheme();
2903
- const navigateToSlide = import_react12.useCallback((slideIndex) => {
2904
- if (slideIndex >= 0 && slideIndex < slides.length) {
2905
- setCurrentSlide(slideIndex);
2906
- onSlideChange?.(slideIndex);
2907
- }
2908
- }, [slides.length, onSlideChange]);
2909
- const goToPreviousSlide = import_react12.useCallback(() => {
2910
- navigateToSlide(currentSlide - 1);
2911
- }, [currentSlide, navigateToSlide]);
2912
- const goToNextSlide = import_react12.useCallback(() => {
2913
- navigateToSlide(currentSlide + 1);
2914
- }, [currentSlide, navigateToSlide]);
2915
- const toggleFullscreen = import_react12.useCallback(() => {
2916
- if (!containerRef.current)
2917
- return;
2918
- if (!isFullscreen) {
2919
- containerRef.current.requestFullscreen?.();
2920
- setIsFullscreen(true);
2921
- } else {
2922
- document.exitFullscreen?.();
2923
- setIsFullscreen(false);
2924
- }
2925
- }, [isFullscreen]);
2926
- import_react12.useEffect(() => {
2927
- const handleKeyDown = (event) => {
2928
- if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) {
2929
- return;
2930
- }
2931
- switch (event.key) {
2932
- case "ArrowLeft":
2933
- event.preventDefault();
2934
- goToPreviousSlide();
2935
- break;
2936
- case "ArrowRight":
2937
- event.preventDefault();
2938
- goToNextSlide();
2939
- break;
2940
- case " ":
2941
- event.preventDefault();
2942
- goToNextSlide();
2943
- break;
2944
- case "Enter":
2945
- event.preventDefault();
2946
- goToNextSlide();
2947
- break;
2948
- case "Backspace":
2949
- event.preventDefault();
2950
- goToPreviousSlide();
2951
- break;
2952
- case "Home":
2953
- event.preventDefault();
2954
- navigateToSlide(0);
2955
- break;
2956
- case "End":
2957
- event.preventDefault();
2958
- navigateToSlide(slides.length - 1);
2959
- break;
2960
- case "f":
2961
- case "F":
2962
- if (!event.ctrlKey && !event.metaKey && !event.altKey) {
2963
- event.preventDefault();
2964
- toggleFullscreen();
2965
- }
2966
- break;
2967
- }
2968
- if (!event.ctrlKey && !event.metaKey && !event.altKey) {
2969
- const num = parseInt(event.key);
2970
- if (num >= 1 && num <= 9 && num <= slides.length) {
2971
- event.preventDefault();
2972
- navigateToSlide(num - 1);
2973
- }
2974
- }
2975
- };
2976
- window.addEventListener("keydown", handleKeyDown);
2977
- return () => window.removeEventListener("keydown", handleKeyDown);
2978
- }, [goToPreviousSlide, goToNextSlide, navigateToSlide, slides.length, toggleFullscreen]);
2979
- import_react12.useEffect(() => {
2980
- if (currentSlide >= slides.length && slides.length > 0) {
2981
- setCurrentSlide(slides.length - 1);
2982
- }
2983
- }, [slides.length, currentSlide]);
2984
- const navigationHeight = showNavigation ? "48px" : "0px";
2985
- return /* @__PURE__ */ import_react12.default.createElement("div", {
2986
- ref: containerRef,
2987
- style: {
2988
- height: containerHeight,
2989
- display: "flex",
2990
- flexDirection: "column",
2991
- backgroundColor: theme2.colors.background,
2992
- position: "relative"
2993
- }
2994
- }, showNavigation && /* @__PURE__ */ import_react12.default.createElement("div", {
2995
- style: {
2996
- height: navigationHeight,
2997
- minHeight: navigationHeight,
2998
- display: "flex",
2999
- alignItems: "center",
3000
- justifyContent: "space-between",
3001
- padding: `0 ${theme2.space[3]}px`,
3002
- borderBottom: `1px solid ${theme2.colors.border}`,
3003
- backgroundColor: theme2.colors.background,
3004
- flexShrink: 0
3005
- }
3006
- }, /* @__PURE__ */ import_react12.default.createElement("button", {
3007
- onClick: goToPreviousSlide,
3008
- disabled: currentSlide === 0,
3009
- style: {
3010
- display: "flex",
3011
- alignItems: "center",
3012
- gap: theme2.space[1],
3013
- padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
3014
- backgroundColor: "transparent",
3015
- border: `1px solid ${theme2.colors.border}`,
3016
- borderRadius: theme2.radii[1],
3017
- color: currentSlide === 0 ? theme2.colors.muted : theme2.colors.text,
3018
- cursor: currentSlide === 0 ? "not-allowed" : "pointer",
3019
- fontSize: theme2.fontSizes[1],
3020
- fontFamily: theme2.fonts.body,
3021
- opacity: currentSlide === 0 ? 0.5 : 1,
3022
- transition: "all 0.2s ease"
3023
- },
3024
- onMouseOver: (e) => {
3025
- if (currentSlide !== 0) {
3026
- e.currentTarget.style.backgroundColor = theme2.colors.backgroundSecondary;
3027
- }
3028
- },
3029
- onMouseOut: (e) => {
3030
- e.currentTarget.style.backgroundColor = "transparent";
3031
- }
3032
- }, /* @__PURE__ */ import_react12.default.createElement(import_lucide_react5.ChevronLeft, {
3033
- size: 16
3034
- }), "Previous"), showSlideCounter && /* @__PURE__ */ import_react12.default.createElement("div", {
3035
- style: {
3036
- display: "flex",
3037
- alignItems: "center",
3038
- gap: theme2.space[2],
3039
- color: theme2.colors.textSecondary,
3040
- fontSize: theme2.fontSizes[1],
3041
- fontFamily: theme2.fonts.monospace
3042
- }
3043
- }, /* @__PURE__ */ import_react12.default.createElement("span", {
3044
- style: { fontWeight: 600 }
3045
- }, "Slide ", currentSlide + 1), /* @__PURE__ */ import_react12.default.createElement("span", {
3046
- style: { opacity: 0.7 }
3047
- }, "of ", slides.length), /* @__PURE__ */ import_react12.default.createElement("select", {
3048
- value: currentSlide,
3049
- onChange: (e) => navigateToSlide(Number(e.target.value)),
3050
- style: {
3051
- marginLeft: theme2.space[2],
3052
- padding: `${theme2.space[0]}px ${theme2.space[1]}px`,
3053
- backgroundColor: theme2.colors.backgroundSecondary,
3054
- border: `1px solid ${theme2.colors.border}`,
3055
- borderRadius: theme2.radii[0],
3056
- color: theme2.colors.text,
3057
- fontSize: theme2.fontSizes[0],
3058
- fontFamily: theme2.fonts.monospace,
3059
- cursor: "pointer"
3060
- }
3061
- }, slides.map((_, index) => /* @__PURE__ */ import_react12.default.createElement("option", {
3062
- key: index,
3063
- value: index
3064
- }, index + 1)))), /* @__PURE__ */ import_react12.default.createElement("div", {
3065
- style: {
3066
- display: "flex",
3067
- alignItems: "center",
3068
- gap: theme2.space[2]
3069
- }
3070
- }, showFullscreenButton && /* @__PURE__ */ import_react12.default.createElement("button", {
3071
- onClick: toggleFullscreen,
3072
- style: {
3073
- display: "flex",
3074
- alignItems: "center",
3075
- justifyContent: "center",
3076
- width: "32px",
3077
- height: "32px",
3078
- backgroundColor: "transparent",
3079
- border: `1px solid ${theme2.colors.border}`,
3080
- borderRadius: theme2.radii[1],
3081
- color: theme2.colors.textSecondary,
3082
- cursor: "pointer",
3083
- transition: "all 0.2s ease"
3084
- },
3085
- onMouseOver: (e) => {
3086
- e.currentTarget.style.backgroundColor = theme2.colors.backgroundSecondary;
3087
- },
3088
- onMouseOut: (e) => {
3089
- e.currentTarget.style.backgroundColor = "transparent";
3090
- },
3091
- title: isFullscreen ? "Exit fullscreen" : "Enter fullscreen"
3092
- }, isFullscreen ? /* @__PURE__ */ import_react12.default.createElement(import_lucide_react5.Minimize2, {
3093
- size: 16
3094
- }) : /* @__PURE__ */ import_react12.default.createElement(import_lucide_react5.Maximize2, {
3095
- size: 16
3096
- })), /* @__PURE__ */ import_react12.default.createElement("button", {
3097
- onClick: goToNextSlide,
3098
- disabled: currentSlide === slides.length - 1,
3099
- style: {
3100
- display: "flex",
3101
- alignItems: "center",
3102
- gap: theme2.space[1],
3103
- padding: `${theme2.space[1]}px ${theme2.space[2]}px`,
3104
- backgroundColor: "transparent",
3105
- border: `1px solid ${theme2.colors.border}`,
3106
- borderRadius: theme2.radii[1],
3107
- color: currentSlide === slides.length - 1 ? theme2.colors.muted : theme2.colors.text,
3108
- cursor: currentSlide === slides.length - 1 ? "not-allowed" : "pointer",
3109
- fontSize: theme2.fontSizes[1],
3110
- fontFamily: theme2.fonts.body,
3111
- opacity: currentSlide === slides.length - 1 ? 0.5 : 1,
3112
- transition: "all 0.2s ease"
3113
- },
3114
- onMouseOver: (e) => {
3115
- if (currentSlide !== slides.length - 1) {
3116
- e.currentTarget.style.backgroundColor = theme2.colors.backgroundSecondary;
3117
- }
3118
- },
3119
- onMouseOut: (e) => {
3120
- e.currentTarget.style.backgroundColor = "transparent";
3121
- }
3122
- }, "Next", /* @__PURE__ */ import_react12.default.createElement(import_lucide_react5.ChevronRight, {
3123
- size: 16
3124
- })))), /* @__PURE__ */ import_react12.default.createElement("div", {
3125
- style: {
3126
- flex: 1,
3127
- overflow: "hidden",
3128
- position: "relative"
3129
- }
3130
- }, slides.length > 0 ? /* @__PURE__ */ import_react12.default.createElement(IndustryMarkdownSlide, {
3131
- content: slides[currentSlide] || "",
3132
- slideIdPrefix: `${slideIdPrefix}-${currentSlide}`,
3133
- slideIndex: currentSlide,
3134
- isVisible: true,
3135
- theme: theme2,
3136
- onCheckboxChange,
3137
- enableHtmlPopout,
3138
- enableKeyboardScrolling,
3139
- onLinkClick,
3140
- handleRunBashCommand,
3141
- handlePromptCopy,
3142
- fontSizeScale
3143
- }) : /* @__PURE__ */ import_react12.default.createElement("div", {
3144
- style: {
3145
- height: "100%",
3146
- display: "flex",
3147
- alignItems: "center",
3148
- justifyContent: "center",
3149
- color: theme2.colors.muted,
3150
- fontSize: theme2.fontSizes[2],
3151
- fontFamily: theme2.fonts.body
3152
- }
3153
- }, "No slides available")), showNavigation && slides.length > 1 && /* @__PURE__ */ import_react12.default.createElement("div", {
3154
- style: {
3155
- position: "absolute",
3156
- bottom: 0,
3157
- left: 0,
3158
- right: 0,
3159
- height: "2px",
3160
- backgroundColor: theme2.colors.border,
3161
- opacity: 0.3
3162
- }
3163
- }, /* @__PURE__ */ import_react12.default.createElement("div", {
3164
- style: {
3165
- height: "100%",
3166
- width: `${(currentSlide + 1) / slides.length * 100}%`,
3167
- backgroundColor: theme2.colors.primary,
3168
- transition: "width 0.3s ease"
3169
- }
3170
- })));
3171
- };
3172
- // industryMarkdown/components/DocumentView.tsx
3173
- var import_react13 = __toESM(require("react"));
3174
- var DocumentView = ({
3175
- content,
3176
- showSegmented = true,
3177
- onCheckboxChange,
3178
- onSectionClick,
3179
- maxWidth = "900px",
3180
- padding = "24px",
3181
- showSectionHeaders = true,
3182
- showSeparators = true,
3183
- slideIdPrefix = "document",
3184
- enableHtmlPopout = true,
3185
- enableKeyboardScrolling = true,
3186
- onLinkClick,
3187
- handleRunBashCommand,
3188
- handlePromptCopy,
3189
- repositoryInfo,
3190
- fontSizeScale
3191
- }) => {
3192
- const containerRef = import_react13.useRef(null);
3193
- const sectionRefs = import_react13.useRef([]);
3194
- const { theme: theme2 } = useTheme();
3195
- const scrollToSection = import_react13.useCallback((sectionIndex) => {
3196
- if (sectionRefs.current[sectionIndex]) {
3197
- sectionRefs.current[sectionIndex]?.scrollIntoView({
3198
- behavior: "smooth",
3199
- block: "start"
3200
- });
3201
- }
3202
- }, []);
3203
- const handleSectionClick = import_react13.useCallback((index) => {
3204
- scrollToSection(index);
3205
- onSectionClick?.(index);
3206
- }, [scrollToSection, onSectionClick]);
3207
- if (typeof content === "string") {
3208
- return /* @__PURE__ */ import_react13.default.createElement("div", {
3209
- ref: containerRef,
3210
- style: {
3211
- height: "100%",
3212
- overflow: "auto",
3213
- backgroundColor: theme2.colors.background,
3214
- padding: typeof padding === "number" ? `${padding}px` : padding
3215
- }
3216
- }, /* @__PURE__ */ import_react13.default.createElement("div", {
3217
- style: {
3218
- maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth,
3219
- margin: "0 auto"
3220
- }
3221
- }, /* @__PURE__ */ import_react13.default.createElement(IndustryMarkdownSlide, {
3222
- content,
3223
- slideIdPrefix,
3224
- slideIndex: 0,
3225
- isVisible: true,
3226
- theme: theme2,
3227
- onCheckboxChange,
3228
- enableHtmlPopout,
3229
- enableKeyboardScrolling,
3230
- onLinkClick,
3231
- handleRunBashCommand,
3232
- fontSizeScale,
3233
- handlePromptCopy,
3234
- repositoryInfo
3235
- })));
3236
- }
3237
- if (!showSegmented) {
3238
- const fullContent = content.join(`
3239
-
3240
- ---
3241
-
3242
- `);
3243
- return /* @__PURE__ */ import_react13.default.createElement("div", {
3244
- ref: containerRef,
3245
- style: {
3246
- height: "100%",
3247
- overflow: "auto",
3248
- backgroundColor: theme2.colors.background,
3249
- padding: typeof padding === "number" ? `${padding}px` : padding
3250
- }
3251
- }, /* @__PURE__ */ import_react13.default.createElement("div", {
3252
- style: {
3253
- maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth,
3254
- margin: "0 auto"
3255
- }
3256
- }, /* @__PURE__ */ import_react13.default.createElement(IndustryMarkdownSlide, {
3257
- content: fullContent,
3258
- slideIdPrefix,
3259
- slideIndex: 0,
3260
- isVisible: true,
3261
- theme: theme2,
3262
- onCheckboxChange,
3263
- enableHtmlPopout,
3264
- enableKeyboardScrolling,
3265
- onLinkClick,
3266
- handleRunBashCommand,
3267
- fontSizeScale,
3268
- handlePromptCopy,
3269
- repositoryInfo
3270
- })));
3271
- }
3272
- return /* @__PURE__ */ import_react13.default.createElement("div", {
3273
- ref: containerRef,
3274
- style: {
3275
- height: "100%",
3276
- overflow: "auto",
3277
- backgroundColor: theme2.colors.background,
3278
- padding: typeof padding === "number" ? `${padding}px` : padding
3279
- }
3280
- }, /* @__PURE__ */ import_react13.default.createElement("div", {
3281
- style: {
3282
- maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth,
3283
- margin: "0 auto"
3284
- }
3285
- }, content.map((slideContent, index) => /* @__PURE__ */ import_react13.default.createElement("div", {
3286
- key: index,
3287
- ref: (el) => {
3288
- if (el)
3289
- sectionRefs.current[index] = el;
3290
- },
3291
- style: {
3292
- marginBottom: index < content.length - 1 ? "48px" : "0",
3293
- scrollMarginTop: "20px"
3294
- }
3295
- }, showSectionHeaders && /* @__PURE__ */ import_react13.default.createElement("div", {
3296
- onClick: () => handleSectionClick(index),
3297
- style: {
3298
- display: "flex",
3299
- alignItems: "center",
3300
- justifyContent: "space-between",
3301
- marginBottom: "16px",
3302
- paddingBottom: "8px",
3303
- borderBottom: `1px solid ${theme2.colors.border}`,
3304
- opacity: 0.7,
3305
- cursor: "pointer",
3306
- transition: "opacity 0.2s ease"
3307
- },
3308
- onMouseOver: (e) => {
3309
- e.currentTarget.style.opacity = "1";
3310
- },
3311
- onMouseOut: (e) => {
3312
- e.currentTarget.style.opacity = "0.7";
3313
- }
3314
- }, /* @__PURE__ */ import_react13.default.createElement("span", {
3315
- style: {
3316
- fontSize: "11px",
3317
- fontWeight: 600,
3318
- color: theme2.colors.textSecondary,
3319
- textTransform: "uppercase",
3320
- letterSpacing: "0.5px"
3321
- }
3322
- }, "Section ", index + 1, " of ", content.length)), /* @__PURE__ */ import_react13.default.createElement(IndustryMarkdownSlide, {
3323
- content: slideContent,
3324
- slideIdPrefix: `${slideIdPrefix}-${index}`,
3325
- slideIndex: index,
3326
- isVisible: true,
3327
- theme: theme2,
3328
- onCheckboxChange,
3329
- enableHtmlPopout,
3330
- enableKeyboardScrolling,
3331
- onLinkClick,
3332
- handleRunBashCommand,
3333
- fontSizeScale,
3334
- handlePromptCopy,
3335
- repositoryInfo
3336
- }), showSeparators && index < content.length - 1 && /* @__PURE__ */ import_react13.default.createElement("div", {
3337
- style: {
3338
- marginTop: "32px",
3339
- marginBottom: "32px",
3340
- height: "1px",
3341
- backgroundColor: theme2.colors.border,
3342
- opacity: 0.3
3343
- }
3344
- })))));
3345
- };
3346
- // industryMarkdown/components/IndustryEditableMarkdownSlide.tsx
3347
- var import_lucide_react6 = require("lucide-react");
3348
- var import_react14 = __toESM(require("react"));
3349
- var IndustryEditableMarkdownSlide = ({
3350
- content,
3351
- onContentChange,
3352
- onSave,
3353
- autoSaveDelay = 1000,
3354
- editable = true,
3355
- showEditButton = true,
3356
- theme: themeProp,
3357
- ...slideProps
3358
- }) => {
3359
- let contextTheme;
3360
- try {
3361
- const themeContext = useTheme();
3362
- contextTheme = themeContext.theme;
3363
- } catch {}
3364
- const theme2 = themeProp || contextTheme;
3365
- if (!theme2) {
3366
- throw new Error("IndustryEditableMarkdownSlide: theme must be provided either as a prop or through ThemeProvider");
3367
- }
3368
- const [isEditing, setIsEditing] = import_react14.useState(false);
3369
- const [editContent, setEditContent] = import_react14.useState(content);
3370
- const [isSaving, setIsSaving] = import_react14.useState(false);
3371
- const textareaRef = import_react14.useRef(null);
3372
- const saveTimeoutRef = import_react14.useRef(undefined);
3373
- import_react14.useEffect(() => {
3374
- setEditContent(content);
3375
- }, [content]);
3376
- import_react14.useEffect(() => {
3377
- if (isEditing && autoSaveDelay && onSave) {
3378
- if (saveTimeoutRef.current) {
3379
- clearTimeout(saveTimeoutRef.current);
3380
- }
3381
- saveTimeoutRef.current = setTimeout(() => {
3382
- handleSave(false);
3383
- }, autoSaveDelay);
3384
- }
3385
- return () => {
3386
- if (saveTimeoutRef.current) {
3387
- clearTimeout(saveTimeoutRef.current);
3388
- }
3389
- };
3390
- }, [editContent, isEditing, autoSaveDelay]);
3391
- const handleEdit = import_react14.useCallback(() => {
3392
- setIsEditing(true);
3393
- setTimeout(() => {
3394
- textareaRef.current?.focus();
3395
- textareaRef.current?.setSelectionRange(0, 0);
3396
- }, 100);
3397
- }, []);
3398
- const handleCancel = import_react14.useCallback(() => {
3399
- setEditContent(content);
3400
- setIsEditing(false);
3401
- }, [content]);
3402
- const handleSave = import_react14.useCallback(async (exitEditMode = true) => {
3403
- if (onContentChange) {
3404
- onContentChange(editContent);
3405
- }
3406
- if (onSave) {
3407
- setIsSaving(true);
3408
- try {
3409
- await onSave(editContent);
3410
- } catch (error) {
3411
- console.error("Failed to save:", error);
3412
- } finally {
3413
- setIsSaving(false);
3414
- }
3415
- }
3416
- if (exitEditMode) {
3417
- setIsEditing(false);
3418
- }
3419
- }, [editContent, onContentChange, onSave]);
3420
- const handleKeyDown = import_react14.useCallback((e) => {
3421
- if (e.key === "Escape") {
3422
- handleCancel();
3423
- } else if ((e.metaKey || e.ctrlKey) && e.key === "s") {
3424
- e.preventDefault();
3425
- handleSave();
3426
- }
3427
- }, [handleCancel, handleSave]);
3428
- const handleTextareaChange = import_react14.useCallback((e) => {
3429
- const textarea = e.target;
3430
- setEditContent(textarea.value);
3431
- textarea.style.height = "auto";
3432
- textarea.style.height = `${textarea.scrollHeight}px`;
3433
- }, []);
3434
- if (isEditing) {
3435
- return /* @__PURE__ */ import_react14.default.createElement("div", {
3436
- style: {
3437
- height: "100%",
3438
- display: "flex",
3439
- flexDirection: "column",
3440
- backgroundColor: theme2.colors.background,
3441
- color: theme2.colors.text
3442
- }
3443
- }, /* @__PURE__ */ import_react14.default.createElement("div", {
3444
- style: {
3445
- display: "flex",
3446
- justifyContent: "space-between",
3447
- alignItems: "center",
3448
- padding: theme2.space[3],
3449
- borderBottom: `1px solid ${theme2.colors.border}`,
3450
- backgroundColor: theme2.colors.muted
3451
- }
3452
- }, /* @__PURE__ */ import_react14.default.createElement("div", {
3453
- style: {
3454
- display: "flex",
3455
- alignItems: "center",
3456
- gap: theme2.space[2],
3457
- fontSize: theme2.fontSizes[1],
3458
- color: theme2.colors.textSecondary
3459
- }
3460
- }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react6.Pencil, {
3461
- size: 16
3462
- }), /* @__PURE__ */ import_react14.default.createElement("span", null, "Editing Mode"), autoSaveDelay && /* @__PURE__ */ import_react14.default.createElement("span", null, "(Auto-save enabled)")), /* @__PURE__ */ import_react14.default.createElement("div", {
3463
- style: {
3464
- display: "flex",
3465
- gap: theme2.space[2]
3466
- }
3467
- }, /* @__PURE__ */ import_react14.default.createElement("button", {
3468
- onClick: () => handleSave(),
3469
- disabled: isSaving,
3470
- style: {
3471
- display: "flex",
3472
- alignItems: "center",
3473
- gap: theme2.space[1],
3474
- padding: `${theme2.space[1]}px ${theme2.space[3]}px`,
3475
- backgroundColor: theme2.colors.primary,
3476
- color: theme2.colors.background,
3477
- border: "none",
3478
- borderRadius: theme2.radii[1],
3479
- fontSize: theme2.fontSizes[1],
3480
- cursor: isSaving ? "not-allowed" : "pointer",
3481
- opacity: isSaving ? 0.7 : 1
3482
- }
3483
- }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react6.Save, {
3484
- size: 14
3485
- }), isSaving ? "Saving..." : "Save"), /* @__PURE__ */ import_react14.default.createElement("button", {
3486
- onClick: handleCancel,
3487
- style: {
3488
- display: "flex",
3489
- alignItems: "center",
3490
- gap: theme2.space[1],
3491
- padding: `${theme2.space[1]}px ${theme2.space[3]}px`,
3492
- backgroundColor: theme2.colors.secondary,
3493
- color: theme2.colors.text,
3494
- border: "none",
3495
- borderRadius: theme2.radii[1],
3496
- fontSize: theme2.fontSizes[1],
3497
- cursor: "pointer"
3498
- }
3499
- }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react6.X, {
3500
- size: 14
3501
- }), "Cancel"))), /* @__PURE__ */ import_react14.default.createElement("div", {
3502
- style: {
3503
- flex: 1,
3504
- padding: theme2.space[4],
3505
- overflow: "auto"
3506
- }
3507
- }, /* @__PURE__ */ import_react14.default.createElement("textarea", {
3508
- ref: textareaRef,
3509
- value: editContent,
3510
- onChange: handleTextareaChange,
3511
- onKeyDown: handleKeyDown,
3512
- style: {
3513
- width: "100%",
3514
- minHeight: "100%",
3515
- padding: theme2.space[3],
3516
- backgroundColor: theme2.colors.background,
3517
- color: theme2.colors.text,
3518
- border: `1px solid ${theme2.colors.border}`,
3519
- borderRadius: theme2.radii[2],
3520
- fontFamily: theme2.fonts.monospace,
3521
- fontSize: theme2.fontSizes[1],
3522
- lineHeight: theme2.lineHeights.relaxed,
3523
- resize: "none",
3524
- outline: "none"
3525
- },
3526
- placeholder: "Enter your markdown content here..."
3527
- })));
3528
- }
3529
- return /* @__PURE__ */ import_react14.default.createElement("div", {
3530
- style: { position: "relative", height: "100%" }
3531
- }, editable && showEditButton && /* @__PURE__ */ import_react14.default.createElement("button", {
3532
- onClick: handleEdit,
3533
- style: {
3534
- position: "absolute",
3535
- top: theme2.space[3],
3536
- right: theme2.space[3],
3537
- display: "flex",
3538
- alignItems: "center",
3539
- gap: theme2.space[1],
3540
- padding: `${theme2.space[1]}px ${theme2.space[3]}px`,
3541
- backgroundColor: theme2.colors.secondary,
3542
- color: theme2.colors.background,
3543
- border: "none",
3544
- borderRadius: theme2.radii[1],
3545
- fontSize: theme2.fontSizes[1],
3546
- cursor: "pointer",
3547
- zIndex: 10,
3548
- transition: "opacity 0.2s",
3549
- opacity: 0.8
3550
- },
3551
- onMouseEnter: (e) => e.currentTarget.style.opacity = "1",
3552
- onMouseLeave: (e) => e.currentTarget.style.opacity = "0.8"
3553
- }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react6.Pencil, {
3554
- size: 14
3555
- }), "Edit"), /* @__PURE__ */ import_react14.default.createElement(IndustryMarkdownSlide, {
3556
- ...slideProps,
3557
- content,
3558
- theme: theme2
3559
- }));
3560
- };
3561
- // industryMarkdown/utils/presentationUtils.ts
3562
- function hashMarkdownString2(str) {
3563
- let hash = 0;
3564
- for (let i = 0;i < str.length; i++) {
3565
- const char = str.charCodeAt(i);
3566
- hash = (hash << 5) - hash + char;
3567
- hash = hash & hash;
3568
- }
3569
- return Math.abs(hash).toString(36);
3570
- }
3571
- function extractSlideTitle(content) {
3572
- const lines = content.split(`
3573
- `).filter((line) => line.trim());
3574
- for (const line of lines) {
3575
- const headingMatch = line.match(/^#+\s+(.+)$/);
3576
- if (headingMatch) {
3577
- return headingMatch[1].trim();
3578
- }
3579
- }
3580
- if (lines.length > 0) {
3581
- const firstLine = lines[0];
3582
- return firstLine.length > 50 ? firstLine.substring(0, 47) + "..." : firstLine;
3583
- }
3584
- return "Untitled Slide";
3585
- }
3586
- function parseMarkdownIntoPresentationFromSource(source) {
3587
- let presentation;
3588
- switch (source.type) {
3589
- case "workspace_file" /* WORKSPACE_FILE */:
3590
- case "github_file" /* GITHUB_FILE */:
3591
- case "draft" /* DRAFT */:
3592
- presentation = parseMarkdownIntoPresentation(source.content);
3593
- break;
3594
- default:
3595
- throw new Error(`Unsupported source type: ${source.type}`);
3596
- }
3597
- presentation.source = source;
3598
- presentation.repositoryInfo = source.repositoryInfo;
3599
- return presentation;
3600
- }
3601
- function createGithubFileSource(content, repositoryInfo) {
3602
- return {
3603
- type: "github_file" /* GITHUB_FILE */,
3604
- content,
3605
- repositoryInfo,
3606
- editable: false,
3607
- deletable: false
3608
- };
3609
- }
3610
- function parseMarkdownIntoPresentation(markdownContent) {
3611
- try {
3612
- if (typeof markdownContent !== "string") {
3613
- console.error("Invalid markdown content provided - not a string");
3614
- return {
3615
- slides: [],
3616
- originalContent: "",
3617
- format: "full_content" /* FULL_CONTENT */
3618
- };
3619
- }
3620
- if (!markdownContent || markdownContent.trim() === "") {
3621
- return {
3622
- slides: [],
3623
- originalContent: "",
3624
- format: "full_content" /* FULL_CONTENT */
3625
- };
3626
- }
3627
- const slides = [];
3628
- let format = "full_content" /* FULL_CONTENT */;
3629
- let slideCounter = 0;
3630
- const headerMatches = Array.from(markdownContent.matchAll(/^(##\s+.*$)/gm));
3631
- if (headerMatches.length > 0) {
3632
- format = "header" /* HEADER */;
3633
- const firstHeaderStart = headerMatches[0].index;
3634
- const firstContent = markdownContent.substring(0, firstHeaderStart).trim();
3635
- if (firstContent) {
3636
- slideCounter++;
3637
- slides.push({
3638
- id: `slide-${slideCounter}-${hashMarkdownString2(firstContent)}`,
3639
- title: extractSlideTitle(firstContent),
3640
- location: {
3641
- startLine: 1,
3642
- endLine: firstContent.split(`
3643
- `).length,
3644
- content: firstContent,
3645
- type: "header" /* HEADER */
3646
- },
3647
- chunks: parseMarkdownChunks(firstContent, `slide-${slideCounter}`)
3648
- });
3649
- }
3650
- for (let i = 0;i < headerMatches.length; i++) {
3651
- const headerMatch = headerMatches[i];
3652
- const startIndex = headerMatch.index;
3653
- const endIndex = i < headerMatches.length - 1 ? headerMatches[i + 1].index : markdownContent.length;
3654
- const content = markdownContent.substring(startIndex, endIndex).trim();
3655
- if (content) {
3656
- slideCounter++;
3657
- const startLine = markdownContent.substring(0, startIndex).split(`
3658
- `).length;
3659
- const endLine = startLine + content.split(`
3660
- `).length - 1;
3661
- slides.push({
3662
- id: `slide-${slideCounter}-${hashMarkdownString2(content)}`,
3663
- title: extractSlideTitle(content),
3664
- location: {
3665
- startLine,
3666
- endLine,
3667
- content,
3668
- type: "header" /* HEADER */
3669
- },
3670
- chunks: parseMarkdownChunks(content, `slide-${slideCounter}`)
3671
- });
3672
- }
3673
- }
3674
- } else if (markdownContent.trim()) {
3675
- slideCounter++;
3676
- const trimmedContent = markdownContent.trim();
3677
- slides.push({
3678
- id: `slide-${slideCounter}-${hashMarkdownString2(trimmedContent)}`,
3679
- title: extractSlideTitle(trimmedContent),
3680
- location: {
3681
- startLine: 1,
3682
- endLine: markdownContent.split(`
3683
- `).length,
3684
- content: trimmedContent,
3685
- type: "full_content" /* FULL_CONTENT */
3686
- },
3687
- chunks: parseMarkdownChunks(trimmedContent, `slide-${slideCounter}`)
3688
- });
3689
- }
3690
- return {
3691
- slides,
3692
- originalContent: markdownContent,
3693
- format
3694
- };
3695
- } catch (error) {
3696
- console.error("Error parsing markdown presentation:", error);
3697
- const content = markdownContent.trim();
3698
- return {
3699
- slides: content ? [
3700
- {
3701
- id: `slide-error-${hashMarkdownString2(content)}`,
3702
- title: extractSlideTitle(content),
3703
- location: {
3704
- startLine: 1,
3705
- endLine: content.split(`
3706
- `).length,
3707
- content,
3708
- type: "full_content" /* FULL_CONTENT */
3709
- },
3710
- chunks: parseMarkdownChunks(content, "slide-error")
3711
- }
3712
- ] : [],
3713
- originalContent: markdownContent,
3714
- format: "full_content" /* FULL_CONTENT */
3715
- };
3716
- }
3717
- }
3718
- function createPresentationWithErrorMessage(errorMessage) {
3719
- const errorMessageMarkdown = `# Error Loading Markdown:
3720
-
3721
- ${errorMessage}`;
3722
- return {
3723
- slides: [
3724
- {
3725
- id: "error",
3726
- title: extractSlideTitle(errorMessageMarkdown),
3727
- location: {
3728
- startLine: 0,
3729
- endLine: 0,
3730
- content: errorMessageMarkdown,
3731
- type: "full_content" /* FULL_CONTENT */
3732
- },
3733
- chunks: parseMarkdownChunks(errorMessageMarkdown, "slide-error")
3734
- }
3735
- ],
3736
- originalContent: errorMessageMarkdown,
3737
- format: "full_content" /* FULL_CONTENT */
3738
- };
3739
- }
3740
- function reconstructMarkdownContent(presentation) {
3741
- switch (presentation.format) {
3742
- case "horizontal_rule" /* HORIZONTAL_RULE */:
3743
- return presentation.slides.map((slide) => slide.location.content).join(`
3744
-
3745
- ---
3746
-
3747
- `);
3748
- case "header" /* HEADER */:
3749
- return presentation.slides.map((slide, index) => {
3750
- if (index === 0 && !slide.location.content.startsWith("##")) {
3751
- return slide.location.content;
3752
- }
3753
- return slide.location.content.startsWith("##") ? slide.location.content : `## ${slide.location.content}`;
3754
- }).join(`
3755
-
3756
- `);
3757
- case "full_content" /* FULL_CONTENT */:
3758
- default:
3759
- return presentation.slides[0]?.location.content || "";
3760
- }
3761
- }
3762
- function getAllSlideTitles(presentation) {
3763
- return presentation.slides.map((slide) => slide.title);
3764
- }
3765
- function findSlideByTitle(presentation, title) {
3766
- return presentation.slides.find((slide) => slide.title === title);
3767
- }
3768
- function findSlideIndexByTitle(presentation, title) {
3769
- return presentation.slides.findIndex((slide) => slide.title === title);
3770
- }
3771
- function updateSlideTitle(slide, newTitle) {
3772
- return {
3773
- ...slide,
3774
- title: newTitle
3775
- };
3776
- }
3777
- function serializePresentationToMarkdown(presentation) {
3778
- return reconstructMarkdownContent(presentation);
3779
- }
3780
- function updateSlideContent(slide, newContent) {
3781
- return {
3782
- ...slide,
3783
- location: {
3784
- ...slide.location,
3785
- content: newContent
3786
- },
3787
- title: extractSlideTitle(newContent),
3788
- chunks: parseMarkdownChunks(newContent, slide.id.split("-")[1] || "slide")
3789
- };
3790
- }
3791
- function updatePresentationSlide(presentation, index, newContent) {
3792
- const updatedSlides = [...presentation.slides];
3793
- if (index >= 0 && index < updatedSlides.length) {
3794
- updatedSlides[index] = updateSlideContent(updatedSlides[index], newContent);
3795
- }
3796
- return {
3797
- ...presentation,
3798
- slides: updatedSlides,
3799
- originalContent: reconstructMarkdownContent({
3800
- ...presentation,
3801
- slides: updatedSlides
3802
- })
3803
- };
3804
- }