@fuzdev/fuz_ui 0.169.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 (323) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/dist/Alert.svelte +108 -0
  4. package/dist/Alert.svelte.d.ts +16 -0
  5. package/dist/Alert.svelte.d.ts.map +1 -0
  6. package/dist/ApiDeclarationList.svelte +35 -0
  7. package/dist/ApiDeclarationList.svelte.d.ts +9 -0
  8. package/dist/ApiDeclarationList.svelte.d.ts.map +1 -0
  9. package/dist/ApiIndex.svelte +65 -0
  10. package/dist/ApiIndex.svelte.d.ts +23 -0
  11. package/dist/ApiIndex.svelte.d.ts.map +1 -0
  12. package/dist/ApiModule.svelte +124 -0
  13. package/dist/ApiModule.svelte.d.ts +22 -0
  14. package/dist/ApiModule.svelte.d.ts.map +1 -0
  15. package/dist/Breadcrumb.svelte +83 -0
  16. package/dist/Breadcrumb.svelte.d.ts +23 -0
  17. package/dist/Breadcrumb.svelte.d.ts.map +1 -0
  18. package/dist/Card.svelte +157 -0
  19. package/dist/Card.svelte.d.ts +13 -0
  20. package/dist/Card.svelte.d.ts.map +1 -0
  21. package/dist/ColorSchemeInput.svelte +65 -0
  22. package/dist/ColorSchemeInput.svelte.d.ts +11 -0
  23. package/dist/ColorSchemeInput.svelte.d.ts.map +1 -0
  24. package/dist/Contextmenu.svelte +30 -0
  25. package/dist/Contextmenu.svelte.d.ts +32 -0
  26. package/dist/Contextmenu.svelte.d.ts.map +1 -0
  27. package/dist/ContextmenuEntry.svelte +74 -0
  28. package/dist/ContextmenuEntry.svelte.d.ts +12 -0
  29. package/dist/ContextmenuEntry.svelte.d.ts.map +1 -0
  30. package/dist/ContextmenuLinkEntry.svelte +112 -0
  31. package/dist/ContextmenuLinkEntry.svelte.d.ts +12 -0
  32. package/dist/ContextmenuLinkEntry.svelte.d.ts.map +1 -0
  33. package/dist/ContextmenuRoot.svelte +372 -0
  34. package/dist/ContextmenuRoot.svelte.d.ts +71 -0
  35. package/dist/ContextmenuRoot.svelte.d.ts.map +1 -0
  36. package/dist/ContextmenuRootForSafariCompatibility.svelte +541 -0
  37. package/dist/ContextmenuRootForSafariCompatibility.svelte.d.ts +79 -0
  38. package/dist/ContextmenuRootForSafariCompatibility.svelte.d.ts.map +1 -0
  39. package/dist/ContextmenuSeparator.svelte +16 -0
  40. package/dist/ContextmenuSeparator.svelte.d.ts +4 -0
  41. package/dist/ContextmenuSeparator.svelte.d.ts.map +1 -0
  42. package/dist/ContextmenuSubmenu.svelte +116 -0
  43. package/dist/ContextmenuSubmenu.svelte.d.ts +10 -0
  44. package/dist/ContextmenuSubmenu.svelte.d.ts.map +1 -0
  45. package/dist/ContextmenuTextEntry.svelte +21 -0
  46. package/dist/ContextmenuTextEntry.svelte.d.ts +10 -0
  47. package/dist/ContextmenuTextEntry.svelte.d.ts.map +1 -0
  48. package/dist/CopyToClipboard.svelte +81 -0
  49. package/dist/CopyToClipboard.svelte.d.ts +18 -0
  50. package/dist/CopyToClipboard.svelte.d.ts.map +1 -0
  51. package/dist/DeclarationDetail.svelte +340 -0
  52. package/dist/DeclarationDetail.svelte.d.ts +8 -0
  53. package/dist/DeclarationDetail.svelte.d.ts.map +1 -0
  54. package/dist/DeclarationLink.svelte +50 -0
  55. package/dist/DeclarationLink.svelte.d.ts +8 -0
  56. package/dist/DeclarationLink.svelte.d.ts.map +1 -0
  57. package/dist/Details.svelte +51 -0
  58. package/dist/Details.svelte.d.ts +20 -0
  59. package/dist/Details.svelte.d.ts.map +1 -0
  60. package/dist/Dialog.svelte +217 -0
  61. package/dist/Dialog.svelte.d.ts +30 -0
  62. package/dist/Dialog.svelte.d.ts.map +1 -0
  63. package/dist/Dialogs.svelte +28 -0
  64. package/dist/Dialogs.svelte.d.ts +11 -0
  65. package/dist/Dialogs.svelte.d.ts.map +1 -0
  66. package/dist/Docs.svelte +179 -0
  67. package/dist/Docs.svelte.d.ts +13 -0
  68. package/dist/Docs.svelte.d.ts.map +1 -0
  69. package/dist/DocsContent.svelte +40 -0
  70. package/dist/DocsContent.svelte.d.ts +14 -0
  71. package/dist/DocsContent.svelte.d.ts.map +1 -0
  72. package/dist/DocsFooter.svelte +64 -0
  73. package/dist/DocsFooter.svelte.d.ts +15 -0
  74. package/dist/DocsFooter.svelte.d.ts.map +1 -0
  75. package/dist/DocsLink.svelte +41 -0
  76. package/dist/DocsLink.svelte.d.ts +12 -0
  77. package/dist/DocsLink.svelte.d.ts.map +1 -0
  78. package/dist/DocsList.svelte +44 -0
  79. package/dist/DocsList.svelte.d.ts +11 -0
  80. package/dist/DocsList.svelte.d.ts.map +1 -0
  81. package/dist/DocsMenu.svelte +55 -0
  82. package/dist/DocsMenu.svelte.d.ts +11 -0
  83. package/dist/DocsMenu.svelte.d.ts.map +1 -0
  84. package/dist/DocsMenuHeader.svelte +15 -0
  85. package/dist/DocsMenuHeader.svelte.d.ts +9 -0
  86. package/dist/DocsMenuHeader.svelte.d.ts.map +1 -0
  87. package/dist/DocsModulesList.svelte +32 -0
  88. package/dist/DocsModulesList.svelte.d.ts +7 -0
  89. package/dist/DocsModulesList.svelte.d.ts.map +1 -0
  90. package/dist/DocsPageLinks.svelte +61 -0
  91. package/dist/DocsPageLinks.svelte.d.ts +8 -0
  92. package/dist/DocsPageLinks.svelte.d.ts.map +1 -0
  93. package/dist/DocsPrimaryNav.svelte +93 -0
  94. package/dist/DocsPrimaryNav.svelte.d.ts +11 -0
  95. package/dist/DocsPrimaryNav.svelte.d.ts.map +1 -0
  96. package/dist/DocsSearch.svelte +48 -0
  97. package/dist/DocsSearch.svelte.d.ts +11 -0
  98. package/dist/DocsSearch.svelte.d.ts.map +1 -0
  99. package/dist/DocsSecondaryNav.svelte +63 -0
  100. package/dist/DocsSecondaryNav.svelte.d.ts +9 -0
  101. package/dist/DocsSecondaryNav.svelte.d.ts.map +1 -0
  102. package/dist/DocsTertiaryNav.svelte +118 -0
  103. package/dist/DocsTertiaryNav.svelte.d.ts +10 -0
  104. package/dist/DocsTertiaryNav.svelte.d.ts.map +1 -0
  105. package/dist/EcosystemLinks.svelte +53 -0
  106. package/dist/EcosystemLinks.svelte.d.ts +7 -0
  107. package/dist/EcosystemLinks.svelte.d.ts.map +1 -0
  108. package/dist/EcosystemLinksPanel.svelte +22 -0
  109. package/dist/EcosystemLinksPanel.svelte.d.ts +8 -0
  110. package/dist/EcosystemLinksPanel.svelte.d.ts.map +1 -0
  111. package/dist/GithubLink.svelte +75 -0
  112. package/dist/GithubLink.svelte.d.ts +14 -0
  113. package/dist/GithubLink.svelte.d.ts.map +1 -0
  114. package/dist/Glyph.svelte +28 -0
  115. package/dist/Glyph.svelte.d.ts +9 -0
  116. package/dist/Glyph.svelte.d.ts.map +1 -0
  117. package/dist/Hashlink.svelte +41 -0
  118. package/dist/Hashlink.svelte.d.ts +8 -0
  119. package/dist/Hashlink.svelte.d.ts.map +1 -0
  120. package/dist/HiddenPersonalLinks.svelte +6 -0
  121. package/dist/HiddenPersonalLinks.svelte.d.ts +27 -0
  122. package/dist/HiddenPersonalLinks.svelte.d.ts.map +1 -0
  123. package/dist/HueInput.svelte +127 -0
  124. package/dist/HueInput.svelte.d.ts +11 -0
  125. package/dist/HueInput.svelte.d.ts.map +1 -0
  126. package/dist/ImgOrSvg.svelte +58 -0
  127. package/dist/ImgOrSvg.svelte.d.ts +25 -0
  128. package/dist/ImgOrSvg.svelte.d.ts.map +1 -0
  129. package/dist/LibraryDetail.svelte +297 -0
  130. package/dist/LibraryDetail.svelte.d.ts +15 -0
  131. package/dist/LibraryDetail.svelte.d.ts.map +1 -0
  132. package/dist/LibrarySummary.svelte +151 -0
  133. package/dist/LibrarySummary.svelte.d.ts +16 -0
  134. package/dist/LibrarySummary.svelte.d.ts.map +1 -0
  135. package/dist/MdnLink.svelte +40 -0
  136. package/dist/MdnLink.svelte.d.ts +8 -0
  137. package/dist/MdnLink.svelte.d.ts.map +1 -0
  138. package/dist/Mdz.svelte +30 -0
  139. package/dist/Mdz.svelte.d.ts +10 -0
  140. package/dist/Mdz.svelte.d.ts.map +1 -0
  141. package/dist/MdzNodeView.svelte +93 -0
  142. package/dist/MdzNodeView.svelte.d.ts +9 -0
  143. package/dist/MdzNodeView.svelte.d.ts.map +1 -0
  144. package/dist/ModuleLink.svelte +48 -0
  145. package/dist/ModuleLink.svelte.d.ts +8 -0
  146. package/dist/ModuleLink.svelte.d.ts.map +1 -0
  147. package/dist/PasteFromClipboard.svelte +35 -0
  148. package/dist/PasteFromClipboard.svelte.d.ts +9 -0
  149. package/dist/PasteFromClipboard.svelte.d.ts.map +1 -0
  150. package/dist/PendingAnimation.svelte +62 -0
  151. package/dist/PendingAnimation.svelte.d.ts +13 -0
  152. package/dist/PendingAnimation.svelte.d.ts.map +1 -0
  153. package/dist/PendingButton.svelte +75 -0
  154. package/dist/PendingButton.svelte.d.ts +17 -0
  155. package/dist/PendingButton.svelte.d.ts.map +1 -0
  156. package/dist/ProjectLinks.svelte +54 -0
  157. package/dist/ProjectLinks.svelte.d.ts +19 -0
  158. package/dist/ProjectLinks.svelte.d.ts.map +1 -0
  159. package/dist/Redirect.svelte +44 -0
  160. package/dist/Redirect.svelte.d.ts +23 -0
  161. package/dist/Redirect.svelte.d.ts.map +1 -0
  162. package/dist/Spiders.svelte +57 -0
  163. package/dist/Spiders.svelte.d.ts +9 -0
  164. package/dist/Spiders.svelte.d.ts.map +1 -0
  165. package/dist/Svg.svelte +99 -0
  166. package/dist/Svg.svelte.d.ts +54 -0
  167. package/dist/Svg.svelte.d.ts.map +1 -0
  168. package/dist/Teleport.svelte +48 -0
  169. package/dist/Teleport.svelte.d.ts +15 -0
  170. package/dist/Teleport.svelte.d.ts.map +1 -0
  171. package/dist/ThemeInput.svelte +75 -0
  172. package/dist/ThemeInput.svelte.d.ts +15 -0
  173. package/dist/ThemeInput.svelte.d.ts.map +1 -0
  174. package/dist/Themed.svelte +101 -0
  175. package/dist/Themed.svelte.d.ts +24 -0
  176. package/dist/Themed.svelte.d.ts.map +1 -0
  177. package/dist/TomeContent.svelte +67 -0
  178. package/dist/TomeContent.svelte.d.ts +12 -0
  179. package/dist/TomeContent.svelte.d.ts.map +1 -0
  180. package/dist/TomeHeader.svelte +56 -0
  181. package/dist/TomeHeader.svelte.d.ts +4 -0
  182. package/dist/TomeHeader.svelte.d.ts.map +1 -0
  183. package/dist/TomeLink.svelte +29 -0
  184. package/dist/TomeLink.svelte.d.ts +10 -0
  185. package/dist/TomeLink.svelte.d.ts.map +1 -0
  186. package/dist/TomeSection.svelte +65 -0
  187. package/dist/TomeSection.svelte.d.ts +24 -0
  188. package/dist/TomeSection.svelte.d.ts.map +1 -0
  189. package/dist/TomeSectionHeader.svelte +90 -0
  190. package/dist/TomeSectionHeader.svelte.d.ts +13 -0
  191. package/dist/TomeSectionHeader.svelte.d.ts.map +1 -0
  192. package/dist/TypeLink.svelte +19 -0
  193. package/dist/TypeLink.svelte.d.ts +7 -0
  194. package/dist/TypeLink.svelte.d.ts.map +1 -0
  195. package/dist/alert.d.ts +7 -0
  196. package/dist/alert.d.ts.map +1 -0
  197. package/dist/alert.js +6 -0
  198. package/dist/api_search.svelte.d.ts +16 -0
  199. package/dist/api_search.svelte.d.ts.map +1 -0
  200. package/dist/api_search.svelte.js +61 -0
  201. package/dist/constants.d.ts +2 -0
  202. package/dist/constants.d.ts.map +1 -0
  203. package/dist/constants.js +3 -0
  204. package/dist/context_helpers.d.ts +17 -0
  205. package/dist/context_helpers.d.ts.map +1 -0
  206. package/dist/context_helpers.js +19 -0
  207. package/dist/contextmenu_helpers.d.ts +16 -0
  208. package/dist/contextmenu_helpers.d.ts.map +1 -0
  209. package/dist/contextmenu_helpers.js +39 -0
  210. package/dist/contextmenu_state.svelte.d.ts +152 -0
  211. package/dist/contextmenu_state.svelte.d.ts.map +1 -0
  212. package/dist/contextmenu_state.svelte.js +424 -0
  213. package/dist/csp.d.ts +160 -0
  214. package/dist/csp.d.ts.map +1 -0
  215. package/dist/csp.js +354 -0
  216. package/dist/csp_of_ryanatkn.d.ts +6 -0
  217. package/dist/csp_of_ryanatkn.d.ts.map +1 -0
  218. package/dist/csp_of_ryanatkn.js +14 -0
  219. package/dist/declaration.svelte.d.ts +84 -0
  220. package/dist/declaration.svelte.d.ts.map +1 -0
  221. package/dist/declaration.svelte.js +66 -0
  222. package/dist/declaration_contextmenu.d.ts +4 -0
  223. package/dist/declaration_contextmenu.d.ts.map +1 -0
  224. package/dist/declaration_contextmenu.js +14 -0
  225. package/dist/dialog.d.ts +24 -0
  226. package/dist/dialog.d.ts.map +1 -0
  227. package/dist/dialog.js +12 -0
  228. package/dist/dimensions.svelte.d.ts +5 -0
  229. package/dist/dimensions.svelte.d.ts.map +1 -0
  230. package/dist/dimensions.svelte.js +4 -0
  231. package/dist/docs_helpers.svelte.d.ts +48 -0
  232. package/dist/docs_helpers.svelte.d.ts.map +1 -0
  233. package/dist/docs_helpers.svelte.js +99 -0
  234. package/dist/helpers.d.ts +2 -0
  235. package/dist/helpers.d.ts.map +1 -0
  236. package/dist/helpers.js +16 -0
  237. package/dist/intersect.svelte.d.ts +47 -0
  238. package/dist/intersect.svelte.d.ts.map +1 -0
  239. package/dist/intersect.svelte.js +92 -0
  240. package/dist/library.svelte.d.ts +197 -0
  241. package/dist/library.svelte.d.ts.map +1 -0
  242. package/dist/library.svelte.js +130 -0
  243. package/dist/library_gen.d.ts +34 -0
  244. package/dist/library_gen.d.ts.map +1 -0
  245. package/dist/library_gen.js +123 -0
  246. package/dist/library_gen_helpers.d.ts +85 -0
  247. package/dist/library_gen_helpers.d.ts.map +1 -0
  248. package/dist/library_gen_helpers.js +188 -0
  249. package/dist/library_helpers.d.ts +54 -0
  250. package/dist/library_helpers.d.ts.map +1 -0
  251. package/dist/library_helpers.js +102 -0
  252. package/dist/logos.d.ts +134 -0
  253. package/dist/logos.d.ts.map +1 -0
  254. package/dist/logos.js +281 -0
  255. package/dist/mdz.d.ts +106 -0
  256. package/dist/mdz.d.ts.map +1 -0
  257. package/dist/mdz.js +1481 -0
  258. package/dist/mdz_components.d.ts +37 -0
  259. package/dist/mdz_components.d.ts.map +1 -0
  260. package/dist/mdz_components.js +12 -0
  261. package/dist/module.svelte.d.ts +47 -0
  262. package/dist/module.svelte.d.ts.map +1 -0
  263. package/dist/module.svelte.js +56 -0
  264. package/dist/module_contextmenu.d.ts +4 -0
  265. package/dist/module_contextmenu.d.ts.map +1 -0
  266. package/dist/module_contextmenu.js +14 -0
  267. package/dist/module_helpers.d.ts +69 -0
  268. package/dist/module_helpers.d.ts.map +1 -0
  269. package/dist/module_helpers.js +87 -0
  270. package/dist/rune_helpers.svelte.d.ts +6 -0
  271. package/dist/rune_helpers.svelte.d.ts.map +1 -0
  272. package/dist/rune_helpers.svelte.js +10 -0
  273. package/dist/storage.d.ts +13 -0
  274. package/dist/storage.d.ts.map +1 -0
  275. package/dist/storage.js +43 -0
  276. package/dist/svelte_helpers.d.ts +37 -0
  277. package/dist/svelte_helpers.d.ts.map +1 -0
  278. package/dist/svelte_helpers.js +245 -0
  279. package/dist/themer.svelte.d.ts +24 -0
  280. package/dist/themer.svelte.d.ts.map +1 -0
  281. package/dist/themer.svelte.js +43 -0
  282. package/dist/tome.d.ts +80 -0
  283. package/dist/tome.d.ts.map +1 -0
  284. package/dist/tome.js +27 -0
  285. package/dist/ts_helpers.d.ts +110 -0
  286. package/dist/ts_helpers.d.ts.map +1 -0
  287. package/dist/ts_helpers.js +533 -0
  288. package/dist/tsdoc_helpers.d.ts +98 -0
  289. package/dist/tsdoc_helpers.d.ts.map +1 -0
  290. package/dist/tsdoc_helpers.js +221 -0
  291. package/package.json +128 -0
  292. package/src/lib/alert.ts +14 -0
  293. package/src/lib/api_search.svelte.ts +85 -0
  294. package/src/lib/constants.ts +3 -0
  295. package/src/lib/context_helpers.ts +47 -0
  296. package/src/lib/contextmenu_helpers.ts +63 -0
  297. package/src/lib/contextmenu_state.svelte.ts +515 -0
  298. package/src/lib/csp.ts +576 -0
  299. package/src/lib/csp_of_ryanatkn.ts +16 -0
  300. package/src/lib/declaration.svelte.ts +102 -0
  301. package/src/lib/declaration_contextmenu.ts +22 -0
  302. package/src/lib/dialog.ts +35 -0
  303. package/src/lib/dimensions.svelte.ts +4 -0
  304. package/src/lib/docs_helpers.svelte.ts +149 -0
  305. package/src/lib/helpers.ts +10 -0
  306. package/src/lib/intersect.svelte.ts +152 -0
  307. package/src/lib/library.svelte.ts +162 -0
  308. package/src/lib/library_gen.ts +160 -0
  309. package/src/lib/library_gen_helpers.ts +262 -0
  310. package/src/lib/library_helpers.ts +123 -0
  311. package/src/lib/logos.ts +302 -0
  312. package/src/lib/mdz.ts +1819 -0
  313. package/src/lib/mdz_components.ts +34 -0
  314. package/src/lib/module.svelte.ts +78 -0
  315. package/src/lib/module_contextmenu.ts +20 -0
  316. package/src/lib/module_helpers.ts +113 -0
  317. package/src/lib/rune_helpers.svelte.ts +10 -0
  318. package/src/lib/storage.ts +48 -0
  319. package/src/lib/svelte_helpers.ts +303 -0
  320. package/src/lib/themer.svelte.ts +68 -0
  321. package/src/lib/tome.ts +38 -0
  322. package/src/lib/ts_helpers.ts +662 -0
  323. package/src/lib/tsdoc_helpers.ts +259 -0
@@ -0,0 +1,221 @@
1
+ /**
2
+ * TSDoc/JSDoc parsing helpers using the TypeScript Compiler API.
3
+ *
4
+ * Provides `tsdoc_parse()` for extracting JSDoc/TSDoc from TypeScript nodes.
5
+ * Primarily designed for build-time code generation but can be used at runtime.
6
+ *
7
+ * ## Design
8
+ *
9
+ * Pure extraction approach: extracts documentation as-is with minimal transformation,
10
+ * preserving source intent. Works around TypeScript Compiler API quirks where needed.
11
+ *
12
+ * Supports both regular TypeScript and Svelte components (via svelte2tsx output).
13
+ *
14
+ * ## Tag support
15
+ *
16
+ * Supports a subset of standard TSDoc tags:
17
+ * `@param`, `@returns`, `@throws`, `@example`, `@deprecated`, `@see`, `@since`, `@nodocs`.
18
+ *
19
+ * The `@nodocs` tag excludes exports from documentation and flat namespace validation.
20
+ * The declaration is still exported and usable, just not documented.
21
+ *
22
+ * Also supports `@mutates` (non-standard) for documenting mutations to parameters or external state.
23
+ * Use format: `@mutates paramName - description of mutation`.
24
+ *
25
+ * Only `@returns` is supported (not `@return`).
26
+ *
27
+ * The `@see` tag supports multiple formats: plain URLs (`https://...`), `{@link}` syntax, and module names.
28
+ * Relative/absolute path support in `@see` is TBD.
29
+ *
30
+ * ## Behavioral notes
31
+ *
32
+ * Due to TS Compiler API limitations:
33
+ * - Preserves dash separator in `@param` descriptions: `@param x desc` → `"- desc"`
34
+ * - `@throws` tags have `{Type}` stripped by TS API; fallback regex extracts first word as error type
35
+ * - TS API strips URL protocols from `@see` tag text; we use `getText()` to preserve original format including `{@link}` syntax
36
+ *
37
+ * All functions are prefixed with `tsdoc_` for clarity.
38
+ */
39
+ import ts from 'typescript';
40
+ /**
41
+ * Convert TSDoc link syntax to mdz-compatible format.
42
+ *
43
+ * Conversions:
44
+ * - `{@link url|text}` → `[text](url)` (markdown link)
45
+ * - `{@link https://...}` → `https://...` (bare URL)
46
+ * - `{@link identifier}` → `` `identifier` `` (backticks)
47
+ * - `@see` variants follow same rules
48
+ *
49
+ * @param content The @see tag content to convert
50
+ */
51
+ const tsdoc_convert_link_to_mdz = (content) => {
52
+ // Check for {@link ...} or {@see ...} syntax
53
+ const link_match = /^\{@(?:link|see)\s+([^}]+)\}$/.exec(content.trim());
54
+ if (link_match) {
55
+ const inner = link_match[1].trim();
56
+ // Check for pipe separator (custom display text)
57
+ const pipe_index = inner.indexOf('|');
58
+ if (pipe_index !== -1) {
59
+ const reference = inner.slice(0, pipe_index).trim();
60
+ const display_text = inner.slice(pipe_index + 1).trim();
61
+ // Convert to markdown link: [text](url)
62
+ return `[${display_text}](${reference})`;
63
+ }
64
+ // No pipe - check if it's a URL or declaration
65
+ if (inner.startsWith('https://') || inner.startsWith('http://')) {
66
+ // Bare URL - return as-is
67
+ return inner;
68
+ }
69
+ else {
70
+ // Declaration or module - wrap in backticks
71
+ return `\`${inner}\``;
72
+ }
73
+ }
74
+ // No {@link} or {@see} syntax - check if it's a bare URL or declaration
75
+ const trimmed = content.trim();
76
+ if (trimmed.startsWith('https://') || trimmed.startsWith('http://')) {
77
+ // Already a bare URL - return as-is
78
+ return trimmed;
79
+ }
80
+ else {
81
+ // Declaration or module - wrap in backticks
82
+ return `\`${trimmed}\``;
83
+ }
84
+ };
85
+ /**
86
+ * Parse JSDoc comment from a TypeScript node.
87
+ *
88
+ * Extracts and parses all JSDoc tags including:
89
+ *
90
+ * - `@param` - parameter descriptions
91
+ * - `@returns` - return value description
92
+ * - `@throws` - error documentation
93
+ * - `@example` - code examples
94
+ * - `@deprecated` - deprecation warnings
95
+ * - `@see` - related references
96
+ * - `@since` - version information
97
+ * - `@mutates` - mutation documentation (non-standard)
98
+ *
99
+ * @param node The TypeScript node to extract JSDoc from
100
+ * @param source_file Source file (used for extracting full` @see` tag text)
101
+ */
102
+ export const tsdoc_parse = (node, source_file) => {
103
+ const tsdoc_comments = ts.getJSDocCommentsAndTags(node);
104
+ if (tsdoc_comments.length === 0)
105
+ return undefined;
106
+ let full_text = '';
107
+ const params = new Map();
108
+ let returns;
109
+ const throws = [];
110
+ const examples = [];
111
+ let deprecated_message;
112
+ const see_also = [];
113
+ let since;
114
+ const mutates = [];
115
+ let nodocs = false;
116
+ // Extract main comment text
117
+ for (const comment of tsdoc_comments) {
118
+ if (ts.isJSDoc(comment) && comment.comment) {
119
+ const text = typeof comment.comment === 'string'
120
+ ? comment.comment
121
+ : comment.comment.map((c) => c.text).join('');
122
+ full_text += text + '\n';
123
+ }
124
+ }
125
+ // Extract tags
126
+ const tags = ts.getJSDocTags(node);
127
+ for (const tag of tags) {
128
+ const tag_text = typeof tag.comment === 'string' ? tag.comment : tag.comment?.map((c) => c.text).join('');
129
+ const tag_name = tag.tagName.text;
130
+ if (tag_name === 'param' && ts.isJSDocParameterTag(tag)) {
131
+ // Extract parameter name and description
132
+ const param_name = ts.isIdentifier(tag.name) ? tag.name.text : tag.name.getText();
133
+ if (param_name && tag_text) {
134
+ params.set(param_name, tag_text.trim());
135
+ }
136
+ }
137
+ else if (tag_name === 'returns' && tag_text) {
138
+ returns = tag_text.trim();
139
+ }
140
+ else if (tag_name === 'throws' && tag_text) {
141
+ // Try to extract error type and description
142
+ const match = /^\{?(\w+)\}?\s+(.+)/.exec(tag_text);
143
+ if (match) {
144
+ throws.push({ type: match[1], description: match[2].trim() });
145
+ }
146
+ else {
147
+ throws.push({ description: tag_text.trim() });
148
+ }
149
+ }
150
+ else if (tag_name === 'example' && tag_text) {
151
+ examples.push(tag_text.trim());
152
+ }
153
+ else if (tag_name === 'deprecated' && tag_text) {
154
+ deprecated_message = tag_text.trim();
155
+ }
156
+ else if (tag_name === 'see') {
157
+ // The TS API strips 'https' from URLs in @see tags, so get full text from source
158
+ const full_tag_text = tag.getText(source_file);
159
+ // Extract content after @see, handling JSDoc formatting artifacts
160
+ const see_content = full_tag_text
161
+ .replace(/^@see\s+/, '') // remove @see prefix
162
+ .replace(/\n\s*\*\s*/g, ' ') // remove JSDoc line continuations
163
+ .trim();
164
+ if (see_content) {
165
+ // Convert TSDoc link syntax to mdz-compatible format
166
+ see_also.push(tsdoc_convert_link_to_mdz(see_content));
167
+ }
168
+ }
169
+ else if (tag_name === 'since' && tag_text) {
170
+ since = tag_text.trim();
171
+ }
172
+ else if (tag_name === 'mutates' && tag_text) {
173
+ mutates.push(tag_text.trim());
174
+ }
175
+ else if (tag_name === 'nodocs') {
176
+ nodocs = true;
177
+ }
178
+ }
179
+ full_text = full_text.trim();
180
+ return {
181
+ text: full_text,
182
+ params,
183
+ returns,
184
+ ...(throws.length && { throws }),
185
+ ...(examples.length && { examples }),
186
+ deprecated_message,
187
+ ...(see_also.length && { see_also }),
188
+ since,
189
+ ...(mutates.length && { mutates }),
190
+ ...(nodocs && { nodocs }),
191
+ };
192
+ };
193
+ /**
194
+ * Apply parsed TSDoc metadata to a declaration.
195
+ *
196
+ * Consolidates the common pattern of assigning TSDoc fields to declarations,
197
+ * with conditional assignment for array fields (only if non-empty).
198
+ *
199
+ * @param declaration declaration object to update
200
+ * @param tsdoc parsed TSDoc comment (if available)
201
+ * @mutates declaration - adds doc_comment, deprecated_message, examples, see_also, throws, since fields
202
+ */
203
+ export const tsdoc_apply_to_declaration = (declaration, tsdoc) => {
204
+ if (!tsdoc)
205
+ return;
206
+ declaration.doc_comment = tsdoc.text;
207
+ declaration.deprecated_message = tsdoc.deprecated_message;
208
+ // Only assign arrays if they have content
209
+ if (tsdoc.examples?.length) {
210
+ declaration.examples = tsdoc.examples;
211
+ }
212
+ if (tsdoc.see_also?.length) {
213
+ declaration.see_also = tsdoc.see_also;
214
+ }
215
+ if (tsdoc.throws?.length) {
216
+ declaration.throws = tsdoc.throws;
217
+ }
218
+ if (tsdoc.since) {
219
+ declaration.since = tsdoc.since;
220
+ }
221
+ };
package/package.json ADDED
@@ -0,0 +1,128 @@
1
+ {
2
+ "name": "@fuzdev/fuz_ui",
3
+ "version": "0.169.0",
4
+ "description": "Svelte UI library",
5
+ "motto": "friendly user zystem",
6
+ "glyph": "🧶",
7
+ "logo": "logo.svg",
8
+ "logo_alt": "a friendly brown spider facing you",
9
+ "public": true,
10
+ "license": "MIT",
11
+ "homepage": "https://www.fuz.dev/",
12
+ "author": {
13
+ "name": "Ryan Atkinson",
14
+ "email": "mail@ryanatkn.com",
15
+ "url": "https://www.ryanatkn.com/"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/ryanatkn/fuz.git"
20
+ },
21
+ "bugs": "https://github.com/ryanatkn/fuz/issues",
22
+ "funding": "https://www.ryanatkn.com/funding",
23
+ "scripts": {
24
+ "start": "gro dev",
25
+ "dev": "gro dev",
26
+ "build": "gro build",
27
+ "check": "gro check",
28
+ "test": "gro test",
29
+ "preview": "vite preview",
30
+ "deploy": "gro deploy"
31
+ },
32
+ "type": "module",
33
+ "engines": {
34
+ "node": ">=22.15"
35
+ },
36
+ "peerDependencies": {
37
+ "@fuzdev/fuz_code": ">=0.37.0",
38
+ "@fuzdev/fuz_css": ">=0.40.0",
39
+ "@fuzdev/fuz_util": ">=0.42.0",
40
+ "@ryanatkn/gro": ">=0.180.0",
41
+ "@sveltejs/kit": "^2.47.3",
42
+ "esm-env": "^1",
43
+ "svelte": "^5",
44
+ "svelte2tsx": "^0.7.45",
45
+ "zod": "^4.1.12"
46
+ },
47
+ "peerDependenciesMeta": {
48
+ "@fuzdev/fuz_code": {
49
+ "optional": true
50
+ },
51
+ "@ryanatkn/gro": {
52
+ "optional": true
53
+ },
54
+ "esm-env": {
55
+ "optional": true
56
+ }
57
+ },
58
+ "devDependencies": {
59
+ "@changesets/changelog-git": "^0.2.1",
60
+ "@fuzdev/fuz_code": "^0.37.0",
61
+ "@fuzdev/fuz_css": "^0.40.0",
62
+ "@fuzdev/fuz_util": "^0.42.0",
63
+ "@ryanatkn/belt": "^0.41.1",
64
+ "@ryanatkn/eslint-config": "^0.9.0",
65
+ "@ryanatkn/gro": "^0.180.0",
66
+ "@sveltejs/adapter-static": "^3.0.10",
67
+ "@sveltejs/kit": "^2.49.0",
68
+ "@sveltejs/package": "^2.5.7",
69
+ "@sveltejs/vite-plugin-svelte": "^6.2.1",
70
+ "@types/node": "^24.10.1",
71
+ "eslint": "^9.39.1",
72
+ "eslint-plugin-svelte": "^3.13.0",
73
+ "esm-env": "^1.2.2",
74
+ "jsdom": "^27.2.0",
75
+ "prettier": "^3.6.2",
76
+ "prettier-plugin-svelte": "^3.4.0",
77
+ "svelte": "^5.45.2",
78
+ "svelte-check": "^4.3.4",
79
+ "svelte2tsx": "^0.7.45",
80
+ "tslib": "^2.8.1",
81
+ "typescript": "^5.9.3",
82
+ "typescript-eslint": "^8.48.0",
83
+ "vitest": "^4.0.14",
84
+ "zod": "^4.1.13"
85
+ },
86
+ "prettier": {
87
+ "plugins": [
88
+ "prettier-plugin-svelte"
89
+ ],
90
+ "useTabs": true,
91
+ "printWidth": 100,
92
+ "singleQuote": true,
93
+ "bracketSpacing": false,
94
+ "overrides": [
95
+ {
96
+ "files": "package.json",
97
+ "options": {
98
+ "useTabs": false
99
+ }
100
+ }
101
+ ]
102
+ },
103
+ "sideEffects": [
104
+ "**/*.css"
105
+ ],
106
+ "files": [
107
+ "dist",
108
+ "src/lib/**/*.ts",
109
+ "!src/lib/**/*.test.*",
110
+ "!dist/**/*.test.*"
111
+ ],
112
+ "exports": {
113
+ "./package.json": "./package.json",
114
+ "./*.js": {
115
+ "types": "./dist/*.d.ts",
116
+ "default": "./dist/*.js"
117
+ },
118
+ "./*.ts": {
119
+ "types": "./dist/*.d.ts",
120
+ "default": "./dist/*.js"
121
+ },
122
+ "./*.svelte": {
123
+ "types": "./dist/*.svelte.d.ts",
124
+ "svelte": "./dist/*.svelte",
125
+ "default": "./dist/*.svelte"
126
+ }
127
+ }
128
+ }
@@ -0,0 +1,14 @@
1
+ // TODO move to module context?
2
+
3
+ export type AlertStatus = 'inform' | 'help' | 'error';
4
+
5
+ export interface AlertStatusOptions {
6
+ color: string;
7
+ icon: string | null;
8
+ }
9
+
10
+ export const alert_status_options: Record<AlertStatus, AlertStatusOptions> = {
11
+ inform: {color: 'var(--text_color_3)', icon: '✻'},
12
+ help: {color: 'var(--color_b_5)', icon: '➺'},
13
+ error: {color: 'var(--color_c_5)', icon: '!?'},
14
+ };
@@ -0,0 +1,85 @@
1
+ import type {Declaration} from './declaration.svelte.js';
2
+ import type {Library} from './library.svelte.js';
3
+
4
+ export interface DeclarationSearchState {
5
+ query: string;
6
+ all: Array<Declaration>;
7
+ filtered: Array<Declaration>;
8
+ }
9
+
10
+ /**
11
+ * Creates search state for the API index page (all declarations across all modules).
12
+ */
13
+ export const create_declaration_search = (library: Library): DeclarationSearchState => {
14
+ let query = $state('');
15
+
16
+ const all = $derived(library.declarations);
17
+
18
+ const filtered = $derived.by(() => {
19
+ const items = query.trim() ? library.search_declarations(query) : all;
20
+ return items.sort((a, b) => a.name.localeCompare(b.name));
21
+ });
22
+
23
+ return {
24
+ get query() {
25
+ return query;
26
+ },
27
+ set query(v: string) {
28
+ query = v;
29
+ },
30
+ get all() {
31
+ return all;
32
+ },
33
+ get filtered() {
34
+ return filtered;
35
+ },
36
+ };
37
+ };
38
+
39
+ /**
40
+ * Creates search state for module-specific declaration lists.
41
+ */
42
+ export const create_module_declaration_search = (
43
+ declarations: Array<Declaration>,
44
+ ): DeclarationSearchState => {
45
+ let query = $state('');
46
+
47
+ const all = $derived(declarations);
48
+
49
+ const filtered = $derived.by(() => {
50
+ const trimmed_query = query.trim();
51
+ if (!trimmed_query) return all.sort((a, b) => a.name.localeCompare(b.name));
52
+
53
+ const terms = trimmed_query.toLowerCase().split(/\s+/);
54
+
55
+ const items = all.filter((d) => {
56
+ const name_lower = d.name.toLowerCase();
57
+ const kind_lower = d.kind.toLowerCase();
58
+ const module_path_lower = d.module_path.toLowerCase();
59
+
60
+ return terms.every(
61
+ (term) =>
62
+ name_lower.includes(term) ||
63
+ kind_lower.includes(term) ||
64
+ module_path_lower.includes(term),
65
+ );
66
+ });
67
+
68
+ return items.sort((a, b) => a.name.localeCompare(b.name));
69
+ });
70
+
71
+ return {
72
+ get query() {
73
+ return query;
74
+ },
75
+ set query(v: string) {
76
+ query = v;
77
+ },
78
+ get all() {
79
+ return all;
80
+ },
81
+ get filtered() {
82
+ return filtered;
83
+ },
84
+ };
85
+ };
@@ -0,0 +1,3 @@
1
+ // TODO the 60px is a hack, need `--docs_primary_nav_height` exported or :root values from Fuz -- the --space_lg also needs to be kept in sync
2
+ // see also the same issue in Moss
3
+ export const MAIN_HEADER_MARGIN_TOP = 'calc(60px + var(--space_lg))';
@@ -0,0 +1,47 @@
1
+ import {getContext, setContext} from 'svelte';
2
+
3
+ // This uses a function instead of a class because of the overloaded type signatures.
4
+ // It could be implemented internally with a class like `SvelteContext`
5
+ // but this is less code and seems a bit simpler.
6
+ // The memory gains of a class appear minimal given the expected usage patterns.
7
+ // See https://github.com/ryanatkn/fuz/pull/56 for more.
8
+
9
+ // TODO maybe remove `error_message`?
10
+
11
+ /**
12
+ * Wraps Svelte's `setContext` and `getContext` for better ergonomics.
13
+ * When no value is set in the context,
14
+ * `get` throws an error and `get_maybe` returns `undefined`.
15
+ * If a `fallback` is provided, the `value` argument to `set` is optional
16
+ * and `get_maybe` is omitted from the type.
17
+ */
18
+ export function create_context<T>(fallback: () => T): {
19
+ get: () => T;
20
+ set: (value?: T) => T;
21
+ };
22
+ export function create_context<T>(): {
23
+ get: (error_message?: string) => T;
24
+ get_maybe: () => T | undefined;
25
+ set: (value: T) => T;
26
+ };
27
+ export function create_context<T>(fallback?: () => T): {
28
+ get: (error_message?: string) => T;
29
+ get_maybe: () => T | undefined;
30
+ set: (value?: T) => T;
31
+ } {
32
+ const key = Symbol();
33
+ const get_maybe = () => {
34
+ const value: T | undefined = getContext(key); // treat `null` as a valid value - the `typescript-eslint` rule below is bugged because `??` would clobber nulls, see issue https://github.com/typescript-eslint/typescript-eslint/issues/7842
35
+ return value === undefined ? fallback?.() : value;
36
+ };
37
+ return {
38
+ get: (error_message?: string) => {
39
+ const value = get_maybe();
40
+ if (value === undefined) throw Error(error_message ?? 'context value is not set');
41
+ return value;
42
+ },
43
+ get_maybe,
44
+ // this is typesafe, so no runtime check:
45
+ set: (value: T | undefined = fallback?.()) => setContext(key, value)!,
46
+ };
47
+ }
@@ -0,0 +1,63 @@
1
+ import {is_editable, swallow, inside_editable} from '@fuzdev/fuz_util/dom.js';
2
+
3
+ import type {ContextmenuState} from './contextmenu_state.svelte.js';
4
+
5
+ // Constants for default prop values
6
+ export const CONTEXTMENU_DEFAULT_OPEN_OFFSET_X = -2;
7
+ export const CONTEXTMENU_DEFAULT_OPEN_OFFSET_Y = -2;
8
+ export const CONTEXTMENU_DEFAULT_BYPASS_WINDOW = 750;
9
+ export const CONTEXTMENU_DEFAULT_BYPASS_MOVE_TOLERANCE = 11;
10
+ export const CONTEXTMENU_DEFAULT_LONGPRESS_DURATION = 633;
11
+ export const CONTEXTMENU_DEFAULT_LONGPRESS_MOVE_TOLERANCE = 21;
12
+
13
+ /**
14
+ * Returns true if valid and narrows the type to HTMLElement | SVGElement.
15
+ */
16
+ export const contextmenu_is_valid_target = (
17
+ target: EventTarget | null,
18
+ shiftKey: boolean,
19
+ ): target is HTMLElement | SVGElement =>
20
+ !shiftKey &&
21
+ (target instanceof HTMLElement || target instanceof SVGElement) &&
22
+ !is_editable(target) &&
23
+ !inside_editable(target);
24
+
25
+ // TODO maybe bind these to the contextmenu instance instead of including the function wrapper
26
+ // TODO customize
27
+ export const contextmenu_create_keyboard_handlers = (
28
+ contextmenu: ContextmenuState,
29
+ ): Map<string, () => void> =>
30
+ new Map([
31
+ ['Escape', () => contextmenu.close()],
32
+ ['ArrowLeft', () => contextmenu.collapse_selected()],
33
+ ['ArrowRight', () => contextmenu.expand_selected()],
34
+ ['ArrowDown', () => contextmenu.select_next()],
35
+ ['ArrowUp', () => contextmenu.select_previous()],
36
+ ['Home', () => contextmenu.select_first()],
37
+ ['End', () => contextmenu.select_last()],
38
+ [' ', () => contextmenu.activate_selected()],
39
+ ['Enter', () => contextmenu.activate_selected()],
40
+ ]);
41
+
42
+ export const contextmenu_create_keydown_handler = (
43
+ keyboard_handlers: Map<string, () => void>,
44
+ ): ((e: KeyboardEvent) => void) => {
45
+ return (e: KeyboardEvent): void => {
46
+ const handler = keyboard_handlers.get(e.key);
47
+ if (!handler || is_editable(e.target)) return;
48
+ swallow(e);
49
+ handler();
50
+ };
51
+ };
52
+
53
+ export const contextmenu_calculate_constrained_x = (
54
+ menu_x: number,
55
+ menu_width: number,
56
+ layout_width: number,
57
+ ): number => menu_x + Math.min(0, layout_width - (menu_x + menu_width));
58
+
59
+ export const contextmenu_calculate_constrained_y = (
60
+ menu_y: number,
61
+ menu_height: number,
62
+ layout_height: number,
63
+ ): number => menu_y + Math.min(0, layout_height - (menu_y + menu_height));