diff --git a/dprint.json b/dprint.json index 278204a..a483c54 100644 --- a/dprint.json +++ b/dprint.json @@ -2,6 +2,7 @@ "lineWidth": 140, "typescript": { "semiColons": "asi", + "indentWidth": 2, "quoteStyle": "preferSingle", "useTabs": false, "trailingCommas": "never", @@ -9,6 +10,7 @@ "importDeclaration.sortNamedImports": "maintain", "operatorPosition": "maintain", "jsx.quoteStyle": "preferDouble", + "jsx.bracketPosition": "maintain", "functionDeclaration.spaceBeforeParentheses": false }, "json": {}, diff --git a/eslint.config.js b/eslint.config.js index 5c1718e..ff1aa56 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -10,6 +10,9 @@ module.exports = nonzzz( 'examples/vue/node_modules', '__tests__/dist', '**/*.d.ts' - ] + ], + rules: { + 'stylistic/indent': 'off' + } } ) diff --git a/src/client/components/search-modules.tsx b/src/client/components/search-modules.tsx index a087509..fa0b9f2 100644 --- a/src/client/components/search-modules.tsx +++ b/src/client/components/search-modules.tsx @@ -2,6 +2,7 @@ import { ChangeEvent, useMemo, useState } from 'react' import type { Module, Sizes } from '../interface' import { convertBytes, uniqBy } from '../shared' import { useTreemapContext } from '../context' +import { flattenModules, wrapperModuleAsSquarifiedModule } from '../components/treemap/shared' import { Text } from './text' import { Spacer } from './spacer' import { Input } from './input' @@ -14,6 +15,17 @@ export interface SearchModulesProps { extra: Sizes } +function extension(filename: string) { + const match = filename.match(/\.([^.]+)$/) + return match ? `${match[1]}` : '' +} + +type ExcludeGroupsModule = Omit + +type FilterModule = ExcludeGroupsModule & { + isDirectory: boolean +} + export function SearchModules(props: SearchModulesProps) { const { treemap } = useTreemapContext() @@ -22,44 +34,34 @@ export function SearchModules(props: SearchModulesProps) { const [regExp, setRegExp] = useState() const [availableMap, setAvailableMap] = useState>({}) - const filtered = useMemo<{ foam: Module; modules: Module[] }[]>(() => { + const filtered = useMemo(() => { if (!regExp) { return [] } - return files - .map((foam) => { - const flatModules = (module: Module): Module[] => (module.groups?.flatMap(flatModules) || []).concat(module) - - const modules = flatModules(foam) - .filter((module) => regExp.test(module.label)) - .sort((a, b) => b[extra] - a[extra]) - .reduce( - (acc, module) => { - const group = !module.groups?.length ? 0 : 1 - acc[group].push(module) - return acc - }, - [[], []] as [Module[], Module[]] - ) - .flat() - - return { - foam, - modules: uniqBy(modules, 'label') - } - }) - .filter((find) => find.modules.length) - .sort((a, b) => a.modules.length - b.modules.length) + const filtered = files.map((module) => { + return { + parent: module, + children: uniqBy( + flattenModules(module.groups).filter(m => regExp.test(m.label)) + .map(m => ({ + ...m, + isDirectory: extension(m.label) ? false : true + })), + 'label' + ) + .sort((a, b) => { + if (a.isDirectory && !b.isDirectory) return -1 + if (!a.isDirectory && b.isDirectory) return 1 + return b[extra] - a[extra] + }) as FilterModule[] + } + }) + return filtered }, [regExp, files, extra]) - const findModules = useMemo( - () => filtered.reduce((acc, find) => acc.concat(find.modules), []), - [filtered] - ) - const findModulesSize = useMemo( - () => findModules.reduce((acc, module) => acc + module[extra], 0), - [findModules, extra] + () => filtered.reduce((acc, module) => acc + module.parent[extra], 0), + [filtered, extra] ) const handleChangeRegExp = (e: ChangeEvent) => { @@ -71,8 +73,8 @@ export function SearchModules(props: SearchModulesProps) { } } - const handleMouseEnter = (module: Module) => { - const check = treemap.current?.check(module) + const handleMouseEnter = (module: FilterModule) => { + const check = treemap.current?.check(wrapperModuleAsSquarifiedModule(module)) setAvailableMap({ ...availableMap, [module.label]: !!check @@ -91,53 +93,53 @@ export function SearchModules(props: SearchModulesProps) { {!!filtered.length && (
- Count: - {' '} - {filtered.length} + Count: + + {filtered.length} + - Total size: - {' '} - {convertBytes(findModulesSize)} + Total size: + + {convertBytes(findModulesSize)} +
)} {filtered.length ? ( - filtered.map((find) => ( -
- -
- {find.modules.map((module) => ( - handleMouseEnter(module)} - onClick={() => treemap.current?.zoom(module)} - stylex={{ fontStyle: 'italic' }} - > - {module.groups?.length ? : } - - - ))} -
+ <> + {filtered.map((module) => ( +
+ + {module.children.map((child) => ( + handleMouseEnter(child)} + onClick={() => + treemap.current?.zoom({ module: wrapperModuleAsSquarifiedModule(child), nativeEvent: Object.create(null) })} + stylex={{ fontStyle: 'italic' }} + > + {child.isDirectory ? : } + + + ))}
- )) - ) + ))} + + ) : (
"No modules found"
- )} + )} ) } diff --git a/src/client/components/treemap/component.tsx b/src/client/components/treemap/component.tsx index 3dc1a1e..9879c09 100644 --- a/src/client/components/treemap/component.tsx +++ b/src/client/components/treemap/component.tsx @@ -5,7 +5,7 @@ import { useApplicationContext } from '../../context' import type { Sizes } from '../../interface' import { PaintEvent, createTreemap } from './treemap' import type { Module } from './interface' -import { sortChildrenBySize } from './shared' +import { flattenModules, sortChildrenBySize } from './shared' function handleModule(data: Module, size: Sizes) { if (Array.isArray(data.groups)) { @@ -47,7 +47,6 @@ export const Treemap = forwardRef((props: TreemapProps, ref: ForwardedRef { if (!visibleChunks.length) return - if (!treemapInstance.current && containerRef.current) { const treemap = createTreemap(visibleChunks) treemapInstance.current = treemap diff --git a/src/client/components/treemap/interface.ts b/src/client/components/treemap/interface.ts index 674efcb..719871d 100644 --- a/src/client/components/treemap/interface.ts +++ b/src/client/components/treemap/interface.ts @@ -7,6 +7,8 @@ export interface Module extends _Module { [prop: string]: any } +export type FlattenedModule = Omit + export interface SquarifiedModule { node: Omit layout: [number, number, number, number] diff --git a/src/client/components/treemap/shared.ts b/src/client/components/treemap/shared.ts index 85295e8..a3e9dcd 100644 --- a/src/client/components/treemap/shared.ts +++ b/src/client/components/treemap/shared.ts @@ -5,6 +5,26 @@ export function sortChildrenBySize(a: Module, b: Module) { return b.size - a.size || +(a.id > b.id) - +(a.id < b.id) } +export function flattenModules & { groups: T[] }>(modules: T[]): Omit[] { + const flattend: Omit[] = [] + for (const module of modules) { + const { groups, ...rest } = module + flattend.push(rest) + if (groups) { + flattend.push(...flattenModules(groups)) + } + } + return flattend +} + +export function wrapperModuleAsSquarifiedModule>(module: T): SquarifiedModule { + return { + node: module, + layout: [0, 0, 0, 0], + children: [] + } +} + export function hueAngleToColor(hue: number, depth: number) { const saturation = 60 - depth * 5 const lightness = 50 + depth * 5 diff --git a/src/client/components/treemap/treemap.ts b/src/client/components/treemap/treemap.ts index 5542dec..88f0221 100644 --- a/src/client/components/treemap/treemap.ts +++ b/src/client/components/treemap/treemap.ts @@ -154,6 +154,9 @@ export class Paint { zoom(node: PaintEvent) { } + check(node: SquarifiedModule) { + } + dispose() { if (!this.mainEl) return this.mainEl.removeChild(this.canvas)