@atmo-dev/kit 0.4.0 → 0.5.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 (144) hide show
  1. package/README.md +35 -0
  2. package/dist/events/DatePicker.svelte +222 -0
  3. package/dist/events/DatePicker.svelte.d.ts +12 -0
  4. package/dist/events/DateTimePicker.svelte +112 -0
  5. package/dist/events/DateTimePicker.svelte.d.ts +10 -0
  6. package/dist/events/EventAttendees.svelte +199 -0
  7. package/dist/events/EventAttendees.svelte.d.ts +19 -0
  8. package/dist/events/EventCard.svelte +148 -0
  9. package/dist/events/EventCard.svelte.d.ts +8 -0
  10. package/dist/events/EventComments.svelte +98 -0
  11. package/dist/events/EventComments.svelte.d.ts +8 -0
  12. package/dist/events/EventEditor.svelte +540 -0
  13. package/dist/events/EventEditor.svelte.d.ts +18 -0
  14. package/dist/events/EventRsvp.svelte +178 -0
  15. package/dist/events/EventRsvp.svelte.d.ts +16 -0
  16. package/dist/events/EventView.svelte +488 -0
  17. package/dist/events/EventView.svelte.d.ts +23 -0
  18. package/dist/events/ImageDropper.svelte +66 -0
  19. package/dist/events/ImageDropper.svelte.d.ts +7 -0
  20. package/dist/events/Map.svelte +36 -0
  21. package/dist/events/Map.svelte.d.ts +8 -0
  22. package/dist/events/PostToBlueskyModal.svelte +246 -0
  23. package/dist/events/PostToBlueskyModal.svelte.d.ts +22 -0
  24. package/dist/events/ShareModal.svelte +174 -0
  25. package/dist/events/ShareModal.svelte.d.ts +23 -0
  26. package/dist/events/StarterPackButton.svelte +72 -0
  27. package/dist/events/StarterPackButton.svelte.d.ts +10 -0
  28. package/dist/events/ThemeApply.svelte +30 -0
  29. package/dist/events/ThemeApply.svelte.d.ts +7 -0
  30. package/dist/events/ThemeBackground.svelte +33 -0
  31. package/dist/events/ThemeBackground.svelte.d.ts +7 -0
  32. package/dist/events/ThemePicker.svelte +104 -0
  33. package/dist/events/ThemePicker.svelte.d.ts +7 -0
  34. package/dist/events/ThumbnailPresets.svelte +71 -0
  35. package/dist/events/ThumbnailPresets.svelte.d.ts +11 -0
  36. package/dist/events/TimePicker.svelte +117 -0
  37. package/dist/events/TimePicker.svelte.d.ts +10 -0
  38. package/dist/events/TimezonePicker.svelte +67 -0
  39. package/dist/events/TimezonePicker.svelte.d.ts +6 -0
  40. package/dist/events/VodPlayer.svelte +154 -0
  41. package/dist/events/VodPlayer.svelte.d.ts +14 -0
  42. package/dist/events/VodTranscript.svelte +75 -0
  43. package/dist/events/VodTranscript.svelte.d.ts +8 -0
  44. package/dist/events/atproto-helpers.d.ts +21 -0
  45. package/dist/events/atproto-helpers.js +61 -0
  46. package/dist/events/cal/helper.d.ts +1 -0
  47. package/dist/events/cal/helper.js +20 -0
  48. package/dist/events/cal/ical.d.ts +22 -0
  49. package/dist/events/cal/ical.js +188 -0
  50. package/dist/events/cal/sanitize.d.ts +3 -0
  51. package/dist/events/cal/sanitize.js +25 -0
  52. package/dist/events/conference.d.ts +65 -0
  53. package/dist/events/conference.js +61 -0
  54. package/dist/events/contrail.d.ts +49 -0
  55. package/dist/events/contrail.js +12 -0
  56. package/dist/events/date-format.d.ts +22 -0
  57. package/dist/events/date-format.js +43 -0
  58. package/dist/events/editor/LinkedRecordsPicker.svelte +104 -0
  59. package/dist/events/editor/LinkedRecordsPicker.svelte.d.ts +12 -0
  60. package/dist/events/editor/LinksSection.svelte +154 -0
  61. package/dist/events/editor/LinksSection.svelte.d.ts +13 -0
  62. package/dist/events/editor/LocationSection.svelte +163 -0
  63. package/dist/events/editor/LocationSection.svelte.d.ts +8 -0
  64. package/dist/events/editor/RecurringModal.svelte +313 -0
  65. package/dist/events/editor/RecurringModal.svelte.d.ts +30 -0
  66. package/dist/events/editor/ThemeSection.svelte +24 -0
  67. package/dist/events/editor/ThemeSection.svelte.d.ts +7 -0
  68. package/dist/events/editor/ThumbnailSection.svelte +181 -0
  69. package/dist/events/editor/ThumbnailSection.svelte.d.ts +13 -0
  70. package/dist/events/editor/adapter.d.ts +73 -0
  71. package/dist/events/editor/adapter.js +9 -0
  72. package/dist/events/editor/location.d.ts +16 -0
  73. package/dist/events/editor/location.js +50 -0
  74. package/dist/events/editor/save.d.ts +43 -0
  75. package/dist/events/editor/save.js +168 -0
  76. package/dist/events/editor/types.d.ts +39 -0
  77. package/dist/events/editor/types.js +9 -0
  78. package/dist/events/event-media.d.ts +4 -0
  79. package/dist/events/event-media.js +4 -0
  80. package/dist/events/event-types.d.ts +79 -0
  81. package/dist/events/event-types.js +11 -0
  82. package/dist/events/event-view/AddToCalendarButton.svelte +31 -0
  83. package/dist/events/event-view/AddToCalendarButton.svelte.d.ts +9 -0
  84. package/dist/events/event-view/EventBadges.svelte +20 -0
  85. package/dist/events/event-view/EventBadges.svelte.d.ts +7 -0
  86. package/dist/events/event-view/EventDateBlock.svelte +43 -0
  87. package/dist/events/event-view/EventDateBlock.svelte.d.ts +7 -0
  88. package/dist/events/event-view/EventHostedBy.svelte +61 -0
  89. package/dist/events/event-view/EventHostedBy.svelte.d.ts +16 -0
  90. package/dist/events/event-view/EventLinksList.svelte +24 -0
  91. package/dist/events/event-view/EventLinksList.svelte.d.ts +9 -0
  92. package/dist/events/event-view/EventLocationBlock.svelte +62 -0
  93. package/dist/events/event-view/EventLocationBlock.svelte.d.ts +7 -0
  94. package/dist/events/event-view/EventLocationMap.svelte +66 -0
  95. package/dist/events/event-view/EventLocationMap.svelte.d.ts +7 -0
  96. package/dist/events/event-view/ExternalRsvpNotice.svelte +34 -0
  97. package/dist/events/event-view/ExternalRsvpNotice.svelte.d.ts +6 -0
  98. package/dist/events/event-view/StreamPlacePlayer.svelte +209 -0
  99. package/dist/events/event-view/StreamPlacePlayer.svelte.d.ts +8 -0
  100. package/dist/events/event-view/format.d.ts +10 -0
  101. package/dist/events/event-view/format.js +112 -0
  102. package/dist/events/event-view/locations.d.ts +36 -0
  103. package/dist/events/event-view/locations.js +243 -0
  104. package/dist/events/event-view/plyr-icons.d.ts +3 -0
  105. package/dist/events/event-view/plyr-icons.js +46 -0
  106. package/dist/events/linked-records.d.ts +18 -0
  107. package/dist/events/linked-records.js +11 -0
  108. package/dist/events/profile-url.d.ts +3 -0
  109. package/dist/events/profile-url.js +11 -0
  110. package/dist/events/schedule/ConferenceTimetable.svelte +340 -0
  111. package/dist/events/schedule/ConferenceTimetable.svelte.d.ts +22 -0
  112. package/dist/events/schedule/DaySchedule.svelte +298 -0
  113. package/dist/events/schedule/DaySchedule.svelte.d.ts +26 -0
  114. package/dist/events/schedule/ScheduleEventCell.svelte +166 -0
  115. package/dist/events/schedule/ScheduleEventCell.svelte.d.ts +25 -0
  116. package/dist/events/schedule/schedule-utils.d.ts +44 -0
  117. package/dist/events/schedule/schedule-utils.js +166 -0
  118. package/dist/events/starter-pack-url.d.ts +3 -0
  119. package/dist/events/starter-pack-url.js +16 -0
  120. package/dist/events/theme.d.ts +9 -0
  121. package/dist/events/theme.js +36 -0
  122. package/dist/events/themes/Blobs.svelte +64 -0
  123. package/dist/events/themes/Blobs.svelte.d.ts +18 -0
  124. package/dist/events/themes/Butterflies.svelte +183 -0
  125. package/dist/events/themes/Butterflies.svelte.d.ts +3 -0
  126. package/dist/events/themes/Fireflies.svelte +134 -0
  127. package/dist/events/themes/Fireflies.svelte.d.ts +3 -0
  128. package/dist/events/themes/Kaleidoscope.svelte +183 -0
  129. package/dist/events/themes/Kaleidoscope.svelte.d.ts +3 -0
  130. package/dist/events/themes/Matrix.svelte +153 -0
  131. package/dist/events/themes/Matrix.svelte.d.ts +3 -0
  132. package/dist/events/themes/Stars.svelte +98 -0
  133. package/dist/events/themes/Stars.svelte.d.ts +3 -0
  134. package/dist/events/thumbnails/designs.d.ts +18 -0
  135. package/dist/events/thumbnails/designs.js +316 -0
  136. package/dist/events/view-data.d.ts +38 -0
  137. package/dist/events/view-data.js +1 -0
  138. package/dist/events-data.d.ts +15 -0
  139. package/dist/events-data.js +9 -0
  140. package/dist/events-editor.d.ts +2 -0
  141. package/dist/events-editor.js +2 -0
  142. package/dist/events.d.ts +19 -0
  143. package/dist/events.js +17 -0
  144. package/package.json +46 -4
@@ -0,0 +1,183 @@
1
+ <script lang="ts">
2
+ import { BROWSER as browser } from 'esm-env';
3
+
4
+ let canvas: HTMLCanvasElement | undefined = $state(undefined);
5
+
6
+ $effect(() => {
7
+ if (!canvas || !browser) return;
8
+
9
+ const ctx = canvas.getContext('2d')!;
10
+ let animId: number;
11
+
12
+ const SEGMENTS = 12;
13
+ const ROTATION_SPEED = 0.06;
14
+
15
+ let lastWidth = 0;
16
+ function resize() {
17
+ const w = window.innerWidth;
18
+ if (w === lastWidth) return;
19
+ lastWidth = w;
20
+ canvas!.width = w;
21
+ canvas!.height = window.screen.height;
22
+ }
23
+ resize();
24
+ window.addEventListener('resize', resize);
25
+
26
+ const accentColor = getComputedStyle(document.documentElement)
27
+ .getPropertyValue('--color-accent-500')
28
+ .trim();
29
+
30
+ // Animated blobs in normalized 0-1 space
31
+ const BLOB_COUNT = 20;
32
+ interface Blob {
33
+ x: number;
34
+ y: number;
35
+ vx: number;
36
+ vy: number;
37
+ size: number;
38
+ hueShift: number;
39
+ alpha: number;
40
+ }
41
+
42
+ const blobs: (Blob & { sharp?: boolean })[] = [
43
+ ...Array.from({ length: BLOB_COUNT }, (): Blob => ({
44
+ x: Math.random(),
45
+ y: Math.random() * 0.8,
46
+ vx: (Math.random() - 0.5) * 0.04,
47
+ vy: (Math.random() - 0.5) * 0.04,
48
+ size: 0.04 + Math.random() * 0.1,
49
+ hueShift: (Math.random() - 0.5) * 80,
50
+ alpha: 0.15 + Math.random() * 0.35
51
+ })),
52
+ // Small sharp dots
53
+ ...Array.from({ length: 10 }, () => ({
54
+ x: Math.random(),
55
+ y: Math.random() * 0.8,
56
+ vx: (Math.random() - 0.5) * 0.06,
57
+ vy: (Math.random() - 0.5) * 0.06,
58
+ size: 0.005 + Math.random() * 0.012,
59
+ hueShift: (Math.random() - 0.5) * 80,
60
+ alpha: 0.15 + Math.random() * 0.2,
61
+ sharp: true
62
+ }))
63
+ ];
64
+
65
+ // Offscreen canvas for one triangle slice
66
+ const sliceCanvas = document.createElement('canvas');
67
+ const sliceCtx = sliceCanvas.getContext('2d')!;
68
+
69
+ let lastTime = performance.now();
70
+ let globalRotation = 0;
71
+
72
+ function renderSlice(r: number, dt: number) {
73
+ const segAngle = Math.PI / SEGMENTS; // half of full segment
74
+ const sliceW = Math.ceil(r);
75
+ const sliceH = Math.ceil(Math.sin(segAngle) * r);
76
+
77
+ sliceCanvas.width = sliceW;
78
+ sliceCanvas.height = sliceH;
79
+ sliceCtx.clearRect(0, 0, sliceW, sliceH);
80
+
81
+ // Clip to the triangle
82
+ sliceCtx.save();
83
+ sliceCtx.beginPath();
84
+ sliceCtx.moveTo(0, 0);
85
+ sliceCtx.lineTo(sliceW, 0);
86
+ sliceCtx.lineTo(Math.cos(segAngle) * r, Math.sin(segAngle) * r);
87
+ sliceCtx.closePath();
88
+ sliceCtx.clip();
89
+
90
+ for (const b of blobs) {
91
+ b.x += b.vx * dt;
92
+ b.y += b.vy * dt;
93
+ if (b.x < 0 || b.x > 1) b.vx *= -1;
94
+ if (b.y < 0 || b.y > 1) b.vy *= -1;
95
+ b.x = Math.max(0, Math.min(1, b.x));
96
+ b.y = Math.max(0, Math.min(1, b.y));
97
+
98
+ const px = b.x * sliceW;
99
+ const py = b.y * sliceH;
100
+ const br = b.size * sliceW;
101
+
102
+ if (b.sharp) {
103
+ sliceCtx.fillStyle = accentColor
104
+ ? `oklch(from ${accentColor} calc(l * 1.4) c calc(h + ${b.hueShift}) / ${b.alpha})`
105
+ : `rgba(230, 210, 255, ${b.alpha})`;
106
+ sliceCtx.beginPath();
107
+ sliceCtx.arc(px, py, br, 0, Math.PI * 2);
108
+ sliceCtx.fill();
109
+ } else {
110
+ const g = sliceCtx.createRadialGradient(px, py, 0, px, py, br);
111
+ g.addColorStop(
112
+ 0,
113
+ accentColor
114
+ ? `oklch(from ${accentColor} calc(l * 1.2) c calc(h + ${b.hueShift}) / ${b.alpha})`
115
+ : `rgba(200, 150, 255, ${b.alpha})`
116
+ );
117
+ g.addColorStop(
118
+ 0.5,
119
+ accentColor
120
+ ? `oklch(from ${accentColor} l c calc(h + ${b.hueShift}) / ${b.alpha * 0.3})`
121
+ : `rgba(200, 150, 255, ${b.alpha * 0.3})`
122
+ );
123
+ g.addColorStop(1, 'transparent');
124
+ sliceCtx.fillStyle = g;
125
+ sliceCtx.fillRect(px - br, py - br, br * 2, br * 2);
126
+ }
127
+ }
128
+
129
+ sliceCtx.restore();
130
+ return { sliceW, sliceH };
131
+ }
132
+
133
+ function draw(now: number) {
134
+ const dt = Math.min((now - lastTime) / 1000, 0.1);
135
+ lastTime = now;
136
+
137
+ const w = canvas!.width;
138
+ const h = canvas!.height;
139
+ const cx = w / 2;
140
+ const cy = h / 2;
141
+ const maxR = Math.hypot(cx, cy);
142
+
143
+ globalRotation += ROTATION_SPEED * dt;
144
+
145
+ renderSlice(maxR, dt);
146
+
147
+ ctx.clearRect(0, 0, w, h);
148
+ ctx.save();
149
+ ctx.translate(cx, cy);
150
+ ctx.rotate(globalRotation);
151
+
152
+ const segAngle = (Math.PI * 2) / SEGMENTS;
153
+
154
+ for (let i = 0; i < SEGMENTS; i++) {
155
+ ctx.save();
156
+ ctx.rotate(segAngle * i);
157
+
158
+ // Normal slice
159
+ ctx.drawImage(sliceCanvas, 0, 0);
160
+
161
+ // Mirrored slice (flip along x-axis to fill the other half)
162
+ ctx.scale(1, -1);
163
+ ctx.drawImage(sliceCanvas, 0, 0);
164
+
165
+ ctx.restore();
166
+ }
167
+
168
+ ctx.restore();
169
+ animId = requestAnimationFrame(draw);
170
+ }
171
+
172
+ animId = requestAnimationFrame(draw);
173
+
174
+ return () => {
175
+ cancelAnimationFrame(animId);
176
+ window.removeEventListener('resize', resize);
177
+ };
178
+ });
179
+ </script>
180
+
181
+ <div class="pointer-events-none fixed inset-0 -z-10 bg-base-50 dark:bg-base-900">
182
+ <canvas bind:this={canvas} class="absolute inset-0 h-full w-full opacity-50"></canvas>
183
+ </div>
@@ -0,0 +1,3 @@
1
+ declare const Kaleidoscope: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type Kaleidoscope = ReturnType<typeof Kaleidoscope>;
3
+ export default Kaleidoscope;
@@ -0,0 +1,153 @@
1
+ <script lang="ts">
2
+ import { BROWSER as browser } from 'esm-env';
3
+
4
+ let canvas: HTMLCanvasElement | undefined = $state(undefined);
5
+
6
+ $effect(() => {
7
+ if (!canvas || !browser) return;
8
+
9
+ const ctx = canvas.getContext('2d')!;
10
+ let animId: number;
11
+
12
+ const fontSize = 14;
13
+ const chars =
14
+ 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン0123456789ABCDEF';
15
+
16
+ // Speeds in units per second
17
+ const DROP_SPEED = 8; // rows per second
18
+ const FADE_RATE = 2; // alpha per second for trail fade
19
+ const MUTATE_CHANCE = 0.8; // chance per column per second
20
+
21
+ let lastWidth = 0;
22
+ function resize() {
23
+ const w = window.innerWidth;
24
+ if (w === lastWidth) return;
25
+ lastWidth = w;
26
+ canvas!.width = w;
27
+ canvas!.height = window.screen.height;
28
+ }
29
+ resize();
30
+ window.addEventListener('resize', resize);
31
+
32
+ let columns = Math.floor(canvas.width / fontSize);
33
+ let rows = Math.ceil(canvas.height / fontSize) + 1;
34
+ let drops = new Array(columns).fill(0).map(() => Math.random() * -100);
35
+ let grid: string[][] = Array.from({ length: columns }, () =>
36
+ Array.from({ length: rows }, () => chars[Math.floor(Math.random() * chars.length)])
37
+ );
38
+
39
+ const accentColor = getComputedStyle(document.documentElement)
40
+ .getPropertyValue('--color-accent-500')
41
+ .trim();
42
+
43
+ let bgColor = '';
44
+ function readBgColor() {
45
+ const isDark = document.documentElement.classList.contains('dark');
46
+ bgColor = getComputedStyle(document.documentElement)
47
+ .getPropertyValue(isDark ? '--color-base-900' : '--color-base-50')
48
+ .trim();
49
+ }
50
+ readBgColor();
51
+
52
+ const themeObserver = new MutationObserver(readBgColor);
53
+ themeObserver.observe(document.documentElement, {
54
+ attributes: true,
55
+ attributeFilter: ['class']
56
+ });
57
+
58
+ let lastResize = canvas.width;
59
+ let lastTime = performance.now();
60
+
61
+ function draw(now: number) {
62
+ const dt = Math.min((now - lastTime) / 1000, 0.1); // delta in seconds, capped
63
+ lastTime = now;
64
+
65
+ const w = canvas!.width;
66
+ const h = canvas!.height;
67
+
68
+ if (w !== lastResize) {
69
+ lastResize = w;
70
+ columns = Math.floor(w / fontSize);
71
+ rows = Math.ceil(h / fontSize) + 1;
72
+ drops = new Array(columns).fill(0).map(() => Math.random() * -100);
73
+ grid = Array.from({ length: columns }, () =>
74
+ Array.from({ length: rows }, () => chars[Math.floor(Math.random() * chars.length)])
75
+ );
76
+ }
77
+
78
+ // Randomly mutate characters — framerate independent
79
+ const mutatePerFrame = MUTATE_CHANCE * dt;
80
+ for (let m = 0; m < columns; m++) {
81
+ if (Math.random() < mutatePerFrame) {
82
+ const row = Math.floor(Math.random() * rows);
83
+ grid[m][row] = chars[Math.floor(Math.random() * chars.length)];
84
+ }
85
+ }
86
+
87
+ // Fade trail — framerate independent
88
+ const fadeAlpha = Math.min(1, FADE_RATE * dt);
89
+ ctx.fillStyle = bgColor
90
+ ? `oklch(from ${bgColor} l c h / ${fadeAlpha})`
91
+ : `rgba(0, 0, 0, ${fadeAlpha})`;
92
+ ctx.fillRect(0, 0, w, h);
93
+
94
+ ctx.font = `${fontSize}px monospace`;
95
+
96
+ const dropStep = DROP_SPEED * dt;
97
+
98
+ for (let i = 0; i < columns; i++) {
99
+ if (drops[i] * fontSize > h && Math.random() < 0.5 * dt) {
100
+ drops[i] = 0;
101
+ }
102
+
103
+ if (drops[i] < 0) {
104
+ drops[i] += dropStep;
105
+ continue;
106
+ }
107
+
108
+ const row = Math.floor(drops[i]);
109
+ const y = row * fontSize;
110
+ const gridRow = ((row % rows) + rows) % rows;
111
+ const char = grid[i]?.[gridRow] ?? '0';
112
+
113
+ // Bright head
114
+ ctx.fillStyle = accentColor
115
+ ? `oklch(from ${accentColor} calc(l * 1.3) c h / 0.9)`
116
+ : `rgba(150, 255, 150, 0.9)`;
117
+ ctx.fillText(char, i * fontSize, y);
118
+
119
+ // Dimmer trail chars
120
+ for (let t = 1; t < 3; t++) {
121
+ const trailRow = (((gridRow - t) % rows) + rows) % rows;
122
+ const trailY = y - t * fontSize;
123
+ if (trailY < 0) break;
124
+ const trailAlpha = 0.4 - t * 0.12;
125
+ ctx.fillStyle = accentColor
126
+ ? `oklch(from ${accentColor} l c h / ${trailAlpha})`
127
+ : `rgba(100, 200, 100, ${trailAlpha})`;
128
+ ctx.fillText(grid[i]?.[trailRow] ?? '0', i * fontSize, trailY);
129
+ }
130
+
131
+ drops[i] += dropStep;
132
+ }
133
+
134
+ animId = requestAnimationFrame(draw);
135
+ }
136
+
137
+ // Fill initial background
138
+ ctx.fillStyle = bgColor ? `oklch(from ${bgColor} l c h)` : '#000';
139
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
140
+
141
+ animId = requestAnimationFrame(draw);
142
+
143
+ return () => {
144
+ cancelAnimationFrame(animId);
145
+ window.removeEventListener('resize', resize);
146
+ themeObserver.disconnect();
147
+ };
148
+ });
149
+ </script>
150
+
151
+ <div class="pointer-events-none fixed inset-0 -z-10 bg-base-50 dark:bg-base-900">
152
+ <canvas bind:this={canvas} class="absolute inset-0 h-full w-full opacity-40"></canvas>
153
+ </div>
@@ -0,0 +1,3 @@
1
+ declare const Matrix: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type Matrix = ReturnType<typeof Matrix>;
3
+ export default Matrix;
@@ -0,0 +1,98 @@
1
+ <script lang="ts">
2
+ import { BROWSER as browser } from 'esm-env';
3
+
4
+ let canvas: HTMLCanvasElement | undefined = $state(undefined);
5
+
6
+ $effect(() => {
7
+ if (!canvas || !browser) return;
8
+
9
+ const ctx = canvas.getContext('2d')!;
10
+ let animId: number;
11
+
12
+ const stars: { x: number; y: number; z: number; pz: number }[] = [];
13
+ const COUNT = 600;
14
+ const SPEED = 300; // pixels per second
15
+
16
+ let lastWidth = 0;
17
+ function resize() {
18
+ const w = window.innerWidth;
19
+ if (w === lastWidth) return;
20
+ lastWidth = w;
21
+ canvas!.width = w;
22
+ canvas!.height = window.screen.height;
23
+ }
24
+ resize();
25
+ window.addEventListener('resize', resize);
26
+
27
+ for (let i = 0; i < COUNT; i++) {
28
+ stars.push({
29
+ x: (Math.random() - 0.5) * canvas.width,
30
+ y: (Math.random() - 0.5) * canvas.height,
31
+ z: Math.random() * canvas.width,
32
+ pz: 0
33
+ });
34
+ }
35
+ stars.forEach((s) => (s.pz = s.z));
36
+
37
+ const accentColor = getComputedStyle(document.documentElement)
38
+ .getPropertyValue('--color-accent-500')
39
+ .trim();
40
+
41
+ let lastTime = performance.now();
42
+
43
+ function draw(now: number) {
44
+ const dt = Math.min((now - lastTime) / 1000, 0.1);
45
+ lastTime = now;
46
+
47
+ const w = canvas!.width;
48
+ const h = canvas!.height;
49
+ const cx = w / 2;
50
+ const cy = h / 2;
51
+ const speed = SPEED * dt;
52
+
53
+ ctx.clearRect(0, 0, w, h);
54
+
55
+ for (const star of stars) {
56
+ star.pz = star.z;
57
+ star.z -= speed;
58
+
59
+ if (star.z <= 0) {
60
+ star.x = (Math.random() - 0.5) * w;
61
+ star.y = (Math.random() - 0.5) * h;
62
+ star.z = w;
63
+ star.pz = w;
64
+ }
65
+
66
+ const sx = (star.x / star.z) * w + cx;
67
+ const sy = (star.y / star.z) * h + cy;
68
+ const px = (star.x / star.pz) * w + cx;
69
+ const py = (star.y / star.pz) * h + cy;
70
+
71
+ const size = Math.max(0, (1 - star.z / w) * 4);
72
+ const alpha = Math.max(0, (1 - star.z / w) * 0.9);
73
+
74
+ ctx.beginPath();
75
+ ctx.moveTo(px, py);
76
+ ctx.lineTo(sx, sy);
77
+ ctx.strokeStyle = accentColor
78
+ ? `oklch(from ${accentColor} l c h / ${alpha})`
79
+ : `rgba(255,255,255,${alpha})`;
80
+ ctx.lineWidth = size;
81
+ ctx.stroke();
82
+ }
83
+
84
+ animId = requestAnimationFrame(draw);
85
+ }
86
+
87
+ animId = requestAnimationFrame(draw);
88
+
89
+ return () => {
90
+ cancelAnimationFrame(animId);
91
+ window.removeEventListener('resize', resize);
92
+ };
93
+ });
94
+ </script>
95
+
96
+ <div class="pointer-events-none fixed inset-0 -z-10 bg-base-50 dark:bg-base-900">
97
+ <canvas bind:this={canvas} class="absolute inset-0 h-full w-full opacity-80"></canvas>
98
+ </div>
@@ -0,0 +1,3 @@
1
+ declare const Stars: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type Stars = ReturnType<typeof Stars>;
3
+ export default Stars;
@@ -0,0 +1,18 @@
1
+ export type ThumbnailRenderer = (ctx: CanvasRenderingContext2D, w: number, h: number, name: string, dateStr: string, seed: number, accent: string) => void;
2
+ export declare const gradientMesh: ThumbnailRenderer;
3
+ export declare const boldType: ThumbnailRenderer;
4
+ export declare const minimal: ThumbnailRenderer;
5
+ export declare const geometric: ThumbnailRenderer;
6
+ export declare const darkGradient: ThumbnailRenderer;
7
+ export declare const waves: ThumbnailRenderer;
8
+ /** Textless gradient-mesh preset — built from 6 overlapping radial hotspots
9
+ * placed around a loose 3×2 grid with seeded jitter. Used as the default
10
+ * thumbnail for new events. */
11
+ export declare const plainMesh: ThumbnailRenderer;
12
+ export declare const DEFAULT_PRESET = "plain";
13
+ export declare const designs: Record<string, ThumbnailRenderer>;
14
+ export declare function resolveAccentColor(name?: string): string;
15
+ /** Stable non-zero integer seed derived from a string (e.g. an event rkey).
16
+ * Same input always produces the same seed, so the picker preview matches
17
+ * the uploaded PNG for a given event. */
18
+ export declare function hashSeed(s: string): number;