mdx-forge 0.1.1

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 (260) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/dist/components/base/styles/callout.css +64 -0
  4. package/dist/components/base/styles/collapsible.css +96 -0
  5. package/dist/components/base/styles/index.css +7 -0
  6. package/dist/components/base/styles/tabs.css +97 -0
  7. package/dist/components/docusaurus/styles.css +291 -0
  8. package/dist/components/generic/styles.css +102 -0
  9. package/dist/components/nextra/styles.css +500 -0
  10. package/dist/components/shared/callout-variants.css +81 -0
  11. package/dist/components/shared/index.css +6 -0
  12. package/dist/components/shared/tokens.css +105 -0
  13. package/dist/components/starlight/styles.css +602 -0
  14. package/dist/components/styles/docusaurus.css +2 -0
  15. package/dist/components/styles/generic.css +2 -0
  16. package/dist/components/styles/nextjs.css +1 -0
  17. package/dist/components/styles/nextra.css +2 -0
  18. package/dist/components/styles/starlight.css +2 -0
  19. package/dist/components/styles/tokens.css +1 -0
  20. package/dist/esm/browser/errors.js +48 -0
  21. package/dist/esm/browser/eval/evaluateModule.js +49 -0
  22. package/dist/esm/browser/index.js +147 -0
  23. package/dist/esm/browser/internal/constants.js +4 -0
  24. package/dist/esm/browser/internal/logger.js +9 -0
  25. package/dist/esm/browser/internal/lru-cache.js +139 -0
  26. package/dist/esm/browser/internal/module-id.js +7 -0
  27. package/dist/esm/browser/internal/runtime-config.js +35 -0
  28. package/dist/esm/browser/internal/semaphore.js +23 -0
  29. package/dist/esm/browser/internal/style-injector.js +32 -0
  30. package/dist/esm/browser/loader/circular.js +15 -0
  31. package/dist/esm/browser/loader/loadModule.js +175 -0
  32. package/dist/esm/browser/preload/core.js +16 -0
  33. package/dist/esm/browser/preload/index.js +77 -0
  34. package/dist/esm/browser/preload/shimLoader.js +88 -0
  35. package/dist/esm/browser/registry/DependencyTracker.js +154 -0
  36. package/dist/esm/browser/registry/ModuleCache.js +168 -0
  37. package/dist/esm/browser/registry/ModuleRegistry.js +156 -0
  38. package/dist/esm/browser/registry/StyleCache.js +94 -0
  39. package/dist/esm/browser/registry/index.js +4 -0
  40. package/dist/esm/browser/runtime/require.js +40 -0
  41. package/dist/esm/browser/styles/injectStyles.js +42 -0
  42. package/dist/esm/browser/types.js +8 -0
  43. package/dist/esm/compiler/index.js +9 -0
  44. package/dist/esm/compiler/internal/components.js +28 -0
  45. package/dist/esm/compiler/internal/logging.js +10 -0
  46. package/dist/esm/compiler/internal/path.js +17 -0
  47. package/dist/esm/compiler/internal/plugin-loader.js +23 -0
  48. package/dist/esm/compiler/internal/trust.js +16 -0
  49. package/dist/esm/compiler/pipeline/common/icon-registry.js +1 -0
  50. package/dist/esm/compiler/pipeline/common/mdx-common.js +61 -0
  51. package/dist/esm/compiler/pipeline/common/pipeline-config.js +163 -0
  52. package/dist/esm/compiler/pipeline/common/pipeline-warnings.js +125 -0
  53. package/dist/esm/compiler/pipeline/rehype/create-diagram-placeholder.js +79 -0
  54. package/dist/esm/compiler/pipeline/rehype/graphviz-placeholder.js +15 -0
  55. package/dist/esm/compiler/pipeline/rehype/lazy-images.js +19 -0
  56. package/dist/esm/compiler/pipeline/rehype/mermaid-placeholder.js +11 -0
  57. package/dist/esm/compiler/pipeline/rehype/plantuml-placeholder.js +11 -0
  58. package/dist/esm/compiler/pipeline/rehype/rehype-raw.js +33 -0
  59. package/dist/esm/compiler/pipeline/rehype/shiki-helpers.js +9 -0
  60. package/dist/esm/compiler/pipeline/rehype/shiki.js +318 -0
  61. package/dist/esm/compiler/pipeline/remark/admonitions.js +168 -0
  62. package/dist/esm/compiler/pipeline/remark/generic-components.js +56 -0
  63. package/dist/esm/compiler/pipeline/remark/github-alerts.js +121 -0
  64. package/dist/esm/compiler/pipeline/transforms/callout.js +78 -0
  65. package/dist/esm/compiler/pipeline/transforms/code-group.js +23 -0
  66. package/dist/esm/compiler/pipeline/transforms/collapsible.js +30 -0
  67. package/dist/esm/compiler/pipeline/transforms/index.js +12 -0
  68. package/dist/esm/compiler/pipeline/transforms/tabs.js +48 -0
  69. package/dist/esm/compiler/pipeline/transforms/utils.js +69 -0
  70. package/dist/esm/compiler/plugins/builder.js +54 -0
  71. package/dist/esm/compiler/plugins/index.js +3 -0
  72. package/dist/esm/compiler/plugins/loader.js +120 -0
  73. package/dist/esm/compiler/plugins/shared-plugins.js +56 -0
  74. package/dist/esm/compiler/plugins/utils.js +13 -0
  75. package/dist/esm/compiler/safe/compile.js +228 -0
  76. package/dist/esm/compiler/transforms/index.js +1 -0
  77. package/dist/esm/compiler/trusted/compile.js +134 -0
  78. package/dist/esm/compiler/trusted/component-mapper.js +85 -0
  79. package/dist/esm/compiler/trusted/hasDefaultExport.js +15 -0
  80. package/dist/esm/compiler/types/compiler.js +1 -0
  81. package/dist/esm/compiler/types/index.js +3 -0
  82. package/dist/esm/compiler/types/mdx.js +3 -0
  83. package/dist/esm/compiler/types/pipeline.js +18 -0
  84. package/dist/esm/components/base/BaseCallout.js +50 -0
  85. package/dist/esm/components/base/BaseCard.js +11 -0
  86. package/dist/esm/components/base/BaseCodeBlock.js +42 -0
  87. package/dist/esm/components/base/BaseTabs.js +168 -0
  88. package/dist/esm/components/base/CopyButton.js +12 -0
  89. package/dist/esm/components/base/createCollapsible.js +63 -0
  90. package/dist/esm/components/base/createIconComponent.js +31 -0
  91. package/dist/esm/components/base/extractTextContent.js +19 -0
  92. package/dist/esm/components/base/icons.js +49 -0
  93. package/dist/esm/components/base/index.js +15 -0
  94. package/dist/esm/components/base/useCopyToClipboard.js +17 -0
  95. package/dist/esm/components/base/useTabState.js +113 -0
  96. package/dist/esm/components/docusaurus/CodeBlock.js +13 -0
  97. package/dist/esm/components/docusaurus/Details.js +18 -0
  98. package/dist/esm/components/docusaurus/Tabs.js +15 -0
  99. package/dist/esm/components/docusaurus/index.js +3 -0
  100. package/dist/esm/components/generic/Callout.js +28 -0
  101. package/dist/esm/components/generic/CodeGroup.js +52 -0
  102. package/dist/esm/components/generic/Collapsible.js +21 -0
  103. package/dist/esm/components/generic/TabItem.js +8 -0
  104. package/dist/esm/components/generic/Tabs.js +13 -0
  105. package/dist/esm/components/generic/index.js +6 -0
  106. package/dist/esm/components/generic/types.js +5 -0
  107. package/dist/esm/components/index.js +8 -0
  108. package/dist/esm/components/internal/clipboard.js +9 -0
  109. package/dist/esm/components/internal/cn.js +4 -0
  110. package/dist/esm/components/internal/constants.js +1 -0
  111. package/dist/esm/components/nextjs/Image.js +36 -0
  112. package/dist/esm/components/nextjs/Link.js +28 -0
  113. package/dist/esm/components/nextjs/index.js +2 -0
  114. package/dist/esm/components/nextra/Bleed.js +18 -0
  115. package/dist/esm/components/nextra/Callout.js +30 -0
  116. package/dist/esm/components/nextra/Cards.js +25 -0
  117. package/dist/esm/components/nextra/FileTree.js +11 -0
  118. package/dist/esm/components/nextra/Steps.js +11 -0
  119. package/dist/esm/components/nextra/Tabs.js +28 -0
  120. package/dist/esm/components/nextra/createNextraWrapper.js +12 -0
  121. package/dist/esm/components/nextra/index.js +6 -0
  122. package/dist/esm/components/registry/index.js +4 -0
  123. package/dist/esm/components/registry/queries.js +69 -0
  124. package/dist/esm/components/registry/registry-data.js +357 -0
  125. package/dist/esm/components/registry/shim-config.js +187 -0
  126. package/dist/esm/components/registry/types.js +3 -0
  127. package/dist/esm/components/starlight/Aside.js +24 -0
  128. package/dist/esm/components/starlight/Badge.js +6 -0
  129. package/dist/esm/components/starlight/Card.js +28 -0
  130. package/dist/esm/components/starlight/CardGrid.js +6 -0
  131. package/dist/esm/components/starlight/Code.js +25 -0
  132. package/dist/esm/components/starlight/FileTree.js +148 -0
  133. package/dist/esm/components/starlight/LinkCard.js +8 -0
  134. package/dist/esm/components/starlight/Steps.js +6 -0
  135. package/dist/esm/components/starlight/Tabs.js +6 -0
  136. package/dist/esm/components/starlight/index.js +9 -0
  137. package/dist/esm/internal/callout.js +43 -0
  138. package/dist/esm/internal/errors.js +27 -0
  139. package/dist/esm/internal/icons.js +41 -0
  140. package/dist/types/browser/errors.d.ts +18 -0
  141. package/dist/types/browser/eval/evaluateModule.d.ts +2 -0
  142. package/dist/types/browser/index.d.ts +20 -0
  143. package/dist/types/browser/internal/constants.d.ts +4 -0
  144. package/dist/types/browser/internal/logger.d.ts +9 -0
  145. package/dist/types/browser/internal/lru-cache.d.ts +33 -0
  146. package/dist/types/browser/internal/module-id.d.ts +1 -0
  147. package/dist/types/browser/internal/runtime-config.d.ts +10 -0
  148. package/dist/types/browser/internal/semaphore.d.ts +7 -0
  149. package/dist/types/browser/internal/style-injector.d.ts +3 -0
  150. package/dist/types/browser/loader/circular.d.ts +4 -0
  151. package/dist/types/browser/loader/loadModule.d.ts +2 -0
  152. package/dist/types/browser/preload/core.d.ts +11 -0
  153. package/dist/types/browser/preload/index.d.ts +21 -0
  154. package/dist/types/browser/preload/shimLoader.d.ts +20 -0
  155. package/dist/types/browser/registry/DependencyTracker.d.ts +23 -0
  156. package/dist/types/browser/registry/ModuleCache.d.ts +30 -0
  157. package/dist/types/browser/registry/ModuleRegistry.d.ts +44 -0
  158. package/dist/types/browser/registry/StyleCache.d.ts +17 -0
  159. package/dist/types/browser/registry/index.d.ts +4 -0
  160. package/dist/types/browser/runtime/require.d.ts +1 -0
  161. package/dist/types/browser/styles/injectStyles.d.ts +3 -0
  162. package/dist/types/browser/types.d.ts +50 -0
  163. package/dist/types/compiler/index.d.ts +6 -0
  164. package/dist/types/compiler/internal/components.d.ts +21 -0
  165. package/dist/types/compiler/internal/logging.d.ts +3 -0
  166. package/dist/types/compiler/internal/path.d.ts +2 -0
  167. package/dist/types/compiler/internal/plugin-loader.d.ts +2 -0
  168. package/dist/types/compiler/internal/trust.d.ts +2 -0
  169. package/dist/types/compiler/pipeline/common/icon-registry.d.ts +1 -0
  170. package/dist/types/compiler/pipeline/common/mdx-common.d.ts +8 -0
  171. package/dist/types/compiler/pipeline/common/pipeline-config.d.ts +39 -0
  172. package/dist/types/compiler/pipeline/common/pipeline-warnings.d.ts +21 -0
  173. package/dist/types/compiler/pipeline/rehype/create-diagram-placeholder.d.ts +15 -0
  174. package/dist/types/compiler/pipeline/rehype/graphviz-placeholder.d.ts +2 -0
  175. package/dist/types/compiler/pipeline/rehype/lazy-images.d.ts +2 -0
  176. package/dist/types/compiler/pipeline/rehype/mermaid-placeholder.d.ts +2 -0
  177. package/dist/types/compiler/pipeline/rehype/plantuml-placeholder.d.ts +2 -0
  178. package/dist/types/compiler/pipeline/rehype/rehype-raw.d.ts +2 -0
  179. package/dist/types/compiler/pipeline/rehype/shiki-helpers.d.ts +2 -0
  180. package/dist/types/compiler/pipeline/rehype/shiki.d.ts +2 -0
  181. package/dist/types/compiler/pipeline/remark/admonitions.d.ts +2 -0
  182. package/dist/types/compiler/pipeline/remark/generic-components.d.ts +6 -0
  183. package/dist/types/compiler/pipeline/remark/github-alerts.d.ts +2 -0
  184. package/dist/types/compiler/pipeline/transforms/callout.d.ts +10 -0
  185. package/dist/types/compiler/pipeline/transforms/code-group.d.ts +3 -0
  186. package/dist/types/compiler/pipeline/transforms/collapsible.d.ts +3 -0
  187. package/dist/types/compiler/pipeline/transforms/index.d.ts +6 -0
  188. package/dist/types/compiler/pipeline/transforms/tabs.d.ts +4 -0
  189. package/dist/types/compiler/pipeline/transforms/utils.d.ts +6 -0
  190. package/dist/types/compiler/plugins/builder.d.ts +14 -0
  191. package/dist/types/compiler/plugins/index.d.ts +3 -0
  192. package/dist/types/compiler/plugins/loader.d.ts +4 -0
  193. package/dist/types/compiler/plugins/shared-plugins.d.ts +13 -0
  194. package/dist/types/compiler/plugins/utils.d.ts +4 -0
  195. package/dist/types/compiler/safe/compile.d.ts +2 -0
  196. package/dist/types/compiler/transforms/index.d.ts +1 -0
  197. package/dist/types/compiler/trusted/compile.d.ts +2 -0
  198. package/dist/types/compiler/trusted/component-mapper.d.ts +10 -0
  199. package/dist/types/compiler/trusted/hasDefaultExport.d.ts +2 -0
  200. package/dist/types/compiler/types/compiler.d.ts +83 -0
  201. package/dist/types/compiler/types/index.d.ts +3 -0
  202. package/dist/types/compiler/types/mdx.d.ts +36 -0
  203. package/dist/types/compiler/types/pipeline.d.ts +54 -0
  204. package/dist/types/components/base/BaseCallout.d.ts +26 -0
  205. package/dist/types/components/base/BaseCard.d.ts +11 -0
  206. package/dist/types/components/base/BaseCodeBlock.d.ts +23 -0
  207. package/dist/types/components/base/BaseTabs.d.ts +52 -0
  208. package/dist/types/components/base/CopyButton.d.ts +8 -0
  209. package/dist/types/components/base/createCollapsible.d.ts +27 -0
  210. package/dist/types/components/base/createIconComponent.d.ts +6 -0
  211. package/dist/types/components/base/extractTextContent.d.ts +2 -0
  212. package/dist/types/components/base/icons.d.ts +50 -0
  213. package/dist/types/components/base/index.d.ts +12 -0
  214. package/dist/types/components/base/useCopyToClipboard.d.ts +5 -0
  215. package/dist/types/components/base/useTabState.d.ts +43 -0
  216. package/dist/types/components/docusaurus/CodeBlock.d.ts +3 -0
  217. package/dist/types/components/docusaurus/Details.d.ts +4 -0
  218. package/dist/types/components/docusaurus/Tabs.d.ts +7 -0
  219. package/dist/types/components/docusaurus/index.d.ts +3 -0
  220. package/dist/types/components/generic/Callout.d.ts +8 -0
  221. package/dist/types/components/generic/CodeGroup.d.ts +4 -0
  222. package/dist/types/components/generic/Collapsible.d.ts +4 -0
  223. package/dist/types/components/generic/TabItem.d.ts +6 -0
  224. package/dist/types/components/generic/Tabs.d.ts +6 -0
  225. package/dist/types/components/generic/index.d.ts +6 -0
  226. package/dist/types/components/generic/types.d.ts +19 -0
  227. package/dist/types/components/index.d.ts +7 -0
  228. package/dist/types/components/internal/clipboard.d.ts +1 -0
  229. package/dist/types/components/internal/cn.d.ts +1 -0
  230. package/dist/types/components/internal/constants.d.ts +1 -0
  231. package/dist/types/components/nextjs/Image.d.ts +25 -0
  232. package/dist/types/components/nextjs/Link.d.ts +19 -0
  233. package/dist/types/components/nextjs/index.d.ts +2 -0
  234. package/dist/types/components/nextra/Bleed.d.ts +17 -0
  235. package/dist/types/components/nextra/Callout.d.ts +10 -0
  236. package/dist/types/components/nextra/Cards.d.ts +18 -0
  237. package/dist/types/components/nextra/FileTree.d.ts +4 -0
  238. package/dist/types/components/nextra/Steps.d.ts +4 -0
  239. package/dist/types/components/nextra/Tabs.d.ts +21 -0
  240. package/dist/types/components/nextra/createNextraWrapper.d.ts +14 -0
  241. package/dist/types/components/nextra/index.d.ts +6 -0
  242. package/dist/types/components/registry/index.d.ts +4 -0
  243. package/dist/types/components/registry/queries.d.ts +11 -0
  244. package/dist/types/components/registry/registry-data.d.ts +303 -0
  245. package/dist/types/components/registry/shim-config.d.ts +18 -0
  246. package/dist/types/components/registry/types.d.ts +25 -0
  247. package/dist/types/components/starlight/Aside.d.ts +6 -0
  248. package/dist/types/components/starlight/Badge.d.ts +9 -0
  249. package/dist/types/components/starlight/Card.d.ts +8 -0
  250. package/dist/types/components/starlight/CardGrid.d.ts +7 -0
  251. package/dist/types/components/starlight/Code.d.ts +11 -0
  252. package/dist/types/components/starlight/FileTree.d.ts +6 -0
  253. package/dist/types/components/starlight/LinkCard.d.ts +8 -0
  254. package/dist/types/components/starlight/Steps.d.ts +6 -0
  255. package/dist/types/components/starlight/Tabs.d.ts +2 -0
  256. package/dist/types/components/starlight/index.d.ts +9 -0
  257. package/dist/types/internal/callout.d.ts +7 -0
  258. package/dist/types/internal/errors.d.ts +3 -0
  259. package/dist/types/internal/icons.d.ts +50 -0
  260. package/package.json +150 -0
@@ -0,0 +1,168 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // packages/webview-app/src/components/shims/base/BaseTabs.tsx
3
+ // factory for creating framework-specific Tabs components w/ shared logic
4
+ import { createContext, useContext, useRef, useCallback, Children, isValidElement, } from 'react';
5
+ import { cn } from '../internal/cn.js';
6
+ import { useTabState, useIndexTabs, } from './useTabState.js';
7
+ // factory function to create framework-specific Tabs components
8
+ // all implementations share the same core logic via useTabState hook
9
+ export function createTabs(config) {
10
+ const { classPrefix, wrapperClass, supportsGroupId = false, tabItemClassName = `${classPrefix}-item`, contextName, } = config;
11
+ // create a unique context for this tabs implementation
12
+ const TabsContext = createContext(false);
13
+ TabsContext.displayName = `${contextName}Context`;
14
+ // the Tabs component
15
+ function Tabs({ children, defaultValue, values, className, groupId, }) {
16
+ const { activeValue, setActiveValue, tabs, tabItems } = useTabState({
17
+ children,
18
+ defaultValue,
19
+ values,
20
+ });
21
+ // refs for tab buttons to enable focus management
22
+ const tabRefs = useRef([]);
23
+ // handle keyboard navigation for tabs
24
+ const handleKeyDown = useCallback((e, currentIndex) => {
25
+ const tabCount = tabs.length;
26
+ let newIndex = currentIndex;
27
+ switch (e.key) {
28
+ case 'ArrowLeft':
29
+ case 'ArrowUp':
30
+ newIndex = (currentIndex - 1 + tabCount) % tabCount;
31
+ break;
32
+ case 'ArrowRight':
33
+ case 'ArrowDown':
34
+ newIndex = (currentIndex + 1) % tabCount;
35
+ break;
36
+ case 'Home':
37
+ newIndex = 0;
38
+ break;
39
+ case 'End':
40
+ newIndex = tabCount - 1;
41
+ break;
42
+ default:
43
+ return;
44
+ }
45
+ e.preventDefault();
46
+ setActiveValue(tabs[newIndex].value);
47
+ tabRefs.current[newIndex]?.focus();
48
+ }, [tabs, setActiveValue]);
49
+ // build wrapper class
50
+ const wrapperClassName = wrapperClass
51
+ ? `${wrapperClass}${className ? ` ${className}` : ''}`
52
+ : `${classPrefix}${className ? ` ${className}` : ''}`;
53
+ return (_jsx(TabsContext.Provider, { value: true, children: _jsxs("div", { className: wrapperClassName, "data-component": "tabs", "data-group-id": supportsGroupId ? groupId : undefined, children: [_jsx("div", { className: `${classPrefix}-header`, role: "tablist", children: tabs.map((tab, index) => (_jsx("button", { ref: (el) => {
54
+ tabRefs.current[index] = el;
55
+ }, role: "tab", className: `${classPrefix}-button${tab.value === activeValue ? ' active' : ''}`, "aria-selected": tab.value === activeValue, onClick: () => setActiveValue(tab.value), onKeyDown: (e) => handleKeyDown(e, index), tabIndex: tab.value === activeValue ? 0 : -1, children: tab.label }, tab.value))) }), _jsx("div", { className: `${classPrefix}-content`, children: tabItems.map((item) => (_jsx("div", { role: "tabpanel", className: `${classPrefix}-panel${item.value === activeValue ? ' active' : ''}`, hidden: item.value !== activeValue, children: item.content }, item.value))) })] }) }));
56
+ }
57
+ Tabs.displayName = contextName;
58
+ // provide TabItem for shared props extraction
59
+ function TabItem({ children }) {
60
+ const isInsideTabs = useContext(TabsContext);
61
+ // if used outside of Tabs context, render directly
62
+ if (!isInsideTabs) {
63
+ return _jsx("div", { className: tabItemClassName, children: children });
64
+ }
65
+ // render content via parent when inside Tabs
66
+ return _jsx(_Fragment, { children: children });
67
+ }
68
+ TabItem.displayName = `${contextName}TabItem`;
69
+ // hook to check if inside Tabs context
70
+ function useTabsContext() {
71
+ return useContext(TabsContext);
72
+ }
73
+ return { Tabs, TabItem, useTabsContext, TabsContext };
74
+ }
75
+ // factory for creating index-based Tabs components (Nextra style)
76
+ // use items array instead of extracting tabs from children
77
+ export function createIndexTabs(config, accessors) {
78
+ const { classPrefix, contextName } = config;
79
+ const { getLabel, isDisabled = () => false } = accessors;
80
+ const TabsContext = createContext(false);
81
+ TabsContext.displayName = `${contextName}Context`;
82
+ // tab subcomponent (compound component pattern)
83
+ function Tab({ children }) {
84
+ return _jsx(_Fragment, { children: children });
85
+ }
86
+ function TabsComponent({ children, items, defaultIndex = 0, selectedIndex: controlledIndex, storageKey, onChange, className, tabClassName, ...props }) {
87
+ const { activeIndex, setActiveIndex } = useIndexTabs({
88
+ items,
89
+ defaultIndex,
90
+ controlledIndex,
91
+ storageKey,
92
+ onChange,
93
+ isDisabled,
94
+ });
95
+ // refs for tab buttons to enable focus management
96
+ const tabRefs = useRef([]);
97
+ // handle keyboard navigation for tabs
98
+ const handleKeyDown = useCallback((e, currentIndex) => {
99
+ const tabCount = items.length;
100
+ let newIndex = currentIndex;
101
+ switch (e.key) {
102
+ case 'ArrowLeft':
103
+ case 'ArrowUp':
104
+ // find previous non-disabled tab
105
+ for (let i = 1; i <= tabCount; i++) {
106
+ const idx = (currentIndex - i + tabCount) % tabCount;
107
+ if (!isDisabled(items[idx])) {
108
+ newIndex = idx;
109
+ break;
110
+ }
111
+ }
112
+ break;
113
+ case 'ArrowRight':
114
+ case 'ArrowDown':
115
+ // find next non-disabled tab
116
+ for (let i = 1; i <= tabCount; i++) {
117
+ const idx = (currentIndex + i) % tabCount;
118
+ if (!isDisabled(items[idx])) {
119
+ newIndex = idx;
120
+ break;
121
+ }
122
+ }
123
+ break;
124
+ case 'Home':
125
+ // find first non-disabled tab
126
+ for (let i = 0; i < tabCount; i++) {
127
+ if (!isDisabled(items[i])) {
128
+ newIndex = i;
129
+ break;
130
+ }
131
+ }
132
+ break;
133
+ case 'End':
134
+ // find last non-disabled tab
135
+ for (let i = tabCount - 1; i >= 0; i--) {
136
+ if (!isDisabled(items[i])) {
137
+ newIndex = i;
138
+ break;
139
+ }
140
+ }
141
+ break;
142
+ default:
143
+ return;
144
+ }
145
+ e.preventDefault();
146
+ setActiveIndex(newIndex);
147
+ tabRefs.current[newIndex]?.focus();
148
+ }, [items, setActiveIndex]);
149
+ // get Tab children for content panels
150
+ const tabChildren = Children.toArray(children).filter((child) => isValidElement(child) && child.type === Tab);
151
+ return (_jsx(TabsContext.Provider, { value: true, children: _jsxs("div", { className: cn(classPrefix, className), ...props, children: [_jsx("div", { className: `${classPrefix}-header`, role: "tablist", children: items.map((item, index) => {
152
+ const label = getLabel(item);
153
+ const disabled = isDisabled(item);
154
+ const selected = index === activeIndex;
155
+ const customClass = tabClassName
156
+ ? typeof tabClassName === 'function'
157
+ ? tabClassName(index, selected)
158
+ : tabClassName
159
+ : undefined;
160
+ return (_jsx("button", { ref: (el) => {
161
+ tabRefs.current[index] = el;
162
+ }, role: "tab", "aria-selected": selected, "aria-disabled": disabled, tabIndex: selected ? 0 : -1, className: cn(`${classPrefix}-button`, selected && `${classPrefix}-button-active`, disabled && `${classPrefix}-button-disabled`, customClass), onClick: () => setActiveIndex(index), onKeyDown: (e) => handleKeyDown(e, index), disabled: disabled, children: label }, index));
163
+ }) }), _jsx("div", { className: `${classPrefix}-content`, children: tabChildren.map((child, index) => (_jsx("div", { role: "tabpanel", hidden: index !== activeIndex, className: `${classPrefix}-panel`, children: index === activeIndex && child }, index))) })] }) }));
164
+ }
165
+ const Tabs = Object.assign(TabsComponent, { Tab });
166
+ Tabs.displayName = contextName;
167
+ return { Tabs, TabsContext };
168
+ }
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCopyToClipboard } from './useCopyToClipboard.js';
3
+ import { COPY_ICONS } from './icons.js';
4
+ // reusable copy-to-clipboard button w/ visual feedback
5
+ export function CopyButton({ text, className = 'copy-button', copiedClassName = 'copied', }) {
6
+ const { copied, copy } = useCopyToClipboard();
7
+ const buttonClass = copied ? `${className} ${copiedClassName}` : className;
8
+ return (_jsx("button", { className: buttonClass, onClick: () => copy(text), title: copied ? 'Copied!' : 'Copy code', "aria-label": copied ? 'Copied!' : 'Copy code', children: _jsx("span", { dangerouslySetInnerHTML: {
9
+ __html: copied ? COPY_ICONS.check : COPY_ICONS.copy,
10
+ } }) }));
11
+ }
12
+ export default CopyButton;
@@ -0,0 +1,63 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // packages/webview-app/src/components/shims/base/createCollapsible.tsx
3
+ // factory for creating framework-specific collapsible/details components
4
+ import { useState, } from 'react';
5
+ import { cn } from '../internal/cn.js';
6
+ import { ChevronIcon } from './icons.js';
7
+ // preset class configurations for each framework
8
+ // class names for Generic Collapsible
9
+ export const GENERIC_COLLAPSIBLE_CLASSES = {
10
+ container: 'mdx-preview-generic-collapsible',
11
+ summary: 'mdx-preview-generic-collapsible-summary',
12
+ icon: 'mdx-preview-generic-collapsible-icon',
13
+ iconOpen: 'open',
14
+ title: 'mdx-preview-generic-collapsible-title',
15
+ content: 'mdx-preview-generic-collapsible-content',
16
+ };
17
+ // class names for Docusaurus Details
18
+ export const DOCUSAURUS_DETAILS_CLASSES = {
19
+ container: 'docusaurus-details',
20
+ summary: 'details-summary',
21
+ icon: 'details-toggle-icon',
22
+ iconOpen: 'expanded',
23
+ title: 'details-summary-text',
24
+ content: 'details-content',
25
+ };
26
+ // factory function to create framework-specific Collapsible components
27
+ export function createCollapsible(config) {
28
+ const { classNames, iconSize = 16, useNativeToggle = true, applyOpenClassToWrapper = true, defaultSummary = 'Details', } = config;
29
+ function Collapsible({ children, summary, title, defaultOpen = false, open, className, }) {
30
+ // resolve prop aliases
31
+ const effectiveSummary = summary ?? title ?? defaultSummary;
32
+ const effectiveDefaultOpen = open ?? defaultOpen;
33
+ const [isOpen, setIsOpen] = useState(effectiveDefaultOpen);
34
+ // native toggle handler (Docusaurus pattern)
35
+ const handleNativeToggle = useNativeToggle
36
+ ? (e) => {
37
+ setIsOpen(e.target.open);
38
+ }
39
+ : undefined;
40
+ // custom click handler (Generic Collapsible pattern)
41
+ const handleSummaryClick = !useNativeToggle
42
+ ? (e) => {
43
+ e.preventDefault();
44
+ setIsOpen(!isOpen);
45
+ }
46
+ : undefined;
47
+ // prevent native toggle when using custom click handling
48
+ const handleDetailsClick = !useNativeToggle
49
+ ? (e) => {
50
+ if (e.target.tagName === 'SUMMARY') {
51
+ e.preventDefault();
52
+ }
53
+ }
54
+ : undefined;
55
+ // determine icon class based on applyOpenClassToWrapper
56
+ const iconWrapperClass = applyOpenClassToWrapper
57
+ ? cn(classNames.icon, isOpen && classNames.iconOpen)
58
+ : classNames.icon;
59
+ const iconSvgClass = !applyOpenClassToWrapper && isOpen ? classNames.iconOpen : undefined;
60
+ return (_jsxs("details", { className: cn(classNames.container, className), "data-component": "collapsible", open: isOpen, onToggle: handleNativeToggle, onClick: handleDetailsClick, children: [_jsxs("summary", { className: classNames.summary, onClick: handleSummaryClick, children: [_jsx("span", { className: iconWrapperClass, children: _jsx(ChevronIcon, { size: iconSize, className: iconSvgClass }) }), _jsx("span", { className: classNames.title, children: effectiveSummary })] }), _jsx("div", { className: classNames.content, children: children })] }));
61
+ }
62
+ return Collapsible;
63
+ }
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // parse an SVG string to extract viewBox, style attributes & inner content
3
+ // called once per icon at module load time (not per-render)
4
+ function parseSvg(svgString) {
5
+ const viewBoxMatch = svgString.match(/viewBox="([^"]+)"/);
6
+ const fillMatch = svgString.match(/\sfill="([^"]+)"/);
7
+ const strokeMatch = svgString.match(/\sstroke="([^"]+)"/);
8
+ const strokeWidthMatch = svgString.match(/stroke-width="([^"]+)"/);
9
+ const strokeLinecapMatch = svgString.match(/stroke-linecap="([^"]+)"/);
10
+ const strokeLinejoinMatch = svgString.match(/stroke-linejoin="([^"]+)"/);
11
+ const innerMatch = svgString.match(/<svg[^>]*>([\s\S]*)<\/svg>/);
12
+ return {
13
+ viewBox: viewBoxMatch?.[1] ?? '0 0 24 24',
14
+ fill: fillMatch?.[1] ?? 'none',
15
+ stroke: strokeMatch?.[1],
16
+ strokeWidth: strokeWidthMatch?.[1],
17
+ strokeLinecap: strokeLinecapMatch?.[1],
18
+ strokeLinejoin: strokeLinejoinMatch?.[1],
19
+ innerHtml: innerMatch?.[1] ?? '',
20
+ };
21
+ }
22
+ // create a React icon component from a shared SVG string
23
+ // parse the SVG once at module level for zero per-render overhead
24
+ // inner content rendered via dangerouslySetInnerHTML (safe: compile-time constants)
25
+ export function createIconComponent(svgString, defaultSize = 16) {
26
+ const parsed = parseSvg(svgString);
27
+ function IconComponent({ size = defaultSize, className, }) {
28
+ return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: parsed.viewBox, fill: parsed.fill, stroke: parsed.stroke, strokeWidth: parsed.strokeWidth, strokeLinecap: parsed.strokeLinecap, strokeLinejoin: parsed.strokeLinejoin, className: className, dangerouslySetInnerHTML: { __html: parsed.innerHtml } }));
29
+ }
30
+ return IconComponent;
31
+ }
@@ -0,0 +1,19 @@
1
+ // packages/webview-app/src/components/shims/base/extractTextContent.ts
2
+ // shared utility for extracting plain text from React children
3
+ import { isValidElement } from 'react';
4
+ // extract plain text content from React children
5
+ export function extractTextContent(node) {
6
+ if (typeof node === 'string') {
7
+ return node;
8
+ }
9
+ if (typeof node === 'number') {
10
+ return String(node);
11
+ }
12
+ if (Array.isArray(node)) {
13
+ return node.map(extractTextContent).join('');
14
+ }
15
+ if (isValidElement(node)) {
16
+ return extractTextContent(node.props.children);
17
+ }
18
+ return '';
19
+ }
@@ -0,0 +1,49 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { CALLOUT_ICONS as SHARED_CALLOUT_ICONS, GITHUB_ICONS as SHARED_GITHUB_ICONS, FILE_TREE_ICONS as SHARED_FILE_TREE_ICONS, LUCIDE_ICONS as SHARED_LUCIDE_ICONS, } from '../../internal/icons.js';
3
+ import { createIconComponent } from './createIconComponent.js';
4
+ // re-export SVG icon registries from shared package
5
+ export const CALLOUT_ICONS = SHARED_CALLOUT_ICONS;
6
+ export const FILE_TREE_ICONS = SHARED_FILE_TREE_ICONS;
7
+ export const GITHUB_ICONS = SHARED_GITHUB_ICONS;
8
+ export const LUCIDE_ICONS = SHARED_LUCIDE_ICONS;
9
+ // unified copy/check icons for clipboard functionality
10
+ // use GitHub Primer style for consistency w/ code blocks
11
+ export const COPY_ICONS = {
12
+ copy: GITHUB_ICONS.copy,
13
+ check: GITHUB_ICONS.check,
14
+ };
15
+ // JSX icon components derived from shared SVG strings
16
+ // eliminates SVG path duplication between shared & webview packages
17
+ // chevron icon (Lucide style) - used for collapsibles & tree views
18
+ export const ChevronIcon = createIconComponent(FILE_TREE_ICONS.chevron, 16);
19
+ // GitHub Primer style lightbulb icon - used for Nextra default callout
20
+ export const LightbulbIcon = createIconComponent(GITHUB_ICONS.lightbulb, 16);
21
+ // GitHub Primer style info icon - used for Nextra info callout
22
+ export const InfoIconGitHub = createIconComponent(GITHUB_ICONS.info, 16);
23
+ // GitHub Primer style warning icon - used for Nextra warning callout
24
+ export const WarningIconGitHub = createIconComponent(GITHUB_ICONS.warning, 16);
25
+ // GitHub Primer style error/octagon icon - used for Nextra error callout
26
+ export const ErrorIconGitHub = createIconComponent(GITHUB_ICONS.error, 16);
27
+ // GitHub Primer style comment/important icon - used for Nextra important callout
28
+ export const ImportantIconGitHub = createIconComponent(GITHUB_ICONS.important, 16);
29
+ // pre-create GitHub variant at module level (avoid per-render allocation)
30
+ const GitHubArrowIcon = createIconComponent(GITHUB_ICONS.arrowRight, 16);
31
+ const LucideArrowIcon = createIconComponent(LUCIDE_ICONS.arrowRight, 16);
32
+ // arrow icon - used for link cards & navigation
33
+ export function ArrowIcon({ size = 16, className, variant = 'lucide', }) {
34
+ if (variant === 'github') {
35
+ return _jsx(GitHubArrowIcon, { size: size, className: className });
36
+ }
37
+ return _jsx(LucideArrowIcon, { size: size, className: className });
38
+ }
39
+ // copy icon (Lucide style) - used for copy buttons
40
+ export const CopyIcon = createIconComponent(LUCIDE_ICONS.copy, 16);
41
+ // check icon (Lucide style) - used for copy confirmation
42
+ export const CheckIcon = createIconComponent(LUCIDE_ICONS.check, 16);
43
+ export const NEXTRA_CALLOUT_ICONS = {
44
+ default: LightbulbIcon,
45
+ info: InfoIconGitHub,
46
+ warning: WarningIconGitHub,
47
+ error: ErrorIconGitHub,
48
+ important: ImportantIconGitHub,
49
+ };
@@ -0,0 +1,15 @@
1
+ // packages/webview-app/src/components/shims/base/index.ts
2
+ // barrel exports for base shim utilities
3
+ export { useTabState, extractTabItems, } from './useTabState.js';
4
+ export { createTabs, } from './BaseTabs.js';
5
+ export { BaseCard } from './BaseCard.js';
6
+ export { ArrowIcon } from './icons.js';
7
+ export { useCopyToClipboard, } from './useCopyToClipboard.js';
8
+ export { extractTextContent } from './extractTextContent.js';
9
+ export { CopyButton } from './CopyButton.js';
10
+ export { CALLOUT_ICONS, FILE_TREE_ICONS } from './icons.js';
11
+ export { createCallout, } from './BaseCallout.js';
12
+ export { createCodeBlock } from './BaseCodeBlock.js';
13
+ export { createCollapsible, GENERIC_COLLAPSIBLE_CLASSES, DOCUSAURUS_DETAILS_CLASSES, } from './createCollapsible.js';
14
+ // re-export generic callout normalization for discoverability
15
+ export { normalizeCalloutType } from '../generic/types.js';
@@ -0,0 +1,17 @@
1
+ // packages/webview-app/src/components/shims/base/useCopyToClipboard.ts
2
+ // shared hook for copy-to-clipboard functionality
3
+ import { useState, useCallback } from 'react';
4
+ import { copyToClipboard } from '../internal/clipboard.js';
5
+ import { CODE_COPY_FEEDBACK_DURATION_MS } from '../internal/constants.js';
6
+ // hook for copy-to-clipboard functionality w/ visual feedback
7
+ export function useCopyToClipboard() {
8
+ const [copied, setCopied] = useState(false);
9
+ const copy = useCallback(async (text) => {
10
+ const success = await copyToClipboard(text);
11
+ if (success) {
12
+ setCopied(true);
13
+ setTimeout(() => setCopied(false), CODE_COPY_FEEDBACK_DURATION_MS);
14
+ }
15
+ }, []);
16
+ return { copied, copy };
17
+ }
@@ -0,0 +1,113 @@
1
+ // packages/webview-app/src/components/shims/base/useTabState.ts
2
+ // shared hook for tab state management across framework shims
3
+ import { useState, useCallback, isValidElement, Children, } from 'react';
4
+ // extract TabItem children w/ their props
5
+ export function extractTabItems(children) {
6
+ const items = [];
7
+ Children.forEach(children, (child) => {
8
+ if (!isValidElement(child)) {
9
+ return;
10
+ }
11
+ const props = child.props;
12
+ // accept either 'value' (Docusaurus) or 'label' (Starlight) as identifier
13
+ const value = props.value ?? props.label;
14
+ if (value !== undefined) {
15
+ items.push({
16
+ value,
17
+ label: props.label || value,
18
+ content: props.children,
19
+ });
20
+ }
21
+ });
22
+ return items;
23
+ }
24
+ // find default tab value from children
25
+ function findDefaultFromChildren(children, tabItems) {
26
+ const childArray = Children.toArray(children);
27
+ for (const item of tabItems) {
28
+ const child = childArray.find((c) => isValidElement(c) && c.props.value === item.value);
29
+ if (child &&
30
+ isValidElement(child) &&
31
+ child.props.default) {
32
+ return item.value;
33
+ }
34
+ }
35
+ return undefined;
36
+ }
37
+ // hook for managing tab state
38
+ // extract tab items from children, determine initial active value
39
+ // & provide state management for tab selection
40
+ export function useTabState(options) {
41
+ const { children, defaultValue, values } = options;
42
+ // extract tab items from children
43
+ const tabItems = extractTabItems(children);
44
+ // use provided values or extracted ones
45
+ const tabs = values ||
46
+ tabItems.map((item) => ({
47
+ value: item.value,
48
+ label: item.label,
49
+ }));
50
+ // determine initial active value
51
+ const initialValue = defaultValue ||
52
+ findDefaultFromChildren(children, tabItems) ||
53
+ tabs[0]?.value ||
54
+ '';
55
+ const [activeValue, setActiveValue] = useState(initialValue);
56
+ // ensure activeValue is valid (in case tabs change)
57
+ const validActiveValue = tabs.find((t) => t.value === activeValue)
58
+ ? activeValue
59
+ : tabs[0]?.value || '';
60
+ return {
61
+ activeValue: validActiveValue,
62
+ setActiveValue,
63
+ tabs,
64
+ tabItems,
65
+ };
66
+ }
67
+ export default useTabState;
68
+ // hook for index-based tab state management
69
+ export function useIndexTabs({ items, defaultIndex = 0, controlledIndex, storageKey, onChange, isDisabled = () => false, }) {
70
+ // get initial index from localStorage if storageKey is provided
71
+ const getInitialIndex = useCallback(() => {
72
+ if (storageKey && typeof window !== 'undefined') {
73
+ try {
74
+ const stored = localStorage.getItem(`nextra-tabs-${storageKey}`);
75
+ if (stored !== null) {
76
+ const parsed = parseInt(stored, 10);
77
+ if (!isNaN(parsed) && parsed >= 0 && parsed < items.length) {
78
+ return parsed;
79
+ }
80
+ }
81
+ }
82
+ catch {
83
+ // ignore localStorage errors
84
+ }
85
+ }
86
+ return defaultIndex;
87
+ }, [storageKey, defaultIndex, items.length]);
88
+ const [internalIndex, setInternalIndex] = useState(getInitialIndex);
89
+ const activeIndex = controlledIndex ?? internalIndex;
90
+ // handle tab selection
91
+ const setActiveIndex = useCallback((index) => {
92
+ // check if tab is disabled
93
+ if (items[index] !== undefined && isDisabled(items[index], index)) {
94
+ return;
95
+ }
96
+ // update internal state if not controlled
97
+ if (controlledIndex === undefined) {
98
+ setInternalIndex(index);
99
+ }
100
+ // save to localStorage if storageKey is provided
101
+ if (storageKey && typeof window !== 'undefined') {
102
+ try {
103
+ localStorage.setItem(`nextra-tabs-${storageKey}`, String(index));
104
+ }
105
+ catch {
106
+ // ignore localStorage errors
107
+ }
108
+ }
109
+ // call onChange callback
110
+ onChange?.(index);
111
+ }, [controlledIndex, items, isDisabled, onChange, storageKey]);
112
+ return { activeIndex, setActiveIndex };
113
+ }
@@ -0,0 +1,13 @@
1
+ // packages/webview-app/src/components/shims/docusaurus/CodeBlock.tsx
2
+ // Docusaurus CodeBlock component shim for MDX Preview
3
+ // provide preview-compatible version of @theme/CodeBlock
4
+ import { createCodeBlock } from '../base/BaseCodeBlock.js';
5
+ // code block component using shared factory
6
+ export const CodeBlock = createCodeBlock({
7
+ classPrefix: 'docusaurus-codeblock',
8
+ codeAsString: false,
9
+ supportsFrames: false,
10
+ showLangBadgeWithTitle: true,
11
+ });
12
+ // default export for compatibility
13
+ export default CodeBlock;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // packages/webview-app/src/components/shims/docusaurus/Details.tsx
3
+ // Docusaurus Details component shim for MDX Preview
4
+ import { createCollapsible, DOCUSAURUS_DETAILS_CLASSES, } from '../base/createCollapsible.js';
5
+ // create base details w/ Docusaurus configuration
6
+ // use native toggle handling (more semantic)
7
+ const BaseDetails = createCollapsible({
8
+ classNames: DOCUSAURUS_DETAILS_CLASSES,
9
+ iconSize: 14,
10
+ useNativeToggle: true,
11
+ applyOpenClassToWrapper: false,
12
+ defaultSummary: 'Details',
13
+ });
14
+ // Docusaurus Details component
15
+ export function Details(props) {
16
+ return _jsx(BaseDetails, { ...props });
17
+ }
18
+ export default Details;
@@ -0,0 +1,15 @@
1
+ // packages/webview-app/src/components/shims/docusaurus/Tabs.tsx
2
+ // Docusaurus Tabs/TabItem component shim for MDX Preview
3
+ // provide preview-compatible versions of @theme/Tabs & @theme/TabItem
4
+ import { createTabs, } from '../base/index.js';
5
+ // create Docusaurus-compatible tabs using the factory
6
+ // use 'mdx-preview-tabs' class prefix w/ 'docusaurus-tabs' wrapper
7
+ // support groupId for tab synchronization
8
+ const { Tabs, TabItem, useTabsContext, TabsContext } = createTabs({
9
+ classPrefix: 'mdx-preview-tabs',
10
+ wrapperClass: 'docusaurus-tabs',
11
+ supportsGroupId: true,
12
+ contextName: 'DocusaurusTabs',
13
+ });
14
+ export { Tabs, TabItem, useTabsContext, TabsContext };
15
+ export default Tabs;
@@ -0,0 +1,3 @@
1
+ export { Tabs, TabItem } from './Tabs.js';
2
+ export { CodeBlock } from './CodeBlock.js';
3
+ export { Details } from './Details.js';
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createCallout } from '../base/BaseCallout.js';
3
+ import { CALLOUT_TITLES, normalizeCalloutType } from './types.js';
4
+ import { CALLOUT_ICONS } from '../base/icons.js';
5
+ // create the base Callout using factory
6
+ const BaseCallout = createCallout({
7
+ classPrefix: 'mdx-preview-generic-callout',
8
+ types: ['note', 'tip', 'warning', 'danger', 'info', 'caution', 'important'],
9
+ defaultType: 'note',
10
+ icons: { type: 'svg', icons: CALLOUT_ICONS },
11
+ defaultTitles: CALLOUT_TITLES,
12
+ layout: 'header',
13
+ });
14
+ // callout component w/ type normalization
15
+ export function Callout(props) {
16
+ // normalize type aliases (success -> tip, error -> danger, etc.)
17
+ const normalizedType = normalizeCalloutType(props.type);
18
+ return _jsx(BaseCallout, { ...props, type: normalizedType });
19
+ }
20
+ // alert component (alias for Callout)
21
+ export function Alert(props) {
22
+ return _jsx(Callout, { ...props });
23
+ }
24
+ // admonition component (alias for Callout, Docusaurus style)
25
+ export function Admonition(props) {
26
+ return _jsx(Callout, { ...props });
27
+ }
28
+ export default Callout;
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // packages/webview-app/src/components/shims/generic/CodeGroup.tsx
3
+ // Generic CodeGroup component shim for MDX Preview
4
+ // provide tabbed code blocks w/o framework dependency
5
+ import { Children, isValidElement, useState } from 'react';
6
+ // extract label from code block element
7
+ function extractLabelFromCodeBlock(child) {
8
+ const props = child.props;
9
+ // try various prop names used by different frameworks
10
+ if (typeof props.title === 'string') {
11
+ return props.title;
12
+ }
13
+ if (typeof props.label === 'string') {
14
+ return props.label;
15
+ }
16
+ if (typeof props.filename === 'string') {
17
+ return props.filename;
18
+ }
19
+ if (typeof props.language === 'string') {
20
+ return props.language;
21
+ }
22
+ if (typeof props.lang === 'string') {
23
+ return props.lang;
24
+ }
25
+ // try to get from className (e.g., "language-javascript")
26
+ if (typeof props.className === 'string') {
27
+ const match = props.className.match(/language-(\w+)/);
28
+ if (match) {
29
+ return match[1];
30
+ }
31
+ }
32
+ return 'Code';
33
+ }
34
+ // render tabbed code blocks from children
35
+ export function CodeGroup({ children, labels }) {
36
+ const childArray = Children.toArray(children).filter(isValidElement);
37
+ const [activeIndex, setActiveIndex] = useState(0);
38
+ // extract tabs from children
39
+ const tabs = childArray.map((child, index) => {
40
+ const label = labels?.[index] || extractLabelFromCodeBlock(child);
41
+ return { label, content: child };
42
+ });
43
+ if (tabs.length === 0) {
44
+ return (_jsx("div", { className: "mdx-preview-generic-code-group-empty", children: children }));
45
+ }
46
+ // if only one code block, just render it directly
47
+ if (tabs.length === 1) {
48
+ return (_jsx("div", { className: "mdx-preview-generic-code-group", children: tabs[0].content }));
49
+ }
50
+ return (_jsxs("div", { className: "mdx-preview-generic-code-group", children: [_jsx("div", { className: "mdx-preview-generic-code-group-header", role: "tablist", children: tabs.map((tab, index) => (_jsx("button", { role: "tab", className: `mdx-preview-generic-code-group-button${index === activeIndex ? ' active' : ''}`, "aria-selected": index === activeIndex, onClick: () => setActiveIndex(index), tabIndex: index === activeIndex ? 0 : -1, children: tab.label }, index))) }), _jsx("div", { className: "mdx-preview-generic-code-group-content", children: tabs.map((tab, index) => (_jsx("div", { role: "tabpanel", className: `mdx-preview-generic-code-group-panel${index === activeIndex ? ' active' : ''}`, hidden: index !== activeIndex, children: tab.content }, index))) })] }));
51
+ }
52
+ export default CodeGroup;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // packages/webview-app/src/components/shims/generic/Collapsible.tsx
3
+ // Generic Collapsible/Accordion component shim for MDX Preview
4
+ import { createCollapsible, GENERIC_COLLAPSIBLE_CLASSES, } from '../base/createCollapsible.js';
5
+ // create base collapsible w/ generic configuration
6
+ // use custom click handling (prevent native toggle for more control)
7
+ const BaseCollapsible = createCollapsible({
8
+ classNames: GENERIC_COLLAPSIBLE_CLASSES,
9
+ iconSize: 16,
10
+ useNativeToggle: false,
11
+ applyOpenClassToWrapper: true,
12
+ });
13
+ // generic Collapsible component
14
+ export function Collapsible(props) {
15
+ return _jsx(BaseCollapsible, { ...props });
16
+ }
17
+ // accordion component (alias for Collapsible)
18
+ export function Accordion(props) {
19
+ return _jsx(Collapsible, { ...props });
20
+ }
21
+ export default Collapsible;