@suzumiyaaoba/mdxr 0.1.0

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 (236) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/dist/cli.d.mts +1 -0
  4. package/dist/cli.mjs +2902 -0
  5. package/dist/components.d.mts +791 -0
  6. package/dist/components.mjs +2 -0
  7. package/dist/config-SI9IyFiC.mjs +184 -0
  8. package/dist/doc-context-CEqzMYKv.d.mts +568 -0
  9. package/dist/index.d.mts +20 -0
  10. package/dist/index.mjs +4 -0
  11. package/dist/ui-GKFD0mx5.mjs +15986 -0
  12. package/package.json +131 -0
  13. package/skill/SKILL.md +49 -0
  14. package/skill/references/components/charts.md +172 -0
  15. package/skill/references/components/document.md +98 -0
  16. package/skill/references/components/forms.md +35 -0
  17. package/skill/references/components/investigation.md +198 -0
  18. package/skill/references/components/layout.md +68 -0
  19. package/skill/references/components/output.md +158 -0
  20. package/skill/references/components/planning.md +155 -0
  21. package/skill/references/components/reports.md +252 -0
  22. package/skill/references/components/shadcn.md +19 -0
  23. package/skill/references/components.md +186 -0
  24. package/skill/references/extending.md +48 -0
  25. package/src/ask-sheet.ts +40 -0
  26. package/src/assets/css.ts +392 -0
  27. package/src/assets/scripts.ts +78 -0
  28. package/src/catalog.ts +287 -0
  29. package/src/cli.ts +178 -0
  30. package/src/client/doc-events.ts +1108 -0
  31. package/src/client/entry.ts +27 -0
  32. package/src/client-js.ts +47 -0
  33. package/src/component-map.ts +47 -0
  34. package/src/components/ui/accordion.tsx +77 -0
  35. package/src/components/ui/alert-dialog.tsx +185 -0
  36. package/src/components/ui/alert.tsx +76 -0
  37. package/src/components/ui/aspect-ratio.tsx +22 -0
  38. package/src/components/ui/attachment.tsx +208 -0
  39. package/src/components/ui/avatar.tsx +106 -0
  40. package/src/components/ui/badge.tsx +52 -0
  41. package/src/components/ui/breadcrumb.tsx +121 -0
  42. package/src/components/ui/bubble.tsx +128 -0
  43. package/src/components/ui/button-group.tsx +88 -0
  44. package/src/components/ui/button.tsx +58 -0
  45. package/src/components/ui/calendar.tsx +226 -0
  46. package/src/components/ui/card.tsx +102 -0
  47. package/src/components/ui/carousel.tsx +246 -0
  48. package/src/components/ui/chart.tsx +379 -0
  49. package/src/components/ui/checkbox.tsx +27 -0
  50. package/src/components/ui/collapsible.tsx +19 -0
  51. package/src/components/ui/combobox.tsx +298 -0
  52. package/src/components/ui/command.tsx +193 -0
  53. package/src/components/ui/context-menu.tsx +271 -0
  54. package/src/components/ui/dialog.tsx +159 -0
  55. package/src/components/ui/direction.tsx +4 -0
  56. package/src/components/ui/drawer.tsx +227 -0
  57. package/src/components/ui/dropdown-menu.tsx +269 -0
  58. package/src/components/ui/empty.tsx +104 -0
  59. package/src/components/ui/field.tsx +237 -0
  60. package/src/components/ui/fieldset.tsx +32 -0
  61. package/src/components/ui/frame.tsx +87 -0
  62. package/src/components/ui/hover-card.tsx +50 -0
  63. package/src/components/ui/input-group.tsx +159 -0
  64. package/src/components/ui/input-otp.tsx +83 -0
  65. package/src/components/ui/input.tsx +19 -0
  66. package/src/components/ui/item.tsx +202 -0
  67. package/src/components/ui/kbd.tsx +26 -0
  68. package/src/components/ui/label.tsx +19 -0
  69. package/src/components/ui/marker.tsx +71 -0
  70. package/src/components/ui/menubar.tsx +284 -0
  71. package/src/components/ui/message-scroller.tsx +128 -0
  72. package/src/components/ui/message.tsx +91 -0
  73. package/src/components/ui/meter.tsx +80 -0
  74. package/src/components/ui/native-select.tsx +64 -0
  75. package/src/components/ui/navigation-menu.tsx +170 -0
  76. package/src/components/ui/pagination.tsx +133 -0
  77. package/src/components/ui/popover.tsx +87 -0
  78. package/src/components/ui/progress.tsx +82 -0
  79. package/src/components/ui/questionnaire.tsx +328 -0
  80. package/src/components/ui/radio-group.tsx +35 -0
  81. package/src/components/ui/resizable.tsx +49 -0
  82. package/src/components/ui/scroll-area.tsx +50 -0
  83. package/src/components/ui/select.tsx +201 -0
  84. package/src/components/ui/separator.tsx +22 -0
  85. package/src/components/ui/sheet.tsx +135 -0
  86. package/src/components/ui/sidebar.tsx +730 -0
  87. package/src/components/ui/skeleton.tsx +13 -0
  88. package/src/components/ui/slider.tsx +51 -0
  89. package/src/components/ui/spinner.tsx +16 -0
  90. package/src/components/ui/switch.tsx +31 -0
  91. package/src/components/ui/table.tsx +113 -0
  92. package/src/components/ui/tabs.tsx +82 -0
  93. package/src/components/ui/textarea.tsx +17 -0
  94. package/src/components/ui/toast.tsx +229 -0
  95. package/src/components/ui/toggle-group.tsx +87 -0
  96. package/src/components/ui/toggle.tsx +43 -0
  97. package/src/components/ui/tooltip.tsx +65 -0
  98. package/src/components.ts +78 -0
  99. package/src/config.ts +56 -0
  100. package/src/define.ts +122 -0
  101. package/src/doc-context.ts +20 -0
  102. package/src/editor.ts +94 -0
  103. package/src/format-error.ts +78 -0
  104. package/src/guards.ts +84 -0
  105. package/src/hooks/use-mobile.ts +21 -0
  106. package/src/html.ts +91 -0
  107. package/src/hydrate/export-index.ts +232 -0
  108. package/src/hydrate/import-scan.ts +169 -0
  109. package/src/hydrate/plugins.ts +118 -0
  110. package/src/hydrate/runtime-module.ts +145 -0
  111. package/src/hydrate-runtime.ts +67 -0
  112. package/src/hydrate.ts +147 -0
  113. package/src/index.ts +16 -0
  114. package/src/init.ts +57 -0
  115. package/src/langs.ts +148 -0
  116. package/src/lines.ts +53 -0
  117. package/src/load-user-module.ts +191 -0
  118. package/src/mdx.ts +248 -0
  119. package/src/paths.ts +36 -0
  120. package/src/rehype/shiki.ts +533 -0
  121. package/src/remark/alerts.ts +53 -0
  122. package/src/remark/ast.ts +96 -0
  123. package/src/remark/callouts.ts +25 -0
  124. package/src/remark/code-file.ts +85 -0
  125. package/src/remark/code-meta.ts +21 -0
  126. package/src/remark/directives.ts +170 -0
  127. package/src/remark/file-paths.ts +64 -0
  128. package/src/remark/headings.ts +131 -0
  129. package/src/remark/no-js.ts +40 -0
  130. package/src/render.ts +337 -0
  131. package/src/serve.ts +322 -0
  132. package/src/styles/globals.css +134 -0
  133. package/src/styles/shadcn.css +641 -0
  134. package/src/tailwind.ts +119 -0
  135. package/src/ui/approvals.tsx +76 -0
  136. package/src/ui/ask-question.tsx +386 -0
  137. package/src/ui/ask.tsx +206 -0
  138. package/src/ui/attrs.ts +51 -0
  139. package/src/ui/audit.tsx +139 -0
  140. package/src/ui/bar-chart.tsx +334 -0
  141. package/src/ui/benchmarks.tsx +143 -0
  142. package/src/ui/bits.tsx +537 -0
  143. package/src/ui/board.tsx +173 -0
  144. package/src/ui/bridge.tsx +207 -0
  145. package/src/ui/bumps.tsx +178 -0
  146. package/src/ui/callout.tsx +106 -0
  147. package/src/ui/changes.tsx +89 -0
  148. package/src/ui/chart-bits.tsx +52 -0
  149. package/src/ui/chart.ts +577 -0
  150. package/src/ui/checks.tsx +203 -0
  151. package/src/ui/child-index.tsx +44 -0
  152. package/src/ui/children.ts +43 -0
  153. package/src/ui/chips.tsx +49 -0
  154. package/src/ui/cmd.tsx +27 -0
  155. package/src/ui/columns.tsx +31 -0
  156. package/src/ui/comments.tsx +544 -0
  157. package/src/ui/compare.tsx +67 -0
  158. package/src/ui/decision.tsx +79 -0
  159. package/src/ui/deps.tsx +78 -0
  160. package/src/ui/details.tsx +43 -0
  161. package/src/ui/diff-parse.ts +307 -0
  162. package/src/ui/diff.tsx +458 -0
  163. package/src/ui/diffstat.tsx +58 -0
  164. package/src/ui/due.tsx +65 -0
  165. package/src/ui/effort.tsx +29 -0
  166. package/src/ui/endpoints.tsx +118 -0
  167. package/src/ui/envvars.tsx +96 -0
  168. package/src/ui/figure.tsx +37 -0
  169. package/src/ui/file-icon.ts +1020 -0
  170. package/src/ui/file-link.ts +32 -0
  171. package/src/ui/file-ref.tsx +39 -0
  172. package/src/ui/files.tsx +112 -0
  173. package/src/ui/findings.tsx +85 -0
  174. package/src/ui/flow.tsx +73 -0
  175. package/src/ui/funnel.tsx +121 -0
  176. package/src/ui/gantt.tsx +443 -0
  177. package/src/ui/gauges.tsx +135 -0
  178. package/src/ui/glossary.tsx +29 -0
  179. package/src/ui/graph-layout.ts +149 -0
  180. package/src/ui/graph-specs.tsx +102 -0
  181. package/src/ui/graph.tsx +278 -0
  182. package/src/ui/grid.tsx +119 -0
  183. package/src/ui/hypothesis.tsx +94 -0
  184. package/src/ui/icon.tsx +80 -0
  185. package/src/ui/incident.tsx +130 -0
  186. package/src/ui/index.ts +342 -0
  187. package/src/ui/ins-del.tsx +41 -0
  188. package/src/ui/json.tsx +190 -0
  189. package/src/ui/layout.ts +9 -0
  190. package/src/ui/line-chart.tsx +251 -0
  191. package/src/ui/matrix.tsx +208 -0
  192. package/src/ui/meta.tsx +73 -0
  193. package/src/ui/option.tsx +64 -0
  194. package/src/ui/owner.tsx +40 -0
  195. package/src/ui/packages.tsx +104 -0
  196. package/src/ui/pathway.tsx +96 -0
  197. package/src/ui/phase.tsx +41 -0
  198. package/src/ui/pie-chart.tsx +170 -0
  199. package/src/ui/plan.tsx +77 -0
  200. package/src/ui/pre.tsx +175 -0
  201. package/src/ui/priority.tsx +51 -0
  202. package/src/ui/props.tsx +77 -0
  203. package/src/ui/quadrant.tsx +172 -0
  204. package/src/ui/radar.tsx +200 -0
  205. package/src/ui/ref.tsx +160 -0
  206. package/src/ui/release.tsx +178 -0
  207. package/src/ui/req.tsx +42 -0
  208. package/src/ui/review.tsx +133 -0
  209. package/src/ui/risk.tsx +67 -0
  210. package/src/ui/sankey.tsx +287 -0
  211. package/src/ui/scatter.tsx +237 -0
  212. package/src/ui/schema.tsx +113 -0
  213. package/src/ui/score.tsx +105 -0
  214. package/src/ui/search.tsx +120 -0
  215. package/src/ui/series.tsx +38 -0
  216. package/src/ui/severity.tsx +69 -0
  217. package/src/ui/shadcn.tsx +216 -0
  218. package/src/ui/spark.tsx +86 -0
  219. package/src/ui/stack.tsx +57 -0
  220. package/src/ui/stats.tsx +63 -0
  221. package/src/ui/status-badge.tsx +66 -0
  222. package/src/ui/statuspage.tsx +238 -0
  223. package/src/ui/steps.tsx +74 -0
  224. package/src/ui/summary.tsx +41 -0
  225. package/src/ui/symbol-ref.tsx +73 -0
  226. package/src/ui/terminal.tsx +117 -0
  227. package/src/ui/tests.tsx +218 -0
  228. package/src/ui/timeline.tsx +63 -0
  229. package/src/ui/toc.tsx +56 -0
  230. package/src/ui/tones.ts +187 -0
  231. package/src/ui/trace.tsx +69 -0
  232. package/src/ui/tree.tsx +281 -0
  233. package/src/ui/treemap.tsx +128 -0
  234. package/src/ui/venn.tsx +258 -0
  235. package/src/ui/verdict.tsx +78 -0
  236. package/src/ui/waterfall.tsx +142 -0
@@ -0,0 +1,392 @@
1
+ /** Base CSS appended after Tailwind utilities (covers what utilities can't). */
2
+ export const BASE_CSS = `
3
+ /* Preflight makes <svg> display:block, which splits inline text around
4
+ * icons; Iconify svgs (.iconify) and lucide-react svgs (.lucide) stay inline. */
5
+ .iconify, .lucide { display: inline-block; }
6
+ .task-list-item { list-style: none; }
7
+ ul.contains-task-list { padding-left: 1.25rem; }
8
+ .task-list-item input[type='checkbox'] { margin-right: 0.4em; }
9
+ /* --- Interaction feedback -------------------------------------------
10
+ * Every [data-copy] button carries an idle and a done icon
11
+ * (.mdxr-copy-idle/.mdxr-copy-done); the delegated event handler
12
+ * (src/client, also bound in the Storybook preview) toggles
13
+ * .copied/.copy-failed for ~1.6s after each clipboard attempt. Success
14
+ * swaps the copy icon for an emerald check with a pop; failure shakes and
15
+ * tints red; pressing the button scales it down briefly. */
16
+ .mdxr-copy {
17
+ display: inline-flex; align-items: center; justify-content: center;
18
+ border-radius: 0.25rem;
19
+ transition: opacity 0.15s ease, color 0.15s ease, transform 0.1s ease;
20
+ }
21
+ .mdxr-copy:hover { opacity: 1; }
22
+ .mdxr-copy:active { transform: scale(0.82); }
23
+ .mdxr-copy:focus-visible {
24
+ outline: 2px solid rgb(14 165 233); outline-offset: 1px; opacity: 1;
25
+ }
26
+ .mdxr-copy.copied, .mdxr-copy.copy-failed { opacity: 1; }
27
+ .mdxr-copy.copy-failed { color: rgb(220 38 38); }
28
+ .dark .mdxr-copy.copy-failed { color: rgb(248 113 113); }
29
+ /* Theme toggle: fixed corner chrome injected by htmlDocument. Cycles
30
+ * auto → light → dark; [data-mode] picks which icon shows. */
31
+ .mdxr-theme {
32
+ position: fixed; top: 0.75rem; right: 0.75rem; z-index: 50;
33
+ display: inline-flex; align-items: center; justify-content: center;
34
+ height: 2rem; width: 2rem; margin: 0; padding: 0; border-radius: 9999px;
35
+ border: 1px solid rgb(229 229 229); color: rgb(82 82 82);
36
+ background: rgb(255 255 255 / 0.85); backdrop-filter: blur(8px);
37
+ cursor: pointer;
38
+ transition: color 0.15s ease, background-color 0.15s ease,
39
+ border-color 0.15s ease, transform 0.1s ease;
40
+ }
41
+ .mdxr-theme:hover { color: rgb(23 23 23); background: rgb(255 255 255); }
42
+ .mdxr-theme:active { transform: scale(0.88); }
43
+ .mdxr-theme:focus-visible {
44
+ outline: 2px solid rgb(14 165 233); outline-offset: 2px;
45
+ }
46
+ .dark .mdxr-theme {
47
+ border-color: rgb(64 64 64); color: rgb(163 163 163);
48
+ background: rgb(23 23 23 / 0.85);
49
+ }
50
+ .dark .mdxr-theme:hover { color: rgb(250 250 250); background: rgb(23 23 23); }
51
+ .mdxr-theme .mdxr-theme-i { display: none; }
52
+ .mdxr-theme[data-mode="auto"] .mdxr-theme-i-auto,
53
+ .mdxr-theme[data-mode="light"] .mdxr-theme-i-light,
54
+ .mdxr-theme[data-mode="dark"] .mdxr-theme-i-dark {
55
+ display: inline-flex;
56
+ animation: mdxr-pop 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);
57
+ }
58
+ .mdxr-theme svg { height: 1rem; width: 1rem; }
59
+ @media print { .mdxr-theme { display: none; } }
60
+ .mdxr-copy-done { display: none; }
61
+ .copied .mdxr-copy-idle { display: none; }
62
+ .copied .mdxr-copy-done {
63
+ display: inline-flex;
64
+ animation: mdxr-pop 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);
65
+ }
66
+ .copy-failed { animation: mdxr-shake 0.32s ease; }
67
+ [data-ask-copy].copy-failed, [data-ask-save].copy-failed {
68
+ border-color: rgb(248 113 113); color: rgb(220 38 38);
69
+ }
70
+ .dark [data-ask-copy].copy-failed, .dark [data-ask-save].copy-failed {
71
+ color: rgb(248 113 113);
72
+ }
73
+ .mdxr-ask [data-ask-copy].copied, .mdxr-ask [data-ask-save].copied {
74
+ border-color: rgb(52 211 153 / 0.6);
75
+ }
76
+ /* Board: cards drag between lanes (and reorder within one). .mdxr-drag
77
+ * marks the card being held; .mdxr-drop-before (on a card) and
78
+ * .mdxr-drop-end (on the lane's card box) draw the insertion line;
79
+ * .mdxr-drop-lane outlines the target lane. The ‹ › move buttons stay
80
+ * visible at low opacity — they're the touch/keyboard path (HTML5 DnD
81
+ * never reaches touch browsers). */
82
+ [data-board-card] { cursor: grab; }
83
+ [data-board-card].mdxr-drag { cursor: grabbing; opacity: 0.4; }
84
+ [data-board-card].mdxr-drop-before { box-shadow: 0 -2px 0 0 rgb(14 165 233); }
85
+ [data-board-cards].mdxr-drop-end {
86
+ box-shadow: inset 0 -2px 0 0 rgb(14 165 233);
87
+ border-radius: 0.375rem;
88
+ }
89
+ [data-board-lane].mdxr-drop-lane {
90
+ outline: 2px dashed rgb(14 165 233 / 0.5);
91
+ outline-offset: -2px;
92
+ }
93
+ .mdxr-move {
94
+ display: inline-flex; align-items: center; justify-content: center;
95
+ height: 1.25rem; width: 1.25rem; border: 0; padding: 0;
96
+ border-radius: 0.25rem; background: transparent;
97
+ color: rgb(163 163 163); cursor: pointer; opacity: 0.6;
98
+ transition: opacity 0.15s ease, color 0.15s ease,
99
+ background-color 0.15s ease, transform 0.1s ease;
100
+ }
101
+ .mdxr-move:not(:disabled):hover {
102
+ opacity: 1; color: rgb(64 64 64); background: rgb(245 245 245);
103
+ }
104
+ .dark .mdxr-move:not(:disabled):hover {
105
+ color: rgb(212 212 212); background: rgb(38 38 38);
106
+ }
107
+ .mdxr-move:not(:disabled):active { transform: scale(0.85); }
108
+ .mdxr-move:focus-visible {
109
+ outline: 2px solid rgb(14 165 233); outline-offset: 1px; opacity: 1;
110
+ }
111
+ .mdxr-move:disabled { opacity: 0.2; cursor: default; }
112
+ @media print {
113
+ .mdxr-card-moves, .mdxr-board-tools, .mdxr-grip { display: none; }
114
+ }
115
+ /* <Comments>: a hover "+" on every code/diff row opens the comment form
116
+ * under that line. The button sits in the code block's left bleed band
117
+ * (.mdxr-cline — its .line child keeps the -1rem band bleed) or over the
118
+ * diff row's line-number gutter (.mdxr-drow); invisible until the row is
119
+ * hovered or the button takes keyboard focus. */
120
+ .mdxr-cline, .mdxr-drow { position: relative; }
121
+ .mdxr-add {
122
+ position: absolute; top: 0; bottom: 0; z-index: 1;
123
+ display: flex; align-items: center; justify-content: center;
124
+ width: 1rem; border: 0; padding: 0; background: transparent;
125
+ color: rgb(163 163 163); cursor: pointer; opacity: 0;
126
+ transition: opacity 0.12s ease, color 0.12s ease;
127
+ }
128
+ .mdxr-cline > .mdxr-add { left: -1rem; }
129
+ .mdxr-drow > .mdxr-add { left: 0.1rem; }
130
+ .mdxr-cline:hover > .mdxr-add, .mdxr-drow:hover > .mdxr-add,
131
+ .mdxr-add:focus-visible { opacity: 1; }
132
+ .mdxr-add:hover { color: rgb(2 132 199); }
133
+ .dark .mdxr-add { color: rgb(115 115 115); }
134
+ .dark .mdxr-add:hover { color: rgb(56 189 248); }
135
+ @media print {
136
+ .mdxr-add, .mdxr-thread-tools, [data-comment-form] { display: none; }
137
+ }
138
+ @keyframes mdxr-pop {
139
+ 0% { transform: scale(0.3); opacity: 0; }
140
+ 70% { transform: scale(1.15); }
141
+ 100% { transform: scale(1); opacity: 1; }
142
+ }
143
+ @keyframes mdxr-shake {
144
+ 0%, 100% { transform: translateX(0); }
145
+ 25% { transform: translateX(-2px); }
146
+ 75% { transform: translateX(2px); }
147
+ }
148
+ /* shiki dual-theme: token spans carry --shiki-* variables, not colors.
149
+ * Scoping to .line descendants keeps spans that share a .shiki ancestor for
150
+ * layout (e.g. <Comments> thread strips) from losing their own colors to an
151
+ * undefined --shiki-* var. .mdxr-diff-hl marks the same kind of token span
152
+ * inside DiffView rows — it is not nested in a .shiki code element, so it
153
+ * joins the selectors here. */
154
+ .shiki .line span, .mdxr-diff-hl {
155
+ color: var(--shiki-light);
156
+ font-style: var(--shiki-light-font-style, normal);
157
+ font-weight: var(--shiki-light-font-weight, normal);
158
+ text-decoration: var(--shiki-light-text-decoration, none);
159
+ }
160
+ @media (prefers-color-scheme: dark) {
161
+ .shiki .line span, .mdxr-diff-hl {
162
+ color: var(--shiki-dark);
163
+ font-style: var(--shiki-dark-font-style, normal);
164
+ font-weight: var(--shiki-dark-font-weight, normal);
165
+ text-decoration: var(--shiki-dark-text-decoration, none);
166
+ }
167
+ }
168
+ /* The .dark class (set by THEME_JS in documents, the toolbar in Storybook)
169
+ * wins over the media query so toggling it re-themes code blocks too. */
170
+ .dark .shiki .line span, .dark .mdxr-diff-hl {
171
+ color: var(--shiki-dark);
172
+ font-style: var(--shiki-dark-font-style, normal);
173
+ font-weight: var(--shiki-dark-font-weight, normal);
174
+ text-decoration: var(--shiki-dark-text-decoration, none);
175
+ }
176
+ html:not(.dark) .shiki .line span, html:not(.dark) .mdxr-diff-hl {
177
+ color: var(--shiki-light);
178
+ font-style: var(--shiki-light-font-style, normal);
179
+ font-weight: var(--shiki-light-font-weight, normal);
180
+ text-decoration: var(--shiki-light-text-decoration, none);
181
+ }
182
+ /* Line-level features: fences carry has-* classes on <code> itself. The code
183
+ * is a column flex box so .line spans become block-level items (bands/numbers
184
+ * span the block width) while the raw "\n" text nodes shiki leaves between
185
+ * them collapse — whitespace-only anonymous flex items never render, so they
186
+ * can't double the line spacing under the pre's white-space: pre. The pre's
187
+ * p-4 (1rem) is mirrored here so highlight bands bleed to the block edge;
188
+ * min-height keeps empty .line spans from collapsing to zero. */
189
+ .shiki { display: flex; flex-direction: column; }
190
+ .shiki .line { display: block; min-height: 1lh; margin: 0 -1rem; padding: 0 1rem; }
191
+ .shiki .line.highlighted { background: rgba(14, 165, 233, 0.1); }
192
+ .dark .shiki .line.highlighted { background: rgba(14, 165, 233, 0.16); }
193
+ .shiki .line.diff.add { background: rgba(16, 185, 129, 0.12); }
194
+ .shiki .line.diff.remove { background: rgba(239, 68, 68, 0.1); }
195
+ .dark .shiki .line.diff.add { background: rgba(16, 185, 129, 0.18); }
196
+ .dark .shiki .line.diff.remove { background: rgba(239, 68, 68, 0.16); }
197
+ .shiki .line.diff.add::before,
198
+ .shiki .line.diff.remove::before {
199
+ display: inline-block; width: 1em; margin-right: 0.5em;
200
+ color: rgba(113, 113, 122, 0.8); user-select: none;
201
+ }
202
+ .shiki .line.diff.add::before { content: '+'; }
203
+ .shiki .line.diff.remove::before { content: '−'; }
204
+ .shiki .line.error { background: rgba(239, 68, 68, 0.12); }
205
+ .shiki .line.warning { background: rgba(245, 158, 11, 0.14); }
206
+ .dark .shiki .line.error { background: rgba(239, 68, 68, 0.2); }
207
+ .dark .shiki .line.warning { background: rgba(245, 158, 11, 0.18); }
208
+ .shiki.has-focused .line:not(.focused) { opacity: 0.4; }
209
+ .shiki .line.focused { opacity: 1; }
210
+ .shiki span.highlighted-word {
211
+ background: rgba(245, 158, 11, 0.18); border-radius: 0.25rem;
212
+ outline: 1px solid rgba(245, 158, 11, 0.35); padding: 0 0.1rem;
213
+ }
214
+ .shiki.has-line-numbers { counter-reset: mdxr-line; }
215
+ .shiki.has-line-numbers .line::before {
216
+ counter-increment: mdxr-line; content: counter(mdxr-line);
217
+ display: inline-block; width: 1.8em; margin-right: 1em;
218
+ text-align: right; color: rgba(113, 113, 122, 0.6); user-select: none;
219
+ }
220
+ .shiki.has-line-numbers .line.diff.add::before,
221
+ .shiki.has-line-numbers .line.diff.remove::before {
222
+ content: counter(mdxr-line); /* numbers win over the +/− gutter marker */
223
+ }
224
+ /* KaTeX display math gets a little breathing room. */
225
+ .katex-display { margin: 1.25rem 0; }
226
+ /* Smooth anchor jumps for the ToC and other in-page links. */
227
+ html { scroll-behavior: smooth; }
228
+ /* Native <details> used by Toc/Details/Tree/Json: drop the default marker,
229
+ * rotate the chevron on open. */
230
+ .mdxr-toc > details > summary::-webkit-details-marker,
231
+ .mdxr-details > summary::-webkit-details-marker,
232
+ .mdxr-tree summary::-webkit-details-marker,
233
+ .mdxr-json summary::-webkit-details-marker { display: none; }
234
+ .mdxr-toc > details > summary::marker,
235
+ .mdxr-details > summary::marker,
236
+ .mdxr-tree summary::marker,
237
+ .mdxr-json summary::marker { content: ""; }
238
+ /* Json: the "N keys/items" badge only matters while the node is folded. */
239
+ .mdxr-json details[open] > summary .mdxr-count { display: none; }
240
+ .mdxr-chev { transition: transform 0.15s ease; }
241
+ details[open] > summary .mdxr-chev { transform: rotate(90deg); }
242
+ /* Smooth expand/collapse for the native <details> blocks (Details, Toc,
243
+ * Tree folders). Chromium animates block-size via ::details-content +
244
+ * interpolate-size; engines without the pseudo-element never match these
245
+ * rules and keep the instant toggle. */
246
+ :root { interpolate-size: allow-keywords; }
247
+ .mdxr-details::details-content,
248
+ .mdxr-toc > details::details-content,
249
+ .mdxr-tree details::details-content {
250
+ block-size: 0;
251
+ overflow-y: clip;
252
+ transition:
253
+ content-visibility 0.22s allow-discrete,
254
+ block-size 0.22s ease;
255
+ }
256
+ .mdxr-details[open]::details-content,
257
+ .mdxr-toc > details[open]::details-content,
258
+ .mdxr-tree details[open]::details-content {
259
+ block-size: auto;
260
+ block-size: calc-size(auto);
261
+ }
262
+ /* ToC outline: numbered top-level entries, guide-lined nested lists. */
263
+ .mdxr-toc-body ul { list-style: none; margin: 0; padding: 0; }
264
+ .mdxr-toc-body li > p { margin: 0; }
265
+ .mdxr-toc-body a {
266
+ display: flex; align-items: baseline; gap: 0.55rem;
267
+ border-radius: 0.375rem; padding: 0.28rem 0.5rem;
268
+ font-size: 0.875rem; line-height: 1.45;
269
+ color: rgb(82 82 82); text-decoration: none;
270
+ transition: color 0.12s, background 0.12s;
271
+ }
272
+ .mdxr-toc-body a:hover { color: rgb(23 23 23); background: rgb(245 245 245); }
273
+ .mdxr-toc-body a:active { background: rgb(229 229 229); }
274
+ .dark .mdxr-toc-body a:active { background: rgb(64 64 64); }
275
+ .dark .mdxr-toc-body a { color: rgb(163 163 163); }
276
+ .dark .mdxr-toc-body a:hover { color: rgb(250 250 250); background: rgb(38 38 38); }
277
+ .mdxr-toc-body > ul { counter-reset: mdxr-toc; }
278
+ .mdxr-toc-body > ul > li { counter-increment: mdxr-toc; }
279
+ .mdxr-toc-body > ul > li > p > a,
280
+ .mdxr-toc-body > ul > li > a { font-weight: 500; color: rgb(64 64 64); }
281
+ .dark .mdxr-toc-body > ul > li > p > a,
282
+ .dark .mdxr-toc-body > ul > li > a { color: rgb(212 212 212); }
283
+ .mdxr-toc-body > ul > li > p > a::before,
284
+ .mdxr-toc-body > ul > li > a::before {
285
+ content: counter(mdxr-toc); min-width: 1em;
286
+ font-size: 0.72rem; font-weight: 400; font-variant-numeric: tabular-nums;
287
+ color: rgb(163 163 163);
288
+ }
289
+ .dark .mdxr-toc-body > ul > li > p > a::before,
290
+ .dark .mdxr-toc-body > ul > li > a::before { color: rgb(115 115 115); }
291
+ .mdxr-toc-body ul ul {
292
+ margin: 0.15rem 0 0.3rem 0.95rem; padding-left: 0.6rem;
293
+ border-left: 1px solid rgb(229 229 229);
294
+ }
295
+ .dark .mdxr-toc-body ul ul { border-color: rgb(64 64 64); }
296
+ .mdxr-toc-body ul ul a { font-size: 0.8125rem; padding: 0.2rem 0.45rem; }
297
+ /* Ask: native form controls stay interactive without hydration. The real
298
+ * inputs are visually hidden; state is styled through :checked/~ siblings. */
299
+ .mdxr-choice {
300
+ transition: color 0.12s, background-color 0.12s, border-color 0.12s,
301
+ transform 0.1s ease;
302
+ }
303
+ .mdxr-choice:active { transform: scale(0.985); }
304
+ .mdxr-choice:has(:checked) {
305
+ border-color: rgb(23 23 23); background: rgb(250 250 250);
306
+ }
307
+ .dark .mdxr-choice:has(:checked) {
308
+ border-color: rgb(163 163 163); background: rgb(38 38 38 / 0.35);
309
+ }
310
+ .mdxr-choice:has(:focus-visible),
311
+ .mdxr-q:has(:focus-visible) input ~ .mdxr-switch {
312
+ outline: 2px solid rgb(14 165 233); outline-offset: 1px;
313
+ }
314
+ .mdxr-mark {
315
+ display: grid; place-items: center; flex-shrink: 0;
316
+ height: 1rem; width: 1rem; margin-top: 0.15rem;
317
+ border: 1px solid rgb(212 212 212); background: rgb(255 255 255);
318
+ color: transparent; transition: all 0.12s;
319
+ }
320
+ .mdxr-mark-box { border-radius: 0.25rem; }
321
+ .mdxr-mark-radio { border-radius: 9999px; }
322
+ .mdxr-mark-radio::after {
323
+ content: ""; width: 0.45rem; height: 0.45rem; border-radius: 9999px;
324
+ background: rgb(23 23 23); transform: scale(0);
325
+ transition: transform 0.12s;
326
+ }
327
+ .mdxr-choice input:checked ~ .mdxr-mark { border-color: rgb(23 23 23); }
328
+ .mdxr-choice input:checked ~ .mdxr-mark-box {
329
+ background: rgb(23 23 23); color: rgb(255 255 255);
330
+ }
331
+ /* Checkbox glyph pops in instead of fading. */
332
+ .mdxr-mark-box svg {
333
+ transform: scale(0.4);
334
+ transition: transform 0.16s cubic-bezier(0.34, 1.56, 0.64, 1);
335
+ }
336
+ .mdxr-choice input:checked ~ .mdxr-mark-box svg { transform: scale(1); }
337
+ .mdxr-choice input:checked ~ .mdxr-mark-radio::after { transform: scale(1); }
338
+ .dark .mdxr-mark { border-color: rgb(82 82 82); background: rgb(23 23 23); }
339
+ .dark .mdxr-mark-radio::after { background: rgb(250 250 250); }
340
+ .dark .mdxr-choice input:checked ~ .mdxr-mark { border-color: rgb(250 250 250); }
341
+ .dark .mdxr-choice input:checked ~ .mdxr-mark-box {
342
+ background: rgb(250 250 250); color: rgb(23 23 23);
343
+ }
344
+ /* Toggle questions: a native checkbox styled as a switch. */
345
+ .mdxr-switch {
346
+ position: relative; flex-shrink: 0;
347
+ height: 1.25rem; width: 2.25rem; border-radius: 9999px;
348
+ background: rgb(212 212 212); transition: background 0.15s;
349
+ }
350
+ .mdxr-switch::after {
351
+ content: ""; position: absolute; top: 0.125rem; left: 0.125rem;
352
+ height: 1rem; width: 1rem; border-radius: 9999px;
353
+ background: rgb(255 255 255); box-shadow: 0 1px 2px rgb(0 0 0 / 0.25);
354
+ transition: transform 0.15s, width 0.15s;
355
+ }
356
+ .mdxr-q input:checked ~ .mdxr-switch { background: rgb(23 23 23); }
357
+ .mdxr-q input:checked ~ .mdxr-switch::after { transform: translateX(1rem); }
358
+ /* Thumb stretches while the switch is held (iOS-style press feedback). */
359
+ .mdxr-q:active .mdxr-switch::after { width: 1.25rem; }
360
+ .mdxr-q:active input:checked ~ .mdxr-switch::after {
361
+ transform: translateX(0.875rem);
362
+ }
363
+ .dark .mdxr-switch { background: rgb(64 64 64); }
364
+ .dark .mdxr-q input:checked ~ .mdxr-switch { background: rgb(245 245 245); }
365
+ .dark .mdxr-q input:checked ~ .mdxr-switch::after { background: rgb(23 23 23); }
366
+ /* Reduced motion: every animation/transition above becomes instant. */
367
+ @media (prefers-reduced-motion: reduce) {
368
+ html { scroll-behavior: auto; }
369
+ .mdxr-add,
370
+ .mdxr-copy,
371
+ .mdxr-chev,
372
+ .mdxr-choice,
373
+ .mdxr-mark,
374
+ .mdxr-mark-box svg,
375
+ .mdxr-move,
376
+ .mdxr-switch,
377
+ .mdxr-switch::after,
378
+ .mdxr-theme,
379
+ .mdxr-toc-body a {
380
+ transition: none;
381
+ }
382
+ .mdxr-copy:active { transform: none; }
383
+ .mdxr-choice:active { transform: none; }
384
+ .mdxr-move:active { transform: none; }
385
+ .mdxr-theme:active { transform: none; }
386
+ .copied .mdxr-copy-done, .copy-failed { animation: none; }
387
+ .mdxr-theme .mdxr-theme-i { animation: none; }
388
+ .mdxr-details::details-content,
389
+ .mdxr-toc > details::details-content,
390
+ .mdxr-tree details::details-content { transition: none; }
391
+ }
392
+ `;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Inline script snippets emitted into rendered documents. Each is a plain
3
+ * authored string (unlike the client bundle, which `client-js.ts` builds
4
+ * from `src/client/`). htmlDocument escapes them for inline `<script>`
5
+ * embedding — keep that in mind before adding `</` sequences here.
6
+ */
7
+
8
+ /**
9
+ * Mermaid is always imported from the CDN at runtime — never bundled into
10
+ * documents or the Storybook bundle. Shared so the preview uses the same
11
+ * build as rendered documents.
12
+ */
13
+ export const MERMAID_CDN_URL =
14
+ "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs";
15
+
16
+ /** Mermaid bootstrap (module). Only injected when the document uses it. */
17
+ export const MERMAID_JS = `
18
+ import mermaid from '${MERMAID_CDN_URL}';
19
+ mermaid.initialize({
20
+ startOnLoad: false,
21
+ theme: matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'default',
22
+ });
23
+ await mermaid.run({ nodes: document.querySelectorAll('.mermaid') });
24
+ `;
25
+
26
+ /**
27
+ * KaTeX stylesheet (fonts resolve relative to this URL on the CDN). Only
28
+ * linked when the document contains math — same CDN-on-demand model as
29
+ * mermaid. Version matches the bundled `katex` dependency.
30
+ */
31
+ export const KATEX_CDN_URL =
32
+ "https://cdn.jsdelivr.net/npm/katex@0.18.7/dist/katex.min.css";
33
+
34
+ /** Live-reload snippet injected by `mdxr serve` only. */
35
+ export const LIVE_RELOAD_JS = `
36
+ var es = new EventSource('/__mdxr_events');
37
+ es.addEventListener('reload', function () { location.reload(); });
38
+ `;
39
+
40
+ /**
41
+ * The shadcn theme maps `dark:` to the `.dark` class, so dark mode is
42
+ * class-based rather than media-based. This head script applies the class
43
+ * before first paint: a stored choice from the theme toggle
44
+ * (localStorage `mdxr-theme`) wins, otherwise the document tracks
45
+ * `prefers-color-scheme` — and keeps tracking it only while no explicit
46
+ * choice is stored.
47
+ */
48
+ export const THEME_JS = `
49
+ var q = matchMedia('(prefers-color-scheme: dark)');
50
+ var stored = null;
51
+ try { stored = localStorage.getItem('mdxr-theme'); } catch (e) {}
52
+ document.documentElement.classList.toggle(
53
+ 'dark',
54
+ stored === 'dark' || (stored !== 'light' && q.matches)
55
+ );
56
+ q.addEventListener('change', function (e) {
57
+ var s = null;
58
+ try { s = localStorage.getItem('mdxr-theme'); } catch (e2) {}
59
+ if (s !== 'light' && s !== 'dark') {
60
+ document.documentElement.classList.toggle('dark', e.matches);
61
+ }
62
+ });
63
+ // This script runs in <head>, before the toggle button is parsed —
64
+ // reflect the stored mode on it once the DOM exists.
65
+ addEventListener('DOMContentLoaded', function () {
66
+ var s = null;
67
+ try { s = localStorage.getItem('mdxr-theme'); } catch (e) {}
68
+ var mode = s === 'light' || s === 'dark' ? s : 'auto';
69
+ document.querySelectorAll('[data-mdxr-theme]').forEach(function (b) {
70
+ if (!(b instanceof HTMLElement)) {
71
+ return;
72
+ }
73
+ b.dataset.mode = mode;
74
+ b.setAttribute('title', 'Theme: ' + mode);
75
+ b.setAttribute('aria-label', 'Switch theme (current: ' + mode + ')');
76
+ });
77
+ });
78
+ `;