@hyvnt/hyvui 0.2.0 → 0.4.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 (181) hide show
  1. package/README.md +294 -253
  2. package/dist/components/ambient/ArcaneVein.svelte +151 -0
  3. package/dist/components/ambient/ArcaneVein.svelte.d.ts +31 -0
  4. package/dist/components/ambient/BrassFiligree.svelte +109 -0
  5. package/dist/components/ambient/BrassFiligree.svelte.d.ts +20 -0
  6. package/dist/components/ambient/CornerBrackets.svelte +91 -87
  7. package/dist/components/ambient/CornerBrackets.svelte.d.ts +8 -0
  8. package/dist/components/ambient/CrystalShard.svelte +151 -0
  9. package/dist/components/ambient/CrystalShard.svelte.d.ts +19 -0
  10. package/dist/components/ambient/DataStream.svelte +117 -94
  11. package/dist/components/ambient/DataStream.svelte.d.ts +6 -0
  12. package/dist/components/ambient/EnergyArc.svelte +189 -0
  13. package/dist/components/ambient/EnergyArc.svelte.d.ts +32 -0
  14. package/dist/components/ambient/GlyphMark.svelte +75 -69
  15. package/dist/components/ambient/GlyphMark.svelte.d.ts +6 -0
  16. package/dist/components/ambient/GridOverlay.svelte +34 -28
  17. package/dist/components/ambient/GridOverlay.svelte.d.ts +8 -0
  18. package/dist/components/ambient/HexGrid.svelte +119 -0
  19. package/dist/components/ambient/HexGrid.svelte.d.ts +21 -0
  20. package/dist/components/ambient/ParallaxLayer.svelte +45 -41
  21. package/dist/components/ambient/ParallaxLayer.svelte.d.ts +7 -0
  22. package/dist/components/ambient/ScanBand.svelte +103 -91
  23. package/dist/components/ambient/ScanBand.svelte.d.ts +8 -0
  24. package/dist/components/ambient/ShimmerCloud.svelte +180 -0
  25. package/dist/components/ambient/ShimmerCloud.svelte.d.ts +21 -0
  26. package/dist/components/ambient/SignalRing.svelte +106 -100
  27. package/dist/components/ambient/SignalRing.svelte.d.ts +6 -0
  28. package/dist/components/ambient/ThreadLine.svelte +78 -78
  29. package/dist/components/ambient/ThreadLine.svelte.d.ts +7 -0
  30. package/dist/components/ambient/Vignette.svelte +30 -26
  31. package/dist/components/ambient/Vignette.svelte.d.ts +6 -0
  32. package/dist/components/depth/DepthLayer.svelte +30 -27
  33. package/dist/components/depth/DepthLayer.svelte.d.ts +8 -0
  34. package/dist/components/depth/DepthStage.svelte +67 -62
  35. package/dist/components/depth/DepthStage.svelte.d.ts +8 -0
  36. package/dist/components/depth/FloatCard.svelte +129 -104
  37. package/dist/components/depth/FloatCard.svelte.d.ts +8 -0
  38. package/dist/components/depth/HorizonGrid.svelte +241 -160
  39. package/dist/components/depth/HorizonGrid.svelte.d.ts +9 -0
  40. package/dist/components/depth/Plinth.svelte +62 -57
  41. package/dist/components/depth/Plinth.svelte.d.ts +10 -0
  42. package/dist/components/display/Avatar.svelte +69 -69
  43. package/dist/components/display/Avatar.svelte.d.ts +5 -0
  44. package/dist/components/display/Badge.svelte +75 -63
  45. package/dist/components/display/Badge.svelte.d.ts +6 -0
  46. package/dist/components/display/Blockquote.svelte +35 -34
  47. package/dist/components/display/Blockquote.svelte.d.ts +4 -0
  48. package/dist/components/display/CodeBlock.svelte +76 -76
  49. package/dist/components/display/CodeBlock.svelte.d.ts +5 -0
  50. package/dist/components/display/MetricCard.svelte +100 -83
  51. package/dist/components/display/MetricCard.svelte.d.ts +6 -0
  52. package/dist/components/display/Table.svelte +106 -104
  53. package/dist/components/display/Table.svelte.d.ts +7 -0
  54. package/dist/components/feedback/Alert.svelte +95 -76
  55. package/dist/components/feedback/Alert.svelte.d.ts +6 -0
  56. package/dist/components/feedback/EmptyState.svelte +75 -68
  57. package/dist/components/feedback/EmptyState.svelte.d.ts +7 -0
  58. package/dist/components/feedback/ErrorState.svelte +78 -73
  59. package/dist/components/feedback/ErrorState.svelte.d.ts +5 -0
  60. package/dist/components/feedback/Skeleton.svelte +58 -52
  61. package/dist/components/feedback/Skeleton.svelte.d.ts +6 -0
  62. package/dist/components/feedback/StatusDot.svelte +84 -54
  63. package/dist/components/feedback/StatusDot.svelte.d.ts +6 -0
  64. package/dist/components/feedback/StatusLine.svelte +128 -122
  65. package/dist/components/feedback/StatusLine.svelte.d.ts +6 -0
  66. package/dist/components/feedback/Toast.svelte +144 -136
  67. package/dist/components/feedback/Toast.svelte.d.ts +10 -0
  68. package/dist/components/inputs/Button.svelte +310 -237
  69. package/dist/components/inputs/Button.svelte.d.ts +8 -0
  70. package/dist/components/inputs/Checkbox.svelte +109 -105
  71. package/dist/components/inputs/Checkbox.svelte.d.ts +5 -0
  72. package/dist/components/inputs/FileUpload.svelte +170 -163
  73. package/dist/components/inputs/FileUpload.svelte.d.ts +5 -0
  74. package/dist/components/inputs/Input.svelte +153 -147
  75. package/dist/components/inputs/Input.svelte.d.ts +7 -0
  76. package/dist/components/inputs/Select.svelte +164 -150
  77. package/dist/components/inputs/Select.svelte.d.ts +8 -0
  78. package/dist/components/inputs/Textarea.svelte +160 -154
  79. package/dist/components/inputs/Textarea.svelte.d.ts +6 -0
  80. package/dist/components/inputs/Toggle.svelte +125 -120
  81. package/dist/components/inputs/Toggle.svelte.d.ts +5 -0
  82. package/dist/components/layout/Card.svelte +81 -76
  83. package/dist/components/layout/Card.svelte.d.ts +11 -0
  84. package/dist/components/layout/Drawer.svelte +140 -109
  85. package/dist/components/layout/Drawer.svelte.d.ts +6 -0
  86. package/dist/components/layout/Grid.svelte +128 -43
  87. package/dist/components/layout/Grid.svelte.d.ts +18 -2
  88. package/dist/components/layout/Modal.svelte +191 -159
  89. package/dist/components/layout/Modal.svelte.d.ts +10 -0
  90. package/dist/components/layout/Panel.svelte +58 -54
  91. package/dist/components/layout/Panel.svelte.d.ts +9 -0
  92. package/dist/components/layout/Popover.svelte +188 -67
  93. package/dist/components/layout/Popover.svelte.d.ts +19 -1
  94. package/dist/components/layout/Stack.svelte +65 -53
  95. package/dist/components/layout/Stack.svelte.d.ts +12 -0
  96. package/dist/components/navigation/Breadcrumb.svelte +78 -73
  97. package/dist/components/navigation/Breadcrumb.svelte.d.ts +8 -0
  98. package/dist/components/navigation/DropdownMenu.svelte +179 -124
  99. package/dist/components/navigation/DropdownMenu.svelte.d.ts +24 -2
  100. package/dist/components/navigation/SidebarNav.svelte +96 -90
  101. package/dist/components/navigation/SidebarNav.svelte.d.ts +9 -0
  102. package/dist/components/navigation/Tabs.svelte +106 -86
  103. package/dist/components/navigation/Tabs.svelte.d.ts +8 -0
  104. package/dist/components/navigation/Topbar.svelte +94 -85
  105. package/dist/components/navigation/Topbar.svelte.d.ts +9 -0
  106. package/dist/components/patterns/ActionBar.svelte +82 -76
  107. package/dist/components/patterns/ActionBar.svelte.d.ts +10 -0
  108. package/dist/components/patterns/ChapterMark.svelte +152 -0
  109. package/dist/components/patterns/ChapterMark.svelte.d.ts +19 -0
  110. package/dist/components/patterns/ConfirmDialog.svelte +75 -64
  111. package/dist/components/patterns/ConfirmDialog.svelte.d.ts +12 -0
  112. package/dist/components/patterns/DepthPortal.svelte +123 -0
  113. package/dist/components/patterns/DepthPortal.svelte.d.ts +24 -0
  114. package/dist/components/patterns/Manifesto.svelte +171 -0
  115. package/dist/components/patterns/Manifesto.svelte.d.ts +25 -0
  116. package/dist/components/patterns/PageHeader.svelte +117 -114
  117. package/dist/components/patterns/PageHeader.svelte.d.ts +8 -0
  118. package/dist/components/patterns/PullQuote.svelte +145 -0
  119. package/dist/components/patterns/PullQuote.svelte.d.ts +23 -0
  120. package/dist/components/patterns/RegisterSwitcher.svelte +132 -0
  121. package/dist/components/patterns/RegisterSwitcher.svelte.d.ts +21 -0
  122. package/dist/components/patterns/SearchBar.svelte +59 -59
  123. package/dist/components/patterns/SearchBar.svelte.d.ts +5 -0
  124. package/dist/components/patterns/ShowcaseFrame.svelte +117 -0
  125. package/dist/components/patterns/ShowcaseFrame.svelte.d.ts +28 -0
  126. package/dist/components/patterns/TerminalBoot.svelte +118 -104
  127. package/dist/components/patterns/TerminalBoot.svelte.d.ts +12 -0
  128. package/dist/components/primitives/Divider.svelte +56 -29
  129. package/dist/components/primitives/Divider.svelte.d.ts +5 -0
  130. package/dist/components/primitives/Icon.svelte +53 -49
  131. package/dist/components/primitives/Icon.svelte.d.ts +9 -0
  132. package/dist/components/primitives/Label.svelte +45 -44
  133. package/dist/components/primitives/Label.svelte.d.ts +6 -0
  134. package/dist/components/primitives/Surface.svelte +154 -87
  135. package/dist/components/primitives/Surface.svelte.d.ts +7 -0
  136. package/dist/components/primitives/Text.svelte +130 -98
  137. package/dist/components/primitives/Text.svelte.d.ts +7 -0
  138. package/dist/components/scenes/ArchiveScene.svelte +102 -95
  139. package/dist/components/scenes/ArchiveScene.svelte.d.ts +17 -1
  140. package/dist/components/scenes/DepthScene.svelte +128 -0
  141. package/dist/components/scenes/DepthScene.svelte.d.ts +36 -0
  142. package/dist/components/scenes/LogScene.svelte +86 -77
  143. package/dist/components/scenes/LogScene.svelte.d.ts +14 -0
  144. package/dist/components/scenes/NarrativeScene.svelte +100 -92
  145. package/dist/components/scenes/NarrativeScene.svelte.d.ts +9 -0
  146. package/dist/components/scenes/ReadoutScene.svelte +131 -107
  147. package/dist/components/scenes/ReadoutScene.svelte.d.ts +14 -1
  148. package/dist/components/scenes/StageScene.svelte +111 -104
  149. package/dist/components/scenes/StageScene.svelte.d.ts +14 -0
  150. package/dist/components/system/AppShell.svelte +62 -0
  151. package/dist/components/system/AppShell.svelte.d.ts +32 -0
  152. package/dist/examples/ArcaneShard.svelte +364 -0
  153. package/dist/examples/ArcaneShard.svelte.d.ts +3 -0
  154. package/dist/examples/FieldReport.svelte +226 -223
  155. package/dist/examples/HextechForge.svelte +324 -0
  156. package/dist/examples/HextechForge.svelte.d.ts +3 -0
  157. package/dist/examples/ObservationDeck.svelte +333 -317
  158. package/dist/examples/SignalLost.svelte +191 -191
  159. package/dist/index.d.ts +15 -1
  160. package/dist/index.js +16 -1
  161. package/dist/styles.css +115 -0
  162. package/dist/system/actions/echo.js +21 -12
  163. package/dist/system/actions/resolve.js +28 -14
  164. package/dist/system/actions/reveal.js +2 -2
  165. package/dist/system/actions/surface.js +12 -2
  166. package/dist/system/depth/depth.css +49 -49
  167. package/dist/system/depth/depth.js +1 -1
  168. package/dist/system/expressions.css +80 -80
  169. package/dist/system/override-template.css +72 -72
  170. package/dist/system/register.css +74 -74
  171. package/dist/system/register.d.ts +1 -1
  172. package/dist/system/register.js +5 -1
  173. package/dist/system/scroll-lock.d.ts +6 -0
  174. package/dist/system/scroll-lock.js +23 -0
  175. package/dist/tokens/arcane.css +96 -0
  176. package/dist/tokens/hextech.css +96 -0
  177. package/dist/tokens/tokens.css +102 -86
  178. package/dist/tokens/tokens.d.ts +41 -0
  179. package/dist/tokens/tokens.js +44 -3
  180. package/dist/utils/motion.js +1 -1
  181. package/package.json +71 -60
@@ -1,94 +1,117 @@
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
+ /**
6
+ * Decorative scrolling hex character column. Renders `aria-hidden`.
7
+ * @example
8
+ * <DataStream width="1.4rem" speed="slow" />
9
+ * <DataStream active={isConnected} />
10
+ */
11
+ interface Props {
12
+ /** Enable the scrolling animation. */
13
+ active?: boolean;
14
+ /** Width of the stream column. */
15
+ width?: string;
16
+ /** Scroll speed. */
17
+ speed?: 'slow' | 'medium';
18
+ /** Additional CSS classes. */
19
+ class?: string;
20
+ }
21
+
22
+ let { active = true, width = '1.2rem', speed = 'slow', class: className = '' }: Props = $props();
23
+
24
+ const chars = '0123456789ABCDEF.:+-';
25
+ const lineCount = 32;
26
+ let rootEl: HTMLDivElement | undefined = $state();
27
+ let visible = $state(true);
28
+ let lines = $state<string[]>([]);
29
+ let intervalId: ReturnType<typeof setInterval> | undefined;
30
+
31
+ const prefersReduced =
32
+ typeof window !== 'undefined'
33
+ ? window.matchMedia('(prefers-reduced-motion: reduce)').matches
34
+ : false;
35
+
36
+ function randomChar(): string {
37
+ return chars[Math.floor(Math.random() * chars.length)];
38
+ }
39
+
40
+ function generateLines(): string[] {
41
+ return Array.from({ length: lineCount }, () => randomChar());
42
+ }
43
+
44
+ function stop() {
45
+ if (!intervalId) return;
46
+ clearInterval(intervalId);
47
+ intervalId = undefined;
48
+ }
49
+
50
+ function start() {
51
+ stop();
52
+ if (!active || prefersReduced || !visible) return;
53
+ const ms = speed === 'slow' ? 600 : 350;
54
+ intervalId = setInterval(() => {
55
+ // Unkeyed each blocks update in-place, so this is stable DOM churn.
56
+ lines = [randomChar(), ...lines.slice(0, lineCount - 1)];
57
+ }, ms);
58
+ }
59
+
60
+ onMount(() => {
61
+ lines = generateLines();
62
+
63
+ const io = new IntersectionObserver(
64
+ (entries) => {
65
+ const entry = entries[0];
66
+ if (!entry) return;
67
+ visible = entry.isIntersecting;
68
+ },
69
+ { root: null, threshold: 0 }
70
+ );
71
+
72
+ if (rootEl) io.observe(rootEl);
73
+
74
+ return () => {
75
+ io.disconnect();
76
+ stop();
77
+ };
78
+ });
79
+
80
+ $effect(() => {
81
+ // Restart interval when relevant inputs change.
82
+ start();
83
+ return stop;
84
+ });
85
+ </script>
86
+
87
+ <div bind:this={rootEl} class={cn('hyvui-data-stream', className)} style:width aria-hidden="true">
88
+ {#each lines as char, i}
89
+ <span class="hyvui-data-stream-char" style:opacity={0.18 - (i / lineCount) * 0.14}>{char}</span>
90
+ {/each}
91
+ </div>
92
+
93
+ <style>
94
+ .hyvui-data-stream {
95
+ display: flex;
96
+ flex-direction: column;
97
+ align-items: center;
98
+ font-family: var(--font-mono);
99
+ font-size: 0.6rem;
100
+ line-height: 1.4;
101
+ letter-spacing: 0.1em;
102
+ color: var(--accent);
103
+ pointer-events: none;
104
+ overflow: hidden;
105
+ }
106
+
107
+ .hyvui-data-stream-char {
108
+ display: block;
109
+ transition: opacity 0.3s var(--ease-fast);
110
+ }
111
+
112
+ @media (prefers-reduced-motion: reduce) {
113
+ .hyvui-data-stream-char {
114
+ transition: none;
115
+ }
116
+ }
117
+ </style>
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Decorative scrolling hex character column. Renders `aria-hidden`.
3
+ * @example
4
+ * <DataStream width="1.4rem" speed="slow" />
5
+ * <DataStream active={isConnected} />
6
+ */
1
7
  interface Props {
2
8
  /** Enable the scrolling animation. */
3
9
  active?: boolean;
@@ -0,0 +1,189 @@
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+
4
+ /**
5
+ * Decorative energy arc (SVG quadratic bezier) between two points.
6
+ * Under `hextech`: single clean cyan arc with traveling dot.
7
+ * Under `arcane`: violet arc with jitter and brighter particle.
8
+ * Parent must have `position: relative`. Renders `aria-hidden`.
9
+ *
10
+ * @example
11
+ * <div style="position: relative; height: 100px;">
12
+ * <EnergyArc x1="10%" y1="100%" x2="90%" y2="100%" bend={-40} />
13
+ * </div>
14
+ */
15
+ interface Props {
16
+ /** Start x (CSS %). */
17
+ x1?: string;
18
+ /** Start y (CSS %). */
19
+ y1?: string;
20
+ /** End x (CSS %). */
21
+ x2?: string;
22
+ /** End y (CSS %). */
23
+ y2?: string;
24
+ /** Control point y-offset in px (negative = arc up, positive = arc down). */
25
+ bend?: number;
26
+ /** Traveling particle speed in seconds. */
27
+ speed?: number;
28
+ /** Enable traveling particle. */
29
+ animated?: boolean;
30
+ /** Additional CSS classes. */
31
+ class?: string;
32
+ }
33
+
34
+ let {
35
+ x1 = '10%',
36
+ y1 = '50%',
37
+ x2 = '90%',
38
+ y2 = '50%',
39
+ bend = -32,
40
+ speed = 2,
41
+ animated = true,
42
+ class: className = ''
43
+ }: Props = $props();
44
+
45
+ const prefersReduced =
46
+ typeof window !== 'undefined'
47
+ ? window.matchMedia('(prefers-reduced-motion: reduce)').matches
48
+ : false;
49
+
50
+ const dur = $derived(`${speed}s`);
51
+ const durJitter = $derived(`${speed * 1.4}s`);
52
+ const shouldAnimate = $derived(animated && !prefersReduced);
53
+
54
+ // We don't know actual px coords until render, so the bezier control point
55
+ // is expressed as a data attribute and animated via SVG animateTransform.
56
+ // For the path `d` we use a placeholder that gets overridden by JS,
57
+ // but since this is a portoflio component, a CSS-only approximation works:
58
+ // we anchor a <path> using % units for x/y and em for control offset.
59
+
60
+ const filterId = `ea-glow-${Math.random().toString(36).slice(2, 8)}`;
61
+
62
+ // Bezier path string: Q cx,cy x2,y2 — control point is midpoint elevated by `bend`
63
+ // We use computed path as a string and pass it as an attribute.
64
+ // Since SVG doesn't mix % and px in path d, we keep all in % and treat bend as %.
65
+ const bendPct = $derived(`${bend}px`);
66
+
67
+ // Path using SVG's ability to do absolute coordinates in %. Not directly possible,
68
+ // so we use a wrapper approach: the SVG has viewBox "0 0 100 100" and we translate %.
69
+ // Keep it simple: use an SVG with proportional coordinates.
70
+ // The consumer positions the SVG fill on the parent, so 0 0 100 100 viewBox is fine.
71
+ const mid = '50%';
72
+ const path = $derived(`M ${x1} ${y1} Q ${mid} calc(50% + ${bendPct}) ${x2} ${y2}`);
73
+ </script>
74
+
75
+ <svg class={cn('hyvui-energy-arc', className)} aria-hidden="true">
76
+ <defs>
77
+ <filter id={filterId} x="-50%" y="-100%" width="200%" height="300%">
78
+ <feGaussianBlur stdDeviation="2" result="blur" />
79
+ <feMerge>
80
+ <feMergeNode in="blur" />
81
+ <feMergeNode in="SourceGraphic" />
82
+ </feMerge>
83
+ </filter>
84
+ </defs>
85
+
86
+ <!-- glow halo -->
87
+ <path
88
+ class="hyvui-ea-halo"
89
+ d={path}
90
+ fill="none"
91
+ stroke-width="5"
92
+ filter="url(#{filterId})"
93
+ />
94
+
95
+ <!-- main arc line -->
96
+ <path
97
+ class="hyvui-ea-line"
98
+ d={path}
99
+ fill="none"
100
+ stroke-width="1"
101
+ />
102
+
103
+ <!-- traveling particle -->
104
+ {#if shouldAnimate}
105
+ <circle class="hyvui-ea-particle" r="3">
106
+ <animateMotion dur={dur} repeatCount="indefinite" keyPoints="0;1" keyTimes="0;1" calcMode="linear">
107
+ <mpath>
108
+ <path d={path} />
109
+ </mpath>
110
+ </animateMotion>
111
+ <animate
112
+ attributeName="opacity"
113
+ values="0;1;1;0"
114
+ keyTimes="0;0.1;0.85;1"
115
+ dur={dur}
116
+ repeatCount="indefinite"
117
+ />
118
+ </circle>
119
+
120
+ <!-- arcane gets a second jitter particle traveling opposite direction -->
121
+ <circle class="hyvui-ea-particle hyvui-ea-particle--jitter" r="2">
122
+ <animateMotion dur={durJitter} repeatCount="indefinite" keyPoints="1;0" keyTimes="0;1" calcMode="linear">
123
+ <mpath>
124
+ <path d={path} />
125
+ </mpath>
126
+ </animateMotion>
127
+ <animate
128
+ attributeName="opacity"
129
+ values="0;0.5;0.5;0"
130
+ keyTimes="0;0.12;0.88;1"
131
+ dur={durJitter}
132
+ repeatCount="indefinite"
133
+ />
134
+ </circle>
135
+ {/if}
136
+ </svg>
137
+
138
+ <style>
139
+ .hyvui-energy-arc {
140
+ position: absolute;
141
+ inset: 0;
142
+ width: 100%;
143
+ height: 100%;
144
+ pointer-events: none;
145
+ overflow: visible;
146
+ }
147
+
148
+ /* ── default (field-notebook) ─────────────────────────────────────── */
149
+ .hyvui-ea-halo { stroke: transparent; }
150
+ .hyvui-ea-line { stroke: rgba(199, 156, 87, 0.25); }
151
+ .hyvui-ea-particle { fill: rgba(199, 156, 87, 0.8); }
152
+ .hyvui-ea-particle--jitter { display: none; }
153
+
154
+ /* ── hextech: clean cyan arc, single particle ─────────────────────── */
155
+ :global([data-register='hextech']) .hyvui-ea-halo {
156
+ stroke: rgba(93, 217, 240, 0.12);
157
+ }
158
+ :global([data-register='hextech']) .hyvui-ea-line {
159
+ stroke: rgba(93, 217, 240, 0.55);
160
+ }
161
+ :global([data-register='hextech']) .hyvui-ea-particle {
162
+ fill: rgba(184, 230, 242, 1);
163
+ }
164
+ :global([data-register='hextech']) .hyvui-ea-particle--jitter {
165
+ display: none;
166
+ }
167
+
168
+ /* ── arcane: violet arc, bidirectional particles ──────────────────── */
169
+ :global([data-register='arcane']) .hyvui-ea-halo {
170
+ stroke: rgba(184, 69, 201, 0.2);
171
+ }
172
+ :global([data-register='arcane']) .hyvui-ea-line {
173
+ stroke: rgba(184, 69, 201, 0.6);
174
+ }
175
+ :global([data-register='arcane']) .hyvui-ea-particle {
176
+ fill: rgba(233, 76, 188, 1);
177
+ }
178
+ :global([data-register='arcane']) .hyvui-ea-particle--jitter {
179
+ display: block;
180
+ fill: rgba(184, 69, 201, 0.7);
181
+ }
182
+
183
+ @media (prefers-reduced-motion: reduce) {
184
+ .hyvui-ea-particle,
185
+ .hyvui-ea-particle--jitter {
186
+ display: none;
187
+ }
188
+ }
189
+ </style>
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Decorative energy arc (SVG quadratic bezier) between two points.
3
+ * Under `hextech`: single clean cyan arc with traveling dot.
4
+ * Under `arcane`: violet arc with jitter and brighter particle.
5
+ * Parent must have `position: relative`. Renders `aria-hidden`.
6
+ *
7
+ * @example
8
+ * <div style="position: relative; height: 100px;">
9
+ * <EnergyArc x1="10%" y1="100%" x2="90%" y2="100%" bend={-40} />
10
+ * </div>
11
+ */
12
+ interface Props {
13
+ /** Start x (CSS %). */
14
+ x1?: string;
15
+ /** Start y (CSS %). */
16
+ y1?: string;
17
+ /** End x (CSS %). */
18
+ x2?: string;
19
+ /** End y (CSS %). */
20
+ y2?: string;
21
+ /** Control point y-offset in px (negative = arc up, positive = arc down). */
22
+ bend?: number;
23
+ /** Traveling particle speed in seconds. */
24
+ speed?: number;
25
+ /** Enable traveling particle. */
26
+ animated?: boolean;
27
+ /** Additional CSS classes. */
28
+ class?: string;
29
+ }
30
+ declare const EnergyArc: import("svelte").Component<Props, {}, "">;
31
+ type EnergyArc = ReturnType<typeof EnergyArc>;
32
+ export default EnergyArc;
@@ -1,69 +1,75 @@
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
+ /**
5
+ * Decorative SVG glyph. Renders `aria-hidden`.
6
+ * @example
7
+ * <GlyphMark variant="reticle" size={32} />
8
+ * <GlyphMark variant="cross" color="var(--accent)" />
9
+ */
10
+ interface Props {
11
+ /** Glyph variant. */
12
+ variant?: 'cross' | 'reticle' | 'coord' | 'mark';
13
+ /** Size in pixels. */
14
+ size?: number;
15
+ /** Glyph color. */
16
+ color?: string;
17
+ /** Additional CSS classes. */
18
+ class?: string;
19
+ }
20
+
21
+ let {
22
+ variant = 'cross',
23
+ size = 24,
24
+ color = 'var(--muted-strong)',
25
+ class: className = ''
26
+ }: Props = $props();
27
+ </script>
28
+
29
+ <svg
30
+ class={cn('hyvui-glyph-mark', className)}
31
+ width={size}
32
+ height={size}
33
+ viewBox="0 0 24 24"
34
+ fill="none"
35
+ stroke={color}
36
+ stroke-width="1"
37
+ aria-hidden="true"
38
+ >
39
+ {#if variant === 'cross'}
40
+ <!-- coordinate cross -->
41
+ <line x1="12" y1="4" x2="12" y2="20" />
42
+ <line x1="4" y1="12" x2="20" y2="12" />
43
+ <circle cx="12" cy="12" r="1.5" fill={color} stroke="none" />
44
+ {:else if variant === 'reticle'}
45
+ <!-- targeting reticle -->
46
+ <circle cx="12" cy="12" r="8" />
47
+ <circle cx="12" cy="12" r="3" />
48
+ <line x1="12" y1="1" x2="12" y2="5" />
49
+ <line x1="12" y1="19" x2="12" y2="23" />
50
+ <line x1="1" y1="12" x2="5" y2="12" />
51
+ <line x1="19" y1="12" x2="23" y2="12" />
52
+ {:else if variant === 'coord'}
53
+ <!-- cartographic coordinate marker -->
54
+ <line x1="12" y1="2" x2="12" y2="8" />
55
+ <line x1="12" y1="16" x2="12" y2="22" />
56
+ <line x1="2" y1="12" x2="8" y2="12" />
57
+ <line x1="16" y1="12" x2="22" y2="12" />
58
+ <rect x="9" y="9" width="6" height="6" rx="0.5" />
59
+ {:else if variant === 'mark'}
60
+ <!-- measurement mark -->
61
+ <line x1="4" y1="20" x2="20" y2="4" />
62
+ <line x1="4" y1="20" x2="4" y2="15" />
63
+ <line x1="4" y1="20" x2="9" y2="20" />
64
+ <circle cx="12" cy="12" r="1" fill={color} stroke="none" />
65
+ {/if}
66
+ </svg>
67
+
68
+ <style>
69
+ .hyvui-glyph-mark {
70
+ display: inline-block;
71
+ pointer-events: none;
72
+ flex-shrink: 0;
73
+ opacity: 0.5;
74
+ }
75
+ </style>
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Decorative SVG glyph. Renders `aria-hidden`.
3
+ * @example
4
+ * <GlyphMark variant="reticle" size={32} />
5
+ * <GlyphMark variant="cross" color="var(--accent)" />
6
+ */
1
7
  interface Props {
2
8
  /** Glyph variant. */
3
9
  variant?: 'cross' | 'reticle' | 'coord' | 'mark';
@@ -1,28 +1,34 @@
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
+ /**
5
+ * Decorative. Parent must have `position: relative`. Renders `aria-hidden`.
6
+ * @example
7
+ * <div style="position: relative;">
8
+ * <GridOverlay />
9
+ * content here
10
+ * </div>
11
+ */
12
+ interface Props {
13
+ /** Additional CSS classes. */
14
+ class?: string;
15
+ }
16
+
17
+ let { class: className = '' }: Props = $props();
18
+ </script>
19
+
20
+ <div class={cn('hyvui-grid-overlay', className)} aria-hidden="true"></div>
21
+
22
+ <style>
23
+ .hyvui-grid-overlay {
24
+ position: absolute;
25
+ inset: 0;
26
+ pointer-events: none;
27
+ background-image:
28
+ linear-gradient(to right, rgba(199, 156, 87, 0.04) 1px, transparent 1px),
29
+ linear-gradient(to bottom, rgba(199, 156, 87, 0.04) 1px, transparent 1px);
30
+ background-size: 72px 72px;
31
+ mask-image: linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
32
+ -webkit-mask-image: linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
33
+ }
34
+ </style>