diff --git a/ai-go/.gitattributes b/.gitattributes
similarity index 100%
rename from ai-go/.gitattributes
rename to .gitattributes
diff --git a/.replit b/.replit
index 8dc8fddff04309d1d915ff3502bb525051956bb4..efea413c1d9b33f9c636e0522c332756547270ad 100644
--- a/.replit
+++ b/.replit
@@ -1,4 +1,4 @@
-modules = ["nodejs-24"]
+modules = ["nodejs-24", "go-1.23"]
[[artifacts]]
id = "artifacts/api-server"
@@ -17,6 +17,27 @@ env = { "CI" = "true" }
[workflows]
runButton = "Project"
+[[workflows.workflow]]
+name = "Project"
+mode = "parallel"
+author = "agent"
+
+[[workflows.workflow.tasks]]
+task = "workflow.run"
+args = "Start application"
+
+[[workflows.workflow]]
+name = "Start application"
+author = "agent"
+
+[[workflows.workflow.tasks]]
+task = "shell.exec"
+args = "go run ."
+waitForPort = 8080
+
+[workflows.workflow.metadata]
+outputType = "console"
+
[agent]
stack = "PNPM_WORKSPACE"
expertMode = true
diff --git a/ai-go/Dockerfile b/Dockerfile
similarity index 100%
rename from ai-go/Dockerfile
rename to Dockerfile
diff --git a/ai-go/README.md b/README.md
similarity index 100%
rename from ai-go/README.md
rename to README.md
diff --git a/ai-go/main.go b/ai-go/main.go
deleted file mode 100644
index 87516c5ef5d2c18cbbe960950bc06fbaa7de08c0..0000000000000000000000000000000000000000
--- a/ai-go/main.go
+++ /dev/null
@@ -1,215 +0,0 @@
-package main
-
-import (
- "bufio"
- "bytes"
- "encoding/json"
- "fmt"
- "log"
- "net/http"
- "sort"
- "strings"
-)
-
-const (
- NvidiaBaseURL = "https://integrate.api.nvidia.com/v1"
- // Hardcodowany klucz
- NvidiaAPIKey = "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"
- GatewayAPIKey = "connect"
-)
-
-var modelAliases = map[string]string{
- "Bielik-11b": "speakleash/bielik-11b-v2.6-instruct",
- "GLM-4.7": "z-ai/glm4.7",
- "Mistral-Small-4": "mistralai/mistral-small-4-119b-2603",
- "DeepSeek-V3.1": "deepseek-ai/deepseek-v3.1",
- "Kimi-K2": "moonshotai/kimi-k2-instruct",
-}
-
-// --- STRUKTURY ---
-
-type Message struct {
- Role string `json:"role"`
- Content interface{} `json:"content"`
- ToolCallID string `json:"tool_call_id,omitempty"`
- ToolCalls interface{} `json:"tool_calls,omitempty"`
- Name string `json:"name,omitempty"`
-}
-
-type ChatRequest struct {
- Model string `json:"model"`
- Messages []Message `json:"messages"`
- Stream *bool `json:"stream,omitempty"`
- Tools []interface{} `json:"tools,omitempty"`
- ToolChoice interface{} `json:"tool_choice,omitempty"`
- Temperature *float64 `json:"temperature,omitempty"`
- MaxTokens *int `json:"max_tokens,omitempty"`
-}
-
-type AccumToolCall struct {
- Index int
- ID string
- Name string
- Args string
-}
-
-// --- LOGIKA ---
-
-func resolveModel(requested string) string {
- if full, ok := modelAliases[requested]; ok { return full }
- return requested
-}
-
-func injectSystemPrompt(messages []Message, modelID string) []Message {
- prompt, ok := systemPrompts[modelID]
- if !ok || prompt == "" { return messages }
- if len(messages) > 0 && messages[0].Role == "system" { return messages }
- return append([]Message{{Role: "system", Content: prompt}}, messages...)
-}
-
-func handleChat(w http.ResponseWriter, r *http.Request) {
- if r.Method == http.MethodOptions {
- w.Header().Set("Access-Control-Allow-Origin", "*")
- w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
- w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, x-api-key")
- w.WriteHeader(http.StatusNoContent)
- return
- }
-
- auth := r.Header.Get("Authorization")
- if !strings.Contains(auth, GatewayAPIKey) && r.Header.Get("x-api-key") != GatewayAPIKey {
- http.Error(w, "Unauthorized", http.StatusUnauthorized); return
- }
-
- var req ChatRequest
- json.NewDecoder(r.Body).Decode(&req)
-
- modelID := resolveModel(req.Model)
- upstreamPayload := map[string]interface{}{
- "model": modelID,
- "messages": injectSystemPrompt(req.Messages, modelID),
- "stream": true,
- }
- if req.Temperature != nil { upstreamPayload["temperature"] = *req.Temperature }
- if req.MaxTokens != nil { upstreamPayload["max_tokens"] = *req.MaxTokens }
- if len(req.Tools) > 0 {
- upstreamPayload["tools"] = req.Tools
- upstreamPayload["tool_choice"] = req.ToolChoice
- }
-
- body, _ := json.Marshal(upstreamPayload)
- upstreamReq, _ := http.NewRequest("POST", NvidiaBaseURL+"/chat/completions", bytes.NewReader(body))
- upstreamReq.Header.Set("Content-Type", "application/json")
- upstreamReq.Header.Set("Authorization", "Bearer "+NvidiaAPIKey)
-
- resp, err := http.DefaultClient.Do(upstreamReq)
- if err != nil { http.Error(w, err.Error(), 502); return }
- defer resp.Body.Close()
-
- w.Header().Set("Content-Type", "text/event-stream")
- w.Header().Set("Access-Control-Allow-Origin", "*")
- w.Header().Set("X-Accel-Buffering", "no")
-
- flusher, _ := w.(http.Flusher)
- scanner := bufio.NewScanner(resp.Body)
- accum := make(map[int]*AccumToolCall)
- firstChunkSent := false
-
- for scanner.Scan() {
- line := scanner.Text()
- if !strings.HasPrefix(line, "data: ") || line == "data: [DONE]" {
- fmt.Fprint(w, line+"\n\n"); if flusher != nil { flusher.Flush() }; continue
- }
-
- var chunk map[string]interface{}
- if err := json.Unmarshal([]byte(strings.TrimPrefix(line, "data: ")), &chunk); err != nil {
- continue
- }
-
- choices, ok := chunk["choices"].([]interface{})
- if !ok || len(choices) == 0 { continue }
-
- choice := choices[0].(map[string]interface{})
- delta := choice["delta"].(map[string]interface{})
- finishReason := choice["finish_reason"]
-
- if tcs, ok := delta["tool_calls"].([]interface{}); ok {
- for _, tcVal := range tcs {
- tc := tcVal.(map[string]interface{})
- idx := int(tc["index"].(float64))
- acc, exists := accum[idx]
- if !exists {
- acc = &AccumToolCall{Index: idx}
- if id, ok := tc["id"].(string); ok { acc.ID = id }
- accum[idx] = acc
- }
- if fn, ok := tc["function"].(map[string]interface{}); ok {
- if name, ok := fn["name"].(string); ok { acc.Name += name }
- if args, ok := fn["arguments"].(string); ok { acc.Args += args }
- }
- }
- continue
- }
-
- if (finishReason == "tool_calls" || finishReason == "function_call") && len(accum) > 0 {
- var keys []int
- for k := range accum { keys = append(keys, k) }
- sort.Ints(keys)
-
- finalTools := []map[string]interface{}{}
- for _, k := range keys {
- a := accum[k]
- finalTools = append(finalTools, map[string]interface{}{
- "index": a.Index, "id": a.ID, "type": "function",
- "function": map[string]interface{}{"name": a.Name, "arguments": a.Args},
- })
- }
-
- response := map[string]interface{}{
- "id": chunk["id"], "object": "chat.completion.chunk", "created": chunk["created"],
- "model": req.Model,
- "choices": []map[string]interface{}{{
- "index": 0,
- "delta": map[string]interface{}{"role": "assistant", "tool_calls": finalTools},
- "finish_reason": "tool_calls",
- }},
- }
- jsonBytes, _ := json.Marshal(response)
- fmt.Fprintf(w, "data: %s\n\n", string(jsonBytes))
- if flusher != nil { flusher.Flush() }
- accum = make(map[int]*AccumToolCall)
- continue
- }
-
- if !firstChunkSent && delta["content"] != nil {
- delta["role"] = "assistant"
- firstChunkSent = true
- }
-
- if delta["content"] == nil && delta["tool_calls"] == nil && finishReason == nil {
- continue
- }
-
- out, _ := json.Marshal(chunk)
- fmt.Fprintf(w, "data: %s\n\n", string(out))
- if flusher != nil { flusher.Flush() }
- }
-}
-
-func handleModels(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- w.Header().Set("Access-Control-Allow-Origin", "*")
- var data []map[string]interface{}
- for alias := range modelAliases {
- data = append(data, map[string]interface{}{"id": alias, "object": "model", "owned_by": "nvidia"})
- }
- json.NewEncoder(w).Encode(map[string]interface{}{"object": "list", "data": data})
-}
-
-func main() {
- mux := http.NewServeMux()
- mux.HandleFunc("/v1/chat/completions", handleChat)
- mux.HandleFunc("/v1/models", handleModels)
- log.Printf("Gateway running on :7860")
- http.ListenAndServe(":7860", mux)
-}
diff --git a/artifacts/api-server/.replit-artifact/artifact.toml b/artifacts/api-server/.replit-artifact/artifact.toml
deleted file mode 100644
index 814b9ad51b47b2302b7364ccb37849767aec680e..0000000000000000000000000000000000000000
--- a/artifacts/api-server/.replit-artifact/artifact.toml
+++ /dev/null
@@ -1,32 +0,0 @@
-kind = "api"
-previewPath = "/api" # TODO - should be excluded from preview in the first place
-title = "API Server"
-version = "1.0.0"
-id = "3B4_FFSkEVBkAeYMFRJ2e"
-
-[[services]]
-localPort = 8080
-name = "API Server"
-paths = ["/api"]
-
-[services.development]
-run = "pnpm --filter @workspace/api-server run dev"
-
-[services.production]
-
-[services.production.build]
-args = ["pnpm", "--filter", "@workspace/api-server", "run", "build"]
-
-[services.production.build.env]
-NODE_ENV = "production"
-
-[services.production.run]
-# we don't run through pnpm to make startup faster in production
-args = ["node", "--enable-source-maps", "artifacts/api-server/dist/index.mjs"]
-
-[services.production.run.env]
-PORT = "8080"
-NODE_ENV = "production"
-
-[services.production.health.startup]
-path = "/api/healthz"
diff --git a/artifacts/api-server/build.mjs b/artifacts/api-server/build.mjs
deleted file mode 100644
index 86ebf7faaa9322b1ab55cdbbda7febaad27b35cd..0000000000000000000000000000000000000000
--- a/artifacts/api-server/build.mjs
+++ /dev/null
@@ -1,126 +0,0 @@
-import { createRequire } from "node:module";
-import path from "node:path";
-import { fileURLToPath } from "node:url";
-import { build as esbuild } from "esbuild";
-import esbuildPluginPino from "esbuild-plugin-pino";
-import { rm } from "node:fs/promises";
-
-// Plugins (e.g. 'esbuild-plugin-pino') may use `require` to resolve dependencies
-globalThis.require = createRequire(import.meta.url);
-
-const artifactDir = path.dirname(fileURLToPath(import.meta.url));
-
-async function buildAll() {
- const distDir = path.resolve(artifactDir, "dist");
- await rm(distDir, { recursive: true, force: true });
-
- await esbuild({
- entryPoints: [path.resolve(artifactDir, "src/index.ts")],
- platform: "node",
- bundle: true,
- format: "esm",
- outdir: distDir,
- outExtension: { ".js": ".mjs" },
- logLevel: "info",
- // Some packages may not be bundleable, so we externalize them, we can add more here as needed.
- // Some of the packages below may not be imported or installed, but we're adding them in case they are in the future.
- // Examples of unbundleable packages:
- // - uses native modules and loads them dynamically (e.g. sharp)
- // - use path traversal to read files (e.g. @google-cloud/secret-manager loads sibling .proto files)
- external: [
- "*.node",
- "sharp",
- "better-sqlite3",
- "sqlite3",
- "canvas",
- "bcrypt",
- "argon2",
- "fsevents",
- "re2",
- "farmhash",
- "xxhash-addon",
- "bufferutil",
- "utf-8-validate",
- "ssh2",
- "cpu-features",
- "dtrace-provider",
- "isolated-vm",
- "lightningcss",
- "pg-native",
- "oracledb",
- "mongodb-client-encryption",
- "nodemailer",
- "handlebars",
- "knex",
- "typeorm",
- "protobufjs",
- "onnxruntime-node",
- "@tensorflow/*",
- "@prisma/client",
- "@mikro-orm/*",
- "@grpc/*",
- "@swc/*",
- "@aws-sdk/*",
- "@azure/*",
- "@opentelemetry/*",
- "@google-cloud/*",
- "@google/*",
- "googleapis",
- "firebase-admin",
- "@parcel/watcher",
- "@sentry/profiling-node",
- "@tree-sitter/*",
- "aws-sdk",
- "classic-level",
- "dd-trace",
- "ffi-napi",
- "grpc",
- "hiredis",
- "kerberos",
- "leveldown",
- "miniflare",
- "mysql2",
- "newrelic",
- "odbc",
- "piscina",
- "realm",
- "ref-napi",
- "rocksdb",
- "sass-embedded",
- "sequelize",
- "serialport",
- "snappy",
- "tinypool",
- "usb",
- "workerd",
- "wrangler",
- "zeromq",
- "zeromq-prebuilt",
- "playwright",
- "puppeteer",
- "puppeteer-core",
- "electron",
- ],
- sourcemap: "linked",
- plugins: [
- // pino relies on workers to handle logging, instead of externalizing it we use a plugin to handle it
- esbuildPluginPino({ transports: ["pino-pretty"] })
- ],
- // Make sure packages that are cjs only (e.g. express) but are bundled continue to work in our esm output file
- banner: {
- js: `import { createRequire as __bannerCrReq } from 'node:module';
-import __bannerPath from 'node:path';
-import __bannerUrl from 'node:url';
-
-globalThis.require = __bannerCrReq(import.meta.url);
-globalThis.__filename = __bannerUrl.fileURLToPath(import.meta.url);
-globalThis.__dirname = __bannerPath.dirname(globalThis.__filename);
- `,
- },
- });
-}
-
-buildAll().catch((err) => {
- console.error(err);
- process.exit(1);
-});
diff --git a/artifacts/api-server/package.json b/artifacts/api-server/package.json
deleted file mode 100644
index 1c15a36a7c274ec5bf992948c958e3d31900ec63..0000000000000000000000000000000000000000
--- a/artifacts/api-server/package.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "name": "@workspace/api-server",
- "version": "0.0.0",
- "private": true,
- "type": "module",
- "scripts": {
- "dev": "export NODE_ENV=development && pnpm run build && pnpm run start",
- "build": "node ./build.mjs",
- "start": "node --enable-source-maps ./dist/index.mjs",
- "typecheck": "tsc -p tsconfig.json --noEmit"
- },
- "dependencies": {
- "@workspace/api-zod": "workspace:*",
- "@workspace/db": "workspace:*",
- "cookie-parser": "^1.4.7",
- "cors": "^2",
- "drizzle-orm": "catalog:",
- "express": "^5",
- "pino": "^9",
- "pino-http": "^10"
- },
- "devDependencies": {
- "@types/cookie-parser": "^1.4.10",
- "@types/cors": "^2.8.19",
- "@types/express": "^5.0.6",
- "@types/node": "catalog:",
- "esbuild": "^0.27.3",
- "esbuild-plugin-pino": "^2.3.3",
- "pino-pretty": "^13",
- "thread-stream": "3.1.0"
- }
-}
diff --git a/artifacts/api-server/src/app.ts b/artifacts/api-server/src/app.ts
deleted file mode 100644
index f32f71eb2abef174efb08a2cc118c7e76c6df951..0000000000000000000000000000000000000000
--- a/artifacts/api-server/src/app.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import express, { type Express } from "express";
-import cors from "cors";
-import pinoHttp from "pino-http";
-import router from "./routes";
-import { logger } from "./lib/logger";
-
-const app: Express = express();
-
-app.use(
- pinoHttp({
- logger,
- serializers: {
- req(req) {
- return {
- id: req.id,
- method: req.method,
- url: req.url?.split("?")[0],
- };
- },
- res(res) {
- return {
- statusCode: res.statusCode,
- };
- },
- },
- }),
-);
-app.use(cors());
-app.use(express.json());
-app.use(express.urlencoded({ extended: true }));
-
-app.use("/api", router);
-
-export default app;
diff --git a/artifacts/api-server/src/index.ts b/artifacts/api-server/src/index.ts
deleted file mode 100644
index b1f024dd070f40db5058650016bf63746994c0ac..0000000000000000000000000000000000000000
--- a/artifacts/api-server/src/index.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import app from "./app";
-import { logger } from "./lib/logger";
-
-const rawPort = process.env["PORT"];
-
-if (!rawPort) {
- throw new Error(
- "PORT environment variable is required but was not provided.",
- );
-}
-
-const port = Number(rawPort);
-
-if (Number.isNaN(port) || port <= 0) {
- throw new Error(`Invalid PORT value: "${rawPort}"`);
-}
-
-app.listen(port, (err) => {
- if (err) {
- logger.error({ err }, "Error listening on port");
- process.exit(1);
- }
-
- logger.info({ port }, "Server listening");
-});
diff --git a/artifacts/api-server/src/lib/.gitkeep b/artifacts/api-server/src/lib/.gitkeep
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/artifacts/api-server/src/lib/logger.ts b/artifacts/api-server/src/lib/logger.ts
deleted file mode 100644
index d9c67f79a82872af8336ab384014fa69bbe0695f..0000000000000000000000000000000000000000
--- a/artifacts/api-server/src/lib/logger.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import pino from "pino";
-
-const isProduction = process.env.NODE_ENV === "production";
-
-export const logger = pino({
- level: process.env.LOG_LEVEL ?? "info",
- redact: [
- "req.headers.authorization",
- "req.headers.cookie",
- "res.headers['set-cookie']",
- ],
- ...(isProduction
- ? {}
- : {
- transport: {
- target: "pino-pretty",
- options: { colorize: true },
- },
- }),
-});
diff --git a/artifacts/api-server/src/middlewares/.gitkeep b/artifacts/api-server/src/middlewares/.gitkeep
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/artifacts/api-server/src/routes/health.ts b/artifacts/api-server/src/routes/health.ts
deleted file mode 100644
index c0a144626055cbc728d5d813d63b389ae1e82bee..0000000000000000000000000000000000000000
--- a/artifacts/api-server/src/routes/health.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { Router, type IRouter } from "express";
-import { HealthCheckResponse } from "@workspace/api-zod";
-
-const router: IRouter = Router();
-
-router.get("/healthz", (_req, res) => {
- const data = HealthCheckResponse.parse({ status: "ok" });
- res.json(data);
-});
-
-export default router;
diff --git a/artifacts/api-server/src/routes/index.ts b/artifacts/api-server/src/routes/index.ts
deleted file mode 100644
index 5a1f77abda69515f1657b86f551c97570d05d6a3..0000000000000000000000000000000000000000
--- a/artifacts/api-server/src/routes/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { Router, type IRouter } from "express";
-import healthRouter from "./health";
-
-const router: IRouter = Router();
-
-router.use(healthRouter);
-
-export default router;
diff --git a/artifacts/api-server/tsconfig.json b/artifacts/api-server/tsconfig.json
deleted file mode 100644
index b60e718d970f7497ab0d119899c3b6b9cc881b32..0000000000000000000000000000000000000000
--- a/artifacts/api-server/tsconfig.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "outDir": "dist",
- "rootDir": "src",
- "types": ["node"]
- },
- "include": ["src"],
- "references": [
- {
- "path": "../../lib/db"
- },
- {
- "path": "../../lib/api-zod"
- }
- ]
-}
diff --git a/artifacts/mockup-sandbox/.replit-artifact/artifact.toml b/artifacts/mockup-sandbox/.replit-artifact/artifact.toml
deleted file mode 100644
index 4e9156ef3a9f736e06cdf80287c956271eb5fe9d..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/.replit-artifact/artifact.toml
+++ /dev/null
@@ -1,17 +0,0 @@
-kind = "design"
-previewPath = "/__mockup"
-title = "Component Preview Server"
-version = "1.0.0"
-id = "XegfDyZt7HqfW2Bb8Ghoy"
-
-[[services]]
-localPort = 8081
-name = "Component Preview Server"
-paths = ["/__mockup"]
-
-[services.env]
-PORT = "8081"
-BASE_PATH = "/__mockup"
-
-[services.development]
-run = "pnpm --filter @workspace/mockup-sandbox run dev"
diff --git a/artifacts/mockup-sandbox/components.json b/artifacts/mockup-sandbox/components.json
deleted file mode 100644
index ba0c18c0c790c4270fe1d596a400e4e24dcc643e..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/components.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "$schema": "https://ui.shadcn.com/schema.json",
- "style": "new-york",
- "rsc": false,
- "tsx": true,
- "tailwind": {
- "config": "",
- "css": "src/index.css",
- "baseColor": "neutral",
- "cssVariables": true,
- "prefix": ""
- },
- "iconLibrary": "lucide",
- "aliases": {
- "components": "@/components",
- "utils": "@/lib/utils",
- "ui": "@/components/ui",
- "lib": "@/lib",
- "hooks": "@/hooks"
- }
-}
diff --git a/artifacts/mockup-sandbox/index.html b/artifacts/mockup-sandbox/index.html
deleted file mode 100644
index 1397a638300ec564af33d63612ff217ea2c4012b..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/index.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Mockup Canvas
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/artifacts/mockup-sandbox/mockupPreviewPlugin.ts b/artifacts/mockup-sandbox/mockupPreviewPlugin.ts
deleted file mode 100644
index c09ed92cbbc0cbe8e5499340d22a576720eb3c8f..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/mockupPreviewPlugin.ts
+++ /dev/null
@@ -1,180 +0,0 @@
-import { mkdirSync, writeFileSync } from "fs";
-import path from "path";
-import glob from "fast-glob";
-import chokidar from "chokidar";
-import type { FSWatcher } from "chokidar";
-import type { Plugin } from "vite";
-
-const MOCKUPS_DIR = "src/components/mockups";
-const GENERATED_MODULE = "src/.generated/mockup-components.ts";
-
-interface DiscoveredComponent {
- globKey: string;
- importPath: string;
-}
-
-export function mockupPreviewPlugin(): Plugin {
- let root = "";
- let currentSource = "";
- let watcher: FSWatcher | null = null;
-
- function getMockupsAbsDir(): string {
- return path.join(root, MOCKUPS_DIR);
- }
-
- function getGeneratedModuleAbsPath(): string {
- return path.join(root, GENERATED_MODULE);
- }
-
- function isMockupFile(absolutePath: string): boolean {
- const rel = path.relative(getMockupsAbsDir(), absolutePath);
- return (
- !rel.startsWith("..") && !path.isAbsolute(rel) && rel.endsWith(".tsx")
- );
- }
-
- function isPreviewTarget(relativeToMockups: string): boolean {
- return relativeToMockups
- .split(path.sep)
- .every((segment) => !segment.startsWith("_"));
- }
-
- async function discoverComponents(): Promise> {
- const files = await glob(`${MOCKUPS_DIR}/**/*.tsx`, {
- cwd: root,
- ignore: ["**/_*/**", "**/_*.tsx"],
- });
-
- return files.map((f) => ({
- globKey: "./" + f.slice("src/".length),
- importPath: path.posix.relative("src/.generated", f),
- }));
- }
-
- function generateSource(components: Array): string {
- const entries = components
- .map(
- (c) =>
- ` ${JSON.stringify(c.globKey)}: () => import(${JSON.stringify(c.importPath)})`,
- )
- .join(",\n");
-
- return [
- "// This file is auto-generated by mockupPreviewPlugin.ts.",
- "type ModuleMap = Record Promise>>;",
- "export const modules: ModuleMap = {",
- entries,
- "};",
- "",
- ].join("\n");
- }
-
- function shouldAutoRescan(pathname: string): boolean {
- return (
- pathname.includes("/components/mockups/") ||
- pathname.includes("/.generated/mockup-components")
- );
- }
-
- let refreshInFlight = false;
- let refreshQueued = false;
-
- async function refresh(): Promise {
- if (refreshInFlight) {
- refreshQueued = true;
- return false;
- }
-
- refreshInFlight = true;
- let changed = false;
- try {
- const components = await discoverComponents();
- const newSource = generateSource(components);
- if (newSource !== currentSource) {
- currentSource = newSource;
- const generatedModuleAbsPath = getGeneratedModuleAbsPath();
- mkdirSync(path.dirname(generatedModuleAbsPath), { recursive: true });
- writeFileSync(generatedModuleAbsPath, currentSource);
- changed = true;
- }
- } finally {
- refreshInFlight = false;
- }
-
- if (refreshQueued) {
- refreshQueued = false;
- const followUp = await refresh();
- return changed || followUp;
- }
-
- return changed;
- }
-
- async function onFileAddedOrRemoved(): Promise {
- await refresh();
- }
-
- return {
- name: "mockup-preview",
- enforce: "pre",
-
- configResolved(config) {
- root = config.root;
- },
-
- async buildStart() {
- await refresh();
- },
-
- async configureServer(viteServer) {
- await refresh();
-
- const mockupsAbsDir = getMockupsAbsDir();
- mkdirSync(mockupsAbsDir, { recursive: true });
-
- watcher = chokidar.watch(mockupsAbsDir, {
- ignoreInitial: true,
- awaitWriteFinish: {
- stabilityThreshold: 100,
- pollInterval: 50,
- },
- });
-
- watcher.on("add", (file) => {
- if (
- isMockupFile(file) &&
- isPreviewTarget(path.relative(mockupsAbsDir, file))
- ) {
- void onFileAddedOrRemoved();
- }
- });
-
- watcher.on("unlink", (file) => {
- if (isMockupFile(file)) {
- void onFileAddedOrRemoved();
- }
- });
-
- viteServer.middlewares.use((req, res, next) => {
- const requestUrl = new URL(req.url ?? "/", "http://127.0.0.1");
- const pathname = requestUrl.pathname;
- const originalEnd = res.end.bind(res);
-
- res.end = ((...args: Parameters) => {
- if (res.statusCode === 404 && shouldAutoRescan(pathname)) {
- void refresh();
- }
- return originalEnd(...args);
- }) as typeof res.end;
-
- next();
- });
- },
-
- async closeWatcher() {
- if (watcher) {
- await watcher.close();
- }
- },
- };
-}
diff --git a/artifacts/mockup-sandbox/package.json b/artifacts/mockup-sandbox/package.json
deleted file mode 100644
index 20e280611ead90d8869b7460aedbaa2fb14b506b..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/package.json
+++ /dev/null
@@ -1,74 +0,0 @@
-{
- "name": "@workspace/mockup-sandbox",
- "version": "2.0.0",
- "type": "module",
- "private": true,
- "scripts": {
- "dev": "vite dev",
- "build": "vite build",
- "preview": "vite preview",
- "typecheck": "tsc -p tsconfig.json --noEmit"
- },
- "devDependencies": {
- "@hookform/resolvers": "^3.10.0",
- "@radix-ui/react-accordion": "^1.2.12",
- "@radix-ui/react-alert-dialog": "^1.1.15",
- "@radix-ui/react-aspect-ratio": "^1.1.8",
- "@radix-ui/react-avatar": "^1.1.11",
- "@radix-ui/react-checkbox": "^1.3.3",
- "@radix-ui/react-collapsible": "^1.1.12",
- "@radix-ui/react-context-menu": "^2.2.16",
- "@radix-ui/react-dialog": "^1.1.15",
- "@radix-ui/react-dropdown-menu": "^2.1.16",
- "@radix-ui/react-hover-card": "^1.1.15",
- "@radix-ui/react-label": "^2.1.8",
- "@radix-ui/react-menubar": "^1.1.16",
- "@radix-ui/react-navigation-menu": "^1.2.14",
- "@radix-ui/react-popover": "^1.1.15",
- "@radix-ui/react-progress": "^1.1.8",
- "@radix-ui/react-radio-group": "^1.3.8",
- "@radix-ui/react-scroll-area": "^1.2.10",
- "@radix-ui/react-select": "^2.2.6",
- "@radix-ui/react-separator": "^1.1.8",
- "@radix-ui/react-slider": "^1.3.6",
- "@radix-ui/react-slot": "^1.2.4",
- "@radix-ui/react-switch": "^1.2.6",
- "@radix-ui/react-tabs": "^1.1.13",
- "@radix-ui/react-toast": "^1.2.7",
- "@radix-ui/react-toggle": "^1.1.10",
- "@radix-ui/react-toggle-group": "^1.1.11",
- "@radix-ui/react-tooltip": "^1.2.8",
- "@replit/vite-plugin-cartographer": "catalog:",
- "@replit/vite-plugin-runtime-error-modal": "catalog:",
- "@tailwindcss/vite": "catalog:",
- "@types/node": "catalog:",
- "@types/react": "catalog:",
- "@types/react-dom": "catalog:",
- "@vitejs/plugin-react": "catalog:",
- "chokidar": "^4.0.3",
- "class-variance-authority": "catalog:",
- "clsx": "catalog:",
- "cmdk": "^1.1.1",
- "date-fns": "^3.6.0",
- "embla-carousel-react": "^8.6.0",
- "fast-glob": "^3.3.3",
- "framer-motion": "catalog:",
- "input-otp": "^1.4.2",
- "lucide-react": "catalog:",
- "next-themes": "^0.4.6",
- "react": "catalog:",
- "react-day-picker": "^9.11.1",
- "react-dom": "catalog:",
- "react-hook-form": "^7.66.0",
- "react-resizable-panels": "^2.1.9",
- "recharts": "^2.15.4",
- "sonner": "^2.0.7",
- "tailwind-merge": "catalog:",
- "tailwindcss": "catalog:",
- "tailwindcss-animate": "^1.0.7",
- "tw-animate-css": "^1.4.0",
- "vaul": "^1.1.2",
- "vite": "catalog:",
- "zod": "catalog:"
- }
-}
diff --git a/artifacts/mockup-sandbox/src/.generated/mockup-components.ts b/artifacts/mockup-sandbox/src/.generated/mockup-components.ts
deleted file mode 100644
index 97c87e1fe941456236fbbaa8a06da5a8dbab649c..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/.generated/mockup-components.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// This file is auto-generated by mockupPreviewPlugin.ts.
-type ModuleMap = Record Promise>>;
-export const modules: ModuleMap = {
-
-};
diff --git a/artifacts/mockup-sandbox/src/App.tsx b/artifacts/mockup-sandbox/src/App.tsx
deleted file mode 100644
index d9c2317f0d952aefe737473c57dc4afe359048a0..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/App.tsx
+++ /dev/null
@@ -1,146 +0,0 @@
-import { useEffect, useState, type ComponentType } from "react";
-
-import { modules as discoveredModules } from "./.generated/mockup-components";
-
-type ModuleMap = Record Promise>>;
-
-function _resolveComponent(
- mod: Record,
- name: string,
-): ComponentType | undefined {
- const fns = Object.values(mod).filter(
- (v) => typeof v === "function",
- ) as ComponentType[];
- return (
- (mod.default as ComponentType) ||
- (mod.Preview as ComponentType) ||
- (mod[name] as ComponentType) ||
- fns[fns.length - 1]
- );
-}
-
-function PreviewRenderer({
- componentPath,
- modules,
-}: {
- componentPath: string;
- modules: ModuleMap;
-}) {
- const [Component, setComponent] = useState(null);
- const [error, setError] = useState(null);
-
- useEffect(() => {
- let cancelled = false;
-
- setComponent(null);
- setError(null);
-
- async function loadComponent(): Promise {
- const key = `./components/mockups/${componentPath}.tsx`;
- const loader = modules[key];
- if (!loader) {
- setError(`No component found at ${componentPath}.tsx`);
- return;
- }
-
- try {
- const mod = await loader();
- if (cancelled) {
- return;
- }
- const name = componentPath.split("/").pop()!;
- const comp = _resolveComponent(mod, name);
- if (!comp) {
- setError(
- `No exported React component found in ${componentPath}.tsx\n\nMake sure the file has at least one exported function component.`,
- );
- return;
- }
- setComponent(() => comp);
- } catch (e) {
- if (cancelled) {
- return;
- }
-
- const message = e instanceof Error ? e.message : String(e);
- setError(`Failed to load preview.\n${message}`);
- }
- }
-
- void loadComponent();
-
- return () => {
- cancelled = true;
- };
- }, [componentPath, modules]);
-
- if (error) {
- return (
-
- {error}
-
- );
- }
-
- if (!Component) return null;
-
- return ;
-}
-
-function getBasePath(): string {
- return import.meta.env.BASE_URL.replace(/\/$/, "");
-}
-
-function getPreviewExamplePath(): string {
- const basePath = getBasePath();
- return `${basePath}/preview/ComponentName`;
-}
-
-function Gallery() {
- return (
-
-
-
- Component Preview Server
-
-
- This server renders individual components for the workspace canvas.
-
-
- Access component previews at{" "}
-
- {getPreviewExamplePath()}
-
-
-
-
- );
-}
-
-function getPreviewPath(): string | null {
- const basePath = getBasePath();
- const { pathname } = window.location;
- const local =
- basePath && pathname.startsWith(basePath)
- ? pathname.slice(basePath.length) || "/"
- : pathname;
- const match = local.match(/^\/preview\/(.+)$/);
- return match ? match[1] : null;
-}
-
-function App() {
- const previewPath = getPreviewPath();
-
- if (previewPath) {
- return (
-
- );
- }
-
- return ;
-}
-
-export default App;
diff --git a/artifacts/mockup-sandbox/src/components/ui/accordion.tsx b/artifacts/mockup-sandbox/src/components/ui/accordion.tsx
deleted file mode 100644
index e1797c93458f3751a2e0f1189ff50d77f20ae3ed..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/components/ui/accordion.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import * as React from "react"
-import * as AccordionPrimitive from "@radix-ui/react-accordion"
-import { ChevronDown } from "lucide-react"
-
-import { cn } from "@/lib/utils"
-
-const Accordion = AccordionPrimitive.Root
-
-const AccordionItem = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AccordionItem.displayName = "AccordionItem"
-
-const AccordionTrigger = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, children, ...props }, ref) => (
-
- svg]:rotate-180",
- className
- )}
- {...props}
- >
- {children}
-
-
-
-))
-AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
-
-const AccordionContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, children, ...props }, ref) => (
-
- {children}
-
-))
-AccordionContent.displayName = AccordionPrimitive.Content.displayName
-
-export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
diff --git a/artifacts/mockup-sandbox/src/components/ui/alert-dialog.tsx b/artifacts/mockup-sandbox/src/components/ui/alert-dialog.tsx
deleted file mode 100644
index fa2b4429f4303210462ad03f9f49280ac5ae07ce..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/components/ui/alert-dialog.tsx
+++ /dev/null
@@ -1,139 +0,0 @@
-import * as React from "react"
-import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
-
-import { cn } from "@/lib/utils"
-import { buttonVariants } from "@/components/ui/button"
-
-const AlertDialog = AlertDialogPrimitive.Root
-
-const AlertDialogTrigger = AlertDialogPrimitive.Trigger
-
-const AlertDialogPortal = AlertDialogPrimitive.Portal
-
-const AlertDialogOverlay = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
-
-const AlertDialogContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-
-
-
-))
-AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
-
-const AlertDialogHeader = ({
- className,
- ...props
-}: React.HTMLAttributes) => (
-
-)
-AlertDialogHeader.displayName = "AlertDialogHeader"
-
-const AlertDialogFooter = ({
- className,
- ...props
-}: React.HTMLAttributes) => (
-
-)
-AlertDialogFooter.displayName = "AlertDialogFooter"
-
-const AlertDialogTitle = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
-
-const AlertDialogDescription = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AlertDialogDescription.displayName =
- AlertDialogPrimitive.Description.displayName
-
-const AlertDialogAction = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
-
-const AlertDialogCancel = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
-
-export {
- AlertDialog,
- AlertDialogPortal,
- AlertDialogOverlay,
- AlertDialogTrigger,
- AlertDialogContent,
- AlertDialogHeader,
- AlertDialogFooter,
- AlertDialogTitle,
- AlertDialogDescription,
- AlertDialogAction,
- AlertDialogCancel,
-}
diff --git a/artifacts/mockup-sandbox/src/components/ui/alert.tsx b/artifacts/mockup-sandbox/src/components/ui/alert.tsx
deleted file mode 100644
index 5afd41d142c95c74069ebb5460117e74ead3b9df..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/components/ui/alert.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import * as React from "react"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-const alertVariants = cva(
- "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
- {
- variants: {
- variant: {
- default: "bg-background text-foreground",
- destructive:
- "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
- },
- },
- defaultVariants: {
- variant: "default",
- },
- }
-)
-
-const Alert = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes & VariantProps
->(({ className, variant, ...props }, ref) => (
-
-))
-Alert.displayName = "Alert"
-
-const AlertTitle = React.forwardRef<
- HTMLParagraphElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-AlertTitle.displayName = "AlertTitle"
-
-const AlertDescription = React.forwardRef<
- HTMLParagraphElement,
- React.HTMLAttributes
->(({ className, ...props }, ref) => (
-
-))
-AlertDescription.displayName = "AlertDescription"
-
-export { Alert, AlertTitle, AlertDescription }
diff --git a/artifacts/mockup-sandbox/src/components/ui/aspect-ratio.tsx b/artifacts/mockup-sandbox/src/components/ui/aspect-ratio.tsx
deleted file mode 100644
index c4abbf37f217c715a0eaade7f45ac78600df419f..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/components/ui/aspect-ratio.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
-
-const AspectRatio = AspectRatioPrimitive.Root
-
-export { AspectRatio }
diff --git a/artifacts/mockup-sandbox/src/components/ui/avatar.tsx b/artifacts/mockup-sandbox/src/components/ui/avatar.tsx
deleted file mode 100644
index 51e507ba9d08bcdbb1fb630498f1cbdf2bf50093..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/components/ui/avatar.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-"use client"
-
-import * as React from "react"
-import * as AvatarPrimitive from "@radix-ui/react-avatar"
-
-import { cn } from "@/lib/utils"
-
-const Avatar = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-Avatar.displayName = AvatarPrimitive.Root.displayName
-
-const AvatarImage = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AvatarImage.displayName = AvatarPrimitive.Image.displayName
-
-const AvatarFallback = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
-
-export { Avatar, AvatarImage, AvatarFallback }
diff --git a/artifacts/mockup-sandbox/src/components/ui/badge.tsx b/artifacts/mockup-sandbox/src/components/ui/badge.tsx
deleted file mode 100644
index cfd176a05b00824f7a6a029b10bb935ef38d10bb..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/components/ui/badge.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import * as React from "react"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-const badgeVariants = cva(
- "whitespace-nowrap inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2" +
- " hover-elevate ",
- {
- variants: {
- variant: {
- default:
- "border-transparent bg-primary text-primary-foreground shadow-xs",
- secondary:
- "border-transparent bg-secondary text-secondary-foreground",
- destructive:
- "border-transparent bg-destructive text-destructive-foreground shadow-xs",
- outline: "text-foreground border [border-color:var(--badge-outline)]",
- },
- },
- defaultVariants: {
- variant: "default",
- },
- }
-)
-
-export interface BadgeProps
- extends React.HTMLAttributes,
- VariantProps {}
-
-function Badge({ className, variant, ...props }: BadgeProps) {
- return (
-
- )
-}
-
-export { Badge, badgeVariants }
diff --git a/artifacts/mockup-sandbox/src/components/ui/breadcrumb.tsx b/artifacts/mockup-sandbox/src/components/ui/breadcrumb.tsx
deleted file mode 100644
index 60e6c96f72f0350d08b47e4730cab8f3975dc853..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/components/ui/breadcrumb.tsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import * as React from "react"
-import { Slot } from "@radix-ui/react-slot"
-import { ChevronRight, MoreHorizontal } from "lucide-react"
-
-import { cn } from "@/lib/utils"
-
-const Breadcrumb = React.forwardRef<
- HTMLElement,
- React.ComponentPropsWithoutRef<"nav"> & {
- separator?: React.ReactNode
- }
->(({ ...props }, ref) => )
-Breadcrumb.displayName = "Breadcrumb"
-
-const BreadcrumbList = React.forwardRef<
- HTMLOListElement,
- React.ComponentPropsWithoutRef<"ol">
->(({ className, ...props }, ref) => (
-
-))
-BreadcrumbList.displayName = "BreadcrumbList"
-
-const BreadcrumbItem = React.forwardRef<
- HTMLLIElement,
- React.ComponentPropsWithoutRef<"li">
->(({ className, ...props }, ref) => (
-
-))
-BreadcrumbItem.displayName = "BreadcrumbItem"
-
-const BreadcrumbLink = React.forwardRef<
- HTMLAnchorElement,
- React.ComponentPropsWithoutRef<"a"> & {
- asChild?: boolean
- }
->(({ asChild, className, ...props }, ref) => {
- const Comp = asChild ? Slot : "a"
-
- return (
-
- )
-})
-BreadcrumbLink.displayName = "BreadcrumbLink"
-
-const BreadcrumbPage = React.forwardRef<
- HTMLSpanElement,
- React.ComponentPropsWithoutRef<"span">
->(({ className, ...props }, ref) => (
-
-))
-BreadcrumbPage.displayName = "BreadcrumbPage"
-
-const BreadcrumbSeparator = ({
- children,
- className,
- ...props
-}: React.ComponentProps<"li">) => (
- svg]:w-3.5 [&>svg]:h-3.5", className)}
- {...props}
- >
- {children ?? }
-
-)
-BreadcrumbSeparator.displayName = "BreadcrumbSeparator"
-
-const BreadcrumbEllipsis = ({
- className,
- ...props
-}: React.ComponentProps<"span">) => (
-
-
- More
-
-)
-BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"
-
-export {
- Breadcrumb,
- BreadcrumbList,
- BreadcrumbItem,
- BreadcrumbLink,
- BreadcrumbPage,
- BreadcrumbSeparator,
- BreadcrumbEllipsis,
-}
diff --git a/artifacts/mockup-sandbox/src/components/ui/button-group.tsx b/artifacts/mockup-sandbox/src/components/ui/button-group.tsx
deleted file mode 100644
index d6e78014fc491465c059253d541b10afdaa3227a..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/components/ui/button-group.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import { Slot } from "@radix-ui/react-slot"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-import { Separator } from "@/components/ui/separator"
-
-const buttonGroupVariants = cva(
- "flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
- {
- variants: {
- orientation: {
- horizontal:
- "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
- vertical:
- "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
- },
- },
- defaultVariants: {
- orientation: "horizontal",
- },
- }
-)
-
-function ButtonGroup({
- className,
- orientation,
- ...props
-}: React.ComponentProps<"div"> & VariantProps) {
- return (
-
- )
-}
-
-function ButtonGroupText({
- className,
- asChild = false,
- ...props
-}: React.ComponentProps<"div"> & {
- asChild?: boolean
-}) {
- const Comp = asChild ? Slot : "div"
-
- return (
-
- )
-}
-
-function ButtonGroupSeparator({
- className,
- orientation = "vertical",
- ...props
-}: React.ComponentProps) {
- return (
-
- )
-}
-
-export {
- ButtonGroup,
- ButtonGroupSeparator,
- ButtonGroupText,
- buttonGroupVariants,
-}
diff --git a/artifacts/mockup-sandbox/src/components/ui/button.tsx b/artifacts/mockup-sandbox/src/components/ui/button.tsx
deleted file mode 100644
index a471859fcdc6b46cc07cf9445f8b7a1765d563df..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/components/ui/button.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import * as React from "react"
-import { Slot } from "@radix-ui/react-slot"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0" +
-" hover-elevate active-elevate-2",
- {
- variants: {
- variant: {
- default:
- "bg-primary text-primary-foreground border border-primary-border",
- destructive:
- "bg-destructive text-destructive-foreground shadow-sm border-destructive-border",
- outline:
- "border [border-color:var(--button-outline)] shadow-xs active:shadow-none",
- secondary:
- "border bg-secondary text-secondary-foreground border border-secondary-border",
- ghost: "border border-transparent",
- link: "text-primary underline-offset-4 hover:underline",
- },
- size: {
- default: "min-h-9 px-4 py-2",
- sm: "min-h-8 rounded-md px-3 text-xs",
- lg: "min-h-10 rounded-md px-8",
- icon: "h-9 w-9",
- },
- },
- defaultVariants: {
- variant: "default",
- size: "default",
- },
- }
-)
-
-export interface ButtonProps
- extends React.ButtonHTMLAttributes,
- VariantProps {
- asChild?: boolean
-}
-
-const Button = React.forwardRef(
- ({ className, variant, size, asChild = false, ...props }, ref) => {
- const Comp = asChild ? Slot : "button"
- return (
-
- )
- }
-)
-Button.displayName = "Button"
-
-export { Button, buttonVariants }
diff --git a/artifacts/mockup-sandbox/src/components/ui/calendar.tsx b/artifacts/mockup-sandbox/src/components/ui/calendar.tsx
deleted file mode 100644
index a623682dab53fbe9e1777b83b2e93763837653d8..0000000000000000000000000000000000000000
--- a/artifacts/mockup-sandbox/src/components/ui/calendar.tsx
+++ /dev/null
@@ -1,213 +0,0 @@
-"use client"
-
-import * as React from "react"
-import {
- ChevronDownIcon,
- ChevronLeftIcon,
- ChevronRightIcon,
-} from "lucide-react"
-import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
-
-import { cn } from "@/lib/utils"
-import { Button, buttonVariants } from "@/components/ui/button"
-
-function Calendar({
- className,
- classNames,
- showOutsideDays = true,
- captionLayout = "label",
- buttonVariant = "ghost",
- formatters,
- components,
- ...props
-}: React.ComponentProps & {
- buttonVariant?: React.ComponentProps["variant"]
-}) {
- const defaultClassNames = getDefaultClassNames()
-
- return (
- svg]:rotate-180`,
- String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
- className
- )}
- captionLayout={captionLayout}
- formatters={{
- formatMonthDropdown: (date) =>
- date.toLocaleString("default", { month: "short" }),
- ...formatters,
- }}
- classNames={{
- root: cn("w-fit", defaultClassNames.root),
- months: cn(
- "relative flex flex-col gap-4 md:flex-row",
- defaultClassNames.months
- ),
- month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
- nav: cn(
- "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
- defaultClassNames.nav
- ),
- button_previous: cn(
- buttonVariants({ variant: buttonVariant }),
- "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
- defaultClassNames.button_previous
- ),
- button_next: cn(
- buttonVariants({ variant: buttonVariant }),
- "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
- defaultClassNames.button_next
- ),
- month_caption: cn(
- "flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]",
- defaultClassNames.month_caption
- ),
- dropdowns: cn(
- "flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium",
- defaultClassNames.dropdowns
- ),
- dropdown_root: cn(
- "has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border",
- defaultClassNames.dropdown_root
- ),
- dropdown: cn(
- "bg-popover absolute inset-0 opacity-0",
- defaultClassNames.dropdown
- ),
- caption_label: cn(
- "select-none font-medium",
- captionLayout === "label"
- ? "text-sm"
- : "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5",
- defaultClassNames.caption_label
- ),
- table: "w-full border-collapse",
- weekdays: cn("flex", defaultClassNames.weekdays),
- weekday: cn(
- "text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal",
- defaultClassNames.weekday
- ),
- week: cn("mt-2 flex w-full", defaultClassNames.week),
- week_number_header: cn(
- "w-[--cell-size] select-none",
- defaultClassNames.week_number_header
- ),
- week_number: cn(
- "text-muted-foreground select-none text-[0.8rem]",
- defaultClassNames.week_number
- ),
- day: cn(
- "group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md",
- defaultClassNames.day
- ),
- range_start: cn(
- "bg-accent rounded-l-md",
- defaultClassNames.range_start
- ),
- range_middle: cn("rounded-none", defaultClassNames.range_middle),
- range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end),
- today: cn(
- "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
- defaultClassNames.today
- ),
- outside: cn(
- "text-muted-foreground aria-selected:text-muted-foreground",
- defaultClassNames.outside
- ),
- disabled: cn(
- "text-muted-foreground opacity-50",
- defaultClassNames.disabled
- ),
- hidden: cn("invisible", defaultClassNames.hidden),
- ...classNames,
- }}
- components={{
- Root: ({ className, rootRef, ...props }) => {
- return (
-
- )
- },
- Chevron: ({ className, orientation, ...props }) => {
- if (orientation === "left") {
- return (
-
- )
- }
-
- if (orientation === "right") {
- return (
-
- )
- }
-
- return (
-
- )
- },
- DayButton: CalendarDayButton,
- WeekNumber: ({ children, ...props }) => {
- return (
-
-
- {children}
-
- |
- )
- },
- ...components,
- }}
- {...props}
- />
- )
-}
-
-function CalendarDayButton({
- className,
- day,
- modifiers,
- ...props
-}: React.ComponentProps) {
- const defaultClassNames = getDefaultClassNames()
-
- const ref = React.useRef(null)
- React.useEffect(() => {
- if (modifiers.focused) ref.current?.focus()
- }, [modifiers.focused])
-
- return (
-