@rizom/site-rizom 0.2.0-alpha.142

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 (37) hide show
  1. package/dist/index.d.ts +135 -0
  2. package/dist/index.js +31089 -0
  3. package/dist/index.js.map +259 -0
  4. package/package.json +54 -0
  5. package/src/content.ts +9 -0
  6. package/src/contracts.ts +157 -0
  7. package/src/create-site.ts +108 -0
  8. package/src/index.ts +63 -0
  9. package/src/runtime/base-site.ts +13 -0
  10. package/src/runtime/boot/boot.boot.d.ts +2 -0
  11. package/src/runtime/boot/boot.boot.js +83 -0
  12. package/src/runtime/canvases/constellation.canvas.d.ts +2 -0
  13. package/src/runtime/canvases/constellation.canvas.js +307 -0
  14. package/src/runtime/canvases/prelude.canvas.d.ts +2 -0
  15. package/src/runtime/canvases/prelude.canvas.js +193 -0
  16. package/src/runtime/canvases/products.canvas.d.ts +2 -0
  17. package/src/runtime/canvases/roots.canvas.d.ts +2 -0
  18. package/src/runtime/canvases/roots.canvas.js +358 -0
  19. package/src/runtime/canvases/tree.canvas.d.ts +2 -0
  20. package/src/runtime/canvases/tree.canvas.js +544 -0
  21. package/src/runtime/default-layout.tsx +10 -0
  22. package/src/runtime/index.ts +8 -0
  23. package/src/runtime/plugin.ts +147 -0
  24. package/src/ui/Badge.tsx +14 -0
  25. package/src/ui/Button.tsx +56 -0
  26. package/src/ui/Divider.tsx +12 -0
  27. package/src/ui/Footer.tsx +76 -0
  28. package/src/ui/Header.tsx +45 -0
  29. package/src/ui/Section.tsx +22 -0
  30. package/src/ui/SideNav.tsx +22 -0
  31. package/src/ui/cn.ts +1 -0
  32. package/src/ui/external-link.ts +8 -0
  33. package/src/ui/frame.tsx +28 -0
  34. package/src/ui/highlighted-text.tsx +45 -0
  35. package/src/ui/index.ts +21 -0
  36. package/src/ui/site-info-links.ts +24 -0
  37. package/src/ui/types.ts +6 -0
@@ -0,0 +1,358 @@
1
+ (function () {
2
+ const canvas = document.getElementById("heroCanvas");
3
+ if (!canvas) return;
4
+ const W = window.innerWidth;
5
+ const H = window.innerHeight;
6
+ canvas.width = W * dpr;
7
+ canvas.height = H * dpr;
8
+ canvas.style.width = "100%";
9
+ canvas.style.height = "100%";
10
+ const ctx = canvas.getContext("2d");
11
+ ctx.scale(dpr, dpr);
12
+
13
+ const docH = Math.max(document.body.scrollHeight, 5000);
14
+ const stripH = Math.min(docH, 8000);
15
+ let staticCanvas = document.createElement("canvas");
16
+ staticCanvas.width = canvas.width;
17
+ staticCanvas.height = stripH * dpr;
18
+
19
+ let nodes = [];
20
+ let seedPoints = [];
21
+ let builtTheme = null;
22
+
23
+ function buildStatic() {
24
+ const light = isLightMode();
25
+ if (builtTheme === light) return;
26
+ builtTheme = light;
27
+ nodes = [];
28
+ seedPoints = [];
29
+ const rng = createRand(133);
30
+
31
+ staticCanvas = document.createElement("canvas");
32
+ staticCanvas.width = canvas.width;
33
+ staticCanvas.height = stripH * dpr;
34
+ const sctx = staticCanvas.getContext("2d");
35
+ sctx.scale(dpr, dpr);
36
+
37
+ // Ambient subterranean glows scattered throughout the full strip
38
+ const ambientCount = Math.max(6, Math.floor(stripH / 900));
39
+ for (let i = 0; i < ambientCount; i++) {
40
+ const ax = rng.range(W * 0.1, W * 0.9);
41
+ const ay = rng.range(stripH * 0.04, stripH * 0.96);
42
+ const ar = rng.range(W * 0.25, W * 0.55);
43
+ const ag = sctx.createRadialGradient(ax, ay, 0, ax, ay, ar);
44
+ if (!light) {
45
+ ag.addColorStop(0, rgba(C.PURPLE, 0.06));
46
+ ag.addColorStop(0.5, rgba(C.AMBER, 0.018));
47
+ ag.addColorStop(1, rgba(C.BG_DEEP, 0));
48
+ } else {
49
+ ag.addColorStop(0, rgba(C.PURPLE, 0.04));
50
+ ag.addColorStop(1, rgba(C.PURPLE, 0));
51
+ }
52
+ sctx.fillStyle = ag;
53
+ sctx.fillRect(ax - ar, ay - ar, ar * 2, ar * 2);
54
+ }
55
+
56
+ // Recursive root branch — gentle downward bias but can grow in any direction
57
+ function root(x, y, angle, len, w, depth, color, op) {
58
+ if (depth <= 0 || w < 0.18 || len < 4) return;
59
+ const j = rng.range(-0.12, 0.12);
60
+ const downBias = 0.1; // gentle gravity preference
61
+ const ex = x + Math.cos(angle + j) * len;
62
+ const ey = y + Math.sin(angle + j) * len + downBias * len;
63
+ const c1x = x + Math.cos(angle + rng.range(-0.3, 0.3)) * len * 0.35;
64
+ const c1y =
65
+ y +
66
+ Math.sin(angle + rng.range(-0.3, 0.3)) * len * 0.35 +
67
+ downBias * len * 0.3;
68
+ const c2x = x + Math.cos(angle + rng.range(-0.2, 0.2)) * len * 0.7;
69
+ const c2y =
70
+ y +
71
+ Math.sin(angle + rng.range(-0.2, 0.2)) * len * 0.7 +
72
+ downBias * len * 0.6;
73
+ drawGlowBezier(
74
+ sctx,
75
+ [x, y, c1x, c1y, c2x, c2y, ex, ey],
76
+ color,
77
+ w,
78
+ Math.max(2, w * 3),
79
+ op,
80
+ light,
81
+ );
82
+
83
+ if (depth <= 2 || rng.next() < 0.35) {
84
+ const nr = Math.max(0.6, w * 0.5);
85
+ drawGlowNode(sctx, ex, ey, nr, color, op * 0.5, light);
86
+ nodes.push({
87
+ x: ex,
88
+ y: ey,
89
+ r: nr,
90
+ color,
91
+ op: op * 0.5,
92
+ phase: rng.next() * Math.PI * 2,
93
+ });
94
+ }
95
+
96
+ const nb =
97
+ depth > 3 ? Math.floor(rng.range(1, 3)) : Math.floor(rng.range(1, 2));
98
+ for (let i = 0; i < nb; i++) {
99
+ const spread = depth > 3 ? rng.range(0.5, 1.2) : rng.range(0.6, 1.5);
100
+ const newAngle = angle + rng.range(-spread, spread);
101
+ let nc = color;
102
+ if (depth <= 3 && rng.next() < 0.22) nc = C.AMBER_LT;
103
+ else if (rng.next() < 0.3)
104
+ nc = nc === C.PURPLE ? C.PURPLE_LT : C.PURPLE;
105
+ root(
106
+ ex,
107
+ ey,
108
+ newAngle,
109
+ len * rng.range(0.5, 0.78),
110
+ w * rng.range(0.52, 0.74),
111
+ depth - 1,
112
+ nc,
113
+ op * rng.range(0.55, 0.82),
114
+ );
115
+ }
116
+ }
117
+
118
+ // Distribute seed bulbs across the FULL strip via jittered grid.
119
+ // Cols scale with viewport width (mobile floors at 3); desktop also
120
+ // gets shorter rows so the network feels rich top to bottom.
121
+ const cols = Math.max(3, Math.round(W / 220));
122
+ const cellW = W / cols;
123
+ const cellH = W < 768 ? 480 : 380;
124
+ const rows = Math.ceil(stripH / cellH);
125
+ for (let r = 0; r < rows; r++) {
126
+ for (let c = 0; c < cols; c++) {
127
+ if (rng.next() < 0.25) continue; // sparse holes
128
+ const sx = c * cellW + rng.range(cellW * 0.1, cellW * 0.9);
129
+ const sy = r * cellH + rng.range(cellH * 0.15, cellH * 0.85);
130
+ if (sy > stripH - 20 || sy < 20) continue;
131
+ seedPoints.push({ x: sx, y: sy });
132
+
133
+ // Bioluminescent seed bulb
134
+ const bulbR = rng.range(2.8, 4.8);
135
+ drawGlowNode(
136
+ sctx,
137
+ sx,
138
+ sy,
139
+ bulbR,
140
+ C.AMBER_LT,
141
+ rng.range(0.55, 0.8),
142
+ light,
143
+ );
144
+ nodes.push({
145
+ x: sx,
146
+ y: sy,
147
+ r: bulbR,
148
+ color: C.AMBER_LT,
149
+ op: 0.72,
150
+ phase: rng.next() * Math.PI * 2,
151
+ isSeed: true,
152
+ });
153
+
154
+ // Local root system from this seed — branches in any direction
155
+ const rootCount = Math.floor(rng.range(1, 3));
156
+ for (let p = 0; p < rootCount; p++) {
157
+ const angle = rng.range(0, Math.PI * 2);
158
+ const len = rng.range(60, 130);
159
+ const w = rng.range(1.2, 2.2);
160
+ root(sx, sy, angle, len, w, 4, C.PURPLE, rng.range(0.35, 0.55));
161
+ }
162
+ }
163
+ }
164
+
165
+ // Lateral rhizomatic interconnects between nearby seeds (any pair, not just adjacent)
166
+ const maxConnect = 260;
167
+ const maxConnect2 = maxConnect * maxConnect;
168
+ for (let i = 0; i < seedPoints.length; i++) {
169
+ const a = seedPoints[i];
170
+ for (let j = i + 1; j < seedPoints.length; j++) {
171
+ const b = seedPoints[j];
172
+ const dx = a.x - b.x;
173
+ const dy = a.y - b.y;
174
+ const d2 = dx * dx + dy * dy;
175
+ if (d2 > maxConnect2) continue;
176
+ if (rng.next() > 0.32) continue; // sparse interconnects
177
+ const midX = (a.x + b.x) / 2 + rng.range(-50, 50);
178
+ const midY = (a.y + b.y) / 2 + rng.range(-30, 70); // mild downward dip
179
+ drawGlowBezier(
180
+ sctx,
181
+ [
182
+ a.x,
183
+ a.y,
184
+ a.x + (midX - a.x) * 0.5,
185
+ a.y + (midY - a.y) * 0.4,
186
+ midX + (b.x - midX) * 0.4,
187
+ midY + (b.y - midY) * 0.5,
188
+ b.x,
189
+ b.y,
190
+ ],
191
+ rng.next() < 0.7 ? C.PURPLE : C.PURPLE_LT,
192
+ rng.range(0.5, 1.1),
193
+ 4,
194
+ rng.range(0.14, 0.26),
195
+ light,
196
+ );
197
+ }
198
+ }
199
+
200
+ // Background capillary fibers — count tracks seed density so the
201
+ // ambient texture scales with viewport (not a fixed number)
202
+ const capCount = Math.floor(seedPoints.length * 2);
203
+ for (let i = 0; i < capCount; i++) {
204
+ const fx = rng.range(0, W);
205
+ const fy = rng.range(0, stripH);
206
+ const fAngle = rng.range(0, Math.PI * 2);
207
+ const fLen = rng.range(25, 70);
208
+ root(
209
+ fx,
210
+ fy,
211
+ fAngle,
212
+ fLen,
213
+ rng.range(0.4, 0.85),
214
+ 3,
215
+ rng.next() < 0.6 ? C.PURPLE : C.PURPLE_LT,
216
+ rng.range(0.12, 0.22),
217
+ );
218
+ }
219
+ }
220
+
221
+ // Drifting spore particles — gentle ambient motion
222
+ const particles = [];
223
+ const rngP = createRand(211);
224
+ const dustC = [C.PURPLE_LT, C.PURPLE, C.AMBER_LT, C.GLOW];
225
+ for (let i = 0; i < 180; i++) {
226
+ particles.push({
227
+ x: rngP.range(0, W),
228
+ y: rngP.range(0, H),
229
+ r: rngP.range(0.3, 1.2),
230
+ vx: rngP.range(-0.04, 0.04),
231
+ vy: rngP.range(0.02, 0.1),
232
+ color: dustC[Math.floor(rngP.next() * dustC.length)],
233
+ alpha: rngP.range(0.04, 0.15),
234
+ phase: rngP.next() * Math.PI * 2,
235
+ });
236
+ }
237
+
238
+ buildStatic();
239
+ window._heroRebuild = function () {
240
+ builtTheme = null;
241
+ buildStatic();
242
+ };
243
+
244
+ // Flowing nutrient pulses spawn at random seed bulbs throughout the strip
245
+ let flows = [];
246
+ let lastFlow = 0;
247
+
248
+ function spawnFlow() {
249
+ if (!seedPoints.length) return;
250
+ const seed = seedPoints[Math.floor(Math.random() * seedPoints.length)];
251
+ flows.push({
252
+ x: seed.x + (Math.random() - 0.5) * 14,
253
+ y: seed.y,
254
+ vy: 60 + Math.random() * 50,
255
+ vx: (Math.random() - 0.5) * 30,
256
+ life: 0,
257
+ maxLife: 5 + Math.random() * 4,
258
+ color: Math.random() < 0.72 ? C.AMBER_LT : C.PURPLE_LT,
259
+ });
260
+ }
261
+
262
+ let t = 0,
263
+ lastTime = 0;
264
+ function animate(timestamp) {
265
+ if (document.hidden) {
266
+ requestAnimationFrame(animate);
267
+ return;
268
+ }
269
+ const dt = lastTime ? Math.min((timestamp - lastTime) / 1000, 0.05) : 0.016;
270
+ lastTime = timestamp;
271
+ t += dt;
272
+
273
+ const light = isLightMode();
274
+ const scrollY = window.scrollY || window.pageYOffset;
275
+ const scrollRatio = (scrollY * 0.7) / Math.max(1, docH - H);
276
+ const srcY = scrollRatio * (stripH - H);
277
+
278
+ ctx.clearRect(0, 0, W, H);
279
+ ctx.drawImage(staticCanvas, 0, srcY * dpr, W * dpr, H * dpr, 0, 0, W, H);
280
+
281
+ // Drifting spore particles (viewport-local)
282
+ particles.forEach((p) => {
283
+ p.x += p.vx;
284
+ p.y += p.vy;
285
+ if (p.x < 0) p.x = W;
286
+ if (p.x > W) p.x = 0;
287
+ if (p.y < 0) p.y = H;
288
+ if (p.y > H) p.y = 0;
289
+ const fl = 0.5 + 0.5 * Math.sin(t * 1.5 + p.phase);
290
+ ctx.fillStyle = rgba(p.color, p.alpha * 2 * fl);
291
+ ctx.beginPath();
292
+ ctx.arc(
293
+ p.x,
294
+ p.y,
295
+ p.r * (0.8 + 0.3 * Math.sin(t + p.phase)),
296
+ 0,
297
+ Math.PI * 2,
298
+ );
299
+ ctx.fill();
300
+ });
301
+
302
+ // Spawn + animate flowing nutrients (world-space coords, drawn relative to srcY)
303
+ if (timestamp - lastFlow > 280 && flows.length < 60) {
304
+ lastFlow = timestamp;
305
+ spawnFlow();
306
+ if (Math.random() < 0.5) spawnFlow();
307
+ }
308
+ for (let i = flows.length - 1; i >= 0; i--) {
309
+ const f = flows[i];
310
+ f.x += f.vx * dt + Math.sin(t * 0.5 + i) * 0.4;
311
+ f.y += f.vy * dt;
312
+ f.life += dt;
313
+ if (f.life > f.maxLife || f.y > stripH) {
314
+ flows.splice(i, 1);
315
+ continue;
316
+ }
317
+ const screenY = f.y - srcY;
318
+ if (screenY < -20 || screenY > H + 20) continue;
319
+ const lr = f.life / f.maxLife;
320
+ const alpha = lr < 0.15 ? lr / 0.15 : lr > 0.85 ? (1 - lr) / 0.15 : 1;
321
+ ctx.fillStyle = rgba(f.color, alpha * 0.35);
322
+ ctx.beginPath();
323
+ ctx.arc(f.x, screenY, 6, 0, Math.PI * 2);
324
+ ctx.fill();
325
+ ctx.fillStyle = rgba(f.color, alpha * 0.55);
326
+ ctx.beginPath();
327
+ ctx.arc(f.x, screenY, 2.6, 0, Math.PI * 2);
328
+ ctx.fill();
329
+ ctx.fillStyle = rgba(light ? C.AMBER_DK : C.CORE, alpha * 0.9);
330
+ ctx.beginPath();
331
+ ctx.arc(f.x, screenY, 1.2, 0, Math.PI * 2);
332
+ ctx.fill();
333
+ }
334
+
335
+ // Pulsing nodes — only those visible in current scroll window
336
+ nodes.forEach((n) => {
337
+ const screenY = n.y - srcY;
338
+ if (screenY < -100 || screenY > H + 100) return;
339
+ const pulse = 0.6 + 0.4 * Math.sin(t * 0.8 + n.phase);
340
+ const pr =
341
+ n.r *
342
+ (n.isSeed
343
+ ? 1.4 + Math.sin(t * 0.6 + n.phase) * 0.3
344
+ : 2 + Math.sin(t * 0.7 + n.phase));
345
+ ctx.fillStyle = rgba(n.color, n.op * 0.1 * pulse);
346
+ ctx.beginPath();
347
+ ctx.arc(n.x, screenY, pr * 5, 0, Math.PI * 2);
348
+ ctx.fill();
349
+ ctx.fillStyle = rgba(C.GLOW, n.op * 0.12 * pulse);
350
+ ctx.beginPath();
351
+ ctx.arc(n.x, screenY, pr * 2, 0, Math.PI * 2);
352
+ ctx.fill();
353
+ });
354
+
355
+ requestAnimationFrame(animate);
356
+ }
357
+ requestAnimationFrame(animate);
358
+ })();
@@ -0,0 +1,2 @@
1
+ declare const content: string;
2
+ export default content;