Compare commits
10 Commits
ea865574b7
...
6782e4d40b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6782e4d40b | ||
|
|
9a9519ce29 | ||
|
|
1b53e04b5d | ||
|
|
7c77ac6c19 | ||
|
|
f0042e49ec | ||
|
|
4e2adf1afb | ||
|
|
209d222eb0 | ||
|
|
15d7f856cb | ||
|
|
0e07c4acd6 | ||
|
|
5257e53487 |
@ -1 +1 @@
|
|||||||
[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.18.1","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[],\"actionBodySizeLimit\":1048576},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false,\"svgo\":false},\"legacy\":{\"collections\":false}}"]
|
[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.18.1","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"server\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":false,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\",\"entrypoint\":\"astro/assets/endpoint/dev\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[],\"actionBodySizeLimit\":1048576},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false,\"svgo\":false},\"legacy\":{\"collections\":false},\"session\":{\"driver\":\"fs-lite\",\"options\":{\"base\":\"/Users/arthurbarre/dev/freelance/rebours/node_modules/.astro/sessions\"}}}"]
|
||||||
1
.astro/types.d.ts
vendored
1
.astro/types.d.ts
vendored
@ -1 +1,2 @@
|
|||||||
/// <reference types="astro/client" />
|
/// <reference types="astro/client" />
|
||||||
|
/// <reference path="content.d.ts" />
|
||||||
@ -3,8 +3,8 @@
|
|||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "rebours-dev",
|
"name": "rebours-dev",
|
||||||
"runtimeExecutable": "pnpm",
|
"runtimeExecutable": "/Users/arthurbarre/.nvm/versions/node/v25.6.1/bin/node",
|
||||||
"runtimeArgs": ["dev"],
|
"runtimeArgs": ["/Users/arthurbarre/.nvm/versions/node/v25.6.1/bin/pnpm", "dev"],
|
||||||
"port": 4321
|
"port": 4321
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
18
.dockerignore
Normal file
18
.dockerignore
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
*.md
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
.astro
|
||||||
|
sanity
|
||||||
|
k8s
|
||||||
|
.gitea
|
||||||
|
migrate-images.mjs
|
||||||
|
seed-sanity.mjs
|
||||||
|
seed-sanity-homepage.mjs
|
||||||
|
clean-duplicates.mjs
|
||||||
99
.gitea/workflows/deploy.yml
Normal file
99
.gitea/workflows/deploy.yml
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
name: Build & Deploy to K3s
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: git.arthurbarre.fr
|
||||||
|
SSR_IMAGE: git.arthurbarre.fr/ordinarthur/rebours-ssr
|
||||||
|
API_IMAGE: git.arthurbarre.fr/ordinarthur/rebours-api
|
||||||
|
REGISTRY_USER: ordinarthur
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Login to Gitea Container Registry
|
||||||
|
run: |
|
||||||
|
echo "${{ secrets.REGISTRY_PASSWORD }}" | \
|
||||||
|
docker login ${{ env.REGISTRY }} -u ${{ env.REGISTRY_USER }} --password-stdin
|
||||||
|
|
||||||
|
- name: Build SSR image
|
||||||
|
run: |
|
||||||
|
docker build \
|
||||||
|
-f Dockerfile.ssr \
|
||||||
|
-t ${{ env.SSR_IMAGE }}:${{ github.sha }} \
|
||||||
|
-t ${{ env.SSR_IMAGE }}:latest \
|
||||||
|
.
|
||||||
|
|
||||||
|
- name: Build API image
|
||||||
|
run: |
|
||||||
|
docker build \
|
||||||
|
-f Dockerfile.api \
|
||||||
|
-t ${{ env.API_IMAGE }}:${{ github.sha }} \
|
||||||
|
-t ${{ env.API_IMAGE }}:latest \
|
||||||
|
.
|
||||||
|
|
||||||
|
- name: Push SSR image
|
||||||
|
run: |
|
||||||
|
docker push ${{ env.SSR_IMAGE }}:${{ github.sha }}
|
||||||
|
docker push ${{ env.SSR_IMAGE }}:latest
|
||||||
|
|
||||||
|
- name: Push API image
|
||||||
|
run: |
|
||||||
|
docker push ${{ env.API_IMAGE }}:${{ github.sha }}
|
||||||
|
docker push ${{ env.API_IMAGE }}:latest
|
||||||
|
|
||||||
|
- name: Install kubectl
|
||||||
|
run: |
|
||||||
|
curl -LO "https://dl.k8s.io/release/$(curl -Ls https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
|
||||||
|
chmod +x kubectl
|
||||||
|
mv kubectl /usr/local/bin/kubectl
|
||||||
|
|
||||||
|
- name: Configure kubeconfig
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.kube
|
||||||
|
echo "${{ secrets.KUBECONFIG }}" | base64 -d > ~/.kube/config
|
||||||
|
|
||||||
|
- name: Apply namespace and shared resources
|
||||||
|
run: |
|
||||||
|
kubectl apply -f k8s/namespace.yml
|
||||||
|
kubectl apply -f k8s/configmap.yml
|
||||||
|
kubectl apply -f k8s/service.yml
|
||||||
|
|
||||||
|
- name: Create image pull secret
|
||||||
|
run: |
|
||||||
|
kubectl -n rebours create secret docker-registry gitea-registry-secret \
|
||||||
|
--docker-server=${{ env.REGISTRY }} \
|
||||||
|
--docker-username=${{ env.REGISTRY_USER }} \
|
||||||
|
--docker-password="${{ secrets.REGISTRY_PASSWORD }}" \
|
||||||
|
--dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
- name: Create app secrets
|
||||||
|
run: |
|
||||||
|
kubectl -n rebours create secret generic rebours-secrets \
|
||||||
|
--from-literal=STRIPE_SECRET_KEY="${{ secrets.STRIPE_SECRET_KEY }}" \
|
||||||
|
--from-literal=STRIPE_WEBHOOK_SECRET="${{ secrets.STRIPE_WEBHOOK_SECRET }}" \
|
||||||
|
--from-literal=SANITY_API_TOKEN="${{ secrets.SANITY_API_TOKEN }}" \
|
||||||
|
--dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
- name: Deploy workloads
|
||||||
|
run: |
|
||||||
|
kubectl apply -f k8s/deployment.yml
|
||||||
|
|
||||||
|
kubectl -n rebours set image deployment/rebours-ssr \
|
||||||
|
rebours-ssr=${{ env.SSR_IMAGE }}:${{ github.sha }}
|
||||||
|
kubectl -n rebours set image deployment/rebours-api \
|
||||||
|
rebours-api=${{ env.API_IMAGE }}:${{ github.sha }}
|
||||||
|
|
||||||
|
kubectl -n rebours rollout status deployment/rebours-api --timeout=120s
|
||||||
|
kubectl -n rebours rollout status deployment/rebours-ssr --timeout=180s
|
||||||
|
kubectl -n rebours rollout status deployment/rebours-proxy --timeout=60s
|
||||||
|
|
||||||
|
- name: Cleanup old images
|
||||||
|
run: |
|
||||||
|
docker image prune -f
|
||||||
44
CLAUDE.md
44
CLAUDE.md
@ -37,7 +37,7 @@ rebours/
|
|||||||
|
|
||||||
| Couche | Techno |
|
| Couche | Techno |
|
||||||
|--------|--------|
|
|--------|--------|
|
||||||
| Front (SSG) | Astro + HTML/CSS/JS vanilla + GSAP |
|
| Front (SSR) | Astro + HTML/CSS/JS vanilla + GSAP |
|
||||||
| CMS | Sanity (headless, hébergé) |
|
| CMS | Sanity (headless, hébergé) |
|
||||||
| API | Fastify (Node.js) |
|
| API | Fastify (Node.js) |
|
||||||
| Paiement | Stripe Checkout (price_data inline) |
|
| Paiement | Stripe Checkout (price_data inline) |
|
||||||
@ -65,20 +65,21 @@ STRIPE_SECRET_KEY=sk_test_...
|
|||||||
STRIPE_WEBHOOK_SECRET=whsec_...
|
STRIPE_WEBHOOK_SECRET=whsec_...
|
||||||
|
|
||||||
DOMAIN=http://localhost:4321
|
DOMAIN=http://localhost:4321
|
||||||
PORT=8888
|
FASTIFY_PORT=3000 # Port Fastify API (prod)
|
||||||
|
ASTRO_PORT=4321 # Port Astro SSR (prod)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Lancer le projet
|
### Lancer le projet
|
||||||
```bash
|
```bash
|
||||||
npm install
|
pnpm install
|
||||||
npm run dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Cela lance en parallèle (via `concurrently`) :
|
Cela lance en parallèle (via `concurrently`) :
|
||||||
- `astro dev` sur http://localhost:4321
|
- `astro dev` sur http://localhost:4321
|
||||||
- `node --watch server.mjs` (mode dev, PORT=8888)
|
- `node --watch server.mjs` (mode dev)
|
||||||
|
|
||||||
Le proxy Vite dans `astro.config.mjs` redirige `/api/*` vers `http://127.0.0.1:8888`.
|
Le proxy Vite dans `astro.config.mjs` redirige `/api/*` vers le serveur Fastify.
|
||||||
|
|
||||||
### Sanity Studio
|
### Sanity Studio
|
||||||
```bash
|
```bash
|
||||||
@ -90,8 +91,8 @@ Accessible sur http://localhost:3333
|
|||||||
|
|
||||||
### Build
|
### Build
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
pnpm build
|
||||||
# Génère ./dist/ (fichiers statiques Astro)
|
# Génère ./dist/ (serveur Astro SSR + assets client)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -116,8 +117,7 @@ Champs principaux :
|
|||||||
1. Ouvrir Sanity Studio
|
1. Ouvrir Sanity Studio
|
||||||
2. Créer un nouveau document "Produit"
|
2. Créer un nouveau document "Produit"
|
||||||
3. Remplir les champs, uploader l'image
|
3. Remplir les champs, uploader l'image
|
||||||
4. Publier
|
4. Publier → visible immédiatement sur le site (SSR, pas de rebuild nécessaire)
|
||||||
5. Rebuild le site : `npm run build` + déployer
|
|
||||||
|
|
||||||
### Images
|
### Images
|
||||||
Les images sont servies via le CDN Sanity avec transformations automatiques.
|
Les images sont servies via le CDN Sanity avec transformations automatiques.
|
||||||
@ -154,12 +154,19 @@ Quand un client clique "Commander" :
|
|||||||
|
|
||||||
### Serveur : ordinarthur@10.10.0.13
|
### Serveur : ordinarthur@10.10.0.13
|
||||||
|
|
||||||
### Architecture prod
|
### Architecture prod (SSR)
|
||||||
```
|
```
|
||||||
Internet -> Nginx (port 80) -> /var/www/html/rebours/dist/ (statiques)
|
Internet -> Nginx (port 80) -> / -> proxy -> Astro SSR :4321
|
||||||
-> /api/* -> proxy -> Fastify :3000
|
-> /_astro/* -> fichiers statiques (dist/client/)
|
||||||
|
-> /api/* -> proxy -> Fastify :3000
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Services systemd
|
||||||
|
| Service | Port | Rôle |
|
||||||
|
|---------|------|------|
|
||||||
|
| `rebours-ssr` | 4321 | Astro SSR (pages dynamiques) |
|
||||||
|
| `rebours` | 3000 | Fastify API (Stripe, checkout) |
|
||||||
|
|
||||||
### Variables d'environnement en prod
|
### Variables d'environnement en prod
|
||||||
```env
|
```env
|
||||||
SANITY_PROJECT_ID=...
|
SANITY_PROJECT_ID=...
|
||||||
@ -167,14 +174,15 @@ SANITY_DATASET=production
|
|||||||
STRIPE_SECRET_KEY=sk_live_...
|
STRIPE_SECRET_KEY=sk_live_...
|
||||||
STRIPE_WEBHOOK_SECRET=whsec_...
|
STRIPE_WEBHOOK_SECRET=whsec_...
|
||||||
DOMAIN=https://rebours.studio
|
DOMAIN=https://rebours.studio
|
||||||
PORT=3000
|
FASTIFY_PORT=3000
|
||||||
|
ASTRO_PORT=4321
|
||||||
```
|
```
|
||||||
|
|
||||||
### Déploiement
|
### Déploiement
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
pnpm build
|
||||||
scp -r dist/* ordinarthur@10.10.0.13:/tmp/rebours-dist/
|
scp -r dist/* ordinarthur@10.10.0.13:/tmp/rebours-dist/
|
||||||
ssh ordinarthur@10.10.0.13 "sudo cp -r /tmp/rebours-dist/* /var/www/html/rebours/dist/"
|
ssh ordinarthur@10.10.0.13 "sudo rm -rf /var/www/html/rebours/dist && sudo mkdir -p /var/www/html/rebours/dist && sudo cp -r /tmp/rebours-dist/* /var/www/html/rebours/dist/ && sudo chown -R ordinarthur:ordinarthur /var/www/html/rebours/dist && sudo systemctl restart rebours-ssr"
|
||||||
```
|
```
|
||||||
|
|
||||||
Si server.mjs a changé :
|
Si server.mjs a changé :
|
||||||
@ -189,8 +197,8 @@ ssh ordinarthur@10.10.0.13 "sudo cp /tmp/server.mjs /var/www/html/rebours/server
|
|||||||
|
|
||||||
| URL | Comportement |
|
| URL | Comportement |
|
||||||
|-----|-------------|
|
|-----|-------------|
|
||||||
| `/` | Page principale Astro (SSG) |
|
| `/` | Page principale Astro (SSR, données Sanity live) |
|
||||||
| `/collection/{slug}` | Page produit (SSG), auto-open panel via `window.__OPEN_PANEL__` |
|
| `/collection/{slug}` | Page produit (SSR), auto-open panel via `window.__OPEN_PANEL__` |
|
||||||
| `/success?session_id=...` | Page de confirmation Stripe |
|
| `/success?session_id=...` | Page de confirmation Stripe |
|
||||||
| `/robots.txt` | Généré au build |
|
| `/robots.txt` | Généré au build |
|
||||||
| `/sitemap.xml` | Généré au build depuis Sanity |
|
| `/sitemap.xml` | Généré au build depuis Sanity |
|
||||||
|
|||||||
15
Dockerfile.api
Normal file
15
Dockerfile.api
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Fastify API — no build step, runs server.mjs directly
|
||||||
|
FROM node:22-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
|
|
||||||
|
COPY package.json pnpm-lock.yaml ./
|
||||||
|
RUN pnpm install --frozen-lockfile --prod
|
||||||
|
|
||||||
|
COPY server.mjs ./
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD ["node", "server.mjs"]
|
||||||
25
Dockerfile.ssr
Normal file
25
Dockerfile.ssr
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# --- Stage 1: Build Astro SSR ---
|
||||||
|
FROM node:22-alpine AS build
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
|
|
||||||
|
COPY package.json pnpm-lock.yaml ./
|
||||||
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN pnpm build
|
||||||
|
|
||||||
|
# --- Stage 2: Runtime ---
|
||||||
|
FROM node:22-alpine AS runtime
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=build /app/dist ./dist
|
||||||
|
COPY --from=build /app/node_modules ./node_modules
|
||||||
|
COPY --from=build /app/package.json ./
|
||||||
|
|
||||||
|
ENV HOST=0.0.0.0
|
||||||
|
ENV PORT=4321
|
||||||
|
EXPOSE 4321
|
||||||
|
|
||||||
|
CMD ["node", "dist/server/entry.mjs"]
|
||||||
@ -1,8 +1,10 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from 'astro/config';
|
||||||
|
import node from '@astrojs/node';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
output: 'static',
|
output: 'server',
|
||||||
|
adapter: node({ mode: 'standalone' }),
|
||||||
outDir: './dist',
|
outDir: './dist',
|
||||||
server: { port: 4321 },
|
server: { port: 4321 },
|
||||||
vite: {
|
vite: {
|
||||||
|
|||||||
44
k8s/configmap.yml
Normal file
44
k8s/configmap.yml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: rebours-config
|
||||||
|
namespace: rebours
|
||||||
|
data:
|
||||||
|
NODE_ENV: "production"
|
||||||
|
SANITY_PROJECT_ID: "y821x5qu"
|
||||||
|
SANITY_DATASET: "production"
|
||||||
|
DOMAIN: "https://rebours.studio"
|
||||||
|
FASTIFY_PORT: "3000"
|
||||||
|
ASTRO_PORT: "4321"
|
||||||
|
proxy.conf: |
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
client_max_body_size 10M;
|
||||||
|
|
||||||
|
# API → Fastify
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://rebours-api:3000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static assets from Astro client build (cached)
|
||||||
|
location /_astro/ {
|
||||||
|
proxy_pass http://rebours-ssr:4321;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# SSR → Astro
|
||||||
|
location / {
|
||||||
|
proxy_pass http://rebours-ssr:4321;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
|
}
|
||||||
|
}
|
||||||
144
k8s/deployment.yml
Normal file
144
k8s/deployment.yml
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
# --- Astro SSR ---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: rebours-ssr
|
||||||
|
namespace: rebours
|
||||||
|
labels:
|
||||||
|
app: rebours-ssr
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: rebours-ssr
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: rebours-ssr
|
||||||
|
spec:
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: gitea-registry-secret
|
||||||
|
containers:
|
||||||
|
- name: rebours-ssr
|
||||||
|
image: git.arthurbarre.fr/ordinarthur/rebours-ssr:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 4321
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: rebours-config
|
||||||
|
- secretRef:
|
||||||
|
name: rebours-secrets
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "512Mi"
|
||||||
|
cpu: "500m"
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 4321
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 4321
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
periodSeconds: 30
|
||||||
|
---
|
||||||
|
# --- Fastify API ---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: rebours-api
|
||||||
|
namespace: rebours
|
||||||
|
labels:
|
||||||
|
app: rebours-api
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: rebours-api
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: rebours-api
|
||||||
|
spec:
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: gitea-registry-secret
|
||||||
|
containers:
|
||||||
|
- name: rebours-api
|
||||||
|
image: git.arthurbarre.fr/ordinarthur/rebours-api:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: rebours-config
|
||||||
|
- secretRef:
|
||||||
|
name: rebours-secrets
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "256Mi"
|
||||||
|
cpu: "300m"
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: 3000
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: 3000
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 30
|
||||||
|
---
|
||||||
|
# --- Nginx Proxy ---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: rebours-proxy
|
||||||
|
namespace: rebours
|
||||||
|
labels:
|
||||||
|
app: rebours-proxy
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: rebours-proxy
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: rebours-proxy
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:alpine
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
volumeMounts:
|
||||||
|
- name: proxy-config
|
||||||
|
mountPath: /etc/nginx/conf.d/default.conf
|
||||||
|
subPath: proxy.conf
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "32Mi"
|
||||||
|
cpu: "25m"
|
||||||
|
limits:
|
||||||
|
memory: "64Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 80
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
volumes:
|
||||||
|
- name: proxy-config
|
||||||
|
configMap:
|
||||||
|
name: rebours-config
|
||||||
4
k8s/namespace.yml
Normal file
4
k8s/namespace.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: rebours
|
||||||
43
k8s/service.yml
Normal file
43
k8s/service.yml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# --- SSR (ClusterIP — internal) ---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: rebours-ssr
|
||||||
|
namespace: rebours
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: rebours-ssr
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 4321
|
||||||
|
targetPort: 4321
|
||||||
|
---
|
||||||
|
# --- API (ClusterIP — internal) ---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: rebours-api
|
||||||
|
namespace: rebours
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: rebours-api
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 3000
|
||||||
|
targetPort: 3000
|
||||||
|
---
|
||||||
|
# --- Proxy (NodePort — external access) ---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: rebours-proxy
|
||||||
|
namespace: rebours
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app: rebours-proxy
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
nodePort: 30083
|
||||||
30
migrate-images.mjs
Normal file
30
migrate-images.mjs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Migration: product.image (single) → product.images (array)
|
||||||
|
* Run: node migrate-images.mjs
|
||||||
|
*/
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { createClient } from '@sanity/client'
|
||||||
|
|
||||||
|
const sanity = createClient({
|
||||||
|
projectId: process.env.SANITY_PROJECT_ID,
|
||||||
|
dataset: process.env.SANITY_DATASET || 'production',
|
||||||
|
apiVersion: '2024-01-01',
|
||||||
|
useCdn: false,
|
||||||
|
token: process.env.SANITY_API_TOKEN,
|
||||||
|
})
|
||||||
|
|
||||||
|
const products = await sanity.fetch('*[_type == "product" && defined(image)]{ _id, image }')
|
||||||
|
|
||||||
|
console.log(`Found ${products.length} products to migrate`)
|
||||||
|
|
||||||
|
for (const p of products) {
|
||||||
|
console.log(`Migrating ${p._id}...`)
|
||||||
|
await sanity
|
||||||
|
.patch(p._id)
|
||||||
|
.set({ images: [p.image] })
|
||||||
|
.unset(['image'])
|
||||||
|
.commit()
|
||||||
|
console.log(` ✓ done`)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Migration complete!')
|
||||||
30
nginx.conf
30
nginx.conf
@ -2,10 +2,7 @@ server {
|
|||||||
listen 80;
|
listen 80;
|
||||||
server_name rebours.studio;
|
server_name rebours.studio;
|
||||||
|
|
||||||
root /var/www/html/rebours/dist;
|
# ── API proxy → Fastify ────────────────<EFBFBD><EFBFBD><EFBFBD>─────────────────────────────────
|
||||||
index index.html;
|
|
||||||
|
|
||||||
# ── API proxy → Fastify ──────────────────────────────────────────────────
|
|
||||||
location /api/ {
|
location /api/ {
|
||||||
proxy_pass http://127.0.0.1:3000;
|
proxy_pass http://127.0.0.1:3000;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
@ -14,28 +11,23 @@ server {
|
|||||||
proxy_set_header X-Forwarded-Proto https;
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Cache : Astro hashed → immutable ─────────────────────────────────────
|
# ── Static assets from Astro client build ──────────────────<EFBFBD><EFBFBD><EFBFBD>─────────────
|
||||||
location /_astro/ {
|
location /_astro/ {
|
||||||
|
root /var/www/html/rebours/dist/client;
|
||||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Cache : CSS/JS sans hash → revalidation ─────────────────────────────
|
location ~* \.(css|js|jpg|jpeg|png|gif|webp|svg|woff2|woff|ttf|ico|mp3)$ {
|
||||||
location ~* \.(css|js)$ {
|
root /var/www/html/rebours/dist/client;
|
||||||
add_header Cache-Control "no-cache";
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Cache : assets → 7 jours ────────────────────────────────────────────
|
|
||||||
location ~* \.(jpg|jpeg|png|gif|webp|svg|woff2|woff|ttf|ico|mp3)$ {
|
|
||||||
add_header Cache-Control "public, max-age=604800";
|
add_header Cache-Control "public, max-age=604800";
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── HTML : jamais caché ──────────────────────────────────────────────────
|
# ── SSR → Astro Node server ─────────────────────<EFBFBD><EFBFBD><EFBFBD>────────────────────────
|
||||||
location ~* \.html$ {
|
|
||||||
add_header Cache-Control "no-store";
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── SPA fallback ─────────────────────────────────────────────────────────
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ $uri.html /index.html;
|
proxy_pass http://127.0.0.1:4321;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,9 +7,11 @@
|
|||||||
"build": "astro build",
|
"build": "astro build",
|
||||||
"preview": "astro preview",
|
"preview": "astro preview",
|
||||||
"server": "NODE_ENV=production node server.mjs",
|
"server": "NODE_ENV=production node server.mjs",
|
||||||
|
"start": "NODE_ENV=production node dist/server/entry.mjs",
|
||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@astrojs/node": "^9.5.5",
|
||||||
"@fastify/cors": "^10.0.2",
|
"@fastify/cors": "^10.0.2",
|
||||||
"@sanity/client": "^7",
|
"@sanity/client": "^7",
|
||||||
"@sanity/image-url": "^1",
|
"@sanity/image-url": "^1",
|
||||||
|
|||||||
133
pnpm-lock.yaml
generated
133
pnpm-lock.yaml
generated
@ -8,6 +8,9 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@astrojs/node':
|
||||||
|
specifier: ^9.5.5
|
||||||
|
version: 9.5.5(astro@5.18.1(@types/node@25.4.0)(jiti@2.6.1)(rollup@4.59.0)(typescript@5.9.3))
|
||||||
'@fastify/cors':
|
'@fastify/cors':
|
||||||
specifier: ^10.0.2
|
specifier: ^10.0.2
|
||||||
version: 10.1.0
|
version: 10.1.0
|
||||||
@ -47,6 +50,11 @@ packages:
|
|||||||
'@astrojs/markdown-remark@6.3.11':
|
'@astrojs/markdown-remark@6.3.11':
|
||||||
resolution: {integrity: sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ==}
|
resolution: {integrity: sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ==}
|
||||||
|
|
||||||
|
'@astrojs/node@9.5.5':
|
||||||
|
resolution: {integrity: sha512-rtU2BGU5u3SfGURpANfMxVzCIoR86MkaN05ncza9rbtuMKJ/XnRJt/BbyVknDbOJ71hoci0SIsJwKcJR8vvi/A==}
|
||||||
|
peerDependencies:
|
||||||
|
astro: ^5.17.3
|
||||||
|
|
||||||
'@astrojs/prism@3.3.0':
|
'@astrojs/prism@3.3.0':
|
||||||
resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==}
|
resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==}
|
||||||
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
|
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
|
||||||
@ -989,6 +997,10 @@ packages:
|
|||||||
defu@6.1.4:
|
defu@6.1.4:
|
||||||
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
|
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
|
||||||
|
|
||||||
|
depd@2.0.0:
|
||||||
|
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||||
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
dequal@2.0.3:
|
dequal@2.0.3:
|
||||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -1038,12 +1050,19 @@ packages:
|
|||||||
resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
|
resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
ee-first@1.1.1:
|
||||||
|
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||||
|
|
||||||
emoji-regex@10.6.0:
|
emoji-regex@10.6.0:
|
||||||
resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
|
resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
|
||||||
|
|
||||||
emoji-regex@8.0.0:
|
emoji-regex@8.0.0:
|
||||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||||
|
|
||||||
|
encodeurl@2.0.0:
|
||||||
|
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
|
||||||
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
entities@4.5.0:
|
entities@4.5.0:
|
||||||
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||||
engines: {node: '>=0.12'}
|
engines: {node: '>=0.12'}
|
||||||
@ -1069,6 +1088,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
escape-html@1.0.3:
|
||||||
|
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
|
||||||
|
|
||||||
escape-string-regexp@5.0.0:
|
escape-string-regexp@5.0.0:
|
||||||
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
|
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@ -1079,6 +1101,10 @@ packages:
|
|||||||
estree-walker@3.0.3:
|
estree-walker@3.0.3:
|
||||||
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
|
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
|
||||||
|
|
||||||
|
etag@1.8.1:
|
||||||
|
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
event-source-polyfill@1.0.31:
|
event-source-polyfill@1.0.31:
|
||||||
resolution: {integrity: sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==}
|
resolution: {integrity: sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==}
|
||||||
|
|
||||||
@ -1149,6 +1175,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==}
|
resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==}
|
||||||
engines: {node: '>=20'}
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
|
fresh@2.0.0:
|
||||||
|
resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
|
||||||
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
fsevents@2.3.3:
|
fsevents@2.3.3:
|
||||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||||
@ -1218,6 +1248,10 @@ packages:
|
|||||||
http-cache-semantics@4.2.0:
|
http-cache-semantics@4.2.0:
|
||||||
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
|
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
|
||||||
|
|
||||||
|
http-errors@2.0.1:
|
||||||
|
resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
|
||||||
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
import-meta-resolve@4.2.0:
|
import-meta-resolve@4.2.0:
|
||||||
resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==}
|
resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==}
|
||||||
|
|
||||||
@ -1423,6 +1457,14 @@ packages:
|
|||||||
micromark@4.0.2:
|
micromark@4.0.2:
|
||||||
resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
|
resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
|
||||||
|
|
||||||
|
mime-db@1.54.0:
|
||||||
|
resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
mime-types@3.0.2:
|
||||||
|
resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
mimic-response@3.1.0:
|
mimic-response@3.1.0:
|
||||||
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
|
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -1475,6 +1517,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
|
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
|
on-finished@2.4.1:
|
||||||
|
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
|
||||||
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
oniguruma-parser@0.12.1:
|
oniguruma-parser@0.12.1:
|
||||||
resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==}
|
resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==}
|
||||||
|
|
||||||
@ -1553,6 +1599,10 @@ packages:
|
|||||||
radix3@1.1.2:
|
radix3@1.1.2:
|
||||||
resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}
|
resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}
|
||||||
|
|
||||||
|
range-parser@1.2.1:
|
||||||
|
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
readable-stream@3.6.2:
|
readable-stream@3.6.2:
|
||||||
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
@ -1663,9 +1713,19 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
send@1.2.1:
|
||||||
|
resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
server-destroy@1.0.1:
|
||||||
|
resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==}
|
||||||
|
|
||||||
set-cookie-parser@2.7.2:
|
set-cookie-parser@2.7.2:
|
||||||
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
|
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
|
||||||
|
|
||||||
|
setprototypeof@1.2.0:
|
||||||
|
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
|
||||||
|
|
||||||
sharp@0.34.5:
|
sharp@0.34.5:
|
||||||
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
|
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
|
||||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||||
@ -1698,6 +1758,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
|
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
|
||||||
engines: {node: '>= 10.x'}
|
engines: {node: '>= 10.x'}
|
||||||
|
|
||||||
|
statuses@2.0.2:
|
||||||
|
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
||||||
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
string-width@4.2.3:
|
string-width@4.2.3:
|
||||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -1764,6 +1828,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==}
|
resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
toidentifier@1.0.1:
|
||||||
|
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
|
||||||
|
engines: {node: '>=0.6'}
|
||||||
|
|
||||||
tree-kill@1.2.2:
|
tree-kill@1.2.2:
|
||||||
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
|
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@ -2061,6 +2129,15 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@astrojs/node@9.5.5(astro@5.18.1(@types/node@25.4.0)(jiti@2.6.1)(rollup@4.59.0)(typescript@5.9.3))':
|
||||||
|
dependencies:
|
||||||
|
'@astrojs/internal-helpers': 0.7.6
|
||||||
|
astro: 5.18.1(@types/node@25.4.0)(jiti@2.6.1)(rollup@4.59.0)(typescript@5.9.3)
|
||||||
|
send: 1.2.1
|
||||||
|
server-destroy: 1.0.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@astrojs/prism@3.3.0':
|
'@astrojs/prism@3.3.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
prismjs: 1.30.0
|
prismjs: 1.30.0
|
||||||
@ -2826,6 +2903,8 @@ snapshots:
|
|||||||
|
|
||||||
defu@6.1.4: {}
|
defu@6.1.4: {}
|
||||||
|
|
||||||
|
depd@2.0.0: {}
|
||||||
|
|
||||||
dequal@2.0.3: {}
|
dequal@2.0.3: {}
|
||||||
|
|
||||||
destr@2.0.5: {}
|
destr@2.0.5: {}
|
||||||
@ -2869,10 +2948,14 @@ snapshots:
|
|||||||
|
|
||||||
dset@3.1.4: {}
|
dset@3.1.4: {}
|
||||||
|
|
||||||
|
ee-first@1.1.1: {}
|
||||||
|
|
||||||
emoji-regex@10.6.0: {}
|
emoji-regex@10.6.0: {}
|
||||||
|
|
||||||
emoji-regex@8.0.0: {}
|
emoji-regex@8.0.0: {}
|
||||||
|
|
||||||
|
encodeurl@2.0.0: {}
|
||||||
|
|
||||||
entities@4.5.0: {}
|
entities@4.5.0: {}
|
||||||
|
|
||||||
entities@6.0.1: {}
|
entities@6.0.1: {}
|
||||||
@ -2939,6 +3022,8 @@ snapshots:
|
|||||||
|
|
||||||
escalade@3.2.0: {}
|
escalade@3.2.0: {}
|
||||||
|
|
||||||
|
escape-html@1.0.3: {}
|
||||||
|
|
||||||
escape-string-regexp@5.0.0: {}
|
escape-string-regexp@5.0.0: {}
|
||||||
|
|
||||||
estree-walker@2.0.2: {}
|
estree-walker@2.0.2: {}
|
||||||
@ -2947,6 +3032,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.8
|
'@types/estree': 1.0.8
|
||||||
|
|
||||||
|
etag@1.8.1: {}
|
||||||
|
|
||||||
event-source-polyfill@1.0.31: {}
|
event-source-polyfill@1.0.31: {}
|
||||||
|
|
||||||
eventemitter3@5.0.4: {}
|
eventemitter3@5.0.4: {}
|
||||||
@ -3020,6 +3107,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tiny-inflate: 1.0.3
|
tiny-inflate: 1.0.3
|
||||||
|
|
||||||
|
fresh@2.0.0: {}
|
||||||
|
|
||||||
fsevents@2.3.3:
|
fsevents@2.3.3:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@ -3149,6 +3238,14 @@ snapshots:
|
|||||||
|
|
||||||
http-cache-semantics@4.2.0: {}
|
http-cache-semantics@4.2.0: {}
|
||||||
|
|
||||||
|
http-errors@2.0.1:
|
||||||
|
dependencies:
|
||||||
|
depd: 2.0.0
|
||||||
|
inherits: 2.0.4
|
||||||
|
setprototypeof: 1.2.0
|
||||||
|
statuses: 2.0.2
|
||||||
|
toidentifier: 1.0.1
|
||||||
|
|
||||||
import-meta-resolve@4.2.0: {}
|
import-meta-resolve@4.2.0: {}
|
||||||
|
|
||||||
inherits@2.0.4: {}
|
inherits@2.0.4: {}
|
||||||
@ -3525,6 +3622,12 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
mime-db@1.54.0: {}
|
||||||
|
|
||||||
|
mime-types@3.0.2:
|
||||||
|
dependencies:
|
||||||
|
mime-db: 1.54.0
|
||||||
|
|
||||||
mimic-response@3.1.0: {}
|
mimic-response@3.1.0: {}
|
||||||
|
|
||||||
mnemonist@0.40.0:
|
mnemonist@0.40.0:
|
||||||
@ -3565,6 +3668,10 @@ snapshots:
|
|||||||
|
|
||||||
on-exit-leak-free@2.1.2: {}
|
on-exit-leak-free@2.1.2: {}
|
||||||
|
|
||||||
|
on-finished@2.4.1:
|
||||||
|
dependencies:
|
||||||
|
ee-first: 1.1.1
|
||||||
|
|
||||||
oniguruma-parser@0.12.1: {}
|
oniguruma-parser@0.12.1: {}
|
||||||
|
|
||||||
oniguruma-to-es@4.3.4:
|
oniguruma-to-es@4.3.4:
|
||||||
@ -3650,6 +3757,8 @@ snapshots:
|
|||||||
|
|
||||||
radix3@1.1.2: {}
|
radix3@1.1.2: {}
|
||||||
|
|
||||||
|
range-parser@1.2.1: {}
|
||||||
|
|
||||||
readable-stream@3.6.2:
|
readable-stream@3.6.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
inherits: 2.0.4
|
inherits: 2.0.4
|
||||||
@ -3820,8 +3929,28 @@ snapshots:
|
|||||||
|
|
||||||
semver@7.7.4: {}
|
semver@7.7.4: {}
|
||||||
|
|
||||||
|
send@1.2.1:
|
||||||
|
dependencies:
|
||||||
|
debug: 4.4.3
|
||||||
|
encodeurl: 2.0.0
|
||||||
|
escape-html: 1.0.3
|
||||||
|
etag: 1.8.1
|
||||||
|
fresh: 2.0.0
|
||||||
|
http-errors: 2.0.1
|
||||||
|
mime-types: 3.0.2
|
||||||
|
ms: 2.1.3
|
||||||
|
on-finished: 2.4.1
|
||||||
|
range-parser: 1.2.1
|
||||||
|
statuses: 2.0.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
|
server-destroy@1.0.1: {}
|
||||||
|
|
||||||
set-cookie-parser@2.7.2: {}
|
set-cookie-parser@2.7.2: {}
|
||||||
|
|
||||||
|
setprototypeof@1.2.0: {}
|
||||||
|
|
||||||
sharp@0.34.5:
|
sharp@0.34.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@img/colour': 1.1.0
|
'@img/colour': 1.1.0
|
||||||
@ -3881,6 +4010,8 @@ snapshots:
|
|||||||
|
|
||||||
split2@4.2.0: {}
|
split2@4.2.0: {}
|
||||||
|
|
||||||
|
statuses@2.0.2: {}
|
||||||
|
|
||||||
string-width@4.2.3:
|
string-width@4.2.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
emoji-regex: 8.0.0
|
emoji-regex: 8.0.0
|
||||||
@ -3951,6 +4082,8 @@ snapshots:
|
|||||||
|
|
||||||
toad-cache@3.7.0: {}
|
toad-cache@3.7.0: {}
|
||||||
|
|
||||||
|
toidentifier@1.0.1: {}
|
||||||
|
|
||||||
tree-kill@1.2.2: {}
|
tree-kill@1.2.2: {}
|
||||||
|
|
||||||
trim-lines@3.0.1: {}
|
trim-lines@3.0.1: {}
|
||||||
|
|||||||
814
public/style.css
814
public/style.css
File diff suppressed because it is too large
Load Diff
@ -9,10 +9,10 @@
|
|||||||
"deploy": "sanity deploy"
|
"deploy": "sanity deploy"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sanity/vision": "^3",
|
"@sanity/vision": "^3.99.0",
|
||||||
"react": "^18",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^18",
|
"react-dom": "^19.2.4",
|
||||||
"sanity": "^3",
|
"sanity": "^3.99.0",
|
||||||
"styled-components": "^6"
|
"styled-components": "^6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
449
sanity/pnpm-lock.yaml
generated
449
sanity/pnpm-lock.yaml
generated
@ -9,20 +9,20 @@ importers:
|
|||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sanity/vision':
|
'@sanity/vision':
|
||||||
specifier: ^3
|
specifier: ^3.99.0
|
||||||
version: 3.99.0(@babel/runtime@7.29.2)(@codemirror/lint@6.9.5)(@codemirror/theme-one-dark@6.1.3)(@emotion/is-prop-valid@1.4.0)(codemirror@6.0.2)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
version: 3.99.0(@babel/runtime@7.29.2)(@codemirror/lint@6.9.5)(@codemirror/theme-one-dark@6.1.3)(@emotion/is-prop-valid@1.4.0)(codemirror@6.0.2)(react-dom@19.2.4(react@19.2.4))(react-is@18.3.1)(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))
|
||||||
react:
|
react:
|
||||||
specifier: ^18
|
specifier: ^19.2.4
|
||||||
version: 18.3.1
|
version: 19.2.4
|
||||||
react-dom:
|
react-dom:
|
||||||
specifier: ^18
|
specifier: ^19.2.4
|
||||||
version: 18.3.1(react@18.3.1)
|
version: 19.2.4(react@19.2.4)
|
||||||
sanity:
|
sanity:
|
||||||
specifier: ^3
|
specifier: ^3.99.0
|
||||||
version: 3.99.0(@emotion/is-prop-valid@1.4.0)(@types/node@25.5.0)(@types/react@19.2.14)(immer@10.2.0)(jiti@2.6.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.9.3)(yaml@2.8.3)
|
version: 3.99.0(@emotion/is-prop-valid@1.4.0)(@types/node@25.5.0)(@types/react@19.2.14)(immer@10.2.0)(jiti@2.6.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(yaml@2.8.3)
|
||||||
styled-components:
|
styled-components:
|
||||||
specifier: ^6
|
specifier: ^6
|
||||||
version: 6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@sanity/eslint-config-studio':
|
'@sanity/eslint-config-studio':
|
||||||
specifier: ^4
|
specifier: ^4
|
||||||
@ -705,6 +705,9 @@ packages:
|
|||||||
'@codemirror/view@6.40.0':
|
'@codemirror/view@6.40.0':
|
||||||
resolution: {integrity: sha512-WA0zdU7xfF10+5I3HhUUq3kqOx3KjqmtQ9lqZjfK7jtYk4G72YW9rezcSywpaUMCWOMlq+6E0pO1IWg1TNIhtg==}
|
resolution: {integrity: sha512-WA0zdU7xfF10+5I3HhUUq3kqOx3KjqmtQ9lqZjfK7jtYk4G72YW9rezcSywpaUMCWOMlq+6E0pO1IWg1TNIhtg==}
|
||||||
|
|
||||||
|
'@codemirror/view@6.41.0':
|
||||||
|
resolution: {integrity: sha512-6H/qadXsVuDY219Yljhohglve8xf4B8xJkVOEWfA5uiYKiTFppjqsvsfR5iPA0RbvRBoOyTZpbLIxe9+0UR8xA==}
|
||||||
|
|
||||||
'@csstools/color-helpers@5.1.0':
|
'@csstools/color-helpers@5.1.0':
|
||||||
resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
|
resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -4259,10 +4262,10 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^17.0.0 || ^18.0.0 || ^19.0.0 || ^0.0.0-experimental
|
react: ^17.0.0 || ^18.0.0 || ^19.0.0 || ^0.0.0-experimental
|
||||||
|
|
||||||
react-dom@18.3.1:
|
react-dom@19.2.4:
|
||||||
resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
|
resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^18.3.1
|
react: ^19.2.4
|
||||||
|
|
||||||
react-fast-compare@3.2.2:
|
react-fast-compare@3.2.2:
|
||||||
resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
|
resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
|
||||||
@ -4310,8 +4313,8 @@ packages:
|
|||||||
react: ^18.3 || >=19.0.0-0
|
react: ^18.3 || >=19.0.0-0
|
||||||
rxjs: ^7
|
rxjs: ^7
|
||||||
|
|
||||||
react@18.3.1:
|
react@19.2.4:
|
||||||
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
read-pkg-up@7.0.1:
|
read-pkg-up@7.0.1:
|
||||||
@ -4513,8 +4516,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
|
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
|
||||||
engines: {node: '>=v12.22.7'}
|
engines: {node: '>=v12.22.7'}
|
||||||
|
|
||||||
scheduler@0.23.2:
|
scheduler@0.27.0:
|
||||||
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
|
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
|
||||||
|
|
||||||
scroll-into-view-if-needed@3.1.0:
|
scroll-into-view-if-needed@3.1.0:
|
||||||
resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==}
|
resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==}
|
||||||
@ -6286,7 +6289,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@codemirror/language': 6.12.3
|
'@codemirror/language': 6.12.3
|
||||||
'@codemirror/state': 6.6.0
|
'@codemirror/state': 6.6.0
|
||||||
'@codemirror/view': 6.40.0
|
'@codemirror/view': 6.41.0
|
||||||
'@lezer/highlight': 1.2.3
|
'@lezer/highlight': 1.2.3
|
||||||
|
|
||||||
'@codemirror/view@6.40.0':
|
'@codemirror/view@6.40.0':
|
||||||
@ -6296,6 +6299,13 @@ snapshots:
|
|||||||
style-mod: 4.1.3
|
style-mod: 4.1.3
|
||||||
w3c-keyname: 2.2.8
|
w3c-keyname: 2.2.8
|
||||||
|
|
||||||
|
'@codemirror/view@6.41.0':
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/state': 6.6.0
|
||||||
|
crelt: 1.0.6
|
||||||
|
style-mod: 4.1.3
|
||||||
|
w3c-keyname: 2.2.8
|
||||||
|
|
||||||
'@csstools/color-helpers@5.1.0': {}
|
'@csstools/color-helpers@5.1.0': {}
|
||||||
|
|
||||||
'@csstools/color-helpers@6.0.2': {}
|
'@csstools/color-helpers@6.0.2': {}
|
||||||
@ -6344,36 +6354,36 @@ snapshots:
|
|||||||
|
|
||||||
'@date-fns/utc@2.1.1': {}
|
'@date-fns/utc@2.1.1': {}
|
||||||
|
|
||||||
'@dnd-kit/accessibility@3.1.1(react@18.3.1)':
|
'@dnd-kit/accessibility@3.1.1(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@dnd-kit/accessibility': 3.1.1(react@18.3.1)
|
'@dnd-kit/accessibility': 3.1.1(react@19.2.4)
|
||||||
'@dnd-kit/utilities': 3.2.2(react@18.3.1)
|
'@dnd-kit/utilities': 3.2.2(react@19.2.4)
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@dnd-kit/modifiers@6.0.1(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
|
'@dnd-kit/modifiers@6.0.1(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@dnd-kit/core': 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@dnd-kit/core': 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
'@dnd-kit/utilities': 3.2.2(react@18.3.1)
|
'@dnd-kit/utilities': 3.2.2(react@19.2.4)
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@dnd-kit/sortable@7.0.2(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
|
'@dnd-kit/sortable@7.0.2(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@dnd-kit/core': 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@dnd-kit/core': 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
'@dnd-kit/utilities': 3.2.2(react@18.3.1)
|
'@dnd-kit/utilities': 3.2.2(react@19.2.4)
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@dnd-kit/utilities@3.2.2(react@18.3.1)':
|
'@dnd-kit/utilities@3.2.2(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@emotion/is-prop-valid@1.4.0':
|
'@emotion/is-prop-valid@1.4.0':
|
||||||
@ -6496,11 +6506,11 @@ snapshots:
|
|||||||
'@floating-ui/core': 1.7.5
|
'@floating-ui/core': 1.7.5
|
||||||
'@floating-ui/utils': 0.2.11
|
'@floating-ui/utils': 0.2.11
|
||||||
|
|
||||||
'@floating-ui/react-dom@2.1.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@floating-ui/react-dom@2.1.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@floating-ui/dom': 1.7.6
|
'@floating-ui/dom': 1.7.6
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
|
|
||||||
'@floating-ui/utils@0.2.11': {}
|
'@floating-ui/utils@0.2.11': {}
|
||||||
|
|
||||||
@ -6697,22 +6707,22 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mux-embed: 5.17.10
|
mux-embed: 5.17.10
|
||||||
|
|
||||||
'@mux/mux-player-react@3.11.7(@types/react@19.2.14)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@mux/mux-player-react@3.11.7(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@mux/mux-player': 3.11.7(react@18.3.1)
|
'@mux/mux-player': 3.11.7(react@19.2.4)
|
||||||
'@mux/playback-core': 0.33.3
|
'@mux/playback-core': 0.33.3
|
||||||
prop-types: 15.8.1
|
prop-types: 15.8.1
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.14
|
'@types/react': 19.2.14
|
||||||
|
|
||||||
'@mux/mux-player@3.11.7(react@18.3.1)':
|
'@mux/mux-player@3.11.7(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@mux/mux-video': 0.30.5
|
'@mux/mux-video': 0.30.5
|
||||||
'@mux/playback-core': 0.33.3
|
'@mux/playback-core': 0.33.3
|
||||||
media-chrome: 4.18.3(react@18.3.1)
|
media-chrome: 4.18.3(react@19.2.4)
|
||||||
player.style: 0.3.1(react@18.3.1)
|
player.style: 0.3.1(react@19.2.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- react
|
- react
|
||||||
|
|
||||||
@ -6832,7 +6842,7 @@ snapshots:
|
|||||||
get-random-values-esm: 1.0.2
|
get-random-values-esm: 1.0.2
|
||||||
lodash: 4.17.23
|
lodash: 4.17.23
|
||||||
|
|
||||||
'@portabletext/editor@1.58.1(@sanity/schema@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@types/react@19.2.14)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rxjs@7.8.2)':
|
'@portabletext/editor@1.58.1(@sanity/schema@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@portabletext/block-tools': 1.1.38(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@types/react@19.2.14)
|
'@portabletext/block-tools': 1.1.38(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@types/react@19.2.14)
|
||||||
'@portabletext/keyboard-shortcuts': 1.1.0
|
'@portabletext/keyboard-shortcuts': 1.1.0
|
||||||
@ -6840,19 +6850,19 @@ snapshots:
|
|||||||
'@portabletext/to-html': 2.0.17
|
'@portabletext/to-html': 2.0.17
|
||||||
'@sanity/schema': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
'@sanity/schema': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
||||||
'@sanity/types': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
'@sanity/types': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
||||||
'@xstate/react': 6.1.0(@types/react@19.2.14)(react@18.3.1)(xstate@5.30.0)
|
'@xstate/react': 6.1.0(@types/react@19.2.14)(react@19.2.4)(xstate@5.30.0)
|
||||||
debug: 4.4.3(supports-color@8.1.1)
|
debug: 4.4.3(supports-color@8.1.1)
|
||||||
get-random-values-esm: 1.0.2
|
get-random-values-esm: 1.0.2
|
||||||
immer: 10.2.0
|
immer: 10.2.0
|
||||||
lodash: 4.17.23
|
lodash: 4.17.23
|
||||||
lodash.startcase: 4.4.0
|
lodash.startcase: 4.4.0
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-compiler-runtime: 19.1.0-rc.2(react@18.3.1)
|
react-compiler-runtime: 19.1.0-rc.2(react@19.2.4)
|
||||||
rxjs: 7.8.2
|
rxjs: 7.8.2
|
||||||
slate: 0.117.2
|
slate: 0.117.2
|
||||||
slate-dom: 0.116.0(slate@0.117.2)
|
slate-dom: 0.116.0(slate@0.117.2)
|
||||||
slate-react: 0.117.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate-dom@0.116.0(slate@0.117.2))(slate@0.117.2)
|
slate-react: 0.117.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(slate-dom@0.116.0(slate@0.117.2))(slate@0.117.2)
|
||||||
use-effect-event: 1.0.2(react@18.3.1)
|
use-effect-event: 1.0.2(react@19.2.4)
|
||||||
xstate: 5.30.0
|
xstate: 5.30.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/react'
|
- '@types/react'
|
||||||
@ -6866,11 +6876,11 @@ snapshots:
|
|||||||
'@sanity/diff-match-patch': 3.2.0
|
'@sanity/diff-match-patch': 3.2.0
|
||||||
lodash: 4.17.23
|
lodash: 4.17.23
|
||||||
|
|
||||||
'@portabletext/react@3.2.4(react@18.3.1)':
|
'@portabletext/react@3.2.4(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@portabletext/toolkit': 2.0.18
|
'@portabletext/toolkit': 2.0.18
|
||||||
'@portabletext/types': 2.0.15
|
'@portabletext/types': 2.0.15
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
'@portabletext/to-html@2.0.17':
|
'@portabletext/to-html@2.0.17':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -6883,16 +6893,16 @@ snapshots:
|
|||||||
|
|
||||||
'@portabletext/types@2.0.15': {}
|
'@portabletext/types@2.0.15': {}
|
||||||
|
|
||||||
'@rexxars/react-json-inspector@9.0.1(react@18.3.1)':
|
'@rexxars/react-json-inspector@9.0.1(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
debounce: 1.2.1
|
debounce: 1.2.1
|
||||||
md5-o-matic: 0.1.1
|
md5-o-matic: 0.1.1
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
'@rexxars/react-split-pane@1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@rexxars/react-split-pane@1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
|
|
||||||
'@rolldown/pluginutils@1.0.0-beta.27': {}
|
'@rolldown/pluginutils@1.0.0-beta.27': {}
|
||||||
|
|
||||||
@ -6980,13 +6990,13 @@ snapshots:
|
|||||||
nanoid: 3.3.11
|
nanoid: 3.3.11
|
||||||
rxjs: 7.8.2
|
rxjs: 7.8.2
|
||||||
|
|
||||||
'@sanity/cli@3.99.0(@types/node@25.5.0)(@types/react@19.2.14)(react@18.3.1)(typescript@5.9.3)(yaml@2.8.3)':
|
'@sanity/cli@3.99.0(@types/node@25.5.0)(@types/react@19.2.14)(react@19.2.4)(typescript@5.9.3)(yaml@2.8.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/traverse': 7.29.0
|
'@babel/traverse': 7.29.0
|
||||||
'@sanity/client': 7.20.0(debug@4.4.3)
|
'@sanity/client': 7.20.0(debug@4.4.3)
|
||||||
'@sanity/codegen': 3.99.0
|
'@sanity/codegen': 3.99.0
|
||||||
'@sanity/runtime-cli': 9.2.0(@types/node@25.5.0)(debug@4.4.3)(typescript@5.9.3)(yaml@2.8.3)
|
'@sanity/runtime-cli': 9.2.0(@types/node@25.5.0)(debug@4.4.3)(typescript@5.9.3)(yaml@2.8.3)
|
||||||
'@sanity/telemetry': 0.8.1(react@18.3.1)
|
'@sanity/telemetry': 0.8.1(react@19.2.4)
|
||||||
'@sanity/template-validator': 2.4.6
|
'@sanity/template-validator': 2.4.6
|
||||||
'@sanity/util': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
'@sanity/util': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
@ -7129,9 +7139,9 @@ snapshots:
|
|||||||
|
|
||||||
'@sanity/generate-help-url@3.0.1': {}
|
'@sanity/generate-help-url@3.0.1': {}
|
||||||
|
|
||||||
'@sanity/icons@3.7.4(react@18.3.1)':
|
'@sanity/icons@3.7.4(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
'@sanity/id-utils@1.0.0':
|
'@sanity/id-utils@1.0.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -7168,24 +7178,24 @@ snapshots:
|
|||||||
- '@types/react'
|
- '@types/react'
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@sanity/insert-menu@1.1.13(@emotion/is-prop-valid@1.4.0)(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))':
|
'@sanity/insert-menu@1.1.13(@emotion/is-prop-valid@1.4.0)(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(react-dom@19.2.4(react@19.2.4))(react-is@18.3.1)(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sanity/icons': 3.7.4(react@18.3.1)
|
'@sanity/icons': 3.7.4(react@19.2.4)
|
||||||
'@sanity/types': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
'@sanity/types': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
||||||
'@sanity/ui': 2.16.22(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
'@sanity/ui': 2.16.22(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.4(react@19.2.4))(react-is@18.3.1)(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))
|
||||||
lodash: 4.17.23
|
lodash: 4.17.23
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-compiler-runtime: 19.1.0-rc.2(react@18.3.1)
|
react-compiler-runtime: 19.1.0-rc.2(react@19.2.4)
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
react-is: 18.3.1
|
react-is: 18.3.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@emotion/is-prop-valid'
|
- '@emotion/is-prop-valid'
|
||||||
- styled-components
|
- styled-components
|
||||||
|
|
||||||
'@sanity/logos@2.2.2(react@18.3.1)':
|
'@sanity/logos@2.2.2(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sanity/color': 3.0.6
|
'@sanity/color': 3.0.6
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
'@sanity/media-library-types@1.2.0': {}
|
'@sanity/media-library-types@1.2.0': {}
|
||||||
|
|
||||||
@ -7240,13 +7250,13 @@ snapshots:
|
|||||||
- '@sanity/client'
|
- '@sanity/client'
|
||||||
- '@sanity/types'
|
- '@sanity/types'
|
||||||
|
|
||||||
'@sanity/preview-url-secret@2.1.16(@sanity/client@7.20.0(debug@4.4.3))(@sanity/icons@3.7.4(react@18.3.1))(sanity@3.99.0(@emotion/is-prop-valid@1.4.0)(@types/node@25.5.0)(@types/react@19.2.14)(immer@10.2.0)(jiti@2.6.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.9.3)(yaml@2.8.3))':
|
'@sanity/preview-url-secret@2.1.16(@sanity/client@7.20.0(debug@4.4.3))(@sanity/icons@3.7.4(react@19.2.4))(sanity@3.99.0(@emotion/is-prop-valid@1.4.0)(@types/node@25.5.0)(@types/react@19.2.14)(immer@10.2.0)(jiti@2.6.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(yaml@2.8.3))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sanity/client': 7.20.0(debug@4.4.3)
|
'@sanity/client': 7.20.0(debug@4.4.3)
|
||||||
'@sanity/uuid': 3.0.2
|
'@sanity/uuid': 3.0.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@sanity/icons': 3.7.4(react@18.3.1)
|
'@sanity/icons': 3.7.4(react@19.2.4)
|
||||||
sanity: 3.99.0(@emotion/is-prop-valid@1.4.0)(@types/node@25.5.0)(@types/react@19.2.14)(immer@10.2.0)(jiti@2.6.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.9.3)(yaml@2.8.3)
|
sanity: 3.99.0(@emotion/is-prop-valid@1.4.0)(@types/node@25.5.0)(@types/react@19.2.14)(immer@10.2.0)(jiti@2.6.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(yaml@2.8.3)
|
||||||
|
|
||||||
'@sanity/runtime-cli@9.2.0(@types/node@25.5.0)(debug@4.4.3)(typescript@5.9.3)(yaml@2.8.3)':
|
'@sanity/runtime-cli@9.2.0(@types/node@25.5.0)(debug@4.4.3)(typescript@5.9.3)(yaml@2.8.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -7307,7 +7317,7 @@ snapshots:
|
|||||||
- debug
|
- debug
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@sanity/sdk@0.0.0-alpha.25(@types/react@19.2.14)(debug@4.4.3)(immer@10.2.0)(react@18.3.1)(use-sync-external-store@1.6.0(react@18.3.1))':
|
'@sanity/sdk@0.0.0-alpha.25(@types/react@19.2.14)(debug@4.4.3)(immer@10.2.0)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sanity/client': 6.29.1(debug@4.4.3)
|
'@sanity/client': 6.29.1(debug@4.4.3)
|
||||||
'@sanity/comlink': 3.1.1
|
'@sanity/comlink': 3.1.1
|
||||||
@ -7318,7 +7328,7 @@ snapshots:
|
|||||||
lodash-es: 4.17.23
|
lodash-es: 4.17.23
|
||||||
reselect: 5.1.1
|
reselect: 5.1.1
|
||||||
rxjs: 7.8.2
|
rxjs: 7.8.2
|
||||||
zustand: 5.0.12(@types/react@19.2.14)(immer@10.2.0)(react@18.3.1)(use-sync-external-store@1.6.0(react@18.3.1))
|
zustand: 5.0.12(@types/react@19.2.14)(immer@10.2.0)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/react'
|
- '@types/react'
|
||||||
- debug
|
- debug
|
||||||
@ -7326,10 +7336,10 @@ snapshots:
|
|||||||
- react
|
- react
|
||||||
- use-sync-external-store
|
- use-sync-external-store
|
||||||
|
|
||||||
'@sanity/telemetry@0.8.1(react@18.3.1)':
|
'@sanity/telemetry@0.8.1(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
lodash: 4.17.23
|
lodash: 4.17.23
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
rxjs: 7.8.2
|
rxjs: 7.8.2
|
||||||
typeid-js: 0.3.0
|
typeid-js: 0.3.0
|
||||||
|
|
||||||
@ -7354,21 +7364,21 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- debug
|
- debug
|
||||||
|
|
||||||
'@sanity/ui@2.16.22(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))':
|
'@sanity/ui@2.16.22(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.4(react@19.2.4))(react-is@18.3.1)(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@floating-ui/react-dom': 2.1.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@floating-ui/react-dom': 2.1.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
'@juggle/resize-observer': 3.4.0
|
'@juggle/resize-observer': 3.4.0
|
||||||
'@sanity/color': 3.0.6
|
'@sanity/color': 3.0.6
|
||||||
'@sanity/icons': 3.7.4(react@18.3.1)
|
'@sanity/icons': 3.7.4(react@19.2.4)
|
||||||
csstype: 3.2.3
|
csstype: 3.2.3
|
||||||
motion: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
motion: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-compiler-runtime: 1.0.0(react@18.3.1)
|
react-compiler-runtime: 1.0.0(react@19.2.4)
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
react-is: 18.3.1
|
react-is: 18.3.1
|
||||||
react-refractor: 2.2.0(react@18.3.1)
|
react-refractor: 2.2.0(react@19.2.4)
|
||||||
styled-components: 6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
styled-components: 6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
use-effect-event: 2.0.3(react@18.3.1)
|
use-effect-event: 2.0.3(react@19.2.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@emotion/is-prop-valid'
|
- '@emotion/is-prop-valid'
|
||||||
|
|
||||||
@ -7401,7 +7411,7 @@ snapshots:
|
|||||||
'@types/uuid': 8.3.4
|
'@types/uuid': 8.3.4
|
||||||
uuid: 8.3.2
|
uuid: 8.3.2
|
||||||
|
|
||||||
'@sanity/vision@3.99.0(@babel/runtime@7.29.2)(@codemirror/lint@6.9.5)(@codemirror/theme-one-dark@6.1.3)(@emotion/is-prop-valid@1.4.0)(codemirror@6.0.2)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))':
|
'@sanity/vision@3.99.0(@babel/runtime@7.29.2)(@codemirror/lint@6.9.5)(@codemirror/theme-one-dark@6.1.3)(@emotion/is-prop-valid@1.4.0)(codemirror@6.0.2)(react-dom@19.2.4(react@19.2.4))(react-is@18.3.1)(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@codemirror/autocomplete': 6.20.1
|
'@codemirror/autocomplete': 6.20.1
|
||||||
'@codemirror/commands': 6.10.3
|
'@codemirror/commands': 6.10.3
|
||||||
@ -7412,25 +7422,25 @@ snapshots:
|
|||||||
'@codemirror/view': 6.40.0
|
'@codemirror/view': 6.40.0
|
||||||
'@juggle/resize-observer': 3.4.0
|
'@juggle/resize-observer': 3.4.0
|
||||||
'@lezer/highlight': 1.2.3
|
'@lezer/highlight': 1.2.3
|
||||||
'@rexxars/react-json-inspector': 9.0.1(react@18.3.1)
|
'@rexxars/react-json-inspector': 9.0.1(react@19.2.4)
|
||||||
'@rexxars/react-split-pane': 1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@rexxars/react-split-pane': 1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
'@sanity/color': 3.0.6
|
'@sanity/color': 3.0.6
|
||||||
'@sanity/icons': 3.7.4(react@18.3.1)
|
'@sanity/icons': 3.7.4(react@19.2.4)
|
||||||
'@sanity/ui': 2.16.22(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
'@sanity/ui': 2.16.22(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.4(react@19.2.4))(react-is@18.3.1)(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))
|
||||||
'@sanity/uuid': 3.0.2
|
'@sanity/uuid': 3.0.2
|
||||||
'@uiw/react-codemirror': 4.25.9(@babel/runtime@7.29.2)(@codemirror/autocomplete@6.20.1)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.40.0)(codemirror@6.0.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@uiw/react-codemirror': 4.25.9(@babel/runtime@7.29.2)(@codemirror/autocomplete@6.20.1)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.40.0)(codemirror@6.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
is-hotkey-esm: 1.0.0
|
is-hotkey-esm: 1.0.0
|
||||||
json-2-csv: 5.5.10
|
json-2-csv: 5.5.10
|
||||||
json5: 2.2.3
|
json5: 2.2.3
|
||||||
lodash: 4.17.23
|
lodash: 4.17.23
|
||||||
quick-lru: 5.1.1
|
quick-lru: 5.1.1
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-compiler-runtime: 19.1.0-rc.2(react@18.3.1)
|
react-compiler-runtime: 19.1.0-rc.2(react@19.2.4)
|
||||||
react-fast-compare: 3.2.2
|
react-fast-compare: 3.2.2
|
||||||
react-rx: 4.2.2(react@18.3.1)(rxjs@7.8.2)
|
react-rx: 4.2.2(react@19.2.4)(rxjs@7.8.2)
|
||||||
rxjs: 7.8.2
|
rxjs: 7.8.2
|
||||||
styled-components: 6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
styled-components: 6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
use-effect-event: 2.0.3(react@18.3.1)
|
use-effect-event: 2.0.3(react@19.2.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@babel/runtime'
|
- '@babel/runtime'
|
||||||
- '@codemirror/lint'
|
- '@codemirror/lint'
|
||||||
@ -7474,24 +7484,24 @@ snapshots:
|
|||||||
|
|
||||||
'@sentry/core@8.55.1': {}
|
'@sentry/core@8.55.1': {}
|
||||||
|
|
||||||
'@sentry/react@8.55.1(react@18.3.1)':
|
'@sentry/react@8.55.1(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sentry/browser': 8.55.1
|
'@sentry/browser': 8.55.1
|
||||||
'@sentry/core': 8.55.1
|
'@sentry/core': 8.55.1
|
||||||
hoist-non-react-statics: 3.3.2
|
hoist-non-react-statics: 3.3.2
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
'@tanstack/react-table@8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@tanstack/react-table@8.21.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/table-core': 8.21.3
|
'@tanstack/table-core': 8.21.3
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
|
|
||||||
'@tanstack/react-virtual@3.13.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@tanstack/react-virtual@3.13.23(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/virtual-core': 3.13.23
|
'@tanstack/virtual-core': 3.13.23
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
|
|
||||||
'@tanstack/table-core@8.21.3': {}
|
'@tanstack/table-core@8.21.3': {}
|
||||||
|
|
||||||
@ -7666,7 +7676,7 @@ snapshots:
|
|||||||
'@codemirror/state': 6.6.0
|
'@codemirror/state': 6.6.0
|
||||||
'@codemirror/view': 6.40.0
|
'@codemirror/view': 6.40.0
|
||||||
|
|
||||||
'@uiw/react-codemirror@4.25.9(@babel/runtime@7.29.2)(@codemirror/autocomplete@6.20.1)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.40.0)(codemirror@6.0.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@uiw/react-codemirror@4.25.9(@babel/runtime@7.29.2)(@codemirror/autocomplete@6.20.1)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.40.0)(codemirror@6.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.29.2
|
'@babel/runtime': 7.29.2
|
||||||
'@codemirror/commands': 6.10.3
|
'@codemirror/commands': 6.10.3
|
||||||
@ -7675,8 +7685,8 @@ snapshots:
|
|||||||
'@codemirror/view': 6.40.0
|
'@codemirror/view': 6.40.0
|
||||||
'@uiw/codemirror-extensions-basic-setup': 4.25.9(@codemirror/autocomplete@6.20.1)(@codemirror/commands@6.10.3)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
|
'@uiw/codemirror-extensions-basic-setup': 4.25.9(@codemirror/autocomplete@6.20.1)(@codemirror/commands@6.10.3)(@codemirror/language@6.12.3)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.6.0)(@codemirror/view@6.40.0)
|
||||||
codemirror: 6.0.2
|
codemirror: 6.0.2
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@codemirror/autocomplete'
|
- '@codemirror/autocomplete'
|
||||||
- '@codemirror/language'
|
- '@codemirror/language'
|
||||||
@ -7699,11 +7709,11 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@xstate/react@6.1.0(@types/react@19.2.14)(react@18.3.1)(xstate@5.30.0)':
|
'@xstate/react@6.1.0(@types/react@19.2.14)(react@19.2.4)(xstate@5.30.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
use-isomorphic-layout-effect: 1.2.1(@types/react@19.2.14)(react@18.3.1)
|
use-isomorphic-layout-effect: 1.2.1(@types/react@19.2.14)(react@19.2.4)
|
||||||
use-sync-external-store: 1.6.0(react@18.3.1)
|
use-sync-external-store: 1.6.0(react@19.2.4)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
xstate: 5.30.0
|
xstate: 5.30.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@ -8063,9 +8073,9 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
custom-media-element: 1.4.6
|
custom-media-element: 1.4.6
|
||||||
|
|
||||||
ce-la-react@0.3.2(react@18.3.1):
|
ce-la-react@0.3.2(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
chalk@2.4.2:
|
chalk@2.4.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -8144,7 +8154,7 @@ snapshots:
|
|||||||
'@codemirror/lint': 6.9.5
|
'@codemirror/lint': 6.9.5
|
||||||
'@codemirror/search': 6.6.0
|
'@codemirror/search': 6.6.0
|
||||||
'@codemirror/state': 6.6.0
|
'@codemirror/state': 6.6.0
|
||||||
'@codemirror/view': 6.40.0
|
'@codemirror/view': 6.41.0
|
||||||
|
|
||||||
color-convert@1.9.3:
|
color-convert@1.9.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -8927,15 +8937,15 @@ snapshots:
|
|||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
|
|
||||||
framer-motion@12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
framer-motion@12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
motion-dom: 12.38.0
|
motion-dom: 12.38.0
|
||||||
motion-utils: 12.36.0
|
motion-utils: 12.36.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@emotion/is-prop-valid': 1.4.0
|
'@emotion/is-prop-valid': 1.4.0
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
|
|
||||||
from2@2.3.0:
|
from2@2.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -9716,22 +9726,22 @@ snapshots:
|
|||||||
|
|
||||||
mdn-data@2.27.1: {}
|
mdn-data@2.27.1: {}
|
||||||
|
|
||||||
media-chrome@4.11.1(react@18.3.1):
|
media-chrome@4.11.1(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vercel/edge': 1.2.2
|
'@vercel/edge': 1.2.2
|
||||||
ce-la-react: 0.3.2(react@18.3.1)
|
ce-la-react: 0.3.2(react@19.2.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- react
|
- react
|
||||||
|
|
||||||
media-chrome@4.16.1(react@18.3.1):
|
media-chrome@4.16.1(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
ce-la-react: 0.3.2(react@18.3.1)
|
ce-la-react: 0.3.2(react@19.2.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- react
|
- react
|
||||||
|
|
||||||
media-chrome@4.18.3(react@18.3.1):
|
media-chrome@4.18.3(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
ce-la-react: 0.3.2(react@18.3.1)
|
ce-la-react: 0.3.2(react@19.2.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- react
|
- react
|
||||||
|
|
||||||
@ -9842,14 +9852,14 @@ snapshots:
|
|||||||
|
|
||||||
motion-utils@12.36.0: {}
|
motion-utils@12.36.0: {}
|
||||||
|
|
||||||
motion@12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
motion@12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
framer-motion: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
framer-motion: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@emotion/is-prop-valid': 1.4.0
|
'@emotion/is-prop-valid': 1.4.0
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
|
|
||||||
ms@2.0.0: {}
|
ms@2.0.0: {}
|
||||||
|
|
||||||
@ -10152,15 +10162,15 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
find-up: 5.0.0
|
find-up: 5.0.0
|
||||||
|
|
||||||
player.style@0.1.10(react@18.3.1):
|
player.style@0.1.10(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
media-chrome: 4.11.1(react@18.3.1)
|
media-chrome: 4.11.1(react@19.2.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- react
|
- react
|
||||||
|
|
||||||
player.style@0.3.1(react@18.3.1):
|
player.style@0.3.1(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
media-chrome: 4.16.1(react@18.3.1)
|
media-chrome: 4.16.1(react@19.2.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- react
|
- react
|
||||||
|
|
||||||
@ -10250,72 +10260,69 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
performance-now: 2.1.0
|
performance-now: 2.1.0
|
||||||
|
|
||||||
react-clientside-effect@1.2.8(react@18.3.1):
|
react-clientside-effect@1.2.8(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.29.2
|
'@babel/runtime': 7.29.2
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
react-compiler-runtime@1.0.0(react@18.3.1):
|
react-compiler-runtime@1.0.0(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
react-compiler-runtime@19.1.0-rc.2(react@18.3.1):
|
react-compiler-runtime@19.1.0-rc.2(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
react-dom@18.3.1(react@18.3.1):
|
react-dom@19.2.4(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
react: 19.2.4
|
||||||
react: 18.3.1
|
scheduler: 0.27.0
|
||||||
scheduler: 0.23.2
|
|
||||||
|
|
||||||
react-fast-compare@3.2.2: {}
|
react-fast-compare@3.2.2: {}
|
||||||
|
|
||||||
react-focus-lock@2.13.7(@types/react@19.2.14)(react@18.3.1):
|
react-focus-lock@2.13.7(@types/react@19.2.14)(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.29.2
|
'@babel/runtime': 7.29.2
|
||||||
focus-lock: 1.3.6
|
focus-lock: 1.3.6
|
||||||
prop-types: 15.8.1
|
prop-types: 15.8.1
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-clientside-effect: 1.2.8(react@18.3.1)
|
react-clientside-effect: 1.2.8(react@19.2.4)
|
||||||
use-callback-ref: 1.3.3(@types/react@19.2.14)(react@18.3.1)
|
use-callback-ref: 1.3.3(@types/react@19.2.14)(react@19.2.4)
|
||||||
use-sidecar: 1.1.3(@types/react@19.2.14)(react@18.3.1)
|
use-sidecar: 1.1.3(@types/react@19.2.14)(react@19.2.4)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.14
|
'@types/react': 19.2.14
|
||||||
|
|
||||||
react-i18next@14.0.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
react-i18next@14.0.2(i18next@23.16.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.29.2
|
'@babel/runtime': 7.29.2
|
||||||
html-parse-stringify: 3.0.1
|
html-parse-stringify: 3.0.1
|
||||||
i18next: 23.16.8
|
i18next: 23.16.8
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
|
|
||||||
react-is@16.13.1: {}
|
react-is@16.13.1: {}
|
||||||
|
|
||||||
react-is@18.3.1: {}
|
react-is@18.3.1: {}
|
||||||
|
|
||||||
react-refractor@2.2.0(react@18.3.1):
|
react-refractor@2.2.0(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
refractor: 3.6.0
|
refractor: 3.6.0
|
||||||
unist-util-filter: 2.0.3
|
unist-util-filter: 2.0.3
|
||||||
unist-util-visit-parents: 3.1.1
|
unist-util-visit-parents: 3.1.1
|
||||||
|
|
||||||
react-refresh@0.17.0: {}
|
react-refresh@0.17.0: {}
|
||||||
|
|
||||||
react-rx@4.2.2(react@18.3.1)(rxjs@7.8.2):
|
react-rx@4.2.2(react@19.2.4)(rxjs@7.8.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
observable-callback: 1.0.3(rxjs@7.8.2)
|
observable-callback: 1.0.3(rxjs@7.8.2)
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-compiler-runtime: 1.0.0(react@18.3.1)
|
react-compiler-runtime: 1.0.0(react@19.2.4)
|
||||||
rxjs: 7.8.2
|
rxjs: 7.8.2
|
||||||
use-effect-event: 2.0.3(react@18.3.1)
|
use-effect-event: 2.0.3(react@19.2.4)
|
||||||
|
|
||||||
react@18.3.1:
|
react@19.2.4: {}
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
|
|
||||||
read-pkg-up@7.0.1:
|
read-pkg-up@7.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -10561,22 +10568,22 @@ snapshots:
|
|||||||
|
|
||||||
safer-buffer@2.1.2: {}
|
safer-buffer@2.1.2: {}
|
||||||
|
|
||||||
sanity@3.99.0(@emotion/is-prop-valid@1.4.0)(@types/node@25.5.0)(@types/react@19.2.14)(immer@10.2.0)(jiti@2.6.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.9.3)(yaml@2.8.3):
|
sanity@3.99.0(@emotion/is-prop-valid@1.4.0)(@types/node@25.5.0)(@types/react@19.2.14)(immer@10.2.0)(jiti@2.6.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(yaml@2.8.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@dnd-kit/core': 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@dnd-kit/core': 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
'@dnd-kit/modifiers': 6.0.1(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
'@dnd-kit/modifiers': 6.0.1(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)
|
||||||
'@dnd-kit/sortable': 7.0.2(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
'@dnd-kit/sortable': 7.0.2(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)
|
||||||
'@dnd-kit/utilities': 3.2.2(react@18.3.1)
|
'@dnd-kit/utilities': 3.2.2(react@19.2.4)
|
||||||
'@juggle/resize-observer': 3.4.0
|
'@juggle/resize-observer': 3.4.0
|
||||||
'@mux/mux-player-react': 3.11.7(@types/react@19.2.14)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@mux/mux-player-react': 3.11.7(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
'@portabletext/block-tools': 1.1.38(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@types/react@19.2.14)
|
'@portabletext/block-tools': 1.1.38(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@types/react@19.2.14)
|
||||||
'@portabletext/editor': 1.58.1(@sanity/schema@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@types/react@19.2.14)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rxjs@7.8.2)
|
'@portabletext/editor': 1.58.1(@sanity/schema@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)
|
||||||
'@portabletext/react': 3.2.4(react@18.3.1)
|
'@portabletext/react': 3.2.4(react@19.2.4)
|
||||||
'@portabletext/toolkit': 2.0.18
|
'@portabletext/toolkit': 2.0.18
|
||||||
'@rexxars/react-json-inspector': 9.0.1(react@18.3.1)
|
'@rexxars/react-json-inspector': 9.0.1(react@19.2.4)
|
||||||
'@sanity/asset-utils': 2.3.0
|
'@sanity/asset-utils': 2.3.0
|
||||||
'@sanity/bifur-client': 0.4.1
|
'@sanity/bifur-client': 0.4.1
|
||||||
'@sanity/cli': 3.99.0(@types/node@25.5.0)(@types/react@19.2.14)(react@18.3.1)(typescript@5.9.3)(yaml@2.8.3)
|
'@sanity/cli': 3.99.0(@types/node@25.5.0)(@types/react@19.2.14)(react@19.2.4)(typescript@5.9.3)(yaml@2.8.3)
|
||||||
'@sanity/client': 7.20.0(debug@4.4.3)
|
'@sanity/client': 7.20.0(debug@4.4.3)
|
||||||
'@sanity/color': 3.0.6
|
'@sanity/color': 3.0.6
|
||||||
'@sanity/comlink': 3.1.1
|
'@sanity/comlink': 3.1.1
|
||||||
@ -10585,28 +10592,28 @@ snapshots:
|
|||||||
'@sanity/diff-patch': 5.0.0
|
'@sanity/diff-patch': 5.0.0
|
||||||
'@sanity/eventsource': 5.0.2
|
'@sanity/eventsource': 5.0.2
|
||||||
'@sanity/export': 3.45.3(@types/react@19.2.14)
|
'@sanity/export': 3.45.3(@types/react@19.2.14)
|
||||||
'@sanity/icons': 3.7.4(react@18.3.1)
|
'@sanity/icons': 3.7.4(react@19.2.4)
|
||||||
'@sanity/id-utils': 1.0.0
|
'@sanity/id-utils': 1.0.0
|
||||||
'@sanity/image-url': 1.2.0
|
'@sanity/image-url': 1.2.0
|
||||||
'@sanity/import': 3.38.3(@types/react@19.2.14)
|
'@sanity/import': 3.38.3(@types/react@19.2.14)
|
||||||
'@sanity/insert-menu': 1.1.13(@emotion/is-prop-valid@1.4.0)(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
'@sanity/insert-menu': 1.1.13(@emotion/is-prop-valid@1.4.0)(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))(react-dom@19.2.4(react@19.2.4))(react-is@18.3.1)(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))
|
||||||
'@sanity/logos': 2.2.2(react@18.3.1)
|
'@sanity/logos': 2.2.2(react@19.2.4)
|
||||||
'@sanity/media-library-types': 1.2.0
|
'@sanity/media-library-types': 1.2.0
|
||||||
'@sanity/message-protocol': 0.13.3
|
'@sanity/message-protocol': 0.13.3
|
||||||
'@sanity/migrate': 3.99.0(@types/react@19.2.14)
|
'@sanity/migrate': 3.99.0(@types/react@19.2.14)
|
||||||
'@sanity/mutator': 3.99.0(@types/react@19.2.14)
|
'@sanity/mutator': 3.99.0(@types/react@19.2.14)
|
||||||
'@sanity/presentation-comlink': 1.0.33(@sanity/client@7.20.0(debug@4.4.3))(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))
|
'@sanity/presentation-comlink': 1.0.33(@sanity/client@7.20.0(debug@4.4.3))(@sanity/types@3.99.0(@types/react@19.2.14)(debug@4.4.3))
|
||||||
'@sanity/preview-url-secret': 2.1.16(@sanity/client@7.20.0(debug@4.4.3))(@sanity/icons@3.7.4(react@18.3.1))(sanity@3.99.0(@emotion/is-prop-valid@1.4.0)(@types/node@25.5.0)(@types/react@19.2.14)(immer@10.2.0)(jiti@2.6.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.9.3)(yaml@2.8.3))
|
'@sanity/preview-url-secret': 2.1.16(@sanity/client@7.20.0(debug@4.4.3))(@sanity/icons@3.7.4(react@19.2.4))(sanity@3.99.0(@emotion/is-prop-valid@1.4.0)(@types/node@25.5.0)(@types/react@19.2.14)(immer@10.2.0)(jiti@2.6.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(yaml@2.8.3))
|
||||||
'@sanity/schema': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
'@sanity/schema': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
||||||
'@sanity/sdk': 0.0.0-alpha.25(@types/react@19.2.14)(debug@4.4.3)(immer@10.2.0)(react@18.3.1)(use-sync-external-store@1.6.0(react@18.3.1))
|
'@sanity/sdk': 0.0.0-alpha.25(@types/react@19.2.14)(debug@4.4.3)(immer@10.2.0)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4))
|
||||||
'@sanity/telemetry': 0.8.1(react@18.3.1)
|
'@sanity/telemetry': 0.8.1(react@19.2.4)
|
||||||
'@sanity/types': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
'@sanity/types': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
||||||
'@sanity/ui': 2.16.22(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
'@sanity/ui': 2.16.22(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.4(react@19.2.4))(react-is@18.3.1)(react@19.2.4)(styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4))
|
||||||
'@sanity/util': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
'@sanity/util': 3.99.0(@types/react@19.2.14)(debug@4.4.3)
|
||||||
'@sanity/uuid': 3.0.2
|
'@sanity/uuid': 3.0.2
|
||||||
'@sentry/react': 8.55.1(react@18.3.1)
|
'@sentry/react': 8.55.1(react@19.2.4)
|
||||||
'@tanstack/react-table': 8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@tanstack/react-table': 8.21.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
'@tanstack/react-virtual': 3.13.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@tanstack/react-virtual': 3.13.23(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
'@types/react-is': 19.2.0
|
'@types/react-is': 19.2.0
|
||||||
'@types/shallow-equals': 1.0.3
|
'@types/shallow-equals': 1.0.3
|
||||||
'@types/speakingurl': 13.0.6
|
'@types/speakingurl': 13.0.6
|
||||||
@ -10614,7 +10621,7 @@ snapshots:
|
|||||||
'@types/use-sync-external-store': 1.5.0
|
'@types/use-sync-external-store': 1.5.0
|
||||||
'@types/which': 3.0.4
|
'@types/which': 3.0.4
|
||||||
'@vitejs/plugin-react': 4.7.0(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(yaml@2.8.3))
|
'@vitejs/plugin-react': 4.7.0(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(yaml@2.8.3))
|
||||||
'@xstate/react': 6.1.0(@types/react@19.2.14)(react@18.3.1)(xstate@5.30.0)
|
'@xstate/react': 6.1.0(@types/react@19.2.14)(react@19.2.4)(xstate@5.30.0)
|
||||||
archiver: 7.0.1
|
archiver: 7.0.1
|
||||||
arrify: 2.0.1
|
arrify: 2.0.1
|
||||||
async-mutex: 0.4.1
|
async-mutex: 0.4.1
|
||||||
@ -10633,7 +10640,7 @@ snapshots:
|
|||||||
exif-component: 1.0.1
|
exif-component: 1.0.1
|
||||||
fast-deep-equal: 3.1.3
|
fast-deep-equal: 3.1.3
|
||||||
form-data: 4.0.5
|
form-data: 4.0.5
|
||||||
framer-motion: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
framer-motion: 12.38.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
get-it: 8.7.0(debug@4.4.3)
|
get-it: 8.7.0(debug@4.4.3)
|
||||||
get-random-values-esm: 1.0.2
|
get-random-values-esm: 1.0.2
|
||||||
groq-js: 1.29.0
|
groq-js: 1.29.0
|
||||||
@ -10663,22 +10670,22 @@ snapshots:
|
|||||||
path-to-regexp: 6.3.0
|
path-to-regexp: 6.3.0
|
||||||
peek-stream: 1.1.3
|
peek-stream: 1.1.3
|
||||||
pirates: 4.0.7
|
pirates: 4.0.7
|
||||||
player.style: 0.1.10(react@18.3.1)
|
player.style: 0.1.10(react@19.2.4)
|
||||||
pluralize-esm: 9.0.5
|
pluralize-esm: 9.0.5
|
||||||
polished: 4.3.1
|
polished: 4.3.1
|
||||||
preferred-pm: 4.1.1
|
preferred-pm: 4.1.1
|
||||||
pretty-ms: 7.0.1
|
pretty-ms: 7.0.1
|
||||||
quick-lru: 5.1.1
|
quick-lru: 5.1.1
|
||||||
raf: 3.4.1
|
raf: 3.4.1
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-compiler-runtime: 19.1.0-rc.2(react@18.3.1)
|
react-compiler-runtime: 19.1.0-rc.2(react@19.2.4)
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
react-fast-compare: 3.2.2
|
react-fast-compare: 3.2.2
|
||||||
react-focus-lock: 2.13.7(@types/react@19.2.14)(react@18.3.1)
|
react-focus-lock: 2.13.7(@types/react@19.2.14)(react@19.2.4)
|
||||||
react-i18next: 14.0.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
react-i18next: 14.0.2(i18next@23.16.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
react-is: 18.3.1
|
react-is: 18.3.1
|
||||||
react-refractor: 2.2.0(react@18.3.1)
|
react-refractor: 2.2.0(react@19.2.4)
|
||||||
react-rx: 4.2.2(react@18.3.1)(rxjs@7.8.2)
|
react-rx: 4.2.2(react@19.2.4)(rxjs@7.8.2)
|
||||||
read-pkg-up: 7.0.1
|
read-pkg-up: 7.0.1
|
||||||
refractor: 3.6.0
|
refractor: 3.6.0
|
||||||
resolve-from: 5.0.0
|
resolve-from: 5.0.0
|
||||||
@ -10692,15 +10699,15 @@ snapshots:
|
|||||||
semver: 7.7.4
|
semver: 7.7.4
|
||||||
shallow-equals: 1.0.0
|
shallow-equals: 1.0.0
|
||||||
speakingurl: 14.0.1
|
speakingurl: 14.0.1
|
||||||
styled-components: 6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
styled-components: 6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
tar-fs: 2.1.4
|
tar-fs: 2.1.4
|
||||||
tar-stream: 3.1.8
|
tar-stream: 3.1.8
|
||||||
tinyglobby: 0.2.15
|
tinyglobby: 0.2.15
|
||||||
urlpattern-polyfill: 10.1.0
|
urlpattern-polyfill: 10.1.0
|
||||||
use-device-pixel-ratio: 1.1.2(react@18.3.1)
|
use-device-pixel-ratio: 1.1.2(react@19.2.4)
|
||||||
use-effect-event: 2.0.3(react@18.3.1)
|
use-effect-event: 2.0.3(react@19.2.4)
|
||||||
use-hot-module-reload: 2.0.0(react@18.3.1)
|
use-hot-module-reload: 2.0.0(react@19.2.4)
|
||||||
use-sync-external-store: 1.6.0(react@18.3.1)
|
use-sync-external-store: 1.6.0(react@19.2.4)
|
||||||
uuid: 11.1.0
|
uuid: 11.1.0
|
||||||
vite: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(yaml@2.8.3)
|
vite: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(yaml@2.8.3)
|
||||||
which: 5.0.0
|
which: 5.0.0
|
||||||
@ -10737,9 +10744,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
xmlchars: 2.2.0
|
xmlchars: 2.2.0
|
||||||
|
|
||||||
scheduler@0.23.2:
|
scheduler@0.27.0: {}
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
|
|
||||||
scroll-into-view-if-needed@3.1.0:
|
scroll-into-view-if-needed@3.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -10846,14 +10851,14 @@ snapshots:
|
|||||||
slate: 0.117.2
|
slate: 0.117.2
|
||||||
tiny-invariant: 1.3.1
|
tiny-invariant: 1.3.1
|
||||||
|
|
||||||
slate-react@0.117.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate-dom@0.116.0(slate@0.117.2))(slate@0.117.2):
|
slate-react@0.117.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(slate-dom@0.116.0(slate@0.117.2))(slate@0.117.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@juggle/resize-observer': 3.4.0
|
'@juggle/resize-observer': 3.4.0
|
||||||
direction: 1.0.4
|
direction: 1.0.4
|
||||||
is-hotkey: 0.2.0
|
is-hotkey: 0.2.0
|
||||||
lodash: 4.17.23
|
lodash: 4.17.23
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
scroll-into-view-if-needed: 3.1.0
|
scroll-into-view-if-needed: 3.1.0
|
||||||
slate: 0.117.2
|
slate: 0.117.2
|
||||||
slate-dom: 0.116.0(slate@0.117.2)
|
slate-dom: 0.116.0(slate@0.117.2)
|
||||||
@ -11020,7 +11025,7 @@ snapshots:
|
|||||||
|
|
||||||
style-mod@4.1.3: {}
|
style-mod@4.1.3: {}
|
||||||
|
|
||||||
styled-components@6.3.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
styled-components@6.3.12(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@emotion/is-prop-valid': 1.4.0
|
'@emotion/is-prop-valid': 1.4.0
|
||||||
'@emotion/unitless': 0.10.0
|
'@emotion/unitless': 0.10.0
|
||||||
@ -11028,12 +11033,12 @@ snapshots:
|
|||||||
css-to-react-native: 3.2.0
|
css-to-react-native: 3.2.0
|
||||||
csstype: 3.2.3
|
csstype: 3.2.3
|
||||||
postcss: 8.4.49
|
postcss: 8.4.49
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
shallowequal: 1.1.0
|
shallowequal: 1.1.0
|
||||||
stylis: 4.3.6
|
stylis: 4.3.6
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 19.2.4(react@19.2.4)
|
||||||
|
|
||||||
stylis@4.3.6: {}
|
stylis@4.3.6: {}
|
||||||
|
|
||||||
@ -11326,46 +11331,46 @@ snapshots:
|
|||||||
|
|
||||||
urlpattern-polyfill@10.1.0: {}
|
urlpattern-polyfill@10.1.0: {}
|
||||||
|
|
||||||
use-callback-ref@1.3.3(@types/react@19.2.14)(react@18.3.1):
|
use-callback-ref@1.3.3(@types/react@19.2.14)(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.14
|
'@types/react': 19.2.14
|
||||||
|
|
||||||
use-device-pixel-ratio@1.1.2(react@18.3.1):
|
use-device-pixel-ratio@1.1.2(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
use-effect-event@1.0.2(react@18.3.1):
|
use-effect-event@1.0.2(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
use-effect-event@2.0.3(react@18.3.1):
|
use-effect-event@2.0.3(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
use-hot-module-reload@2.0.0(react@18.3.1):
|
use-hot-module-reload@2.0.0(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
use-isomorphic-layout-effect@1.2.1(@types/react@19.2.14)(react@18.3.1):
|
use-isomorphic-layout-effect@1.2.1(@types/react@19.2.14)(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.14
|
'@types/react': 19.2.14
|
||||||
|
|
||||||
use-sidecar@1.1.3(@types/react@19.2.14)(react@18.3.1):
|
use-sidecar@1.1.3(@types/react@19.2.14)(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
detect-node-es: 1.1.0
|
detect-node-es: 1.1.0
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.14
|
'@types/react': 19.2.14
|
||||||
|
|
||||||
use-sync-external-store@1.6.0(react@18.3.1):
|
use-sync-external-store@1.6.0(react@19.2.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
@ -11593,9 +11598,9 @@ snapshots:
|
|||||||
|
|
||||||
zod@3.25.76: {}
|
zod@3.25.76: {}
|
||||||
|
|
||||||
zustand@5.0.12(@types/react@19.2.14)(immer@10.2.0)(react@18.3.1)(use-sync-external-store@1.6.0(react@18.3.1)):
|
zustand@5.0.12(@types/react@19.2.14)(immer@10.2.0)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.14
|
'@types/react': 19.2.14
|
||||||
immer: 10.2.0
|
immer: 10.2.0
|
||||||
react: 18.3.1
|
react: 19.2.4
|
||||||
use-sync-external-store: 1.6.0(react@18.3.1)
|
use-sync-external-store: 1.6.0(react@19.2.4)
|
||||||
|
|||||||
@ -9,6 +9,25 @@ export default defineConfig({
|
|||||||
projectId: 'y821x5qu',
|
projectId: 'y821x5qu',
|
||||||
dataset: 'production',
|
dataset: 'production',
|
||||||
|
|
||||||
plugins: [structureTool()],
|
plugins: [
|
||||||
|
structureTool({
|
||||||
|
structure: (S) =>
|
||||||
|
S.list()
|
||||||
|
.title('Contenu')
|
||||||
|
.items([
|
||||||
|
S.listItem()
|
||||||
|
.title('Page d\'accueil')
|
||||||
|
.id('homePage')
|
||||||
|
.child(
|
||||||
|
S.document()
|
||||||
|
.schemaType('homePage')
|
||||||
|
.documentId('homePage')
|
||||||
|
.title('Page d\'accueil')
|
||||||
|
),
|
||||||
|
S.divider(),
|
||||||
|
S.documentTypeListItem('product').title('Produits'),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
],
|
||||||
schema: { types: schemaTypes },
|
schema: { types: schemaTypes },
|
||||||
})
|
})
|
||||||
|
|||||||
167
sanity/schemas/homePage.ts
Normal file
167
sanity/schemas/homePage.ts
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
import { defineType, defineField } from 'sanity'
|
||||||
|
|
||||||
|
export default defineType({
|
||||||
|
name: 'homePage',
|
||||||
|
title: 'Page d\'accueil',
|
||||||
|
type: 'document',
|
||||||
|
groups: [
|
||||||
|
{ name: 'hero', title: 'Hero' },
|
||||||
|
{ name: 'collection', title: 'Collection' },
|
||||||
|
{ name: 'contact', title: 'Contact / WhatsApp' },
|
||||||
|
{ name: 'footer', title: 'Footer' },
|
||||||
|
{ name: 'seo', title: 'SEO' },
|
||||||
|
],
|
||||||
|
fields: [
|
||||||
|
// ── HERO ──────────────────────────────────────────────────
|
||||||
|
defineField({
|
||||||
|
name: 'heroLabel',
|
||||||
|
title: 'Label hero',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: '// ARCHIVE_001 — 2026',
|
||||||
|
group: 'hero',
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'heroTitle',
|
||||||
|
title: 'Titre hero',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: 'REBOURS STUDIO',
|
||||||
|
description: 'Utiliser | pour un retour à la ligne (ex: REBOURS|STUDIO)',
|
||||||
|
group: 'hero',
|
||||||
|
validation: (rule) => rule.required(),
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'heroSubtitle',
|
||||||
|
title: 'Sous-titre hero',
|
||||||
|
type: 'text',
|
||||||
|
rows: 2,
|
||||||
|
initialValue: 'Mobilier d\'art contemporain.\nSpace Age × Memphis.',
|
||||||
|
group: 'hero',
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'heroStatus',
|
||||||
|
title: 'Status hero',
|
||||||
|
type: 'text',
|
||||||
|
rows: 2,
|
||||||
|
initialValue: 'STATUS: [PROTOTYPE EN COURS]\nCOLLECTION_001 — BIENTÔT DISPONIBLE',
|
||||||
|
group: 'hero',
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'heroImage',
|
||||||
|
title: 'Image hero',
|
||||||
|
type: 'image',
|
||||||
|
options: { hotspot: true },
|
||||||
|
description: 'Image principale du hero. Si vide, utilise l\'image du premier produit.',
|
||||||
|
group: 'hero',
|
||||||
|
fields: [
|
||||||
|
defineField({
|
||||||
|
name: 'alt',
|
||||||
|
title: 'Texte alternatif',
|
||||||
|
type: 'string',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
|
||||||
|
// ── COLLECTION ────────────────────────────────────────────
|
||||||
|
defineField({
|
||||||
|
name: 'collectionLabel',
|
||||||
|
title: 'Label collection',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: '// COLLECTION_001',
|
||||||
|
group: 'collection',
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'collectionCta',
|
||||||
|
title: 'Texte d\'action collection',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: 'CLIQUER POUR OUVRIR',
|
||||||
|
description: 'Affiché après le nombre d\'objets',
|
||||||
|
group: 'collection',
|
||||||
|
}),
|
||||||
|
|
||||||
|
// ── CONTACT / WHATSAPP ────────────────────────────────────
|
||||||
|
defineField({
|
||||||
|
name: 'contactLabel',
|
||||||
|
title: 'Label contact',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: '// CONTACT',
|
||||||
|
group: 'contact',
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'contactTitle',
|
||||||
|
title: 'Titre contact',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: 'UNE QUESTION ? PARLONS-EN',
|
||||||
|
description: 'Utiliser | pour un retour à la ligne',
|
||||||
|
group: 'contact',
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'contactDescription',
|
||||||
|
title: 'Description contact',
|
||||||
|
type: 'text',
|
||||||
|
rows: 2,
|
||||||
|
initialValue: 'Commandes sur mesure, questions techniques,\nou simplement dire bonjour.',
|
||||||
|
group: 'contact',
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'whatsappNumber',
|
||||||
|
title: 'Numéro WhatsApp',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: '33651755191',
|
||||||
|
description: 'Format international sans + (ex: 33612345678)',
|
||||||
|
group: 'contact',
|
||||||
|
validation: (rule) => rule.required(),
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'whatsappButtonText',
|
||||||
|
title: 'Texte bouton WhatsApp',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: 'CONTACTEZ-NOUS SUR WHATSAPP',
|
||||||
|
group: 'contact',
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'contactResponseTime',
|
||||||
|
title: 'Temps de réponse',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: 'RÉPONSE SOUS 24H',
|
||||||
|
group: 'contact',
|
||||||
|
}),
|
||||||
|
|
||||||
|
// ── FOOTER ────────────────────────────────────────────────
|
||||||
|
defineField({
|
||||||
|
name: 'footerText',
|
||||||
|
title: 'Texte footer',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: '© 2026 REBOURS STUDIO — PARIS',
|
||||||
|
group: 'footer',
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'instagramUrl',
|
||||||
|
title: 'Lien Instagram',
|
||||||
|
type: 'url',
|
||||||
|
initialValue: 'https://instagram.com/rebour.studio',
|
||||||
|
group: 'footer',
|
||||||
|
}),
|
||||||
|
|
||||||
|
// ── SEO ───────────────────────────────────────────────────
|
||||||
|
defineField({
|
||||||
|
name: 'seoTitle',
|
||||||
|
title: 'Titre SEO',
|
||||||
|
type: 'string',
|
||||||
|
initialValue: 'REBOURS — Mobilier d\'art contemporain | Collection 001',
|
||||||
|
group: 'seo',
|
||||||
|
}),
|
||||||
|
defineField({
|
||||||
|
name: 'seoDescription',
|
||||||
|
title: 'Description SEO',
|
||||||
|
type: 'text',
|
||||||
|
rows: 3,
|
||||||
|
initialValue: 'REBOURS Studio crée du mobilier d\'art contemporain inspiré du Space Age et du mouvement Memphis. Pièces uniques fabriquées à Paris. Collection 001 en cours.',
|
||||||
|
group: 'seo',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
preview: {
|
||||||
|
prepare() {
|
||||||
|
return { title: 'Page d\'accueil' }
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
@ -1,3 +1,4 @@
|
|||||||
import product from './product'
|
import product from './product'
|
||||||
|
import homePage from './homePage'
|
||||||
|
|
||||||
export const schemaTypes = [product]
|
export const schemaTypes = [product, homePage]
|
||||||
|
|||||||
@ -103,18 +103,24 @@ export default defineType({
|
|||||||
rows: 4,
|
rows: 4,
|
||||||
}),
|
}),
|
||||||
defineField({
|
defineField({
|
||||||
name: 'image',
|
name: 'images',
|
||||||
title: 'Image produit',
|
title: 'Images produit',
|
||||||
type: 'image',
|
type: 'array',
|
||||||
options: { hotspot: true },
|
description: 'La première image est utilisée comme image principale',
|
||||||
validation: (rule) => rule.required(),
|
validation: (rule) => rule.required().min(1),
|
||||||
fields: [
|
of: [
|
||||||
defineField({
|
{
|
||||||
name: 'alt',
|
type: 'image',
|
||||||
title: 'Texte alternatif',
|
options: { hotspot: true },
|
||||||
type: 'string',
|
fields: [
|
||||||
description: 'Description de l\'image pour le SEO et l\'accessibilité',
|
defineField({
|
||||||
}),
|
name: 'alt',
|
||||||
|
title: 'Texte alternatif',
|
||||||
|
type: 'string',
|
||||||
|
description: 'Description de l\'image pour le SEO et l\'accessibilité',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
defineField({
|
defineField({
|
||||||
@ -174,7 +180,7 @@ export default defineType({
|
|||||||
select: {
|
select: {
|
||||||
title: 'productDisplayName',
|
title: 'productDisplayName',
|
||||||
subtitle: 'type',
|
subtitle: 'type',
|
||||||
media: 'image',
|
media: 'images.0',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
54
seed-sanity-homepage.mjs
Normal file
54
seed-sanity-homepage.mjs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { createClient } from '@sanity/client'
|
||||||
|
import dotenv from 'dotenv'
|
||||||
|
|
||||||
|
dotenv.config()
|
||||||
|
|
||||||
|
const client = createClient({
|
||||||
|
projectId: process.env.SANITY_PROJECT_ID,
|
||||||
|
dataset: process.env.SANITY_DATASET || 'production',
|
||||||
|
apiVersion: '2024-01-01',
|
||||||
|
useCdn: false,
|
||||||
|
token: process.env.SANITY_API_TOKEN,
|
||||||
|
})
|
||||||
|
|
||||||
|
const homePage = {
|
||||||
|
_id: 'homePage',
|
||||||
|
_type: 'homePage',
|
||||||
|
|
||||||
|
// Hero
|
||||||
|
heroLabel: '// ARCHIVE_001 — 2026',
|
||||||
|
heroTitle: 'REBOURS|STUDIO',
|
||||||
|
heroSubtitle: 'Mobilier d\'art contemporain.\nSpace Age × Memphis.',
|
||||||
|
heroStatus: 'STATUS: [PROTOTYPE EN COURS]\nCOLLECTION_001 — BIENTÔT DISPONIBLE',
|
||||||
|
|
||||||
|
// Collection
|
||||||
|
collectionLabel: '// COLLECTION_001',
|
||||||
|
collectionCta: 'CLIQUER POUR OUVRIR',
|
||||||
|
|
||||||
|
// Contact / WhatsApp
|
||||||
|
contactLabel: '// CONTACT',
|
||||||
|
contactTitle: 'UNE QUESTION ?|PARLONS-EN',
|
||||||
|
contactDescription: 'Commandes sur mesure, questions techniques,\nou simplement dire bonjour.',
|
||||||
|
whatsappNumber: '33651755191',
|
||||||
|
whatsappButtonText: 'CONTACTEZ-NOUS SUR WHATSAPP',
|
||||||
|
contactResponseTime: 'RÉPONSE SOUS 24H',
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
footerText: '© 2026 REBOURS STUDIO — PARIS',
|
||||||
|
instagramUrl: 'https://instagram.com/rebour.studio',
|
||||||
|
|
||||||
|
// SEO
|
||||||
|
seoTitle: 'REBOURS — Mobilier d\'art contemporain | Collection 001',
|
||||||
|
seoDescription: 'REBOURS Studio crée du mobilier d\'art contemporain inspiré du Space Age et du mouvement Memphis. Pièces uniques fabriquées à Paris. Collection 001 en cours.',
|
||||||
|
}
|
||||||
|
|
||||||
|
async function seed() {
|
||||||
|
console.log('Creating homePage document...')
|
||||||
|
const result = await client.createOrReplace(homePage)
|
||||||
|
console.log(`✓ homePage created: ${result._id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
seed().catch((err) => {
|
||||||
|
console.error('Error:', err.message)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
@ -71,7 +71,7 @@ app.post('/api/checkout', async (request, reply) => {
|
|||||||
description,
|
description,
|
||||||
price,
|
price,
|
||||||
currency,
|
currency,
|
||||||
"imageUrl": image.asset->url,
|
"imageUrl": images[0].asset->url,
|
||||||
"slug": slug.current
|
"slug": slug.current
|
||||||
}`,
|
}`,
|
||||||
{ slug }
|
{ slug }
|
||||||
@ -131,7 +131,7 @@ app.get('/api/session/:id', async (request) => {
|
|||||||
|
|
||||||
// ── Start ───────────────────────────────────────────────────────────────────
|
// ── Start ───────────────────────────────────────────────────────────────────
|
||||||
try {
|
try {
|
||||||
await app.listen({ port: process.env.PORT ?? 3000, host: '0.0.0.0' })
|
await app.listen({ port: process.env.FASTIFY_PORT ?? process.env.PORT ?? 3000, host: '0.0.0.0' })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
app.log.error(err)
|
app.log.error(err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
|
|||||||
@ -12,6 +12,8 @@ const {
|
|||||||
ogImage = 'https://rebours.studio/assets/lamp-violet.jpg',
|
ogImage = 'https://rebours.studio/assets/lamp-violet.jpg',
|
||||||
canonical = 'https://rebours.studio/',
|
canonical = 'https://rebours.studio/',
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
|
|
||||||
|
const cssVersion = Date.now();
|
||||||
---
|
---
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@ -56,7 +58,7 @@ const {
|
|||||||
|
|
||||||
<slot name="head" />
|
<slot name="head" />
|
||||||
|
|
||||||
<link rel="stylesheet" href="/style.css">
|
<link rel="stylesheet" href={`/style.css?v=${cssVersion}`}>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<slot />
|
<slot />
|
||||||
|
|||||||
@ -5,7 +5,7 @@ export const sanity = createClient({
|
|||||||
projectId: import.meta.env.SANITY_PROJECT_ID,
|
projectId: import.meta.env.SANITY_PROJECT_ID,
|
||||||
dataset: import.meta.env.SANITY_DATASET || 'production',
|
dataset: import.meta.env.SANITY_DATASET || 'production',
|
||||||
apiVersion: '2024-01-01',
|
apiVersion: '2024-01-01',
|
||||||
useCdn: true,
|
useCdn: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const builder = imageUrlBuilder(sanity)
|
const builder = imageUrlBuilder(sanity)
|
||||||
@ -29,8 +29,8 @@ const PRODUCT_FIELDS = `
|
|||||||
description,
|
description,
|
||||||
specs,
|
specs,
|
||||||
notes,
|
notes,
|
||||||
image,
|
images,
|
||||||
"imageAlt": image.alt,
|
"imageAlt": images[0].alt,
|
||||||
seoTitle,
|
seoTitle,
|
||||||
seoDescription,
|
seoDescription,
|
||||||
price,
|
price,
|
||||||
@ -51,3 +51,28 @@ export async function getProductBySlug(slug) {
|
|||||||
{ slug }
|
{ slug }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getHomePage() {
|
||||||
|
return sanity.fetch(
|
||||||
|
`*[_type == "homePage" && _id == "homePage"][0] {
|
||||||
|
heroLabel,
|
||||||
|
heroTitle,
|
||||||
|
heroSubtitle,
|
||||||
|
heroStatus,
|
||||||
|
heroImage,
|
||||||
|
"heroImageAlt": heroImage.alt,
|
||||||
|
collectionLabel,
|
||||||
|
collectionCta,
|
||||||
|
contactLabel,
|
||||||
|
contactTitle,
|
||||||
|
contactDescription,
|
||||||
|
whatsappNumber,
|
||||||
|
whatsappButtonText,
|
||||||
|
contactResponseTime,
|
||||||
|
footerText,
|
||||||
|
instagramUrl,
|
||||||
|
seoTitle,
|
||||||
|
seoDescription
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@ -1,26 +1,21 @@
|
|||||||
---
|
---
|
||||||
import Base from '../../layouts/Base.astro';
|
import Base from '../../layouts/Base.astro';
|
||||||
import { getPublishedProducts, urlFor } from '../../lib/sanity.mjs';
|
import { getPublishedProducts, getProductBySlug, urlFor } from '../../lib/sanity.mjs';
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
const { slug } = Astro.params;
|
||||||
const products = await getPublishedProducts();
|
const product = await getProductBySlug(slug);
|
||||||
|
|
||||||
return products.map(p => ({
|
if (!product) {
|
||||||
params: { slug: p.slug },
|
return Astro.redirect('/');
|
||||||
props: {
|
|
||||||
slug: p.slug,
|
|
||||||
name: p.name,
|
|
||||||
title: p.seoTitle || `REBOURS — ${p.productDisplayName} | Collection 001`,
|
|
||||||
description: p.seoDescription || p.description?.substring(0, 155) || '',
|
|
||||||
ogImage: p.image ? urlFor(p.image).width(1200).url() : '',
|
|
||||||
productName: p.productDisplayName,
|
|
||||||
price: p.price ? String(p.price / 100) : null,
|
|
||||||
availability: p.availability || 'https://schema.org/PreOrder',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { slug, title, description, ogImage, name, productName, price, availability } = Astro.props;
|
const name = product.name;
|
||||||
|
const title = product.seoTitle || `REBOURS — ${product.productDisplayName} | Collection 001`;
|
||||||
|
const description = product.seoDescription || product.description?.substring(0, 155) || '';
|
||||||
|
const ogImage = product.images?.[0] ? urlFor(product.images[0]).width(1200).url() : '';
|
||||||
|
const productName = product.productDisplayName;
|
||||||
|
const price = product.price ? String(product.price / 100) : null;
|
||||||
|
const availability = product.availability || 'https://schema.org/PreOrder';
|
||||||
|
|
||||||
const allProducts = await getPublishedProducts();
|
const allProducts = await getPublishedProducts();
|
||||||
|
|
||||||
@ -81,7 +76,10 @@ const schemaBreadcrumb = {
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel-inner">
|
<div class="panel-inner">
|
||||||
<div class="panel-img-col">
|
<div class="panel-img-col">
|
||||||
<img id="panel-img" src="" alt="Image produit REBOURS Studio">
|
<div class="panel-gallery" id="panel-gallery">
|
||||||
|
<img id="panel-img" src="" alt="Image produit REBOURS Studio">
|
||||||
|
</div>
|
||||||
|
<div class="panel-gallery-nav" id="panel-gallery-nav"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-info-col">
|
<div class="panel-info-col">
|
||||||
<p class="panel-index" id="panel-index"></p>
|
<p class="panel-index" id="panel-index"></p>
|
||||||
@ -109,11 +107,11 @@ const schemaBreadcrumb = {
|
|||||||
<p id="panel-desc" class="panel-desc"></p>
|
<p id="panel-desc" class="panel-desc"></p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<details class="accordion">
|
<details class="accordion" open>
|
||||||
<summary>SPÉCIFICATIONS TECHNIQUES <span>↓</span></summary>
|
<summary>SPÉCIFICATIONS TECHNIQUES <span>↓</span></summary>
|
||||||
<div class="accordion-body" id="panel-specs"></div>
|
<div class="accordion-body" id="panel-specs"></div>
|
||||||
</details>
|
</details>
|
||||||
<details class="accordion">
|
<details class="accordion" open>
|
||||||
<summary>NOTES DE CONCEPTION <span>↓</span></summary>
|
<summary>NOTES DE CONCEPTION <span>↓</span></summary>
|
||||||
<div class="accordion-body" id="panel-notes"></div>
|
<div class="accordion-body" id="panel-notes"></div>
|
||||||
</details>
|
</details>
|
||||||
@ -173,9 +171,9 @@ const schemaBreadcrumb = {
|
|||||||
<p class="hero-sub mono-sm">STATUS: [PROTOTYPE EN COURS]<br>COLLECTION_001 — BIENTÔT DISPONIBLE</p>
|
<p class="hero-sub mono-sm">STATUS: [PROTOTYPE EN COURS]<br>COLLECTION_001 — BIENTÔT DISPONIBLE</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="hero-right">
|
<div class="hero-right">
|
||||||
{allProducts[0]?.image && (
|
{allProducts[0]?.images?.[0] && (
|
||||||
<img
|
<img
|
||||||
src={urlFor(allProducts[0].image).width(1024).url()}
|
src={urlFor(allProducts[0].images[0]).width(1024).url()}
|
||||||
alt="REBOURS — Mobilier d'art contemporain, Paris 2026"
|
alt="REBOURS — Mobilier d'art contemporain, Paris 2026"
|
||||||
class="hero-img"
|
class="hero-img"
|
||||||
width="1024" height="1024"
|
width="1024" height="1024"
|
||||||
@ -194,8 +192,13 @@ const schemaBreadcrumb = {
|
|||||||
|
|
||||||
<div class="product-grid">
|
<div class="product-grid">
|
||||||
{allProducts.map((p, i) => {
|
{allProducts.map((p, i) => {
|
||||||
const imgUrl = p.image ? urlFor(p.image).width(800).url() : '';
|
const mainImg = p.images?.[0];
|
||||||
|
const imgUrl = mainImg ? urlFor(mainImg).width(800).url() : '';
|
||||||
const alt = p.imageAlt || `${p.productDisplayName} — mobilier d'art contemporain, REBOURS Studio Paris`;
|
const alt = p.imageAlt || `${p.productDisplayName} — mobilier d'art contemporain, REBOURS Studio Paris`;
|
||||||
|
const allImgs = (p.images || []).map(img => ({
|
||||||
|
url: urlFor(img).width(1200).url(),
|
||||||
|
alt: img.alt || alt,
|
||||||
|
}));
|
||||||
return (
|
return (
|
||||||
<article class="product-card"
|
<article class="product-card"
|
||||||
data-index={p.index}
|
data-index={p.index}
|
||||||
@ -207,7 +210,8 @@ const schemaBreadcrumb = {
|
|||||||
data-desc={p.description}
|
data-desc={p.description}
|
||||||
data-specs={p.specs || ''}
|
data-specs={p.specs || ''}
|
||||||
data-notes={p.notes || ''}
|
data-notes={p.notes || ''}
|
||||||
data-img={p.image ? urlFor(p.image).width(1200).url() : ''}
|
data-img={mainImg ? urlFor(mainImg).width(1200).url() : ''}
|
||||||
|
data-images={JSON.stringify(allImgs)}
|
||||||
data-price={p.price ? String(p.price) : ''}
|
data-price={p.price ? String(p.price) : ''}
|
||||||
data-slug={p.slug}
|
data-slug={p.slug}
|
||||||
data-img-alt={alt}
|
data-img-alt={alt}
|
||||||
|
|||||||
@ -1,12 +1,38 @@
|
|||||||
---
|
---
|
||||||
import Base from '../layouts/Base.astro';
|
import Base from '../layouts/Base.astro';
|
||||||
import { getPublishedProducts, urlFor } from '../lib/sanity.mjs';
|
import { getPublishedProducts, getHomePage, urlFor } from '../lib/sanity.mjs';
|
||||||
|
|
||||||
const products = await getPublishedProducts();
|
const [products, home] = await Promise.all([getPublishedProducts(), getHomePage()]);
|
||||||
|
|
||||||
const firstImage = products[0]?.image
|
const heroImg = home?.heroImage
|
||||||
? urlFor(products[0].image).width(1024).url()
|
? urlFor(home.heroImage).width(1024).url()
|
||||||
: '/assets/table-terrazzo.jpg';
|
: products[0]?.images?.[0]
|
||||||
|
? urlFor(products[0].images[0]).width(1024).url()
|
||||||
|
: '/assets/table-terrazzo.jpg';
|
||||||
|
const heroImgAlt = home?.heroImageAlt || 'REBOURS — Mobilier d\'art contemporain, Paris 2026';
|
||||||
|
|
||||||
|
const heroLabel = home?.heroLabel || '// ARCHIVE_001 — 2026';
|
||||||
|
const heroTitleParts = (home?.heroTitle || 'REBOURS|STUDIO').split('|');
|
||||||
|
const heroSubtitle = home?.heroSubtitle || 'Mobilier d\'art contemporain.\nSpace Age × Memphis.';
|
||||||
|
const heroStatus = home?.heroStatus || 'STATUS: [PROTOTYPE EN COURS]\nCOLLECTION_001 — BIENTÔT DISPONIBLE';
|
||||||
|
|
||||||
|
const collectionLabel = home?.collectionLabel || '// COLLECTION_001';
|
||||||
|
const collectionCta = home?.collectionCta || 'CLIQUER POUR OUVRIR';
|
||||||
|
|
||||||
|
const contactLabel = home?.contactLabel || '// CONTACT';
|
||||||
|
const contactTitleParts = (home?.contactTitle || 'UNE QUESTION ?|PARLONS-EN').split('|');
|
||||||
|
const contactDesc = home?.contactDescription || 'Commandes sur mesure, questions techniques,\nou simplement dire bonjour.';
|
||||||
|
const whatsappNumber = home?.whatsappNumber || '33651755191';
|
||||||
|
const whatsappBtnText = home?.whatsappButtonText || 'CONTACTEZ-NOUS SUR WHATSAPP';
|
||||||
|
const contactResponseTime = home?.contactResponseTime || 'RÉPONSE SOUS 24H';
|
||||||
|
|
||||||
|
const footerText = home?.footerText || '© 2026 REBOURS STUDIO — PARIS';
|
||||||
|
const instagramUrl = home?.instagramUrl || 'https://instagram.com/rebour.studio';
|
||||||
|
|
||||||
|
const seoTitle = home?.seoTitle || 'REBOURS — Mobilier d\'art contemporain | Collection 001';
|
||||||
|
const seoDesc = home?.seoDescription || 'REBOURS Studio crée du mobilier d\'art contemporain inspiré du Space Age et du mouvement Memphis. Pièces uniques fabriquées à Paris. Collection 001 en cours.';
|
||||||
|
|
||||||
|
const firstImage = heroImg;
|
||||||
|
|
||||||
const schemaOrg = {
|
const schemaOrg = {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
@ -25,7 +51,7 @@ const schemaOrg = {
|
|||||||
"@type": "Product",
|
"@type": "Product",
|
||||||
"name": p.productDisplayName,
|
"name": p.productDisplayName,
|
||||||
"description": p.seoDescription || p.description?.substring(0, 155),
|
"description": p.seoDescription || p.description?.substring(0, 155),
|
||||||
"image": p.image ? urlFor(p.image).width(1024).url() : undefined,
|
"image": p.images?.[0] ? urlFor(p.images[0]).width(1024).url() : undefined,
|
||||||
},
|
},
|
||||||
"price": String(p.price / 100),
|
"price": String(p.price / 100),
|
||||||
"priceCurrency": p.currency || 'EUR',
|
"priceCurrency": p.currency || 'EUR',
|
||||||
@ -36,8 +62,8 @@ const schemaOrg = {
|
|||||||
---
|
---
|
||||||
|
|
||||||
<Base
|
<Base
|
||||||
title="REBOURS — Mobilier d'art contemporain | Collection 001"
|
title={seoTitle}
|
||||||
description="REBOURS Studio crée du mobilier d'art contemporain inspiré du Space Age et du mouvement Memphis. Pièces uniques fabriquées à Paris. Collection 001 en cours."
|
description={seoDesc}
|
||||||
canonical="https://rebours.studio/"
|
canonical="https://rebours.studio/"
|
||||||
>
|
>
|
||||||
<Fragment slot="head">
|
<Fragment slot="head">
|
||||||
@ -54,7 +80,10 @@ const schemaOrg = {
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel-inner">
|
<div class="panel-inner">
|
||||||
<div class="panel-img-col">
|
<div class="panel-img-col">
|
||||||
<img id="panel-img" src="" alt="Image produit REBOURS Studio">
|
<div class="panel-gallery" id="panel-gallery">
|
||||||
|
<img id="panel-img" src="" alt="Image produit REBOURS Studio">
|
||||||
|
</div>
|
||||||
|
<div class="panel-gallery-nav" id="panel-gallery-nav"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-info-col">
|
<div class="panel-info-col">
|
||||||
<p class="panel-index" id="panel-index"></p>
|
<p class="panel-index" id="panel-index"></p>
|
||||||
@ -82,11 +111,11 @@ const schemaOrg = {
|
|||||||
<p id="panel-desc" class="panel-desc"></p>
|
<p id="panel-desc" class="panel-desc"></p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<details class="accordion">
|
<details class="accordion" open>
|
||||||
<summary>SPÉCIFICATIONS TECHNIQUES <span>↓</span></summary>
|
<summary>SPÉCIFICATIONS TECHNIQUES <span>↓</span></summary>
|
||||||
<div class="accordion-body" id="panel-specs"></div>
|
<div class="accordion-body" id="panel-specs"></div>
|
||||||
</details>
|
</details>
|
||||||
<details class="accordion">
|
<details class="accordion" open>
|
||||||
<summary>NOTES DE CONCEPTION <span>↓</span></summary>
|
<summary>NOTES DE CONCEPTION <span>↓</span></summary>
|
||||||
<div class="accordion-body" id="panel-notes"></div>
|
<div class="accordion-body" id="panel-notes"></div>
|
||||||
</details>
|
</details>
|
||||||
@ -141,15 +170,15 @@ const schemaOrg = {
|
|||||||
<!-- HERO -->
|
<!-- HERO -->
|
||||||
<section class="hero" aria-label="Introduction">
|
<section class="hero" aria-label="Introduction">
|
||||||
<div class="hero-left">
|
<div class="hero-left">
|
||||||
<p class="label">// ARCHIVE_001 — 2026</p>
|
<p class="label">{heroLabel}</p>
|
||||||
<h1>REBOURS<br>STUDIO</h1>
|
<h1>{heroTitleParts.map((part, i) => <>{i > 0 && <br/>}{part}</>)}</h1>
|
||||||
<p class="hero-sub">Mobilier d'art contemporain.<br>Space Age × Memphis.</p>
|
<p class="hero-sub" set:html={heroSubtitle.replace(/\n/g, '<br>')} />
|
||||||
<p class="hero-sub mono-sm">STATUS: [PROTOTYPE EN COURS]<br>COLLECTION_001 — BIENTÔT DISPONIBLE</p>
|
<p class="hero-sub mono-sm" set:html={heroStatus.replace(/\n/g, '<br>')} />
|
||||||
</div>
|
</div>
|
||||||
<div class="hero-right">
|
<div class="hero-right">
|
||||||
<img
|
<img
|
||||||
src={firstImage}
|
src={heroImg}
|
||||||
alt="REBOURS — Mobilier d'art contemporain, Paris 2026"
|
alt={heroImgAlt}
|
||||||
class="hero-img"
|
class="hero-img"
|
||||||
width="1024" height="1024"
|
width="1024" height="1024"
|
||||||
fetchpriority="high">
|
fetchpriority="high">
|
||||||
@ -161,14 +190,19 @@ const schemaOrg = {
|
|||||||
<!-- COLLECTION GRID -->
|
<!-- COLLECTION GRID -->
|
||||||
<section class="collection" id="collection" aria-label="Collection 001">
|
<section class="collection" id="collection" aria-label="Collection 001">
|
||||||
<div class="collection-header">
|
<div class="collection-header">
|
||||||
<p class="label">// COLLECTION_001</p>
|
<p class="label">{collectionLabel}</p>
|
||||||
<span class="label">{products.length} OBJETS — CLIQUER POUR OUVRIR</span>
|
<span class="label">{products.length} OBJETS — {collectionCta}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="product-grid">
|
<div class="product-grid">
|
||||||
{products.map((p, i) => {
|
{products.map((p, i) => {
|
||||||
const imgUrl = p.image ? urlFor(p.image).width(800).url() : '';
|
const mainImg = p.images?.[0];
|
||||||
|
const imgUrl = mainImg ? urlFor(mainImg).width(800).url() : '';
|
||||||
const alt = p.imageAlt || `${p.productDisplayName} — mobilier d'art contemporain, REBOURS Studio Paris`;
|
const alt = p.imageAlt || `${p.productDisplayName} — mobilier d'art contemporain, REBOURS Studio Paris`;
|
||||||
|
const allImgs = (p.images || []).map(img => ({
|
||||||
|
url: urlFor(img).width(1200).url(),
|
||||||
|
alt: img.alt || alt,
|
||||||
|
}));
|
||||||
return (
|
return (
|
||||||
<article class="product-card"
|
<article class="product-card"
|
||||||
data-index={p.index}
|
data-index={p.index}
|
||||||
@ -180,7 +214,8 @@ const schemaOrg = {
|
|||||||
data-desc={p.description}
|
data-desc={p.description}
|
||||||
data-specs={p.specs || ''}
|
data-specs={p.specs || ''}
|
||||||
data-notes={p.notes || ''}
|
data-notes={p.notes || ''}
|
||||||
data-img={p.image ? urlFor(p.image).width(1200).url() : ''}
|
data-img={mainImg ? urlFor(mainImg).width(1200).url() : ''}
|
||||||
|
data-images={JSON.stringify(allImgs)}
|
||||||
data-price={p.price ? String(p.price) : ''}
|
data-price={p.price ? String(p.price) : ''}
|
||||||
data-slug={p.slug}
|
data-slug={p.slug}
|
||||||
data-img-alt={alt}
|
data-img-alt={alt}
|
||||||
@ -202,30 +237,32 @@ const schemaOrg = {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- NEWSLETTER -->
|
<!-- CONTACT WHATSAPP -->
|
||||||
<section class="newsletter" id="contact" aria-label="Accès anticipé">
|
<section class="newsletter" id="contact" aria-label="Contact WhatsApp">
|
||||||
<div class="nl-left">
|
<div class="nl-left">
|
||||||
<p class="label">// ACCÈS_ANTICIPÉ</p>
|
<p class="label">{contactLabel}</p>
|
||||||
<h2>REJOINDRE<br>L'EXPÉRIENCE</h2>
|
<h2>{contactTitleParts.map((part, i) => <>{i > 0 && <br/>}{part}</>)}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="nl-right">
|
<div class="nl-right">
|
||||||
<form class="nl-form" onsubmit="event.preventDefault();" aria-label="Inscription newsletter">
|
<div class="nl-form" style="pointer-events: auto;">
|
||||||
<label for="nl-email">EMAIL :</label>
|
<p class="mono-sm" style="line-height: 1.9; margin-bottom: 0.5rem;" set:html={contactDesc.replace(/\n/g, '<br>')} />
|
||||||
<div class="nl-row">
|
<a href={`https://wa.me/${whatsappNumber}`} target="_blank" rel="noopener" class="whatsapp-btn" aria-label="Nous contacter sur WhatsApp">
|
||||||
<input type="email" id="nl-email" name="email" placeholder="votre@email.com" autocomplete="email" required>
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" style="flex-shrink:0;">
|
||||||
<button type="submit">ENVOYER →</button>
|
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
|
||||||
</div>
|
</svg>
|
||||||
<p class="mono-sm"><span class="blink">■</span> CONNECTION_STATUS: PENDING</p>
|
{whatsappBtnText}
|
||||||
</form>
|
</a>
|
||||||
|
<p class="mono-sm"><span class="blink">■</span> {contactResponseTime}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<span>© 2026 REBOURS STUDIO — PARIS</span>
|
<span>{footerText}</span>
|
||||||
<nav aria-label="Liens secondaires">
|
<nav aria-label="Liens secondaires">
|
||||||
<a href="https://instagram.com/rebour.studio" rel="noopener" target="_blank">INSTAGRAM</a>
|
<a href={instagramUrl} rel="noopener" target="_blank">INSTAGRAM</a>
|
||||||
/
|
/
|
||||||
<a href="#" class="contact-trigger">CONTACT</a>
|
<a href="#" class="contact-trigger">CONTACT</a>
|
||||||
</nav>
|
</nav>
|
||||||
@ -234,7 +271,7 @@ const schemaOrg = {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- CONTACT MODAL -->
|
<!-- CONTACT MODAL -->
|
||||||
<div id="contact-modal" class="contact-modal" aria-hidden="true">
|
<div id="contact-modal" class="contact-modal" aria-hidden="true" data-whatsapp={whatsappNumber}>
|
||||||
<div class="contact-modal-backdrop"></div>
|
<div class="contact-modal-backdrop"></div>
|
||||||
<div class="contact-modal-content">
|
<div class="contact-modal-content">
|
||||||
<div class="contact-modal-header">
|
<div class="contact-modal-header">
|
||||||
@ -263,7 +300,7 @@ const schemaOrg = {
|
|||||||
<button type="submit" class="contact-submit">
|
<button type="submit" class="contact-submit">
|
||||||
ENVOYER LE MESSAGE →
|
ENVOYER LE MESSAGE →
|
||||||
</button>
|
</button>
|
||||||
<p class="mono-sm contact-note"><span class="blink">■</span> REDIRECTION VERS VOTRE CLIENT MAIL</p>
|
<p class="mono-sm contact-note"><span class="blink">■</span> REDIRECTION VERS WHATSAPP</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -46,10 +46,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const x = e.clientX;
|
const x = e.clientX;
|
||||||
const y = e.clientY;
|
const y = e.clientY;
|
||||||
|
|
||||||
cursorH.style.left = (x - 20) + 'px';
|
cursorH.style.left = (x - 16) + 'px';
|
||||||
cursorH.style.top = y + 'px';
|
cursorH.style.top = y + 'px';
|
||||||
cursorV.style.left = x + 'px';
|
cursorV.style.left = x + 'px';
|
||||||
cursorV.style.top = (y - 20) + 'px';
|
cursorV.style.top = (y - 16) + 'px';
|
||||||
cursorCenter.style.left = x + 'px';
|
cursorCenter.style.left = x + 'px';
|
||||||
cursorCenter.style.top = y + 'px';
|
cursorCenter.style.top = y + 'px';
|
||||||
cursorCoords.style.left = (x + 16) + 'px';
|
cursorCoords.style.left = (x + 16) + 'px';
|
||||||
@ -85,6 +85,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
attachCursorHover(document.querySelectorAll(
|
attachCursorHover(document.querySelectorAll(
|
||||||
'a, button, input, .product-card, summary, .panel-close'
|
'a, button, input, .product-card, summary, .panel-close'
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// WhatsApp hover — green center dot
|
||||||
|
document.querySelectorAll('.whatsapp-btn').forEach(el => {
|
||||||
|
el.addEventListener('mouseenter', () => cursorCenter.classList.add('cad-whatsapp'));
|
||||||
|
el.addEventListener('mouseleave', () => cursorCenter.classList.remove('cad-whatsapp'));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
@ -131,8 +137,70 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
// 3. GSAP SCROLL ANIMATIONS — CAD REVEAL
|
// 3. GSAP SCROLL ANIMATIONS — CAD REVEAL
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
|
|
||||||
// ---- Hero parallax ----
|
// ---- Header fade in ----
|
||||||
|
const header = document.querySelector('.header');
|
||||||
|
if (header) {
|
||||||
|
gsap.fromTo(header,
|
||||||
|
{ opacity: 0, y: -10 },
|
||||||
|
{ opacity: 1, y: 0, duration: 0.5, ease: 'power2.out' }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Hero animations (scroll-triggered, replay in/out) ----
|
||||||
|
const heroLabel = document.querySelector('.hero-left .label');
|
||||||
|
const heroH1 = document.querySelector('.hero-left h1');
|
||||||
|
const heroSubs = document.querySelectorAll('.hero-sub');
|
||||||
const heroImg = document.querySelector('.hero-img');
|
const heroImg = document.querySelector('.hero-img');
|
||||||
|
const heroRight = document.querySelector('.hero-right');
|
||||||
|
|
||||||
|
const heroTl = gsap.timeline({
|
||||||
|
defaults: { ease: 'power3.out' },
|
||||||
|
scrollTrigger: {
|
||||||
|
trigger: '.hero',
|
||||||
|
start: 'top 95%',
|
||||||
|
end: 'bottom 5%',
|
||||||
|
toggleActions: 'play reverse play reverse',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (heroLabel) {
|
||||||
|
heroTl.fromTo(heroLabel,
|
||||||
|
{ opacity: 0, x: -20 },
|
||||||
|
{ opacity: 1, x: 0, duration: 0.6 },
|
||||||
|
0.1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heroH1) {
|
||||||
|
heroTl.fromTo(heroH1,
|
||||||
|
{ opacity: 0, y: 40, clipPath: 'inset(0 0 100% 0)' },
|
||||||
|
{ opacity: 1, y: 0, clipPath: 'inset(0 0 0% 0)', duration: 1 },
|
||||||
|
0.2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
heroSubs.forEach((sub, i) => {
|
||||||
|
heroTl.fromTo(sub,
|
||||||
|
{ opacity: 0, y: 20 },
|
||||||
|
{ opacity: 1, y: 0, duration: 0.6 },
|
||||||
|
0.5 + i * 0.15
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (heroImg && heroRight) {
|
||||||
|
heroTl.fromTo(heroRight,
|
||||||
|
{ clipPath: 'inset(0 0 0 100%)' },
|
||||||
|
{ clipPath: 'inset(0 0 0 0%)', duration: 1.2, ease: 'power4.inOut' },
|
||||||
|
0.3
|
||||||
|
);
|
||||||
|
heroTl.fromTo(heroImg,
|
||||||
|
{ scale: 1.15, opacity: 0 },
|
||||||
|
{ scale: 1, opacity: 0.92, duration: 1.4, ease: 'power2.out' },
|
||||||
|
0.4
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hero parallax on scroll
|
||||||
if (heroImg) {
|
if (heroImg) {
|
||||||
gsap.to(heroImg, {
|
gsap.to(heroImg, {
|
||||||
yPercent: 15,
|
yPercent: 15,
|
||||||
@ -153,280 +221,88 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
line.className = 'cad-construction-line';
|
line.className = 'cad-construction-line';
|
||||||
collectionHeader.appendChild(line);
|
collectionHeader.appendChild(line);
|
||||||
|
|
||||||
gsap.from(line, {
|
gsap.fromTo(line,
|
||||||
scaleX: 0,
|
{ scaleX: 0 },
|
||||||
transformOrigin: 'left center',
|
{
|
||||||
duration: 0.8,
|
scaleX: 1,
|
||||||
ease: 'power2.out',
|
transformOrigin: 'left center',
|
||||||
scrollTrigger: {
|
duration: 0.8,
|
||||||
trigger: collectionHeader,
|
ease: 'power2.out',
|
||||||
start: 'top 85%',
|
scrollTrigger: {
|
||||||
},
|
trigger: collectionHeader,
|
||||||
});
|
start: 'top 95%',
|
||||||
|
end: 'bottom 5%',
|
||||||
|
toggleActions: 'play reverse play reverse',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Product cards: staggered CAD reveal ----
|
// ---- Product cards: scale + fade reveal on scroll (replays) ----
|
||||||
const cards = document.querySelectorAll('.product-card');
|
const cards = document.querySelectorAll('.product-card');
|
||||||
|
|
||||||
cards.forEach((card, i) => {
|
cards.forEach((card, i) => {
|
||||||
|
const imgWrap = card.querySelector('.card-img-wrap');
|
||||||
const img = card.querySelector('.card-img-wrap img');
|
const img = card.querySelector('.card-img-wrap img');
|
||||||
const meta = card.querySelector('.card-meta');
|
const meta = card.querySelector('.card-meta');
|
||||||
const imgWrap = card.querySelector('.card-img-wrap');
|
|
||||||
|
|
||||||
if (!img) return;
|
if (!img) return;
|
||||||
|
|
||||||
// Create a CAD scan line per card
|
|
||||||
const scanLine = document.createElement('div');
|
|
||||||
scanLine.className = 'card-scanline';
|
|
||||||
imgWrap.appendChild(scanLine);
|
|
||||||
|
|
||||||
// Create corner marks per card
|
|
||||||
const cornerOverlay = document.createElement('div');
|
|
||||||
cornerOverlay.className = 'card-corners';
|
|
||||||
cornerOverlay.innerHTML =
|
|
||||||
'<span class="cc cc-tl"></span>' +
|
|
||||||
'<span class="cc cc-tr"></span>' +
|
|
||||||
'<span class="cc cc-br"></span>' +
|
|
||||||
'<span class="cc cc-bl"></span>';
|
|
||||||
imgWrap.appendChild(cornerOverlay);
|
|
||||||
|
|
||||||
// Create coordinate annotation per card
|
|
||||||
const coordTag = document.createElement('div');
|
|
||||||
coordTag.className = 'card-coord-tag';
|
|
||||||
coordTag.textContent = `[${String(i + 1).padStart(3, '0')}] — ${img.naturalWidth || '1024'} × ${img.naturalHeight || '1024'} px`;
|
|
||||||
imgWrap.appendChild(coordTag);
|
|
||||||
|
|
||||||
// GSAP timeline triggered on scroll
|
|
||||||
const tl = gsap.timeline({
|
const tl = gsap.timeline({
|
||||||
scrollTrigger: {
|
scrollTrigger: {
|
||||||
trigger: card,
|
trigger: card,
|
||||||
start: 'top 88%',
|
start: 'top 95%',
|
||||||
toggleActions: 'play none none none',
|
end: 'bottom 5%',
|
||||||
|
toggleActions: 'play reverse play reverse',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 1. Image clip-path reveal (bottom → top scan)
|
// Clip-path reveal + scale + fade
|
||||||
|
tl.fromTo(imgWrap,
|
||||||
|
{ clipPath: 'inset(8% 8% 8% 8%)' },
|
||||||
|
{ clipPath: 'inset(0% 0% 0% 0%)', duration: 0.8, ease: 'power3.out' },
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
tl.fromTo(img,
|
tl.fromTo(img,
|
||||||
{ clipPath: 'inset(100% 0 0 0)', filter: 'brightness(1.8) grayscale(100%)' },
|
{ opacity: 0, scale: 1.12 },
|
||||||
{ clipPath: 'inset(0% 0 0 0)', filter: 'brightness(1) grayscale(15%)',
|
{ opacity: 1, scale: 1, duration: 0.9, ease: 'power2.out' },
|
||||||
duration: 0.9, ease: 'power3.out' },
|
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
// 2. Scan line sweeps up
|
|
||||||
tl.fromTo(scanLine,
|
|
||||||
{ top: '100%', opacity: 1 },
|
|
||||||
{ top: '-2%', opacity: 0, duration: 0.9, ease: 'power3.out' },
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
// 3. Corner brackets appear
|
|
||||||
tl.fromTo(cornerOverlay.querySelectorAll('.cc'),
|
|
||||||
{ opacity: 0, scale: 0.5 },
|
|
||||||
{ opacity: 1, scale: 1, duration: 0.4, stagger: 0.06, ease: 'back.out(2)' },
|
|
||||||
0.3
|
|
||||||
);
|
|
||||||
|
|
||||||
// 4. Coordinate tag types in
|
|
||||||
tl.fromTo(coordTag,
|
|
||||||
{ opacity: 0, x: -10 },
|
|
||||||
{ opacity: 1, x: 0, duration: 0.4, ease: 'power2.out' },
|
|
||||||
0.5
|
|
||||||
);
|
|
||||||
|
|
||||||
// 5. Meta bar slides in
|
|
||||||
if (meta) {
|
if (meta) {
|
||||||
tl.fromTo(meta,
|
tl.fromTo(meta,
|
||||||
{ opacity: 0, y: 8 },
|
{ opacity: 0, y: 15 },
|
||||||
{ opacity: 1, y: 0, duration: 0.4, ease: 'power2.out' },
|
{ opacity: 1, y: 0, duration: 0.5, ease: 'power2.out' },
|
||||||
0.4
|
0.25
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ---- Newsletter section: slide in ----
|
// ---- Newsletter section: slide in (replays) ----
|
||||||
const nlLeft = document.querySelector('.nl-left');
|
const nlLeft = document.querySelector('.nl-left');
|
||||||
const nlRight = document.querySelector('.nl-right');
|
const nlRight = document.querySelector('.nl-right');
|
||||||
if (nlLeft && nlRight) {
|
if (nlLeft && nlRight) {
|
||||||
gsap.from(nlLeft, {
|
gsap.fromTo(nlLeft,
|
||||||
opacity: 0, x: -30, duration: 0.7, ease: 'power2.out',
|
{ opacity: 0, x: -40 },
|
||||||
scrollTrigger: { trigger: '.newsletter', start: 'top 80%' },
|
{
|
||||||
});
|
opacity: 1, x: 0, duration: 0.7, ease: 'power2.out',
|
||||||
gsap.from(nlRight, {
|
scrollTrigger: { trigger: '.newsletter', start: 'top 95%', end: 'bottom 5%', toggleActions: 'play reverse play reverse' },
|
||||||
opacity: 0, x: 30, duration: 0.7, ease: 'power2.out', delay: 0.15,
|
}
|
||||||
scrollTrigger: { trigger: '.newsletter', start: 'top 80%' },
|
);
|
||||||
});
|
gsap.fromTo(nlRight,
|
||||||
|
{ opacity: 0, x: 40 },
|
||||||
|
{
|
||||||
|
opacity: 1, x: 0, duration: 0.7, ease: 'power2.out', delay: 0.15,
|
||||||
|
scrollTrigger: { trigger: '.newsletter', start: 'top 95%', end: 'bottom 5%', toggleActions: 'play reverse play reverse' },
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
// 4. TECHNICAL DRAWING OVERLAY (panel)
|
// 4. (REMOVED) — no overlay effects on panel image
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
|
|
||||||
const panelImgCol = document.querySelector('.panel-img-col');
|
|
||||||
let techOverlay = null;
|
|
||||||
let techTimeline = null;
|
|
||||||
|
|
||||||
function createTechOverlay(card) {
|
|
||||||
if (techOverlay) techOverlay.remove();
|
|
||||||
|
|
||||||
techOverlay = document.createElement('div');
|
|
||||||
techOverlay.className = 'tech-overlay';
|
|
||||||
|
|
||||||
// Corner brackets
|
|
||||||
['tl', 'tr', 'br', 'bl'].forEach(pos => {
|
|
||||||
const corner = document.createElement('div');
|
|
||||||
corner.className = `tech-corner tech-corner--${pos}`;
|
|
||||||
techOverlay.appendChild(corner);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Center crosshair
|
|
||||||
const centerH = document.createElement('div');
|
|
||||||
centerH.className = 'tech-center-h';
|
|
||||||
const centerV = document.createElement('div');
|
|
||||||
centerV.className = 'tech-center-v';
|
|
||||||
techOverlay.appendChild(centerH);
|
|
||||||
techOverlay.appendChild(centerV);
|
|
||||||
|
|
||||||
// Horizontal dimension line
|
|
||||||
const dimH = document.createElement('div');
|
|
||||||
dimH.className = 'tech-dim tech-dim--h';
|
|
||||||
dimH.innerHTML =
|
|
||||||
'<span class="tech-dim-arrow">◂</span>' +
|
|
||||||
'<span class="tech-dim-line"></span>' +
|
|
||||||
'<span class="tech-dim-text">840</span>' +
|
|
||||||
'<span class="tech-dim-line"></span>' +
|
|
||||||
'<span class="tech-dim-arrow">▸</span>';
|
|
||||||
techOverlay.appendChild(dimH);
|
|
||||||
|
|
||||||
// Vertical dimension line
|
|
||||||
const dimV = document.createElement('div');
|
|
||||||
dimV.className = 'tech-dim tech-dim--v';
|
|
||||||
dimV.innerHTML =
|
|
||||||
'<span class="tech-dim-arrow">▴</span>' +
|
|
||||||
'<span class="tech-dim-line"></span>' +
|
|
||||||
'<span class="tech-dim-text">420</span>' +
|
|
||||||
'<span class="tech-dim-line"></span>' +
|
|
||||||
'<span class="tech-dim-arrow">▾</span>';
|
|
||||||
techOverlay.appendChild(dimV);
|
|
||||||
|
|
||||||
// Reference text
|
|
||||||
const ref = document.createElement('div');
|
|
||||||
ref.className = 'tech-ref';
|
|
||||||
const idx = card ? card.dataset.index : '001';
|
|
||||||
ref.textContent = `REF: ${idx} — SCALE 1:5 — UNIT: mm`;
|
|
||||||
techOverlay.appendChild(ref);
|
|
||||||
|
|
||||||
// Blueprint grid
|
|
||||||
const grid = document.createElement('div');
|
|
||||||
grid.className = 'tech-grid';
|
|
||||||
techOverlay.appendChild(grid);
|
|
||||||
|
|
||||||
// Scan line
|
|
||||||
const scanline = document.createElement('div');
|
|
||||||
scanline.className = 'tech-scanline';
|
|
||||||
techOverlay.appendChild(scanline);
|
|
||||||
|
|
||||||
if (panelImgCol) panelImgCol.appendChild(techOverlay);
|
|
||||||
}
|
|
||||||
|
|
||||||
function animateTechOverlay() {
|
|
||||||
if (!techOverlay) return;
|
|
||||||
|
|
||||||
// Kill previous timeline
|
|
||||||
if (techTimeline) techTimeline.kill();
|
|
||||||
|
|
||||||
const corners = techOverlay.querySelectorAll('.tech-corner');
|
|
||||||
const centerH = techOverlay.querySelector('.tech-center-h');
|
|
||||||
const centerV = techOverlay.querySelector('.tech-center-v');
|
|
||||||
const dimH = techOverlay.querySelector('.tech-dim--h');
|
|
||||||
const dimV = techOverlay.querySelector('.tech-dim--v');
|
|
||||||
const ref = techOverlay.querySelector('.tech-ref');
|
|
||||||
const grid = techOverlay.querySelector('.tech-grid');
|
|
||||||
const scanline = techOverlay.querySelector('.tech-scanline');
|
|
||||||
|
|
||||||
techTimeline = gsap.timeline();
|
|
||||||
|
|
||||||
// 1. Blueprint grid fades in
|
|
||||||
techTimeline.fromTo(grid,
|
|
||||||
{ opacity: 0 },
|
|
||||||
{ opacity: 1, duration: 0.6, ease: 'power1.in' },
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
// 2. Scan line sweeps
|
|
||||||
techTimeline.fromTo(scanline,
|
|
||||||
{ top: '0%', opacity: 1 },
|
|
||||||
{ top: '100%', opacity: 0, duration: 1.1, ease: 'power2.inOut' },
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
// 3. Corner brackets draw in (scale from corner)
|
|
||||||
corners.forEach((c, i) => {
|
|
||||||
const origins = ['top left', 'top right', 'bottom right', 'bottom left'];
|
|
||||||
techTimeline.fromTo(c,
|
|
||||||
{ opacity: 0, scale: 0, borderColor: 'rgba(232,168,0,0)' },
|
|
||||||
{ opacity: 1, scale: 1, borderColor: 'rgba(232,168,0,0.6)',
|
|
||||||
transformOrigin: origins[i],
|
|
||||||
duration: 0.4, ease: 'back.out(1.5)' },
|
|
||||||
0.15 + i * 0.08
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 4. Center crosshair extends
|
|
||||||
techTimeline.fromTo(centerH,
|
|
||||||
{ scaleX: 0, opacity: 0 },
|
|
||||||
{ scaleX: 1, opacity: 1, duration: 0.5, ease: 'power2.out' },
|
|
||||||
0.3
|
|
||||||
);
|
|
||||||
techTimeline.fromTo(centerV,
|
|
||||||
{ scaleY: 0, opacity: 0 },
|
|
||||||
{ scaleY: 1, opacity: 1, duration: 0.5, ease: 'power2.out' },
|
|
||||||
0.35
|
|
||||||
);
|
|
||||||
|
|
||||||
// 5. Dimension lines extend
|
|
||||||
techTimeline.fromTo(dimH,
|
|
||||||
{ opacity: 0, scaleX: 0 },
|
|
||||||
{ opacity: 1, scaleX: 1, transformOrigin: 'center center',
|
|
||||||
duration: 0.6, ease: 'power2.out' },
|
|
||||||
0.4
|
|
||||||
);
|
|
||||||
techTimeline.fromTo(dimV,
|
|
||||||
{ opacity: 0, scaleY: 0 },
|
|
||||||
{ opacity: 1, scaleY: 1, transformOrigin: 'center center',
|
|
||||||
duration: 0.6, ease: 'power2.out' },
|
|
||||||
0.45
|
|
||||||
);
|
|
||||||
|
|
||||||
// 6. Reference text types in
|
|
||||||
techTimeline.fromTo(ref,
|
|
||||||
{ opacity: 0, x: -15 },
|
|
||||||
{ opacity: 1, x: 0, duration: 0.4, ease: 'power2.out' },
|
|
||||||
0.6
|
|
||||||
);
|
|
||||||
|
|
||||||
// 7. Panel image scan reveal
|
|
||||||
const panelImg = document.getElementById('panel-img');
|
|
||||||
if (panelImg) {
|
|
||||||
techTimeline.fromTo(panelImg,
|
|
||||||
{ clipPath: 'inset(0 0 100% 0)', filter: 'brightness(1.8) grayscale(100%)' },
|
|
||||||
{ clipPath: 'inset(0 0 0% 0)', filter: 'brightness(1) contrast(1) grayscale(0%)',
|
|
||||||
duration: 1, ease: 'power3.out' },
|
|
||||||
0.05
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideTechOverlay() {
|
|
||||||
if (techTimeline) techTimeline.kill();
|
|
||||||
if (techOverlay) {
|
|
||||||
gsap.to(techOverlay, { opacity: 0, duration: 0.3, onComplete: () => {
|
|
||||||
if (techOverlay) techOverlay.remove();
|
|
||||||
techOverlay = null;
|
|
||||||
}});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
// 5. PRODUCT PANEL
|
// 5. PRODUCT PANEL
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
@ -436,18 +312,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const panelCards = document.querySelectorAll('.product-card');
|
const panelCards = document.querySelectorAll('.product-card');
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
img: document.getElementById('panel-img'),
|
img: document.getElementById('panel-img'),
|
||||||
index: document.getElementById('panel-index'),
|
gallery: document.getElementById('panel-gallery'),
|
||||||
name: document.getElementById('panel-name'),
|
galleryNav: document.getElementById('panel-gallery-nav'),
|
||||||
type: document.getElementById('panel-type'),
|
index: document.getElementById('panel-index'),
|
||||||
mat: document.getElementById('panel-mat'),
|
name: document.getElementById('panel-name'),
|
||||||
year: document.getElementById('panel-year'),
|
type: document.getElementById('panel-type'),
|
||||||
status: document.getElementById('panel-status'),
|
mat: document.getElementById('panel-mat'),
|
||||||
desc: document.getElementById('panel-desc'),
|
year: document.getElementById('panel-year'),
|
||||||
specs: document.getElementById('panel-specs'),
|
status: document.getElementById('panel-status'),
|
||||||
notes: document.getElementById('panel-notes'),
|
desc: document.getElementById('panel-desc'),
|
||||||
|
specs: document.getElementById('panel-specs'),
|
||||||
|
notes: document.getElementById('panel-notes'),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let currentGalleryIndex = 0;
|
||||||
|
let currentGalleryImages = [];
|
||||||
|
|
||||||
// ---- CHECKOUT LOGIC ----
|
// ---- CHECKOUT LOGIC ----
|
||||||
const checkoutSection = document.getElementById('checkout-section');
|
const checkoutSection = document.getElementById('checkout-section');
|
||||||
const checkoutToggleBtn = document.getElementById('checkout-toggle-btn');
|
const checkoutToggleBtn = document.getElementById('checkout-toggle-btn');
|
||||||
@ -508,9 +389,67 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
.replace(/[^a-z0-9-]/g, '');
|
.replace(/[^a-z0-9-]/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showGalleryImage(index) {
|
||||||
|
if (!currentGalleryImages.length) return;
|
||||||
|
currentGalleryIndex = index;
|
||||||
|
fields.img.src = currentGalleryImages[index].url;
|
||||||
|
fields.img.alt = currentGalleryImages[index].alt;
|
||||||
|
|
||||||
|
// Update nav dots
|
||||||
|
fields.galleryNav.querySelectorAll('.gallery-dot').forEach((dot, i) => {
|
||||||
|
dot.classList.toggle('active', i === index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function openPanel(card, pushState = true) {
|
function openPanel(card, pushState = true) {
|
||||||
fields.img.src = card.dataset.img;
|
// Gallery setup
|
||||||
fields.img.alt = card.dataset.imgAlt || card.dataset.name;
|
try {
|
||||||
|
currentGalleryImages = JSON.parse(card.dataset.images || '[]');
|
||||||
|
} catch { currentGalleryImages = []; }
|
||||||
|
|
||||||
|
if (currentGalleryImages.length > 0) {
|
||||||
|
currentGalleryIndex = 0;
|
||||||
|
fields.img.src = currentGalleryImages[0].url;
|
||||||
|
fields.img.alt = currentGalleryImages[0].alt;
|
||||||
|
} else {
|
||||||
|
fields.img.src = card.dataset.img;
|
||||||
|
fields.img.alt = card.dataset.imgAlt || card.dataset.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build nav dots
|
||||||
|
fields.galleryNav.innerHTML = '';
|
||||||
|
if (currentGalleryImages.length > 1) {
|
||||||
|
fields.galleryNav.style.display = 'flex';
|
||||||
|
currentGalleryImages.forEach((_, i) => {
|
||||||
|
const dot = document.createElement('button');
|
||||||
|
dot.className = 'gallery-dot' + (i === 0 ? ' active' : '');
|
||||||
|
dot.setAttribute('aria-label', `Image ${i + 1}`);
|
||||||
|
dot.addEventListener('click', () => showGalleryImage(i));
|
||||||
|
fields.galleryNav.appendChild(dot);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Arrow buttons
|
||||||
|
const prevBtn = document.createElement('button');
|
||||||
|
prevBtn.className = 'gallery-arrow gallery-prev';
|
||||||
|
prevBtn.textContent = '←';
|
||||||
|
prevBtn.setAttribute('aria-label', 'Image précédente');
|
||||||
|
prevBtn.addEventListener('click', () => {
|
||||||
|
showGalleryImage((currentGalleryIndex - 1 + currentGalleryImages.length) % currentGalleryImages.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
const nextBtn = document.createElement('button');
|
||||||
|
nextBtn.className = 'gallery-arrow gallery-next';
|
||||||
|
nextBtn.textContent = '→';
|
||||||
|
nextBtn.setAttribute('aria-label', 'Image suivante');
|
||||||
|
nextBtn.addEventListener('click', () => {
|
||||||
|
showGalleryImage((currentGalleryIndex + 1) % currentGalleryImages.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
fields.galleryNav.prepend(prevBtn);
|
||||||
|
fields.galleryNav.appendChild(nextBtn);
|
||||||
|
} else {
|
||||||
|
fields.galleryNav.style.display = 'none';
|
||||||
|
}
|
||||||
fields.index.textContent = card.dataset.index;
|
fields.index.textContent = card.dataset.index;
|
||||||
fields.name.textContent = card.dataset.name;
|
fields.name.textContent = card.dataset.name;
|
||||||
fields.type.textContent = card.dataset.type;
|
fields.type.textContent = card.dataset.type;
|
||||||
@ -547,7 +486,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
checkoutSubmitBtn.textContent = 'PROCÉDER AU PAIEMENT →';
|
checkoutSubmitBtn.textContent = 'PROCÉDER AU PAIEMENT →';
|
||||||
checkoutForm.reset();
|
checkoutForm.reset();
|
||||||
|
|
||||||
panel.querySelectorAll('details').forEach(d => d.removeAttribute('open'));
|
panel.querySelectorAll('details').forEach(d => d.setAttribute('open', ''));
|
||||||
panel.classList.add('is-open');
|
panel.classList.add('is-open');
|
||||||
panel.setAttribute('aria-hidden', 'false');
|
panel.setAttribute('aria-hidden', 'false');
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
@ -556,10 +495,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
'summary, .panel-close, .checkout-btn, .checkout-submit'
|
'summary, .panel-close, .checkout-btn, .checkout-submit'
|
||||||
));
|
));
|
||||||
|
|
||||||
// Technical drawing overlay (delayed for panel slide-in)
|
|
||||||
createTechOverlay(card);
|
|
||||||
setTimeout(() => animateTechOverlay(), 350);
|
|
||||||
|
|
||||||
if (pushState) {
|
if (pushState) {
|
||||||
const cardSlug = card.dataset.slug || toSlug(card.dataset.name);
|
const cardSlug = card.dataset.slug || toSlug(card.dataset.name);
|
||||||
history.pushState({ slug: cardSlug }, '', `/collection/${cardSlug}`);
|
history.pushState({ slug: cardSlug }, '', `/collection/${cardSlug}`);
|
||||||
@ -567,7 +502,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closePanel(pushState = true) {
|
function closePanel(pushState = true) {
|
||||||
hideTechOverlay();
|
|
||||||
panel.classList.remove('is-open');
|
panel.classList.remove('is-open');
|
||||||
panel.setAttribute('aria-hidden', 'true');
|
panel.setAttribute('aria-hidden', 'true');
|
||||||
document.body.style.overflow = '';
|
document.body.style.overflow = '';
|
||||||
@ -727,7 +661,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Form → mailto
|
// Form → WhatsApp
|
||||||
if (contactForm) {
|
if (contactForm) {
|
||||||
contactForm.addEventListener('submit', (e) => {
|
contactForm.addEventListener('submit', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -736,9 +670,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const subject = document.getElementById('contact-subject').value.trim() || 'Contact depuis rebours.studio';
|
const subject = document.getElementById('contact-subject').value.trim() || 'Contact depuis rebours.studio';
|
||||||
const message = document.getElementById('contact-message').value.trim();
|
const message = document.getElementById('contact-message').value.trim();
|
||||||
|
|
||||||
const body = `${message}\n\n— ${name}\n${email}`;
|
const waNumber = contactModal.dataset.whatsapp || '33651755191';
|
||||||
const mailto = `mailto:contact@rebours.fr?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
const text = `*${subject}*\n\n${message}\n\n— ${name}\n${email}`;
|
||||||
window.location.href = mailto;
|
window.open(`https://wa.me/${waNumber}?text=${encodeURIComponent(text)}`, '_blank');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user