@principal-ai/logo-component 0.1.4 → 0.1.6

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.
@@ -0,0 +1,47 @@
1
+ import React from "react";
2
+ type ChaosMode = "none" | "fragmented";
3
+ type ChartPattern = "latency" | "cpu" | "noise";
4
+ interface OpenTypeTextRevealProps {
5
+ /** The text to display */
6
+ text: string;
7
+ /** URL or path to the font file (.otf, .ttf, .woff) */
8
+ fontUrl: string;
9
+ /** Font size in pixels */
10
+ fontSize?: number;
11
+ /** Width of the SVG container */
12
+ width?: number;
13
+ /** Height of the SVG container */
14
+ height?: number;
15
+ /** Center the text in the container */
16
+ centerText?: boolean;
17
+ /** Show time-series chart intro animation (default: true when chaosMode="fragmented") */
18
+ showChartIntro?: boolean;
19
+ /** Duration the chart is visible before lines fade (default: 1.5s) */
20
+ chartDuration?: number;
21
+ /** Duration for chart lines to fade out (default: 0.5s) */
22
+ chartLineFadeDuration?: number;
23
+ /** Pause duration after lines fade, before dots move (default: 0.3s) */
24
+ chartPauseDuration?: number;
25
+ /** Duration for dots to animate from chart to target positions (default: 0.8s) */
26
+ chartTransitionDuration?: number;
27
+ /** Telemetry pattern style for the chart */
28
+ chartPattern?: ChartPattern;
29
+ chaosMode?: ChaosMode;
30
+ chaosDuration?: number;
31
+ dotsDuration?: number;
32
+ flowDuration?: number;
33
+ flowDelay?: number;
34
+ particlesPerPath?: number;
35
+ particleRadius?: number;
36
+ color?: string;
37
+ particleColor?: string;
38
+ strokeWidth?: number;
39
+ opacity?: number;
40
+ showGlow?: boolean;
41
+ fadeAfterAssembly?: boolean;
42
+ fadeOpacity?: number;
43
+ loop?: boolean;
44
+ loopDelay?: number;
45
+ }
46
+ export declare const OpenTypeTextReveal: React.FC<OpenTypeTextRevealProps>;
47
+ export {};
@@ -0,0 +1,471 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.OpenTypeTextReveal = void 0;
40
+ const react_1 = __importStar(require("react"));
41
+ const opentype_js_1 = __importDefault(require("opentype.js"));
42
+ let globalIdCounter = 0;
43
+ /**
44
+ * Estimates path length from SVG path data including curves.
45
+ */
46
+ function estimatePathLength(d) {
47
+ var _a;
48
+ // Simple estimation - count segments and approximate
49
+ const commands = d.match(/[MLHVCSQTAZ][^MLHVCSQTAZ]*/gi) || [];
50
+ let length = 0;
51
+ let lastX = 0, lastY = 0;
52
+ let startX = 0, startY = 0;
53
+ for (const cmd of commands) {
54
+ const type = cmd[0].toUpperCase();
55
+ const nums = ((_a = cmd.slice(1).match(/-?\d+\.?\d*/g)) === null || _a === void 0 ? void 0 : _a.map(Number)) || [];
56
+ switch (type) {
57
+ case 'M':
58
+ lastX = nums[0] || 0;
59
+ lastY = nums[1] || 0;
60
+ startX = lastX;
61
+ startY = lastY;
62
+ break;
63
+ case 'L':
64
+ if (nums.length >= 2) {
65
+ length += Math.sqrt((nums[0] - lastX) ** 2 + (nums[1] - lastY) ** 2);
66
+ lastX = nums[0];
67
+ lastY = nums[1];
68
+ }
69
+ break;
70
+ case 'H':
71
+ if (nums.length >= 1) {
72
+ length += Math.abs(nums[0] - lastX);
73
+ lastX = nums[0];
74
+ }
75
+ break;
76
+ case 'V':
77
+ if (nums.length >= 1) {
78
+ length += Math.abs(nums[0] - lastY);
79
+ lastY = nums[0];
80
+ }
81
+ break;
82
+ case 'C':
83
+ // Cubic bezier - approximate with chord length * 1.5
84
+ if (nums.length >= 6) {
85
+ const dx = nums[4] - lastX;
86
+ const dy = nums[5] - lastY;
87
+ length += Math.sqrt(dx * dx + dy * dy) * 1.5;
88
+ lastX = nums[4];
89
+ lastY = nums[5];
90
+ }
91
+ break;
92
+ case 'Q':
93
+ // Quadratic bezier - approximate with chord length * 1.3
94
+ if (nums.length >= 4) {
95
+ const dx = nums[2] - lastX;
96
+ const dy = nums[3] - lastY;
97
+ length += Math.sqrt(dx * dx + dy * dy) * 1.3;
98
+ lastX = nums[2];
99
+ lastY = nums[3];
100
+ }
101
+ break;
102
+ case 'Z':
103
+ length += Math.sqrt((startX - lastX) ** 2 + (startY - lastY) ** 2);
104
+ lastX = startX;
105
+ lastY = startY;
106
+ break;
107
+ }
108
+ }
109
+ return length || 100;
110
+ }
111
+ /**
112
+ * Get start and end points from path
113
+ */
114
+ function getPathEndpoints(d) {
115
+ const coords = d.match(/-?\d+\.?\d*/g);
116
+ if (!coords || coords.length < 2) {
117
+ return { start: { x: 0, y: 0 }, end: { x: 0, y: 0 } };
118
+ }
119
+ // Start is first two coords (after M)
120
+ const start = { x: parseFloat(coords[0]), y: parseFloat(coords[1]) };
121
+ // End is last two coords before Z (or just last two)
122
+ const end = {
123
+ x: parseFloat(coords[coords.length - 2]),
124
+ y: parseFloat(coords[coords.length - 1])
125
+ };
126
+ return { start, end };
127
+ }
128
+ /**
129
+ * Seeded random for consistent chaos patterns
130
+ */
131
+ function seededRandom(seed) {
132
+ return () => {
133
+ seed = (seed * 1103515245 + 12345) & 0x7fffffff;
134
+ return seed / 0x7fffffff;
135
+ };
136
+ }
137
+ /**
138
+ * Generate time-series chart positions for dots
139
+ */
140
+ function generateChartPositions(numDots, width, height, pattern, seed) {
141
+ if (numDots === 0)
142
+ return [];
143
+ const random = seededRandom(seed);
144
+ const positions = [];
145
+ // Chart area with padding
146
+ const padding = width * 0.1;
147
+ const chartWidth = width - padding * 2;
148
+ const chartHeight = height * 0.6;
149
+ const chartTop = height * 0.2;
150
+ // Generate y-values based on pattern
151
+ const yValues = [];
152
+ switch (pattern) {
153
+ case "latency": {
154
+ // Mostly stable baseline with occasional spikes
155
+ const baseline = 0.3;
156
+ const numSpikes = Math.max(1, Math.floor(numDots * 0.15)); // ~15% are spikes
157
+ const spikeIndices = new Set();
158
+ // Pick random spike positions
159
+ while (spikeIndices.size < numSpikes) {
160
+ spikeIndices.add(Math.floor(random() * numDots));
161
+ }
162
+ for (let i = 0; i < numDots; i++) {
163
+ if (spikeIndices.has(i)) {
164
+ // Spike: 60-95% height
165
+ yValues.push(0.6 + random() * 0.35);
166
+ }
167
+ else {
168
+ // Baseline with small noise: 20-40%
169
+ yValues.push(baseline + (random() - 0.5) * 0.2);
170
+ }
171
+ }
172
+ break;
173
+ }
174
+ case "cpu": {
175
+ // Sine wave foundation with noise - gradual rises and drops
176
+ const frequency = 2 + random() * 2; // 2-4 cycles across the chart
177
+ for (let i = 0; i < numDots; i++) {
178
+ const t = i / (numDots - 1 || 1);
179
+ const sine = Math.sin(t * Math.PI * frequency) * 0.3;
180
+ const noise = (random() - 0.5) * 0.15;
181
+ yValues.push(0.5 + sine + noise);
182
+ }
183
+ break;
184
+ }
185
+ case "noise":
186
+ default: {
187
+ // Irregular fluctuations using smoothed noise
188
+ let value = 0.5;
189
+ for (let i = 0; i < numDots; i++) {
190
+ // Random walk with mean reversion
191
+ const drift = (0.5 - value) * 0.1; // Pull toward center
192
+ const noise = (random() - 0.5) * 0.25;
193
+ value = Math.max(0.15, Math.min(0.85, value + drift + noise));
194
+ yValues.push(value);
195
+ }
196
+ break;
197
+ }
198
+ }
199
+ // Convert to positions
200
+ for (let i = 0; i < numDots; i++) {
201
+ const x = padding + (i / (numDots - 1 || 1)) * chartWidth;
202
+ // Invert y since SVG y increases downward
203
+ const y = chartTop + (1 - yValues[i]) * chartHeight;
204
+ positions.push({ x, y });
205
+ }
206
+ return positions;
207
+ }
208
+ /**
209
+ * Split compound path into individual contours
210
+ */
211
+ function splitPathIntoContours(d) {
212
+ const contours = [];
213
+ const parts = d.split(/(?=[Mm])/);
214
+ for (const part of parts) {
215
+ const trimmed = part.trim();
216
+ if (trimmed) {
217
+ contours.push(trimmed);
218
+ }
219
+ }
220
+ return contours;
221
+ }
222
+ const OpenTypeTextReveal = ({ text, fontUrl, fontSize = 72, width = 600, height = 150, centerText = true, showChartIntro, chartDuration = 1.5, chartLineFadeDuration = 0.5, chartPauseDuration = 0.3, chartTransitionDuration = 0.8, chartPattern = "latency", chaosMode = "none", chaosDuration = 2, dotsDuration = 1.5, flowDuration = 2, flowDelay = 0.3, particlesPerPath = 1, particleRadius = 2, color = "currentColor", particleColor, strokeWidth = 1.5, opacity = 0.9, showGlow = true, fadeAfterAssembly = true, fadeOpacity = 0.5, loop = true, loopDelay = 1, }) => {
223
+ const idRef = (0, react_1.useRef)(null);
224
+ if (idRef.current === null) {
225
+ idRef.current = `otr${globalIdCounter++}`;
226
+ }
227
+ const uniqueId = idRef.current;
228
+ const finalParticleColor = particleColor || color;
229
+ const isFragmented = chaosMode === "fragmented";
230
+ // Chart intro is on by default when fragmented mode is active
231
+ const shouldShowChartIntro = showChartIntro !== null && showChartIntro !== void 0 ? showChartIntro : isFragmented;
232
+ // Font and path state
233
+ const [font, setFont] = (0, react_1.useState)(null);
234
+ const [error, setError] = (0, react_1.useState)(null);
235
+ const [cycle, setCycle] = (0, react_1.useState)(0);
236
+ // Load font
237
+ (0, react_1.useEffect)(() => {
238
+ let cancelled = false;
239
+ opentype_js_1.default.load(fontUrl)
240
+ .then((loadedFont) => {
241
+ if (!cancelled) {
242
+ setFont(loadedFont);
243
+ setError(null);
244
+ }
245
+ })
246
+ .catch((err) => {
247
+ if (!cancelled) {
248
+ setError(err.message || "Failed to load font");
249
+ }
250
+ });
251
+ return () => {
252
+ cancelled = true;
253
+ };
254
+ }, [fontUrl]);
255
+ // Generate paths from font
256
+ const { paths, textWidth, textHeight } = (0, react_1.useMemo)(() => {
257
+ if (!font) {
258
+ return { paths: [], textWidth: 0, textHeight: fontSize };
259
+ }
260
+ // Get the path for the text
261
+ const textPath = font.getPath(text, 0, fontSize, fontSize);
262
+ const pathData = textPath.toPathData(2); // 2 decimal places
263
+ // Split into individual contours (each letter shape)
264
+ const contours = splitPathIntoContours(pathData);
265
+ const pathInfos = contours.map((d, index) => ({
266
+ d,
267
+ id: `contour-${index}`,
268
+ length: estimatePathLength(d),
269
+ endpoints: getPathEndpoints(d),
270
+ }));
271
+ // Calculate bounds
272
+ const bbox = textPath.getBoundingBox();
273
+ return {
274
+ paths: pathInfos,
275
+ textWidth: bbox.x2 - bbox.x1,
276
+ textHeight: bbox.y2 - bbox.y1,
277
+ };
278
+ }, [font, text, fontSize]);
279
+ // Calculate centering offset
280
+ const offsetX = centerText ? (width - textWidth) / 2 : 0;
281
+ const offsetY = centerText ? (height - textHeight) / 2 - (fontSize * 0.2) : 0;
282
+ // Apply offset to paths
283
+ const resolvedPaths = (0, react_1.useMemo)(() => {
284
+ return paths.map((path) => (Object.assign(Object.assign({}, path), { d: offsetPathData(path.d, offsetX, offsetY), endpoints: {
285
+ start: { x: path.endpoints.start.x + offsetX, y: path.endpoints.start.y + offsetY },
286
+ end: { x: path.endpoints.end.x + offsetX, y: path.endpoints.end.y + offsetY },
287
+ } })));
288
+ }, [paths, offsetX, offsetY]);
289
+ // Generate fragment offsets
290
+ const fragmentOffsets = (0, react_1.useMemo)(() => {
291
+ const random = seededRandom(42);
292
+ return resolvedPaths.map(() => ({
293
+ x: (random() - 0.5) * 150,
294
+ y: (random() - 0.5) * 100,
295
+ }));
296
+ }, [resolvedPaths]);
297
+ // Generate chart positions for the intro animation
298
+ const chartPositions = (0, react_1.useMemo)(() => {
299
+ if (!shouldShowChartIntro)
300
+ return [];
301
+ return generateChartPositions(resolvedPaths.length, width, height, chartPattern, 123);
302
+ }, [shouldShowChartIntro, resolvedPaths.length, width, height, chartPattern]);
303
+ // Target positions for dots after chart phase
304
+ // Always go to final letter positions (path start points)
305
+ const dotTargetPositions = (0, react_1.useMemo)(() => {
306
+ return resolvedPaths.map((path) => path.endpoints.start);
307
+ }, [resolvedPaths]);
308
+ // Chart intro timing
309
+ const chartPhaseEndTime = shouldShowChartIntro
310
+ ? chartDuration + chartLineFadeDuration + chartPauseDuration + chartTransitionDuration
311
+ : 0;
312
+ // Timing calculations (offset by chart phase if present)
313
+ const numPaths = resolvedPaths.length || 1;
314
+ const perItemDotsDuration = (dotsDuration * 0.5) / numPaths;
315
+ const perItemLinesDuration = (dotsDuration * 0.5) / numPaths;
316
+ const perItemAssemblyDuration = chaosDuration / numPaths;
317
+ const dotsPhaseEnd = chartPhaseEndTime + dotsDuration * 0.5;
318
+ const linesPhaseEnd = chartPhaseEndTime + dotsDuration;
319
+ // Skip assembly phase when chart intro handles the transition
320
+ const needsAssembly = isFragmented && !shouldShowChartIntro;
321
+ const assemblyEndTime = needsAssembly
322
+ ? chartPhaseEndTime + dotsDuration + chaosDuration
323
+ : chartPhaseEndTime + dotsDuration;
324
+ const flowBeginTime = assemblyEndTime + flowDelay;
325
+ const totalDuration = flowBeginTime + flowDuration;
326
+ // Loop via remount
327
+ (0, react_1.useEffect)(() => {
328
+ if (!loop)
329
+ return;
330
+ const timeout = setTimeout(() => {
331
+ setCycle((c) => c + 1);
332
+ }, (totalDuration + loopDelay) * 1000);
333
+ return () => clearTimeout(timeout);
334
+ }, [loop, totalDuration, loopDelay, cycle]);
335
+ if (error) {
336
+ return (react_1.default.createElement("svg", { width: width, height: height },
337
+ react_1.default.createElement("text", { x: 10, y: 30, fill: "red", fontSize: 14 },
338
+ "Error: ",
339
+ error)));
340
+ }
341
+ if (!font) {
342
+ return (react_1.default.createElement("svg", { width: width, height: height },
343
+ react_1.default.createElement("text", { x: 10, y: 30, fill: color, fontSize: 14 }, "Loading font...")));
344
+ }
345
+ return (react_1.default.createElement("svg", { key: cycle, width: width, height: height, viewBox: `0 0 ${width} ${height}`, xmlns: "http://www.w3.org/2000/svg", style: { opacity } },
346
+ react_1.default.createElement("defs", null,
347
+ showGlow && (react_1.default.createElement("filter", { id: `glow-${uniqueId}`, x: "-50%", y: "-50%", width: "200%", height: "200%" },
348
+ react_1.default.createElement("feGaussianBlur", { stdDeviation: "2", result: "blur" }),
349
+ react_1.default.createElement("feMerge", null,
350
+ react_1.default.createElement("feMergeNode", { in: "blur" }),
351
+ react_1.default.createElement("feMergeNode", { in: "SourceGraphic" })))),
352
+ react_1.default.createElement("radialGradient", { id: `particleGradient-${uniqueId}`, cx: "50%", cy: "50%", r: "50%" },
353
+ react_1.default.createElement("stop", { offset: "0%", style: { stopColor: finalParticleColor, stopOpacity: 1 } }),
354
+ react_1.default.createElement("stop", { offset: "100%", style: { stopColor: finalParticleColor, stopOpacity: 0.3 } }))),
355
+ shouldShowChartIntro && chartPositions.length > 0 && (react_1.default.createElement("g", { className: "chart-intro" },
356
+ react_1.default.createElement("polyline", { points: chartPositions.map(p => `${p.x},${p.y}`).join(' '), fill: "none", stroke: color, strokeWidth: strokeWidth * 0.75, strokeLinecap: "round", strokeLinejoin: "round", opacity: "0" },
357
+ react_1.default.createElement("animate", { attributeName: "opacity", from: "0", to: "0.6", dur: "0.3s", begin: "0s", fill: "freeze" }),
358
+ react_1.default.createElement("animate", { attributeName: "opacity", from: "0.6", to: "0", dur: `${chartLineFadeDuration}s`, begin: `${chartDuration}s`, fill: "freeze" })),
359
+ chartPositions.map((chartPos, index) => {
360
+ const targetPos = dotTargetPositions[index];
361
+ if (!targetPos)
362
+ return null;
363
+ const dotRadius = strokeWidth;
364
+ const dotAppearDelay = (index / chartPositions.length) * 0.5; // Stagger appearance
365
+ const transitionBegin = chartDuration + chartLineFadeDuration + chartPauseDuration;
366
+ return (react_1.default.createElement("circle", { key: `chart-dot-${index}`, cx: chartPos.x, cy: chartPos.y, r: dotRadius, fill: color, opacity: "0" },
367
+ react_1.default.createElement("animate", { attributeName: "opacity", from: "0", to: "1", dur: "0.15s", begin: `${dotAppearDelay}s`, fill: "freeze" }),
368
+ react_1.default.createElement("animate", { attributeName: "cx", from: chartPos.x, to: targetPos.x, dur: `${chartTransitionDuration}s`, begin: `${transitionBegin}s`, fill: "freeze", calcMode: "spline", keySplines: "0.4 0 0.2 1", keyTimes: "0;1" }),
369
+ react_1.default.createElement("animate", { attributeName: "cy", from: chartPos.y, to: targetPos.y, dur: `${chartTransitionDuration}s`, begin: `${transitionBegin}s`, fill: "freeze", calcMode: "spline", keySplines: "0.4 0 0.2 1", keyTimes: "0;1" }),
370
+ react_1.default.createElement("animate", { attributeName: "opacity", from: "1", to: "0", dur: "0.2s", begin: `${dotsPhaseEnd + (index + 1) * perItemLinesDuration}s`, fill: "freeze" })));
371
+ }))),
372
+ react_1.default.createElement("g", { className: "opentype-paths" }, resolvedPaths.map((path, index) => {
373
+ const offset = fragmentOffsets[index];
374
+ const dotRadius = strokeWidth / 2;
375
+ // Skip fragment offset when chart intro handles the transition
376
+ const useFragmentOffset = isFragmented && !shouldShowChartIntro;
377
+ return (react_1.default.createElement("g", { key: path.id, transform: useFragmentOffset ? `translate(${offset.x}, ${offset.y})` : undefined },
378
+ isFragmented && !shouldShowChartIntro && (react_1.default.createElement(react_1.default.Fragment, null,
379
+ react_1.default.createElement("circle", { cx: path.endpoints.start.x, cy: path.endpoints.start.y, r: dotRadius, fill: color, opacity: "0" },
380
+ react_1.default.createElement("animate", { attributeName: "opacity", from: "0", to: "1", dur: "0.15s", begin: `${chartPhaseEndTime + index * perItemDotsDuration}s`, fill: "freeze" }),
381
+ react_1.default.createElement("animate", { attributeName: "opacity", from: "1", to: "0", dur: "0.2s", begin: `${dotsPhaseEnd + (index + 1) * perItemLinesDuration}s`, fill: "freeze" })))),
382
+ (() => {
383
+ // Determine animation mode
384
+ const shouldDrawLines = isFragmented || shouldShowChartIntro;
385
+ const drawDuration = shouldShowChartIntro && !isFragmented
386
+ ? perItemLinesDuration
387
+ : perItemLinesDuration + chaosDuration;
388
+ return (react_1.default.createElement("path", { d: path.d, fill: "none", stroke: color, strokeWidth: strokeWidth, strokeLinecap: "round", strokeLinejoin: "round", opacity: shouldDrawLines ? 0 : 1, strokeDasharray: shouldDrawLines ? path.length : undefined, strokeDashoffset: shouldDrawLines ? path.length : undefined },
389
+ shouldDrawLines && (react_1.default.createElement(react_1.default.Fragment, null,
390
+ react_1.default.createElement("animate", { attributeName: "opacity", values: `0;1;1;${fadeAfterAssembly ? fadeOpacity : 1}`, keyTimes: "0;0.1;0.9;1", dur: `${drawDuration}s`, begin: `${dotsPhaseEnd + index * perItemLinesDuration}s`, fill: "freeze" }),
391
+ react_1.default.createElement("animate", { attributeName: "stroke-dashoffset", from: path.length, to: "0", dur: `${perItemLinesDuration}s`, begin: `${dotsPhaseEnd + index * perItemLinesDuration}s`, fill: "freeze", calcMode: "spline", keySplines: "0.4 0 0.2 1", keyTimes: "0;1" }))),
392
+ !shouldDrawLines && fadeAfterAssembly && (react_1.default.createElement("animate", { attributeName: "opacity", from: "1", to: fadeOpacity, dur: "0.5s", begin: `${flowBeginTime}s`, fill: "freeze" }))));
393
+ })(),
394
+ useFragmentOffset && (react_1.default.createElement("animateTransform", { attributeName: "transform", type: "translate", from: `${offset.x} ${offset.y}`, to: "0 0", dur: `${perItemAssemblyDuration}s`, begin: `${linesPhaseEnd + index * perItemAssemblyDuration}s`, fill: "freeze", calcMode: "spline", keySplines: "0.33 0 0.2 1", keyTimes: "0;1" }))));
395
+ })),
396
+ react_1.default.createElement("g", { className: "opentype-particles", filter: showGlow ? `url(#glow-${uniqueId})` : undefined }, resolvedPaths.flatMap((path, pathIndex) => {
397
+ return Array.from({ length: particlesPerPath }).map((_, particleIndex) => {
398
+ const particleDelay = (particleIndex / particlesPerPath) * flowDuration;
399
+ const beginTime = flowBeginTime + particleDelay;
400
+ return (react_1.default.createElement("circle", { key: `particle-${pathIndex}-${particleIndex}`, r: particleRadius, fill: `url(#particleGradient-${uniqueId})`, opacity: "0" },
401
+ react_1.default.createElement("animateMotion", { dur: `${flowDuration}s`, begin: `${beginTime}s`, fill: "freeze", path: path.d }),
402
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "0;1;1;0", keyTimes: "0;0.1;0.9;1", dur: `${flowDuration}s`, begin: `${beginTime}s`, fill: "freeze" })));
403
+ });
404
+ }))));
405
+ };
406
+ exports.OpenTypeTextReveal = OpenTypeTextReveal;
407
+ /**
408
+ * Offset all coordinates in path data
409
+ */
410
+ function offsetPathData(d, offsetX, offsetY) {
411
+ let result = "";
412
+ let i = 0;
413
+ let coordIndex = 0;
414
+ while (i < d.length) {
415
+ const char = d[i];
416
+ // Check for command letters
417
+ if (/[MmLlHhVvCcSsQqTtAaZz]/.test(char)) {
418
+ result += char;
419
+ // Reset coord tracking for absolute commands, or handle relative
420
+ if (char === 'Z' || char === 'z') {
421
+ coordIndex = 0;
422
+ }
423
+ else if (char === 'H' || char === 'h') {
424
+ // Horizontal - only X coords
425
+ coordIndex = -1; // Special handling
426
+ }
427
+ else if (char === 'V' || char === 'v') {
428
+ // Vertical - only Y coords
429
+ coordIndex = -2; // Special handling
430
+ }
431
+ else {
432
+ coordIndex = 0;
433
+ }
434
+ i++;
435
+ }
436
+ else if (/[-\d.]/.test(char)) {
437
+ // Parse number
438
+ let numStr = "";
439
+ while (i < d.length && /[-\d.eE]/.test(d[i])) {
440
+ numStr += d[i];
441
+ i++;
442
+ }
443
+ const num = parseFloat(numStr);
444
+ // Apply offset based on coordinate type
445
+ if (coordIndex === -1) {
446
+ // H command - X only
447
+ result += String(num + offsetX);
448
+ }
449
+ else if (coordIndex === -2) {
450
+ // V command - Y only
451
+ result += String(num + offsetY);
452
+ }
453
+ else if (coordIndex % 2 === 0) {
454
+ // X coordinate
455
+ result += String(num + offsetX);
456
+ }
457
+ else {
458
+ // Y coordinate
459
+ result += String(num + offsetY);
460
+ }
461
+ if (coordIndex >= 0)
462
+ coordIndex++;
463
+ }
464
+ else {
465
+ // Whitespace or comma
466
+ result += char;
467
+ i++;
468
+ }
469
+ }
470
+ return result;
471
+ }
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface SquareLogoProps {
3
+ width?: number;
4
+ height?: number;
5
+ colors?: string[];
6
+ opacity?: number;
7
+ }
8
+ export declare const SquareLogo: React.FC<SquareLogoProps>;
9
+ export {};
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SquareLogo = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const SquareLogo = ({ width = 150, height = 150, colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#96CEB4', '#FFEAA7', '#DDA15E', '#BC6C25', '#E76F51'], opacity = 0.9, }) => {
9
+ const rectangleStyle = {
10
+ transition: 'all 0.3s ease',
11
+ };
12
+ return (react_1.default.createElement("svg", { width: width, height: height, viewBox: "0 0 100 100", xmlns: "http://www.w3.org/2000/svg", style: { opacity } },
13
+ react_1.default.createElement("defs", null,
14
+ react_1.default.createElement("filter", { id: "glow" },
15
+ react_1.default.createElement("feGaussianBlur", { stdDeviation: "1.5", result: "coloredBlur" }),
16
+ react_1.default.createElement("feMerge", null,
17
+ react_1.default.createElement("feMergeNode", { in: "coloredBlur" }),
18
+ react_1.default.createElement("feMergeNode", { in: "SourceGraphic" })))),
19
+ react_1.default.createElement("rect", { x: "10", y: "10", width: "10", height: "15", fill: colors[1], style: rectangleStyle, filter: "url(#glow)" },
20
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "0.8;1;0.8", dur: "3s", repeatCount: "indefinite" })),
21
+ react_1.default.createElement("rect", { x: "20", y: "10", width: "15", height: "80", fill: colors[0], style: rectangleStyle, filter: "url(#glow)" },
22
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "1;0.8;1", dur: "3s", repeatCount: "indefinite", begin: "0.3s" })),
23
+ react_1.default.createElement("rect", { x: "35", y: "10", width: "30", height: "12", fill: colors[0], style: rectangleStyle, filter: "url(#glow)" },
24
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "0.8;1;0.8", dur: "3s", repeatCount: "indefinite", begin: "0.6s" })),
25
+ react_1.default.createElement("rect", { x: "65", y: "10", width: "25", height: "12", fill: colors[0], style: rectangleStyle, filter: "url(#glow)" },
26
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "1;0.8;1", dur: "3s", repeatCount: "indefinite", begin: "0.9s" })),
27
+ react_1.default.createElement("rect", { x: "35", y: "22", width: "15", height: "18", fill: colors[3], style: rectangleStyle, filter: "url(#glow)" },
28
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "0.8;1;0.8", dur: "3s", repeatCount: "indefinite", begin: "1.2s" })),
29
+ react_1.default.createElement("rect", { x: "50", y: "22", width: "15", height: "18", fill: colors[4], style: rectangleStyle, filter: "url(#glow)" },
30
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "1;0.8;1", dur: "3s", repeatCount: "indefinite", begin: "1.5s" })),
31
+ react_1.default.createElement("rect", { x: "65", y: "22", width: "12", height: "18", fill: colors[0], style: rectangleStyle, filter: "url(#glow)" },
32
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "0.8;1;0.8", dur: "3s", repeatCount: "indefinite", begin: "1.8s" })),
33
+ react_1.default.createElement("rect", { x: "77", y: "22", width: "13", height: "28", fill: colors[0], style: rectangleStyle, filter: "url(#glow)" },
34
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "1;0.8;1", dur: "3s", repeatCount: "indefinite", begin: "2.1s" })),
35
+ react_1.default.createElement("rect", { x: "77", y: "50", width: "13", height: "40", fill: colors[5], style: rectangleStyle, filter: "url(#glow)" },
36
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "0.8;1;0.8", dur: "3s", repeatCount: "indefinite", begin: "2.1s" })),
37
+ react_1.default.createElement("rect", { x: "35", y: "40", width: "55", height: "10", fill: colors[0], style: rectangleStyle, filter: "url(#glow)" },
38
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "0.8;1;0.8", dur: "3s", repeatCount: "indefinite", begin: "2.4s" })),
39
+ react_1.default.createElement("rect", { x: "10", y: "25", width: "10", height: "35", fill: colors[6], style: rectangleStyle, filter: "url(#glow)" },
40
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "1;0.8;1", dur: "3s", repeatCount: "indefinite", begin: "2.7s" })),
41
+ react_1.default.createElement("rect", { x: "35", y: "50", width: "20", height: "20", fill: colors[7], style: rectangleStyle, filter: "url(#glow)" },
42
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "0.8;1;0.8", dur: "3s", repeatCount: "indefinite", begin: "0.3s" })),
43
+ react_1.default.createElement("rect", { x: "55", y: "50", width: "22", height: "20", fill: colors[8], style: rectangleStyle, filter: "url(#glow)" },
44
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "1;0.8;1", dur: "3s", repeatCount: "indefinite", begin: "0.6s" })),
45
+ react_1.default.createElement("rect", { x: "10", y: "60", width: "10", height: "30", fill: colors[1], style: rectangleStyle, filter: "url(#glow)" },
46
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "0.8;1;0.8", dur: "3s", repeatCount: "indefinite", begin: "0.9s" })),
47
+ react_1.default.createElement("rect", { x: "35", y: "70", width: "25", height: "20", fill: colors[2], style: rectangleStyle, filter: "url(#glow)" },
48
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "1;0.8;1", dur: "3s", repeatCount: "indefinite", begin: "1.2s" })),
49
+ react_1.default.createElement("rect", { x: "60", y: "70", width: "17", height: "20", fill: colors[3], style: rectangleStyle, filter: "url(#glow)" },
50
+ react_1.default.createElement("animate", { attributeName: "opacity", values: "0.8;1;0.8", dur: "3s", repeatCount: "indefinite", begin: "1.5s" })),
51
+ react_1.default.createElement("line", { x1: "20", y1: "10", x2: "20", y2: "90", stroke: "rgba(255, 255, 255, 0.15)", strokeWidth: "0.5" }),
52
+ react_1.default.createElement("line", { x1: "35", y1: "10", x2: "35", y2: "90", stroke: "rgba(255, 255, 255, 0.15)", strokeWidth: "0.5" }),
53
+ react_1.default.createElement("line", { x1: "10", y1: "22", x2: "90", y2: "22", stroke: "rgba(255, 255, 255, 0.15)", strokeWidth: "0.5" }),
54
+ react_1.default.createElement("line", { x1: "10", y1: "40", x2: "90", y2: "40", stroke: "rgba(255, 255, 255, 0.15)", strokeWidth: "0.5" }),
55
+ react_1.default.createElement("line", { x1: "10", y1: "50", x2: "90", y2: "50", stroke: "rgba(255, 255, 255, 0.15)", strokeWidth: "0.5" })));
56
+ };
57
+ exports.SquareLogo = SquareLogo;
@@ -0,0 +1,28 @@
1
+ import React from "react";
2
+ import { PathDefinition } from "./presets";
3
+ type ChaosMode = "none" | "fragmented";
4
+ interface TelemetryRevealProps {
5
+ width?: number;
6
+ height?: number;
7
+ paths?: PathDefinition[];
8
+ preset?: "network" | "tree" | "circuit" | "hexagon" | "codebase";
9
+ viewBox?: string;
10
+ chaosMode?: ChaosMode;
11
+ chaosDuration?: number;
12
+ dotsDuration?: number;
13
+ flowDuration?: number;
14
+ flowDelay?: number;
15
+ particlesPerPath?: number;
16
+ particleRadius?: number;
17
+ color?: string;
18
+ particleColor?: string;
19
+ strokeWidth?: number;
20
+ opacity?: number;
21
+ showGlow?: boolean;
22
+ fadeAfterAssembly?: boolean;
23
+ fadeOpacity?: number;
24
+ loop?: boolean;
25
+ loopDelay?: number;
26
+ }
27
+ export declare const TelemetryReveal: React.FC<TelemetryRevealProps>;
28
+ export {};