Initial dev-1.0 commit for TS and Shadcn migration

This commit is contained in:
LukeGus committed 2025-07-17 01:13:30 -05:00
commit 00a827df09
82 files changed
+45402

No files matched your search

+117
View File
@@ -0,0 +1,117 @@
name: Build and Push Docker Image
on:
push:
branches:
- development
paths-ignore:
- '**.md'
- '.gitignore'
workflow_dispatch:
inputs:
tag_name:
description: "Custom tag name for the Docker image"
required: false
default: ""
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64
driver-opts: |
image=moby/buildkit:master
network=host
- name: Cache npm dependencies
uses: actions/cache@v3
with:
path: |
~/.npm
node_modules
*/*/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Determine Docker image tag
run: |
echo "REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
if [ "${{ github.event.inputs.tag_name }}" == "" ]; then
IMAGE_TAG="${{ github.ref_name }}-development-latest"
else
IMAGE_TAG="${{ github.event.inputs.tag_name }}"
fi
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
- name: Build and Push Multi-Arch Docker Image
uses: docker/build-push-action@v5
with:
context: .
file: ./docker/Dockerfile
push: true
platforms: linux/amd64,linux/arm64
tags: ghcr.io/${{ env.REPO_OWNER }}/termix:${{ env.IMAGE_TAG }}
labels: |
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
build-args: |
BUILDKIT_INLINE_CACHE=1
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
outputs: type=registry,compression=zstd,compression-level=19
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
- name: Notify via ntfy
if: success()
run: |
curl -d "Docker image build and push completed successfully for tag: ${{ env.IMAGE_TAG }}" \
https://ntfy.karmaa.site/termix-build
- name: Delete all untagged image versions
if: success()
uses: quartx-analytics/ghcr-cleaner@v1
with:
owner-type: user
token: ${{ secrets.GHCR_TOKEN }}
repository-owner: ${{ github.repository_owner }}
delete-untagged: true
- name: Cleanup Docker Images Locally
if: always()
run: |
docker image prune -af
docker system prune -af --volumes
+24
View File
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+62
View File
@@ -0,0 +1,62 @@
# Repo Stats
![GitHub Repo stars](https://img.shields.io/github/stars/LukeGus/Termix?style=flat&label=Stars)
![GitHub forks](https://img.shields.io/github/forks/LukeGus/Termix?style=flat&label=Forks)
![GitHub Release](https://img.shields.io/github/v/release/LukeGus/Termix?style=flat&label=Release)
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720"></a>
#### Top Technologies
[![React Badge](https://img.shields.io/badge/-React-61DBFB?style=flat-square&labelColor=black&logo=react&logoColor=61DBFB)](#)
[![Javascript Badge](https://img.shields.io/badge/-Javascript-F0DB4F?style=flat-square&labelColor=black&logo=javascript&logoColor=F0DB4F)](#)
[![Nodejs Badge](https://img.shields.io/badge/-Nodejs-3C873A?style=flat-square&labelColor=black&logo=node.js&logoColor=3C873A)](#)
[![HTML Badge](https://img.shields.io/badge/-HTML-E34F26?style=flat-square&labelColor=black&logo=html5&logoColor=E34F26)](#)
[![Tailwind CSS Badge](https://img.shields.io/badge/-TailwindCSS-38B2AC?style=flat-square&labelColor=black&logo=tailwindcss&logoColor=38B2AC)](#)
[![Docker Badge](https://img.shields.io/badge/-Docker-2496ED?style=flat-square&labelColor=black&logo=docker&logoColor=2496ED)](#)
[![MongoDB Badge](https://img.shields.io/badge/-MongoDB-47A248?style=flat-square&labelColor=black&logo=mongodb&logoColor=47A248)](#)
[![MUI Joy Badge](https://img.shields.io/badge/-MUI%20Joy-007FFF?style=flat-square&labelColor=black&logo=mui&logoColor=007FFF)](#)
<br />
<p align="center">
<a href="https://github.com/LukeGus/Termix">
<img alt="Termix Banner" src=../../Termix/repo-images/TermixLogo.png style="width: 125px; height: auto;"> </a>
</p>
If you would like, you can support the project here!\
[![PayPal](https://img.shields.io/badge/PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white)](https://paypal.me/LukeGustafson803)
# Overview
Termix is an open-source forever free self-hosted Homepage (other protocols planned, see [Planned Features](#planned-features)) server management panel inspired by [Nexterm](https://github.com/gnmyt/Nexterm). Its purpose is to provide an all-in-one docker-hosted web solution to manage your servers in one easy place. I'm using this project to help me learn [React](https://github.com/facebook/react), [Vite](https://github.com/vitejs/vite-plugin-react), and [Docker](https://www.docker.com) but also because I could never settle on a server management software that I enjoyed to use.
> [!WARNING]
> This app is in the VERY early stages of development. Expect bugs, data loss, and unexplainable issues! For that reason, I recommend you securely tunnel your connection to Termix through a VPN.
# Features
- Homepage
- Split Screen (Up to 4) & Tab System
- User Authentication
- Save Hosts (and easily view, connect, and manage them)
- SSHTerminal Themes
# Planned Features
- VNC
- RDP
- SFTP (build in file transfer)
- ChatGPT/Ollama Integration (for commands)
- Apps (like notes, AI, etc)
- User Management (roles, permissions, etc.)
- Homepage Tunneling
- More Authentication Methods
- More Security Features (like 2FA, etc.)
# Installation
Visit the Termix [Wiki](https://github.com/LukeGus/Termix/wiki) for information on how to install Termix. You can also use these links to go directly to guide. [Docker](https://github.com/LukeGus/Termix/wiki/Docker) or [Manual](https://github.com/LukeGus/Termix/wiki/Manual).
# Support
If you need help with Termix, you can join the [Discord](https://discord.gg/jVQGdvHDrf) server and visit the support channel. You can also open an issue or open a pull request on the [GitHub](https://github.com/LukeGus/Termix/issues) repo. If you would like to support me financially, you can on [Paypal](https://paypal.me/LukeGustafson803).
# Show-off
![Demo Image](../../Termix/repo-images/DemoImage1.png)
![Demo Image](../../Termix/repo-images/DemoImage2.png)
# License
Distributed under the MIT license. See LICENSE for more information.
+21
View File
@@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/index.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
+81
View File
@@ -0,0 +1,81 @@
# Stage 1: Install dependencies and build frontend
FROM node:18-alpine AS deps
WORKDIR /app
# Copy dependency files
COPY package*.json ./
# Install dependencies with caching
RUN npm ci --force && \
npm cache clean --force
# Stage 2: Build frontend
FROM deps AS frontend-builder
WORKDIR /app
# Copy source files
COPY . .
# Build frontend
RUN npm run build
# Stage 3: Production dependencies
FROM node:18-alpine AS production-deps
WORKDIR /app
# Copy only production dependency files
COPY package*.json ./
# Install only production dependencies
RUN npm ci --only=production --ignore-scripts --force && \
npm cache clean --force
# Stage 4: Build native modules
FROM node:18-alpine AS native-builder
WORKDIR /app
# Install build dependencies
RUN apk add --no-cache python3 make g++
# Copy dependency files
COPY package*.json ./
# Install only the native modules we need
RUN npm ci --only=production bcrypt better-sqlite3 --force && \
npm cache clean --force
# Stage 5: Final image
FROM node:18-alpine
ENV DATA_DIR=/app/data \
PORT=8080
# Install dependencies in a single layer
RUN apk add --no-cache nginx gettext su-exec && \
mkdir -p /app/data && \
chown -R node:node /app/data
# Setup nginx and frontend
COPY docker/nginx.conf /etc/nginx/nginx.conf
COPY --from=frontend-builder /app/dist /usr/share/nginx/html
RUN chown -R nginx:nginx /usr/share/nginx/html
# Setup backend
WORKDIR /app
COPY package*.json ./
# Copy production dependencies and native modules
COPY --from=production-deps /app/node_modules /app/node_modules
COPY --from=native-builder /app/node_modules/bcrypt /app/node_modules/bcrypt
COPY --from=native-builder /app/node_modules/better-sqlite3 /app/node_modules/better-sqlite3
# Copy backend source
COPY src/backend/ ./src/backend/
RUN chown -R node:node /app
VOLUME ["/app/data"]
# Expose ports
EXPOSE ${PORT} 8081 8082 8083 8084 8085
COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
CMD ["/entrypoint.sh"]
+17
View File
@@ -0,0 +1,17 @@
services:
termix:
#image: ghcr.io/lukegus/termix:latest
image: ghcr.io/lukegus/termix:dev-0.3-development-latest
container_name: termix
restart: unless-stopped
ports:
- "3800:8080"
volumes:
- termix-data:/app/data
environment:
# Generate random salt here https://www.lastpass.com/features/password-generator (max 32 characters, include all characters for settings)
SALT: "2v.F7!6a!jIzmJsu|[)h61$ZMXs;,i+~"
volumes:
termix-data:
driver: local
+30
View File
@@ -0,0 +1,30 @@
#!/bin/sh
set -e
export PORT=${PORT:-8080}
echo "Configuring web UI to run on port: $PORT"
envsubst '${PORT}' < /etc/nginx/nginx.conf > /etc/nginx/nginx.conf.tmp
mv /etc/nginx/nginx.conf.tmp /etc/nginx/nginx.conf
mkdir -p /app/data
chown -R node:node /app/data
chmod 755 /app/data
echo "Starting nginx..."
nginx
# Start backend services
echo "Starting backend services..."
cd /app
export NODE_ENV=production
if command -v su-exec > /dev/null 2>&1; then
su-exec node node src/backend/starter.cjs
else
su -s /bin/sh node -c "node src/backend/starter.cjs"
fi
echo "All services started"
tail -f /dev/null
+91
View File
@@ -0,0 +1,91 @@
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen ${PORT};
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /database.io/ {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /ssh.io/ {
proxy_pass http://127.0.0.1:8082;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /rdp.io/ {
proxy_pass http://127.0.0.1:8083;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /vnc.io/ {
proxy_pass http://127.0.0.1:8084;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /sftp.io/ {
proxy_pass http://127.0.0.1:8085;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
+53
View File
@@ -0,0 +1,53 @@
name: Deploy VitePress site to Pages
on:
push:
branches: [docs]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: yarn
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Install dependencies
run: yarn install
- name: Build with VitePress
run: yarn run docs:build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: .vitepress/dist
name: github-pages
retention-days: 1
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
needs: build
runs-on: ubuntu-latest
name: Deploy
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+1
View File
@@ -0,0 +1 @@
/node_modules/
+275
View File
@@ -0,0 +1,275 @@
import {
useMediaQuery
} from "./chunk-6F5JWMBQ.js";
import {
computed,
ref,
shallowRef,
watch
} from "./chunk-VJWGEPT5.js";
// node_modules/vitepress/dist/client/theme-default/index.js
import "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/styles/fonts.css";
// node_modules/vitepress/dist/client/theme-default/without-fonts.js
import "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/styles/vars.css";
import "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/styles/base.css";
import "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/styles/icons.css";
import "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/styles/utils.css";
import "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/styles/components/custom-block.css";
import "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code.css";
import "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code-group.css";
import "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/styles/components/vp-doc.css";
import "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/styles/components/vp-sponsor.css";
import VPBadge from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue";
import Layout from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/Layout.vue";
import { default as default2 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue";
import { default as default3 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPButton.vue";
import { default as default4 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPDocAsideSponsors.vue";
import { default as default5 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPFeatures.vue";
import { default as default6 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPHomeContent.vue";
import { default as default7 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPHomeFeatures.vue";
import { default as default8 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPHomeHero.vue";
import { default as default9 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPHomeSponsors.vue";
import { default as default10 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPImage.vue";
import { default as default11 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPLink.vue";
import { default as default12 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPNavBarSearch.vue";
import { default as default13 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPSocialLink.vue";
import { default as default14 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPSocialLinks.vue";
import { default as default15 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPSponsors.vue";
import { default as default16 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPTeamMembers.vue";
import { default as default17 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPTeamPage.vue";
import { default as default18 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageSection.vue";
import { default as default19 } from "C:/Users/Luke/Documents/Personal Projects/Termix/docs/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageTitle.vue";
// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js
import { onContentUpdated } from "vitepress";
// node_modules/vitepress/dist/client/theme-default/composables/outline.js
import { getScrollOffset } from "vitepress";
// node_modules/vitepress/dist/client/theme-default/support/utils.js
import { withBase } from "vitepress";
// node_modules/vitepress/dist/client/theme-default/composables/data.js
import { useData as useData$ } from "vitepress";
var useData = useData$;
// node_modules/vitepress/dist/client/theme-default/support/utils.js
function ensureStartingSlash(path) {
return path.startsWith("/") ? path : `/${path}`;
}
// node_modules/vitepress/dist/client/theme-default/support/sidebar.js
function getSidebar(_sidebar, path) {
if (Array.isArray(_sidebar))
return addBase(_sidebar);
if (_sidebar == null)
return [];
path = ensureStartingSlash(path);
const dir = Object.keys(_sidebar).sort((a, b) => {
return b.split("/").length - a.split("/").length;
}).find((dir2) => {
return path.startsWith(ensureStartingSlash(dir2));
});
const sidebar = dir ? _sidebar[dir] : [];
return Array.isArray(sidebar) ? addBase(sidebar) : addBase(sidebar.items, sidebar.base);
}
function getSidebarGroups(sidebar) {
const groups = [];
let lastGroupIndex = 0;
for (const index in sidebar) {
const item = sidebar[index];
if (item.items) {
lastGroupIndex = groups.push(item);
continue;
}
if (!groups[lastGroupIndex]) {
groups.push({ items: [] });
}
groups[lastGroupIndex].items.push(item);
}
return groups;
}
function addBase(items, _base) {
return [...items].map((_item) => {
const item = { ..._item };
const base = item.base || _base;
if (base && item.link)
item.link = base + item.link;
if (item.items)
item.items = addBase(item.items, base);
return item;
});
}
// node_modules/vitepress/dist/client/theme-default/composables/sidebar.js
function useSidebar() {
const { frontmatter, page, theme: theme2 } = useData();
const is960 = useMediaQuery("(min-width: 960px)");
const isOpen = ref(false);
const _sidebar = computed(() => {
const sidebarConfig = theme2.value.sidebar;
const relativePath = page.value.relativePath;
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : [];
});
const sidebar = ref(_sidebar.value);
watch(_sidebar, (next, prev) => {
if (JSON.stringify(next) !== JSON.stringify(prev))
sidebar.value = _sidebar.value;
});
const hasSidebar = computed(() => {
return frontmatter.value.sidebar !== false && sidebar.value.length > 0 && frontmatter.value.layout !== "home";
});
const leftAside = computed(() => {
if (hasAside)
return frontmatter.value.aside == null ? theme2.value.aside === "left" : frontmatter.value.aside === "left";
return false;
});
const hasAside = computed(() => {
if (frontmatter.value.layout === "home")
return false;
if (frontmatter.value.aside != null)
return !!frontmatter.value.aside;
return theme2.value.aside !== false;
});
const isSidebarEnabled = computed(() => hasSidebar.value && is960.value);
const sidebarGroups = computed(() => {
return hasSidebar.value ? getSidebarGroups(sidebar.value) : [];
});
function open() {
isOpen.value = true;
}
function close() {
isOpen.value = false;
}
function toggle() {
isOpen.value ? close() : open();
}
return {
isOpen,
sidebar,
sidebarGroups,
hasSidebar,
hasAside,
leftAside,
isSidebarEnabled,
open,
close,
toggle
};
}
// node_modules/vitepress/dist/client/theme-default/composables/outline.js
var ignoreRE = /\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/;
var resolvedHeaders = [];
function getHeaders(range) {
const headers = [
...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")
].filter((el) => el.id && el.hasChildNodes()).map((el) => {
const level = Number(el.tagName[1]);
return {
element: el,
title: serializeHeader(el),
link: "#" + el.id,
level
};
});
return resolveHeaders(headers, range);
}
function serializeHeader(h) {
let ret = "";
for (const node of h.childNodes) {
if (node.nodeType === 1) {
if (ignoreRE.test(node.className))
continue;
ret += node.textContent;
} else if (node.nodeType === 3) {
ret += node.textContent;
}
}
return ret.trim();
}
function resolveHeaders(headers, range) {
if (range === false) {
return [];
}
const levelsRange = (typeof range === "object" && !Array.isArray(range) ? range.level : range) || 2;
const [high, low] = typeof levelsRange === "number" ? [levelsRange, levelsRange] : levelsRange === "deep" ? [2, 6] : levelsRange;
return buildTree(headers, high, low);
}
function buildTree(data, min, max) {
resolvedHeaders.length = 0;
const result = [];
const stack = [];
data.forEach((item) => {
const node = { ...item, children: [] };
let parent = stack[stack.length - 1];
while (parent && parent.level >= node.level) {
stack.pop();
parent = stack[stack.length - 1];
}
if (node.element.classList.contains("ignore-header") || parent && "shouldIgnore" in parent) {
stack.push({ level: node.level, shouldIgnore: true });
return;
}
if (node.level > max || node.level < min)
return;
resolvedHeaders.push({ element: node.element, link: node.link });
if (parent)
parent.children.push(node);
else
result.push(node);
stack.push(node);
});
return result;
}
// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js
function useLocalNav() {
const { theme: theme2, frontmatter } = useData();
const headers = shallowRef([]);
const hasLocalNav = computed(() => {
return headers.value.length > 0;
});
onContentUpdated(() => {
headers.value = getHeaders(frontmatter.value.outline ?? theme2.value.outline);
});
return {
headers,
hasLocalNav
};
}
// node_modules/vitepress/dist/client/theme-default/without-fonts.js
var theme = {
Layout,
enhanceApp: ({ app }) => {
app.component("Badge", VPBadge);
}
};
var without_fonts_default = theme;
export {
default2 as VPBadge,
default3 as VPButton,
default4 as VPDocAsideSponsors,
default5 as VPFeatures,
default6 as VPHomeContent,
default7 as VPHomeFeatures,
default8 as VPHomeHero,
default9 as VPHomeSponsors,
default10 as VPImage,
default11 as VPLink,
default12 as VPNavBarSearch,
default13 as VPSocialLink,
default14 as VPSocialLinks,
default15 as VPSponsors,
default16 as VPTeamMembers,
default17 as VPTeamPage,
default18 as VPTeamPageSection,
default19 as VPTeamPageTitle,
without_fonts_default as default,
useLocalNav,
useSidebar
};
//# sourceMappingURL=@theme_index.js.map
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../../node_modules/vitepress/dist/client/theme-default/index.js", "../../../node_modules/vitepress/dist/client/theme-default/without-fonts.js", "../../../node_modules/vitepress/dist/client/theme-default/composables/local-nav.js", "../../../node_modules/vitepress/dist/client/theme-default/composables/outline.js", "../../../node_modules/vitepress/dist/client/theme-default/support/utils.js", "../../../node_modules/vitepress/dist/client/theme-default/composables/data.js", "../../../node_modules/vitepress/dist/client/theme-default/support/sidebar.js", "../../../node_modules/vitepress/dist/client/theme-default/composables/sidebar.js"],
"sourcesContent": ["import './styles/fonts.css';\nexport * from './without-fonts';\nexport { default as default } from './without-fonts';\n", "import './styles/vars.css';\nimport './styles/base.css';\nimport './styles/icons.css';\nimport './styles/utils.css';\nimport './styles/components/custom-block.css';\nimport './styles/components/vp-code.css';\nimport './styles/components/vp-code-group.css';\nimport './styles/components/vp-doc.css';\nimport './styles/components/vp-sponsor.css';\nimport VPBadge from './components/VPBadge.vue';\nimport Layout from './Layout.vue';\nexport { default as VPBadge } from './components/VPBadge.vue';\nexport { default as VPButton } from './components/VPButton.vue';\nexport { default as VPDocAsideSponsors } from './components/VPDocAsideSponsors.vue';\nexport { default as VPFeatures } from './components/VPFeatures.vue';\nexport { default as VPHomeContent } from './components/VPHomeContent.vue';\nexport { default as VPHomeFeatures } from './components/VPHomeFeatures.vue';\nexport { default as VPHomeHero } from './components/VPHomeHero.vue';\nexport { default as VPHomeSponsors } from './components/VPHomeSponsors.vue';\nexport { default as VPImage } from './components/VPImage.vue';\nexport { default as VPLink } from './components/VPLink.vue';\nexport { default as VPNavBarSearch } from './components/VPNavBarSearch.vue';\nexport { default as VPSocialLink } from './components/VPSocialLink.vue';\nexport { default as VPSocialLinks } from './components/VPSocialLinks.vue';\nexport { default as VPSponsors } from './components/VPSponsors.vue';\nexport { default as VPTeamMembers } from './components/VPTeamMembers.vue';\nexport { default as VPTeamPage } from './components/VPTeamPage.vue';\nexport { default as VPTeamPageSection } from './components/VPTeamPageSection.vue';\nexport { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue';\nexport { useLocalNav } from './composables/local-nav';\nexport { useSidebar } from './composables/sidebar';\nconst theme = {\n Layout,\n enhanceApp: ({ app }) => {\n app.component('Badge', VPBadge);\n }\n};\nexport default theme;\n", "import { onContentUpdated } from 'vitepress';\nimport { computed, shallowRef } from 'vue';\nimport { getHeaders } from '../composables/outline';\nimport { useData } from './data';\nexport function useLocalNav() {\n const { theme, frontmatter } = useData();\n const headers = shallowRef([]);\n const hasLocalNav = computed(() => {\n return headers.value.length > 0;\n });\n onContentUpdated(() => {\n headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline);\n });\n return {\n headers,\n hasLocalNav\n };\n}\n", "import { getScrollOffset } from 'vitepress';\nimport { onMounted, onUnmounted, onUpdated } from 'vue';\nimport { throttleAndDebounce } from '../support/utils';\nimport { useAside } from './aside';\nconst ignoreRE = /\\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\\b/;\n// cached list of anchor elements from resolveHeaders\nconst resolvedHeaders = [];\nexport function resolveTitle(theme) {\n return ((typeof theme.outline === 'object' &&\n !Array.isArray(theme.outline) &&\n theme.outline.label) ||\n theme.outlineTitle ||\n 'On this page');\n}\nexport function getHeaders(range) {\n const headers = [\n ...document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)')\n ]\n .filter((el) => el.id && el.hasChildNodes())\n .map((el) => {\n const level = Number(el.tagName[1]);\n return {\n element: el,\n title: serializeHeader(el),\n link: '#' + el.id,\n level\n };\n });\n return resolveHeaders(headers, range);\n}\nfunction serializeHeader(h) {\n let ret = '';\n for (const node of h.childNodes) {\n if (node.nodeType === 1) {\n if (ignoreRE.test(node.className))\n continue;\n ret += node.textContent;\n }\n else if (node.nodeType === 3) {\n ret += node.textContent;\n }\n }\n return ret.trim();\n}\nexport function resolveHeaders(headers, range) {\n if (range === false) {\n return [];\n }\n const levelsRange = (typeof range === 'object' && !Array.isArray(range)\n ? range.level\n : range) || 2;\n const [high, low] = typeof levelsRange === 'number'\n ? [levelsRange, levelsRange]\n : levelsRange === 'deep'\n ? [2, 6]\n : levelsRange;\n return buildTree(headers, high, low);\n}\nexport function useActiveAnchor(container, marker) {\n const { isAsideEnabled } = useAside();\n const onScroll = throttleAndDebounce(setActiveLink, 100);\n let prevActiveLink = null;\n onMounted(() => {\n requestAnimationFrame(setActiveLink);\n window.addEventListener('scroll', onScroll);\n });\n onUpdated(() => {\n // sidebar update means Line truncated
"mappings": "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",
"names": ["default", "dir", "theme", "theme"]
}
+58
View File
@@ -0,0 +1,58 @@
{
"hash": "44a0f075",
"configHash": "41819f4d",
"lockfileHash": "db040343",
"browserHash": "3d4b0518",
"optimized": {
"vue": {
"src": "../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
"file": "vue.js",
"fileHash": "b9adcfb0",
"needsInterop": false
},
"vitepress > @vue/devtools-api": {
"src": "../../../node_modules/@vue/devtools-api/dist/index.js",
"file": "vitepress___@vue_devtools-api.js",
"fileHash": "54f476e8",
"needsInterop": false
},
"vitepress > @vueuse/core": {
"src": "../../../node_modules/@vueuse/core/index.mjs",
"file": "vitepress___@vueuse_core.js",
"fileHash": "9e36f6ef",
"needsInterop": false
},
"vitepress > @vueuse/integrations/useFocusTrap": {
"src": "../../../node_modules/@vueuse/integrations/useFocusTrap.mjs",
"file": "vitepress___@vueuse_integrations_useFocusTrap.js",
"fileHash": "a04cdc76",
"needsInterop": false
},
"vitepress > mark.js/src/vanilla.js": {
"src": "../../../node_modules/mark.js/src/vanilla.js",
"file": "vitepress___mark__js_src_vanilla__js.js",
"fileHash": "0d42ca90",
"needsInterop": false
},
"vitepress > minisearch": {
"src": "../../../node_modules/minisearch/dist/es/index.js",
"file": "vitepress___minisearch.js",
"fileHash": "42d278a1",
"needsInterop": false
},
"@theme/index": {
"src": "../../../node_modules/vitepress/dist/client/theme-default/index.js",
"file": "@theme_index.js",
"fileHash": "fb8354da",
"needsInterop": false
}
},
"chunks": {
"chunk-6F5JWMBQ": {
"file": "chunk-6F5JWMBQ.js"
},
"chunk-VJWGEPT5": {
"file": "chunk-VJWGEPT5.js"
}
}
}
File diff suppressed because it is too large. Load diff
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../../node_modules/@vueuse/shared/index.mjs", "../../../node_modules/@vueuse/core/index.mjs"],
"sourcesContent": ["import { shallowRef, watchEffect, readonly, watch, customRef, getCurrentScope, onScopeDispose, effectScope, getCurrentInstance, hasInjectionContext, inject, provide, ref, isRef, unref, toValue as toValue$1, computed, reactive, toRefs as toRefs$1, toRef as toRef$1, onBeforeMount, nextTick, onBeforeUnmount, onMounted, onUnmounted, isReactive } from 'vue';\n\nfunction computedEager(fn, options) {\n var _a;\n const result = shallowRef();\n watchEffect(() => {\n result.value = fn();\n }, {\n ...options,\n flush: (_a = options == null ? void 0 : options.flush) != null ? _a : \"sync\"\n });\n return readonly(result);\n}\n\nfunction computedWithControl(source, fn) {\n let v = void 0;\n let track;\n let trigger;\n const dirty = shallowRef(true);\n const update = () => {\n dirty.value = true;\n trigger();\n };\n watch(source, update, { flush: \"sync\" });\n const get = typeof fn === \"function\" ? fn : fn.get;\n const set = typeof fn === \"function\" ? void 0 : fn.set;\n const result = customRef((_track, _trigger) => {\n track = _track;\n trigger = _trigger;\n return {\n get() {\n if (dirty.value) {\n v = get(v);\n dirty.value = false;\n }\n track();\n return v;\n },\n set(v2) {\n set == null ? void 0 : set(v2);\n }\n };\n });\n if (Object.isExtensible(result))\n result.trigger = update;\n return result;\n}\n\nfunction tryOnScopeDispose(fn) {\n if (getCurrentScope()) {\n onScopeDispose(fn);\n return true;\n }\n return false;\n}\n\nfunction createEventHook() {\n const fns = /* @__PURE__ */ new Set();\n const off = (fn) => {\n fns.delete(fn);\n };\n const clear = () => {\n fns.clear();\n };\n const on = (fn) => {\n fns.add(fn);\n const offFn = () => off(fn);\n tryOnScopeDispose(offFn);\n return {\n off: offFn\n };\n };\n const trigger = (...args) => {\n return Promise.all(Array.from(fns).map((fn) => fn(...args)));\n };\n return {\n on,\n off,\n trigger,\n clear\n };\n}\n\nfunction createGlobalState(stateFactory) {\n let initialized = false;\n let state;\n const scope = effectScope(true);\n return (...args) => {\n if (!initialized) {\n state = scope.run(() => stateFactory(...args));\n initialized = true;\n }\n return state;\n };\n}\n\nconst localProvidedStateMap = /* @__PURE__ */ new WeakMap();\n\nconst injectLocal = (...args) => {\n var _a;\n const key = args[0];\n const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy;\n if (instance == null && !hasInjectionContext())\n throw new Error(\"injectLocal must be called in setup\");\n if (instance && localProvidedStateMap.has(instance) && key in localProvidedStateMap.get(instance))\n return localProvidedStateMap.get(instance)[key];\n return inject(...args);\n};\n\nconst provideLocal = (key, value) => {\n var _a;\n const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy;\n if (instance == null)\n throw new Error(\"provideLocal must be called in setup\");\n if (!localProvidedStateMap.has(instance))\n localProvidedStateMap.set(instance, /* @__PURE__ */ Object.create(null));\n const localProvidedState = localProvidedStateMap.get(instance);\n localProvidedState[key] = value;\n provide(key, value);\n};\n\nfunction createInjectionState(composable, options) {\n const key = (options == null ? void 0 : options.injectionKey) || Symbol(composable.name || \"InjectionState\");\n const defaultValue = options == null ? void 0 : options.defaultValue;\n const useProvidingState = (...args) => {\n const state = composable(...args);\n provideLocal(key, state);\n return state;\n };\n const useInjectedState = () => injectLocal(key, defaultValue);\n return [useProvidingState, useInjectedState];\n}\n\nfunction createRef(value, deep) {\n if (deep === true) {\n return ref(value);\n } else {\n return shallowRef(value);\n }\n}\n\nfunction createSharedComposable(composable) {\n let subscribers = 0;\n let state;\n let scope;\n const dispose = () => {\n subscribers -= 1;\n if (scope && subscribers <= 0) {\n scope.stop();\n state = void 0;\n scope = void 0;\n }\n };\n return (...args) => {\n subscribers += 1;\n if (!scope) {\n scope = effectScope(true);\n state = scope.run(() => composable(...args));\n }\n tryOnScopeDispose(dispose);\n return state;\n };\n}\n\nfunction extendRef(ref, extend, { enumerable = false, unwrap = true } = {}) {\n for (const [key, value] of Object.entries(extend)) {\n if (key === \"value\")\n continue;\n if (isRef(value) && unwrap) {\n Object.defineProperty(ref, key, {\n get() {\n return value.value;\n },\n set(v) {\n value.value = v;\n },\n enumerable\n });\n } else {\n Object.defineProperty(ref, key, { value, enumerable });\n }\n }Line truncated
"mappings": "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 truncated
"names": ["get", "set", "ref", "keys", "invoke", "toRef", "toRefs", "toValue", "window", "document", "timestamp", "navigator", "events", "getValue", "ref", "defaults", "toRef", "set", "onUpdated", "preventDefault", "toRefs", "now", "keys", "get", "isReadonly"]
}
File diff suppressed because it is too large. Load diff
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../../node_modules/@vue/shared/dist/shared.esm-bundler.js", "../../../node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js", "../../../node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js", "../../../node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js", "../../../node_modules/vue/dist/vue.runtime.esm-bundler.js"],
"sourcesContent": ["/**\n* @vue/shared v3.5.13\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/\n/*! #__NO_SIDE_EFFECTS__ */\n// @__NO_SIDE_EFFECTS__\nfunction makeMap(str) {\n const map = /* @__PURE__ */ Object.create(null);\n for (const key of str.split(\",\")) map[key] = 1;\n return (val) => val in map;\n}\n\nconst EMPTY_OBJ = !!(process.env.NODE_ENV !== \"production\") ? Object.freeze({}) : {};\nconst EMPTY_ARR = !!(process.env.NODE_ENV !== \"production\") ? Object.freeze([]) : [];\nconst NOOP = () => {\n};\nconst NO = () => false;\nconst isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter\n(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97);\nconst isModelListener = (key) => key.startsWith(\"onUpdate:\");\nconst extend = Object.assign;\nconst remove = (arr, el) => {\n const i = arr.indexOf(el);\n if (i > -1) {\n arr.splice(i, 1);\n }\n};\nconst hasOwnProperty = Object.prototype.hasOwnProperty;\nconst hasOwn = (val, key) => hasOwnProperty.call(val, key);\nconst isArray = Array.isArray;\nconst isMap = (val) => toTypeString(val) === \"[object Map]\";\nconst isSet = (val) => toTypeString(val) === \"[object Set]\";\nconst isDate = (val) => toTypeString(val) === \"[object Date]\";\nconst isRegExp = (val) => toTypeString(val) === \"[object RegExp]\";\nconst isFunction = (val) => typeof val === \"function\";\nconst isString = (val) => typeof val === \"string\";\nconst isSymbol = (val) => typeof val === \"symbol\";\nconst isObject = (val) => val !== null && typeof val === \"object\";\nconst isPromise = (val) => {\n return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch);\n};\nconst objectToString = Object.prototype.toString;\nconst toTypeString = (value) => objectToString.call(value);\nconst toRawType = (value) => {\n return toTypeString(value).slice(8, -1);\n};\nconst isPlainObject = (val) => toTypeString(val) === \"[object Object]\";\nconst isIntegerKey = (key) => isString(key) && key !== \"NaN\" && key[0] !== \"-\" && \"\" + parseInt(key, 10) === key;\nconst isReservedProp = /* @__PURE__ */ makeMap(\n // the leading comma is intentional so empty string \"\" is also included\n \",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted\"\n);\nconst isBuiltInDirective = /* @__PURE__ */ makeMap(\n \"bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo\"\n);\nconst cacheStringFunction = (fn) => {\n const cache = /* @__PURE__ */ Object.create(null);\n return (str) => {\n const hit = cache[str];\n return hit || (cache[str] = fn(str));\n };\n};\nconst camelizeRE = /-(\\w)/g;\nconst camelize = cacheStringFunction(\n (str) => {\n return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : \"\");\n }\n);\nconst hyphenateRE = /\\B([A-Z])/g;\nconst hyphenate = cacheStringFunction(\n (str) => str.replace(hyphenateRE, \"-$1\").toLowerCase()\n);\nconst capitalize = cacheStringFunction((str) => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n});\nconst toHandlerKey = cacheStringFunction(\n (str) => {\n const s = str ? `on${capitalize(str)}` : ``;\n return s;\n }\n);\nconst hasChanged = (value, oldValue) => !Object.is(value, oldValue);\nconst invokeArrayFns = (fns, ...arg) => {\n for (let i = 0; i < fns.length; i++) {\n fns[i](...arg);\n }\n};\nconst def = (obj, key, value, writable = false) => {\n Object.defineProperty(obj, key, {\n configurable: true,\n enumerable: false,\n writable,\n value\n });\n};\nconst looseToNumber = (val) => {\n const n = parseFloat(val);\n return isNaN(n) ? val : n;\n};\nconst toNumber = (val) => {\n const n = isString(val) ? Number(val) : NaN;\n return isNaN(n) ? val : n;\n};\nlet _globalThis;\nconst getGlobalThis = () => {\n return _globalThis || (_globalThis = typeof globalThis !== \"undefined\" ? globalThis : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : typeof global !== \"undefined\" ? global : {});\n};\nconst identRE = /^[_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*$/;\nfunction genPropsAccessExp(name) {\n return identRE.test(name) ? `__props.${name}` : `__props[${JSON.stringify(name)}]`;\n}\nfunction genCacheKey(source, options) {\n return source + JSON.stringify(\n options,\n (_, val) => typeof val === \"function\" ? val.toString() : val\n );\n}\n\nconst PatchFlags = {\n \"TEXT\": 1,\n \"1\": \"TEXT\",\n \"CLASS\": 2,\n \"2\": \"CLASS\",\n \"STYLE\": 4,\n \"4\": \"STYLE\",\n \"PROPS\": 8,\n \"8\": \"PROPS\",\n \"FULL_PROPS\": 16,\n \"16\": \"FULL_PROPS\",\n \"NEED_HYDRATION\": 32,\n \"32\": \"NEED_HYDRATION\",\n \"STABLE_FRAGMENT\": 64,\n \"64\": \"STABLE_FRAGMENT\",\n \"KEYED_FRAGMENT\": 128,\n \"128\": \"KEYED_FRAGMENT\",\n \"UNKEYED_FRAGMENT\": 256,\n \"256\": \"UNKEYED_FRAGMENT\",\n \"NEED_PATCH\": 512,\n \"512\": \"NEED_PATCH\",\n \"DYNAMIC_SLine truncated
"mappings": "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 truncated
"names": ["map", "computed", "computed", "self", "hasOwnProperty", "isRef", "readonly", "effect", "isRef", "isRef", "p", "version", "callHook", "remove", "ref", "patchProp", "hydrate", "hasWarned", "resolve", "watch", "render", "computed", "h", "createApp", "effect", "remove2", "track", "trigger", "isModelListener", "emit", "render2", "warn", "warn", "callHook", "resolve", "watch", "isBoolean", "def", "enterCbKey", "compile", "warn"]
}
+3
View File
@@ -0,0 +1,3 @@
{
"type": "module"
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../../node_modules/@vue/devtools-shared/dist/index.js", "../../../node_modules/perfect-debounce/dist/index.mjs", "../../../node_modules/hookable/dist/index.mjs", "../../../node_modules/birpc/dist/index.mjs", "../../../node_modules/@vue/devtools-kit/dist/index.js"],
"sourcesContent": ["var __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __esm = (fn, res) => function __init() {\n return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;\n};\nvar __commonJS = (cb, mod) => function __require() {\n return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target2) => (target2 = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target2, \"default\", { value: mod, enumerable: true }) : target2,\n mod\n));\n\n// ../../node_modules/.pnpm/[email protected]_@[email protected]_@[email protected][email protected][email protected]_96eb05a9d65343021e53791dd83f3773/node_modules/tsup/assets/esm_shims.js\nvar init_esm_shims = __esm({\n \"../../node_modules/.pnpm/[email protected]_@[email protected]_@[email protected][email protected][email protected]_96eb05a9d65343021e53791dd83f3773/node_modules/tsup/assets/esm_shims.js\"() {\n \"use strict\";\n }\n});\n\n// ../../node_modules/.pnpm/[email protected]/node_modules/rfdc/index.js\nvar require_rfdc = __commonJS({\n \"../../node_modules/.pnpm/[email protected]/node_modules/rfdc/index.js\"(exports, module) {\n \"use strict\";\n init_esm_shims();\n module.exports = rfdc2;\n function copyBuffer(cur) {\n if (cur instanceof Buffer) {\n return Buffer.from(cur);\n }\n return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length);\n }\n function rfdc2(opts) {\n opts = opts || {};\n if (opts.circles) return rfdcCircles(opts);\n const constructorHandlers = /* @__PURE__ */ new Map();\n constructorHandlers.set(Date, (o) => new Date(o));\n constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)));\n constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)));\n if (opts.constructorHandlers) {\n for (const handler2 of opts.constructorHandlers) {\n constructorHandlers.set(handler2[0], handler2[1]);\n }\n }\n let handler = null;\n return opts.proto ? cloneProto : clone;\n function cloneArray(a, fn) {\n const keys = Object.keys(a);\n const a2 = new Array(keys.length);\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i];\n const cur = a[k];\n if (typeof cur !== \"object\" || cur === null) {\n a2[k] = cur;\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn);\n } else if (ArrayBuffer.isView(cur)) {\n a2[k] = copyBuffer(cur);\n } else {\n a2[k] = fn(cur);\n }\n }\n return a2;\n }\n function clone(o) {\n if (typeof o !== \"object\" || o === null) return o;\n if (Array.isArray(o)) return cloneArray(o, clone);\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, clone);\n }\n const o2 = {};\n for (const k in o) {\n if (Object.hasOwnProperty.call(o, k) === false) continue;\n const cur = o[k];\n if (typeof cur !== \"object\" || cur === null) {\n o2[k] = cur;\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone);\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur);\n } else {\n o2[k] = clone(cur);\n }\n }\n return o2;\n }\n function cloneProto(o) {\n if (typeof o !== \"object\" || o === null) return o;\n if (Array.isArray(o)) return cloneArray(o, cloneProto);\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, cloneProto);\n }\n const o2 = {};\n for (const k in o) {\n const cur = o[k];\n if (tLine truncated
"mappings": "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 truncated
"names": ["hooks", "hooks", "hook", "hook", "hooks", "clearTimeout", "setTimeout", "__create", "__defProp", "__getOwnPropDesc", "__getOwnPropNames", "__getProtoOf", "__hasOwnProp", "__esm", "__commonJS", "__copyProps", "__toESM", "init_esm_shims", "init_esm_shims", "init_esm_shims", "_a", "init_esm_shims", "init_esm_shims", "init_esm_shims", "_a2", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "__toESM", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "init_esm_shims", "_a22", "init_esm_shims", "init_esm_shims"]
}
+583
View File
@@ -0,0 +1,583 @@
import {
DefaultMagicKeysAliasMap,
StorageSerializers,
TransitionPresets,
assert,
breakpointsAntDesign,
breakpointsBootstrapV5,
breakpointsElement,
breakpointsMasterCss,
breakpointsPrimeFlex,
breakpointsQuasar,
breakpointsSematic,
breakpointsTailwind,
breakpointsVuetify,
breakpointsVuetifyV2,
breakpointsVuetifyV3,
bypassFilter,
camelize,
clamp,
cloneFnJSON,
computedAsync,
computedEager,
computedInject,
computedWithControl,
containsProp,
controlledRef,
createEventHook,
createFetch,
createFilterWrapper,
createGlobalState,
createInjectionState,
createRef,
createReusableTemplate,
createSharedComposable,
createSingletonPromise,
createTemplatePromise,
createUnrefFn,
customStorageEventName,
debounceFilter,
defaultDocument,
defaultLocation,
defaultNavigator,
defaultWindow,
executeTransition,
extendRef,
formatDate,
formatTimeAgo,
get,
getLifeCycleTarget,
getSSRHandler,
hasOwn,
hyphenate,
identity,
increaseWithUnit,
injectLocal,
invoke,
isClient,
isDef,
isDefined,
isIOS,
isObject,
isWorker,
makeDestructurable,
mapGamepadToXbox360Controller,
noop,
normalizeDate,
notNullish,
now,
objectEntries,
objectOmit,
objectPick,
onClickOutside,
onElementRemoval,
onKeyDown,
onKeyPressed,
onKeyStroke,
onKeyUp,
onLongPress,
onStartTyping,
pausableFilter,
promiseTimeout,
provideLocal,
provideSSRWidth,
pxValue,
rand,
reactify,
reactifyObject,
reactiveComputed,
reactiveOmit,
reactivePick,
refAutoReset,
refDebounced,
refDefault,
refThrottled,
refWithControl,
resolveRef,
resolveUnref,
set,
setSSRHandler,
syncRef,
syncRefs,
templateRef,
throttleFilter,
timestamp,
toArray,
toReactive,
toRef,
toRefs,
toValue,
tryOnBeforeMount,
tryOnBeforeUnmount,
tryOnMounted,
tryOnScopeDispose,
tryOnUnmounted,
unrefElement,
until,
useActiveElement,
useAnimate,
useArrayDifference,
useArrayEvery,
useArrayFilter,
useArrayFind,
useArrayFindIndex,
useArrayFindLast,
useArrayIncludes,
useArrayJoin,
useArrayMap,
useArrayReduce,
useArraySome,
useArrayUnique,
useAsyncQueue,
useAsyncState,
useBase64,
useBattery,
useBluetooth,
useBreakpoints,
useBroadcastChannel,
useBrowserLocation,
useCached,
useClipboard,
useClipboardItems,
useCloned,
useColorMode,
useConfirmDialog,
useCountdown,
useCounter,
useCssVar,
useCurrentElement,
useCycleList,
useDark,
useDateFormat,
useDebounceFn,
useDebouncedRefHistory,
useDeviceMotion,
useDeviceOrientation,
useDevicePixelRatio,
useDevicesList,
useDisplayMedia,
useDocumentVisibility,
useDraggable,
useDropZone,
useElementBounding,
useElementByPoint,
useElementHover,
useElementSize,
useElementVisibility,
useEventBus,
useEventListener,
useEventSource,
useEyeDropper,
useFavicon,
useFetch,
useFileDialog,
useFileSystemAccess,
useFocus,
useFocusWithin,
useFps,
useFullscreen,
useGamepad,
useGeolocation,
useIdle,
useImage,
useInfiniteScroll,
useIntersectionObserver,
useInterval,
useIntervalFn,
useKeyModifier,
useLastChanged,
useLocalStorage,
useMagicKeys,
useManualRefHistory,
useMediaControls,
useMediaQuery,
useMemoize,
useMemory,
useMounted,
useMouse,
useMouseInElement,
useMousePressed,
useMutationObserver,
useNavigatorLanguage,
useNetwork,
useNow,
useObjectUrl,
useOffsetPagination,
useOnline,
usePageLeave,
useParallax,
useParentElement,
usePerformanceObserver,
usePermission,
usePointer,
usePointerLock,
usePointerSwipe,
usePreferredColorScheme,
usePreferredContrast,
usePreferredDark,
usePreferredLanguages,
usePreferredReducedMotion,
usePreferredReducedTransparency,
usePrevious,
useRafFn,
useRefHistory,
useResizeObserver,
useSSRWidth,
useScreenOrientation,
useScreenSafeArea,
useScriptTag,
useScroll,
useScrollLock,
useSessionStorage,
useShare,
useSorted,
useSpeechRecognition,
useSpeechSynthesis,
useStepper,
useStorage,
useStorageAsync,
useStyleTag,
useSupported,
useSwipe,
useTemplateRefsList,
useTextDirection,
useTextSelection,
useTextareaAutosize,
useThrottleFn,
useThrottledRefHistory,
useTimeAgo,
useTimeout,
useTimeoutFn,
useTimeoutPoll,
useTimestamp,
useTitle,
useToNumber,
useToString,
useToggle,
useTransition,
useUrlSearchParams,
useUserMedia,
useVModel,
useVModels,
useVibrate,
useVirtualList,
useWakeLock,
useWebNotification,
useWebSocket,
useWebWorker,
useWebWorkerFn,
useWindowFocus,
useWindowScroll,
useWindowSize,
watchArray,
watchAtMost,
watchDebounced,
watchDeep,
watchIgnorable,
watchImmediate,
watchOnce,
watchPausable,
watchThrottled,
watchTriggerable,
watchWithFilter,
whenever
} from "./chunk-6F5JWMBQ.js";
import "./chunk-VJWGEPT5.js";
export {
DefaultMagicKeysAliasMap,
StorageSerializers,
TransitionPresets,
assert,
computedAsync as asyncComputed,
refAutoReset as autoResetRef,
breakpointsAntDesign,
breakpointsBootstrapV5,
breakpointsElement,
breakpointsMasterCss,
breakpointsPrimeFlex,
breakpointsQuasar,
breakpointsSematic,
breakpointsTailwind,
breakpointsVuetify,
breakpointsVuetifyV2,
breakpointsVuetifyV3,
bypassFilter,
camelize,
clamp,
cloneFnJSON,
computedAsync,
computedEager,
computedInject,
computedWithControl,
containsProp,
computedWithControl as controlledComputed,
controlledRef,
createEventHook,
createFetch,
createFilterWrapper,
createGlobalState,
createInjectionState,
reactify as createReactiveFn,
createRef,
createReusableTemplate,
createSharedComposable,
createSingletonPromise,
createTemplatePromise,
createUnrefFn,
customStorageEventName,
debounceFilter,
refDebounced as debouncedRef,
watchDebounced as debouncedWatch,
defaultDocument,
defaultLocation,
defaultNavigator,
defaultWindow,
computedEager as eagerComputed,
executeTransition,
extendRef,
formatDate,
formatTimeAgo,
get,
getLifeCycleTarget,
getSSRHandler,
hasOwn,
hyphenate,
identity,
watchIgnorable as ignorableWatch,
increaseWithUnit,
injectLocal,
invoke,
isClient,
isDef,
isDefined,
isIOS,
isObject,
isWorker,
makeDestructurable,
mapGamepadToXbox360Controller,
noop,
normalizeDate,
notNullish,
now,
objectEntries,
objectOmit,
objectPick,
onClickOutside,
onElementRemoval,
onKeyDown,
onKeyPressed,
onKeyStroke,
onKeyUp,
onLongPress,
onStartTyping,
pausableFilter,
watchPausable as pausableWatch,
promiseTimeout,
provideLocal,
provideSSRWidth,
pxValue,
rand,
reactify,
reactifyObject,
reactiveComputed,
reactiveOmit,
reactivePick,
refAutoReset,
refDebounced,
refDefault,
refThrottled,
refWithControl,
resolveRef,
resolveUnref,
set,
setSSRHandler,
syncRef,
syncRefs,
templateRef,
throttleFilter,
refThrottled as throttledRef,
watchThrottled as throttledWatch,
timestamp,
toArray,
toReactive,
toRef,
toRefs,
toValue,
tryOnBeforeMount,
tryOnBeforeUnmount,
tryOnMounted,
tryOnScopeDispose,
tryOnUnmounted,
unrefElement,
until,
useActiveElement,
useAnimate,
useArrayDifference,
useArrayEvery,
useArrayFilter,
useArrayFind,
useArrayFindIndex,
useArrayFindLast,
useArrayIncludes,
useArrayJoin,
useArrayMap,
useArrayReduce,
useArraySome,
useArrayUnique,
useAsyncQueue,
useAsyncState,
useBase64,
useBattery,
useBluetooth,
useBreakpoints,
useBroadcastChannel,
useBrowserLocation,
useCached,
useClipboard,
useClipboardItems,
useCloned,
useColorMode,
useConfirmDialog,
useCountdown,
useCounter,
useCssVar,
useCurrentElement,
useCycleList,
useDark,
useDateFormat,
refDebounced as useDebounce,
useDebounceFn,
useDebouncedRefHistory,
useDeviceMotion,
useDeviceOrientation,
useDevicePixelRatio,
useDevicesList,
useDisplayMedia,
useDocumentVisibility,
useDraggable,
useDropZone,
useElementBounding,
useElementByPoint,
useElementHover,
useElementSize,
useElementVisibility,
useEventBus,
useEventListener,
useEventSource,
useEyeDropper,
useFavicon,
useFetch,
useFileDialog,
useFileSystemAccess,
useFocus,
useFocusWithin,
useFps,
useFullscreen,
useGamepad,
useGeolocation,
useIdle,
useImage,
useInfiniteScroll,
useIntersectionObserver,
useInterval,
useIntervalFn,
useKeyModifier,
useLastChanged,
useLocalStorage,
useMagicKeys,
useManualRefHistory,
useMediaControls,
useMediaQuery,
useMemoize,
useMemory,
useMounted,
useMouse,
useMouseInElement,
useMousePressed,
useMutationObserver,
useNavigatorLanguage,
useNetwork,
useNow,
useObjectUrl,
useOffsetPagination,
useOnline,
usePageLeave,
useParallax,
useParentElement,
usePerformanceObserver,
usePermission,
usePointer,
usePointerLock,
usePointerSwipe,
usePreferredColorScheme,
usePreferredContrast,
usePreferredDark,
usePreferredLanguages,
usePreferredReducedMotion,
usePreferredReducedTransparency,
usePrevious,
useRafFn,
useRefHistory,
useResizeObserver,
useSSRWidth,
useScreenOrientation,
useScreenSafeArea,
useScriptTag,
useScroll,
useScrollLock,
useSessionStorage,
useShare,
useSorted,
useSpeechRecognition,
useSpeechSynthesis,
useStepper,
useStorage,
useStorageAsync,
useStyleTag,
useSupported,
useSwipe,
useTemplateRefsList,
useTextDirection,
useTextSelection,
useTextareaAutosize,
refThrottled as useThrottle,
useThrottleFn,
useThrottledRefHistory,
useTimeAgo,
useTimeout,
useTimeoutFn,
useTimeoutPoll,
useTimestamp,
useTitle,
useToNumber,
useToString,
useToggle,
useTransition,
useUrlSearchParams,
useUserMedia,
useVModel,
useVModels,
useVibrate,
useVirtualList,
useWakeLock,
useWebNotification,
useWebSocket,
useWebWorker,
useWebWorkerFn,
useWindowFocus,
useWindowScroll,
useWindowSize,
watchArray,
watchAtMost,
watchDebounced,
watchDeep,
watchIgnorable,
watchImmediate,
watchOnce,
watchPausable,
watchThrottled,
watchTriggerable,
watchWithFilter,
whenever
};
//# sourceMappingURL=vitepress___@vueuse_core.js.map
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../../node_modules/tabbable/src/index.js", "../../../node_modules/focus-trap/index.js", "../../../node_modules/@vueuse/integrations/useFocusTrap.mjs"],
"sourcesContent": ["// NOTE: separate `:not()` selectors has broader browser support than the newer\n// `:not([inert], [inert] *)` (Feb 2023)\n// CAREFUL: JSDom does not support `:not([inert] *)` as a selector; using it causes\n// the entire query to fail, resulting in no nodes found, which will break a lot\n// of things... so we have to rely on JS to identify nodes inside an inert container\nconst candidateSelectors = [\n 'input:not([inert])',\n 'select:not([inert])',\n 'textarea:not([inert])',\n 'a[href]:not([inert])',\n 'button:not([inert])',\n '[tabindex]:not(slot):not([inert])',\n 'audio[controls]:not([inert])',\n 'video[controls]:not([inert])',\n '[contenteditable]:not([contenteditable=\"false\"]):not([inert])',\n 'details>summary:first-of-type:not([inert])',\n 'details:not([inert])',\n];\nconst candidateSelector = /* #__PURE__ */ candidateSelectors.join(',');\n\nconst NoElement = typeof Element === 'undefined';\n\nconst matches = NoElement\n ? function () {}\n : Element.prototype.matches ||\n Element.prototype.msMatchesSelector ||\n Element.prototype.webkitMatchesSelector;\n\nconst getRootNode =\n !NoElement && Element.prototype.getRootNode\n ? (element) => element?.getRootNode?.()\n : (element) => element?.ownerDocument;\n\n/**\n * Determines if a node is inert or in an inert ancestor.\n * @param {Element} [node]\n * @param {boolean} [lookUp] If true and `node` is not inert, looks up at ancestors to\n * see if any of them are inert. If false, only `node` itself is considered.\n * @returns {boolean} True if inert itself or by way of being in an inert ancestor.\n * False if `node` is falsy.\n */\nconst isInert = function (node, lookUp = true) {\n // CAREFUL: JSDom does not support inert at all, so we can't use the `HTMLElement.inert`\n // JS API property; we have to check the attribute, which can either be empty or 'true';\n // if it's `null` (not specified) or 'false', it's an active element\n const inertAtt = node?.getAttribute?.('inert');\n const inert = inertAtt === '' || inertAtt === 'true';\n\n // NOTE: this could also be handled with `node.matches('[inert], :is([inert] *)')`\n // if it weren't for `matches()` not being a function on shadow roots; the following\n // code works for any kind of node\n // CAREFUL: JSDom does not appear to support certain selectors like `:not([inert] *)`\n // so it likely would not support `:is([inert] *)` either...\n const result = inert || (lookUp && node && isInert(node.parentNode)); // recursive\n\n return result;\n};\n\n/**\n * Determines if a node's content is editable.\n * @param {Element} [node]\n * @returns True if it's content-editable; false if it's not or `node` is falsy.\n */\nconst isContentEditable = function (node) {\n // CAREFUL: JSDom does not support the `HTMLElement.isContentEditable` API so we have\n // to use the attribute directly to check for this, which can either be empty or 'true';\n // if it's `null` (not specified) or 'false', it's a non-editable element\n const attValue = node?.getAttribute?.('contenteditable');\n return attValue === '' || attValue === 'true';\n};\n\n/**\n * @param {Element} el container to check in\n * @param {boolean} includeContainer add container to check\n * @param {(node: Element) => boolean} filter filter candidates\n * @returns {Element[]}\n */\nconst getCandidates = function (el, includeContainer, filter) {\n // even if `includeContainer=false`, we still have to check it for inertness because\n // if it's inert, all its children are inert\n if (isInert(el)) {\n return [];\n }\n\n let candidates = Array.prototype.slice.apply(\n el.querySelectorAll(candidateSelector)\n );\n if (includeContainer && matches.call(el, candidateSelector)) {\n candidates.unshift(el);\n }\n candidates = candidates.filter(filter);\n return candidates;\n};\n\n/**\n * @callback GetShadowRoot\n * @param {Element} element to check for shadow root\n * @returns {ShadowRoot|boolean} ShadowRoot if available or boolean indicating if a shadowRoot is attached but not available.\n */\n\n/**\n * @callback ShadowRootFilter\n * @param {Element} shadowHostNode the element which contains shadow content\n * @returns {boolean} true if a shadow root could potentially contain valid candidates.\n */\n\n/**\n * @typedef {Object} CandidateScope\n * @property {Element} scopeParent contains inner candidates\n * @property {Element[]} candidates list of candidates found in the scope parent\n */\n\n/**\n * @typedef {Object} IterativeOptions\n * @property {GetShadowRoot|boolean} getShadowRoot true if shadow support is enabled; falsy if not;\n * if a function, implies shadow support is enabled and either returns the shadow root of an element\n * or a boolean stating if it has an undisclosed shadow root\n * @property {(node: Element) => boolean} filter filter candidates\n * @property {boolean} flatten if true then result will flatten any CandidateScope into the returned list\n * @property {Line truncated
"mappings": "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 truncated
"names": ["candidateSelectors", "candidateSelector", "join", "NoElement", "Element", "matches", "prototype", "msMatchesSelector", "webkitMatchesSelector", "getRootNode", "element", "_element$getRootNode", "call", "ownerDocument", "isInert", "node", "lookUp", "_node$getAttribute", "inertAtt", "getAttribute", "inert", "result", "parentNode", "isContentEditable", "_node$getAttribute2", "attValue", "getCandidates", "el", "includeContainer", "filter", "candidates", "Array", "slice", "apply", "querySelectorAll", "unshift", "getCandidatesIteratively", "elements", "options", "elementsToCheck", "from", "length", "shift", "tagName", "assigned", "assignedElements", "content", "children", "nestedCandidates", "flatten", "push", "scopeParent", "validCandidate", "includes", "shadowRoot", "getShadowRoot", "validShadowRoot", "shadowRootFilter", "hasTabIndex", "isNaN", "parseInt", "getTabIndex", "Error", "tabIndex", "test", "getSortOrderTabIndex", "isScope", "sortOrderedTabbables", "a", "b", "documentOrder", "isInput", "isHiddenInput", "type", "isDetailsWithSummary", "r", "some", "child", "getCheckedRadio", "nodes", "form", "i", "checked", "isTabbableRadio", "name", "radioScope", "queryRadios", "radioSet", "window", "CSS", "escape", "err", "console", "error", "message", "isRadio", "isNonTabbableRadio", "isNodeAttached", "_nodeRoot", "nodeRoot", "nodeRootHost", "host", "attached", "_nodeRootHost", "_nodeRootHost$ownerDo", "_node$ownerDocument", "contains", "_nodeRoot2", "_nodeRootHost2", "_nodeRootHost2$ownerD", "isZeroArea", "_node$getBoundingClie", "getBoundingClientRect", "width", "height", "isHidden", "_ref", "displayCheck", "getComputedStyle", "visibility", "isDirectSummary", "nodeUnderDetails", "parentElement", "originalNode", "rootNode", "assignedSlot", "getClientRects", "isDisabledFromFieldset", "disabled", "item", "isNodeMatchingSelectorFocusable", "isNodeMatchingSelectorTabbable", "isValidShadowRootTabbable", "shadowHostNode", "sortByOrder", "regularTabbables", "orderedTabbables", "forEach", "candidateTabindex", "sort", "reduce", "acc", "sortable", "concat", "tabbable", "container", "bind", "focusable", "isTabbable", "focusableCandidateSelector", "isFocusable", "activeFocusTraps", "activateTrap", "trapStack", "trap", "length", "activeTrap", "_setPausedState", "trapIndex", "indexOf", "push", "splice", "deactivateTrap", "_isManuallyPaused", "isSelectableInput", "node", "tagName", "toLowerCase", "select", "isEscapeEvent", "e", "key", "keyCode", "isTabEvent", "isKeyForward", "shiftKey", "isKeyBackward", "delay", "fn", "setTimeout", "valueOrHandler", "value", "_len", "arguments", "params", "Array", "_key", "apply", "getActualTarget", "event", "target", "shadowRoot", "composedPath", "internalTrapStack", "createFocusTrap", "elements", "userOptions", "doc", "document", "config", "_objectSpread", "returnFocusOnDeactivate", "escapeDeactivates", "delayInitialFocus", "state", "containers", "containerGroups", "tabbableGroups", "nodeFocusedBeforeActivation", "mostRecentlyFocusedNode", "active", "paused", "manuallyPaused", "delayInitialFocusTimer", "undefined", "recentNavEvent", "getOption", "configOverrideOptions", "optionName", "configOptionName", "findContainerIndex", "element", "findIndex", "_ref", "container", "tabbableNodes", "contains", "includes", "find", "getNodeForOption", "_ref2", "_ref2$hasFallback", "hasFallback", "_ref2$params", "optionValue", "_toConsumableArray", "Error", "concat", "querySelector", "err", "message", "getInitialFocusNode", "isFocusable", "tabbableOptions", "activeElement", "firstTabbableGroup", "firstTabbableNode", "updateTabbableNodes", "map", "tabbable", "focusableNodes", "focusable", "lastTabbableNode", "firstDomTabbableNode", "isTabbable", "lastDomTabbableNode", "slice", "reverse", "posTabIndexesFound", "getTabIndex", "nextTabbableNode", "forward", "nodeIdx", "el", "filter", "group", "g", "getActiveElement", "tryFocus", "focus", "preventScroll", "getReturnFocusNode", "previousActiveElement", "findNextNavNode", "_ref3", "_ref3$isBackward", "isBackward", "destinationNode", "containerIndex", "containerGroup", "startOfGroupIndex", "_ref4", "destinationGroupIndex", "destinationGroup", "lastOfGroupIndex", "_ref5", "checkPointerDown", "clickOutsideDeactivates", "deactivate", "returnFocus", "allowOutsideClick", "preventDefault", "checkFocusIn", "targetContained", "Document", "stopImmediatePropagation", "nextNode", "navAcrossContainers", "mruContainerIdx", "mruTabIdx", "some", "n", "checkKeyNav", "checkTabKey", "checkEscapeKey", "checkClick", "addListeners", "addEventListener", "capture", "passive", "removeListeners", "removeEventListener", "checkDomRemoval", "mutations", "isFocusedNodeRemoved", "mutation", "removedNodes", "from", "mutationObserver", "window", "MutationObserver", "updateObservedNodes", "disconnect", "observe", "subtree", "childList", "activate", "activateOptions", "onActivate", "onPostActivate", "checkCanFocusTrap", "finishActivation", "then", "deactivateOptions", "options", "onDeactiLine truncated
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../../node_modules/mark.js/src/lib/domiterator.js", "../../../node_modules/mark.js/src/lib/mark.js", "../../../node_modules/mark.js/src/vanilla.js"],
"sourcesContent": ["/**\n * A NodeIterator with iframes support and a method to check if an element is\n * matching a specified selector\n * @example\n * const iterator = new DOMIterator(\n * document.querySelector(\"#context\"), true\n * );\n * iterator.forEachNode(NodeFilter.SHOW_TEXT, node => {\n * console.log(node);\n * }, node => {\n * if(DOMIterator.matches(node.parentNode, \".ignore\")){\n * return NodeFilter.FILTER_REJECT;\n * } else {\n * return NodeFilter.FILTER_ACCEPT;\n * }\n * }, () => {\n * console.log(\"DONE\");\n * });\n * @todo Outsource into separate repository\n */\nexport default class DOMIterator {\n\n /**\n * @param {HTMLElement|HTMLElement[]|NodeList|string} ctx - The context DOM\n * element, an array of DOM elements, a NodeList or a selector\n * @param {boolean} [iframes=true] - A boolean indicating if iframes should\n * be handled\n * @param {string[]} [exclude=[]] - An array containing exclusion selectors\n * for iframes\n * @param {number} [iframesTimeout=5000] - A number indicating the ms to\n * wait before an iframe should be skipped, in case the load event isn't\n * fired. This also applies if the user is offline and the resource of the\n * iframe is online (either by the browsers \"offline\" mode or because\n * there's no internet connection)\n */\n constructor(ctx, iframes = true, exclude = [], iframesTimeout = 5000) {\n /**\n * The context of the instance. Either a DOM element, an array of DOM\n * elements, a NodeList or a selector\n * @type {HTMLElement|HTMLElement[]|NodeList|string}\n * @access protected\n */\n this.ctx = ctx;\n /**\n * Boolean indicating if iframe support is enabled\n * @type {boolean}\n * @access protected\n */\n this.iframes = iframes;\n /**\n * An array containing exclusion selectors for iframes\n * @type {string[]}\n */\n this.exclude = exclude;\n /**\n * The maximum ms to wait for a load event before skipping an iframe\n * @type {number}\n */\n this.iframesTimeout = iframesTimeout;\n }\n\n /**\n * Checks if the specified DOM element matches the selector\n * @param {HTMLElement} element - The DOM element\n * @param {string|string[]} selector - The selector or an array with\n * selectors\n * @return {boolean}\n * @access public\n */\n static matches(element, selector) {\n const selectors = typeof selector === 'string' ? [selector] : selector,\n fn = (\n element.matches ||\n element.matchesSelector ||\n element.msMatchesSelector ||\n element.mozMatchesSelector ||\n element.oMatchesSelector ||\n element.webkitMatchesSelector\n );\n if (fn) {\n let match = false;\n selectors.every(sel => {\n if (fn.call(element, sel)) {\n match = true;\n return false;\n }\n return true;\n });\n return match;\n } else { // may be false e.g. when el is a textNode\n return false;\n }\n }\n\n /**\n * Returns all contexts filtered by duplicates (even nested)\n * @return {HTMLElement[]} - An array containing DOM contexts\n * @access protected\n */\n getContexts() {\n let ctx,\n filteredCtx = [];\n if (typeof this.ctx === 'undefined' || !this.ctx) { // e.g. null\n ctx = [];\n } else if (NodeList.prototype.isPrototypeOf(this.ctx)) {\n ctx = Array.prototype.slice.call(this.ctx);\n } else if (Array.isArray(this.ctx)) {\n ctx = this.ctx;\n } else if (typeof this.ctx === 'string') {\n ctx = Array.prototype.slice.call(\n document.querySelectorAll(this.ctx)\n );\n } else { // e.g. HTMLElement or element inside iframe\n ctx = [this.ctx];\n }\n // filter duplicate text nodes\n ctx.forEach(ctx => {\n const isDescendant = filteredCtx.filter(contexts => {\n return contexts.contains(ctx);\n }).length > 0;\n if (filteredCtx.indexOf(ctx) === -1 && !isDescendant) {\n filteredCtx.push(ctx);\n }\n });\n return filteredCtx;\n }\n\n /**\n * @callback DOMIterator~getIframeContentsSuccessCallback\n * @param {HTMLDocument} contents - The contentDocument of the iframe\n */\n /**\n * Calls the success callback function with the iframe document. If it can't\n * be accessed it calls the error callback function\n * @param {HTMLElement} ifr - The iframe DOM element\n * @param {DOMIterator~getIframeContentsSuccessCallback} successFn\n * @param {function} [errorFn]\n * @access protected\n */\n getIframeContents(ifr, successFn, errorFn = () => {}) {\n let doc;\n try {\n const ifrWin = ifr.contentWindow;\n doc = ifrWin.document;\n if (!ifrWin || !doc) { // no permission = null. Undefined in Phantom\n throw new Error('iframe inaccessible');\n }\n } catch (e) {\n errorFn();\n }\n if (doc) {\n successFn(doc);\n }\n }\n\n /Line truncated
"mappings": "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 truncated
"names": ["ctx", "ifr", "node", "dct", "Mark"]
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../../node_modules/minisearch/src/SearchableMap/TreeIterator.ts", "../../../node_modules/minisearch/src/SearchableMap/fuzzySearch.ts", "../../../node_modules/minisearch/src/SearchableMap/SearchableMap.ts", "../../../node_modules/minisearch/src/MiniSearch.ts"],
"sourcesContent": ["import type { RadixTree, Entry, LeafType } from './types'\n\n/** @ignore */\nconst ENTRIES = 'ENTRIES'\n\n/** @ignore */\nconst KEYS = 'KEYS'\n\n/** @ignore */\nconst VALUES = 'VALUES'\n\n/** @ignore */\nconst LEAF = '' as LeafType\n\ninterface Iterators<T> {\n ENTRIES: Entry<T>\n KEYS: string\n VALUES: T\n}\n\ntype Kind<T> = keyof Iterators<T>\ntype Result<T, K extends keyof Iterators<T>> = Iterators<T>[K]\n\ntype IteratorPath<T> = {\n node: RadixTree<T>,\n keys: string[]\n}[]\n\nexport type IterableSet<T> = {\n _tree: RadixTree<T>,\n _prefix: string\n}\n\n/**\n * @private\n */\nclass TreeIterator<T, K extends Kind<T>> implements Iterator<Result<T, K>> {\n set: IterableSet<T>\n _type: K\n _path: IteratorPath<T>\n\n constructor (set: IterableSet<T>, type: K) {\n const node = set._tree\n const keys = Array.from(node.keys())\n this.set = set\n this._type = type\n this._path = keys.length > 0 ? [{ node, keys }] : []\n }\n\n next (): IteratorResult<Result<T, K>> {\n const value = this.dive()\n this.backtrack()\n return value\n }\n\n dive (): IteratorResult<Result<T, K>> {\n if (this._path.length === 0) { return { done: true, value: undefined } }\n const { node, keys } = last(this._path)!\n if (last(keys) === LEAF) { return { done: false, value: this.result() } }\n\n const child = node.get(last(keys)!)!\n this._path.push({ node: child, keys: Array.from(child.keys()) })\n return this.dive()\n }\n\n backtrack (): void {\n if (this._path.length === 0) { return }\n const keys = last(this._path)!.keys\n keys.pop()\n if (keys.length > 0) { return }\n this._path.pop()\n this.backtrack()\n }\n\n key (): string {\n return this.set._prefix + this._path\n .map(({ keys }) => last(keys))\n .filter(key => key !== LEAF)\n .join('')\n }\n\n value (): T {\n return last(this._path)!.node.get(LEAF)!\n }\n\n result (): Result<T, K> {\n switch (this._type) {\n case VALUES: return this.value() as Result<T, K>\n case KEYS: return this.key() as Result<T, K>\n default: return [this.key(), this.value()] as Result<T, K>\n }\n }\n\n [Symbol.iterator] () {\n return this\n }\n}\n\nconst last = <T>(array: T[]): T | undefined => {\n return array[array.length - 1]\n}\n\nexport { TreeIterator, ENTRIES, KEYS, VALUES, LEAF }\n", "/* eslint-disable no-labels */\nimport { LEAF } from './TreeIterator'\nimport type { RadixTree } from './types'\n\nexport type FuzzyResult<T> = [T, number]\n\nexport type FuzzyResults<T> = Map<string, FuzzyResult<T>>\n\n/**\n * @ignore\n */\nexport const fuzzySearch = <T = any>(node: RadixTree<T>, query: string, maxDistance: number): FuzzyResults<T> => {\n const results: FuzzyResults<T> = new Map()\n if (query === undefined) return results\n\n // Number of columns in the Levenshtein matrix.\n const n = query.length + 1\n\n // Matching terms can never be longer than N + maxDistance.\n const m = n + maxDistance\n\n // Fill first matrix row and column with numbers: 0 1 2 3 ...\n const matrix = new Uint8Array(m * n).fill(maxDistance + 1)\n for (let j = 0; j < n; ++j) matrix[j] = j\n for (let i = 1; i < m; ++i) matrix[i * n] = i\n\n recurse(\n node,\n query,\n maxDistance,\n results,\n matrix,\n 1,\n n,\n ''\n )\n\n return results\n}\n\n// Modified version of http://stevehanov.ca/blog/?id=114\n\n// This builds a Levenshtein matrix for a given query and continuously updates\n// it for nodes in the radix tree that fall within the given maximum edit\n// distance. Keeping the same matrix around is beneficial especially for larger\n// edit distances.\n//\n// k a t e <-- query\n// 0 1 2 3 4\n// c 1 1 2 3 4\n// a 2 2 1 2 3\n// t 3 3 2 1 [2] <-- edit distance\n// ^\n// ^ term in radix tree, rows are added and removed as needed\n\nconst recurse = <T = any>(\n node: RadixTree<T>,\n query: string,\n maxDistance: number,\n results: FuzzyResults<T>,\n matrix: Uint8Array,\n m: number,\n n: number,\n prefix: string\n): void => {\n const offset = m * n\n\n key: for (const key of node.keys()) {\n if (key === LEAF) {\n // We've reached a leaf node. Check if the edit distance acceptable and\n // store the result if it is.\n const distance = matrix[offset - 1]\n if (distance <= maxDistance) {\n results.set(prefix, [node.get(key)!, distance])\n }\n } else {\n // Iterate over all characters in the key. Update the Levenshtein matrix\n // and check if the minimum distance in the last row is still within the\n // maximum edit distance. If it is, we can recurse over all child nodes.\n let i = m\n for (let pos = 0; pos < key.length; ++pos, ++i) {\n const char = key[pos]\n const thisRowOffset = n * i\n const prevRowOffset = thisRowOffset - n\n\n // Set the first column based on the previous row, Line truncated
"mappings": "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 truncated
"names": ["last", "node", "child", "key", "chunk", "promise", "conditions", "options", "results", "query", "boosts", "data"]
}
+343
View File
@@ -0,0 +1,343 @@
import {
BaseTransition,
BaseTransitionPropsValidators,
Comment,
DeprecationTypes,
EffectScope,
ErrorCodes,
ErrorTypeStrings,
Fragment,
KeepAlive,
ReactiveEffect,
Static,
Suspense,
Teleport,
Text,
TrackOpTypes,
Transition,
TransitionGroup,
TriggerOpTypes,
VueElement,
assertNumber,
callWithAsyncErrorHandling,
callWithErrorHandling,
camelize,
capitalize,
cloneVNode,
compatUtils,
compile,
computed,
createApp,
createBaseVNode,
createBlock,
createCommentVNode,
createElementBlock,
createHydrationRenderer,
createPropsRestProxy,
createRenderer,
createSSRApp,
createSlots,
createStaticVNode,
createTextVNode,
createVNode,
customRef,
defineAsyncComponent,
defineComponent,
defineCustomElement,
defineEmits,
defineExpose,
defineModel,
defineOptions,
defineProps,
defineSSRCustomElement,
defineSlots,
devtools,
effect,
effectScope,
getCurrentInstance,
getCurrentScope,
getCurrentWatcher,
getTransitionRawChildren,
guardReactiveProps,
h,
handleError,
hasInjectionContext,
hydrate,
hydrateOnIdle,
hydrateOnInteraction,
hydrateOnMediaQuery,
hydrateOnVisible,
initCustomFormatter,
initDirectivesForSSR,
inject,
isMemoSame,
isProxy,
isReactive,
isReadonly,
isRef,
isRuntimeOnly,
isShallow,
isVNode,
markRaw,
mergeDefaults,
mergeModels,
mergeProps,
nextTick,
normalizeClass,
normalizeProps,
normalizeStyle,
onActivated,
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onDeactivated,
onErrorCaptured,
onMounted,
onRenderTracked,
onRenderTriggered,
onScopeDispose,
onServerPrefetch,
onUnmounted,
onUpdated,
onWatcherCleanup,
openBlock,
popScopeId,
provide,
proxyRefs,
pushScopeId,
queuePostFlushCb,
reactive,
readonly,
ref,
registerRuntimeCompiler,
render,
renderList,
renderSlot,
resolveComponent,
resolveDirective,
resolveDynamicComponent,
resolveFilter,
resolveTransitionHooks,
setBlockTracking,
setDevtoolsHook,
setTransitionHooks,
shallowReactive,
shallowReadonly,
shallowRef,
ssrContextKey,
ssrUtils,
stop,
toDisplayString,
toHandlerKey,
toHandlers,
toRaw,
toRef,
toRefs,
toValue,
transformVNodeArgs,
triggerRef,
unref,
useAttrs,
useCssModule,
useCssVars,
useHost,
useId,
useModel,
useSSRContext,
useShadowRoot,
useSlots,
useTemplateRef,
useTransitionState,
vModelCheckbox,
vModelDynamic,
vModelRadio,
vModelSelect,
vModelText,
vShow,
version,
warn,
watch,
watchEffect,
watchPostEffect,
watchSyncEffect,
withAsyncContext,
withCtx,
withDefaults,
withDirectives,
withKeys,
withMemo,
withModifiers,
withScopeId
} from "./chunk-VJWGEPT5.js";
export {
BaseTransition,
BaseTransitionPropsValidators,
Comment,
DeprecationTypes,
EffectScope,
ErrorCodes,
ErrorTypeStrings,
Fragment,
KeepAlive,
ReactiveEffect,
Static,
Suspense,
Teleport,
Text,
TrackOpTypes,
Transition,
TransitionGroup,
TriggerOpTypes,
VueElement,
assertNumber,
callWithAsyncErrorHandling,
callWithErrorHandling,
camelize,
capitalize,
cloneVNode,
compatUtils,
compile,
computed,
createApp,
createBlock,
createCommentVNode,
createElementBlock,
createBaseVNode as createElementVNode,
createHydrationRenderer,
createPropsRestProxy,
createRenderer,
createSSRApp,
createSlots,
createStaticVNode,
createTextVNode,
createVNode,
customRef,
defineAsyncComponent,
defineComponent,
defineCustomElement,
defineEmits,
defineExpose,
defineModel,
defineOptions,
defineProps,
defineSSRCustomElement,
defineSlots,
devtools,
effect,
effectScope,
getCurrentInstance,
getCurrentScope,
getCurrentWatcher,
getTransitionRawChildren,
guardReactiveProps,
h,
handleError,
hasInjectionContext,
hydrate,
hydrateOnIdle,
hydrateOnInteraction,
hydrateOnMediaQuery,
hydrateOnVisible,
initCustomFormatter,
initDirectivesForSSR,
inject,
isMemoSame,
isProxy,
isReactive,
isReadonly,
isRef,
isRuntimeOnly,
isShallow,
isVNode,
markRaw,
mergeDefaults,
mergeModels,
mergeProps,
nextTick,
normalizeClass,
normalizeProps,
normalizeStyle,
onActivated,
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onDeactivated,
onErrorCaptured,
onMounted,
onRenderTracked,
onRenderTriggered,
onScopeDispose,
onServerPrefetch,
onUnmounted,
onUpdated,
onWatcherCleanup,
openBlock,
popScopeId,
provide,
proxyRefs,
pushScopeId,
queuePostFlushCb,
reactive,
readonly,
ref,
registerRuntimeCompiler,
render,
renderList,
renderSlot,
resolveComponent,
resolveDirective,
resolveDynamicComponent,
resolveFilter,
resolveTransitionHooks,
setBlockTracking,
setDevtoolsHook,
setTransitionHooks,
shallowReactive,
shallowReadonly,
shallowRef,
ssrContextKey,
ssrUtils,
stop,
toDisplayString,
toHandlerKey,
toHandlers,
toRaw,
toRef,
toRefs,
toValue,
transformVNodeArgs,
triggerRef,
unref,
useAttrs,
useCssModule,
useCssVars,
useHost,
useId,
useModel,
useSSRContext,
useShadowRoot,
useSlots,
useTemplateRef,
useTransitionState,
vModelCheckbox,
vModelDynamic,
vModelRadio,
vModelSelect,
vModelText,
vShow,
version,
warn,
watch,
watchEffect,
watchPostEffect,
watchSyncEffect,
withAsyncContext,
withCtx,
withDefaults,
withDirectives,
withKeys,
withMemo,
withModifiers,
withScopeId
};
//# sourceMappingURL=vue.js.map
+7
View File
@@ -0,0 +1,7 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}
+43
View File
@@ -0,0 +1,43 @@
import { defineConfig } from 'vitepress'
// https://vitepress.dev/reference/site-config
export default defineConfig({
title: "Termix",
description: "Doccumentation",
lastUpdated: true,
cleanUrls: true,
metaChunk: true,
base: '/',
head: [['link', { rel: 'icon', href: '/favicon.ico' }]],
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: 'Home', link: '/' },
{ text: 'Docs', link: '/docs' }
],
search: {
provider: "local",
},
footer: {
message: "Distributed under the MIT License",
copyright: "© 2025 Luke Gustafson",
},
sidebar: [
{
text: 'Examples',
items: [
{ text: 'Docs', link: '/docs' },
{ text: 'GitHub', link: 'https://github.com/LukeGus/Termix' }
]
}
],
socialLinks: [
{ icon: 'github', link: 'https://github.com/LukeGus/Termix' },
{ icon: "discord", link: "https://discord.gg/jVQGdvHDrf" },
]
}
})
+125
View File
@@ -0,0 +1,125 @@
# Termix Documentation
Termix is a powerful web-based Homepage terminal emulator that allows you to connect to your servers directly from your browser. With features like split screen, tab system, and saved hosts, Termix makes server management easier than ever.
## Installation
Termix can be installed using Docker, Docker Compose, or manually. Choose the method that works best for your environment.
### Docker Installation
The simplest way to get Termix up and running is with Docker:
```bash
# Create a persistent volume for MongoDB data
docker volume create mongodb-data
# Run the Termix container
docker run -d \
--name termix \
--restart unless-stopped \
-p 8080:8080 \
-v mongodb-data:/data/db \
-e SALT="2v.F7!6a!jIzmJsu|[)h61$ZMXs;,i+~" \
ghcr.io/lukegus/termix:latest
```
::: warning
Make sure to replace the SALT value with your own secure random string, using all characters and a maximum length of 32 characters. You can generate one at LastPass Password Generator.
:::
### Docker Compose Installation
For a more comprehensive setup, you can use Docker Compose:
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
# Generate random salt here https://www.lastpass.com/features/password-generator
# (max 32 characters, include all characters for settings)
SALT: "2v.F7!6a!jIzmJsu|[)h61$ZMXs;,i+~"
PORT: "8080"
volumes:
termix-data:
driver: local
```
To start the container, run:
```bash
docker-compose up -d
```
### Manual Installation
If you prefer a manual installation, follow these steps:
#### Required Packages
- NPM
- NodeJS
- MongoDB
#### Installation Steps
1. Clone the repository:
```bash
git clone https://github.com/LukeGus/Termix.git
cd Termix
```
2. Install dependencies and build the project:
```bash
npm install
npm run build
```
3. Start the application:
```bash
npm run start
```
::: tip
For production environments, we recommend running the website via Nginx. See the Nginx configuration in the Docker directory of the repository.
:::
4. Start the backend services. Navigate to the backend directory:
```bash
cd src/backend
node database.cjs
node ssh.cjs
```
This will start the WebSocket services on ports 8081 and 8082.
## Usage
Once installed, Termix will be available at `http://localhost:8080` (or whichever port you configured).
1. Create an account or log in
2. Add your Homepage connection details
3. Connect to your servers
4. Enjoy the terminal experience right in your browser!
## Security Considerations
- Always use a strong, unique SALT value
- Keep your server up to date with the latest Termix releases
- Consider using key-based authentication rather than passwords
- For production deployments, set up HTTPS using a reverse proxy
## Troubleshooting
If you encounter any issues:
1. Check the container logs: `docker logs termix`
2. Ensure the correct ports are exposed and not blocked by a firewall
3. Check the GitHub repository for known issues or to file a new one
+40
View File
@@ -0,0 +1,40 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: "Termix"
text: "Web-based Homepage Client"
tagline: Clientless web-based Homepage terminal emulator that stores and manages your connection details
image:
src: /logo512.webp
alt: Termix
actions:
- theme: brand
text: Get Started
link: /docs
- theme: alt
text: GitHub
link: 'https://github.com/LukeGus/Termix'
features:
- icon: 📡
title: Homepage
details: Connect to any Homepage server directly from your browser with no client installation needed. Supports key-based and password authentication.
- icon: 🗂️
title: Split Screen & Tab System
details: View up to 4 terminals simultaneously with the split screen feature. Organize multiple connections with an intuitive tab system.
- icon: 🔐
title: User Authentication
details: Secure multi-user support with authentication system. Each user gets their own isolated environment and saved connections.
- icon: 💾
title: Save Hosts
details: Store and manage your connection details securely. Quickly connect to your favorite servers with just a click.
- icon: 🎨
title: SSHTerminal Themes
details: Customize your terminal experience with various color schemes and themes to reduce eye strain and match your preference.
- icon: 🐳
title: Easy Deployment
details: Quick setup using Docker or Docker Compose. Get up and running in minutes with minimal configuration required.
---
+2458
View File
File diff suppressed because it is too large. Load diff
+14
View File
@@ -0,0 +1,14 @@
{
"scripts": {
"docs:dev": "vitepress dev",
"docs:build": "vitepress build",
"docs:preview": "vitepress preview"
},
"dependencies": {
"node": "^22.15.0",
"yarn": "^1.22.22"
},
"devDependencies": {
"vitepress": "^1.6.3"
}
}
+1
View File
@@ -0,0 +1 @@
termix.site
Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+1194
View File
File diff suppressed because it is too large. Load diff
+23
View File
@@ -0,0 +1,23 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { globalIgnores } from 'eslint/config'
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs['recommended-latest'],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])
+13
View File
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Termix</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
+5045
View File
File diff suppressed because it is too large. Load diff
+61
View File
@@ -0,0 +1,61 @@
{
"name": "termix",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@hookform/resolvers": "^5.1.1",
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-checkbox": "^1.3.2",
"@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slider": "^1.3.5",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.5",
"@radix-ui/react-tabs": "^1.1.12",
"@radix-ui/react-tooltip": "^1.2.7",
"@tailwindcss/vite": "^4.1.11",
"@xterm/addon-attach": "^0.11.0",
"@xterm/addon-clipboard": "^0.1.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-unicode11": "^0.8.0",
"@xterm/xterm": "^5.5.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.525.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-hook-form": "^7.60.0",
"react-resizable-panels": "^3.0.3",
"react-xtermjs": "^1.0.10",
"ssh2": "^1.16.0",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.11",
"ws": "^8.18.3",
"zod": "^4.0.5"
},
"devDependencies": {
"@eslint/js": "^9.30.1",
"@types/node": "^24.0.13",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@vitejs/plugin-react-swc": "^3.10.2",
"eslint": "^9.30.1",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.3.0",
"tw-animate-css": "^1.3.5",
"typescript": "~5.8.3",
"typescript-eslint": "^8.35.1",
"vite": "^7.0.4"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

+46
View File
@@ -0,0 +1,46 @@
import React from "react"
import {Homepage} from "@/apps/Homepage/Homepage.tsx"
import {SSH} from "@/apps/SSH/SSH.tsx"
import {SSHTunnel} from "@/apps/SSH Tunnel/SSHTunnel.tsx";
import {ConfigEditor} from "@/apps/Config Editor/ConfigEditor.tsx";
import {Tools} from "@/apps/Tools/Tools.tsx";
function App() {
const [view, setView] = React.useState<string>("homepage")
const renderActiveView = () => {
switch (view) {
case "homepage":
return <Homepage
onSelectView={setView}
/>
case "ssh":
return <SSH
onSelectView={setView}
/>
case "ssh_tunnel":
return <SSHTunnel
onSelectView={setView}
/>
case "config_editor":
return <ConfigEditor
onSelectView={setView}
/>
case "tools":
return <Tools
onSelectView={setView}
/>
}
}
return (
<div className="flex">
<main>
{renderActiveView()}
</main>
</div>
)
}
export default App
+18
View File
@@ -0,0 +1,18 @@
import {ConfigEditorSidebar} from "@/apps/Config Editor/ConfigEditorSidebar.tsx";
import React from "react";
interface ConfigEditorProps {
onSelectView: (view: string) => void;
}
export function ConfigEditor({ onSelectView }: ConfigEditorProps): React.ReactElement {
return (
<div>
<ConfigEditorSidebar
onSelectView={onSelectView}
/>
Config Editor
</div>
)
}
@@ -0,0 +1,58 @@
import React from 'react';
import {
CornerDownLeft
} from "lucide-react"
import {
Button
} from "@/components/ui/button.tsx"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuItem, SidebarProvider,
} from "@/components/ui/sidebar.tsx"
import {
Separator,
} from "@/components/ui/separator.tsx"
interface SidebarProps {
onSelectView: (view: string) => void;
}
export function ConfigEditorSidebar({ onSelectView }: SidebarProps): React.ReactElement {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel className="text-lg text-center font-bold text-white">
Termix / Config Editor
</SidebarGroupLabel>
<Separator className="p-0.25 mt-1 mb-1" />
<SidebarGroupContent className="flex flex-col flex-grow">
<SidebarMenu>
{/* Sidebar Items */}
<SidebarMenuItem key={"Homepage"}>
<Button className="w-full mt-2 mb-2 h-8" onClick={() => onSelectView("homepage")} variant="outline">
<CornerDownLeft/>
Return
</Button>
<Separator className="p-0.25 mt-1 mb-1" />
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}
+16
View File
@@ -0,0 +1,16 @@
import {HomepageSidebar} from "@/apps/Homepage/HomepageSidebar.tsx";
import React from "react";
interface HomepageProps {
onSelectView: (view: string) => void;
}
export function Homepage({ onSelectView }: HomepageProps): React.ReactElement {
return (
<div className="flex">
<HomepageSidebar
onSelectView={onSelectView}
/>
</div>
)
}
+82
View File
@@ -0,0 +1,82 @@
import React from 'react';
import {
Computer,
Server,
File,
Hammer
} from "lucide-react";
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem, SidebarProvider,
} from "@/components/ui/sidebar.tsx"
import {
Separator,
} from "@/components/ui/separator.tsx"
interface SidebarProps {
onSelectView: (view: string) => void;
}
export function HomepageSidebar({ onSelectView }: SidebarProps): React.ReactElement {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel className="text-lg text-center font-bold text-white">
Termix
</SidebarGroupLabel>
<Separator className="p-0.25 mt-1 mb-1" />
<SidebarGroupContent>
<SidebarMenu>
{/* Sidebar Items */}
<SidebarMenuItem key={"SSH"}>
<SidebarMenuButton asChild onClick={() => onSelectView("ssh")}>
<div>
<Computer/>
<span>{"SSH"}</span>
</div>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem key={"SSH Tunnel"}>
<SidebarMenuButton asChild onClick={() => onSelectView("ssh_tunnel")}>
<div>
<Server/>
<span>{"SSH Tunnel"}</span>
</div>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem key={"Config Editor"}>
<SidebarMenuButton asChild onClick={() => onSelectView("config_editor")}>
<div>
<File/>
<span>{"Config Editor"}</span>
</div>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem key={"Tools"}>
<SidebarMenuButton asChild onClick={() => onSelectView("tools")}>
<div>
<Hammer/>
<span>{"Tools"}</span>
</div>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}
+18
View File
@@ -0,0 +1,18 @@
import React from "react";
import {SSHTunnelSidebar} from "@/apps/SSH Tunnel/SSHTunnelSidebar.tsx";
interface ConfigEditorProps {
onSelectView: (view: string) => void;
}
export function SSHTunnel({ onSelectView }: ConfigEditorProps): React.ReactElement {
return (
<div>
<SSHTunnelSidebar
onSelectView={onSelectView}
/>
SSH Tunnel
</div>
)
}
+58
View File
@@ -0,0 +1,58 @@
import React from 'react';
import {
CornerDownLeft
} from "lucide-react"
import {
Button
} from "@/components/ui/button.tsx"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuItem, SidebarProvider,
} from "@/components/ui/sidebar.tsx"
import {
Separator,
} from "@/components/ui/separator.tsx"
interface SidebarProps {
onSelectView: (view: string) => void;
}
export function SSHTunnelSidebar({ onSelectView }: SidebarProps): React.ReactElement {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel className="text-lg text-center font-bold text-white">
Termix / SSH Tunnel
</SidebarGroupLabel>
<Separator className="p-0.25 mt-1 mb-1" />
<SidebarGroupContent className="flex flex-col flex-grow">
<SidebarMenu>
{/* Sidebar Items */}
<SidebarMenuItem key={"Homepage"}>
<Button className="w-full mt-2 mb-2 h-8" onClick={() => onSelectView("homepage")} variant="outline">
<CornerDownLeft/>
Return
</Button>
<Separator className="p-0.25 mt-1 mb-1" />
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}
+474
View File
@@ -0,0 +1,474 @@
import React, { useState, useRef } from "react";
import { SSHSidebar } from "@/apps/SSH/SSHSidebar.tsx";
import { SSHTerminal } from "./SSHTerminal.tsx";
import { SSHTopbar } from "@/apps/SSH/SSHTopbar.tsx";
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@/components/ui/resizable';
interface ConfigEditorProps {
onSelectView: (view: string) => void;
}
type Tab = {
id: number;
title: string;
hostConfig: any;
terminalRef: React.RefObject<any>;
};
function TerminalOverlay({ tabId, splitScreen }: { tabId: number, splitScreen: boolean }) {
React.useEffect(() => {
const el = document.getElementById(`terminal-container-${tabId}`);
if (el) {
el.style.opacity = '1';
el.style.zIndex = '10';
el.style.left = splitScreen ? '8px' : '0px';
el.style.width = splitScreen ? 'calc(100% - 8px)' : '100%';
}
return () => {
if (el) {
el.style.opacity = '0';
el.style.zIndex = '1';
}
};
}, [tabId, splitScreen]);
return <div style={{ width: '100%', height: '100%', position: 'relative' }} />;
}
export function SSH({ onSelectView }: ConfigEditorProps): React.ReactElement {
const [allTabs, setAllTabs] = useState<Tab[]>([]);
const [currentTab, setCurrentTab] = useState<number | null>(null);
const [allSplitScreenTab, setAllSplitScreenTab] = useState<number[]>([]);
const nextTabId = useRef(1);
const [splitKey, setSplitKey] = useState(0);
const setActiveTab = (tabId: number) => {
setCurrentTab(tabId);
};
// Helper to fit all visible terminals
const fitVisibleTerminals = () => {
allTabs.forEach((terminal) => {
const isVisible =
(allSplitScreenTab.length === 0 && terminal.id === currentTab) ||
(allSplitScreenTab.length > 0 && (terminal.id === currentTab || allSplitScreenTab.includes(terminal.id)));
if (isVisible && terminal.terminalRef && terminal.terminalRef.current && typeof terminal.terminalRef.current.fit === 'function') {
terminal.terminalRef.current.fit();
}
});
};
// Wrap setSplitScreenTab to fit before and after
const setSplitScreenTab = (tabId: number) => {
fitVisibleTerminals();
setAllSplitScreenTab((prev) => {
let next;
if (prev.includes(tabId)) {
next = prev.filter((id) => id !== tabId);
} else if (prev.length < 3) {
next = [...prev, tabId];
} else {
next = prev;
}
setTimeout(() => fitVisibleTerminals(), 0);
return next;
});
};
const setCloseTab = (tabId: number) => {
// Find the tab and call disconnect on its terminal
const tab = allTabs.find((t) => t.id === tabId);
if (tab && tab.terminalRef && tab.terminalRef.current && typeof tab.terminalRef.current.disconnect === "function") {
tab.terminalRef.current.disconnect();
}
setAllTabs((prev) => prev.filter((tab) => tab.id !== tabId));
setAllSplitScreenTab((prev) => prev.filter((id) => id !== tabId));
if (currentTab === tabId) {
const remainingTabs = allTabs.filter((tab) => tab.id !== tabId);
setCurrentTab(remainingTabs.length > 0 ? remainingTabs[0].id : null);
}
};
// Render all terminals absolutely positioned, always mounted
const renderAllTerminals = () => (
<div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', pointerEvents: 'none', zIndex: 1 }}>
{allTabs.map((tab) => (
<div
key={tab.id}
id={`terminal-container-${tab.id}`}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: 1,
opacity: 0,
pointerEvents: 'auto',
transition: 'opacity 0.15s',
}}
data-terminal-id={tab.id}
>
<SSHTerminal
key={tab.id}
ref={tab.terminalRef}
hostConfig={tab.hostConfig}
isVisible={false}
title={tab.title}
showTitle={false}
splitScreen={false}
/>
</div>
))}
</div>
);
// Helper to show a terminal in a panel by toggling zIndex/opacity
const showTerminal = (tab: Tab, splitScreen: boolean) => (
<TerminalOverlay tabId={tab.id} splitScreen={splitScreen} />
);
const renderTerminals = () => {
if (allSplitScreenTab.length === 0) {
return (
<>
{allTabs.map((tab) => (
<div
key={tab.id}
style={{
height: '100%',
width: '100%',
position: 'absolute',
top: 0,
left: 0,
zIndex: tab.id === currentTab ? 10 : 1,
opacity: tab.id === currentTab ? 1 : 0,
transition: 'opacity 0.15s',
marginTop: 0,
}}
>
<TerminalOverlay tabId={tab.id} splitScreen={false} />
</div>
))}
</>
);
}
// Split screen logic
const splitTabs = allTabs.filter((tab) => allSplitScreenTab.includes(tab.id));
const mainTab = allTabs.find((tab) => tab.id === currentTab);
const layoutTabs = [mainTab, ...splitTabs.filter((t) => t && t.id !== currentTab)].filter((t): t is Tab => !!t);
// 2 splits: horizontal
if (layoutTabs.length === 2) {
const [tab1, tab2] = layoutTabs;
return (
<ResizablePanelGroup key={splitKey} direction="horizontal" className="h-full w-full">
<ResizablePanel key={tab1.id} defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<div style={{height: '100%', width: '100%', display: 'flex', flexDirection: 'column', background: '#09090b', margin: 0, padding: 0, position: 'relative'}}>
<div style={{
background: '#18181b',
color: '#fff',
fontSize: 13,
height: 28,
lineHeight: '28px',
padding: '0 10px',
borderBottom: '1px solid #222224',
letterSpacing: 1,
margin: 0,
}}>{tab1.title}</div>
<div style={{flex: 1, position: 'relative', height: '100%', width: '100%', margin: 0, padding: 0}}>
{showTerminal(tab1, true)}
</div>
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel key={tab2.id} defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<div style={{height: '100%', width: '100%', display: 'flex', flexDirection: 'column', background: '#09090b', margin: 0, padding: 0, position: 'relative'}}>
<div style={{
background: '#18181b',
color: '#fff',
fontSize: 13,
height: 28,
lineHeight: '28px',
padding: '0 10px',
borderBottom: '1px solid #222224',
letterSpacing: 1,
margin: 0,
}}>{tab2.title}</div>
<div style={{flex: 1, position: 'relative', height: '100%', width: '100%', margin: 0, padding: 0}}>
{showTerminal(tab2, true)}
</div>
</div>
</ResizablePanel>
</ResizablePanelGroup>
);
}
// 3 splits: vertical group (top: horizontal with 2, bottom: single)
if (layoutTabs.length === 3) {
return (
<ResizablePanelGroup key={splitKey} direction="vertical" className="h-full w-full">
<ResizablePanel defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<ResizablePanelGroup direction="horizontal" className="h-full w-full">
{/* Left/top panel */}
<ResizablePanel key={layoutTabs[0].id} defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<div style={{height: '100%', width: '100%', display: 'flex', flexDirection: 'column', background: '#09090b', margin: 0, padding: 0, position: 'relative'}}>
<div style={{
background: '#18181b',
color: '#fff',
fontSize: 13,
height: 28,
lineHeight: '28px',
padding: '0 10px',
borderBottom: '1px solid #222224',
letterSpacing: 1,
margin: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}}>{layoutTabs[0].title}</div>
<div style={{flex: 1, position: 'relative', height: '100%', width: '100%', margin: 0, padding: 0}}>
{showTerminal(layoutTabs[0], true)}
</div>
</div>
</ResizablePanel>
<ResizableHandle />
{/* Right/top panel (no reset button here) */}
<ResizablePanel key={layoutTabs[1].id} defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<div style={{height: '100%', width: '100%', display: 'flex', flexDirection: 'column', background: '#09090b', margin: 0, padding: 0, position: 'relative'}}>
<div style={{
background: '#18181b',
color: '#fff',
fontSize: 13,
height: 28,
lineHeight: '28px',
padding: '0 10px',
borderBottom: '1px solid #222224',
letterSpacing: 1,
margin: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}}>
<span>{layoutTabs[1].title}</span>
</div>
<div style={{flex: 1, position: 'relative', height: '100%', width: '100%', margin: 0, padding: 0}}>
{showTerminal(layoutTabs[1], true)}
</div>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<div style={{height: '100%', width: '100%', display: 'flex', flexDirection: 'column', background: '#09090b', margin: 0, padding: 0, position: 'relative'}}>
<div style={{
background: '#18181b',
color: '#fff',
fontSize: 13,
height: 28,
lineHeight: '28px',
padding: '0 10px',
borderBottom: '1px solid #222224',
letterSpacing: 1,
margin: 0,
display: 'flex',
alignItems: 'center',
}}>{layoutTabs[2].title}</div>
<div style={{flex: 1, position: 'relative', height: '100%', width: '100%', margin: 0, padding: 0}}>
{showTerminal(layoutTabs[2], true)}
</div>
</div>
</ResizablePanel>
</ResizablePanelGroup>
);
}
// 4 splits: 2x2 grid (vertical group with two horizontal groups)
if (layoutTabs.length === 4) {
return (
<ResizablePanelGroup key={splitKey} direction="vertical" className="h-full w-full">
<ResizablePanel defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<ResizablePanelGroup direction="horizontal" className="h-full w-full">
<ResizablePanel key={layoutTabs[0].id} defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<div style={{height: '100%', width: '100%', display: 'flex', flexDirection: 'column', background: '#09090b', margin: 0, padding: 0, position: 'relative'}}>
<div style={{
background: '#18181b',
color: '#fff',
fontSize: 13,
height: 28,
lineHeight: '28px',
padding: '0 10px',
borderBottom: '1px solid #222224',
letterSpacing: 1,
margin: 0,
}}>{layoutTabs[0].title}</div>
<div style={{flex: 1, position: 'relative', height: '100%', width: '100%', margin: 0, padding: 0}}>
{showTerminal(layoutTabs[0], true)}
</div>
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel key={layoutTabs[1].id} defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<div style={{height: '100%', width: '100%', display: 'flex', flexDirection: 'column', background: '#09090b', margin: 0, padding: 0, position: 'relative'}}>
<div style={{
background: '#18181b',
color: '#fff',
fontSize: 13,
height: 28,
lineHeight: '28px',
padding: '0 10px',
borderBottom: '1px solid #222224',
letterSpacing: 1,
margin: 0,
}}>{layoutTabs[1].title}</div>
<div style={{flex: 1, position: 'relative', height: '100%', width: '100%', margin: 0, padding: 0}}>
{showTerminal(layoutTabs[1], true)}
</div>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<ResizablePanelGroup direction="horizontal" className="h-full w-full">
<ResizablePanel key={layoutTabs[2].id} defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<div style={{height: '100%', width: '100%', display: 'flex', flexDirection: 'column', background: '#09090b', margin: 0, padding: 0, position: 'relative'}}>
<div style={{
background: '#18181b',
color: '#fff',
fontSize: 13,
height: 28,
lineHeight: '28px',
padding: '0 10px',
borderBottom: '1px solid #222224',
letterSpacing: 1,
margin: 0,
}}>{layoutTabs[2].title}</div>
<div style={{flex: 1, position: 'relative', height: '100%', width: '100%', margin: 0, padding: 0}}>
{showTerminal(layoutTabs[2], true)}
</div>
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel key={layoutTabs[3].id} defaultSize={50} minSize={20} className="!overflow-hidden h-full w-full">
<div style={{height: '100%', width: '100%', display: 'flex', flexDirection: 'column', background: '#09090b', margin: 0, padding: 0, position: 'relative'}}>
<div style={{
background: '#18181b',
color: '#fff',
fontSize: 13,
height: 28,
lineHeight: '28px',
padding: '0 10px',
borderBottom: '1px solid #222224',
letterSpacing: 1,
margin: 0,
}}>{layoutTabs[3].title}</div>
<div style={{flex: 1, position: 'relative', height: '100%', width: '100%', margin: 0, padding: 0}}>
{showTerminal(layoutTabs[3], true)}
</div>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
</ResizablePanelGroup>
);
}
return null;
};
const onAddHostSubmit = (data: any) => {
const id = nextTabId.current++;
const title = `${data.ip || "Host"}:${data.port || 22}`;
const terminalRef = React.createRef<any>();
const newTab: Tab = {
id,
title,
hostConfig: data,
terminalRef,
};
setAllTabs((prev) => [...prev, newTab]);
setCurrentTab(id);
setAllSplitScreenTab((prev) => prev.filter((tid) => tid !== id));
};
const getLayoutStyle = () => {
if (allSplitScreenTab.length === 0) {
return "flex flex-col h-full w-full";
} else if (allSplitScreenTab.length === 1) {
return "grid grid-cols-2 h-full w-full";
} else if (allSplitScreenTab.length === 2) {
return "grid grid-cols-2 grid-rows-2 h-full w-full";
} else {
return "grid grid-cols-2 grid-rows-2 h-full w-full";
}
};
return (
<div style={{ display: 'flex', width: '100vw', height: '100vh', overflow: 'hidden' }}>
{/* Sidebar: fixed width */}
<div style={{ width: 256, flexShrink: 0, height: '100vh', position: 'relative', zIndex: 2, margin: 0, padding: 0, border: 'none' }}>
<SSHSidebar
onSelectView={onSelectView}
onAddHostSubmit={onAddHostSubmit}
/>
</div>
{/* Main area: fills the rest */}
<div
className="terminal-container"
style={{
flex: 1,
height: '100vh',
position: 'relative',
overflow: 'hidden',
margin: 0,
padding: 0,
border: 'none',
}}
>
{/* Always render the topbar at the top */}
<div style={{ position: 'absolute', top: 0, left: 0, width: '100%', zIndex: 10 }}>
<SSHTopbar
allTabs={allTabs}
currentTab={currentTab ?? -1}
setActiveTab={setActiveTab}
allSplitScreenTab={allSplitScreenTab}
setSplitScreenTab={setSplitScreenTab}
setCloseTab={setCloseTab}
/>
</div>
{/* Split area below the topbar */}
<div style={{ height: 'calc(100% - 46px)', marginTop: 46, position: 'relative' }}>
{/* Absolutely render all terminals for persistence */}
{allSplitScreenTab.length > 0 && (
<div style={{ position: 'absolute', top: 0, right: 0, zIndex: 20, height: 28 }}>
<button
style={{
background: '#18181b',
color: '#fff',
borderLeft: '1px solid #222224',
borderRight: '1px solid #222224',
borderTop: 'none',
borderBottom: '1px solid #222224',
borderRadius: 0,
padding: '2px 10px',
cursor: 'pointer',
fontSize: 13,
margin: 0,
height: 28,
display: 'flex',
alignItems: 'center',
}}
onClick={() => setSplitKey((k) => k + 1)}
>
Reset Split Sizes
</button>
</div>
)}
{renderAllTerminals()}
{renderTerminals()}
</div>
</div>
</div>
);
}
+198
View File
@@ -0,0 +1,198 @@
import React from 'react';
import {
CornerDownLeft,
Plus
} from "lucide-react"
import {
Button
} from "@/components/ui/button.tsx"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuItem, SidebarProvider,
} from "@/components/ui/sidebar.tsx"
import {
Separator,
} from "@/components/ui/separator.tsx"
import {
Sheet,
SheetClose,
SheetContent,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger
} from "@/components/ui/sheet.tsx";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form.tsx";
import { useForm } from "react-hook-form"
import { Input } from "@/components/ui/input.tsx";
interface SidebarProps {
onSelectView: (view: string) => void;
onAddHostSubmit: (data: any) => void;
}
export function SSHSidebar({ onSelectView, onAddHostSubmit }: SidebarProps): React.ReactElement {
const addHostForm = useForm({
defaultValues: {
}
})
const onAddHostSubmitReset = (data: any) => {
addHostForm.reset();
onAddHostSubmit(data);
}
return (
<SidebarProvider>
<Sidebar className="h-full flex flex-col">
<SidebarContent className="flex flex-col flex-grow h-full">
<SidebarGroup className="flex flex-col flex-grow h-full">
<SidebarGroupLabel className="text-lg text-center font-bold text-white">
Termix / SSH
</SidebarGroupLabel>
<Separator className="p-0.25 mt-1 mb-1" />
<SidebarGroupContent className="flex flex-col flex-grow h-full">
<SidebarMenu className="flex flex-col flex-grow h-full">
<SidebarMenuItem key="Homepage">
<Button
className="w-full mt-2 mb-2 h-8"
onClick={() => onSelectView("homepage")}
variant="outline"
>
<CornerDownLeft />
Return
</Button>
<Separator className="p-0.25 mt-1 mb-1" />
</SidebarMenuItem>
<SidebarMenuItem key="AddHost">
<Sheet>
<SheetTrigger asChild>
<Button
className="w-full mt-2 mb-2 h-8"
variant="outline"
>
<Plus />
Add Host
</Button>
</SheetTrigger>
<SheetContent
side="left"
className="w-[256px] fixed top-0 left-0 h-full z-[100] flex flex-col"
>
<SheetHeader className="pb-0.5">
<SheetTitle>Add Host</SheetTitle>
</SheetHeader>
{/* Scrollable content */}
<div className="flex-1 overflow-y-auto px-4">
<Form {...addHostForm}>
<form
id="add-host-form"
onSubmit={addHostForm.handleSubmit(onAddHostSubmitReset)}
className="space-y-3"
>
<FormField
control={addHostForm.control}
name="ip"
render={({ field }) => (
<FormItem>
<FormLabel>IP</FormLabel>
<FormControl>
<Input placeholder="127.0.0.1" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={addHostForm.control}
name="port"
render={({ field }) => (
<FormItem>
<FormLabel>Port</FormLabel>
<FormControl>
<Input placeholder="22" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={addHostForm.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="username123" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={addHostForm.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<FormControl>
<Input placeholder="password123" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
</div>
<Separator className="p-0.25 mt-2" />
<SheetFooter className="px-4 pt-1 pb-4">
<SheetClose asChild>
<Button type="submit" form="add-host-form">
Add Host
</Button>
</SheetClose>
<SheetClose asChild>
<Button variant="outline">Close</Button>
</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>
</SidebarMenuItem>
<SidebarMenuItem key="Main" className="flex flex-col flex-grow">
<div className="flex w-full flex-grow rounded-md bg-[#09090b] border border-[#434345] p-2 mb-1">
</div>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
);
}
+79
View File
@@ -0,0 +1,79 @@
import React from "react";
import {Button} from "@/components/ui/button.tsx";
import {X, SeparatorVertical} from "lucide-react"
interface TerminalTab {
id: number;
title: string;
}
interface SSHTabListProps {
allTabs: TerminalTab[];
currentTab: number;
setActiveTab: (tab: number) => void;
allSplitScreenTab: number[];
setSplitScreenTab: (tab: number) => void;
setCloseTab: (tab: number) => void;
}
export function SSHTabList({
allTabs,
currentTab,
setActiveTab,
allSplitScreenTab = [],
setSplitScreenTab,
setCloseTab,
}: SSHTabListProps): React.ReactElement {
const isSplitScreenActive = allSplitScreenTab.length > 0;
return (
<div className="inline-flex items-center h-full px-[0.5rem] overflow-x-auto">
{allTabs.map((terminal, index) => {
const isActive = terminal.id === currentTab;
const isSplit = allSplitScreenTab.includes(terminal.id);
const isSplitButtonDisabled =
(isActive && !isSplitScreenActive) ||
(allSplitScreenTab.length >= 3 && !isSplit);
return (
<div
key={terminal.id}
className={index < allTabs.length - 1 ? "mr-[0.5rem]" : ""}
>
<div className="inline-flex rounded-md shadow-sm" role="group">
{/* Set Active Tab Button */}
<Button
onClick={() => setActiveTab(terminal.id)}
disabled={isSplit}
variant="outline"
className={`rounded-r-none ${isActive ? '!bg-[#1d1d1f] !text-white !border-[#2d2d30] !hover:bg-[#1d1d1f] !active:bg-[#1d1d1f] !focus:bg-[#1d1d1f] !hover:text-white !active:text-white !focus:text-white' : ''}`}
>
{terminal.title}
</Button>
{/* Split Screen Button */}
<Button
onClick={() => setSplitScreenTab(terminal.id)}
disabled={isSplitButtonDisabled || isActive}
variant="outline"
className="rounded-none p-0 !w-9 !h-9"
>
<SeparatorVertical className="!w-5 !h-5" strokeWidth={2.5} />
</Button>
{/* Close Tab Button */}
<Button
onClick={() => setCloseTab(terminal.id)}
disabled={(isSplitScreenActive && isActive) || isSplit}
variant="outline"
className="rounded-l-none p-0 !w-9 !h-9"
>
<X className="!w-5 !h-5" strokeWidth={2.5} />
</Button>
</div>
</div>
);
})}
</div>
);
}
+178
View File
@@ -0,0 +1,178 @@
import React, { useEffect, useRef, useState, useImperativeHandle, forwardRef } from 'react';
import { useXTerm } from 'react-xtermjs';
import { FitAddon } from '@xterm/addon-fit';
import { ClipboardAddon } from '@xterm/addon-clipboard';
interface SSHTerminalProps {
hostConfig: any;
isVisible: boolean;
title?: string;
showTitle?: boolean;
splitScreen?: boolean;
}
export const SSHTerminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
{ hostConfig, isVisible, splitScreen = false },
ref
) {
console.log('Rendering SSHTerminal', { hostConfig, isVisible });
const { instance: terminal, ref: xtermRef } = useXTerm();
const fitAddonRef = useRef<FitAddon | null>(null);
const webSocketRef = useRef<WebSocket | null>(null);
const resizeTimeout = useRef<NodeJS.Timeout | null>(null);
const [visible, setVisible] = useState(false);
useImperativeHandle(ref, () => ({
disconnect: () => {
if (webSocketRef.current) {
webSocketRef.current.close();
}
},
fit: () => {
if (fitAddonRef.current) {
fitAddonRef.current.fit();
}
}
}), []);
useEffect(() => {
function handleWindowResize() {
fitAddonRef.current?.fit();
}
window.addEventListener('resize', handleWindowResize);
return () => window.removeEventListener('resize', handleWindowResize);
}, []);
useEffect(() => {
if (!terminal || !xtermRef.current || !hostConfig) return;
const fitAddon = new FitAddon();
const clipboardAddon = new ClipboardAddon();
fitAddonRef.current = fitAddon;
terminal.loadAddon(fitAddon);
terminal.loadAddon(clipboardAddon);
terminal.open(xtermRef.current);
terminal.options = {
cursorBlink: true,
cursorStyle: 'bar',
scrollback: 5000,
fontSize: 15,
theme: {
background: '#09090b',
foreground: '#f7f7f7',
},
};
const onResize = () => {
if (!xtermRef.current) return;
const { width, height } = xtermRef.current.getBoundingClientRect();
if (width < 100 || height < 50) return;
if (resizeTimeout.current) clearTimeout(resizeTimeout.current);
resizeTimeout.current = setTimeout(() => {
fitAddonRef.current?.fit();
// Always send cols + 1
const cols = terminal.cols + 1;
const rows = terminal.rows;
webSocketRef.current?.send(JSON.stringify({
type: 'resize',
data: { cols, rows }
}));
}, 100);
};
const resizeObserver = new ResizeObserver(onResize);
resizeObserver.observe(xtermRef.current);
setTimeout(() => {
fitAddon.fit();
setVisible(true);
// Always send cols + 1
const cols = terminal.cols + 1;
const rows = terminal.rows;
const ws = new WebSocket('ws://localhost:8082');
webSocketRef.current = ws;
ws.addEventListener('open', () => {
terminal.writeln('WebSocket opened');
ws.send(JSON.stringify({
type: 'connectToHost',
data: {
cols,
rows,
hostConfig: hostConfig
}
}));
terminal.onData((data) => {
ws.send(JSON.stringify({
type: 'input',
data
}));
});
});
ws.addEventListener('message', (event) => {
try {
const msg = JSON.parse(event.data);
console.log('WS message received:', msg); // Debug log
if (msg.type === 'data') {
terminal.write(msg.data);
} else if (msg.type === 'error') {
terminal.writeln(`\r\n[ERROR] ${msg.message}`);
} else if (msg.type === 'connected') {
terminal.writeln('[SSH connected. Waiting for prompt...]');
} else {
console.log('Unhandled message:', msg);
}
} catch (err) {
console.error('Failed to parse message', err);
}
});
ws.addEventListener('close', () => {
terminal.writeln('\r\n[Connection closed]');
});
ws.addEventListener('error', () => {
terminal.writeln('\r\n[Connection error]');
});
}, 300);
return () => {
resizeObserver.disconnect();
if (resizeTimeout.current) clearTimeout(resizeTimeout.current);
webSocketRef.current?.close();
};
}, [xtermRef, terminal, hostConfig]);
useEffect(() => {
if (isVisible && fitAddonRef.current) {
fitAddonRef.current.fit();
}
}, [isVisible]);
return (
<div
ref={xtermRef}
style={{
position: 'absolute',
top: splitScreen ? 0 : 48,
left: 0,
right: '-1ch',
bottom: 0,
marginLeft: 2,
opacity: visible && isVisible ? 1 : 0,
}}
/>
);
});
+37
View File
@@ -0,0 +1,37 @@
import {SSHTabList} from "@/apps/SSH/SSHTabList.tsx";
import React from "react";
interface TerminalTab {
id: number;
title: string;
}
interface SSHTopbarProps {
allTabs: TerminalTab[];
currentTab: number;
setActiveTab: (tab: number) => void;
allSplitScreenTab: number[];
setSplitScreenTab: (tab: number) => void;
setCloseTab: (tab: number) => void;
}
export function SSHTopbar({ allTabs, currentTab, setActiveTab, allSplitScreenTab, setSplitScreenTab, setCloseTab }: SSHTopbarProps): React.ReactElement {
return (
<div className="flex h-11.5 z-100" style={{
position: 'absolute',
left: 0,
width: '100%',
backgroundColor: '#18181b',
borderBottom: '1px solid #222224',
}}>
<SSHTabList
allTabs={allTabs}
currentTab={currentTab}
setActiveTab={setActiveTab}
allSplitScreenTab={allSplitScreenTab}
setSplitScreenTab={setSplitScreenTab}
setCloseTab={setCloseTab}
/>
</div>
)
}
+18
View File
@@ -0,0 +1,18 @@
import React from "react";
import {TemplateSidebar} from "@/apps/Template/TemplateSidebar.tsx";
interface ConfigEditorProps {
onSelectView: (view: string) => void;
}
export function Template({ onSelectView }: ConfigEditorProps): React.ReactElement {
return (
<div>
<TemplateSidebar
onSelectView={onSelectView}
/>
Template
</div>
)
}
+58
View File
@@ -0,0 +1,58 @@
import React from 'react';
import {
CornerDownLeft
} from "lucide-react"
import {
Button
} from "@/components/ui/button.tsx"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuItem, SidebarProvider,
} from "@/components/ui/sidebar.tsx"
import {
Separator,
} from "@/components/ui/separator.tsx"
interface SidebarProps {
onSelectView: (view: string) => void;
}
export function TemplateSidebar({ onSelectView }: SidebarProps): React.ReactElement {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel className="text-lg text-center font-bold text-white">
Termix / Template
</SidebarGroupLabel>
<Separator className="p-0.25 mt-1 mb-1" />
<SidebarGroupContent className="flex flex-col flex-grow">
<SidebarMenu>
{/* Sidebar Items */}
<SidebarMenuItem key={"Homepage"}>
<Button className="w-full mt-2 mb-2 h-8" onClick={() => onSelectView("homepage")} variant="outline">
<CornerDownLeft/>
Return
</Button>
<Separator className="p-0.25 mt-1 mb-1" />
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}
+18
View File
@@ -0,0 +1,18 @@
import React from "react";
import {ToolsSidebar} from "@/apps/Tools/ToolsSidebar.tsx";
interface ConfigEditorProps {
onSelectView: (view: string) => void;
}
export function Tools({ onSelectView }: ConfigEditorProps): React.ReactElement {
return (
<div>
<ToolsSidebar
onSelectView={onSelectView}
/>
Template
</div>
)
}
+58
View File
@@ -0,0 +1,58 @@
import React from 'react';
import {
CornerDownLeft
} from "lucide-react"
import {
Button
} from "@/components/ui/button.tsx"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuItem, SidebarProvider,
} from "@/components/ui/sidebar.tsx"
import {
Separator,
} from "@/components/ui/separator.tsx"
interface SidebarProps {
onSelectView: (view: string) => void;
}
export function ToolsSidebar({ onSelectView }: SidebarProps): React.ReactElement {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel className="text-lg text-center font-bold text-white">
Termix / Tools
</SidebarGroupLabel>
<Separator className="p-0.25 mt-1 mb-1" />
<SidebarGroupContent className="flex flex-col flex-grow">
<SidebarMenu>
{/* Sidebar Items */}
<SidebarMenuItem key={"Homepage"}>
<Button className="w-full mt-2 mb-2 h-8" onClick={() => onSelectView("homepage")} variant="outline">
<CornerDownLeft/>
Return
</Button>
<Separator className="p-0.25 mt-1 mb-1" />
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}
+142
View File
@@ -0,0 +1,142 @@
const WebSocket = require('ws');
const { Client } = require('ssh2');
const wss = new WebSocket.Server({ port: 8082 });
wss.on('connection', (ws) => {
let sshConn = null;
let sshStream = null;
ws.on('close', () => {
cleanupSSH();
});
ws.on('message', (msg) => {
let parsed;
try {
parsed = JSON.parse(msg);
} catch (e) {
console.error('Invalid JSON received:', msg);
ws.send(JSON.stringify({ type: 'error', message: 'Invalid JSON' }));
return;
}
const { type, data } = parsed;
switch (type) {
case 'connectToHost':
handleConnectToHost(data);
break;
case 'resize':
handleResize(data);
break;
case 'disconnect':
cleanupSSH();
break;
case 'input':
if (sshStream) sshStream.write(data);
break;
default:
console.warn('Unknown message type:', type);
}
});
function handleConnectToHost({ cols, rows, hostConfig }) {
const { ip, port, username, password } = hostConfig;
sshConn = new Client();
sshConn.on('ready', () => {
sshConn.shell({
term: "xterm-256color",
cols,
rows,
modes: {
ECHO: 1,
ECHOCTL: 0,
ICANON: 1,
TTY_OP_OSWRAP: 1
}
}, (err, stream) => {
if (err) {
console.error('Shell error:', err);
ws.send(JSON.stringify({ type: 'error', message: 'Shell error: ' + err.message }));
return;
}
sshStream = stream;
stream.on('data', (chunk) => {
ws.send(JSON.stringify({ type: 'data', data: chunk.toString() }));
});
stream.on('close', () => {
cleanupSSH();
});
stream.on('error', (err) => {
console.error('SSH stream error:', err.message);
ws.send(JSON.stringify({ type: 'error', message: 'SSH stream error: ' + err.message }));
});
ws.send(JSON.stringify({ type: 'connected', message: 'SSH connected' }));
// stream.write('\n'); // Force prompt to appear (removed to avoid double prompt)
console.log('Sent connected message and newline to SSH stream');
});
});
sshConn.on('error', (err) => {
console.error('SSH connection error:', err.message);
ws.send(JSON.stringify({ type: 'error', message: 'SSH error: ' + err.message }));
cleanupSSH();
});
sshConn.on('close', () => {
cleanupSSH();
});
sshConn.connect({
host: ip,
port,
username,
password,
keepaliveInterval: 5000,
keepaliveCountMax: 10,
readyTimeout: 10000,
tcpKeepAlive: true,
});
}
function handleResize({ cols, rows }) {
if (sshStream && sshStream.setWindow) {
sshStream.setWindow(rows, cols, rows, cols);
ws.send(JSON.stringify({ type: 'resized', cols, rows }));
}
}
function cleanupSSH() {
if (sshStream) {
try {
sshStream.end();
} catch (e) {
console.error('Error closing stream:', e.message);
}
sshStream = null;
}
if (sshConn) {
try {
sshConn.end();
} catch (e) {
console.error('Error closing connection:', e.message);
}
sshConn = null;
}
}
});
console.log('WebSocket server running on ws://localhost:8082');
+73
View File
@@ -0,0 +1,73 @@
import { createContext, useContext, useEffect, useState } from "react"
type Theme = "dark" | "light" | "system"
type ThemeProviderProps = {
children: React.ReactNode
defaultTheme?: Theme
storageKey?: string
}
type ThemeProviderState = {
theme: Theme
setTheme: (theme: Theme) => void
}
const initialState: ThemeProviderState = {
theme: "system",
setTheme: () => null,
}
const ThemeProviderContext = createContext<ThemeProviderState>(initialState)
export function ThemeProvider({
children,
defaultTheme = "system",
storageKey = "vite-ui-theme",
...props
}: ThemeProviderProps) {
const [theme, setTheme] = useState<Theme>(
() => (localStorage.getItem(storageKey) as Theme) || defaultTheme
)
useEffect(() => {
const root = window.document.documentElement
root.classList.remove("light", "dark")
if (theme === "system") {
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
.matches
? "dark"
: "light"
root.classList.add(systemTheme)
return
}
root.classList.add(theme)
}, [theme])
const value = {
theme,
setTheme: (theme: Theme) => {
localStorage.setItem(storageKey, theme)
setTheme(theme)
},
}
return (
<ThemeProviderContext.Provider {...props} value={value}>
{children}
</ThemeProviderContext.Provider>
)
}
export const useTheme = () => {
const context = useContext(ThemeProviderContext)
if (context === undefined)
throw new Error("useTheme must be used within a ThemeProvider")
return context
}
+59
View File
@@ -0,0 +1,59 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-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",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
secondary:
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
ghost:
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
function Button({
className,
variant,
size,
asChild = false,
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean
}) {
const Comp = asChild ? Slot : "button"
return (
<Comp
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
}
export { Button, buttonVariants }
+165
View File
@@ -0,0 +1,165 @@
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { Slot } from "@radix-ui/react-slot"
import {
Controller,
FormProvider,
useFormContext,
useFormState,
type ControllerProps,
type FieldPath,
type FieldValues,
} from "react-hook-form"
import { cn } from "@/lib/utils"
import { Label } from "@/components/ui/label"
const Form = FormProvider
type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = {
name: TName
}
const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue
)
const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>({
...props
}: ControllerProps<TFieldValues, TName>) => {
return (
<FormFieldContext.Provider value={{ name: props.name }}>
<Controller {...props} />
</FormFieldContext.Provider>
)
}
const useFormField = () => {
const fieldContext = React.useContext(FormFieldContext)
const itemContext = React.useContext(FormItemContext)
const { getFieldState } = useFormContext()
const formState = useFormState({ name: fieldContext.name })
const fieldState = getFieldState(fieldContext.name, formState)
if (!fieldContext) {
throw new Error("useFormField should be used within <FormField>")
}
const { id } = itemContext
return {
id,
name: fieldContext.name,
formItemId: `${id}-form-item`,
formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`,
...fieldState,
}
}
type FormItemContextValue = {
id: string
}
const FormItemContext = React.createContext<FormItemContextValue>(
{} as FormItemContextValue
)
function FormItem({ className, ...props }: React.ComponentProps<"div">) {
const id = React.useId()
return (
<FormItemContext.Provider value={{ id }}>
<div
data-slot="form-item"
className={cn("grid gap-2", className)}
{...props}
/>
</FormItemContext.Provider>
)
}
function FormLabel({
className,
...props
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
const { error, formItemId } = useFormField()
return (
<Label
data-slot="form-label"
data-error={!!error}
className={cn("data-[error=true]:text-destructive", className)}
htmlFor={formItemId}
{...props}
/>
)
}
function FormControl({ ...props }: React.ComponentProps<typeof Slot>) {
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
return (
<Slot
data-slot="form-control"
id={formItemId}
aria-describedby={
!error
? `${formDescriptionId}`
: `${formDescriptionId} ${formMessageId}`
}
aria-invalid={!!error}
{...props}
/>
)
}
function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
const { formDescriptionId } = useFormField()
return (
<p
data-slot="form-description"
id={formDescriptionId}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}
function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
const { error, formMessageId } = useFormField()
const body = error ? String(error?.message ?? "") : props.children
if (!body) {
return null
}
return (
<p
data-slot="form-message"
id={formMessageId}
className={cn("text-destructive text-sm", className)}
{...props}
>
{body}
</p>
)
}
export {
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
}
+21
View File
@@ -0,0 +1,21 @@
import * as React from "react"
import { cn } from "@/lib/utils"
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
<input
type={type}
data-slot="input"
className={cn(
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"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",
className
)}
{...props}
/>
)
}
export { Input }
+22
View File
@@ -0,0 +1,22 @@
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cn } from "@/lib/utils"
function Label({
className,
...props
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
return (
<LabelPrimitive.Root
data-slot="label"
className={cn(
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
className
)}
{...props}
/>
)
}
export { Label }
+54
View File
@@ -0,0 +1,54 @@
import * as React from "react"
import { GripVerticalIcon } from "lucide-react"
import * as ResizablePrimitive from "react-resizable-panels"
import { cn } from "@/lib/utils"
function ResizablePanelGroup({
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) {
return (
<ResizablePrimitive.PanelGroup
data-slot="resizable-panel-group"
className={cn(
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
className
)}
{...props}
/>
)
}
function ResizablePanel({
...props
}: React.ComponentProps<typeof ResizablePrimitive.Panel>) {
return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />
}
function ResizableHandle({
withHandle,
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
withHandle?: boolean
}) {
return (
<ResizablePrimitive.PanelResizeHandle
data-slot="resizable-handle"
className={cn(
"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90",
className
)}
{...props}
>
{withHandle && (
<div className="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-xs border">
<GripVerticalIcon className="size-2.5" />
</div>
)}
</ResizablePrimitive.PanelResizeHandle>
)
}
export { ResizablePanelGroup, ResizablePanel, ResizableHandle }
+28
View File
@@ -0,0 +1,28 @@
"use client"
import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator"
import { cn } from "@/lib/utils"
function Separator({
className,
orientation = "horizontal",
decorative = true,
...props
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
return (
<SeparatorPrimitive.Root
data-slot="separator"
decorative={decorative}
orientation={orientation}
className={cn(
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
className
)}
{...props}
/>
)
}
export { Separator }
+137
View File
@@ -0,0 +1,137 @@
import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog"
import { XIcon } from "lucide-react"
import { cn } from "@/lib/utils"
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
return <SheetPrimitive.Root data-slot="sheet" {...props} />
}
function SheetTrigger({
...props
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
}
function SheetClose({
...props
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
}
function SheetPortal({
...props
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
}
function SheetOverlay({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
return (
<SheetPrimitive.Overlay
data-slot="sheet-overlay"
className={cn(
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
className
)}
{...props}
/>
)
}
function SheetContent({
className,
children,
side = "right",
...props
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
side?: "top" | "right" | "bottom" | "left"
}) {
return (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
data-slot="sheet-content"
className={cn(
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
side === "right" &&
"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
side === "left" &&
"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
side === "top" &&
"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
side === "bottom" &&
"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
className
)}
{...props}
>
{children}
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
<XIcon className="size-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>
)
}
function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sheet-header"
className={cn("flex flex-col gap-1.5 p-4", className)}
{...props}
/>
)
}
function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sheet-footer"
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
{...props}
/>
)
}
function SheetTitle({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Title>) {
return (
<SheetPrimitive.Title
data-slot="sheet-title"
className={cn("text-foreground font-semibold", className)}
{...props}
/>
)
}
function SheetDescription({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Description>) {
return (
<SheetPrimitive.Description
data-slot="sheet-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}
export {
Sheet,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}
+725
View File
@@ -0,0 +1,725 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { PanelLeftIcon } from "lucide-react"
import { useIsMobile } from "@/hooks/use-mobile"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Separator } from "@/components/ui/separator"
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
} from "@/components/ui/sheet"
import { Skeleton } from "@/components/ui/skeleton"
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"
const SIDEBAR_COOKIE_NAME = "sidebar_state"
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
const SIDEBAR_WIDTH = "16rem"
const SIDEBAR_WIDTH_MOBILE = "18rem"
const SIDEBAR_WIDTH_ICON = "3rem"
const SIDEBAR_KEYBOARD_SHORTCUT = "b"
type SidebarContextProps = {
state: "expanded" | "collapsed"
open: boolean
setOpen: (open: boolean) => void
openMobile: boolean
setOpenMobile: (open: boolean) => void
isMobile: boolean
toggleSidebar: () => void
}
const SidebarContext = React.createContext<SidebarContextProps | null>(null)
function useSidebar() {
const context = React.useContext(SidebarContext)
if (!context) {
throw new Error("useSidebar must be used within a SidebarProvider.")
}
return context
}
function SidebarProvider({
defaultOpen = true,
open: openProp,
onOpenChange: setOpenProp,
className,
style,
children,
...props
}: React.ComponentProps<"div"> & {
defaultOpen?: boolean
open?: boolean
onOpenChange?: (open: boolean) => void
}) {
const isMobile = useIsMobile()
const [openMobile, setOpenMobile] = React.useState(false)
// This is the internal state of the sidebar.
// We use openProp and setOpenProp for control from outside the component.
const [_open, _setOpen] = React.useState(defaultOpen)
const open = openProp ?? _open
const setOpen = React.useCallback(
(value: boolean | ((value: boolean) => boolean)) => {
const openState = typeof value === "function" ? value(open) : value
if (setOpenProp) {
setOpenProp(openState)
} else {
_setOpen(openState)
}
// This sets the cookie to keep the sidebar state.
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
},
[setOpenProp, open]
)
// Helper to toggle the sidebar.
const toggleSidebar = React.useCallback(() => {
return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)
}, [isMobile, setOpen, setOpenMobile])
// Adds a keyboard shortcut to toggle the sidebar.
React.useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (
event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
(event.metaKey || event.ctrlKey)
) {
event.preventDefault()
toggleSidebar()
}
}
window.addEventListener("keydown", handleKeyDown)
return () => window.removeEventListener("keydown", handleKeyDown)
}, [toggleSidebar])
// We add a state so that we can do data-state="expanded" or "collapsed".
// This makes it easier to style the sidebar with Tailwind classes.
const state = open ? "expanded" : "collapsed"
const contextValue = React.useMemo<SidebarContextProps>(
() => ({
state,
open,
setOpen,
isMobile,
openMobile,
setOpenMobile,
toggleSidebar,
}),
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
)
return (
<SidebarContext.Provider value={contextValue}>
<TooltipProvider delayDuration={0}>
<div
data-slot="sidebar-wrapper"
style={
{
"--sidebar-width": SIDEBAR_WIDTH,
"--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
...style,
} as React.CSSProperties
}
className={cn(
"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex h-full w-full",
className
)}
{...props}
>
{children}
</div>
</TooltipProvider>
</SidebarContext.Provider>
)
}
function Sidebar({
side = "left",
variant = "sidebar",
collapsible = "offcanvas",
className,
children,
...props
}: React.ComponentProps<"div"> & {
side?: "left" | "right"
variant?: "sidebar" | "floating" | "inset"
collapsible?: "offcanvas" | "icon" | "none"
}) {
const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
if (collapsible === "none") {
return (
<div
data-slot="sidebar"
className={cn(
"bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col",
className
)}
{...props}
>
{children}
</div>
)
}
if (isMobile) {
return (
<Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
<SheetContent
data-sidebar="sidebar"
data-slot="sidebar"
data-mobile="true"
className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
style={
{
"--sidebar-width": SIDEBAR_WIDTH_MOBILE,
} as React.CSSProperties
}
side={side}
>
<SheetHeader className="sr-only">
<SheetTitle>Sidebar</SheetTitle>
<SheetDescription>Displays the mobile sidebar.</SheetDescription>
</SheetHeader>
<div className="flex h-full w-full flex-col">{children}</div>
</SheetContent>
</Sheet>
)
}
return (
<div
className="group peer text-sidebar-foreground hidden md:block"
data-state={state}
data-collapsible={state === "collapsed" ? collapsible : ""}
data-variant={variant}
data-side={side}
data-slot="sidebar"
>
{/* This is what handles the sidebar gap on desktop */}
<div
data-slot="sidebar-gap"
className={cn(
"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
"group-data-[collapsible=offcanvas]:w-0",
"group-data-[side=right]:rotate-180",
variant === "floating" || variant === "inset"
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
)}
/>
<div
data-slot="sidebar-container"
className={cn(
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
side === "left"
? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
: "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
// Adjust the padding for floating and inset variants.
variant === "floating" || variant === "inset"
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
className
)}
{...props}
>
<div
data-sidebar="sidebar"
data-slot="sidebar-inner"
className="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
>
{children}
</div>
</div>
</div>
)
}
function SidebarTrigger({
className,
onClick,
...props
}: React.ComponentProps<typeof Button>) {
const { toggleSidebar } = useSidebar()
return (
<Button
data-sidebar="trigger"
data-slot="sidebar-trigger"
variant="ghost"
size="icon"
className={cn("size-7", className)}
onClick={(event) => {
onClick?.(event)
toggleSidebar()
}}
{...props}
>
<PanelLeftIcon />
<span className="sr-only">Toggle Sidebar</span>
</Button>
)
}
function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
const { toggleSidebar } = useSidebar()
return (
<button
data-sidebar="rail"
data-slot="sidebar-rail"
aria-label="Toggle Sidebar"
tabIndex={-1}
onClick={toggleSidebar}
title="Toggle Sidebar"
className={cn(
"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex",
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
"hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full",
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
className
)}
{...props}
/>
)
}
function SidebarInset({ className, ...props }: React.ComponentProps<"main">) {
return (
<main
data-slot="sidebar-inset"
className={cn(
"bg-background relative flex w-full flex-1 flex-col",
"md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
className
)}
{...props}
/>
)
}
function SidebarInput({
className,
...props
}: React.ComponentProps<typeof Input>) {
return (
<Input
data-slot="sidebar-input"
data-sidebar="input"
className={cn("bg-background h-8 w-full shadow-none", className)}
{...props}
/>
)
}
function SidebarHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sidebar-header"
data-sidebar="header"
className={cn("flex flex-col gap-2 p-2", className)}
{...props}
/>
)
}
function SidebarFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sidebar-footer"
data-sidebar="footer"
className={cn("flex flex-col gap-2 p-2", className)}
{...props}
/>
)
}
function SidebarSeparator({
className,
...props
}: React.ComponentProps<typeof Separator>) {
return (
<Separator
data-slot="sidebar-separator"
data-sidebar="separator"
className={cn("bg-sidebar-border mx-2 w-auto", className)}
{...props}
/>
)
}
function SidebarContent({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sidebar-content"
data-sidebar="content"
className={cn(
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
className
)}
{...props}
/>
)
}
function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sidebar-group"
data-sidebar="group"
className={cn("relative flex w-full min-w-0 flex-col p-2", className)}
{...props}
/>
)
}
function SidebarGroupLabel({
className,
asChild = false,
...props
}: React.ComponentProps<"div"> & { asChild?: boolean }) {
const Comp = asChild ? Slot : "div"
return (
<Comp
data-slot="sidebar-group-label"
data-sidebar="group-label"
className={cn(
"text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
className
)}
{...props}
/>
)
}
function SidebarGroupAction({
className,
asChild = false,
...props
}: React.ComponentProps<"button"> & { asChild?: boolean }) {
const Comp = asChild ? Slot : "button"
return (
<Comp
data-slot="sidebar-group-action"
data-sidebar="group-action"
className={cn(
"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
// Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 md:after:hidden",
"group-data-[collapsible=icon]:hidden",
className
)}
{...props}
/>
)
}
function SidebarGroupContent({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="sidebar-group-content"
data-sidebar="group-content"
className={cn("w-full text-sm", className)}
{...props}
/>
)
}
function SidebarMenu({ className, ...props }: React.ComponentProps<"ul">) {
return (
<ul
data-slot="sidebar-menu"
data-sidebar="menu"
className={cn("flex w-full min-w-0 flex-col gap-1", className)}
{...props}
/>
)
}
function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) {
return (
<li
data-slot="sidebar-menu-item"
data-sidebar="menu-item"
className={cn("group/menu-item relative", className)}
{...props}
/>
)
}
const sidebarMenuButtonVariants = cva(
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
{
variants: {
variant: {
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
outline:
"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]",
},
size: {
default: "h-8 text-sm",
sm: "h-7 text-xs",
lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
function SidebarMenuButton({
asChild = false,
isActive = false,
variant = "default",
size = "default",
tooltip,
className,
...props
}: React.ComponentProps<"button"> & {
asChild?: boolean
isActive?: boolean
tooltip?: string | React.ComponentProps<typeof TooltipContent>
} & VariantProps<typeof sidebarMenuButtonVariants>) {
const Comp = asChild ? Slot : "button"
const { isMobile, state } = useSidebar()
const button = (
<Comp
data-slot="sidebar-menu-button"
data-sidebar="menu-button"
data-size={size}
data-active={isActive}
className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
{...props}
/>
)
if (!tooltip) {
return button
}
if (typeof tooltip === "string") {
tooltip = {
children: tooltip,
}
}
return (
<Tooltip>
<TooltipTrigger asChild>{button}</TooltipTrigger>
<TooltipContent
side="right"
align="center"
hidden={state !== "collapsed" || isMobile}
{...tooltip}
/>
</Tooltip>
)
}
function SidebarMenuAction({
className,
asChild = false,
showOnHover = false,
...props
}: React.ComponentProps<"button"> & {
asChild?: boolean
showOnHover?: boolean
}) {
const Comp = asChild ? Slot : "button"
return (
<Comp
data-slot="sidebar-menu-action"
data-sidebar="menu-action"
className={cn(
"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
// Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 md:after:hidden",
"peer-data-[size=sm]/menu-button:top-1",
"peer-data-[size=default]/menu-button:top-1.5",
"peer-data-[size=lg]/menu-button:top-2.5",
"group-data-[collapsible=icon]:hidden",
showOnHover &&
"peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0",
className
)}
{...props}
/>
)
}
function SidebarMenuBadge({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="sidebar-menu-badge"
data-sidebar="menu-badge"
className={cn(
"text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none",
"peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
"peer-data-[size=sm]/menu-button:top-1",
"peer-data-[size=default]/menu-button:top-1.5",
"peer-data-[size=lg]/menu-button:top-2.5",
"group-data-[collapsible=icon]:hidden",
className
)}
{...props}
/>
)
}
function SidebarMenuSkeleton({
className,
showIcon = false,
...props
}: React.ComponentProps<"div"> & {
showIcon?: boolean
}) {
// Random width between 50 to 90%.
const width = React.useMemo(() => {
return `${Math.floor(Math.random() * 40) + 50}%`
}, [])
return (
<div
data-slot="sidebar-menu-skeleton"
data-sidebar="menu-skeleton"
className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
{...props}
>
{showIcon && (
<Skeleton
className="size-4 rounded-md"
data-sidebar="menu-skeleton-icon"
/>
)}
<Skeleton
className="h-4 max-w-(--skeleton-width) flex-1"
data-sidebar="menu-skeleton-text"
style={
{
"--skeleton-width": width,
} as React.CSSProperties
}
/>
</div>
)
}
function SidebarMenuSub({ className, ...props }: React.ComponentProps<"ul">) {
return (
<ul
data-slot="sidebar-menu-sub"
data-sidebar="menu-sub"
className={cn(
"border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5",
"group-data-[collapsible=icon]:hidden",
className
)}
{...props}
/>
)
}
function SidebarMenuSubItem({
className,
...props
}: React.ComponentProps<"li">) {
return (
<li
data-slot="sidebar-menu-sub-item"
data-sidebar="menu-sub-item"
className={cn("group/menu-sub-item relative", className)}
{...props}
/>
)
}
function SidebarMenuSubButton({
asChild = false,
size = "md",
isActive = false,
className,
...props
}: React.ComponentProps<"a"> & {
asChild?: boolean
size?: "sm" | "md"
isActive?: boolean
}) {
const Comp = asChild ? Slot : "a"
return (
<Comp
data-slot="sidebar-menu-sub-button"
data-sidebar="menu-sub-button"
data-size={size}
data-active={isActive}
className={cn(
"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
size === "sm" && "text-xs",
size === "md" && "text-sm",
"group-data-[collapsible=icon]:hidden",
className
)}
{...props}
/>
)
}
export {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupAction,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarInput,
SidebarInset,
SidebarMenu,
SidebarMenuAction,
SidebarMenuBadge,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSkeleton,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarProvider,
SidebarRail,
SidebarSeparator,
SidebarTrigger,
// eslint-disable-next-line react-refresh/only-export-components
useSidebar,
}
+13
View File
@@ -0,0 +1,13 @@
import { cn } from "@/lib/utils"
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="skeleton"
className={cn("bg-accent animate-pulse rounded-md", className)}
{...props}
/>
)
}
export { Skeleton }
+61
View File
@@ -0,0 +1,61 @@
"use client"
import * as React from "react"
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
import { cn } from "@/lib/utils"
function TooltipProvider({
delayDuration = 0,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
return (
<TooltipPrimitive.Provider
data-slot="tooltip-provider"
delayDuration={delayDuration}
{...props}
/>
)
}
function Tooltip({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
return (
<TooltipProvider>
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
)
}
function TooltipTrigger({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
}
function TooltipContent({
className,
sideOffset = 0,
children,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
return (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
data-slot="tooltip-content"
sideOffset={sideOffset}
className={cn(
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
className
)}
{...props}
>
{children}
<TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
</TooltipPrimitive.Content>
</TooltipPrimitive.Portal>
)
}
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
+19
View File
@@ -0,0 +1,19 @@
import * as React from "react"
const MOBILE_BREAKPOINT = 768
export function useIsMobile() {
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
React.useEffect(() => {
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
const onChange = () => {
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
}
mql.addEventListener("change", onChange)
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
return () => mql.removeEventListener("change", onChange)
}, [])
return !!isMobile
}
+132
View File
@@ -0,0 +1,132 @@
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
:root {
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #09090b;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823);
--card: oklch(1 0 0);
--card-foreground: oklch(0.141 0.005 285.823);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.141 0.005 285.823);
--primary: oklch(0.21 0.006 285.885);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.967 0.001 286.375);
--secondary-foreground: oklch(0.21 0.006 285.885);
--muted: oklch(0.967 0.001 286.375);
--muted-foreground: oklch(0.552 0.016 285.938);
--accent: oklch(0.967 0.001 286.375);
--accent-foreground: oklch(0.21 0.006 285.885);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.92 0.004 286.32);
--input: oklch(0.92 0.004 286.32);
--ring: oklch(0.705 0.015 286.067);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.141 0.005 285.823);
--sidebar-primary: oklch(0.21 0.006 285.885);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.967 0.001 286.375);
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
--sidebar-border: oklch(0.92 0.004 286.32);
--sidebar-ring: oklch(0.705 0.015 286.067);
}
@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}
.dark {
--background: oklch(0.141 0.005 285.823);
--foreground: oklch(0.985 0 0);
--card: oklch(0.21 0.006 285.885);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.21 0.006 285.885);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.92 0.004 286.32);
--primary-foreground: oklch(0.21 0.006 285.885);
--secondary: oklch(0.274 0.006 286.033);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.274 0.006 286.033);
--muted-foreground: oklch(0.705 0.015 286.067);
--accent: oklch(0.274 0.006 286.033);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.552 0.016 285.938);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.21 0.006 285.885);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.274 0.006 286.033);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.552 0.016 285.938);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}
+6
View File
@@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
+13
View File
@@ -0,0 +1,13 @@
import {StrictMode} from 'react'
import {createRoot} from 'react-dom/client'
import './index.css'
import App from './App.tsx'
import {ThemeProvider} from "@/components/theme-provider"
createRoot(document.getElementById('root')!).render(
<StrictMode>
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
<App/>
</ThemeProvider>
</StrictMode>,
)
+1
View File
@@ -0,0 +1 @@
/// <reference types="vite/client" />
+35
View File
@@ -0,0 +1,35 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
/* shadcn */
"baseUrl": ".",
"paths": {
"@/*": [
"./src/*"
]
}
},
"include": ["src"]
}
+17
View File
@@ -0,0 +1,17 @@
{
"files": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.node.json"
}
],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
+25
View File
@@ -0,0 +1,25 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2023",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}
+14
View File
@@ -0,0 +1,14 @@
import path from "path"
import tailwindcss from "@tailwindcss/vite"
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
// https://vite.dev/config/
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
})