@flanksource/clicky-ui 0.3.22 → 0.3.23

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 (184) hide show
  1. package/dist/components/CountryFlag.cjs +55 -0
  2. package/dist/components/CountryFlag.cjs.map +1 -0
  3. package/dist/components/CountryFlag.d.ts +8 -0
  4. package/dist/components/CountryFlag.d.ts.map +1 -0
  5. package/dist/components/CountryFlag.js +38 -0
  6. package/dist/components/CountryFlag.js.map +1 -0
  7. package/dist/components/CountryPicker.cjs +35 -0
  8. package/dist/components/CountryPicker.cjs.map +1 -0
  9. package/dist/components/CountryPicker.d.ts +4 -0
  10. package/dist/components/CountryPicker.d.ts.map +1 -0
  11. package/dist/components/CountryPicker.js +35 -0
  12. package/dist/components/CountryPicker.js.map +1 -0
  13. package/dist/components/SplitButton.cjs +3 -2
  14. package/dist/components/SplitButton.cjs.map +1 -1
  15. package/dist/components/SplitButton.d.ts +6 -1
  16. package/dist/components/SplitButton.d.ts.map +1 -1
  17. package/dist/components/SplitButton.js +3 -2
  18. package/dist/components/SplitButton.js.map +1 -1
  19. package/dist/components/country-options.cjs +34 -0
  20. package/dist/components/country-options.cjs.map +1 -0
  21. package/dist/components/country-options.d.ts +8 -0
  22. package/dist/components/country-options.d.ts.map +1 -0
  23. package/dist/components/country-options.js +34 -0
  24. package/dist/components/country-options.js.map +1 -0
  25. package/dist/components.cjs +11 -0
  26. package/dist/components.cjs.map +1 -1
  27. package/dist/components.d.ts +4 -0
  28. package/dist/components.d.ts.map +1 -1
  29. package/dist/components.js +11 -0
  30. package/dist/components.js.map +1 -1
  31. package/dist/data/Clicky.cjs +4 -1
  32. package/dist/data/Clicky.cjs.map +1 -1
  33. package/dist/data/Clicky.d.ts.map +1 -1
  34. package/dist/data/Clicky.js +4 -1
  35. package/dist/data/Clicky.js.map +1 -1
  36. package/dist/data/CodeDiff.cjs +3 -18
  37. package/dist/data/CodeDiff.cjs.map +1 -1
  38. package/dist/data/CodeDiff.d.ts.map +1 -1
  39. package/dist/data/CodeDiff.js +3 -18
  40. package/dist/data/CodeDiff.js.map +1 -1
  41. package/dist/data/DataTable.cjs +182 -64
  42. package/dist/data/DataTable.cjs.map +1 -1
  43. package/dist/data/DataTable.d.ts +9 -1
  44. package/dist/data/DataTable.d.ts.map +1 -1
  45. package/dist/data/DataTable.grouping.cjs +26 -0
  46. package/dist/data/DataTable.grouping.cjs.map +1 -1
  47. package/dist/data/DataTable.grouping.d.ts +38 -0
  48. package/dist/data/DataTable.grouping.d.ts.map +1 -1
  49. package/dist/data/DataTable.grouping.js +26 -0
  50. package/dist/data/DataTable.grouping.js.map +1 -1
  51. package/dist/data/DataTable.js +183 -65
  52. package/dist/data/DataTable.js.map +1 -1
  53. package/dist/data/DataTableGroupingControls.cjs +84 -0
  54. package/dist/data/DataTableGroupingControls.cjs.map +1 -0
  55. package/dist/data/DataTableGroupingControls.d.ts +17 -0
  56. package/dist/data/DataTableGroupingControls.d.ts.map +1 -0
  57. package/dist/data/DataTableGroupingControls.js +84 -0
  58. package/dist/data/DataTableGroupingControls.js.map +1 -0
  59. package/dist/data/HighlightedTokens.cjs +21 -0
  60. package/dist/data/HighlightedTokens.cjs.map +1 -0
  61. package/dist/data/HighlightedTokens.d.ts +6 -0
  62. package/dist/data/HighlightedTokens.d.ts.map +1 -0
  63. package/dist/data/HighlightedTokens.js +21 -0
  64. package/dist/data/HighlightedTokens.js.map +1 -0
  65. package/dist/data/code-highlight.cjs +0 -6
  66. package/dist/data/code-highlight.cjs.map +1 -1
  67. package/dist/data/code-highlight.d.ts +4 -3
  68. package/dist/data/code-highlight.d.ts.map +1 -1
  69. package/dist/data/code-highlight.js +1 -7
  70. package/dist/data/code-highlight.js.map +1 -1
  71. package/dist/data/diagnostics/DiagnosticsDetailPanel.cjs +6 -2
  72. package/dist/data/diagnostics/DiagnosticsDetailPanel.cjs.map +1 -1
  73. package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts +8 -1
  74. package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts.map +1 -1
  75. package/dist/data/diagnostics/DiagnosticsDetailPanel.js +6 -2
  76. package/dist/data/diagnostics/DiagnosticsDetailPanel.js.map +1 -1
  77. package/dist/data/diagnostics/ErrorDetails.cjs +29 -5
  78. package/dist/data/diagnostics/ErrorDetails.cjs.map +1 -1
  79. package/dist/data/diagnostics/ErrorDetails.d.ts +3 -1
  80. package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -1
  81. package/dist/data/diagnostics/ErrorDetails.js +29 -5
  82. package/dist/data/diagnostics/ErrorDetails.js.map +1 -1
  83. package/dist/data/diagnostics/FrameSourceWindow.cjs +54 -24
  84. package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
  85. package/dist/data/diagnostics/FrameSourceWindow.d.ts +2 -1
  86. package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
  87. package/dist/data/diagnostics/FrameSourceWindow.js +54 -24
  88. package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
  89. package/dist/data/diagnostics/FrameSourceWindow.utils.cjs.map +1 -1
  90. package/dist/data/diagnostics/FrameSourceWindow.utils.d.ts +3 -0
  91. package/dist/data/diagnostics/FrameSourceWindow.utils.d.ts.map +1 -1
  92. package/dist/data/diagnostics/FrameSourceWindow.utils.js.map +1 -1
  93. package/dist/data/diagnostics/JvmStackTrace.cjs +14 -30
  94. package/dist/data/diagnostics/JvmStackTrace.cjs.map +1 -1
  95. package/dist/data/diagnostics/JvmStackTrace.d.ts +6 -9
  96. package/dist/data/diagnostics/JvmStackTrace.d.ts.map +1 -1
  97. package/dist/data/diagnostics/JvmStackTrace.js +15 -31
  98. package/dist/data/diagnostics/JvmStackTrace.js.map +1 -1
  99. package/dist/data/diagnostics/RenderedStackTrace.cjs +14 -144
  100. package/dist/data/diagnostics/RenderedStackTrace.cjs.map +1 -1
  101. package/dist/data/diagnostics/RenderedStackTrace.d.ts +6 -6
  102. package/dist/data/diagnostics/RenderedStackTrace.d.ts.map +1 -1
  103. package/dist/data/diagnostics/RenderedStackTrace.js +15 -145
  104. package/dist/data/diagnostics/RenderedStackTrace.js.map +1 -1
  105. package/dist/data/diagnostics/StackFrameRow.cjs +65 -0
  106. package/dist/data/diagnostics/StackFrameRow.cjs.map +1 -0
  107. package/dist/data/diagnostics/StackFrameRow.d.ts +13 -0
  108. package/dist/data/diagnostics/StackFrameRow.d.ts.map +1 -0
  109. package/dist/data/diagnostics/StackFrameRow.js +65 -0
  110. package/dist/data/diagnostics/StackFrameRow.js.map +1 -0
  111. package/dist/data/diagnostics/ThreadCard.cjs +9 -2
  112. package/dist/data/diagnostics/ThreadCard.cjs.map +1 -1
  113. package/dist/data/diagnostics/ThreadCard.d.ts +3 -1
  114. package/dist/data/diagnostics/ThreadCard.d.ts.map +1 -1
  115. package/dist/data/diagnostics/ThreadCard.js +9 -2
  116. package/dist/data/diagnostics/ThreadCard.js.map +1 -1
  117. package/dist/data/diagnostics/frame-heuristics.cjs +26 -0
  118. package/dist/data/diagnostics/frame-heuristics.cjs.map +1 -0
  119. package/dist/data/diagnostics/frame-heuristics.d.ts +5 -0
  120. package/dist/data/diagnostics/frame-heuristics.d.ts.map +1 -0
  121. package/dist/data/diagnostics/frame-heuristics.js +26 -0
  122. package/dist/data/diagnostics/frame-heuristics.js.map +1 -0
  123. package/dist/data/diagnostics/jvm-stacktrace.cjs +5 -7
  124. package/dist/data/diagnostics/jvm-stacktrace.cjs.map +1 -1
  125. package/dist/data/diagnostics/jvm-stacktrace.d.ts.map +1 -1
  126. package/dist/data/diagnostics/jvm-stacktrace.js +5 -7
  127. package/dist/data/diagnostics/jvm-stacktrace.js.map +1 -1
  128. package/dist/data/diagnostics/stacktrace-parse.cjs +4 -9
  129. package/dist/data/diagnostics/stacktrace-parse.cjs.map +1 -1
  130. package/dist/data/diagnostics/stacktrace-parse.d.ts.map +1 -1
  131. package/dist/data/diagnostics/stacktrace-parse.js +4 -9
  132. package/dist/data/diagnostics/stacktrace-parse.js.map +1 -1
  133. package/dist/data/version-info.cjs +3 -3
  134. package/dist/data/version-info.js +3 -3
  135. package/dist/data.cjs +7 -1
  136. package/dist/data.cjs.map +1 -1
  137. package/dist/data.d.ts +4 -2
  138. package/dist/data.d.ts.map +1 -1
  139. package/dist/data.js +8 -2
  140. package/dist/data.js.map +1 -1
  141. package/dist/index.cjs +18 -1
  142. package/dist/index.cjs.map +1 -1
  143. package/dist/index.js +19 -2
  144. package/dist/index.js.map +1 -1
  145. package/dist/rpc/CommandForm.cjs +8 -18
  146. package/dist/rpc/CommandForm.cjs.map +1 -1
  147. package/dist/rpc/CommandForm.d.ts +8 -2
  148. package/dist/rpc/CommandForm.d.ts.map +1 -1
  149. package/dist/rpc/CommandForm.js +9 -19
  150. package/dist/rpc/CommandForm.js.map +1 -1
  151. package/dist/rpc/OperationActionDialog.cjs +3 -3
  152. package/dist/rpc/OperationActionDialog.cjs.map +1 -1
  153. package/dist/rpc/OperationActionDialog.js +3 -3
  154. package/dist/rpc/OperationActionDialog.js.map +1 -1
  155. package/dist/rpc/OperationCommandPage.cjs +7 -7
  156. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  157. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  158. package/dist/rpc/OperationCommandPage.js +7 -7
  159. package/dist/rpc/OperationCommandPage.js.map +1 -1
  160. package/dist/rpc/apiClient.cjs +17 -3
  161. package/dist/rpc/apiClient.cjs.map +1 -1
  162. package/dist/rpc/apiClient.d.ts +4 -4
  163. package/dist/rpc/apiClient.d.ts.map +1 -1
  164. package/dist/rpc/apiClient.js +17 -3
  165. package/dist/rpc/apiClient.js.map +1 -1
  166. package/dist/rpc/formMetadata.cjs +5 -9
  167. package/dist/rpc/formMetadata.cjs.map +1 -1
  168. package/dist/rpc/formMetadata.d.ts +3 -3
  169. package/dist/rpc/formMetadata.d.ts.map +1 -1
  170. package/dist/rpc/formMetadata.js +5 -9
  171. package/dist/rpc/formMetadata.js.map +1 -1
  172. package/dist/rpc/rpc-story.fixtures.d.ts.map +1 -1
  173. package/dist/rpc/types.cjs.map +1 -1
  174. package/dist/rpc/types.d.ts +1 -0
  175. package/dist/rpc/types.d.ts.map +1 -1
  176. package/dist/rpc/types.js.map +1 -1
  177. package/dist/rpc/useOperations.cjs.map +1 -1
  178. package/dist/rpc/useOperations.d.ts +4 -4
  179. package/dist/rpc/useOperations.d.ts.map +1 -1
  180. package/dist/rpc/useOperations.js.map +1 -1
  181. package/dist/rpc.d.ts +2 -2
  182. package/dist/rpc.d.ts.map +1 -1
  183. package/dist/styles.css +1 -1
  184. package/package.json +2 -1
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const select = require("../components/select.cjs");
5
+ const utils = require("../lib/utils.cjs");
6
+ const Icon = require("./Icon.cjs");
7
+ const UiExpandAll = require("../icons/components/UiExpandAll.cjs");
8
+ const UiCollapseAll = require("../icons/components/UiCollapseAll.cjs");
9
+ function DataTableGroupingControls({
10
+ modes,
11
+ value,
12
+ hasGroups,
13
+ allExpanded,
14
+ allCollapsed,
15
+ onModeChange,
16
+ onExpandAll,
17
+ onCollapseAll
18
+ }) {
19
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20
+ "div",
21
+ {
22
+ className: "flex shrink-0 items-center gap-1",
23
+ role: "group",
24
+ "aria-label": "Grouping controls",
25
+ children: [
26
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-44 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
27
+ select.Select,
28
+ {
29
+ "aria-label": "Group rows by",
30
+ value,
31
+ options: modes,
32
+ onChange: (event) => onModeChange(event.target.value)
33
+ }
34
+ ) }),
35
+ /* @__PURE__ */ jsxRuntime.jsx(
36
+ GroupingButton,
37
+ {
38
+ label: "Expand all groups",
39
+ pressed: allExpanded,
40
+ disabled: !hasGroups,
41
+ onClick: onExpandAll,
42
+ icon: UiExpandAll.UiExpandAll
43
+ }
44
+ ),
45
+ /* @__PURE__ */ jsxRuntime.jsx(
46
+ GroupingButton,
47
+ {
48
+ label: "Collapse all groups",
49
+ pressed: allCollapsed,
50
+ disabled: !hasGroups,
51
+ onClick: onCollapseAll,
52
+ icon: UiCollapseAll.UiCollapseAll
53
+ }
54
+ )
55
+ ]
56
+ }
57
+ );
58
+ }
59
+ function GroupingButton({
60
+ label,
61
+ pressed,
62
+ disabled,
63
+ onClick,
64
+ icon
65
+ }) {
66
+ return /* @__PURE__ */ jsxRuntime.jsx(
67
+ "button",
68
+ {
69
+ type: "button",
70
+ "aria-label": label,
71
+ title: label,
72
+ "aria-pressed": pressed,
73
+ disabled,
74
+ onClick,
75
+ className: utils.cn(
76
+ "inline-flex h-control-h w-control-h items-center justify-center rounded-md border border-border bg-background text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-50",
77
+ pressed && "bg-accent text-accent-foreground"
78
+ ),
79
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon, className: "text-sm" })
80
+ }
81
+ );
82
+ }
83
+ exports.DataTableGroupingControls = DataTableGroupingControls;
84
+ //# sourceMappingURL=DataTableGroupingControls.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTableGroupingControls.cjs","sources":["../../src/data/DataTableGroupingControls.tsx"],"sourcesContent":["import { Select } from \"../components/select\";\nimport { UiCollapseAll, UiExpandAll } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\n\ntype GroupingControlMode = {\n value: string;\n label: string;\n};\n\nexport type DataTableGroupingControlsProps = {\n modes: GroupingControlMode[];\n value: string;\n hasGroups: boolean;\n allExpanded: boolean;\n allCollapsed: boolean;\n onModeChange: (value: string) => void;\n onExpandAll: () => void;\n onCollapseAll: () => void;\n};\n\nexport function DataTableGroupingControls({\n modes,\n value,\n hasGroups,\n allExpanded,\n allCollapsed,\n onModeChange,\n onExpandAll,\n onCollapseAll,\n}: DataTableGroupingControlsProps) {\n return (\n <div\n className=\"flex shrink-0 items-center gap-1\"\n role=\"group\"\n aria-label=\"Grouping controls\"\n >\n <div className=\"w-44 shrink-0\">\n <Select\n aria-label=\"Group rows by\"\n value={value}\n options={modes}\n onChange={(event) => onModeChange(event.target.value)}\n />\n </div>\n <GroupingButton\n label=\"Expand all groups\"\n pressed={allExpanded}\n disabled={!hasGroups}\n onClick={onExpandAll}\n icon={UiExpandAll}\n />\n <GroupingButton\n label=\"Collapse all groups\"\n pressed={allCollapsed}\n disabled={!hasGroups}\n onClick={onCollapseAll}\n icon={UiCollapseAll}\n />\n </div>\n );\n}\n\nfunction GroupingButton({\n label,\n pressed,\n disabled,\n onClick,\n icon,\n}: {\n label: string;\n pressed: boolean;\n disabled: boolean;\n onClick: () => void;\n icon: StaticIconComponent;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n aria-pressed={pressed}\n disabled={disabled}\n onClick={onClick}\n className={cn(\n \"inline-flex h-control-h w-control-h items-center justify-center rounded-md border border-border bg-background text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n pressed && \"bg-accent text-accent-foreground\",\n )}\n >\n <Icon icon={icon} className=\"text-sm\" />\n </button>\n );\n}\n"],"names":["jsxs","jsx","Select","UiExpandAll","UiCollapseAll","cn","Icon"],"mappings":";;;;;;;;AAqBO,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmC;AACjC,SACEA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,MAAK;AAAA,MACL,cAAW;AAAA,MAEX,UAAA;AAAA,QAAAC,2BAAAA,IAAC,OAAA,EAAI,WAAU,iBACb,UAAAA,2BAAAA;AAAAA,UAACC,OAAAA;AAAAA,UAAA;AAAA,YACC,cAAW;AAAA,YACX;AAAA,YACA,SAAS;AAAA,YACT,UAAU,CAAC,UAAU,aAAa,MAAM,OAAO,KAAK;AAAA,UAAA;AAAA,QAAA,GAExD;AAAA,QACAD,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAM;AAAA,YACN,SAAS;AAAA,YACT,UAAU,CAAC;AAAA,YACX,SAAS;AAAA,YACT,MAAME,YAAAA;AAAAA,UAAA;AAAA,QAAA;AAAA,QAERF,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAM;AAAA,YACN,SAAS;AAAA,YACT,UAAU,CAAC;AAAA,YACX,SAAS;AAAA,YACT,MAAMG,cAAAA;AAAAA,UAAA;AAAA,QAAA;AAAA,MACR;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACEH,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,OAAO;AAAA,MACP,gBAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA,WAAWI,MAAAA;AAAAA,QACT;AAAA,QACA,WAAW;AAAA,MAAA;AAAA,MAGb,UAAAJ,2BAAAA,IAACK,KAAAA,MAAA,EAAK,MAAY,WAAU,UAAA,CAAU;AAAA,IAAA;AAAA,EAAA;AAG5C;;"}
@@ -0,0 +1,17 @@
1
+ type GroupingControlMode = {
2
+ value: string;
3
+ label: string;
4
+ };
5
+ export type DataTableGroupingControlsProps = {
6
+ modes: GroupingControlMode[];
7
+ value: string;
8
+ hasGroups: boolean;
9
+ allExpanded: boolean;
10
+ allCollapsed: boolean;
11
+ onModeChange: (value: string) => void;
12
+ onExpandAll: () => void;
13
+ onCollapseAll: () => void;
14
+ };
15
+ export declare function DataTableGroupingControls({ modes, value, hasGroups, allExpanded, allCollapsed, onModeChange, onExpandAll, onCollapseAll, }: DataTableGroupingControlsProps): import("react/jsx-runtime").JSX.Element;
16
+ export {};
17
+ //# sourceMappingURL=DataTableGroupingControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTableGroupingControls.d.ts","sourceRoot":"","sources":["../../src/data/DataTableGroupingControls.tsx"],"names":[],"mappings":"AAKA,KAAK,mBAAmB,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC;AAEF,wBAAgB,yBAAyB,CAAC,EACxC,KAAK,EACL,KAAK,EACL,SAAS,EACT,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,aAAa,GACd,EAAE,8BAA8B,2CA+BhC"}
@@ -0,0 +1,84 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { Select } from "../components/select.js";
3
+ import { cn } from "../lib/utils.js";
4
+ import { Icon } from "./Icon.js";
5
+ import { UiExpandAll } from "../icons/components/UiExpandAll.js";
6
+ import { UiCollapseAll } from "../icons/components/UiCollapseAll.js";
7
+ function DataTableGroupingControls({
8
+ modes,
9
+ value,
10
+ hasGroups,
11
+ allExpanded,
12
+ allCollapsed,
13
+ onModeChange,
14
+ onExpandAll,
15
+ onCollapseAll
16
+ }) {
17
+ return /* @__PURE__ */ jsxs(
18
+ "div",
19
+ {
20
+ className: "flex shrink-0 items-center gap-1",
21
+ role: "group",
22
+ "aria-label": "Grouping controls",
23
+ children: [
24
+ /* @__PURE__ */ jsx("div", { className: "w-44 shrink-0", children: /* @__PURE__ */ jsx(
25
+ Select,
26
+ {
27
+ "aria-label": "Group rows by",
28
+ value,
29
+ options: modes,
30
+ onChange: (event) => onModeChange(event.target.value)
31
+ }
32
+ ) }),
33
+ /* @__PURE__ */ jsx(
34
+ GroupingButton,
35
+ {
36
+ label: "Expand all groups",
37
+ pressed: allExpanded,
38
+ disabled: !hasGroups,
39
+ onClick: onExpandAll,
40
+ icon: UiExpandAll
41
+ }
42
+ ),
43
+ /* @__PURE__ */ jsx(
44
+ GroupingButton,
45
+ {
46
+ label: "Collapse all groups",
47
+ pressed: allCollapsed,
48
+ disabled: !hasGroups,
49
+ onClick: onCollapseAll,
50
+ icon: UiCollapseAll
51
+ }
52
+ )
53
+ ]
54
+ }
55
+ );
56
+ }
57
+ function GroupingButton({
58
+ label,
59
+ pressed,
60
+ disabled,
61
+ onClick,
62
+ icon
63
+ }) {
64
+ return /* @__PURE__ */ jsx(
65
+ "button",
66
+ {
67
+ type: "button",
68
+ "aria-label": label,
69
+ title: label,
70
+ "aria-pressed": pressed,
71
+ disabled,
72
+ onClick,
73
+ className: cn(
74
+ "inline-flex h-control-h w-control-h items-center justify-center rounded-md border border-border bg-background text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-50",
75
+ pressed && "bg-accent text-accent-foreground"
76
+ ),
77
+ children: /* @__PURE__ */ jsx(Icon, { icon, className: "text-sm" })
78
+ }
79
+ );
80
+ }
81
+ export {
82
+ DataTableGroupingControls
83
+ };
84
+ //# sourceMappingURL=DataTableGroupingControls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTableGroupingControls.js","sources":["../../src/data/DataTableGroupingControls.tsx"],"sourcesContent":["import { Select } from \"../components/select\";\nimport { UiCollapseAll, UiExpandAll } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\n\ntype GroupingControlMode = {\n value: string;\n label: string;\n};\n\nexport type DataTableGroupingControlsProps = {\n modes: GroupingControlMode[];\n value: string;\n hasGroups: boolean;\n allExpanded: boolean;\n allCollapsed: boolean;\n onModeChange: (value: string) => void;\n onExpandAll: () => void;\n onCollapseAll: () => void;\n};\n\nexport function DataTableGroupingControls({\n modes,\n value,\n hasGroups,\n allExpanded,\n allCollapsed,\n onModeChange,\n onExpandAll,\n onCollapseAll,\n}: DataTableGroupingControlsProps) {\n return (\n <div\n className=\"flex shrink-0 items-center gap-1\"\n role=\"group\"\n aria-label=\"Grouping controls\"\n >\n <div className=\"w-44 shrink-0\">\n <Select\n aria-label=\"Group rows by\"\n value={value}\n options={modes}\n onChange={(event) => onModeChange(event.target.value)}\n />\n </div>\n <GroupingButton\n label=\"Expand all groups\"\n pressed={allExpanded}\n disabled={!hasGroups}\n onClick={onExpandAll}\n icon={UiExpandAll}\n />\n <GroupingButton\n label=\"Collapse all groups\"\n pressed={allCollapsed}\n disabled={!hasGroups}\n onClick={onCollapseAll}\n icon={UiCollapseAll}\n />\n </div>\n );\n}\n\nfunction GroupingButton({\n label,\n pressed,\n disabled,\n onClick,\n icon,\n}: {\n label: string;\n pressed: boolean;\n disabled: boolean;\n onClick: () => void;\n icon: StaticIconComponent;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n aria-pressed={pressed}\n disabled={disabled}\n onClick={onClick}\n className={cn(\n \"inline-flex h-control-h w-control-h items-center justify-center rounded-md border border-border bg-background text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n pressed && \"bg-accent text-accent-foreground\",\n )}\n >\n <Icon icon={icon} className=\"text-sm\" />\n </button>\n );\n}\n"],"names":[],"mappings":";;;;;;AAqBO,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmC;AACjC,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,MAAK;AAAA,MACL,cAAW;AAAA,MAEX,UAAA;AAAA,QAAA,oBAAC,OAAA,EAAI,WAAU,iBACb,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,cAAW;AAAA,YACX;AAAA,YACA,SAAS;AAAA,YACT,UAAU,CAAC,UAAU,aAAa,MAAM,OAAO,KAAK;AAAA,UAAA;AAAA,QAAA,GAExD;AAAA,QACA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAM;AAAA,YACN,SAAS;AAAA,YACT,UAAU,CAAC;AAAA,YACX,SAAS;AAAA,YACT,MAAM;AAAA,UAAA;AAAA,QAAA;AAAA,QAER;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAM;AAAA,YACN,SAAS;AAAA,YACT,UAAU,CAAC;AAAA,YACX,SAAS;AAAA,YACT,MAAM;AAAA,UAAA;AAAA,QAAA;AAAA,MACR;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,OAAO;AAAA,MACP,gBAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,WAAW;AAAA,MAAA;AAAA,MAGb,UAAA,oBAAC,MAAA,EAAK,MAAY,WAAU,UAAA,CAAU;AAAA,IAAA;AAAA,EAAA;AAG5C;"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ function HighlightedTokens({
5
+ tokens,
6
+ content
7
+ }) {
8
+ if (!tokens || tokens.length === 0) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: content });
9
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: tokens.map((token, index) => /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenStyle(token), children: token.content }, index)) });
10
+ }
11
+ function tokenStyle(token) {
12
+ const style = {};
13
+ if (token.color) style.color = token.color;
14
+ const fontStyle = token.fontStyle ?? 0;
15
+ if (fontStyle & 1) style.fontStyle = "italic";
16
+ if (fontStyle & 2) style.fontWeight = 700;
17
+ if (fontStyle & 4) style.textDecorationLine = "underline";
18
+ return style;
19
+ }
20
+ exports.HighlightedTokens = HighlightedTokens;
21
+ //# sourceMappingURL=HighlightedTokens.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HighlightedTokens.cjs","sources":["../../src/data/HighlightedTokens.tsx"],"sourcesContent":["import type { CSSProperties } from \"react\";\nimport type { HighlightedLine, HighlightedToken } from \"./code-highlight\";\n\n// HighlightedTokens paints one `highlightToLines` line as themed spans, falling\n// back to the raw text when tokenization was unavailable (unsupported language,\n// highlighter failure, or the tokens simply not loaded yet). Shared by every\n// surface that paints its own gutter — CodeDiff's diff rows and the stack-frame\n// source window — none of which can embed Shiki's own `<pre>` because their line\n// numbers are not a contiguous 1..N run.\nexport function HighlightedTokens({\n tokens,\n content,\n}: {\n tokens: HighlightedLine | undefined;\n content: string;\n}) {\n if (!tokens || tokens.length === 0) return <>{content}</>;\n return (\n <>\n {tokens.map((token, index) => (\n <span key={index} style={tokenStyle(token)}>\n {token.content}\n </span>\n ))}\n </>\n );\n}\n\n// Shiki's `fontStyle` is a bitmask: 1=italic, 2=bold, 4=underline.\nfunction tokenStyle(token: HighlightedToken): CSSProperties {\n const style: CSSProperties = {};\n if (token.color) style.color = token.color;\n const fontStyle = token.fontStyle ?? 0;\n if (fontStyle & 1) style.fontStyle = \"italic\";\n if (fontStyle & 2) style.fontWeight = 700;\n if (fontStyle & 4) style.textDecorationLine = \"underline\";\n return style;\n}\n"],"names":["jsx"],"mappings":";;;AASO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AACF,GAGG;AACD,MAAI,CAAC,UAAU,OAAO,WAAW,EAAG,8DAAU,UAAA,SAAQ;AACtD,+DAEK,UAAA,OAAO,IAAI,CAAC,OAAO,UAClBA,+BAAC,QAAA,EAAiB,OAAO,WAAW,KAAK,GACtC,UAAA,MAAM,QAAA,GADE,KAEX,CACD,GACH;AAEJ;AAGA,SAAS,WAAW,OAAwC;AAC1D,QAAM,QAAuB,CAAA;AAC7B,MAAI,MAAM,MAAO,OAAM,QAAQ,MAAM;AACrC,QAAM,YAAY,MAAM,aAAa;AACrC,MAAI,YAAY,EAAG,OAAM,YAAY;AACrC,MAAI,YAAY,EAAG,OAAM,aAAa;AACtC,MAAI,YAAY,EAAG,OAAM,qBAAqB;AAC9C,SAAO;AACT;;"}
@@ -0,0 +1,6 @@
1
+ import { HighlightedLine } from './code-highlight';
2
+ export declare function HighlightedTokens({ tokens, content, }: {
3
+ tokens: HighlightedLine | undefined;
4
+ content: string;
5
+ }): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=HighlightedTokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HighlightedTokens.d.ts","sourceRoot":"","sources":["../../src/data/HighlightedTokens.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,kBAAkB,CAAC;AAQ1E,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,OAAO,GACR,EAAE;IACD,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB,2CAWA"}
@@ -0,0 +1,21 @@
1
+ import { jsx, Fragment } from "react/jsx-runtime";
2
+ function HighlightedTokens({
3
+ tokens,
4
+ content
5
+ }) {
6
+ if (!tokens || tokens.length === 0) return /* @__PURE__ */ jsx(Fragment, { children: content });
7
+ return /* @__PURE__ */ jsx(Fragment, { children: tokens.map((token, index) => /* @__PURE__ */ jsx("span", { style: tokenStyle(token), children: token.content }, index)) });
8
+ }
9
+ function tokenStyle(token) {
10
+ const style = {};
11
+ if (token.color) style.color = token.color;
12
+ const fontStyle = token.fontStyle ?? 0;
13
+ if (fontStyle & 1) style.fontStyle = "italic";
14
+ if (fontStyle & 2) style.fontWeight = 700;
15
+ if (fontStyle & 4) style.textDecorationLine = "underline";
16
+ return style;
17
+ }
18
+ export {
19
+ HighlightedTokens
20
+ };
21
+ //# sourceMappingURL=HighlightedTokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HighlightedTokens.js","sources":["../../src/data/HighlightedTokens.tsx"],"sourcesContent":["import type { CSSProperties } from \"react\";\nimport type { HighlightedLine, HighlightedToken } from \"./code-highlight\";\n\n// HighlightedTokens paints one `highlightToLines` line as themed spans, falling\n// back to the raw text when tokenization was unavailable (unsupported language,\n// highlighter failure, or the tokens simply not loaded yet). Shared by every\n// surface that paints its own gutter — CodeDiff's diff rows and the stack-frame\n// source window — none of which can embed Shiki's own `<pre>` because their line\n// numbers are not a contiguous 1..N run.\nexport function HighlightedTokens({\n tokens,\n content,\n}: {\n tokens: HighlightedLine | undefined;\n content: string;\n}) {\n if (!tokens || tokens.length === 0) return <>{content}</>;\n return (\n <>\n {tokens.map((token, index) => (\n <span key={index} style={tokenStyle(token)}>\n {token.content}\n </span>\n ))}\n </>\n );\n}\n\n// Shiki's `fontStyle` is a bitmask: 1=italic, 2=bold, 4=underline.\nfunction tokenStyle(token: HighlightedToken): CSSProperties {\n const style: CSSProperties = {};\n if (token.color) style.color = token.color;\n const fontStyle = token.fontStyle ?? 0;\n if (fontStyle & 1) style.fontStyle = \"italic\";\n if (fontStyle & 2) style.fontWeight = 700;\n if (fontStyle & 4) style.textDecorationLine = \"underline\";\n return style;\n}\n"],"names":[],"mappings":";AASO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AACF,GAGG;AACD,MAAI,CAAC,UAAU,OAAO,WAAW,EAAG,wCAAU,UAAA,SAAQ;AACtD,yCAEK,UAAA,OAAO,IAAI,CAAC,OAAO,UAClB,oBAAC,QAAA,EAAiB,OAAO,WAAW,KAAK,GACtC,UAAA,MAAM,QAAA,GADE,KAEX,CACD,GACH;AAEJ;AAGA,SAAS,WAAW,OAAwC;AAC1D,QAAM,QAAuB,CAAA;AAC7B,MAAI,MAAM,MAAO,OAAM,QAAQ,MAAM;AACrC,QAAM,YAAY,MAAM,aAAa;AACrC,MAAI,YAAY,EAAG,OAAM,YAAY;AACrC,MAAI,YAAY,EAAG,OAAM,aAAa;AACtC,MAAI,YAAY,EAAG,OAAM,qBAAqB;AAC9C,SAAO;AACT;"}
@@ -42,7 +42,6 @@ const SUPPORTED_LANGS = [
42
42
  const SUPPORTED_THEMES = ["github-light", "github-dark"];
43
43
  const DEFAULT_THEME = "github-light";
44
44
  let highlighterLoad = null;
45
- let transformersLoad = null;
46
45
  function loadHighlighter() {
47
46
  highlighterLoad ?? (highlighterLoad = (async () => {
48
47
  const [{ createHighlighterCore }, { createOnigurumaEngine }] = await Promise.all([
@@ -75,10 +74,6 @@ function loadHighlighter() {
75
74
  })());
76
75
  return highlighterLoad;
77
76
  }
78
- function loadShikiTransformers() {
79
- transformersLoad ?? (transformersLoad = import("@shikijs/transformers"));
80
- return transformersLoad;
81
- }
82
77
  function languageFromPath(path) {
83
78
  if (!path) return void 0;
84
79
  const basename = path.slice(path.lastIndexOf("/") + 1);
@@ -141,5 +136,4 @@ async function highlightToLines(source, opts) {
141
136
  exports.highlightCode = highlightCode;
142
137
  exports.highlightToLines = highlightToLines;
143
138
  exports.languageFromPath = languageFromPath;
144
- exports.loadShikiTransformers = loadShikiTransformers;
145
139
  //# sourceMappingURL=code-highlight.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"code-highlight.cjs","sources":["../../src/data/code-highlight.ts"],"sourcesContent":["// Lazy-loaded wrapper around a Shiki *core* highlighter pre-registered with a\n// fixed language + theme set. The default `shiki` entry point bundles every\n// grammar/theme as separate dynamic imports — Vite then code-splits each into\n// its own chunk (~280 langs + 50 themes), even when only a handful are ever\n// used. Switching to `shiki/core` and registering a curated subset cuts the\n// app dist by ~6M and ~300 chunks.\n//\n// Languages are picked from what the renderer actually emits (Clicky code\n// blocks + Java stack traces). Anything outside the list silently falls back\n// to plain text — same behavior as before, just without paying for grammars\n// nobody asked for.\n\nimport type { HighlighterCore, ThemeRegistrationAny } from \"shiki/core\";\n\ntype ShikiTransformersModule = typeof import(\"@shikijs/transformers\");\ntype ShikiTransformer = NonNullable<\n Parameters<HighlighterCore[\"codeToHtml\"]>[1][\"transformers\"]\n>[number];\n\nconst SUPPORTED_LANGS = [\n \"java\",\n \"go\",\n \"python\",\n \"javascript\",\n \"typescript\",\n \"tsx\",\n \"jsx\",\n \"json\",\n \"yaml\",\n \"bash\",\n \"shell\",\n \"sql\",\n \"xml\",\n \"html\",\n \"css\",\n] as const;\n\ntype SupportedLang = (typeof SUPPORTED_LANGS)[number];\n\nconst SUPPORTED_THEMES = [\"github-light\", \"github-dark\"] as const;\ntype SupportedTheme = (typeof SUPPORTED_THEMES)[number];\nconst DEFAULT_THEME: SupportedTheme = \"github-light\";\n\nlet highlighterLoad: Promise<HighlighterCore> | null = null;\nlet transformersLoad: Promise<ShikiTransformersModule> | null = null;\n\nfunction loadHighlighter(): Promise<HighlighterCore> {\n highlighterLoad ??= (async () => {\n const [{ createHighlighterCore }, { createOnigurumaEngine }] = await Promise.all([\n import(\"shiki/core\"),\n import(\"shiki/engine/oniguruma\"),\n ]);\n return createHighlighterCore({\n themes: [\n import(\"@shikijs/themes/github-light\") as Promise<{ default: ThemeRegistrationAny }>,\n import(\"@shikijs/themes/github-dark\") as Promise<{ default: ThemeRegistrationAny }>,\n ],\n langs: [\n import(\"@shikijs/langs/java\"),\n import(\"@shikijs/langs/go\"),\n import(\"@shikijs/langs/python\"),\n import(\"@shikijs/langs/javascript\"),\n import(\"@shikijs/langs/typescript\"),\n import(\"@shikijs/langs/tsx\"),\n import(\"@shikijs/langs/jsx\"),\n import(\"@shikijs/langs/json\"),\n import(\"@shikijs/langs/yaml\"),\n import(\"@shikijs/langs/bash\"),\n import(\"@shikijs/langs/sql\"),\n import(\"@shikijs/langs/xml\"),\n import(\"@shikijs/langs/html\"),\n import(\"@shikijs/langs/css\"),\n ],\n engine: createOnigurumaEngine(import(\"shiki/wasm\")),\n });\n })();\n return highlighterLoad;\n}\n\nexport function loadShikiTransformers(): Promise<ShikiTransformersModule> {\n transformersLoad ??= import(\"@shikijs/transformers\");\n return transformersLoad;\n}\n\nexport type HighlightOptions = {\n lang: string;\n theme?: string;\n transformers?: ShikiTransformer[];\n};\n\n// Derive a highlighter language hint from a file path's extension (e.g.\n// \"src/app.tsx\" → \"tsx\"). Returns undefined for extensionless paths and dotfiles;\n// `resolveLang` then maps aliases and drops anything unsupported.\nexport function languageFromPath(path: string | undefined): string | undefined {\n if (!path) return undefined;\n const basename = path.slice(path.lastIndexOf(\"/\") + 1);\n const dot = basename.lastIndexOf(\".\");\n if (dot <= 0) return undefined;\n return basename.slice(dot + 1).toLowerCase();\n}\n\nfunction resolveLang(input: string): SupportedLang | null {\n const lang = input.toLowerCase();\n if ((SUPPORTED_LANGS as readonly string[]).includes(lang)) return lang as SupportedLang;\n if (lang === \"shell\" || lang === \"sh\" || lang === \"zsh\") return \"bash\";\n if (lang === \"ts\") return \"typescript\";\n if (lang === \"js\") return \"javascript\";\n if (lang === \"py\") return \"python\";\n if (lang === \"yml\") return \"yaml\";\n return null;\n}\n\nfunction resolveTheme(input: string | undefined): SupportedTheme {\n if (input && (SUPPORTED_THEMES as readonly string[]).includes(input)) {\n return input as SupportedTheme;\n }\n return DEFAULT_THEME;\n}\n\nexport async function highlightCode(\n source: string,\n opts: HighlightOptions,\n): Promise<string | null> {\n if (!source || !opts.lang) return null;\n const lang = resolveLang(opts.lang);\n if (!lang) return null;\n try {\n const highlighter = await loadHighlighter();\n return highlighter.codeToHtml(source, {\n lang,\n theme: resolveTheme(opts.theme),\n ...(opts.transformers ? { transformers: opts.transformers } : {}),\n });\n } catch {\n return null;\n }\n}\n\n// A single highlighted token: its text, an optional hex `color`, and Shiki's\n// `fontStyle` bitmask (1=italic, 2=bold, 4=underline).\nexport type HighlightedToken = { content: string; color?: string; fontStyle?: number };\nexport type HighlightedLine = HighlightedToken[];\n\n// Tokenize `source` into per-line themed tokens for `CodeDiff`, which paints its\n// own diff gutters/rows rather than embedding Shiki's `<pre>` HTML. Returns null\n// on empty source, an unsupported language, or a highlighter failure — the caller\n// then renders plain text (same graceful degradation as `highlightCode`).\nexport async function highlightToLines(\n source: string,\n opts: HighlightOptions,\n): Promise<HighlightedLine[] | null> {\n if (!source || !opts.lang) return null;\n const lang = resolveLang(opts.lang);\n if (!lang) return null;\n try {\n const highlighter = await loadHighlighter();\n const { tokens } = highlighter.codeToTokens(source, {\n lang,\n theme: resolveTheme(opts.theme),\n });\n return tokens.map((line) =>\n line.map((token) => ({\n content: token.content,\n ...(token.color ? { color: token.color } : {}),\n ...(token.fontStyle ? { fontStyle: token.fontStyle } : {}),\n })),\n );\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAmBA,MAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIA,MAAM,mBAAmB,CAAC,gBAAgB,aAAa;AAEvD,MAAM,gBAAgC;AAEtC,IAAI,kBAAmD;AACvD,IAAI,mBAA4D;AAEhE,SAAS,kBAA4C;AACnD,yCAAqB,YAAY;AAC/B,UAAM,CAAC,EAAE,yBAAyB,EAAE,uBAAuB,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC/E,OAAO,YAAY;AAAA,MACnB,OAAO,wBAAwB;AAAA,IAAA,CAChC;AACD,WAAO,sBAAsB;AAAA,MAC3B,QAAQ;AAAA,QACN,OAAO,8BAA8B;AAAA,QACrC,OAAO,6BAA6B;AAAA,MAAA;AAAA,MAEtC,OAAO;AAAA,QACL,OAAO,qBAAqB;AAAA,QAC5B,OAAO,mBAAmB;AAAA,QAC1B,OAAO,uBAAuB;AAAA,QAC9B,OAAO,2BAA2B;AAAA,QAClC,OAAO,2BAA2B;AAAA,QAClC,OAAO,oBAAoB;AAAA,QAC3B,OAAO,oBAAoB;AAAA,QAC3B,OAAO,qBAAqB;AAAA,QAC5B,OAAO,qBAAqB;AAAA,QAC5B,OAAO,qBAAqB;AAAA,QAC5B,OAAO,oBAAoB;AAAA,QAC3B,OAAO,oBAAoB;AAAA,QAC3B,OAAO,qBAAqB;AAAA,QAC5B,OAAO,oBAAoB;AAAA,MAAA;AAAA,MAE7B,QAAQ,sBAAsB,OAAO,YAAY,CAAC;AAAA,IAAA,CACnD;AAAA,EACH,GAAA;AACA,SAAO;AACT;AAEO,SAAS,wBAA0D;AACxE,0CAAqB,OAAO,uBAAuB;AACnD,SAAO;AACT;AAWO,SAAS,iBAAiB,MAA8C;AAC7E,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,WAAW,KAAK,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC;AACrD,QAAM,MAAM,SAAS,YAAY,GAAG;AACpC,MAAI,OAAO,EAAG,QAAO;AACrB,SAAO,SAAS,MAAM,MAAM,CAAC,EAAE,YAAA;AACjC;AAEA,SAAS,YAAY,OAAqC;AACxD,QAAM,OAAO,MAAM,YAAA;AACnB,MAAK,gBAAsC,SAAS,IAAI,EAAG,QAAO;AAClE,MAAI,SAAS,WAAW,SAAS,QAAQ,SAAS,MAAO,QAAO;AAChE,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,SAAS,MAAO,QAAO;AAC3B,SAAO;AACT;AAEA,SAAS,aAAa,OAA2C;AAC/D,MAAI,SAAU,iBAAuC,SAAS,KAAK,GAAG;AACpE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,eAAsB,cACpB,QACA,MACwB;AACxB,MAAI,CAAC,UAAU,CAAC,KAAK,KAAM,QAAO;AAClC,QAAM,OAAO,YAAY,KAAK,IAAI;AAClC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,UAAM,cAAc,MAAM,gBAAA;AAC1B,WAAO,YAAY,WAAW,QAAQ;AAAA,MACpC;AAAA,MACA,OAAO,aAAa,KAAK,KAAK;AAAA,MAC9B,GAAI,KAAK,eAAe,EAAE,cAAc,KAAK,aAAA,IAAiB,CAAA;AAAA,IAAC,CAChE;AAAA,EACH,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAWA,eAAsB,iBACpB,QACA,MACmC;AACnC,MAAI,CAAC,UAAU,CAAC,KAAK,KAAM,QAAO;AAClC,QAAM,OAAO,YAAY,KAAK,IAAI;AAClC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,UAAM,cAAc,MAAM,gBAAA;AAC1B,UAAM,EAAE,OAAA,IAAW,YAAY,aAAa,QAAQ;AAAA,MAClD;AAAA,MACA,OAAO,aAAa,KAAK,KAAK;AAAA,IAAA,CAC/B;AACD,WAAO,OAAO;AAAA,MAAI,CAAC,SACjB,KAAK,IAAI,CAAC,WAAW;AAAA,QACnB,SAAS,MAAM;AAAA,QACf,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAA,IAAU,CAAA;AAAA,QAC3C,GAAI,MAAM,YAAY,EAAE,WAAW,MAAM,UAAA,IAAc,CAAA;AAAA,MAAC,EACxD;AAAA,IAAA;AAAA,EAEN,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;;;"}
1
+ {"version":3,"file":"code-highlight.cjs","sources":["../../src/data/code-highlight.ts"],"sourcesContent":["// Lazy-loaded wrapper around a Shiki *core* highlighter pre-registered with a\n// fixed language + theme set. The default `shiki` entry point bundles every\n// grammar/theme as separate dynamic imports — Vite then code-splits each into\n// its own chunk (~280 langs + 50 themes), even when only a handful are ever\n// used. Switching to `shiki/core` and registering a curated subset cuts the\n// app dist by ~6M and ~300 chunks.\n//\n// Languages are picked from what the renderer actually emits (Clicky code\n// blocks + Java stack traces). Anything outside the list silently falls back\n// to plain text — same behavior as before, just without paying for grammars\n// nobody asked for.\n\nimport type { HighlighterCore, ThemeRegistrationAny } from \"shiki/core\";\n\ntype ShikiTransformer = NonNullable<\n Parameters<HighlighterCore[\"codeToHtml\"]>[1][\"transformers\"]\n>[number];\n\nconst SUPPORTED_LANGS = [\n \"java\",\n \"go\",\n \"python\",\n \"javascript\",\n \"typescript\",\n \"tsx\",\n \"jsx\",\n \"json\",\n \"yaml\",\n \"bash\",\n \"shell\",\n \"sql\",\n \"xml\",\n \"html\",\n \"css\",\n] as const;\n\ntype SupportedLang = (typeof SUPPORTED_LANGS)[number];\n\nconst SUPPORTED_THEMES = [\"github-light\", \"github-dark\"] as const;\ntype SupportedTheme = (typeof SUPPORTED_THEMES)[number];\nconst DEFAULT_THEME: SupportedTheme = \"github-light\";\n\nlet highlighterLoad: Promise<HighlighterCore> | null = null;\n\nfunction loadHighlighter(): Promise<HighlighterCore> {\n highlighterLoad ??= (async () => {\n const [{ createHighlighterCore }, { createOnigurumaEngine }] = await Promise.all([\n import(\"shiki/core\"),\n import(\"shiki/engine/oniguruma\"),\n ]);\n return createHighlighterCore({\n themes: [\n import(\"@shikijs/themes/github-light\") as Promise<{ default: ThemeRegistrationAny }>,\n import(\"@shikijs/themes/github-dark\") as Promise<{ default: ThemeRegistrationAny }>,\n ],\n langs: [\n import(\"@shikijs/langs/java\"),\n import(\"@shikijs/langs/go\"),\n import(\"@shikijs/langs/python\"),\n import(\"@shikijs/langs/javascript\"),\n import(\"@shikijs/langs/typescript\"),\n import(\"@shikijs/langs/tsx\"),\n import(\"@shikijs/langs/jsx\"),\n import(\"@shikijs/langs/json\"),\n import(\"@shikijs/langs/yaml\"),\n import(\"@shikijs/langs/bash\"),\n import(\"@shikijs/langs/sql\"),\n import(\"@shikijs/langs/xml\"),\n import(\"@shikijs/langs/html\"),\n import(\"@shikijs/langs/css\"),\n ],\n engine: createOnigurumaEngine(import(\"shiki/wasm\")),\n });\n })();\n return highlighterLoad;\n}\n\nexport type HighlightOptions = {\n /** Highlighter language. Undefined when the caller has none, in which case\n * both entry points return null and the caller renders plain text — better\n * than guessing a grammar and mis-colouring the source. */\n lang: string | undefined;\n theme?: string;\n transformers?: ShikiTransformer[];\n};\n\n// Derive a highlighter language hint from a file path's extension (e.g.\n// \"src/app.tsx\" → \"tsx\"). Returns undefined for extensionless paths and dotfiles;\n// `resolveLang` then maps aliases and drops anything unsupported.\nexport function languageFromPath(path: string | undefined): string | undefined {\n if (!path) return undefined;\n const basename = path.slice(path.lastIndexOf(\"/\") + 1);\n const dot = basename.lastIndexOf(\".\");\n if (dot <= 0) return undefined;\n return basename.slice(dot + 1).toLowerCase();\n}\n\nfunction resolveLang(input: string): SupportedLang | null {\n const lang = input.toLowerCase();\n if ((SUPPORTED_LANGS as readonly string[]).includes(lang)) return lang as SupportedLang;\n if (lang === \"shell\" || lang === \"sh\" || lang === \"zsh\") return \"bash\";\n if (lang === \"ts\") return \"typescript\";\n if (lang === \"js\") return \"javascript\";\n if (lang === \"py\") return \"python\";\n if (lang === \"yml\") return \"yaml\";\n return null;\n}\n\nfunction resolveTheme(input: string | undefined): SupportedTheme {\n if (input && (SUPPORTED_THEMES as readonly string[]).includes(input)) {\n return input as SupportedTheme;\n }\n return DEFAULT_THEME;\n}\n\nexport async function highlightCode(\n source: string,\n opts: HighlightOptions,\n): Promise<string | null> {\n if (!source || !opts.lang) return null;\n const lang = resolveLang(opts.lang);\n if (!lang) return null;\n try {\n const highlighter = await loadHighlighter();\n return highlighter.codeToHtml(source, {\n lang,\n theme: resolveTheme(opts.theme),\n ...(opts.transformers ? { transformers: opts.transformers } : {}),\n });\n } catch {\n return null;\n }\n}\n\n// A single highlighted token: its text, an optional hex `color`, and Shiki's\n// `fontStyle` bitmask (1=italic, 2=bold, 4=underline).\nexport type HighlightedToken = { content: string; color?: string; fontStyle?: number };\nexport type HighlightedLine = HighlightedToken[];\n\n// Tokenize `source` into per-line themed tokens for the renderers that paint\n// their own gutters/rows rather than embedding Shiki's `<pre>` HTML `CodeDiff`\n// (add/remove markers) and `FrameSourceWindow` (absolute, possibly\n// non-contiguous, source line numbers). Returns null on empty source, an\n// unsupported language, or a highlighter failure — the caller then renders plain\n// text (same graceful degradation as `highlightCode`).\nexport async function highlightToLines(\n source: string,\n opts: HighlightOptions,\n): Promise<HighlightedLine[] | null> {\n if (!source || !opts.lang) return null;\n const lang = resolveLang(opts.lang);\n if (!lang) return null;\n try {\n const highlighter = await loadHighlighter();\n const { tokens } = highlighter.codeToTokens(source, {\n lang,\n theme: resolveTheme(opts.theme),\n });\n return tokens.map((line) =>\n line.map((token) => ({\n content: token.content,\n ...(token.color ? { color: token.color } : {}),\n ...(token.fontStyle ? { fontStyle: token.fontStyle } : {}),\n })),\n );\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  import { HighlighterCore } from 'shiki/core';
2
- type ShikiTransformersModule = typeof import("@shikijs/transformers");
3
2
  type ShikiTransformer = NonNullable<Parameters<HighlighterCore["codeToHtml"]>[1]["transformers"]>[number];
4
- export declare function loadShikiTransformers(): Promise<ShikiTransformersModule>;
5
3
  export type HighlightOptions = {
6
- lang: string;
4
+ /** Highlighter language. Undefined when the caller has none, in which case
5
+ * both entry points return null and the caller renders plain text — better
6
+ * than guessing a grammar and mis-colouring the source. */
7
+ lang: string | undefined;
7
8
  theme?: string;
8
9
  transformers?: ShikiTransformer[];
9
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"code-highlight.d.ts","sourceRoot":"","sources":["../../src/data/code-highlight.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAwB,MAAM,YAAY,CAAC;AAExE,KAAK,uBAAuB,GAAG,cAAc,uBAAuB,CAAC,CAAC;AACtE,KAAK,gBAAgB,GAAG,WAAW,CACjC,UAAU,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAC7D,CAAC,MAAM,CAAC,CAAC;AA8DV,wBAAgB,qBAAqB,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAGxE;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC,CAAC;AAKF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAM7E;AAoBD,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB;AAID,MAAM,MAAM,gBAAgB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACvF,MAAM,MAAM,eAAe,GAAG,gBAAgB,EAAE,CAAC;AAMjD,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAoBnC"}
1
+ {"version":3,"file":"code-highlight.d.ts","sourceRoot":"","sources":["../../src/data/code-highlight.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAwB,MAAM,YAAY,CAAC;AAExE,KAAK,gBAAgB,GAAG,WAAW,CACjC,UAAU,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAC7D,CAAC,MAAM,CAAC,CAAC;AA6DV,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;gEAE4D;IAC5D,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC,CAAC;AAKF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAM7E;AAoBD,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB;AAID,MAAM,MAAM,gBAAgB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACvF,MAAM,MAAM,eAAe,GAAG,gBAAgB,EAAE,CAAC;AAQjD,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAoBnC"}
@@ -18,7 +18,6 @@ const SUPPORTED_LANGS = [
18
18
  const SUPPORTED_THEMES = ["github-light", "github-dark"];
19
19
  const DEFAULT_THEME = "github-light";
20
20
  let highlighterLoad = null;
21
- let transformersLoad = null;
22
21
  function loadHighlighter() {
23
22
  highlighterLoad ?? (highlighterLoad = (async () => {
24
23
  const [{ createHighlighterCore }, { createOnigurumaEngine }] = await Promise.all([
@@ -51,10 +50,6 @@ function loadHighlighter() {
51
50
  })());
52
51
  return highlighterLoad;
53
52
  }
54
- function loadShikiTransformers() {
55
- transformersLoad ?? (transformersLoad = import("@shikijs/transformers"));
56
- return transformersLoad;
57
- }
58
53
  function languageFromPath(path) {
59
54
  if (!path) return void 0;
60
55
  const basename = path.slice(path.lastIndexOf("/") + 1);
@@ -117,7 +112,6 @@ async function highlightToLines(source, opts) {
117
112
  export {
118
113
  highlightCode,
119
114
  highlightToLines,
120
- languageFromPath,
121
- loadShikiTransformers
115
+ languageFromPath
122
116
  };
123
117
  //# sourceMappingURL=code-highlight.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"code-highlight.js","sources":["../../src/data/code-highlight.ts"],"sourcesContent":["// Lazy-loaded wrapper around a Shiki *core* highlighter pre-registered with a\n// fixed language + theme set. The default `shiki` entry point bundles every\n// grammar/theme as separate dynamic imports — Vite then code-splits each into\n// its own chunk (~280 langs + 50 themes), even when only a handful are ever\n// used. Switching to `shiki/core` and registering a curated subset cuts the\n// app dist by ~6M and ~300 chunks.\n//\n// Languages are picked from what the renderer actually emits (Clicky code\n// blocks + Java stack traces). Anything outside the list silently falls back\n// to plain text — same behavior as before, just without paying for grammars\n// nobody asked for.\n\nimport type { HighlighterCore, ThemeRegistrationAny } from \"shiki/core\";\n\ntype ShikiTransformersModule = typeof import(\"@shikijs/transformers\");\ntype ShikiTransformer = NonNullable<\n Parameters<HighlighterCore[\"codeToHtml\"]>[1][\"transformers\"]\n>[number];\n\nconst SUPPORTED_LANGS = [\n \"java\",\n \"go\",\n \"python\",\n \"javascript\",\n \"typescript\",\n \"tsx\",\n \"jsx\",\n \"json\",\n \"yaml\",\n \"bash\",\n \"shell\",\n \"sql\",\n \"xml\",\n \"html\",\n \"css\",\n] as const;\n\ntype SupportedLang = (typeof SUPPORTED_LANGS)[number];\n\nconst SUPPORTED_THEMES = [\"github-light\", \"github-dark\"] as const;\ntype SupportedTheme = (typeof SUPPORTED_THEMES)[number];\nconst DEFAULT_THEME: SupportedTheme = \"github-light\";\n\nlet highlighterLoad: Promise<HighlighterCore> | null = null;\nlet transformersLoad: Promise<ShikiTransformersModule> | null = null;\n\nfunction loadHighlighter(): Promise<HighlighterCore> {\n highlighterLoad ??= (async () => {\n const [{ createHighlighterCore }, { createOnigurumaEngine }] = await Promise.all([\n import(\"shiki/core\"),\n import(\"shiki/engine/oniguruma\"),\n ]);\n return createHighlighterCore({\n themes: [\n import(\"@shikijs/themes/github-light\") as Promise<{ default: ThemeRegistrationAny }>,\n import(\"@shikijs/themes/github-dark\") as Promise<{ default: ThemeRegistrationAny }>,\n ],\n langs: [\n import(\"@shikijs/langs/java\"),\n import(\"@shikijs/langs/go\"),\n import(\"@shikijs/langs/python\"),\n import(\"@shikijs/langs/javascript\"),\n import(\"@shikijs/langs/typescript\"),\n import(\"@shikijs/langs/tsx\"),\n import(\"@shikijs/langs/jsx\"),\n import(\"@shikijs/langs/json\"),\n import(\"@shikijs/langs/yaml\"),\n import(\"@shikijs/langs/bash\"),\n import(\"@shikijs/langs/sql\"),\n import(\"@shikijs/langs/xml\"),\n import(\"@shikijs/langs/html\"),\n import(\"@shikijs/langs/css\"),\n ],\n engine: createOnigurumaEngine(import(\"shiki/wasm\")),\n });\n })();\n return highlighterLoad;\n}\n\nexport function loadShikiTransformers(): Promise<ShikiTransformersModule> {\n transformersLoad ??= import(\"@shikijs/transformers\");\n return transformersLoad;\n}\n\nexport type HighlightOptions = {\n lang: string;\n theme?: string;\n transformers?: ShikiTransformer[];\n};\n\n// Derive a highlighter language hint from a file path's extension (e.g.\n// \"src/app.tsx\" → \"tsx\"). Returns undefined for extensionless paths and dotfiles;\n// `resolveLang` then maps aliases and drops anything unsupported.\nexport function languageFromPath(path: string | undefined): string | undefined {\n if (!path) return undefined;\n const basename = path.slice(path.lastIndexOf(\"/\") + 1);\n const dot = basename.lastIndexOf(\".\");\n if (dot <= 0) return undefined;\n return basename.slice(dot + 1).toLowerCase();\n}\n\nfunction resolveLang(input: string): SupportedLang | null {\n const lang = input.toLowerCase();\n if ((SUPPORTED_LANGS as readonly string[]).includes(lang)) return lang as SupportedLang;\n if (lang === \"shell\" || lang === \"sh\" || lang === \"zsh\") return \"bash\";\n if (lang === \"ts\") return \"typescript\";\n if (lang === \"js\") return \"javascript\";\n if (lang === \"py\") return \"python\";\n if (lang === \"yml\") return \"yaml\";\n return null;\n}\n\nfunction resolveTheme(input: string | undefined): SupportedTheme {\n if (input && (SUPPORTED_THEMES as readonly string[]).includes(input)) {\n return input as SupportedTheme;\n }\n return DEFAULT_THEME;\n}\n\nexport async function highlightCode(\n source: string,\n opts: HighlightOptions,\n): Promise<string | null> {\n if (!source || !opts.lang) return null;\n const lang = resolveLang(opts.lang);\n if (!lang) return null;\n try {\n const highlighter = await loadHighlighter();\n return highlighter.codeToHtml(source, {\n lang,\n theme: resolveTheme(opts.theme),\n ...(opts.transformers ? { transformers: opts.transformers } : {}),\n });\n } catch {\n return null;\n }\n}\n\n// A single highlighted token: its text, an optional hex `color`, and Shiki's\n// `fontStyle` bitmask (1=italic, 2=bold, 4=underline).\nexport type HighlightedToken = { content: string; color?: string; fontStyle?: number };\nexport type HighlightedLine = HighlightedToken[];\n\n// Tokenize `source` into per-line themed tokens for `CodeDiff`, which paints its\n// own diff gutters/rows rather than embedding Shiki's `<pre>` HTML. Returns null\n// on empty source, an unsupported language, or a highlighter failure — the caller\n// then renders plain text (same graceful degradation as `highlightCode`).\nexport async function highlightToLines(\n source: string,\n opts: HighlightOptions,\n): Promise<HighlightedLine[] | null> {\n if (!source || !opts.lang) return null;\n const lang = resolveLang(opts.lang);\n if (!lang) return null;\n try {\n const highlighter = await loadHighlighter();\n const { tokens } = highlighter.codeToTokens(source, {\n lang,\n theme: resolveTheme(opts.theme),\n });\n return tokens.map((line) =>\n line.map((token) => ({\n content: token.content,\n ...(token.color ? { color: token.color } : {}),\n ...(token.fontStyle ? { fontStyle: token.fontStyle } : {}),\n })),\n );\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"code-highlight.js","sources":["../../src/data/code-highlight.ts"],"sourcesContent":["// Lazy-loaded wrapper around a Shiki *core* highlighter pre-registered with a\n// fixed language + theme set. The default `shiki` entry point bundles every\n// grammar/theme as separate dynamic imports — Vite then code-splits each into\n// its own chunk (~280 langs + 50 themes), even when only a handful are ever\n// used. Switching to `shiki/core` and registering a curated subset cuts the\n// app dist by ~6M and ~300 chunks.\n//\n// Languages are picked from what the renderer actually emits (Clicky code\n// blocks + Java stack traces). Anything outside the list silently falls back\n// to plain text — same behavior as before, just without paying for grammars\n// nobody asked for.\n\nimport type { HighlighterCore, ThemeRegistrationAny } from \"shiki/core\";\n\ntype ShikiTransformer = NonNullable<\n Parameters<HighlighterCore[\"codeToHtml\"]>[1][\"transformers\"]\n>[number];\n\nconst SUPPORTED_LANGS = [\n \"java\",\n \"go\",\n \"python\",\n \"javascript\",\n \"typescript\",\n \"tsx\",\n \"jsx\",\n \"json\",\n \"yaml\",\n \"bash\",\n \"shell\",\n \"sql\",\n \"xml\",\n \"html\",\n \"css\",\n] as const;\n\ntype SupportedLang = (typeof SUPPORTED_LANGS)[number];\n\nconst SUPPORTED_THEMES = [\"github-light\", \"github-dark\"] as const;\ntype SupportedTheme = (typeof SUPPORTED_THEMES)[number];\nconst DEFAULT_THEME: SupportedTheme = \"github-light\";\n\nlet highlighterLoad: Promise<HighlighterCore> | null = null;\n\nfunction loadHighlighter(): Promise<HighlighterCore> {\n highlighterLoad ??= (async () => {\n const [{ createHighlighterCore }, { createOnigurumaEngine }] = await Promise.all([\n import(\"shiki/core\"),\n import(\"shiki/engine/oniguruma\"),\n ]);\n return createHighlighterCore({\n themes: [\n import(\"@shikijs/themes/github-light\") as Promise<{ default: ThemeRegistrationAny }>,\n import(\"@shikijs/themes/github-dark\") as Promise<{ default: ThemeRegistrationAny }>,\n ],\n langs: [\n import(\"@shikijs/langs/java\"),\n import(\"@shikijs/langs/go\"),\n import(\"@shikijs/langs/python\"),\n import(\"@shikijs/langs/javascript\"),\n import(\"@shikijs/langs/typescript\"),\n import(\"@shikijs/langs/tsx\"),\n import(\"@shikijs/langs/jsx\"),\n import(\"@shikijs/langs/json\"),\n import(\"@shikijs/langs/yaml\"),\n import(\"@shikijs/langs/bash\"),\n import(\"@shikijs/langs/sql\"),\n import(\"@shikijs/langs/xml\"),\n import(\"@shikijs/langs/html\"),\n import(\"@shikijs/langs/css\"),\n ],\n engine: createOnigurumaEngine(import(\"shiki/wasm\")),\n });\n })();\n return highlighterLoad;\n}\n\nexport type HighlightOptions = {\n /** Highlighter language. Undefined when the caller has none, in which case\n * both entry points return null and the caller renders plain text — better\n * than guessing a grammar and mis-colouring the source. */\n lang: string | undefined;\n theme?: string;\n transformers?: ShikiTransformer[];\n};\n\n// Derive a highlighter language hint from a file path's extension (e.g.\n// \"src/app.tsx\" → \"tsx\"). Returns undefined for extensionless paths and dotfiles;\n// `resolveLang` then maps aliases and drops anything unsupported.\nexport function languageFromPath(path: string | undefined): string | undefined {\n if (!path) return undefined;\n const basename = path.slice(path.lastIndexOf(\"/\") + 1);\n const dot = basename.lastIndexOf(\".\");\n if (dot <= 0) return undefined;\n return basename.slice(dot + 1).toLowerCase();\n}\n\nfunction resolveLang(input: string): SupportedLang | null {\n const lang = input.toLowerCase();\n if ((SUPPORTED_LANGS as readonly string[]).includes(lang)) return lang as SupportedLang;\n if (lang === \"shell\" || lang === \"sh\" || lang === \"zsh\") return \"bash\";\n if (lang === \"ts\") return \"typescript\";\n if (lang === \"js\") return \"javascript\";\n if (lang === \"py\") return \"python\";\n if (lang === \"yml\") return \"yaml\";\n return null;\n}\n\nfunction resolveTheme(input: string | undefined): SupportedTheme {\n if (input && (SUPPORTED_THEMES as readonly string[]).includes(input)) {\n return input as SupportedTheme;\n }\n return DEFAULT_THEME;\n}\n\nexport async function highlightCode(\n source: string,\n opts: HighlightOptions,\n): Promise<string | null> {\n if (!source || !opts.lang) return null;\n const lang = resolveLang(opts.lang);\n if (!lang) return null;\n try {\n const highlighter = await loadHighlighter();\n return highlighter.codeToHtml(source, {\n lang,\n theme: resolveTheme(opts.theme),\n ...(opts.transformers ? { transformers: opts.transformers } : {}),\n });\n } catch {\n return null;\n }\n}\n\n// A single highlighted token: its text, an optional hex `color`, and Shiki's\n// `fontStyle` bitmask (1=italic, 2=bold, 4=underline).\nexport type HighlightedToken = { content: string; color?: string; fontStyle?: number };\nexport type HighlightedLine = HighlightedToken[];\n\n// Tokenize `source` into per-line themed tokens for the renderers that paint\n// their own gutters/rows rather than embedding Shiki's `<pre>` HTML `CodeDiff`\n// (add/remove markers) and `FrameSourceWindow` (absolute, possibly\n// non-contiguous, source line numbers). Returns null on empty source, an\n// unsupported language, or a highlighter failure — the caller then renders plain\n// text (same graceful degradation as `highlightCode`).\nexport async function highlightToLines(\n source: string,\n opts: HighlightOptions,\n): Promise<HighlightedLine[] | null> {\n if (!source || !opts.lang) return null;\n const lang = resolveLang(opts.lang);\n if (!lang) return null;\n try {\n const highlighter = await loadHighlighter();\n const { tokens } = highlighter.codeToTokens(source, {\n lang,\n theme: resolveTheme(opts.theme),\n });\n return tokens.map((line) =>\n line.map((token) => ({\n content: token.content,\n ...(token.color ? { color: token.color } : {}),\n ...(token.fontStyle ? { fontStyle: token.fontStyle } : {}),\n })),\n );\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -37,6 +37,7 @@ function DiagnosticsDetailPanel({
37
37
  onCollectStack,
38
38
  runMeta,
39
39
  resolveSource,
40
+ frameActions,
40
41
  headerActions,
41
42
  singleItem
42
43
  }) {
@@ -98,7 +99,8 @@ function DiagnosticsDetailPanel({
98
99
  collectBusy: collectBusy ?? false,
99
100
  singleItem: singleItem ?? false,
100
101
  ...onCollectStack ? { onCollectStack } : {},
101
- ...resolveSource ? { resolveSource } : {}
102
+ ...resolveSource ? { resolveSource } : {},
103
+ ...frameActions ? { frameActions } : {}
102
104
  }
103
105
  ) })
104
106
  ] });
@@ -188,6 +190,7 @@ function StackBlock(props) {
188
190
  collectBusy,
189
191
  onCollectStack,
190
192
  resolveSource,
193
+ frameActions,
191
194
  singleItem
192
195
  } = props;
193
196
  const stack = process.stack_capture;
@@ -337,7 +340,8 @@ function StackBlock(props) {
337
340
  thread: t,
338
341
  search,
339
342
  hideRuntimeOnly,
340
- ...resolveSource ? { resolveSource } : {}
343
+ ...resolveSource ? { resolveSource } : {},
344
+ ...frameActions ? { frameActions } : {}
341
345
  },
342
346
  t.id
343
347
  )),