mirror of
https://github.com/lordmathis/lemma.git
synced 2025-12-23 01:54:28 +00:00
Compare commits
5 Commits
7424ce4385
...
d9f1a16d94
| Author | SHA1 | Date | |
|---|---|---|---|
| d9f1a16d94 | |||
| 0999fa9315 | |||
| cc8c8fd414 | |||
| 9ba37b3342 | |||
| 140ccd6879 |
76
app/package-lock.json
generated
76
app/package-lock.json
generated
@@ -15,6 +15,7 @@
|
|||||||
"@codemirror/state": "^6.5.2",
|
"@codemirror/state": "^6.5.2",
|
||||||
"@codemirror/theme-one-dark": "^6.1.3",
|
"@codemirror/theme-one-dark": "^6.1.3",
|
||||||
"@codemirror/view": "^6.38.6",
|
"@codemirror/view": "^6.38.6",
|
||||||
|
"@floating-ui/react": "^0.27.16",
|
||||||
"@mantine/core": "^8.3.7",
|
"@mantine/core": "^8.3.7",
|
||||||
"@mantine/hooks": "^8.3.7",
|
"@mantine/hooks": "^8.3.7",
|
||||||
"@mantine/modals": "^8.3.7",
|
"@mantine/modals": "^8.3.7",
|
||||||
@@ -22,9 +23,9 @@
|
|||||||
"@react-hook/resize-observer": "^2.0.2",
|
"@react-hook/resize-observer": "^2.0.2",
|
||||||
"@tabler/icons-react": "^3.35.0",
|
"@tabler/icons-react": "^3.35.0",
|
||||||
"codemirror": "^6.0.2",
|
"codemirror": "^6.0.2",
|
||||||
"react": "^18.3.1",
|
"react": "^19.2.0",
|
||||||
"react-arborist": "^3.4.3",
|
"react-arborist": "^3.4.3",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^19.2.0",
|
||||||
"rehype-highlight": "^7.0.2",
|
"rehype-highlight": "^7.0.2",
|
||||||
"rehype-mathjax": "^7.1.0",
|
"rehype-mathjax": "^7.1.0",
|
||||||
"rehype-react": "^8.0.0",
|
"rehype-react": "^8.0.0",
|
||||||
@@ -41,8 +42,8 @@
|
|||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
"@types/babel__core": "^7.20.5",
|
"@types/babel__core": "^7.20.5",
|
||||||
"@types/node": "^24.10.1",
|
"@types/node": "^24.10.1",
|
||||||
"@types/react": "^18.3.20",
|
"@types/react": "^19.2.5",
|
||||||
"@types/react-dom": "^18.3.6",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
||||||
"@typescript-eslint/parser": "^8.32.1",
|
"@typescript-eslint/parser": "^8.32.1",
|
||||||
"@vitejs/plugin-react": "^5.1.1",
|
"@vitejs/plugin-react": "^5.1.1",
|
||||||
@@ -2558,32 +2559,24 @@
|
|||||||
"undici-types": "~7.16.0"
|
"undici-types": "~7.16.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/prop-types": {
|
|
||||||
"version": "15.7.13",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
|
|
||||||
"integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "18.3.20",
|
"version": "19.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.5.tgz",
|
||||||
"integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==",
|
"integrity": "sha512-keKxkZMqnDicuvFoJbzrhbtdLSPhj/rZThDlKWCDbgXmUg0rEUFtRssDXKYmtXluZlIqiC5VqkCgRwzuyLHKHw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react-dom": {
|
"node_modules/@types/react-dom": {
|
||||||
"version": "18.3.6",
|
"version": "19.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
|
||||||
"integrity": "sha512-nf22//wEbKXusP6E9pfOCDwFdHAX4u172eaJI4YkDRQEZiorm6KfYnSC2SWLDMVWUOWPERmJnN0ujeAfTBLvrw==",
|
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^18.0.0"
|
"@types/react": "^19.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/unist": {
|
"node_modules/@types/unist": {
|
||||||
@@ -5808,9 +5801,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -7426,13 +7419,10 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "18.3.1",
|
"version": "19.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
|
||||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
|
||||||
"loose-envify": "^1.1.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -7494,16 +7484,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "18.3.1",
|
"version": "19.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
|
||||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0",
|
"scheduler": "^0.27.0"
|
||||||
"scheduler": "^0.23.2"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^18.3.1"
|
"react": "^19.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
@@ -8089,13 +8078,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/scheduler": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.23.2",
|
"version": "0.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
||||||
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
|
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"dependencies": {
|
|
||||||
"loose-envify": "^1.1.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "6.3.1",
|
"version": "6.3.1",
|
||||||
@@ -9157,12 +9143,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/use-sync-external-store": {
|
"node_modules/use-sync-external-store": {
|
||||||
"version": "1.2.2",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
|
||||||
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
|
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
"@codemirror/state": "^6.5.2",
|
"@codemirror/state": "^6.5.2",
|
||||||
"@codemirror/theme-one-dark": "^6.1.3",
|
"@codemirror/theme-one-dark": "^6.1.3",
|
||||||
"@codemirror/view": "^6.38.6",
|
"@codemirror/view": "^6.38.6",
|
||||||
|
"@floating-ui/react": "^0.27.16",
|
||||||
"@mantine/core": "^8.3.7",
|
"@mantine/core": "^8.3.7",
|
||||||
"@mantine/hooks": "^8.3.7",
|
"@mantine/hooks": "^8.3.7",
|
||||||
"@mantine/modals": "^8.3.7",
|
"@mantine/modals": "^8.3.7",
|
||||||
@@ -42,9 +43,9 @@
|
|||||||
"@react-hook/resize-observer": "^2.0.2",
|
"@react-hook/resize-observer": "^2.0.2",
|
||||||
"@tabler/icons-react": "^3.35.0",
|
"@tabler/icons-react": "^3.35.0",
|
||||||
"codemirror": "^6.0.2",
|
"codemirror": "^6.0.2",
|
||||||
"react": "^18.3.1",
|
"react": "^19.2.0",
|
||||||
"react-arborist": "^3.4.3",
|
"react-arborist": "^3.4.3",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^19.2.0",
|
||||||
"rehype-highlight": "^7.0.2",
|
"rehype-highlight": "^7.0.2",
|
||||||
"rehype-mathjax": "^7.1.0",
|
"rehype-mathjax": "^7.1.0",
|
||||||
"rehype-react": "^8.0.0",
|
"rehype-react": "^8.0.0",
|
||||||
@@ -61,8 +62,8 @@
|
|||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
"@types/babel__core": "^7.20.5",
|
"@types/babel__core": "^7.20.5",
|
||||||
"@types/node": "^24.10.1",
|
"@types/node": "^24.10.1",
|
||||||
"@types/react": "^18.3.20",
|
"@types/react": "^19.2.5",
|
||||||
"@types/react-dom": "^18.3.6",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
||||||
"@typescript-eslint/parser": "^8.32.1",
|
"@typescript-eslint/parser": "^8.32.1",
|
||||||
"@vitejs/plugin-react": "^5.1.1",
|
"@vitejs/plugin-react": "^5.1.1",
|
||||||
|
|||||||
@@ -69,7 +69,19 @@ vi.mock('react-arborist', () => ({
|
|||||||
|
|
||||||
// Mock resize observer hook
|
// Mock resize observer hook
|
||||||
vi.mock('@react-hook/resize-observer', () => ({
|
vi.mock('@react-hook/resize-observer', () => ({
|
||||||
default: vi.fn(),
|
default: vi.fn(
|
||||||
|
(
|
||||||
|
_target: unknown,
|
||||||
|
callback: (entry: { contentRect: { width: number; height: number } }) => void
|
||||||
|
) => {
|
||||||
|
// Immediately call the callback with a mock entry to provide size
|
||||||
|
if (callback) {
|
||||||
|
setTimeout(() => {
|
||||||
|
callback({ contentRect: { width: 300, height: 600 } });
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Mock contexts
|
// Mock contexts
|
||||||
@@ -172,7 +184,7 @@ describe('FileTree', () => {
|
|||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders file tree with files', () => {
|
it('renders file tree with files', async () => {
|
||||||
const { getByTestId } = render(
|
const { getByTestId } = render(
|
||||||
<TestWrapper>
|
<TestWrapper>
|
||||||
<FileTree
|
<FileTree
|
||||||
@@ -184,7 +196,9 @@ describe('FileTree', () => {
|
|||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(getByTestId('file-tree')).toBeInTheDocument();
|
await waitFor(() => {
|
||||||
|
expect(getByTestId('file-tree')).toBeInTheDocument();
|
||||||
|
});
|
||||||
expect(getByTestId('file-node-1')).toBeInTheDocument();
|
expect(getByTestId('file-node-1')).toBeInTheDocument();
|
||||||
expect(getByTestId('file-node-2')).toBeInTheDocument();
|
expect(getByTestId('file-node-2')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
@@ -201,6 +215,10 @@ describe('FileTree', () => {
|
|||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(getByTestId('file-node-1')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
const fileNode = getByTestId('file-node-1');
|
const fileNode = getByTestId('file-node-1');
|
||||||
fireEvent.click(fileNode);
|
fireEvent.click(fileNode);
|
||||||
|
|
||||||
@@ -209,7 +227,7 @@ describe('FileTree', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('filters out hidden files when showHiddenFiles is false', () => {
|
it('filters out hidden files when showHiddenFiles is false', async () => {
|
||||||
const { getByTestId, queryByTestId } = render(
|
const { getByTestId, queryByTestId } = render(
|
||||||
<TestWrapper>
|
<TestWrapper>
|
||||||
<FileTree
|
<FileTree
|
||||||
@@ -221,6 +239,10 @@ describe('FileTree', () => {
|
|||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(getByTestId('file-node-1')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
// Should show regular files
|
// Should show regular files
|
||||||
expect(getByTestId('file-node-1')).toBeInTheDocument();
|
expect(getByTestId('file-node-1')).toBeInTheDocument();
|
||||||
expect(getByTestId('file-node-2')).toBeInTheDocument();
|
expect(getByTestId('file-node-2')).toBeInTheDocument();
|
||||||
@@ -229,7 +251,7 @@ describe('FileTree', () => {
|
|||||||
expect(queryByTestId('file-node-4')).not.toBeInTheDocument();
|
expect(queryByTestId('file-node-4')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows hidden files when showHiddenFiles is true', () => {
|
it('shows hidden files when showHiddenFiles is true', async () => {
|
||||||
const { getByTestId } = render(
|
const { getByTestId } = render(
|
||||||
<TestWrapper>
|
<TestWrapper>
|
||||||
<FileTree
|
<FileTree
|
||||||
@@ -241,13 +263,17 @@ describe('FileTree', () => {
|
|||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(getByTestId('file-node-1')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
// Should show all files including hidden
|
// Should show all files including hidden
|
||||||
expect(getByTestId('file-node-1')).toBeInTheDocument();
|
expect(getByTestId('file-node-1')).toBeInTheDocument();
|
||||||
expect(getByTestId('file-node-2')).toBeInTheDocument();
|
expect(getByTestId('file-node-2')).toBeInTheDocument();
|
||||||
expect(getByTestId('file-node-4')).toBeInTheDocument();
|
expect(getByTestId('file-node-4')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders empty tree when no files provided', () => {
|
it('renders empty tree when no files provided', async () => {
|
||||||
const { getByTestId } = render(
|
const { getByTestId } = render(
|
||||||
<TestWrapper>
|
<TestWrapper>
|
||||||
<FileTree
|
<FileTree
|
||||||
@@ -259,6 +285,10 @@ describe('FileTree', () => {
|
|||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(getByTestId('file-tree')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
const tree = getByTestId('file-tree');
|
const tree = getByTestId('file-tree');
|
||||||
expect(tree).toBeInTheDocument();
|
expect(tree).toBeInTheDocument();
|
||||||
expect(tree.children).toHaveLength(0);
|
expect(tree.children).toHaveLength(0);
|
||||||
@@ -276,6 +306,10 @@ describe('FileTree', () => {
|
|||||||
</TestWrapper>
|
</TestWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(getByTestId('file-node-2')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
// Click on folder (has children)
|
// Click on folder (has children)
|
||||||
const folderNode = getByTestId('file-node-2');
|
const folderNode = getByTestId('file-node-2');
|
||||||
fireEvent.click(folderNode);
|
fireEvent.click(folderNode);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useRef, useState, useLayoutEffect, useCallback } from 'react';
|
import React, { useRef, useState, useCallback } from 'react';
|
||||||
import { Tree, type NodeApi } from 'react-arborist';
|
import { Tree, type NodeApi } from 'react-arborist';
|
||||||
import {
|
import {
|
||||||
IconFile,
|
IconFile,
|
||||||
@@ -23,15 +23,11 @@ interface FileTreeProps {
|
|||||||
loadFileList: () => Promise<void>;
|
loadFileList: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useSize = (target: React.RefObject<HTMLElement>): Size | undefined => {
|
const useSize = (
|
||||||
|
target: React.RefObject<HTMLElement | null>
|
||||||
|
): Size | undefined => {
|
||||||
const [size, setSize] = useState<Size>();
|
const [size, setSize] = useState<Size>();
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
if (target.current) {
|
|
||||||
setSize(target.current.getBoundingClientRect());
|
|
||||||
}
|
|
||||||
}, [target]);
|
|
||||||
|
|
||||||
useResizeObserver(target, (entry) => setSize(entry.contentRect));
|
useResizeObserver(target, (entry) => setSize(entry.contentRect));
|
||||||
return size;
|
return size;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useRef, useLayoutEffect, useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
import { Box } from '@mantine/core';
|
import { Box } from '@mantine/core';
|
||||||
import { Tree, type NodeApi } from 'react-arborist';
|
import { Tree, type NodeApi } from 'react-arborist';
|
||||||
import {
|
import {
|
||||||
@@ -21,15 +21,11 @@ interface Size {
|
|||||||
height: number;
|
height: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useSize = (target: React.RefObject<HTMLElement>): Size | undefined => {
|
const useSize = (
|
||||||
|
target: React.RefObject<HTMLElement | null>
|
||||||
|
): Size | undefined => {
|
||||||
const [size, setSize] = useState<Size>();
|
const [size, setSize] = useState<Size>();
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
if (target.current) {
|
|
||||||
setSize(target.current.getBoundingClientRect());
|
|
||||||
}
|
|
||||||
}, [target]);
|
|
||||||
|
|
||||||
useResizeObserver(target, (entry) => setSize(entry.contentRect));
|
useResizeObserver(target, (entry) => setSize(entry.contentRect));
|
||||||
return size;
|
return size;
|
||||||
};
|
};
|
||||||
@@ -239,7 +235,10 @@ export const FolderSelector: React.FC<FolderSelectorProps> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Root option */}
|
{/* Root option */}
|
||||||
<RootNode isSelected={selectedPath === ''} onSelect={() => onSelect('')} />
|
<RootNode
|
||||||
|
isSelected={selectedPath === ''}
|
||||||
|
onSelect={() => onSelect('')}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Folder tree */}
|
{/* Folder tree */}
|
||||||
{size && folders.length > 0 && (
|
{size && folders.length > 0 && (
|
||||||
@@ -255,7 +254,11 @@ export const FolderSelector: React.FC<FolderSelectorProps> = ({
|
|||||||
disableDrop={() => true}
|
disableDrop={() => true}
|
||||||
>
|
>
|
||||||
{(props) => (
|
{(props) => (
|
||||||
<FolderNode {...props} selectedPath={selectedPath} onSelect={onSelect} />
|
<FolderNode
|
||||||
|
{...props}
|
||||||
|
selectedPath={selectedPath}
|
||||||
|
onSelect={onSelect}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</Tree>
|
</Tree>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user