feat: Implement view management features with a new UI for editing and listing views
- Added a resizable panel layout in the studio app to display the view list alongside the main application. - Refactored the studio store to include new methods for fetching and managing route views. - Introduced a new DataItemForm component for configuring data items in views. - Created a ViewEditor component for adding and editing views, including data items and queries. - Enhanced the ViewList component to support searching, adding, editing, and deleting views. - Updated UI components (Button, Checkbox, Dialog, Input, Label, Table) for better styling and functionality. - Added environment configuration for API URL. - Introduced a new workspace configuration for pnpm.
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^5.1.6"
|
"nanoid": "^5.1.6",
|
||||||
|
"zod": "^4.2.1",
|
||||||
|
"zod-to-json-schema": "^3.25.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
pnpm-lock.yaml
generated
20
pnpm-lock.yaml
generated
@@ -11,6 +11,12 @@ importers:
|
|||||||
nanoid:
|
nanoid:
|
||||||
specifier: ^5.1.6
|
specifier: ^5.1.6
|
||||||
version: 5.1.6
|
version: 5.1.6
|
||||||
|
zod:
|
||||||
|
specifier: ^4.2.1
|
||||||
|
version: 4.2.1
|
||||||
|
zod-to-json-schema:
|
||||||
|
specifier: ^3.25.1
|
||||||
|
version: 3.25.1(zod@4.2.1)
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@@ -19,6 +25,20 @@ packages:
|
|||||||
engines: {node: ^18 || >=20}
|
engines: {node: ^18 || >=20}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
zod-to-json-schema@3.25.1:
|
||||||
|
resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==}
|
||||||
|
peerDependencies:
|
||||||
|
zod: ^3.25 || ^4
|
||||||
|
|
||||||
|
zod@4.2.1:
|
||||||
|
resolution: {integrity: sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==}
|
||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
nanoid@5.1.6: {}
|
nanoid@5.1.6: {}
|
||||||
|
|
||||||
|
zod-to-json-schema@3.25.1(zod@4.2.1):
|
||||||
|
dependencies:
|
||||||
|
zod: 4.2.1
|
||||||
|
|
||||||
|
zod@4.2.1: {}
|
||||||
|
|||||||
1
web/.env.example
Normal file
1
web/.env.example
Normal file
@@ -0,0 +1 @@
|
|||||||
|
VITE_API_URL='http://localhost:4005'
|
||||||
3
web/.gitignore
vendored
3
web/.gitignore
vendored
@@ -4,3 +4,6 @@ node_modules
|
|||||||
.astro
|
.astro
|
||||||
|
|
||||||
dist
|
dist
|
||||||
|
|
||||||
|
.env
|
||||||
|
!.env*example
|
||||||
@@ -11,6 +11,7 @@ dotenv.config();
|
|||||||
const isDev = process.env.NODE_ENV === 'development';
|
const isDev = process.env.NODE_ENV === 'development';
|
||||||
|
|
||||||
let target = process.env.VITE_API_URL || 'http://localhost:51515';
|
let target = process.env.VITE_API_URL || 'http://localhost:51515';
|
||||||
|
console.log('API Proxy Target:', target);
|
||||||
const apiProxy = { target: target, changeOrigin: true, ws: true, rewriteWsOrigin: true, secure: false, cookieDomainRewrite: 'localhost' };
|
const apiProxy = { target: target, changeOrigin: true, ws: true, rewriteWsOrigin: true, secure: false, cookieDomainRewrite: 'localhost' };
|
||||||
let proxy = {
|
let proxy = {
|
||||||
'/root/': apiProxy,
|
'/root/': apiProxy,
|
||||||
|
|||||||
@@ -23,11 +23,14 @@
|
|||||||
"@astrojs/react": "^4.4.2",
|
"@astrojs/react": "^4.4.2",
|
||||||
"@astrojs/sitemap": "^3.6.0",
|
"@astrojs/sitemap": "^3.6.0",
|
||||||
"@astrojs/vue": "^5.1.3",
|
"@astrojs/vue": "^5.1.3",
|
||||||
|
"@kevisual/cache": "^0.0.5",
|
||||||
"@kevisual/context": "^0.0.4",
|
"@kevisual/context": "^0.0.4",
|
||||||
"@kevisual/query": "^0.0.33",
|
"@kevisual/query": "^0.0.33",
|
||||||
"@kevisual/query-login": "^0.0.7",
|
"@kevisual/query-login": "^0.0.7",
|
||||||
"@kevisual/registry": "^0.0.1",
|
"@kevisual/registry": "^0.0.1",
|
||||||
"@kevisual/router": "^0.0.51",
|
"@kevisual/router": "^0.0.52",
|
||||||
|
"@radix-ui/react-checkbox": "^1.3.3",
|
||||||
|
"@radix-ui/react-label": "^2.1.8",
|
||||||
"@radix-ui/react-slot": "^1.2.4",
|
"@radix-ui/react-slot": "^1.2.4",
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
"@uiw/react-md-editor": "^4.0.11",
|
"@uiw/react-md-editor": "^4.0.11",
|
||||||
@@ -39,13 +42,17 @@
|
|||||||
"dayjs": "^1.11.19",
|
"dayjs": "^1.11.19",
|
||||||
"es-toolkit": "^1.43.0",
|
"es-toolkit": "^1.43.0",
|
||||||
"github-markdown-css": "^5.8.1",
|
"github-markdown-css": "^5.8.1",
|
||||||
|
"handsontable": "^16.2.0",
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"lucide-react": "^0.562.0",
|
"lucide-react": "^0.562.0",
|
||||||
"marked": "^17.0.1",
|
"marked": "^17.0.1",
|
||||||
"marked-highlight": "^2.2.3",
|
"marked-highlight": "^2.2.3",
|
||||||
"nanoid": "^5.1.6",
|
"nanoid": "^5.1.6",
|
||||||
|
"papaparse": "^5.5.3",
|
||||||
"react": "^19.2.3",
|
"react": "^19.2.3",
|
||||||
"react-dom": "^19.2.3",
|
"react-dom": "^19.2.3",
|
||||||
|
"react-hook-form": "^7.69.0",
|
||||||
|
"react-resizable-panels": "^4.1.0",
|
||||||
"react-toastify": "^11.0.5",
|
"react-toastify": "^11.0.5",
|
||||||
"tailwind-merge": "^3.4.0",
|
"tailwind-merge": "^3.4.0",
|
||||||
"vue": "^3.5.26",
|
"vue": "^3.5.26",
|
||||||
@@ -55,7 +62,7 @@
|
|||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@kevisual/api": "^0.0.10",
|
"@kevisual/api": "^0.0.14",
|
||||||
"@kevisual/types": "^0.0.10",
|
"@kevisual/types": "^0.0.10",
|
||||||
"@types/react": "^19.2.7",
|
"@types/react": "^19.2.7",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
@@ -63,7 +70,7 @@
|
|||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
"tw-animate-css": "^1.4.0"
|
"tw-animate-css": "^1.4.0"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.26.2",
|
"packageManager": "pnpm@10.27.0",
|
||||||
"onlyBuiltDependencies": [
|
"onlyBuiltDependencies": [
|
||||||
"@tailwindcss/oxide",
|
"@tailwindcss/oxide",
|
||||||
"esbuild",
|
"esbuild",
|
||||||
|
|||||||
265
web/pnpm-lock.yaml
generated
265
web/pnpm-lock.yaml
generated
@@ -20,6 +20,9 @@ importers:
|
|||||||
'@astrojs/vue':
|
'@astrojs/vue':
|
||||||
specifier: ^5.1.3
|
specifier: ^5.1.3
|
||||||
version: 5.1.3(@types/node@24.7.2)(astro@5.16.6(@types/node@24.7.2)(idb-keyval@6.2.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.52.4)(typescript@5.9.3))(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.52.4)(vue@3.5.26(typescript@5.9.3))
|
version: 5.1.3(@types/node@24.7.2)(astro@5.16.6(@types/node@24.7.2)(idb-keyval@6.2.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.52.4)(typescript@5.9.3))(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.52.4)(vue@3.5.26(typescript@5.9.3))
|
||||||
|
'@kevisual/cache':
|
||||||
|
specifier: ^0.0.5
|
||||||
|
version: 0.0.5
|
||||||
'@kevisual/context':
|
'@kevisual/context':
|
||||||
specifier: ^0.0.4
|
specifier: ^0.0.4
|
||||||
version: 0.0.4
|
version: 0.0.4
|
||||||
@@ -33,8 +36,14 @@ importers:
|
|||||||
specifier: ^0.0.1
|
specifier: ^0.0.1
|
||||||
version: 0.0.1(typescript@5.9.3)
|
version: 0.0.1(typescript@5.9.3)
|
||||||
'@kevisual/router':
|
'@kevisual/router':
|
||||||
specifier: ^0.0.51
|
specifier: ^0.0.52
|
||||||
version: 0.0.51
|
version: 0.0.52
|
||||||
|
'@radix-ui/react-checkbox':
|
||||||
|
specifier: ^1.3.3
|
||||||
|
version: 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
'@radix-ui/react-label':
|
||||||
|
specifier: ^2.1.8
|
||||||
|
version: 2.1.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
'@radix-ui/react-slot':
|
'@radix-ui/react-slot':
|
||||||
specifier: ^1.2.4
|
specifier: ^1.2.4
|
||||||
version: 1.2.4(@types/react@19.2.7)(react@19.2.3)
|
version: 1.2.4(@types/react@19.2.7)(react@19.2.3)
|
||||||
@@ -46,7 +55,7 @@ importers:
|
|||||||
version: 4.0.11(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
version: 4.0.11(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
antd:
|
antd:
|
||||||
specifier: ^6.1.3
|
specifier: ^6.1.3
|
||||||
version: 6.1.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
version: 6.1.3(moment@2.30.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
astro:
|
astro:
|
||||||
specifier: ^5.16.6
|
specifier: ^5.16.6
|
||||||
version: 5.16.6(@types/node@24.7.2)(idb-keyval@6.2.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.52.4)(typescript@5.9.3)
|
version: 5.16.6(@types/node@24.7.2)(idb-keyval@6.2.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.52.4)(typescript@5.9.3)
|
||||||
@@ -68,6 +77,9 @@ importers:
|
|||||||
github-markdown-css:
|
github-markdown-css:
|
||||||
specifier: ^5.8.1
|
specifier: ^5.8.1
|
||||||
version: 5.8.1
|
version: 5.8.1
|
||||||
|
handsontable:
|
||||||
|
specifier: ^16.2.0
|
||||||
|
version: 16.2.0
|
||||||
highlight.js:
|
highlight.js:
|
||||||
specifier: ^11.11.1
|
specifier: ^11.11.1
|
||||||
version: 11.11.1
|
version: 11.11.1
|
||||||
@@ -83,12 +95,21 @@ importers:
|
|||||||
nanoid:
|
nanoid:
|
||||||
specifier: ^5.1.6
|
specifier: ^5.1.6
|
||||||
version: 5.1.6
|
version: 5.1.6
|
||||||
|
papaparse:
|
||||||
|
specifier: ^5.5.3
|
||||||
|
version: 5.5.3
|
||||||
react:
|
react:
|
||||||
specifier: ^19.2.3
|
specifier: ^19.2.3
|
||||||
version: 19.2.3
|
version: 19.2.3
|
||||||
react-dom:
|
react-dom:
|
||||||
specifier: ^19.2.3
|
specifier: ^19.2.3
|
||||||
version: 19.2.3(react@19.2.3)
|
version: 19.2.3(react@19.2.3)
|
||||||
|
react-hook-form:
|
||||||
|
specifier: ^7.69.0
|
||||||
|
version: 7.69.0(react@19.2.3)
|
||||||
|
react-resizable-panels:
|
||||||
|
specifier: ^4.1.0
|
||||||
|
version: 4.1.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
react-toastify:
|
react-toastify:
|
||||||
specifier: ^11.0.5
|
specifier: ^11.0.5
|
||||||
version: 11.0.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
version: 11.0.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
@@ -103,8 +124,8 @@ importers:
|
|||||||
version: 5.0.9(@types/react@19.2.7)(react@19.2.3)
|
version: 5.0.9(@types/react@19.2.7)(react@19.2.3)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@kevisual/api':
|
'@kevisual/api':
|
||||||
specifier: ^0.0.10
|
specifier: ^0.0.14
|
||||||
version: 0.0.10
|
version: 0.0.14
|
||||||
'@kevisual/types':
|
'@kevisual/types':
|
||||||
specifier: ^0.0.10
|
specifier: ^0.0.10
|
||||||
version: 0.0.10
|
version: 0.0.10
|
||||||
@@ -539,6 +560,9 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@handsontable/pikaday@1.0.0':
|
||||||
|
resolution: {integrity: sha512-1VN6N38t5/DcjJ7y7XUYrDx1LuzvvzlrFdBdMG90Qo1xc8+LXHqbWbsTEm5Ec5gXTEbDEO53vUT35R+2COmOyg==}
|
||||||
|
|
||||||
'@img/colour@1.0.0':
|
'@img/colour@1.0.0':
|
||||||
resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==}
|
resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -681,17 +705,20 @@ packages:
|
|||||||
'@jridgewell/trace-mapping@0.3.31':
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||||
|
|
||||||
'@kevisual/api@0.0.10':
|
'@kevisual/api@0.0.14':
|
||||||
resolution: {integrity: sha512-AF5DcXPfVEZtvIJw9EC8EXkhU33dS08v9+b4mIrzCi0ETRvwAlQ2cg8WgfY6exJYzbFg6M4h+POhXvPujrk9mA==}
|
resolution: {integrity: sha512-GOs61Jvjxs+7PB8+iSPko9/RGeWENxltHueV75M6W0psRsnx/J+06I48/cO413FwCoqSOqpOoivdRgSENdHM9g==}
|
||||||
|
|
||||||
'@kevisual/cache@0.0.3':
|
'@kevisual/cache@0.0.3':
|
||||||
resolution: {integrity: sha512-BWEck69KYL96/ywjYVkML974RHjDJTj2ITQND1zFPR+hlBV1H1p55QZgSYRJCObg3EAV1S9Zic/fR2T4pfe8yg==}
|
resolution: {integrity: sha512-BWEck69KYL96/ywjYVkML974RHjDJTj2ITQND1zFPR+hlBV1H1p55QZgSYRJCObg3EAV1S9Zic/fR2T4pfe8yg==}
|
||||||
|
|
||||||
|
'@kevisual/cache@0.0.5':
|
||||||
|
resolution: {integrity: sha512-fgtUYGUUq/DY0KFV4CkWszNqvQUaA8XvMTUjoR9ZXRpau5IIDolD/Wen2TFsZ7G3Rfy+lef5dnaiZVDkZwdVKg==}
|
||||||
|
|
||||||
'@kevisual/context@0.0.4':
|
'@kevisual/context@0.0.4':
|
||||||
resolution: {integrity: sha512-HJeLeZQLU+7tCluSfOyvkgKLs0HjCZrdJlZgEgKRSa8XTwZfMAUt6J7qZTbrZAHBlPtX68EPu/PI8JMCeu3WAQ==}
|
resolution: {integrity: sha512-HJeLeZQLU+7tCluSfOyvkgKLs0HjCZrdJlZgEgKRSa8XTwZfMAUt6J7qZTbrZAHBlPtX68EPu/PI8JMCeu3WAQ==}
|
||||||
|
|
||||||
'@kevisual/js-filter@0.0.2':
|
'@kevisual/js-filter@0.0.3':
|
||||||
resolution: {integrity: sha512-SS8diRpjrAIEQKT8YMTa1XTucQKuPbG04UChXtp7wd1jPsvQaNKYapErRA8qx4igwoVQt6eAYADwYzXhB1fN2A==}
|
resolution: {integrity: sha512-vgUB2fUAWS75GUFr/a/tGSSDrPUUmVDktO38k3hIKwU3ZE4tpuhcVxrpUbkXlFS5i0rbL2mAQeID1C6kIlMGRg==}
|
||||||
|
|
||||||
'@kevisual/load@0.0.6':
|
'@kevisual/load@0.0.6':
|
||||||
resolution: {integrity: sha512-+3YTFehRcZ1haGel5DKYMUwmi5i6f2psyaPZlfkKU/cOXgkpwoG9/BEqPCnPjicKqqnksEpixVRkyHJ+5bjLVA==}
|
resolution: {integrity: sha512-+3YTFehRcZ1haGel5DKYMUwmi5i6f2psyaPZlfkKU/cOXgkpwoG9/BEqPCnPjicKqqnksEpixVRkyHJ+5bjLVA==}
|
||||||
@@ -707,8 +734,8 @@ packages:
|
|||||||
'@kevisual/registry@0.0.1':
|
'@kevisual/registry@0.0.1':
|
||||||
resolution: {integrity: sha512-//OHu9m4JDrMjgP8o8dcjZd3D3IAUkRVlkTSviouZEH7r5m7mccA3Hvzw0XJ/lelx6exC6LWsyv6c4uV0Dp+gw==}
|
resolution: {integrity: sha512-//OHu9m4JDrMjgP8o8dcjZd3D3IAUkRVlkTSviouZEH7r5m7mccA3Hvzw0XJ/lelx6exC6LWsyv6c4uV0Dp+gw==}
|
||||||
|
|
||||||
'@kevisual/router@0.0.51':
|
'@kevisual/router@0.0.52':
|
||||||
resolution: {integrity: sha512-i9qYBeS/um78oC912oWJD3iElB+5NTKyTrz1Hzf4DckiUFnjLL81UPwjIh5I2l9+ul0IZ/Pxx+sFSF99fJkzKg==}
|
resolution: {integrity: sha512-Qiv3P1XjzD813Tm79S+atrDb2eickGCI9tuy/aCu512LcoYYJqZhwwkeT4ES0DinnA13Ckqd43QWBR6UmuYkHQ==}
|
||||||
|
|
||||||
'@kevisual/types@0.0.10':
|
'@kevisual/types@0.0.10':
|
||||||
resolution: {integrity: sha512-Q73uzzjk9UidumnmCvOpgzqDDvQxsblz22bIFuoiioUFJWwaparx8bpd8ArRyFojicYL1YJoFDzDZ9j9NN8grA==}
|
resolution: {integrity: sha512-Q73uzzjk9UidumnmCvOpgzqDDvQxsblz22bIFuoiioUFJWwaparx8bpd8ArRyFojicYL1YJoFDzDZ9j9NN8grA==}
|
||||||
@@ -763,6 +790,19 @@ packages:
|
|||||||
'@radix-ui/primitive@1.1.3':
|
'@radix-ui/primitive@1.1.3':
|
||||||
resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==}
|
resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==}
|
||||||
|
|
||||||
|
'@radix-ui/react-checkbox@1.3.3':
|
||||||
|
resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-compose-refs@1.1.2':
|
'@radix-ui/react-compose-refs@1.1.2':
|
||||||
resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==}
|
resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -838,6 +878,19 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-label@2.1.8':
|
||||||
|
resolution: {integrity: sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-portal@1.1.9':
|
'@radix-ui/react-portal@1.1.9':
|
||||||
resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==}
|
resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -953,6 +1006,24 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-use-previous@1.1.1':
|
||||||
|
resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-use-size@1.1.1':
|
||||||
|
resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@rc-component/async-validator@5.0.4':
|
'@rc-component/async-validator@5.0.4':
|
||||||
resolution: {integrity: sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==}
|
resolution: {integrity: sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==}
|
||||||
engines: {node: '>=14.x'}
|
engines: {node: '>=14.x'}
|
||||||
@@ -1541,6 +1612,9 @@ packages:
|
|||||||
'@types/sax@1.2.7':
|
'@types/sax@1.2.7':
|
||||||
resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
|
resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
|
||||||
|
|
||||||
|
'@types/trusted-types@2.0.7':
|
||||||
|
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
||||||
|
|
||||||
'@types/unist@2.0.11':
|
'@types/unist@2.0.11':
|
||||||
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
|
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
|
||||||
|
|
||||||
@@ -1741,6 +1815,9 @@ packages:
|
|||||||
bcp-47-match@2.0.3:
|
bcp-47-match@2.0.3:
|
||||||
resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==}
|
resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==}
|
||||||
|
|
||||||
|
bignumber.js@9.3.1:
|
||||||
|
resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==}
|
||||||
|
|
||||||
birpc@2.8.0:
|
birpc@2.8.0:
|
||||||
resolution: {integrity: sha512-Bz2a4qD/5GRhiHSwj30c/8kC8QGj12nNDwz3D4ErQ4Xhy35dsSDvF+RA/tWpjyU0pdGtSDiEk6B5fBGE1qNVhw==}
|
resolution: {integrity: sha512-Bz2a4qD/5GRhiHSwj30c/8kC8QGj12nNDwz3D4ErQ4Xhy35dsSDvF+RA/tWpjyU0pdGtSDiEk6B5fBGE1qNVhw==}
|
||||||
|
|
||||||
@@ -1793,6 +1870,9 @@ packages:
|
|||||||
character-reference-invalid@2.0.1:
|
character-reference-invalid@2.0.1:
|
||||||
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
|
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
|
||||||
|
|
||||||
|
chevrotain@6.5.0:
|
||||||
|
resolution: {integrity: sha512-BwqQ/AgmKJ8jcMEjaSnfMybnKMgGTrtDKowfTP3pX4jwVy0kNjRsT/AP6h+wC3+3NC+X8X15VWBnTCQlX+wQFg==}
|
||||||
|
|
||||||
chokidar@4.0.3:
|
chokidar@4.0.3:
|
||||||
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
||||||
engines: {node: '>= 14.16.0'}
|
engines: {node: '>= 14.16.0'}
|
||||||
@@ -1855,6 +1935,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==}
|
resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
core-js@3.47.0:
|
||||||
|
resolution: {integrity: sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==}
|
||||||
|
|
||||||
cross-fetch@4.0.0:
|
cross-fetch@4.0.0:
|
||||||
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
|
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
|
||||||
|
|
||||||
@@ -1977,6 +2060,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
|
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
|
dompurify@3.3.1:
|
||||||
|
resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==}
|
||||||
|
|
||||||
domutils@3.2.2:
|
domutils@3.2.2:
|
||||||
resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
|
resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
|
||||||
|
|
||||||
@@ -2157,6 +2243,9 @@ packages:
|
|||||||
h3@1.15.4:
|
h3@1.15.4:
|
||||||
resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==}
|
resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==}
|
||||||
|
|
||||||
|
handsontable@16.2.0:
|
||||||
|
resolution: {integrity: sha512-4zhMQON9DPyip/6YIPH2G7jN+QEJ0uabCZruhrhOqTqr3Qf/FDjsTInUaEzMCmhhdii5MbA6PGyLfUad6t1sXA==}
|
||||||
|
|
||||||
hast-util-from-html@2.0.3:
|
hast-util-from-html@2.0.3:
|
||||||
resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==}
|
resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==}
|
||||||
|
|
||||||
@@ -2241,6 +2330,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
|
resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
|
||||||
engines: {node: '>=18.18.0'}
|
engines: {node: '>=18.18.0'}
|
||||||
|
|
||||||
|
hyperformula@3.1.1:
|
||||||
|
resolution: {integrity: sha512-v+yvRPZGL73KinH2lvS4/1QMe2xNviTfgIcVgKjzKGi66xEuvuoDRgQ48ODc4XhD+c+JLNfs9Ln1GnHQ5TDNGA==}
|
||||||
|
|
||||||
i18next-browser-languagedetector@8.2.0:
|
i18next-browser-languagedetector@8.2.0:
|
||||||
resolution: {integrity: sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==}
|
resolution: {integrity: sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==}
|
||||||
|
|
||||||
@@ -2432,6 +2524,10 @@ packages:
|
|||||||
lru-cache@10.4.3:
|
lru-cache@10.4.3:
|
||||||
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
||||||
|
|
||||||
|
lru-cache@11.2.4:
|
||||||
|
resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==}
|
||||||
|
engines: {node: 20 || >=22}
|
||||||
|
|
||||||
lru-cache@5.1.1:
|
lru-cache@5.1.1:
|
||||||
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
||||||
|
|
||||||
@@ -2641,6 +2737,9 @@ packages:
|
|||||||
mitt@3.0.1:
|
mitt@3.0.1:
|
||||||
resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
|
resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
|
||||||
|
|
||||||
|
moment@2.30.1:
|
||||||
|
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
||||||
|
|
||||||
mrmime@2.0.1:
|
mrmime@2.0.1:
|
||||||
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -2694,6 +2793,9 @@ packages:
|
|||||||
nth-check@2.1.1:
|
nth-check@2.1.1:
|
||||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||||
|
|
||||||
|
numbro@2.5.0:
|
||||||
|
resolution: {integrity: sha512-xDcctDimhzko/e+y+Q2/8i3qNC9Svw1QgOkSkQoO0kIPI473tR9QRbo2KP88Ty9p8WbPy+3OpTaAIzehtuHq+A==}
|
||||||
|
|
||||||
ofetch@1.5.1:
|
ofetch@1.5.1:
|
||||||
resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==}
|
resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==}
|
||||||
|
|
||||||
@@ -2732,6 +2834,9 @@ packages:
|
|||||||
pako@0.2.9:
|
pako@0.2.9:
|
||||||
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
|
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
|
||||||
|
|
||||||
|
papaparse@5.5.3:
|
||||||
|
resolution: {integrity: sha512-5QvjGxYVjxO59MGU2lHVYpRWBBtKHnlIAcSe1uNFCkkptUh63NFRj0FJQm7nR67puEruUci/ZkjmEFrjCAyP4A==}
|
||||||
|
|
||||||
parse-entities@4.0.2:
|
parse-entities@4.0.2:
|
||||||
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
|
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
|
||||||
|
|
||||||
@@ -2824,6 +2929,12 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^19.2.3
|
react: ^19.2.3
|
||||||
|
|
||||||
|
react-hook-form@7.69.0:
|
||||||
|
resolution: {integrity: sha512-yt6ZGME9f4F6WHwevrvpAjh42HMvocuSnSIHUGycBqXIJdhqGSPQzTpGF+1NLREk/58IdPxEMfPcFCjlMhclGw==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.8.0 || ^17 || ^18 || ^19
|
||||||
|
|
||||||
react-i18next@15.7.4:
|
react-i18next@15.7.4:
|
||||||
resolution: {integrity: sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw==}
|
resolution: {integrity: sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2873,6 +2984,12 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
react-resizable-panels@4.1.0:
|
||||||
|
resolution: {integrity: sha512-8ZpOwdKQz6bCs2LGnfS6HuBITxkOLelSMzBX4DrWsgHaU3ukTPxmBNAeK8Bsp3LAEdtXeG6ll6UPN7OJNua4sw==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^18.0.0 || ^19.0.0
|
||||||
|
react-dom: ^18.0.0 || ^19.0.0
|
||||||
|
|
||||||
react-style-singleton@2.2.3:
|
react-style-singleton@2.2.3:
|
||||||
resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
|
resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -2926,6 +3043,9 @@ packages:
|
|||||||
regex@6.0.1:
|
regex@6.0.1:
|
||||||
resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==}
|
resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==}
|
||||||
|
|
||||||
|
regexp-to-ast@0.4.0:
|
||||||
|
resolution: {integrity: sha512-4qf/7IsIKfSNHQXSwial1IFmfM1Cc/whNBQqRwe0V2stPe7KmN1U0tWQiIx6JiirgSrisjE0eECdNf7Tav1Ntw==}
|
||||||
|
|
||||||
rehype-attr@3.0.3:
|
rehype-attr@3.0.3:
|
||||||
resolution: {integrity: sha512-Up50Xfra8tyxnkJdCzLBIBtxOcB2M1xdeKe1324U06RAvSjYm7ULSeoM+b/nYPQPVd7jsXJ9+39IG1WAJPXONw==}
|
resolution: {integrity: sha512-Up50Xfra8tyxnkJdCzLBIBtxOcB2M1xdeKe1324U06RAvSjYm7ULSeoM+b/nYPQPVd7jsXJ9+39IG1WAJPXONw==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
@@ -3159,6 +3279,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==}
|
resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==}
|
||||||
engines: {node: '>=12.22'}
|
engines: {node: '>=12.22'}
|
||||||
|
|
||||||
|
tiny-emitter@2.1.0:
|
||||||
|
resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==}
|
||||||
|
|
||||||
tiny-inflate@1.0.3:
|
tiny-inflate@1.0.3:
|
||||||
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
|
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
|
||||||
|
|
||||||
@@ -4037,6 +4160,8 @@ snapshots:
|
|||||||
'@esbuild/win32-x64@0.25.10':
|
'@esbuild/win32-x64@0.25.10':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@handsontable/pikaday@1.0.0': {}
|
||||||
|
|
||||||
'@img/colour@1.0.0':
|
'@img/colour@1.0.0':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -4145,20 +4270,27 @@ snapshots:
|
|||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
'@kevisual/api@0.0.10':
|
'@kevisual/api@0.0.14':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@kevisual/js-filter': 0.0.2
|
'@kevisual/js-filter': 0.0.3
|
||||||
'@kevisual/load': 0.0.6
|
'@kevisual/load': 0.0.6
|
||||||
es-toolkit: 1.43.0
|
es-toolkit: 1.43.0
|
||||||
|
eventemitter3: 5.0.1
|
||||||
nanoid: 5.1.6
|
nanoid: 5.1.6
|
||||||
|
|
||||||
'@kevisual/cache@0.0.3':
|
'@kevisual/cache@0.0.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
idb-keyval: 6.2.2
|
idb-keyval: 6.2.2
|
||||||
|
|
||||||
|
'@kevisual/cache@0.0.5':
|
||||||
|
dependencies:
|
||||||
|
idb-keyval: 6.2.2
|
||||||
|
lru-cache: 11.2.4
|
||||||
|
nanoid: 5.1.6
|
||||||
|
|
||||||
'@kevisual/context@0.0.4': {}
|
'@kevisual/context@0.0.4': {}
|
||||||
|
|
||||||
'@kevisual/js-filter@0.0.2': {}
|
'@kevisual/js-filter@0.0.3': {}
|
||||||
|
|
||||||
'@kevisual/load@0.0.6':
|
'@kevisual/load@0.0.6':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4190,8 +4322,9 @@ snapshots:
|
|||||||
- react-native
|
- react-native
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
'@kevisual/router@0.0.51':
|
'@kevisual/router@0.0.52':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
eventemitter3: 5.0.1
|
||||||
path-to-regexp: 8.3.0
|
path-to-regexp: 8.3.0
|
||||||
selfsigned: 5.4.0
|
selfsigned: 5.4.0
|
||||||
send: 1.2.1
|
send: 1.2.1
|
||||||
@@ -4328,6 +4461,22 @@ snapshots:
|
|||||||
|
|
||||||
'@radix-ui/primitive@1.1.3': {}
|
'@radix-ui/primitive@1.1.3': {}
|
||||||
|
|
||||||
|
'@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.3
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
|
||||||
|
'@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
|
||||||
|
'@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
|
||||||
|
'@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.7)(react@19.2.3)
|
||||||
|
'@radix-ui/react-use-size': 1.1.1(@types/react@19.2.7)(react@19.2.3)
|
||||||
|
react: 19.2.3
|
||||||
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.2.7
|
||||||
|
'@types/react-dom': 19.2.3(@types/react@19.2.7)
|
||||||
|
|
||||||
'@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.7)(react@19.2.3)':
|
'@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.7)(react@19.2.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 19.2.3
|
react: 19.2.3
|
||||||
@@ -4399,6 +4548,15 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.7
|
'@types/react': 19.2.7
|
||||||
|
|
||||||
|
'@radix-ui/react-label@2.1.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
|
react: 19.2.3
|
||||||
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.2.7
|
||||||
|
'@types/react-dom': 19.2.3(@types/react@19.2.7)
|
||||||
|
|
||||||
'@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
'@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
@@ -4485,6 +4643,19 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.7
|
'@types/react': 19.2.7
|
||||||
|
|
||||||
|
'@radix-ui/react-use-previous@1.1.1(@types/react@19.2.7)(react@19.2.3)':
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.3
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.2.7
|
||||||
|
|
||||||
|
'@radix-ui/react-use-size@1.1.1(@types/react@19.2.7)(react@19.2.3)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
|
||||||
|
react: 19.2.3
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.2.7
|
||||||
|
|
||||||
'@rc-component/async-validator@5.0.4':
|
'@rc-component/async-validator@5.0.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.28.4
|
'@babel/runtime': 7.28.4
|
||||||
@@ -4648,7 +4819,7 @@ snapshots:
|
|||||||
react: 19.2.3
|
react: 19.2.3
|
||||||
react-dom: 19.2.3(react@19.2.3)
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
|
||||||
'@rc-component/picker@1.9.0(dayjs@1.11.19)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
'@rc-component/picker@1.9.0(dayjs@1.11.19)(moment@2.30.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rc-component/overflow': 1.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@rc-component/overflow': 1.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
'@rc-component/resize-observer': 1.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@rc-component/resize-observer': 1.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
@@ -4659,6 +4830,7 @@ snapshots:
|
|||||||
react-dom: 19.2.3(react@19.2.3)
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
dayjs: 1.11.19
|
dayjs: 1.11.19
|
||||||
|
moment: 2.30.1
|
||||||
|
|
||||||
'@rc-component/portal@2.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
'@rc-component/portal@2.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5091,6 +5263,9 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 17.0.45
|
'@types/node': 17.0.45
|
||||||
|
|
||||||
|
'@types/trusted-types@2.0.7':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@types/unist@2.0.11': {}
|
'@types/unist@2.0.11': {}
|
||||||
|
|
||||||
'@types/unist@3.0.3': {}
|
'@types/unist@3.0.3': {}
|
||||||
@@ -5317,7 +5492,7 @@ snapshots:
|
|||||||
|
|
||||||
ansi-styles@6.2.3: {}
|
ansi-styles@6.2.3: {}
|
||||||
|
|
||||||
antd@6.1.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
antd@6.1.3(moment@2.30.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ant-design/colors': 8.0.0
|
'@ant-design/colors': 8.0.0
|
||||||
'@ant-design/cssinjs': 2.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@ant-design/cssinjs': 2.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
@@ -5343,7 +5518,7 @@ snapshots:
|
|||||||
'@rc-component/mutate-observer': 2.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@rc-component/mutate-observer': 2.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
'@rc-component/notification': 1.2.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@rc-component/notification': 1.2.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
'@rc-component/pagination': 1.2.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@rc-component/pagination': 1.2.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
'@rc-component/picker': 1.9.0(dayjs@1.11.19)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@rc-component/picker': 1.9.0(dayjs@1.11.19)(moment@2.30.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
'@rc-component/progress': 1.0.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@rc-component/progress': 1.0.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
'@rc-component/qrcode': 1.1.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@rc-component/qrcode': 1.1.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
'@rc-component/rate': 1.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
'@rc-component/rate': 1.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
@@ -5513,6 +5688,8 @@ snapshots:
|
|||||||
|
|
||||||
bcp-47-match@2.0.3: {}
|
bcp-47-match@2.0.3: {}
|
||||||
|
|
||||||
|
bignumber.js@9.3.1: {}
|
||||||
|
|
||||||
birpc@2.8.0: {}
|
birpc@2.8.0: {}
|
||||||
|
|
||||||
boolbase@1.0.0: {}
|
boolbase@1.0.0: {}
|
||||||
@@ -5562,6 +5739,11 @@ snapshots:
|
|||||||
|
|
||||||
character-reference-invalid@2.0.1: {}
|
character-reference-invalid@2.0.1: {}
|
||||||
|
|
||||||
|
chevrotain@6.5.0:
|
||||||
|
dependencies:
|
||||||
|
regexp-to-ast: 0.4.0
|
||||||
|
optional: true
|
||||||
|
|
||||||
chokidar@4.0.3:
|
chokidar@4.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
readdirp: 4.1.2
|
readdirp: 4.1.2
|
||||||
@@ -5612,6 +5794,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-what: 5.5.0
|
is-what: 5.5.0
|
||||||
|
|
||||||
|
core-js@3.47.0: {}
|
||||||
|
|
||||||
cross-fetch@4.0.0:
|
cross-fetch@4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
node-fetch: 2.7.0
|
node-fetch: 2.7.0
|
||||||
@@ -5719,6 +5903,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
domelementtype: 2.3.0
|
domelementtype: 2.3.0
|
||||||
|
|
||||||
|
dompurify@3.3.1:
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/trusted-types': 2.0.7
|
||||||
|
|
||||||
domutils@3.2.2:
|
domutils@3.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
dom-serializer: 2.0.0
|
dom-serializer: 2.0.0
|
||||||
@@ -5930,6 +6118,16 @@ snapshots:
|
|||||||
ufo: 1.6.1
|
ufo: 1.6.1
|
||||||
uncrypto: 0.1.3
|
uncrypto: 0.1.3
|
||||||
|
|
||||||
|
handsontable@16.2.0:
|
||||||
|
dependencies:
|
||||||
|
'@handsontable/pikaday': 1.0.0
|
||||||
|
core-js: 3.47.0
|
||||||
|
dompurify: 3.3.1
|
||||||
|
moment: 2.30.1
|
||||||
|
numbro: 2.5.0
|
||||||
|
optionalDependencies:
|
||||||
|
hyperformula: 3.1.1
|
||||||
|
|
||||||
hast-util-from-html@2.0.3:
|
hast-util-from-html@2.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
@@ -6126,6 +6324,12 @@ snapshots:
|
|||||||
|
|
||||||
human-signals@8.0.1: {}
|
human-signals@8.0.1: {}
|
||||||
|
|
||||||
|
hyperformula@3.1.1:
|
||||||
|
dependencies:
|
||||||
|
chevrotain: 6.5.0
|
||||||
|
tiny-emitter: 2.1.0
|
||||||
|
optional: true
|
||||||
|
|
||||||
i18next-browser-languagedetector@8.2.0:
|
i18next-browser-languagedetector@8.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.28.4
|
'@babel/runtime': 7.28.4
|
||||||
@@ -6266,6 +6470,8 @@ snapshots:
|
|||||||
|
|
||||||
lru-cache@10.4.3: {}
|
lru-cache@10.4.3: {}
|
||||||
|
|
||||||
|
lru-cache@11.2.4: {}
|
||||||
|
|
||||||
lru-cache@5.1.1:
|
lru-cache@5.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
yallist: 3.1.1
|
yallist: 3.1.1
|
||||||
@@ -6743,6 +6949,8 @@ snapshots:
|
|||||||
|
|
||||||
mitt@3.0.1: {}
|
mitt@3.0.1: {}
|
||||||
|
|
||||||
|
moment@2.30.1: {}
|
||||||
|
|
||||||
mrmime@2.0.1: {}
|
mrmime@2.0.1: {}
|
||||||
|
|
||||||
ms@2.1.3: {}
|
ms@2.1.3: {}
|
||||||
@@ -6778,6 +6986,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
boolbase: 1.0.0
|
boolbase: 1.0.0
|
||||||
|
|
||||||
|
numbro@2.5.0:
|
||||||
|
dependencies:
|
||||||
|
bignumber.js: 9.3.1
|
||||||
|
|
||||||
ofetch@1.5.1:
|
ofetch@1.5.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
destr: 2.0.5
|
destr: 2.0.5
|
||||||
@@ -6820,6 +7032,8 @@ snapshots:
|
|||||||
|
|
||||||
pako@0.2.9: {}
|
pako@0.2.9: {}
|
||||||
|
|
||||||
|
papaparse@5.5.3: {}
|
||||||
|
|
||||||
parse-entities@4.0.2:
|
parse-entities@4.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 2.0.11
|
'@types/unist': 2.0.11
|
||||||
@@ -6910,6 +7124,10 @@ snapshots:
|
|||||||
react: 19.2.3
|
react: 19.2.3
|
||||||
scheduler: 0.27.0
|
scheduler: 0.27.0
|
||||||
|
|
||||||
|
react-hook-form@7.69.0(react@19.2.3):
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.3
|
||||||
|
|
||||||
react-i18next@15.7.4(i18next@25.6.0(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3):
|
react-i18next@15.7.4(i18next@25.6.0(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.28.4
|
'@babel/runtime': 7.28.4
|
||||||
@@ -6960,6 +7178,11 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.7
|
'@types/react': 19.2.7
|
||||||
|
|
||||||
|
react-resizable-panels@4.1.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.3
|
||||||
|
react-dom: 19.2.3(react@19.2.3)
|
||||||
|
|
||||||
react-style-singleton@2.2.3(@types/react@19.2.7)(react@19.2.3):
|
react-style-singleton@2.2.3(@types/react@19.2.7)(react@19.2.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
get-nonce: 1.0.1
|
get-nonce: 1.0.1
|
||||||
@@ -7026,6 +7249,9 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
regex-utilities: 2.3.0
|
regex-utilities: 2.3.0
|
||||||
|
|
||||||
|
regexp-to-ast@0.4.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
rehype-attr@3.0.3:
|
rehype-attr@3.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
unified: 11.0.5
|
unified: 11.0.5
|
||||||
@@ -7396,6 +7622,9 @@ snapshots:
|
|||||||
|
|
||||||
throttle-debounce@5.0.2: {}
|
throttle-debounce@5.0.2: {}
|
||||||
|
|
||||||
|
tiny-emitter@2.1.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
tiny-inflate@1.0.3: {}
|
tiny-inflate@1.0.3: {}
|
||||||
|
|
||||||
tinyexec@1.0.2: {}
|
tinyexec@1.0.2: {}
|
||||||
|
|||||||
2
web/pnpm-workspace.yaml
Normal file
2
web/pnpm-workspace.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
onlyBuiltDependencies:
|
||||||
|
- core-js
|
||||||
@@ -2,9 +2,18 @@ import { toast, ToastContainer } from 'react-toastify';
|
|||||||
import { useStudioStore } from './store.ts';
|
import { useStudioStore } from './store.ts';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { MonitorPlay, Play } from 'lucide-react';
|
import { MonitorPlay, Play } from 'lucide-react';
|
||||||
|
import { Panel, Group } from 'react-resizable-panels'
|
||||||
|
import { ViewList } from '../view/list.tsx';
|
||||||
export const AppProvider = () => {
|
export const AppProvider = () => {
|
||||||
return <main className='w-full'>
|
return <main className='w-full h-screen flex flex-col overflow-hidden'>
|
||||||
|
<Group className="h-full flex-1 overflow-hidden">
|
||||||
|
<Panel defaultSize={300} minSize={250} maxSize={500} className="border-r overflow-auto">
|
||||||
|
<ViewList />
|
||||||
|
</Panel>
|
||||||
|
<Panel>
|
||||||
<App />
|
<App />
|
||||||
|
</Panel>
|
||||||
|
</Group>
|
||||||
<ToastContainer
|
<ToastContainer
|
||||||
position="top-right"
|
position="top-right"
|
||||||
autoClose={3000}
|
autoClose={3000}
|
||||||
@@ -28,12 +37,12 @@ interface RouteItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const App = () => {
|
export const App = () => {
|
||||||
const { routes, getRoutes, run } = useStudioStore();
|
const { routes, getRouteList, run } = useStudioStore();
|
||||||
const [expandedIds, setExpandedIds] = useState<Set<string>>(new Set());
|
const [expandedIds, setExpandedIds] = useState<Set<string>>(new Set());
|
||||||
const [visibleIds, setVisibleIds] = useState<Set<string>>(new Set());
|
const [visibleIds, setVisibleIds] = useState<Set<string>>(new Set());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getRoutes();
|
getRouteList();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const toggleDescription = (id: string) => {
|
const toggleDescription = (id: string) => {
|
||||||
@@ -58,7 +67,7 @@ export const App = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-5xl mx-auto p-6">
|
<div className="max-w-5xl mx-auto p-6 h-full overflow-auto">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
{routes.map((route: RouteItem) => {
|
{routes.map((route: RouteItem) => {
|
||||||
const isExpanded = expandedIds.has(route.id);
|
const isExpanded = expandedIds.has(route.id);
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { QueryProxy, ProxyItem } from '@kevisual/api'
|
import { QueryProxy, RouterViewData } from '@kevisual/api'
|
||||||
// import { query } from '@/modules/query.ts'
|
import { query } from '@/modules/query.ts'
|
||||||
import { QueryClient } from '@kevisual/query';
|
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { QueryRouterServer } from '@kevisual/router/src/route.ts'
|
import { use } from '@kevisual/context'
|
||||||
|
import { MyCache } from '@kevisual/cache'
|
||||||
|
|
||||||
type RouteItem = {
|
type RouteItem = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -13,58 +12,81 @@ type RouteItem = {
|
|||||||
description?: string;
|
description?: string;
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, any>;
|
||||||
}
|
}
|
||||||
// type ProxyItem = {
|
|
||||||
// title?: string;
|
type RouteViewList = Array<RouterViewData>;
|
||||||
// type?: 'api' | 'context' | 'page';
|
|
||||||
// description?: string;
|
|
||||||
// api?: {
|
|
||||||
// url: string;
|
|
||||||
// },
|
|
||||||
// context?: {
|
|
||||||
// key: string;
|
|
||||||
// },
|
|
||||||
// page?: {},
|
|
||||||
// where?: string;
|
|
||||||
// whereList?: Array<{ title: string; where: string }>;
|
|
||||||
// }
|
|
||||||
interface StudioState {
|
interface StudioState {
|
||||||
routes: Array<RouteItem>;
|
routes: Array<RouteItem>;
|
||||||
getRoutes: () => Promise<void>;
|
getRouteList: () => Promise<void>;
|
||||||
run: (route: RouteItem) => Promise<void>;
|
run: (route: RouteItem) => Promise<void>;
|
||||||
queryProxy?: QueryProxy;
|
queryProxy?: QueryProxy;
|
||||||
router?: QueryRouterServer;
|
init: (force?: boolean) => Promise<{ queryProxy: QueryProxy }>;
|
||||||
init: (opts?: { url?: string }) => Promise<{ router: QueryRouterServer; queryProxy: QueryProxy }>;
|
routeViewList: RouteViewList;
|
||||||
|
getViewList: () => Promise<void>;
|
||||||
proxy?: ProxyItem;
|
getCurrentView: () => Promise<void>;
|
||||||
setProxy?: (proxy: ProxyItem) => void;
|
updateRouteView: (view: RouterViewData) => Promise<void>;
|
||||||
proxyList?: ProxyItem[];
|
deleteRouteView: (id: string) => Promise<void>;
|
||||||
setProxyList?: (list: ProxyItem[]) => void;
|
currentView?: RouterViewData;
|
||||||
}
|
}
|
||||||
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||||
export const useStudioStore = create<StudioState>((set, get) => ({
|
export const useStudioStore = create<StudioState>((set, get) => ({
|
||||||
routes: [],
|
routes: [],
|
||||||
getRoutes: async () => {
|
getRouteList: async () => {
|
||||||
const state = get();
|
await get().getCurrentView();
|
||||||
|
const state = await get().init();
|
||||||
|
|
||||||
let queryProxy = state.queryProxy;
|
let queryProxy = state.queryProxy;
|
||||||
if (!queryProxy) {
|
const url = new URL(window.location.href);
|
||||||
const init = await state.init();
|
const viewId = url.searchParams.get('viewId') || 'default';
|
||||||
queryProxy = init.queryProxy;
|
const routes: any[] = await queryProxy.listRoutes(() => true, { viewId });
|
||||||
}
|
|
||||||
console.log('query proxy', queryProxy.router);
|
|
||||||
const routes: any[] = await queryProxy.listRoutes(() => true, "")
|
|
||||||
console.log('fetched routes', routes);
|
|
||||||
set({ routes });
|
set({ routes });
|
||||||
|
get().getViewList();
|
||||||
|
},
|
||||||
|
getViewList: async () => {
|
||||||
|
const res = await query.post({ path: 'views', key: 'list' });
|
||||||
|
if (res.code === 200) {
|
||||||
|
const list = res.data.list as RouteViewList || [];
|
||||||
|
set({ routeViewList: list });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getCurrentView: async () => {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
const viewId = url.searchParams.get('viewId');
|
||||||
|
if (!viewId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await query.post({ path: 'views', key: 'current', data: { viewId: viewId } });
|
||||||
|
if (res.code === 200) {
|
||||||
|
const view = res.data as RouterViewData;
|
||||||
|
set({ currentView: view });
|
||||||
|
} else {
|
||||||
|
set({ currentView: undefined });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
routeViewList: [],
|
||||||
|
updateRouteView: async (view: RouterViewData) => {
|
||||||
|
const res = await query.post({ path: 'views', key: 'update', data: view });
|
||||||
|
if (res.code !== 200) {
|
||||||
|
toast.error(`视图更新失败:${res.message || '未知错误'}`);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
get().getViewList();
|
||||||
|
toast.success('视图更新成功');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteRouteView: async (id: string) => {
|
||||||
|
const res = await query.post({ path: 'views', key: 'delete', data: { id } });
|
||||||
|
if (res.code !== 200) {
|
||||||
|
toast.error(`视图删除失败:${res.message || '未知错误'}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
get().getViewList();
|
||||||
|
toast.success('视图删除成功');
|
||||||
},
|
},
|
||||||
run: async (route: RouteItem) => {
|
run: async (route: RouteItem) => {
|
||||||
const state = get();
|
const state = await get().init();
|
||||||
let queryProxy = state.queryProxy!;
|
let queryProxy = state.queryProxy;
|
||||||
if (!state.queryProxy) {
|
|
||||||
const init = await state.init();
|
|
||||||
queryProxy = init.queryProxy;
|
|
||||||
}
|
|
||||||
console.log('running route', route, queryProxy.query.url);
|
|
||||||
const res = await queryProxy.run({ path: route.path, key: route.key });
|
const res = await queryProxy.run({ path: route.path, key: route.key });
|
||||||
console.log('route run result', res);
|
|
||||||
if (res.code !== 200) {
|
if (res.code !== 200) {
|
||||||
toast.error(`运行失败:${res.message || '未知错误'}`);
|
toast.error(`运行失败:${res.message || '未知错误'}`);
|
||||||
} else if (res.code === 200) {
|
} else if (res.code === 200) {
|
||||||
@@ -73,51 +95,38 @@ export const useStudioStore = create<StudioState>((set, get) => ({
|
|||||||
},
|
},
|
||||||
queryProxy: undefined,
|
queryProxy: undefined,
|
||||||
router: undefined,
|
router: undefined,
|
||||||
init: async () => {
|
init: async (force?: boolean) => {
|
||||||
const proxy = get().proxy || localStorageProxy.get();
|
|
||||||
const url = proxy.type === 'api' && proxy.api ? proxy.api.url : '/client/router';
|
|
||||||
// let _url = 'http://localhost:52002/api/router';
|
// let _url = 'http://localhost:52002/api/router';
|
||||||
let _url = 'http://localhost:52000/api/router';
|
let _url = 'http://localhost:52000/api/router';
|
||||||
// let _url = '/api/router';
|
// let _url = '/api/router';
|
||||||
|
let queryProxy = get().queryProxy;
|
||||||
const query = new QueryClient({
|
if (queryProxy && !force) {
|
||||||
url: _url,
|
return { queryProxy };
|
||||||
|
}
|
||||||
|
let currentView: RouterViewData | undefined = get().currentView;
|
||||||
|
console.log('currentView in init', currentView);
|
||||||
|
const routerViewData: RouterViewData = currentView || {
|
||||||
|
views: [{
|
||||||
|
id: 'default',
|
||||||
|
title: '默认视图',
|
||||||
|
query: `WHERE path = 'file' `
|
||||||
|
}],
|
||||||
|
data: {
|
||||||
|
items: []
|
||||||
|
},
|
||||||
|
viewId: 'default',
|
||||||
|
}
|
||||||
|
console.log('initializing query proxy with view', routerViewData);
|
||||||
|
queryProxy = new QueryProxy({
|
||||||
|
routerViewData
|
||||||
});
|
});
|
||||||
const router = new QueryRouterServer();
|
|
||||||
const queryProxy = new QueryProxy({ query, router });
|
|
||||||
await queryProxy.init();
|
await queryProxy.init();
|
||||||
set({ queryProxy, router });
|
await sleep(500);
|
||||||
return { router, queryProxy }
|
set({ queryProxy });
|
||||||
},
|
return { queryProxy }
|
||||||
proxy: undefined,
|
|
||||||
setProxy: (proxy: ProxyItem) => {
|
|
||||||
localStorageProxy.set(proxy);
|
|
||||||
set({ proxy });
|
|
||||||
},
|
|
||||||
proxyList: [],
|
|
||||||
setProxyList: (list: ProxyItem[]) => {
|
|
||||||
set({ proxyList: list });
|
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const localStorageProxy = {
|
use('studioStore', () => {
|
||||||
get: (): ProxyItem => {
|
return useStudioStore.getState();
|
||||||
const data = localStorage.getItem('PROXY_CONFIG')
|
});
|
||||||
if (data) {
|
|
||||||
return JSON.parse(data)
|
|
||||||
}
|
|
||||||
const defult: ProxyItem = {
|
|
||||||
title: '默认',
|
|
||||||
description: '默认',
|
|
||||||
type: 'api',
|
|
||||||
api: {
|
|
||||||
url: '/client/router'
|
|
||||||
},
|
|
||||||
}
|
|
||||||
localStorageProxy.set(defult)
|
|
||||||
return defult;
|
|
||||||
},
|
|
||||||
set: (proxy: ProxyItem) => {
|
|
||||||
localStorage.setItem('PROXY_CONFIG', JSON.stringify(proxy))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
200
web/src/apps/view/components/DataItemForm.tsx
Normal file
200
web/src/apps/view/components/DataItemForm.tsx
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
import { Label } from "@/components/ui/label"
|
||||||
|
import { Input } from "@/components/ui/input"
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox"
|
||||||
|
import { Query } from "@kevisual/query"
|
||||||
|
import { QueryRouterServer } from "@kevisual/router"
|
||||||
|
import { nanoid } from "nanoid"
|
||||||
|
|
||||||
|
export type RouterViewItem = RouterViewApi | RouterViewContext | RouterViewWorker;
|
||||||
|
type RouteViewBase = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
enabled?: boolean;
|
||||||
|
}
|
||||||
|
export type RouterViewApi = {
|
||||||
|
type: 'api',
|
||||||
|
api: {
|
||||||
|
url: string,
|
||||||
|
// 已初始化的query实例,不需要编辑配置
|
||||||
|
query?: Query
|
||||||
|
}
|
||||||
|
} & RouteViewBase;
|
||||||
|
|
||||||
|
export type RouterViewContext = {
|
||||||
|
type: 'context',
|
||||||
|
context: {
|
||||||
|
key: string,
|
||||||
|
// 从context中获取router,不需要编辑配置
|
||||||
|
router?: QueryRouterServer
|
||||||
|
}
|
||||||
|
} & RouteViewBase;
|
||||||
|
export type RouterViewWorker = {
|
||||||
|
type: 'worker',
|
||||||
|
worker: {
|
||||||
|
type: 'Worker' | 'SharedWorker' | 'serviceWorker',
|
||||||
|
url: string,
|
||||||
|
// 已初始化的worker实例,不需要编辑配置
|
||||||
|
worker?: Worker | SharedWorker | ServiceWorker,
|
||||||
|
/**
|
||||||
|
* worker选项
|
||||||
|
* default: { type: 'module' }
|
||||||
|
*/
|
||||||
|
workerOptions?: {
|
||||||
|
type: 'module' | 'classic'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} & RouteViewBase;
|
||||||
|
interface DataItemFormProps {
|
||||||
|
item: RouterViewItem
|
||||||
|
onChange: (item: any) => void
|
||||||
|
onRemove: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DataItemForm = ({ item, onChange, onRemove }: DataItemFormProps) => {
|
||||||
|
const handleChange = (field: string, value: any) => {
|
||||||
|
if (field === 'type') {
|
||||||
|
const newItem: RouterViewItem = { ...item, type: value }
|
||||||
|
if (value === 'api' && !('api' in item)) {
|
||||||
|
(newItem as RouterViewApi).api = { url: '' }
|
||||||
|
} else if (value === 'context' && !('context' in item)) {
|
||||||
|
(newItem as RouterViewContext).context = { key: '' }
|
||||||
|
} else if (value === 'worker' && !('worker' in item)) {
|
||||||
|
(newItem as RouterViewWorker).worker = { type: 'Worker', url: '', workerOptions: { type: 'module' } }
|
||||||
|
}
|
||||||
|
if (!newItem.id) {
|
||||||
|
newItem.id = nanoid(16)
|
||||||
|
}
|
||||||
|
onChange(newItem)
|
||||||
|
} else {
|
||||||
|
onChange({ ...item, [field]: value })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleNestedChange = (parent: string, field: string, value: any) => {
|
||||||
|
const parentValue = item[parent as keyof RouterViewItem] as Record<string, any> | undefined
|
||||||
|
const newParentValue: Record<string, any> = {
|
||||||
|
...(parentValue || {}),
|
||||||
|
[field]: value
|
||||||
|
}
|
||||||
|
onChange({ ...item, [parent]: newParentValue })
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleNestedDeepChange = (parent: string, nestedParent: string, field: string, value: any) => {
|
||||||
|
const parentValue = item[parent as keyof RouterViewItem] as Record<string, any> | undefined
|
||||||
|
const nestedValue = parentValue?.[nestedParent] as Record<string, any> | undefined
|
||||||
|
const newNestedValue: Record<string, any> = {
|
||||||
|
...(nestedValue || {}),
|
||||||
|
[field]: value
|
||||||
|
}
|
||||||
|
const newParentValue: Record<string, any> = {
|
||||||
|
...(parentValue || {}),
|
||||||
|
[nestedParent]: newNestedValue
|
||||||
|
}
|
||||||
|
onChange({ ...item, [parent]: newParentValue })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="border rounded-lg p-4 mb-4 space-y-4">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<h3 className="font-medium">数据项配置</h3>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onRemove}
|
||||||
|
className="text-sm text-red-500 hover:text-red-700"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>标题</Label>
|
||||||
|
<Input
|
||||||
|
value={item.title || ''}
|
||||||
|
onChange={(e) => handleChange('title', e.target.value)}
|
||||||
|
placeholder="输入标题"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>类型</Label>
|
||||||
|
<select
|
||||||
|
value={item.type}
|
||||||
|
onChange={(e) => handleChange('type', e.target.value)}
|
||||||
|
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<option value="api">API</option>
|
||||||
|
<option value="context">Context</option>
|
||||||
|
<option value="worker">Worker</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Checkbox
|
||||||
|
id="enabled"
|
||||||
|
checked={item.enabled !== false}
|
||||||
|
onCheckedChange={(checked) => handleChange('enabled', checked)}
|
||||||
|
/>
|
||||||
|
<Label htmlFor="enabled" className="cursor-pointer">启用</Label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{(item.type === 'api') && (
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>API URL</Label>
|
||||||
|
<Input
|
||||||
|
value={item.api?.url || ''}
|
||||||
|
onChange={(e) => handleNestedChange('api', 'url', e.target.value)}
|
||||||
|
placeholder="输入 API 地址"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{item.type === 'context' && (
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Context Key</Label>
|
||||||
|
<Input
|
||||||
|
value={item.context?.key || ''}
|
||||||
|
onChange={(e) => handleNestedChange('context', 'key', e.target.value)}
|
||||||
|
placeholder="输入 Context Key"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{item.type === 'worker' && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Worker Type</Label>
|
||||||
|
<select
|
||||||
|
value={item.worker?.type || 'Worker'}
|
||||||
|
onChange={(e) => handleNestedChange('worker', 'type', e.target.value)}
|
||||||
|
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<option value="Worker">Worker</option>
|
||||||
|
<option value="SharedWorker">SharedWorker</option>
|
||||||
|
<option value="serviceWorker">ServiceWorker</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Worker URL</Label>
|
||||||
|
<Input
|
||||||
|
value={item.worker?.url || ''}
|
||||||
|
onChange={(e) => handleNestedChange('worker', 'url', e.target.value)}
|
||||||
|
placeholder="输入 Worker URL"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Worker Options Type</Label>
|
||||||
|
<select
|
||||||
|
value={item.worker?.workerOptions?.type || 'module'}
|
||||||
|
onChange={(e) => handleNestedDeepChange('worker', 'workerOptions', 'type', e.target.value)}
|
||||||
|
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<option value="module">Module</option>
|
||||||
|
<option value="classic">Classic</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
146
web/src/apps/view/components/ViewEditor.tsx
Normal file
146
web/src/apps/view/components/ViewEditor.tsx
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
import { useState, useEffect } from "react"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Label } from "@/components/ui/label"
|
||||||
|
import { Input } from "@/components/ui/input"
|
||||||
|
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
||||||
|
import { DataItemForm } from "@/apps/view/components/DataItemForm"
|
||||||
|
import { ViewFormItem } from "@/apps/view/components/ViewFormItem"
|
||||||
|
import { nanoid } from "nanoid"
|
||||||
|
|
||||||
|
interface ViewEditorProps {
|
||||||
|
open: boolean
|
||||||
|
onOpenChange: (open: boolean) => void
|
||||||
|
data?: {
|
||||||
|
id?: string
|
||||||
|
title?: string
|
||||||
|
data?: { items: any[] }
|
||||||
|
views?: any[]
|
||||||
|
}
|
||||||
|
onSave: (data: any) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ViewEditor = ({ open, onOpenChange, data, onSave }: ViewEditorProps) => {
|
||||||
|
const [title, setTitle] = useState('')
|
||||||
|
const [dataItems, setDataItems] = useState<any[]>([])
|
||||||
|
const [views, setViews] = useState<any[]>([])
|
||||||
|
|
||||||
|
const isUpdate = !!data?.id
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
setTitle(data?.title || '')
|
||||||
|
setDataItems(data?.data?.items || [])
|
||||||
|
setViews(data?.views || [])
|
||||||
|
}
|
||||||
|
}, [open, data])
|
||||||
|
|
||||||
|
const handleAddDataItem = () => {
|
||||||
|
setDataItems([...dataItems, { type: 'api', api: { url: '' } }])
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleUpdateDataItem = (index: number, item: any) => {
|
||||||
|
const newItems = [...dataItems]
|
||||||
|
newItems[index] = item
|
||||||
|
setDataItems(newItems)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRemoveDataItem = (index: number) => {
|
||||||
|
setDataItems(dataItems.filter((_, i) => i !== index))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAddView = () => {
|
||||||
|
setViews([...views, { id: nanoid(16), title: '', query: '' }])
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleUpdateView = (index: number, view: any) => {
|
||||||
|
const newViews = [...views]
|
||||||
|
newViews[index] = view
|
||||||
|
setViews(newViews)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRemoveView = (index: number) => {
|
||||||
|
setViews(views.filter((_, i) => i !== index))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
const viewData = {
|
||||||
|
id: data?.id,
|
||||||
|
title,
|
||||||
|
data: {
|
||||||
|
items: dataItems
|
||||||
|
},
|
||||||
|
views
|
||||||
|
}
|
||||||
|
onSave(viewData)
|
||||||
|
onOpenChange(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
onOpenChange(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>{isUpdate ? '编辑视图' : '新增视图'}</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<div className="space-y-6 max-h-[70vh] overflow-y-auto">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="title">视图标题</Label>
|
||||||
|
<Input
|
||||||
|
id="title"
|
||||||
|
value={title}
|
||||||
|
onChange={(e) => setTitle(e.target.value)}
|
||||||
|
placeholder="输入视图标题"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<h3 className="font-medium">数据项配置 (data.items)</h3>
|
||||||
|
<Button type="button" variant="outline" size="sm" onClick={handleAddDataItem}>
|
||||||
|
添加数据项
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{dataItems.map((item, index) => (
|
||||||
|
<DataItemForm
|
||||||
|
key={index}
|
||||||
|
item={item}
|
||||||
|
onChange={(newItem) => handleUpdateDataItem(index, newItem)}
|
||||||
|
onRemove={() => handleRemoveDataItem(index)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<h3 className="font-medium">视图配置 (views)</h3>
|
||||||
|
<Button type="button" variant="outline" size="sm" onClick={handleAddView}>
|
||||||
|
添加视图
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{views.map((view, index) => (
|
||||||
|
<ViewFormItem
|
||||||
|
key={view.id || index}
|
||||||
|
view={view}
|
||||||
|
onChange={(newView) => handleUpdateView(index, newView)}
|
||||||
|
onRemove={() => handleRemoveView(index)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<Button type="button" variant="outline" onClick={handleClose}>
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
|
<Button type="button" onClick={handleSave}>
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
58
web/src/apps/view/components/ViewFormItem.tsx
Normal file
58
web/src/apps/view/components/ViewFormItem.tsx
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { Label } from "@/components/ui/label"
|
||||||
|
import { Input } from "@/components/ui/input"
|
||||||
|
|
||||||
|
interface ViewFormProps {
|
||||||
|
view: any
|
||||||
|
onChange: (view: any) => void
|
||||||
|
onRemove: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ViewFormItem = ({ view, onChange, onRemove }: ViewFormProps) => {
|
||||||
|
const handleChange = (field: string, value: any) => {
|
||||||
|
onChange({ ...view, [field]: value })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="border rounded-lg p-4 mb-4 space-y-4">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<h3 className="font-medium">视图配置</h3>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onRemove}
|
||||||
|
className="text-sm text-red-500 hover:text-red-700"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>ID</Label>
|
||||||
|
<Input
|
||||||
|
value={view.id || ''}
|
||||||
|
onChange={(e) => handleChange('id', e.target.value)}
|
||||||
|
placeholder="自动生成"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>标题</Label>
|
||||||
|
<Input
|
||||||
|
value={view.title || ''}
|
||||||
|
onChange={(e) => handleChange('title', e.target.value)}
|
||||||
|
placeholder="输入视图标题"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>查询语句</Label>
|
||||||
|
<Input
|
||||||
|
value={view.query || ''}
|
||||||
|
onChange={(e) => handleChange('query', e.target.value)}
|
||||||
|
placeholder="输入查询语句"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
10
web/src/apps/view/form.ts
Normal file
10
web/src/apps/view/form.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { RouterViewQuery, RouterViewItem } from '@kevisual/api';
|
||||||
|
type ViewFormData = {
|
||||||
|
id?: string;
|
||||||
|
title: string;
|
||||||
|
data?: {
|
||||||
|
items: RouterViewItem[];
|
||||||
|
},
|
||||||
|
views: RouterViewQuery[];
|
||||||
|
};
|
||||||
129
web/src/apps/view/list.tsx
Normal file
129
web/src/apps/view/list.tsx
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { useStudioStore } from '../studio/store.ts';
|
||||||
|
import { Search, RotateCw, Plus, MoreHorizontal, Layout, Edit2, Trash2 } from "lucide-react";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import { ViewEditor } from "@/apps/view/components/ViewEditor.tsx";
|
||||||
|
|
||||||
|
export const ViewList = () => {
|
||||||
|
const { routeViewList, updateRouteView, deleteRouteView } = useStudioStore();
|
||||||
|
const [selectedItems, setSelectedItems] = useState<string[]>([]);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [editorOpen, setEditorOpen] = useState(false);
|
||||||
|
const [editingView, setEditingView] = useState<any>(null);
|
||||||
|
|
||||||
|
const filteredViews = routeViewList.filter(view =>
|
||||||
|
(view.title || '未命名视图').toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
|
(view.description || '').toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const handleRefresh = () => {
|
||||||
|
// 刷新逻辑
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAdd = () => {
|
||||||
|
handleEdit({});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEdit = (view: any) => {
|
||||||
|
setEditingView(view);
|
||||||
|
setEditorOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = (id: string) => {
|
||||||
|
if (confirm('确定要删除这个视图吗?')) {
|
||||||
|
deleteRouteView(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveView = (viewData: any) => {
|
||||||
|
updateRouteView(viewData);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full h-full max-w-4xl p-4 border rounded-md shadow-sm">
|
||||||
|
<div className="flex items-center space-x-2 mb-4">
|
||||||
|
<div className="relative flex-1">
|
||||||
|
<Input
|
||||||
|
placeholder="搜索视图..."
|
||||||
|
className="pl-3 pr-8"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
<Search className="absolute right-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
|
||||||
|
</div>
|
||||||
|
<Button variant="outline" size="icon" className="h-10 w-10" onClick={handleRefresh}>
|
||||||
|
<RotateCw className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" size="icon" className="h-10 w-10" onClick={handleAdd}>
|
||||||
|
<Plus className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead className="font-medium">视图名称</TableHead>
|
||||||
|
<TableHead className="w-10"></TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{filteredViews.length === 0 ? (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={4} className="text-center py-4 text-gray-500">
|
||||||
|
{searchTerm ? '未找到匹配的视图' : '暂无视图'}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
) : (
|
||||||
|
filteredViews.map((view) => (
|
||||||
|
<TableRow key={view.id} className={selectedItems.includes(view.id) ? "bg-gray-100" : ""}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Layout className="h-4 w-4 mr-2 text-gray-500" />
|
||||||
|
{view.title || '未命名视图'}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<div className="flex items-center space-x-1">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-8 w-8"
|
||||||
|
onClick={() => handleEdit(view)}
|
||||||
|
>
|
||||||
|
<Edit2 className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="h-8 w-8 text-red-500 hover:text-red-700"
|
||||||
|
onClick={() => handleDelete(view.id)}
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
<ViewEditor
|
||||||
|
open={editorOpen}
|
||||||
|
onOpenChange={setEditorOpen}
|
||||||
|
data={editingView}
|
||||||
|
onSave={handleSaveView}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -38,8 +38,8 @@ const buttonVariants = cva(
|
|||||||
|
|
||||||
function Button({
|
function Button({
|
||||||
className,
|
className,
|
||||||
variant,
|
variant = "default",
|
||||||
size,
|
size = "default",
|
||||||
asChild = false,
|
asChild = false,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"button"> &
|
}: React.ComponentProps<"button"> &
|
||||||
@@ -51,6 +51,8 @@ function Button({
|
|||||||
return (
|
return (
|
||||||
<Comp
|
<Comp
|
||||||
data-slot="button"
|
data-slot="button"
|
||||||
|
data-variant={variant}
|
||||||
|
data-size={size}
|
||||||
className={cn(buttonVariants({ variant, size, className }))}
|
className={cn(buttonVariants({ variant, size, className }))}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
30
web/src/components/ui/checkbox.tsx
Normal file
30
web/src/components/ui/checkbox.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
||||||
|
import { CheckIcon } from "lucide-react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Checkbox({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
|
||||||
|
return (
|
||||||
|
<CheckboxPrimitive.Root
|
||||||
|
data-slot="checkbox"
|
||||||
|
className={cn(
|
||||||
|
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<CheckboxPrimitive.Indicator
|
||||||
|
data-slot="checkbox-indicator"
|
||||||
|
className="grid place-content-center text-current transition-none"
|
||||||
|
>
|
||||||
|
<CheckIcon className="size-3.5" />
|
||||||
|
</CheckboxPrimitive.Indicator>
|
||||||
|
</CheckboxPrimitive.Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Checkbox }
|
||||||
42
web/src/components/ui/dialog.tsx
Normal file
42
web/src/components/ui/dialog.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
|
||||||
|
const Dialog = ({ open, onOpenChange, children }: { open: boolean; onOpenChange: (open: boolean) => void; children: React.ReactNode }) => {
|
||||||
|
if (!open) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||||
|
<div className="fixed inset-0 bg-black/50" onClick={() => onOpenChange(false)} />
|
||||||
|
<div className="relative z-50 w-full max-w-2xl max-h-[90vh] overflow-auto bg-white rounded-lg shadow-lg p-6">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const DialogHeader = ({ className, children, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div className={cn("flex flex-col space-y-1.5 text-center sm:text-left mb-4", className)} {...props}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const DialogTitle = ({ className, children, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => (
|
||||||
|
<h2 className={cn("text-lg font-semibold leading-none tracking-tight", className)} {...props}>
|
||||||
|
{children}
|
||||||
|
</h2>
|
||||||
|
)
|
||||||
|
|
||||||
|
const DialogContent = ({ className, children, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div className={cn("", className)} {...props}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const DialogFooter = ({ className, children, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 mt-4", className)} {...props}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
export { Dialog, DialogHeader, DialogTitle, DialogContent, DialogFooter }
|
||||||
21
web/src/components/ui/input.tsx
Normal file
21
web/src/components/ui/input.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
type={type}
|
||||||
|
data-slot="input"
|
||||||
|
className={cn(
|
||||||
|
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||||
|
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
||||||
|
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Input }
|
||||||
22
web/src/components/ui/label.tsx
Normal file
22
web/src/components/ui/label.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as LabelPrimitive from "@radix-ui/react-label"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Label({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
||||||
|
return (
|
||||||
|
<LabelPrimitive.Root
|
||||||
|
data-slot="label"
|
||||||
|
className={cn(
|
||||||
|
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Label }
|
||||||
114
web/src/components/ui/table.tsx
Normal file
114
web/src/components/ui/table.tsx
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="table-container"
|
||||||
|
className="relative w-full overflow-x-auto"
|
||||||
|
>
|
||||||
|
<table
|
||||||
|
data-slot="table"
|
||||||
|
className={cn("w-full caption-bottom text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
||||||
|
return (
|
||||||
|
<thead
|
||||||
|
data-slot="table-header"
|
||||||
|
className={cn("[&_tr]:border-b", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
||||||
|
return (
|
||||||
|
<tbody
|
||||||
|
data-slot="table-body"
|
||||||
|
className={cn("[&_tr:last-child]:border-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
||||||
|
return (
|
||||||
|
<tfoot
|
||||||
|
data-slot="table-footer"
|
||||||
|
className={cn(
|
||||||
|
"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
||||||
|
return (
|
||||||
|
<tr
|
||||||
|
data-slot="table-row"
|
||||||
|
className={cn(
|
||||||
|
"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
||||||
|
return (
|
||||||
|
<th
|
||||||
|
data-slot="table-head"
|
||||||
|
className={cn(
|
||||||
|
"text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
||||||
|
return (
|
||||||
|
<td
|
||||||
|
data-slot="table-cell"
|
||||||
|
className={cn(
|
||||||
|
"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableCaption({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"caption">) {
|
||||||
|
return (
|
||||||
|
<caption
|
||||||
|
data-slot="table-caption"
|
||||||
|
className={cn("text-muted-foreground mt-4 text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Table,
|
||||||
|
TableHeader,
|
||||||
|
TableBody,
|
||||||
|
TableFooter,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableCaption,
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Query } from '@kevisual/query'
|
import { QueryClient } from '@kevisual/query'
|
||||||
|
|
||||||
const getUrl = () => {
|
const getUrl = () => {
|
||||||
const host = window.location.host
|
const host = window.location.host
|
||||||
@@ -10,6 +10,10 @@ const getUrl = () => {
|
|||||||
return '/client/router'
|
return '/client/router'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const query = new Query({
|
export const query = new QueryClient({
|
||||||
url: getUrl()
|
url: '/api/router',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const queryClient = new QueryClient({
|
||||||
|
url: getUrl(),
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user