import React, { useMemo, useState } from 'react' import { type Meta, type StoryObj } from '@storybook/react-vite' import { NumericFormat } from 'react-number-format' import { DocsTemplate } from '../../../.storybook' import TreeListBox from './TreeListBox' import { data } from './data' import { CheckboxState, type DateCheckState, type GenericNode, getFlattenNestedTreeList, type NestedCheckboxProps, } from '../Form/NestedCheckboxHelper' import SearchBar from '../SearchBar/SearchBar' import { toast } from '../Toast/Toast' const meta: Meta = { title: 'Components/TreeListBox', component: TreeListBox, parameters: { docs: { page: () => ( The TreeListBox component is an advanced multi-select interface that allows users to drill down through multiple hierarchical levels of options. Each checkbox in the list can have nested child options, and selecting a parent checkbox will automatically select all of its children. This component is ideal for managing complex, nested data structures and providing users with a clear and efficient way to make selections across multiple layers. } /> ), }, }, } export default meta type Story = StoryObj const HandleTreeListBox = ( args: { data: GenericNode[] } & NestedCheckboxProps, ) => { const { data: categoriesData } = args const flattenData = getFlattenNestedTreeList({ nestedData: (categoriesData as GenericNode[]) ?? [], childrenKey: 'children', parentKey: 'parent_category_id', idKey: 'id', }) const defaultItemStates = useMemo( () => flattenData.map((i) => ({ id: i['id'] as string | number, state: CheckboxState.UNCHECKED, })), [flattenData], ) const [itemStates, setItemStates] = useState(defaultItemStates) return ( ) } const Template: Story = { render: (args) => , } const tableConfig = [ { label: 'Categories/Subcategories', dataKey: 'name', children: (data: GenericNode) => ( {(data as { name: string }).name} ), }, { label: 'Est. Sales', dataKey: 'est_revenue', children: (data: GenericNode) => ( ), }, ] const identifierKeys = { displayKey: 'name', idKey: 'id', parentKey: 'parent_category_id', } const commonProps: NestedCheckboxProps = { data: data, tableConfig: tableConfig, identifierKeys, customHeight: '400px', customWidth: '100%', hasData: true, isLoading: false, onChange: () => toast({ type: 'info', message: 'Checkbox state changed' }), itemStates: [], setItemStates: () => {}, } export const Basic: Story = { ...Template, args: { ...commonProps, }, } export const WithSearchBar = () => { const [search, setSearch] = useState('') return (
setSearch(value)} debounce={300} />
) } export const Loading: Story = { ...Template, args: { ...commonProps, isLoading: true, }, } export const NoData: Story = { ...Template, args: { ...commonProps, hasData: false, noDataText: { primaryText: 'No data available', secondaryText: 'Please try again later', }, }, } export const DisabledHierarchy: Story = { ...Template, args: { ...commonProps, ignoreNodeHierarchy: true, }, parameters: { docs: { description: { story: `This example demonstrates the TreeListBox with disabled hierarchy behavior. When \`ignoreNodeHierarchy\` is set to \`true\`, selecting or deselecting a node will not affect its parent or child nodes. This is useful when you want to allow independent selection of nodes regardless of their hierarchical relationship.`, }, }, }, }