This commit is contained in:
Arthur Belleville 2025-10-10 11:06:44 +02:00
parent bafe29086a
commit 374a1ec4b8
No known key found for this signature in database
116 changed files with 653 additions and 589 deletions

View file

@ -12,7 +12,7 @@ repos:
entry: just typecheck
language: python
pass_filenames: false
files: \.ts*
files: ^ui/.*\.(ts|tsx)$
- id: test-ui
name: Test Frontend
entry: just test-frontend

View file

@ -1,18 +0,0 @@
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReact from "eslint-plugin-react";
/** @type {import('eslint').Linter.Config[]} */
export default [
{ files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"] },
{ languageOptions: { globals: globals.browser } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
pluginReact.configs.flat.recommended,
{
rules: {
"react/react-in-jsx-scope": "off",
},
},
];

View file

@ -6,16 +6,18 @@
"scripts": {
"dev": "vite dev",
"typecheck": "npx tsgo --build .",
"lint": "eslint .",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write .",
"preview": "vite preview",
"build:staging": "tsc -b && vite build --mode staging",
"build:prod": "tsc -b && vite build --mode production",
"deploy:staging": "pnpm run build:staging && wrangler deploy",
"deploy:prod": "pnpm run build:prod && wrangler deploy",
"cf-typegen": "wrangler types",
"test": "vitest run --mode dev",
"test:watch": "vitest watch",
"test:coverage": "vitest run --coverage"
"test": "vitest run --mode dev --passWithNoTests",
"test:watch": "vitest watch --passWithNoTests",
"test:coverage": "vitest run --coverage --passWithNoTests"
},
"devDependencies": {
"@biomejs/biome": "2.2.5",
@ -42,6 +44,7 @@
"eslint": "^9.22.0",
"eslint-plugin-react": "^7.37.4",
"globals": "^16.0.0",
"happy-dom": "^20.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"lucide-react": "^0.460.0",
@ -58,7 +61,7 @@
"typescript-eslint": "^8.26.1",
"vite": "^6.2.2",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.1.1",
"vitest": "^3.2.4",
"wrangler": "^4.24.3"
},
"dependencies": {

View file

@ -144,6 +144,9 @@ importers:
globals:
specifier: ^16.0.0
version: 16.0.0
happy-dom:
specifier: ^20.0.0
version: 20.0.0
jest:
specifier: ^29.7.0
version: 29.7.0(@types/node@22.13.10)
@ -193,8 +196,8 @@ importers:
specifier: ^5.1.4
version: 5.1.4(typescript@5.7.3)(vite@6.2.2(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2))
vitest:
specifier: ^3.1.1
version: 3.1.1(@types/debug@4.1.12)(@types/node@22.13.10)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.29.2)
specifier: ^3.2.4
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.13.10)(happy-dom@20.0.0)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.29.2)
wrangler:
specifier: ^4.24.3
version: 4.24.3
@ -2065,12 +2068,18 @@ packages:
'@types/babel__traverse@7.20.6':
resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==}
'@types/chai@5.2.2':
resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==}
'@types/cookie@0.6.0':
resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
'@types/estree-jsx@1.0.5':
resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
@ -2122,6 +2131,9 @@ packages:
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
'@types/node@20.19.20':
resolution: {integrity: sha512-2Q7WS25j4pS1cS8yw3d6buNCVJukOTeQ39bAnwR6sOJbaxvyCGebzTMypDFN82CxBLnl+lSWVdCCWbRY6y9yZQ==}
'@types/node@22.13.10':
resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==}
@ -2160,6 +2172,9 @@ packages:
'@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
'@types/whatwg-mimetype@3.0.2':
resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==}
'@types/ws@8.18.0':
resolution: {integrity: sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==}
@ -2331,34 +2346,34 @@ packages:
peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0
'@vitest/expect@3.1.1':
resolution: {integrity: sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==}
'@vitest/expect@3.2.4':
resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
'@vitest/mocker@3.1.1':
resolution: {integrity: sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==}
'@vitest/mocker@3.2.4':
resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==}
peerDependencies:
msw: ^2.4.9
vite: ^5.0.0 || ^6.0.0
vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0
peerDependenciesMeta:
msw:
optional: true
vite:
optional: true
'@vitest/pretty-format@3.1.1':
resolution: {integrity: sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==}
'@vitest/pretty-format@3.2.4':
resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
'@vitest/runner@3.1.1':
resolution: {integrity: sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==}
'@vitest/runner@3.2.4':
resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==}
'@vitest/snapshot@3.1.1':
resolution: {integrity: sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==}
'@vitest/snapshot@3.2.4':
resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==}
'@vitest/spy@3.1.1':
resolution: {integrity: sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==}
'@vitest/spy@3.2.4':
resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
'@vitest/utils@3.1.1':
resolution: {integrity: sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==}
'@vitest/utils@3.2.4':
resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
abab@2.0.6:
resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
@ -2778,6 +2793,15 @@ packages:
supports-color:
optional: true
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
decimal.js@10.5.0:
resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==}
@ -2926,8 +2950,8 @@ packages:
resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==}
engines: {node: '>= 0.4'}
es-module-lexer@1.6.0:
resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==}
es-module-lexer@1.7.0:
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
es-object-atoms@1.1.1:
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
@ -3239,6 +3263,10 @@ packages:
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
happy-dom@20.0.0:
resolution: {integrity: sha512-GkWnwIFxVGCf2raNrxImLo397RdGhLapj5cT3R2PT7FwL62Ze1DROhzmYW7+J3p9105DYMVenEejEbnq5wA37w==}
engines: {node: '>=20.0.0'}
has-bigints@1.1.0:
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
engines: {node: '>= 0.4'}
@ -3718,6 +3746,9 @@ packages:
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
js-tokens@9.0.1:
resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
js-yaml@3.14.1:
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
hasBin: true
@ -3943,6 +3974,9 @@ packages:
loupe@3.1.3:
resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==}
loupe@3.2.1:
resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
@ -4852,6 +4886,9 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
strip-literal@3.1.0:
resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
style-to-js@1.1.17:
resolution: {integrity: sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==}
@ -4916,16 +4953,16 @@ packages:
resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
engines: {node: '>=12.0.0'}
tinypool@1.0.2:
resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==}
tinypool@1.1.1:
resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
engines: {node: ^18.0.0 || >=20.0.0}
tinyrainbow@2.0.0:
resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
engines: {node: '>=14.0.0'}
tinyspy@3.0.2:
resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
tinyspy@4.0.4:
resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==}
engines: {node: '>=14.0.0'}
tmpl@1.0.5:
@ -5036,6 +5073,9 @@ packages:
undici-types@6.20.0:
resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
undici@5.29.0:
resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==}
engines: {node: '>=14.0'}
@ -5153,8 +5193,8 @@ packages:
vfile@6.0.3:
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
vite-node@3.1.1:
resolution: {integrity: sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==}
vite-node@3.2.4:
resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
@ -5206,16 +5246,16 @@ packages:
yaml:
optional: true
vitest@3.1.1:
resolution: {integrity: sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==}
vitest@3.2.4:
resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@types/debug': ^4.1.12
'@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
'@vitest/browser': 3.1.1
'@vitest/ui': 3.1.1
'@vitest/browser': 3.2.4
'@vitest/ui': 3.2.4
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
@ -7625,12 +7665,18 @@ snapshots:
dependencies:
'@babel/types': 7.26.8
'@types/chai@5.2.2':
dependencies:
'@types/deep-eql': 4.0.2
'@types/cookie@0.6.0': {}
'@types/debug@4.1.12':
dependencies:
'@types/ms': 2.1.0
'@types/deep-eql@4.0.2': {}
'@types/estree-jsx@1.0.5':
dependencies:
'@types/estree': 1.0.6
@ -7693,6 +7739,10 @@ snapshots:
'@types/ms@2.1.0': {}
'@types/node@20.19.20':
dependencies:
undici-types: 6.21.0
'@types/node@22.13.10':
dependencies:
undici-types: 6.20.0
@ -7732,6 +7782,8 @@ snapshots:
'@types/unist@3.0.3': {}
'@types/whatwg-mimetype@3.0.2': {}
'@types/ws@8.18.0':
dependencies:
'@types/node': 22.13.10
@ -7951,44 +8003,46 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@vitest/expect@3.1.1':
'@vitest/expect@3.2.4':
dependencies:
'@vitest/spy': 3.1.1
'@vitest/utils': 3.1.1
'@types/chai': 5.2.2
'@vitest/spy': 3.2.4
'@vitest/utils': 3.2.4
chai: 5.2.0
tinyrainbow: 2.0.0
'@vitest/mocker@3.1.1(vite@6.2.2(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2))':
'@vitest/mocker@3.2.4(vite@6.2.2(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2))':
dependencies:
'@vitest/spy': 3.1.1
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
vite: 6.2.2(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)
'@vitest/pretty-format@3.1.1':
'@vitest/pretty-format@3.2.4':
dependencies:
tinyrainbow: 2.0.0
'@vitest/runner@3.1.1':
'@vitest/runner@3.2.4':
dependencies:
'@vitest/utils': 3.1.1
'@vitest/utils': 3.2.4
pathe: 2.0.3
strip-literal: 3.1.0
'@vitest/snapshot@3.1.1':
'@vitest/snapshot@3.2.4':
dependencies:
'@vitest/pretty-format': 3.1.1
'@vitest/pretty-format': 3.2.4
magic-string: 0.30.17
pathe: 2.0.3
'@vitest/spy@3.1.1':
'@vitest/spy@3.2.4':
dependencies:
tinyspy: 3.0.2
tinyspy: 4.0.4
'@vitest/utils@3.1.1':
'@vitest/utils@3.2.4':
dependencies:
'@vitest/pretty-format': 3.1.1
loupe: 3.1.3
'@vitest/pretty-format': 3.2.4
loupe: 3.2.1
tinyrainbow: 2.0.0
abab@2.0.6: {}
@ -8444,6 +8498,10 @@ snapshots:
dependencies:
ms: 2.1.3
debug@4.4.3:
dependencies:
ms: 2.1.3
decimal.js@10.5.0: {}
decode-named-character-reference@1.2.0:
@ -8639,7 +8697,7 @@ snapshots:
iterator.prototype: 1.1.5
safe-array-concat: 1.1.3
es-module-lexer@1.6.0: {}
es-module-lexer@1.7.0: {}
es-object-atoms@1.1.1:
dependencies:
@ -9036,6 +9094,12 @@ snapshots:
graphemer@1.4.0: {}
happy-dom@20.0.0:
dependencies:
'@types/node': 20.19.20
'@types/whatwg-mimetype': 3.0.2
whatwg-mimetype: 3.0.0
has-bigints@1.1.0: {}
has-flag@4.0.0: {}
@ -9741,6 +9805,8 @@ snapshots:
js-tokens@4.0.0: {}
js-tokens@9.0.1: {}
js-yaml@3.14.1:
dependencies:
argparse: 1.0.10
@ -9963,6 +10029,8 @@ snapshots:
loupe@3.1.3: {}
loupe@3.2.1: {}
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
@ -11307,6 +11375,10 @@ snapshots:
strip-json-comments@3.1.1: {}
strip-literal@3.1.0:
dependencies:
js-tokens: 9.0.1
style-to-js@1.1.17:
dependencies:
style-to-object: 1.0.9
@ -11364,11 +11436,11 @@ snapshots:
fdir: 6.4.6(picomatch@4.0.2)
picomatch: 4.0.2
tinypool@1.0.2: {}
tinypool@1.1.1: {}
tinyrainbow@2.0.0: {}
tinyspy@3.0.2: {}
tinyspy@4.0.4: {}
tmpl@1.0.5: {}
@ -11478,6 +11550,8 @@ snapshots:
undici-types@6.20.0: {}
undici-types@6.21.0: {}
undici@5.29.0:
dependencies:
'@fastify/busboy': 2.1.1
@ -11639,11 +11713,11 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.2
vite-node@3.1.1(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2):
vite-node@3.2.4(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2):
dependencies:
cac: 6.7.14
debug: 4.4.0
es-module-lexer: 1.6.0
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
vite: 6.2.2(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)
transitivePeerDependencies:
@ -11682,31 +11756,35 @@ snapshots:
jiti: 2.4.2
lightningcss: 1.29.2
vitest@3.1.1(@types/debug@4.1.12)(@types/node@22.13.10)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.29.2):
vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.13.10)(happy-dom@20.0.0)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.29.2):
dependencies:
'@vitest/expect': 3.1.1
'@vitest/mocker': 3.1.1(vite@6.2.2(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2))
'@vitest/pretty-format': 3.1.1
'@vitest/runner': 3.1.1
'@vitest/snapshot': 3.1.1
'@vitest/spy': 3.1.1
'@vitest/utils': 3.1.1
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
'@vitest/mocker': 3.2.4(vite@6.2.2(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
'@vitest/spy': 3.2.4
'@vitest/utils': 3.2.4
chai: 5.2.0
debug: 4.4.0
debug: 4.4.3
expect-type: 1.2.1
magic-string: 0.30.17
pathe: 2.0.3
picomatch: 4.0.2
std-env: 3.9.0
tinybench: 2.9.0
tinyexec: 0.3.2
tinypool: 1.0.2
tinyglobby: 0.2.14
tinypool: 1.1.1
tinyrainbow: 2.0.0
vite: 6.2.2(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)
vite-node: 3.1.1(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)
vite-node: 3.2.4(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/debug': 4.1.12
'@types/node': 22.13.10
happy-dom: 20.0.0
jsdom: 20.0.3
transitivePeerDependencies:
- jiti

View file

@ -1,10 +1,10 @@
import { BrowserRouter as Router, useRoutes } from "react-router-dom";
import { ThemeProvider } from "@ui/contexts/ThemeContext";
import { SessionProvider } from "@ui/contexts/SessionContext";
import { AllCommunityModule, ModuleRegistry } from "ag-grid-community";
import { UserStoreProvider } from "@ui/providers/UserStoreProvider";
import { DatadogRumProvider } from "@ui/providers/DatadogRumProvider";
import { ThemeProvider } from "@ui/contexts/ThemeContext";
import { routes } from "@ui/lib/routes";
import { DatadogRumProvider } from "@ui/providers/DatadogRumProvider";
import { UserStoreProvider } from "@ui/providers/UserStoreProvider";
import { AllCommunityModule, ModuleRegistry } from "ag-grid-community";
import { BrowserRouter as Router, useRoutes } from "react-router-dom";
// Register all Community features
ModuleRegistry.registerModules([AllCommunityModule]);

View file

@ -1,7 +1,7 @@
import { useEffect, useState } from "react";
import { useSession } from "../contexts/SessionContext";
import { Navigate, Outlet, useSearchParams } from "react-router-dom";
import { match } from "ts-pattern";
import { useSession } from "../contexts/SessionContext";
import { LoadingSpinner } from "./LoadingSpinner";
export const AuthenticationGateway = () => {

View file

@ -1,8 +1,8 @@
import { screen, waitFor } from "@testing-library/react";
import { AuthenticationGateway } from "@ui/components/AuthenticationGateway";
import { Routes, Route } from "react-router-dom";
import { SessionTestProvider } from "@ui/contexts/SessionContext";
import { renderWithRouter } from "@ui/utils/testHelpers";
import { Route, Routes } from "react-router-dom";
describe("PublicRoute", () => {
it("shows loading state initially", () => {

View file

@ -1,16 +1,17 @@
import { useState } from "react";
import { Switch } from "@ui/ui-library/switch";
import { Text } from "@ui/ui-library/text";
import { Button } from "@ui/ui-library/button";
import { MinusIcon, PlusIcon, CopyIcon } from "@ui/ui-library/icons";
import { CopyIcon, MinusIcon, PlusIcon } from "@ui/ui-library/icons";
import {
Select,
SelectButton,
SelectPopover,
SelectListBox,
SelectListItem,
SelectPopover,
} from "@ui/ui-library/select";
import { Switch } from "@ui/ui-library/switch";
import { Text } from "@ui/ui-library/text";
import { useTimePicker } from "@ui/ui-library/time-picker";
import { useState } from "react";
interface TimeRange {
start: string;
end: string;

View file

@ -1,6 +1,6 @@
import { render, screen, fireEvent } from "@testing-library/react";
import { LoginWithGoogle } from "./LoginWithGoogle";
import { useLoginGoogle } from "../../hooks/auth";
import { fireEvent, render, screen } from "@testing-library/react";
import { LoginWithGoogle } from "@ui/components/BrandButtons/LoginWithGoogle";
import { useLoginGoogle } from "@ui/hooks/auth";
import { vi } from "vitest";
vi.mock("../../hooks/auth", () => ({

View file

@ -1,9 +1,9 @@
import { ChannelBadge } from "@ui/components/ChannelBadge";
import { UserTablo } from "@ui/types/tablos.types";
import { Badge } from "@ui/ui-library/badge";
import { ReactNode } from "react";
import { Channel } from "stream-chat";
import { twMerge } from "tailwind-merge";
import { ChannelBadge } from "@ui/components/ChannelBadge";
interface ChannelPreviewProps {
channel: Channel;

View file

@ -1,8 +1,8 @@
import { useState } from "react";
import { ImageColorPicker } from "./ImageColorPicker";
import { ClickOutside } from "./ClickOutside";
import { StatusPicker } from "./StatusPicker";
import { Database } from "@ui/types/database.types";
import { useState } from "react";
import { ClickOutside } from "./ClickOutside";
import { ImageColorPicker } from "./ImageColorPicker";
import { StatusPicker } from "./StatusPicker";
type Tablo = Database["public"]["Tables"]["tablos"]["Row"];
type StatusType = "todo" | "in_progress" | "done";

View file

@ -1,6 +1,6 @@
import { UserTablo } from "@ui/types/tablos.types";
import { ChannelHeader, useChannelStateContext } from "stream-chat-react";
import { ChannelBadge } from "./ChannelBadge";
import { UserTablo } from "@ui/types/tablos.types";
interface CustomChannelHeaderProps {
tablos: UserTablo[];

View file

@ -1,5 +1,5 @@
import { ClickOutside } from "./ClickOutside";
import { UserTablo } from "@ui/types/tablos.types";
import { ClickOutside } from "./ClickOutside";
interface DeleteTabloModalProps {
tablo: UserTablo | null;

View file

@ -1,10 +1,10 @@
import { EventAndTablo } from "@ui/types/events.types";
import { DialogBody } from "@ui/ui-library/dialog";
import { Text, Strong } from "@ui/ui-library/text";
import { Button } from "@ui/ui-library/button";
import { DialogBody } from "@ui/ui-library/dialog";
import { Strong, Text } from "@ui/ui-library/text";
import { CalendarIcon, User } from "lucide-react";
import { CustomModal } from "./CustomModal";
import { twMerge } from "tailwind-merge";
import { CustomModal } from "./CustomModal";
interface EventDetailsModalProps {
event: EventAndTablo | null;

View file

@ -1,19 +1,19 @@
import { Event, EventInsert } from "@ui/types/events.types";
import { useState, useEffect } from "react";
import { useTablosList } from "@ui/hooks/tablos";
import { getLocalTimeZone, parseDate, today } from "@internationalized/date";
import { useCreateEvents, useEvent, useUpdateEvent } from "@ui/hooks/events";
import { useTablosList } from "@ui/hooks/tablos";
import { useUser } from "@ui/providers/UserStoreProvider";
import { Event, EventInsert } from "@ui/types/events.types";
import { DatePicker, DatePickerButton } from "@ui/ui-library/date-picker";
import {
Select,
SelectButton,
SelectPopover,
SelectListBox,
SelectListItem,
SelectPopover,
} from "@ui/ui-library/select";
import { useTimePicker } from "@ui/ui-library/time-picker";
import { DatePicker, DatePickerButton } from "@ui/ui-library/date-picker";
import { useEffect, useState } from "react";
import { Group } from "react-aria-components";
import { getLocalTimeZone, parseDate, today } from "@internationalized/date";
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
export const EventModal = ({ mode }: { mode: "create" | "edit" }) => {

View file

@ -1,6 +1,6 @@
import { EventTypeConfig } from "@ui/hooks/event-types";
import { Button } from "@ui/ui-library/button";
import { CustomModal } from "./CustomModal";
import { Label, TextField, TextArea, Description, Input } from "@ui/ui-library/field";
import { Description, Input, Label, TextArea, TextField } from "@ui/ui-library/field";
import { NumberField, NumberInput } from "@ui/ui-library/number-field";
import {
Select,
@ -9,7 +9,7 @@ import {
SelectListItem,
SelectPopover,
} from "@ui/ui-library/select";
import { EventTypeConfig } from "@ui/hooks/event-types";
import { CustomModal } from "./CustomModal";
export function EventTypeModal({
isModalOpen,

View file

@ -1,18 +1,18 @@
import { useState, useRef } from "react";
import { useTablosList, useCreateTablo } from "@ui/hooks/tablos";
import { useCreateEvents } from "@ui/hooks/events";
import { useCreateTablo, useTablosList } from "@ui/hooks/tablos";
import { useUser } from "@ui/providers/UserStoreProvider";
import { EventInsert } from "@ui/types/events.types";
import { CreateTablo } from "@ui/types/tablos.types";
import {
Select,
SelectButton,
SelectPopover,
SelectListBox,
SelectListItem,
SelectPopover,
} from "@ui/ui-library/select";
import { parseICSFile, ParsedICSEvent } from "@ui/utils/helpers";
import { EventInsert } from "@ui/types/events.types";
import { CreateTablo } from "@ui/types/tablos.types";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { ParsedICSEvent, parseICSFile } from "@ui/utils/helpers";
import { useRef, useState } from "react";
interface ImportICSModalProps {
onClose: () => void;

View file

@ -1,4 +1,4 @@
import { render, screen, fireEvent } from "@testing-library/react";
import { fireEvent, render, screen } from "@testing-library/react";
import { Layout } from "@ui/components/Layout";
import { SessionProvider } from "@ui/contexts/SessionContext";
import { renderWithProviders } from "@ui/utils/testHelpers";

View file

@ -1,10 +1,10 @@
import { MenuIcon } from "lucide-react";
import { useState } from "react";
import { SideNavigation } from "./NavigationBar";
import { Outlet } from "react-router-dom";
import { twMerge } from "tailwind-merge";
import { Button } from "../ui-library/button";
import { Icon } from "../ui-library/icon";
import { MenuIcon } from "lucide-react";
import { twMerge } from "tailwind-merge";
import { Outlet } from "react-router-dom";
import { SideNavigation } from "./NavigationBar";
export function Layout() {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);

View file

@ -1,6 +1,7 @@
import { screen, fireEvent } from "@testing-library/react";
import { SideNavigation, MainNavigation, UserMenuPopover } from "@ui/components/NavigationBar";
import { fireEvent, screen } from "@testing-library/react";
import { MainNavigation, SideNavigation, UserMenuPopover } from "@ui/components/NavigationBar";
import { renderWithProviders } from "@ui/utils/testHelpers";
describe("NavigationBar", () => {
describe("SideNavigation", () => {
it("renders the side navigation with correct initial state", () => {

View file

@ -1,38 +1,37 @@
import { twMerge } from "tailwind-merge";
import { useUser } from "@ui/providers/UserStoreProvider";
import { Avatar, AvatarBadge } from "@ui/ui-library/avatar";
import { Button } from "@ui/ui-library/button";
import { Dialog } from "@ui/ui-library/dialog";
import { Disclosure, DisclosureControl, DisclosurePanel } from "@ui/ui-library/disclosure";
import { Icon } from "@ui/ui-library/icon";
import { AvailableIcon } from "@ui/ui-library/icons";
import { Link } from "@ui/ui-library/link";
import { Popover } from "@ui/ui-library/popover";
import { Text } from "@ui/ui-library/text";
import { isProd, isStaging } from "@ui/utils/helpers";
import { getXtabloIcon } from "@ui/utils/iconHelpers";
import {
SendIcon,
CalendarCheckIcon,
CalendarIcon,
ChevronRightIcon,
ConstructionIcon,
PlusIcon,
MinusIcon,
ReceiptTextIcon,
Grid2X2Icon,
NotebookPenIcon,
MessageCircleIcon,
SquareKanban,
Kanban,
CalendarIcon,
CalendarCheckIcon,
ListCheckIcon,
MessageCircleIcon,
MinusIcon,
NotebookPenIcon,
PlusIcon,
ReceiptTextIcon,
SendIcon,
SquareKanban,
} from "lucide-react";
import { useRef, useState } from "react";
import { LinkProps, Separator } from "react-aria-components";
import { Link as RouterLink, useLocation } from "react-router-dom";
import { Separator } from "react-aria-components";
import { Link } from "@ui/ui-library/link";
import { Icon } from "@ui/ui-library/icon";
import { Avatar, AvatarBadge } from "@ui/ui-library/avatar";
import { Dialog } from "@ui/ui-library/dialog";
import { Button } from "@ui/ui-library/button";
import { DisclosurePanel, DisclosureControl, Disclosure } from "@ui/ui-library/disclosure";
import { LinkProps } from "react-aria-components";
import { Popover } from "@ui/ui-library/popover";
import { AvailableIcon } from "@ui/ui-library/icons";
import { useState, useRef } from "react";
import { getXtabloIcon } from "@ui/utils/iconHelpers";
import { ThemeSwitcher } from "./ThemeSwitcher";
import { Text } from "@ui/ui-library/text";
import { twMerge } from "tailwind-merge";
import { SignOutButton } from "./SignOutButton";
import { useUser } from "@ui/providers/UserStoreProvider";
import { isProd, isStaging } from "@ui/utils/helpers";
import { ThemeSwitcher } from "./ThemeSwitcher";
type NavLinkItem = {
isActive?: boolean;

View file

@ -2,7 +2,7 @@ import { screen, waitFor } from "@testing-library/react";
import { ProtectedRoute } from "@ui/components/ProtectedRoute";
import { SessionTestProvider } from "@ui/contexts/SessionContext";
import { renderWithRouter } from "@ui/utils/testHelpers";
import { Routes, Route } from "react-router-dom";
import { Route, Routes } from "react-router-dom";
describe("ProtectedRoute", () => {
beforeEach(() => {

View file

@ -1,7 +1,7 @@
import { useSession } from "@ui/contexts/SessionContext";
import { useEffect, useState } from "react";
import { Navigate, Outlet } from "react-router-dom";
import { match } from "ts-pattern";
import { useSession } from "@ui/contexts/SessionContext";
import { LoadingSpinner } from "./LoadingSpinner";
interface ProtectedRouteProps {

View file

@ -1,9 +1,9 @@
import React from "react";
import { DeleteDevisModalButton } from "@ui/components/devis/DeleteDevisModal";
import { ViewDevisModalButton } from "@ui/components/devis/ViewDevisModal";
import { Database } from "@ui/types/database.types";
import { Button } from "@ui/ui-library/button";
import { Download } from "lucide-react";
import React from "react";
type Devis = Database["public"]["Tables"]["devis"]["Row"];
interface RowActionMenuProps {

View file

@ -1,9 +1,9 @@
import { screen, fireEvent } from "@testing-library/react";
import { UseMutationResult } from "@tanstack/react-query";
import { fireEvent, screen } from "@testing-library/react";
import { SignOutButton } from "@ui/components/SignOutButton";
import * as AuthHooks from "@ui/hooks/auth";
import { UseMutationResult } from "@tanstack/react-query";
import { vi } from "vitest";
import { renderWithRouter } from "@ui/utils/testHelpers";
import { vi } from "vitest";
// Create a mock mutation result
const createMockMutationResult = (

View file

@ -1,7 +1,7 @@
import { Button } from "../ui-library/button";
import { useLogout } from "../hooks/auth";
import { LogOutIcon, AlertCircleIcon, CheckCircleIcon } from "lucide-react";
import { AlertCircleIcon, CheckCircleIcon, LogOutIcon } from "lucide-react";
import { useState } from "react";
import { useLogout } from "../hooks/auth";
import { Button } from "../ui-library/button";
import { toast } from "../ui-library/toast/toast-queue";
export const SignOutButton = () => {

View file

@ -1,21 +1,21 @@
import { ClickOutside } from "./ClickOutside";
import { useState, useEffect, useRef } from "react";
import { ImageColorPicker } from "./ImageColorPicker";
import { StatusPicker } from "./StatusPicker";
import { useInviteUser } from "@ui/hooks/invite";
import { TabloUpdate, UserTablo } from "@ui/types/tablos.types";
import { useTabloMembers } from "@ui/hooks/tablos";
import { useUser } from "@ui/providers/UserStoreProvider";
import {
useTabloFileNames,
useCreateTabloFile,
useDeleteTabloFile,
useDownloadTabloFile,
useTabloFileNames,
} from "@ui/hooks/tablo_data";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { FileTrigger } from "@ui/ui-library/file-trigger";
import { useTabloMembers } from "@ui/hooks/tablos";
import { useUser } from "@ui/providers/UserStoreProvider";
import { TabloUpdate, UserTablo } from "@ui/types/tablos.types";
import { Button } from "@ui/ui-library/button";
import { Trash2Icon, DownloadIcon } from "lucide-react";
import { FileTrigger } from "@ui/ui-library/file-trigger";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { DownloadIcon, Trash2Icon } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { ClickOutside } from "./ClickOutside";
import { ImageColorPicker } from "./ImageColorPicker";
import { StatusPicker } from "./StatusPicker";
type StatusType = "todo" | "in_progress" | "done";

View file

@ -1,7 +1,7 @@
import React, { useState } from "react";
import { Button } from "@ui/ui-library/button";
import { ArrowLeft, ArrowRight, HelpCircle, X } from "lucide-react";
import React, { useState } from "react";
import { twMerge } from "tailwind-merge";
import { X, ArrowRight, ArrowLeft, HelpCircle } from "lucide-react";
interface TutorialStep {
id: string;

View file

@ -1,4 +1,4 @@
import { render, screen, fireEvent } from "@testing-library/react";
import { fireEvent, render, screen } from "@testing-library/react";
import { ThemeSwitcher } from "@ui/components/ThemeSwitcher";
import * as ThemeContext from "@ui/contexts/ThemeContext";
import { vi } from "vitest";

View file

@ -1,7 +1,7 @@
import { ToggleButtonGroup, ToggleButton } from "../ui-library/button";
import { twMerge } from "tailwind-merge";
import { useTheme } from "@ui/contexts/ThemeContext";
import { Text } from "@ui/ui-library/text";
import { twMerge } from "tailwind-merge";
import { ToggleButton, ToggleButtonGroup } from "../ui-library/button";
const translation = {
light: "Clair",

View file

@ -1,14 +1,14 @@
import { useState } from "react";
import { useTablosList } from "@ui/hooks/tablos";
import { useGenerateWebcalToken } from "@ui/hooks/webcal";
import {
Select,
SelectButton,
SelectPopover,
SelectListBox,
SelectListItem,
SelectPopover,
} from "@ui/ui-library/select";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { useState } from "react";
interface WebcalModalProps {
onClose: () => void;

View file

@ -1,4 +1,6 @@
import { CalendarDate } from "@internationalized/date";
import { Button } from "@ui/ui-library/button";
import { DateField, DateInput } from "@ui/ui-library/date-field";
import {
Dialog,
DialogBody,
@ -6,16 +8,12 @@ import {
DialogFooter,
DialogHeader,
} from "@ui/ui-library/dialog";
import { Modal } from "@ui/ui-library/modal";
import { PlusIcon } from "lucide-react";
import { FieldError, Input, Label, TextArea, TextField } from "@ui/ui-library/field";
import { Form } from "@ui/ui-library/form";
import { DateField, DateInput } from "@ui/ui-library/date-field";
import { FieldError, Input, Label } from "@ui/ui-library/field";
import { TextField, TextArea } from "@ui/ui-library/field";
import { Modal } from "@ui/ui-library/modal";
import { calculateTax, calculateTotal } from "@ui/utils/helpers";
import { PlusIcon } from "lucide-react";
import { useState } from "react";
import { CalendarDate } from "@internationalized/date";
import { calculateTotal } from "@ui/utils/helpers";
import { calculateTax } from "@ui/utils/helpers";
const now = new Date();
const defaultFormData = {

View file

@ -1,11 +1,13 @@
import { Button } from "@ui/ui-library/button";
import { DialogBody, DialogFooter } from "@ui/ui-library/dialog";
import { DialogCloseButton } from "@ui/ui-library/dialog";
import { DialogHeader } from "@ui/ui-library/dialog";
import { Dialog } from "@ui/ui-library/dialog";
import { TrashIcon } from "lucide-react";
import {
Dialog,
DialogBody,
DialogCloseButton,
DialogFooter,
DialogHeader,
} from "@ui/ui-library/dialog";
import { Modal } from "@ui/ui-library/modal";
import { TrashIcon } from "lucide-react";
import { useState } from "react";
export const DeleteDevisModalButton = ({

View file

@ -1,12 +1,14 @@
import { Database } from "@ui/types/database.types";
import { Button } from "@ui/ui-library/button";
import { DialogBody, DialogFooter } from "@ui/ui-library/dialog";
import { DialogCloseButton } from "@ui/ui-library/dialog";
import { Dialog, DialogHeader } from "@ui/ui-library/dialog";
import { EyeIcon } from "lucide-react";
import {
Dialog,
DialogBody,
DialogCloseButton,
DialogFooter,
DialogHeader,
} from "@ui/ui-library/dialog";
import { Modal } from "@ui/ui-library/modal";
import { EyeIcon } from "lucide-react";
import { useState } from "react";
type Devis = Database["public"]["Tables"]["devis"]["Row"];

View file

@ -1,7 +1,7 @@
import { Button } from "@ui/ui-library/button";
import { twMerge } from "tailwind-merge";
import { Link } from "react-router-dom";
import { getXtabloIcon } from "@ui/utils/iconHelpers";
import { Link } from "react-router-dom";
import { twMerge } from "tailwind-merge";
export function Header() {
const logo = getXtabloIcon();

View file

@ -1,14 +1,13 @@
import React, { useState, useCallback } from "react";
import { Plus, Filter } from "lucide-react";
import { Button } from "@ui/ui-library/button";
import { Icon } from "@ui/ui-library/icon";
import { SearchField } from "@ui/ui-library/search-field";
import { SearchInput } from "@ui/ui-library/search-field";
import {
KanbanBoard as KanbanBoardType,
KanbanTask,
KanbanFilters as KanbanFiltersType,
KanbanTask,
} from "@ui/types/kanban.types";
import { Button } from "@ui/ui-library/button";
import { Icon } from "@ui/ui-library/icon";
import { SearchField, SearchInput } from "@ui/ui-library/search-field";
import { Filter, Plus } from "lucide-react";
import React, { useCallback, useState } from "react";
interface KanbanBoardProps {
board: KanbanBoardType;

View file

@ -1,6 +1,6 @@
import { createContext, useContext, useEffect, useState } from "react";
import { Session, User } from "@supabase/supabase-js";
import { supabase } from "@ui/hooks/auth";
import { createContext, useContext, useEffect, useState } from "react";
const SessionContext = createContext<{
session: Session | null;

View file

@ -1,4 +1,4 @@
import { createContext, useContext, useState, useEffect, ReactNode } from "react";
import { createContext, ReactNode, useContext, useEffect, useState } from "react";
type Theme = "dark" | "light" | "system";

View file

@ -1,10 +1,10 @@
import { createClient, Session, User as SupabaseUser } from "@supabase/supabase-js";
import { useMutation } from "@tanstack/react-query";
import { useNavigate } from "react-router-dom";
import { useState } from "react";
import { match } from "ts-pattern";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { User as SupabaseUser, Session, createClient } from "@supabase/supabase-js";
import { api, queryClient } from "@ui/lib/api";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { match } from "ts-pattern";
export type User = SupabaseUser & {
user_metadata: {

View file

@ -1,9 +1,9 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { queryClient } from "@ui/lib/api";
import { supabase } from "@ui/hooks/auth";
import { useSession } from "@ui/contexts/SessionContext";
import { useEffect, useState } from "react";
import { supabase } from "@ui/hooks/auth";
import { queryClient } from "@ui/lib/api";
import { Database } from "@ui/types/database.types";
import { useEffect, useState } from "react";
export type TimeRange = {
start: string;

View file

@ -1,6 +1,6 @@
import { useEffect, useState } from "react";
import { Channel, StreamChat } from "stream-chat";
import { useParams } from "react-router-dom";
import { Channel, StreamChat } from "stream-chat";
export const useChannelFromUrl = (client: StreamChat) => {
const [channel, setChannel] = useState<Channel | null>(null);

View file

@ -1,7 +1,7 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useSession } from "@ui/contexts/SessionContext";
import { Database } from "@ui/types/database.types";
import { supabase } from "./auth";
import { useSession } from "@ui/contexts/SessionContext";
type Devis = Database["public"]["Tables"]["devis"];

View file

@ -1,9 +1,9 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { supabase } from "./auth";
import { useSession } from "@ui/contexts/SessionContext";
import { Database } from "@ui/types/database.types";
import { queryClient } from "@ui/lib/api";
import { Database } from "@ui/types/database.types";
import { useMemo } from "react";
import { supabase } from "./auth";
export type EventTypeData = {
id: string;

View file

@ -1,8 +1,8 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { supabase } from "./auth";
import { useUser } from "@ui/providers/UserStoreProvider";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { Event, EventAndTablo, EventInsert, EventUpdate } from "@ui/types/events.types";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { supabase } from "./auth";
// Fetch events for a specific tablo
export const useEventsByTablo = (tabloId: string | null) => {

View file

@ -1,7 +1,7 @@
import { useMutation } from "@tanstack/react-query";
import { supabase } from "./auth";
import { useUser } from "@ui/providers/UserStoreProvider";
import { FeedbackData } from "@ui/pages/feedback";
import { useUser } from "@ui/providers/UserStoreProvider";
import { supabase } from "./auth";
// Create new feedback
export const useCreateFeedback = () => {

View file

@ -1,6 +1,6 @@
import { useMutation } from "@tanstack/react-query";
import { api } from "@ui/lib/api";
import { useSession } from "@ui/contexts/SessionContext";
import { api } from "@ui/lib/api";
import { toast } from "@ui/ui-library/toast/toast-queue";
// Invite user by email

View file

@ -1,6 +1,6 @@
import { useMutation } from "@tanstack/react-query";
import { supabase } from "./auth";
import { useUser } from "@ui/providers/UserStoreProvider";
import { supabase } from "./auth";
export interface SupportTicketData {
issue_type: "bug" | "performance" | "security" | "feature_request" | "account" | "other";

View file

@ -1,15 +1,15 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Database } from "@ui/types/database.types";
import { supabase } from "./auth";
import { useSession } from "@ui/contexts/SessionContext";
import { api } from "@ui/lib/api";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { RemoveNullFromObject } from "@ui/types/removeNull";
import { useUser } from "@ui/providers/UserStoreProvider";
import { CreateTablo } from "@ui/types/tablos.types";
import { EventInsertInTablo } from "@ui/types/events.types";
import { useNavigate } from "react-router-dom";
import { invalidatePublicSlots } from "@ui/hooks/public";
import { api } from "@ui/lib/api";
import { useUser } from "@ui/providers/UserStoreProvider";
import { Database } from "@ui/types/database.types";
import { EventInsertInTablo } from "@ui/types/events.types";
import { RemoveNullFromObject } from "@ui/types/removeNull";
import { CreateTablo } from "@ui/types/tablos.types";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { useNavigate } from "react-router-dom";
import { supabase } from "./auth";
type Tablo = Database["public"]["Tables"]["tablos"];

View file

@ -1,7 +1,7 @@
import { useMutation } from "@tanstack/react-query";
import { useSession } from "@ui/contexts/SessionContext";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { api } from "@ui/lib/api";
import { toast } from "@ui/ui-library/toast/toast-queue";
export interface WebcalToken {
token: string;

View file

@ -1,5 +1,5 @@
import axios from "axios";
import { QueryClient } from "@tanstack/react-query";
import axios from "axios";
// Create axios instance with default config
export const api = axios.create({

View file

@ -1,28 +1,28 @@
import { RouteObject } from "react-router-dom";
import { ProtectedRoute } from "@ui/components/ProtectedRoute";
import { Layout } from "@ui/components/Layout";
import { TabloPage } from "@ui/pages/tablo";
import { DevisPage } from "@ui/pages/devis";
import { FacturesPage } from "@ui/pages/factures";
import { PlanningPage } from "@ui/pages/planning";
import { NotFoundPage } from "@ui/pages/NotFoundPage";
import { JoinPage } from "@ui/pages/join";
import { OAuthSigninPage } from "@ui/pages/oauth-signin";
import { LandingPage } from "@ui/pages/landing";
import { LoginPage } from "@ui/pages/login";
import { SignUpPage } from "@ui/pages/signup";
import { ResetPasswordPage } from "@ui/pages/reset-password";
import { AuthenticationGateway } from "@ui/components/AuthenticationGateway";
import ChatProvider from "@ui/providers/ChatProvider";
import { EventModal } from "@ui/components/EventModal";
import { ChantiersPage } from "@ui/pages/chantiers";
import { ChatPage } from "@ui/pages/chat";
import { FeedbackPage } from "@ui/pages/feedback";
import { SupportPage } from "@ui/pages/support";
import { Layout } from "@ui/components/Layout";
import { ProtectedRoute } from "@ui/components/ProtectedRoute";
import { AvailabilitiesPage } from "@ui/pages/availabilities";
import { BookingsPage } from "@ui/pages/bookings";
import { ChantiersPage } from "@ui/pages/chantiers";
import { ChatPage } from "@ui/pages/chat";
import { DevisPage } from "@ui/pages/devis";
import { EventTypesPage } from "@ui/pages/event-types-page";
import { FacturesPage } from "@ui/pages/factures";
import { FeedbackPage } from "@ui/pages/feedback";
import { JoinPage } from "@ui/pages/join";
import { LandingPage } from "@ui/pages/landing";
import { LoginPage } from "@ui/pages/login";
import { NotFoundPage } from "@ui/pages/NotFoundPage";
import { OAuthSigninPage } from "@ui/pages/oauth-signin";
import { PublicBookingPage } from "@ui/pages/PublicBookingPage";
import { PlanningPage } from "@ui/pages/planning";
import { ResetPasswordPage } from "@ui/pages/reset-password";
import { SignUpPage } from "@ui/pages/signup";
import { SupportPage } from "@ui/pages/support";
import { TabloPage } from "@ui/pages/tablo";
import ChatProvider from "@ui/providers/ChatProvider";
import { RouteObject } from "react-router-dom";
export const routes: RouteObject[] = [
// Protected routes

View file

@ -1,7 +1,7 @@
import { QueryClientProvider } from "@tanstack/react-query";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { App } from "./App";
import { QueryClientProvider } from "@tanstack/react-query";
import { queryClient } from "./lib/api";
import { GlobalToastRegion } from "./ui-library/toast/toast-region";

View file

@ -1,6 +1,6 @@
import { twMerge } from "tailwind-merge";
import { Button } from "@ui/ui-library/button";
import { useNavigate } from "react-router-dom";
import { twMerge } from "tailwind-merge";
export const NotFoundPage = () => {
const navigate = useNavigate();

View file

@ -1,28 +1,28 @@
import { useParams } from "react-router-dom";
import { useState } from "react";
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
import { Strong, Text } from "@ui/ui-library/text";
import { Button } from "@ui/ui-library/button";
import { CustomModal } from "@ui/components/CustomModal";
import { TextField, Label, Input, FieldError } from "@ui/ui-library/field";
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
import { useSession } from "@ui/contexts/SessionContext";
import { useTheme } from "@ui/contexts/ThemeContext";
import { useSignUpWithoutPassword } from "@ui/hooks/auth";
import { TimeSlot, usePublicSlots } from "@ui/hooks/public";
import { useCreateTabloWithOwner } from "@ui/hooks/tablos";
import { useMaybeUser } from "@ui/providers/UserStoreProvider";
import { EventInsertInTablo } from "@ui/types/events.types";
import { Button } from "@ui/ui-library/button";
import { FieldError, Input, Label, TextField } from "@ui/ui-library/field";
import { Strong, Text } from "@ui/ui-library/text";
import {
CalendarIcon,
ClockIcon,
MapPinIcon,
UserIcon,
ChevronLeftIcon,
ChevronRightIcon,
SunIcon,
MoonIcon,
ClockIcon,
MapPinIcon,
MonitorIcon,
MoonIcon,
SunIcon,
UserIcon,
} from "lucide-react";
import { usePublicSlots, TimeSlot } from "@ui/hooks/public";
import { useSignUpWithoutPassword } from "@ui/hooks/auth";
import { useCreateTabloWithOwner } from "@ui/hooks/tablos";
import { EventInsertInTablo } from "@ui/types/events.types";
import { useSession } from "@ui/contexts/SessionContext";
import { useState } from "react";
import { useParams } from "react-router-dom";
export function PublicBookingPage() {
const { user_info, event_type_standard_name } = useParams<{

View file

@ -1,23 +1,23 @@
import { Strong, Text } from "@ui/ui-library/text";
import { DateValue, getLocalTimeZone, today } from "@internationalized/date";
import { AvailabilityCard } from "@ui/components/AvailabilityCard";
import { Button } from "@ui/ui-library/button";
import { AvailabilityVisualization } from "@ui/components/AvailabilityVisualization";
import { CustomModal } from "@ui/components/CustomModal";
import {
DEFAULT_AVAILABILITIES,
Exception,
useAvailabilities,
WeeklyAvailability,
} from "@ui/hooks/availabilities";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { useState } from "react";
import { Button } from "@ui/ui-library/button";
import { Checkbox } from "@ui/ui-library/checkbox";
import { PlusIcon } from "@ui/ui-library/icons";
import { AvailabilityVisualization } from "@ui/components/AvailabilityVisualization";
import { SaveIcon } from "lucide-react";
import { DatePicker, DatePickerInput } from "@ui/ui-library/date-picker";
import { Label } from "@ui/ui-library/field";
import { DateValue, getLocalTimeZone, today } from "@internationalized/date";
import { RadioGroup, Radios, Radio } from "@ui/ui-library/radio-group";
import { CustomModal } from "@ui/components/CustomModal";
import { PlusIcon } from "@ui/ui-library/icons";
import { Radio, RadioGroup, Radios } from "@ui/ui-library/radio-group";
import { Strong, Text } from "@ui/ui-library/text";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { SaveIcon } from "lucide-react";
import { useState } from "react";
const DAYS_OF_WEEK = [0, 1, 2, 3, 4, 5, 6];
const DAYS_OF_WEEK_DISPLAY = [

View file

@ -1,7 +1,13 @@
import { useState, useMemo, useEffect } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { Text, Strong } from "@ui/ui-library/text";
import { EventDetailsModal } from "@ui/components/EventDetailsModal";
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
import { useEventsByTablo } from "@ui/hooks/events";
import { useGetAllTabloAccess, useTablosList } from "@ui/hooks/tablos";
import { EventAndTablo } from "@ui/types/events.types";
import { Badge } from "@ui/ui-library/badge";
import { Button } from "@ui/ui-library/button";
import { Input } from "@ui/ui-library/field";
import { CalendarIcon } from "@ui/ui-library/icons/outline/calendar";
import { Radio, RadioGroup, Radios } from "@ui/ui-library/radio-group";
import {
Select,
SelectButton,
@ -11,19 +17,12 @@ import {
SelectPopover,
StatusIcon,
} from "@ui/ui-library/select";
import { Input } from "@ui/ui-library/field";
import { SearchIcon } from "lucide-react";
import { CalendarIcon } from "@ui/ui-library/icons/outline/calendar";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { useEventsByTablo } from "@ui/hooks/events";
import { useTablosList, useGetAllTabloAccess } from "@ui/hooks/tablos";
import { EventAndTablo } from "@ui/types/events.types";
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
import { EventDetailsModal } from "@ui/components/EventDetailsModal";
import { RadioGroup, Radios, Radio } from "@ui/ui-library/radio-group";
import { Badge } from "@ui/ui-library/badge";
import { twMerge } from "tailwind-merge";
import { Strong, Text } from "@ui/ui-library/text";
import { getTextColorFromTabloColor } from "@ui/utils/helpers";
import { ChevronLeft, ChevronRight, SearchIcon } from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { twMerge } from "tailwind-merge";
type BookingStatus = "all" | "upcoming" | "past";

View file

@ -1,17 +1,17 @@
import {
ChannelList,
MessageList,
MessageInput,
Window,
Channel,
useChatContext,
} from "stream-chat-react";
import { useUser } from "@ui/providers/UserStoreProvider";
import { ChannelPreview } from "@ui/components/ChannelPreview";
import { CustomChannelHeader } from "@ui/components/CustomChannelHeader";
import { useChannelFromUrl } from "@ui/hooks/channel";
import { useTablosList } from "@ui/hooks/tablos";
import { CustomChannelHeader } from "@ui/components/CustomChannelHeader";
import { useUser } from "@ui/providers/UserStoreProvider";
import { useEffect, useState } from "react";
import {
Channel,
ChannelList,
MessageInput,
MessageList,
useChatContext,
Window,
} from "stream-chat-react";
export function ChatPage() {
const user = useUser();

View file

@ -1,9 +1,10 @@
import { screen, waitFor, within } from "@testing-library/react";
import { describe, it, expect, beforeEach, vi } from "vitest";
import { DevisPage } from "@ui/pages/devis";
import { useDevisList, useCreateDevis, useDeleteDevis, useUpdateDevis } from "@ui/hooks/devis";
import userEvent from "@testing-library/user-event";
import { useCreateDevis, useDeleteDevis, useDevisList, useUpdateDevis } from "@ui/hooks/devis";
import { DevisPage } from "@ui/pages/devis";
import { renderWithProviders, waitForGridToBeInTheDOM } from "@ui/utils/testHelpers";
import { beforeEach, describe, expect, it, vi } from "vitest";
// Mock the hooks
vi.mock("@ui/hooks/devis");

View file

@ -1,12 +1,11 @@
import { NotebookPenIcon } from "lucide-react";
import { AllCommunityModule, ColDef, ModuleRegistry, themeQuartz } from "ag-grid-community";
import { AgGridReact } from "ag-grid-react";
import { useDevisList, useCreateDevis, useDeleteDevis, useUpdateDevis } from "@ui/hooks/devis";
import { useState } from "react";
import { Database } from "@ui/types/database.types";
import { CalendarDate, DateValue } from "@internationalized/date";
import { RowActionMenu } from "@ui/components/RowActionMenu";
import { CustomLoadingOverlay } from "@ui/components/CustomLoadingOverlay";
import { CreateDevisModal } from "@ui/components/devis/CreateDevisModal";
import { ViewDevisModal } from "@ui/components/devis/ViewDevisModal";
import { RowActionMenu } from "@ui/components/RowActionMenu";
import { useCreateDevis, useDeleteDevis, useDevisList, useUpdateDevis } from "@ui/hooks/devis";
import { Database } from "@ui/types/database.types";
import { Badge, BadgeColor } from "@ui/ui-library/badge";
import {
EmptyState,
EmptyStateActions,
@ -14,14 +13,18 @@ import {
EmptyStateHeading,
EmptyStateIcon,
} from "@ui/ui-library/empty-state";
import { CreateDevisModal } from "@ui/components/devis/CreateDevisModal";
import { calculateTotal, calculateTax, exportDevisToPdf, statusToText } from "@ui/utils/helpers";
import { ViewDevisModal } from "@ui/components/devis/ViewDevisModal";
import { Badge, BadgeColor } from "@ui/ui-library/badge";
import { Select, SelectButton } from "@ui/ui-library/select";
import { SelectListBox } from "@ui/ui-library/select";
import { SelectPopover } from "@ui/ui-library/select";
import { SelectListItem } from "@ui/ui-library/select";
import {
Select,
SelectButton,
SelectListBox,
SelectListItem,
SelectPopover,
} from "@ui/ui-library/select";
import { calculateTax, calculateTotal, exportDevisToPdf, statusToText } from "@ui/utils/helpers";
import { AllCommunityModule, ColDef, ModuleRegistry, themeQuartz } from "ag-grid-community";
import { AgGridReact } from "ag-grid-react";
import { NotebookPenIcon } from "lucide-react";
import { useState } from "react";
ModuleRegistry.registerModules([AllCommunityModule]);

View file

@ -1,12 +1,12 @@
import { useState } from "react";
import { Strong, Text } from "@ui/ui-library/text";
import { Button, ToggleButton } from "@ui/ui-library/button";
import { PlusIcon, EditIcon, TrashIcon, CheckIcon, XIcon, ExternalLinkIcon } from "lucide-react";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { EventTypeModal } from "@ui/components/EventTypeModal";
import { EventTypeConfig, useEventTypes } from "@ui/hooks/event-types";
import { useUser } from "@ui/providers/UserStoreProvider";
import { Button, ToggleButton } from "@ui/ui-library/button";
import { CopyButton } from "@ui/ui-library/clipboard";
import { Strong, Text } from "@ui/ui-library/text";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { CheckIcon, EditIcon, ExternalLinkIcon, PlusIcon, TrashIcon, XIcon } from "lucide-react";
import { useState } from "react";
export function EventTypesPage() {
const user = useUser();

View file

@ -1,13 +1,13 @@
import React, { useState } from "react";
import { Button } from "@ui/ui-library/button";
import { Form } from "@ui/ui-library/form";
import { TextField, Label, TextArea, Description } from "@ui/ui-library/field";
import { Text } from "@ui/ui-library/text";
import { Separator } from "react-aria-components";
import { SendIcon, ArrowLeftIcon } from "lucide-react";
import { twMerge } from "tailwind-merge";
import { useNavigate } from "react-router-dom";
import { useCreateFeedback } from "@ui/hooks/feedback";
import { Button } from "@ui/ui-library/button";
import { Description, Label, TextArea, TextField } from "@ui/ui-library/field";
import { Form } from "@ui/ui-library/form";
import { Text } from "@ui/ui-library/text";
import { ArrowLeftIcon, SendIcon } from "lucide-react";
import React, { useState } from "react";
import { Separator } from "react-aria-components";
import { useNavigate } from "react-router-dom";
import { twMerge } from "tailwind-merge";
export interface FeedbackData {
fd_type: "bug" | "feature" | "improvement" | "other";

View file

@ -1,7 +1,7 @@
import { useParams, useNavigate, useSearchParams } from "react-router-dom";
import { useUser } from "@ui/providers/UserStoreProvider";
import { useJoinTablo } from "@ui/hooks/invite";
import { useUser } from "@ui/providers/UserStoreProvider";
import { toast } from "@ui/ui-library/toast/toast-queue";
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
export const JoinPage = () => {
const { tablo_name } = useParams<{ tablo_name: string }>();

View file

@ -1,21 +1,21 @@
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import { KanbanBoard } from "@ui/components/kanban/KanbanBoard";
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
import { useTablosList } from "@ui/hooks/tablos";
import {
KanbanBoard as KanbanBoardType,
KanbanTask,
KanbanColumn,
KanbanTask,
TaskStatus,
} from "@ui/types/kanban.types";
import {
Select,
SelectButton,
SelectPopover,
SelectListBox,
SelectListItem,
SelectPopover,
} from "@ui/ui-library/select";
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
// Mock data for demonstration
const createMockKanbanBoard = (tabloId: string, tabloName: string): KanbanBoardType => {

View file

@ -1,9 +1,8 @@
import { Button } from "@ui/ui-library/button";
import { twMerge } from "tailwind-merge";
import logo from "../assets/icon.jpg";
import { Header } from "@ui/components/header";
import { Button } from "@ui/ui-library/button";
import { Link } from "react-router-dom";
import { twMerge } from "tailwind-merge";
import logo from "../assets/icon.jpg";
export const LandingPage = () => {
window.location.href = "https://www.xtablo.com";

View file

@ -1,14 +1,14 @@
import { Button } from "@ui/ui-library/button";
import { twMerge } from "tailwind-merge";
import { useState } from "react";
import { Label, Input, TextField, FieldError } from "@ui/ui-library/field";
import { useLoginEmail } from "@ui/hooks/auth";
import { Form } from "@ui/ui-library/form";
import { LoginWithGoogle } from "@ui/components/BrandButtons/LoginWithGoogle";
import { Link } from "react-router-dom";
import { useTheme } from "@ui/contexts/ThemeContext";
import { SunIcon, MoonIcon, MonitorIcon } from "lucide-react";
import { AnimatedBackground } from "@ui/components/AnimatedBackground";
import { LoginWithGoogle } from "@ui/components/BrandButtons/LoginWithGoogle";
import { useTheme } from "@ui/contexts/ThemeContext";
import { useLoginEmail } from "@ui/hooks/auth";
import { Button } from "@ui/ui-library/button";
import { FieldError, Input, Label, TextField } from "@ui/ui-library/field";
import { Form } from "@ui/ui-library/form";
import { MonitorIcon, MoonIcon, SunIcon } from "lucide-react";
import { useState } from "react";
import { Link } from "react-router-dom";
import { twMerge } from "tailwind-merge";
export function LoginPage() {
const redirectUrl = localStorage.getItem("redirectUrl");

View file

@ -1,7 +1,7 @@
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useSession } from "@ui/contexts/SessionContext";
import { useSignUpToStream } from "@ui/hooks/auth";
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
export const OAuthSigninPage = () => {
const navigate = useNavigate();

View file

@ -1,19 +1,19 @@
import { useState, useEffect } from "react";
import { ImportICSModal } from "@ui/components/ImportICSModal";
import { WebcalModal } from "@ui/components/WebcalModal";
import { useDeleteEvent, useEventsByTablo } from "@ui/hooks/events";
import { useGetAllTabloAccess, useTablosList } from "@ui/hooks/tablos";
import { useEventsByTablo, useDeleteEvent } from "@ui/hooks/events";
import { EventAndTablo } from "@ui/types/events.types";
import {
Select,
SelectButton,
SelectPopover,
SelectListBox,
SelectListItem,
SelectPopover,
} from "@ui/ui-library/select";
import { Outlet, useNavigate, useParams } from "react-router-dom";
import { generateICSFromEvents, downloadICSFile } from "@ui/utils/helpers";
import { ImportICSModal } from "@ui/components/ImportICSModal";
import { WebcalModal } from "@ui/components/WebcalModal";
import { downloadICSFile, generateICSFromEvents } from "@ui/utils/helpers";
import { FolderInputIcon, PlusIcon } from "lucide-react";
import { EventAndTablo } from "@ui/types/events.types";
import { useEffect, useState } from "react";
import { Outlet, useNavigate, useParams } from "react-router-dom";
type ViewType = "month" | "week" | "day";

View file

@ -1,10 +1,10 @@
import { Button } from "@ui/ui-library/button";
import { twMerge } from "tailwind-merge";
import { Link, useNavigate } from "react-router-dom";
import { useState } from "react";
import { Label, Input, TextField, FieldError } from "@ui/ui-library/field";
import { FieldError, Input, Label, TextField } from "@ui/ui-library/field";
import { Form } from "@ui/ui-library/form";
import { Text } from "@ui/ui-library/text";
import { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { twMerge } from "tailwind-merge";
export function ResetPasswordPage() {
const navigate = useNavigate();

View file

@ -1,15 +1,15 @@
import { Button } from "@ui/ui-library/button";
import { twMerge } from "tailwind-merge";
import { Link, useNavigate } from "react-router-dom";
import { useState } from "react";
import { Label, Input, TextField, FieldError } from "@ui/ui-library/field";
import { AnimatedBackground } from "@ui/components/AnimatedBackground";
import { LoginWithGoogle } from "@ui/components/BrandButtons/LoginWithGoogle";
import { useTheme } from "@ui/contexts/ThemeContext";
import { useSignUp } from "@ui/hooks/auth";
import { Button } from "@ui/ui-library/button";
import { FieldError, Input, Label, TextField } from "@ui/ui-library/field";
import { Form } from "@ui/ui-library/form";
import { Text } from "@ui/ui-library/text";
import { LoginWithGoogle } from "@ui/components/BrandButtons/LoginWithGoogle";
import { AnimatedBackground } from "@ui/components/AnimatedBackground";
import { useTheme } from "@ui/contexts/ThemeContext";
import { SunIcon, MoonIcon, MonitorIcon } from "lucide-react";
import { MonitorIcon, MoonIcon, SunIcon } from "lucide-react";
import { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { twMerge } from "tailwind-merge";
export function SignUpPage() {
const navigate = useNavigate();

View file

@ -1,13 +1,13 @@
import React, { useState } from "react";
import { SupportTicketData, useCreateSupportTicket } from "@ui/hooks/support";
import { Button } from "@ui/ui-library/button";
import { Description, Label, TextArea, TextField } from "@ui/ui-library/field";
import { Form } from "@ui/ui-library/form";
import { TextField, Label, TextArea, Description } from "@ui/ui-library/field";
import { Text } from "@ui/ui-library/text";
import { ArrowLeftIcon, SendIcon } from "lucide-react";
import React, { useState } from "react";
import { Separator } from "react-aria-components";
import { SendIcon, ArrowLeftIcon } from "lucide-react";
import { twMerge } from "tailwind-merge";
import { useNavigate } from "react-router-dom";
import { useCreateSupportTicket, SupportTicketData } from "@ui/hooks/support";
import { twMerge } from "tailwind-merge";
export function SupportPage() {
const navigate = useNavigate();

View file

@ -1,20 +1,20 @@
import { CreateTabloModal } from "@ui/components/CreateTabloModal";
import { TabloModal } from "@ui/components/TabloModal";
import { DeleteTabloModal } from "@ui/components/DeleteTabloModal";
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
import { TabloModal } from "@ui/components/TabloModal";
import { TabloTutorial } from "@ui/components/TabloTutorial";
import { useCreateTablo, useDeleteTablo, useTablosList, useUpdateTablo } from "@ui/hooks/tablos";
import { TabloInsert, TabloUpdate, UserTablo } from "@ui/types/tablos.types";
import {
Select,
SelectButton,
SelectPopover,
SelectListBox,
SelectListItem,
SelectPopover,
} from "@ui/ui-library/select";
import { useState, useEffect } from "react";
import { useTablosList, useCreateTablo, useUpdateTablo, useDeleteTablo } from "@ui/hooks/tablos";
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
import { TabloInsert, TabloUpdate, UserTablo } from "@ui/types/tablos.types";
import { useNavigate } from "react-router-dom";
import { HelpCircle } from "lucide-react";
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
type FilterOption = {
id: "all" | "todo" | "in_progress" | "done";

View file

@ -1,6 +1,6 @@
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
import { Chat, useCreateChatClient } from "stream-chat-react";
import { useUser } from "./UserStoreProvider";
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
export default function ChatProvider({ children }: { children: React.ReactNode }) {
const apiKey = import.meta.env.VITE_STREAM_CHAT_API_KEY as string;

View file

@ -1,10 +1,10 @@
import { createStore, StoreApi, useStore } from "zustand";
import React from "react";
import { useQuery } from "@tanstack/react-query";
import { Tables } from "@ui/types/database.types";
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
import { useSession } from "@ui/contexts/SessionContext";
import { api } from "@ui/lib/api";
import { LoadingSpinner } from "@ui/components/LoadingSpinner";
import { Tables } from "@ui/types/database.types";
import React from "react";
import { createStore, StoreApi, useStore } from "zustand";
export type User = Tables<"profiles"> & {
streamToken: string | null;

View file

@ -1,6 +1,6 @@
import { Database } from "@ui/types/database.types";
import { RemoveNullFromObject } from "@ui/types/removeNull";
import { EventInsertInTablo } from "@ui/types/events.types";
import { RemoveNullFromObject } from "@ui/types/removeNull";
export type UserTablo = RemoveNullFromObject<
Database["public"]["Views"]["user_tablos"]["Row"],

View file

@ -1,7 +1,7 @@
import React from "react";
import { FallbackAvatarProps, getFallbackAvatarDataUrl } from "./initials";
import { twMerge } from "tailwind-merge";
import { useImageLoadingStatus } from "./hooks/use-image-loading-status";
import { FallbackAvatarProps, getFallbackAvatarDataUrl } from "./initials";
const AvatarContext = React.createContext<{
badgeId: string;

View file

@ -1,5 +1,3 @@
export type { BadgeColor } from "./badge.styles";
export { getBadgeStyles } from "./badge.styles";
export { Badge } from "./badge";
export type { BadgeColor } from "./badge.styles";
export { getBadgeStyles } from "./badge.styles";

View file

@ -1,14 +1,14 @@
import {
Breadcrumb as RACBreadcrumb,
Breadcrumbs as RACBreadcrumbs,
BreadcrumbProps as RACBreadcrumbProps,
BreadcrumbsProps as RACBreadcrumbsProps,
LinkProps,
composeRenderProps,
LinkProps,
Breadcrumb as RACBreadcrumb,
BreadcrumbProps as RACBreadcrumbProps,
Breadcrumbs as RACBreadcrumbs,
BreadcrumbsProps as RACBreadcrumbsProps,
} from "react-aria-components";
import { twMerge } from "tailwind-merge";
import { Link } from "./link";
import { ChevronRightIcon } from "./icons";
import { Link } from "./link";
export function Breadcrumbs<T extends object>({ className, ...props }: RACBreadcrumbsProps<T>) {
return <RACBreadcrumbs {...props} className={twMerge("flex gap-1", className)} />;

View file

@ -1,17 +1,17 @@
import React from "react";
import {
composeRenderProps,
Button as RACButton,
ButtonProps as RACButtonProps,
ToggleButton as RACToggleButton,
ToggleButtonProps as RACToggleButtonProps,
ToggleButtonGroup as RACToggleButtonGroup,
ToggleButtonProps as RACToggleButtonProps,
ToggleButtonGroupProps,
composeRenderProps,
} from "react-aria-components";
import { twMerge } from "tailwind-merge";
import { AsChildProps, Slot } from "./slot";
import { SpinnerIcon } from "./icons";
import { NonFousableTooltipTarget, TooltipTrigger, Tooltip } from "./tooltip";
import { AsChildProps, Slot } from "./slot";
import { NonFousableTooltipTarget, Tooltip, TooltipTrigger } from "./tooltip";
type Color = "accent" | "success" | "destructive";

View file

@ -1,27 +1,27 @@
import { CalendarDate, getLocalTimeZone, isToday } from "@internationalized/date";
import { useDateFormatter } from "@react-aria/i18n";
import { CalendarState } from "@react-stately/calendar";
import React from "react";
import {
Heading,
Calendar as RACCalendar,
CalendarGridHeader as RACCalendarGridHeader,
CalendarProps as RACCalendarProps,
CalendarCell,
CalendarGrid,
CalendarGridBody,
CalendarHeaderCell,
CalendarStateContext,
composeRenderProps,
DateValue,
Heading,
Calendar as RACCalendar,
CalendarGridHeader as RACCalendarGridHeader,
CalendarProps as RACCalendarProps,
Text,
useLocale,
composeRenderProps,
CalendarStateContext,
} from "react-aria-components";
import { Button, ButtonGroup } from "./button";
import { twMerge } from "tailwind-merge";
import { ChevronLeftIcon, ChevronRightIcon } from "./icons";
import { CalendarDate, getLocalTimeZone, isToday } from "@internationalized/date";
import { CalendarState } from "@react-stately/calendar";
import { useDateFormatter } from "@react-aria/i18n";
import { NativeSelect, NativeSelectField } from "./native-select";
import { Button, ButtonGroup } from "./button";
import { Label } from "./field";
import { ChevronLeftIcon, ChevronRightIcon } from "./icons";
import { NativeSelect, NativeSelectField } from "./native-select";
export type YearRange = number | [yearsBefore: number, yearsAfter: number];

View file

@ -7,10 +7,10 @@ import {
CheckboxGroupProps as RACCheckboxGroupProps,
CheckboxProps as RACCheckboxProps,
} from "react-aria-components";
import { groupBox } from "./utils";
import { twMerge } from "tailwind-merge";
import { DescriptionContext, DescriptionProvider } from "./field";
import { CheckIcon, MinusIcon } from "./icons";
import { groupBox } from "./utils";
export interface CheckboxGroupProps extends Omit<RACCheckboxGroupProps, "children"> {
children?: ReactNode;

View file

@ -1,9 +1,9 @@
import React from "react";
import { twMerge } from "tailwind-merge";
import { Button, ButtonProps } from "./button";
import { useCopyToClipboard } from "./hooks/use-clipboard";
import { TooltipTrigger, Tooltip } from "./tooltip";
import { CheckIcon, CopyIcon } from "./icons";
import { twMerge } from "tailwind-merge";
import { Tooltip, TooltipTrigger } from "./tooltip";
export type ClipboardProps = {
timeout?: number;

View file

@ -1,15 +1,16 @@
import React from "react";
import {
ComboBoxStateContext,
composeRenderProps,
Group,
GroupProps,
ComboBox as RACComboBox,
ComboBoxProps as RACComboBoxProps,
ComboBoxStateContext,
GroupProps,
Group,
composeRenderProps,
} from "react-aria-components";
import { ButtonProps, Button } from "./button";
import { inputField } from "./utils";
import { twMerge } from "tailwind-merge";
import { Button, ButtonProps } from "./button";
import { Input } from "./field";
import { ChevronDownIcon, XIcon } from "./icons";
import {
SelectListBox,
SelectListItemDescription,
@ -17,8 +18,7 @@ import {
SelectPopover,
SelectSection,
} from "./select";
import { Input } from "./field";
import { ChevronDownIcon, XIcon } from "./icons";
import { inputField } from "./utils";
export function ComboBox(props: RACComboBoxProps<object>) {
return (

View file

@ -1,14 +1,14 @@
import {
composeRenderProps,
DateSegment,
DateValue,
DateField as RACDateField,
DateFieldProps as RACDateFieldProps,
DateInput as RACDateInput,
DateInputProps as RACDateInputProps,
DateSegment,
DateValue,
composeRenderProps,
} from "react-aria-components";
import { inputField } from "./utils";
import { twMerge } from "tailwind-merge";
import { inputField } from "./utils";
export interface DateFieldProps<T extends DateValue> extends RACDateFieldProps<T> {}

View file

@ -1,21 +1,21 @@
import React from "react";
import {
composeRenderProps,
DatePickerStateContext,
DateValue,
Group,
DatePicker as RACDatePicker,
DatePickerProps as RACDatePickerProps,
DateValue,
DatePickerStateContext,
useLocale,
Group,
composeRenderProps,
} from "react-aria-components";
import { twMerge } from "tailwind-merge";
import { Button } from "./button";
import { Calendar, YearRange } from "./calendar";
import { DateInput, DateInputProps } from "./date-field";
import { Dialog } from "./dialog";
import { CalendarIcon } from "./icons/outline/calendar";
import { Popover } from "./popover";
import { inputField } from "./utils";
import { twMerge } from "tailwind-merge";
import { CalendarIcon } from "./icons/outline/calendar";
export interface DatePickerProps<T extends DateValue> extends RACDatePickerProps<T> {}

View file

@ -4,17 +4,17 @@ import {
DateRangePickerProps as AriaDateRangePickerProps,
DateRangePickerStateContext,
DateValue,
useLocale,
Group,
useLocale,
} from "react-aria-components";
import { twMerge } from "tailwind-merge";
import { Button } from "./button";
import { DateInput } from "./date-field";
import { Dialog } from "./dialog";
import { CalendarIcon } from "./icons";
import { Popover } from "./popover";
import { RangeCalendar } from "./range-calendar";
import { composeTailwindRenderProps, inputField } from "./utils";
import { twMerge } from "tailwind-merge";
import { CalendarIcon } from "./icons";
export interface DateRangePickerProps<T extends DateValue> extends AriaDateRangePickerProps<T> {}

View file

@ -1,14 +1,14 @@
import React from "react";
import {
DialogProps as RACDialogProps,
Dialog as RACDialog,
composeRenderProps,
Dialog as RACDialog,
DialogProps as RACDialogProps,
} from "react-aria-components";
import { twMerge } from "tailwind-merge";
import React from "react";
import { BaseHeadingProps, Heading } from "./heading";
import { Button, ButtonProps } from "./button";
import { Text } from "./text";
import { BaseHeadingProps, Heading } from "./heading";
import { XIcon } from "./icons";
import { Text } from "./text";
export { DialogTrigger } from "react-aria-components";

View file

@ -1,7 +1,7 @@
import { twMerge } from "tailwind-merge";
import { TextProps } from "react-aria-components";
import { Text } from "./text";
import { twMerge } from "tailwind-merge";
import { Heading, HeadingProps } from "./heading";
import { Text } from "./text";
export function EmptyState({ className, ...props }: React.JSX.IntrinsicElements["div"]) {
return (

View file

@ -1,24 +1,24 @@
import React from "react";
import {
composeRenderProps,
FieldErrorProps,
GroupContext,
InputProps,
LabelContext,
LabelProps,
FieldError as RACFieldError,
Input as RACInput,
Label as RACLabel,
TextProps,
LabelContext,
GroupContext,
TextFieldProps as RACTextFieldProps,
TextField as RACTextField,
Text as RACText,
TextArea as RACTextArea,
TextAreaProps as RACTextAreaProps,
Text as RACText,
composeRenderProps,
TextField as RACTextField,
TextFieldProps as RACTextFieldProps,
TextProps,
} from "react-aria-components";
import { twMerge } from "tailwind-merge";
import { DisplayLevel, displayLevels, inputField } from "./utils";
import { Text } from "./text";
import { DisplayLevel, displayLevels, inputField } from "./utils";
// https://react-spectrum.adobe.com/react-aria/Group.html#advanced-customization
export function LabeledGroup({

View file

@ -6,9 +6,9 @@ import {
GridListItemProps,
GridListProps,
} from "react-aria-components";
import { twMerge } from "tailwind-merge";
import { Checkbox } from "./checkbox";
import { composeTailwindRenderProps } from "./utils";
import { twMerge } from "tailwind-merge";
export function GridList<T extends object>({ children, ...props }: GridListProps<T>) {
return (

View file

@ -1,21 +1,21 @@
import React from "react";
import {
useFloating,
autoUpdate,
offset,
flip,
shift,
useDismiss,
useRole,
useInteractions,
FloatingFocusManager,
useHover,
safePolygon,
flip,
offset,
Placement,
ReferenceType,
safePolygon,
shift,
useDismiss,
useFloating,
useHover,
useInteractions,
useRole,
} from "@floating-ui/react";
import { Heading, HeadingProps } from "./heading";
import React from "react";
import { twMerge } from "tailwind-merge";
import { Heading, HeadingProps } from "./heading";
interface PopoverOptions {
placement?: Placement;

View file

@ -1,13 +1,13 @@
import React from "react";
import {
composeRenderProps,
ListBoxItemProps,
ListBox as RACListBox,
ListBoxItem as RACListBoxItem,
ListBoxProps as RACListBoxProps,
ListBoxItemProps,
composeRenderProps,
} from "react-aria-components";
import { composeTailwindRenderProps } from "./utils";
import { twMerge } from "tailwind-merge";
import { composeTailwindRenderProps } from "./utils";
export interface ListBoxProps<T> extends Omit<RACListBoxProps<T>, "layout" | "orientation"> {}

View file

@ -1,22 +1,22 @@
import React from "react";
import {
Collection,
composeRenderProps,
Header,
Menu as RACMenu,
MenuItem as RACMenuItem,
MenuProps as RACMenuProps,
MenuItemProps as RACMenuItemProps,
composeRenderProps,
Separator,
Header,
MenuSectionProps as RACMenuSectionProps,
MenuProps as RACMenuProps,
MenuSection as RACMenuSection,
Collection,
MenuSectionProps as RACMenuSectionProps,
Separator,
} from "react-aria-components";
import { twMerge } from "tailwind-merge";
import { Popover, PopoverProps } from "./popover";
import { Button, ButtonProps } from "./button";
import { composeTailwindRenderProps } from "./utils";
import { Small } from "./text";
import { CheckIcon, ChevronDownIcon, ChevronRightIcon } from "./icons";
import { Popover, PopoverProps } from "./popover";
import { Small } from "./text";
import { composeTailwindRenderProps } from "./utils";
export { MenuTrigger, SubmenuTrigger } from "react-aria-components";

View file

@ -1,8 +1,8 @@
import React from "react";
import {
Modal as RACModal,
ModalOverlay as RACModalOverlay,
ModalOverlayProps as RACModalOverlayProps,
Modal as RACModal,
} from "react-aria-components";
import { composeTailwindRenderProps } from "./utils";

View file

@ -1,21 +1,21 @@
import React, { useState } from "react";
import { useFilter } from "react-aria";
import {
ComboBox,
ComboBoxProps as RACComboBoxProps,
Key,
ListBoxItemProps,
composeRenderProps,
GroupProps,
LabelContext,
Group,
GroupProps,
Key,
LabelContext,
ListBoxItemProps,
ComboBoxProps as RACComboBoxProps,
} from "react-aria-components";
import { useListData, ListData } from "react-stately";
import { useFilter } from "react-aria";
import { DescriptionProvider, LabeledGroup, Input, DescriptionContext } from "./field";
import { Popover } from "./popover";
import { ListBox, ListBoxItem } from "./list-box";
import { Button } from "./button";
import { ListData, useListData } from "react-stately";
import { twMerge } from "tailwind-merge";
import { Button } from "./button";
import { DescriptionContext, DescriptionProvider, Input, LabeledGroup } from "./field";
import { ListBox, ListBoxItem } from "./list-box";
import { Popover } from "./popover";
import { TagGroup, TagList } from "./tag-group";
import { composeTailwindRenderProps, inputField } from "./utils";

View file

@ -1,9 +1,9 @@
import React from "react";
import { useFocusRing } from "react-aria";
import { twMerge } from "tailwind-merge";
import { inputField } from "./utils";
import { DescriptionContext, DescriptionProvider } from "./field";
import { LabelContext } from "react-aria-components";
import { twMerge } from "tailwind-merge";
import { DescriptionContext, DescriptionProvider } from "./field";
import { inputField } from "./utils";
export function NativeSelectField({ className, ...props }: React.JSX.IntrinsicElements["div"]) {
const labelId = React.useId();

View file

@ -1,14 +1,14 @@
import {
Group,
InputProps,
NumberField as RACNumberField,
NumberFieldProps as RACNumberFieldProps,
InputProps,
Group,
} from "react-aria-components";
import { Input } from "./field";
import { composeTailwindRenderProps, inputField } from "./utils";
import { Button } from "./button";
import { Separator } from "./separator";
import { Input } from "./field";
import { MinusIcon, PlusIcon } from "./icons";
import { Separator } from "./separator";
import { composeTailwindRenderProps, inputField } from "./utils";
export interface NumberFieldProps extends RACNumberFieldProps {}

View file

@ -1,8 +1,8 @@
import { LinkProps } from "react-aria-components";
import { twMerge } from "tailwind-merge";
import { Button } from "./button";
import { Link } from "./link";
import { LinkProps } from "react-aria-components";
import { ChevronLeftIcon, ChevronRightIcon } from "./icons";
import { Link } from "./link";
export function Pagination({
className,

View file

@ -1,9 +1,9 @@
import React from "react";
import { InputProps, Group } from "react-aria-components";
import { Input } from "./field";
import { Group, InputProps } from "react-aria-components";
import { ToggleButton } from "./button";
import { composeTailwindRenderProps } from "./utils";
import { Input } from "./field";
import { EyeIcon, EyeOffIcon } from "./icons";
import { composeTailwindRenderProps } from "./utils";
export function PasswordInput({ className, ...props }: InputProps) {
const [isPasswordVisible, setIsPasswordVisible] = React.useState(false);

View file

@ -1,10 +1,10 @@
import React from "react";
import {
PopoverContext,
Popover as RACPopover,
PopoverProps as RACPopoverProps,
useSlottedContext,
PopoverContext,
} from "react-aria-components";
import React from "react";
import { composeTailwindRenderProps } from "./utils";
export interface PopoverProps extends Omit<RACPopoverProps, "children"> {

View file

@ -1,16 +1,16 @@
import { getLocalTimeZone, isToday } from "@internationalized/date";
import {
RangeCalendar as RACRangeCalendar,
RangeCalendarProps as RACRangeCalendarProps,
CalendarCell,
CalendarGrid,
CalendarGridBody,
DateValue,
Text,
composeRenderProps,
DateValue,
RangeCalendar as RACRangeCalendar,
RangeCalendarProps as RACRangeCalendarProps,
Text,
} from "react-aria-components";
import { CalendarGridHeader, CalendarHeader } from "./calendar";
import { twMerge } from "tailwind-merge";
import { getLocalTimeZone, isToday } from "@internationalized/date";
import { CalendarGridHeader, CalendarHeader } from "./calendar";
export interface RangeCalendarProps<T extends DateValue>
extends Omit<RACRangeCalendarProps<T>, "visibleDuration"> {

Some files were not shown because too many files have changed in this diff Show more