@launchsecure/launch-kit 0.0.25 → 0.0.26

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.
Files changed (126) hide show
  1. package/README.md +50 -0
  2. package/dist/beacon/beacon.mjs +1016 -0
  3. package/dist/beacon/beacon.mjs.map +1 -0
  4. package/dist/beacon/beacon.umd.js +87 -0
  5. package/dist/beacon/beacon.umd.js.map +1 -0
  6. package/dist/beacon/index-DAIDnjfR.mjs +513 -0
  7. package/dist/beacon/index-DAIDnjfR.mjs.map +1 -0
  8. package/dist/beacon/types/capture/element.d.ts +3 -0
  9. package/dist/beacon/types/capture/element.d.ts.map +1 -0
  10. package/dist/beacon/types/capture/framework.d.ts +3 -0
  11. package/dist/beacon/types/capture/framework.d.ts.map +1 -0
  12. package/dist/beacon/types/capture/metadata.d.ts +3 -0
  13. package/dist/beacon/types/capture/metadata.d.ts.map +1 -0
  14. package/dist/beacon/types/capture/overlay.d.ts +7 -0
  15. package/dist/beacon/types/capture/overlay.d.ts.map +1 -0
  16. package/dist/beacon/types/capture/picker.d.ts +12 -0
  17. package/dist/beacon/types/capture/picker.d.ts.map +1 -0
  18. package/dist/beacon/types/capture/screenshot.d.ts +7 -0
  19. package/dist/beacon/types/capture/screenshot.d.ts.map +1 -0
  20. package/dist/beacon/types/capture/selector.d.ts +2 -0
  21. package/dist/beacon/types/capture/selector.d.ts.map +1 -0
  22. package/dist/beacon/types/element.d.ts +50 -0
  23. package/dist/beacon/types/element.d.ts.map +1 -0
  24. package/dist/beacon/types/index.d.ts +4 -0
  25. package/dist/beacon/types/index.d.ts.map +1 -0
  26. package/dist/beacon/types/transport/submit.d.ts +3 -0
  27. package/dist/beacon/types/transport/submit.d.ts.map +1 -0
  28. package/dist/beacon/types/types.d.ts +88 -0
  29. package/dist/beacon/types/types.d.ts.map +1 -0
  30. package/dist/beacon/types/ui/button.d.ts +2 -0
  31. package/dist/beacon/types/ui/button.d.ts.map +1 -0
  32. package/dist/beacon/types/ui/drawer.d.ts +31 -0
  33. package/dist/beacon/types/ui/drawer.d.ts.map +1 -0
  34. package/dist/beacon/types/ui/icons.d.ts +9 -0
  35. package/dist/beacon/types/ui/icons.d.ts.map +1 -0
  36. package/dist/beacon/types/ui/pick-mode-overlay.d.ts +25 -0
  37. package/dist/beacon/types/ui/pick-mode-overlay.d.ts.map +1 -0
  38. package/dist/beacon/types/ui/pin-popover.d.ts +14 -0
  39. package/dist/beacon/types/ui/pin-popover.d.ts.map +1 -0
  40. package/dist/chart-client/assets/{index-C8ANseEa.js → index-Bk1hawjD.js} +63 -58
  41. package/dist/chart-client/assets/index-DpaGa3bY.css +1 -0
  42. package/dist/chart-client/index.html +2 -2
  43. package/dist/client/assets/index-Bfel4OQ5.css +32 -0
  44. package/dist/client/assets/{index-Ds9UP_cj.js → index-eC-WuUWB.js} +58 -58
  45. package/dist/client/index.html +2 -2
  46. package/dist/council-client/assets/{index-Dc41S-R2.js → index-Cs_MVXHf.js} +14 -14
  47. package/dist/council-client/assets/index-P5kMsT5a.css +1 -0
  48. package/dist/council-client/index.html +2 -2
  49. package/dist/deck-client/assets/{_baseUniq-2gclQXo7.js → _baseUniq-C2xT_eYu.js} +1 -1
  50. package/dist/deck-client/assets/{arc-DcMY5Wm0.js → arc-CmVL9pGd.js} +1 -1
  51. package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-B8iirmmJ.js → architectureDiagram-Q4EWVU46-BSFgdjve.js} +1 -1
  52. package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-B4JBLjmJ.js → blockDiagram-DXYQGD6D-DuLzscvP.js} +1 -1
  53. package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-CojrJAk8.js → c4Diagram-AHTNJAMY-CfCJB8eY.js} +1 -1
  54. package/dist/deck-client/assets/channel-B4aNO8ZB.js +1 -0
  55. package/dist/deck-client/assets/{chunk-4BX2VUAB-Bmb_BMDo.js → chunk-4BX2VUAB-DxmLYTWZ.js} +1 -1
  56. package/dist/deck-client/assets/{chunk-4TB4RGXK-CumBy8qe.js → chunk-4TB4RGXK-CCnf7GFE.js} +1 -1
  57. package/dist/deck-client/assets/{chunk-55IACEB6-Ka8Hb1wD.js → chunk-55IACEB6-Db9DApcj.js} +1 -1
  58. package/dist/deck-client/assets/{chunk-EDXVE4YY-B3sIPiQo.js → chunk-EDXVE4YY-DmYDq8ZI.js} +1 -1
  59. package/dist/deck-client/assets/{chunk-FMBD7UC4-C1tYkaqu.js → chunk-FMBD7UC4-BGhUlF20.js} +1 -1
  60. package/dist/deck-client/assets/{chunk-OYMX7WX6-D7Wacbky.js → chunk-OYMX7WX6-CpEnicQZ.js} +1 -1
  61. package/dist/deck-client/assets/{chunk-QZHKN3VN-ChXI0vO3.js → chunk-QZHKN3VN-Doa7LKwf.js} +1 -1
  62. package/dist/deck-client/assets/{chunk-YZCP3GAM-BXhiqf8u.js → chunk-YZCP3GAM-CpkIlH6V.js} +1 -1
  63. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-BHTI0yWz.js +1 -0
  64. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-BHTI0yWz.js +1 -0
  65. package/dist/deck-client/assets/clone-HduFm7qU.js +1 -0
  66. package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-Bqp3p68D.js → cose-bilkent-S5V4N54A-Bkh8Bfcb.js} +1 -1
  67. package/dist/deck-client/assets/{dagre-KV5264BT-BS-rtyhZ.js → dagre-KV5264BT-Bp0XpTgH.js} +1 -1
  68. package/dist/deck-client/assets/{diagram-5BDNPKRD-BIrj9YGI.js → diagram-5BDNPKRD-ZHiyGYPQ.js} +1 -1
  69. package/dist/deck-client/assets/{diagram-G4DWMVQ6-noHWPIg4.js → diagram-G4DWMVQ6-BW-Q8_H5.js} +1 -1
  70. package/dist/deck-client/assets/{diagram-MMDJMWI5-C2qHxvqV.js → diagram-MMDJMWI5-6I3LTafu.js} +1 -1
  71. package/dist/deck-client/assets/{diagram-TYMM5635-BytnGQr-.js → diagram-TYMM5635-CyM5YK28.js} +1 -1
  72. package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BfK5m2YQ.js → erDiagram-SMLLAGMA-CjNxVJHk.js} +1 -1
  73. package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-Cq925G1Z.js → flowDiagram-DWJPFMVM-BDQHuAJR.js} +1 -1
  74. package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DhhHPAmj.js → ganttDiagram-T4ZO3ILL-B7MnkpbP.js} +1 -1
  75. package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-B3Lc0h9q.js → gitGraphDiagram-UUTBAWPF-C9dZAcYD.js} +1 -1
  76. package/dist/deck-client/assets/{graph-RTawgVWm.js → graph-CjdBnzUy.js} +1 -1
  77. package/dist/deck-client/assets/{index-BfIfJXmS.js → index-DeIVPW63.js} +68 -68
  78. package/dist/deck-client/assets/index-LKZDAS9S.css +1 -0
  79. package/dist/deck-client/assets/{infoDiagram-42DDH7IO-BlR584kX.js → infoDiagram-42DDH7IO-C7d3iRC3.js} +1 -1
  80. package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-DygKoNGY.js → ishikawaDiagram-UXIWVN3A-BcYGKj09.js} +1 -1
  81. package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-BnaiYp9N.js → journeyDiagram-VCZTEJTY-DqFlRrOL.js} +1 -1
  82. package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-BQBUBzJC.js → kanban-definition-6JOO6SKY-BJhPp1NR.js} +1 -1
  83. package/dist/deck-client/assets/{layout-DeZ8HI1T.js → layout-DIeS6GvK.js} +1 -1
  84. package/dist/deck-client/assets/{linear-C6roLi_9.js → linear-He_yJy5H.js} +1 -1
  85. package/dist/deck-client/assets/{min-CbUksbuI.js → min-DQ6Kx06t.js} +1 -1
  86. package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-iNxV62yN.js → mindmap-definition-QFDTVHPH-sQ62L8T2.js} +1 -1
  87. package/dist/deck-client/assets/{pieDiagram-DEJITSTG-DHVA0jaG.js → pieDiagram-DEJITSTG-BqCWmU2K.js} +1 -1
  88. package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-DBeKKLUQ.js → quadrantDiagram-34T5L4WZ-rQ1TJOoe.js} +1 -1
  89. package/dist/deck-client/assets/{requirementDiagram-MS252O5E-CBwITx7p.js → requirementDiagram-MS252O5E-BO2MPBOM.js} +1 -1
  90. package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BtE-1YTU.js → sankeyDiagram-XADWPNL6-BgsHEVex.js} +1 -1
  91. package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-DN96yPP2.js → sequenceDiagram-FGHM5R23-B3j1yMLU.js} +1 -1
  92. package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-VUkKC2uJ.js → stateDiagram-FHFEXIEX-C8jFlZou.js} +1 -1
  93. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BoqepHW0.js +1 -0
  94. package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-oUeZhRns.js → timeline-definition-GMOUNBTQ-tM-qo4Zk.js} +1 -1
  95. package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-D87fK90n.js → vennDiagram-DHZGUBPP-B0-6kOEu.js} +1 -1
  96. package/dist/deck-client/assets/wardley-RL74JXVD-HpBk07P-.js +162 -0
  97. package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-Ca_i0QRA.js → wardleyDiagram-NUSXRM2D-BkA1NLDE.js} +1 -1
  98. package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-CUOJVIvq.js → xychartDiagram-5P7HB3ND-CEKGSuI-.js} +1 -1
  99. package/dist/deck-client/index.html +2 -2
  100. package/dist/server/chart-serve.js +990 -116
  101. package/dist/server/cli.js +28413 -6982
  102. package/dist/server/council-entry.js +0 -0
  103. package/dist/server/deck-mcp-entry.js +332 -3
  104. package/dist/server/deck-serve.js +288 -0
  105. package/dist/server/fb-wizard.js +0 -0
  106. package/dist/server/graph/queries/classify.scm +8 -0
  107. package/dist/server/graph/queries/exports.scm +7 -0
  108. package/dist/server/graph-mcp-entry.js +1639 -197
  109. package/dist/server/recall-entry.js +1112 -0
  110. package/package.json +47 -21
  111. package/dist/chart-client/assets/index--120d9P9.css +0 -1
  112. package/dist/client/assets/index-Bf8zdL3x.css +0 -32
  113. package/dist/council-client/assets/index-CofZh7pS.css +0 -1
  114. package/dist/deck-client/assets/channel-ERh5jKXV.js +0 -1
  115. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-CMi1Gaev.js +0 -1
  116. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-CMi1Gaev.js +0 -1
  117. package/dist/deck-client/assets/clone-DfWhlD4X.js +0 -1
  118. package/dist/deck-client/assets/index-765AIQ9z.css +0 -1
  119. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CA0IjulK.js +0 -1
  120. package/dist/deck-client/assets/wardley-RL74JXVD-DYbYcpDp.js +0 -162
  121. package/dist/server/deck-server/deck-mcp-entry.js +0 -1789
  122. package/dist/server/deck-server/deck-serve.js +0 -1275
  123. package/dist/server/server/chart-serve.js +0 -4643
  124. package/dist/server/server/cli.js +0 -13360
  125. package/dist/server/server/fb-wizard.js +0 -136
  126. package/dist/server/server/graph-mcp-entry.js +0 -6776
File without changes
@@ -892,6 +892,277 @@ var init_contract_generator = __esm({
892
892
  }
893
893
  });
894
894
 
895
+ // src/server/rich-html-render.ts
896
+ function renderRichHtml(opts) {
897
+ const theme = opts.theme ?? "light";
898
+ const title = escapeHtml(opts.title ?? "LaunchDeck");
899
+ if (opts.framework === "wired") {
900
+ return renderWired(opts.content, theme, title);
901
+ }
902
+ if (opts.framework === "reveal") {
903
+ return renderReveal(opts.content, theme, title);
904
+ }
905
+ return opts.content;
906
+ }
907
+ function themeResolverScript(initial) {
908
+ return `<script>
909
+ (function () {
910
+ function applyTheme(t) {
911
+ if (t !== 'light' && t !== 'dark') return;
912
+ var prev = document.documentElement.dataset.theme;
913
+ document.documentElement.dataset.theme = t;
914
+ if (prev !== t) {
915
+ document.dispatchEvent(new CustomEvent('deck-theme', { detail: t }));
916
+ }
917
+ }
918
+ // 1) initial preference: URL > prefers-color-scheme (standalone) > baked-in default
919
+ var url = new URL(window.location.href);
920
+ var fromUrl = url.searchParams.get('theme');
921
+ if (fromUrl === 'light' || fromUrl === 'dark') {
922
+ applyTheme(fromUrl);
923
+ } else if (window.parent === window) {
924
+ var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
925
+ applyTheme(prefersDark ? 'dark' : 'light');
926
+ } else {
927
+ applyTheme(${JSON.stringify(initial)});
928
+ }
929
+ // 2) live updates from parent deck
930
+ window.addEventListener('message', function (e) {
931
+ if (e.data && e.data.type === 'deck-theme') applyTheme(e.data.theme);
932
+ });
933
+ // 3) tell parent we are ready so it can push the current theme back
934
+ if (window.parent !== window) {
935
+ window.parent.postMessage({ type: 'deck-iframe-ready' }, '*');
936
+ }
937
+ })();
938
+ </script>`;
939
+ }
940
+ function renderWired(body, initialTheme, title) {
941
+ const LIGHT = { bg: "#ffffff", fg: "#18181b", accent: "#7c3aed", cardBg: "#ffffff" };
942
+ const DARK = { bg: "#0e0e10", fg: "#e4e4e7", accent: "#a78bfa", cardBg: "#1a1a1d" };
943
+ const wiredVarsBlock = (vars) => `
944
+ --wired-card-background-fill: ${vars.cardBg};
945
+ --wired-button-color: ${vars.fg};
946
+ --wired-combo-popup-bg: ${vars.cardBg};
947
+ --wired-progress-color: ${vars.accent};
948
+ --wired-progress-label-background: ${vars.cardBg};
949
+ --wired-progress-label-color: ${vars.fg};
950
+ `;
951
+ return `<!DOCTYPE html>
952
+ <html lang="en" data-theme="${initialTheme}">
953
+ <head>
954
+ <meta charset="utf-8">
955
+ <meta name="viewport" content="width=device-width, initial-scale=1">
956
+ <title>${title}</title>
957
+ <script type="module" src="${WIRED_CDN}"></script>
958
+ <link href="https://fonts.googleapis.com/css2?family=Gloria+Hallelujah&family=DM+Sans:wght@400;600;700&display=swap" rel="stylesheet">
959
+ <style>
960
+ *, *::before, *::after { box-sizing: border-box; }
961
+ html, body {
962
+ margin: 0;
963
+ min-height: 100%;
964
+ font-family: 'Gloria Hallelujah', 'DM Sans', system-ui, sans-serif;
965
+ background: var(--page-bg);
966
+ color: var(--page-fg);
967
+ transition: background 0.15s, color 0.15s;
968
+ }
969
+ body { padding: 24px; }
970
+ h1, h2, h3, h4 { font-family: 'Gloria Hallelujah', cursive; margin: 0.5em 0; color: var(--page-fg); }
971
+ a { color: var(--page-accent); }
972
+ .row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin: 8px 0; }
973
+ .col { display: flex; flex-direction: column; gap: 12px; align-items: stretch; }
974
+ .card { padding: 16px; }
975
+
976
+ /* Light theme */
977
+ :root[data-theme="light"] {
978
+ --page-bg: ${LIGHT.bg};
979
+ --page-fg: ${LIGHT.fg};
980
+ --page-accent: ${LIGHT.accent};
981
+ ${wiredVarsBlock(LIGHT)}
982
+ }
983
+
984
+ /* Dark theme */
985
+ :root[data-theme="dark"] {
986
+ --page-bg: ${DARK.bg};
987
+ --page-fg: ${DARK.fg};
988
+ --page-accent: ${DARK.accent};
989
+ ${wiredVarsBlock(DARK)}
990
+ }
991
+
992
+ /* Hosts: text color inherits via component "color: inherit" rules.
993
+ Transparent background lets the page bg show through where the
994
+ rough.js rectangle leaves space. */
995
+ wired-button, wired-card, wired-checkbox, wired-radio, wired-toggle,
996
+ wired-input, wired-textarea, wired-search-input, wired-combo, wired-item,
997
+ wired-listbox, wired-link, wired-tabs, wired-tab, wired-fab,
998
+ wired-icon-button, wired-divider, wired-progress, wired-slider,
999
+ wired-calendar, wired-dialog {
1000
+ color: var(--page-fg);
1001
+ background: transparent;
1002
+ }
1003
+ </style>
1004
+ </head>
1005
+ <body>
1006
+ ${body}
1007
+ ${themeResolverScript(initialTheme)}
1008
+ <script type="module">
1009
+ // wired-input / wired-textarea / wired-search-input render their native
1010
+ // <input>/<textarea> INSIDE shadow DOM. Outer CSS cannot reach those, and
1011
+ // the native control has appearance:auto which the UA repaints over any
1012
+ // "background: transparent" rule. We must set inline styles directly on
1013
+ // the inner element with !important.
1014
+ //
1015
+ // We register one applier per theme. Re-runs when theme changes or new
1016
+ // nodes are added so the page reacts live to the deck sun/moon toggle.
1017
+ const FG = { light: ${JSON.stringify(LIGHT.fg)}, dark: ${JSON.stringify(DARK.fg)} };
1018
+ const TAGS = ['wired-input', 'wired-textarea', 'wired-search-input'];
1019
+ const DARK_PROPS = [
1020
+ 'appearance', '-webkit-appearance',
1021
+ 'background', 'background-color',
1022
+ 'color', '-webkit-text-fill-color', 'caret-color',
1023
+ 'border', 'outline',
1024
+ ];
1025
+
1026
+ function applyDark(node) {
1027
+ const s = node.style;
1028
+ s.setProperty('appearance', 'none', 'important');
1029
+ s.setProperty('-webkit-appearance', 'none', 'important');
1030
+ s.setProperty('background', 'transparent', 'important');
1031
+ s.setProperty('background-color', 'transparent', 'important');
1032
+ s.setProperty('color', FG.dark, 'important');
1033
+ s.setProperty('-webkit-text-fill-color', FG.dark, 'important');
1034
+ s.setProperty('caret-color', FG.dark, 'important');
1035
+ s.setProperty('border', 'none', 'important');
1036
+ s.setProperty('outline', 'none', 'important');
1037
+ }
1038
+
1039
+ function applyLight(node) {
1040
+ DARK_PROPS.forEach((p) => node.style.removeProperty(p));
1041
+ }
1042
+
1043
+ function placeholderStyle(host, theme) {
1044
+ const existing = host.shadowRoot.querySelector('style[data-deck-theme]');
1045
+ if (existing) existing.remove();
1046
+ if (theme !== 'dark') return;
1047
+ const style = document.createElement('style');
1048
+ style.dataset.deckTheme = '1';
1049
+ style.textContent =
1050
+ '::placeholder{color:' + FG.dark + '99 !important;' +
1051
+ '-webkit-text-fill-color:' + FG.dark + '99 !important;}';
1052
+ host.shadowRoot.appendChild(style);
1053
+ }
1054
+
1055
+ function sweepOnce() {
1056
+ const theme = document.documentElement.dataset.theme;
1057
+ for (const tag of TAGS) {
1058
+ for (const host of document.querySelectorAll(tag)) {
1059
+ if (!host.shadowRoot) continue;
1060
+ const inner = host.shadowRoot.querySelector('input, textarea');
1061
+ if (!inner) continue;
1062
+ if (theme === 'dark') applyDark(inner);
1063
+ else applyLight(inner);
1064
+ placeholderStyle(host, theme);
1065
+ }
1066
+ }
1067
+ }
1068
+
1069
+ // Initial + late-upgrade catch (CDN script loads async).
1070
+ sweepOnce();
1071
+ let elapsed = 0;
1072
+ function tick() {
1073
+ sweepOnce();
1074
+ elapsed += 100;
1075
+ if (elapsed < 3000) setTimeout(tick, 100);
1076
+ }
1077
+ setTimeout(tick, 100);
1078
+
1079
+ // Re-sweep on theme change.
1080
+ document.addEventListener('deck-theme', sweepOnce);
1081
+ // Re-sweep when new nodes are added.
1082
+ new MutationObserver(sweepOnce).observe(document.body, { subtree: true, childList: true });
1083
+
1084
+ // whenDefined fires when each tag is registered \u2014 allSettled-style, never hangs.
1085
+ TAGS.forEach((tag) => {
1086
+ customElements.whenDefined(tag).then(sweepOnce).catch(() => {});
1087
+ });
1088
+ </script>
1089
+ </body>
1090
+ </html>`;
1091
+ }
1092
+ function renderReveal(content, initialTheme, title) {
1093
+ const slides = content.includes("<section") ? content : content.split(/\n\s*---\s*\n/).map((md) => `<section data-markdown><textarea data-template>
1094
+ ${md.trim()}
1095
+ </textarea></section>`).join("\n");
1096
+ return `<!DOCTYPE html>
1097
+ <html lang="en" data-theme="${initialTheme}">
1098
+ <head>
1099
+ <meta charset="utf-8">
1100
+ <meta name="viewport" content="width=device-width, initial-scale=1">
1101
+ <title>${title}</title>
1102
+ <link rel="stylesheet" href="${REVEAL_CSS}">
1103
+ <link id="reveal-theme-light" rel="stylesheet" href="${REVEAL_THEME("light")}" ${initialTheme === "dark" ? "disabled" : ""}>
1104
+ <link id="reveal-theme-dark" rel="stylesheet" href="${REVEAL_THEME("dark")}" ${initialTheme === "dark" ? "" : "disabled"}>
1105
+ <style>
1106
+ html, body { margin: 0; height: 100%; }
1107
+ .reveal .slides { text-align: left; }
1108
+ .reveal .slides section { padding: 0 32px; }
1109
+ </style>
1110
+ </head>
1111
+ <body>
1112
+ <div class="reveal">
1113
+ <div class="slides">
1114
+ ${slides}
1115
+ </div>
1116
+ </div>
1117
+ <script src="${REVEAL_JS}"></script>
1118
+ <script src="${REVEAL_MD}"></script>
1119
+ <script src="${REVEAL_HL}"></script>
1120
+ <script src="${REVEAL_NOTES}"></script>
1121
+ <script>
1122
+ Reveal.initialize({
1123
+ hash: true,
1124
+ slideNumber: 'c/t',
1125
+ controls: true,
1126
+ progress: true,
1127
+ transition: 'slide',
1128
+ plugins: [RevealMarkdown, RevealHighlight, RevealNotes],
1129
+ });
1130
+ // React to theme changes: flip which stylesheet is enabled.
1131
+ function syncRevealTheme() {
1132
+ var dark = document.documentElement.dataset.theme === 'dark';
1133
+ var lightLink = document.getElementById('reveal-theme-light');
1134
+ var darkLink = document.getElementById('reveal-theme-dark');
1135
+ if (lightLink) lightLink.disabled = dark;
1136
+ if (darkLink) darkLink.disabled = !dark;
1137
+ }
1138
+ document.addEventListener('deck-theme', syncRevealTheme);
1139
+ syncRevealTheme();
1140
+ </script>
1141
+ ${themeResolverScript(initialTheme)}
1142
+ </body>
1143
+ </html>`;
1144
+ }
1145
+ function escapeHtml(s) {
1146
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1147
+ }
1148
+ function slugify(label) {
1149
+ return label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "block";
1150
+ }
1151
+ var WIRED_CDN, REVEAL_VER, REVEAL_CSS, REVEAL_THEME, REVEAL_JS, REVEAL_MD, REVEAL_HL, REVEAL_NOTES;
1152
+ var init_rich_html_render = __esm({
1153
+ "src/server/rich-html-render.ts"() {
1154
+ "use strict";
1155
+ WIRED_CDN = "https://unpkg.com/wired-elements?module";
1156
+ REVEAL_VER = "5.1.0";
1157
+ REVEAL_CSS = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/reveal.css`;
1158
+ REVEAL_THEME = (t) => `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/theme/${t === "dark" ? "black" : "white"}.css`;
1159
+ REVEAL_JS = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/reveal.js`;
1160
+ REVEAL_MD = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/markdown/markdown.js`;
1161
+ REVEAL_HL = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/highlight/highlight.js`;
1162
+ REVEAL_NOTES = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/notes/notes.js`;
1163
+ }
1164
+ });
1165
+
895
1166
  // src/server/deck-serve.ts
896
1167
  var deck_serve_exports = {};
897
1168
  __export(deck_serve_exports, {
@@ -1067,6 +1338,29 @@ async function startDeckServer(opts = {}) {
1067
1338
  console.error("Failed to generate blast radius HTML:", err);
1068
1339
  }
1069
1340
  }
1341
+ if (block.type === "rich-html" && block.content) {
1342
+ try {
1343
+ const html = renderRichHtml({
1344
+ framework: block.framework ?? "raw",
1345
+ content: block.content,
1346
+ theme: block.theme,
1347
+ title: block.label
1348
+ });
1349
+ const sessionEncoded = encodeURIComponent(body.session);
1350
+ const baseUrl = `/deck-files/${sessionEncoded}`;
1351
+ const filename = `${slugify(block.label)}.html`;
1352
+ const dir = import_node_path3.default.join(cwd, ".launchsecure", "deck-files", body.session);
1353
+ import_node_fs3.default.mkdirSync(dir, { recursive: true });
1354
+ import_node_fs3.default.writeFileSync(import_node_path3.default.join(dir, filename), html);
1355
+ block.type = "iframe";
1356
+ block.src = `${baseUrl}/${filename}`;
1357
+ delete block.content;
1358
+ delete block.framework;
1359
+ delete block.theme;
1360
+ } catch (err) {
1361
+ console.error("Failed to generate rich-html:", err);
1362
+ }
1363
+ }
1070
1364
  }
1071
1365
  broadcastToClients({
1072
1366
  type: "session",
@@ -1280,6 +1574,7 @@ var init_deck_serve = __esm({
1280
1574
  init_deck_config();
1281
1575
  init_blast_radius_render();
1282
1576
  init_contract_generator();
1577
+ init_rich_html_render();
1283
1578
  DEFAULT_PORT = 52829;
1284
1579
  MAX_PORT_SCAN = 3;
1285
1580
  MIME_TYPES = {
@@ -1381,6 +1676,29 @@ async function handleTool(name, args) {
1381
1676
  return text(JSON.stringify({ error: `Failed to generate blast radius HTML: ${err}` }));
1382
1677
  }
1383
1678
  }
1679
+ if (block.type === "rich-html" && block.content) {
1680
+ try {
1681
+ const html = renderRichHtml({
1682
+ framework: block.framework ?? "raw",
1683
+ content: block.content,
1684
+ theme: block.theme,
1685
+ title: block.label
1686
+ });
1687
+ const sessionEncoded = encodeURIComponent(session);
1688
+ const baseUrl = `/deck-files/${sessionEncoded}`;
1689
+ const filename = `${slugify(block.label)}.html`;
1690
+ const dir = (0, import_node_path4.join)(projectRoot, ".launchsecure", "deck-files", session);
1691
+ import_node_fs4.default.mkdirSync(dir, { recursive: true });
1692
+ import_node_fs4.default.writeFileSync((0, import_node_path4.join)(dir, filename), html);
1693
+ block.type = "iframe";
1694
+ block.src = `${baseUrl}/${filename}`;
1695
+ delete block.content;
1696
+ delete block.framework;
1697
+ delete block.theme;
1698
+ } catch (err) {
1699
+ return text(JSON.stringify({ error: `Failed to generate rich-html: ${err}` }));
1700
+ }
1701
+ }
1384
1702
  }
1385
1703
  try {
1386
1704
  await httpPost(`${lock.url}/api/deck`, { session, mode, blocks, prompt });
@@ -1643,6 +1961,7 @@ var init_deck_mcp = __esm({
1643
1961
  init_deck_config();
1644
1962
  init_blast_radius_render();
1645
1963
  init_contract_generator();
1964
+ init_rich_html_render();
1646
1965
  SERVER_INFO = {
1647
1966
  name: "launch-deck",
1648
1967
  version: "0.0.3"
@@ -1650,7 +1969,7 @@ var init_deck_mcp = __esm({
1650
1969
  TOOLS = [
1651
1970
  {
1652
1971
  name: "deck",
1653
- description: 'Push visual blocks (HTML, Mermaid diagrams, options, markdown) to the LaunchDeck browser.\n\nEach call creates a named session tab in the browser. Tabs accumulate \u2014 previous sessions are preserved.\n\nModes:\n- "show": Display content and return immediately. Terminal confirms delivery. No user feedback.\n- "feedback": Display content with an input bar for the user to respond. Returns immediately with session info. Call `await_feedback` with the same session ID to block until the user responds.\n\nBlock types:\n- html: Raw HTML/CSS (rendered in a sandboxed iframe)\n- mermaid: Mermaid diagram DSL (flowchart, sequence, ERD, etc.)\n- markdown: Rendered markdown text\n- options: Selection cards \u2014 user picks one or more\n- blast-radius: Interactive D3 radial graph for blast radius analysis. Requires `manifest` field.\n\nAfter calling this tool, the user should check the LaunchDeck browser tab to view content.',
1972
+ description: 'Push visual blocks (HTML, Mermaid diagrams, options, markdown) to the LaunchDeck browser.\n\nEach call creates a named session tab in the browser. Tabs accumulate \u2014 previous sessions are preserved.\n\nModes:\n- "show": Display content and return immediately. Terminal confirms delivery. No user feedback.\n- "feedback": Display content with an input bar for the user to respond. Returns immediately with session info. Call `await_feedback` with the same session ID to block until the user responds.\n\nBlock types:\n- html: Raw HTML/CSS (sandboxed iframe \u2014 NO scripts). Use for static markup only.\n- mermaid: Mermaid diagram DSL (flowchart, sequence, ERD, etc.)\n- markdown: Rendered markdown text\n- options: Selection cards \u2014 user picks one or more\n- blast-radius: Interactive D3 radial graph for blast radius analysis. Requires `manifest` field.\n- rich-html: Self-contained HTML page with FULL JS support (events, animations, CDN scripts). Specify `framework` and `content`:\n \u2022 framework: "wired" \u2014 wireframe UI via wired-elements (https://wiredjs.com). `content` is body HTML using <wired-button>, <wired-input>, <wired-card>, <wired-checkbox>, <wired-combo>, <wired-slider>, <wired-tabs>/<wired-tab>, etc. Hand-drawn aesthetic. Loads CDN automatically.\n \u2022 framework: "reveal" \u2014 slide presentation via reveal.js (https://revealjs.com). `content` is markdown slides joined by `\\n---\\n` (recommended) OR raw <section>\u2026</section> HTML. Arrow keys navigate. Supports code highlighting and speaker notes. Loads CDN automatically.\n \u2022 framework: "raw" \u2014 `content` is a complete <!DOCTYPE html> document (caller controls everything).\n Optional `theme: "light" | "dark"` sets the INITIAL preference. The deck\'s sun/moon toggle overrides live \u2014 content reacts in place. Usually omit it; only set when the AI has a specific reason (e.g. mockup that only makes sense in one mode). Standalone downloads fall back to OS prefers-color-scheme.\n\nAfter calling this tool, the user should check the LaunchDeck browser tab to view content.',
1654
1973
  inputSchema: {
1655
1974
  type: "object",
1656
1975
  properties: {
@@ -1669,9 +1988,19 @@ var init_deck_mcp = __esm({
1669
1988
  items: {
1670
1989
  type: "object",
1671
1990
  properties: {
1672
- type: { type: "string", enum: ["html", "mermaid", "options", "markdown", "blast-radius"] },
1991
+ type: { type: "string", enum: ["html", "mermaid", "options", "markdown", "blast-radius", "rich-html"] },
1673
1992
  label: { type: "string", description: "Label for this block (shown as sub-tab if multiple blocks)" },
1674
- content: { type: "string", description: "Content string (HTML, Mermaid DSL, Markdown)" },
1993
+ content: { type: "string", description: "Content string (HTML, Mermaid DSL, Markdown, or rich-html body)" },
1994
+ framework: {
1995
+ type: "string",
1996
+ enum: ["wired", "reveal", "raw"],
1997
+ description: "For rich-html only: which framework to wrap content with."
1998
+ },
1999
+ theme: {
2000
+ type: "string",
2001
+ enum: ["light", "dark"],
2002
+ description: "For rich-html only: theme for the generated page."
2003
+ },
1675
2004
  manifest: {
1676
2005
  type: "object",
1677
2006
  description: 'For blast-radius type: BlastRadiusManifest object. Generates an interactive D3 radial graph.\n\nRequired fields:\n- mode: "structural" (file-level, rings = hops) or "feature" (rings = modify/create/ripple)\n- title: string \u2014 shown in header (e.g. "lib/permissions/types.ts" or "Channels for Comms")\n- layers: array of { id, name, icon, color } \u2014 defines the project layers (e.g. db/api/ui). icon = Lucide icon name, color = hex fill color\n- rings: array of { id, name, color } \u2014 defines concentric rings. For structural: [{id:"hop1",name:"Direct",color:"#f97316"},{id:"hop2",name:"Indirect",color:"#eab308"}]. For feature: [{id:"modify",name:"Modify",color:"#f97316"},{id:"create",name:"Create",color:"#22c55e"},{id:"ripple",name:"Ripple",color:"#eab308"}]\n- center: { name, description } \u2014 the center node label and tooltip\n- nodes: array of { id, name, layer, ring, path?, reason?, type? } \u2014 layer refs layers[].id, ring refs rings[].id\n- edges: array of { source, target } \u2014 source/target are node ids, use "center" for edges from the center node\n\nOptional: subtitle (shown above title)\n\nExample layers: [{id:"db",name:"Database",icon:"database",color:"#172554"},{id:"api",name:"API",icon:"server",color:"#1e3a5f"},{id:"ui",name:"UI",icon:"layout-dashboard",color:"#0c4a6e"}]'