@cloudvoyant/helix-svelte 0.16.0 → 0.17.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 (63) hide show
  1. package/dist/Chart.svelte +52 -0
  2. package/dist/Chart.svelte.d.ts +22 -0
  3. package/dist/CopyButton.svelte +58 -0
  4. package/dist/CopyButton.svelte.d.ts +12 -0
  5. package/dist/Figure.svelte +32 -0
  6. package/dist/Figure.svelte.d.ts +14 -0
  7. package/dist/InlineLaTeX.svelte +34 -0
  8. package/dist/InlineLaTeX.svelte.d.ts +9 -0
  9. package/dist/LaTeX.svelte +34 -0
  10. package/dist/LaTeX.svelte.d.ts +9 -0
  11. package/dist/Manim.svelte +119 -0
  12. package/dist/Manim.svelte.d.ts +12 -0
  13. package/dist/Notice.svelte +87 -0
  14. package/dist/Notice.svelte.d.ts +12 -0
  15. package/dist/PrevNext.svelte +47 -0
  16. package/dist/PrevNext.svelte.d.ts +15 -0
  17. package/dist/Reveal.svelte +40 -0
  18. package/dist/Reveal.svelte.d.ts +9 -0
  19. package/dist/YouTube.svelte +85 -0
  20. package/dist/YouTube.svelte.d.ts +13 -0
  21. package/dist/YoutubeTimestampAt.svelte +20 -0
  22. package/dist/YoutubeTimestampAt.svelte.d.ts +10 -0
  23. package/dist/YoutubeTimestamps.svelte +100 -0
  24. package/dist/YoutubeTimestamps.svelte.d.ts +11 -0
  25. package/dist/code-block/CodeBlock.svelte +67 -0
  26. package/dist/code-block/CodeBlock.svelte.d.ts +17 -0
  27. package/dist/code-block/CodeBlockContent.svelte +19 -0
  28. package/dist/code-block/CodeBlockContent.svelte.d.ts +8 -0
  29. package/dist/code-block/CodeBlockContext.svelte.d.ts +11 -0
  30. package/dist/code-block/CodeBlockContext.svelte.js +7 -0
  31. package/dist/code-block/CodeBlockCopyButton.svelte +19 -0
  32. package/dist/code-block/CodeBlockCopyButton.svelte.d.ts +8 -0
  33. package/dist/code-block/CodeBlockHeader.svelte +15 -0
  34. package/dist/code-block/CodeBlockHeader.svelte.d.ts +9 -0
  35. package/dist/code-block/CodeBlockTitle.svelte +15 -0
  36. package/dist/code-block/CodeBlockTitle.svelte.d.ts +9 -0
  37. package/dist/code-block/CodeRenderer.svelte +78 -0
  38. package/dist/code-block/CodeRenderer.svelte.d.ts +12 -0
  39. package/dist/code-block/LanguageTabsCodeBlock.svelte +119 -0
  40. package/dist/code-block/LanguageTabsCodeBlock.svelte.d.ts +12 -0
  41. package/dist/code-block/MultiFileCodeBlock.svelte +75 -0
  42. package/dist/code-block/MultiFileCodeBlock.svelte.d.ts +12 -0
  43. package/dist/code-block/index.d.ts +7 -0
  44. package/dist/code-block/index.js +8 -0
  45. package/dist/index.d.ts +15 -0
  46. package/dist/index.js +15 -0
  47. package/dist/questions/MultipleChoiceQuestion.svelte +167 -0
  48. package/dist/questions/MultipleChoiceQuestion.svelte.d.ts +19 -0
  49. package/dist/questions/NumericQuestion.svelte +139 -0
  50. package/dist/questions/NumericQuestion.svelte.d.ts +20 -0
  51. package/dist/questions/Quiz.svelte +119 -0
  52. package/dist/questions/Quiz.svelte.d.ts +11 -0
  53. package/dist/questions/SingleChoiceQuestion.svelte +141 -0
  54. package/dist/questions/SingleChoiceQuestion.svelte.d.ts +19 -0
  55. package/dist/questions/index.d.ts +4 -0
  56. package/dist/questions/index.js +5 -0
  57. package/dist/radio-group/RadioGroup.svelte +16 -0
  58. package/dist/radio-group/RadioGroup.svelte.d.ts +7 -0
  59. package/dist/radio-group/RadioGroupItem.svelte +26 -0
  60. package/dist/radio-group/RadioGroupItem.svelte.d.ts +7 -0
  61. package/dist/radio-group/index.d.ts +2 -0
  62. package/dist/radio-group/index.js +3 -0
  63. package/package.json +12 -3
@@ -0,0 +1,52 @@
1
+ <!-- libs/helix-svelte/src/Chart.svelte -->
2
+ <!-- Closely based on: diffbook Chart, rebuilt on TanStack Charts (shared definition with React),
3
+ mirrored from @cloudvoyant/helix-react -->
4
+ <script lang="ts">
5
+ import { Chart as TanStackChart } from '@tanstack/charts/svelte';
6
+ import { chartRootBase, cn, buildChartDefinition } from '@cloudvoyant/helix';
7
+ import type { HTMLAttributes } from 'svelte/elements';
8
+
9
+ type Props = {
10
+ type: 'line' | 'bar' | 'area' | 'pie';
11
+ data: Record<string, string | number>[];
12
+ series: { key: string; label?: string; color?: string }[];
13
+ xKey?: string;
14
+ nameKey?: string;
15
+ height?: number;
16
+ showLegend?: boolean;
17
+ showGrid?: boolean;
18
+ showAxis?: boolean;
19
+ /** Pre-rendered SVG markup (server/static path). */
20
+ svg?: string;
21
+ class?: string;
22
+ } & HTMLAttributes<HTMLDivElement>;
23
+
24
+ let {
25
+ type,
26
+ data,
27
+ series,
28
+ xKey = 'name',
29
+ nameKey = 'name',
30
+ height = 320,
31
+ showLegend = true,
32
+ showGrid = true,
33
+ showAxis = true,
34
+ svg = undefined,
35
+ class: className = '',
36
+ ...rest
37
+ }: Props = $props();
38
+
39
+ const definition = $derived(
40
+ buildChartDefinition({ type, data, series, xKey, nameKey, height, showLegend, showGrid, showAxis }),
41
+ );
42
+
43
+ const classes = $derived(cn(chartRootBase, className));
44
+ </script>
45
+
46
+ <div data-chart-state={svg !== undefined ? 'prerendered' : 'ready'} data-chart-type={type} class={classes} {...rest}>
47
+ {#if svg !== undefined}
48
+ <div class="flex w-full justify-center [&>svg]:max-w-full">{@html svg}</div>
49
+ {:else}
50
+ <TanStackChart definition={definition} {height} ariaLabel={type === 'pie' ? 'Pie chart' : 'Chart'} />
51
+ {/if}
52
+ </div>
@@ -0,0 +1,22 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ type Props = {
3
+ type: 'line' | 'bar' | 'area' | 'pie';
4
+ data: Record<string, string | number>[];
5
+ series: {
6
+ key: string;
7
+ label?: string;
8
+ color?: string;
9
+ }[];
10
+ xKey?: string;
11
+ nameKey?: string;
12
+ height?: number;
13
+ showLegend?: boolean;
14
+ showGrid?: boolean;
15
+ showAxis?: boolean;
16
+ /** Pre-rendered SVG markup (server/static path). */
17
+ svg?: string;
18
+ class?: string;
19
+ } & HTMLAttributes<HTMLDivElement>;
20
+ declare const Chart: import("svelte").Component<Props, {}, "">;
21
+ type Chart = ReturnType<typeof Chart>;
22
+ export default Chart;
@@ -0,0 +1,58 @@
1
+ <!-- libs/helix-svelte/src/CopyButton.svelte -->
2
+ <!-- Closely based on: Shark UI clipboard (@ark-ui/svelte/clipboard), mirrored from @cloudvoyant/helix-react -->
3
+ <script lang="ts">
4
+ import {
5
+ ClipboardRoot,
6
+ ClipboardTrigger,
7
+ ClipboardIndicator,
8
+ type ClipboardRootProps,
9
+ } from '@ark-ui/svelte/clipboard';
10
+ import { clipboardTriggerBase, cn } from '@cloudvoyant/helix';
11
+
12
+ type Props = Omit<ClipboardRootProps, 'value' | 'class'> & {
13
+ /** Text copied to the clipboard when clicked. */
14
+ value: string;
15
+ /** Accessible label for the trigger (default `Copy`). */
16
+ label?: string;
17
+ /** Extra classes for the trigger. */
18
+ class?: string;
19
+ };
20
+
21
+ let { value, label = 'Copy', class: className = '', ...rest }: Props = $props();
22
+
23
+ const classes = $derived(cn(clipboardTriggerBase, className));
24
+ </script>
25
+
26
+ <ClipboardRoot {value} {...rest}>
27
+ <ClipboardTrigger class={classes} aria-label={label}>
28
+ <ClipboardIndicator>
29
+ {#snippet copied()}
30
+ <svg
31
+ xmlns="http://www.w3.org/2000/svg"
32
+ viewBox="0 0 24 24"
33
+ fill="none"
34
+ stroke="currentColor"
35
+ stroke-width="2"
36
+ stroke-linecap="round"
37
+ stroke-linejoin="round"
38
+ aria-hidden="true"
39
+ >
40
+ <path d="M20 6 9 17l-5-5"></path>
41
+ </svg>
42
+ {/snippet}
43
+ <svg
44
+ xmlns="http://www.w3.org/2000/svg"
45
+ viewBox="0 0 24 24"
46
+ fill="none"
47
+ stroke="currentColor"
48
+ stroke-width="2"
49
+ stroke-linecap="round"
50
+ stroke-linejoin="round"
51
+ aria-hidden="true"
52
+ >
53
+ <rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect>
54
+ <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
55
+ </svg>
56
+ </ClipboardIndicator>
57
+ </ClipboardTrigger>
58
+ </ClipboardRoot>
@@ -0,0 +1,12 @@
1
+ import { type ClipboardRootProps } from '@ark-ui/svelte/clipboard';
2
+ type Props = Omit<ClipboardRootProps, 'value' | 'class'> & {
3
+ /** Text copied to the clipboard when clicked. */
4
+ value: string;
5
+ /** Accessible label for the trigger (default `Copy`). */
6
+ label?: string;
7
+ /** Extra classes for the trigger. */
8
+ class?: string;
9
+ };
10
+ declare const CopyButton: import("svelte").Component<Props, {}, "">;
11
+ type CopyButton = ReturnType<typeof CopyButton>;
12
+ export default CopyButton;
@@ -0,0 +1,32 @@
1
+ <!-- libs/helix-svelte/src/Figure.svelte -->
2
+ <!-- Closely based on: diffbook Figure (packages/diffbook-ui/src/components/Figure.tsx),
3
+ mirrored from @cloudvoyant/helix-react -->
4
+ <script lang="ts">
5
+ import { Ark } from '@ark-ui/svelte/factory';
6
+ import { figureRootBase, figureImageBase, figureCaptionBase, cn } from '@cloudvoyant/helix';
7
+ import type { HTMLAttributes } from 'svelte/elements';
8
+ import type { Snippet } from 'svelte';
9
+
10
+ type Props = {
11
+ src?: string;
12
+ alt?: string;
13
+ caption?: string;
14
+ /** A custom image element (e.g. `<img srcSet="…" sizes="…">`). When provided it replaces
15
+ * the default `<img>` built from `src`/`alt`. */
16
+ img?: Snippet;
17
+ class?: string;
18
+ } & HTMLAttributes<HTMLElement>;
19
+
20
+ let { src, alt, img, caption, class: className = '', ...rest }: Props = $props();
21
+
22
+ const classes = $derived(cn(figureRootBase, className));
23
+ </script>
24
+
25
+ <Ark as="figure" class={classes} {...rest}>
26
+ {#if img}
27
+ {@render img()}
28
+ {:else if src}
29
+ <Ark as="img" {src} {alt} loading="lazy" class={figureImageBase} />
30
+ {/if}
31
+ {#if caption}<Ark as="figcaption" class={figureCaptionBase}>{caption}</Ark>{/if}
32
+ </Ark>
@@ -0,0 +1,14 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { Snippet } from 'svelte';
3
+ type Props = {
4
+ src?: string;
5
+ alt?: string;
6
+ caption?: string;
7
+ /** A custom image element (e.g. `<img srcSet="…" sizes="…">`). When provided it replaces
8
+ * the default `<img>` built from `src`/`alt`. */
9
+ img?: Snippet;
10
+ class?: string;
11
+ } & HTMLAttributes<HTMLElement>;
12
+ declare const Figure: import("svelte").Component<Props, {}, "">;
13
+ type Figure = ReturnType<typeof Figure>;
14
+ export default Figure;
@@ -0,0 +1,34 @@
1
+ <!-- libs/helix-svelte/src/InlineLaTeX.svelte -->
2
+ <!-- Inline LaTeX equation (displayMode: false), mirrored from @cloudvoyant/helix-react -->
3
+ <script lang="ts">
4
+ import { Ark } from '@ark-ui/svelte/factory';
5
+ import { latexRootBase, latexInlineBase, latexErrorBase, toLaTeX, cn } from '@cloudvoyant/helix';
6
+ import type { HTMLAttributes } from 'svelte/elements';
7
+
8
+ type Props = {
9
+ latex: string;
10
+ html?: string;
11
+ class?: string;
12
+ } & HTMLAttributes<HTMLSpanElement>;
13
+
14
+ let { latex, html = undefined, class: className = '', ...rest }: Props = $props();
15
+
16
+ let markup = $derived.by(() => {
17
+ if (html !== undefined) return html;
18
+ try {
19
+ return toLaTeX(latex);
20
+ } catch {
21
+ return latex;
22
+ }
23
+ });
24
+
25
+ const classes = $derived(cn(latexRootBase, latexInlineBase, className));
26
+ </script>
27
+
28
+ <Ark as="span" {...rest} data-latex-state="done" class={classes}>
29
+ {#if markup === latex && html === undefined}
30
+ <code class={latexErrorBase}>{latex}</code>
31
+ {:else}
32
+ <span>{@html markup}</span>
33
+ {/if}
34
+ </Ark>
@@ -0,0 +1,9 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ type Props = {
3
+ latex: string;
4
+ html?: string;
5
+ class?: string;
6
+ } & HTMLAttributes<HTMLSpanElement>;
7
+ declare const InlineLaTeX: import("svelte").Component<Props, {}, "">;
8
+ type InlineLaTeX = ReturnType<typeof InlineLaTeX>;
9
+ export default InlineLaTeX;
@@ -0,0 +1,34 @@
1
+ <!-- libs/helix-svelte/src/LaTeX.svelte -->
2
+ <!-- Closely based on: diffbook's KaTeX pipeline; block component, mirrored from @cloudvoyant/helix-react -->
3
+ <script lang="ts">
4
+ import { Ark } from '@ark-ui/svelte/factory';
5
+ import { latexRootBase, latexDisplayBase, latexErrorBase, toLaTeX, cn } from '@cloudvoyant/helix';
6
+ import type { HTMLAttributes } from 'svelte/elements';
7
+
8
+ type Props = {
9
+ latex: string;
10
+ html?: string;
11
+ class?: string;
12
+ } & HTMLAttributes<HTMLDivElement>;
13
+
14
+ let { latex, html = undefined, class: className = '', ...rest }: Props = $props();
15
+
16
+ let markup = $derived.by(() => {
17
+ if (html !== undefined) return html;
18
+ try {
19
+ return toLaTeX(latex, { displayMode: true });
20
+ } catch {
21
+ return latex;
22
+ }
23
+ });
24
+
25
+ const classes = $derived(cn(latexRootBase, latexDisplayBase, className));
26
+ </script>
27
+
28
+ <Ark as="div" {...rest} data-latex-state="done" class={classes}>
29
+ {#if markup === latex && html === undefined}
30
+ <code class={latexErrorBase}>{latex}</code>
31
+ {:else}
32
+ <span>{@html markup}</span>
33
+ {/if}
34
+ </Ark>
@@ -0,0 +1,9 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ type Props = {
3
+ latex: string;
4
+ html?: string;
5
+ class?: string;
6
+ } & HTMLAttributes<HTMLDivElement>;
7
+ declare const LaTeX: import("svelte").Component<Props, {}, "">;
8
+ type LaTeX = ReturnType<typeof LaTeX>;
9
+ export default LaTeX;
@@ -0,0 +1,119 @@
1
+ <!-- libs/helix-svelte/src/Manim.svelte -->
2
+ <!-- Closely based on: diffbook Manim, rebuilt with the scene builder as a prop (client-only),
3
+ mirrored from @cloudvoyant/helix-react -->
4
+ <script lang="ts">
5
+ import { Ark } from '@ark-ui/svelte/factory';
6
+ import {
7
+ manimRootBase,
8
+ manimContainerBase,
9
+ manimPlaceholderBase,
10
+ manimPlaceholderLabelBase,
11
+ manimErrorBase,
12
+ manimCaptionBase,
13
+ cn,
14
+ } from '@cloudvoyant/helix';
15
+ import type { ManimRecordingScene, ManimModule } from '@cloudvoyant/helix';
16
+ import type { HTMLAttributes } from 'svelte/elements';
17
+
18
+ type Status = 'loading' | 'ready' | 'error';
19
+
20
+ interface ManimPlayerLike {
21
+ sequence(builder: (scene: ManimRecordingScene) => Promise<void>): Promise<void>;
22
+ dispose?(): void;
23
+ }
24
+
25
+ type Props = {
26
+ build: (manim: ManimModule, scene: ManimRecordingScene) => Promise<void> | void;
27
+ width?: number;
28
+ height?: number;
29
+ caption?: string;
30
+ class?: string;
31
+ } & HTMLAttributes<HTMLElement>;
32
+
33
+ let {
34
+ build,
35
+ width = 800,
36
+ height = 450,
37
+ caption,
38
+ class: className = '',
39
+ ...rest
40
+ }: Props = $props();
41
+
42
+ let wrapper: HTMLDivElement;
43
+ let container: HTMLDivElement;
44
+ let status: Status = $state('loading');
45
+ let errorMsg: string = $state('');
46
+
47
+ $effect(() => {
48
+ const w = wrapper;
49
+ if (!w) return;
50
+ let disposed = false;
51
+ let player: ManimPlayerLike | null = null;
52
+ let resizeTimer: ReturnType<typeof setTimeout> | undefined;
53
+ let mountedWidth = 0;
54
+ let generation = 0;
55
+
56
+ async function mount(pixelWidth: number): Promise<void> {
57
+ const gen = ++generation;
58
+ try {
59
+ const manim: ManimModule = await import('manim-web');
60
+ if (disposed || gen !== generation || !container) return;
61
+ player?.dispose?.();
62
+ container.replaceChildren();
63
+ mountedWidth = pixelWidth;
64
+ player = new manim.Player(container, {
65
+ width: pixelWidth,
66
+ height: Math.round((pixelWidth * height) / width),
67
+ backgroundOpacity: 0,
68
+ autoPlay: true,
69
+ loop: false,
70
+ }) as unknown as ManimPlayerLike;
71
+ status = 'ready';
72
+ const current = player;
73
+ await current.sequence(async (scene) => {
74
+ await build(manim, scene);
75
+ });
76
+ } catch (err) {
77
+ if (gen === generation) {
78
+ errorMsg = `Failed to load animation: ${err instanceof Error ? err.message : String(err)}`;
79
+ status = 'error';
80
+ }
81
+ }
82
+ }
83
+
84
+ const initialWidth = Math.floor(w.getBoundingClientRect().width);
85
+ if (initialWidth > 0) void mount(initialWidth);
86
+
87
+ const observer = new ResizeObserver((entries) => {
88
+ const measured = Math.floor(entries[0]?.contentRect.width ?? 0);
89
+ if (measured <= 0 || measured === mountedWidth) return;
90
+ clearTimeout(resizeTimer);
91
+ resizeTimer = setTimeout(() => {
92
+ if (!disposed) void mount(measured);
93
+ }, 200);
94
+ });
95
+ observer.observe(w);
96
+
97
+ return () => {
98
+ disposed = true;
99
+ clearTimeout(resizeTimer);
100
+ observer.disconnect();
101
+ player?.dispose?.();
102
+ };
103
+ });
104
+
105
+ const classes = $derived(cn(manimRootBase, className));
106
+ </script>
107
+
108
+ <Ark as="figure" data-manim-state={status} class={classes} {...rest}>
109
+ <div bind:this={wrapper} class={manimContainerBase}>
110
+ <div bind:this={container} class="w-full"></div>
111
+ {#if status === 'loading'}
112
+ <div class={manimPlaceholderBase} style={`aspect-ratio: ${width} / ${height};`}>
113
+ <span class={manimPlaceholderLabelBase}>Loading animation…</span>
114
+ </div>
115
+ {/if}
116
+ {#if status === 'error'}<div class={manimErrorBase}>{errorMsg}</div>{/if}
117
+ </div>
118
+ {#if caption}<Ark as="figcaption" class={manimCaptionBase}>{caption}</Ark>{/if}
119
+ </Ark>
@@ -0,0 +1,12 @@
1
+ import type { ManimRecordingScene, ManimModule } from '@cloudvoyant/helix';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type Props = {
4
+ build: (manim: ManimModule, scene: ManimRecordingScene) => Promise<void> | void;
5
+ width?: number;
6
+ height?: number;
7
+ caption?: string;
8
+ class?: string;
9
+ } & HTMLAttributes<HTMLElement>;
10
+ declare const Manim: import("svelte").Component<Props, {}, "">;
11
+ type Manim = ReturnType<typeof Manim>;
12
+ export default Manim;
@@ -0,0 +1,87 @@
1
+ <!-- libs/helix-svelte/src/Notice.svelte -->
2
+ <!-- Closely based on: diffbook Notice (packages/diffbook-ui/src/components/Notice.tsx + ui/alert.tsx),
3
+ mirrored from @cloudvoyant/helix-react -->
4
+ <script lang="ts">
5
+ import { Ark } from '@ark-ui/svelte/factory';
6
+ import { noticeVariants, noticeTitleBase, noticeDescriptionBase, cn } from '@cloudvoyant/helix';
7
+ import type { HTMLAttributes } from 'svelte/elements';
8
+ import type { Snippet } from 'svelte';
9
+
10
+ type Variant = 'info' | 'success' | 'warning' | 'error' | 'none';
11
+
12
+ type Props = {
13
+ variant?: Variant;
14
+ title?: string;
15
+ children?: Snippet;
16
+ class?: string;
17
+ } & HTMLAttributes<HTMLDivElement>;
18
+
19
+ let { variant = 'info', title, children, class: className = '', ...rest }: Props = $props();
20
+
21
+ const classes = $derived(cn(noticeVariants({ variant }), className));
22
+ </script>
23
+
24
+ <Ark as="div" role={variant === 'error' ? 'alert' : variant === 'none' ? undefined : 'status'} class={classes} {...rest}>
25
+ {#if variant === 'success'}
26
+ <svg
27
+ xmlns="http://www.w3.org/2000/svg"
28
+ viewBox="0 0 24 24"
29
+ fill="none"
30
+ stroke="currentColor"
31
+ stroke-width="2"
32
+ stroke-linecap="round"
33
+ stroke-linejoin="round"
34
+ aria-hidden="true"
35
+ >
36
+ <circle cx="12" cy="12" r="10"></circle>
37
+ <path d="m9 12 2 2 4-4"></path>
38
+ </svg>
39
+ {:else if variant === 'warning'}
40
+ <svg
41
+ xmlns="http://www.w3.org/2000/svg"
42
+ viewBox="0 0 24 24"
43
+ fill="none"
44
+ stroke="currentColor"
45
+ stroke-width="2"
46
+ stroke-linecap="round"
47
+ stroke-linejoin="round"
48
+ aria-hidden="true"
49
+ >
50
+ <path d="m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"></path>
51
+ <path d="M12 9v4"></path>
52
+ <path d="M12 17h.01"></path>
53
+ </svg>
54
+ {:else if variant === 'error'}
55
+ <svg
56
+ xmlns="http://www.w3.org/2000/svg"
57
+ viewBox="0 0 24 24"
58
+ fill="none"
59
+ stroke="currentColor"
60
+ stroke-width="2"
61
+ stroke-linecap="round"
62
+ stroke-linejoin="round"
63
+ aria-hidden="true"
64
+ >
65
+ <circle cx="12" cy="12" r="10"></circle>
66
+ <path d="m15 9-6 6"></path>
67
+ <path d="m9 9 6 6"></path>
68
+ </svg>
69
+ {:else if variant === 'info'}
70
+ <svg
71
+ xmlns="http://www.w3.org/2000/svg"
72
+ viewBox="0 0 24 24"
73
+ fill="none"
74
+ stroke="currentColor"
75
+ stroke-width="2"
76
+ stroke-linecap="round"
77
+ stroke-linejoin="round"
78
+ aria-hidden="true"
79
+ >
80
+ <circle cx="12" cy="12" r="10"></circle>
81
+ <path d="M12 16v-4"></path>
82
+ <path d="M12 8h.01"></path>
83
+ </svg>
84
+ {/if}
85
+ {#if title}<div class={noticeTitleBase}>{title}</div>{/if}
86
+ {#if children}<div class={noticeDescriptionBase}>{@render children()}</div>{/if}
87
+ </Ark>
@@ -0,0 +1,12 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { Snippet } from 'svelte';
3
+ type Variant = 'info' | 'success' | 'warning' | 'error' | 'none';
4
+ type Props = {
5
+ variant?: Variant;
6
+ title?: string;
7
+ children?: Snippet;
8
+ class?: string;
9
+ } & HTMLAttributes<HTMLDivElement>;
10
+ declare const Notice: import("svelte").Component<Props, {}, "">;
11
+ type Notice = ReturnType<typeof Notice>;
12
+ export default Notice;
@@ -0,0 +1,47 @@
1
+ <!-- libs/helix-svelte/src/PrevNext.svelte -->
2
+ <!-- Closely based on: diffbook PrevNext (packages/diffbook-ui/src/components/PrevNext.tsx),
3
+ mirrored from @cloudvoyant/helix-react -->
4
+ <script lang="ts">
5
+ import { Ark } from '@ark-ui/svelte/factory';
6
+ import {
7
+ prevNextRootBase,
8
+ prevNextLinkBase,
9
+ prevNextLinkNextBase,
10
+ prevNextDirectionBase,
11
+ prevNextTitleBase,
12
+ prevNextSpacerBase,
13
+ cn,
14
+ } from '@cloudvoyant/helix';
15
+ import type { HTMLAttributes } from 'svelte/elements';
16
+
17
+ type Props = {
18
+ prev?: { title: string; href: string };
19
+ next?: { title: string; href: string };
20
+ class?: string;
21
+ } & HTMLAttributes<HTMLElement>;
22
+
23
+ let { prev, next, class: className = '', ...rest }: Props = $props();
24
+
25
+ const classes = $derived(cn(prevNextRootBase, className));
26
+ </script>
27
+
28
+ {#if prev || next}
29
+ <Ark as="nav" class={classes} aria-label="Previous and next pages" {...rest}>
30
+ {#if prev}
31
+ <Ark as="a" href={prev.href} class={prevNextLinkBase}>
32
+ <Ark as="span" class={prevNextDirectionBase}>Previous</Ark>
33
+ <Ark as="span" class={prevNextTitleBase}>← {prev.title}</Ark>
34
+ </Ark>
35
+ {:else}
36
+ <Ark as="span" class={prevNextSpacerBase}></Ark>
37
+ {/if}
38
+ {#if next}
39
+ <Ark as="a" href={next.href} class={cn(prevNextLinkBase, prevNextLinkNextBase)}>
40
+ <Ark as="span" class={prevNextDirectionBase}>Next</Ark>
41
+ <Ark as="span" class={prevNextTitleBase}>{next.title} →</Ark>
42
+ </Ark>
43
+ {:else}
44
+ <Ark as="span" class={prevNextSpacerBase}></Ark>
45
+ {/if}
46
+ </Ark>
47
+ {/if}
@@ -0,0 +1,15 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ type Props = {
3
+ prev?: {
4
+ title: string;
5
+ href: string;
6
+ };
7
+ next?: {
8
+ title: string;
9
+ href: string;
10
+ };
11
+ class?: string;
12
+ } & HTMLAttributes<HTMLElement>;
13
+ declare const PrevNext: import("svelte").Component<Props, {}, "">;
14
+ type PrevNext = ReturnType<typeof PrevNext>;
15
+ export default PrevNext;
@@ -0,0 +1,40 @@
1
+ <!-- libs/helix-svelte/src/Reveal.svelte -->
2
+ <!-- Closely based on: diffbook QA (packages/diffbook-ui/src/components/QA.tsx), renamed Reveal,
3
+ rebuilt on Ark UI Collapsible, mirrored from @cloudvoyant/helix-react -->
4
+ <script lang="ts">
5
+ import { CollapsibleRoot, CollapsibleTrigger, CollapsibleContent } from '@ark-ui/svelte/collapsible';
6
+ import { revealRootBase, revealTriggerBase, revealChevronBase, revealContentBase, cn } from '@cloudvoyant/helix';
7
+ import type { Snippet } from 'svelte';
8
+
9
+ type Props = {
10
+ question: string;
11
+ children?: Snippet;
12
+ class?: string;
13
+ };
14
+
15
+ let { question, children, class: className = '' }: Props = $props();
16
+
17
+ const classes = $derived(cn(revealRootBase, className));
18
+ </script>
19
+
20
+ <CollapsibleRoot class={classes}>
21
+ <CollapsibleTrigger class={revealTriggerBase}>
22
+ <svg
23
+ class={revealChevronBase}
24
+ xmlns="http://www.w3.org/2000/svg"
25
+ viewBox="0 0 24 24"
26
+ fill="none"
27
+ stroke="currentColor"
28
+ stroke-width="2"
29
+ stroke-linecap="round"
30
+ stroke-linejoin="round"
31
+ aria-hidden="true"
32
+ >
33
+ <path d="m9 18 6-6-6-6"></path>
34
+ </svg>
35
+ <span>{question}</span>
36
+ </CollapsibleTrigger>
37
+ <CollapsibleContent class={revealContentBase}>
38
+ {#if children}{@render children()}{/if}
39
+ </CollapsibleContent>
40
+ </CollapsibleRoot>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from 'svelte';
2
+ type Props = {
3
+ question: string;
4
+ children?: Snippet;
5
+ class?: string;
6
+ };
7
+ declare const Reveal: import("svelte").Component<Props, {}, "">;
8
+ type Reveal = ReturnType<typeof Reveal>;
9
+ export default Reveal;