@fuzdev/fuz_ui 0.201.0 → 0.203.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 (85) hide show
  1. package/dist/ApiIndex.svelte +6 -3
  2. package/dist/ApiIndex.svelte.d.ts +1 -1
  3. package/dist/ApiIndex.svelte.d.ts.map +1 -1
  4. package/dist/ApiModule.svelte +72 -21
  5. package/dist/ApiModule.svelte.d.ts +1 -1
  6. package/dist/ApiModule.svelte.d.ts.map +1 -1
  7. package/dist/ContextmenuEntry.svelte +11 -10
  8. package/dist/ContextmenuEntry.svelte.d.ts +1 -1
  9. package/dist/ContextmenuEntry.svelte.d.ts.map +1 -1
  10. package/dist/ContextmenuLinkEntry.svelte +30 -12
  11. package/dist/ContextmenuLinkEntry.svelte.d.ts +2 -1
  12. package/dist/ContextmenuLinkEntry.svelte.d.ts.map +1 -1
  13. package/dist/ContextmenuMenu.svelte +207 -0
  14. package/dist/ContextmenuMenu.svelte.d.ts +41 -0
  15. package/dist/ContextmenuMenu.svelte.d.ts.map +1 -0
  16. package/dist/ContextmenuRoot.svelte +58 -260
  17. package/dist/ContextmenuRoot.svelte.d.ts +2 -60
  18. package/dist/ContextmenuRoot.svelte.d.ts.map +1 -1
  19. package/dist/ContextmenuRootForSafariCompatibility.svelte +72 -283
  20. package/dist/ContextmenuRootForSafariCompatibility.svelte.d.ts +2 -58
  21. package/dist/ContextmenuRootForSafariCompatibility.svelte.d.ts.map +1 -1
  22. package/dist/ContextmenuSeparator.svelte +2 -1
  23. package/dist/ContextmenuSeparator.svelte.d.ts.map +1 -1
  24. package/dist/ContextmenuSubmenu.svelte +27 -23
  25. package/dist/ContextmenuSubmenu.svelte.d.ts +1 -1
  26. package/dist/ContextmenuSubmenu.svelte.d.ts.map +1 -1
  27. package/dist/ContextmenuTextEntry.svelte +7 -3
  28. package/dist/ContextmenuTextEntry.svelte.d.ts +2 -1
  29. package/dist/ContextmenuTextEntry.svelte.d.ts.map +1 -1
  30. package/dist/CopyToClipboard.svelte +5 -2
  31. package/dist/CopyToClipboard.svelte.d.ts.map +1 -1
  32. package/dist/DeclarationLink.svelte +15 -2
  33. package/dist/DeclarationLink.svelte.d.ts +7 -0
  34. package/dist/DeclarationLink.svelte.d.ts.map +1 -1
  35. package/dist/DialogContent.svelte +3 -1
  36. package/dist/DialogContent.svelte.d.ts.map +1 -1
  37. package/dist/Docs.svelte +11 -8
  38. package/dist/Docs.svelte.d.ts.map +1 -1
  39. package/dist/DocsLink.svelte +3 -1
  40. package/dist/DocsLink.svelte.d.ts.map +1 -1
  41. package/dist/DocsSearch.svelte +4 -1
  42. package/dist/DocsSearch.svelte.d.ts.map +1 -1
  43. package/dist/DocsTertiaryNav.svelte +2 -1
  44. package/dist/DocsTertiaryNav.svelte.d.ts.map +1 -1
  45. package/dist/LibraryDetail.svelte +9 -3
  46. package/dist/LibraryDetail.svelte.d.ts +1 -1
  47. package/dist/LibraryDetail.svelte.d.ts.map +1 -1
  48. package/dist/ModuleLink.svelte +2 -1
  49. package/dist/ModuleLink.svelte.d.ts.map +1 -1
  50. package/dist/Svg.svelte +46 -9
  51. package/dist/Svg.svelte.d.ts.map +1 -1
  52. package/dist/TypeLink.svelte +2 -1
  53. package/dist/TypeLink.svelte.d.ts.map +1 -1
  54. package/dist/contextmenu_helpers.d.ts +324 -1
  55. package/dist/contextmenu_helpers.d.ts.map +1 -1
  56. package/dist/contextmenu_helpers.js +403 -2
  57. package/dist/contextmenu_state.svelte.d.ts +61 -15
  58. package/dist/contextmenu_state.svelte.d.ts.map +1 -1
  59. package/dist/contextmenu_state.svelte.js +206 -119
  60. package/dist/declaration.svelte.d.ts +1 -0
  61. package/dist/declaration.svelte.d.ts.map +1 -1
  62. package/dist/declaration.svelte.js +2 -1
  63. package/dist/icons.d.ts +469 -0
  64. package/dist/icons.d.ts.map +1 -0
  65. package/dist/icons.js +578 -0
  66. package/dist/library.svelte.d.ts +30 -3
  67. package/dist/library.svelte.d.ts.map +1 -1
  68. package/dist/library.svelte.js +38 -0
  69. package/dist/logos.d.ts +1 -3
  70. package/dist/logos.d.ts.map +1 -1
  71. package/dist/logos.js +1 -1
  72. package/dist/module.svelte.d.ts +62 -1
  73. package/dist/module.svelte.d.ts.map +1 -1
  74. package/dist/module.svelte.js +71 -1
  75. package/dist/svg.d.ts +69 -10
  76. package/dist/svg.d.ts.map +1 -1
  77. package/package.json +2 -2
  78. package/src/lib/contextmenu_helpers.ts +546 -3
  79. package/src/lib/contextmenu_state.svelte.ts +219 -119
  80. package/src/lib/declaration.svelte.ts +2 -1
  81. package/src/lib/icons.ts +671 -0
  82. package/src/lib/library.svelte.ts +43 -1
  83. package/src/lib/logos.ts +1 -1
  84. package/src/lib/module.svelte.ts +97 -2
  85. package/src/lib/svg.ts +70 -9
@@ -1,8 +1,9 @@
1
1
  <script lang="ts">
2
- import type {Snippet} from 'svelte';
2
+ import {onDestroy, type Snippet} from 'svelte';
3
3
  import {swallow} from '@fuzdev/fuz_util/dom.js';
4
4
 
5
5
  import {contextmenu_context, contextmenu_dimensions_context} from './contextmenu_state.svelte.js';
6
+ import {contextmenu_calculate_submenu_translate} from './contextmenu_helpers.js';
6
7
  import type {Dimensions} from './dimensions.svelte.js';
7
8
 
8
9
  const {
@@ -32,6 +33,10 @@
32
33
 
33
34
  let translate_x = $state.raw(0);
34
35
  let translate_y = $state.raw(0);
36
+ // Measure-and-correct loop: `update_position` reads `translate_x`/`translate_y`
37
+ // (subtracting them from the measured rect to recover the untranslated base position)
38
+ // and writes them back, so the effect re-runs after the transform applies -
39
+ // the second pass measures the same base and writes identical values, settling.
35
40
  $effect(() => {
36
41
  if (el) update_position(el, layout, parent_dimensions);
37
42
  });
@@ -39,23 +44,23 @@
39
44
  const {x, y, width, height} = el.getBoundingClientRect();
40
45
  dimensions.width = width;
41
46
  dimensions.height = height;
42
- const base_x = x - translate_x;
43
- const base_y = y - translate_y;
44
- const overflow_right = base_x + width + parent_dimensions.width - layout.width;
45
- if (overflow_right <= 0) {
46
- translate_x = parent_dimensions.width;
47
- } else {
48
- const overflow_left = width - base_x;
49
- if (overflow_left <= 0) {
50
- translate_x = -width;
51
- } else if (overflow_left > overflow_right) {
52
- translate_x = parent_dimensions.width - overflow_right;
53
- } else {
54
- translate_x = overflow_left - width;
55
- }
56
- }
57
- translate_y = Math.min(0, layout.height - (base_y + height));
47
+ const translate = contextmenu_calculate_submenu_translate({
48
+ base_x: x - translate_x,
49
+ base_y: y - translate_y,
50
+ width,
51
+ height,
52
+ parent_width: parent_dimensions.width,
53
+ layout_width: layout.width,
54
+ layout_height: layout.height,
55
+ });
56
+ translate_x = translate.x;
57
+ translate_y = translate.y;
58
58
  };
59
+
60
+ let select_timeout: NodeJS.Timeout | null = null;
61
+ onDestroy(() => {
62
+ if (select_timeout !== null) clearTimeout(select_timeout);
63
+ });
59
64
  </script>
60
65
 
61
66
  <li role="none" style:--contextmenu_depth={submenu.depth}>
@@ -64,7 +69,6 @@
64
69
  class="menuitem plain selectable"
65
70
  class:selected
66
71
  role="menuitem"
67
- aria-label="contextmenu submenmu"
68
72
  aria-haspopup="menu"
69
73
  tabindex="-1"
70
74
  onmouseenter={(e) => {
@@ -73,7 +77,11 @@
73
77
  // fires immediately when the contextmenu appears,
74
78
  // and then the newly mounted selected entry immediately receives a click event.
75
79
  // The timeout ensures the click event is not passed through.
76
- setTimeout(() => contextmenu.select(submenu));
80
+ if (select_timeout !== null) clearTimeout(select_timeout);
81
+ select_timeout = setTimeout(() => {
82
+ select_timeout = null;
83
+ contextmenu.select(submenu);
84
+ });
77
85
  }}
78
86
  aria-expanded={selected}
79
87
  >
@@ -111,8 +119,4 @@
111
119
  max-width: var(--contextmenu_width);
112
120
  width: 100%;
113
121
  }
114
- /* TODO hacky, needed because the base `.menuitem` added z-index */
115
- .menuitem {
116
- z-index: unset;
117
- }
118
122
  </style>
@@ -1,4 +1,4 @@
1
- import type { Snippet } from 'svelte';
1
+ import { type Snippet } from 'svelte';
2
2
  type $$ComponentProps = {
3
3
  icon?: Snippet;
4
4
  menu: Snippet;
@@ -1 +1 @@
1
- {"version":3,"file":"ContextmenuSubmenu.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/ContextmenuSubmenu.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AAMnC,KAAK,gBAAgB,GAAI;IACxB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;CAClB,CAAC;AAoFH,QAAA,MAAM,kBAAkB,sDAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"ContextmenuSubmenu.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/ContextmenuSubmenu.svelte"],"names":[],"mappings":"AAGA,OAAO,EAAY,KAAK,OAAO,EAAC,MAAM,QAAQ,CAAC;AAO9C,KAAK,gBAAgB,GAAI;IACxB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;CAClB,CAAC;AA6FH,QAAA,MAAM,kBAAkB,sDAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
@@ -1,21 +1,25 @@
1
1
  <script lang="ts">
2
+ import type {SvgData} from './svg.js';
3
+ import Svg from './Svg.svelte';
2
4
  import ContextmenuEntry from './ContextmenuEntry.svelte';
3
5
  import type {ContextmenuRun} from './contextmenu_state.svelte.js';
4
6
 
5
7
  const {
6
8
  run,
7
9
  content,
8
- icon: icon_text,
10
+ icon: icon_value,
9
11
  }: {
10
12
  run: ContextmenuRun;
11
13
  content: string; // TODO @many rethink this API
12
- icon: string; // TODO @many rethink this API
14
+ icon: SvgData | string;
13
15
  } = $props();
14
16
 
15
17
  // TODO consider making this the implicit default entry, so consumers can simply declare `{run, content}`
16
18
  </script>
17
19
 
18
20
  <ContextmenuEntry {run}>
19
- {#snippet icon()}{icon_text}{/snippet}
21
+ {#snippet icon()}{#if typeof icon_value === 'string'}{icon_value}{:else}<Svg
22
+ data={icon_value}
23
+ />{/if}{/snippet}
20
24
  {content}
21
25
  </ContextmenuEntry>
@@ -1,8 +1,9 @@
1
+ import type { SvgData } from './svg.js';
1
2
  import type { ContextmenuRun } from './contextmenu_state.svelte.js';
2
3
  type $$ComponentProps = {
3
4
  run: ContextmenuRun;
4
5
  content: string;
5
- icon: string;
6
+ icon: SvgData | string;
6
7
  };
7
8
  declare const ContextmenuTextEntry: import("svelte").Component<$$ComponentProps, {}, "">;
8
9
  type ContextmenuTextEntry = ReturnType<typeof ContextmenuTextEntry>;
@@ -1 +1 @@
1
- {"version":3,"file":"ContextmenuTextEntry.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/ContextmenuTextEntry.svelte"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,+BAA+B,CAAC;AAEjE,KAAK,gBAAgB,GAAI;IACxB,GAAG,EAAE,cAAc,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACb,CAAC;AAqBH,QAAA,MAAM,oBAAoB,sDAAwC,CAAC;AACnE,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACpE,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"ContextmenuTextEntry.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/ContextmenuTextEntry.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,UAAU,CAAC;AAGtC,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,+BAA+B,CAAC;AAEjE,KAAK,gBAAgB,GAAI;IACxB,GAAG,EAAE,cAAc,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;CACvB,CAAC;AAuBH,QAAA,MAAM,oBAAoB,sDAAwC,CAAC;AACnE,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACpE,eAAe,oBAAoB,CAAC"}
@@ -4,6 +4,9 @@
4
4
  import type {SvelteHTMLElements} from 'svelte/elements';
5
5
  import {scale, slide} from 'svelte/transition';
6
6
 
7
+ import {icon_checkmark, icon_copy} from './icons.js';
8
+ import Svg from './Svg.svelte';
9
+
7
10
  // TODO @many should this have the Button suffix?
8
11
 
9
12
  // TODO add docs entry, see also PasteFromClipboard.svelte
@@ -73,8 +76,8 @@
73
76
  {#if children}
74
77
  {@render children(copied, failed)}
75
78
  {:else if copied}
76
- <div in:scale={{duration: 200}}>✓</div>
79
+ <div in:scale={{duration: 200}}><Svg data={icon_checkmark} /></div>
77
80
  {:else}
78
- <div in:slide>⧉</div>
81
+ <div in:slide><Svg data={icon_copy} /></div>
79
82
  {/if}
80
83
  </button>
@@ -1 +1 @@
1
- {"version":3,"file":"CopyToClipboard.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/CopyToClipboard.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAGvD,KAAK,gBAAgB,GAAI,UAAU,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,GAAG;IAC/E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IACtD,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD,CAAC;AA+DH,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"CopyToClipboard.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/CopyToClipboard.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAMvD,KAAK,gBAAgB,GAAI,UAAU,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,GAAG;IAC/E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IACtD,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD,CAAC;AAkEH,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
@@ -8,6 +8,7 @@
8
8
 
9
9
  const {
10
10
  name,
11
+ module_path,
11
12
  hash,
12
13
  full = false,
13
14
  children,
@@ -15,6 +16,13 @@
15
16
  ...rest
16
17
  }: SvelteHTMLElements['a'] & {
17
18
  name: string;
19
+ /**
20
+ * Module path of the declaration's defining module. When provided,
21
+ * resolution is scoped to that module's declarations — exact even when
22
+ * names collide across modules. Without it, resolution falls back to the
23
+ * library-wide by-name map.
24
+ */
25
+ module_path?: string;
18
26
  /** URL fragment to append, with or without the `#`. */
19
27
  hash?: string;
20
28
  /**
@@ -25,9 +33,14 @@
25
33
  full?: boolean;
26
34
  } = $props();
27
35
 
28
- const library = library_context.get();
36
+ const get_library = library_context.get();
37
+ const library = $derived(get_library());
29
38
 
30
- const declaration = $derived(library.declaration_by_name.get(name));
39
+ const declaration = $derived(
40
+ module_path === undefined
41
+ ? library.declaration_by_name.get(name)
42
+ : library.module_by_path.get(module_path)?.get_declaration_by_name(name),
43
+ );
31
44
 
32
45
  // When linking a foreign library's docs, prefer its full URL; fall back to
33
46
  // the site-local path if `homepage_url` is unavailable.
@@ -1,6 +1,13 @@
1
1
  import type { SvelteHTMLElements } from 'svelte/elements';
2
2
  type $$ComponentProps = SvelteHTMLElements['a'] & {
3
3
  name: string;
4
+ /**
5
+ * Module path of the declaration's defining module. When provided,
6
+ * resolution is scoped to that module's declarations — exact even when
7
+ * names collide across modules. Without it, resolution falls back to the
8
+ * library-wide by-name map.
9
+ */
10
+ module_path?: string;
4
11
  /** URL fragment to append, with or without the `#`. */
5
12
  hash?: string;
6
13
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"DeclarationLink.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DeclarationLink.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAOvD,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAoDH,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"DeclarationLink.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DeclarationLink.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAOvD,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG;IAClD,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AA0DH,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
@@ -3,6 +3,8 @@
3
3
  import type {HTMLAttributes, SvelteHTMLElements} from 'svelte/elements';
4
4
 
5
5
  import {dialog_context, type DialogContext, type DialogCloseButtonAttrs} from './dialog.js';
6
+ import {icon_close} from './icons.js';
7
+ import Svg from './Svg.svelte';
6
8
 
7
9
  /**
8
10
  * The default content surface for `Dialog`: a fuz_css `.pane` card with a
@@ -133,7 +135,7 @@ content with its own overflow (e.g. `Code`) scrolls instead of forcing the card
133
135
  <!-- rendered after `children` so a content control (or an `autofocus` element)
134
136
  takes initial focus on open, not the close button -->
135
137
  {#if close_button === true}
136
- <button {...close_button_attrs}>✕</button>
138
+ <button {...close_button_attrs}><Svg data={icon_close} /></button>
137
139
  {:else if close_button}
138
140
  {@render close_button(close_button_attrs, dialog)}
139
141
  {/if}
@@ -1 +1 @@
1
- {"version":3,"file":"DialogContent.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DialogContent.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAC,cAAc,EAAqB,MAAM,iBAAiB,CAAC;AAExE,OAAO,EAAiB,KAAK,aAAa,EAAE,KAAK,sBAAsB,EAAC,MAAM,aAAa,CAAC;AAE3F,KAAK,gBAAgB,GAAI,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IAC3E;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;IACzF;;;;;;;;;;;;OAYG;IACH,QAAQ,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;CAC3C,CAAC;AAoEH,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"DialogContent.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DialogContent.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAC,cAAc,EAAqB,MAAM,iBAAiB,CAAC;AAExE,OAAO,EAAiB,KAAK,aAAa,EAAE,KAAK,sBAAsB,EAAC,MAAM,aAAa,CAAC;AAI3F,KAAK,gBAAgB,GAAI,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IAC3E;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;IACzF;;;;;;;;;;;;OAYG;IACH,QAAQ,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;CAC3C,CAAC;AAsEH,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
package/dist/Docs.svelte CHANGED
@@ -10,6 +10,7 @@
10
10
  import DocsSecondaryNav from './DocsSecondaryNav.svelte';
11
11
  import DocsTertiaryNav from './DocsTertiaryNav.svelte';
12
12
  import Dialog from './Dialog.svelte';
13
+ import DialogContent from './DialogContent.svelte';
13
14
  import DocsFooter from './DocsFooter.svelte';
14
15
  import {site_context} from './site.svelte.js';
15
16
  import {FUZ_DEV_URL} from './constants.js';
@@ -83,15 +84,17 @@
83
84
  <!-- TODO this is messy rendering `DocsSecondaryNav` twice to handle responsive states with SSR correctly -->
84
85
  {#if show_secondary_nav_dialog && innerWidth.current && innerWidth.current <= TERTIARY_NAV_BREAKPOINT}
85
86
  <Dialog onclose={() => (show_secondary_nav_dialog = false)}>
86
- <div class="pane" style:--docs_menu_width={docs_menu_width}>
87
- <div class="p_xl pb_0">
88
- <Breadcrumb />
89
- </div>
90
- <div class="px_lg pb_xl">
91
- <DocsSecondaryNav {tomes} sidebar={false} />
92
- <DocsTertiaryNav {tomes} {tomes_by_slug} sidebar={false} />
87
+ <DialogContent padding="">
88
+ <div style:--docs_menu_width={docs_menu_width}>
89
+ <div class="p_xl pb_0">
90
+ <Breadcrumb />
91
+ </div>
92
+ <div class="px_lg pb_xl">
93
+ <DocsSecondaryNav {tomes} sidebar={false} />
94
+ <DocsTertiaryNav {tomes} {tomes_by_slug} sidebar={false} />
95
+ </div>
93
96
  </div>
94
- </div>
97
+ </DialogContent>
95
98
  </Dialog>
96
99
  {/if}
97
100
 
@@ -1 +1 @@
1
- {"version":3,"file":"Docs.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/Docs.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AAMpC,OAAO,EAAC,IAAI,EAAgB,MAAM,WAAW,CAAC;AAU7C,KAAK,gBAAgB,GAAI;IACxB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CAClB,CAAC;AAkGH,QAAA,MAAM,IAAI,sDAAwC,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"Docs.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/Docs.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AAMpC,OAAO,EAAC,IAAI,EAAgB,MAAM,WAAW,CAAC;AAW7C,KAAK,gBAAgB,GAAI;IACxB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CAClB,CAAC;AAqGH,QAAA,MAAM,IAAI,sDAAwC,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
@@ -19,7 +19,9 @@
19
19
  display_text?: string | null;
20
20
  children?: Snippet<[Declaration | undefined, Module | undefined]>;
21
21
  } = $props();
22
- const library = library_context.get();
22
+
23
+ const get_library = library_context.get();
24
+ const library = $derived(get_library());
23
25
 
24
26
  // Try to find as declaration first, then module
25
27
  const declaration = $derived(library.declaration_by_name.get(reference));
@@ -1 +1 @@
1
- {"version":3,"file":"DocsLink.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DocsLink.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AAKpC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,oBAAoB,CAAC;AAE9C,KAAK,gBAAgB,GAAI;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,WAAW,GAAG,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CAClE,CAAC;AA0CH,QAAA,MAAM,QAAQ,sDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"DocsLink.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DocsLink.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AAKpC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,oBAAoB,CAAC;AAE9C,KAAK,gBAAgB,GAAI;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,WAAW,GAAG,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CAClE,CAAC;AA4CH,QAAA,MAAM,QAAQ,sDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -1,6 +1,9 @@
1
1
  <script lang="ts">
2
2
  import type {SvelteHTMLElements} from 'svelte/elements';
3
3
 
4
+ import {icon_close} from './icons.js';
5
+ import Svg from './Svg.svelte';
6
+
4
7
  let {
5
8
  placeholder = 'search modules and declarations...',
6
9
  module_count,
@@ -71,7 +74,7 @@
71
74
  title="clear search"
72
75
  aria-label="clear search"
73
76
  >
74
- 🗙
77
+ <Svg data={icon_close} />
75
78
  </button>
76
79
  {/if}
77
80
  </label>
@@ -1 +1 @@
1
- {"version":3,"file":"DocsSearch.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DocsSearch.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAEvD,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,OAAO,CAAC,GAAG;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;OAEG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,YAAY,EAAE,MAAM,CAAC;CACrB,CAAC;AA+DH,QAAA,MAAM,UAAU,kEAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"DocsSearch.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DocsSearch.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAKvD,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,OAAO,CAAC,GAAG;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;OAEG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,YAAY,EAAE,MAAM,CAAC;CACrB,CAAC;AAkEH,QAAA,MAAM,UAAU,kEAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -29,7 +29,8 @@
29
29
  .filter((t) => t !== undefined) ?? [],
30
30
  );
31
31
 
32
- const library = library_context.get();
32
+ const get_library = library_context.get();
33
+ const library = $derived(get_library());
33
34
 
34
35
  const modules_related_to_selected = $derived(
35
36
  selected_tome?.related_modules
@@ -1 +1 @@
1
- {"version":3,"file":"DocsTertiaryNav.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DocsTertiaryNav.svelte"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAGxD,OAAO,EAAmB,IAAI,EAAC,MAAM,WAAW,CAAC;AAOhD,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,OAAO,CAAC,GAAG;IACtD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACnB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAwFH,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"DocsTertiaryNav.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DocsTertiaryNav.svelte"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAGxD,OAAO,EAAmB,IAAI,EAAC,MAAM,WAAW,CAAC;AAOhD,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,OAAO,CAAC,GAAG;IACtD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACnB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAyFH,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
@@ -12,7 +12,7 @@ with file-type coloring. Uses svelte-docinfo's file type predicates for module c
12
12
  import {format_url} from '@fuzdev/fuz_util/url.js';
13
13
  import type {Snippet} from 'svelte';
14
14
 
15
- import type {Library} from './library.svelte.js';
15
+ import {library_context, type Library} from './library.svelte.js';
16
16
  import ImgOrSvg from './ImgOrSvg.svelte';
17
17
  import DeclarationLink from './DeclarationLink.svelte';
18
18
  import ModuleLink from './ModuleLink.svelte';
@@ -44,6 +44,8 @@ with file-type coloring. Uses svelte-docinfo's file type predicates for module c
44
44
  children?: Snippet<[library: Library]>;
45
45
  } = $props();
46
46
 
47
+ library_context.set(() => library);
48
+
47
49
  // TODO show other data (lines of code)
48
50
 
49
51
  const {pkg_json} = $derived(library);
@@ -175,11 +177,15 @@ with file-type coloring. Uses svelte-docinfo's file type predicates for module c
175
177
  {module.path}
176
178
  </ModuleLink>
177
179
  </span>
178
- {#if module.declarations.length > 0}
180
+ {#if module.has_declarations}
179
181
  <ul class="declarations unstyled">
180
182
  {#each module.declarations as declaration (declaration.name)}
181
183
  <li>
182
- <DeclarationLink name={declaration.name} full={links_full} />
184
+ <DeclarationLink
185
+ name={declaration.name}
186
+ module_path={module.path}
187
+ full={links_full}
188
+ />
183
189
  </li>
184
190
  {/each}
185
191
  </ul>
@@ -1,5 +1,5 @@
1
1
  import type { Snippet } from 'svelte';
2
- import type { Library } from './library.svelte.js';
2
+ import { type Library } from './library.svelte.js';
3
3
  type $$ComponentProps = {
4
4
  library: Library;
5
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"LibraryDetail.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/LibraryDetail.svelte"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AAEpC,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,qBAAqB,CAAC;AAOhD,KAAK,gBAAgB,GAAI;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACrC,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;CACvC,CAAC;AAiKH;;;;;;GAMG;AACH,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"LibraryDetail.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/LibraryDetail.svelte"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AAEpC,OAAO,EAAkB,KAAK,OAAO,EAAC,MAAM,qBAAqB,CAAC;AAOjE,KAAK,gBAAgB,GAAI;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACrC,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;CACvC,CAAC;AAmKH;;;;;;GAMG;AACH,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -25,7 +25,8 @@
25
25
  full?: boolean;
26
26
  } = $props();
27
27
 
28
- const library = library_context.get();
28
+ const get_library = library_context.get();
29
+ const library = $derived(get_library());
29
30
 
30
31
  const module = $derived(library.module_by_path.get(module_path));
31
32
 
@@ -1 +1 @@
1
- {"version":3,"file":"ModuleLink.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/ModuleLink.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAOvD,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAoDH,QAAA,MAAM,UAAU,sDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ModuleLink.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/ModuleLink.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAOvD,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAqDH,QAAA,MAAM,UAAU,sDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
package/dist/Svg.svelte CHANGED
@@ -4,6 +4,29 @@
4
4
 
5
5
  import type {SvgData} from './svg.js';
6
6
 
7
+ /**
8
+ * Renders an `SvgData` icon definition to inline `svg` markup, never via `@html`.
9
+ *
10
+ * ## Security
11
+ *
12
+ * `SvgData` is rendered structurally into a fixed element set - `svg`, `defs`,
13
+ * `linearGradient`/`radialGradient`, `stop`, and `path`. None of these expose a
14
+ * navigation or script sink (no `src` or `foreignObject`, and a gradient `href`
15
+ * only references another gradient as a template, never a document location),
16
+ * and Svelte routes `on*` spread keys through `addEventListener` rather than
17
+ * writing inline handler attributes. So even an untrusted `SvgData` cannot
18
+ * introduce script execution or navigation - which is why the data is rendered
19
+ * through typed fields (`paths`, `gradients`) instead of a raw-markup escape
20
+ * hatch.
21
+ *
22
+ * The one residual: a `style` value (`data.style`, a path's `style`, or a
23
+ * gradient's `attrs.style`) can still issue network requests via `url(...)`, so
24
+ * sanitize styles if you render untrusted data and that matters. Per-instance
25
+ * `svg` attributes come from this component's own props, not from `data`.
26
+ *
27
+ * @module
28
+ */
29
+
7
30
  const {
8
31
  data,
9
32
  fill,
@@ -44,29 +67,43 @@
44
67
  const final_width = $derived(width ?? size); // TODO @many default value? `100%` or omitted or something else?
45
68
  const final_height = $derived(height ?? size); // TODO @many default value? `100%` or omitted or something else?
46
69
 
47
- // merge `style` so users don't accidentally clobber any style data - maybe support other attrs or somehow clean this up?
70
+ // merge `style` so the icon's own style and a per-instance `style` prop don't clobber each other
48
71
  const style = $derived(
49
- data.attrs?.style && rest.style
50
- ? ensure_end(data.attrs.style, ';') + ' ' + rest.style
51
- : (data.attrs?.style ?? rest.style),
72
+ data.style && rest.style
73
+ ? ensure_end(data.style, ';') + ' ' + rest.style
74
+ : (data.style ?? rest.style),
52
75
  );
53
-
54
- // TODO dont use @html
55
76
  </script>
56
77
 
57
78
  <svg
58
79
  viewBox={data.viewBox ?? '0 0 100 100'}
59
- {...data.attrs}
60
80
  {...rest}
61
81
  aria-label={label ?? data.label}
62
- class="{data.attrs?.class} {rest.class}"
63
82
  class:inline
64
83
  style:width={final_width}
65
84
  style:height={final_height}
66
85
  style:flex-shrink={shrink ? 1 : 0}
67
86
  {style}
68
87
  >
69
- {#if data.raw}{@html data.raw}{/if}<!-- eslint-disable-line svelte/no-at-html-tags -->
88
+ {#if data.gradients}
89
+ <defs>
90
+ {#each data.gradients as gradient (gradient.id)}
91
+ {#if gradient.type === 'radial'}
92
+ <radialGradient id={gradient.id} {...gradient.attrs}>
93
+ {#each gradient.stops as stop (stop)}
94
+ <stop offset={stop.offset} stop-color={stop.color} stop-opacity={stop.opacity} />
95
+ {/each}
96
+ </radialGradient>
97
+ {:else}
98
+ <linearGradient id={gradient.id} {...gradient.attrs}>
99
+ {#each gradient.stops as stop (stop)}
100
+ <stop offset={stop.offset} stop-color={stop.color} stop-opacity={stop.opacity} />
101
+ {/each}
102
+ </linearGradient>
103
+ {/if}
104
+ {/each}
105
+ </defs>
106
+ {/if}
70
107
  {#if data.paths}
71
108
  {#each data.paths as path (path)}
72
109
  <path fill={final_fill} {...path} />
@@ -1 +1 @@
1
- {"version":3,"file":"Svg.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/Svg.svelte"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAExD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,UAAU,CAAC;AAErC,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,KAAK,CAAC,GAAG;IACpD,IAAI,EAAE,OAAO,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AA8CH,QAAA,MAAM,GAAG,sDAAwC,CAAC;AAClD,KAAK,GAAG,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,CAAC;AAClC,eAAe,GAAG,CAAC"}
1
+ {"version":3,"file":"Svg.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/Svg.svelte"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAExD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,UAAU,CAAC;AAErC,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,KAAK,CAAC,GAAG;IACpD,IAAI,EAAE,OAAO,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAqFH,QAAA,MAAM,GAAG,sDAAwC,CAAC;AAClD,KAAK,GAAG,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,CAAC;AAClC,eAAe,GAAG,CAAC"}
@@ -13,7 +13,8 @@
13
13
  hash?: string;
14
14
  } = $props();
15
15
 
16
- const library = library_context.get();
16
+ const get_library = library_context.get();
17
+ const library = $derived(get_library());
17
18
 
18
19
  // TODO is not extensible
19
20
  // TODO maybe better name?
@@ -1 +1 @@
1
- {"version":3,"file":"TypeLink.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/TypeLink.svelte"],"names":[],"mappings":"AAQC,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AA0BH,QAAA,MAAM,QAAQ,sDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"TypeLink.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/TypeLink.svelte"],"names":[],"mappings":"AAQC,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AA2BH,QAAA,MAAM,QAAQ,sDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}