@hyvnt/hyvui 0.3.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.
- package/README.md +37 -7
- package/dist/components/ambient/ArcaneVein.svelte +151 -0
- package/dist/components/ambient/ArcaneVein.svelte.d.ts +31 -0
- package/dist/components/ambient/BrassFiligree.svelte +109 -0
- package/dist/components/ambient/BrassFiligree.svelte.d.ts +20 -0
- package/dist/components/ambient/CornerBrackets.svelte +8 -0
- package/dist/components/ambient/CornerBrackets.svelte.d.ts +8 -0
- package/dist/components/ambient/CrystalShard.svelte +151 -0
- package/dist/components/ambient/CrystalShard.svelte.d.ts +19 -0
- package/dist/components/ambient/DataStream.svelte +7 -1
- package/dist/components/ambient/DataStream.svelte.d.ts +6 -0
- package/dist/components/ambient/EnergyArc.svelte +189 -0
- package/dist/components/ambient/EnergyArc.svelte.d.ts +32 -0
- package/dist/components/ambient/GlyphMark.svelte +6 -0
- package/dist/components/ambient/GlyphMark.svelte.d.ts +6 -0
- package/dist/components/ambient/GridOverlay.svelte +8 -0
- package/dist/components/ambient/GridOverlay.svelte.d.ts +8 -0
- package/dist/components/ambient/HexGrid.svelte +119 -0
- package/dist/components/ambient/HexGrid.svelte.d.ts +21 -0
- package/dist/components/ambient/ParallaxLayer.svelte +9 -1
- package/dist/components/ambient/ParallaxLayer.svelte.d.ts +7 -0
- package/dist/components/ambient/ScanBand.svelte +8 -0
- package/dist/components/ambient/ScanBand.svelte.d.ts +8 -0
- package/dist/components/ambient/ShimmerCloud.svelte +180 -0
- package/dist/components/ambient/ShimmerCloud.svelte.d.ts +21 -0
- package/dist/components/ambient/SignalRing.svelte +7 -1
- package/dist/components/ambient/SignalRing.svelte.d.ts +6 -0
- package/dist/components/ambient/ThreadLine.svelte +7 -0
- package/dist/components/ambient/ThreadLine.svelte.d.ts +7 -0
- package/dist/components/ambient/Vignette.svelte +6 -0
- package/dist/components/ambient/Vignette.svelte.d.ts +6 -0
- package/dist/components/depth/DepthLayer.svelte +8 -0
- package/dist/components/depth/DepthLayer.svelte.d.ts +8 -0
- package/dist/components/depth/DepthStage.svelte +8 -4
- package/dist/components/depth/DepthStage.svelte.d.ts +8 -0
- package/dist/components/depth/FloatCard.svelte +17 -1
- package/dist/components/depth/FloatCard.svelte.d.ts +8 -0
- package/dist/components/depth/HorizonGrid.svelte +25 -0
- package/dist/components/depth/HorizonGrid.svelte.d.ts +9 -0
- package/dist/components/depth/Plinth.svelte +10 -0
- package/dist/components/depth/Plinth.svelte.d.ts +10 -0
- package/dist/components/display/Avatar.svelte +5 -0
- package/dist/components/display/Avatar.svelte.d.ts +5 -0
- package/dist/components/display/Badge.svelte +16 -0
- package/dist/components/display/Badge.svelte.d.ts +6 -0
- package/dist/components/display/Blockquote.svelte +4 -0
- package/dist/components/display/Blockquote.svelte.d.ts +4 -0
- package/dist/components/display/CodeBlock.svelte +5 -0
- package/dist/components/display/CodeBlock.svelte.d.ts +5 -0
- package/dist/components/display/MetricCard.svelte +23 -0
- package/dist/components/display/MetricCard.svelte.d.ts +6 -0
- package/dist/components/display/Table.svelte +7 -0
- package/dist/components/display/Table.svelte.d.ts +7 -0
- package/dist/components/feedback/Alert.svelte +24 -0
- package/dist/components/feedback/Alert.svelte.d.ts +6 -0
- package/dist/components/feedback/EmptyState.svelte +7 -0
- package/dist/components/feedback/EmptyState.svelte.d.ts +7 -0
- package/dist/components/feedback/ErrorState.svelte +5 -0
- package/dist/components/feedback/ErrorState.svelte.d.ts +5 -0
- package/dist/components/feedback/Skeleton.svelte +6 -0
- package/dist/components/feedback/Skeleton.svelte.d.ts +6 -0
- package/dist/components/feedback/StatusDot.svelte +36 -1
- package/dist/components/feedback/StatusDot.svelte.d.ts +6 -0
- package/dist/components/feedback/StatusLine.svelte +8 -2
- package/dist/components/feedback/StatusLine.svelte.d.ts +6 -0
- package/dist/components/feedback/Toast.svelte +16 -2
- package/dist/components/feedback/Toast.svelte.d.ts +10 -0
- package/dist/components/inputs/Button.svelte +74 -4
- package/dist/components/inputs/Button.svelte.d.ts +8 -0
- package/dist/components/inputs/Checkbox.svelte +5 -0
- package/dist/components/inputs/Checkbox.svelte.d.ts +5 -0
- package/dist/components/inputs/FileUpload.svelte +5 -0
- package/dist/components/inputs/FileUpload.svelte.d.ts +5 -0
- package/dist/components/inputs/Input.svelte +10 -2
- package/dist/components/inputs/Input.svelte.d.ts +7 -0
- package/dist/components/inputs/Select.svelte +8 -0
- package/dist/components/inputs/Select.svelte.d.ts +8 -0
- package/dist/components/inputs/Textarea.svelte +9 -2
- package/dist/components/inputs/Textarea.svelte.d.ts +6 -0
- package/dist/components/inputs/Toggle.svelte +6 -1
- package/dist/components/inputs/Toggle.svelte.d.ts +5 -0
- package/dist/components/layout/Card.svelte +11 -0
- package/dist/components/layout/Card.svelte.d.ts +11 -0
- package/dist/components/layout/Drawer.svelte +7 -0
- package/dist/components/layout/Drawer.svelte.d.ts +6 -0
- package/dist/components/layout/Grid.svelte +10 -0
- package/dist/components/layout/Grid.svelte.d.ts +10 -0
- package/dist/components/layout/Modal.svelte +15 -0
- package/dist/components/layout/Modal.svelte.d.ts +10 -0
- package/dist/components/layout/Panel.svelte +9 -0
- package/dist/components/layout/Panel.svelte.d.ts +9 -0
- package/dist/components/layout/Popover.svelte +10 -0
- package/dist/components/layout/Popover.svelte.d.ts +9 -0
- package/dist/components/layout/Stack.svelte +12 -0
- package/dist/components/layout/Stack.svelte.d.ts +12 -0
- package/dist/components/navigation/Breadcrumb.svelte +8 -0
- package/dist/components/navigation/Breadcrumb.svelte.d.ts +8 -0
- package/dist/components/navigation/DropdownMenu.svelte +12 -0
- package/dist/components/navigation/DropdownMenu.svelte.d.ts +12 -0
- package/dist/components/navigation/SidebarNav.svelte +10 -0
- package/dist/components/navigation/SidebarNav.svelte.d.ts +9 -0
- package/dist/components/navigation/Tabs.svelte +26 -1
- package/dist/components/navigation/Tabs.svelte.d.ts +8 -0
- package/dist/components/navigation/Topbar.svelte +9 -0
- package/dist/components/navigation/Topbar.svelte.d.ts +9 -0
- package/dist/components/patterns/ActionBar.svelte +11 -0
- package/dist/components/patterns/ActionBar.svelte.d.ts +10 -0
- package/dist/components/patterns/ChapterMark.svelte +152 -0
- package/dist/components/patterns/ChapterMark.svelte.d.ts +19 -0
- package/dist/components/patterns/ConfirmDialog.svelte +12 -0
- package/dist/components/patterns/ConfirmDialog.svelte.d.ts +12 -0
- package/dist/components/patterns/DepthPortal.svelte +123 -0
- package/dist/components/patterns/DepthPortal.svelte.d.ts +24 -0
- package/dist/components/patterns/Manifesto.svelte +171 -0
- package/dist/components/patterns/Manifesto.svelte.d.ts +25 -0
- package/dist/components/patterns/PageHeader.svelte +8 -0
- package/dist/components/patterns/PageHeader.svelte.d.ts +8 -0
- package/dist/components/patterns/PullQuote.svelte +145 -0
- package/dist/components/patterns/PullQuote.svelte.d.ts +23 -0
- package/dist/components/patterns/RegisterSwitcher.svelte +132 -0
- package/dist/components/patterns/RegisterSwitcher.svelte.d.ts +21 -0
- package/dist/components/patterns/SearchBar.svelte +5 -0
- package/dist/components/patterns/SearchBar.svelte.d.ts +5 -0
- package/dist/components/patterns/ShowcaseFrame.svelte +117 -0
- package/dist/components/patterns/ShowcaseFrame.svelte.d.ts +28 -0
- package/dist/components/patterns/TerminalBoot.svelte +15 -1
- package/dist/components/patterns/TerminalBoot.svelte.d.ts +12 -0
- package/dist/components/primitives/Divider.svelte +30 -0
- package/dist/components/primitives/Divider.svelte.d.ts +5 -0
- package/dist/components/primitives/Icon.svelte +9 -0
- package/dist/components/primitives/Icon.svelte.d.ts +9 -0
- package/dist/components/primitives/Label.svelte +6 -0
- package/dist/components/primitives/Label.svelte.d.ts +6 -0
- package/dist/components/primitives/Surface.svelte +67 -2
- package/dist/components/primitives/Surface.svelte.d.ts +7 -0
- package/dist/components/primitives/Text.svelte +32 -0
- package/dist/components/primitives/Text.svelte.d.ts +7 -0
- package/dist/components/scenes/ArchiveScene.svelte +10 -0
- package/dist/components/scenes/ArchiveScene.svelte.d.ts +10 -0
- package/dist/components/scenes/DepthScene.svelte +128 -0
- package/dist/components/scenes/DepthScene.svelte.d.ts +36 -0
- package/dist/components/scenes/LogScene.svelte +14 -0
- package/dist/components/scenes/LogScene.svelte.d.ts +14 -0
- package/dist/components/scenes/NarrativeScene.svelte +9 -0
- package/dist/components/scenes/NarrativeScene.svelte.d.ts +9 -0
- package/dist/components/scenes/ReadoutScene.svelte +11 -0
- package/dist/components/scenes/ReadoutScene.svelte.d.ts +11 -0
- package/dist/components/scenes/StageScene.svelte +14 -0
- package/dist/components/scenes/StageScene.svelte.d.ts +14 -0
- package/dist/components/system/AppShell.svelte +62 -0
- package/dist/components/system/AppShell.svelte.d.ts +32 -0
- package/dist/examples/ArcaneShard.svelte +364 -0
- package/dist/examples/ArcaneShard.svelte.d.ts +3 -0
- package/dist/examples/HextechForge.svelte +324 -0
- package/dist/examples/HextechForge.svelte.d.ts +3 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.js +16 -1
- package/dist/styles.css +2 -0
- package/dist/system/actions/echo.js +13 -4
- package/dist/system/actions/resolve.js +20 -6
- package/dist/system/actions/reveal.js +1 -1
- package/dist/system/actions/surface.js +1 -3
- package/dist/system/register.d.ts +1 -1
- package/dist/system/register.js +5 -1
- package/dist/tokens/arcane.css +96 -0
- package/dist/tokens/hextech.css +96 -0
- package/dist/tokens/tokens.css +6 -4
- package/dist/tokens/tokens.d.ts +41 -0
- package/dist/tokens/tokens.js +41 -0
- package/package.json +6 -2
|
@@ -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,6 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { cn } from '../../utils/cn.js';
|
|
3
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
|
+
*/
|
|
4
10
|
interface Props {
|
|
5
11
|
/** Glyph variant. */
|
|
6
12
|
variant?: 'cross' | 'reticle' | 'coord' | 'mark';
|
|
@@ -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,6 +1,14 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { cn } from '../../utils/cn.js';
|
|
3
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
|
+
*/
|
|
4
12
|
interface Props {
|
|
5
13
|
/** Additional CSS classes. */
|
|
6
14
|
class?: string;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../utils/cn.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Decorative hex grid overlay. Adapts color and character per active register:
|
|
6
|
+
* hextech → cyan precise etching; arcane → violet cracked. Parent must have
|
|
7
|
+
* `position: relative`. Renders `aria-hidden`.
|
|
8
|
+
* @example
|
|
9
|
+
* <div style="position: relative;">
|
|
10
|
+
* <HexGrid />
|
|
11
|
+
* content here
|
|
12
|
+
* </div>
|
|
13
|
+
*/
|
|
14
|
+
interface Props {
|
|
15
|
+
/** Controls animation playback. */
|
|
16
|
+
animated?: boolean;
|
|
17
|
+
/** Override grid opacity (0–1). Defaults to register's --reg-ornament-opacity. */
|
|
18
|
+
opacity?: number | undefined;
|
|
19
|
+
/** Additional CSS classes. */
|
|
20
|
+
class?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let { animated = true, opacity = undefined, class: className = '' }: Props = $props();
|
|
24
|
+
|
|
25
|
+
const prefersReduced =
|
|
26
|
+
typeof window !== 'undefined'
|
|
27
|
+
? window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
28
|
+
: false;
|
|
29
|
+
|
|
30
|
+
const shouldAnimate = $derived(animated && !prefersReduced);
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<div
|
|
34
|
+
class={cn('hyvui-hex-grid', shouldAnimate && 'hyvui-hex-grid--animated', className)}
|
|
35
|
+
style={opacity !== undefined ? `--hex-opacity-override: ${opacity}` : undefined}
|
|
36
|
+
aria-hidden="true"
|
|
37
|
+
></div>
|
|
38
|
+
|
|
39
|
+
<style>
|
|
40
|
+
.hyvui-hex-grid {
|
|
41
|
+
position: absolute;
|
|
42
|
+
inset: 0;
|
|
43
|
+
pointer-events: none;
|
|
44
|
+
|
|
45
|
+
/* Hex pattern via three-angle stripes (vertical + two diagonals).
|
|
46
|
+
Color and opacity come from register tokens so they shift automatically. */
|
|
47
|
+
background-image:
|
|
48
|
+
linear-gradient(to right, var(--hg-color) 1px, transparent 1px),
|
|
49
|
+
linear-gradient(60deg, var(--hg-color) 1px, transparent 1px),
|
|
50
|
+
linear-gradient(-60deg, var(--hg-color) 1px, transparent 1px);
|
|
51
|
+
background-size: 40px 23px;
|
|
52
|
+
|
|
53
|
+
opacity: var(--hex-opacity-override, var(--reg-ornament-opacity));
|
|
54
|
+
mask-image: linear-gradient(to bottom, transparent, black 12%, black 88%, transparent);
|
|
55
|
+
-webkit-mask-image: linear-gradient(
|
|
56
|
+
to bottom,
|
|
57
|
+
transparent,
|
|
58
|
+
black 12%,
|
|
59
|
+
black 88%,
|
|
60
|
+
transparent
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
/* default color (field-notebook) */
|
|
64
|
+
--hg-color: rgba(199, 156, 87, 0.45);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* ── hextech ─ cyan precision ─────────────────────────────────────── */
|
|
68
|
+
:global([data-register='hextech']) .hyvui-hex-grid {
|
|
69
|
+
--hg-color: rgba(93, 217, 240, 0.55);
|
|
70
|
+
background-size: 48px 28px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* ── arcane ─ violet instability ─────────────────────────────────── */
|
|
74
|
+
:global([data-register='arcane']) .hyvui-hex-grid {
|
|
75
|
+
--hg-color: rgba(184, 69, 201, 0.5);
|
|
76
|
+
background-size: 40px 23px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* ── pulse animation ─────────────────────────────────────────────── */
|
|
80
|
+
.hyvui-hex-grid--animated {
|
|
81
|
+
animation: hg-pulse var(--orn-shimmer-rate, 4s) var(--orn-pulse-rhythm, ease-in-out) infinite;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
:global([data-register='arcane']) .hyvui-hex-grid--animated {
|
|
85
|
+
animation:
|
|
86
|
+
hg-pulse var(--orn-shimmer-rate, 2.4s) var(--orn-pulse-rhythm, ease-in-out) infinite,
|
|
87
|
+
hg-flicker 7s step-end infinite;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@keyframes hg-pulse {
|
|
91
|
+
0%,
|
|
92
|
+
100% {
|
|
93
|
+
opacity: var(--hex-opacity-override, var(--reg-ornament-opacity));
|
|
94
|
+
}
|
|
95
|
+
50% {
|
|
96
|
+
opacity: calc(var(--hex-opacity-override, var(--reg-ornament-opacity)) * 1.8);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@keyframes hg-flicker {
|
|
101
|
+
0%,
|
|
102
|
+
97%,
|
|
103
|
+
100% {
|
|
104
|
+
opacity: var(--hex-opacity-override, var(--reg-ornament-opacity));
|
|
105
|
+
}
|
|
106
|
+
98% {
|
|
107
|
+
opacity: 0.02;
|
|
108
|
+
}
|
|
109
|
+
99% {
|
|
110
|
+
opacity: calc(var(--hex-opacity-override, var(--reg-ornament-opacity)) * 2.2);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@media (prefers-reduced-motion: reduce) {
|
|
115
|
+
.hyvui-hex-grid--animated {
|
|
116
|
+
animation: none;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decorative hex grid overlay. Adapts color and character per active register:
|
|
3
|
+
* hextech → cyan precise etching; arcane → violet cracked. Parent must have
|
|
4
|
+
* `position: relative`. Renders `aria-hidden`.
|
|
5
|
+
* @example
|
|
6
|
+
* <div style="position: relative;">
|
|
7
|
+
* <HexGrid />
|
|
8
|
+
* content here
|
|
9
|
+
* </div>
|
|
10
|
+
*/
|
|
11
|
+
interface Props {
|
|
12
|
+
/** Controls animation playback. */
|
|
13
|
+
animated?: boolean;
|
|
14
|
+
/** Override grid opacity (0–1). Defaults to register's --reg-ornament-opacity. */
|
|
15
|
+
opacity?: number | undefined;
|
|
16
|
+
/** Additional CSS classes. */
|
|
17
|
+
class?: string;
|
|
18
|
+
}
|
|
19
|
+
declare const HexGrid: import("svelte").Component<Props, {}, "">;
|
|
20
|
+
type HexGrid = ReturnType<typeof HexGrid>;
|
|
21
|
+
export default HexGrid;
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
import { cn } from '../../utils/cn.js';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Reads `--px` and `--py` CSS custom properties for pointer-driven parallax. Set these on a parent via JS.
|
|
7
|
+
* @example
|
|
8
|
+
* <div onpointermove={trackPointer} style="position:relative;">
|
|
9
|
+
* <ParallaxLayer strength={12}><GlyphMark /></ParallaxLayer>
|
|
10
|
+
* </div>
|
|
11
|
+
*/
|
|
5
12
|
interface Props {
|
|
6
13
|
/** Motion multiplier applied to --px/--py custom properties. */
|
|
7
14
|
strength?: number;
|
|
@@ -25,7 +32,8 @@
|
|
|
25
32
|
<style>
|
|
26
33
|
.hyvui-parallax {
|
|
27
34
|
will-change: transform;
|
|
28
|
-
|
|
35
|
+
backface-visibility: hidden;
|
|
36
|
+
transition: transform 0.15s var(--ease-smooth);
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
+
/**
|
|
3
|
+
* Reads `--px` and `--py` CSS custom properties for pointer-driven parallax. Set these on a parent via JS.
|
|
4
|
+
* @example
|
|
5
|
+
* <div onpointermove={trackPointer} style="position:relative;">
|
|
6
|
+
* <ParallaxLayer strength={12}><GlyphMark /></ParallaxLayer>
|
|
7
|
+
* </div>
|
|
8
|
+
*/
|
|
2
9
|
interface Props {
|
|
3
10
|
/** Motion multiplier applied to --px/--py custom properties. */
|
|
4
11
|
strength?: number;
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { cn } from '../../utils/cn.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Decorative. Parent must have `position: relative`. Renders `aria-hidden`.
|
|
6
|
+
* @example
|
|
7
|
+
* <div style="position: relative;">
|
|
8
|
+
* <ScanBand axis="x" duration="6s" />
|
|
9
|
+
* content with scan line
|
|
10
|
+
* </div>
|
|
11
|
+
*/
|
|
4
12
|
interface Props {
|
|
5
13
|
/** Enable the scan animation. */
|
|
6
14
|
active?: boolean;
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decorative. Parent must have `position: relative`. Renders `aria-hidden`.
|
|
3
|
+
* @example
|
|
4
|
+
* <div style="position: relative;">
|
|
5
|
+
* <ScanBand axis="x" duration="6s" />
|
|
6
|
+
* content with scan line
|
|
7
|
+
* </div>
|
|
8
|
+
*/
|
|
1
9
|
interface Props {
|
|
2
10
|
/** Enable the scan animation. */
|
|
3
11
|
active?: boolean;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../utils/cn.js';
|
|
3
|
+
import { onMount } from 'svelte';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Particle-smoke ambient effect using canvas.
|
|
7
|
+
* Under `hextech`: slow blue-mist dots, precise motion.
|
|
8
|
+
* Under `arcane`: pink/violet shimmer drift, chaotic.
|
|
9
|
+
* Parent must have `position: relative`. Renders `aria-hidden`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* <div style="position: relative;">
|
|
13
|
+
* <ShimmerCloud />
|
|
14
|
+
* content
|
|
15
|
+
* </div>
|
|
16
|
+
*/
|
|
17
|
+
interface Props {
|
|
18
|
+
/** Particle count. */
|
|
19
|
+
count?: number;
|
|
20
|
+
/** Additional CSS classes. */
|
|
21
|
+
class?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let { count = 28, class: className = '' }: Props = $props();
|
|
25
|
+
|
|
26
|
+
const prefersReduced =
|
|
27
|
+
typeof window !== 'undefined'
|
|
28
|
+
? window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
29
|
+
: false;
|
|
30
|
+
|
|
31
|
+
let canvas: HTMLCanvasElement | undefined = $state();
|
|
32
|
+
let rafId: number | undefined;
|
|
33
|
+
|
|
34
|
+
type Particle = {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
r: number;
|
|
38
|
+
vx: number;
|
|
39
|
+
vy: number;
|
|
40
|
+
alpha: number;
|
|
41
|
+
alphaDir: number;
|
|
42
|
+
alphaSpeed: number;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function getRegister(): string {
|
|
46
|
+
if (typeof document === 'undefined') return '';
|
|
47
|
+
return document.body.dataset.register ?? '';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getParticleColor(register: string): string {
|
|
51
|
+
if (register === 'hextech') return '93, 217, 240';
|
|
52
|
+
if (register === 'arcane') return '184, 69, 201';
|
|
53
|
+
return '199, 156, 87';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getParticleColorB(register: string): string {
|
|
57
|
+
// Second color for arcane (two-color particles add richness)
|
|
58
|
+
if (register === 'arcane') return '233, 76, 188';
|
|
59
|
+
return getParticleColor(register);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
onMount(() => {
|
|
63
|
+
if (prefersReduced || !canvas) return;
|
|
64
|
+
|
|
65
|
+
const ctx = canvas.getContext('2d');
|
|
66
|
+
if (!ctx) return;
|
|
67
|
+
|
|
68
|
+
let particles: Particle[] = [];
|
|
69
|
+
|
|
70
|
+
function resize() {
|
|
71
|
+
if (!canvas || !canvas.parentElement) return;
|
|
72
|
+
const { width, height } = canvas.parentElement.getBoundingClientRect();
|
|
73
|
+
canvas.width = width;
|
|
74
|
+
canvas.height = height;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function spawn(): Particle {
|
|
78
|
+
const w = canvas?.width ?? 400;
|
|
79
|
+
const h = canvas?.height ?? 300;
|
|
80
|
+
const register = getRegister();
|
|
81
|
+
const fast = register === 'arcane';
|
|
82
|
+
return {
|
|
83
|
+
x: Math.random() * w,
|
|
84
|
+
y: Math.random() * h,
|
|
85
|
+
r: 1 + Math.random() * (fast ? 3 : 2),
|
|
86
|
+
vx: (Math.random() - 0.5) * (fast ? 0.45 : 0.2),
|
|
87
|
+
vy: -(Math.random() * (fast ? 0.5 : 0.3) + 0.05),
|
|
88
|
+
alpha: Math.random() * 0.3,
|
|
89
|
+
alphaDir: 1,
|
|
90
|
+
alphaSpeed: 0.003 + Math.random() * (fast ? 0.008 : 0.004)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
resize();
|
|
95
|
+
particles = Array.from({ length: count }, spawn);
|
|
96
|
+
|
|
97
|
+
const ro = new ResizeObserver(resize);
|
|
98
|
+
if (canvas.parentElement) ro.observe(canvas.parentElement);
|
|
99
|
+
|
|
100
|
+
let io_visible = true;
|
|
101
|
+
const io = new IntersectionObserver((entries) => {
|
|
102
|
+
io_visible = entries[0]?.isIntersecting ?? true;
|
|
103
|
+
});
|
|
104
|
+
io.observe(canvas);
|
|
105
|
+
|
|
106
|
+
function draw() {
|
|
107
|
+
if (!ctx || !canvas) return;
|
|
108
|
+
const register = getRegister();
|
|
109
|
+
const colorA = getParticleColor(register);
|
|
110
|
+
const colorB = getParticleColorB(register);
|
|
111
|
+
|
|
112
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
113
|
+
|
|
114
|
+
if (io_visible) {
|
|
115
|
+
particles.forEach((p, i) => {
|
|
116
|
+
// breathing alpha
|
|
117
|
+
p.alpha += p.alphaDir * p.alphaSpeed;
|
|
118
|
+
if (p.alpha >= (register === 'arcane' ? 0.38 : 0.22)) p.alphaDir = -1;
|
|
119
|
+
if (p.alpha <= 0.02) p.alphaDir = 1;
|
|
120
|
+
|
|
121
|
+
// drift
|
|
122
|
+
p.x += p.vx;
|
|
123
|
+
p.y += p.vy;
|
|
124
|
+
|
|
125
|
+
// wrap
|
|
126
|
+
if (p.y < -10) p.y = canvas.height + 10;
|
|
127
|
+
if (p.x < -10) p.x = canvas.width + 10;
|
|
128
|
+
if (p.x > canvas.width + 10) p.x = -10;
|
|
129
|
+
|
|
130
|
+
const color = i % 2 === 0 ? colorA : colorB;
|
|
131
|
+
ctx.beginPath();
|
|
132
|
+
ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
|
|
133
|
+
ctx.fillStyle = `rgba(${color}, ${p.alpha})`;
|
|
134
|
+
ctx.fill();
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
rafId = requestAnimationFrame(draw);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
rafId = requestAnimationFrame(draw);
|
|
142
|
+
|
|
143
|
+
return () => {
|
|
144
|
+
if (rafId !== undefined) cancelAnimationFrame(rafId);
|
|
145
|
+
ro.disconnect();
|
|
146
|
+
io.disconnect();
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
</script>
|
|
150
|
+
|
|
151
|
+
<canvas
|
|
152
|
+
bind:this={canvas}
|
|
153
|
+
class={cn('hyvui-shimmer-cloud', className)}
|
|
154
|
+
aria-hidden="true"
|
|
155
|
+
></canvas>
|
|
156
|
+
|
|
157
|
+
<style>
|
|
158
|
+
.hyvui-shimmer-cloud {
|
|
159
|
+
position: absolute;
|
|
160
|
+
inset: 0;
|
|
161
|
+
width: 100%;
|
|
162
|
+
height: 100%;
|
|
163
|
+
pointer-events: none;
|
|
164
|
+
opacity: 0.7;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
:global([data-register='hextech']) .hyvui-shimmer-cloud {
|
|
168
|
+
opacity: 0.55;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
:global([data-register='arcane']) .hyvui-shimmer-cloud {
|
|
172
|
+
opacity: 0.85;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@media (prefers-reduced-motion: reduce) {
|
|
176
|
+
.hyvui-shimmer-cloud {
|
|
177
|
+
display: none;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Particle-smoke ambient effect using canvas.
|
|
3
|
+
* Under `hextech`: slow blue-mist dots, precise motion.
|
|
4
|
+
* Under `arcane`: pink/violet shimmer drift, chaotic.
|
|
5
|
+
* Parent must have `position: relative`. Renders `aria-hidden`.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* <div style="position: relative;">
|
|
9
|
+
* <ShimmerCloud />
|
|
10
|
+
* content
|
|
11
|
+
* </div>
|
|
12
|
+
*/
|
|
13
|
+
interface Props {
|
|
14
|
+
/** Particle count. */
|
|
15
|
+
count?: number;
|
|
16
|
+
/** Additional CSS classes. */
|
|
17
|
+
class?: string;
|
|
18
|
+
}
|
|
19
|
+
declare const ShimmerCloud: import("svelte").Component<Props, {}, "">;
|
|
20
|
+
type ShimmerCloud = ReturnType<typeof ShimmerCloud>;
|
|
21
|
+
export default ShimmerCloud;
|