3 Commits

Author SHA1 Message Date
ahmed f4b7cef249 Revert CI, gitea bug
Publish Docker Image / Publish Docker Image (push) Successful in 51s
2025-05-02 13:41:50 -04:00
ahmed 4ff5e016b0 Embed version and fps
Publish Docker Image / build (push) Failing after 2m0s
2025-05-02 13:29:34 -04:00
ahmed 84b1c36073 [#1] Remove office phone and add email app
Publish Docker Image / Publish Docker Image (push) Successful in 1m1s
2025-05-01 22:32:48 -04:00
13 changed files with 521 additions and 216 deletions
+14 -6
View File
@@ -1,28 +1,36 @@
version: "1"
name: Publish Docker Image
on:
push:
tags:
- "v[0-9]+\\.[0-9]+\\.[0-9]+"
- "*"
jobs:
build:
name: Publish Docker Image
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v3
- name: Login to Registry
run: echo "${{ secrets.ACCESS_TOKEN }}" | docker login git.altaiar.dev -u "${{ secrets.USERNAME }}" --password-stdin
run: echo "${{ secrets.ACCESS_TOKEN }}" \
| docker login git.altaiar.dev -u "${{ secrets.USERNAME }}" --password-stdin
- name: Build & Tag Image
run: |
docker build -t git.altaiar.dev/${{ gitea.repository }}:${{ gitea.ref_name }} .
docker tag git.altaiar.dev/${{ gitea.repository }}:${{ gitea.ref_name }} git.altaiar.dev/${{ gitea.repository }}:latest
docker build \
--build-arg APP_VERSION=${{ gitea.ref_name }} \
--label org.opencontainers.image.version=${{ gitea.ref_name }} \
-t git.altaiar.dev/${{ gitea.repository }}:${{ gitea.ref_name }} .
docker tag \
git.altaiar.dev/${{ gitea.repository }}:${{ gitea.ref_name }} \
git.altaiar.dev/${{ gitea.repository }}:latest
- name: Push Images
run: |
+9 -3
View File
@@ -1,9 +1,18 @@
ARG APP_VERSION=dev
FROM node:lts-alpine AS deps
ARG APP_VERSION
WORKDIR /app
RUN corepack enable && corepack prepare yarn@4.9.1 --activate
COPY package.json yarn.lock .yarnrc.yml ./
RUN yarn install --immutable
FROM node:lts-alpine AS runner
ARG APP_VERSION=dev
ENV NEXT_PUBLIC_APP_VERSION=$APP_VERSION \
APP_VERSION=$APP_VERSION \
NODE_ENV=production \
NEXT_TELEMETRY_DISABLED=1 \
PORT=3000
LABEL org.opencontainers.image.version=$APP_VERSION
WORKDIR /app
RUN corepack enable && corepack prepare yarn@4.9.1 --activate \
&& addgroup -S nodejs -g 1001 \
@@ -13,8 +22,5 @@ COPY --from=deps /app/package.json ./package.json
COPY . .
RUN chown -R nextjs:nodejs /app
USER nextjs
ENV NODE_ENV=production \
NEXT_TELEMETRY_DISABLED=1 \
PORT=3000
EXPOSE 3000
CMD ["sh", "-c", "yarn build && yarn start -p $PORT"]
+5 -1
View File
@@ -1,5 +1,9 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {};
const nextConfig: NextConfig = {
env: {
NEXT_PUBLIC_APP_VERSION: process.env.NEXT_PUBLIC_APP_VERSION || "dev",
},
};
export default nextConfig;
+1
View File
@@ -35,6 +35,7 @@
"eslint": "^9",
"eslint-config-next": "15.3.0",
"tailwindcss": "^4",
"tailwindcss-text-fill-stroke": "^2.0.0-beta.3",
"typescript": "^5"
},
"packageManager": "yarn@4.9.1+sha512.f95ce356460e05be48d66401c1ae64ef84d163dd689964962c6888a9810865e39097a5e9de748876c2e0bf89b232d583c33982773e9903ae7a76257270986538"
+1
View File
@@ -1 +1,2 @@
@import "tailwindcss";
@plugin "tailwindcss-text-fill-stroke";
+12 -124
View File
@@ -15,7 +15,6 @@ import {
BackSide,
} from "three";
import { Billboard, Text } from "@react-three/drei";
import { useConfig } from "../hooks/useConfig";
interface ButtonsProps {
menuTraversal: Stack<View>;
@@ -23,7 +22,6 @@ interface ButtonsProps {
pendingView: View | null;
setPendingView: Dispatch<SetStateAction<View | null>>;
goPreviousView(): void;
phoneHovered: boolean;
currentView: View;
}
@@ -35,11 +33,8 @@ export const Buttons = ({
pendingView,
setPendingView,
goPreviousView,
phoneHovered,
currentView,
}: ButtonsProps) => {
const config = useConfig();
const [hovered, setHovered] = useState<View | null>(null);
const desktopRef = useDisableRaycast(currentView !== View.MainView);
@@ -47,8 +42,6 @@ export const Buttons = ({
const sideRef = useDisableRaycast(currentView !== View.MainView);
const cellphoneRef = useDisableRaycast(currentView !== View.DesktopView);
const pcRef = useDisableRaycast(currentView !== View.DesktopView);
const resumeRef = useDisableRaycast(currentView !== View.SideView);
const phoneRef = useDisableRaycast(currentView !== View.SideView);
const goToView = useCallback(
(view: View) => {
@@ -89,12 +82,12 @@ export const Buttons = ({
}, [menuTraversal, pendingView, setPendingView]);
useEffect(() => {
if (hovered || phoneHovered) {
if (hovered) {
document.body.style.cursor = "pointer";
} else {
document.body.style.cursor = "auto";
}
}, [hovered, phoneHovered]);
}, [hovered]);
const mainMenuSpring = useThreeSpring<MeshStandardMaterial>({
opacity: currentView === View.MainView ? 1 : 0,
@@ -116,14 +109,11 @@ export const Buttons = ({
const printerMenuSpring = useThreeSpring<MeshStandardMaterial>({
opacity: currentView === View.PrinterView ? 1 : 0,
});
const sideMenuSpring = useThreeSpring<MeshStandardMaterial>({
opacity: currentView === View.SideView ? 1 : 0,
});
const desktopViewSpring = useThreeSpring<BufferGeometry>({
scale: hovered === View.DesktopView ? 1.25 : 1,
});
const sideViewSpring = useThreeSpring<BufferGeometry>({
scale: hovered === View.SideView ? 1.25 : 1,
const resumeViewSpring = useThreeSpring<BufferGeometry>({
scale: hovered === View.ResumeView ? 1.25 : 1,
});
const cellphoneViewSpring = useThreeSpring<BufferGeometry>({
scale: hovered === View.CellphoneView ? 1.25 : 1,
@@ -134,15 +124,9 @@ export const Buttons = ({
const creditsViewSpring = useThreeSpring<BufferGeometry>({
scale: hovered === View.CreditsView ? 1.25 : 1,
});
const resumeViewSpring = useThreeSpring<BufferGeometry>({
scale: hovered === View.ResumeView ? 1.25 : 1,
});
const printerViewSpring = useThreeSpring<BufferGeometry>({
scale: hovered === View.PrinterView ? 1.25 : 1,
});
const phoneViewSpring = useThreeSpring<BufferGeometry>({
scale: hovered === View.PhoneView ? 1.25 : 1,
});
return (
<>
@@ -242,16 +226,16 @@ export const Buttons = ({
position={[2.525, 6, 6.75]}
onClick={
currentView === View.MainView
? () => goToView(View.SideView)
? () => goToView(View.ResumeView)
: undefined
}
onPointerOver={
currentView === View.MainView
? () => setHovered(View.SideView)
? () => setHovered(View.ResumeView)
: undefined
}
onPointerOut={() => setHovered(null)}
scale={sideViewSpring.scale}
scale={resumeViewSpring.scale}
>
<sphereGeometry args={[0.6, 32, 32]} />
<animated.meshStandardMaterial
@@ -260,7 +244,10 @@ export const Buttons = ({
opacity={mainMenuSpring.opacity}
/>
</animated.mesh>
<animated.mesh position={[2.525, 6, 6.75]} scale={sideViewSpring.scale}>
<animated.mesh
position={[2.525, 6, 6.75]}
scale={resumeViewSpring.scale}
>
<sphereGeometry args={[0.65, 32, 32]} />
<animated.meshStandardMaterial
transparent
@@ -277,7 +264,7 @@ export const Buttons = ({
fillOpacity={mainMenuSpring.opacity}
outlineOpacity={mainMenuSpring.opacity}
>
Resume & Contact
Resume
</AnimatedText>
</Billboard>
</group>
@@ -450,105 +437,6 @@ export const Buttons = ({
</AnimatedText>
</Billboard>
</group>
{/* Side Menu */}
<group>
<animated.mesh
ref={resumeRef}
position={[2.845, 4.75, 6.454]}
onClick={
currentView === View.SideView
? () => goToView(View.ResumeView)
: undefined
}
onPointerOver={
currentView === View.SideView
? () => setHovered(View.ResumeView)
: undefined
}
onPointerOut={() => setHovered(null)}
scale={resumeViewSpring.scale}
>
<sphereGeometry args={[0.175, 32, 32]} />
<animated.meshStandardMaterial
transparent
color="white"
opacity={sideMenuSpring.opacity}
/>
</animated.mesh>
<animated.mesh
position={[2.845, 4.75, 6.454]}
scale={resumeViewSpring.scale}
>
<sphereGeometry args={[0.175 + 7 / 480, 32, 32]} />
<animated.meshStandardMaterial
transparent
color="black"
opacity={sideMenuSpring.opacity}
side={BackSide}
/>
</animated.mesh>
<Billboard position={[2.845, 5.1875, 6.454]}>
<AnimatedText
font="/assets/inter.ttf"
fontSize={0.21875}
outlineWidth={7 / 480}
fillOpacity={sideMenuSpring.opacity}
outlineOpacity={sideMenuSpring.opacity}
>
Resume
</AnimatedText>
</Billboard>
{config.phoneNumber && (
<>
<animated.mesh
ref={phoneRef}
position={[3.75, 5.125, 7]}
onClick={
currentView === View.SideView
? () => goToView(View.PhoneView)
: undefined
}
onPointerOver={
currentView === View.SideView
? () => setHovered(View.PhoneView)
: undefined
}
onPointerOut={() => setHovered(null)}
scale={phoneViewSpring.scale}
>
<sphereGeometry args={[0.175, 32, 32]} />
<animated.meshStandardMaterial
transparent
color="white"
opacity={sideMenuSpring.opacity}
/>
</animated.mesh>
<animated.mesh
position={[3.75, 5.125, 7]}
scale={phoneViewSpring.scale}
>
<sphereGeometry args={[0.175 + 7 / 480, 32, 32]} />
<animated.meshStandardMaterial
transparent
color="black"
opacity={sideMenuSpring.opacity}
side={BackSide}
/>
</animated.mesh>
<Billboard position={[3.75, 5.515, 7]}>
<AnimatedText
font="/assets/inter.ttf"
fontSize={0.21875}
outlineWidth={7 / 480}
fillOpacity={sideMenuSpring.opacity}
outlineOpacity={sideMenuSpring.opacity}
>
Contact
</AnimatedText>
</Billboard>
</>
)}
</group>
</>
);
};
+33 -65
View File
@@ -26,9 +26,11 @@ import {
Suspense,
useCallback,
type JSX,
type Dispatch,
type SetStateAction,
} from "react";
import Stack from "@/util/stack";
import { Canvas } from "@react-three/fiber";
import { Canvas, useFrame } from "@react-three/fiber";
import { mdiArrowLeftBold } from "@mdi/js";
import { Icon } from "@mdi/react";
import { PDF } from "../util/PDF";
@@ -42,12 +44,35 @@ import { Buttons } from "./Buttons";
import { Credits } from "../ui/Credits";
import { isWebGL2Available } from "@react-three/drei";
import { useWindowSize } from "../hooks/useWindowSize";
import { Info } from "../util/Info";
const AnimatedCam = threeAnimated(PerspectiveCamera);
const AnimatedButton = webAnimated.button as React.ComponentType<
React.ButtonHTMLAttributes<HTMLButtonElement> & { children?: React.ReactNode }
>;
function FpsUpdater({
onUpdate,
}: {
onUpdate: Dispatch<SetStateAction<number>>;
}) {
const fpsRef = useRef([0]);
useFrame((_, delta) => fpsRef.current.push(1 / delta));
useEffect(() => {
const id = setInterval(() => {
const avg =
fpsRef.current.reduce((a, b) => a + b, 0) / fpsRef.current.length;
fpsRef.current = [];
onUpdate(avg);
}, 1000);
return () => clearInterval(id);
}, [onUpdate]);
return null;
}
export function Scene(props: JSX.IntrinsicElements["group"]) {
const { nodes, materials } = useGLTF("/scene.glb") as unknown as GLTFResult;
const { progress } = useProgress();
@@ -55,8 +80,8 @@ export function Scene(props: JSX.IntrinsicElements["group"]) {
const config = useConfig();
// States
const [fps, setFps] = useState(0);
const [pendingView, setPendingView] = useState<View | null>(null);
const [phoneHovered, setPhoneHovered] = useState(false);
const [backHovered, setBackHovered] = useState(false);
const [backClicked, setBackClicked] = useState(false);
const [menuTraversal, setMenuTraversal] = useState<Stack<View>>(() => {
@@ -126,7 +151,7 @@ export function Scene(props: JSX.IntrinsicElements["group"]) {
{isWebGL2Available() ? (
width >= 1.5 * height ? (
<>
<div className="pointer-events-none fixed z-[999999999]">
<div className="pointer-events-none fixed z-[999999999] size-full">
<AnimatedButton
style={{
transform: backScale.to(
@@ -151,6 +176,10 @@ export function Scene(props: JSX.IntrinsicElements["group"]) {
className="stroke-[0.75] stroke-black"
/>
</AnimatedButton>
<div className="min-w-12 text-white bottom-0 right-0 absolute m-3 p-1 text-xs text-right text-stroke-2 text-stroke-black paint-sfm">
<Info />
{isNaN(fps) ? "-" : fps.toFixed(0)} fps
</div>
</div>
<Canvas
shadows
@@ -174,6 +203,7 @@ export function Scene(props: JSX.IntrinsicElements["group"]) {
}
>
<group {...props} dispose={null}>
<FpsUpdater onUpdate={setFps} />
<Environment preset="apartment" />
<AnimatedCam makeDefault {...cameraSpring} />
<Buttons
@@ -182,7 +212,6 @@ export function Scene(props: JSX.IntrinsicElements["group"]) {
pendingView={pendingView}
setPendingView={setPendingView}
goPreviousView={goPreviousView}
phoneHovered={phoneHovered}
currentView={currentView}
/>
<group>
@@ -321,67 +350,6 @@ export function Scene(props: JSX.IntrinsicElements["group"]) {
</Html>
</mesh>
</group>
<group
position={[4, 4.74056, 7.25]}
rotation={[-Math.PI, -Math.PI / 4, -Math.PI]}
scale={0.3}
>
<group
position={[-0.45957, -1.57735, -0.97302]}
rotation={[-Math.PI / 2, 0, 0]}
scale={100}
onClick={
config.phoneNumber && currentView === View.PhoneView
? () => {
window.open(
`tel:${config.phoneNumber}`,
"_blank",
"noopener,noreferrer"
);
}
: undefined
}
onPointerOver={
config.phoneNumber && currentView === View.PhoneView
? () => setPhoneHovered(true)
: undefined
}
onPointerOut={() => setPhoneHovered(false)}
>
<mesh
castShadow
receiveShadow
geometry={nodes.Top.geometry}
material={materials.TopMaterial}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.OfficePhoneBody.geometry}
material={materials.OfficePhoneBodyMaterial}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Screen.geometry}
material={materials.ScreenMaterial}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Buttons.geometry}
material={materials.HandleAndButtonsMaterial}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Handle.geometry}
material={materials.HandleAndButtonsMaterial}
position={[-0.01639, -0.0078, 0.02006]}
rotation={[-0.37437, 0, Math.PI / 2]}
/>
</group>
</group>
<Text
position={[-2.415, 12.5, -6]}
font="/assets/inter-bold.ttf"
+1 -7
View File
@@ -36,11 +36,6 @@ export const views: PerspectiveCameraProps[] = [
position: [3.0143, 5.5, 6.0997],
rotation: [-2.55743, -0.69621, -2.74104],
},
{
// SideView
position: [0.5, 7.75, 4.15],
rotation: [-2.1005, -0.68155, -2.35619],
},
{
// CreditsView
position: [1.25, 5.9822, -2.075],
@@ -56,8 +51,7 @@ export enum View {
CellphoneView = 4,
DesktopView = 5,
PhoneView = 6,
SideView = 7,
CreditsView = 8,
CreditsView = 7,
}
export const hashtoView: Record<string, View> = {
+12
View File
@@ -27,6 +27,7 @@ import {
mdiWifi,
mdiBattery80,
mdiHelp,
mdiEmail,
} from "@mdi/js";
import Icon from "@mdi/react";
import { useRef, useState } from "react";
@@ -88,6 +89,17 @@ export const CellphoneUI = () => {
<div className={`${appClass} ${fillerClass}`}>
<Icon path={mdiCalculator} className="text-neutral-300" />
</div>
{config.email && (
<a
href={`mailto:${config.email}`}
target="_blank"
className={appClass}
onMouseOver={handleEnter}
onMouseOut={handleLeave}
>
<Icon path={mdiEmail} className="text-neutral-300" />
</a>
)}
{config.socials?.matrix && (
<a
href={`https://matrix.to/#/${config.socials.matrix}`}
+5
View File
@@ -0,0 +1,5 @@
import { type HTMLAttributes } from "react";
export const Info = (props: HTMLAttributes<HTMLParagraphElement>) => (
<p {...props}>{process.env.NEXT_PUBLIC_APP_VERSION}</p>
);
+5
View File
@@ -66,6 +66,11 @@ export async function register() {
format: "phone",
nullable: true,
},
email: {
type: "string",
format: "email",
nullable: true,
},
fallbackUrl: {
type: "string",
format: "uri",
+1
View File
@@ -16,6 +16,7 @@ export interface Config {
tags?: string[];
}[];
phoneNumber?: string;
email?: string;
fallbackUrl?: string;
name: [string, string];
status?: string;
+422 -10
View File
@@ -403,6 +403,48 @@ __metadata:
languageName: node
linkType: hard
"@jridgewell/gen-mapping@npm:^0.3.2":
version: 0.3.8
resolution: "@jridgewell/gen-mapping@npm:0.3.8"
dependencies:
"@jridgewell/set-array": "npm:^1.2.1"
"@jridgewell/sourcemap-codec": "npm:^1.4.10"
"@jridgewell/trace-mapping": "npm:^0.3.24"
checksum: 10c0/c668feaf86c501d7c804904a61c23c67447b2137b813b9ce03eca82cb9d65ac7006d766c218685d76e3d72828279b6ee26c347aa1119dab23fbaf36aed51585a
languageName: node
linkType: hard
"@jridgewell/resolve-uri@npm:^3.1.0":
version: 3.1.2
resolution: "@jridgewell/resolve-uri@npm:3.1.2"
checksum: 10c0/d502e6fb516b35032331406d4e962c21fe77cdf1cbdb49c6142bcbd9e30507094b18972778a6e27cbad756209cfe34b1a27729e6fa08a2eb92b33943f680cf1e
languageName: node
linkType: hard
"@jridgewell/set-array@npm:^1.2.1":
version: 1.2.1
resolution: "@jridgewell/set-array@npm:1.2.1"
checksum: 10c0/2a5aa7b4b5c3464c895c802d8ae3f3d2b92fcbe84ad12f8d0bfbb1f5ad006717e7577ee1fd2eac00c088abe486c7adb27976f45d2941ff6b0b92b2c3302c60f4
languageName: node
linkType: hard
"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14":
version: 1.5.0
resolution: "@jridgewell/sourcemap-codec@npm:1.5.0"
checksum: 10c0/2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18
languageName: node
linkType: hard
"@jridgewell/trace-mapping@npm:^0.3.24":
version: 0.3.25
resolution: "@jridgewell/trace-mapping@npm:0.3.25"
dependencies:
"@jridgewell/resolve-uri": "npm:^3.1.0"
"@jridgewell/sourcemap-codec": "npm:^1.4.14"
checksum: 10c0/3d1ce6ebc69df9682a5a8896b414c6537e428a1d68b02fcc8363b04284a8ca0df04d0ee3013132252ab14f2527bc13bea6526a912ecb5658f0e39fd2860b4df4
languageName: node
linkType: hard
"@mdi/js@npm:^7.4.47":
version: 7.4.47
resolution: "@mdi/js@npm:7.4.47"
@@ -1410,6 +1452,30 @@ __metadata:
languageName: node
linkType: hard
"any-promise@npm:^1.0.0":
version: 1.3.0
resolution: "any-promise@npm:1.3.0"
checksum: 10c0/60f0298ed34c74fef50daab88e8dab786036ed5a7fad02e012ab57e376e0a0b4b29e83b95ea9b5e7d89df762f5f25119b83e00706ecaccb22cfbacee98d74889
languageName: node
linkType: hard
"anymatch@npm:~3.1.2":
version: 3.1.3
resolution: "anymatch@npm:3.1.3"
dependencies:
normalize-path: "npm:^3.0.0"
picomatch: "npm:^2.0.4"
checksum: 10c0/57b06ae984bc32a0d22592c87384cd88fe4511b1dd7581497831c56d41939c8a001b28e7b853e1450f2bf61992dfcaa8ae2d0d161a0a90c4fb631ef07098fbac
languageName: node
linkType: hard
"arg@npm:^5.0.2":
version: 5.0.2
resolution: "arg@npm:5.0.2"
checksum: 10c0/ccaf86f4e05d342af6666c569f844bec426595c567d32a8289715087825c2ca7edd8a3d204e4d2fb2aa4602e09a57d0c13ea8c9eea75aac3dbb4af5514e6800e
languageName: node
linkType: hard
"argparse@npm:^2.0.1":
version: 2.0.1
resolution: "argparse@npm:2.0.1"
@@ -1617,6 +1683,13 @@ __metadata:
languageName: node
linkType: hard
"binary-extensions@npm:^2.0.0":
version: 2.3.0
resolution: "binary-extensions@npm:2.3.0"
checksum: 10c0/75a59cafc10fb12a11d510e77110c6c7ae3f4ca22463d52487709ca7f18f69d886aa387557cc9864fbdb10153d0bdb4caacabf11541f55e89ed6e18d12ece2b5
languageName: node
linkType: hard
"bl@npm:^4.0.3":
version: 4.1.0
resolution: "bl@npm:4.1.0"
@@ -1647,7 +1720,7 @@ __metadata:
languageName: node
linkType: hard
"braces@npm:^3.0.3":
"braces@npm:^3.0.3, braces@npm:~3.0.2":
version: 3.0.3
resolution: "braces@npm:3.0.3"
dependencies:
@@ -1744,6 +1817,13 @@ __metadata:
languageName: node
linkType: hard
"camelcase-css@npm:^2.0.1":
version: 2.0.1
resolution: "camelcase-css@npm:2.0.1"
checksum: 10c0/1a1a3137e8a781e6cbeaeab75634c60ffd8e27850de410c162cce222ea331cd1ba5364e8fb21c95e5ca76f52ac34b81a090925ca00a87221355746d049c6e273
languageName: node
linkType: hard
"camera-controls@npm:^2.9.0":
version: 2.10.1
resolution: "camera-controls@npm:2.10.1"
@@ -1795,6 +1875,25 @@ __metadata:
languageName: node
linkType: hard
"chokidar@npm:^3.6.0":
version: 3.6.0
resolution: "chokidar@npm:3.6.0"
dependencies:
anymatch: "npm:~3.1.2"
braces: "npm:~3.0.2"
fsevents: "npm:~2.3.2"
glob-parent: "npm:~5.1.2"
is-binary-path: "npm:~2.1.0"
is-glob: "npm:~4.0.1"
normalize-path: "npm:~3.0.0"
readdirp: "npm:~3.6.0"
dependenciesMeta:
fsevents:
optional: true
checksum: 10c0/8361dcd013f2ddbe260eacb1f3cb2f2c6f2b0ad118708a343a5ed8158941a39cb8fb1d272e0f389712e74ee90ce8ba864eece9e0e62b9705cb468a2f6d917462
languageName: node
linkType: hard
"chownr@npm:^1.1.1":
version: 1.1.4
resolution: "chownr@npm:1.1.4"
@@ -1859,6 +1958,13 @@ __metadata:
languageName: node
linkType: hard
"commander@npm:^4.0.0":
version: 4.1.1
resolution: "commander@npm:4.1.1"
checksum: 10c0/84a76c08fe6cc08c9c93f62ac573d2907d8e79138999312c92d4155bc2325d487d64d13f669b2000c9f8caf70493c1be2dac74fec3c51d5a04f8bc3ae1830bab
languageName: node
linkType: hard
"concat-map@npm:0.0.1":
version: 0.0.1
resolution: "concat-map@npm:0.0.1"
@@ -1889,6 +1995,15 @@ __metadata:
languageName: node
linkType: hard
"cssesc@npm:^3.0.0":
version: 3.0.0
resolution: "cssesc@npm:3.0.0"
bin:
cssesc: bin/cssesc
checksum: 10c0/6bcfd898662671be15ae7827120472c5667afb3d7429f1f917737f3bf84c4176003228131b643ae74543f17a394446247df090c597bb9a728cce298606ed0aa7
languageName: node
linkType: hard
"csstype@npm:^3.0.2":
version: 3.1.3
resolution: "csstype@npm:3.1.3"
@@ -2032,6 +2147,20 @@ __metadata:
languageName: node
linkType: hard
"didyoumean@npm:^1.2.2":
version: 1.2.2
resolution: "didyoumean@npm:1.2.2"
checksum: 10c0/95d0b53d23b851aacff56dfadb7ecfedce49da4232233baecfeecb7710248c4aa03f0aa8995062f0acafaf925adf8536bd7044a2e68316fd7d411477599bc27b
languageName: node
linkType: hard
"dlv@npm:^1.1.3":
version: 1.1.3
resolution: "dlv@npm:1.1.3"
checksum: 10c0/03eb4e769f19a027fd5b43b59e8a05e3fd2100ac239ebb0bf9a745de35d449e2f25cfaf3aa3934664551d72856f4ae8b7822016ce5c42c2d27c18ae79429ec42
languageName: node
linkType: hard
"doctrine@npm:^2.1.0":
version: 2.1.0
resolution: "doctrine@npm:2.1.0"
@@ -2687,6 +2816,15 @@ __metadata:
languageName: node
linkType: hard
"flat@npm:^6.0.1":
version: 6.0.1
resolution: "flat@npm:6.0.1"
bin:
flat: cli.js
checksum: 10c0/9dc0dbe6e2acc012512a53130d9ba1c82c1a596cdca91b23d11716348361c4a68928409bb4433c4493a17595c3efd0cab9f09e23dd3f9962a58af225c3efc23a
languageName: node
linkType: hard
"flatted@npm:^3.2.9":
version: 3.3.3
resolution: "flatted@npm:3.3.3"
@@ -2729,6 +2867,25 @@ __metadata:
languageName: node
linkType: hard
"fsevents@npm:~2.3.2":
version: 2.3.3
resolution: "fsevents@npm:2.3.3"
dependencies:
node-gyp: "npm:latest"
checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60
conditions: os=darwin
languageName: node
linkType: hard
"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin<compat/fsevents>":
version: 2.3.3
resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin<compat/fsevents>::version=2.3.3&hash=df0bf1"
dependencies:
node-gyp: "npm:latest"
conditions: os=darwin
languageName: node
linkType: hard
"function-bind@npm:^1.1.2":
version: 1.1.2
resolution: "function-bind@npm:1.1.2"
@@ -2812,7 +2969,7 @@ __metadata:
languageName: node
linkType: hard
"glob-parent@npm:^5.1.2":
"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2":
version: 5.1.2
resolution: "glob-parent@npm:5.1.2"
dependencies:
@@ -2830,7 +2987,7 @@ __metadata:
languageName: node
linkType: hard
"glob@npm:^10.2.2":
"glob@npm:^10.2.2, glob@npm:^10.3.10":
version: 10.4.5
resolution: "glob@npm:10.4.5"
dependencies:
@@ -3104,6 +3261,15 @@ __metadata:
languageName: node
linkType: hard
"is-binary-path@npm:~2.1.0":
version: 2.1.0
resolution: "is-binary-path@npm:2.1.0"
dependencies:
binary-extensions: "npm:^2.0.0"
checksum: 10c0/a16eaee59ae2b315ba36fad5c5dcaf8e49c3e27318f8ab8fa3cdb8772bf559c8d1ba750a589c2ccb096113bb64497084361a25960899cb6172a6925ab6123d38
languageName: node
linkType: hard
"is-boolean-object@npm:^1.2.1":
version: 1.2.2
resolution: "is-boolean-object@npm:1.2.2"
@@ -3195,7 +3361,7 @@ __metadata:
languageName: node
linkType: hard
"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3":
"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1":
version: 4.0.3
resolution: "is-glob@npm:4.0.3"
dependencies:
@@ -3378,6 +3544,15 @@ __metadata:
languageName: node
linkType: hard
"jiti@npm:^1.21.6":
version: 1.21.7
resolution: "jiti@npm:1.21.7"
bin:
jiti: bin/jiti.js
checksum: 10c0/77b61989c758ff32407cdae8ddc77f85e18e1a13fc4977110dbd2e05fc761842f5f71bce684d9a01316e1c4263971315a111385759951080bbfe17cbb5de8f7a
languageName: node
linkType: hard
"jiti@npm:^2.4.2":
version: 2.4.2
resolution: "jiti@npm:2.4.2"
@@ -3663,6 +3838,20 @@ __metadata:
languageName: node
linkType: hard
"lilconfig@npm:^3.0.0, lilconfig@npm:^3.1.3":
version: 3.1.3
resolution: "lilconfig@npm:3.1.3"
checksum: 10c0/f5604e7240c5c275743561442fbc5abf2a84ad94da0f5adc71d25e31fa8483048de3dcedcb7a44112a942fed305fd75841cdf6c9681c7f640c63f1049e9a5dcc
languageName: node
linkType: hard
"lines-and-columns@npm:^1.1.6":
version: 1.2.4
resolution: "lines-and-columns@npm:1.2.4"
checksum: 10c0/3da6ee62d4cd9f03f5dc90b4df2540fb85b352081bee77fe4bbcd12c9000ead7f35e0a38b8d09a9bb99b13223446dd8689ff3c4959807620726d788701a83d2d
languageName: node
linkType: hard
"locate-path@npm:^6.0.0":
version: 6.0.0
resolution: "locate-path@npm:6.0.0"
@@ -3923,6 +4112,17 @@ __metadata:
languageName: node
linkType: hard
"mz@npm:^2.7.0":
version: 2.7.0
resolution: "mz@npm:2.7.0"
dependencies:
any-promise: "npm:^1.0.0"
object-assign: "npm:^4.0.1"
thenify-all: "npm:^1.0.0"
checksum: 10c0/103114e93f87362f0b56ab5b2e7245051ad0276b646e3902c98397d18bb8f4a77f2ea4a2c9d3ad516034ea3a56553b60d3f5f78220001ca4c404bd711bd0af39
languageName: node
linkType: hard
"nanoid@npm:^3.3.6, nanoid@npm:^3.3.8":
version: 3.3.11
resolution: "nanoid@npm:3.3.11"
@@ -4063,13 +4263,27 @@ __metadata:
languageName: node
linkType: hard
"object-assign@npm:^4.1.1":
"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0":
version: 3.0.0
resolution: "normalize-path@npm:3.0.0"
checksum: 10c0/e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046
languageName: node
linkType: hard
"object-assign@npm:^4.0.1, object-assign@npm:^4.1.1":
version: 4.1.1
resolution: "object-assign@npm:4.1.1"
checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414
languageName: node
linkType: hard
"object-hash@npm:^3.0.0":
version: 3.0.0
resolution: "object-hash@npm:3.0.0"
checksum: 10c0/a06844537107b960c1c8b96cd2ac8592a265186bfa0f6ccafe0d34eabdb526f6fa81da1f37c43df7ed13b12a4ae3457a16071603bcd39d8beddb5f08c37b0f47
languageName: node
linkType: hard
"object-inspect@npm:^1.13.3":
version: 1.13.4
resolution: "object-inspect@npm:1.13.4"
@@ -4280,7 +4494,7 @@ __metadata:
languageName: node
linkType: hard
"picomatch@npm:^2.3.1":
"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.3.1":
version: 2.3.1
resolution: "picomatch@npm:2.3.1"
checksum: 10c0/26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be
@@ -4294,6 +4508,20 @@ __metadata:
languageName: node
linkType: hard
"pify@npm:^2.3.0":
version: 2.3.0
resolution: "pify@npm:2.3.0"
checksum: 10c0/551ff8ab830b1052633f59cb8adc9ae8407a436e06b4a9718bcb27dc5844b83d535c3a8512b388b6062af65a98c49bdc0dd523d8b2617b188f7c8fee457158dc
languageName: node
linkType: hard
"pirates@npm:^4.0.1":
version: 4.0.7
resolution: "pirates@npm:4.0.7"
checksum: 10c0/a51f108dd811beb779d58a76864bbd49e239fa40c7984cd11596c75a121a8cc789f1c8971d8bb15f0dbf9d48b76c05bb62fcbce840f89b688c0fa64b37e8478a
languageName: node
linkType: hard
"portfolio-2@workspace:.":
version: 0.0.0-use.local
resolution: "portfolio-2@workspace:."
@@ -4321,6 +4549,7 @@ __metadata:
react-dom: "npm:^19.1.0"
react-pdf: "npm:^9.2.1"
tailwindcss: "npm:^4"
tailwindcss-text-fill-stroke: "npm:^2.0.0-beta.3"
three: "npm:^0.175.0"
typescript: "npm:^5"
languageName: unknown
@@ -4333,6 +4562,76 @@ __metadata:
languageName: node
linkType: hard
"postcss-import@npm:^15.1.0":
version: 15.1.0
resolution: "postcss-import@npm:15.1.0"
dependencies:
postcss-value-parser: "npm:^4.0.0"
read-cache: "npm:^1.0.0"
resolve: "npm:^1.1.7"
peerDependencies:
postcss: ^8.0.0
checksum: 10c0/518aee5c83ea6940e890b0be675a2588db68b2582319f48c3b4e06535a50ea6ee45f7e63e4309f8754473245c47a0372632378d1d73d901310f295a92f26f17b
languageName: node
linkType: hard
"postcss-js@npm:^4.0.1":
version: 4.0.1
resolution: "postcss-js@npm:4.0.1"
dependencies:
camelcase-css: "npm:^2.0.1"
peerDependencies:
postcss: ^8.4.21
checksum: 10c0/af35d55cb873b0797d3b42529514f5318f447b134541844285c9ac31a17497297eb72296902967911bb737a75163441695737300ce2794e3bd8c70c13a3b106e
languageName: node
linkType: hard
"postcss-load-config@npm:^4.0.2":
version: 4.0.2
resolution: "postcss-load-config@npm:4.0.2"
dependencies:
lilconfig: "npm:^3.0.0"
yaml: "npm:^2.3.4"
peerDependencies:
postcss: ">=8.0.9"
ts-node: ">=9.0.0"
peerDependenciesMeta:
postcss:
optional: true
ts-node:
optional: true
checksum: 10c0/3d7939acb3570b0e4b4740e483d6e555a3e2de815219cb8a3c8fc03f575a6bde667443aa93369c0be390af845cb84471bf623e24af833260de3a105b78d42519
languageName: node
linkType: hard
"postcss-nested@npm:^6.2.0":
version: 6.2.0
resolution: "postcss-nested@npm:6.2.0"
dependencies:
postcss-selector-parser: "npm:^6.1.1"
peerDependencies:
postcss: ^8.2.14
checksum: 10c0/7f9c3f2d764191a39364cbdcec350f26a312431a569c9ef17408021424726b0d67995ff5288405e3724bb7152a4c92f73c027e580ec91e798800ed3c52e2bc6e
languageName: node
linkType: hard
"postcss-selector-parser@npm:^6.1.1, postcss-selector-parser@npm:^6.1.2":
version: 6.1.2
resolution: "postcss-selector-parser@npm:6.1.2"
dependencies:
cssesc: "npm:^3.0.0"
util-deprecate: "npm:^1.0.2"
checksum: 10c0/523196a6bd8cf660bdf537ad95abd79e546d54180f9afb165a4ab3e651ac705d0f8b8ce6b3164fb9e3279ce482c5f751a69eb2d3a1e8eb0fd5e82294fb3ef13e
languageName: node
linkType: hard
"postcss-value-parser@npm:^4.0.0":
version: 4.2.0
resolution: "postcss-value-parser@npm:4.2.0"
checksum: 10c0/f4142a4f56565f77c1831168e04e3effd9ffcc5aebaf0f538eee4b2d465adfd4b85a44257bb48418202a63806a7da7fe9f56c330aebb3cac898e46b4cbf49161
languageName: node
linkType: hard
"postcss@npm:8.4.31":
version: 8.4.31
resolution: "postcss@npm:8.4.31"
@@ -4344,7 +4643,7 @@ __metadata:
languageName: node
linkType: hard
"postcss@npm:^8.4.41":
"postcss@npm:^8.4.41, postcss@npm:^8.4.47":
version: 8.5.3
resolution: "postcss@npm:8.5.3"
dependencies:
@@ -4539,6 +4838,15 @@ __metadata:
languageName: node
linkType: hard
"read-cache@npm:^1.0.0":
version: 1.0.0
resolution: "read-cache@npm:1.0.0"
dependencies:
pify: "npm:^2.3.0"
checksum: 10c0/90cb2750213c7dd7c80cb420654344a311fdec12944e81eb912cd82f1bc92aea21885fa6ce442e3336d9fccd663b8a7a19c46d9698e6ca55620848ab932da814
languageName: node
linkType: hard
"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0":
version: 3.6.2
resolution: "readable-stream@npm:3.6.2"
@@ -4550,6 +4858,15 @@ __metadata:
languageName: node
linkType: hard
"readdirp@npm:~3.6.0":
version: 3.6.0
resolution: "readdirp@npm:3.6.0"
dependencies:
picomatch: "npm:^2.2.1"
checksum: 10c0/6fa848cf63d1b82ab4e985f4cf72bd55b7dcfd8e0a376905804e48c3634b7e749170940ba77b32804d5fe93b3cc521aa95a8d7e7d725f830da6d93f3669ce66b
languageName: node
linkType: hard
"reflect.getprototypeof@npm:^1.0.6, reflect.getprototypeof@npm:^1.0.9":
version: 1.0.10
resolution: "reflect.getprototypeof@npm:1.0.10"
@@ -4608,7 +4925,7 @@ __metadata:
languageName: node
linkType: hard
"resolve@npm:^1.22.4":
"resolve@npm:^1.1.7, resolve@npm:^1.22.4, resolve@npm:^1.22.8":
version: 1.22.10
resolution: "resolve@npm:1.22.10"
dependencies:
@@ -4634,7 +4951,7 @@ __metadata:
languageName: node
linkType: hard
"resolve@patch:resolve@npm%3A^1.22.4#optional!builtin<compat/resolve>":
"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin<compat/resolve>, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin<compat/resolve>":
version: 1.22.10
resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin<compat/resolve>::version=1.22.10&hash=c3c19d"
dependencies:
@@ -5221,6 +5538,24 @@ __metadata:
languageName: node
linkType: hard
"sucrase@npm:^3.35.0":
version: 3.35.0
resolution: "sucrase@npm:3.35.0"
dependencies:
"@jridgewell/gen-mapping": "npm:^0.3.2"
commander: "npm:^4.0.0"
glob: "npm:^10.3.10"
lines-and-columns: "npm:^1.1.6"
mz: "npm:^2.7.0"
pirates: "npm:^4.0.1"
ts-interface-checker: "npm:^0.1.9"
bin:
sucrase: bin/sucrase
sucrase-node: bin/sucrase-node
checksum: 10c0/ac85f3359d2c2ecbf5febca6a24ae9bf96c931f05fde533c22a94f59c6a74895e5d5f0e871878dfd59c2697a75ebb04e4b2224ef0bfc24ca1210735c2ec191ef
languageName: node
linkType: hard
"supports-color@npm:^7.0.0, supports-color@npm:^7.1.0":
version: 7.2.0
resolution: "supports-color@npm:7.2.0"
@@ -5256,6 +5591,16 @@ __metadata:
languageName: node
linkType: hard
"tailwindcss-text-fill-stroke@npm:^2.0.0-beta.3":
version: 2.0.0-beta.3
resolution: "tailwindcss-text-fill-stroke@npm:2.0.0-beta.3"
dependencies:
flat: "npm:^6.0.1"
tailwindcss: "npm:^3.4.17"
checksum: 10c0/3f3510479fb7cbc5af28d6bd74edcd4e6d6ca354dca6c44a95bdb65a412f084913e2fb68774449171105298d7faffa744089810e9d7b3ff21a2478dde9581dc8
languageName: node
linkType: hard
"tailwindcss@npm:4.1.4, tailwindcss@npm:^4":
version: 4.1.4
resolution: "tailwindcss@npm:4.1.4"
@@ -5263,6 +5608,39 @@ __metadata:
languageName: node
linkType: hard
"tailwindcss@npm:^3.4.17":
version: 3.4.17
resolution: "tailwindcss@npm:3.4.17"
dependencies:
"@alloc/quick-lru": "npm:^5.2.0"
arg: "npm:^5.0.2"
chokidar: "npm:^3.6.0"
didyoumean: "npm:^1.2.2"
dlv: "npm:^1.1.3"
fast-glob: "npm:^3.3.2"
glob-parent: "npm:^6.0.2"
is-glob: "npm:^4.0.3"
jiti: "npm:^1.21.6"
lilconfig: "npm:^3.1.3"
micromatch: "npm:^4.0.8"
normalize-path: "npm:^3.0.0"
object-hash: "npm:^3.0.0"
picocolors: "npm:^1.1.1"
postcss: "npm:^8.4.47"
postcss-import: "npm:^15.1.0"
postcss-js: "npm:^4.0.1"
postcss-load-config: "npm:^4.0.2"
postcss-nested: "npm:^6.2.0"
postcss-selector-parser: "npm:^6.1.2"
resolve: "npm:^1.22.8"
sucrase: "npm:^3.35.0"
bin:
tailwind: lib/cli.js
tailwindcss: lib/cli.js
checksum: 10c0/cc42c6e7fdf88a5507a0d7fea37f1b4122bec158977f8c017b2ae6828741f9e6f8cb90282c6bf2bd5951fd1220a53e0a50ca58f5c1c00eb7f5d9f8b80dc4523c
languageName: node
linkType: hard
"tapable@npm:^2.2.0":
version: 2.2.1
resolution: "tapable@npm:2.2.1"
@@ -5319,6 +5697,24 @@ __metadata:
languageName: node
linkType: hard
"thenify-all@npm:^1.0.0":
version: 1.6.0
resolution: "thenify-all@npm:1.6.0"
dependencies:
thenify: "npm:>= 3.1.0 < 4"
checksum: 10c0/9b896a22735e8122754fe70f1d65f7ee691c1d70b1f116fda04fea103d0f9b356e3676cb789506e3909ae0486a79a476e4914b0f92472c2e093d206aed4b7d6b
languageName: node
linkType: hard
"thenify@npm:>= 3.1.0 < 4":
version: 3.3.1
resolution: "thenify@npm:3.3.1"
dependencies:
any-promise: "npm:^1.0.0"
checksum: 10c0/f375aeb2b05c100a456a30bc3ed07ef03a39cbdefe02e0403fb714b8c7e57eeaad1a2f5c4ecfb9ce554ce3db9c2b024eba144843cd9e344566d9fcee73b04767
languageName: node
linkType: hard
"three-mesh-bvh@npm:^0.8.3":
version: 0.8.3
resolution: "three-mesh-bvh@npm:0.8.3"
@@ -5423,6 +5819,13 @@ __metadata:
languageName: node
linkType: hard
"ts-interface-checker@npm:^0.1.9":
version: 0.1.13
resolution: "ts-interface-checker@npm:0.1.13"
checksum: 10c0/232509f1b84192d07b81d1e9b9677088e590ac1303436da1e92b296e9be8e31ea042e3e1fd3d29b1742ad2c959e95afe30f63117b8f1bc3a3850070a5142fea7
languageName: node
linkType: hard
"tsconfig-paths@npm:^3.15.0":
version: 3.15.0
resolution: "tsconfig-paths@npm:3.15.0"
@@ -5661,7 +6064,7 @@ __metadata:
languageName: node
linkType: hard
"util-deprecate@npm:^1.0.1":
"util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2":
version: 1.0.2
resolution: "util-deprecate@npm:1.0.2"
checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942
@@ -5831,6 +6234,15 @@ __metadata:
languageName: node
linkType: hard
"yaml@npm:^2.3.4":
version: 2.7.1
resolution: "yaml@npm:2.7.1"
bin:
yaml: bin.mjs
checksum: 10c0/ee2126398ab7d1fdde566b4013b68e36930b9e6d8e68b6db356875c99614c10d678b6f45597a145ff6d63814961221fc305bf9242af8bf7450177f8a68537590
languageName: node
linkType: hard
"yocto-queue@npm:^0.1.0":
version: 0.1.0
resolution: "yocto-queue@npm:0.1.0"