// // Copyright 2024 DXOS.org // import React from 'react'; import { faker } from '@dxos/random'; import { Treegrid } from './Treegrid'; import { withTheme } from '../../testing'; import { Icon } from '../Icon'; faker.seed(1234); type StorybookNode = { id: string; title: string; icon?: string; nodes?: StorybookNode[]; }; type StorybookIteratorNode = { node: StorybookNode; path: string[]; parentOf?: string[]; }; const content = { id: 'root', title: 'Root', nodes: [ { id: faker.string.uuid(), title: 'Personal Space', icon: 'ph--house--regular', nodes: [ { id: faker.string.uuid(), title: faker.commerce.productName(), }, { id: faker.string.uuid(), title: faker.commerce.productName(), }, { id: faker.string.uuid(), title: faker.commerce.productName(), nodes: [ { id: faker.string.uuid(), title: faker.commerce.productName(), nodes: [ { id: faker.string.uuid(), title: faker.commerce.productName(), }, { id: faker.string.uuid(), title: faker.commerce.productName(), }, ], }, ], }, ], }, { id: faker.string.uuid(), title: faker.commerce.productName(), icon: 'ph--planet--regular', nodes: [ { id: faker.string.uuid(), title: faker.commerce.productName(), }, ], }, { id: faker.string.uuid(), title: faker.commerce.productName(), icon: 'ph--sailboat--regular', }, { id: faker.string.uuid(), title: faker.commerce.productName(), icon: 'ph--planet--regular', }, ], } satisfies StorybookNode; function* visitor(node: StorybookNode, isOpen?: (node: StorybookNode) => boolean): Generator { const stack: StorybookIteratorNode[] = [ { node, path: [node.id], parentOf: (node.nodes ?? []).map(({ id }) => id), }, ]; while (stack.length > 0) { const { node, path, parentOf } = stack.pop()!; if (path.length > 1) { yield { node, path, parentOf }; } const children = Array.from(node.nodes ?? []); if (path.length === 1 || isOpen?.(node)) { for (let i = children.length - 1; i >= 0; i--) { const child = children[i]; stack.push({ node: child, path: [...path, child.id], ...((child.nodes?.length ?? 0) > 0 && { parentOf: child.nodes!.map(({ id }) => id), }), }); } } } } const flattenedContent = Array.from(visitor(content, () => true)); const DefaultStory = () => { return ( {flattenedContent.map(({ node, parentOf, path }) => { return ( {node.icon && } {node.title} ); })} ); }; export default { title: 'ui/react-ui-core/Treegrid', component: Treegrid.Root, render: DefaultStory, decorators: [withTheme], }; export const Default = {};