diff --git a/.github/workflows/frontend-tests.yaml b/.github/workflows/frontend-tests.yaml index 4ee2617d7..ffac902a4 100644 --- a/.github/workflows/frontend-tests.yaml +++ b/.github/workflows/frontend-tests.yaml @@ -29,7 +29,7 @@ jobs: cache: "pnpm" - name: Install dependencies - run: pnpm install --frozen-lockfile --filter=testing-view --filter=flashing-view --filter=competition-view --filter=logging-view --filter=adj-view --filter=ui --filter=core + run: pnpm install --frozen-lockfile --filter="./frontend/**" - name: Build frontend run: pnpm build --filter="./frontend/**" diff --git a/.github/workflows/publish-frontend-kit.yaml b/.github/workflows/publish-frontend-kit.yaml new file mode 100644 index 000000000..ee6d1ac4f --- /dev/null +++ b/.github/workflows/publish-frontend-kit.yaml @@ -0,0 +1,202 @@ +name: Publish Frontend Kit + +# Publishes @hyperloop-upv/frontend-kit to GitHub Packages so a frontend in +# another repository can install it. +# +# Normally runs as part of release.yaml, at the same version as the Control +# Station, so the two always ship together. Can also be dispatched on its own +# to cut a kit-only release. +# +# As with electron-app, the version is injected here and is not committed: the +# number in package.json is a placeholder, and the git tag created by +# release.yaml is the record of what was published from which commit. +# +# A published version can never be reused. Deleting it does not free the +# number: if 11.3.2 is wrong, publish 11.3.3. + +on: + workflow_call: + inputs: + version: + description: "Version to publish, without a leading v" + required: true + type: string + dry-run: + description: "Pack and check only, do not publish" + type: boolean + default: true + tag: + description: "npm dist-tag. Derived from the version when empty" + type: string + default: "" + workflow_dispatch: + inputs: + version: + description: "Version to publish (e.g., 11.3.2)" + required: true + dry-run: + description: "Pack and check only, do not publish" + type: boolean + default: true + tag: + description: "npm dist-tag. Leave empty to derive it from the version" + default: "" + +jobs: + publish: + name: Publish @hyperloop-upv/frontend-kit + runs-on: ubuntu-latest + permissions: + contents: read + # Not the default. Without it, publishing fails with a bare 403. + packages: write + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 10.26.0 + + - uses: actions/setup-node@v4 + with: + node-version: "24" + cache: "pnpm" + # Writes an auth-ready npmrc outside the working tree, so the git + # tree stays clean. + registry-url: "https://npm.pkg.github.com" + scope: "@hyperloop-upv" + + - name: Resolve version and dist-tag + id: resolve + shell: bash + run: | + set -euo pipefail + + # release.yaml tags as v, so accept either spelling. + version="${{ inputs.version }}" + version="${version#v}" + + if [ -z "$version" ]; then + echo "::error::version is empty" + exit 1 + fi + + requested="${{ inputs.tag }}" + if [ -n "$requested" ]; then + tag="$requested" + elif [ "${version#*-}" != "$version" ]; then + # A prerelease such as 11.3.2-beta-2 must not land on "latest", or + # it becomes the default install for every consumer. + tag="next" + else + tag="latest" + fi + + echo "version=$version" >> $GITHUB_OUTPUT + echo "tag=$tag" >> $GITHUB_OUTPUT + echo "publishing $version under dist-tag $tag" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + # Same approach as electron-app in release.yaml: set it here, do not + # expect it committed. + - name: Set the version + working-directory: frontend/frontend-kit/kit + run: pnpm version ${{ steps.resolve.outputs.version }} --no-git-tag-version --allow-same-version + + - name: Build + run: pnpm build --filter=@hyperloop-upv/frontend-kit + + - name: Pack + shell: bash + run: | + set -euo pipefail + mkdir -p /tmp/kit + pnpm --filter @hyperloop-upv/frontend-kit exec pnpm pack --pack-destination /tmp/kit + echo "::group::Tarball contents" + tar -tzf /tmp/kit/hyperloop-upv-frontend-kit-${{ steps.resolve.outputs.version }}.tgz | sort + echo "::endgroup::" + + # Catches the failures that are cheap to prevent and impossible to undo + # once a version is published. + - name: Check the tarball + shell: bash + run: | + set -euo pipefail + T=/tmp/kit/hyperloop-upv-frontend-kit-${{ steps.resolve.outputs.version }}.tgz + + # Via a file, not a pipe: a heredoc would occupy stdin and the + # script would read nothing. + tar -xzOf "$T" package/package.json > /tmp/kit/packed.json + + EXPECTED_VERSION="${{ steps.resolve.outputs.version }}" python3 - <<'PY' + import json, os, sys + + p = json.load(open("/tmp/kit/packed.json")) + failures = [] + + def check(cond, msg): + print((" ok " if cond else " FAIL ") + msg) + if not cond: + failures.append(msg) + + check( + p["version"] == os.environ["EXPECTED_VERSION"], + f"version is {os.environ['EXPECTED_VERSION']}, got {p['version']}", + ) + check(not p.get("private"), "private:true does not survive") + check("preinstall" not in p.get("scripts", {}), "the preinstall hook does not survive") + check( + p["exports"]["."]["default"].startswith("./dist"), + "publishConfig.exports was applied (npm publish would skip it)", + ) + check(p["exports"]["./core"]["default"] == "./dist/core/index.js", "./core points at dist") + check( + p["exports"]["./globals.css"] == "./src/styles/globals.css", + "globals.css is served from the shipped src, so Tailwind can scan it", + ) + check( + set(p.get("peerDependencies", {})) + >= {"react", "react-dom", "lucide-react", "tailwindcss", "tw-animate-css"}, + "the five peer dependencies are declared", + ) + check( + not any(str(v).startswith("workspace:") for v in p.get("dependencies", {}).values()), + "no literal workspace: range leaked into the tarball", + ) + + if failures: + sys.exit("\nRefusing to publish: " + "; ".join(failures)) + print("\ntarball ok") + PY + + # Tailwind needs the kit's sources to find its classes in node_modules. + tar -tzf "$T" | grep -qx 'package/src/components/shadcn/sidebar.tsx' \ + || { echo "::error::src/ is missing from the tarball"; exit 1; } + echo " ok src/ ships alongside dist/" + + - uses: actions/upload-artifact@v4 + with: + name: frontend-kit-${{ steps.resolve.outputs.version }} + path: /tmp/kit/*.tgz + retention-days: 7 + + # Fails closed: anything other than an explicit boolean false skips this. + - name: Publish + if: ${{ inputs.dry-run == false }} + run: pnpm publish --filter=@hyperloop-upv/frontend-kit --no-git-checks --tag ${{ steps.resolve.outputs.tag }} + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Summary + shell: bash + run: | + V='${{ steps.resolve.outputs.version }}' + if [ '${{ inputs.dry-run }}' = 'true' ]; then + echo "### Dry run: nothing was published" >> $GITHUB_STEP_SUMMARY + echo "Tarball for \`$V\` is attached as an artifact. Re-run with dry-run off to publish." >> $GITHUB_STEP_SUMMARY + else + echo "### Published \`@hyperloop-upv/frontend-kit@$V\`" >> $GITHUB_STEP_SUMMARY + echo "dist-tag: \`${{ steps.resolve.outputs.tag }}\`" >> $GITHUB_STEP_SUMMARY + fi diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 11e23b750..8ee9c41cf 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -30,6 +30,10 @@ on: description: "Include ADJ Viewer" type: boolean default: true + publish-kit: + description: "Publish @hyperloop-upv/frontend-kit at this same version" + type: boolean + default: true jobs: @@ -44,6 +48,7 @@ jobs: include_flashing: ${{ steps.get_version.outputs.include_flashing }} include_logging: ${{ steps.get_version.outputs.include_logging }} include_adj: ${{ steps.get_version.outputs.include_adj }} + publish_kit: ${{ steps.get_version.outputs.publish_kit }} steps: - name: Determine version id: get_version @@ -55,6 +60,7 @@ jobs: echo "include_flashing=${{ github.event.inputs.include-flashing }}" >> $GITHUB_OUTPUT echo "include_logging=${{ github.event.inputs.include-logging }}" >> $GITHUB_OUTPUT echo "include_adj=${{ github.event.inputs.include-adj }}" >> $GITHUB_OUTPUT + echo "publish_kit=${{ github.event.inputs.publish-kit }}" >> $GITHUB_OUTPUT create-draft-release: name: Create Draft Release @@ -380,3 +386,18 @@ jobs: | xargs gh release upload v${{ needs.determine-version.outputs.version }} --clobber env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + publish-frontend-kit: + name: Publish Frontend Kit + # Last, and only once the Control Station release itself succeeded: + # publishing to the registry cannot be undone, so it must not happen for a + # release that failed to build. + needs: [determine-version, package-and-upload] + if: needs.determine-version.outputs.publish_kit == 'true' + permissions: + contents: read + packages: write + uses: ./.github/workflows/publish-frontend-kit.yaml + with: + version: ${{ needs.determine-version.outputs.version }} + dry-run: false diff --git a/.gitignore b/.gitignore index bc66fec72..261bb754d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,9 @@ node_modules/ # Global binaries *.exe +# Build output +dist/ + # electron modules electron-app/python electron-app/logger diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..3aa5e8bf2 --- /dev/null +++ b/.npmrc @@ -0,0 +1,11 @@ +; Where to look for the @hyperloop-upv scope. Needed so that `pnpm publish` +; targets GitHub Packages instead of npmjs.com. +; +; Deliberately no auth token line here: every @hyperloop-upv/* dependency in +; this monorepo is a workspace link, so pnpm never contacts the registry and +; nobody needs a token to install. Adding _authToken=${NODE_AUTH_TOKEN} would +; make `pnpm install` fail for anyone without that variable set. +; +; That holds only while no @hyperloop-upv/* dependency here comes from the +; registry. If one ever does, auth becomes mandatory for all contributors. +@hyperloop-upv:registry=https://npm.pkg.github.com diff --git a/README.md b/README.md index ebbe5a239..ea2a5c2d7 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,9 @@ Our `pnpm-workspace.yaml` defines the following workspaces: | `blcu-programming` | Python | FastAPI service that flashes firmware to the BLCU board via TFTP | | `hyperloop-control-station` | JS | The main Control Station electron desktop application | | `e2e` | TS | End-to-end tests for the whole app (Playwright) | -| `@workspace/ui` | TS/React | Shared UI component library (frontend-kit) | -| `@workspace/core` | TS | Shared business logic and types (frontend-kit) | -| `@workspace/eslint-config` | ESLint | Common ESLint configuration (frontend-kit) | -| `@workspace/typescript-config` | TS | Common TypeScript configuration (frontend-kit) | +| `@hyperloop-upv/frontend-kit` | TS/React | Shared UI components, hooks, icons and the WebSocket layer (its `./core` subpath) | +| `@hyperloop-upv/eslint-config` | ESLint | Common ESLint configuration (frontend-kit) | +| `@hyperloop-upv/typescript-config` | TS | Common TypeScript configuration (frontend-kit) | --- @@ -82,4 +81,4 @@ All Turbo scripts support filtering to target specific workspaces: - `pnpm ui:add ` - To add shadcn/ui components - > Note: don't forget to also include it in frontend-kit/ui/src/components/shadcn/index.ts to be able to access it from @workspace/ui \ No newline at end of file + > Note: don't forget to also include it in frontend-kit/kit/src/components/shadcn/index.ts to be able to access it from @hyperloop-upv/frontend-kit \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md index 1e8e97ab0..aba6db2f5 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -15,10 +15,9 @@ The frontend is organized as 7 workspaces out of 10 in the whole monorepo, divid | `testing-view` | Primary telemetry testing and debugging interface | | `competition-view` | Competition-focused UI (simplified view) | | `flashing-view` | UI for flashing firmware to the BLCU board | -| `frontend-kit/ui` or `@workspace/ui` | Component library built on shadcn/ui and Radix UI | -| `frontend-kit/core` or `@workspace/core` | Shared business logic, WebSocket utilities, and types | -| `frontend-kit/eslint-config` or `@workspace/eslint-config` | Common ESLint configurations | -| `frontend-kit/typescript-config` or `@workspace/typescript-config` | Common TypeScript configurations | +| `frontend-kit/kit` or `@hyperloop-upv/frontend-kit` | Component library built on shadcn/ui and Radix UI, plus the framework-agnostic `./core` subpath (WebSocket, logging, types) | +| `frontend-kit/eslint-config` or `@hyperloop-upv/eslint-config` | Common ESLint configurations | +| `frontend-kit/typescript-config` or `@hyperloop-upv/typescript-config` | Common TypeScript configurations | ## Key Technologies @@ -66,7 +65,7 @@ Testing View supports multiple workspaces to organize different testing scenario The frontend connects to the Go backend via WebSocket for real-time communication: -- **Connection**: `useWebSocket` hook from `@workspace/core` +- **Connection**: `useWebSocket` hook from `@hyperloop-upv/frontend-kit/core` - **Topics**: Subscribe to specific data streams using `useTopic` - `podData/update` - Telemetry data - `connection/update` - Backend connection status @@ -76,8 +75,8 @@ The frontend connects to the Go backend via WebSocket for real-time communicatio Example: ```tsx -import { useTopic, useWebSocket } from "@workspace/ui/hooks"; -import { socketService } from "@workspace/core"; +import { useTopic, useWebSocket } from "@hyperloop-upv/frontend-kit/hooks"; +import { socketService } from "@hyperloop-upv/frontend-kit/core"; const { isConnected } = useWebSocket(); @@ -88,7 +87,7 @@ useTopic("podData/update", (data) => { socketService.post("order/send", ); ``` -## Component Library (@workspace/ui) +## Component Library (@hyperloop-upv/frontend-kit) The shared UI package provides: @@ -97,11 +96,11 @@ The shared UI package provides: - Hooks (useWebSocket, useTopic, useLogger) - Icons from Lucide React -Import components from `@workspace/ui`: +Import components from `@hyperloop-upv/frontend-kit`: ```tsx -import { Button, Dialog } from "@workspace/ui"; -import { Plus, Settings } from "@workspace/ui/icons"; +import { Button, Dialog } from "@hyperloop-upv/frontend-kit"; +import { Plus, Settings } from "@hyperloop-upv/frontend-kit/icons"; ``` ## Development Patterns @@ -119,14 +118,14 @@ To add a new Lucide icon to the shared UI library: 1. Look up the icon on [Lucide Icons](https://lucide.dev/icons) 2. Find the **first category** listed for that icon -3. Add the import to the corresponding category file in `frontend-kit/ui/src/icons/` +3. Add the import to the corresponding category file in `frontend-kit/kit/src/icons/` 4. If the category file doesn't exist, create it and add its export to `index.ts` 5. Keep the same alphabetical order as the icon categories **Example:** The `Axe` icon's first category is `Tools`, so you would add its import to `tools.ts`: ```js -// frontend-kit/ui/src/icons/tools.ts +// frontend-kit/kit/src/icons/tools.ts export { Axe, Hammer } from "lucide-react"; ``` diff --git a/frontend/adj-view/CLAUDE.md b/frontend/adj-view/CLAUDE.md index c248655aa..8cae41649 100644 --- a/frontend/adj-view/CLAUDE.md +++ b/frontend/adj-view/CLAUDE.md @@ -76,21 +76,21 @@ A what-if estimate of each board's link usage, computed only from the ADJ and th ### Workspace dependency -Only shared package used is `@workspace/ui` (from `frontend-kit/ui`), for shadcn/Radix components, Lucide icons, and small utilities (`cn`, `getTypeBadgeClass`/`typeBadgeClasses` from `@workspace/ui/lib`): +Only shared package used is `@hyperloop-upv/frontend-kit` (from `frontend-kit/kit`), for shadcn/Radix components, Lucide icons, and small utilities (`cn`, `getTypeBadgeClass`/`typeBadgeClasses` from `@hyperloop-upv/frontend-kit/lib`): ```tsx -import { Button, Combobox } from "@workspace/ui/components"; -import { BookOpen, GitCommit } from "@workspace/ui/icons"; -import { cn, getTypeBadgeClass, typeBadgeClasses } from "@workspace/ui/lib"; +import { Button, Combobox } from "@hyperloop-upv/frontend-kit/components"; +import { BookOpen, GitCommit } from "@hyperloop-upv/frontend-kit/icons"; +import { cn, getTypeBadgeClass, typeBadgeClasses } from "@hyperloop-upv/frontend-kit/lib"; ``` -No `@workspace/core` dependency (no WebSocket/backend integration here). +No `@hyperloop-upv/frontend-kit/core` dependency (no WebSocket/backend integration here). ### Styling Tailwind v4 with CSS-variable theming, dark mode via `.dark` class on `` (toggled in `App.tsx`, persisted to `localStorage["adj-view-dark-mode"]`). `NetworkTab`'s SVG reads the same CSS variables (`var(--primary)`, `var(--foreground)`, etc.) directly in inline styles so the diagram adapts automatically between themes. UI copy is English (sentence case, no all-caps labels); numbers use `tabular-nums` rather than a monospace font. -Branding: the header and empty state use the team mark `@workspace/ui/outreach/main/logo_icon.svg` (not the H11 isotype the other views use), via `TeamLogo` in `AdjViewerPage.tsx`. The header pairs it with the software-team logo (`outreach/main/software_black.png` + `dark:invert`; don't use `software_white.png`, which is 8000 px / 430 KB). That SVG draws the mark in only the middle ~49% of its 900×900 viewBox, so `TeamLogo` scales the image up inside a clipped box; a plain `` renders it tiny. +Branding: the header and empty state use the team mark `@hyperloop-upv/frontend-kit/outreach/main/logo_icon.svg` (not the H11 isotype the other views use), via `TeamLogo` in `AdjViewerPage.tsx`. The header pairs it with the software-team logo (`outreach/main/software_black.png` + `dark:invert`; don't use `software_white.png`, which is 8000 px / 430 KB). That SVG draws the mark in only the middle ~49% of its 900×900 viewBox, so `TeamLogo` scales the image up inside a clipped box; a plain `` renders it tiny. The layout must work down to phone width (check 390 / 768 / 1440 px) without the page scrolling sideways. The header wraps into title + theme toggle, then a full-width row of load controls below `lg`. The tab bar scrolls inside itself, and wide tables and the Network SVG scroll inside their own containers. diff --git a/frontend/adj-view/eslint.config.js b/frontend/adj-view/eslint.config.js index df360b435..a2b580035 100644 --- a/frontend/adj-view/eslint.config.js +++ b/frontend/adj-view/eslint.config.js @@ -1,3 +1,3 @@ -import { config } from "@workspace/eslint-config/vite"; +import { config } from "@hyperloop-upv/eslint-config/vite"; export default config; diff --git a/frontend/adj-view/package.json b/frontend/adj-view/package.json index 21d527ed4..1bfbc55f3 100644 --- a/frontend/adj-view/package.json +++ b/frontend/adj-view/package.json @@ -13,7 +13,7 @@ "dependencies": { "@tailwindcss/vite": "^4.1.18", "@vitejs/plugin-react-swc": "^4.2.3", - "@workspace/ui": "workspace:*", + "@hyperloop-upv/frontend-kit": "workspace:*", "lucide-react": "^0.563.0", "react": "^19.2.4", "react-dom": "^19.2.4", @@ -22,8 +22,8 @@ "devDependencies": { "@types/react": "19.2.11", "@types/react-dom": "19.2.3", - "@workspace/eslint-config": "workspace:^", - "@workspace/typescript-config": "workspace:*", + "@hyperloop-upv/eslint-config": "workspace:^", + "@hyperloop-upv/typescript-config": "workspace:*", "eslint": "^9.39.2", "typescript": "^5.9.3", "vite": "^7.3.1" diff --git a/frontend/adj-view/src/adj/v2/AdjViewerTabs.tsx b/frontend/adj-view/src/adj/v2/AdjViewerTabs.tsx index 630d95c99..dba4c2c8d 100644 --- a/frontend/adj-view/src/adj/v2/AdjViewerTabs.tsx +++ b/frontend/adj-view/src/adj/v2/AdjViewerTabs.tsx @@ -7,7 +7,7 @@ import { TabsContent, TabsList, TabsTrigger, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; import { Activity, ChevronDown, @@ -19,8 +19,8 @@ import { Plug, Server, TrendingUp, -} from "@workspace/ui/icons"; -import { cn, getTypeBadgeClass, typeBadgeClasses } from "@workspace/ui/lib"; +} from "@hyperloop-upv/frontend-kit/icons"; +import { cn, getTypeBadgeClass, typeBadgeClasses } from "@hyperloop-upv/frontend-kit/lib"; import { Fragment, useCallback, useMemo, useRef, useState } from "react"; import type { AdjArchiveV2, AdjMeasurement, AdjPacket, AdjSocket } from "./types"; import { NetworkTab } from "./NetworkTab"; diff --git a/frontend/adj-view/src/adj/v2/NetworkTab.tsx b/frontend/adj-view/src/adj/v2/NetworkTab.tsx index 63de5afb7..73d80b311 100644 --- a/frontend/adj-view/src/adj/v2/NetworkTab.tsx +++ b/frontend/adj-view/src/adj/v2/NetworkTab.tsx @@ -11,7 +11,7 @@ import { boardPort, protocolFromSocketType, resolveTarget, type Protocol } from // Hyperloop UPV's actual brand palette (no separate secondary brand color // documented anywhere in the repo) — --primary is the brand orange, and // --foreground pairs it with black/white, matching the logo assets under -// frontend-kit/ui/src/outreach. Both adapt automatically in light/dark mode. +// frontend-kit/kit/src/outreach. Both adapt automatically in light/dark mode. const PROTOCOL_COLOR: Record = { TCP: "var(--foreground)", // bidirectional UDP: "var(--primary)", // unidirectional: board → backend diff --git a/frontend/adj-view/src/adj/v2/SocketsTab.tsx b/frontend/adj-view/src/adj/v2/SocketsTab.tsx index 7df69831d..11b661e60 100644 --- a/frontend/adj-view/src/adj/v2/SocketsTab.tsx +++ b/frontend/adj-view/src/adj/v2/SocketsTab.tsx @@ -1,9 +1,9 @@ // Sockets tab: every socket declared in the ADJ, one row each, with the board // side, where it points, the general_info port name, and the packets that use it. // All socket interpretation comes from sockets.ts, shared with the Network tab. -import { Badge } from "@workspace/ui/components"; -import { AlertTriangle, ChevronDown, ExternalLink } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { Badge } from "@hyperloop-upv/frontend-kit/components"; +import { AlertTriangle, ChevronDown, ExternalLink } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { Fragment, useMemo, useRef, useState } from "react"; import type { BoardMeta } from "./AdjViewerTabs"; import { diff --git a/frontend/adj-view/src/adj/v2/ThroughputHelp.tsx b/frontend/adj-view/src/adj/v2/ThroughputHelp.tsx index 7f652257f..82f1f7cee 100644 --- a/frontend/adj-view/src/adj/v2/ThroughputHelp.tsx +++ b/frontend/adj-view/src/adj/v2/ThroughputHelp.tsx @@ -9,8 +9,8 @@ import { SheetHeader, SheetTitle, SheetTrigger, -} from "@workspace/ui/components"; -import { BookOpen } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit/components"; +import { BookOpen } from "@hyperloop-upv/frontend-kit/icons"; import type { ReactNode } from "react"; import { ETH_FCS_BYTES, diff --git a/frontend/adj-view/src/adj/v2/ThroughputTab.tsx b/frontend/adj-view/src/adj/v2/ThroughputTab.tsx index 08c6bb98b..de70c0250 100644 --- a/frontend/adj-view/src/adj/v2/ThroughputTab.tsx +++ b/frontend/adj-view/src/adj/v2/ThroughputTab.tsx @@ -6,9 +6,9 @@ import { TooltipContent, TooltipProvider, TooltipTrigger, -} from "@workspace/ui/components"; -import { AlertTriangle, ChevronDown, ChevronRight, ChevronUp, Pencil } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +} from "@hyperloop-upv/frontend-kit/components"; +import { AlertTriangle, ChevronDown, ChevronRight, ChevronUp, Pencil } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { Fragment, useMemo, useRef, useState, type CSSProperties, type ReactNode } from "react"; import type { BoardMeta } from "./AdjViewerTabs"; import { ThroughputHelp } from "./ThroughputHelp"; diff --git a/frontend/adj-view/src/adj/v2/ui.tsx b/frontend/adj-view/src/adj/v2/ui.tsx index a844ff022..85c4bac9c 100644 --- a/frontend/adj-view/src/adj/v2/ui.tsx +++ b/frontend/adj-view/src/adj/v2/ui.tsx @@ -1,8 +1,8 @@ // Small presentational pieces shared by the v2 list tabs (Boards, Measurements, // Packets, Sockets). -import { Input } from "@workspace/ui/components"; -import { ChevronDown, ChevronUp, Search } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { Input } from "@hyperloop-upv/frontend-kit/components"; +import { ChevronDown, ChevronUp, Search } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; export type SortDir = "asc" | "desc"; diff --git a/frontend/adj-view/src/components/AdjViewerPage.tsx b/frontend/adj-view/src/components/AdjViewerPage.tsx index a1c0c6006..1596cff0d 100644 --- a/frontend/adj-view/src/components/AdjViewerPage.tsx +++ b/frontend/adj-view/src/components/AdjViewerPage.tsx @@ -14,12 +14,12 @@ import { TooltipContent, TooltipProvider, TooltipTrigger, -} from "@workspace/ui/components"; -import { AlertTriangle, GitCommit, Loader2, RefreshCw, SunMoon } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; -import logo from "@workspace/ui/outreach/main/logo_icon.svg"; +} from "@hyperloop-upv/frontend-kit/components"; +import { AlertTriangle, GitCommit, Loader2, RefreshCw, SunMoon } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; +import logo from "@hyperloop-upv/frontend-kit/outreach/main/logo_icon.svg"; // Black strokes on transparency; inverted in dark mode (software_white.png is 8000 px / 430 KB). -import softwareLogo from "@workspace/ui/outreach/main/software_black.png"; +import softwareLogo from "@hyperloop-upv/frontend-kit/outreach/main/software_black.png"; import { useCallback, useEffect, useState } from "react"; import { config } from "../../config"; import { parseAdj, summarizeAdj, type ParsedAdj } from "../adj"; diff --git a/frontend/adj-view/src/components/UnsupportedAdjNotice.tsx b/frontend/adj-view/src/components/UnsupportedAdjNotice.tsx index 61b0ec8c8..a6f45e1cf 100644 --- a/frontend/adj-view/src/components/UnsupportedAdjNotice.tsx +++ b/frontend/adj-view/src/components/UnsupportedAdjNotice.tsx @@ -1,4 +1,4 @@ -import { AlertTriangle } from "@workspace/ui/icons"; +import { AlertTriangle } from "@hyperloop-upv/frontend-kit/icons"; import { SUPPORTED_ADJ_VERSIONS } from "../adj"; export function UnsupportedAdjNotice({ version }: { version: number }) { diff --git a/frontend/adj-view/src/index.css b/frontend/adj-view/src/index.css index ebe6a1c75..67d14219d 100644 --- a/frontend/adj-view/src/index.css +++ b/frontend/adj-view/src/index.css @@ -1,7 +1,7 @@ -@import "@workspace/ui/globals.css"; +@import "@hyperloop-upv/frontend-kit/globals.css"; /* Ensure Tailwind v4 scans adj-view source files directly. - The @source paths in globals.css resolve via the @workspace/ui symlink + The @source paths in globals.css resolve via the @hyperloop-upv/frontend-kit symlink and don't correctly reach this project's source tree. */ @source "./**/*.{ts,tsx}"; diff --git a/frontend/adj-view/tsconfig.json b/frontend/adj-view/tsconfig.json index fc0aa4474..483ebaa0f 100644 --- a/frontend/adj-view/tsconfig.json +++ b/frontend/adj-view/tsconfig.json @@ -4,11 +4,5 @@ { "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" } ], - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@workspace/ui/*": ["../frontend-kit/ui/src/*"] - } - }, "exclude": ["node_modules"] } diff --git a/frontend/competition-view/eslint.config.js b/frontend/competition-view/eslint.config.js index df360b435..a2b580035 100644 --- a/frontend/competition-view/eslint.config.js +++ b/frontend/competition-view/eslint.config.js @@ -1,3 +1,3 @@ -import { config } from "@workspace/eslint-config/vite"; +import { config } from "@hyperloop-upv/eslint-config/vite"; export default config; diff --git a/frontend/competition-view/package.json b/frontend/competition-view/package.json index 462843d6a..a6457d8dc 100644 --- a/frontend/competition-view/package.json +++ b/frontend/competition-view/package.json @@ -15,8 +15,7 @@ "dependencies": { "@tailwindcss/vite": "^4.1.18", "@vitejs/plugin-react-swc": "^4.2.3", - "@workspace/core": "workspace:*", - "@workspace/ui": "workspace:*", + "@hyperloop-upv/frontend-kit": "workspace:*", "lucide-react": "^0.563.0", "react": "^19.2.4", "react-dom": "^19.2.4", @@ -28,8 +27,8 @@ "devDependencies": { "@types/react": "^19.2.11", "@types/react-dom": "^19.2.3", - "@workspace/eslint-config": "workspace:^", - "@workspace/typescript-config": "workspace:*", + "@hyperloop-upv/eslint-config": "workspace:^", + "@hyperloop-upv/typescript-config": "workspace:*", "eslint": "^9.39.2", "globals": "^17.3.0", "typescript": "^5.9.3", diff --git a/frontend/competition-view/src/App.tsx b/frontend/competition-view/src/App.tsx index 6299147bb..e9e89e547 100644 --- a/frontend/competition-view/src/App.tsx +++ b/frontend/competition-view/src/App.tsx @@ -1,4 +1,4 @@ -import { useTopic, useWebSocket } from "@workspace/ui/hooks"; +import { useTopic, useWebSocket } from "@hyperloop-upv/frontend-kit/hooks"; import { useState } from "react"; import { Route, Routes } from "react-router"; import ErrorBoundary from "./components/ErrorBoundary"; diff --git a/frontend/competition-view/src/components/ErrorBoundary.tsx b/frontend/competition-view/src/components/ErrorBoundary.tsx index c343d4178..a31dc88a7 100644 --- a/frontend/competition-view/src/components/ErrorBoundary.tsx +++ b/frontend/competition-view/src/components/ErrorBoundary.tsx @@ -1,5 +1,5 @@ -import { Button, Card, CardContent, CardHeader, CardTitle } from "@workspace/ui/components"; -import { AlertTriangle } from "@workspace/ui/icons"; +import { Button, Card, CardContent, CardHeader, CardTitle } from "@hyperloop-upv/frontend-kit/components"; +import { AlertTriangle } from "@hyperloop-upv/frontend-kit/icons"; import { Component, type ErrorInfo, type ReactNode } from "react"; interface Props { diff --git a/frontend/competition-view/src/components/KeyboardShortcutsHelp.tsx b/frontend/competition-view/src/components/KeyboardShortcutsHelp.tsx index 56e3200b7..5572745d4 100644 --- a/frontend/competition-view/src/components/KeyboardShortcutsHelp.tsx +++ b/frontend/competition-view/src/components/KeyboardShortcutsHelp.tsx @@ -4,8 +4,8 @@ import { DialogHeader, DialogTitle, Separator, -} from "@workspace/ui/components"; -import { Keyboard } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit/components"; +import { Keyboard } from "@hyperloop-upv/frontend-kit/icons"; import { SHORTCUT_DEFS } from "../hooks/useKeyboardShortcuts"; interface KeyboardShortcutsHelpProps { diff --git a/frontend/competition-view/src/components/header/ConnectionBadge.tsx b/frontend/competition-view/src/components/header/ConnectionBadge.tsx index 97f564253..3a140946e 100644 --- a/frontend/competition-view/src/components/header/ConnectionBadge.tsx +++ b/frontend/competition-view/src/components/header/ConnectionBadge.tsx @@ -1,4 +1,4 @@ -import { Badge } from "@workspace/ui/components"; +import { Badge } from "@hyperloop-upv/frontend-kit/components"; interface ConnectionBadgeProps { /** Clear label identifying what this badge reports on, e.g. "Backend" or "VCU". */ diff --git a/frontend/competition-view/src/components/header/DashboardStatusBar.tsx b/frontend/competition-view/src/components/header/DashboardStatusBar.tsx index ab4b3f1e8..e88552aac 100644 --- a/frontend/competition-view/src/components/header/DashboardStatusBar.tsx +++ b/frontend/competition-view/src/components/header/DashboardStatusBar.tsx @@ -1,4 +1,4 @@ -import { Separator } from "@workspace/ui/components"; +import { Separator } from "@hyperloop-upv/frontend-kit/components"; import { formatAxisValue } from "../../constants/chartConfig"; import { BOARDS, HVAL_THRESHOLD_V, HVBMS, VCU } from "../../constants/measurements"; import { useIsStale } from "../../hooks/useIsStale"; diff --git a/frontend/competition-view/src/components/header/Header.tsx b/frontend/competition-view/src/components/header/Header.tsx index ac107e9d7..1e1f2d6c3 100644 --- a/frontend/competition-view/src/components/header/Header.tsx +++ b/frontend/competition-view/src/components/header/Header.tsx @@ -1,4 +1,4 @@ -import { Separator, SidebarTrigger } from "@workspace/ui/components"; +import { Separator, SidebarTrigger } from "@hyperloop-upv/frontend-kit/components"; import { useLocation } from "react-router"; import { BOARDS } from "../../constants/measurements"; import { PAGES } from "../../constants/pages"; diff --git a/frontend/competition-view/src/components/header/HvalIndicator.tsx b/frontend/competition-view/src/components/header/HvalIndicator.tsx index 13443f853..1c05717d0 100644 --- a/frontend/competition-view/src/components/header/HvalIndicator.tsx +++ b/frontend/competition-view/src/components/header/HvalIndicator.tsx @@ -1,4 +1,4 @@ -import { Badge } from "@workspace/ui/components"; +import { Badge } from "@hyperloop-upv/frontend-kit/components"; import { useEffect, useState } from "react"; import { BOARDS, HVAL_THRESHOLD_V, HVBMS } from "../../constants/measurements"; import useMeasurement from "../../hooks/useMeasurement"; diff --git a/frontend/competition-view/src/components/header/OrdersSheet.tsx b/frontend/competition-view/src/components/header/OrdersSheet.tsx index 6b85490b5..fb14796bd 100644 --- a/frontend/competition-view/src/components/header/OrdersSheet.tsx +++ b/frontend/competition-view/src/components/header/OrdersSheet.tsx @@ -8,9 +8,9 @@ import { SheetTitle, SheetTrigger, Skeleton, -} from "@workspace/ui/components"; -import { Send } from "@workspace/ui/icons"; -import { useWebSocket } from "@workspace/ui/hooks"; +} from "@hyperloop-upv/frontend-kit/components"; +import { Send } from "@hyperloop-upv/frontend-kit/icons"; +import { useWebSocket } from "@hyperloop-upv/frontend-kit/hooks"; import { useState } from "react"; import useOrdersCatalog from "../../hooks/useOrdersCatalog"; import { useStore } from "../../store/store"; diff --git a/frontend/competition-view/src/components/sidebar/AboutItem.tsx b/frontend/competition-view/src/components/sidebar/AboutItem.tsx index 92c2bcc02..533752d99 100644 --- a/frontend/competition-view/src/components/sidebar/AboutItem.tsx +++ b/frontend/competition-view/src/components/sidebar/AboutItem.tsx @@ -5,10 +5,10 @@ import { DialogTitle, Separator, SidebarMenuButton, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; import { Info } from "lucide-react"; import { useState } from "react"; -import logo from "@workspace/ui/outreach/h11/h11-isotipo_black.svg"; +import logo from "@hyperloop-upv/frontend-kit/outreach/h11/h11-isotipo_black.svg"; /** * Sidebar footer item that opens the About dialog with team credits. diff --git a/frontend/competition-view/src/components/sidebar/AppSidebar.tsx b/frontend/competition-view/src/components/sidebar/AppSidebar.tsx index e6c79531b..c9217eaff 100644 --- a/frontend/competition-view/src/components/sidebar/AppSidebar.tsx +++ b/frontend/competition-view/src/components/sidebar/AppSidebar.tsx @@ -4,7 +4,7 @@ import { SidebarFooter, SidebarHeader, SidebarRail, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; import { PAGES_ARRAY } from "../../constants/pages"; import AboutItem from "./AboutItem"; import ConnectionStatusGroup from "./ConnectionStatusGroup"; diff --git a/frontend/competition-view/src/components/sidebar/ConnectionStatusGroup.tsx b/frontend/competition-view/src/components/sidebar/ConnectionStatusGroup.tsx index 76fff79cb..13a6000be 100644 --- a/frontend/competition-view/src/components/sidebar/ConnectionStatusGroup.tsx +++ b/frontend/competition-view/src/components/sidebar/ConnectionStatusGroup.tsx @@ -4,8 +4,8 @@ import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, -} from "@workspace/ui/components"; -import { Plug, Unplug } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit/components"; +import { Plug, Unplug } from "@hyperloop-upv/frontend-kit/icons"; import useConnections from "../../hooks/useConnections"; interface ConnectionStatusGroupProps { diff --git a/frontend/competition-view/src/components/sidebar/LoggerItem.tsx b/frontend/competition-view/src/components/sidebar/LoggerItem.tsx index 5f6894133..d616ef758 100644 --- a/frontend/competition-view/src/components/sidebar/LoggerItem.tsx +++ b/frontend/competition-view/src/components/sidebar/LoggerItem.tsx @@ -1,5 +1,5 @@ -import { SidebarMenuButton } from "@workspace/ui/components"; -import { cn } from "@workspace/ui/lib"; +import { SidebarMenuButton } from "@hyperloop-upv/frontend-kit/components"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { LOGGER_CONTROL_CONFIG } from "../../constants/loggerControlConfig"; import { useLogger } from "../../hooks/useLogger"; diff --git a/frontend/competition-view/src/components/sidebar/Logo.tsx b/frontend/competition-view/src/components/sidebar/Logo.tsx index e11cff854..f6e23de99 100644 --- a/frontend/competition-view/src/components/sidebar/Logo.tsx +++ b/frontend/competition-view/src/components/sidebar/Logo.tsx @@ -1,6 +1,6 @@ -import { SidebarMenuButton } from "@workspace/ui/components"; +import { SidebarMenuButton } from "@hyperloop-upv/frontend-kit/components"; import { Link } from "react-router"; -import logo from "@workspace/ui/outreach/h11/h11-isotipo_black.svg"; +import logo from "@hyperloop-upv/frontend-kit/outreach/h11/h11-isotipo_black.svg"; const Logo = () => ( diff --git a/frontend/competition-view/src/components/sidebar/NavigationGroup.tsx b/frontend/competition-view/src/components/sidebar/NavigationGroup.tsx index 41da64c38..09380d3c4 100644 --- a/frontend/competition-view/src/components/sidebar/NavigationGroup.tsx +++ b/frontend/competition-view/src/components/sidebar/NavigationGroup.tsx @@ -4,8 +4,8 @@ import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, -} from "@workspace/ui/components"; -import { type LucideIcon } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit/components"; +import { type LucideIcon } from "@hyperloop-upv/frontend-kit/icons"; import { Link, useLocation } from "react-router"; interface NavItem { diff --git a/frontend/competition-view/src/components/sidebar/ShortcutsItem.tsx b/frontend/competition-view/src/components/sidebar/ShortcutsItem.tsx index 6ec99f0c3..458416316 100644 --- a/frontend/competition-view/src/components/sidebar/ShortcutsItem.tsx +++ b/frontend/competition-view/src/components/sidebar/ShortcutsItem.tsx @@ -1,5 +1,5 @@ -import { SidebarMenuButton } from "@workspace/ui/components"; -import { Keyboard } from "@workspace/ui/icons"; +import { SidebarMenuButton } from "@hyperloop-upv/frontend-kit/components"; +import { Keyboard } from "@hyperloop-upv/frontend-kit/icons"; interface ShortcutsItemProps { onShowShortcuts: () => void; diff --git a/frontend/competition-view/src/components/sidebar/ThemeToggleItem.tsx b/frontend/competition-view/src/components/sidebar/ThemeToggleItem.tsx index 79867f748..c8e228801 100644 --- a/frontend/competition-view/src/components/sidebar/ThemeToggleItem.tsx +++ b/frontend/competition-view/src/components/sidebar/ThemeToggleItem.tsx @@ -1,5 +1,5 @@ -import { SidebarMenuButton } from "@workspace/ui/components"; -import { SunMoon } from "@workspace/ui/icons"; +import { SidebarMenuButton } from "@hyperloop-upv/frontend-kit/components"; +import { SunMoon } from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../store/store"; const ThemeToggleItem = () => { diff --git a/frontend/competition-view/src/constants/loggerControlConfig.tsx b/frontend/competition-view/src/constants/loggerControlConfig.tsx index 02b9ea10a..67dfae3ee 100644 --- a/frontend/competition-view/src/constants/loggerControlConfig.tsx +++ b/frontend/competition-view/src/constants/loggerControlConfig.tsx @@ -1,4 +1,4 @@ -import { AlertCircle, Loader2, Play, Square } from "@workspace/ui/icons"; +import { AlertCircle, Loader2, Play, Square } from "@hyperloop-upv/frontend-kit/icons"; import type { LoggerStatus } from "../types/logger"; interface LoggerControlOption { diff --git a/frontend/competition-view/src/constants/pages.ts b/frontend/competition-view/src/constants/pages.ts index bcc269e15..69f4ab322 100644 --- a/frontend/competition-view/src/constants/pages.ts +++ b/frontend/competition-view/src/constants/pages.ts @@ -1,4 +1,4 @@ -import { Battery, Layout, MessageSquare } from "@workspace/ui/icons"; +import { Battery, Layout, MessageSquare } from "@hyperloop-upv/frontend-kit/icons"; export const PAGES = { "/": { title: "Competition View", icon: Layout }, diff --git a/frontend/competition-view/src/hooks/useLogger.ts b/frontend/competition-view/src/hooks/useLogger.ts index 96ba34c9a..aec3dce7c 100644 --- a/frontend/competition-view/src/hooks/useLogger.ts +++ b/frontend/competition-view/src/hooks/useLogger.ts @@ -1,5 +1,5 @@ -import { logger, socketService } from "@workspace/core"; -import { useTopic } from "@workspace/ui/hooks"; +import { logger, socketService } from "@hyperloop-upv/frontend-kit/core"; +import { useTopic } from "@hyperloop-upv/frontend-kit/hooks"; import { useEffect, useState } from "react"; import type { LoggerStatus } from "../types/logger"; diff --git a/frontend/competition-view/src/hooks/useOrdersCatalog.ts b/frontend/competition-view/src/hooks/useOrdersCatalog.ts index a838165e4..86db9259a 100644 --- a/frontend/competition-view/src/hooks/useOrdersCatalog.ts +++ b/frontend/competition-view/src/hooks/useOrdersCatalog.ts @@ -1,4 +1,4 @@ -import { useFetchConfig } from "@workspace/ui/hooks"; +import { useFetchConfig } from "@hyperloop-upv/frontend-kit/hooks"; import { useEffect } from "react"; import { useStore } from "../store/store"; import type { OrdersData } from "../types/catalog"; diff --git a/frontend/competition-view/src/hooks/usePodCatalog.ts b/frontend/competition-view/src/hooks/usePodCatalog.ts index 2d414132a..92adf9ef8 100644 --- a/frontend/competition-view/src/hooks/usePodCatalog.ts +++ b/frontend/competition-view/src/hooks/usePodCatalog.ts @@ -1,4 +1,4 @@ -import { useFetchConfig, useWebSocket } from "@workspace/ui/hooks"; +import { useFetchConfig, useWebSocket } from "@hyperloop-upv/frontend-kit/hooks"; import { useEffect } from "react"; import { useStore } from "../store/store"; diff --git a/frontend/competition-view/src/hooks/useSendOrder.ts b/frontend/competition-view/src/hooks/useSendOrder.ts index 1ce0fc966..b0f7dbd0c 100644 --- a/frontend/competition-view/src/hooks/useSendOrder.ts +++ b/frontend/competition-view/src/hooks/useSendOrder.ts @@ -1,4 +1,4 @@ -import { logger, socketService } from "@workspace/core"; +import { logger, socketService } from "@hyperloop-upv/frontend-kit/core"; import { useCallback } from "react"; import type { Order } from "../constants/orders"; diff --git a/frontend/competition-view/src/index.css b/frontend/competition-view/src/index.css index e7caa9cec..0477b43b7 100644 --- a/frontend/competition-view/src/index.css +++ b/frontend/competition-view/src/index.css @@ -1,7 +1,7 @@ -@import "@workspace/ui/globals.css"; +@import "@hyperloop-upv/frontend-kit/globals.css"; /* Ensure Tailwind v4 scans competition-view source files directly. - The @source paths in globals.css resolve via the @workspace/ui symlink + The @source paths in globals.css resolve via the @hyperloop-upv/frontend-kit symlink and don't correctly reach this project's source tree. */ @source "./**/*.{ts,tsx}"; diff --git a/frontend/competition-view/src/layout/AppLayout.tsx b/frontend/competition-view/src/layout/AppLayout.tsx index f9d3b8d39..91ec01225 100644 --- a/frontend/competition-view/src/layout/AppLayout.tsx +++ b/frontend/competition-view/src/layout/AppLayout.tsx @@ -1,4 +1,4 @@ -import { SidebarInset, SidebarProvider } from "@workspace/ui/components"; +import { SidebarInset, SidebarProvider } from "@hyperloop-upv/frontend-kit/components"; import { useEffect, type ReactNode } from "react"; import Header from "../components/header/Header"; import AppSidebar from "../components/sidebar/AppSidebar"; diff --git a/frontend/competition-view/src/pages/Messages/Messages.tsx b/frontend/competition-view/src/pages/Messages/Messages.tsx index 8df2d0c84..f81c5b379 100644 --- a/frontend/competition-view/src/pages/Messages/Messages.tsx +++ b/frontend/competition-view/src/pages/Messages/Messages.tsx @@ -1,5 +1,5 @@ -import { Button, Separator, Slider } from "@workspace/ui/components"; -import { ChevronDown } from "@workspace/ui/icons"; +import { Button, Separator, Slider } from "@hyperloop-upv/frontend-kit/components"; +import { ChevronDown } from "@hyperloop-upv/frontend-kit/icons"; import { useEffect, useRef, useState } from "react"; import { useStore } from "../../store/store"; import type { MessageKind } from "../../types/message"; diff --git a/frontend/competition-view/src/pages/Messages/components/MessageItem.tsx b/frontend/competition-view/src/pages/Messages/components/MessageItem.tsx index a37f267d8..f2ce37091 100644 --- a/frontend/competition-view/src/pages/Messages/components/MessageItem.tsx +++ b/frontend/competition-view/src/pages/Messages/components/MessageItem.tsx @@ -1,4 +1,4 @@ -import { Badge } from "@workspace/ui/components"; +import { Badge } from "@hyperloop-upv/frontend-kit/components"; import { memo } from "react"; import { formatMessageTimestamp, messageContent } from "../../../lib/message"; import type { Message, MessageKind } from "../../../types/message"; diff --git a/frontend/competition-view/src/pages/Orders/Orders.tsx b/frontend/competition-view/src/pages/Orders/Orders.tsx index cf432b6e8..611706ca9 100644 --- a/frontend/competition-view/src/pages/Orders/Orders.tsx +++ b/frontend/competition-view/src/pages/Orders/Orders.tsx @@ -1,5 +1,5 @@ -import { Skeleton } from "@workspace/ui/components"; -import { useWebSocket } from "@workspace/ui/hooks"; +import { Skeleton } from "@hyperloop-upv/frontend-kit/components"; +import { useWebSocket } from "@hyperloop-upv/frontend-kit/hooks"; import useOrdersCatalog from "../../hooks/useOrdersCatalog"; import { useStore } from "../../store/store"; import OrdersList from "./components/OrdersList"; diff --git a/frontend/competition-view/src/pages/Orders/components/OrderButton.tsx b/frontend/competition-view/src/pages/Orders/components/OrderButton.tsx index a90c25223..86748a32b 100644 --- a/frontend/competition-view/src/pages/Orders/components/OrderButton.tsx +++ b/frontend/competition-view/src/pages/Orders/components/OrderButton.tsx @@ -1,5 +1,5 @@ -import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@workspace/ui/components"; -import { AlertTriangle, Check, Send } from "@workspace/ui/icons"; +import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@hyperloop-upv/frontend-kit/components"; +import { AlertTriangle, Check, Send } from "@hyperloop-upv/frontend-kit/icons"; import { useState } from "react"; import useSendOrder from "../../../hooks/useSendOrder"; import { orderButtonColorClass, type OrderColorLevel } from "../../../constants/orderColors"; diff --git a/frontend/competition-view/src/pages/Orders/components/OrderParameters.tsx b/frontend/competition-view/src/pages/Orders/components/OrderParameters.tsx index 967e1ef7d..dd676017e 100644 --- a/frontend/competition-view/src/pages/Orders/components/OrderParameters.tsx +++ b/frontend/competition-view/src/pages/Orders/components/OrderParameters.tsx @@ -8,7 +8,7 @@ import { SelectItem, SelectTrigger, SelectValue, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; import type { CommandParameter, NumericParameter, ParameterValues } from "../../../types/catalog"; /** True when the field holds a number outside the parameter's safeRange (empty/NaN doesn't count). */ diff --git a/frontend/competition-view/src/pages/Orders/components/OrderRow.tsx b/frontend/competition-view/src/pages/Orders/components/OrderRow.tsx index 2ed9f317c..bca442a72 100644 --- a/frontend/competition-view/src/pages/Orders/components/OrderRow.tsx +++ b/frontend/competition-view/src/pages/Orders/components/OrderRow.tsx @@ -7,8 +7,8 @@ import { Tooltip, TooltipContent, TooltipTrigger, -} from "@workspace/ui/components"; -import { Check, ChevronDown, Send } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit/components"; +import { Check, ChevronDown, Send } from "@hyperloop-upv/frontend-kit/icons"; import { useMemo, useState } from "react"; import useSendOrder from "../../../hooks/useSendOrder"; import useMeasurement from "../../../hooks/useMeasurement"; diff --git a/frontend/competition-view/src/pages/Orders/components/OrdersList.tsx b/frontend/competition-view/src/pages/Orders/components/OrdersList.tsx index e49d1c1d1..7d1ca9d1f 100644 --- a/frontend/competition-view/src/pages/Orders/components/OrdersList.tsx +++ b/frontend/competition-view/src/pages/Orders/components/OrdersList.tsx @@ -1,4 +1,4 @@ -import { Button } from "@workspace/ui/components"; +import { Button } from "@hyperloop-upv/frontend-kit/components"; import type { BoardOrdersData } from "../../../types/catalog"; import { BOARDS, VCU } from "../../../constants/measurements"; import { diff --git a/frontend/competition-view/src/pages/Overview/Overview.tsx b/frontend/competition-view/src/pages/Overview/Overview.tsx index d8238c430..a31f03b53 100644 --- a/frontend/competition-view/src/pages/Overview/Overview.tsx +++ b/frontend/competition-view/src/pages/Overview/Overview.tsx @@ -1,5 +1,5 @@ -import { Button } from "@workspace/ui/components"; -import { ChevronDown, MessageSquare } from "@workspace/ui/icons"; +import { Button } from "@hyperloop-upv/frontend-kit/components"; +import { ChevronDown, MessageSquare } from "@hyperloop-upv/frontend-kit/icons"; import { BatteryFull, Gauge, diff --git a/frontend/competition-view/src/pages/Overview/components/MetricCard.tsx b/frontend/competition-view/src/pages/Overview/components/MetricCard.tsx index c106835f8..759271f61 100644 --- a/frontend/competition-view/src/pages/Overview/components/MetricCard.tsx +++ b/frontend/competition-view/src/pages/Overview/components/MetricCard.tsx @@ -3,7 +3,7 @@ import { CardContent, CardHeader, CardTitle, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; interface MetricCardProps { label: string; diff --git a/frontend/competition-view/src/pages/Overview/components/OrdersPanel.tsx b/frontend/competition-view/src/pages/Overview/components/OrdersPanel.tsx index e00453186..55c3f3ce5 100644 --- a/frontend/competition-view/src/pages/Overview/components/OrdersPanel.tsx +++ b/frontend/competition-view/src/pages/Overview/components/OrdersPanel.tsx @@ -1,6 +1,6 @@ -import { Skeleton } from "@workspace/ui/components"; -import { Send } from "@workspace/ui/icons"; -import { useWebSocket } from "@workspace/ui/hooks"; +import { Skeleton } from "@hyperloop-upv/frontend-kit/components"; +import { Send } from "@hyperloop-upv/frontend-kit/icons"; +import { useWebSocket } from "@hyperloop-upv/frontend-kit/hooks"; import useOrdersCatalog from "../../../hooks/useOrdersCatalog"; import { useStore } from "../../../store/store"; import OrdersList from "../../Orders/components/OrdersList"; diff --git a/frontend/competition-view/src/pages/Overview/components/TrackProgress.tsx b/frontend/competition-view/src/pages/Overview/components/TrackProgress.tsx index f7a14c346..2b3ffe8d2 100644 --- a/frontend/competition-view/src/pages/Overview/components/TrackProgress.tsx +++ b/frontend/competition-view/src/pages/Overview/components/TrackProgress.tsx @@ -1,4 +1,4 @@ -import { Card, CardContent } from "@workspace/ui/components"; +import { Card, CardContent } from "@hyperloop-upv/frontend-kit/components"; import { MapPin } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import podIconDark from "../../../assets/pod-dark.svg"; diff --git a/frontend/competition-view/src/pages/Overview/components/VehicleStateBanner.tsx b/frontend/competition-view/src/pages/Overview/components/VehicleStateBanner.tsx index cd127111c..84d914801 100644 --- a/frontend/competition-view/src/pages/Overview/components/VehicleStateBanner.tsx +++ b/frontend/competition-view/src/pages/Overview/components/VehicleStateBanner.tsx @@ -1,4 +1,4 @@ -import { Badge } from "@workspace/ui/components"; +import { Badge } from "@hyperloop-upv/frontend-kit/components"; import { BOARDS, VCU } from "../../../constants/measurements"; import useMeasurement from "../../../hooks/useMeasurement"; diff --git a/frontend/competition-view/src/types/telemetry.ts b/frontend/competition-view/src/types/telemetry.ts index 2f8248553..481e62d39 100644 --- a/frontend/competition-view/src/types/telemetry.ts +++ b/frontend/competition-view/src/types/telemetry.ts @@ -1,10 +1,10 @@ -export type { TelemetryPacket, VariableValue, Variables } from "@workspace/core"; +export type { TelemetryPacket, VariableValue, Variables } from "@hyperloop-upv/frontend-kit/core"; /** * The backend sends a batch of packets keyed by numeric packet ID. * Each packet carries its own `measurementUpdates` map. */ -export type TelemetryData = Record; +export type TelemetryData = Record; /** * Telemetry keyed first by board name then by measurement ID. diff --git a/frontend/competition-view/tsconfig.json b/frontend/competition-view/tsconfig.json index a351dd46e..1d8aa51b5 100644 --- a/frontend/competition-view/tsconfig.json +++ b/frontend/competition-view/tsconfig.json @@ -7,8 +7,7 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "@/*": ["./*"], - "@workspace/ui/*": ["../frontend-kit/ui/src/*"] + "@/*": ["./*"] } }, "exclude": ["node_modules"] diff --git a/frontend/flashing-view/eslint.config.js b/frontend/flashing-view/eslint.config.js index df360b435..a2b580035 100644 --- a/frontend/flashing-view/eslint.config.js +++ b/frontend/flashing-view/eslint.config.js @@ -1,3 +1,3 @@ -import { config } from "@workspace/eslint-config/vite"; +import { config } from "@hyperloop-upv/eslint-config/vite"; export default config; diff --git a/frontend/flashing-view/package.json b/frontend/flashing-view/package.json index 725224d9f..0f09a72f5 100644 --- a/frontend/flashing-view/package.json +++ b/frontend/flashing-view/package.json @@ -13,7 +13,7 @@ "dependencies": { "@tailwindcss/vite": "^4.1.18", "@vitejs/plugin-react-swc": "^4.2.3", - "@workspace/ui": "workspace:*", + "@hyperloop-upv/frontend-kit": "workspace:*", "lucide-react": "^0.563.0", "react": "^19.2.4", "react-dom": "^19.2.4", @@ -22,8 +22,8 @@ "devDependencies": { "@types/react": "19.2.11", "@types/react-dom": "19.2.3", - "@workspace/eslint-config": "workspace:^", - "@workspace/typescript-config": "workspace:*", + "@hyperloop-upv/eslint-config": "workspace:^", + "@hyperloop-upv/typescript-config": "workspace:*", "eslint": "^9.39.2", "typescript": "^5.9.3", "vite": "^7.3.1" diff --git a/frontend/flashing-view/src/features/flash-station/components/board-card.tsx b/frontend/flashing-view/src/features/flash-station/components/board-card.tsx index 5da96b47c..5b2fbc950 100644 --- a/frontend/flashing-view/src/features/flash-station/components/board-card.tsx +++ b/frontend/flashing-view/src/features/flash-station/components/board-card.tsx @@ -1,5 +1,5 @@ -import { Badge } from "@workspace/ui/components"; -import { cn } from "@workspace/ui/lib/utils"; +import { Badge } from "@hyperloop-upv/frontend-kit/components"; +import { cn } from "@hyperloop-upv/frontend-kit/lib/utils"; import type { Board } from "../types"; type Props = { diff --git a/frontend/flashing-view/src/features/flash-station/components/section-card.tsx b/frontend/flashing-view/src/features/flash-station/components/section-card.tsx index 91d81701f..29c4dd4a0 100644 --- a/frontend/flashing-view/src/features/flash-station/components/section-card.tsx +++ b/frontend/flashing-view/src/features/flash-station/components/section-card.tsx @@ -1,4 +1,4 @@ -import { Card, CardContent, CardHeader, CardTitle } from "@workspace/ui/components"; +import { Card, CardContent, CardHeader, CardTitle } from "@hyperloop-upv/frontend-kit/components"; import type { ReactNode } from "react"; type Props = { diff --git a/frontend/flashing-view/src/features/flash-station/flash-station-view.tsx b/frontend/flashing-view/src/features/flash-station/flash-station-view.tsx index b1aedd96f..c70587175 100644 --- a/frontend/flashing-view/src/features/flash-station/flash-station-view.tsx +++ b/frontend/flashing-view/src/features/flash-station/flash-station-view.tsx @@ -1,8 +1,8 @@ -import { Badge, Button, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@workspace/ui/components"; -import { FileCode2, Loader2, SunMoon, Upload } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib/utils"; +import { Badge, Button, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@hyperloop-upv/frontend-kit/components"; +import { FileCode2, Loader2, SunMoon, Upload } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib/utils"; import { useEffect, useRef, useState } from "react"; -import logo from "@workspace/ui/outreach/h11/h11-isotipo_black.svg"; +import logo from "@hyperloop-upv/frontend-kit/outreach/h11/h11-isotipo_black.svg"; import { BoardCard } from "./components/board-card"; import { SectionCard } from "./components/section-card"; import type { Board, BoardsResponse, GeneralState, OperationalState } from "./types"; diff --git a/frontend/flashing-view/src/index.css b/frontend/flashing-view/src/index.css index 6824f52fb..b5950dca2 100644 --- a/frontend/flashing-view/src/index.css +++ b/frontend/flashing-view/src/index.css @@ -1 +1 @@ -@import "@workspace/ui/globals.css"; +@import "@hyperloop-upv/frontend-kit/globals.css"; diff --git a/frontend/flashing-view/tsconfig.json b/frontend/flashing-view/tsconfig.json index fc0aa4474..483ebaa0f 100644 --- a/frontend/flashing-view/tsconfig.json +++ b/frontend/flashing-view/tsconfig.json @@ -4,11 +4,5 @@ { "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" } ], - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@workspace/ui/*": ["../frontend-kit/ui/src/*"] - } - }, "exclude": ["node_modules"] } diff --git a/frontend/frontend-kit/core/eslint.config.js b/frontend/frontend-kit/core/eslint.config.js deleted file mode 100644 index f79dd7d64..000000000 --- a/frontend/frontend-kit/core/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -import { config } from "@workspace/eslint-config/react-internal"; - -/** @type {import("eslint").Linter.Config} */ -export default config; diff --git a/frontend/frontend-kit/core/package.json b/frontend/frontend-kit/core/package.json deleted file mode 100644 index bb358f5a3..000000000 --- a/frontend/frontend-kit/core/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@workspace/core", - "version": "1.0.0", - "description": "", - "main": "index.js", - "type": "module", - "scripts": { - "preinstall": "npx only-allow pnpm", - "lint": "eslint ." - }, - "keywords": [], - "author": "", - "license": "ISC", - "packageManager": "pnpm@10.24.0", - "devDependencies": { - "@workspace/eslint-config": "workspace:*", - "eslint": "^9.39.2" - }, - "exports": { - ".": "./src/index.ts" - }, - "dependencies": { - "rxjs": "^7.8.2" - } -} diff --git a/frontend/frontend-kit/core/src/logger.ts b/frontend/frontend-kit/core/src/logger.ts deleted file mode 100644 index b6ff4f42e..000000000 --- a/frontend/frontend-kit/core/src/logger.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { loggerColors } from "./loggerColors"; -import type { LoggerModule } from "./types"; - -/** - * Creates a logger for a given module - * @param module - the module to log for (it's just a colored string that will be shown between `[` and `]` before the message itself) - * @returns a logger object with `log`, `warn`, and `error` methods - */ -function createLogger(module: LoggerModule) { - const color = loggerColors[module]; - const prefix = `[${module.toUpperCase()}]`; - - return { - // It's important to use `bind` here to correctly display log file path and line number in the console - // Otherwise, console prints will just point to this file - log: console.log.bind(console, `${color}${prefix}${loggerColors.reset}`), - warn: console.warn.bind(console, `${color}${prefix}${loggerColors.reset}`), - error: console.error.bind( - console, - `${color}${prefix}${loggerColors.reset}`, - ), - }; -} - -/** - * Logger object with methods for each module - */ -export const logger = { - testingView: createLogger("testing-view"), - competitionView: createLogger("competition-view"), - core: createLogger("core"), - ui: createLogger("ui"), -}; diff --git a/frontend/frontend-kit/core/src/loggerColors.ts b/frontend/frontend-kit/core/src/loggerColors.ts deleted file mode 100644 index c99f7d68d..000000000 --- a/frontend/frontend-kit/core/src/loggerColors.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const loggerColors = { - "testing-view": "\x1b[36m", // Cyan - "competition-view": "\x1b[35m", // Magenta - core: "\x1b[33m", // Yellow - ui: "\x1b[32m", // Green - reset: "\x1b[0m", -}; diff --git a/frontend/frontend-kit/core/src/types.ts b/frontend/frontend-kit/core/src/types.ts deleted file mode 100644 index e0346cc78..000000000 --- a/frontend/frontend-kit/core/src/types.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Options for the `onTopic` method of the `SocketService` class. - */ -export interface TopicOptions { - /** The downsampling method to use. */ - downsample?: "min-max" | "none"; - - /** The throttle time in milliseconds. */ - throttle?: number; -} - -/** - * The value of a variable in a telemetry packet. - */ -export type VariableValue = - | { last: number; average: number } - | boolean - | string - | number; - -/** - * The variables of a telemetry packet. - */ -export type Variables = Record; - -/** - * A telemetry packet that arrives in high frequency.\ - * Don't confuse it with the `TelemetryCatalogItem` type. - */ -export interface TelemetryPacket { - count: number; - cycleTime: number; - hexValue: string; - id: number; - measurementUpdates: Variables; -} - -/** - * The modules that can be logged to. Used for the `logger` object. - */ -export type LoggerModule = "testing-view" | "competition-view" | "core" | "ui"; diff --git a/frontend/frontend-kit/core/tsconfig.json b/frontend/frontend-kit/core/tsconfig.json deleted file mode 100644 index 0bedc71da..000000000 --- a/frontend/frontend-kit/core/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "@workspace/typescript-config/react-library.json", - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@workspace/ui/*": ["./src/*"] - } - }, - "include": ["."], - "exclude": ["node_modules", "dist"] -} diff --git a/frontend/frontend-kit/esling-config/base.js b/frontend/frontend-kit/eslint-config/base.js similarity index 100% rename from frontend/frontend-kit/esling-config/base.js rename to frontend/frontend-kit/eslint-config/base.js diff --git a/frontend/frontend-kit/esling-config/package.json b/frontend/frontend-kit/eslint-config/package.json similarity index 94% rename from frontend/frontend-kit/esling-config/package.json rename to frontend/frontend-kit/eslint-config/package.json index dfb4d11d7..9434cda68 100644 --- a/frontend/frontend-kit/esling-config/package.json +++ b/frontend/frontend-kit/eslint-config/package.json @@ -1,5 +1,5 @@ { - "name": "@workspace/eslint-config", + "name": "@hyperloop-upv/eslint-config", "version": "0.0.0", "type": "module", "private": true, diff --git a/frontend/frontend-kit/esling-config/react-internal.js b/frontend/frontend-kit/eslint-config/react-internal.js similarity index 100% rename from frontend/frontend-kit/esling-config/react-internal.js rename to frontend/frontend-kit/eslint-config/react-internal.js diff --git a/frontend/frontend-kit/esling-config/vite.js b/frontend/frontend-kit/eslint-config/vite.js similarity index 100% rename from frontend/frontend-kit/esling-config/vite.js rename to frontend/frontend-kit/eslint-config/vite.js diff --git a/frontend/frontend-kit/kit/README.md b/frontend/frontend-kit/kit/README.md new file mode 100644 index 000000000..8c3f279ff --- /dev/null +++ b/frontend/frontend-kit/kit/README.md @@ -0,0 +1,248 @@ +# `@hyperloop-upv/frontend-kit` + +The shared frontend package for the Hyperloop Control Station: reusable styled +components and hooks built on **React**, **Shadcn/UI** and **Tailwind CSS**, +plus the framework-agnostic WebSocket and logging layer. + +It is built for publication, so a frontend living in another repository can use +it too. See [Using it from another repository](#using-it-from-another-repository). + +## Project Guidelines + +### Where code goes + +> - Logic that needs React hooks (`useState`, `useEffect`, ...) or TSX belongs +> in `src/components`, `src/hooks` or `src/lib`. +> - **Logic that does NOT need React** (websocket connections, for example) +> belongs in `src/core`, published as the `./core` subpath. That boundary is +> enforced by a lint rule, not just convention: `src/core` may not import +> React. It keeps `./core` usable from a plain Node script or an Electron main +> process. + +### Import paths + +```ts +import { Button } from "@hyperloop-upv/frontend-kit/components"; +import { useTopic } from "@hyperloop-upv/frontend-kit/hooks"; +import { ChevronDown } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; +import { socketService } from "@hyperloop-upv/frontend-kit/core"; +import logo from "@hyperloop-upv/frontend-kit/outreach/main/logo_icon.svg"; +``` + +Inside this package, always use **relative** imports. Referring to the package +by its own name makes the published build depend on self-reference resolution, +which bundlers support unevenly. + +--- + +## Icon Management + +We use a custom Rust-based tool, **icons-master**, to manage our Lucide icon exports. This tool helps keep our icons organized by category and ensures we don't have duplicate exports. + +### Usage + +Here are the scripts you can run: + +```bash +# Install dependencies +pnpm install + +# Run linter +pnpm lint + +# Add a new icon from Lucide (Example: pnpm icon:add arrow-up src/icons) +pnpm icon:add src/icons + +# Remove an existing icon export (Example: pnpm icon:remove arrow-up src/icons) +pnpm icon:remove src/icons +``` + +--- + +## Build + +```bash +pnpm --filter @hyperloop-upv/frontend-kit build +``` + +Vite in library mode with Rollup's `preserveModules`, which mirrors `src/` into +`dist/`. That is what keeps the wildcard subpath exports (`./components/*`) +resolving as components are added, with no entry list to maintain. Rollup is +used rather than `tsc` or `tsup` because it rewrites relative specifiers with +real `.js` extensions; the other two emit extensionless imports, which are not +valid ESM. + +`exports` points at `src/`, so the five apps in this monorepo keep compiling +kit source directly and keep their HMR. `publishConfig.exports` points at +`dist/` and is what an external consumer sees. **Publish with `pnpm publish`:** +`npm publish` ignores that override and would ship a package whose exports +point at `.tsx`, with no error at publish time. + +The tarball ships `src/` as well as `dist/`. That is deliberate: the published +`globals.css` lives in `src/styles/` and its own `@source` directive resolves +relative to itself, so Tailwind finds the kit's classes inside `node_modules` +with no build-time transform. + +--- + +## Using it from another repository + +The kit is published to **GitHub Packages**, not npmjs.com. That registry +requires a token for every request, **including downloading a public package**, +so there is a one-time setup per contributor and per CI job. + +`.npmrc` in the consuming repository: + +``` +@hyperloop-upv:registry=https://npm.pkg.github.com +//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN} +``` + +Each contributor exports `NODE_AUTH_TOKEN` with a **classic** personal access +token carrying the `read:packages` scope, from +. Use a classic token: fine-grained ones +still have patchy support for this registry. Without the variable, the install +fails with `ERR_PNPM_FETCH_401`. + +In CI, use the job's own token and grant it read access to packages: + +```yaml +permissions: + contents: read + packages: read # required even for a public package +steps: + - run: pnpm install --frozen-lockfile + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +Then install the package and the peer dependencies it expects you to own: + +```bash +pnpm add @hyperloop-upv/frontend-kit +pnpm add react react-dom lucide-react tw-animate-css +pnpm add -D tailwindcss @tailwindcss/vite +``` + +> To try a change before it is published, build a tarball with +> `pnpm --filter @hyperloop-upv/frontend-kit exec pnpm pack` and +> `pnpm add` that file directly. No registry and no token involved. + +`src/index.css`: + +```css +@import "@hyperloop-upv/frontend-kit/globals.css"; + +/* Add your own sources. The kit's stylesheet can only register files inside + the kit, because its directive resolves relative to node_modules. */ +@source "./**/*.{ts,tsx}"; +``` + +That single import brings the theme variables, the four themes, the dark and +pink variants, the `@theme inline` map, the base layer, scrollbars, +`tw-animate-css` and the Archivo font. + +`vite.config.ts`: + +```ts +import tailwindcss from "@tailwindcss/vite"; +import react from "@vitejs/plugin-react-swc"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [react(), tailwindcss()], + // The kit declares react/react-dom as peers; dedupe guarantees one copy, + // since two copies of React break hooks. + resolve: { dedupe: ["react", "react-dom"] }, +}); +``` + +Do not add `@radix-ui/*` to your own dependencies. The kit owns those, and two +copies of the same Radix package cause real focus-trap and scroll-lock bugs. + +Your `tsconfig` needs **no `paths` entry** for the kit, and must use +`"moduleResolution": "bundler"` (or `"nodenext"`) so TypeScript honours the +package's `exports` map. + +### Pointing it at a backend + +The socket defaults to `ws://127.0.0.1:4000/backend`. For anything else, set it +once when the app boots: + +```ts +import { configureSocket } from "@hyperloop-upv/frontend-kit/core"; + +configureSocket({ url: import.meta.env.VITE_WS_URL }); +// or: configureSocket({ host: "pod.local", port: 8080, secure: true }); +``` + +### Registering your own logger module + +```ts +import { ansi, createLogger, registerLoggerColor } from "@hyperloop-upv/frontend-kit/core"; + +registerLoggerColor("pod-dashboard", ansi.cyan); +export const log = createLogger("pod-dashboard"); +``` + +--- + +## Releasing + +The kit rides along with the Control Station: **Actions -> Release Electron App** +publishes the kit at the same version as its last job, so `v11.3.2` of the +Control Station and `@hyperloop-upv/frontend-kit@11.3.2` always mean the same +commit. Nothing extra to run. The `publish-kit` input, on by default, turns it +off for a release that should not move the package. + +That job is last and depends on the whole release succeeding, because +publishing cannot be undone and must not happen for a release that failed to +build. + +**The `version` in this `package.json` is a placeholder**, the same `0.0.0` +convention `electron-app` uses. CI injects the real number with +`pnpm version --no-git-tag-version`, and the git tag is the record of what was +published from which commit. Do not bump it by hand expecting it to mean +anything. + +### The dist-tag + +A version with a prerelease part (`11.3.2-beta-2`, `11.3.2-1`) is published +under the `next` dist-tag instead of `latest`, so `pnpm add +@hyperloop-upv/frontend-kit` keeps resolving to the last stable release. Taking +a prerelease is then explicit: + +```bash +pnpm add @hyperloop-upv/frontend-kit@next +``` + +### Publishing the kit on its own + +For a kit-only release, Actions -> **Publish Frontend Kit** -> enter the +version, leave **dry-run on**. It packs, prints the tarball contents and +attaches it as an artifact without publishing. Read that, then run it again +with dry-run off. Pick a version above the last published one; the Control +Station numbering is shared, so a kit-only release normally takes the next +patch. + +First release only: check the package is public under Organisation -> Packages +-> Package settings, and that this repository has write access. + +**A published version can never be reused.** Deleting a version does not free +the number. If `11.3.2` is wrong, publish `11.3.3`. + +### Versioning, and what it means for a consumer + +Versions are shared with the Control Station, so the numbers track **releases +of the station, not the kit's own API**. A minor bump may carry a breaking +change to a component, and a major bump may change nothing here at all. An +external consumer should therefore pin the exact version it was tested +against, or pin a patch range and read the release notes before moving: + +```json +"@hyperloop-upv/frontend-kit": "~11.3.2" +``` + +The five apps in this monorepo stay on `workspace:*` and are unaffected by what +is published: pnpm always prefers the local link. diff --git a/frontend/frontend-kit/ui/components.json b/frontend/frontend-kit/kit/components.json similarity index 50% rename from frontend/frontend-kit/ui/components.json rename to frontend/frontend-kit/kit/components.json index 29e8e6d99..b37aad469 100644 --- a/frontend/frontend-kit/ui/components.json +++ b/frontend/frontend-kit/kit/components.json @@ -11,10 +11,10 @@ }, "iconLibrary": "lucide", "aliases": { - "components": "@workspace/ui/components", - "hooks": "@workspace/ui/hooks/shadcn", - "lib": "@workspace/ui/lib", - "utils": "@workspace/ui/lib/utils", - "ui": "@workspace/ui/components/shadcn" + "components": "@hyperloop-upv/frontend-kit/components", + "hooks": "@hyperloop-upv/frontend-kit/hooks/shadcn", + "lib": "@hyperloop-upv/frontend-kit/lib", + "utils": "@hyperloop-upv/frontend-kit/lib/utils", + "ui": "@hyperloop-upv/frontend-kit/components/shadcn" } } diff --git a/frontend/frontend-kit/kit/eslint.config.js b/frontend/frontend-kit/kit/eslint.config.js new file mode 100644 index 000000000..4865ba27c --- /dev/null +++ b/frontend/frontend-kit/kit/eslint.config.js @@ -0,0 +1,30 @@ +import { config } from "@hyperloop-upv/eslint-config/react-internal"; + +/** @type {import("eslint").Linter.Config} */ +export default [ + ...config, + { + // src/core is published as the ./core subpath and must stay usable outside + // a React app, so the React-free boundary is enforced rather than just + // documented in the README. + files: ["src/core/**/*.ts"], + rules: { + "no-restricted-imports": [ + "error", + { + paths: [ + { + name: "react", + message: + "src/core must stay React-free. Anything needing React belongs in src/hooks or src/components.", + }, + { + name: "react-dom", + message: "src/core must stay React-free.", + }, + ], + }, + ], + }, + }, +]; diff --git a/frontend/frontend-kit/kit/package.json b/frontend/frontend-kit/kit/package.json new file mode 100644 index 000000000..74395fb25 --- /dev/null +++ b/frontend/frontend-kit/kit/package.json @@ -0,0 +1,144 @@ +{ + "name": "@hyperloop-upv/frontend-kit", + "version": "0.0.0", + "description": "Shared React + Tailwind component kit and WebSocket layer for Hyperloop UPV frontends", + "license": "MIT", + "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/Hyperloop-UPV/software.git", + "directory": "frontend/frontend-kit/kit" + }, + "homepage": "https://github.com/Hyperloop-UPV/software/tree/develop/frontend/frontend-kit/kit", + "bugs": { + "url": "https://github.com/Hyperloop-UPV/software/issues" + }, + "sideEffects": [ + "**/*.css" + ], + "files": [ + "dist", + "src", + "postcss.config.mjs", + "components.json", + "README.md" + ], + "scripts": { + "build": "vite build", + "lint": "eslint .", + "icon:add": "icons-master add", + "icon:remove": "icons-master remove" + }, + "peerDependencies": { + "lucide-react": ">=0.500.0 <1", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwindcss": "^4.1.0", + "tw-animate-css": "^1.4.0" + }, + "dependencies": { + "@base-ui/react": "^1.3.0", + "@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-label": "^2.1.8", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-tabs": "^1.1.13", + "@radix-ui/react-tooltip": "^1.2.8", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "radix-ui": "^1.4.3", + "react-resizable-panels": "^4.6.0", + "rxjs": "^7.8.2", + "tailwind-merge": "^3.4.0" + }, + "devDependencies": { + "@hyperloop-upv/eslint-config": "workspace:*", + "@hyperloop-upv/typescript-config": "workspace:*", + "@maximka76667/icons-master": "^1.0.3", + "@tailwindcss/postcss": "^4.1.18", + "@turbo/gen": "^2.8.3", + "@types/node": "^25.2.0", + "@types/react": "^19.2.11", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react-swc": "^4.2.3", + "eslint": "^9.39.2", + "lucide-react": "^0.563.0", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "tailwindcss": "^4.1.18", + "tinyglobby": "^0.2.17", + "tw-animate-css": "^1.4.0", + "typescript": "^5.9.3", + "vite": "^7.3.1", + "vite-plugin-dts": "^5.1.2" + }, + "exports": { + ".": "./src/index.ts", + "./core": "./src/core/index.ts", + "./globals.css": "./src/styles/globals.css", + "./postcss.config": "./postcss.config.mjs", + "./lib": "./src/lib/index.ts", + "./components": "./src/components/index.ts", + "./hooks": "./src/hooks/index.ts", + "./lib/*": "./src/lib/*.ts", + "./components/*": "./src/components/*.tsx", + "./hooks/*": "./src/hooks/*.ts", + "./store": "./src/store/index.ts", + "./icons": "./src/icons/index.ts", + "./outreach/*": "./src/outreach/*", + "./package.json": "./package.json" + }, + "publishConfig": { + "registry": "https://npm.pkg.github.com", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./core": { + "types": "./dist/core/index.d.ts", + "default": "./dist/core/index.js" + }, + "./globals.css": "./src/styles/globals.css", + "./postcss.config": "./postcss.config.mjs", + "./lib": { + "types": "./dist/lib/index.d.ts", + "default": "./dist/lib/index.js" + }, + "./components": { + "types": "./dist/components/index.d.ts", + "default": "./dist/components/index.js" + }, + "./hooks": { + "types": "./dist/hooks/index.d.ts", + "default": "./dist/hooks/index.js" + }, + "./icons": { + "types": "./dist/icons/index.d.ts", + "default": "./dist/icons/index.js" + }, + "./lib/*": { + "types": "./dist/lib/*.d.ts", + "default": "./dist/lib/*.js" + }, + "./components/*": { + "types": "./dist/components/*.d.ts", + "default": "./dist/components/*.js" + }, + "./hooks/*": { + "types": "./dist/hooks/*.d.ts", + "default": "./dist/hooks/*.js" + }, + "./outreach/*": "./src/outreach/*", + "./package.json": "./package.json" + } + } +} diff --git a/frontend/frontend-kit/ui/postcss.config.mjs b/frontend/frontend-kit/kit/postcss.config.mjs similarity index 100% rename from frontend/frontend-kit/ui/postcss.config.mjs rename to frontend/frontend-kit/kit/postcss.config.mjs diff --git a/frontend/frontend-kit/ui/src/components/custom/custom-component.tsx b/frontend/frontend-kit/kit/src/components/custom/custom-component.tsx similarity index 92% rename from frontend/frontend-kit/ui/src/components/custom/custom-component.tsx rename to frontend/frontend-kit/kit/src/components/custom/custom-component.tsx index 1718e0799..c00d3d997 100644 --- a/frontend/frontend-kit/ui/src/components/custom/custom-component.tsx +++ b/frontend/frontend-kit/kit/src/components/custom/custom-component.tsx @@ -1,4 +1,4 @@ -import { cn } from "@workspace/ui/lib/utils"; +import { cn } from "../../lib/utils"; import React from "react"; interface CustomComponentProps extends React.HTMLAttributes {} diff --git a/frontend/frontend-kit/ui/src/components/custom/index.ts b/frontend/frontend-kit/kit/src/components/custom/index.ts similarity index 100% rename from frontend/frontend-kit/ui/src/components/custom/index.ts rename to frontend/frontend-kit/kit/src/components/custom/index.ts diff --git a/frontend/frontend-kit/ui/src/components/custom/segmented-control.tsx b/frontend/frontend-kit/kit/src/components/custom/segmented-control.tsx similarity index 100% rename from frontend/frontend-kit/ui/src/components/custom/segmented-control.tsx rename to frontend/frontend-kit/kit/src/components/custom/segmented-control.tsx diff --git a/frontend/frontend-kit/ui/src/components/index.ts b/frontend/frontend-kit/kit/src/components/index.ts similarity index 100% rename from frontend/frontend-kit/ui/src/components/index.ts rename to frontend/frontend-kit/kit/src/components/index.ts diff --git a/frontend/frontend-kit/ui/src/components/shadcn/badge.tsx b/frontend/frontend-kit/kit/src/components/shadcn/badge.tsx similarity index 97% rename from frontend/frontend-kit/ui/src/components/shadcn/badge.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/badge.tsx index c5659a22b..127f9ab69 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/badge.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/badge.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@workspace/ui/lib/utils"; +import { cn } from "../../lib/utils"; const badgeVariants = cva( "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", diff --git a/frontend/frontend-kit/ui/src/components/shadcn/button.tsx b/frontend/frontend-kit/kit/src/components/shadcn/button.tsx similarity index 98% rename from frontend/frontend-kit/ui/src/components/shadcn/button.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/button.tsx index 53fc38d33..eba30dd36 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/button.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/button.tsx @@ -2,7 +2,7 @@ import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" import { Slot } from "radix-ui" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" const buttonVariants = cva( "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", diff --git a/frontend/frontend-kit/ui/src/components/shadcn/card.tsx b/frontend/frontend-kit/kit/src/components/shadcn/card.tsx similarity index 97% rename from frontend/frontend-kit/ui/src/components/shadcn/card.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/card.tsx index 2e7392a65..96c5f2f66 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/card.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/card.tsx @@ -1,6 +1,6 @@ import * as React from "react" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Card({ className, ...props }: React.ComponentProps<"div">) { return ( diff --git a/frontend/frontend-kit/ui/src/components/shadcn/checkbox.tsx b/frontend/frontend-kit/kit/src/components/shadcn/checkbox.tsx similarity index 96% rename from frontend/frontend-kit/ui/src/components/shadcn/checkbox.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/checkbox.tsx index bca5ecca4..69e911593 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/checkbox.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/checkbox.tsx @@ -4,7 +4,7 @@ import * as React from "react" import * as CheckboxPrimitive from "@radix-ui/react-checkbox" import { CheckIcon } from "lucide-react" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Checkbox({ className, diff --git a/frontend/frontend-kit/ui/src/components/shadcn/collapsible.tsx b/frontend/frontend-kit/kit/src/components/shadcn/collapsible.tsx similarity index 100% rename from frontend/frontend-kit/ui/src/components/shadcn/collapsible.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/collapsible.tsx diff --git a/frontend/frontend-kit/ui/src/components/shadcn/combobox.tsx b/frontend/frontend-kit/kit/src/components/shadcn/combobox.tsx similarity index 98% rename from frontend/frontend-kit/ui/src/components/shadcn/combobox.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/combobox.tsx index 36b00ad18..2d2f910d9 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/combobox.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/combobox.tsx @@ -4,14 +4,14 @@ import * as React from "react" import { Combobox as ComboboxPrimitive } from "@base-ui/react" import { CheckIcon, ChevronDownIcon, XIcon } from "lucide-react" -import { cn } from "@workspace/ui/lib/utils" -import { Button } from "@workspace/ui/components/shadcn/button" +import { cn } from "../../lib/utils" +import { Button } from "./button" import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, -} from "@workspace/ui/components/shadcn/input-group" +} from "./input-group" const Combobox = ComboboxPrimitive.Root diff --git a/frontend/frontend-kit/ui/src/components/shadcn/context-menu.tsx b/frontend/frontend-kit/kit/src/components/shadcn/context-menu.tsx similarity index 99% rename from frontend/frontend-kit/ui/src/components/shadcn/context-menu.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/context-menu.tsx index bd6991efb..75535c54e 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/context-menu.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/context-menu.tsx @@ -4,7 +4,7 @@ import * as React from "react" import * as ContextMenuPrimitive from "@radix-ui/react-context-menu" import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function ContextMenu({ ...props diff --git a/frontend/frontend-kit/ui/src/components/shadcn/dialog.tsx b/frontend/frontend-kit/kit/src/components/shadcn/dialog.tsx similarity index 98% rename from frontend/frontend-kit/ui/src/components/shadcn/dialog.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/dialog.tsx index b905322cf..9c866fbaa 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/dialog.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/dialog.tsx @@ -4,7 +4,7 @@ import * as React from "react" import * as DialogPrimitive from "@radix-ui/react-dialog" import { XIcon } from "lucide-react" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Dialog({ ...props diff --git a/frontend/frontend-kit/ui/src/components/shadcn/dropdown-menu.tsx b/frontend/frontend-kit/kit/src/components/shadcn/dropdown-menu.tsx similarity index 99% rename from frontend/frontend-kit/ui/src/components/shadcn/dropdown-menu.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/dropdown-menu.tsx index 6c011e181..fa24a3dae 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/dropdown-menu.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/dropdown-menu.tsx @@ -4,7 +4,7 @@ import * as React from "react" import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function DropdownMenu({ ...props diff --git a/frontend/frontend-kit/ui/src/components/shadcn/field.tsx b/frontend/frontend-kit/kit/src/components/shadcn/field.tsx similarity index 97% rename from frontend/frontend-kit/ui/src/components/shadcn/field.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/field.tsx index 7d7b87450..90359f929 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/field.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/field.tsx @@ -3,9 +3,9 @@ import { useMemo } from "react" import { cva, type VariantProps } from "class-variance-authority" -import { cn } from "@workspace/ui/lib/utils" -import { Label } from "@workspace/ui/components/shadcn/label" -import { Separator } from "@workspace/ui/components/shadcn/separator" +import { cn } from "../../lib/utils" +import { Label } from "./label" +import { Separator } from "./separator" function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { return ( diff --git a/frontend/frontend-kit/ui/src/components/shadcn/index.ts b/frontend/frontend-kit/kit/src/components/shadcn/index.ts similarity index 100% rename from frontend/frontend-kit/ui/src/components/shadcn/index.ts rename to frontend/frontend-kit/kit/src/components/shadcn/index.ts diff --git a/frontend/frontend-kit/ui/src/components/shadcn/input-group.tsx b/frontend/frontend-kit/kit/src/components/shadcn/input-group.tsx similarity index 95% rename from frontend/frontend-kit/ui/src/components/shadcn/input-group.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/input-group.tsx index 3b8f6fece..7a809428e 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/input-group.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/input-group.tsx @@ -3,10 +3,10 @@ import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" -import { cn } from "@workspace/ui/lib/utils" -import { Button } from "@workspace/ui/components/shadcn/button" -import { Input } from "@workspace/ui/components/shadcn/input" -import { Textarea } from "@workspace/ui/components/shadcn/textarea" +import { cn } from "../../lib/utils" +import { Button } from "./button" +import { Input } from "./input" +import { Textarea } from "./textarea" function InputGroup({ className, ...props }: React.ComponentProps<"div">) { return ( diff --git a/frontend/frontend-kit/ui/src/components/shadcn/input.tsx b/frontend/frontend-kit/kit/src/components/shadcn/input.tsx similarity index 95% rename from frontend/frontend-kit/ui/src/components/shadcn/input.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/input.tsx index 2882b5343..7af0b67d6 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/input.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/input.tsx @@ -1,6 +1,6 @@ import * as React from "react" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Input({ className, type, ...props }: React.ComponentProps<"input">) { return ( diff --git a/frontend/frontend-kit/ui/src/components/shadcn/label.tsx b/frontend/frontend-kit/kit/src/components/shadcn/label.tsx similarity index 92% rename from frontend/frontend-kit/ui/src/components/shadcn/label.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/label.tsx index 4aeafb539..eec5bce9c 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/label.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/label.tsx @@ -3,7 +3,7 @@ import * as React from "react" import * as LabelPrimitive from "@radix-ui/react-label" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Label({ className, diff --git a/frontend/frontend-kit/ui/src/components/shadcn/popover.tsx b/frontend/frontend-kit/kit/src/components/shadcn/popover.tsx similarity index 97% rename from frontend/frontend-kit/ui/src/components/shadcn/popover.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/popover.tsx index d15b81e2a..b82cf17b5 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/popover.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/popover.tsx @@ -3,7 +3,7 @@ import * as React from "react" import * as PopoverPrimitive from "@radix-ui/react-popover" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Popover({ ...props diff --git a/frontend/frontend-kit/ui/src/components/shadcn/resizable.tsx b/frontend/frontend-kit/kit/src/components/shadcn/resizable.tsx similarity index 97% rename from frontend/frontend-kit/ui/src/components/shadcn/resizable.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/resizable.tsx index bbaca1e2b..dd57afbf6 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/resizable.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/resizable.tsx @@ -3,7 +3,7 @@ import { GripVerticalIcon } from "lucide-react" import * as ResizablePrimitive from "react-resizable-panels" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function ResizablePanelGroup({ className, diff --git a/frontend/frontend-kit/ui/src/components/shadcn/select.tsx b/frontend/frontend-kit/kit/src/components/shadcn/select.tsx similarity index 99% rename from frontend/frontend-kit/ui/src/components/shadcn/select.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/select.tsx index 84bf00ebe..4f862b6f7 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/select.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/select.tsx @@ -4,7 +4,7 @@ import * as SelectPrimitive from "@radix-ui/react-select"; import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"; import * as React from "react"; -import { cn } from "@workspace/ui/lib/utils"; +import { cn } from "../../lib/utils"; function Select({ ...props diff --git a/frontend/frontend-kit/ui/src/components/shadcn/separator.tsx b/frontend/frontend-kit/kit/src/components/shadcn/separator.tsx similarity index 93% rename from frontend/frontend-kit/ui/src/components/shadcn/separator.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/separator.tsx index 4e9594c2f..c8ff3cf7d 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/separator.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/separator.tsx @@ -3,7 +3,7 @@ import * as React from "react" import * as SeparatorPrimitive from "@radix-ui/react-separator" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Separator({ className, diff --git a/frontend/frontend-kit/ui/src/components/shadcn/sheet.tsx b/frontend/frontend-kit/kit/src/components/shadcn/sheet.tsx similarity index 98% rename from frontend/frontend-kit/ui/src/components/shadcn/sheet.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/sheet.tsx index 02c8b3050..83d35d01d 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/sheet.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/sheet.tsx @@ -4,7 +4,7 @@ import * as React from "react" import * as SheetPrimitive from "@radix-ui/react-dialog" import { XIcon } from "lucide-react" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Sheet({ ...props }: React.ComponentProps) { return diff --git a/frontend/frontend-kit/ui/src/components/shadcn/sidebar.tsx b/frontend/frontend-kit/kit/src/components/shadcn/sidebar.tsx similarity index 97% rename from frontend/frontend-kit/ui/src/components/shadcn/sidebar.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/sidebar.tsx index f0ac18058..43f8599a2 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/sidebar.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/sidebar.tsx @@ -5,25 +5,25 @@ import { cva, type VariantProps } from "class-variance-authority"; import { PanelLeftIcon } from "lucide-react"; import * as React from "react"; -import { Button } from "@workspace/ui/components/shadcn/button"; -import { Input } from "@workspace/ui/components/shadcn/input"; -import { Separator } from "@workspace/ui/components/shadcn/separator"; +import { Button } from "./button"; +import { Input } from "./input"; +import { Separator } from "./separator"; import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, -} from "@workspace/ui/components/shadcn/sheet"; -import { Skeleton } from "@workspace/ui/components/shadcn/skeleton"; +} from "./sheet"; +import { Skeleton } from "./skeleton"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, -} from "@workspace/ui/components/shadcn/tooltip"; -import { useIsMobile } from "@workspace/ui/hooks/shadcn/use-mobile"; -import { cn } from "@workspace/ui/lib/utils"; +} from "./tooltip"; +import { useIsMobile } from "../../hooks/shadcn/use-mobile"; +import { cn } from "../../lib/utils"; const SIDEBAR_COOKIE_NAME = "sidebar_state"; const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7; diff --git a/frontend/frontend-kit/ui/src/components/shadcn/skeleton.tsx b/frontend/frontend-kit/kit/src/components/shadcn/skeleton.tsx similarity index 84% rename from frontend/frontend-kit/ui/src/components/shadcn/skeleton.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/skeleton.tsx index 98ad83512..f0d550c36 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/skeleton.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/skeleton.tsx @@ -1,4 +1,4 @@ -import { cn } from "@workspace/ui/lib/utils"; +import { cn } from "../../lib/utils"; function Skeleton({ className, ...props }: React.ComponentProps<"div">) { return ( diff --git a/frontend/frontend-kit/ui/src/components/shadcn/slider.tsx b/frontend/frontend-kit/kit/src/components/shadcn/slider.tsx similarity index 97% rename from frontend/frontend-kit/ui/src/components/shadcn/slider.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/slider.tsx index d930c32eb..f0b563b4e 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/slider.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/slider.tsx @@ -3,7 +3,7 @@ import * as React from "react" import { Slider as SliderPrimitive } from "radix-ui" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Slider({ className, diff --git a/frontend/frontend-kit/ui/src/components/shadcn/spinner.tsx b/frontend/frontend-kit/kit/src/components/shadcn/spinner.tsx similarity index 86% rename from frontend/frontend-kit/ui/src/components/shadcn/spinner.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/spinner.tsx index 4fde36d58..0a196027e 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/spinner.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/spinner.tsx @@ -1,6 +1,6 @@ import { Loader2Icon } from "lucide-react"; -import { cn } from "@workspace/ui/lib/utils"; +import { cn } from "../../lib/utils"; function Spinner({ className, ...props }: React.ComponentProps<"svg">) { return ( diff --git a/frontend/frontend-kit/ui/src/components/shadcn/table.tsx b/frontend/frontend-kit/kit/src/components/shadcn/table.tsx similarity index 98% rename from frontend/frontend-kit/ui/src/components/shadcn/table.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/table.tsx index e73bb2e8e..8d7b5d29a 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/table.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/table.tsx @@ -1,6 +1,6 @@ import * as React from "react" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Table({ className, ...props }: React.ComponentProps<"table">) { return ( diff --git a/frontend/frontend-kit/ui/src/components/shadcn/tabs.tsx b/frontend/frontend-kit/kit/src/components/shadcn/tabs.tsx similarity index 97% rename from frontend/frontend-kit/ui/src/components/shadcn/tabs.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/tabs.tsx index 8546fa567..7af96362d 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/tabs.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/tabs.tsx @@ -3,7 +3,7 @@ import * as React from "react" import * as TabsPrimitive from "@radix-ui/react-tabs" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Tabs({ className, diff --git a/frontend/frontend-kit/ui/src/components/shadcn/textarea.tsx b/frontend/frontend-kit/kit/src/components/shadcn/textarea.tsx similarity index 94% rename from frontend/frontend-kit/ui/src/components/shadcn/textarea.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/textarea.tsx index 41da51ac4..baad8eed6 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/textarea.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/textarea.tsx @@ -1,6 +1,6 @@ import * as React from "react" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { return ( diff --git a/frontend/frontend-kit/ui/src/components/shadcn/tooltip.tsx b/frontend/frontend-kit/kit/src/components/shadcn/tooltip.tsx similarity index 97% rename from frontend/frontend-kit/ui/src/components/shadcn/tooltip.tsx rename to frontend/frontend-kit/kit/src/components/shadcn/tooltip.tsx index 1508a9418..f7d14967a 100644 --- a/frontend/frontend-kit/ui/src/components/shadcn/tooltip.tsx +++ b/frontend/frontend-kit/kit/src/components/shadcn/tooltip.tsx @@ -3,7 +3,7 @@ import * as React from "react" import * as TooltipPrimitive from "@radix-ui/react-tooltip" -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "../../lib/utils" function TooltipProvider({ delayDuration = 0, diff --git a/frontend/frontend-kit/core/src/index.ts b/frontend/frontend-kit/kit/src/core/index.ts similarity index 78% rename from frontend/frontend-kit/core/src/index.ts rename to frontend/frontend-kit/kit/src/core/index.ts index c1f7d87f3..005c4cefa 100644 --- a/frontend/frontend-kit/core/src/index.ts +++ b/frontend/frontend-kit/kit/src/core/index.ts @@ -1,4 +1,5 @@ export * from "./logger"; +export * from "./loggerColors"; export * from "./minMaxDownsample"; export * from "./types"; export * from "./websocket"; diff --git a/frontend/frontend-kit/kit/src/core/logger.ts b/frontend/frontend-kit/kit/src/core/logger.ts new file mode 100644 index 000000000..05633e82a --- /dev/null +++ b/frontend/frontend-kit/kit/src/core/logger.ts @@ -0,0 +1,46 @@ +import { DEFAULT_LOGGER_COLOR, loggerColors } from "./loggerColors"; +import type { LoggerModule } from "./types"; + +export interface Logger { + log: (...args: unknown[]) => void; + warn: (...args: unknown[]) => void; + error: (...args: unknown[]) => void; +} + +/** + * Creates a logger for a given module + * @param module - the module to log for (it's just a colored string that will be shown between `[` and `]` before the message itself) + * @param color - ANSI escape to use. Defaults to the color registered for `module`, or gray when none is registered. Use the `ansi` map. + * @returns a logger object with `log`, `warn`, and `error` methods + */ +export function createLogger(module: LoggerModule, color?: string): Logger { + const prefixColor = color ?? loggerColors[module] ?? DEFAULT_LOGGER_COLOR; + const prefix = `[${module.toUpperCase()}]`; + + return { + // It's important to use `bind` here to correctly display log file path and line number in the console + // Otherwise, console prints will just point to this file + log: console.log.bind(console, `${prefixColor}${prefix}${loggerColors.reset}`), + warn: console.warn.bind( + console, + `${prefixColor}${prefix}${loggerColors.reset}`, + ), + error: console.error.bind( + console, + `${prefixColor}${prefix}${loggerColors.reset}`, + ), + }; +} + +/** + * Logger object with methods for each module + */ +export const logger = { + testingView: createLogger("testing-view"), + competitionView: createLogger("competition-view"), + loggingView: createLogger("logging-view"), + flashingView: createLogger("flashing-view"), + adjView: createLogger("adj-view"), + core: createLogger("core"), + ui: createLogger("ui"), +}; diff --git a/frontend/frontend-kit/kit/src/core/loggerColors.ts b/frontend/frontend-kit/kit/src/core/loggerColors.ts new file mode 100644 index 000000000..abd985b32 --- /dev/null +++ b/frontend/frontend-kit/kit/src/core/loggerColors.ts @@ -0,0 +1,41 @@ +/** + * Raw ANSI escapes, exported so a custom module can pick its own color. + */ +export const ansi = { + black: "\x1b[30m", + red: "\x1b[31m", + green: "\x1b[32m", + yellow: "\x1b[33m", + blue: "\x1b[34m", + magenta: "\x1b[35m", + cyan: "\x1b[36m", + white: "\x1b[37m", + gray: "\x1b[90m", + reset: "\x1b[0m", +} as const; + +/** + * Color per module name. Typed as an open record so that an app outside this + * repository can register its own module through `registerLoggerColor`. + */ +export const loggerColors: Record = { + "testing-view": ansi.cyan, + "competition-view": ansi.magenta, + "logging-view": ansi.blue, + "flashing-view": ansi.red, + "adj-view": ansi.white, + core: ansi.yellow, + ui: ansi.green, + reset: ansi.reset, +}; + +/** Color used for a module that has no registered color. */ +export const DEFAULT_LOGGER_COLOR = ansi.gray; + +/** + * Registers the color a module is logged with, so a later `createLogger` call + * for that module picks it up. + */ +export const registerLoggerColor = (module: string, color: string) => { + loggerColors[module] = color; +}; diff --git a/frontend/frontend-kit/core/src/minMaxDownsample.ts b/frontend/frontend-kit/kit/src/core/minMaxDownsample.ts similarity index 100% rename from frontend/frontend-kit/core/src/minMaxDownsample.ts rename to frontend/frontend-kit/kit/src/core/minMaxDownsample.ts diff --git a/frontend/frontend-kit/kit/src/core/types.ts b/frontend/frontend-kit/kit/src/core/types.ts new file mode 100644 index 000000000..e8b600a69 --- /dev/null +++ b/frontend/frontend-kit/kit/src/core/types.ts @@ -0,0 +1,81 @@ +/** + * Options for the `onTopic` method of the `SocketService` class. + */ +export interface TopicOptions { + /** The downsampling method to use. */ + downsample?: "min-max" | "none"; + + /** The throttle time in milliseconds. */ + throttle?: number; +} + +/** + * The value of a variable in a telemetry packet. + */ +export type VariableValue = + | { last: number; average: number } + | boolean + | string + | number; + +/** + * The variables of a telemetry packet. + */ +export type Variables = Record; + +/** + * A telemetry packet that arrives in high frequency.\ + * Don't confuse it with the `TelemetryCatalogItem` type. + */ +export interface TelemetryPacket { + count: number; + cycleTime: number; + hexValue: string; + id: number; + measurementUpdates: Variables; +} + +/** + * The modules this package ships a color for. + */ +export type KnownLoggerModule = + | "testing-view" + | "competition-view" + | "logging-view" + | "flashing-view" + | "adj-view" + | "core" + | "ui"; + +/** + * A logger module name. Any string is accepted, so an app built on top of this + * package can register its own module; the `KnownLoggerModule` members keep + * their autocomplete and their built-in color. + */ +export type LoggerModule = KnownLoggerModule | (string & {}); + +/** + * Connection settings for the `socketService`. + * + * When `url` is given it wins over every other field. Otherwise the URL is + * built as `${secure ? "wss" : "ws"}://${host}:${port}${path}`. + */ +export interface SocketConfig { + /** Complete WebSocket URL, e.g. "wss://pod.hyperloopupv.com/backend". */ + url?: string; + + /** Hostname or IP. Defaults to "127.0.0.1". */ + host?: string; + + /** Port. Defaults to 4000. */ + port?: number; + + /** Path, leading slash included. Defaults to "/backend". */ + path?: string; + + /** Use wss:// instead of ws://. Defaults to false. */ + secure?: boolean; + + /** Heartbeat period in milliseconds. 0 disables it. Defaults to 1000. */ + heartbeatIntervalMs?: number; +} diff --git a/frontend/frontend-kit/core/src/websocket.ts b/frontend/frontend-kit/kit/src/core/websocket.ts similarity index 62% rename from frontend/frontend-kit/core/src/websocket.ts rename to frontend/frontend-kit/kit/src/core/websocket.ts index 03e291a6a..859c6ef70 100644 --- a/frontend/frontend-kit/core/src/websocket.ts +++ b/frontend/frontend-kit/kit/src/core/websocket.ts @@ -18,7 +18,40 @@ import { import { webSocket, WebSocketSubject } from "rxjs/webSocket"; import { logger } from "./logger"; import { minMaxDownsample } from "./minMaxDownsample"; -import { type TopicOptions } from "./types"; +import { type SocketConfig, type TopicOptions } from "./types"; + +/** + * Values used for every field a caller leaves out. + */ +const DEFAULT_CONFIG = { + host: "127.0.0.1", + port: 4000, + path: "/backend", + secure: false, + heartbeatIntervalMs: 1000, +} as const; + +/** + * Builds the URL `connect` would use for a given config. + * @param config - the connection settings. `url` wins over every other field. + * @returns the resolved WebSocket URL. + */ +export const resolveSocketUrl = (config: SocketConfig = {}): string => { + if (config.url) return config.url; + + const host = config.host ?? DEFAULT_CONFIG.host; + const port = config.port ?? DEFAULT_CONFIG.port; + const path = config.path ?? DEFAULT_CONFIG.path; + const scheme = (config.secure ?? DEFAULT_CONFIG.secure) ? "wss" : "ws"; + + return `${scheme}://${host}:${port}${path}`; +}; + +/** + * Normalizes the backward-compatible `connect(port)` form into a config object. + */ +const toConfig = (options: number | SocketConfig = {}): SocketConfig => + typeof options === "number" ? { port: options } : options; /** * Service for connecting to the WebSocket server and subscribing to topics @@ -69,18 +102,47 @@ class SocketService { */ private heartbeatInterval: ReturnType | null = null; + /** + * Connection settings applied by the last `configure` or `connect` call. + */ + private config: SocketConfig = {}; + + /** + * The URL the current or next connection targets. + */ + get url(): string { + return resolveSocketUrl(this.config); + } + + /** + * Sets the connection defaults, merging with whatever was configured before. + * Call it once when the app boots, before anything calls `connect`. + * + * It does not affect an already open socket: use `reconnect` for that. + * @param config - the connection settings to merge in. + */ + configure(config: SocketConfig) { + this.config = { ...this.config, ...config }; + } + /** * Connects to the WebSocket server by creating a new connection object and pushing it to `socketSource$`. - * @param port - the port to connect to. Defaults to 4000. + * Does nothing when a connection is already open. + * @param options - the connection settings, or a bare port number. The number + * form is kept for backward compatibility: `connect(4000)` is exactly + * `connect({ port: 4000 })`. Whatever is passed is merged into the stored config. */ - connect(port: number = 4000) { + connect(options: number | SocketConfig = {}) { if (this.ws) return; - logger.core.log("Connecting to WebSocket..."); + this.config = { ...this.config, ...toConfig(options) }; + const url = resolveSocketUrl(this.config); + + logger.core.log(`Connecting to WebSocket at ${url}...`); this.status$.next("connecting"); this.ws = webSocket({ - url: `ws://127.0.0.1:${port}/backend`, + url, deserializer: (e) => JSON.parse(e.data), openObserver: { next: () => { @@ -108,16 +170,46 @@ class SocketService { this.socketSource$.next(this.ws); } + /** + * Closes the connection, stops the heartbeat and reports "disconnected". + * Does nothing when there is no open connection. + */ + disconnect() { + if (!this.ws) return; + + logger.core.log("Closing WebSocket..."); + this.ws.complete(); + this.cleanup(); + } + + /** + * Closes the current connection and opens a new one. + * + * `connect` alone cannot do this: it returns early while a socket is open. + * @param options - the connection settings to use, as in `connect`. Omit them to reuse the stored config. + */ + reconnect(options?: number | SocketConfig) { + this.disconnect(); + this.connect(options); + } + /** * Starts the periodic heartbeat that lets the backend detect a dead or * frozen GUI. The backend expects one at least every 3 seconds and treats * a missing heartbeat as a disconnection. + * + * A `heartbeatIntervalMs` of 0 disables it. */ private startHeartbeat() { this.stopHeartbeat(); + + const interval = + this.config.heartbeatIntervalMs ?? DEFAULT_CONFIG.heartbeatIntervalMs; + if (interval <= 0) return; + this.heartbeatInterval = setInterval(() => { this.ws?.next({ topic: "connection/heartbeat", payload: {} }); - }, 1000); + }, interval); } private stopHeartbeat() { @@ -202,3 +294,10 @@ class SocketService { } export const socketService = new SocketService(); + +/** + * Sets the connection defaults on the shared `socketService`. + * Convenience wrapper so an app can configure the socket in one line at boot. + */ +export const configureSocket = (config: SocketConfig) => + socketService.configure(config); diff --git a/frontend/frontend-kit/ui/src/hooks/index.ts b/frontend/frontend-kit/kit/src/hooks/index.ts similarity index 100% rename from frontend/frontend-kit/ui/src/hooks/index.ts rename to frontend/frontend-kit/kit/src/hooks/index.ts diff --git a/frontend/frontend-kit/ui/src/hooks/shadcn/index.ts b/frontend/frontend-kit/kit/src/hooks/shadcn/index.ts similarity index 100% rename from frontend/frontend-kit/ui/src/hooks/shadcn/index.ts rename to frontend/frontend-kit/kit/src/hooks/shadcn/index.ts diff --git a/frontend/frontend-kit/ui/src/hooks/shadcn/use-mobile.ts b/frontend/frontend-kit/kit/src/hooks/shadcn/use-mobile.ts similarity index 100% rename from frontend/frontend-kit/ui/src/hooks/shadcn/use-mobile.ts rename to frontend/frontend-kit/kit/src/hooks/shadcn/use-mobile.ts diff --git a/frontend/frontend-kit/ui/src/hooks/webSocket/fetchConfig.ts b/frontend/frontend-kit/kit/src/hooks/webSocket/fetchConfig.ts similarity index 96% rename from frontend/frontend-kit/ui/src/hooks/webSocket/fetchConfig.ts rename to frontend/frontend-kit/kit/src/hooks/webSocket/fetchConfig.ts index b1358dfad..9ab182fc9 100644 --- a/frontend/frontend-kit/ui/src/hooks/webSocket/fetchConfig.ts +++ b/frontend/frontend-kit/kit/src/hooks/webSocket/fetchConfig.ts @@ -1,4 +1,4 @@ -import { logger } from "@workspace/core"; +import { logger } from "../../core"; import { useCallback, useEffect, useRef, useState } from "react"; export function useFetchConfig(baseUrl: string, endpoint: string) { diff --git a/frontend/frontend-kit/ui/src/hooks/webSocket/index.ts b/frontend/frontend-kit/kit/src/hooks/webSocket/index.ts similarity index 100% rename from frontend/frontend-kit/ui/src/hooks/webSocket/index.ts rename to frontend/frontend-kit/kit/src/hooks/webSocket/index.ts diff --git a/frontend/frontend-kit/ui/src/hooks/webSocket/useErrorSubscription.ts b/frontend/frontend-kit/kit/src/hooks/webSocket/useErrorSubscription.ts similarity index 85% rename from frontend/frontend-kit/ui/src/hooks/webSocket/useErrorSubscription.ts rename to frontend/frontend-kit/kit/src/hooks/webSocket/useErrorSubscription.ts index 6b1eb734f..2a546f458 100644 --- a/frontend/frontend-kit/ui/src/hooks/webSocket/useErrorSubscription.ts +++ b/frontend/frontend-kit/kit/src/hooks/webSocket/useErrorSubscription.ts @@ -1,4 +1,4 @@ -import { socketService } from "@workspace/core"; +import { socketService } from "../../core"; import { useEffect } from "react"; const useErrorSubscription = (callback: (err: Error) => void) => { diff --git a/frontend/frontend-kit/ui/src/hooks/webSocket/useTopic.ts b/frontend/frontend-kit/kit/src/hooks/webSocket/useTopic.ts similarity index 92% rename from frontend/frontend-kit/ui/src/hooks/webSocket/useTopic.ts rename to frontend/frontend-kit/kit/src/hooks/webSocket/useTopic.ts index baf695585..b1f4b0740 100644 --- a/frontend/frontend-kit/ui/src/hooks/webSocket/useTopic.ts +++ b/frontend/frontend-kit/kit/src/hooks/webSocket/useTopic.ts @@ -1,4 +1,4 @@ -import { logger, socketService, type TopicOptions } from "@workspace/core"; +import { logger, socketService, type TopicOptions } from "../../core"; import { useEffect, useRef } from "react"; import { useWebSocket } from "./useWebSocket"; diff --git a/frontend/frontend-kit/kit/src/hooks/webSocket/useWebSocket.ts b/frontend/frontend-kit/kit/src/hooks/webSocket/useWebSocket.ts new file mode 100644 index 000000000..702e71591 --- /dev/null +++ b/frontend/frontend-kit/kit/src/hooks/webSocket/useWebSocket.ts @@ -0,0 +1,28 @@ +import { socketService, type SocketConfig } from "../../core"; +import { useEffect, useState } from "react"; + +/** + * Opens the shared WebSocket connection and tracks its status. + * @param config - connection settings. Omit them to use whatever was set with + * `configureSocket`, which falls back to ws://127.0.0.1:4000/backend. + */ +export const useWebSocket = (config?: SocketConfig) => { + const [status, setStatus] = useState("disconnected"); + + useEffect(() => { + socketService.connect(config); + + const statusSub = socketService.status$.subscribe(setStatus); + + return () => { + statusSub.unsubscribe(); + }; + }, [JSON.stringify(config)]); + + return { + isConnected: status === "connected", + status, + url: socketService.url, + reconnect: () => socketService.reconnect(config), + }; +}; diff --git a/frontend/frontend-kit/ui/src/icons/accessibility.ts b/frontend/frontend-kit/kit/src/icons/accessibility.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/accessibility.ts rename to frontend/frontend-kit/kit/src/icons/accessibility.ts diff --git a/frontend/frontend-kit/ui/src/icons/account.ts b/frontend/frontend-kit/kit/src/icons/account.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/account.ts rename to frontend/frontend-kit/kit/src/icons/account.ts diff --git a/frontend/frontend-kit/ui/src/icons/arrows.ts b/frontend/frontend-kit/kit/src/icons/arrows.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/arrows.ts rename to frontend/frontend-kit/kit/src/icons/arrows.ts diff --git a/frontend/frontend-kit/ui/src/icons/cursors.ts b/frontend/frontend-kit/kit/src/icons/cursors.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/cursors.ts rename to frontend/frontend-kit/kit/src/icons/cursors.ts diff --git a/frontend/frontend-kit/ui/src/icons/design.ts b/frontend/frontend-kit/kit/src/icons/design.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/design.ts rename to frontend/frontend-kit/kit/src/icons/design.ts diff --git a/frontend/frontend-kit/ui/src/icons/development.ts b/frontend/frontend-kit/kit/src/icons/development.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/development.ts rename to frontend/frontend-kit/kit/src/icons/development.ts diff --git a/frontend/frontend-kit/ui/src/icons/devices.ts b/frontend/frontend-kit/kit/src/icons/devices.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/devices.ts rename to frontend/frontend-kit/kit/src/icons/devices.ts diff --git a/frontend/frontend-kit/ui/src/icons/files.ts b/frontend/frontend-kit/kit/src/icons/files.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/files.ts rename to frontend/frontend-kit/kit/src/icons/files.ts diff --git a/frontend/frontend-kit/ui/src/icons/gaming.ts b/frontend/frontend-kit/kit/src/icons/gaming.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/gaming.ts rename to frontend/frontend-kit/kit/src/icons/gaming.ts diff --git a/frontend/frontend-kit/ui/src/icons/index.ts b/frontend/frontend-kit/kit/src/icons/index.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/index.ts rename to frontend/frontend-kit/kit/src/icons/index.ts diff --git a/frontend/frontend-kit/ui/src/icons/layout.ts b/frontend/frontend-kit/kit/src/icons/layout.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/layout.ts rename to frontend/frontend-kit/kit/src/icons/layout.ts diff --git a/frontend/frontend-kit/ui/src/icons/mail.ts b/frontend/frontend-kit/kit/src/icons/mail.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/mail.ts rename to frontend/frontend-kit/kit/src/icons/mail.ts diff --git a/frontend/frontend-kit/ui/src/icons/math.ts b/frontend/frontend-kit/kit/src/icons/math.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/math.ts rename to frontend/frontend-kit/kit/src/icons/math.ts diff --git a/frontend/frontend-kit/ui/src/icons/notifications.ts b/frontend/frontend-kit/kit/src/icons/notifications.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/notifications.ts rename to frontend/frontend-kit/kit/src/icons/notifications.ts diff --git a/frontend/frontend-kit/ui/src/icons/photography.ts b/frontend/frontend-kit/kit/src/icons/photography.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/photography.ts rename to frontend/frontend-kit/kit/src/icons/photography.ts diff --git a/frontend/frontend-kit/ui/src/icons/science.ts b/frontend/frontend-kit/kit/src/icons/science.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/science.ts rename to frontend/frontend-kit/kit/src/icons/science.ts diff --git a/frontend/frontend-kit/ui/src/icons/shapes.ts b/frontend/frontend-kit/kit/src/icons/shapes.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/shapes.ts rename to frontend/frontend-kit/kit/src/icons/shapes.ts diff --git a/frontend/frontend-kit/ui/src/icons/social.ts b/frontend/frontend-kit/kit/src/icons/social.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/social.ts rename to frontend/frontend-kit/kit/src/icons/social.ts diff --git a/frontend/frontend-kit/ui/src/icons/text.ts b/frontend/frontend-kit/kit/src/icons/text.ts similarity index 100% rename from frontend/frontend-kit/ui/src/icons/text.ts rename to frontend/frontend-kit/kit/src/icons/text.ts diff --git a/frontend/frontend-kit/ui/src/index.ts b/frontend/frontend-kit/kit/src/index.ts similarity index 100% rename from frontend/frontend-kit/ui/src/index.ts rename to frontend/frontend-kit/kit/src/index.ts diff --git a/frontend/frontend-kit/ui/src/lib/index.ts b/frontend/frontend-kit/kit/src/lib/index.ts similarity index 100% rename from frontend/frontend-kit/ui/src/lib/index.ts rename to frontend/frontend-kit/kit/src/lib/index.ts diff --git a/frontend/frontend-kit/ui/src/lib/typeUtils.ts b/frontend/frontend-kit/kit/src/lib/typeUtils.ts similarity index 100% rename from frontend/frontend-kit/ui/src/lib/typeUtils.ts rename to frontend/frontend-kit/kit/src/lib/typeUtils.ts diff --git a/frontend/frontend-kit/ui/src/lib/utils.ts b/frontend/frontend-kit/kit/src/lib/utils.ts similarity index 100% rename from frontend/frontend-kit/ui/src/lib/utils.ts rename to frontend/frontend-kit/kit/src/lib/utils.ts diff --git a/frontend/frontend-kit/ui/src/outreach/h11/h11-isotipo_black.svg b/frontend/frontend-kit/kit/src/outreach/h11/h11-isotipo_black.svg similarity index 100% rename from frontend/frontend-kit/ui/src/outreach/h11/h11-isotipo_black.svg rename to frontend/frontend-kit/kit/src/outreach/h11/h11-isotipo_black.svg diff --git a/frontend/frontend-kit/ui/src/outreach/main/check_black.png b/frontend/frontend-kit/kit/src/outreach/main/check_black.png similarity index 100% rename from frontend/frontend-kit/ui/src/outreach/main/check_black.png rename to frontend/frontend-kit/kit/src/outreach/main/check_black.png diff --git a/frontend/frontend-kit/ui/src/outreach/main/full_logo_black.png b/frontend/frontend-kit/kit/src/outreach/main/full_logo_black.png similarity index 100% rename from frontend/frontend-kit/ui/src/outreach/main/full_logo_black.png rename to frontend/frontend-kit/kit/src/outreach/main/full_logo_black.png diff --git a/frontend/frontend-kit/ui/src/outreach/main/hyperloop_black.png b/frontend/frontend-kit/kit/src/outreach/main/hyperloop_black.png similarity index 100% rename from frontend/frontend-kit/ui/src/outreach/main/hyperloop_black.png rename to frontend/frontend-kit/kit/src/outreach/main/hyperloop_black.png diff --git a/frontend/frontend-kit/ui/src/outreach/main/logo_icon.svg b/frontend/frontend-kit/kit/src/outreach/main/logo_icon.svg similarity index 100% rename from frontend/frontend-kit/ui/src/outreach/main/logo_icon.svg rename to frontend/frontend-kit/kit/src/outreach/main/logo_icon.svg diff --git a/frontend/frontend-kit/ui/src/outreach/main/software_black.png b/frontend/frontend-kit/kit/src/outreach/main/software_black.png similarity index 100% rename from frontend/frontend-kit/ui/src/outreach/main/software_black.png rename to frontend/frontend-kit/kit/src/outreach/main/software_black.png diff --git a/frontend/frontend-kit/ui/src/outreach/main/software_white.png b/frontend/frontend-kit/kit/src/outreach/main/software_white.png similarity index 100% rename from frontend/frontend-kit/ui/src/outreach/main/software_white.png rename to frontend/frontend-kit/kit/src/outreach/main/software_white.png diff --git a/frontend/frontend-kit/kit/src/store/index.ts b/frontend/frontend-kit/kit/src/store/index.ts new file mode 100644 index 000000000..86a1b09fe --- /dev/null +++ b/frontend/frontend-kit/kit/src/store/index.ts @@ -0,0 +1,6 @@ +// NOTE: ./use-dark-mode-store does not exist, so this barrel is broken and +// nothing imports it. It is left in place, and in the dev exports, but excluded +// from the build (vite.config.ts), from tsconfig.build.json and from +// publishConfig.exports. If you add use-dark-mode-store.ts, re-add "./store" in +// those three places for it to work from the published package. +export * from "./use-dark-mode-store"; diff --git a/frontend/frontend-kit/ui/src/styles/globals.css b/frontend/frontend-kit/kit/src/styles/globals.css similarity index 97% rename from frontend/frontend-kit/ui/src/styles/globals.css rename to frontend/frontend-kit/kit/src/styles/globals.css index 642cae773..4ad617b0c 100644 --- a/frontend/frontend-kit/ui/src/styles/globals.css +++ b/frontend/frontend-kit/kit/src/styles/globals.css @@ -1,9 +1,9 @@ @import url("https://fonts.googleapis.com/css2?family=Archivo:wght@100;200;300;400;500;600;700;800;900&display=swap"); @import "tailwindcss"; -@source "../../../../testing-view/**/*.{ts,tsx}"; -@source "../../../../competition-view/**/*.{ts,tsx}"; -/* @source "../../src/components*.{ts,tsx}"; */ +/* Scan only this package's own sources. Each app declares its own @source glob + in its index.css, because paths resolved from here go through the + @hyperloop-upv/frontend-kit symlink and don't reach the app's source tree. */ @source "../**/*.{ts,tsx}"; @import "tw-animate-css"; diff --git a/frontend/frontend-kit/kit/tsconfig.build.json b/frontend/frontend-kit/kit/tsconfig.build.json new file mode 100644 index 000000000..991dd6126 --- /dev/null +++ b/frontend/frontend-kit/kit/tsconfig.build.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": false, + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true, + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src"], + "exclude": ["src/store", "node_modules", "dist"] +} diff --git a/frontend/frontend-kit/kit/tsconfig.json b/frontend/frontend-kit/kit/tsconfig.json new file mode 100644 index 000000000..9e5e83901 --- /dev/null +++ b/frontend/frontend-kit/kit/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "@hyperloop-upv/typescript-config/react-library.json", + "include": ["."], + "exclude": ["node_modules", "dist"] +} diff --git a/frontend/frontend-kit/kit/vite.config.ts b/frontend/frontend-kit/kit/vite.config.ts new file mode 100644 index 000000000..89edaee08 --- /dev/null +++ b/frontend/frontend-kit/kit/vite.config.ts @@ -0,0 +1,88 @@ +import { readFileSync } from "node:fs"; +import { isAbsolute, resolve } from "node:path"; +import react from "@vitejs/plugin-react-swc"; +import { globSync } from "tinyglobby"; +import { defineConfig, type Plugin } from "vite"; +import dts from "vite-plugin-dts"; + +/** + * Rollup strips module-level directives from the emitted JavaScript, so the + * 18 shadcn files that opt into client rendering would lose it. They are inert + * in Vite and Electron but required by a React Server Components consumer, so + * put them back on the chunks whose source had one. + */ +const preserveUseClient = (): Plugin => ({ + name: "preserve-use-client", + renderChunk(code, chunk) { + const source = chunk.facadeModuleId; + if (!source) return null; + + const directive = readFileSync(source, "utf8").trimStart(); + if (!directive.startsWith('"use client"') && !directive.startsWith("'use client'")) { + return null; + } + + return { code: `"use client";\n${code}`, map: null }; + }, +}); + +// Every source file is its own Rollup entry. Together with preserveModules this +// mirrors src/ into dist/, which is what keeps the wildcard subpath exports +// ("./components/*") resolvable in the published package: a new component works +// with no entry list to maintain. +const entries = globSync(["src/**/*.{ts,tsx}"], { + ignore: [ + // ./store re-exports ./use-dark-mode-store, which does not exist. Kept on + // disk and in the dev exports, left out of the published surface. + "src/store/**", + "src/**/*.test.{ts,tsx}", + "src/**/*.d.ts", + ], +}).map((file) => resolve(file)); + +export default defineConfig({ + plugins: [ + react(), + preserveUseClient(), + dts({ + tsconfigPath: "./tsconfig.build.json", + entryRoot: "src", + outDir: "dist", + // One .d.ts per module, mirroring dist/. Rolling them into a single file + // would break per-subpath type resolution. + rollupTypes: false, + insertTypesEntry: false, + }), + ], + build: { + target: "es2022", + outDir: "dist", + emptyOutDir: true, + // Keeps the Tailwind class strings readable and the output debuggable. The + // consuming app minifies anyway. + minify: false, + sourcemap: true, + rollupOptions: { + input: entries, + // Vite defaults this to false for app builds, which Rollup rejects + // together with preserveModules. + preserveEntrySignatures: "strict", + // Anything that is not a relative or absolute path is a bare specifier, + // i.e. a dependency: leave it as an import instead of inlining it. + external: (id) => !id.startsWith(".") && !isAbsolute(id), + output: { + format: "es", + dir: "dist", + preserveModules: true, + preserveModulesRoot: "src", + entryFileNames: "[name].js", + chunkFileNames: "[name].js", + }, + onwarn(warning, warn) { + // preserveUseClient puts these back; Rollup's warning is expected. + if (warning.code === "MODULE_LEVEL_DIRECTIVE") return; + warn(warning); + }, + }, + }, +}); diff --git a/frontend/frontend-kit/typescript-config/package.json b/frontend/frontend-kit/typescript-config/package.json index eeb097e57..87fa43108 100644 --- a/frontend/frontend-kit/typescript-config/package.json +++ b/frontend/frontend-kit/typescript-config/package.json @@ -1,8 +1,5 @@ { - "name": "@workspace/typescript-config", + "name": "@hyperloop-upv/typescript-config", "version": "0.0.0", - "private": true, - "publishConfig": { - "access": "public" - } + "private": true } diff --git a/frontend/frontend-kit/ui/README.md b/frontend/frontend-kit/ui/README.md deleted file mode 100644 index 7b5a9e4f9..000000000 --- a/frontend/frontend-kit/ui/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# UI Package - Frontend Kit - -This package is the main UI and React shared component library for the Hyperloop Control Station. It provides reusable, styled components and hooks built on top of **React**, **Shadcn/UI**, and **Tailwind CSS**. - -## Project Guidelines - -### React-Only Logic - -> This package is specifically for **UI and React-related components**. -> -> - If your logic requires React hooks (`useState`, `useEffect`, etc.) or TSX, it belongs here. -> - **If your logic does NOT need React** (e.g., websocket connections), it should be implemented in the `@workspace/core` package. This keeps the codebase clean and allows for better reuse across different environments. - ---- - -## Icon Management - -We use a custom Rust-based tool, **icons-master**, to manage our Lucide icon exports. This tool helps keep our icons organized by category and ensures we don't have duplicate exports. - -### Usage - -Here are the scripts you can run: - -```bash -# Install dependencies -pnpm install - -# Run linter -pnpm lint - -# Add a new icon from Lucide (Example: pnpm icon:add arrow-up src/icons) -pnpm icon:add src/icons - -# Remove an existing icon export (Example: pnpm icon:remove arrow-up src/icons) -pnpm icon:remove src/icons -``` diff --git a/frontend/frontend-kit/ui/eslint.config.js b/frontend/frontend-kit/ui/eslint.config.js deleted file mode 100644 index f79dd7d64..000000000 --- a/frontend/frontend-kit/ui/eslint.config.js +++ /dev/null @@ -1,4 +0,0 @@ -import { config } from "@workspace/eslint-config/react-internal"; - -/** @type {import("eslint").Linter.Config} */ -export default config; diff --git a/frontend/frontend-kit/ui/package.json b/frontend/frontend-kit/ui/package.json deleted file mode 100644 index 874546f7d..000000000 --- a/frontend/frontend-kit/ui/package.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "name": "@workspace/ui", - "version": "0.0.0", - "type": "module", - "private": true, - "scripts": { - "preinstall": "npx only-allow pnpm", - "lint": "eslint .", - "icon:add": "icons-master add", - "icon:remove": "icons-master remove" - }, - "dependencies": { - "@base-ui/react": "^1.3.0", - "@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-label": "^2.1.8", - "@radix-ui/react-popover": "^1.1.15", - "@radix-ui/react-select": "^2.2.6", - "@radix-ui/react-separator": "^1.1.8", - "@radix-ui/react-slot": "^1.2.4", - "@radix-ui/react-tabs": "^1.1.13", - "@radix-ui/react-tooltip": "^1.2.8", - "@workspace/core": "workspace:*", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "lucide-react": "^0.563.0", - "next-themes": "^0.4.6", - "radix-ui": "^1.4.3", - "react": "^19.2.4", - "react-dom": "^19.2.4", - "react-resizable-panels": "^4.6.0", - "rxjs": "^7.8.2", - "tailwind-merge": "^3.4.0", - "tw-animate-css": "^1.4.0", - "zod": "^4.3.6", - "zustand": "^5.0.11" - }, - "devDependencies": { - "@maximka76667/icons-master": "^1.0.3", - "@tailwindcss/postcss": "^4.1.18", - "@turbo/gen": "^2.8.3", - "@types/node": "^25.2.0", - "@types/react": "^19.2.11", - "@types/react-dom": "^19.2.3", - "@workspace/eslint-config": "workspace:*", - "@workspace/typescript-config": "workspace:*", - "eslint": "^9.39.2", - "tailwindcss": "^4.1.18", - "typescript": "^5.9.3" - }, - "exports": { - ".": "./src/index.ts", - "./globals.css": "./src/styles/globals.css", - "./postcss.config": "./postcss.config.mjs", - "./lib": "./src/lib/index.ts", - "./components": "./src/components/index.ts", - "./hooks": "./src/hooks/index.ts", - "./lib/*": "./src/lib/*.ts", - "./components/*": "./src/components/*.tsx", - "./hooks/*": "./src/hooks/*.ts", - "./store": "./src/store/index.ts", - "./icons": "./src/icons/index.ts", - "./outreach/*": "./src/outreach/*" - } -} diff --git a/frontend/frontend-kit/ui/src/hooks/webSocket/useWebSocket.ts b/frontend/frontend-kit/ui/src/hooks/webSocket/useWebSocket.ts deleted file mode 100644 index 081f12c6a..000000000 --- a/frontend/frontend-kit/ui/src/hooks/webSocket/useWebSocket.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { socketService } from "@workspace/core"; -import { useEffect, useState } from "react"; - -export const useWebSocket = () => { - const [status, setStatus] = useState("disconnected"); - - useEffect(() => { - socketService.connect(); - - const statusSub = socketService.status$.subscribe(setStatus); - - return () => { - statusSub.unsubscribe(); - }; - }, []); - - return { - isConnected: status === "connected", - status, - reconnect: () => socketService.connect(), - }; -}; diff --git a/frontend/frontend-kit/ui/src/store/index.ts b/frontend/frontend-kit/ui/src/store/index.ts deleted file mode 100644 index b0baa1aa0..000000000 --- a/frontend/frontend-kit/ui/src/store/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./use-dark-mode-store"; diff --git a/frontend/frontend-kit/ui/tsconfig.json b/frontend/frontend-kit/ui/tsconfig.json deleted file mode 100644 index 0bedc71da..000000000 --- a/frontend/frontend-kit/ui/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "@workspace/typescript-config/react-library.json", - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@workspace/ui/*": ["./src/*"] - } - }, - "include": ["."], - "exclude": ["node_modules", "dist"] -} diff --git a/frontend/logging-view/CLAUDE.md b/frontend/logging-view/CLAUDE.md index 9ef79714c..7e821d9e0 100644 --- a/frontend/logging-view/CLAUDE.md +++ b/frontend/logging-view/CLAUDE.md @@ -19,7 +19,7 @@ There is no test suite; verify with `pnpm build` and `pnpm lint`. Lint currently ## What this app is -An **offline analysis tool for backend log sessions**. The user opens a session folder written by the backend logger; the app reads its CSVs and the session's ADJ, and plots them. It has **no WebSocket or live backend connection**: the `telemetry`, `messages`, `catalog` and `connections` store slices and the `@workspace/core` dependency are leftovers from the `competition-view` scaffold and nothing reads them. +An **offline analysis tool for backend log sessions**. The user opens a session folder written by the backend logger; the app reads its CSVs and the session's ADJ, and plots them. It has **no WebSocket or live backend connection**: the `telemetry`, `messages`, `catalog` and `connections` store slices and the `@hyperloop-upv/frontend-kit/core` dependency are leftovers from the `competition-view` scaffold and nothing reads them. Routing is a `HashRouter` (`src/main.tsx`, needed when served from the Electron app). `/` redirects to `/simple`; `/normal` is a placeholder page ("still under development"). @@ -57,14 +57,14 @@ A single Zustand store (`src/store/store.ts`) composed of slices. The ones in us ## Workspace dependencies -Components, icons and utilities come from `@workspace/ui` (`frontend-kit/ui`): +Components, icons and utilities come from `@hyperloop-upv/frontend-kit` (`frontend-kit/kit`): ```tsx -import { Button, Sidebar } from "@workspace/ui/components"; -import { Plus } from "@workspace/ui/icons"; +import { Button, Sidebar } from "@hyperloop-upv/frontend-kit/components"; +import { Plus } from "@hyperloop-upv/frontend-kit/icons"; ``` -To add an icon: find it on lucide.dev, add its export to the file in `frontend-kit/ui/src/icons/` named after its **first** category, and re-export from `index.ts` if that file is new. +To add an icon: find it on lucide.dev, add its export to the file in `frontend-kit/kit/src/icons/` named after its **first** category, and re-export from `index.ts` if that file is new. ## Gotchas diff --git a/frontend/logging-view/eslint.config.js b/frontend/logging-view/eslint.config.js index df360b435..a2b580035 100644 --- a/frontend/logging-view/eslint.config.js +++ b/frontend/logging-view/eslint.config.js @@ -1,3 +1,3 @@ -import { config } from "@workspace/eslint-config/vite"; +import { config } from "@hyperloop-upv/eslint-config/vite"; export default config; diff --git a/frontend/logging-view/package.json b/frontend/logging-view/package.json index c84682d79..51ac0ca12 100644 --- a/frontend/logging-view/package.json +++ b/frontend/logging-view/package.json @@ -17,8 +17,7 @@ "@tanstack/react-virtual": "^3.13.18", "@types/plotly.js": "^3.0.10", "@vitejs/plugin-react-swc": "^4.2.3", - "@workspace/core": "workspace:*", - "@workspace/ui": "workspace:*", + "@hyperloop-upv/frontend-kit": "workspace:*", "jspdf": "^4.2.1", "jspdf-autotable": "^5.0.8", "lucide-react": "^0.563.0", @@ -32,8 +31,8 @@ "devDependencies": { "@types/react": "^19.2.11", "@types/react-dom": "^19.2.3", - "@workspace/eslint-config": "workspace:^", - "@workspace/typescript-config": "workspace:*", + "@hyperloop-upv/eslint-config": "workspace:^", + "@hyperloop-upv/typescript-config": "workspace:*", "eslint": "^9.39.2", "globals": "^17.3.0", "typescript": "^5.9.3", diff --git a/frontend/logging-view/src/components/KeyboardShortcutsHelp.tsx b/frontend/logging-view/src/components/KeyboardShortcutsHelp.tsx index 97377d448..75190b2b8 100644 --- a/frontend/logging-view/src/components/KeyboardShortcutsHelp.tsx +++ b/frontend/logging-view/src/components/KeyboardShortcutsHelp.tsx @@ -4,8 +4,8 @@ import { DialogHeader, DialogTitle, Separator, -} from "@workspace/ui/components"; -import { Keyboard } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit/components"; +import { Keyboard } from "@hyperloop-upv/frontend-kit/icons"; // NOTE: the original hooks module was not available at this path in some // environments. Define a local fallback for SHORTCUT_DEFS here so this // component compiles and still shows useful keyboard shortcuts. Keep the diff --git a/frontend/logging-view/src/components/PlotAddedToast.tsx b/frontend/logging-view/src/components/PlotAddedToast.tsx index 807de4ef6..3b8a91040 100644 --- a/frontend/logging-view/src/components/PlotAddedToast.tsx +++ b/frontend/logging-view/src/components/PlotAddedToast.tsx @@ -2,8 +2,8 @@ // (issue: adding a plot gave no on-screen feedback). Mirrors SessionStatusToast's // auto-dismiss + manual-dismiss pattern, but anchored bottom-right so it never // overlaps that top-right session toast. -import { CheckCircle2, X } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { CheckCircle2, X } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useEffect } from "react"; import { useStore } from "../store/store"; import { sessionStatusStyles } from "./sidebar/sessionStatusStyles"; diff --git a/frontend/logging-view/src/components/SessionStatusToast.tsx b/frontend/logging-view/src/components/SessionStatusToast.tsx index 529c4e396..2b09c66a0 100644 --- a/frontend/logging-view/src/components/SessionStatusToast.tsx +++ b/frontend/logging-view/src/components/SessionStatusToast.tsx @@ -4,8 +4,8 @@ // + manual-dismiss pattern used by the signalLoadWarning banner in PlotStudio.tsx. // Bottom-right, same corner as PlotAddedToast, so every transient notification // in the app reads as one consistent toast stack. -import { AlertTriangle, X } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { AlertTriangle, X } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useEffect } from "react"; import { useStore } from "../store/store"; import { adjWarningClass, sessionStatusStyles } from "./sidebar/sessionStatusStyles"; diff --git a/frontend/logging-view/src/components/header/Header.tsx b/frontend/logging-view/src/components/header/Header.tsx index c2a35adfb..292893b75 100644 --- a/frontend/logging-view/src/components/header/Header.tsx +++ b/frontend/logging-view/src/components/header/Header.tsx @@ -1,9 +1,9 @@ // Top bar with the page title and a Normal / Simple mode segmented control. // Mode switching navigates between routes (/normal, /simple) rather than // store state, since each mode has a distinct UI. -import { SegmentedControl } from "@workspace/ui/components"; +import { SegmentedControl } from "@hyperloop-upv/frontend-kit/components"; import { useLocation, useNavigate } from "react-router"; -import logo from "@workspace/ui/outreach/h11/h11-isotipo_black.svg"; +import logo from "@hyperloop-upv/frontend-kit/outreach/h11/h11-isotipo_black.svg"; type ViewMode = "normal" | "simple"; diff --git a/frontend/logging-view/src/components/sidebar/AppSidebar.tsx b/frontend/logging-view/src/components/sidebar/AppSidebar.tsx index 7d2f61a26..9b736e31b 100644 --- a/frontend/logging-view/src/components/sidebar/AppSidebar.tsx +++ b/frontend/logging-view/src/components/sidebar/AppSidebar.tsx @@ -8,7 +8,7 @@ import { SidebarFooter, SidebarHeader, SidebarSeparator, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; import FolderPickerGroup from "./FolderPickerGroup"; import SeriesGroup from "./SeriesGroup"; import SeriesSelectionBar from "./SeriesSelectionBar"; diff --git a/frontend/logging-view/src/components/sidebar/FolderPickerGroup.tsx b/frontend/logging-view/src/components/sidebar/FolderPickerGroup.tsx index 12ad990e6..216b1e9fa 100644 --- a/frontend/logging-view/src/components/sidebar/FolderPickerGroup.tsx +++ b/frontend/logging-view/src/components/sidebar/FolderPickerGroup.tsx @@ -9,7 +9,7 @@ import { SidebarGroup, SidebarGroupContent, SidebarGroupLabel, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; import { AlertTriangle, BookOpen, @@ -18,8 +18,8 @@ import { GitCommit, Timer, X, -} from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +} from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useCallback, useRef, useState } from "react"; import { useStore } from "../../store/store"; import type { DroppedFile } from "../../types/session"; diff --git a/frontend/logging-view/src/components/sidebar/Logo.tsx b/frontend/logging-view/src/components/sidebar/Logo.tsx index ebbf05718..f8d5e8a93 100644 --- a/frontend/logging-view/src/components/sidebar/Logo.tsx +++ b/frontend/logging-view/src/components/sidebar/Logo.tsx @@ -1,6 +1,6 @@ -import { SidebarMenuButton } from "@workspace/ui/components"; +import { SidebarMenuButton } from "@hyperloop-upv/frontend-kit/components"; import { Link } from "react-router"; -import logo from "@workspace/ui/outreach/h11/h11-isotipo_black.svg"; +import logo from "@hyperloop-upv/frontend-kit/outreach/h11/h11-isotipo_black.svg"; const Logo = () => ( diff --git a/frontend/logging-view/src/components/sidebar/NavigationGroup.tsx b/frontend/logging-view/src/components/sidebar/NavigationGroup.tsx index 41da64c38..09380d3c4 100644 --- a/frontend/logging-view/src/components/sidebar/NavigationGroup.tsx +++ b/frontend/logging-view/src/components/sidebar/NavigationGroup.tsx @@ -4,8 +4,8 @@ import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, -} from "@workspace/ui/components"; -import { type LucideIcon } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit/components"; +import { type LucideIcon } from "@hyperloop-upv/frontend-kit/icons"; import { Link, useLocation } from "react-router"; interface NavItem { diff --git a/frontend/logging-view/src/components/sidebar/SeriesGroup.tsx b/frontend/logging-view/src/components/sidebar/SeriesGroup.tsx index 5f688e210..898370360 100644 --- a/frontend/logging-view/src/components/sidebar/SeriesGroup.tsx +++ b/frontend/logging-view/src/components/sidebar/SeriesGroup.tsx @@ -43,9 +43,9 @@ import { SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, -} from "@workspace/ui/components"; -import { ChevronRight, GripVertical, Layers, Plus } from "@workspace/ui/icons"; -import { cn, getTypeBadgeClass } from "@workspace/ui/lib"; +} from "@hyperloop-upv/frontend-kit/components"; +import { ChevronRight, GripVertical, Layers, Plus } from "@hyperloop-upv/frontend-kit/icons"; +import { cn, getTypeBadgeClass } from "@hyperloop-upv/frontend-kit/lib"; import { useMemo, useRef, useState } from "react"; import { useAssignSignalsToPlot } from "../simple/hooks/useStudioSignals"; import type { PlotState } from "../../types/plotStudio"; diff --git a/frontend/logging-view/src/components/sidebar/SeriesSelectionBar.tsx b/frontend/logging-view/src/components/sidebar/SeriesSelectionBar.tsx index e8929a806..3847ee414 100644 --- a/frontend/logging-view/src/components/sidebar/SeriesSelectionBar.tsx +++ b/frontend/logging-view/src/components/sidebar/SeriesSelectionBar.tsx @@ -2,8 +2,8 @@ // checked, letting the user add them all to an existing plot or spin up a // new plot containing them — turns the (previously decorative) checkbox // selection into a real bulk-assign action. -import { Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@workspace/ui/components"; -import { Layers, Plus, X } from "@workspace/ui/icons"; +import { Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@hyperloop-upv/frontend-kit/components"; +import { Layers, Plus, X } from "@hyperloop-upv/frontend-kit/icons"; import { useMemo, useState } from "react"; import { useAssignSignalsToPlot } from "../simple/hooks/useStudioSignals"; import { useStore } from "../../store/store"; diff --git a/frontend/logging-view/src/components/sidebar/SessionStatusBadge.tsx b/frontend/logging-view/src/components/sidebar/SessionStatusBadge.tsx index 54123631c..0a63c0600 100644 --- a/frontend/logging-view/src/components/sidebar/SessionStatusBadge.tsx +++ b/frontend/logging-view/src/components/sidebar/SessionStatusBadge.tsx @@ -1,9 +1,9 @@ // Persistent green/yellow/red status pill shown in the sidebar for the currently // open session (logger settings / CSV / ADJ availability). See SessionStatus in // types/session.ts for the cascade this reflects. -import { Badge } from "@workspace/ui/components"; -import { AlertTriangle } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { Badge } from "@hyperloop-upv/frontend-kit/components"; +import { AlertTriangle } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import type { SessionStatus } from "../../types/session"; import { adjWarningClass, sessionStatusStyles } from "./sessionStatusStyles"; diff --git a/frontend/logging-view/src/components/sidebar/SidebarToggleHandle.tsx b/frontend/logging-view/src/components/sidebar/SidebarToggleHandle.tsx index 485a2ac13..8248dc54a 100644 --- a/frontend/logging-view/src/components/sidebar/SidebarToggleHandle.tsx +++ b/frontend/logging-view/src/components/sidebar/SidebarToggleHandle.tsx @@ -1,7 +1,7 @@ // Sidebar toggle handle — click to open/close the sidebar. -import { useSidebar } from "@workspace/ui/components"; -import { ChevronLeft, ChevronRight } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { useSidebar } from "@hyperloop-upv/frontend-kit/components"; +import { ChevronLeft, ChevronRight } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useState } from "react"; const SidebarToggleHandle = () => { diff --git a/frontend/logging-view/src/components/sidebar/ThemeToggleItem.tsx b/frontend/logging-view/src/components/sidebar/ThemeToggleItem.tsx index 79867f748..c8e228801 100644 --- a/frontend/logging-view/src/components/sidebar/ThemeToggleItem.tsx +++ b/frontend/logging-view/src/components/sidebar/ThemeToggleItem.tsx @@ -1,5 +1,5 @@ -import { SidebarMenuButton } from "@workspace/ui/components"; -import { SunMoon } from "@workspace/ui/icons"; +import { SidebarMenuButton } from "@hyperloop-upv/frontend-kit/components"; +import { SunMoon } from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../store/store"; const ThemeToggleItem = () => { diff --git a/frontend/logging-view/src/components/sidebar/sessionStatusStyles.ts b/frontend/logging-view/src/components/sidebar/sessionStatusStyles.ts index 373849805..18dc22675 100644 --- a/frontend/logging-view/src/components/sidebar/sessionStatusStyles.ts +++ b/frontend/logging-view/src/components/sidebar/sessionStatusStyles.ts @@ -1,6 +1,6 @@ // Shared green/yellow/red styling for SessionStatus, used by both the persistent // sidebar badge and the transient toast so the two stay visually consistent. -import { AlertTriangle, CheckCircle2, XCircle } from "@workspace/ui/icons"; +import { AlertTriangle, CheckCircle2, XCircle } from "@hyperloop-upv/frontend-kit/icons"; import type { SessionStatusLevel } from "../../types/session"; export const sessionStatusStyles: Record< diff --git a/frontend/logging-view/src/components/simple/PlotStudio.tsx b/frontend/logging-view/src/components/simple/PlotStudio.tsx index 65007b33c..b49e938e3 100644 --- a/frontend/logging-view/src/components/simple/PlotStudio.tsx +++ b/frontend/logging-view/src/components/simple/PlotStudio.tsx @@ -2,9 +2,9 @@ // plots and composed series are managed in the right studio panel, laid out // VS Code-style: a fixed activity bar with one open section at a time, and // only the plots area scrolls. -import { Button, Separator } from "@workspace/ui/components"; -import { FileDown, PanelRight, Plus, X } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { Button, Separator } from "@hyperloop-upv/frontend-kit/components"; +import { FileDown, PanelRight, Plus, X } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useEffect, useRef, useState } from "react"; import { useStore } from "../../store/store"; import PdfExportModal from "./modals/PdfExportModal"; diff --git a/frontend/logging-view/src/components/simple/SignalSelect.tsx b/frontend/logging-view/src/components/simple/SignalSelect.tsx index 7ca3d9eeb..0e1066be1 100644 --- a/frontend/logging-view/src/components/simple/SignalSelect.tsx +++ b/frontend/logging-view/src/components/simple/SignalSelect.tsx @@ -2,9 +2,9 @@ // "Composed" entry for operations/transforms); choosing a board drills into // its series with a filter box and a back button. Built on Popover because // Radix Select cannot nest levels. -import { Input, Popover, PopoverContent, PopoverTrigger } from "@workspace/ui/components"; -import { Check, ChevronDown, ChevronLeft, ChevronRight, Search } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { Input, Popover, PopoverContent, PopoverTrigger } from "@hyperloop-upv/frontend-kit/components"; +import { Check, ChevronDown, ChevronLeft, ChevronRight, Search } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useState } from "react"; import { useAvailableSignals, type AvailableSignal } from "./hooks/useStudioSignals"; diff --git a/frontend/logging-view/src/components/simple/StatsPanel.tsx b/frontend/logging-view/src/components/simple/StatsPanel.tsx index 822e68d39..e749095ca 100644 --- a/frontend/logging-view/src/components/simple/StatsPanel.tsx +++ b/frontend/logging-view/src/components/simple/StatsPanel.tsx @@ -1,9 +1,9 @@ // Statistics panel shown under a plot. Metrics are computed over the visible // X range only (live — the parent tracks the current Plotly viewport, // debounced, and passes it down as `visibleRange`). -import { Button, Separator } from "@workspace/ui/components"; -import { X } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { Button, Separator } from "@hyperloop-upv/frontend-kit/components"; +import { X } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useMemo } from "react"; import { fmt } from "../../lib/plotStudio/format"; import { computeRangeStats } from "../../lib/plotStudio/stats"; diff --git a/frontend/logging-view/src/components/simple/modals/OperationModal.tsx b/frontend/logging-view/src/components/simple/modals/OperationModal.tsx index daab005c9..7626158bc 100644 --- a/frontend/logging-view/src/components/simple/modals/OperationModal.tsx +++ b/frontend/logging-view/src/components/simple/modals/OperationModal.tsx @@ -8,8 +8,8 @@ import { DialogTitle, Input, Label, -} from "@workspace/ui/components"; -import { cn } from "@workspace/ui/lib"; +} from "@hyperloop-upv/frontend-kit/components"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useState } from "react"; import { performOperation } from "../../../lib/plotStudio/operations"; import { useStore } from "../../../store/store"; diff --git a/frontend/logging-view/src/components/simple/modals/PdfExportModal.tsx b/frontend/logging-view/src/components/simple/modals/PdfExportModal.tsx index ddf87d728..53c52d25a 100644 --- a/frontend/logging-view/src/components/simple/modals/PdfExportModal.tsx +++ b/frontend/logging-view/src/components/simple/modals/PdfExportModal.tsx @@ -15,7 +15,7 @@ import { Label, SegmentedControl, Spinner, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; import { useState } from "react"; import type { PdfExportOptions, PdfExportResult } from "../../../lib/pdfExport/types"; diff --git a/frontend/logging-view/src/components/simple/modals/TransformModal.tsx b/frontend/logging-view/src/components/simple/modals/TransformModal.tsx index a0f89d246..eb1049e9a 100644 --- a/frontend/logging-view/src/components/simple/modals/TransformModal.tsx +++ b/frontend/logging-view/src/components/simple/modals/TransformModal.tsx @@ -8,7 +8,7 @@ import { DialogTitle, Input, Label, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; import { useState } from "react"; import { applyTransform } from "../../../lib/plotStudio/transforms"; import { useStore } from "../../../store/store"; diff --git a/frontend/logging-view/src/components/simple/plots/PlotWrapper.tsx b/frontend/logging-view/src/components/simple/plots/PlotWrapper.tsx index 303bf9a63..a42471c9b 100644 --- a/frontend/logging-view/src/components/simple/plots/PlotWrapper.tsx +++ b/frontend/logging-view/src/components/simple/plots/PlotWrapper.tsx @@ -16,7 +16,7 @@ import { Tooltip, TooltipContent, TooltipTrigger, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; import { Activity, AlertTriangle, @@ -26,9 +26,9 @@ import { RefreshCw, Trash2, Unlock, -} from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; -import logoIcon from "@workspace/ui/outreach/main/logo_icon.svg?inline"; +} from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; +import logoIcon from "@hyperloop-upv/frontend-kit/outreach/main/logo_icon.svg?inline"; import Plotly from "plotly.js-dist"; import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react"; import { useShallow } from "zustand/react/shallow"; diff --git a/frontend/logging-view/src/components/simple/sidebar/ComposedSection.tsx b/frontend/logging-view/src/components/simple/sidebar/ComposedSection.tsx index 389578cb0..470d77433 100644 --- a/frontend/logging-view/src/components/simple/sidebar/ComposedSection.tsx +++ b/frontend/logging-view/src/components/simple/sidebar/ComposedSection.tsx @@ -1,7 +1,7 @@ // Composed Series: signals derived from session data — math operations // (A ∘ B) and expression transforms f(x) — managed in a single panel. -import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@workspace/ui/components"; -import { Trash2 } from "@workspace/ui/icons"; +import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@hyperloop-upv/frontend-kit/components"; +import { Trash2 } from "@hyperloop-upv/frontend-kit/icons"; import { useState } from "react"; import { useStore } from "../../../store/store"; import OperationModal from "../modals/OperationModal"; diff --git a/frontend/logging-view/src/components/simple/sidebar/FFTSection.tsx b/frontend/logging-view/src/components/simple/sidebar/FFTSection.tsx index 63bb0b2f5..80ca50ac2 100644 --- a/frontend/logging-view/src/components/simple/sidebar/FFTSection.tsx +++ b/frontend/logging-view/src/components/simple/sidebar/FFTSection.tsx @@ -1,7 +1,7 @@ // FFT sample-rate control. Shows the rate auto-detected from the loaded data // (median Δt of the first signal) and lets the user override it manually. -import { Button, Input, Label } from "@workspace/ui/components"; -import { RefreshCw, Timer } from "@workspace/ui/icons"; +import { Button, Input, Label } from "@hyperloop-upv/frontend-kit/components"; +import { RefreshCw, Timer } from "@hyperloop-upv/frontend-kit/icons"; import { useMemo, useState } from "react"; import { useStore } from "../../../store/store"; diff --git a/frontend/logging-view/src/components/simple/sidebar/PlotsSection.tsx b/frontend/logging-view/src/components/simple/sidebar/PlotsSection.tsx index 3a18631e2..38542f1b7 100644 --- a/frontend/logging-view/src/components/simple/sidebar/PlotsSection.tsx +++ b/frontend/logging-view/src/components/simple/sidebar/PlotsSection.tsx @@ -21,9 +21,9 @@ import { Tooltip, TooltipContent, TooltipTrigger, -} from "@workspace/ui/components"; -import { Activity, Eye, EyeOff, GripVertical, Plus, Trash2, X } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +} from "@hyperloop-upv/frontend-kit/components"; +import { Activity, Eye, EyeOff, GripVertical, Plus, Trash2, X } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useState } from "react"; import { useShallow } from "zustand/react/shallow"; import { resolveSignalColor } from "../../../lib/plotStudio/palette"; diff --git a/frontend/logging-view/src/components/simple/sidebar/StudioSidebar.tsx b/frontend/logging-view/src/components/simple/sidebar/StudioSidebar.tsx index 5055aaacd..52047cdff 100644 --- a/frontend/logging-view/src/components/simple/sidebar/StudioSidebar.tsx +++ b/frontend/logging-view/src/components/simple/sidebar/StudioSidebar.tsx @@ -1,8 +1,8 @@ // VS Code-style studio panel: a persistent activity bar (icon strip) on the // right edge; clicking an icon opens that section in a panel next to it, // clicking the active icon again closes the panel. -import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@workspace/ui/components"; -import { cn } from "@workspace/ui/lib"; +import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@hyperloop-upv/frontend-kit/components"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { STUDIO_SECTIONS } from "./studioSections"; interface StudioSidebarProps { diff --git a/frontend/logging-view/src/components/simple/sidebar/studioSections.ts b/frontend/logging-view/src/components/simple/sidebar/studioSections.ts index d683f0247..d70c99b3f 100644 --- a/frontend/logging-view/src/components/simple/sidebar/studioSections.ts +++ b/frontend/logging-view/src/components/simple/sidebar/studioSections.ts @@ -1,7 +1,7 @@ // Registry of the studio panel sections, VS Code-style: the activity bar // shows one icon per section and the panel displays a single section at a time. -import { Activity, Layers, Timer } from "@workspace/ui/icons"; -import type { LucideIcon } from "@workspace/ui/icons"; +import { Activity, Layers, Timer } from "@hyperloop-upv/frontend-kit/icons"; +import type { LucideIcon } from "@hyperloop-upv/frontend-kit/icons"; import ComposedSection from "./ComposedSection"; import FFTSection from "./FFTSection"; import PlotsSection from "./PlotsSection"; diff --git a/frontend/logging-view/src/index.css b/frontend/logging-view/src/index.css index aba9402f3..14a5cfb86 100644 --- a/frontend/logging-view/src/index.css +++ b/frontend/logging-view/src/index.css @@ -1,7 +1,7 @@ -@import "@workspace/ui/globals.css"; +@import "@hyperloop-upv/frontend-kit/globals.css"; /* Ensure Tailwind v4 scans competition-view source files directly. - The @source paths in globals.css resolve via the @workspace/ui symlink + The @source paths in globals.css resolve via the @hyperloop-upv/frontend-kit symlink and don't correctly reach this project's source tree. */ @source "./**/*.{ts,tsx}"; diff --git a/frontend/logging-view/src/layout/AppLayout.tsx b/frontend/logging-view/src/layout/AppLayout.tsx index 32c29ccb7..865fc79d8 100644 --- a/frontend/logging-view/src/layout/AppLayout.tsx +++ b/frontend/logging-view/src/layout/AppLayout.tsx @@ -1,5 +1,5 @@ import { DndContext } from "@dnd-kit/core"; -import { SidebarInset, SidebarProvider } from "@workspace/ui/components"; +import { SidebarInset, SidebarProvider } from "@hyperloop-upv/frontend-kit/components"; import { useEffect, type ReactNode } from "react"; import Header from "../components/header/Header"; import PlotAddedToast from "../components/PlotAddedToast"; diff --git a/frontend/logging-view/src/lib/pdfExport/assets.ts b/frontend/logging-view/src/lib/pdfExport/assets.ts index 845c3622e..77acc339c 100644 --- a/frontend/logging-view/src/lib/pdfExport/assets.ts +++ b/frontend/logging-view/src/lib/pdfExport/assets.ts @@ -1,7 +1,7 @@ // Branding assets + page geometry shared by every page builder in this module. -import fullLogo from "@workspace/ui/outreach/main/full_logo_black.png?inline"; -import swLogo from "@workspace/ui/outreach/main/software_black.png?inline"; -import checkLogo from "@workspace/ui/outreach/main/check_black.png?inline"; +import fullLogo from "@hyperloop-upv/frontend-kit/outreach/main/full_logo_black.png?inline"; +import swLogo from "@hyperloop-upv/frontend-kit/outreach/main/software_black.png?inline"; +import checkLogo from "@hyperloop-upv/frontend-kit/outreach/main/check_black.png?inline"; export const PDF_ASSETS = { fullLogo, diff --git a/frontend/logging-view/src/pages/NormalPage.tsx b/frontend/logging-view/src/pages/NormalPage.tsx index 983c9c877..d0f21e0d8 100644 --- a/frontend/logging-view/src/pages/NormalPage.tsx +++ b/frontend/logging-view/src/pages/NormalPage.tsx @@ -1,7 +1,7 @@ // Normal mode: full-featured log analysis view. // Placeholder — UI to be implemented. -import swLogoBlack from "@workspace/ui/outreach/main/software_black.png?inline"; -import swLogoWhite from "@workspace/ui/outreach/main/software_white.png?inline"; +import swLogoBlack from "@hyperloop-upv/frontend-kit/outreach/main/software_black.png?inline"; +import swLogoWhite from "@hyperloop-upv/frontend-kit/outreach/main/software_white.png?inline"; import { useStore } from "../store/store"; const NormalPage = () => { diff --git a/frontend/logging-view/tsconfig.json b/frontend/logging-view/tsconfig.json index a351dd46e..1d8aa51b5 100644 --- a/frontend/logging-view/tsconfig.json +++ b/frontend/logging-view/tsconfig.json @@ -7,8 +7,7 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "@/*": ["./*"], - "@workspace/ui/*": ["../frontend-kit/ui/src/*"] + "@/*": ["./*"] } }, "exclude": ["node_modules"] diff --git a/frontend/testing-view/eslint.config.js b/frontend/testing-view/eslint.config.js index df360b435..a2b580035 100644 --- a/frontend/testing-view/eslint.config.js +++ b/frontend/testing-view/eslint.config.js @@ -1,3 +1,3 @@ -import { config } from "@workspace/eslint-config/vite"; +import { config } from "@hyperloop-upv/eslint-config/vite"; export default config; diff --git a/frontend/testing-view/package.json b/frontend/testing-view/package.json index abaeca8a3..f6aaa504b 100644 --- a/frontend/testing-view/package.json +++ b/frontend/testing-view/package.json @@ -24,8 +24,7 @@ "@tanstack/react-virtual": "^3.13.18", "@types/lodash": "^4.17.23", "@vitejs/plugin-react-swc": "^4.2.3", - "@workspace/core": "workspace:*", - "@workspace/ui": "workspace:*", + "@hyperloop-upv/frontend-kit": "workspace:*", "lodash": "^4.17.23", "react": "^19.2.4", "react-dom": "^19.2.4", @@ -39,8 +38,8 @@ "devDependencies": { "@types/react": "^19.2.11", "@types/react-dom": "^19.2.3", - "@workspace/eslint-config": "workspace:^", - "@workspace/typescript-config": "workspace:*", + "@hyperloop-upv/eslint-config": "workspace:^", + "@hyperloop-upv/typescript-config": "workspace:*", "eslint": "^9.39.2", "globals": "^17.3.0", "typescript": "^5.9.3", diff --git a/frontend/testing-view/src/App.tsx b/frontend/testing-view/src/App.tsx index 506f86ed4..68a459c72 100644 --- a/frontend/testing-view/src/App.tsx +++ b/frontend/testing-view/src/App.tsx @@ -1,4 +1,4 @@ -import { useTopic, useWebSocket } from "@workspace/ui/hooks"; +import { useTopic, useWebSocket } from "@hyperloop-upv/frontend-kit/hooks"; import { Route, Routes } from "react-router"; import { AppModeRouter } from "./components/AppModeRouter"; import { ModeSwitcher } from "./components/devTools/ModeSwitcher"; diff --git a/frontend/testing-view/src/components/Error.tsx b/frontend/testing-view/src/components/Error.tsx index bb800471d..06f63411d 100644 --- a/frontend/testing-view/src/components/Error.tsx +++ b/frontend/testing-view/src/components/Error.tsx @@ -1,5 +1,5 @@ -import { Button } from "@workspace/ui"; -import { RefreshCw, Terminal } from "@workspace/ui/icons"; +import { Button } from "@hyperloop-upv/frontend-kit"; +import { RefreshCw, Terminal } from "@hyperloop-upv/frontend-kit/icons"; import { useEffect, useState } from "react"; import errorGif from "../assets/error.gif"; import { useStore } from "../store/store"; diff --git a/frontend/testing-view/src/components/ErrorBoundary.tsx b/frontend/testing-view/src/components/ErrorBoundary.tsx index a69c23611..7d40fc906 100644 --- a/frontend/testing-view/src/components/ErrorBoundary.tsx +++ b/frontend/testing-view/src/components/ErrorBoundary.tsx @@ -1,4 +1,4 @@ -import { logger } from "@workspace/core"; +import { logger } from "@hyperloop-upv/frontend-kit/core"; import React, { Component, type ReactNode } from "react"; import { Error } from "./Error"; diff --git a/frontend/testing-view/src/components/devTools/ModeSwitcher.tsx b/frontend/testing-view/src/components/devTools/ModeSwitcher.tsx index c25c69428..67134b9ea 100644 --- a/frontend/testing-view/src/components/devTools/ModeSwitcher.tsx +++ b/frontend/testing-view/src/components/devTools/ModeSwitcher.tsx @@ -1,4 +1,4 @@ -import { Button } from "@workspace/ui"; +import { Button } from "@hyperloop-upv/frontend-kit"; import { useStore } from "../../store/store"; import type { AppMode } from "../../types/app/mode"; diff --git a/frontend/testing-view/src/components/header/Header.tsx b/frontend/testing-view/src/components/header/Header.tsx index 1f6b977c2..38b77814a 100644 --- a/frontend/testing-view/src/components/header/Header.tsx +++ b/frontend/testing-view/src/components/header/Header.tsx @@ -1,4 +1,4 @@ -import { Separator, SidebarTrigger } from "@workspace/ui"; +import { Separator, SidebarTrigger } from "@hyperloop-upv/frontend-kit"; import { useLocation } from "react-router"; import { PAGES } from "../../constants/pages"; import { KeyBindingsButton } from "../../features/keyBindings/components/KeyBindingsButton"; diff --git a/frontend/testing-view/src/components/header/ModeBadge.tsx b/frontend/testing-view/src/components/header/ModeBadge.tsx index d4ec401b3..fc8a13f47 100644 --- a/frontend/testing-view/src/components/header/ModeBadge.tsx +++ b/frontend/testing-view/src/components/header/ModeBadge.tsx @@ -1,4 +1,4 @@ -import { cn } from "@workspace/ui/lib"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useStore } from "../../store/store"; import type { AppMode } from "../../types/app/mode"; diff --git a/frontend/testing-view/src/components/header/ReconnectButton.tsx b/frontend/testing-view/src/components/header/ReconnectButton.tsx index e783d768b..608591fec 100644 --- a/frontend/testing-view/src/components/header/ReconnectButton.tsx +++ b/frontend/testing-view/src/components/header/ReconnectButton.tsx @@ -1,6 +1,6 @@ -import { Button } from "@workspace/ui"; -import { useWebSocket } from "@workspace/ui/hooks"; -import { RefreshCw } from "@workspace/ui/icons"; +import { Button } from "@hyperloop-upv/frontend-kit"; +import { useWebSocket } from "@hyperloop-upv/frontend-kit/hooks"; +import { RefreshCw } from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../store/store"; export const ReconnectButton = () => { diff --git a/frontend/testing-view/src/components/leftSidebar/AppSidebar.tsx b/frontend/testing-view/src/components/leftSidebar/AppSidebar.tsx index 35940ea2e..4207f3f9b 100644 --- a/frontend/testing-view/src/components/leftSidebar/AppSidebar.tsx +++ b/frontend/testing-view/src/components/leftSidebar/AppSidebar.tsx @@ -4,7 +4,7 @@ import { SidebarFooter, SidebarHeader, SidebarRail, -} from "@workspace/ui/components"; +} from "@hyperloop-upv/frontend-kit/components"; import { PAGES_ARRAY } from "../../constants/pages"; import ColorSchemeToggle from "./ColorSchemeToggle"; import ConnectionStatusGroup from "./ConnectionStatusGroup"; diff --git a/frontend/testing-view/src/components/leftSidebar/ColorSchemeToggle.tsx b/frontend/testing-view/src/components/leftSidebar/ColorSchemeToggle.tsx index 75dbacd84..888245317 100644 --- a/frontend/testing-view/src/components/leftSidebar/ColorSchemeToggle.tsx +++ b/frontend/testing-view/src/components/leftSidebar/ColorSchemeToggle.tsx @@ -1,5 +1,5 @@ -import { SidebarMenuButton } from "@workspace/ui"; -import { Palette } from "@workspace/ui/icons"; +import { SidebarMenuButton } from "@hyperloop-upv/frontend-kit"; +import { Palette } from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../store/store"; import { colorSchemes } from "../../types/app/colorSchema"; diff --git a/frontend/testing-view/src/components/leftSidebar/ConnectionStatusGroup.tsx b/frontend/testing-view/src/components/leftSidebar/ConnectionStatusGroup.tsx index eb82bbb38..da90e1f2a 100644 --- a/frontend/testing-view/src/components/leftSidebar/ConnectionStatusGroup.tsx +++ b/frontend/testing-view/src/components/leftSidebar/ConnectionStatusGroup.tsx @@ -4,8 +4,8 @@ import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, -} from "@workspace/ui"; -import { Plug, Unplug } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit"; +import { Plug, Unplug } from "@hyperloop-upv/frontend-kit/icons"; import useConnections from "../../hooks/useConnections"; interface ConnectionStatusGroupProps { diff --git a/frontend/testing-view/src/components/leftSidebar/DevToolsItem.tsx b/frontend/testing-view/src/components/leftSidebar/DevToolsItem.tsx index 95e2dff3d..915df8ee0 100644 --- a/frontend/testing-view/src/components/leftSidebar/DevToolsItem.tsx +++ b/frontend/testing-view/src/components/leftSidebar/DevToolsItem.tsx @@ -2,8 +2,8 @@ import { SidebarGroup, SidebarGroupLabel, SidebarMenuButton, -} from "@workspace/ui"; -import { Eye, EyeOff } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit"; +import { Eye, EyeOff } from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../store/store"; const DevToolsItem = () => { diff --git a/frontend/testing-view/src/components/leftSidebar/Logo.tsx b/frontend/testing-view/src/components/leftSidebar/Logo.tsx index 5fc0c9855..2ca72ac37 100644 --- a/frontend/testing-view/src/components/leftSidebar/Logo.tsx +++ b/frontend/testing-view/src/components/leftSidebar/Logo.tsx @@ -1,6 +1,6 @@ -import { SidebarMenuButton } from "@workspace/ui"; +import { SidebarMenuButton } from "@hyperloop-upv/frontend-kit"; import { Link } from "react-router"; -import logo from "@workspace/ui/outreach/h11/h11-isotipo_black.svg"; +import logo from "@hyperloop-upv/frontend-kit/outreach/h11/h11-isotipo_black.svg"; const Logo = () => { return ( diff --git a/frontend/testing-view/src/components/leftSidebar/NavigationGroup.tsx b/frontend/testing-view/src/components/leftSidebar/NavigationGroup.tsx index 079c17583..5d73d7da4 100644 --- a/frontend/testing-view/src/components/leftSidebar/NavigationGroup.tsx +++ b/frontend/testing-view/src/components/leftSidebar/NavigationGroup.tsx @@ -4,8 +4,8 @@ import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, -} from "@workspace/ui/components"; -import { type LucideIcon } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit/components"; +import { type LucideIcon } from "@hyperloop-upv/frontend-kit/icons"; import { Link } from "react-router"; interface NavigationGroupProps { diff --git a/frontend/testing-view/src/components/leftSidebar/SettingsItem.tsx b/frontend/testing-view/src/components/leftSidebar/SettingsItem.tsx index a0d4e9e60..4dc35c249 100644 --- a/frontend/testing-view/src/components/leftSidebar/SettingsItem.tsx +++ b/frontend/testing-view/src/components/leftSidebar/SettingsItem.tsx @@ -1,5 +1,5 @@ -import { SidebarMenuButton } from "@workspace/ui"; -import { Settings } from "@workspace/ui/icons"; +import { SidebarMenuButton } from "@hyperloop-upv/frontend-kit"; +import { Settings } from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../store/store"; const SettingsItem = () => { diff --git a/frontend/testing-view/src/components/leftSidebar/ThemeToggleItem.tsx b/frontend/testing-view/src/components/leftSidebar/ThemeToggleItem.tsx index ee88db6fa..ca8ddf746 100644 --- a/frontend/testing-view/src/components/leftSidebar/ThemeToggleItem.tsx +++ b/frontend/testing-view/src/components/leftSidebar/ThemeToggleItem.tsx @@ -1,5 +1,5 @@ -import { SidebarMenuButton } from "@workspace/ui"; -import { SunMoon } from "@workspace/ui/icons"; +import { SidebarMenuButton } from "@hyperloop-upv/frontend-kit"; +import { SunMoon } from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../store/store"; const ThemeToggleItem = () => { diff --git a/frontend/testing-view/src/components/settings/BooleanField.tsx b/frontend/testing-view/src/components/settings/BooleanField.tsx index be4b6594a..b66804756 100644 --- a/frontend/testing-view/src/components/settings/BooleanField.tsx +++ b/frontend/testing-view/src/components/settings/BooleanField.tsx @@ -1,5 +1,5 @@ -import { Checkbox } from "@workspace/ui/components/shadcn/checkbox"; -import { Label } from "@workspace/ui/components/shadcn/label"; +import { Checkbox } from "@hyperloop-upv/frontend-kit/components/shadcn/checkbox"; +import { Label } from "@hyperloop-upv/frontend-kit/components/shadcn/label"; import type { FieldProps } from "../../types/common/settings"; export const BooleanField = ({ diff --git a/frontend/testing-view/src/components/settings/ComboboxField.tsx b/frontend/testing-view/src/components/settings/ComboboxField.tsx index 8c14abf1f..b73149a2a 100644 --- a/frontend/testing-view/src/components/settings/ComboboxField.tsx +++ b/frontend/testing-view/src/components/settings/ComboboxField.tsx @@ -5,10 +5,10 @@ import { ComboboxInput, ComboboxItem, ComboboxList, -} from "@workspace/ui/components"; -import { Button } from "@workspace/ui/components/shadcn/button"; -import { Label } from "@workspace/ui/components/shadcn/label"; -import { RefreshCw } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit/components"; +import { Button } from "@hyperloop-upv/frontend-kit/components/shadcn/button"; +import { Label } from "@hyperloop-upv/frontend-kit/components/shadcn/label"; +import { RefreshCw } from "@hyperloop-upv/frontend-kit/icons"; import { useEffect, useState } from "react"; import type { BranchesFetchState } from "../../hooks/useBranches"; import type { FieldProps } from "../../types/common/settings"; diff --git a/frontend/testing-view/src/components/settings/MultiCheckboxField.tsx b/frontend/testing-view/src/components/settings/MultiCheckboxField.tsx index 8ece18567..8e89254de 100644 --- a/frontend/testing-view/src/components/settings/MultiCheckboxField.tsx +++ b/frontend/testing-view/src/components/settings/MultiCheckboxField.tsx @@ -1,5 +1,5 @@ -import { Checkbox } from "@workspace/ui/components/shadcn/checkbox"; -import { Label } from "@workspace/ui/components/shadcn/label"; +import { Checkbox } from "@hyperloop-upv/frontend-kit/components/shadcn/checkbox"; +import { Label } from "@hyperloop-upv/frontend-kit/components/shadcn/label"; import type { FieldProps } from "../../types/common/settings"; export const MultiCheckboxField = ({ diff --git a/frontend/testing-view/src/components/settings/PathField.tsx b/frontend/testing-view/src/components/settings/PathField.tsx index 1f64c40c0..32f62b70f 100644 --- a/frontend/testing-view/src/components/settings/PathField.tsx +++ b/frontend/testing-view/src/components/settings/PathField.tsx @@ -1,6 +1,6 @@ -import { Button, Input, Label } from "@workspace/ui"; -import { FolderOpen } from "@workspace/ui/icons"; -import { logger } from "@workspace/core"; +import { Button, Input, Label } from "@hyperloop-upv/frontend-kit"; +import { FolderOpen } from "@hyperloop-upv/frontend-kit/icons"; +import { logger } from "@hyperloop-upv/frontend-kit/core"; import { useOpenFolder } from "../../hooks/useOpenFolder"; import type { FieldProps } from "../../types/common/settings"; diff --git a/frontend/testing-view/src/components/settings/SelectField.tsx b/frontend/testing-view/src/components/settings/SelectField.tsx index 798acf4f9..7b17e4f6e 100644 --- a/frontend/testing-view/src/components/settings/SelectField.tsx +++ b/frontend/testing-view/src/components/settings/SelectField.tsx @@ -1,11 +1,11 @@ -import { Label } from "@workspace/ui/components/shadcn/label"; +import { Label } from "@hyperloop-upv/frontend-kit/components/shadcn/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, -} from "@workspace/ui/components/shadcn/select"; +} from "@hyperloop-upv/frontend-kit/components/shadcn/select"; import type { FieldProps } from "../../types/common/settings"; export const SelectField = ({ field, value, onChange }: FieldProps) => ( diff --git a/frontend/testing-view/src/components/settings/SettingsDialog.tsx b/frontend/testing-view/src/components/settings/SettingsDialog.tsx index 2ffda360c..5720450be 100644 --- a/frontend/testing-view/src/components/settings/SettingsDialog.tsx +++ b/frontend/testing-view/src/components/settings/SettingsDialog.tsx @@ -1,7 +1,7 @@ import { Dialog } from "@base-ui/react"; -import { socketService } from "@workspace/core"; -import { Badge, Button } from "@workspace/ui"; -import { AlertTriangle, CheckCircle2, Loader2, X } from "@workspace/ui/icons"; +import { socketService } from "@hyperloop-upv/frontend-kit/core"; +import { Badge, Button } from "@hyperloop-upv/frontend-kit"; +import { AlertTriangle, CheckCircle2, Loader2, X } from "@hyperloop-upv/frontend-kit/icons"; import { useEffect, useState, useTransition } from "react"; import { config } from "../../../config"; import { DEFAULT_CONFIG } from "../../constants/defaultConfig"; diff --git a/frontend/testing-view/src/components/settings/TextField.tsx b/frontend/testing-view/src/components/settings/TextField.tsx index 71969dfb6..d4e9c1ebe 100644 --- a/frontend/testing-view/src/components/settings/TextField.tsx +++ b/frontend/testing-view/src/components/settings/TextField.tsx @@ -1,5 +1,5 @@ -import { Input } from "@workspace/ui/components/shadcn/input"; -import { Label } from "@workspace/ui/components/shadcn/label"; +import { Input } from "@hyperloop-upv/frontend-kit/components/shadcn/input"; +import { Label } from "@hyperloop-upv/frontend-kit/components/shadcn/label"; import type { FieldProps } from "../../types/common/settings"; /** diff --git a/frontend/testing-view/src/constants/loggerControlConfig.tsx b/frontend/testing-view/src/constants/loggerControlConfig.tsx index 03127b9e4..021dbfaa7 100644 --- a/frontend/testing-view/src/constants/loggerControlConfig.tsx +++ b/frontend/testing-view/src/constants/loggerControlConfig.tsx @@ -1,4 +1,4 @@ -import { AlertCircle, Loader2, Play, Square } from "@workspace/ui/icons"; +import { AlertCircle, Loader2, Play, Square } from "@hyperloop-upv/frontend-kit/icons"; import type { LoggerStatus } from "../types/common/logger"; interface LoggerControlOption { diff --git a/frontend/testing-view/src/constants/pages.ts b/frontend/testing-view/src/constants/pages.ts index 82867a064..df368ffa7 100644 --- a/frontend/testing-view/src/constants/pages.ts +++ b/frontend/testing-view/src/constants/pages.ts @@ -1,4 +1,4 @@ -import { FlaskConical, ScrollText } from "@workspace/ui/icons"; +import { FlaskConical, ScrollText } from "@hyperloop-upv/frontend-kit/icons"; /** Pages of the application showed in the left sidebar. */ export const PAGES = { diff --git a/frontend/testing-view/src/features/charts/components/ChartLegend.tsx b/frontend/testing-view/src/features/charts/components/ChartLegend.tsx index 6872ff719..558986bf7 100644 --- a/frontend/testing-view/src/features/charts/components/ChartLegend.tsx +++ b/frontend/testing-view/src/features/charts/components/ChartLegend.tsx @@ -1,4 +1,4 @@ -import { Eye, EyeOff, X } from "@workspace/ui/icons"; +import { Eye, EyeOff, X } from "@hyperloop-upv/frontend-kit/icons"; import { COLORS } from "../constants/chartsColors"; import type { WorkspaceChartSeries } from "../types/charts"; import { ChartSettings } from "./ChartSettings"; diff --git a/frontend/testing-view/src/features/charts/components/ChartSettings.tsx b/frontend/testing-view/src/features/charts/components/ChartSettings.tsx index 8f7bd4871..dbd498c4a 100644 --- a/frontend/testing-view/src/features/charts/components/ChartSettings.tsx +++ b/frontend/testing-view/src/features/charts/components/ChartSettings.tsx @@ -4,8 +4,8 @@ import { Popover, PopoverContent, PopoverTrigger, -} from "@workspace/ui"; -import { Settings2 } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit"; +import { Settings2 } from "@hyperloop-upv/frontend-kit/icons"; import { config } from "../../../../config"; import { useStore } from "../../../store/store"; diff --git a/frontend/testing-view/src/features/charts/components/ChartSurface.tsx b/frontend/testing-view/src/features/charts/components/ChartSurface.tsx index d2f0ee3b3..9e16d9f2d 100644 --- a/frontend/testing-view/src/features/charts/components/ChartSurface.tsx +++ b/frontend/testing-view/src/features/charts/components/ChartSurface.tsx @@ -1,7 +1,7 @@ -import type { TelemetryPacket } from "@workspace/core"; -import { Button } from "@workspace/ui"; -import { ChevronLeft, ChevronRight, X } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import type { TelemetryPacket } from "@hyperloop-upv/frontend-kit/core"; +import { Button } from "@hyperloop-upv/frontend-kit"; +import { ChevronLeft, ChevronRight, X } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { memo, useEffect, useRef, useState } from "react"; import uPlot from "uplot"; import { useShallow } from "zustand/shallow"; diff --git a/frontend/testing-view/src/features/charts/components/ChartsGrid.tsx b/frontend/testing-view/src/features/charts/components/ChartsGrid.tsx index 17c2b8deb..5fcf71fcd 100644 --- a/frontend/testing-view/src/features/charts/components/ChartsGrid.tsx +++ b/frontend/testing-view/src/features/charts/components/ChartsGrid.tsx @@ -1,5 +1,5 @@ import { SortableContext, rectSortingStrategy } from "@dnd-kit/sortable"; -import { cn } from "@workspace/ui/lib"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import type { WorkspaceChartConfig } from "../types/charts"; import { SortableChart } from "./SortableChart"; diff --git a/frontend/testing-view/src/features/charts/components/TelemetryChart.tsx b/frontend/testing-view/src/features/charts/components/TelemetryChart.tsx index 896300fa4..295bacf0f 100644 --- a/frontend/testing-view/src/features/charts/components/TelemetryChart.tsx +++ b/frontend/testing-view/src/features/charts/components/TelemetryChart.tsx @@ -1,7 +1,7 @@ import type { DraggableAttributes } from "@dnd-kit/core"; import type { SyntheticListenerMap } from "@dnd-kit/core/dist/hooks/utilities"; -import { GripVertical, Trash2 } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib/utils"; +import { GripVertical, Trash2 } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib/utils"; import { useRef, useState } from "react"; import "uplot/dist/uPlot.min.css"; import { useStore } from "../../../store/store"; diff --git a/frontend/testing-view/src/features/filtering/components/FilterCategoryItem.tsx b/frontend/testing-view/src/features/filtering/components/FilterCategoryItem.tsx index 05f2a2467..c0e48a549 100644 --- a/frontend/testing-view/src/features/filtering/components/FilterCategoryItem.tsx +++ b/frontend/testing-view/src/features/filtering/components/FilterCategoryItem.tsx @@ -3,8 +3,8 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger, -} from "@workspace/ui"; -import { ChevronDown, ChevronLeft } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit"; +import { ChevronDown, ChevronLeft } from "@hyperloop-upv/frontend-kit/icons"; import { useState } from "react"; import { useShallow } from "zustand/shallow"; import { useStore } from "../../../store/store"; diff --git a/frontend/testing-view/src/features/filtering/components/FilterDialog.tsx b/frontend/testing-view/src/features/filtering/components/FilterDialog.tsx index 150d4098c..a313ca1ad 100644 --- a/frontend/testing-view/src/features/filtering/components/FilterDialog.tsx +++ b/frontend/testing-view/src/features/filtering/components/FilterDialog.tsx @@ -5,8 +5,8 @@ import { DialogDescription, DialogHeader, DialogTitle, -} from "@workspace/ui"; -import { AlertTriangle } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit"; +import { AlertTriangle } from "@hyperloop-upv/frontend-kit/icons"; import { type ComponentType } from "react"; import type { BoardName } from "../../../types/data/board"; diff --git a/frontend/testing-view/src/features/filtering/components/FilterItem.tsx b/frontend/testing-view/src/features/filtering/components/FilterItem.tsx index c5e4dac6e..be37da535 100644 --- a/frontend/testing-view/src/features/filtering/components/FilterItem.tsx +++ b/frontend/testing-view/src/features/filtering/components/FilterItem.tsx @@ -1,4 +1,4 @@ -import { Badge, Checkbox } from "@workspace/ui"; +import { Badge, Checkbox } from "@hyperloop-upv/frontend-kit"; import type { CatalogItem } from "../../../types/common/item"; interface FilterItemProps { diff --git a/frontend/testing-view/src/features/keyBindings/components/AddKeyBindingDialog.tsx b/frontend/testing-view/src/features/keyBindings/components/AddKeyBindingDialog.tsx index 5106f0795..939b892cf 100644 --- a/frontend/testing-view/src/features/keyBindings/components/AddKeyBindingDialog.tsx +++ b/frontend/testing-view/src/features/keyBindings/components/AddKeyBindingDialog.tsx @@ -14,8 +14,8 @@ import { SelectLabel, SelectTrigger, SelectValue, -} from "@workspace/ui"; -import { X } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit"; +import { X } from "@hyperloop-upv/frontend-kit/icons"; import { useEffect, useRef, useState } from "react"; import { getDefaultParameterValues } from "../../../lib/commandUtils"; import { useStore } from "../../../store/store"; diff --git a/frontend/testing-view/src/features/keyBindings/components/KeyBindingCard.tsx b/frontend/testing-view/src/features/keyBindings/components/KeyBindingCard.tsx index 68d1e5596..8a7ba38ff 100644 --- a/frontend/testing-view/src/features/keyBindings/components/KeyBindingCard.tsx +++ b/frontend/testing-view/src/features/keyBindings/components/KeyBindingCard.tsx @@ -1,6 +1,6 @@ -import { Badge, Button } from "@workspace/ui"; -import { ChevronDown, X } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { Badge, Button } from "@hyperloop-upv/frontend-kit"; +import { ChevronDown, X } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useState } from "react"; import { useStore } from "../../../store/store"; import type { KeyBinding } from "../types/keyBinding"; diff --git a/frontend/testing-view/src/features/keyBindings/components/KeyBindingsButton.tsx b/frontend/testing-view/src/features/keyBindings/components/KeyBindingsButton.tsx index 8b1b9fe67..ee61dc575 100644 --- a/frontend/testing-view/src/features/keyBindings/components/KeyBindingsButton.tsx +++ b/frontend/testing-view/src/features/keyBindings/components/KeyBindingsButton.tsx @@ -1,5 +1,5 @@ -import { Button } from "@workspace/ui"; -import { Keyboard } from "@workspace/ui/icons"; +import { Button } from "@hyperloop-upv/frontend-kit"; +import { Keyboard } from "@hyperloop-upv/frontend-kit/icons"; import { useState } from "react"; import { KeyBindingsDialog } from "./KeyBindingsDialog"; diff --git a/frontend/testing-view/src/features/keyBindings/components/KeyBindingsDialog.tsx b/frontend/testing-view/src/features/keyBindings/components/KeyBindingsDialog.tsx index 1ebf3c429..3678b3945 100644 --- a/frontend/testing-view/src/features/keyBindings/components/KeyBindingsDialog.tsx +++ b/frontend/testing-view/src/features/keyBindings/components/KeyBindingsDialog.tsx @@ -5,8 +5,8 @@ import { DialogDescription, DialogHeader, DialogTitle, -} from "@workspace/ui"; -import { Plus } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit"; +import { Plus } from "@hyperloop-upv/frontend-kit/icons"; import { useState } from "react"; import { useShallow } from "zustand/shallow"; import { useStore } from "../../../store/store"; diff --git a/frontend/testing-view/src/features/keyBindings/components/OrphanedKeyBindingCard.tsx b/frontend/testing-view/src/features/keyBindings/components/OrphanedKeyBindingCard.tsx index 7afcbff84..c95a85cf5 100644 --- a/frontend/testing-view/src/features/keyBindings/components/OrphanedKeyBindingCard.tsx +++ b/frontend/testing-view/src/features/keyBindings/components/OrphanedKeyBindingCard.tsx @@ -1,5 +1,5 @@ -import { Badge, Button } from "@workspace/ui"; -import { AlertTriangle, X } from "@workspace/ui/icons"; +import { Badge, Button } from "@hyperloop-upv/frontend-kit"; +import { AlertTriangle, X } from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../../store/store"; import type { KeyBinding } from "../types/keyBinding"; diff --git a/frontend/testing-view/src/features/keyBindings/hooks/useGlobalKeyBindings.ts b/frontend/testing-view/src/features/keyBindings/hooks/useGlobalKeyBindings.ts index bc53f6e72..c196fcc63 100644 --- a/frontend/testing-view/src/features/keyBindings/hooks/useGlobalKeyBindings.ts +++ b/frontend/testing-view/src/features/keyBindings/hooks/useGlobalKeyBindings.ts @@ -1,4 +1,4 @@ -import { logger, socketService } from "@workspace/core"; +import { logger, socketService } from "@hyperloop-upv/frontend-kit/core"; import { useEffect } from "react"; import { useLogger } from "../../../hooks/useLogger"; import { getDefaultParameterValues } from "../../../lib/commandUtils"; diff --git a/frontend/testing-view/src/features/workspace/components/DndOverlay.tsx b/frontend/testing-view/src/features/workspace/components/DndOverlay.tsx index 16ebaab93..c53aa59b2 100644 --- a/frontend/testing-view/src/features/workspace/components/DndOverlay.tsx +++ b/frontend/testing-view/src/features/workspace/components/DndOverlay.tsx @@ -1,5 +1,5 @@ import { DragOverlay } from "@dnd-kit/core"; -import { Badge } from "@workspace/ui"; +import { Badge } from "@hyperloop-upv/frontend-kit"; import { TelemetryChart } from "../../charts/components/TelemetryChart"; import type { WorkspaceChartConfig } from "../../charts/types/charts"; import type { DndActiveData } from "../types/dndData"; diff --git a/frontend/testing-view/src/features/workspace/components/EmptyWorkspace.tsx b/frontend/testing-view/src/features/workspace/components/EmptyWorkspace.tsx index 489f8e804..14de73b44 100644 --- a/frontend/testing-view/src/features/workspace/components/EmptyWorkspace.tsx +++ b/frontend/testing-view/src/features/workspace/components/EmptyWorkspace.tsx @@ -1,5 +1,5 @@ -import { Button } from "@workspace/ui"; -import { LayoutGrid, Plus } from "@workspace/ui/icons"; +import { Button } from "@hyperloop-upv/frontend-kit"; +import { LayoutGrid, Plus } from "@hyperloop-upv/frontend-kit/icons"; interface EmptyWorkspaceProps { onAddChart: () => void; diff --git a/frontend/testing-view/src/features/workspace/components/LoggerControl.tsx b/frontend/testing-view/src/features/workspace/components/LoggerControl.tsx index 460db5e9e..292e0318f 100644 --- a/frontend/testing-view/src/features/workspace/components/LoggerControl.tsx +++ b/frontend/testing-view/src/features/workspace/components/LoggerControl.tsx @@ -1,6 +1,6 @@ -import { Button, Separator } from "@workspace/ui"; -import { FolderOpen, Settings2 } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { Button, Separator } from "@hyperloop-upv/frontend-kit"; +import { FolderOpen, Settings2 } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { LOGGER_CONTROL_CONFIG } from "../../../constants/loggerControlConfig"; import { useLogger } from "../../../hooks/useLogger"; import { useOpenFolder } from "../../../hooks/useOpenFolder"; diff --git a/frontend/testing-view/src/features/workspace/components/MainPanel.tsx b/frontend/testing-view/src/features/workspace/components/MainPanel.tsx index 9c4f2caa5..49a6bc74d 100644 --- a/frontend/testing-view/src/features/workspace/components/MainPanel.tsx +++ b/frontend/testing-view/src/features/workspace/components/MainPanel.tsx @@ -1,5 +1,5 @@ import { useDroppable } from "@dnd-kit/core"; -import { cn } from "@workspace/ui/lib"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useStore } from "../../../store/store"; import { ChartsGrid } from "../../charts/components/ChartsGrid"; import type { DndActiveData } from "../types/dndData"; diff --git a/frontend/testing-view/src/features/workspace/components/Toolbar.tsx b/frontend/testing-view/src/features/workspace/components/Toolbar.tsx index ccfb6a2cc..8cd0ba71f 100644 --- a/frontend/testing-view/src/features/workspace/components/Toolbar.tsx +++ b/frontend/testing-view/src/features/workspace/components/Toolbar.tsx @@ -1,5 +1,5 @@ -import { Button } from "@workspace/ui"; -import { ChevronLeft, Plus } from "@workspace/ui/icons"; +import { Button } from "@hyperloop-upv/frontend-kit"; +import { ChevronLeft, Plus } from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../../store/store"; interface TestingToolbarProps { diff --git a/frontend/testing-view/src/features/workspace/components/WorkspaceDialog.tsx b/frontend/testing-view/src/features/workspace/components/WorkspaceDialog.tsx index b261884ff..31ace59de 100644 --- a/frontend/testing-view/src/features/workspace/components/WorkspaceDialog.tsx +++ b/frontend/testing-view/src/features/workspace/components/WorkspaceDialog.tsx @@ -1,4 +1,4 @@ -import { Button } from "@workspace/ui"; +import { Button } from "@hyperloop-upv/frontend-kit"; import { Dialog, DialogContent, @@ -6,10 +6,10 @@ import { DialogFooter, DialogHeader, DialogTitle, -} from "@workspace/ui/components/shadcn/dialog"; -import { Input } from "@workspace/ui/components/shadcn/input"; -import { Label } from "@workspace/ui/components/shadcn/label"; -import { Textarea } from "@workspace/ui/components/shadcn/textarea"; +} from "@hyperloop-upv/frontend-kit/components/shadcn/dialog"; +import { Input } from "@hyperloop-upv/frontend-kit/components/shadcn/input"; +import { Label } from "@hyperloop-upv/frontend-kit/components/shadcn/label"; +import { Textarea } from "@hyperloop-upv/frontend-kit/components/shadcn/textarea"; import { useEffect, useState } from "react"; interface WorkspaceDialogProps { diff --git a/frontend/testing-view/src/features/workspace/components/WorkspaceSwitcher.tsx b/frontend/testing-view/src/features/workspace/components/WorkspaceSwitcher.tsx index 6a1a90607..980990168 100644 --- a/frontend/testing-view/src/features/workspace/components/WorkspaceSwitcher.tsx +++ b/frontend/testing-view/src/features/workspace/components/WorkspaceSwitcher.tsx @@ -7,7 +7,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, useSidebar, -} from "@workspace/ui"; +} from "@hyperloop-upv/frontend-kit"; import { ChevronsUpDown, Folder, @@ -15,8 +15,8 @@ import { Plus, SquareLibrary, Trash2, -} from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +} from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useState } from "react"; import { useStore } from "../../../store/store"; import type { Workspace } from "../types/workspace"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarContent.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarContent.tsx index ff41e515e..2451f1767 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarContent.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarContent.tsx @@ -2,7 +2,7 @@ import { ResizableHandle, ResizablePanel, ResizablePanelGroup, -} from "@workspace/ui"; +} from "@hyperloop-upv/frontend-kit"; import { useStore } from "../../../../store/store"; import { CommandsSection } from "./sections/CommandsSection"; import MessagesSection from "./sections/MessagesSection"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarHeader.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarHeader.tsx index 737f6ec91..8e54d6409 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarHeader.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarHeader.tsx @@ -1,4 +1,4 @@ -import { Button } from "@workspace/ui"; +import { Button } from "@hyperloop-upv/frontend-kit"; import { Activity, MessageSquare, @@ -6,7 +6,7 @@ import { PanelRight, Terminal, X, -} from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../../../store/store"; import { RightSidebarToggle } from "./RightSidebarToggle"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarToggle.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarToggle.tsx index 65a6d16e7..d39ff7b2f 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarToggle.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/RightSidebarToggle.tsx @@ -4,7 +4,7 @@ import { TooltipContent, TooltipProvider, TooltipTrigger, -} from "@workspace/ui"; +} from "@hyperloop-upv/frontend-kit"; import type { ReactNode } from "react"; interface RightSidebarToggleProps { diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/sections/MessageItem.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/sections/MessageItem.tsx index 4b5ccbcb9..4958930e2 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/sections/MessageItem.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/sections/MessageItem.tsx @@ -3,9 +3,9 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger, -} from "@workspace/ui"; -import { ChevronDown } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +} from "@hyperloop-upv/frontend-kit"; +import { ChevronDown } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useState } from "react"; import { MESSAGE_KIND_COLORS } from "../../../../../constants/messageKindColors"; import { formatTimestamp } from "../../../../../lib/utils"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/sections/MessagesSection.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/sections/MessagesSection.tsx index 5343bb876..35e1d07a5 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/sections/MessagesSection.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/sections/MessagesSection.tsx @@ -1,5 +1,5 @@ -import { Button } from "@workspace/ui"; -import { Trash2 } from "@workspace/ui/icons"; +import { Button } from "@hyperloop-upv/frontend-kit"; +import { Trash2 } from "@hyperloop-upv/frontend-kit/icons"; import { useStore } from "../../../../../store/store"; import { MessagesList } from "./MessagesList"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/CategoryHeader.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/CategoryHeader.tsx index f0ff3c78b..78106ea6c 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/CategoryHeader.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/CategoryHeader.tsx @@ -1,4 +1,4 @@ -import { ChevronDown, ChevronLeft } from "@workspace/ui/icons"; +import { ChevronDown, ChevronLeft } from "@hyperloop-upv/frontend-kit/icons"; interface CategoryHeaderProps { name: string; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/CategoryItem.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/CategoryItem.tsx index 3622797d8..0932d1cfc 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/CategoryItem.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/CategoryItem.tsx @@ -1,4 +1,4 @@ -import { Collapsible, CollapsibleContent } from "@workspace/ui"; +import { Collapsible, CollapsibleContent } from "@hyperloop-upv/frontend-kit"; import { type ComponentType } from "react"; import { useShallow } from "zustand/shallow"; import { useStore } from "../../../../../store/store"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/EmptyTab.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/EmptyTab.tsx index ec9885d21..655931fc9 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/EmptyTab.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/EmptyTab.tsx @@ -1,6 +1,6 @@ // EmptyTabState.tsx -import { Button } from "@workspace/ui"; -import { Filter, ListFilterPlus } from "@workspace/ui/icons"; +import { Button } from "@hyperloop-upv/frontend-kit"; +import { Filter, ListFilterPlus } from "@hyperloop-upv/frontend-kit/icons"; interface EmptyTabProps { title: string; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/TabHeader.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/TabHeader.tsx index d585ad9b6..5dda2d51b 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/TabHeader.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/TabHeader.tsx @@ -1,5 +1,5 @@ -import { Button } from "@workspace/ui"; -import { AlertTriangle, ListFilterPlus } from "@workspace/ui/icons"; +import { Button } from "@hyperloop-upv/frontend-kit"; +import { AlertTriangle, ListFilterPlus } from "@hyperloop-upv/frontend-kit/icons"; import { useShallow } from "zustand/shallow"; import { detectExtraBoards } from "../../../../../lib/utils"; import { useStore } from "../../../../../store/store"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/VirtualizedList.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/VirtualizedList.tsx index c646ffeb3..010ab6793 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/VirtualizedList.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/VirtualizedList.tsx @@ -1,6 +1,6 @@ // frontend/testing-view/src/components/common/VirtualizedList.tsx import { useVirtualizer } from "@tanstack/react-virtual"; -import { cn } from "@workspace/ui/lib"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useCallback, useRef } from "react"; import type { BoardName } from "../../../../../types/data/board"; import type { VirtualRow } from "../../../../../types/data/virtualization"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/commands/CommandItem.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/commands/CommandItem.tsx index df9ac8168..c62fca81c 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/commands/CommandItem.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/commands/CommandItem.tsx @@ -1,12 +1,12 @@ -import { logger, socketService } from "@workspace/core"; +import { logger, socketService } from "@hyperloop-upv/frontend-kit/core"; import { Badge, Collapsible, CollapsibleContent, CollapsibleTrigger, -} from "@workspace/ui"; -import { ChevronDown, Play, Send } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +} from "@hyperloop-upv/frontend-kit"; +import { ChevronDown, Play, Send } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useState } from "react"; import { getDefaultParameterValues } from "../../../../../../lib/commandUtils"; import { useStore } from "../../../../../../store/store"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/commands/CommandParameters.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/commands/CommandParameters.tsx index dcf19f32a..c1335cbb9 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/commands/CommandParameters.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/commands/CommandParameters.tsx @@ -7,7 +7,7 @@ import { SelectItem, SelectTrigger, SelectValue, -} from "@workspace/ui"; +} from "@hyperloop-upv/frontend-kit"; import type { CommandParameter, EnumCommandParameter, diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/ChartPicker.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/ChartPicker.tsx index 8a06598d0..ec1a238db 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/ChartPicker.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/ChartPicker.tsx @@ -6,8 +6,8 @@ import { DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, -} from "@workspace/ui"; -import { Plus } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit"; +import { Plus } from "@hyperloop-upv/frontend-kit/icons"; import type { WorkspaceChartConfig } from "../../../../../charts/types/charts"; interface ChartPickerProps { diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryHeader.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryHeader.tsx index fb4edf7a2..54bae57ab 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryHeader.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryHeader.tsx @@ -1,6 +1,6 @@ -import { Badge, Separator } from "@workspace/ui"; -import { Activity, ChevronDown } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { Badge, Separator } from "@hyperloop-upv/frontend-kit"; +import { Activity, ChevronDown } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { memo, useEffect, useRef, useState } from "react"; import { useStore } from "../../../../../../store/store"; import type { TelemetryCatalogItem } from "../../../../../../types/data/telemetryCatalogItem"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryItem.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryItem.tsx index d263e7cd6..9a9897f1e 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryItem.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryItem.tsx @@ -2,7 +2,7 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger, -} from "@workspace/ui"; +} from "@hyperloop-upv/frontend-kit"; import { memo } from "react"; import { useStore } from "../../../../../../store/store"; import type { TelemetryCatalogItem } from "../../../../../../types/data/telemetryCatalogItem"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryValue.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryValue.tsx index ab9934224..aac4c9df3 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryValue.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/TelemetryValue.tsx @@ -1,6 +1,6 @@ -import { Badge } from "@workspace/ui"; -import { Check, X } from "@workspace/ui/icons"; -import { cn } from "@workspace/ui/lib"; +import { Badge } from "@hyperloop-upv/frontend-kit"; +import { Check, X } from "@hyperloop-upv/frontend-kit/icons"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useCallback } from "react"; import { useStore } from "../../../../../../store/store"; diff --git a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/VariableItem.tsx b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/VariableItem.tsx index c53865b97..4fb335e83 100644 --- a/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/VariableItem.tsx +++ b/frontend/testing-view/src/features/workspace/components/rightSidebar/tabs/telemetry/VariableItem.tsx @@ -1,6 +1,6 @@ import { useDraggable } from "@dnd-kit/core"; -import { Badge } from "@workspace/ui"; -import { cn } from "@workspace/ui/lib"; +import { Badge } from "@hyperloop-upv/frontend-kit"; +import { cn } from "@hyperloop-upv/frontend-kit/lib"; import { useShallow } from "zustand/shallow"; import { canAddSeriesToChart, diff --git a/frontend/testing-view/src/hooks/useAppConfigs.ts b/frontend/testing-view/src/hooks/useAppConfigs.ts index 07b885fda..c52d26780 100644 --- a/frontend/testing-view/src/hooks/useAppConfigs.ts +++ b/frontend/testing-view/src/hooks/useAppConfigs.ts @@ -1,4 +1,4 @@ -import { useFetchConfig } from "@workspace/ui/hooks"; +import { useFetchConfig } from "@hyperloop-upv/frontend-kit/hooks"; import { useEffect } from "react"; import { useStore } from "../store/store"; import type { OrdersData, PacketsData } from "../types/data/board"; diff --git a/frontend/testing-view/src/hooks/useAppMode.ts b/frontend/testing-view/src/hooks/useAppMode.ts index 79951cdc4..67e2aa66c 100644 --- a/frontend/testing-view/src/hooks/useAppMode.ts +++ b/frontend/testing-view/src/hooks/useAppMode.ts @@ -1,4 +1,4 @@ -import { logger } from "@workspace/core"; +import { logger } from "@hyperloop-upv/frontend-kit/core"; import { useCallback, useEffect } from "react"; import { useStore } from "../store/store"; import type { OrdersData, PacketsData } from "../types/data/board"; diff --git a/frontend/testing-view/src/hooks/useBoardData.ts b/frontend/testing-view/src/hooks/useBoardData.ts index 22ff3d8f9..82cdf0c74 100644 --- a/frontend/testing-view/src/hooks/useBoardData.ts +++ b/frontend/testing-view/src/hooks/useBoardData.ts @@ -1,4 +1,4 @@ -import { logger } from "@workspace/core"; +import { logger } from "@hyperloop-upv/frontend-kit/core"; import { useMemo } from "react"; import { formatName } from "../lib/utils"; import { MOCK_COMMANDS_CATALOG } from "../mocks/commands"; diff --git a/frontend/testing-view/src/hooks/useErrorHandler.ts b/frontend/testing-view/src/hooks/useErrorHandler.ts index fcba6be94..9abbc7f8e 100644 --- a/frontend/testing-view/src/hooks/useErrorHandler.ts +++ b/frontend/testing-view/src/hooks/useErrorHandler.ts @@ -1,5 +1,5 @@ -import { logger } from "@workspace/core"; -import useErrorSubscription from "@workspace/ui/hooks/webSocket/useErrorSubscription"; +import { logger } from "@hyperloop-upv/frontend-kit/core"; +import useErrorSubscription from "@hyperloop-upv/frontend-kit/hooks/webSocket/useErrorSubscription"; import { useEffect } from "react"; import { useStore } from "../store/store"; diff --git a/frontend/testing-view/src/hooks/useLogger.ts b/frontend/testing-view/src/hooks/useLogger.ts index 1f612a591..45182476b 100644 --- a/frontend/testing-view/src/hooks/useLogger.ts +++ b/frontend/testing-view/src/hooks/useLogger.ts @@ -1,5 +1,5 @@ -import { logger, socketService } from "@workspace/core"; -import { useTopic } from "@workspace/ui/hooks"; +import { logger, socketService } from "@hyperloop-upv/frontend-kit/core"; +import { useTopic } from "@hyperloop-upv/frontend-kit/hooks"; import { useEffect, useState } from "react"; import { config } from "../../config"; import { useStore } from "../store/store"; diff --git a/frontend/testing-view/src/hooks/useOpenFolder.ts b/frontend/testing-view/src/hooks/useOpenFolder.ts index 25c65b3f1..bb33e01f5 100644 --- a/frontend/testing-view/src/hooks/useOpenFolder.ts +++ b/frontend/testing-view/src/hooks/useOpenFolder.ts @@ -1,4 +1,4 @@ -import { logger } from "@workspace/core"; +import { logger } from "@hyperloop-upv/frontend-kit/core"; export const useOpenFolder = () => { const openFolder = (path?: string) => { diff --git a/frontend/testing-view/src/index.css b/frontend/testing-view/src/index.css index 6824f52fb..07cbe7182 100644 --- a/frontend/testing-view/src/index.css +++ b/frontend/testing-view/src/index.css @@ -1 +1,6 @@ -@import "@workspace/ui/globals.css"; +@import "@hyperloop-upv/frontend-kit/globals.css"; + +/* Ensure Tailwind v4 scans testing-view source files directly. + The @source paths in globals.css resolve via the @hyperloop-upv/frontend-kit symlink + and don't correctly reach this project's source tree. */ +@source "./**/*.{ts,tsx}"; diff --git a/frontend/testing-view/src/layout/AppLayout.tsx b/frontend/testing-view/src/layout/AppLayout.tsx index 407a8bb9e..e1abad52e 100644 --- a/frontend/testing-view/src/layout/AppLayout.tsx +++ b/frontend/testing-view/src/layout/AppLayout.tsx @@ -1,4 +1,4 @@ -import { SidebarInset, SidebarProvider } from "@workspace/ui/components"; +import { SidebarInset, SidebarProvider } from "@hyperloop-upv/frontend-kit/components"; import React, { useEffect } from "react"; import Header from "../components/header/Header"; import AppSidebar from "../components/leftSidebar/AppSidebar"; diff --git a/frontend/testing-view/src/lib/utils.test.ts b/frontend/testing-view/src/lib/utils.test.ts index e98d286cf..6066db679 100644 --- a/frontend/testing-view/src/lib/utils.test.ts +++ b/frontend/testing-view/src/lib/utils.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { typeBadgeClasses, getTypeBadgeClass } from "@workspace/ui/lib"; +import { typeBadgeClasses, getTypeBadgeClass } from "@hyperloop-upv/frontend-kit/lib"; import type { FilterScope } from "../features/filtering/types/filters"; import type { MessageTimestamp } from "../types/data/message"; import { diff --git a/frontend/testing-view/src/lib/utils.ts b/frontend/testing-view/src/lib/utils.ts index cbb9a32c1..93943445d 100644 --- a/frontend/testing-view/src/lib/utils.ts +++ b/frontend/testing-view/src/lib/utils.ts @@ -1,6 +1,6 @@ -import type { VariableValue } from "@workspace/core"; +import type { VariableValue } from "@hyperloop-upv/frontend-kit/core"; import { ACRONYMS } from "../constants/acronyms"; -export { getTypeBadgeClass } from "@workspace/ui/lib"; +export { getTypeBadgeClass } from "@hyperloop-upv/frontend-kit/lib"; import type { FilterScope, TabFilter, diff --git a/frontend/testing-view/src/pages/Testing.tsx b/frontend/testing-view/src/pages/Testing.tsx index d9c57e1ed..d8fa89583 100644 --- a/frontend/testing-view/src/pages/Testing.tsx +++ b/frontend/testing-view/src/pages/Testing.tsx @@ -3,8 +3,8 @@ import { ResizableHandle, ResizablePanel, ResizablePanelGroup, -} from "@workspace/ui"; -import { SquareLibrary } from "@workspace/ui/icons"; +} from "@hyperloop-upv/frontend-kit"; +import { SquareLibrary } from "@hyperloop-upv/frontend-kit/icons"; import { FilterController } from "../features/filtering/components/FilterController"; import { useGlobalKeyBindings } from "../features/keyBindings/hooks/useGlobalKeyBindings"; import { DndOverlay } from "../features/workspace/components/DndOverlay"; diff --git a/frontend/testing-view/src/types/telemetry/telemetry.ts b/frontend/testing-view/src/types/telemetry/telemetry.ts index 330c63722..306d00915 100644 --- a/frontend/testing-view/src/types/telemetry/telemetry.ts +++ b/frontend/testing-view/src/types/telemetry/telemetry.ts @@ -1,4 +1,4 @@ -import type { TelemetryPacket } from "@workspace/core"; +import type { TelemetryPacket } from "@hyperloop-upv/frontend-kit/core"; /** * Map of telemetry packets per telemetry packetid. diff --git a/frontend/testing-view/tsconfig.json b/frontend/testing-view/tsconfig.json index 3b2ce502f..a9428b2d0 100644 --- a/frontend/testing-view/tsconfig.json +++ b/frontend/testing-view/tsconfig.json @@ -11,8 +11,7 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "@/*": ["./*"], - "@workspace/ui/*": ["../frontend-kit/ui/src/*"] + "@/*": ["./*"] } }, "exclude": ["node_modules"] diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index f094c3328..17c874774 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "@workspace/typescript-config/base.json" + "extends": "@hyperloop-upv/typescript-config/base.json" } diff --git a/package.json b/package.json index 02a60047e..931a30035 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,11 @@ "lint": "turbo lint", "preview": "turbo preview", "test": "turbo test", - "ui:add": "pnpm dlx shadcn@latest add -c frontend/frontend-kit/ui" + "ui:add": "pnpm dlx shadcn@latest add -c frontend/frontend-kit/kit" }, "devDependencies": { - "@workspace/eslint-config": "workspace:*", - "@workspace/typescript-config": "workspace:*", + "@hyperloop-upv/eslint-config": "workspace:*", + "@hyperloop-upv/typescript-config": "workspace:*", "prettier": "^3.8.1", "prettier-plugin-tailwindcss": "^0.7.2", "turbo": "^2.8.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 62b462a5e..af1732f70 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,10 +8,10 @@ importers: .: devDependencies: - '@workspace/eslint-config': + '@hyperloop-upv/eslint-config': specifier: workspace:* - version: link:frontend/frontend-kit/esling-config - '@workspace/typescript-config': + version: link:frontend/frontend-kit/eslint-config + '@hyperloop-upv/typescript-config': specifier: workspace:* version: link:frontend/frontend-kit/typescript-config prettier: @@ -76,15 +76,15 @@ importers: frontend/adj-view: dependencies: + '@hyperloop-upv/frontend-kit': + specifier: workspace:* + version: link:../frontend-kit/kit '@tailwindcss/vite': specifier: ^4.1.18 version: 4.3.0(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) '@vitejs/plugin-react-swc': specifier: ^4.2.3 version: 4.2.3(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) - '@workspace/ui': - specifier: workspace:* - version: link:../frontend-kit/ui lucide-react: specifier: ^0.563.0 version: 0.563.0(react@19.2.4) @@ -98,18 +98,18 @@ importers: specifier: ^4.1.18 version: 4.3.0 devDependencies: + '@hyperloop-upv/eslint-config': + specifier: workspace:^ + version: link:../frontend-kit/eslint-config + '@hyperloop-upv/typescript-config': + specifier: workspace:* + version: link:../frontend-kit/typescript-config '@types/react': specifier: 19.2.11 version: 19.2.11 '@types/react-dom': specifier: 19.2.3 version: 19.2.3(@types/react@19.2.11) - '@workspace/eslint-config': - specifier: workspace:^ - version: link:../frontend-kit/esling-config - '@workspace/typescript-config': - specifier: workspace:* - version: link:../frontend-kit/typescript-config eslint: specifier: ^9.39.2 version: 9.39.4(jiti@2.6.1) @@ -122,18 +122,15 @@ importers: frontend/competition-view: dependencies: + '@hyperloop-upv/frontend-kit': + specifier: workspace:* + version: link:../frontend-kit/kit '@tailwindcss/vite': specifier: ^4.1.18 version: 4.3.0(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) '@vitejs/plugin-react-swc': specifier: ^4.2.3 version: 4.2.3(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) - '@workspace/core': - specifier: workspace:* - version: link:../frontend-kit/core - '@workspace/ui': - specifier: workspace:* - version: link:../frontend-kit/ui lucide-react: specifier: ^0.563.0 version: 0.563.0(react@19.2.4) @@ -156,18 +153,18 @@ importers: specifier: ^5.0.11 version: 5.0.11(@types/react@19.2.11)(immer@11.1.0)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) devDependencies: + '@hyperloop-upv/eslint-config': + specifier: workspace:^ + version: link:../frontend-kit/eslint-config + '@hyperloop-upv/typescript-config': + specifier: workspace:* + version: link:../frontend-kit/typescript-config '@types/react': specifier: ^19.2.11 version: 19.2.11 '@types/react-dom': specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.11) - '@workspace/eslint-config': - specifier: workspace:^ - version: link:../frontend-kit/esling-config - '@workspace/typescript-config': - specifier: workspace:* - version: link:../frontend-kit/typescript-config eslint: specifier: ^9.39.2 version: 9.39.2(jiti@2.6.1) @@ -183,15 +180,15 @@ importers: frontend/flashing-view: dependencies: + '@hyperloop-upv/frontend-kit': + specifier: workspace:* + version: link:../frontend-kit/kit '@tailwindcss/vite': specifier: ^4.1.18 version: 4.3.0(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) '@vitejs/plugin-react-swc': specifier: ^4.2.3 version: 4.2.3(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) - '@workspace/ui': - specifier: workspace:* - version: link:../frontend-kit/ui lucide-react: specifier: ^0.563.0 version: 0.563.0(react@19.2.4) @@ -205,18 +202,18 @@ importers: specifier: ^4.1.18 version: 4.3.0 devDependencies: + '@hyperloop-upv/eslint-config': + specifier: workspace:^ + version: link:../frontend-kit/eslint-config + '@hyperloop-upv/typescript-config': + specifier: workspace:* + version: link:../frontend-kit/typescript-config '@types/react': specifier: 19.2.11 version: 19.2.11 '@types/react-dom': specifier: 19.2.3 version: 19.2.3(@types/react@19.2.11) - '@workspace/eslint-config': - specifier: workspace:^ - version: link:../frontend-kit/esling-config - '@workspace/typescript-config': - specifier: workspace:* - version: link:../frontend-kit/typescript-config eslint: specifier: ^9.39.2 version: 9.39.4(jiti@2.6.1) @@ -227,51 +224,38 @@ importers: specifier: ^7.3.1 version: 7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0) - frontend/frontend-kit/core: - dependencies: - rxjs: - specifier: ^7.8.2 - version: 7.8.2 - devDependencies: - '@workspace/eslint-config': - specifier: workspace:* - version: link:../esling-config - eslint: - specifier: ^9.39.2 - version: 9.39.2(jiti@2.6.1) - - frontend/frontend-kit/esling-config: + frontend/frontend-kit/eslint-config: devDependencies: '@eslint/js': specifier: ^9.39.2 - version: 9.39.2 + version: 9.39.4 '@typescript-eslint/eslint-plugin': specifier: ^8.54.0 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': specifier: ^8.54.0 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) eslint: specifier: ^9.39.2 - version: 9.39.2(jiti@2.6.1) + version: 9.39.4(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.2(jiti@2.6.1)) + version: 10.1.8(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-only-warn: specifier: ^1.1.0 version: 1.1.0 eslint-plugin-react: specifier: ^7.37.5 - version: 7.37.5(eslint@9.39.2(jiti@2.6.1)) + version: 7.37.5(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-react-hooks: specifier: ^7.0.1 - version: 7.0.1(eslint@9.39.2(jiti@2.6.1)) + version: 7.0.1(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-react-refresh: specifier: ^0.5.0 - version: 0.5.0(eslint@9.39.2(jiti@2.6.1)) + version: 0.5.0(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-turbo: specifier: ^2.8.3 - version: 2.8.3(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.3) + version: 2.8.3(eslint@9.39.4(jiti@2.6.1))(turbo@2.8.3) globals: specifier: ^17.3.0 version: 17.3.0 @@ -280,11 +264,9 @@ importers: version: 5.9.3 typescript-eslint: specifier: ^8.54.0 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - frontend/frontend-kit/typescript-config: {} - - frontend/frontend-kit/ui: + frontend/frontend-kit/kit: dependencies: '@base-ui/react': specifier: ^1.3.0 @@ -325,30 +307,15 @@ importers: '@radix-ui/react-tooltip': specifier: ^1.2.8 version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@workspace/core': - specifier: workspace:* - version: link:../core class-variance-authority: specifier: ^0.7.1 version: 0.7.1 clsx: specifier: ^2.1.1 version: 2.1.1 - lucide-react: - specifier: ^0.563.0 - version: 0.563.0(react@19.2.4) - next-themes: - specifier: ^0.4.6 - version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) radix-ui: specifier: ^1.4.3 version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: - specifier: ^19.2.4 - version: 19.2.4 - react-dom: - specifier: ^19.2.4 - version: 19.2.4(react@19.2.4) react-resizable-panels: specifier: ^4.6.0 version: 4.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -358,16 +325,13 @@ importers: tailwind-merge: specifier: ^3.4.0 version: 3.4.0 - tw-animate-css: - specifier: ^1.4.0 - version: 1.4.0 - zod: - specifier: ^4.3.6 - version: 4.3.6 - zustand: - specifier: ^5.0.11 - version: 5.0.11(@types/react@19.2.11)(immer@11.1.0)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) devDependencies: + '@hyperloop-upv/eslint-config': + specifier: workspace:* + version: link:../eslint-config + '@hyperloop-upv/typescript-config': + specifier: workspace:* + version: link:../typescript-config '@maximka76667/icons-master': specifier: ^1.0.3 version: 1.0.3 @@ -386,27 +350,50 @@ importers: '@types/react-dom': specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.11) - '@workspace/eslint-config': - specifier: workspace:* - version: link:../esling-config - '@workspace/typescript-config': - specifier: workspace:* - version: link:../typescript-config + '@vitejs/plugin-react-swc': + specifier: ^4.2.3 + version: 4.2.3(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) eslint: specifier: ^9.39.2 - version: 9.39.2(jiti@2.6.1) + version: 9.39.4(jiti@2.6.1) + lucide-react: + specifier: ^0.563.0 + version: 0.563.0(react@19.2.4) + react: + specifier: ^19.2.4 + version: 19.2.4 + react-dom: + specifier: ^19.2.4 + version: 19.2.4(react@19.2.4) tailwindcss: specifier: ^4.1.18 - version: 4.1.18 + version: 4.3.0 + tinyglobby: + specifier: ^0.2.17 + version: 0.2.17 + tw-animate-css: + specifier: ^1.4.0 + version: 1.4.0 typescript: specifier: ^5.9.3 version: 5.9.3 + vite: + specifier: ^7.3.1 + version: 7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0) + vite-plugin-dts: + specifier: ^5.1.2 + version: 5.1.2(esbuild@0.27.2)(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) + + frontend/frontend-kit/typescript-config: {} frontend/logging-view: dependencies: '@dnd-kit/core': specifier: ^6.3.1 version: 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@hyperloop-upv/frontend-kit': + specifier: workspace:* + version: link:../frontend-kit/kit '@tailwindcss/vite': specifier: ^4.1.18 version: 4.3.0(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) @@ -419,12 +406,6 @@ importers: '@vitejs/plugin-react-swc': specifier: ^4.2.3 version: 4.2.3(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) - '@workspace/core': - specifier: workspace:* - version: link:../frontend-kit/core - '@workspace/ui': - specifier: workspace:* - version: link:../frontend-kit/ui jspdf: specifier: ^4.2.1 version: 4.2.1 @@ -453,18 +434,18 @@ importers: specifier: ^5.0.11 version: 5.0.11(@types/react@19.2.11)(immer@11.1.0)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) devDependencies: + '@hyperloop-upv/eslint-config': + specifier: workspace:^ + version: link:../frontend-kit/eslint-config + '@hyperloop-upv/typescript-config': + specifier: workspace:* + version: link:../frontend-kit/typescript-config '@types/react': specifier: ^19.2.11 version: 19.2.11 '@types/react-dom': specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.11) - '@workspace/eslint-config': - specifier: workspace:^ - version: link:../frontend-kit/esling-config - '@workspace/typescript-config': - specifier: workspace:* - version: link:../frontend-kit/typescript-config eslint: specifier: ^9.39.2 version: 9.39.2(jiti@2.6.1) @@ -492,6 +473,9 @@ importers: '@dnd-kit/utilities': specifier: ^3.2.2 version: 3.2.2(react@19.2.4) + '@hyperloop-upv/frontend-kit': + specifier: workspace:* + version: link:../frontend-kit/kit '@radix-ui/react-slot': specifier: ^1.2.4 version: 1.2.4(@types/react@19.2.11)(react@19.2.4) @@ -507,12 +491,6 @@ importers: '@vitejs/plugin-react-swc': specifier: ^4.2.3 version: 4.2.3(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) - '@workspace/core': - specifier: workspace:* - version: link:../frontend-kit/core - '@workspace/ui': - specifier: workspace:* - version: link:../frontend-kit/ui lodash: specifier: ^4.17.23 version: 4.17.23 @@ -541,18 +519,18 @@ importers: specifier: ^5.0.11 version: 5.0.11(@types/react@19.2.11)(immer@11.1.0)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) devDependencies: + '@hyperloop-upv/eslint-config': + specifier: workspace:^ + version: link:../frontend-kit/eslint-config + '@hyperloop-upv/typescript-config': + specifier: workspace:* + version: link:../frontend-kit/typescript-config '@types/react': specifier: ^19.2.11 version: 19.2.11 '@types/react-dom': specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.11) - '@workspace/eslint-config': - specifier: workspace:^ - version: link:../frontend-kit/esling-config - '@workspace/typescript-config': - specifier: workspace:* - version: link:../frontend-kit/typescript-config eslint: specifier: ^9.39.2 version: 9.39.2(jiti@2.6.1) @@ -959,24 +937,12 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@floating-ui/core@1.7.4': - resolution: {integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==} - '@floating-ui/core@1.7.5': resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} - '@floating-ui/dom@1.7.5': - resolution: {integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==} - '@floating-ui/dom@1.7.6': resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} - '@floating-ui/react-dom@2.1.7': - resolution: {integrity: sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - '@floating-ui/react-dom@2.1.8': resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==} peerDependencies: @@ -1886,6 +1852,15 @@ packages: '@rolldown/pluginutils@1.0.0-rc.2': resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} + '@rollup/pluginutils@5.5.1': + resolution: {integrity: sha512-P9ZvnfouRu4MSC+ilERaw6FmZs8zqKhpHxEs4aGDGWQAMzQGXnhvCSvoNwokfNvdt7t3Y5Y4p6gStQgezeIqug==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.57.1': resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} cpu: [arm] @@ -2512,6 +2487,28 @@ packages: '@vitest/utils@4.0.18': resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} + '@volar/language-core@2.4.30': + resolution: {integrity: sha512-73fjwEV8wat6aOZ6U/y/hqtE30ocrIWECg67b0txGczOMNw+MffLmvJ5fnFfN9drVUEYZzLdaNo6VAy6G6avMw==} + + '@volar/language-service@2.4.30': + resolution: {integrity: sha512-w/xDsASiqC71ggCOm7sTDXDNk/l72XEptodeRC68tgZ0e5QM4hM3zAqBGC7mBctvhrpYwKfMG+t9xcUo2hEFtA==} + peerDependencies: + typescript: <7 + peerDependenciesMeta: + typescript: + optional: true + + '@volar/source-map@2.4.30': + resolution: {integrity: sha512-zym1ob/KwDDyN+0jGVtxwbxJSRRnUvv5HspCtz3yEfVVdCG4/dzxJktMGPAgemqRuVs81O0o/y0q3qOUErR8kg==} + + '@volar/typescript@2.4.30': + resolution: {integrity: sha512-/DgA5tgYFPfrLFuSjIMXMGHk1LQv2+P8eny6+BhGNzFJELWIW7UZlc56ZLIRFhLsPpMfIFxM8/HvOPBggrjTZg==} + peerDependencies: + typescript: <7 + peerDependenciesMeta: + typescript: + optional: true + '@xmldom/xmldom@0.8.11': resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} engines: {node: '>=10.0.0'} @@ -2535,6 +2532,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.19.0: + resolution: {integrity: sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==} + engines: {node: '>=0.4.0'} + hasBin: true + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -2956,6 +2958,9 @@ packages: resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} engines: {node: '>=0.10.0'} + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + compress-commons@4.1.2: resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} engines: {node: '>= 10'} @@ -2967,6 +2972,12 @@ packages: resolution: {integrity: sha512-Uy5YN9KEu0WWDaZAVJ5FAmZoaJt9rdK6kH+utItPyGsCqCgaTKkrmZx3zoE0/3q6S3bcp3Ihkk+ZqPxWxFK5og==} engines: {node: '>=20'} + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + confbox@0.3.2: + resolution: {integrity: sha512-ZUAKhKlkCOrIGKc8cj7zek9s9z1mveHif/25nUshI2BzCRzF7KH7KHa+Lnh2ubq+e1tIlaFuP763mzW4qVoehg==} + config-file-ts@0.2.6: resolution: {integrity: sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==} @@ -3333,6 +3344,7 @@ packages: eslint@9.39.2: resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true peerDependencies: jiti: '*' @@ -3343,6 +3355,7 @@ packages: eslint@9.39.4: resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true peerDependencies: jiti: '*' @@ -3371,6 +3384,9 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -3389,6 +3405,9 @@ packages: exponential-backoff@3.1.3: resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} + exsolve@1.2.0: + resolution: {integrity: sha512-h1pQPR9XoeSMdntRNCjyTznaume4UpfXrULBnlkZ2CUM/G5eSa+pBByGldO5uR8dxbPC+OuJXsPPNf+JZ81ADg==} + external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} @@ -3588,6 +3607,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + glob@10.5.0: resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me @@ -4039,6 +4061,9 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + lazy-val@1.0.5: resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} @@ -4190,6 +4215,10 @@ packages: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} + local-pkg@1.2.1: + resolution: {integrity: sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==} + engines: {node: '>=14'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -4406,6 +4435,9 @@ packages: engines: {node: '>=10'} hasBin: true + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -4445,12 +4477,6 @@ packages: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} - next-themes@0.4.6: - resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} - peerDependencies: - react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - no-case@2.3.2: resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} @@ -4598,6 +4624,9 @@ packages: pascal-case@2.0.1: resolution: {integrity: sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==} + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-case@2.1.1: resolution: {integrity: sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==} @@ -4654,6 +4683,16 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} + engines: {node: '>=12'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pkg-types@2.4.0: + resolution: {integrity: sha512-07Fys7iVx0X6TcviMOgogM1Lk33ZyqOezMnU79S+kffWqwolG/5W9V8EgQSeYCIfFTYVgssRbnH630Oa2+soBA==} + playwright-core@1.58.2: resolution: {integrity: sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==} engines: {node: '>=18'} @@ -4778,6 +4817,9 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -5310,6 +5352,10 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + tinygradient@1.1.5: resolution: {integrity: sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==} @@ -5465,6 +5511,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + uglify-js@3.19.3: resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} @@ -5497,6 +5546,40 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + unplugin-dts@1.1.2: + resolution: {integrity: sha512-RDqy90XUmFj6rz4U5YoTMdYdaCJe2ZnQZaWIjkWS4952Gv0zBTQyqWtlGgVMPYHa982dURvyoc+sUOFIcDFv+w==} + peerDependencies: + '@microsoft/api-extractor': '>=7' + '@rspack/core': ^1 + '@vue/language-core': ^3.1.5 + esbuild: '*' + rolldown: '*' + rollup: '>=3' + typescript: '>=4' + vite: '>=3' + webpack: ^4 || ^5 + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@rspack/core': + optional: true + '@vue/language-core': + optional: true + esbuild: + optional: true + rolldown: + optional: true + rollup: + optional: true + vite: + optional: true + webpack: + optional: true + + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} + until-async@3.0.2: resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} @@ -5566,6 +5649,20 @@ packages: resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} engines: {node: '>=0.6.0'} + vite-plugin-dts@5.1.2: + resolution: {integrity: sha512-1bXUz836sWq6ewEMQre3ZtNFVfZk/92DppgCCKP8tWx/NWwV2wHuXlRHb2TztHjbikPxvyAGLGu7hVh94Plwww==} + peerDependencies: + '@microsoft/api-extractor': '>=7' + rollup: '>=3' + vite: '>=3' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + rollup: + optional: true + vite: + optional: true + vite@7.3.1: resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -5640,9 +5737,28 @@ packages: jsdom: optional: true + vscode-jsonrpc@10.0.0: + resolution: {integrity: sha512-USSfxg0vDIpTQqlQBGxF3mBARyoS8cU7LHLpbYNh6dOJt32dlskxPWB0Irrh5TllTmyf7oNLAvqDqzklbwwnpA==} + engines: {node: '>=14.17.0'} + + vscode-languageserver-protocol@3.18.5: + resolution: {integrity: sha512-FW4fBMzZ99N8xeob4py0l050wgCoRgTpEq5Xcsb9lM1bc29UKGR/wSV+4knaqFxssFHajy7OzNiKP/m3U1ZEuA==} + + vscode-languageserver-textdocument@1.0.16: + resolution: {integrity: sha512-qeNEuOi9a3qkqRf7Gfez2WL2VwlBTLCNekHBGO9kxPVUp9XuY15yfTJ9jwvOwKI0I2MhUUfZq95NSp+LK1CLQg==} + + vscode-languageserver-types@3.18.5: + resolution: {integrity: sha512-kPd6+JQNz3HMJvjKlqUxERSlZHAntl/aGpsk7ImwIh0ewDKDcjgAEyVSYciPiOJD3ftbK9IrfiqUeTZLSbCizw==} + + vscode-uri@3.2.0: + resolution: {integrity: sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==} + wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + when-exit@2.1.5: resolution: {integrity: sha512-VGkKJ564kzt6Ms1dbgPP/yuIoQCrsFAnRbptpC5wOEsDaNsbCB2bnfnaA8i/vRs5tjUSEOtIuvl9/MyVsvQZCg==} @@ -6212,30 +6328,15 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 - '@floating-ui/core@1.7.4': - dependencies: - '@floating-ui/utils': 0.2.11 - '@floating-ui/core@1.7.5': dependencies: '@floating-ui/utils': 0.2.11 - '@floating-ui/dom@1.7.5': - dependencies: - '@floating-ui/core': 1.7.4 - '@floating-ui/utils': 0.2.11 - '@floating-ui/dom@1.7.6': dependencies: '@floating-ui/core': 1.7.5 '@floating-ui/utils': 0.2.11 - '@floating-ui/react-dom@2.1.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@floating-ui/dom': 1.7.5 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - '@floating-ui/react-dom@2.1.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@floating-ui/dom': 1.7.6 @@ -6817,7 +6918,7 @@ snapshots: '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@floating-ui/react-dom': 2.1.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@floating-ui/react-dom': 2.1.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.11))(@types/react@19.2.11)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.11)(react@19.2.4) '@radix-ui/react-context': 1.1.2(@types/react@19.2.11)(react@19.2.4) @@ -7199,6 +7300,14 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.2': {} + '@rollup/pluginutils@5.5.1(rollup@4.57.1)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.57.1 + '@rollup/rollup-android-arm-eabi@4.57.1': optional: true @@ -7642,15 +7751,15 @@ snapshots: '@types/node': 25.2.0 optional: true - '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.54.0 - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.4.0(typescript@5.9.3) @@ -7658,14 +7767,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.54.0 '@typescript-eslint/types': 8.54.0 '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.54.0 debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -7688,13 +7797,13 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.54.0 '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -7717,13 +7826,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) '@typescript-eslint/scope-manager': 8.54.0 '@typescript-eslint/types': 8.54.0 '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -7804,6 +7913,30 @@ snapshots: '@vitest/pretty-format': 4.0.18 tinyrainbow: 3.0.3 + '@volar/language-core@2.4.30': + dependencies: + '@volar/source-map': 2.4.30 + + '@volar/language-service@2.4.30(typescript@5.9.3)': + dependencies: + '@volar/language-core': 2.4.30 + vscode-languageserver-protocol: 3.18.5 + vscode-languageserver-textdocument: 1.0.16 + vscode-uri: 3.2.0 + optionalDependencies: + typescript: 5.9.3 + + '@volar/source-map@2.4.30': {} + + '@volar/typescript@2.4.30(typescript@5.9.3)': + dependencies: + '@volar/language-core': 2.4.30 + '@volar/language-service': 2.4.30(typescript@5.9.3) + path-browserify: 1.0.1 + vscode-uri: 3.2.0 + optionalDependencies: + typescript: 5.9.3 + '@xmldom/xmldom@0.8.11': {} abbrev@3.0.1: {} @@ -7818,6 +7951,8 @@ snapshots: acorn@8.15.0: {} + acorn@8.19.0: {} + agent-base@6.0.2: dependencies: debug: 4.4.3 @@ -8409,6 +8544,8 @@ snapshots: compare-version@0.1.2: {} + compare-versions@6.1.1: {} + compress-commons@4.1.2: dependencies: buffer-crc32: 0.2.13 @@ -8430,6 +8567,10 @@ snapshots: semver: 7.7.3 uint8array-extras: 1.5.0 + confbox@0.1.8: {} + + confbox@0.3.2: {} + config-file-ts@0.2.6: dependencies: glob: 10.5.0 @@ -8902,28 +9043,28 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)): + eslint-config-prettier@10.1.8(eslint@9.39.4(jiti@2.6.1)): dependencies: - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) eslint-plugin-only-warn@1.1.0: {} - eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)): + eslint-plugin-react-hooks@7.0.1(eslint@9.39.4(jiti@2.6.1)): dependencies: '@babel/core': 7.29.0 '@babel/parser': 7.29.0 - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) hermes-parser: 0.25.1 zod: 4.3.6 zod-validation-error: 4.0.2(zod@4.3.6) transitivePeerDependencies: - supports-color - eslint-plugin-react-refresh@0.5.0(eslint@9.39.2(jiti@2.6.1)): + eslint-plugin-react-refresh@0.5.0(eslint@9.39.4(jiti@2.6.1)): dependencies: - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) - eslint-plugin-react@7.37.5(eslint@9.39.2(jiti@2.6.1)): + eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -8931,11 +9072,11 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.2 - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 + minimatch: 3.1.5 object.entries: 1.1.9 object.fromentries: 2.0.8 object.values: 1.2.1 @@ -8945,10 +9086,10 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-turbo@2.8.3(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.3): + eslint-plugin-turbo@2.8.3(eslint@9.39.4(jiti@2.6.1))(turbo@2.8.3): dependencies: dotenv: 16.0.3 - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.39.4(jiti@2.6.1) turbo: 2.8.3 eslint-scope@8.4.0: @@ -9060,6 +9201,8 @@ snapshots: estraverse@5.3.0: {} + estree-walker@2.0.2: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.8 @@ -9082,6 +9225,8 @@ snapshots: exponential-backoff@3.1.3: {} + exsolve@1.2.0: {} + external-editor@3.1.0: dependencies: chardet: 0.7.0 @@ -9156,6 +9301,10 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fdir@6.5.0(picomatch@4.0.7): + optionalDependencies: + picomatch: 4.0.7 + fflate@0.8.3: {} figures@3.2.0: @@ -9313,6 +9462,8 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regexp@0.4.1: {} + glob@10.5.0: dependencies: foreground-child: 3.3.1 @@ -9822,6 +9973,8 @@ snapshots: dependencies: json-buffer: 3.0.1 + kolorist@1.8.0: {} + lazy-val@1.0.5: {} lazystream@1.0.1: @@ -9931,6 +10084,12 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 + local-pkg@1.2.1: + dependencies: + mlly: 1.8.2 + pkg-types: 2.4.0 + quansync: 0.2.11 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -10129,6 +10288,13 @@ snapshots: mkdirp@1.0.4: {} + mlly@1.8.2: + dependencies: + acorn: 8.19.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.4 + ms@2.1.3: {} msw@2.14.6(@types/node@25.2.0)(typescript@5.9.3): @@ -10198,11 +10364,6 @@ snapshots: netmask@2.0.2: {} - next-themes@0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - no-case@2.3.2: dependencies: lower-case: 1.1.4 @@ -10401,6 +10562,8 @@ snapshots: camel-case: 3.0.0 upper-case-first: 1.1.2 + path-browserify@1.0.1: {} + path-case@2.1.1: dependencies: no-case: 2.3.2 @@ -10440,6 +10603,20 @@ snapshots: picomatch@4.0.3: {} + picomatch@4.0.7: {} + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 + + pkg-types@2.4.0: + dependencies: + confbox: 0.3.2 + exsolve: 1.2.0 + pathe: 2.0.3 + playwright-core@1.58.2: {} playwright@1.58.2: @@ -10517,6 +10694,8 @@ snapshots: punycode@2.3.1: {} + quansync@0.2.11: {} + queue-microtask@1.2.3: {} quick-lru@5.1.1: {} @@ -11181,6 +11360,11 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 + tinygradient@1.1.5: dependencies: '@types/tinycolor2': 1.4.6 @@ -11332,13 +11516,13 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): + typescript-eslint@8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.4(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -11348,6 +11532,8 @@ snapshots: typescript@6.0.3: optional: true + ufo@1.6.4: {} + uglify-js@3.19.3: optional: true @@ -11374,6 +11560,32 @@ snapshots: universalify@2.0.1: {} + unplugin-dts@1.1.2(esbuild@0.27.2)(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)): + dependencies: + '@rollup/pluginutils': 5.5.1(rollup@4.57.1) + '@volar/typescript': 2.4.30(typescript@5.9.3) + compare-versions: 6.1.1 + debug: 4.4.3 + glob-to-regexp: 0.4.1 + kolorist: 1.8.0 + local-pkg: 1.2.1 + magic-string: 0.30.21 + typescript: 5.9.3 + unplugin: 2.3.11 + optionalDependencies: + esbuild: 0.27.2 + rollup: 4.57.1 + vite: 7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0) + transitivePeerDependencies: + - supports-color + + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.15.0 + picomatch: 4.0.3 + webpack-virtual-modules: 0.6.2 + until-async@3.0.2: optional: true @@ -11441,6 +11653,21 @@ snapshots: extsprintf: 1.4.1 optional: true + vite-plugin-dts@5.1.2(esbuild@0.27.2)(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)): + dependencies: + unplugin-dts: 1.1.2(esbuild@0.27.2)(rollup@4.57.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0)) + optionalDependencies: + rollup: 4.57.1 + vite: 7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0) + transitivePeerDependencies: + - '@rspack/core' + - '@vue/language-core' + - esbuild + - rolldown + - supports-color + - typescript + - webpack + vite@7.3.1(@types/node@25.2.0)(jiti@2.6.1)(lightningcss@1.32.0): dependencies: esbuild: 0.27.2 @@ -11448,7 +11675,7 @@ snapshots: picomatch: 4.0.3 postcss: 8.5.6 rollup: 4.57.1 - tinyglobby: 0.2.15 + tinyglobby: 0.2.17 optionalDependencies: '@types/node': 25.2.0 fsevents: 2.3.3 @@ -11529,10 +11756,25 @@ snapshots: - tsx - yaml + vscode-jsonrpc@10.0.0: {} + + vscode-languageserver-protocol@3.18.5: + dependencies: + vscode-jsonrpc: 10.0.0 + vscode-languageserver-types: 3.18.5 + + vscode-languageserver-textdocument@1.0.16: {} + + vscode-languageserver-types@3.18.5: {} + + vscode-uri@3.2.0: {} + wcwidth@1.0.1: dependencies: defaults: 1.0.4 + webpack-virtual-modules@0.6.2: {} + when-exit@2.1.5: {} which-boxed-primitive@1.1.1: