mirror of
https://github.com/logancyang/obsidian-copilot.git
synced 2026-07-22 07:50:24 +00:00
feat: Support project context preview. (#1551)
* feat: Support project context preview. * feat: add test file. * fix: Fix state update issues and remove extension section.
This commit is contained in:
parent
b33f5cf321
commit
4539338dfe
15 changed files with 2325 additions and 210 deletions
615
package-lock.json
generated
615
package-lock.json
generated
|
|
@ -32,13 +32,14 @@
|
|||
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
||||
"@radix-ui/react-label": "^2.1.0",
|
||||
"@radix-ui/react-popover": "^1.1.4",
|
||||
"@radix-ui/react-scroll-area": "^1.2.2",
|
||||
"@radix-ui/react-scroll-area": "^1.2.9",
|
||||
"@radix-ui/react-select": "^2.1.2",
|
||||
"@radix-ui/react-separator": "^1.1.7",
|
||||
"@radix-ui/react-slider": "^1.2.1",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@radix-ui/react-switch": "^1.1.1",
|
||||
"@radix-ui/react-tabs": "^1.1.3",
|
||||
"@radix-ui/react-tooltip": "^1.1.6",
|
||||
"@radix-ui/react-tooltip": "^1.2.7",
|
||||
"@tabler/icons-react": "^2.14.0",
|
||||
"async-mutex": "^0.5.0",
|
||||
"axios": "^1.3.4",
|
||||
|
|
@ -65,6 +66,7 @@
|
|||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.3.5",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-resizable-panels": "^3.0.2",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"sse": "github:mpetazzoni/sse.js",
|
||||
"tailwind-merge": "^2.5.5",
|
||||
|
|
@ -5175,6 +5177,24 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
||||
"integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz",
|
||||
|
|
@ -6254,6 +6274,24 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
||||
"integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-roving-focus": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.1.tgz",
|
||||
|
|
@ -6374,20 +6412,20 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-scroll-area": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.2.tgz",
|
||||
"integrity": "sha512-EFI1N/S3YxZEW/lJ/H1jY3njlvTd8tBmgKEn4GHi51+aMm94i6NmAJstsm5cu3yJwYqYc93gpCPm21FeAbFk6g==",
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.9.tgz",
|
||||
"integrity": "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/number": "1.1.0",
|
||||
"@radix-ui/primitive": "1.1.1",
|
||||
"@radix-ui/react-compose-refs": "1.1.1",
|
||||
"@radix-ui/react-context": "1.1.1",
|
||||
"@radix-ui/react-direction": "1.1.0",
|
||||
"@radix-ui/react-presence": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.0.1",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||
"@radix-ui/number": "1.1.1",
|
||||
"@radix-ui/primitive": "1.1.2",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-direction": "1.1.1",
|
||||
"@radix-ui/react-presence": "1.1.4",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6404,16 +6442,22 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/primitive": {
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/number": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
|
||||
"integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
|
||||
"integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/primitive": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz",
|
||||
"integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
|
||||
"integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
|
||||
"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6425,13 +6469,44 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-primitive": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
|
||||
"integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-context": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
|
||||
"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-direction": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
|
||||
"integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-presence": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz",
|
||||
"integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-slot": "1.1.1"
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6448,14 +6523,49 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
|
||||
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-primitive": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
|
||||
"integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.1"
|
||||
"@radix-ui/react-slot": "1.2.3"
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-use-callback-ref": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
|
||||
"integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-use-layout-effect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
|
||||
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
|
|
@ -6509,6 +6619,24 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
||||
"integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-visually-hidden": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz",
|
||||
|
|
@ -6532,6 +6660,52 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-separator": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz",
|
||||
"integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.1.3"
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
|
||||
"integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-slot": "1.2.3"
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slider": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.2.1.tgz",
|
||||
|
|
@ -6566,12 +6740,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
||||
"integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
|
||||
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.0"
|
||||
"@radix-ui/react-compose-refs": "1.1.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6583,6 +6757,21 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
|
||||
"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-switch": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.1.tgz",
|
||||
|
|
@ -6762,23 +6951,23 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.6.tgz",
|
||||
"integrity": "sha512-TLB5D8QLExS1uDn7+wH/bjEmRurNMTzNrtq7IjaS4kjion9NtzsTGkvR5+i7yc9q01Pi2KMM2cN3f8UG4IvvXA==",
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.7.tgz",
|
||||
"integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.1",
|
||||
"@radix-ui/react-compose-refs": "1.1.1",
|
||||
"@radix-ui/react-context": "1.1.1",
|
||||
"@radix-ui/react-dismissable-layer": "1.1.3",
|
||||
"@radix-ui/react-id": "1.1.0",
|
||||
"@radix-ui/react-popper": "1.2.1",
|
||||
"@radix-ui/react-portal": "1.1.3",
|
||||
"@radix-ui/react-presence": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.0.1",
|
||||
"@radix-ui/react-slot": "1.1.1",
|
||||
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||
"@radix-ui/react-visually-hidden": "1.1.1"
|
||||
"@radix-ui/primitive": "1.1.2",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-dismissable-layer": "1.1.10",
|
||||
"@radix-ui/react-id": "1.1.1",
|
||||
"@radix-ui/react-popper": "1.2.7",
|
||||
"@radix-ui/react-portal": "1.1.9",
|
||||
"@radix-ui/react-presence": "1.1.4",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-slot": "1.2.3",
|
||||
"@radix-ui/react-use-controllable-state": "1.2.2",
|
||||
"@radix-ui/react-visually-hidden": "1.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6796,18 +6985,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/primitive": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
|
||||
"integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==",
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz",
|
||||
"integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz",
|
||||
"integrity": "sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==",
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
|
||||
"integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.0.1"
|
||||
"@radix-ui/react-primitive": "2.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6825,9 +7014,24 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
|
||||
"integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
|
||||
"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-context": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
|
||||
"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6840,16 +7044,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-dismissable-layer": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz",
|
||||
"integrity": "sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==",
|
||||
"version": "1.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz",
|
||||
"integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.1",
|
||||
"@radix-ui/react-compose-refs": "1.1.1",
|
||||
"@radix-ui/react-primitive": "2.0.1",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||
"@radix-ui/react-use-escape-keydown": "1.1.0"
|
||||
"@radix-ui/primitive": "1.1.2",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1",
|
||||
"@radix-ui/react-use-escape-keydown": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6866,22 +7070,40 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-id": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
|
||||
"integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz",
|
||||
"integrity": "sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw==",
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz",
|
||||
"integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react-dom": "^2.0.0",
|
||||
"@radix-ui/react-arrow": "1.1.1",
|
||||
"@radix-ui/react-compose-refs": "1.1.1",
|
||||
"@radix-ui/react-context": "1.1.1",
|
||||
"@radix-ui/react-primitive": "2.0.1",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.0",
|
||||
"@radix-ui/react-use-rect": "1.1.0",
|
||||
"@radix-ui/react-use-size": "1.1.0",
|
||||
"@radix-ui/rect": "1.1.0"
|
||||
"@radix-ui/react-arrow": "1.1.7",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1",
|
||||
"@radix-ui/react-use-rect": "1.1.1",
|
||||
"@radix-ui/react-use-size": "1.1.1",
|
||||
"@radix-ui/rect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6899,13 +7121,37 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-portal": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz",
|
||||
"integrity": "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==",
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
|
||||
"integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.0.1",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-presence": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz",
|
||||
"integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6923,12 +7169,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
|
||||
"integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
|
||||
"integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-slot": "1.1.1"
|
||||
"@radix-ui/react-slot": "1.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6945,13 +7191,29 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-callback-ref": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
|
||||
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
|
||||
"integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-controllable-state": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
|
||||
"integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.1"
|
||||
"@radix-ui/react-use-effect-event": "0.0.2",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -6963,6 +7225,81 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-escape-keydown": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
|
||||
"integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-layout-effect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
|
||||
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-rect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
|
||||
"integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/rect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-size": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
|
||||
"integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/rect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
|
||||
"integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-callback-ref": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
|
||||
|
|
@ -6994,6 +7331,39 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-effect-event": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
|
||||
"integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-effect-event/node_modules/@radix-ui/react-use-layout-effect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
|
||||
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-escape-keydown": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
|
||||
|
|
@ -7075,12 +7445,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-visually-hidden": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz",
|
||||
"integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==",
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
|
||||
"integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.0.1"
|
||||
"@radix-ui/react-primitive": "2.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -7097,28 +7467,13 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
|
||||
"integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
|
||||
"integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
|
||||
"integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-slot": "1.1.1"
|
||||
"@radix-ui/react-slot": "1.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
|
|
@ -7135,24 +7490,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
|
||||
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/rect": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz",
|
||||
|
|
@ -18688,6 +19025,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-resizable-panels": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-3.0.2.tgz",
|
||||
"integrity": "sha512-j4RNII75fnHkLnbsTb5G5YsDvJsSEZrJK2XSF2z0Tc2jIonYlIVir/Yh/5LvcUFCfs1HqrMAoiBFmIrRjC4XnA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/react-style-singleton": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
|
||||
|
|
|
|||
|
|
@ -99,13 +99,14 @@
|
|||
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
||||
"@radix-ui/react-label": "^2.1.0",
|
||||
"@radix-ui/react-popover": "^1.1.4",
|
||||
"@radix-ui/react-scroll-area": "^1.2.2",
|
||||
"@radix-ui/react-scroll-area": "^1.2.9",
|
||||
"@radix-ui/react-select": "^2.1.2",
|
||||
"@radix-ui/react-separator": "^1.1.7",
|
||||
"@radix-ui/react-slider": "^1.2.1",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@radix-ui/react-switch": "^1.1.1",
|
||||
"@radix-ui/react-tabs": "^1.1.3",
|
||||
"@radix-ui/react-tooltip": "^1.1.6",
|
||||
"@radix-ui/react-tooltip": "^1.2.7",
|
||||
"@tabler/icons-react": "^2.14.0",
|
||||
"async-mutex": "^0.5.0",
|
||||
"axios": "^1.3.4",
|
||||
|
|
@ -132,6 +133,7 @@
|
|||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.3.5",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-resizable-panels": "^3.0.2",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"sse": "github:mpetazzoni/sse.js",
|
||||
"tailwind-merge": "^2.5.5",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { ProjectConfig, setCurrentProject } from "@/aiParams";
|
||||
import { AddProjectModal } from "@/components/modals/AddProjectModal";
|
||||
import { AddProjectModal } from "@/components/modals/project/AddProjectModal";
|
||||
import { ConfirmModal } from "@/components/modals/ConfirmModal";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||
|
|
@ -11,6 +11,7 @@ import {
|
|||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { SearchBar } from "@/components/ui/SearchBar";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { logError } from "@/logger";
|
||||
import { updateSetting } from "@/settings/model";
|
||||
|
|
@ -25,12 +26,10 @@ import {
|
|||
Search,
|
||||
Trash2,
|
||||
X,
|
||||
XCircle,
|
||||
} from "lucide-react";
|
||||
import { App, Notice } from "obsidian";
|
||||
import React, { memo, useEffect, useMemo, useState } from "react";
|
||||
import { filterProjects } from "@/utils/projectUtils";
|
||||
import { Input } from "../ui/input";
|
||||
|
||||
function ProjectItem({
|
||||
project,
|
||||
|
|
@ -356,23 +355,11 @@ export const ProjectList = memo(
|
|||
{projects.length > 0 && (
|
||||
<div className="tw-px-4 tw-pb-2 tw-pt-3">
|
||||
<div className="tw-relative">
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search projects..."
|
||||
<SearchBar
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
onChange={setSearchQuery}
|
||||
placeholder="Search projects..."
|
||||
/>
|
||||
{searchQuery && (
|
||||
<Button
|
||||
variant={"secondary"}
|
||||
onClick={() => setSearchQuery("")}
|
||||
className="tw-absolute tw-right-8 tw-top-1/2 tw-size-4 -tw-translate-y-1/2 tw-transform tw-rounded-full tw-p-0 tw-transition-colors"
|
||||
aria-label="Clear search"
|
||||
>
|
||||
<XCircle className="tw-size-4 tw-text-muted/60 hover:tw-text-accent-hover" />
|
||||
</Button>
|
||||
)}
|
||||
<Search className="tw-absolute tw-right-3 tw-top-1/2 tw-size-4 -tw-translate-y-1/2 tw-transform tw-text-muted" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ function ExtensionInputModalContent({
|
|||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
validateAndConfirm(extension);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@ import React, { useState } from "react";
|
|||
import { createRoot, Root } from "react-dom/client";
|
||||
import {
|
||||
categorizePatterns,
|
||||
getDecodedPatterns,
|
||||
createPatternSettingsValue,
|
||||
getDecodedPatterns,
|
||||
getExtensionPattern,
|
||||
getFilePattern,
|
||||
getTagPattern,
|
||||
} from "@/search/searchUtils";
|
||||
import { File, FileText, Folder, Tag, Wrench, X } from "lucide-react";
|
||||
import {
|
||||
|
|
@ -148,7 +151,7 @@ function PatternMatchingModalContent({
|
|||
<DropdownMenuItem
|
||||
onSelect={() => {
|
||||
new TagSearchModal(app, (tag) => {
|
||||
const tagPattern = `#${tag}`;
|
||||
const tagPattern = getTagPattern(tag);
|
||||
if (tagPatterns.includes(tagPattern)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -185,7 +188,7 @@ function PatternMatchingModalContent({
|
|||
new AddContextNoteModal({
|
||||
app,
|
||||
onNoteSelect: (note) => {
|
||||
const notePattern = `[[${note.basename}]]`;
|
||||
const notePattern = getFilePattern(note);
|
||||
if (notePatterns.includes(notePattern)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -206,7 +209,7 @@ function PatternMatchingModalContent({
|
|||
<DropdownMenuItem
|
||||
onSelect={() => {
|
||||
new ExtensionInputModal(app, (extension) => {
|
||||
const extensionPattern = `*.${extension}`;
|
||||
const extensionPattern = getExtensionPattern(extension);
|
||||
if (extensionPatterns.includes(extensionPattern)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ import {
|
|||
categorizePatterns,
|
||||
createPatternSettingsValue,
|
||||
getDecodedPatterns,
|
||||
getExtensionPattern,
|
||||
getFilePattern,
|
||||
getTagPattern,
|
||||
} from "@/search/searchUtils";
|
||||
import { File, FileText, Folder, Tag, Wrench, X } from "lucide-react";
|
||||
import { App, Modal, TFile } from "obsidian";
|
||||
|
|
@ -148,7 +151,7 @@ function ProjectPatternMatchingModalContent({
|
|||
<DropdownMenuItem
|
||||
onSelect={() => {
|
||||
new TagSearchModal(app, (tag) => {
|
||||
const tagPattern = `#${tag}`;
|
||||
const tagPattern = getTagPattern(tag);
|
||||
if (tagPatterns.includes(tagPattern)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -185,7 +188,7 @@ function ProjectPatternMatchingModalContent({
|
|||
new ProjectFileSelectModal({
|
||||
app,
|
||||
onFileSelect: (file: TFile) => {
|
||||
const filePattern = `[[${file.basename}]]`;
|
||||
const filePattern = getFilePattern(file);
|
||||
if (notePatterns.includes(filePattern)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -206,7 +209,7 @@ function ProjectPatternMatchingModalContent({
|
|||
<DropdownMenuItem
|
||||
onSelect={() => {
|
||||
new ExtensionInputModal(app, (extension) => {
|
||||
const extensionPattern = `*.${extension}`;
|
||||
const extensionPattern = getExtensionPattern(extension);
|
||||
if (extensionPatterns.includes(extensionPattern)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { ProjectConfig } from "@/aiParams";
|
||||
import { ProjectPatternMatchingModal } from "@/components/modals/ProjectPatternMatchingModal";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { FormField } from "@/components/ui/form-field";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
|
@ -14,6 +13,9 @@ import { HelpCircle } from "lucide-react";
|
|||
import { App, Modal, Notice } from "obsidian";
|
||||
import React, { useState } from "react";
|
||||
import { createRoot, Root } from "react-dom/client";
|
||||
import { ContextManageModal } from "@/components/modals/project/context-manage-modal";
|
||||
import { TruncatedText } from "@/components/TruncatedText";
|
||||
import { getDecodedPatterns } from "@/search/searchUtils";
|
||||
|
||||
interface AddProjectModalContentProps {
|
||||
initialProject?: ProjectConfig;
|
||||
|
|
@ -31,7 +33,7 @@ function AddProjectModalContent({ initialProject, onSave, onCancel }: AddProject
|
|||
inclusions: false,
|
||||
});
|
||||
|
||||
const [formData, setFormData] = useState<Partial<ProjectConfig>>(
|
||||
const [formData, setFormData] = useState<ProjectConfig>(
|
||||
initialProject || {
|
||||
id: randomUUID(),
|
||||
name: "",
|
||||
|
|
@ -53,6 +55,23 @@ function AddProjectModalContent({ initialProject, onSave, onCancel }: AddProject
|
|||
}
|
||||
);
|
||||
|
||||
const showContext = getDecodedPatterns(
|
||||
formData.contextSource.inclusions || formData.contextSource.exclusions || "nothing"
|
||||
)
|
||||
.reverse()
|
||||
.join(",");
|
||||
|
||||
const handleEditProjectContext = (originP: ProjectConfig) => {
|
||||
const modal = new ContextManageModal(
|
||||
app,
|
||||
async (updatedProject: ProjectConfig) => {
|
||||
setFormData(updatedProject);
|
||||
},
|
||||
originP
|
||||
);
|
||||
modal.open();
|
||||
};
|
||||
|
||||
const isFormValid = () => {
|
||||
return formData.name && formData.projectModelKey;
|
||||
};
|
||||
|
|
@ -130,7 +149,9 @@ function AddProjectModalContent({ initialProject, onSave, onCancel }: AddProject
|
|||
|
||||
return (
|
||||
<div className="tw-flex tw-flex-col tw-gap-2 tw-p-4">
|
||||
<div className="tw-mb-2 tw-text-xl tw-font-bold tw-text-normal">Add New Project</div>
|
||||
<div className="tw-mb-2 tw-text-xl tw-font-bold tw-text-normal">
|
||||
{initialProject ? "Edit Project" : "New Project"}
|
||||
</div>
|
||||
|
||||
<div className="tw-flex tw-flex-col tw-gap-2">
|
||||
<FormField
|
||||
|
|
@ -236,7 +257,7 @@ function AddProjectModalContent({ initialProject, onSave, onCancel }: AddProject
|
|||
<FormField
|
||||
label={
|
||||
<div className="tw-flex tw-items-center tw-gap-2">
|
||||
<span>Inclusions</span>
|
||||
<span>Project Context</span>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
|
|
@ -261,53 +282,19 @@ function AddProjectModalContent({ initialProject, onSave, onCancel }: AddProject
|
|||
description="Define patterns to include specific files or folders in the project context"
|
||||
>
|
||||
<div className="tw-flex tw-items-center tw-gap-2">
|
||||
<div className="tw-flex-1 tw-text-xs tw-text-muted">
|
||||
{formData.contextSource?.inclusions?.trim()
|
||||
? "Patterns configured"
|
||||
: "No patterns configured"}
|
||||
<div className="tw-flex tw-flex-1 tw-flex-row">
|
||||
<span className="tw-text-sm">Patterns configure:</span>
|
||||
<TruncatedText className="tw-max-w-[100px] tw-text-sm tw-text-accent">
|
||||
{showContext}
|
||||
</TruncatedText>
|
||||
</div>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() =>
|
||||
new ProjectPatternMatchingModal(
|
||||
app,
|
||||
(value: string) => {
|
||||
handleInputChange("contextSource.inclusions", value);
|
||||
},
|
||||
formData.contextSource?.inclusions || "",
|
||||
"Manage Inclusions"
|
||||
).open()
|
||||
}
|
||||
onClick={() => {
|
||||
handleEditProjectContext(formData);
|
||||
}}
|
||||
>
|
||||
Manage Patterns
|
||||
</Button>
|
||||
</div>
|
||||
</FormField>
|
||||
|
||||
<FormField
|
||||
label="Exclusions"
|
||||
description="Exclude specific files or patterns from the included folders above"
|
||||
>
|
||||
<div className="tw-flex tw-items-center tw-gap-2">
|
||||
<div className="tw-flex-1 tw-text-xs tw-text-muted">
|
||||
{formData.contextSource?.exclusions?.trim()
|
||||
? "Patterns configured"
|
||||
: "No patterns configured"}
|
||||
</div>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() =>
|
||||
new ProjectPatternMatchingModal(
|
||||
app,
|
||||
(value: string) => {
|
||||
handleInputChange("contextSource.exclusions", value);
|
||||
},
|
||||
formData.contextSource?.exclusions || "",
|
||||
"Manage Exclusions"
|
||||
).open()
|
||||
}
|
||||
>
|
||||
Manage Patterns
|
||||
Manage Context
|
||||
</Button>
|
||||
</div>
|
||||
</FormField>
|
||||
1059
src/components/modals/project/context-manage-modal.tsx
Normal file
1059
src/components/modals/project/context-manage-modal.tsx
Normal file
File diff suppressed because it is too large
Load diff
39
src/components/ui/SearchBar.tsx
Normal file
39
src/components/ui/SearchBar.tsx
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import React from "react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { XCircle, Search } from "lucide-react";
|
||||
|
||||
interface SearchBarProps {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export const SearchBar: React.FC<SearchBarProps> = ({
|
||||
value,
|
||||
onChange,
|
||||
placeholder = "Search...",
|
||||
}) => {
|
||||
return (
|
||||
<div className="tw-relative">
|
||||
<Input
|
||||
type="text"
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
className="tw-pr-10" // Add padding to prevent text overlap with icons
|
||||
/>
|
||||
{value && (
|
||||
<Button
|
||||
variant={"secondary"}
|
||||
onClick={() => onChange("")}
|
||||
className="tw-absolute tw-right-8 tw-top-1/2 tw-size-4 -tw-translate-y-1/2 tw-transform tw-rounded-full tw-p-0 tw-transition-colors"
|
||||
aria-label="Clear search"
|
||||
>
|
||||
<XCircle className="tw-size-4 tw-text-muted/60 hover:tw-text-accent-hover" />
|
||||
</Button>
|
||||
)}
|
||||
<Search className="tw-absolute tw-right-3 tw-top-1/2 tw-size-4 -tw-translate-y-1/2 tw-transform tw-text-muted" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
45
src/components/ui/resizable.tsx
Normal file
45
src/components/ui/resizable.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import * as React from "react";
|
||||
import { GripVertical } from "lucide-react";
|
||||
import * as ResizablePrimitive from "react-resizable-panels";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const ResizablePanelGroup = ({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
|
||||
<ResizablePrimitive.PanelGroup
|
||||
className={cn(
|
||||
"tw-flex tw-size-full data-[panel-group-direction=vertical]:tw-flex-col",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
const ResizablePanel = ResizablePrimitive.Panel;
|
||||
|
||||
const ResizableHandle = ({
|
||||
withHandle,
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
|
||||
withHandle?: boolean;
|
||||
}) => (
|
||||
// tw-bg-border -> --divider-color: var(--background-modifier-border);
|
||||
<ResizablePrimitive.PanelResizeHandle
|
||||
className={cn(
|
||||
"tw-relative tw-flex tw-w-px tw-items-center tw-justify-center tw-bg-[var(--background-modifier-border)] after:tw-absolute after:tw-inset-y-0 after:tw-left-1/2 after:tw-w-1 after:tw--translate-x-1/2 focus-visible:tw-outline-none focus-visible:tw-ring-1 focus-visible:tw-ring-ring focus-visible:tw-ring-offset-1 data-[panel-group-direction=vertical]:tw-h-px data-[panel-group-direction=vertical]:tw-w-full data-[panel-group-direction=vertical]:after:tw-left-0 data-[panel-group-direction=vertical]:after:tw-h-1 data-[panel-group-direction=vertical]:after:tw-w-full data-[panel-group-direction=vertical]:after:tw--translate-y-1/2 data-[panel-group-direction=vertical]:after:tw-translate-x-0 [&[data-panel-group-direction=vertical]>div]:tw-rotate-90",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{withHandle && (
|
||||
<div className="tw-z-sidedock tw-flex tw-h-4 tw-w-3 tw-items-center tw-justify-center tw-rounded-sm tw-border tw-border-solid tw-border-border">
|
||||
<GripVertical className="tw-size-2.5" />
|
||||
</div>
|
||||
)}
|
||||
</ResizablePrimitive.PanelResizeHandle>
|
||||
);
|
||||
|
||||
export { ResizablePanelGroup, ResizablePanel, ResizableHandle };
|
||||
48
src/components/ui/scroll-area.tsx
Normal file
48
src/components/ui/scroll-area.tsx
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import * as React from "react";
|
||||
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const ScrollArea = React.forwardRef<
|
||||
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<ScrollAreaPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn("tw-relative tw-overflow-hidden", className)}
|
||||
{...props}
|
||||
>
|
||||
{/*[&>div:first-child]:!tw-block:for override the first child div style's (display: table)*/}
|
||||
<ScrollAreaPrimitive.Viewport className="tw-size-full tw-rounded-[inherit] [&>div:first-child]:!tw-block">
|
||||
{children}
|
||||
</ScrollAreaPrimitive.Viewport>
|
||||
<ScrollBar />
|
||||
<ScrollAreaPrimitive.Corner />
|
||||
</ScrollAreaPrimitive.Root>
|
||||
));
|
||||
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
||||
|
||||
const ScrollBar = React.forwardRef<
|
||||
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||
>(({ className, orientation = "vertical", ...props }, ref) => (
|
||||
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
||||
ref={ref}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"tw-flex tw-touch-none tw-select-none tw-transition-colors",
|
||||
orientation === "vertical" &&
|
||||
"tw-h-full tw-w-2.5 tw-border-l tw-border-l-transparent tw-p-[1px]",
|
||||
orientation === "horizontal" &&
|
||||
"tw-h-2.5 tw-flex-col tw-border-t tw-border-t-transparent tw-p-[1px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{/* tw-bg-border -> --divider-color: var(--background-modifier-border); */}
|
||||
<ScrollAreaPrimitive.ScrollAreaThumb className="tw-relative tw-flex-1 tw-rounded-full tw-bg-[var(--background-modifier-border)]" />
|
||||
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||
));
|
||||
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
||||
|
||||
export { ScrollArea, ScrollBar };
|
||||
27
src/components/ui/separator.tsx
Normal file
27
src/components/ui/separator.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Separator = React.forwardRef<
|
||||
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
||||
>(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => (
|
||||
// tw-bg-border -> --divider-color: var(--background-modifier-border);
|
||||
<SeparatorPrimitive.Root
|
||||
ref={ref}
|
||||
decorative={decorative}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"tw-shrink-0 tw-bg-[var(--background-modifier-border)]",
|
||||
orientation === "horizontal" ? "tw-h-[1px] tw-w-full" : "tw-h-full tw-w-[1px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
||||
|
||||
export { Separator };
|
||||
|
|
@ -5,7 +5,7 @@ import { getTagsFromNote, stripHash } from "@/utils";
|
|||
import { Embeddings } from "@langchain/core/embeddings";
|
||||
import { App, TFile } from "obsidian";
|
||||
|
||||
interface PatternCategory {
|
||||
export interface PatternCategory {
|
||||
tagPatterns?: string[];
|
||||
extensionPatterns?: string[];
|
||||
folderPatterns?: string[];
|
||||
|
|
@ -331,3 +331,15 @@ export function extractAppIgnoreSettings(app: App): string[] {
|
|||
|
||||
return appIgnoreFolders;
|
||||
}
|
||||
|
||||
export function getTagPattern(tag: string): string {
|
||||
return `#${tag}`;
|
||||
}
|
||||
|
||||
export function getFilePattern(file: TFile): string {
|
||||
return `[[${file.basename}]]`;
|
||||
}
|
||||
|
||||
export function getExtensionPattern(extension: string): string {
|
||||
return `*.${extension}`;
|
||||
}
|
||||
|
|
|
|||
546
src/tests/context-manage-modal.test.ts
Normal file
546
src/tests/context-manage-modal.test.ts
Normal file
|
|
@ -0,0 +1,546 @@
|
|||
import { TFile } from "obsidian";
|
||||
import {
|
||||
createPatternSettingsValue,
|
||||
getFilePattern,
|
||||
shouldIndexFile,
|
||||
PatternCategory,
|
||||
} from "@/search/searchUtils";
|
||||
|
||||
// Mock dependencies
|
||||
jest.mock("obsidian", () => ({
|
||||
TFile: class TFile {
|
||||
path: string;
|
||||
basename: string;
|
||||
extension: string;
|
||||
|
||||
constructor(path: string = "") {
|
||||
this.path = path;
|
||||
const parts = path.split("/");
|
||||
const filename = parts[parts.length - 1];
|
||||
this.basename = filename.replace(/\.[^/.]+$/, "");
|
||||
this.extension = filename.split(".").pop() || "";
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock("@/search/searchUtils", () => ({
|
||||
getMatchingPatterns: jest.fn(),
|
||||
shouldIndexFile: jest.fn(),
|
||||
getFilePattern: jest.fn(),
|
||||
createPatternSettingsValue: jest.fn(),
|
||||
categorizePatterns: jest.fn(),
|
||||
getDecodedPatterns: jest.fn(),
|
||||
}));
|
||||
|
||||
// Mock types and interfaces
|
||||
interface GroupItem {
|
||||
id: string;
|
||||
name: string;
|
||||
isIgnored?: boolean;
|
||||
}
|
||||
|
||||
interface GroupListItem {
|
||||
tags: Record<string, Array<GroupItem>>;
|
||||
folders: Record<string, Array<GroupItem>>;
|
||||
extensions: Record<string, Array<GroupItem>>;
|
||||
notes: Array<GroupItem>;
|
||||
}
|
||||
|
||||
interface IgnoreItems {
|
||||
files: Set<TFile>;
|
||||
}
|
||||
|
||||
// Test helper functions
|
||||
const createTestFile = (path: string): TFile => {
|
||||
const file = new TFile();
|
||||
file.path = path;
|
||||
const parts = path.split("/");
|
||||
const filename = parts[parts.length - 1];
|
||||
file.basename = filename.replace(/\.[^/.]+$/, "");
|
||||
file.extension = filename.split(".").pop() || "";
|
||||
return file;
|
||||
};
|
||||
|
||||
const createMockPatternCategory = (overrides: Partial<PatternCategory> = {}): PatternCategory => ({
|
||||
tagPatterns: [],
|
||||
folderPatterns: [],
|
||||
extensionPatterns: [],
|
||||
notePatterns: [],
|
||||
...overrides,
|
||||
});
|
||||
|
||||
// Implementation of the functions to test
|
||||
const createAndPopulateGroupList = (
|
||||
appFiles: TFile[],
|
||||
inclusionPatterns: PatternCategory | null,
|
||||
exclusionPatterns: PatternCategory | null
|
||||
): GroupListItem => {
|
||||
const projectAllFiles = appFiles.filter((file) =>
|
||||
shouldIndexFile(file, inclusionPatterns, exclusionPatterns)
|
||||
);
|
||||
|
||||
// Initialize groups
|
||||
const tags: Record<string, Array<GroupItem>> = {};
|
||||
const folders: Record<string, Array<GroupItem>> = {};
|
||||
const extensions: Record<string, Array<GroupItem>> = {};
|
||||
const notes: Array<GroupItem> = [];
|
||||
|
||||
(inclusionPatterns?.tagPatterns ?? []).forEach((tag) => {
|
||||
tags[tag] = [];
|
||||
});
|
||||
(inclusionPatterns?.folderPatterns ?? []).forEach((folder) => {
|
||||
folders[folder] = [];
|
||||
});
|
||||
(inclusionPatterns?.extensionPatterns ?? []).forEach((extension) => {
|
||||
extensions[extension] = [];
|
||||
});
|
||||
|
||||
// Populate with matching files
|
||||
projectAllFiles.forEach((file) => {
|
||||
const groupItem: GroupItem = {
|
||||
id: file.path,
|
||||
name: file.basename,
|
||||
};
|
||||
|
||||
// Add to notes array
|
||||
notes.push(groupItem);
|
||||
|
||||
// Add to appropriate groups based on patterns
|
||||
(inclusionPatterns?.tagPatterns ?? []).forEach((tag) => {
|
||||
if (tags[tag]) {
|
||||
tags[tag].push(groupItem);
|
||||
}
|
||||
});
|
||||
|
||||
(inclusionPatterns?.folderPatterns ?? []).forEach((folder) => {
|
||||
if (folders[folder] && file.path.includes(folder)) {
|
||||
folders[folder].push(groupItem);
|
||||
}
|
||||
});
|
||||
|
||||
(inclusionPatterns?.extensionPatterns ?? []).forEach((extension) => {
|
||||
if (extensions[extension] && file.extension === extension.replace("*.", "")) {
|
||||
extensions[extension].push(groupItem);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return { tags, folders, extensions, notes };
|
||||
};
|
||||
|
||||
const convertGroupListToInclusions = (list: GroupListItem, appFiles: TFile[]): string => {
|
||||
const tagPatterns = Object.keys(list.tags);
|
||||
const folderPatterns = Object.keys(list.folders);
|
||||
const extensionPatterns = Object.keys(list.extensions);
|
||||
const notePatterns = list.notes
|
||||
.map((note) => {
|
||||
const file = appFiles.find((file) => file.path === note.id);
|
||||
if (file) {
|
||||
return getFilePattern(file);
|
||||
}
|
||||
})
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
return createPatternSettingsValue({
|
||||
tagPatterns,
|
||||
folderPatterns,
|
||||
extensionPatterns,
|
||||
notePatterns,
|
||||
});
|
||||
};
|
||||
|
||||
const convertDeletedItemsToExclusions = (items: IgnoreItems): string => {
|
||||
const notePatterns = Array.from(items.files).map((file) => getFilePattern(file));
|
||||
return createPatternSettingsValue({ notePatterns }) || "";
|
||||
};
|
||||
|
||||
describe("Context Manage Modal Functions", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
// Setup default mocks
|
||||
(shouldIndexFile as jest.Mock).mockReturnValue(true);
|
||||
(getFilePattern as jest.Mock).mockImplementation((file: TFile) => `[[${file.basename}]]`);
|
||||
(createPatternSettingsValue as jest.Mock).mockImplementation(
|
||||
({ tagPatterns = [], folderPatterns = [], extensionPatterns = [], notePatterns = [] }) => {
|
||||
const patterns = [...tagPatterns, ...folderPatterns, ...extensionPatterns, ...notePatterns];
|
||||
return patterns.join(",");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe("createAndPopulateGroupList", () => {
|
||||
it("Should create empty GroupList when there are no files", () => {
|
||||
const result = createAndPopulateGroupList([], null, null);
|
||||
|
||||
expect(result).toEqual({
|
||||
tags: {},
|
||||
folders: {},
|
||||
extensions: {},
|
||||
notes: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("Should correctly filter files based on inclusion and exclusion patterns", () => {
|
||||
const files = [
|
||||
createTestFile("test1.md"),
|
||||
createTestFile("test2.pdf"),
|
||||
createTestFile("test3.txt"),
|
||||
];
|
||||
|
||||
(shouldIndexFile as jest.Mock)
|
||||
.mockReturnValueOnce(true)
|
||||
.mockReturnValueOnce(false)
|
||||
.mockReturnValueOnce(true);
|
||||
|
||||
const inclusionPatterns = createMockPatternCategory();
|
||||
const exclusionPatterns = createMockPatternCategory();
|
||||
|
||||
const result = createAndPopulateGroupList(files, inclusionPatterns, exclusionPatterns);
|
||||
|
||||
expect(shouldIndexFile).toHaveBeenCalledTimes(3);
|
||||
expect(result.notes).toHaveLength(2);
|
||||
expect(result.notes[0].id).toBe("test1.md");
|
||||
expect(result.notes[1].id).toBe("test3.txt");
|
||||
});
|
||||
|
||||
it("Should initialize groups based on inclusion patterns", () => {
|
||||
const files = [createTestFile("test.md")];
|
||||
const inclusionPatterns = createMockPatternCategory({
|
||||
tagPatterns: ["#important", "#work"],
|
||||
folderPatterns: ["docs", "projects"],
|
||||
extensionPatterns: ["*.md", "*.pdf"],
|
||||
});
|
||||
|
||||
const result = createAndPopulateGroupList(files, inclusionPatterns, null);
|
||||
|
||||
expect(Object.keys(result.tags)).toEqual(["#important", "#work"]);
|
||||
expect(Object.keys(result.folders)).toEqual(["docs", "projects"]);
|
||||
expect(Object.keys(result.extensions)).toEqual(["*.md", "*.pdf"]);
|
||||
});
|
||||
|
||||
it("Should add files to appropriate groups", () => {
|
||||
const files = [createTestFile("docs/test.md"), createTestFile("projects/work.pdf")];
|
||||
|
||||
const inclusionPatterns = createMockPatternCategory({
|
||||
folderPatterns: ["docs", "projects"],
|
||||
extensionPatterns: ["*.md", "*.pdf"],
|
||||
});
|
||||
|
||||
const result = createAndPopulateGroupList(files, inclusionPatterns, null);
|
||||
|
||||
expect(result.folders["docs"]).toHaveLength(1);
|
||||
expect(result.folders["docs"][0].name).toBe("test");
|
||||
expect(result.folders["projects"]).toHaveLength(1);
|
||||
expect(result.folders["projects"][0].name).toBe("work");
|
||||
});
|
||||
|
||||
it("Should handle duplicate patterns", () => {
|
||||
const files = [createTestFile("test.md")];
|
||||
const inclusionPatterns = createMockPatternCategory({
|
||||
tagPatterns: ["#tag", "#tag", "#tag"],
|
||||
folderPatterns: ["folder", "folder"],
|
||||
});
|
||||
|
||||
const result = createAndPopulateGroupList(files, inclusionPatterns, null);
|
||||
|
||||
expect(Object.keys(result.tags)).toEqual(["#tag"]);
|
||||
expect(Object.keys(result.folders)).toEqual(["folder"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("convertGroupListToInclusions", () => {
|
||||
it("Should convert empty GroupList to empty string", () => {
|
||||
const emptyGroupList: GroupListItem = {
|
||||
tags: {},
|
||||
folders: {},
|
||||
extensions: {},
|
||||
notes: [],
|
||||
};
|
||||
|
||||
const result = convertGroupListToInclusions(emptyGroupList, []);
|
||||
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
tagPatterns: [],
|
||||
folderPatterns: [],
|
||||
extensionPatterns: [],
|
||||
notePatterns: [],
|
||||
});
|
||||
expect(result).toBe("");
|
||||
});
|
||||
|
||||
it("Should correctly extract all pattern types", () => {
|
||||
const groupList: GroupListItem = {
|
||||
tags: { "#important": [], "#work": [] },
|
||||
folders: { docs: [], projects: [] },
|
||||
extensions: { "*.md": [], "*.pdf": [] },
|
||||
notes: [
|
||||
{ id: "note1.md", name: "note1" },
|
||||
{ id: "note2.md", name: "note2" },
|
||||
],
|
||||
};
|
||||
|
||||
const appFiles = [createTestFile("note1.md"), createTestFile("note2.md")];
|
||||
|
||||
convertGroupListToInclusions(groupList, appFiles);
|
||||
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
tagPatterns: ["#important", "#work"],
|
||||
folderPatterns: ["docs", "projects"],
|
||||
extensionPatterns: ["*.md", "*.pdf"],
|
||||
notePatterns: ["[[note1]]", "[[note2]]"],
|
||||
});
|
||||
});
|
||||
|
||||
it("Should handle notes without corresponding files", () => {
|
||||
const groupList: GroupListItem = {
|
||||
tags: {},
|
||||
folders: {},
|
||||
extensions: {},
|
||||
notes: [
|
||||
{ id: "missing.md", name: "missing" },
|
||||
{ id: "existing.md", name: "existing" },
|
||||
],
|
||||
};
|
||||
|
||||
const appFiles = [createTestFile("existing.md")];
|
||||
|
||||
convertGroupListToInclusions(groupList, appFiles);
|
||||
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
tagPatterns: [],
|
||||
folderPatterns: [],
|
||||
extensionPatterns: [],
|
||||
notePatterns: ["[[existing]]"],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("convertDeletedItemsToExclusions", () => {
|
||||
it("Should convert empty IgnoreItems to empty string", () => {
|
||||
const emptyIgnoreItems: IgnoreItems = {
|
||||
files: new Set(),
|
||||
};
|
||||
|
||||
const result = convertDeletedItemsToExclusions(emptyIgnoreItems);
|
||||
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
notePatterns: [],
|
||||
});
|
||||
expect(result).toBe("");
|
||||
});
|
||||
|
||||
it("Should correctly convert ignored files to exclusion patterns", () => {
|
||||
const file1 = createTestFile("ignore1.md");
|
||||
const file2 = createTestFile("ignore2.pdf");
|
||||
|
||||
const ignoreItems: IgnoreItems = {
|
||||
files: new Set([file1, file2]),
|
||||
};
|
||||
|
||||
convertDeletedItemsToExclusions(ignoreItems);
|
||||
|
||||
expect(getFilePattern).toHaveBeenCalledWith(file1);
|
||||
expect(getFilePattern).toHaveBeenCalledWith(file2);
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
notePatterns: ["[[ignore1]]", "[[ignore2]]"],
|
||||
});
|
||||
});
|
||||
|
||||
it("Should handle a single ignored file", () => {
|
||||
const file = createTestFile("single.md");
|
||||
const ignoreItems: IgnoreItems = {
|
||||
files: new Set([file]),
|
||||
};
|
||||
|
||||
convertDeletedItemsToExclusions(ignoreItems);
|
||||
|
||||
expect(getFilePattern).toHaveBeenCalledWith(file);
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
notePatterns: ["[[single]]"],
|
||||
});
|
||||
});
|
||||
|
||||
it("Should handle case when createPatternSettingsValue returns undefined", () => {
|
||||
(createPatternSettingsValue as jest.Mock).mockReturnValueOnce(undefined);
|
||||
|
||||
const file = createTestFile("test.md");
|
||||
const ignoreItems: IgnoreItems = {
|
||||
files: new Set([file]),
|
||||
};
|
||||
|
||||
const result = convertDeletedItemsToExclusions(ignoreItems);
|
||||
|
||||
expect(result).toBe("");
|
||||
});
|
||||
});
|
||||
|
||||
// Boundary conditions and error handling tests
|
||||
describe("Boundary Condition Tests", () => {
|
||||
describe("createAndPopulateGroupList", () => {
|
||||
it("Should handle null inclusion patterns", () => {
|
||||
const files = [createTestFile("test.md")];
|
||||
const result = createAndPopulateGroupList(files, null, null);
|
||||
|
||||
expect(result.tags).toEqual({});
|
||||
expect(result.folders).toEqual({});
|
||||
expect(result.extensions).toEqual({});
|
||||
expect(result.notes).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("Should handle file paths with special characters", () => {
|
||||
const files = [
|
||||
createTestFile("folder with spaces/file-with-dashes.md"),
|
||||
createTestFile("中文文件夹/中文文件.md"),
|
||||
createTestFile("folder/file@#$%.md"),
|
||||
];
|
||||
|
||||
const result = createAndPopulateGroupList(files, null, null);
|
||||
|
||||
expect(result.notes).toHaveLength(3);
|
||||
expect(result.notes[0].name).toBe("file-with-dashes");
|
||||
expect(result.notes[1].name).toBe("中文文件");
|
||||
expect(result.notes[2].name).toBe("file@#$%");
|
||||
});
|
||||
});
|
||||
|
||||
describe("convertGroupListToInclusions", () => {
|
||||
it("Should handle large number of patterns", () => {
|
||||
const tags: Record<string, Array<GroupItem>> = {};
|
||||
const folders: Record<string, Array<GroupItem>> = {};
|
||||
const extensions: Record<string, Array<GroupItem>> = {};
|
||||
|
||||
// Create many patterns
|
||||
for (let i = 0; i < 100; i++) {
|
||||
tags[`#tag${i}`] = [];
|
||||
folders[`folder${i}`] = [];
|
||||
extensions[`*.ext${i}`] = [];
|
||||
}
|
||||
|
||||
const groupList: GroupListItem = { tags, folders, extensions, notes: [] };
|
||||
convertGroupListToInclusions(groupList, []);
|
||||
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
tagPatterns: expect.arrayContaining([`#tag0`, `#tag99`]),
|
||||
folderPatterns: expect.arrayContaining([`folder0`, `folder99`]),
|
||||
extensionPatterns: expect.arrayContaining([`*.ext0`, `*.ext99`]),
|
||||
notePatterns: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("Should handle invalid file paths in notes", () => {
|
||||
const groupList: GroupListItem = {
|
||||
tags: {},
|
||||
folders: {},
|
||||
extensions: {},
|
||||
notes: [
|
||||
{ id: "", name: "" },
|
||||
{ id: " ", name: " " },
|
||||
{ id: "valid.md", name: "valid" },
|
||||
],
|
||||
};
|
||||
|
||||
const appFiles = [createTestFile("valid.md")];
|
||||
convertGroupListToInclusions(groupList, appFiles);
|
||||
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
tagPatterns: [],
|
||||
folderPatterns: [],
|
||||
extensionPatterns: [],
|
||||
notePatterns: ["[[valid]]"],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("convertDeletedItemsToExclusions", () => {
|
||||
it("Should handle large number of ignored files", () => {
|
||||
const files = new Set<TFile>();
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
files.add(createTestFile(`file${i}.md`));
|
||||
}
|
||||
|
||||
const ignoreItems: IgnoreItems = { files };
|
||||
convertDeletedItemsToExclusions(ignoreItems);
|
||||
|
||||
expect(getFilePattern).toHaveBeenCalledTimes(1000);
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
notePatterns: expect.arrayContaining(["[[file0]]", "[[file999]]"]),
|
||||
});
|
||||
});
|
||||
|
||||
it("Should handle filenames with special characters", () => {
|
||||
const files = [
|
||||
createTestFile("file with spaces.md"),
|
||||
createTestFile("file-with-dashes.md"),
|
||||
createTestFile("file_with_underscores.md"),
|
||||
createTestFile("file@#$%.md"),
|
||||
];
|
||||
|
||||
const ignoreItems: IgnoreItems = { files: new Set(files) };
|
||||
convertDeletedItemsToExclusions(ignoreItems);
|
||||
|
||||
expect(getFilePattern).toHaveBeenCalledTimes(4);
|
||||
files.forEach((file) => {
|
||||
expect(getFilePattern).toHaveBeenCalledWith(file);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Integration tests
|
||||
describe("Integration Tests", () => {
|
||||
it("Should correctly handle the complete workflow", () => {
|
||||
// 1. Create initial file list
|
||||
const appFiles = [
|
||||
createTestFile("docs/readme.md"),
|
||||
createTestFile("src/main.ts"),
|
||||
createTestFile("tests/test.spec.ts"),
|
||||
createTestFile("config.json"),
|
||||
];
|
||||
|
||||
// 2. Set inclusion patterns
|
||||
const inclusionPatterns = createMockPatternCategory({
|
||||
folderPatterns: ["docs", "src"],
|
||||
extensionPatterns: ["*.md", "*.ts"],
|
||||
});
|
||||
|
||||
// 3. Create GroupList
|
||||
const groupList = createAndPopulateGroupList(appFiles, inclusionPatterns, null);
|
||||
|
||||
// 4. Convert to inclusions
|
||||
const inclusions = convertGroupListToInclusions(groupList, appFiles);
|
||||
|
||||
// 5. Create ignore items and convert to exclusions
|
||||
const ignoreItems: IgnoreItems = {
|
||||
files: new Set([createTestFile("config.json")]),
|
||||
};
|
||||
const exclusions = convertDeletedItemsToExclusions(ignoreItems);
|
||||
|
||||
// Verify results
|
||||
expect(groupList.folders).toHaveProperty("docs");
|
||||
expect(groupList.folders).toHaveProperty("src");
|
||||
expect(Object.prototype.hasOwnProperty.call(groupList.extensions, "*.md")).toBe(true);
|
||||
expect(Object.prototype.hasOwnProperty.call(groupList.extensions, "*.ts")).toBe(true);
|
||||
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
tagPatterns: [],
|
||||
folderPatterns: ["docs", "src"],
|
||||
extensionPatterns: ["*.md", "*.ts"],
|
||||
notePatterns: expect.any(Array),
|
||||
});
|
||||
|
||||
expect(createPatternSettingsValue).toHaveBeenCalledWith({
|
||||
notePatterns: ["[[config]]"],
|
||||
});
|
||||
|
||||
// Verify inclusions and exclusions variables
|
||||
// Since createPatternSettingsValue is mocked to return all patterns as comma-separated list
|
||||
expect(inclusions).toContain("docs");
|
||||
expect(inclusions).toContain("src");
|
||||
expect(inclusions).toContain("*.md");
|
||||
expect(inclusions).toContain("*.ts");
|
||||
|
||||
expect(exclusions).toBe("[[config]]");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -40,6 +40,14 @@ module.exports = {
|
|||
green: "var(--color-green)",
|
||||
blue: "var(--color-blue)",
|
||||
},
|
||||
"context-manager": {
|
||||
blue: "var(--color-blue)",
|
||||
green: "var(--color-green)",
|
||||
red: "var(--color-red)",
|
||||
yellow: "var(--color-yellow)",
|
||||
orange: "var(--color-orange)",
|
||||
purple: "var(--color-purple)",
|
||||
},
|
||||
},
|
||||
backgroundColor: {
|
||||
inherit: colors.inherit,
|
||||
|
|
|
|||
Loading…
Reference in a new issue