components-svelte 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 (242) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +103 -0
  3. package/dist/components/Search.svelte +320 -0
  4. package/dist/components/Search.svelte.d.ts +31 -0
  5. package/dist/components/SearchButton.svelte +82 -0
  6. package/dist/components/SearchButton.svelte.d.ts +13 -0
  7. package/dist/components/SearchProvider.svelte +87 -0
  8. package/dist/components/SearchProvider.svelte.d.ts +17 -0
  9. package/dist/components/accordion/Accordion.svelte +150 -0
  10. package/dist/components/accordion/Accordion.svelte.d.ts +25 -0
  11. package/dist/components/accordion/AccordionCover.svelte +68 -0
  12. package/dist/components/accordion/AccordionCover.svelte.d.ts +13 -0
  13. package/dist/components/accordion/AccordionGroup.svelte +23 -0
  14. package/dist/components/accordion/AccordionGroup.svelte.d.ts +8 -0
  15. package/dist/components/accordion/accordion-url-utils.d.ts +4 -0
  16. package/dist/components/accordion/accordion-url-utils.js +48 -0
  17. package/dist/components/accordion/index.d.ts +29 -0
  18. package/dist/components/accordion/index.js +6 -0
  19. package/dist/components/badge/Badge.svelte +152 -0
  20. package/dist/components/badge/Badge.svelte.d.ts +23 -0
  21. package/dist/components/badge/index.d.ts +1 -0
  22. package/dist/components/badge/index.js +2 -0
  23. package/dist/components/callout/Callout.svelte +317 -0
  24. package/dist/components/callout/Callout.svelte.d.ts +17 -0
  25. package/dist/components/callout/Check.svelte +9 -0
  26. package/dist/components/callout/Check.svelte.d.ts +4 -0
  27. package/dist/components/callout/Danger.svelte +9 -0
  28. package/dist/components/callout/Danger.svelte.d.ts +4 -0
  29. package/dist/components/callout/Info.svelte +9 -0
  30. package/dist/components/callout/Info.svelte.d.ts +4 -0
  31. package/dist/components/callout/Note.svelte +9 -0
  32. package/dist/components/callout/Note.svelte.d.ts +4 -0
  33. package/dist/components/callout/Tip.svelte +9 -0
  34. package/dist/components/callout/Tip.svelte.d.ts +4 -0
  35. package/dist/components/callout/Warning.svelte +9 -0
  36. package/dist/components/callout/Warning.svelte.d.ts +4 -0
  37. package/dist/components/callout/index.d.ts +8 -0
  38. package/dist/components/callout/index.js +8 -0
  39. package/dist/components/card/Card.svelte +172 -0
  40. package/dist/components/card/Card.svelte.d.ts +21 -0
  41. package/dist/components/card/index.d.ts +3 -0
  42. package/dist/components/card/index.js +2 -0
  43. package/dist/components/code-block/BaseCodeBlock.svelte +249 -0
  44. package/dist/components/code-block/BaseCodeBlock.svelte.d.ts +10 -0
  45. package/dist/components/code-block/CodeBlock.svelte +185 -0
  46. package/dist/components/code-block/CodeBlock.svelte.d.ts +5 -0
  47. package/dist/components/code-block/CodeFooter.svelte +34 -0
  48. package/dist/components/code-block/CodeFooter.svelte.d.ts +8 -0
  49. package/dist/components/code-block/CodeHeader.svelte +52 -0
  50. package/dist/components/code-block/CodeHeader.svelte.d.ts +11 -0
  51. package/dist/components/code-block/CopyToClipboardButton.svelte +124 -0
  52. package/dist/components/code-block/CopyToClipboardButton.svelte.d.ts +4 -0
  53. package/dist/components/code-block/index.d.ts +10 -0
  54. package/dist/components/code-block/index.js +5 -0
  55. package/dist/components/code-block/types.d.ts +85 -0
  56. package/dist/components/code-block/types.js +1 -0
  57. package/dist/components/code-group/CodeGroup.svelte +327 -0
  58. package/dist/components/code-group/CodeGroup.svelte.d.ts +24 -0
  59. package/dist/components/code-group/CodeGroupSelect.svelte +170 -0
  60. package/dist/components/code-group/CodeGroupSelect.svelte.d.ts +25 -0
  61. package/dist/components/code-group/CodeSelectDropdown.svelte +74 -0
  62. package/dist/components/code-group/CodeSelectDropdown.svelte.d.ts +9 -0
  63. package/dist/components/code-group/LanguageDropdown.svelte +134 -0
  64. package/dist/components/code-group/LanguageDropdown.svelte.d.ts +11 -0
  65. package/dist/components/code-group/LanguageIcon.svelte +24 -0
  66. package/dist/components/code-group/LanguageIcon.svelte.d.ts +8 -0
  67. package/dist/components/code-group/context.d.ts +14 -0
  68. package/dist/components/code-group/context.js +2 -0
  69. package/dist/components/code-group/index.d.ts +8 -0
  70. package/dist/components/code-group/index.js +4 -0
  71. package/dist/components/color/Color.svelte +34 -0
  72. package/dist/components/color/Color.svelte.d.ts +10 -0
  73. package/dist/components/color/ColorItem.svelte +140 -0
  74. package/dist/components/color/ColorItem.svelte.d.ts +10 -0
  75. package/dist/components/color/ColorRow.svelte +27 -0
  76. package/dist/components/color/ColorRow.svelte.d.ts +8 -0
  77. package/dist/components/color/index.d.ts +1 -0
  78. package/dist/components/color/index.js +8 -0
  79. package/dist/components/columns/Box.svelte +15 -0
  80. package/dist/components/columns/Box.svelte.d.ts +7 -0
  81. package/dist/components/columns/Columns.svelte +31 -0
  82. package/dist/components/columns/Columns.svelte.d.ts +10 -0
  83. package/dist/components/columns/constants.d.ts +5 -0
  84. package/dist/components/columns/constants.js +3 -0
  85. package/dist/components/columns/index.d.ts +5 -0
  86. package/dist/components/columns/index.js +3 -0
  87. package/dist/components/expandable/Expandable.svelte +182 -0
  88. package/dist/components/expandable/Expandable.svelte.d.ts +22 -0
  89. package/dist/components/expandable/index.d.ts +3 -0
  90. package/dist/components/expandable/index.js +2 -0
  91. package/dist/components/frame/Frame.svelte +118 -0
  92. package/dist/components/frame/Frame.svelte.d.ts +15 -0
  93. package/dist/components/frame/index.d.ts +3 -0
  94. package/dist/components/frame/index.js +2 -0
  95. package/dist/components/icon/Icon.svelte +129 -0
  96. package/dist/components/icon/Icon.svelte.d.ts +18 -0
  97. package/dist/components/icon/index.d.ts +2 -0
  98. package/dist/components/icon/index.js +1 -0
  99. package/dist/components/index.d.ts +22 -0
  100. package/dist/components/index.js +22 -0
  101. package/dist/components/mermaid/Mermaid.svelte +181 -0
  102. package/dist/components/mermaid/Mermaid.svelte.d.ts +11 -0
  103. package/dist/components/mermaid/ZoomControls.svelte +74 -0
  104. package/dist/components/mermaid/ZoomControls.svelte.d.ts +12 -0
  105. package/dist/components/mermaid/index.d.ts +7 -0
  106. package/dist/components/mermaid/index.js +4 -0
  107. package/dist/components/mermaid/use-pan-zoom.svelte.d.ts +11 -0
  108. package/dist/components/mermaid/use-pan-zoom.svelte.js +41 -0
  109. package/dist/components/panel/Panel.svelte +27 -0
  110. package/dist/components/panel/Panel.svelte.d.ts +9 -0
  111. package/dist/components/panel/index.d.ts +3 -0
  112. package/dist/components/panel/index.js +2 -0
  113. package/dist/components/property/DeprecatedPill.svelte +16 -0
  114. package/dist/components/property/DeprecatedPill.svelte.d.ts +6 -0
  115. package/dist/components/property/InfoPill.svelte +32 -0
  116. package/dist/components/property/InfoPill.svelte.d.ts +10 -0
  117. package/dist/components/property/ParamHead.svelte +188 -0
  118. package/dist/components/property/ParamHead.svelte.d.ts +22 -0
  119. package/dist/components/property/Property.svelte +123 -0
  120. package/dist/components/property/Property.svelte.d.ts +24 -0
  121. package/dist/components/property/RequiredPill.svelte +16 -0
  122. package/dist/components/property/RequiredPill.svelte.d.ts +6 -0
  123. package/dist/components/property/index.d.ts +11 -0
  124. package/dist/components/property/index.js +6 -0
  125. package/dist/components/search/index.d.ts +7 -0
  126. package/dist/components/search/index.js +4 -0
  127. package/dist/components/search/use-search.d.ts +9 -0
  128. package/dist/components/search/use-search.js +6 -0
  129. package/dist/components/steps/Step.svelte +314 -0
  130. package/dist/components/steps/Step.svelte.d.ts +26 -0
  131. package/dist/components/steps/Steps.svelte +51 -0
  132. package/dist/components/steps/Steps.svelte.d.ts +11 -0
  133. package/dist/components/steps/constants.d.ts +4 -0
  134. package/dist/components/steps/constants.js +2 -0
  135. package/dist/components/steps/context.d.ts +10 -0
  136. package/dist/components/steps/context.js +2 -0
  137. package/dist/components/steps/index.d.ts +32 -0
  138. package/dist/components/steps/index.js +6 -0
  139. package/dist/components/tabs/Tabs.svelte +254 -0
  140. package/dist/components/tabs/Tabs.svelte.d.ts +16 -0
  141. package/dist/components/tabs/TabsItem.svelte +56 -0
  142. package/dist/components/tabs/TabsItem.svelte.d.ts +15 -0
  143. package/dist/components/tabs/context.d.ts +20 -0
  144. package/dist/components/tabs/context.js +2 -0
  145. package/dist/components/tabs/index.d.ts +27 -0
  146. package/dist/components/tabs/index.js +5 -0
  147. package/dist/components/tile/Tile.svelte +124 -0
  148. package/dist/components/tile/Tile.svelte.d.ts +12 -0
  149. package/dist/components/tile/index.d.ts +2 -0
  150. package/dist/components/tile/index.js +1 -0
  151. package/dist/components/tooltip/Tooltip.svelte +170 -0
  152. package/dist/components/tooltip/Tooltip.svelte.d.ts +23 -0
  153. package/dist/components/tooltip/index.d.ts +2 -0
  154. package/dist/components/tooltip/index.js +1 -0
  155. package/dist/components/tree/Tree.svelte +226 -0
  156. package/dist/components/tree/Tree.svelte.d.ts +9 -0
  157. package/dist/components/tree/TreeFile.svelte +44 -0
  158. package/dist/components/tree/TreeFile.svelte.d.ts +6 -0
  159. package/dist/components/tree/TreeFolder.svelte +107 -0
  160. package/dist/components/tree/TreeFolder.svelte.d.ts +10 -0
  161. package/dist/components/tree/context.d.ts +3 -0
  162. package/dist/components/tree/context.js +7 -0
  163. package/dist/components/tree/index.d.ts +10 -0
  164. package/dist/components/tree/index.js +9 -0
  165. package/dist/components/tree/tree-level-context.d.ts +8 -0
  166. package/dist/components/tree/tree-level-context.js +7 -0
  167. package/dist/components/tree/use-tree-level.d.ts +3 -0
  168. package/dist/components/tree/use-tree-level.js +5 -0
  169. package/dist/components/tree/utils.d.ts +9 -0
  170. package/dist/components/tree/utils.js +86 -0
  171. package/dist/components/update/Update.svelte +210 -0
  172. package/dist/components/update/Update.svelte.d.ts +34 -0
  173. package/dist/components/update/index.d.ts +4 -0
  174. package/dist/components/update/index.js +3 -0
  175. package/dist/components/view/View.svelte +52 -0
  176. package/dist/components/view/View.svelte.d.ts +14 -0
  177. package/dist/components/view/index.d.ts +3 -0
  178. package/dist/components/view/index.js +2 -0
  179. package/dist/constants/brands.d.ts +2 -0
  180. package/dist/constants/brands.js +4 -0
  181. package/dist/constants/index.d.ts +6 -0
  182. package/dist/constants/index.js +6 -0
  183. package/dist/constants/selectors.d.ts +125 -0
  184. package/dist/constants/selectors.js +125 -0
  185. package/dist/hooks/index.d.ts +8 -0
  186. package/dist/hooks/index.js +6 -0
  187. package/dist/hooks/use-expandable-memory.svelte.d.ts +6 -0
  188. package/dist/hooks/use-expandable-memory.svelte.js +89 -0
  189. package/dist/hooks/use-expandable.svelte.d.ts +15 -0
  190. package/dist/hooks/use-expandable.svelte.js +53 -0
  191. package/dist/hooks/use-get-shiki-highlighted-html.svelte.d.ts +8 -0
  192. package/dist/hooks/use-get-shiki-highlighted-html.svelte.js +36 -0
  193. package/dist/hooks/use-has-hover.d.ts +2 -0
  194. package/dist/hooks/use-has-hover.js +10 -0
  195. package/dist/hooks/use-is-dark-theme.svelte.d.ts +3 -0
  196. package/dist/hooks/use-is-dark-theme.svelte.js +25 -0
  197. package/dist/hooks/use-isomorphic-layout-effect.d.ts +3 -0
  198. package/dist/hooks/use-isomorphic-layout-effect.js +6 -0
  199. package/dist/index.d.ts +2 -0
  200. package/dist/index.js +2 -0
  201. package/dist/styles.css +2 -0
  202. package/dist/utils/cn.d.ts +3 -0
  203. package/dist/utils/cn.js +7 -0
  204. package/dist/utils/copy-to-clipboard.d.ts +4 -0
  205. package/dist/utils/copy-to-clipboard.js +50 -0
  206. package/dist/utils/dedent.d.ts +1 -0
  207. package/dist/utils/dedent.js +125 -0
  208. package/dist/utils/enhance-video-props.d.ts +4 -0
  209. package/dist/utils/enhance-video-props.js +25 -0
  210. package/dist/utils/get-node-text.d.ts +2 -0
  211. package/dist/utils/get-node-text.js +26 -0
  212. package/dist/utils/icon-utils.d.ts +18 -0
  213. package/dist/utils/icon-utils.js +30 -0
  214. package/dist/utils/is-absolute-url.d.ts +4 -0
  215. package/dist/utils/is-absolute-url.js +11 -0
  216. package/dist/utils/is-remote-url.d.ts +2 -0
  217. package/dist/utils/is-remote-url.js +12 -0
  218. package/dist/utils/make-marker-ids-unique.d.ts +2 -0
  219. package/dist/utils/make-marker-ids-unique.js +36 -0
  220. package/dist/utils/shiki/code-styling.d.ts +13 -0
  221. package/dist/utils/shiki/code-styling.js +1 -0
  222. package/dist/utils/shiki/constants.d.ts +21 -0
  223. package/dist/utils/shiki/constants.js +116 -0
  224. package/dist/utils/shiki/get-code-styling.d.ts +9 -0
  225. package/dist/utils/shiki/get-code-styling.js +38 -0
  226. package/dist/utils/shiki/get-shiki-background-colors.d.ts +20 -0
  227. package/dist/utils/shiki/get-shiki-background-colors.js +56 -0
  228. package/dist/utils/shiki/index.d.ts +30 -0
  229. package/dist/utils/shiki/index.js +209 -0
  230. package/dist/utils/shiki/lib.d.ts +4 -0
  231. package/dist/utils/shiki/lib.js +49 -0
  232. package/dist/utils/shiki/shiki-themes.d.ts +2 -0
  233. package/dist/utils/shiki/shiki-themes.js +64 -0
  234. package/dist/utils/shiki/snippet-presets.d.ts +27 -0
  235. package/dist/utils/shiki/snippet-presets.js +44 -0
  236. package/dist/utils/shiki/worker-client.d.ts +9 -0
  237. package/dist/utils/shiki/worker-client.js +22 -0
  238. package/dist/utils/shiki/worker.d.ts +1 -0
  239. package/dist/utils/shiki/worker.js +134 -0
  240. package/dist/utils/slugify.d.ts +2 -0
  241. package/dist/utils/slugify.js +9 -0
  242. package/package.json +100 -0
@@ -0,0 +1,181 @@
1
+ <script module lang="ts">
2
+ // Svelte's module script keeps the counter shared across component instances,
3
+ // matching React's per-instance useId() uniqueness for duplicate diagrams.
4
+ let nextMermaidId = 0;
5
+ </script>
6
+
7
+ <script lang="ts">
8
+ import mermaid, { type MermaidConfig } from "mermaid";
9
+ import { onMount } from "svelte";
10
+ import { Classes } from "../../constants/selectors";
11
+ import { useIsDarkTheme } from "../../hooks/use-is-dark-theme.svelte";
12
+ import { cn } from "../../utils/cn";
13
+ import { makeMarkerIdsUnique } from "../../utils/make-marker-ids-unique";
14
+ import { usePanZoom } from "./use-pan-zoom.svelte";
15
+ import ZoomControls from "./ZoomControls.svelte";
16
+
17
+ const MIN_HEIGHT_FOR_CONTROLS = 120;
18
+ const GANTT_DEFAULT_WIDTH = 800;
19
+
20
+ export type MermaidPlacement =
21
+ | "top-left"
22
+ | "top-right"
23
+ | "bottom-left"
24
+ | "bottom-right";
25
+
26
+ export type MermaidProps = {
27
+ chart: string;
28
+ className?: string;
29
+ ariaLabel?: string;
30
+ placement?: MermaidPlacement;
31
+ actions?: boolean;
32
+ };
33
+
34
+ let {
35
+ chart,
36
+ className,
37
+ ariaLabel = "Mermaid diagram",
38
+ placement = "bottom-right",
39
+ actions,
40
+ }: MermaidProps = $props();
41
+
42
+ let svg = $state("");
43
+ let error = $state<string | null>(null);
44
+ let showControls = $state(false);
45
+ let containerRef = $state<HTMLDivElement | null>(null);
46
+
47
+ const id = `mermaid-${nextMermaidId++}`;
48
+ const theme = useIsDarkTheme();
49
+ const panZoom = usePanZoom();
50
+
51
+ let rootClass = $derived(cn(Classes.Mermaid, "group relative overflow-hidden", className));
52
+ let errorClass = $derived(
53
+ cn(
54
+ Classes.Mermaid,
55
+ "rounded-md border border-red-200 bg-red-50 p-4 text-red-700 text-sm dark:border-red-900/50 dark:bg-red-950/50 dark:text-red-400",
56
+ className
57
+ )
58
+ );
59
+
60
+ onMount(() => {
61
+ panZoom.reset();
62
+ error = null;
63
+ });
64
+
65
+ $effect(() => {
66
+ const currentChart = chart;
67
+ const isDarkTheme = theme.isDarkTheme;
68
+ let cancelled = false;
69
+
70
+ const renderChart = async () => {
71
+ const mermaidConfig: MermaidConfig = {
72
+ startOnLoad: false,
73
+ fontFamily: "inherit",
74
+ theme: isDarkTheme ? "dark" : "default",
75
+ gantt: {
76
+ useWidth: GANTT_DEFAULT_WIDTH,
77
+ },
78
+ };
79
+
80
+ // create a temporary container for mermaid to render into
81
+ const tempContainer = document.createElement("div");
82
+ tempContainer.style.position = "absolute";
83
+ tempContainer.style.left = "-9999px";
84
+ tempContainer.style.top = "-9999px";
85
+ document.body.appendChild(tempContainer);
86
+
87
+ try {
88
+ mermaid.initialize(mermaidConfig);
89
+
90
+ const uniqueId = `mermaid-${id.replace(/:/g, "")}-${Date.now()}`;
91
+
92
+ const { svg: renderedSvg } = await mermaid.render(
93
+ uniqueId,
94
+ currentChart,
95
+ tempContainer
96
+ );
97
+
98
+ if (!cancelled) {
99
+ const uniqueSvg = makeMarkerIdsUnique(renderedSvg, uniqueId);
100
+ svg = uniqueSvg;
101
+ error = null;
102
+ }
103
+ } catch (err) {
104
+ console.error("Error while rendering mermaid", err);
105
+
106
+ if (!cancelled) {
107
+ const message = err instanceof Error ? err.message : "Failed to render diagram";
108
+ error = message;
109
+ svg = "";
110
+ }
111
+ } finally {
112
+ tempContainer.parentNode?.removeChild(tempContainer);
113
+ }
114
+ };
115
+
116
+ renderChart().catch(console.error);
117
+
118
+ return () => {
119
+ cancelled = true;
120
+ };
121
+ });
122
+
123
+ $effect(() => {
124
+ if (actions !== undefined) {
125
+ return;
126
+ }
127
+
128
+ const container = containerRef;
129
+
130
+ if (!container || typeof ResizeObserver === "undefined") {
131
+ return;
132
+ }
133
+
134
+ const resizeObserver = new ResizeObserver((entries) => {
135
+ for (const entry of entries) {
136
+ const height = entry.contentRect.height;
137
+ showControls = height >= MIN_HEIGHT_FOR_CONTROLS;
138
+ }
139
+ });
140
+
141
+ resizeObserver.observe(container);
142
+
143
+ return () => {
144
+ resizeObserver.disconnect();
145
+ };
146
+ });
147
+ </script>
148
+
149
+ {#if error}
150
+ <div
151
+ class={errorClass}
152
+ data-component-part="mermaid-error"
153
+ role="alert"
154
+ >
155
+ <p class="font-medium" data-component-part="mermaid-error-title">Failed to render diagram</p>
156
+ <p class="mt-1 text-xs" data-component-part="mermaid-error-message">{error}</p>
157
+ </div>
158
+ {:else}
159
+ <div class={rootClass}>
160
+ {#if actions === true || (actions === undefined && showControls)}
161
+ <ZoomControls
162
+ onPan={panZoom.pan}
163
+ onReset={panZoom.reset}
164
+ onZoomIn={panZoom.zoomIn}
165
+ onZoomOut={panZoom.zoomOut}
166
+ panStep={panZoom.panStep}
167
+ placement={placement}
168
+ />
169
+ {/if}
170
+ <div
171
+ aria-label={ariaLabel}
172
+ data-component-part="mermaid-diagram"
173
+ bind:this={containerRef}
174
+ role="img"
175
+ style={panZoom.style}
176
+ >
177
+ <!-- Svelte equivalent of React's dangerouslySetInnerHTML; Mermaid owns this SVG. -->
178
+ {@html svg}
179
+ </div>
180
+ </div>
181
+ {/if}
@@ -0,0 +1,11 @@
1
+ export type MermaidPlacement = "top-left" | "top-right" | "bottom-left" | "bottom-right";
2
+ export type MermaidProps = {
3
+ chart: string;
4
+ className?: string;
5
+ ariaLabel?: string;
6
+ placement?: MermaidPlacement;
7
+ actions?: boolean;
8
+ };
9
+ declare const Mermaid: import("svelte").Component<MermaidProps, {}, "">;
10
+ type Mermaid = ReturnType<typeof Mermaid>;
11
+ export default Mermaid;
@@ -0,0 +1,74 @@
1
+ <script lang="ts">
2
+ import {
3
+ ChevronDown,
4
+ ChevronLeft,
5
+ ChevronRight,
6
+ ChevronUp,
7
+ RotateCcw,
8
+ ZoomIn,
9
+ ZoomOut,
10
+ } from "@lucide/svelte";
11
+ import { cn } from "../../utils/cn";
12
+ import type { MermaidPlacement } from "./Mermaid.svelte";
13
+
14
+ export type ZoomControlsProps = {
15
+ onZoomIn: () => void;
16
+ onZoomOut: () => void;
17
+ onReset: () => void;
18
+ onPan: (dx: number, dy: number) => void;
19
+ panStep: number;
20
+ placement?: MermaidPlacement;
21
+ };
22
+
23
+ let { onZoomIn, onZoomOut, onReset, onPan, panStep, placement }: ZoomControlsProps = $props();
24
+
25
+ const buttonClass = cn(
26
+ "flex size-7 cursor-pointer touch-manipulation items-center justify-center rounded-md border border-stone-200 bg-white text-stone-900 transition-[transform] duration-100 hover:bg-stone-50 motion-safe:active:scale-95 dark:border-white/10 dark:bg-stone-900 dark:text-white dark:hover:bg-stone-800 [&_svg]:size-4"
27
+ );
28
+
29
+ let controlsClass = $derived(
30
+ cn(
31
+ "absolute z-10 grid grid-cols-3 gap-1",
32
+ placement === "top-left" && "top-2 left-2",
33
+ placement === "top-right" && "top-2 right-2",
34
+ placement === "bottom-left" && "bottom-2 left-2",
35
+ placement === "bottom-right" && "right-2 bottom-2"
36
+ )
37
+ );
38
+ </script>
39
+
40
+ <!-- The React implementation uses a labelled group for these non-semantic controls. -->
41
+ <div
42
+ aria-label="Diagram zoom and pan controls"
43
+ class={controlsClass}
44
+ data-component-part="zoom-controls"
45
+ role="group"
46
+ >
47
+ <div aria-hidden="true" class="pointer-events-none"></div>
48
+
49
+ <button aria-label="Pan up" class={buttonClass} title="Pan up" type="button" onclick={() => onPan(0, panStep)}>
50
+ <ChevronUp aria-hidden="true" />
51
+ </button>
52
+ <button aria-label="Zoom in" class={buttonClass} title="Zoom in" type="button" onclick={onZoomIn}>
53
+ <ZoomIn aria-hidden="true" />
54
+ </button>
55
+
56
+ <button aria-label="Pan left" class={buttonClass} title="Pan left" type="button" onclick={() => onPan(panStep, 0)}>
57
+ <ChevronLeft aria-hidden="true" />
58
+ </button>
59
+ <button aria-label="Reset view" class={buttonClass} title="Reset view" type="button" onclick={onReset}>
60
+ <RotateCcw aria-hidden="true" />
61
+ </button>
62
+ <button aria-label="Pan right" class={buttonClass} title="Pan right" type="button" onclick={() => onPan(-panStep, 0)}>
63
+ <ChevronRight aria-hidden="true" />
64
+ </button>
65
+
66
+ <div aria-hidden="true" class="pointer-events-none"></div>
67
+
68
+ <button aria-label="Pan down" class={buttonClass} title="Pan down" type="button" onclick={() => onPan(0, -panStep)}>
69
+ <ChevronDown aria-hidden="true" />
70
+ </button>
71
+ <button aria-label="Zoom out" class={buttonClass} title="Zoom out" type="button" onclick={onZoomOut}>
72
+ <ZoomOut aria-hidden="true" />
73
+ </button>
74
+ </div>
@@ -0,0 +1,12 @@
1
+ import type { MermaidPlacement } from "./Mermaid.svelte";
2
+ export type ZoomControlsProps = {
3
+ onZoomIn: () => void;
4
+ onZoomOut: () => void;
5
+ onReset: () => void;
6
+ onPan: (dx: number, dy: number) => void;
7
+ panStep: number;
8
+ placement?: MermaidPlacement;
9
+ };
10
+ declare const ZoomControls: import("svelte").Component<ZoomControlsProps, {}, "">;
11
+ type ZoomControls = ReturnType<typeof ZoomControls>;
12
+ export default ZoomControls;
@@ -0,0 +1,7 @@
1
+ import Mermaid from "./Mermaid.svelte";
2
+ import ZoomControls from "./ZoomControls.svelte";
3
+ export type { MermaidProps, MermaidPlacement } from "./Mermaid.svelte";
4
+ export { Mermaid, ZoomControls };
5
+ export type { UsePanZoomReturn } from "./use-pan-zoom.svelte";
6
+ export { usePanZoom } from "./use-pan-zoom.svelte";
7
+ export type { ZoomControlsProps } from "./ZoomControls.svelte";
@@ -0,0 +1,4 @@
1
+ import Mermaid from "./Mermaid.svelte";
2
+ import ZoomControls from "./ZoomControls.svelte";
3
+ export { Mermaid, ZoomControls };
4
+ export { usePanZoom } from "./use-pan-zoom.svelte";
@@ -0,0 +1,11 @@
1
+ type UsePanZoomReturn = {
2
+ style: string;
3
+ zoomIn: () => void;
4
+ zoomOut: () => void;
5
+ reset: () => void;
6
+ pan: (dx: number, dy: number) => void;
7
+ panStep: number;
8
+ };
9
+ declare const usePanZoom: () => UsePanZoomReturn;
10
+ export { usePanZoom };
11
+ export type { UsePanZoomReturn };
@@ -0,0 +1,41 @@
1
+ const MIN_SCALE = 0.25;
2
+ const MAX_SCALE = 4;
3
+ const ZOOM_STEP = 0.15;
4
+ const PAN_STEP = 50;
5
+ const DEFAULT_TRANSFORM = { scale: 1, x: 0, y: 0 };
6
+ const usePanZoom = () => {
7
+ let transform = $state({ ...DEFAULT_TRANSFORM });
8
+ const zoomIn = () => {
9
+ transform = {
10
+ ...transform,
11
+ scale: Math.min(transform.scale + ZOOM_STEP, MAX_SCALE),
12
+ };
13
+ };
14
+ const zoomOut = () => {
15
+ transform = {
16
+ ...transform,
17
+ scale: Math.max(transform.scale - ZOOM_STEP, MIN_SCALE),
18
+ };
19
+ };
20
+ const reset = () => {
21
+ transform = { ...DEFAULT_TRANSFORM };
22
+ };
23
+ const pan = (dx, dy) => {
24
+ transform = {
25
+ ...transform,
26
+ x: transform.x + dx,
27
+ y: transform.y + dy,
28
+ };
29
+ };
30
+ return {
31
+ get style() {
32
+ return `transform: translate(${transform.x}px, ${transform.y}px) scale(${transform.scale}); transform-origin: center center; transition: transform 0.15s ease-out;`;
33
+ },
34
+ zoomIn,
35
+ zoomOut,
36
+ reset,
37
+ pan,
38
+ panStep: PAN_STEP,
39
+ };
40
+ };
41
+ export { usePanZoom };
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import type { HTMLAttributes } from "svelte/elements";
4
+ import { cn } from "../../utils/cn";
5
+
6
+ export type PanelProps = HTMLAttributes<HTMLDivElement> & {
7
+ children?: Snippet;
8
+ className?: string;
9
+ };
10
+
11
+ let {
12
+ children,
13
+ class: classAttribute,
14
+ className,
15
+ ...restProps
16
+ }: PanelProps = $props();
17
+
18
+ let panelClass = $derived(
19
+ cn("block xl:hidden", classAttribute ?? className)
20
+ );
21
+ </script>
22
+
23
+ <div class={panelClass} {...restProps}>
24
+ {#if children}
25
+ {@render children()}
26
+ {/if}
27
+ </div>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ export type PanelProps = HTMLAttributes<HTMLDivElement> & {
4
+ children?: Snippet;
5
+ className?: string;
6
+ };
7
+ declare const Panel: import("svelte").Component<PanelProps, {}, "">;
8
+ type Panel = ReturnType<typeof Panel>;
9
+ export default Panel;
@@ -0,0 +1,3 @@
1
+ import Panel from "./Panel.svelte";
2
+ export type { default as PanelProps } from "./Panel.svelte";
3
+ export { Panel };
@@ -0,0 +1,2 @@
1
+ import Panel from "./Panel.svelte";
2
+ export { Panel };
@@ -0,0 +1,16 @@
1
+ <script lang="ts">
2
+ type DeprecatedPillProps = {
3
+ label?: string;
4
+ };
5
+
6
+ let { label }: DeprecatedPillProps = $props();
7
+ </script>
8
+
9
+ {#if label}
10
+ <div
11
+ class="whitespace-nowrap rounded-md bg-amber-100/50 px-2 py-0.5 font-medium text-amber-600 dark:bg-amber-400/10 dark:text-amber-300"
12
+ data-component-part="field-deprecated-pill"
13
+ >
14
+ {label}
15
+ </div>
16
+ {/if}
@@ -0,0 +1,6 @@
1
+ type DeprecatedPillProps = {
2
+ label?: string;
3
+ };
4
+ declare const DeprecatedPill: import("svelte").Component<DeprecatedPillProps, {}, "">;
5
+ type DeprecatedPill = ReturnType<typeof DeprecatedPill>;
6
+ export default DeprecatedPill;
@@ -0,0 +1,32 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { cn } from "../../utils/cn";
4
+
5
+ type InfoPillProps = {
6
+ children?: Snippet;
7
+ prefix?: string;
8
+ class?: string;
9
+ className?: string;
10
+ };
11
+
12
+ let {
13
+ children,
14
+ prefix,
15
+ class: classAttribute,
16
+ className,
17
+ }: InfoPillProps = $props();
18
+
19
+ let pillClass = $derived(
20
+ cn(
21
+ "flex items-center gap-1 break-all rounded-md bg-stone-100/50 px-2 py-0.5 font-medium text-stone-600 dark:bg-white/5 dark:text-stone-200",
22
+ classAttribute ?? className
23
+ )
24
+ );
25
+ </script>
26
+
27
+ <div class={pillClass} data-component-part="field-info-pill">
28
+ {#if prefix}
29
+ <span class="text-stone-400 dark:text-stone-500">{prefix}</span>
30
+ {/if}
31
+ <span>{#if children}{@render children()}{/if}</span>
32
+ </div>
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from "svelte";
2
+ type InfoPillProps = {
3
+ children?: Snippet;
4
+ prefix?: string;
5
+ class?: string;
6
+ className?: string;
7
+ };
8
+ declare const InfoPill: import("svelte").Component<InfoPillProps, {}, "">;
9
+ type InfoPill = ReturnType<typeof InfoPill>;
10
+ export default InfoPill;
@@ -0,0 +1,188 @@
1
+ <script lang="ts">
2
+ import slugify from "@sindresorhus/slugify";
3
+ import { onMount } from "svelte";
4
+ import Icon from "../icon/Icon.svelte";
5
+ import { cn } from "../../utils/cn";
6
+ import { copyToClipboard } from "../../utils/copy-to-clipboard";
7
+ import DeprecatedPill from "./DeprecatedPill.svelte";
8
+ import InfoPill from "./InfoPill.svelte";
9
+ import RequiredPill from "./RequiredPill.svelte";
10
+
11
+ type ParamHeadProps = {
12
+ name?: string | null;
13
+ type: string;
14
+ location?: string;
15
+ hidden?: boolean;
16
+ default?: unknown;
17
+ required?: boolean;
18
+ deprecated?: boolean;
19
+ id?: string;
20
+ pre?: string[];
21
+ post?: string[];
22
+ class?: string;
23
+ className?: string;
24
+ onMount?: () => void;
25
+ navigateToHeaderAriaLabel?: string;
26
+ defaultLabel?: string;
27
+ requiredLabel?: string;
28
+ deprecatedLabel?: string;
29
+ };
30
+
31
+ let {
32
+ name,
33
+ type,
34
+ location,
35
+ required,
36
+ deprecated,
37
+ default: defaultValue,
38
+ id,
39
+ pre,
40
+ post,
41
+ onMount: onMountProp,
42
+ navigateToHeaderAriaLabel,
43
+ defaultLabel,
44
+ requiredLabel,
45
+ deprecatedLabel,
46
+ }: ParamHeadProps = $props();
47
+
48
+ let pillsElement: HTMLDivElement | null = $state(null);
49
+ let isMultiLine = $state(false);
50
+ let paramId = $derived(id ?? slugify(name ?? "", { decamelize: true }));
51
+
52
+ // ResizeObserver replaces the React effect that tracks wrapped metadata pills.
53
+ function observePills(node: HTMLDivElement) {
54
+ const checkHeight = () => {
55
+ isMultiLine = node.offsetHeight > 28;
56
+ };
57
+
58
+ pillsElement = node;
59
+ checkHeight();
60
+
61
+ if (typeof ResizeObserver === "undefined") {
62
+ return;
63
+ }
64
+
65
+ const resizeObserver = new ResizeObserver(checkHeight);
66
+ resizeObserver.observe(node);
67
+
68
+ return {
69
+ destroy() {
70
+ resizeObserver.unobserve(node);
71
+ if (pillsElement === node) {
72
+ pillsElement = null;
73
+ }
74
+ },
75
+ };
76
+ }
77
+
78
+ async function copyAnchorLink() {
79
+ if (paramId) {
80
+ await copyToClipboard(`${window.location.href.split("#")[0]}#${paramId}`);
81
+ window.location.hash = paramId;
82
+ }
83
+ }
84
+
85
+ function handleFieldNameKeydown(event: KeyboardEvent) {
86
+ if (event.key === "Enter" || event.key === " ") {
87
+ event.preventDefault();
88
+ void copyAnchorLink();
89
+ }
90
+ }
91
+
92
+ // Svelte effect replaces React's onMount effect and also reacts to a changed callback prop.
93
+ $effect(() => {
94
+ onMountProp?.();
95
+ });
96
+ </script>
97
+
98
+ {#if name != null}
99
+ <div class="group/param-head param-head relative flex break-all font-mono text-sm" id={paramId}>
100
+ <div class="mr-5 flex flex-1 flex-col content-start py-0.5">
101
+ <div class="flex flex-wrap items-center gap-2">
102
+ {#if paramId}
103
+ <div class="absolute -top-1.5 -left-9">
104
+ <a
105
+ aria-label={navigateToHeaderAriaLabel}
106
+ class="group/link flex items-center border-0 py-2 opacity-0 focus:opacity-100 focus:outline-0 group-hover/param-head:opacity-100"
107
+ href={`#${paramId}`}
108
+ onclick={copyAnchorLink}
109
+ >
110
+ &#8203;
111
+ <div class="flex size-6 items-center justify-center rounded-md bg-white text-stone-400 shadow-sm ring-1 ring-stone-400/30 hover:ring-stone-400/60 group-focus/link:border-2 group-focus/link:border-primary dark:bg-background-dark dark:text-white/50 dark:ring-1 dark:ring-stone-700/25 dark:brightness-[1.35] dark:group-focus/link:border-primary-light dark:hover:ring-white/20 dark:hover:brightness-150">
112
+ <span aria-hidden="true" class="contents">
113
+ <Icon
114
+ class="size-3 bg-stone-400 dark:bg-white/50"
115
+ icon="link"
116
+ overrideColor={true}
117
+ overrideSize={true}
118
+ />
119
+ </span>
120
+ </div>
121
+ </a>
122
+ </div>
123
+ {/if}
124
+ {#each pre ?? [] as item, index (index)}
125
+ <div
126
+ class="rounded-md bg-stone-100/50 px-2 py-0.5 text-stone-600 dark:bg-white/5 dark:text-stone-200"
127
+ data-component-part="field-meta-pre"
128
+ >
129
+ {item}
130
+ </div>
131
+ {/each}
132
+ <!-- Keep the React field-name click behavior and add equivalent keyboard support. -->
133
+ <div
134
+ aria-label={paramId ? `Copy anchor link for ${name}` : undefined}
135
+ class="overflow-wrap-anywhere cursor-pointer font-semibold text-primary dark:text-primary-light"
136
+ data-component-part="field-name"
137
+ onclick={copyAnchorLink}
138
+ onkeydown={handleFieldNameKeydown}
139
+ role="button"
140
+ tabindex="0"
141
+ >
142
+ {name}
143
+ </div>
144
+ <div
145
+ bind:this={pillsElement}
146
+ use:observePills
147
+ class={cn(
148
+ "inline items-center gap-2 font-medium text-xs [&_div]:mr-2 [&_div]:inline",
149
+ isMultiLine ? "[&_div]:leading-6" : "[&_div]:leading-5"
150
+ )}
151
+ data-component-part="field-meta"
152
+ >
153
+ {#if type}
154
+ <InfoPill>{#snippet children()}{type}{/snippet}</InfoPill>
155
+ {/if}
156
+ {#if location}
157
+ <InfoPill>{#snippet children()}{location}{/snippet}</InfoPill>
158
+ {/if}
159
+ {#if defaultValue != null}
160
+ <InfoPill prefix={defaultLabel}>
161
+ {#snippet children()}
162
+ {typeof defaultValue === "string"
163
+ ? defaultValue === ""
164
+ ? '""'
165
+ : defaultValue
166
+ : JSON.stringify(defaultValue)}
167
+ {/snippet}
168
+ </InfoPill>
169
+ {/if}
170
+ {#if required}
171
+ <RequiredPill label={requiredLabel} />
172
+ {/if}
173
+ {#if deprecated}
174
+ <DeprecatedPill label={deprecatedLabel} />
175
+ {/if}
176
+ {#each post ?? [] as item, index (index)}
177
+ <div
178
+ class="rounded-md bg-stone-100/50 px-2 py-0.5 text-stone-600 dark:bg-white/5 dark:text-stone-200"
179
+ data-component-part="field-meta-post"
180
+ >
181
+ {item}
182
+ </div>
183
+ {/each}
184
+ </div>
185
+ </div>
186
+ </div>
187
+ </div>
188
+ {/if}
@@ -0,0 +1,22 @@
1
+ type ParamHeadProps = {
2
+ name?: string | null;
3
+ type: string;
4
+ location?: string;
5
+ hidden?: boolean;
6
+ default?: unknown;
7
+ required?: boolean;
8
+ deprecated?: boolean;
9
+ id?: string;
10
+ pre?: string[];
11
+ post?: string[];
12
+ class?: string;
13
+ className?: string;
14
+ onMount?: () => void;
15
+ navigateToHeaderAriaLabel?: string;
16
+ defaultLabel?: string;
17
+ requiredLabel?: string;
18
+ deprecatedLabel?: string;
19
+ };
20
+ declare const ParamHead: import("svelte").Component<ParamHeadProps, {}, "">;
21
+ type ParamHead = ReturnType<typeof ParamHead>;
22
+ export default ParamHead;