From f748c0816a10b8c044d62ba85a0922ce0a50dce9 Mon Sep 17 00:00:00 2001 From: aushe02 <32467683+aushe02@users.noreply.github.com> Date: Sat, 23 May 2026 09:51:26 -0400 Subject: [PATCH 1/4] UI setup --- .npmrc | 2 + .nvmrc | 1 + electron/main.ts | 4 +- index.html | 2 +- package-lock.json | 906 +++++++++++++++++++++++++++++++++-- package.json | 1 + src/index.css | 191 ++++++++ src/pages/home/home.test.tsx | 67 +-- src/pages/home/home.tsx | 240 ++++++---- 9 files changed, 1235 insertions(+), 179 deletions(-) create mode 100644 .npmrc create mode 100644 .nvmrc diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..66662a4 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +# Registry settings +registry=https://registry.npmjs.org/ diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..f677377 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24.11.1 \ No newline at end of file diff --git a/electron/main.ts b/electron/main.ts index 6a3fcab..1e372cf 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -30,7 +30,9 @@ function createWindow() { win = new BrowserWindow({ width: 1000, height: 700, - resizable: false, + resizable: true, + minWidth: 800, + minHeight: 600, icon: path.join(process.env.VITE_PUBLIC, "electron.svg"), webPreferences: { preload: path.join(__dirname, "preload.mjs"), diff --git a/index.html b/index.html index 7f98189..c32e4ab 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - Electron + Vite + React + FastAPI + OpenPep
diff --git a/package-lock.json b/package-lock.json index 6505dcb..c0e7732 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "electron-react-ts-fastapi-template", "version": "0.0.0", "dependencies": { + "@aushe02/openpep-storybook": "^0.1.0", "@radix-ui/react-slot": "^1.2.0", "@tailwindcss/vite": "^4.1.4", "axios": "^1.9.0", @@ -116,6 +117,46 @@ "dev": true, "license": "MIT" }, + "node_modules/@aushe02/openpep-storybook": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@aushe02/openpep-storybook/-/openpep-storybook-0.1.0.tgz", + "integrity": "sha512-OjIp04X5fnnCAIz1wcIgjz+MFlVlE8eBuKkpu4qzYEZsCoai4K+bWgeOTZPcVL0cZ229tXENrCsBPEEz4KmGsA==", + "license": "MIT", + "dependencies": { + "next": "16.2.6", + "react": "19.2.4", + "react-dom": "19.2.4" + }, + "engines": { + "node": ">=24.11.1" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@aushe02/openpep-storybook/node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@aushe02/openpep-storybook/node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -878,6 +919,16 @@ "node": ">=14.14" } }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", @@ -1541,56 +1592,522 @@ "node": ">=18.18.0" } }, - "node_modules/@humanfs/node": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", - "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", - "dev": true, - "license": "Apache-2.0", + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, "dependencies": { - "@humanfs/core": "^0.19.2", - "@humanfs/types": "^0.15.0", - "@humanwhocodes/retry": "^0.4.0" + "@emnapi/runtime": "^1.7.0" }, "engines": { - "node": ">=18.18.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanfs/types": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", - "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", - "dev": true, - "license": "Apache-2.0", + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=18.18.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12.22" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=18.18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://opencollective.com/libvips" } }, "node_modules/@isaacs/fs-minipass": { @@ -1711,6 +2228,140 @@ "node": ">=10" } }, + "node_modules/@next/env": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.6.tgz", + "integrity": "sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.6.tgz", + "integrity": "sha512-ZJGkkcNfYgrrMkqOdZ7zoLa1TOy0qpcMfk/z4Mh/FKUz40gVO+HNQWqmLxf67Z5WB64DRp0dhEbyHfel+6sJUg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.6.tgz", + "integrity": "sha512-v/YLBHIY132Ced3puBJ7YJKw1lqsCrgcNo2aRJlCEyQrrCeRJlvGlnmxhPxNQI3KE3N1DN5r9TPNPvka3nq5RQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.6.tgz", + "integrity": "sha512-RPOvqlYBbcQjkz9VQQDZ2T2bARIjXZV1KFlt+V2Mr6SW/e4I9fcKsaA0hdyf2FHoTlsV2xnBd5Y912rP/1Ce6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.6.tgz", + "integrity": "sha512-URUTu1+dMkxJsPFgm+OeEvq9wf5sujw0EvgYy80TDGHTSLTnIHeqb0Eu8A3sC95IRgjejQL+kC4mw+4yPxiAXA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.6.tgz", + "integrity": "sha512-DOj182mPV8G3UkrayLoREM5YEYI+Dk5wv7Ox9xl1fFibAELEsFD0lDPfHIeILlutMMfdyhlzYPELG3peuKaurw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.6.tgz", + "integrity": "sha512-HKQ5SP/V/ub73UvF7n/zeJlxk2kLmtL7Wzrg4WfmkjmNos5onJ2tKu7yZOPdL18A6Svfn3max29ym+ry7NkK4g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.6.tgz", + "integrity": "sha512-LZXpTlPyS5v7HhSmnvsLGP3iIYgYOBnc8r8ArlT55sGHV89bR2HlDdBjWQ+PY6SJMmk8TuVGFuxalnP3k/0Dwg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.6.tgz", + "integrity": "sha512-F0+4i0h9J6C4eE3EAPWsoCk7UW/dbzOjyzxY0qnDUOYFu6FFmdZ6l97/XdV3/Nz3VYyO7UWjyEJUXkGqcoXfMA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", @@ -2087,6 +2738,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -3490,6 +4150,18 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.32", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.32.tgz", + "integrity": "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/bidi-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", @@ -3691,7 +4363,6 @@ "version": "1.0.30001715", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz", "integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3805,6 +4476,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -4140,9 +4817,10 @@ } }, "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", "engines": { "node": ">=8" } @@ -5808,7 +6486,6 @@ "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@asamuzakjp/css-color": "^5.1.11", "@asamuzakjp/dom-selector": "^7.1.1", @@ -6438,6 +7115,87 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/next": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/next/-/next-16.2.6.tgz", + "integrity": "sha512-qOVgKJg1+At15NpeUP+eJgCHvTCgXsogweq87Ri/Ix7PkqQHg4sdaXmSFqKlgaIXE4kW0g25LE68W87UANlHtw==", + "license": "MIT", + "dependencies": { + "@next/env": "16.2.6", + "@swc/helpers": "0.5.15", + "baseline-browser-mapping": "^2.9.19", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.2.6", + "@next/swc-darwin-x64": "16.2.6", + "@next/swc-linux-arm64-gnu": "16.2.6", + "@next/swc-linux-arm64-musl": "16.2.6", + "@next/swc-linux-x64-gnu": "16.2.6", + "@next/swc-linux-x64-musl": "16.2.6", + "@next/swc-win32-arm64-msvc": "16.2.6", + "@next/swc-win32-x64-msvc": "16.2.6", + "sharp": "^0.34.5" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/node-abi": { "version": "4.31.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.31.0.tgz", @@ -7258,7 +8016,7 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -7297,6 +8055,51 @@ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==" }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -7494,6 +8297,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", diff --git a/package.json b/package.json index a033597..298cf6e 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "test:coverage": "vitest run --coverage" }, "dependencies": { + "@aushe02/openpep-storybook": "^0.1.0", "@radix-ui/react-slot": "^1.2.0", "@tailwindcss/vite": "^4.1.4", "axios": "^1.9.0", diff --git a/src/index.css b/src/index.css index 0643bf0..2e168bb 100644 --- a/src/index.css +++ b/src/index.css @@ -118,3 +118,194 @@ @apply bg-background text-foreground; } } + +/* ===================================================== + OpenPep — root sizing + Ensure the full viewport is available to the app at + all window sizes, with no inherited constraints. + ===================================================== */ + +html, +body, +#root { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; +} + +/* ===================================================== + OpenPep — app shell overrides + Remove the storybook titlebar row; use the native + Electron window titlebar instead. + ===================================================== */ + +.op-app { + grid-template-rows: 1fr !important; +} + +/* ===================================================== + OpenPep — fit-to-window layout overrides + Each view is wrapped in an op-view-{name} div so CSS + can target it precisely without guessing inline styles. + ===================================================== */ + +/* Workspace body: flex column so view wrappers fill it */ +.op-workspace-body { + display: flex !important; + flex-direction: column !important; + overflow: hidden !important; +} + +/* Default for all view wrappers: fill height, scroll */ +.op-workspace-body > [class^="op-view-"] { + flex: 1 1 0 !important; + min-height: 0 !important; + overflow-y: auto !important; + overflow-x: hidden !important; +} + +/* ---- Formula (Editor) view ---- */ + +/* Grid: header row auto, content row fills remaining height */ +.op-view-formula > div { + height: 100% !important; + grid-template-rows: auto 1fr !important; + align-items: stretch !important; + overflow: hidden !important; +} + +/* Left column: ingredients panel — fill its grid cell */ +.op-view-formula > div > .op-panel { + display: flex !important; + flex-direction: column !important; + overflow: hidden !important; + min-height: 0 !important; + height: auto !important; +} + +/* Ingredients table — scroll within the panel */ +.op-view-formula > div > .op-panel .op-panel-body-flush { + flex: 1 1 0 !important; + overflow-y: auto !important; + min-height: 0 !important; +} + +/* Right column: scroll the stacked panels as a group */ +.op-view-formula > div > div:last-child { + overflow-y: auto !important; + min-height: 0 !important; + align-content: start; +} + +/* Right column panels: don't clip content, column scrolls instead */ +.op-view-formula > div > div:last-child > .op-panel { + overflow: visible !important; + height: auto !important; + flex-shrink: 0 !important; +} + +/* ---- Library view ---- */ + +.op-view-library { + overflow: hidden !important; +} + +/* Grid: single 1fr row fills the wrapper height */ +.op-view-library > div { + height: 100% !important; + grid-template-rows: 1fr !important; + align-items: stretch !important; + overflow: hidden !important; +} + +/* Left panel (ingredient list): flex column, fill its grid cell */ +.op-view-library > div > .op-panel:first-child { + display: flex !important; + flex-direction: column !important; + overflow: hidden !important; + min-height: 0 !important; +} + +/* Search + chips section: stack vertically to reduce height */ +.op-view-library > div > .op-panel:first-child > div:nth-child(2) { + flex-direction: column !important; + align-items: stretch !important; +} + +/* Chips row: single line, horizontal scroll so they don't stack */ +.op-view-library > div > .op-panel:first-child > div:nth-child(2) > div:last-child { + flex-wrap: nowrap !important; + overflow-x: auto !important; +} + +/* Ingredient table: take all remaining panel height */ +.op-view-library > div > .op-panel:first-child .op-panel-body-flush { + flex: 1 1 0 !important; + overflow-y: auto !important; + min-height: 0 !important; +} + +/* Right detail panel: keep sticky/start alignment, scroll internally */ +.op-view-library > div > .op-panel:last-child { + align-self: start !important; + max-height: 100% !important; + overflow-y: auto !important; +} + +/* ---- Versions view ---- */ + +.op-view-versions { + overflow: hidden !important; +} + +/* Grid: single 1fr row fills wrapper height */ +.op-view-versions > div { + height: 100% !important; + grid-template-rows: 1fr !important; + align-items: stretch !important; + overflow: hidden !important; +} + +/* Left panel (timeline): flex column, fill its grid cell */ +.op-view-versions > div > .op-panel:first-child { + display: flex !important; + flex-direction: column !important; + overflow: hidden !important; + min-height: 0 !important; +} + +/* Header and stats rows: never compress */ +.op-view-versions > div > .op-panel:first-child > :not(:last-child) { + flex-shrink: 0 !important; +} + +/* Timeline list: fill remaining height and scroll */ +.op-view-versions > div > .op-panel:first-child > div:last-child { + flex: 1 1 0 !important; + overflow-y: auto !important; + min-height: 0 !important; +} + +/* Right panel (diff): keep sticky/start, scroll internally */ +.op-view-versions > div > .op-panel:last-child { + align-self: start !important; + max-height: 100% !important; + overflow-y: auto !important; +} + +/* Version entry note body: clamp to 2 lines so entries stay compact */ +.op-view-versions > div > .op-panel:first-child > div:last-child > div > div[style*="margin-top: 4px"] { + display: -webkit-box !important; + -webkit-line-clamp: 2 !important; + -webkit-box-orient: vertical !important; + overflow: hidden !important; +} + +/* Version entry stats footer: single row, no wrapping */ +.op-view-versions > div > .op-panel:first-child > div:last-child > div > div[style*="gap: 12px"] { + flex-wrap: nowrap !important; + overflow: hidden !important; + white-space: nowrap !important; +} diff --git a/src/pages/home/home.test.tsx b/src/pages/home/home.test.tsx index 29cde7f..1418af8 100644 --- a/src/pages/home/home.test.tsx +++ b/src/pages/home/home.test.tsx @@ -1,59 +1,20 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; -import { render, screen, waitFor } from "@testing-library/react"; -import HomePage from "./home"; - -const mockGet = vi.fn(); -const mockAxios = { get: mockGet }; - -vi.mock("@/hooks/useAxios", () => ({ - default: () => mockAxios, -})); - -describe("HomePage", () => { - beforeEach(() => { - mockGet.mockResolvedValue({ data: { message: "Hello from API" } }); - window.electron = { - sendNotification: vi.fn(), - openExternal: vi.fn(), - }; - }); - - it("renders static content", () => { - render(); - expect( - screen.getByText(/This template is designed/i) - ).toBeInTheDocument(); - }); - - it("fetches and displays the API message", async () => { - render(); - await waitFor(() => { - expect(screen.getByText("Hello from API")).toBeInTheDocument(); - }); - }); - - it("shows an error message when the fetch fails", async () => { - mockGet.mockRejectedValueOnce(new Error("Network error")); - render(); - await waitFor(() => { - expect(screen.getByText("An Error Occurred")).toBeInTheDocument(); - }); +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/react"; +import OpenPepApp from "./home"; + +describe("OpenPepApp", () => { + it("renders the app shell", () => { + render(); + expect(document.querySelector(".op-root")).toBeInTheDocument(); }); - it("renders the Refetch Data and Send Notification buttons", () => { - render(); - expect( - screen.getByRole("button", { name: /Refetch Data/i }) - ).toBeInTheDocument(); - expect( - screen.getByRole("button", { name: /Send Notification/i }) - ).toBeInTheDocument(); + it("renders the sidebar", () => { + render(); + expect(document.querySelector(".op-sidebar")).toBeInTheDocument(); }); - it("renders the See Guide button", () => { - render(); - expect( - screen.getByRole("button", { name: /See Guide/i }) - ).toBeInTheDocument(); + it("renders the workspace", () => { + render(); + expect(document.querySelector(".op-workspace")).toBeInTheDocument(); }); }); diff --git a/src/pages/home/home.tsx b/src/pages/home/home.tsx index e00c5fb..17b4ada 100644 --- a/src/pages/home/home.tsx +++ b/src/pages/home/home.tsx @@ -1,95 +1,167 @@ -import { Button } from "@/components/ui/button"; -import useAxios from "@/hooks/useAxios"; -import { useEffect, useState } from "react"; -import logoVite from "../../assets/vite.svg"; -import logoReact from "../../assets/react.svg"; -import logoElectron from "../../assets/electron.svg"; -import logoFastAPI from "../../assets/fastapi.svg"; +import { useState, useEffect } from "react"; +import "@aushe02/openpep-storybook/tokens.css"; +import { + Sidebar, + WorkspaceHeader, + FormulaView, + ResultsView, + VersionsView, + CompareView, + LibraryView, + IoView, + SettingsView, + Button, + Icons, + FORMULAS, + DEFAULT_CONDITIONS, + type NavView, + type Formula, +} from "@aushe02/openpep-storybook"; -const HomePage = () => { - const axios = useAxios(); - const [loading, setLoading] = useState(false); - const [message, setMessage] = useState(""); - const [refetchData, setRefetchData] = useState(false); +const FORMULA_PALETTE = ["#0ea5e9", "#a78bfa", "#34d399", "#f472b6", "#fbbf24"]; + +export default function OpenPepApp() { + const [formulas, setFormulas] = useState(() => + structuredClone(FORMULAS) + ); + const [currentFormulaId, setCurrentFormulaId] = useState(formulas[0].id); + const [view, setView] = useState("formula"); + const current = formulas.find((f) => f.id === currentFormulaId) ?? formulas[0]; useEffect(() => { - const fetchData = async () => { - try { - setLoading(true); - const response = await axios.get("/data"); - setMessage(response.data.message); - } catch { - setMessage("An Error Occurred"); - } finally { - setLoading(false); - } + document.title = `OpenPep — ${current.name}`; + }, [current.name]); + + const updateFormula = (next: Formula) => { + setFormulas((prev) => prev.map((f) => (f.id === next.id ? next : f))); + }; + + const newFormula = () => { + const id = "f-" + Date.now(); + const f: Formula = { + id, + name: "Untitled formula", + starred: false, + color: FORMULA_PALETTE[formulas.length % FORMULA_PALETTE.length], + description: "New propellant — start adding ingredients.", + tags: ["draft"], + updatedAt: "just now", + currentVersion: "v0.1.0", + components: [ + { ingredientId: null, weight: 0 }, + { ingredientId: null, weight: 0 }, + { ingredientId: null, weight: 0 }, + ], + conditions: { ...DEFAULT_CONDITIONS }, + results: { + isp: 0, + cstar: 0, + density: 0, + molecularWt: 0, + cpcv: 0, + chamberTemp: 0, + exhaustTemp: 0, + expansionRatio: 1, + }, }; - fetchData(); - }, [refetchData, axios]); + setFormulas((prev) => [...prev, f]); + setCurrentFormulaId(id); + setView("formula"); + }; - return ( -
-
- Electron - React - Vite - FastAPI -
-

- This template is designed to quickly bootstrap projects. -

-
-

- Start by customizing the components and backend to fit your needs. - Happy coding! -

-
-

- {loading ? "Loading" : <>{message}} -

-
- - -
- -
-
- -
+ + ), + results: ( + <> + + + + ), + versions: ( + + ), + compare: null, + library: null, + io: null, + settings: null, + }; -
-

- Created by me for the community to use! -

-
+ return ( +
+
+ { + setCurrentFormulaId(id); + setView("formula"); + }} + onNewFormula={newFormula} + /> +
+ +
+ {view === "formula" && ( +
+ setView("results")} + /> +
+ )} + {view === "results" &&
} + {view === "versions" &&
} + {view === "compare" && ( +
+ +
+ )} + {view === "library" &&
} + {view === "io" &&
} + {view === "settings" &&
} +
+
+
); -}; - -export default HomePage; +} From d88cc41503a1ef0cc34b2a773212c4f650e17e93 Mon Sep 17 00:00:00 2001 From: aushe02 <32467683+aushe02@users.noreply.github.com> Date: Sat, 23 May 2026 09:52:35 -0400 Subject: [PATCH 2/4] UI setup --- eslint.config.js | 4 ++-- src/pages/home/home.test.tsx | 2 +- src/pages/home/home.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 2a3a1ff..c431674 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -13,7 +13,7 @@ export default [ files: ['src/**/*.{ts,tsx}', 'electron/preload.ts'], languageOptions: { parser: tsParser, - ecmaVersion: 2020, + ecmaVersion: 2022, globals: sanitize(globals.browser), }, plugins: { @@ -35,7 +35,7 @@ export default [ files: ['electron/main.ts', 'vite.config.ts', 'vitest.config.ts'], languageOptions: { parser: tsParser, - ecmaVersion: 2020, + ecmaVersion: 2022, globals: sanitize(globals.node), }, plugins: { diff --git a/src/pages/home/home.test.tsx b/src/pages/home/home.test.tsx index 1418af8..f80d3f0 100644 --- a/src/pages/home/home.test.tsx +++ b/src/pages/home/home.test.tsx @@ -1,5 +1,5 @@ import { describe, it, expect } from "vitest"; -import { render, screen } from "@testing-library/react"; +import { render } from "@testing-library/react"; import OpenPepApp from "./home"; describe("OpenPepApp", () => { diff --git a/src/pages/home/home.tsx b/src/pages/home/home.tsx index 17b4ada..cd012fd 100644 --- a/src/pages/home/home.tsx +++ b/src/pages/home/home.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import React, { useState, useEffect } from "react"; import "@aushe02/openpep-storybook/tokens.css"; import { Sidebar, From 99581bb11d6954cc5d8d07221656e1d278c4f180 Mon Sep 17 00:00:00 2001 From: aushe02 <32467683+aushe02@users.noreply.github.com> Date: Sat, 23 May 2026 09:53:16 -0400 Subject: [PATCH 3/4] UI setup --- eslint.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index c431674..b414eb5 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -14,7 +14,7 @@ export default [ languageOptions: { parser: tsParser, ecmaVersion: 2022, - globals: sanitize(globals.browser), + globals: { ...sanitize(globals.browser), structuredClone: 'readonly' }, }, plugins: { '@typescript-eslint': tsPlugin, From 112a6a1a46e14559307bf816b2d70fbef1b36225 Mon Sep 17 00:00:00 2001 From: aushe02 <32467683+aushe02@users.noreply.github.com> Date: Sat, 23 May 2026 10:00:29 -0400 Subject: [PATCH 4/4] Update pipelines --- .github/workflows/ci.yml | 14 -------------- vitest.config.ts | 12 +++++++++++- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9ed2ec..d9112ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,20 +7,6 @@ on: branches: [main, develop] jobs: - squash-check: - name: Squash Check - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' && github.base_ref == 'develop' - steps: - - name: Require single commit - run: | - COUNT=${{ github.event.pull_request.commits }} - if [ "$COUNT" -ne 1 ]; then - echo "PRs to develop must be squashed into a single commit. Found $COUNT commits." - exit 1 - fi - echo "Squash check passed ($COUNT commit)." - lint: name: Lint runs-on: ubuntu-latest diff --git a/vitest.config.ts b/vitest.config.ts index fd3095e..90abe02 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -8,11 +8,21 @@ const __dirname = fileURLToPath(new URL(".", import.meta.url)); export default defineConfig({ plugins: [react()], resolve: { - alias: { "@": path.resolve(__dirname, "src") }, + alias: { + "@": path.resolve(__dirname, "src"), + react: path.resolve(__dirname, "node_modules/react"), + "react-dom": path.resolve(__dirname, "node_modules/react-dom"), + }, + dedupe: ["react", "react-dom"], }, test: { environment: "jsdom", setupFiles: ["./src/test-setup.ts"], + server: { + deps: { + inline: ["@aushe02/openpep-storybook"], + }, + }, coverage: { provider: "v8", reporter: ["text", "lcov"],