@hyvnt/hyvui 0.2.0 → 0.3.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 (86) hide show
  1. package/README.md +264 -253
  2. package/dist/components/ambient/CornerBrackets.svelte +83 -87
  3. package/dist/components/ambient/DataStream.svelte +111 -94
  4. package/dist/components/ambient/GlyphMark.svelte +69 -69
  5. package/dist/components/ambient/GridOverlay.svelte +26 -28
  6. package/dist/components/ambient/ParallaxLayer.svelte +37 -41
  7. package/dist/components/ambient/ScanBand.svelte +95 -91
  8. package/dist/components/ambient/SignalRing.svelte +100 -100
  9. package/dist/components/ambient/ThreadLine.svelte +71 -78
  10. package/dist/components/ambient/Vignette.svelte +24 -26
  11. package/dist/components/depth/DepthLayer.svelte +22 -27
  12. package/dist/components/depth/DepthStage.svelte +63 -62
  13. package/dist/components/depth/FloatCard.svelte +113 -104
  14. package/dist/components/depth/HorizonGrid.svelte +216 -160
  15. package/dist/components/depth/Plinth.svelte +52 -57
  16. package/dist/components/display/Avatar.svelte +64 -69
  17. package/dist/components/display/Badge.svelte +59 -63
  18. package/dist/components/display/Blockquote.svelte +31 -34
  19. package/dist/components/display/CodeBlock.svelte +71 -76
  20. package/dist/components/display/MetricCard.svelte +77 -83
  21. package/dist/components/display/Table.svelte +99 -104
  22. package/dist/components/feedback/Alert.svelte +71 -76
  23. package/dist/components/feedback/EmptyState.svelte +68 -68
  24. package/dist/components/feedback/ErrorState.svelte +73 -73
  25. package/dist/components/feedback/Skeleton.svelte +52 -52
  26. package/dist/components/feedback/StatusDot.svelte +49 -54
  27. package/dist/components/feedback/StatusLine.svelte +122 -122
  28. package/dist/components/feedback/Toast.svelte +130 -136
  29. package/dist/components/inputs/Button.svelte +240 -237
  30. package/dist/components/inputs/Checkbox.svelte +104 -105
  31. package/dist/components/inputs/FileUpload.svelte +165 -163
  32. package/dist/components/inputs/Input.svelte +145 -147
  33. package/dist/components/inputs/Select.svelte +156 -150
  34. package/dist/components/inputs/Textarea.svelte +153 -154
  35. package/dist/components/inputs/Toggle.svelte +120 -120
  36. package/dist/components/layout/Card.svelte +70 -76
  37. package/dist/components/layout/Drawer.svelte +133 -109
  38. package/dist/components/layout/Grid.svelte +118 -43
  39. package/dist/components/layout/Grid.svelte.d.ts +8 -2
  40. package/dist/components/layout/Modal.svelte +176 -159
  41. package/dist/components/layout/Panel.svelte +49 -54
  42. package/dist/components/layout/Popover.svelte +178 -67
  43. package/dist/components/layout/Popover.svelte.d.ts +10 -1
  44. package/dist/components/layout/Stack.svelte +53 -53
  45. package/dist/components/navigation/Breadcrumb.svelte +70 -73
  46. package/dist/components/navigation/DropdownMenu.svelte +167 -124
  47. package/dist/components/navigation/DropdownMenu.svelte.d.ts +12 -2
  48. package/dist/components/navigation/SidebarNav.svelte +86 -90
  49. package/dist/components/navigation/Tabs.svelte +81 -86
  50. package/dist/components/navigation/Topbar.svelte +85 -85
  51. package/dist/components/patterns/ActionBar.svelte +71 -76
  52. package/dist/components/patterns/ConfirmDialog.svelte +63 -64
  53. package/dist/components/patterns/PageHeader.svelte +109 -114
  54. package/dist/components/patterns/SearchBar.svelte +54 -59
  55. package/dist/components/patterns/TerminalBoot.svelte +104 -104
  56. package/dist/components/primitives/Divider.svelte +26 -29
  57. package/dist/components/primitives/Icon.svelte +44 -49
  58. package/dist/components/primitives/Label.svelte +39 -44
  59. package/dist/components/primitives/Surface.svelte +89 -87
  60. package/dist/components/primitives/Text.svelte +98 -98
  61. package/dist/components/scenes/ArchiveScene.svelte +92 -95
  62. package/dist/components/scenes/ArchiveScene.svelte.d.ts +7 -1
  63. package/dist/components/scenes/LogScene.svelte +72 -77
  64. package/dist/components/scenes/NarrativeScene.svelte +91 -92
  65. package/dist/components/scenes/ReadoutScene.svelte +120 -107
  66. package/dist/components/scenes/ReadoutScene.svelte.d.ts +3 -1
  67. package/dist/components/scenes/StageScene.svelte +97 -104
  68. package/dist/examples/FieldReport.svelte +226 -223
  69. package/dist/examples/ObservationDeck.svelte +333 -317
  70. package/dist/examples/SignalLost.svelte +191 -191
  71. package/dist/styles.css +113 -0
  72. package/dist/system/actions/echo.js +9 -9
  73. package/dist/system/actions/resolve.js +9 -9
  74. package/dist/system/actions/reveal.js +1 -1
  75. package/dist/system/actions/surface.js +13 -1
  76. package/dist/system/depth/depth.css +49 -49
  77. package/dist/system/depth/depth.js +1 -1
  78. package/dist/system/expressions.css +80 -80
  79. package/dist/system/override-template.css +72 -72
  80. package/dist/system/register.css +74 -74
  81. package/dist/system/scroll-lock.d.ts +6 -0
  82. package/dist/system/scroll-lock.js +23 -0
  83. package/dist/tokens/tokens.css +100 -86
  84. package/dist/tokens/tokens.js +4 -4
  85. package/dist/utils/motion.js +1 -1
  86. package/package.json +67 -60
@@ -1,87 +1,83 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
-
4
- interface Props {
5
- /** Bracket arm length in pixels. */
6
- size?: number;
7
- /** Bracket color. */
8
- color?: string;
9
- /** Additional CSS classes. */
10
- class?: string;
11
- }
12
-
13
- let {
14
- size = 32,
15
- color = 'rgba(199, 156, 87, 0.24)',
16
- class: className = '',
17
- }: Props = $props();
18
- </script>
19
-
20
- <div class={cn('hyvui-corners', className)} aria-hidden="true">
21
- <span
22
- class="hyvui-corner hyvui-corner-tl"
23
- style:width="{size}px"
24
- style:height="{size}px"
25
- style:border-color={color}
26
- ></span>
27
- <span
28
- class="hyvui-corner hyvui-corner-tr"
29
- style:width="{size}px"
30
- style:height="{size}px"
31
- style:border-color={color}
32
- ></span>
33
- <span
34
- class="hyvui-corner hyvui-corner-bl"
35
- style:width="{size}px"
36
- style:height="{size}px"
37
- style:border-color={color}
38
- ></span>
39
- <span
40
- class="hyvui-corner hyvui-corner-br"
41
- style:width="{size}px"
42
- style:height="{size}px"
43
- style:border-color={color}
44
- ></span>
45
- </div>
46
-
47
- <style>
48
- .hyvui-corners {
49
- position: absolute;
50
- inset: 0;
51
- pointer-events: none;
52
- }
53
-
54
- .hyvui-corner {
55
- position: absolute;
56
- border-style: solid;
57
- border-width: 0;
58
- }
59
-
60
- .hyvui-corner-tl {
61
- top: 0;
62
- left: 0;
63
- border-top-width: 1px;
64
- border-left-width: 1px;
65
- }
66
-
67
- .hyvui-corner-tr {
68
- top: 0;
69
- right: 0;
70
- border-top-width: 1px;
71
- border-right-width: 1px;
72
- }
73
-
74
- .hyvui-corner-bl {
75
- bottom: 0;
76
- left: 0;
77
- border-bottom-width: 1px;
78
- border-left-width: 1px;
79
- }
80
-
81
- .hyvui-corner-br {
82
- bottom: 0;
83
- right: 0;
84
- border-bottom-width: 1px;
85
- border-right-width: 1px;
86
- }
87
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+
4
+ interface Props {
5
+ /** Bracket arm length in pixels. */
6
+ size?: number;
7
+ /** Bracket color. */
8
+ color?: string;
9
+ /** Additional CSS classes. */
10
+ class?: string;
11
+ }
12
+
13
+ let { size = 32, color = 'rgba(199, 156, 87, 0.24)', class: className = '' }: Props = $props();
14
+ </script>
15
+
16
+ <div class={cn('hyvui-corners', className)} aria-hidden="true">
17
+ <span
18
+ class="hyvui-corner hyvui-corner-tl"
19
+ style:width="{size}px"
20
+ style:height="{size}px"
21
+ style:border-color={color}
22
+ ></span>
23
+ <span
24
+ class="hyvui-corner hyvui-corner-tr"
25
+ style:width="{size}px"
26
+ style:height="{size}px"
27
+ style:border-color={color}
28
+ ></span>
29
+ <span
30
+ class="hyvui-corner hyvui-corner-bl"
31
+ style:width="{size}px"
32
+ style:height="{size}px"
33
+ style:border-color={color}
34
+ ></span>
35
+ <span
36
+ class="hyvui-corner hyvui-corner-br"
37
+ style:width="{size}px"
38
+ style:height="{size}px"
39
+ style:border-color={color}
40
+ ></span>
41
+ </div>
42
+
43
+ <style>
44
+ .hyvui-corners {
45
+ position: absolute;
46
+ inset: 0;
47
+ pointer-events: none;
48
+ }
49
+
50
+ .hyvui-corner {
51
+ position: absolute;
52
+ border-style: solid;
53
+ border-width: 0;
54
+ }
55
+
56
+ .hyvui-corner-tl {
57
+ top: 0;
58
+ left: 0;
59
+ border-top-width: 1px;
60
+ border-left-width: 1px;
61
+ }
62
+
63
+ .hyvui-corner-tr {
64
+ top: 0;
65
+ right: 0;
66
+ border-top-width: 1px;
67
+ border-right-width: 1px;
68
+ }
69
+
70
+ .hyvui-corner-bl {
71
+ bottom: 0;
72
+ left: 0;
73
+ border-bottom-width: 1px;
74
+ border-left-width: 1px;
75
+ }
76
+
77
+ .hyvui-corner-br {
78
+ bottom: 0;
79
+ right: 0;
80
+ border-bottom-width: 1px;
81
+ border-right-width: 1px;
82
+ }
83
+ </style>
@@ -1,94 +1,111 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
- import { onMount } from 'svelte';
4
-
5
- interface Props {
6
- /** Enable the scrolling animation. */
7
- active?: boolean;
8
- /** Width of the stream column. */
9
- width?: string;
10
- /** Scroll speed. */
11
- speed?: 'slow' | 'medium';
12
- /** Additional CSS classes. */
13
- class?: string;
14
- }
15
-
16
- let {
17
- active = true,
18
- width = '1.2rem',
19
- speed = 'slow',
20
- class: className = '',
21
- }: Props = $props();
22
-
23
- const chars = '0123456789ABCDEF.:+-';
24
- const lineCount = 32;
25
- let lines = $state<string[]>([]);
26
- let intervalId: ReturnType<typeof setInterval> | undefined;
27
-
28
- const prefersReduced =
29
- typeof window !== 'undefined'
30
- ? window.matchMedia('(prefers-reduced-motion: reduce)').matches
31
- : false;
32
-
33
- function randomChar(): string {
34
- return chars[Math.floor(Math.random() * chars.length)];
35
- }
36
-
37
- function generateLines(): string[] {
38
- return Array.from({ length: lineCount }, () => randomChar());
39
- }
40
-
41
- onMount(() => {
42
- lines = generateLines();
43
-
44
- if (active && !prefersReduced) {
45
- const ms = speed === 'slow' ? 600 : 350;
46
- intervalId = setInterval(() => {
47
- lines = [randomChar(), ...lines.slice(0, lineCount - 1)];
48
- }, ms);
49
- }
50
-
51
- return () => {
52
- if (intervalId) clearInterval(intervalId);
53
- };
54
- });
55
- </script>
56
-
57
- <div
58
- class={cn('hyvui-data-stream', className)}
59
- style:width={width}
60
- aria-hidden="true"
61
- >
62
- {#each lines as char, i}
63
- <span
64
- class="hyvui-data-stream-char"
65
- style:opacity={0.18 - (i / lineCount) * 0.14}
66
- >{char}</span>
67
- {/each}
68
- </div>
69
-
70
- <style>
71
- .hyvui-data-stream {
72
- display: flex;
73
- flex-direction: column;
74
- align-items: center;
75
- font-family: var(--font-mono);
76
- font-size: 0.6rem;
77
- line-height: 1.4;
78
- letter-spacing: 0.1em;
79
- color: var(--accent);
80
- pointer-events: none;
81
- overflow: hidden;
82
- }
83
-
84
- .hyvui-data-stream-char {
85
- display: block;
86
- transition: opacity 0.3s ease-out;
87
- }
88
-
89
- @media (prefers-reduced-motion: reduce) {
90
- .hyvui-data-stream-char {
91
- transition: none;
92
- }
93
- }
94
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+ import { onMount } from 'svelte';
4
+
5
+ interface Props {
6
+ /** Enable the scrolling animation. */
7
+ active?: boolean;
8
+ /** Width of the stream column. */
9
+ width?: string;
10
+ /** Scroll speed. */
11
+ speed?: 'slow' | 'medium';
12
+ /** Additional CSS classes. */
13
+ class?: string;
14
+ }
15
+
16
+ let { active = true, width = '1.2rem', speed = 'slow', class: className = '' }: Props = $props();
17
+
18
+ const chars = '0123456789ABCDEF.:+-';
19
+ const lineCount = 32;
20
+ let rootEl: HTMLDivElement | undefined = $state();
21
+ let visible = $state(true);
22
+ let lines = $state<string[]>([]);
23
+ let intervalId: ReturnType<typeof setInterval> | undefined;
24
+
25
+ const prefersReduced =
26
+ typeof window !== 'undefined'
27
+ ? window.matchMedia('(prefers-reduced-motion: reduce)').matches
28
+ : false;
29
+
30
+ function randomChar(): string {
31
+ return chars[Math.floor(Math.random() * chars.length)];
32
+ }
33
+
34
+ function generateLines(): string[] {
35
+ return Array.from({ length: lineCount }, () => randomChar());
36
+ }
37
+
38
+ function stop() {
39
+ if (!intervalId) return;
40
+ clearInterval(intervalId);
41
+ intervalId = undefined;
42
+ }
43
+
44
+ function start() {
45
+ stop();
46
+ if (!active || prefersReduced || !visible) return;
47
+ const ms = speed === 'slow' ? 600 : 350;
48
+ intervalId = setInterval(() => {
49
+ // Unkeyed each blocks update in-place, so this is stable DOM churn.
50
+ lines = [randomChar(), ...lines.slice(0, lineCount - 1)];
51
+ }, ms);
52
+ }
53
+
54
+ onMount(() => {
55
+ lines = generateLines();
56
+
57
+ const io = new IntersectionObserver(
58
+ (entries) => {
59
+ const entry = entries[0];
60
+ if (!entry) return;
61
+ visible = entry.isIntersecting;
62
+ },
63
+ { root: null, threshold: 0 }
64
+ );
65
+
66
+ if (rootEl) io.observe(rootEl);
67
+
68
+ return () => {
69
+ io.disconnect();
70
+ stop();
71
+ };
72
+ });
73
+
74
+ $effect(() => {
75
+ // Restart interval when relevant inputs change.
76
+ start();
77
+ return stop;
78
+ });
79
+ </script>
80
+
81
+ <div bind:this={rootEl} class={cn('hyvui-data-stream', className)} style:width aria-hidden="true">
82
+ {#each lines as char, i}
83
+ <span class="hyvui-data-stream-char" style:opacity={0.18 - (i / lineCount) * 0.14}>{char}</span>
84
+ {/each}
85
+ </div>
86
+
87
+ <style>
88
+ .hyvui-data-stream {
89
+ display: flex;
90
+ flex-direction: column;
91
+ align-items: center;
92
+ font-family: var(--font-mono);
93
+ font-size: 0.6rem;
94
+ line-height: 1.4;
95
+ letter-spacing: 0.1em;
96
+ color: var(--accent);
97
+ pointer-events: none;
98
+ overflow: hidden;
99
+ }
100
+
101
+ .hyvui-data-stream-char {
102
+ display: block;
103
+ transition: opacity 0.3s ease-out;
104
+ }
105
+
106
+ @media (prefers-reduced-motion: reduce) {
107
+ .hyvui-data-stream-char {
108
+ transition: none;
109
+ }
110
+ }
111
+ </style>
@@ -1,69 +1,69 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
-
4
- interface Props {
5
- /** Glyph variant. */
6
- variant?: 'cross' | 'reticle' | 'coord' | 'mark';
7
- /** Size in pixels. */
8
- size?: number;
9
- /** Glyph color. */
10
- color?: string;
11
- /** Additional CSS classes. */
12
- class?: string;
13
- }
14
-
15
- let {
16
- variant = 'cross',
17
- size = 24,
18
- color = 'var(--muted-strong)',
19
- class: className = '',
20
- }: Props = $props();
21
- </script>
22
-
23
- <svg
24
- class={cn('hyvui-glyph-mark', className)}
25
- width={size}
26
- height={size}
27
- viewBox="0 0 24 24"
28
- fill="none"
29
- stroke={color}
30
- stroke-width="1"
31
- aria-hidden="true"
32
- >
33
- {#if variant === 'cross'}
34
- <!-- coordinate cross -->
35
- <line x1="12" y1="4" x2="12" y2="20" />
36
- <line x1="4" y1="12" x2="20" y2="12" />
37
- <circle cx="12" cy="12" r="1.5" fill={color} stroke="none" />
38
- {:else if variant === 'reticle'}
39
- <!-- targeting reticle -->
40
- <circle cx="12" cy="12" r="8" />
41
- <circle cx="12" cy="12" r="3" />
42
- <line x1="12" y1="1" x2="12" y2="5" />
43
- <line x1="12" y1="19" x2="12" y2="23" />
44
- <line x1="1" y1="12" x2="5" y2="12" />
45
- <line x1="19" y1="12" x2="23" y2="12" />
46
- {:else if variant === 'coord'}
47
- <!-- cartographic coordinate marker -->
48
- <line x1="12" y1="2" x2="12" y2="8" />
49
- <line x1="12" y1="16" x2="12" y2="22" />
50
- <line x1="2" y1="12" x2="8" y2="12" />
51
- <line x1="16" y1="12" x2="22" y2="12" />
52
- <rect x="9" y="9" width="6" height="6" rx="0.5" />
53
- {:else if variant === 'mark'}
54
- <!-- measurement mark -->
55
- <line x1="4" y1="20" x2="20" y2="4" />
56
- <line x1="4" y1="20" x2="4" y2="15" />
57
- <line x1="4" y1="20" x2="9" y2="20" />
58
- <circle cx="12" cy="12" r="1" fill={color} stroke="none" />
59
- {/if}
60
- </svg>
61
-
62
- <style>
63
- .hyvui-glyph-mark {
64
- display: inline-block;
65
- pointer-events: none;
66
- flex-shrink: 0;
67
- opacity: 0.5;
68
- }
69
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+
4
+ interface Props {
5
+ /** Glyph variant. */
6
+ variant?: 'cross' | 'reticle' | 'coord' | 'mark';
7
+ /** Size in pixels. */
8
+ size?: number;
9
+ /** Glyph color. */
10
+ color?: string;
11
+ /** Additional CSS classes. */
12
+ class?: string;
13
+ }
14
+
15
+ let {
16
+ variant = 'cross',
17
+ size = 24,
18
+ color = 'var(--muted-strong)',
19
+ class: className = ''
20
+ }: Props = $props();
21
+ </script>
22
+
23
+ <svg
24
+ class={cn('hyvui-glyph-mark', className)}
25
+ width={size}
26
+ height={size}
27
+ viewBox="0 0 24 24"
28
+ fill="none"
29
+ stroke={color}
30
+ stroke-width="1"
31
+ aria-hidden="true"
32
+ >
33
+ {#if variant === 'cross'}
34
+ <!-- coordinate cross -->
35
+ <line x1="12" y1="4" x2="12" y2="20" />
36
+ <line x1="4" y1="12" x2="20" y2="12" />
37
+ <circle cx="12" cy="12" r="1.5" fill={color} stroke="none" />
38
+ {:else if variant === 'reticle'}
39
+ <!-- targeting reticle -->
40
+ <circle cx="12" cy="12" r="8" />
41
+ <circle cx="12" cy="12" r="3" />
42
+ <line x1="12" y1="1" x2="12" y2="5" />
43
+ <line x1="12" y1="19" x2="12" y2="23" />
44
+ <line x1="1" y1="12" x2="5" y2="12" />
45
+ <line x1="19" y1="12" x2="23" y2="12" />
46
+ {:else if variant === 'coord'}
47
+ <!-- cartographic coordinate marker -->
48
+ <line x1="12" y1="2" x2="12" y2="8" />
49
+ <line x1="12" y1="16" x2="12" y2="22" />
50
+ <line x1="2" y1="12" x2="8" y2="12" />
51
+ <line x1="16" y1="12" x2="22" y2="12" />
52
+ <rect x="9" y="9" width="6" height="6" rx="0.5" />
53
+ {:else if variant === 'mark'}
54
+ <!-- measurement mark -->
55
+ <line x1="4" y1="20" x2="20" y2="4" />
56
+ <line x1="4" y1="20" x2="4" y2="15" />
57
+ <line x1="4" y1="20" x2="9" y2="20" />
58
+ <circle cx="12" cy="12" r="1" fill={color} stroke="none" />
59
+ {/if}
60
+ </svg>
61
+
62
+ <style>
63
+ .hyvui-glyph-mark {
64
+ display: inline-block;
65
+ pointer-events: none;
66
+ flex-shrink: 0;
67
+ opacity: 0.5;
68
+ }
69
+ </style>
@@ -1,28 +1,26 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
-
4
- interface Props {
5
- /** Additional CSS classes. */
6
- class?: string;
7
- }
8
-
9
- let {
10
- class: className = '',
11
- }: Props = $props();
12
- </script>
13
-
14
- <div class={cn('hyvui-grid-overlay', className)} aria-hidden="true"></div>
15
-
16
- <style>
17
- .hyvui-grid-overlay {
18
- position: absolute;
19
- inset: 0;
20
- pointer-events: none;
21
- background-image:
22
- linear-gradient(to right, rgba(199, 156, 87, 0.04) 1px, transparent 1px),
23
- linear-gradient(to bottom, rgba(199, 156, 87, 0.04) 1px, transparent 1px);
24
- background-size: 72px 72px;
25
- mask-image: linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
26
- -webkit-mask-image: linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
27
- }
28
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+
4
+ interface Props {
5
+ /** Additional CSS classes. */
6
+ class?: string;
7
+ }
8
+
9
+ let { class: className = '' }: Props = $props();
10
+ </script>
11
+
12
+ <div class={cn('hyvui-grid-overlay', className)} aria-hidden="true"></div>
13
+
14
+ <style>
15
+ .hyvui-grid-overlay {
16
+ position: absolute;
17
+ inset: 0;
18
+ pointer-events: none;
19
+ background-image:
20
+ linear-gradient(to right, rgba(199, 156, 87, 0.04) 1px, transparent 1px),
21
+ linear-gradient(to bottom, rgba(199, 156, 87, 0.04) 1px, transparent 1px);
22
+ background-size: 72px 72px;
23
+ mask-image: linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
24
+ -webkit-mask-image: linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
25
+ }
26
+ </style>
@@ -1,41 +1,37 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
- import type { Snippet } from 'svelte';
4
-
5
- interface Props {
6
- /** Motion multiplier applied to --px/--py custom properties. */
7
- strength?: number;
8
- /** Additional CSS classes. */
9
- class?: string;
10
- /** Content to apply parallax to. */
11
- children?: Snippet;
12
- }
13
-
14
- let {
15
- strength = 18,
16
- class: className = '',
17
- children,
18
- }: Props = $props();
19
- </script>
20
-
21
- <div
22
- class={cn('hyvui-parallax', className)}
23
- style:transform="translate(calc(var(--px, 0) * {strength}px), calc(var(--py, 0) * {strength}px))"
24
- aria-hidden="true"
25
- >
26
- {#if children}{@render children()}{/if}
27
- </div>
28
-
29
- <style>
30
- .hyvui-parallax {
31
- will-change: transform;
32
- transition: transform 0.15s ease-out;
33
- }
34
-
35
- @media (prefers-reduced-motion: reduce) {
36
- .hyvui-parallax {
37
- transform: none !important;
38
- transition: none;
39
- }
40
- }
41
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ interface Props {
6
+ /** Motion multiplier applied to --px/--py custom properties. */
7
+ strength?: number;
8
+ /** Additional CSS classes. */
9
+ class?: string;
10
+ /** Content to apply parallax to. */
11
+ children?: Snippet;
12
+ }
13
+
14
+ let { strength = 18, class: className = '', children }: Props = $props();
15
+ </script>
16
+
17
+ <div
18
+ class={cn('hyvui-parallax', className)}
19
+ style:transform="translate(calc(var(--px, 0) * {strength}px), calc(var(--py, 0) * {strength}px))"
20
+ aria-hidden="true"
21
+ >
22
+ {#if children}{@render children()}{/if}
23
+ </div>
24
+
25
+ <style>
26
+ .hyvui-parallax {
27
+ will-change: transform;
28
+ transition: transform 0.15s ease-out;
29
+ }
30
+
31
+ @media (prefers-reduced-motion: reduce) {
32
+ .hyvui-parallax {
33
+ transform: none !important;
34
+ transition: none;
35
+ }
36
+ }
37
+ </style>