import * as React from 'react' import type { StoryFn, Meta } from '@storybook/react-webpack5' import type { Column, GridRowMeta } from '..' import { Grid, GridCellDefault } from '..' export default { title: 'pv-grid/Examples/Tree', tags: ['hidden'], } satisfies Meta const currencyFormatter = new Intl.NumberFormat(undefined, { style: 'currency', currency: 'USD', }) type Author = { id: string name: string } type Category = { id: string name: string } type Book = { id: string title: string price: number } function isAuthor(author: Author | Book): author is Author { return !!(author as Author).name } export const TreeGrid: StoryFn = () => { const treeRows = React.useMemo>( () => ({ a100: { id: 'a100', name: 'Jules Verne' }, 1001: { id: '1001', title: 'Journey to the Center of the Earth', price: 11.99, }, 1002: { id: '1002', title: 'Twenty Thousand Leagues Under the Sea', price: 35.65, }, 1003: { id: '1003', title: 'Around the World In Eighty Days', price: 29.98, }, a200: { id: 'a200', name: 'Roald Dahl' }, 1004: { id: '1004', title: 'James and the Giant Peach', price: 7.99, }, }), [] ) const treeData = React.useMemo( () => ({ ids: ['a100', 'a200'], meta: new Map>( Object.entries({ a100: { type: 'tree', children: ['1001', '1002', '1003'] }, a200: { type: 'tree', children: ['1004'] }, }) ), data: treeRows, }), [treeRows] ) const columns = React.useMemo[]>( () => [ { id: 'title', label: 'Name', width: 400, tree: true, cell: { value({ row }) { if (isAuthor(row)) { return row.name } return row.title }, }, }, { id: 'price', label: 'Price', width: 200, header: { align: 'right', }, cell: { label: ({ value }: { value: number }) => value ? currencyFormatter.format(value) : '', Renderer: ({ label, tabIndex }) => ( ), }, }, ], [] ) return } TreeGrid.parameters = { docs: { source: { code: ` import React from 'react' import type { Column, GridRowMeta } from '@planview/pv-grid' import { Grid, GridCellDefault } from '@planview/pv-grid' const currencyFormatter = new Intl.NumberFormat(undefined, { style: 'currency', currency: 'USD', }) type Author = { id: string name: string } type Category = { id: string name: string } type Book = { id: string title: string price: number } function isAuthor(author: Author | Book): author is Author { return !!(author as Author).name } export const TreeGrid = () => { const treeRows = React.useMemo>( () => ({ a100: { id: 'a100', name: 'Jules Verne' }, 1001: { id: '1001', title: 'Journey to the Center of the Earth', price: 11.99, }, 1002: { id: '1002', title: 'Twenty Thousand Leagues Under the Sea', price: 35.65, }, 1003: { id: '1003', title: 'Around the World In Eighty Days', price: 29.98, }, a200: { id: 'a200', name: 'Roald Dahl' }, 1004: { id: '1004', title: 'James and the Giant Peach', price: 7.99, }, }), [] ) const treeData = React.useMemo( () => ({ ids: ['a100', 'a200'], meta: new Map>( Object.entries({ a100: { type: 'tree', children: ['1001', '1002', '1003'] }, a200: { type: 'tree', children: ['1004'] }, }) ), data: treeRows, }), [treeRows] ) const columns = React.useMemo[]>( () => [ { id: 'title', label: 'Name', width: 400, tree: true, cell: { value({ row }) { if (isAuthor(row)) { return row.name } return row.title }, }, }, { id: 'price', label: 'Price', width: 200, header: { align: 'right', }, cell: { label: ({ value }: { value: number }) => value ? currencyFormatter.format(value) : '', Renderer: ({ label, tabIndex }) => ( ), }, }, ], [] ) return } `, }, }, } function isCategory(category: Category | Book): category is Category { return !!(category as Category).name } export const TreeGridGroup: StoryFn = () => { const treeRows = React.useMemo>( () => ({ a100: { id: 'a100', name: 'Older books' }, 1001: { id: '1001', title: 'Journey to the Center of the Earth', price: 11.99, }, 1002: { id: '1002', title: 'Twenty Thousand Leagues Under the Sea', price: 35.65, }, 1003: { id: '1003', title: 'Around the World In Eighty Days', price: 29.98, }, a200: { id: 'a200', name: 'Newer books' }, 1004: { id: '1004', title: 'James and the Giant Peach', price: 7.99, }, }), [] ) const treeData = React.useMemo( () => ({ ids: ['a100', 'a200'], meta: new Map>( Object.entries({ a100: { type: 'group', children: ['1001', '1002', '1003'] }, a200: { type: 'group', children: ['1004'] }, }) ), data: treeRows, }), [treeRows] ) const columns = React.useMemo[]>( () => [ { id: 'title', label: 'Name', width: 400, tree: true, cell: { value({ row }) { if (isCategory(row)) { return row.name } return row.title }, }, }, { id: 'price', label: 'Price', width: 200, header: { align: 'right', }, cell: { label: ({ value }: { value: number }) => value ? currencyFormatter.format(value) : '', Renderer: ({ label, tabIndex }) => ( ), }, }, ], [] ) return } TreeGridGroup.parameters = { docs: { source: { code: ` import React from 'react' import type { Column, GridRowMeta } from '@planview/pv-grid' import { Grid, GridCellDefault } from '@planview/pv-grid' const currencyFormatter = new Intl.NumberFormat(undefined, { style: 'currency', currency: 'USD', }) type Category = { id: string name: string } type Book = { id: string title: string price: number } function isCategory(category: Category | Book): category is Category { return !!(category as Category).name } export const TreeGridGroup = () => { const treeRows = React.useMemo>( () => ({ a100: { id: 'a100', name: 'Older books' }, 1001: { id: '1001', title: 'Journey to the Center of the Earth', price: 11.99, }, 1002: { id: '1002', title: 'Twenty Thousand Leagues Under the Sea', price: 35.65, }, 1003: { id: '1003', title: 'Around the World In Eighty Days', price: 29.98, }, a200: { id: 'a200', name: 'Newer books' }, 1004: { id: '1004', title: 'James and the Giant Peach', price: 7.99, }, }), [] ) const treeData = React.useMemo( () => ({ ids: ['a100', 'a200'], meta: new Map>( Object.entries({ a100: { type: 'group', children: ['1001', '1002', '1003'] }, a200: { type: 'group', children: ['1004'] }, }) ), data: treeRows, }), [treeRows] ) const columns = React.useMemo[]>( () => [ { id: 'title', label: 'Name', width: 400, tree: true, cell: { value({ row }) { if (isCategory(row)) { return row.name } return row.title }, }, }, { id: 'price', label: 'Price', width: 200, header: { align: 'right', }, cell: { label: ({ value }: { value: number }) => value ? currencyFormatter.format(value) : '', Renderer: ({ label, tabIndex }) => ( ), }, }, ], [] ) return } `, }, }, }