import { assembler, getSchemaKey } from "@hatchifyjs/core" import type { PartialSchema } from "@hatchifyjs/core" import type { HatchifyReactRest } from "@hatchifyjs/react-rest" import type { Fields, Filters, Include, RestClient, PaginationObject, GetSchemaNames, GetSchemaFromName, } from "@hatchifyjs/rest-client" import type { HatchifyDataGridProps as InternalHatchifyDataGridProps } from "../components/HatchifyDataGrid/index.js" import type { HatchifyEverythingProps as InternalHatchifyEverythingProps } from "../components/HatchifyEverything/index.js" import type { HatchifyNavigationProps as InternalHatchifyNavigationProps } from "../components/HatchifyNavigation/HatchifyNavigation.js" import type { HatchifyEmptyProps } from "../components/HatchifyEmpty/index.js" import type { DataGridState } from "../hooks/useDataGridState.js" import type { ReplaceColumnProps, ExtraColumnProps, } from "../components/HatchifyColumn/index.js" import hatchifyReactRest from "@hatchifyjs/react-rest" import { HatchifyDataGrid } from "../components/HatchifyDataGrid/index.js" import { HatchifyColumn } from "../components/HatchifyColumn/index.js" import { HatchifyEmpty } from "../components/HatchifyEmpty/index.js" import { HatchifyEverything } from "../components/HatchifyEverything/index.js" import useDataGridState from "../hooks/useDataGridState.js" import type { SortObject, XDataGridProps } from "../presentation/index.js" import { HatchifyNavigation } from "../components/HatchifyNavigation/index.js" import { HatchifyNoSchemas } from "../components/HatchifyNoSchemas/index.js" import { HatchifyFilters } from "../components/HatchifyFilters/index.js" import { HatchifyPagination } from "../components/HatchifyPagination/index.js" import { HatchifyList } from "../components/HatchifyList/index.js" type HatchifyEverythingProps> = Omit< InternalHatchifyEverythingProps, "finalSchemas" | "partialSchemas" | "restClient" > type HatchifyNavigationProps> = Omit< InternalHatchifyNavigationProps, "finalSchemas" | "partialSchemas" > type HatchifyDataGridProps< TSchemas extends Record, TSchemaName extends GetSchemaNames, > = Omit< InternalHatchifyDataGridProps, "finalSchemas" | "partialSchemas" | "schemaName" | "restClient" > type HatchifyFiltersProps< TSchemas extends Record, TSchemaName extends GetSchemaNames, > = XDataGridProps type HatchifyPaginationProps< TSchemas extends Record, TSchemaName extends GetSchemaNames, > = XDataGridProps type HatchifyListProps< TSchemas extends Record, TSchemaName extends GetSchemaNames, > = XDataGridProps type HatchifyColumnProps< TSchemas extends Record, TSchemaName extends GetSchemaNames, > = | Omit, "allSchemas" | "schemaName"> | Omit, "allSchemas" | "schemaName"> type Components> = { [SchemaName in keyof TSchemas]: { // compound (state managed) DataGrid: (( props: HatchifyDataGridProps, ) => React.ReactElement) & { Column: ( props: HatchifyColumnProps, ) => React.ReactElement Empty: (props: HatchifyEmptyProps) => React.ReactElement } // unmanaged state Filters: ( props: HatchifyFiltersProps, ) => React.ReactElement Pagination: ( props: HatchifyPaginationProps, ) => React.ReactElement List: (props: HatchifyListProps) => React.ReactElement } } export type HatchifyApp> = { components: Components Everything: (props: HatchifyEverythingProps) => JSX.Element Navigation: (props: HatchifyNavigationProps) => JSX.Element NoSchemas: () => JSX.Element model: HatchifyReactRest state: { [SchemaName in keyof TSchemas]: { useDataGridState: ({ defaultSelected, onSelectedChange, fields, include, defaultPage, defaultSort, alwaysSorted, baseFilter, minimumLoadTime, }?: { defaultSelected?: HatchifyDataGridProps< TSchemas, SchemaName >["defaultSelected"] onSelectedChange?: HatchifyDataGridProps< TSchemas, SchemaName >["onSelectedChange"] fields?: Fields include?: Include> defaultPage?: PaginationObject defaultSort?: SortObject alwaysSorted?: boolean baseFilter?: Filters minimumLoadTime?: number }) => DataGridState } } } export function hatchifyReact< const TSchemas extends Record, const TSchemaName extends GetSchemaNames, >(restClient: RestClient): HatchifyApp { const { completeSchemaMap: partialSchemas } = restClient const finalSchemas = assembler(partialSchemas) const reactRest = hatchifyReactRest(restClient) const components = Object.entries(partialSchemas).reduce( (acc, [schemaName, schema]) => { const key = schemaName as keyof typeof acc const schemaKey = getSchemaKey(schema) const dataGridCompoundComponents = ( props: HatchifyDataGridProps, ) => ( > finalSchemas={finalSchemas} partialSchemas={partialSchemas} schemaName={schemaKey} restClient={reactRest} {...props} /> ) function Column(props: HatchifyColumnProps) { return ( > allSchemas={finalSchemas} schemaName={schemaKey} {...props} /> ) } function Empty(props: HatchifyEmptyProps) { return } Column.displayName = "Column" Empty.displayName = "Empty" dataGridCompoundComponents.Column = Column dataGridCompoundComponents.Empty = Empty acc[key] = { DataGrid: dataGridCompoundComponents, Filters: (props) => ( > {...props} /> ), Pagination: (props) => ( > {...props} /> ), List: (props) => ( > {...props} /> ), } return acc }, {} as HatchifyApp["components"], ) const state = Object.entries(partialSchemas).reduce( (acc, [schemaName, schema]) => { const key = schemaName as keyof typeof acc acc[key] = { useDataGridState: ({ defaultSelected, onSelectedChange, fields, include, defaultPage, defaultSort, alwaysSorted, baseFilter, minimumLoadTime, } = {}) => useDataGridState>( finalSchemas, partialSchemas, key, reactRest, { defaultSelected, onSelectedChange, fields, include, defaultPage, defaultSort, alwaysSorted, baseFilter, minimumLoadTime, }, ), } return acc }, {} as HatchifyApp["state"], ) const Everything = (props: HatchifyEverythingProps) => ( ) const Navigation = (props: HatchifyNavigationProps) => ( ) const NoSchemas = () => return { components, Everything, Navigation, NoSchemas, model: reactRest, state, } }