@principal-ai/logo-component 0.1.14 → 0.1.16
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 +2 -1
- package/dist/Logo.d.ts +7 -1
- package/dist/Logo.js +40 -23
- package/dist/TrailCityDiagram.d.ts +50 -0
- package/dist/TrailCityDiagram.js +277 -0
- package/dist/esm/Logo.js +40 -23
- package/dist/esm/TrailCityDiagram.js +241 -0
- package/dist/esm/index.js +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +1 -0
- package/dist/index.js +3 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -53,7 +53,8 @@ npm run export-icon -- --size=512 --color=#ff00ff --svg-only
|
|
|
53
53
|
|
|
54
54
|
- `--size <number>` – Output width and height in pixels (default: `1024`).
|
|
55
55
|
- `--color <hex>` – Stroke color for the wireframe (default: `#00ffff`).
|
|
56
|
-
- `--particle-color <hex>` –
|
|
56
|
+
- `--particle-color <hex>` – Orbiting particle color (defaults to `--color`).
|
|
57
|
+
- `--letter-color <hex>` – "P" letter dots color (defaults to `--particle-color`, then `--color`).
|
|
57
58
|
- `--opacity <0-1>` – Overrides the root SVG opacity (default: `1`).
|
|
58
59
|
- `--output <path>` – Destination directory (default: `exports`).
|
|
59
60
|
- `--name <string>` – Base file name used for the exports (default: `logo`).
|
package/dist/Logo.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ interface LogoProps {
|
|
|
5
5
|
color?: string;
|
|
6
6
|
/** Color for orbiting particles (defaults to color) */
|
|
7
7
|
particleColor?: string;
|
|
8
|
-
/** Color for the "P" letter
|
|
8
|
+
/** Color for the "P" letter in the center (defaults to particleColor, then color) */
|
|
9
9
|
letterColor?: string;
|
|
10
10
|
opacity?: number;
|
|
11
11
|
/** Color for horizontal latitude lines (defaults to color) */
|
|
@@ -24,6 +24,12 @@ interface LogoProps {
|
|
|
24
24
|
showGlow?: boolean;
|
|
25
25
|
/** Accent color for the outer sphere outline (defaults to color) */
|
|
26
26
|
accentColor?: string;
|
|
27
|
+
/** Use a text-based P instead of dots (defaults to false) */
|
|
28
|
+
useTextLetter?: boolean;
|
|
29
|
+
/** Font family for text-based P (defaults to Georgia) */
|
|
30
|
+
letterFontFamily?: string;
|
|
31
|
+
/** Background color for the SVG */
|
|
32
|
+
backgroundColor?: string;
|
|
27
33
|
}
|
|
28
34
|
export declare const Logo: React.FC<LogoProps>;
|
|
29
35
|
export {};
|
package/dist/Logo.js
CHANGED
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.Logo = void 0;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const Logo = ({ width = 150, height = 150, color = "currentColor", particleColor, letterColor, opacity = 0.9, horizontalColor, verticalColor, diagonalColor, outlineColor, showOutline = true, axisColor, showGlow = false, accentColor, }) => {
|
|
8
|
+
const Logo = ({ width = 150, height = 150, color = "currentColor", particleColor, letterColor, opacity = 0.9, horizontalColor, verticalColor, diagonalColor, outlineColor, showOutline = true, axisColor, showGlow = false, accentColor, useTextLetter = false, letterFontFamily = "Georgia, serif", backgroundColor, }) => {
|
|
9
9
|
const finalParticleColor = particleColor || color;
|
|
10
10
|
const finalLetterColor = letterColor || particleColor || color;
|
|
11
11
|
const finalHorizontalColor = horizontalColor || color;
|
|
@@ -22,31 +22,48 @@ const Logo = ({ width = 150, height = 150, color = "currentColor", particleColor
|
|
|
22
22
|
react_1.default.createElement("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.8 } },
|
|
23
23
|
react_1.default.createElement("animate", { attributeName: "stop-opacity", values: "0.8;0.3;0.8", dur: "2s", repeatCount: "indefinite" })),
|
|
24
24
|
react_1.default.createElement("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } }))),
|
|
25
|
+
backgroundColor && (react_1.default.createElement("rect", { x: "30", y: "30", width: "140", height: "140", fill: backgroundColor })),
|
|
25
26
|
showGlow && (react_1.default.createElement("circle", { cx: "100", cy: "100", r: "80", fill: "url(#sphereGlow)", opacity: "0.5" })),
|
|
26
|
-
react_1.default.createElement("
|
|
27
|
-
react_1.default.createElement("
|
|
28
|
-
react_1.default.createElement("
|
|
29
|
-
react_1.default.createElement("
|
|
30
|
-
react_1.default.createElement("
|
|
31
|
-
react_1.default.createElement("
|
|
32
|
-
react_1.default.createElement("
|
|
33
|
-
react_1.default.createElement("
|
|
34
|
-
react_1.default.createElement("
|
|
35
|
-
react_1.default.createElement("
|
|
36
|
-
react_1.default.createElement("circle", { cx: "108", cy: "95", r: "2", fill: finalLetterColor, opacity: "0.9" }),
|
|
37
|
-
react_1.default.createElement("circle", { cx: "103", cy: "100", r: "2", fill: finalLetterColor, opacity: "0.9" }),
|
|
38
|
-
react_1.default.createElement("circle", { cx: "98", cy: "100", r: "2", fill: finalLetterColor, opacity: "0.9" }),
|
|
39
|
-
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "27", fill: "none", stroke: finalHorizontalColor, strokeWidth: "1", opacity: "0.7" }),
|
|
40
|
-
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "27", ry: "67", fill: "none", stroke: finalVerticalColor, strokeWidth: "1", opacity: "0.7" }),
|
|
41
|
-
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "35", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(30 100 100)" }),
|
|
42
|
-
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "35", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(60 100 100)" }),
|
|
43
|
-
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "35", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(120 100 100)" }),
|
|
44
|
-
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "35", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(150 100 100)" }),
|
|
27
|
+
react_1.default.createElement("line", { x1: "100", y1: "33", x2: "100", y2: "68", stroke: finalAxisColor, strokeWidth: "1", opacity: "0.7" }),
|
|
28
|
+
react_1.default.createElement("line", { x1: "100", y1: "167", x2: "100", y2: "132", stroke: finalAxisColor, strokeWidth: "1", opacity: "0.7" }),
|
|
29
|
+
react_1.default.createElement("line", { x1: "33", y1: "100", x2: "68", y2: "100", stroke: finalAxisColor, strokeWidth: "1", opacity: "0.7" }),
|
|
30
|
+
react_1.default.createElement("line", { x1: "167", y1: "100", x2: "132", y2: "100", stroke: finalAxisColor, strokeWidth: "1", opacity: "0.7" }),
|
|
31
|
+
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "32", fill: "none", stroke: finalHorizontalColor, strokeWidth: "1", opacity: "0.7" }),
|
|
32
|
+
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "32", ry: "67", fill: "none", stroke: finalVerticalColor, strokeWidth: "1", opacity: "0.7" }),
|
|
33
|
+
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "40", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(30 100 100)" }),
|
|
34
|
+
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "40", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(60 100 100)" }),
|
|
35
|
+
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "40", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(120 100 100)" }),
|
|
36
|
+
react_1.default.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "40", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(150 100 100)" }),
|
|
45
37
|
showOutline && (react_1.default.createElement("circle", { cx: "100", cy: "100", r: "67", fill: "none", stroke: finalOutlineColor, strokeWidth: "1.5", opacity: "0.9" })),
|
|
46
|
-
react_1.default.createElement("
|
|
38
|
+
useTextLetter ? (react_1.default.createElement("text", { x: "100", y: "100", textAnchor: "middle", dominantBaseline: "central", fill: finalLetterColor, fontSize: "48", fontFamily: letterFontFamily, fontWeight: "bold", opacity: "0.9" }, "P")) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
39
|
+
react_1.default.createElement("circle", { cx: "90", cy: "79", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
40
|
+
react_1.default.createElement("circle", { cx: "90", cy: "86", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
41
|
+
react_1.default.createElement("circle", { cx: "90", cy: "93", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
42
|
+
react_1.default.createElement("circle", { cx: "90", cy: "100", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
43
|
+
react_1.default.createElement("circle", { cx: "90", cy: "107", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
44
|
+
react_1.default.createElement("circle", { cx: "90", cy: "114", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
45
|
+
react_1.default.createElement("circle", { cx: "90", cy: "121", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
46
|
+
react_1.default.createElement("circle", { cx: "97", cy: "79", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
47
|
+
react_1.default.createElement("circle", { cx: "104", cy: "79", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
48
|
+
react_1.default.createElement("circle", { cx: "111", cy: "86", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
49
|
+
react_1.default.createElement("circle", { cx: "111", cy: "93", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
50
|
+
react_1.default.createElement("circle", { cx: "104", cy: "100", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
51
|
+
react_1.default.createElement("circle", { cx: "97", cy: "100", r: "2.5", fill: finalLetterColor, opacity: "0.9" }))),
|
|
52
|
+
react_1.default.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
53
|
+
react_1.default.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 167,100 A 67,32 0 0,1 33,100 A 67,32 0 0,1 167,100" })),
|
|
54
|
+
react_1.default.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
55
|
+
react_1.default.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 100,33 A 32,67 0 0,0 100,167 A 32,67 0 0,0 100,33" })),
|
|
56
|
+
react_1.default.createElement("g", { transform: "rotate(30 100 100)" },
|
|
47
57
|
react_1.default.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
48
|
-
react_1.default.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M
|
|
58
|
+
react_1.default.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 167,100 A 67,40 0 0,1 33,100 A 67,40 0 0,1 167,100" }))),
|
|
59
|
+
react_1.default.createElement("g", { transform: "rotate(60 100 100)" },
|
|
49
60
|
react_1.default.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
50
|
-
react_1.default.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M
|
|
61
|
+
react_1.default.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 167,100 A 67,40 0 0,0 33,100 A 67,40 0 0,0 167,100" }))),
|
|
62
|
+
react_1.default.createElement("g", { transform: "rotate(120 100 100)" },
|
|
63
|
+
react_1.default.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
64
|
+
react_1.default.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 167,100 A 67,40 0 0,1 33,100 A 67,40 0 0,1 167,100" }))),
|
|
65
|
+
react_1.default.createElement("g", { transform: "rotate(150 100 100)" },
|
|
66
|
+
react_1.default.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
67
|
+
react_1.default.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 167,100 A 67,40 0 0,0 33,100 A 67,40 0 0,0 167,100" })))));
|
|
51
68
|
};
|
|
52
69
|
exports.Logo = Logo;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Theme } from '@principal-ade/industry-theme';
|
|
3
|
+
export interface TrailCityDiagramProps {
|
|
4
|
+
/**
|
|
5
|
+
* Theme supplying the diagram's colors. Optional — every color falls
|
|
6
|
+
* back to a sensible dark-mode default when the theme (or an
|
|
7
|
+
* individual color) is missing, so the component renders standalone.
|
|
8
|
+
*/
|
|
9
|
+
theme?: Theme;
|
|
10
|
+
/** Optional className applied to the wrapping <svg>. */
|
|
11
|
+
className?: string;
|
|
12
|
+
/** Hide the side snippet pane + leader line. */
|
|
13
|
+
hideSnippet?: boolean;
|
|
14
|
+
/** When false, the snippet system (leader, marker dot, cell border,
|
|
15
|
+
* snippet card) fades out to opacity 0 with a 700ms reveal delay on
|
|
16
|
+
* the way back in. Used to hold the snippet until the typed
|
|
17
|
+
* explanation finishes. */
|
|
18
|
+
snippetVisible?: boolean;
|
|
19
|
+
/** Hide the dashed trail polyline and its numbered markers. Used when
|
|
20
|
+
* the surface is explaining the file city itself and the trail would
|
|
21
|
+
* be a distraction. */
|
|
22
|
+
hideTrail?: boolean;
|
|
23
|
+
/** When false, the trail polyline + numbered markers fade out (opacity
|
|
24
|
+
* 0) without unmounting. Used to hold the trail off-screen until the
|
|
25
|
+
* codeTrail step's typed explanation finishes. */
|
|
26
|
+
trailVisible?: boolean;
|
|
27
|
+
/** Show a row of small sign-off stamp placeholders under the snippet.
|
|
28
|
+
* Four filled "team" stamps + one empty slot to make collaboration
|
|
29
|
+
* legible on the whyTrails step. */
|
|
30
|
+
stampRowVisible?: boolean;
|
|
31
|
+
/** True once the visitor has signed off. Hides the empty placeholder
|
|
32
|
+
* slot so the page's HTML LgtmStamp overlay can occupy it without
|
|
33
|
+
* visual conflict. */
|
|
34
|
+
userStamped?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Spotlight the trail: dim the city + snippet so only the dashed
|
|
37
|
+
* polyline and numbered markers are at full visibility. Trail line
|
|
38
|
+
* also thickens and re-enables its dash animation. Used to draw
|
|
39
|
+
* attention when the page is explaining what a code trail is.
|
|
40
|
+
*/
|
|
41
|
+
highlightTrail?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Static SVG version of the FileCity trail overlay — a top-down grid of
|
|
45
|
+
* building rectangles with numbered markers wired by a dashed path, plus
|
|
46
|
+
* an L-routed leader line to a snippet card. Mirrors the look of
|
|
47
|
+
* `TrailFilePath` + `TrailLeaderLine` from the 3D panel without the
|
|
48
|
+
* three.js projection — suitable for marketing surfaces.
|
|
49
|
+
*/
|
|
50
|
+
export declare function TrailCityDiagram({ theme, className, hideSnippet, snippetVisible, hideTrail, trailVisible, highlightTrail, stampRowVisible, userStamped, }: TrailCityDiagramProps): React.JSX.Element;
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.TrailCityDiagram = TrailCityDiagram;
|
|
38
|
+
const react_1 = __importStar(require("react"));
|
|
39
|
+
const VIEW_W = 700;
|
|
40
|
+
const VIEW_H = 700;
|
|
41
|
+
const CITY_COLS = 12;
|
|
42
|
+
const CITY_ROWS = 12;
|
|
43
|
+
const CELL_W = 50;
|
|
44
|
+
const CELL_H = 50;
|
|
45
|
+
const CITY_OFFSET_X = 50;
|
|
46
|
+
const CITY_OFFSET_Y = 50;
|
|
47
|
+
/** Center point of a grid cell, in viewBox coords. */
|
|
48
|
+
function cellCenter(col, row) {
|
|
49
|
+
return {
|
|
50
|
+
x: CITY_OFFSET_X + col * CELL_W + CELL_W / 2,
|
|
51
|
+
y: CITY_OFFSET_Y + row * CELL_H + CELL_H / 2,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function buildCity(palette, pinned) {
|
|
55
|
+
const rng = mulberry32(7);
|
|
56
|
+
const cells = [];
|
|
57
|
+
for (let r = 0; r < CITY_ROWS; r++) {
|
|
58
|
+
for (let c = 0; c < CITY_COLS; c++) {
|
|
59
|
+
const isPinned = pinned.has(`${c},${r}`);
|
|
60
|
+
// Pinned cells (the ones markers sit on top of) always get a
|
|
61
|
+
// building so the marker has something to be centered on. Other
|
|
62
|
+
// cells skip occasionally to break up the grid.
|
|
63
|
+
const skipRoll = rng();
|
|
64
|
+
// Keep the RNG sequence stable so colors don't shift after dropping
|
|
65
|
+
// the per-building size jitter.
|
|
66
|
+
rng();
|
|
67
|
+
rng();
|
|
68
|
+
const colorRoll = rng();
|
|
69
|
+
if (!isPinned && skipRoll < 0.18)
|
|
70
|
+
continue;
|
|
71
|
+
const w = CELL_W - 8;
|
|
72
|
+
const h = CELL_H - 8;
|
|
73
|
+
cells.push({
|
|
74
|
+
x: CITY_OFFSET_X + c * CELL_W + (CELL_W - w) / 2,
|
|
75
|
+
y: CITY_OFFSET_Y + r * CELL_H + (CELL_H - h) / 2,
|
|
76
|
+
w,
|
|
77
|
+
h,
|
|
78
|
+
fill: palette[Math.floor(colorRoll * palette.length)],
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return cells;
|
|
83
|
+
}
|
|
84
|
+
function mulberry32(seed) {
|
|
85
|
+
let t = seed;
|
|
86
|
+
return () => {
|
|
87
|
+
t = (t + 0x6d2b79f5) | 0;
|
|
88
|
+
let r = t;
|
|
89
|
+
r = Math.imul(r ^ (r >>> 15), r | 1);
|
|
90
|
+
r ^= r + Math.imul(r ^ (r >>> 7), r | 61);
|
|
91
|
+
return ((r ^ (r >>> 14)) >>> 0) / 4294967296;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** VH leader from `a` (marker) to `b` (snippet anchor): exits `a` going
|
|
95
|
+
* vertically toward `b.y`, then turns and runs horizontally to `b.x`. */
|
|
96
|
+
function lRoutePath(a, b, radius = 12) {
|
|
97
|
+
const goingUp = b.y < a.y;
|
|
98
|
+
const ySign = goingUp ? -1 : 1;
|
|
99
|
+
const xSign = b.x < a.x ? -1 : 1;
|
|
100
|
+
const r = Math.min(radius, Math.abs(a.y - b.y) / 2, Math.abs(a.x - b.x) / 2);
|
|
101
|
+
return [
|
|
102
|
+
`M ${a.x} ${a.y}`,
|
|
103
|
+
`L ${a.x} ${b.y - ySign * r}`,
|
|
104
|
+
`Q ${a.x} ${b.y} ${a.x + xSign * r} ${b.y}`,
|
|
105
|
+
`L ${b.x} ${b.y}`,
|
|
106
|
+
].join(' ');
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Static SVG version of the FileCity trail overlay — a top-down grid of
|
|
110
|
+
* building rectangles with numbered markers wired by a dashed path, plus
|
|
111
|
+
* an L-routed leader line to a snippet card. Mirrors the look of
|
|
112
|
+
* `TrailFilePath` + `TrailLeaderLine` from the 3D panel without the
|
|
113
|
+
* three.js projection — suitable for marketing surfaces.
|
|
114
|
+
*/
|
|
115
|
+
function TrailCityDiagram({ theme, className, hideSnippet = false, snippetVisible = true, hideTrail = false, trailVisible = true, highlightTrail = false, stampRowVisible = false, userStamped = false, }) {
|
|
116
|
+
var _a, _b, _c, _d, _e, _f;
|
|
117
|
+
const snippetGateStyle = {
|
|
118
|
+
opacity: snippetVisible ? 1 : 0,
|
|
119
|
+
transition: 'opacity 500ms ease',
|
|
120
|
+
transitionDelay: snippetVisible ? '700ms' : '0ms',
|
|
121
|
+
};
|
|
122
|
+
const trailGateStyle = {
|
|
123
|
+
opacity: trailVisible ? 1 : 0,
|
|
124
|
+
transition: 'opacity 500ms ease',
|
|
125
|
+
};
|
|
126
|
+
const stampRowGateStyle = {
|
|
127
|
+
opacity: stampRowVisible ? 1 : 0,
|
|
128
|
+
transition: 'opacity 500ms ease',
|
|
129
|
+
transitionDelay: stampRowVisible ? '700ms' : '0ms',
|
|
130
|
+
};
|
|
131
|
+
const colors = theme === null || theme === void 0 ? void 0 : theme.colors;
|
|
132
|
+
const uid = (0, react_1.useId)().replace(/:/g, '');
|
|
133
|
+
const accent = (_a = colors === null || colors === void 0 ? void 0 : colors.primary) !== null && _a !== void 0 ? _a : '#22d3ee';
|
|
134
|
+
const surface = (_b = colors === null || colors === void 0 ? void 0 : colors.surface) !== null && _b !== void 0 ? _b : '#0f1419';
|
|
135
|
+
const text = (_c = colors === null || colors === void 0 ? void 0 : colors.text) !== null && _c !== void 0 ? _c : '#f8fafc';
|
|
136
|
+
const muted = (_d = colors === null || colors === void 0 ? void 0 : colors.textMuted) !== null && _d !== void 0 ? _d : '#94a3b8';
|
|
137
|
+
const bg = (_e = colors === null || colors === void 0 ? void 0 : colors.background) !== null && _e !== void 0 ? _e : '#0a0f14';
|
|
138
|
+
const success = (_f = colors === null || colors === void 0 ? void 0 : colors.success) !== null && _f !== void 0 ? _f : '#10b981';
|
|
139
|
+
// Silvery white-grey ink for ACK stamps — brighter than `muted` so it
|
|
140
|
+
// reads cleanly against the dark city.
|
|
141
|
+
const silver = '#d1d8e0';
|
|
142
|
+
const palette = (0, react_1.useMemo)(() => [
|
|
143
|
+
withAlpha(accent, 0.18),
|
|
144
|
+
withAlpha(accent, 0.32),
|
|
145
|
+
withAlpha(text, 0.08),
|
|
146
|
+
withAlpha(text, 0.14),
|
|
147
|
+
withAlpha(text, 0.22),
|
|
148
|
+
], [accent, text]);
|
|
149
|
+
const markerCells = (0, react_1.useMemo)(() => [
|
|
150
|
+
{ col: 1, row: 10, label: '1' },
|
|
151
|
+
{ col: 3, row: 7, label: '2' },
|
|
152
|
+
{ col: 6, row: 9, label: '3' },
|
|
153
|
+
{ col: 4, row: 5, label: '4' },
|
|
154
|
+
], []);
|
|
155
|
+
const pinnedCells = (0, react_1.useMemo)(() => new Set(markerCells.map(m => `${m.col},${m.row}`)), [markerCells]);
|
|
156
|
+
const buildings = (0, react_1.useMemo)(() => buildCity(palette, pinnedCells), [palette, pinnedCells]);
|
|
157
|
+
const markers = (0, react_1.useMemo)(() => markerCells.map(m => {
|
|
158
|
+
const c = cellCenter(m.col, m.row);
|
|
159
|
+
return { x: c.x, y: c.y, label: m.label };
|
|
160
|
+
}), [markerCells]);
|
|
161
|
+
const trailPath = (0, react_1.useMemo)(() => {
|
|
162
|
+
const [first, ...rest] = markers;
|
|
163
|
+
if (!first)
|
|
164
|
+
return '';
|
|
165
|
+
return [`M ${first.x} ${first.y}`, ...rest.map(m => `L ${m.x} ${m.y}`)].join(' ');
|
|
166
|
+
}, [markers]);
|
|
167
|
+
const activeMarker = markers[markers.length - 1];
|
|
168
|
+
const snippetAnchor = { x: VIEW_W - 320, y: 100 };
|
|
169
|
+
const leaderPath = (0, react_1.useMemo)(() => activeMarker
|
|
170
|
+
? lRoutePath({ x: activeMarker.x, y: activeMarker.y }, snippetAnchor)
|
|
171
|
+
: '', [activeMarker, snippetAnchor.x, snippetAnchor.y]);
|
|
172
|
+
return (react_1.default.createElement("svg", { viewBox: `0 0 ${VIEW_W} ${VIEW_H}`, className: className, style: { display: 'block', width: '100%', height: 'auto', overflow: 'visible' }, role: "img", "aria-label": "A trail of code locations connected across a top-down city of files" },
|
|
173
|
+
react_1.default.createElement("defs", null,
|
|
174
|
+
react_1.default.createElement("linearGradient", { id: `fade-${uid}`, x1: "0", x2: "0", y1: "0", y2: "1" },
|
|
175
|
+
react_1.default.createElement("stop", { offset: "0%", stopColor: bg, stopOpacity: 0 }),
|
|
176
|
+
react_1.default.createElement("stop", { offset: "100%", stopColor: bg, stopOpacity: 0.7 }))),
|
|
177
|
+
react_1.default.createElement("rect", { x: 0, y: 0, width: VIEW_W, height: VIEW_H, fill: bg, rx: 12 }),
|
|
178
|
+
react_1.default.createElement("g", { style: {
|
|
179
|
+
opacity: highlightTrail ? 0.2 : 1,
|
|
180
|
+
transition: 'opacity 300ms ease',
|
|
181
|
+
} }, buildings.map((b, i) => (react_1.default.createElement("rect", { key: i, x: b.x, y: b.y, width: b.w, height: b.h, fill: b.fill, stroke: withAlpha(text, 0.08), strokeWidth: 0.5, rx: 2 })))),
|
|
182
|
+
!hideSnippet && (() => {
|
|
183
|
+
const activeCell = markerCells[markerCells.length - 1];
|
|
184
|
+
if (!activeCell)
|
|
185
|
+
return null;
|
|
186
|
+
return (react_1.default.createElement("g", { style: snippetGateStyle },
|
|
187
|
+
react_1.default.createElement("rect", { x: CITY_OFFSET_X + activeCell.col * CELL_W + 4, y: CITY_OFFSET_Y + activeCell.row * CELL_H + 4, width: CELL_W - 8, height: CELL_H - 8, fill: "none", stroke: accent, strokeWidth: 2, rx: 2, style: {
|
|
188
|
+
opacity: highlightTrail ? 0.2 : 1,
|
|
189
|
+
transition: 'opacity 300ms ease',
|
|
190
|
+
} })));
|
|
191
|
+
})(),
|
|
192
|
+
react_1.default.createElement("rect", { x: 0, y: VIEW_H - 80, width: VIEW_W, height: 80, fill: `url(#fade-${uid})`, pointerEvents: "none" }),
|
|
193
|
+
!hideTrail && (react_1.default.createElement("g", { style: trailGateStyle },
|
|
194
|
+
react_1.default.createElement("path", { d: trailPath, fill: "none", stroke: accent, strokeWidth: highlightTrail ? 3.5 : 2, strokeLinecap: "round", strokeDasharray: "6 5", opacity: highlightTrail ? 1 : 0.9, style: {
|
|
195
|
+
transition: 'stroke-width 300ms ease, opacity 300ms ease',
|
|
196
|
+
filter: highlightTrail
|
|
197
|
+
? `drop-shadow(0 0 8px ${withAlpha(accent, 0.7)})`
|
|
198
|
+
: undefined,
|
|
199
|
+
} }, highlightTrail && (react_1.default.createElement("animate", { attributeName: "stroke-dashoffset", from: 0, to: -44, dur: "1.4s", repeatCount: "indefinite" }))))),
|
|
200
|
+
!hideSnippet && (react_1.default.createElement("g", { style: snippetGateStyle },
|
|
201
|
+
react_1.default.createElement("path", { d: leaderPath, fill: "none", stroke: accent, strokeWidth: 1.5, strokeDasharray: "5 4", opacity: highlightTrail ? 0 : 0.7, style: { transition: 'opacity 300ms ease' } }),
|
|
202
|
+
activeMarker && (react_1.default.createElement("circle", { cx: activeMarker.x, cy: activeMarker.y, r: 3.5, fill: accent, opacity: highlightTrail ? 0 : 1, style: { transition: 'opacity 300ms ease' } })))),
|
|
203
|
+
!hideTrail && (react_1.default.createElement("g", { style: trailGateStyle }, markers.map((m, i) => {
|
|
204
|
+
const isActive = i === markers.length - 1;
|
|
205
|
+
const size = 22;
|
|
206
|
+
const half = size / 2;
|
|
207
|
+
return (react_1.default.createElement("g", { key: m.label },
|
|
208
|
+
isActive && (react_1.default.createElement("rect", { x: m.x - half - 4, y: m.y - half - 4, width: size + 8, height: size + 8, rx: 6, fill: accent, opacity: 0.18 },
|
|
209
|
+
react_1.default.createElement("animate", { attributeName: "opacity", values: "0.28;0;0.28", dur: "2.4s", repeatCount: "indefinite" }))),
|
|
210
|
+
react_1.default.createElement("rect", { x: m.x - half, y: m.y - half, width: size, height: size, rx: 4, fill: surface, stroke: accent, strokeWidth: 1.75 }),
|
|
211
|
+
react_1.default.createElement("text", { x: m.x, y: m.y + 1, textAnchor: "middle", dominantBaseline: "central", fontSize: 14, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: text }, m.label)));
|
|
212
|
+
}))),
|
|
213
|
+
!hideSnippet && (react_1.default.createElement("g", { style: snippetGateStyle },
|
|
214
|
+
react_1.default.createElement("g", { style: {
|
|
215
|
+
opacity: highlightTrail ? 0.15 : 1,
|
|
216
|
+
transition: 'opacity 300ms ease',
|
|
217
|
+
} },
|
|
218
|
+
react_1.default.createElement("circle", { cx: snippetAnchor.x, cy: snippetAnchor.y, r: 3.5, fill: accent }),
|
|
219
|
+
react_1.default.createElement(SnippetCard, { x: snippetAnchor.x, y: snippetAnchor.y - 22, surface: surface, text: text, muted: muted, accent: accent })))),
|
|
220
|
+
react_1.default.createElement("g", { style: stampRowGateStyle }, [
|
|
221
|
+
{ initials: 'AJ', kind: 'LGTM', rotation: -6 },
|
|
222
|
+
{ initials: 'MK', kind: 'ACK', rotation: 4 },
|
|
223
|
+
{ initials: 'RT', kind: 'LGTM', rotation: -3 },
|
|
224
|
+
{ initials: null, kind: null, rotation: 0 },
|
|
225
|
+
].map((s, i) => {
|
|
226
|
+
const isEmpty = s.initials === null;
|
|
227
|
+
if (isEmpty && userStamped)
|
|
228
|
+
return null;
|
|
229
|
+
const W = 54;
|
|
230
|
+
const H = 36;
|
|
231
|
+
const gap = 6;
|
|
232
|
+
const rowX = snippetAnchor.x;
|
|
233
|
+
const rowY = snippetAnchor.y + 200;
|
|
234
|
+
const cx = rowX + i * (W + gap) + W / 2;
|
|
235
|
+
const cy = rowY + H / 2;
|
|
236
|
+
const ink = isEmpty ? muted : s.kind === 'LGTM' ? success : silver;
|
|
237
|
+
return (react_1.default.createElement("g", { key: i, transform: `translate(${cx}, ${cy}) rotate(${s.rotation})`, opacity: isEmpty ? 0.55 : 0.85 },
|
|
238
|
+
react_1.default.createElement("rect", { x: -W / 2, y: -H / 2, width: W, height: H, rx: 4, fill: isEmpty ? 'none' : withAlpha(ink, 0.08), stroke: ink, strokeWidth: 1.5, strokeDasharray: isEmpty ? '3 3' : undefined }),
|
|
239
|
+
!isEmpty && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
240
|
+
react_1.default.createElement("rect", { x: -W / 2 + 3, y: -H / 2 + 3, width: W - 6, height: H - 6, rx: 2, fill: "none", stroke: ink, strokeWidth: 0.75, opacity: 0.7 }),
|
|
241
|
+
react_1.default.createElement("text", { x: 0, y: -5, textAnchor: "middle", dominantBaseline: "central", fontSize: 11, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: ink, letterSpacing: "0.1em" }, s.initials),
|
|
242
|
+
react_1.default.createElement("text", { x: 0, y: 7, textAnchor: "middle", dominantBaseline: "central", fontSize: 7, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: ink, letterSpacing: "0.14em" }, s.kind))),
|
|
243
|
+
isEmpty && (react_1.default.createElement("text", { x: 0, y: 1, textAnchor: "middle", dominantBaseline: "central", fontSize: 18, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: ink, opacity: 0.7 }, "+"))));
|
|
244
|
+
}))));
|
|
245
|
+
}
|
|
246
|
+
function SnippetCard({ x, y, surface, text, muted, accent, }) {
|
|
247
|
+
const W = 280;
|
|
248
|
+
const H = 200;
|
|
249
|
+
const HEADER = 28;
|
|
250
|
+
const lines = [
|
|
251
|
+
{ w: 170, c: muted },
|
|
252
|
+
{ w: 220, c: text },
|
|
253
|
+
{ w: 130, c: accent },
|
|
254
|
+
{ w: 200, c: text },
|
|
255
|
+
{ w: 150, c: muted },
|
|
256
|
+
{ w: 100, c: text },
|
|
257
|
+
];
|
|
258
|
+
return (react_1.default.createElement("g", { transform: `translate(${x}, ${y})` },
|
|
259
|
+
react_1.default.createElement("rect", { width: W, height: H, rx: 10, fill: surface, stroke: withAlpha(accent, 0.55), strokeWidth: 1.5 }),
|
|
260
|
+
react_1.default.createElement("rect", { width: W, height: HEADER, rx: 10, fill: withAlpha(accent, 0.08) }),
|
|
261
|
+
react_1.default.createElement("text", { x: 16, y: HEADER / 2, dominantBaseline: "central", fontSize: 13, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: text }, "db/users.ts:42"),
|
|
262
|
+
react_1.default.createElement("g", { transform: `translate(16, ${HEADER + 18})` }, lines.map((l, i) => (react_1.default.createElement("rect", { key: i, x: 0, y: i * 20, width: l.w, height: 7, rx: 2, fill: l.c, opacity: 0.75 }))))));
|
|
263
|
+
}
|
|
264
|
+
function withAlpha(color, alpha) {
|
|
265
|
+
// Accept #rgb / #rrggbb / rgb()/rgba()/hsl()/named — leave non-hex
|
|
266
|
+
// as-is and rely on the caller. For hex, append a 2-digit alpha.
|
|
267
|
+
if (/^#([0-9a-f]{3}){1,2}$/i.test(color)) {
|
|
268
|
+
let hex = color.slice(1);
|
|
269
|
+
if (hex.length === 3)
|
|
270
|
+
hex = hex.split('').map(c => c + c).join('');
|
|
271
|
+
const a = Math.round(Math.max(0, Math.min(1, alpha)) * 255)
|
|
272
|
+
.toString(16)
|
|
273
|
+
.padStart(2, '0');
|
|
274
|
+
return `#${hex}${a}`;
|
|
275
|
+
}
|
|
276
|
+
return color;
|
|
277
|
+
}
|
package/dist/esm/Logo.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export const Logo = ({ width = 150, height = 150, color = "currentColor", particleColor, letterColor, opacity = 0.9, horizontalColor, verticalColor, diagonalColor, outlineColor, showOutline = true, axisColor, showGlow = false, accentColor, }) => {
|
|
2
|
+
export const Logo = ({ width = 150, height = 150, color = "currentColor", particleColor, letterColor, opacity = 0.9, horizontalColor, verticalColor, diagonalColor, outlineColor, showOutline = true, axisColor, showGlow = false, accentColor, useTextLetter = false, letterFontFamily = "Georgia, serif", backgroundColor, }) => {
|
|
3
3
|
const finalParticleColor = particleColor || color;
|
|
4
4
|
const finalLetterColor = letterColor || particleColor || color;
|
|
5
5
|
const finalHorizontalColor = horizontalColor || color;
|
|
@@ -16,30 +16,47 @@ export const Logo = ({ width = 150, height = 150, color = "currentColor", partic
|
|
|
16
16
|
React.createElement("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.8 } },
|
|
17
17
|
React.createElement("animate", { attributeName: "stop-opacity", values: "0.8;0.3;0.8", dur: "2s", repeatCount: "indefinite" })),
|
|
18
18
|
React.createElement("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } }))),
|
|
19
|
+
backgroundColor && (React.createElement("rect", { x: "30", y: "30", width: "140", height: "140", fill: backgroundColor })),
|
|
19
20
|
showGlow && (React.createElement("circle", { cx: "100", cy: "100", r: "80", fill: "url(#sphereGlow)", opacity: "0.5" })),
|
|
20
|
-
React.createElement("
|
|
21
|
-
React.createElement("
|
|
22
|
-
React.createElement("
|
|
23
|
-
React.createElement("
|
|
24
|
-
React.createElement("
|
|
25
|
-
React.createElement("
|
|
26
|
-
React.createElement("
|
|
27
|
-
React.createElement("
|
|
28
|
-
React.createElement("
|
|
29
|
-
React.createElement("
|
|
30
|
-
React.createElement("circle", { cx: "108", cy: "95", r: "2", fill: finalLetterColor, opacity: "0.9" }),
|
|
31
|
-
React.createElement("circle", { cx: "103", cy: "100", r: "2", fill: finalLetterColor, opacity: "0.9" }),
|
|
32
|
-
React.createElement("circle", { cx: "98", cy: "100", r: "2", fill: finalLetterColor, opacity: "0.9" }),
|
|
33
|
-
React.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "27", fill: "none", stroke: finalHorizontalColor, strokeWidth: "1", opacity: "0.7" }),
|
|
34
|
-
React.createElement("ellipse", { cx: "100", cy: "100", rx: "27", ry: "67", fill: "none", stroke: finalVerticalColor, strokeWidth: "1", opacity: "0.7" }),
|
|
35
|
-
React.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "35", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(30 100 100)" }),
|
|
36
|
-
React.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "35", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(60 100 100)" }),
|
|
37
|
-
React.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "35", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(120 100 100)" }),
|
|
38
|
-
React.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "35", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(150 100 100)" }),
|
|
21
|
+
React.createElement("line", { x1: "100", y1: "33", x2: "100", y2: "68", stroke: finalAxisColor, strokeWidth: "1", opacity: "0.7" }),
|
|
22
|
+
React.createElement("line", { x1: "100", y1: "167", x2: "100", y2: "132", stroke: finalAxisColor, strokeWidth: "1", opacity: "0.7" }),
|
|
23
|
+
React.createElement("line", { x1: "33", y1: "100", x2: "68", y2: "100", stroke: finalAxisColor, strokeWidth: "1", opacity: "0.7" }),
|
|
24
|
+
React.createElement("line", { x1: "167", y1: "100", x2: "132", y2: "100", stroke: finalAxisColor, strokeWidth: "1", opacity: "0.7" }),
|
|
25
|
+
React.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "32", fill: "none", stroke: finalHorizontalColor, strokeWidth: "1", opacity: "0.7" }),
|
|
26
|
+
React.createElement("ellipse", { cx: "100", cy: "100", rx: "32", ry: "67", fill: "none", stroke: finalVerticalColor, strokeWidth: "1", opacity: "0.7" }),
|
|
27
|
+
React.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "40", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(30 100 100)" }),
|
|
28
|
+
React.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "40", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(60 100 100)" }),
|
|
29
|
+
React.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "40", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(120 100 100)" }),
|
|
30
|
+
React.createElement("ellipse", { cx: "100", cy: "100", rx: "67", ry: "40", fill: "none", stroke: finalDiagonalColor, strokeWidth: "1", opacity: "0.7", transform: "rotate(150 100 100)" }),
|
|
39
31
|
showOutline && (React.createElement("circle", { cx: "100", cy: "100", r: "67", fill: "none", stroke: finalOutlineColor, strokeWidth: "1.5", opacity: "0.9" })),
|
|
40
|
-
React.createElement("
|
|
32
|
+
useTextLetter ? (React.createElement("text", { x: "100", y: "100", textAnchor: "middle", dominantBaseline: "central", fill: finalLetterColor, fontSize: "48", fontFamily: letterFontFamily, fontWeight: "bold", opacity: "0.9" }, "P")) : (React.createElement(React.Fragment, null,
|
|
33
|
+
React.createElement("circle", { cx: "90", cy: "79", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
34
|
+
React.createElement("circle", { cx: "90", cy: "86", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
35
|
+
React.createElement("circle", { cx: "90", cy: "93", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
36
|
+
React.createElement("circle", { cx: "90", cy: "100", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
37
|
+
React.createElement("circle", { cx: "90", cy: "107", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
38
|
+
React.createElement("circle", { cx: "90", cy: "114", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
39
|
+
React.createElement("circle", { cx: "90", cy: "121", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
40
|
+
React.createElement("circle", { cx: "97", cy: "79", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
41
|
+
React.createElement("circle", { cx: "104", cy: "79", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
42
|
+
React.createElement("circle", { cx: "111", cy: "86", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
43
|
+
React.createElement("circle", { cx: "111", cy: "93", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
44
|
+
React.createElement("circle", { cx: "104", cy: "100", r: "2.5", fill: finalLetterColor, opacity: "0.9" }),
|
|
45
|
+
React.createElement("circle", { cx: "97", cy: "100", r: "2.5", fill: finalLetterColor, opacity: "0.9" }))),
|
|
46
|
+
React.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
47
|
+
React.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 167,100 A 67,32 0 0,1 33,100 A 67,32 0 0,1 167,100" })),
|
|
48
|
+
React.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
49
|
+
React.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 100,33 A 32,67 0 0,0 100,167 A 32,67 0 0,0 100,33" })),
|
|
50
|
+
React.createElement("g", { transform: "rotate(30 100 100)" },
|
|
41
51
|
React.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
42
|
-
React.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M
|
|
52
|
+
React.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 167,100 A 67,40 0 0,1 33,100 A 67,40 0 0,1 167,100" }))),
|
|
53
|
+
React.createElement("g", { transform: "rotate(60 100 100)" },
|
|
43
54
|
React.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
44
|
-
React.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M
|
|
55
|
+
React.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 167,100 A 67,40 0 0,0 33,100 A 67,40 0 0,0 167,100" }))),
|
|
56
|
+
React.createElement("g", { transform: "rotate(120 100 100)" },
|
|
57
|
+
React.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
58
|
+
React.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 167,100 A 67,40 0 0,1 33,100 A 67,40 0 0,1 167,100" }))),
|
|
59
|
+
React.createElement("g", { transform: "rotate(150 100 100)" },
|
|
60
|
+
React.createElement("circle", { r: "2.5", fill: finalParticleColor, opacity: "0.9" },
|
|
61
|
+
React.createElement("animateMotion", { dur: "8s", repeatCount: "indefinite", path: "M 167,100 A 67,40 0 0,0 33,100 A 67,40 0 0,0 167,100" })))));
|
|
45
62
|
};
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React, { useId, useMemo } from 'react';
|
|
3
|
+
const VIEW_W = 700;
|
|
4
|
+
const VIEW_H = 700;
|
|
5
|
+
const CITY_COLS = 12;
|
|
6
|
+
const CITY_ROWS = 12;
|
|
7
|
+
const CELL_W = 50;
|
|
8
|
+
const CELL_H = 50;
|
|
9
|
+
const CITY_OFFSET_X = 50;
|
|
10
|
+
const CITY_OFFSET_Y = 50;
|
|
11
|
+
/** Center point of a grid cell, in viewBox coords. */
|
|
12
|
+
function cellCenter(col, row) {
|
|
13
|
+
return {
|
|
14
|
+
x: CITY_OFFSET_X + col * CELL_W + CELL_W / 2,
|
|
15
|
+
y: CITY_OFFSET_Y + row * CELL_H + CELL_H / 2,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function buildCity(palette, pinned) {
|
|
19
|
+
const rng = mulberry32(7);
|
|
20
|
+
const cells = [];
|
|
21
|
+
for (let r = 0; r < CITY_ROWS; r++) {
|
|
22
|
+
for (let c = 0; c < CITY_COLS; c++) {
|
|
23
|
+
const isPinned = pinned.has(`${c},${r}`);
|
|
24
|
+
// Pinned cells (the ones markers sit on top of) always get a
|
|
25
|
+
// building so the marker has something to be centered on. Other
|
|
26
|
+
// cells skip occasionally to break up the grid.
|
|
27
|
+
const skipRoll = rng();
|
|
28
|
+
// Keep the RNG sequence stable so colors don't shift after dropping
|
|
29
|
+
// the per-building size jitter.
|
|
30
|
+
rng();
|
|
31
|
+
rng();
|
|
32
|
+
const colorRoll = rng();
|
|
33
|
+
if (!isPinned && skipRoll < 0.18)
|
|
34
|
+
continue;
|
|
35
|
+
const w = CELL_W - 8;
|
|
36
|
+
const h = CELL_H - 8;
|
|
37
|
+
cells.push({
|
|
38
|
+
x: CITY_OFFSET_X + c * CELL_W + (CELL_W - w) / 2,
|
|
39
|
+
y: CITY_OFFSET_Y + r * CELL_H + (CELL_H - h) / 2,
|
|
40
|
+
w,
|
|
41
|
+
h,
|
|
42
|
+
fill: palette[Math.floor(colorRoll * palette.length)],
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return cells;
|
|
47
|
+
}
|
|
48
|
+
function mulberry32(seed) {
|
|
49
|
+
let t = seed;
|
|
50
|
+
return () => {
|
|
51
|
+
t = (t + 0x6d2b79f5) | 0;
|
|
52
|
+
let r = t;
|
|
53
|
+
r = Math.imul(r ^ (r >>> 15), r | 1);
|
|
54
|
+
r ^= r + Math.imul(r ^ (r >>> 7), r | 61);
|
|
55
|
+
return ((r ^ (r >>> 14)) >>> 0) / 4294967296;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** VH leader from `a` (marker) to `b` (snippet anchor): exits `a` going
|
|
59
|
+
* vertically toward `b.y`, then turns and runs horizontally to `b.x`. */
|
|
60
|
+
function lRoutePath(a, b, radius = 12) {
|
|
61
|
+
const goingUp = b.y < a.y;
|
|
62
|
+
const ySign = goingUp ? -1 : 1;
|
|
63
|
+
const xSign = b.x < a.x ? -1 : 1;
|
|
64
|
+
const r = Math.min(radius, Math.abs(a.y - b.y) / 2, Math.abs(a.x - b.x) / 2);
|
|
65
|
+
return [
|
|
66
|
+
`M ${a.x} ${a.y}`,
|
|
67
|
+
`L ${a.x} ${b.y - ySign * r}`,
|
|
68
|
+
`Q ${a.x} ${b.y} ${a.x + xSign * r} ${b.y}`,
|
|
69
|
+
`L ${b.x} ${b.y}`,
|
|
70
|
+
].join(' ');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Static SVG version of the FileCity trail overlay — a top-down grid of
|
|
74
|
+
* building rectangles with numbered markers wired by a dashed path, plus
|
|
75
|
+
* an L-routed leader line to a snippet card. Mirrors the look of
|
|
76
|
+
* `TrailFilePath` + `TrailLeaderLine` from the 3D panel without the
|
|
77
|
+
* three.js projection — suitable for marketing surfaces.
|
|
78
|
+
*/
|
|
79
|
+
export function TrailCityDiagram({ theme, className, hideSnippet = false, snippetVisible = true, hideTrail = false, trailVisible = true, highlightTrail = false, stampRowVisible = false, userStamped = false, }) {
|
|
80
|
+
var _a, _b, _c, _d, _e, _f;
|
|
81
|
+
const snippetGateStyle = {
|
|
82
|
+
opacity: snippetVisible ? 1 : 0,
|
|
83
|
+
transition: 'opacity 500ms ease',
|
|
84
|
+
transitionDelay: snippetVisible ? '700ms' : '0ms',
|
|
85
|
+
};
|
|
86
|
+
const trailGateStyle = {
|
|
87
|
+
opacity: trailVisible ? 1 : 0,
|
|
88
|
+
transition: 'opacity 500ms ease',
|
|
89
|
+
};
|
|
90
|
+
const stampRowGateStyle = {
|
|
91
|
+
opacity: stampRowVisible ? 1 : 0,
|
|
92
|
+
transition: 'opacity 500ms ease',
|
|
93
|
+
transitionDelay: stampRowVisible ? '700ms' : '0ms',
|
|
94
|
+
};
|
|
95
|
+
const colors = theme === null || theme === void 0 ? void 0 : theme.colors;
|
|
96
|
+
const uid = useId().replace(/:/g, '');
|
|
97
|
+
const accent = (_a = colors === null || colors === void 0 ? void 0 : colors.primary) !== null && _a !== void 0 ? _a : '#22d3ee';
|
|
98
|
+
const surface = (_b = colors === null || colors === void 0 ? void 0 : colors.surface) !== null && _b !== void 0 ? _b : '#0f1419';
|
|
99
|
+
const text = (_c = colors === null || colors === void 0 ? void 0 : colors.text) !== null && _c !== void 0 ? _c : '#f8fafc';
|
|
100
|
+
const muted = (_d = colors === null || colors === void 0 ? void 0 : colors.textMuted) !== null && _d !== void 0 ? _d : '#94a3b8';
|
|
101
|
+
const bg = (_e = colors === null || colors === void 0 ? void 0 : colors.background) !== null && _e !== void 0 ? _e : '#0a0f14';
|
|
102
|
+
const success = (_f = colors === null || colors === void 0 ? void 0 : colors.success) !== null && _f !== void 0 ? _f : '#10b981';
|
|
103
|
+
// Silvery white-grey ink for ACK stamps — brighter than `muted` so it
|
|
104
|
+
// reads cleanly against the dark city.
|
|
105
|
+
const silver = '#d1d8e0';
|
|
106
|
+
const palette = useMemo(() => [
|
|
107
|
+
withAlpha(accent, 0.18),
|
|
108
|
+
withAlpha(accent, 0.32),
|
|
109
|
+
withAlpha(text, 0.08),
|
|
110
|
+
withAlpha(text, 0.14),
|
|
111
|
+
withAlpha(text, 0.22),
|
|
112
|
+
], [accent, text]);
|
|
113
|
+
const markerCells = useMemo(() => [
|
|
114
|
+
{ col: 1, row: 10, label: '1' },
|
|
115
|
+
{ col: 3, row: 7, label: '2' },
|
|
116
|
+
{ col: 6, row: 9, label: '3' },
|
|
117
|
+
{ col: 4, row: 5, label: '4' },
|
|
118
|
+
], []);
|
|
119
|
+
const pinnedCells = useMemo(() => new Set(markerCells.map(m => `${m.col},${m.row}`)), [markerCells]);
|
|
120
|
+
const buildings = useMemo(() => buildCity(palette, pinnedCells), [palette, pinnedCells]);
|
|
121
|
+
const markers = useMemo(() => markerCells.map(m => {
|
|
122
|
+
const c = cellCenter(m.col, m.row);
|
|
123
|
+
return { x: c.x, y: c.y, label: m.label };
|
|
124
|
+
}), [markerCells]);
|
|
125
|
+
const trailPath = useMemo(() => {
|
|
126
|
+
const [first, ...rest] = markers;
|
|
127
|
+
if (!first)
|
|
128
|
+
return '';
|
|
129
|
+
return [`M ${first.x} ${first.y}`, ...rest.map(m => `L ${m.x} ${m.y}`)].join(' ');
|
|
130
|
+
}, [markers]);
|
|
131
|
+
const activeMarker = markers[markers.length - 1];
|
|
132
|
+
const snippetAnchor = { x: VIEW_W - 320, y: 100 };
|
|
133
|
+
const leaderPath = useMemo(() => activeMarker
|
|
134
|
+
? lRoutePath({ x: activeMarker.x, y: activeMarker.y }, snippetAnchor)
|
|
135
|
+
: '', [activeMarker, snippetAnchor.x, snippetAnchor.y]);
|
|
136
|
+
return (React.createElement("svg", { viewBox: `0 0 ${VIEW_W} ${VIEW_H}`, className: className, style: { display: 'block', width: '100%', height: 'auto', overflow: 'visible' }, role: "img", "aria-label": "A trail of code locations connected across a top-down city of files" },
|
|
137
|
+
React.createElement("defs", null,
|
|
138
|
+
React.createElement("linearGradient", { id: `fade-${uid}`, x1: "0", x2: "0", y1: "0", y2: "1" },
|
|
139
|
+
React.createElement("stop", { offset: "0%", stopColor: bg, stopOpacity: 0 }),
|
|
140
|
+
React.createElement("stop", { offset: "100%", stopColor: bg, stopOpacity: 0.7 }))),
|
|
141
|
+
React.createElement("rect", { x: 0, y: 0, width: VIEW_W, height: VIEW_H, fill: bg, rx: 12 }),
|
|
142
|
+
React.createElement("g", { style: {
|
|
143
|
+
opacity: highlightTrail ? 0.2 : 1,
|
|
144
|
+
transition: 'opacity 300ms ease',
|
|
145
|
+
} }, buildings.map((b, i) => (React.createElement("rect", { key: i, x: b.x, y: b.y, width: b.w, height: b.h, fill: b.fill, stroke: withAlpha(text, 0.08), strokeWidth: 0.5, rx: 2 })))),
|
|
146
|
+
!hideSnippet && (() => {
|
|
147
|
+
const activeCell = markerCells[markerCells.length - 1];
|
|
148
|
+
if (!activeCell)
|
|
149
|
+
return null;
|
|
150
|
+
return (React.createElement("g", { style: snippetGateStyle },
|
|
151
|
+
React.createElement("rect", { x: CITY_OFFSET_X + activeCell.col * CELL_W + 4, y: CITY_OFFSET_Y + activeCell.row * CELL_H + 4, width: CELL_W - 8, height: CELL_H - 8, fill: "none", stroke: accent, strokeWidth: 2, rx: 2, style: {
|
|
152
|
+
opacity: highlightTrail ? 0.2 : 1,
|
|
153
|
+
transition: 'opacity 300ms ease',
|
|
154
|
+
} })));
|
|
155
|
+
})(),
|
|
156
|
+
React.createElement("rect", { x: 0, y: VIEW_H - 80, width: VIEW_W, height: 80, fill: `url(#fade-${uid})`, pointerEvents: "none" }),
|
|
157
|
+
!hideTrail && (React.createElement("g", { style: trailGateStyle },
|
|
158
|
+
React.createElement("path", { d: trailPath, fill: "none", stroke: accent, strokeWidth: highlightTrail ? 3.5 : 2, strokeLinecap: "round", strokeDasharray: "6 5", opacity: highlightTrail ? 1 : 0.9, style: {
|
|
159
|
+
transition: 'stroke-width 300ms ease, opacity 300ms ease',
|
|
160
|
+
filter: highlightTrail
|
|
161
|
+
? `drop-shadow(0 0 8px ${withAlpha(accent, 0.7)})`
|
|
162
|
+
: undefined,
|
|
163
|
+
} }, highlightTrail && (React.createElement("animate", { attributeName: "stroke-dashoffset", from: 0, to: -44, dur: "1.4s", repeatCount: "indefinite" }))))),
|
|
164
|
+
!hideSnippet && (React.createElement("g", { style: snippetGateStyle },
|
|
165
|
+
React.createElement("path", { d: leaderPath, fill: "none", stroke: accent, strokeWidth: 1.5, strokeDasharray: "5 4", opacity: highlightTrail ? 0 : 0.7, style: { transition: 'opacity 300ms ease' } }),
|
|
166
|
+
activeMarker && (React.createElement("circle", { cx: activeMarker.x, cy: activeMarker.y, r: 3.5, fill: accent, opacity: highlightTrail ? 0 : 1, style: { transition: 'opacity 300ms ease' } })))),
|
|
167
|
+
!hideTrail && (React.createElement("g", { style: trailGateStyle }, markers.map((m, i) => {
|
|
168
|
+
const isActive = i === markers.length - 1;
|
|
169
|
+
const size = 22;
|
|
170
|
+
const half = size / 2;
|
|
171
|
+
return (React.createElement("g", { key: m.label },
|
|
172
|
+
isActive && (React.createElement("rect", { x: m.x - half - 4, y: m.y - half - 4, width: size + 8, height: size + 8, rx: 6, fill: accent, opacity: 0.18 },
|
|
173
|
+
React.createElement("animate", { attributeName: "opacity", values: "0.28;0;0.28", dur: "2.4s", repeatCount: "indefinite" }))),
|
|
174
|
+
React.createElement("rect", { x: m.x - half, y: m.y - half, width: size, height: size, rx: 4, fill: surface, stroke: accent, strokeWidth: 1.75 }),
|
|
175
|
+
React.createElement("text", { x: m.x, y: m.y + 1, textAnchor: "middle", dominantBaseline: "central", fontSize: 14, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: text }, m.label)));
|
|
176
|
+
}))),
|
|
177
|
+
!hideSnippet && (React.createElement("g", { style: snippetGateStyle },
|
|
178
|
+
React.createElement("g", { style: {
|
|
179
|
+
opacity: highlightTrail ? 0.15 : 1,
|
|
180
|
+
transition: 'opacity 300ms ease',
|
|
181
|
+
} },
|
|
182
|
+
React.createElement("circle", { cx: snippetAnchor.x, cy: snippetAnchor.y, r: 3.5, fill: accent }),
|
|
183
|
+
React.createElement(SnippetCard, { x: snippetAnchor.x, y: snippetAnchor.y - 22, surface: surface, text: text, muted: muted, accent: accent })))),
|
|
184
|
+
React.createElement("g", { style: stampRowGateStyle }, [
|
|
185
|
+
{ initials: 'AJ', kind: 'LGTM', rotation: -6 },
|
|
186
|
+
{ initials: 'MK', kind: 'ACK', rotation: 4 },
|
|
187
|
+
{ initials: 'RT', kind: 'LGTM', rotation: -3 },
|
|
188
|
+
{ initials: null, kind: null, rotation: 0 },
|
|
189
|
+
].map((s, i) => {
|
|
190
|
+
const isEmpty = s.initials === null;
|
|
191
|
+
if (isEmpty && userStamped)
|
|
192
|
+
return null;
|
|
193
|
+
const W = 54;
|
|
194
|
+
const H = 36;
|
|
195
|
+
const gap = 6;
|
|
196
|
+
const rowX = snippetAnchor.x;
|
|
197
|
+
const rowY = snippetAnchor.y + 200;
|
|
198
|
+
const cx = rowX + i * (W + gap) + W / 2;
|
|
199
|
+
const cy = rowY + H / 2;
|
|
200
|
+
const ink = isEmpty ? muted : s.kind === 'LGTM' ? success : silver;
|
|
201
|
+
return (React.createElement("g", { key: i, transform: `translate(${cx}, ${cy}) rotate(${s.rotation})`, opacity: isEmpty ? 0.55 : 0.85 },
|
|
202
|
+
React.createElement("rect", { x: -W / 2, y: -H / 2, width: W, height: H, rx: 4, fill: isEmpty ? 'none' : withAlpha(ink, 0.08), stroke: ink, strokeWidth: 1.5, strokeDasharray: isEmpty ? '3 3' : undefined }),
|
|
203
|
+
!isEmpty && (React.createElement(React.Fragment, null,
|
|
204
|
+
React.createElement("rect", { x: -W / 2 + 3, y: -H / 2 + 3, width: W - 6, height: H - 6, rx: 2, fill: "none", stroke: ink, strokeWidth: 0.75, opacity: 0.7 }),
|
|
205
|
+
React.createElement("text", { x: 0, y: -5, textAnchor: "middle", dominantBaseline: "central", fontSize: 11, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: ink, letterSpacing: "0.1em" }, s.initials),
|
|
206
|
+
React.createElement("text", { x: 0, y: 7, textAnchor: "middle", dominantBaseline: "central", fontSize: 7, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: ink, letterSpacing: "0.14em" }, s.kind))),
|
|
207
|
+
isEmpty && (React.createElement("text", { x: 0, y: 1, textAnchor: "middle", dominantBaseline: "central", fontSize: 18, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: ink, opacity: 0.7 }, "+"))));
|
|
208
|
+
}))));
|
|
209
|
+
}
|
|
210
|
+
function SnippetCard({ x, y, surface, text, muted, accent, }) {
|
|
211
|
+
const W = 280;
|
|
212
|
+
const H = 200;
|
|
213
|
+
const HEADER = 28;
|
|
214
|
+
const lines = [
|
|
215
|
+
{ w: 170, c: muted },
|
|
216
|
+
{ w: 220, c: text },
|
|
217
|
+
{ w: 130, c: accent },
|
|
218
|
+
{ w: 200, c: text },
|
|
219
|
+
{ w: 150, c: muted },
|
|
220
|
+
{ w: 100, c: text },
|
|
221
|
+
];
|
|
222
|
+
return (React.createElement("g", { transform: `translate(${x}, ${y})` },
|
|
223
|
+
React.createElement("rect", { width: W, height: H, rx: 10, fill: surface, stroke: withAlpha(accent, 0.55), strokeWidth: 1.5 }),
|
|
224
|
+
React.createElement("rect", { width: W, height: HEADER, rx: 10, fill: withAlpha(accent, 0.08) }),
|
|
225
|
+
React.createElement("text", { x: 16, y: HEADER / 2, dominantBaseline: "central", fontSize: 13, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: text }, "db/users.ts:42"),
|
|
226
|
+
React.createElement("g", { transform: `translate(16, ${HEADER + 18})` }, lines.map((l, i) => (React.createElement("rect", { key: i, x: 0, y: i * 20, width: l.w, height: 7, rx: 2, fill: l.c, opacity: 0.75 }))))));
|
|
227
|
+
}
|
|
228
|
+
function withAlpha(color, alpha) {
|
|
229
|
+
// Accept #rgb / #rrggbb / rgb()/rgba()/hsl()/named — leave non-hex
|
|
230
|
+
// as-is and rely on the caller. For hex, append a 2-digit alpha.
|
|
231
|
+
if (/^#([0-9a-f]{3}){1,2}$/i.test(color)) {
|
|
232
|
+
let hex = color.slice(1);
|
|
233
|
+
if (hex.length === 3)
|
|
234
|
+
hex = hex.split('').map(c => c + c).join('');
|
|
235
|
+
const a = Math.round(Math.max(0, Math.min(1, alpha)) * 255)
|
|
236
|
+
.toString(16)
|
|
237
|
+
.padStart(2, '0');
|
|
238
|
+
return `#${hex}${a}`;
|
|
239
|
+
}
|
|
240
|
+
return color;
|
|
241
|
+
}
|
package/dist/esm/index.js
CHANGED
|
@@ -6,5 +6,6 @@ export { WreathLogo } from './WreathLogo';
|
|
|
6
6
|
export { TelemetryReveal } from './TelemetryReveal';
|
|
7
7
|
export { TextReveal } from './TextReveal';
|
|
8
8
|
export { OpenTypeTextReveal } from './OpenTypeTextReveal';
|
|
9
|
+
export { TrailCityDiagram } from './TrailCityDiagram';
|
|
9
10
|
export { TELEMETRY_PRESETS } from './presets';
|
|
10
11
|
export { STROKE_CHARACTERS, layoutText } from './strokeCharacters';
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export { WreathLogo } from './WreathLogo';
|
|
|
6
6
|
export { TelemetryReveal } from './TelemetryReveal';
|
|
7
7
|
export { TextReveal } from './TextReveal';
|
|
8
8
|
export { OpenTypeTextReveal } from './OpenTypeTextReveal';
|
|
9
|
+
export { TrailCityDiagram } from './TrailCityDiagram';
|
|
10
|
+
export type { TrailCityDiagramProps } from './TrailCityDiagram';
|
|
9
11
|
export { TELEMETRY_PRESETS } from './presets';
|
|
10
12
|
export { STROKE_CHARACTERS, layoutText } from './strokeCharacters';
|
|
11
13
|
export type { PathDefinition, ShapePreset } from './presets';
|
package/dist/index.esm.js
CHANGED
|
@@ -6,5 +6,6 @@ export { WreathLogo } from './WreathLogo';
|
|
|
6
6
|
export { TelemetryReveal } from './TelemetryReveal';
|
|
7
7
|
export { TextReveal } from './TextReveal';
|
|
8
8
|
export { OpenTypeTextReveal } from './OpenTypeTextReveal';
|
|
9
|
+
export { TrailCityDiagram } from './TrailCityDiagram';
|
|
9
10
|
export { TELEMETRY_PRESETS } from './presets';
|
|
10
11
|
export { STROKE_CHARACTERS, layoutText } from './strokeCharacters';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.layoutText = exports.STROKE_CHARACTERS = exports.TELEMETRY_PRESETS = exports.OpenTypeTextReveal = exports.TextReveal = exports.TelemetryReveal = exports.WreathLogo = exports.SquareLogo = exports.ForksLogo = exports.LogoSmall = exports.Logo = void 0;
|
|
3
|
+
exports.layoutText = exports.STROKE_CHARACTERS = exports.TELEMETRY_PRESETS = exports.TrailCityDiagram = exports.OpenTypeTextReveal = exports.TextReveal = exports.TelemetryReveal = exports.WreathLogo = exports.SquareLogo = exports.ForksLogo = exports.LogoSmall = exports.Logo = void 0;
|
|
4
4
|
var Logo_1 = require("./Logo");
|
|
5
5
|
Object.defineProperty(exports, "Logo", { enumerable: true, get: function () { return Logo_1.Logo; } });
|
|
6
6
|
var LogoSmall_1 = require("./LogoSmall");
|
|
@@ -17,6 +17,8 @@ var TextReveal_1 = require("./TextReveal");
|
|
|
17
17
|
Object.defineProperty(exports, "TextReveal", { enumerable: true, get: function () { return TextReveal_1.TextReveal; } });
|
|
18
18
|
var OpenTypeTextReveal_1 = require("./OpenTypeTextReveal");
|
|
19
19
|
Object.defineProperty(exports, "OpenTypeTextReveal", { enumerable: true, get: function () { return OpenTypeTextReveal_1.OpenTypeTextReveal; } });
|
|
20
|
+
var TrailCityDiagram_1 = require("./TrailCityDiagram");
|
|
21
|
+
Object.defineProperty(exports, "TrailCityDiagram", { enumerable: true, get: function () { return TrailCityDiagram_1.TrailCityDiagram; } });
|
|
20
22
|
var presets_1 = require("./presets");
|
|
21
23
|
Object.defineProperty(exports, "TELEMETRY_PRESETS", { enumerable: true, get: function () { return presets_1.TELEMETRY_PRESETS; } });
|
|
22
24
|
var strokeCharacters_1 = require("./strokeCharacters");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@principal-ai/logo-component",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Animated wireframe sphere logo component",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"react": "^18.0.0 || ^19.0.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@principal-ade/industry-theme": "^0.1.
|
|
29
|
+
"@principal-ade/industry-theme": "^0.1.19",
|
|
30
30
|
"@storybook/addon-essentials": "^8.6.14",
|
|
31
31
|
"@storybook/blocks": "^8.6.14",
|
|
32
32
|
"@storybook/react": "^8.6.14",
|