From b3d6e9531106b4593fbe7d8c08cb25bb8ce91781 Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sat, 11 Nov 2023 14:07:44 +0000 Subject: [PATCH] customising value display --- demo/src/App.tsx | 14 +-- demo/src/FastUI/components/Json.tsx | 22 +++++ demo/src/FastUI/components/display.tsx | 130 ++++++++++++++++--------- demo/src/FastUI/components/index.tsx | 14 +++ demo/src/FastUI/components/table.tsx | 8 +- demo/src/FastUI/hooks/customRender.ts | 6 +- demo/src/FastUI/index.tsx | 3 +- 7 files changed, 136 insertions(+), 61 deletions(-) create mode 100644 demo/src/FastUI/components/Json.tsx diff --git a/demo/src/App.tsx b/demo/src/App.tsx index c736df8c..9344402a 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -8,12 +8,14 @@ export default function App() { ) } -const customRender: CustomRender = () => { - // const { type } = props - // if (type == 'Modal') { - // return () => modal - // } - return null +const customRender: CustomRender = (props) => { + const { type } = props + if (type == 'DisplayPrimitive') { + const { value } = props + if (typeof value == 'boolean') { + return () => <>{value ? '👍' : '👎'} + } + } } const bootstrapClassName: ClassNameGenerator = (props) => { diff --git a/demo/src/FastUI/components/Json.tsx b/demo/src/FastUI/components/Json.tsx new file mode 100644 index 00000000..f0e97377 --- /dev/null +++ b/demo/src/FastUI/components/Json.tsx @@ -0,0 +1,22 @@ +import {FC} from 'react' + +export type JSON = string | number | boolean | null | JSON[] | { [key: string]: JSON } + +export interface JsonProps { + value: JSON + type: 'JSON' +} + +export const JsonComp: FC = ({ value }) => { + // if the value is a string, we assume it's already JSON, and parse it + if (typeof value === 'string') { + value = JSON.parse(value) + } + return ( +
+
+        {JSON.stringify(value, null, 2)}
+      
+
+ ) +} diff --git a/demo/src/FastUI/components/display.tsx b/demo/src/FastUI/components/display.tsx index f6af0e53..8af3f55e 100644 --- a/demo/src/FastUI/components/display.tsx +++ b/demo/src/FastUI/components/display.tsx @@ -1,6 +1,6 @@ import { FC } from 'react' - -export type JSON = string | number | boolean | null | JSON[] | { [key: string]: JSON } +import {JsonComp, JSON} from './Json' +import {useCustomRender} from '../hooks/customRender' // eslint-disable-next-line react-refresh/only-export-components export enum DisplayChoices { @@ -15,21 +15,95 @@ export enum DisplayChoices { inline_code = 'inline_code', } -export interface DisplayProps { +interface DisplayProps { display?: DisplayChoices value?: JSON + type: 'Display' } -export const DisplayComp: FC = ({ value, display }) => { - display = display ?? DisplayChoices.auto - value = value ?? null +export type AllDisplayProps = DisplayProps | DisplayArrayProps | DisplayObjectProps | DisplayPrimitiveProps + +export const DisplayComp: FC = (props) => { + const CustomRenderComp = useCustomRender(props) + if (CustomRenderComp) { + return + } + + const display = props.display ?? DisplayChoices.auto + const value = props.value ?? null if (display == DisplayChoices.json) { - return + return } else if (Array.isArray(value)) { - return + return } else if (typeof value === 'object' && value !== null) { - return + return + } else { + return + } +} + +interface DisplayArrayProps { + value: JSON[] + display?: DisplayChoices + type: 'DisplayArray' +} + +export const DisplayArray: FC = (props) => { + const CustomRenderComp = useCustomRender(props) + if (CustomRenderComp) { + return + } + const { display, value } = props + + return ( + <> + {value.map((v, i) => ( + + ,{' '} + + ))} + + ) +} + +interface DisplayObjectProps { + value: { [key: string]: JSON } + display?: DisplayChoices + type: 'DisplayObject' +} + +export const DisplayObject: FC = (props) => { + const CustomRenderComp = useCustomRender(props) + if (CustomRenderComp) { + return } + const { display, value } = props + + return ( + <> + {Object.entries(value).map(([key, v], i) => ( + + {key}: ,{' '} + + ))} + + ) +} + +type JSONPrimitive = string | number | boolean | null + +interface DisplayPrimitiveProps { + value: JSONPrimitive + display: DisplayChoices + type: 'DisplayPrimitive' +} + +export const DisplayPrimitive: FC = (props) => { + const CustomRenderComp = useCustomRender(props) + if (CustomRenderComp) { + return + } + const { display, value } = props switch (display) { case DisplayChoices.auto: @@ -51,42 +125,6 @@ export const DisplayComp: FC = ({ value, display }) => { } } -const DisplayJsonComp: FC<{ value: JSON }> = ({ value }) => { - // if the value is a string, we assume it's already JSON, and parse it - if (typeof value === 'string') { - value = JSON.parse(value) - } - return ( -
-
-        {JSON.stringify(value, null, 2)}
-      
-
- ) -} - -const DisplayArray: FC<{ display?: DisplayChoices; value: JSON[] }> = ({ display, value }) => ( - <> - {value.map((v, i) => ( - - ,{' '} - - ))} - -) - -const DisplayObject: FC<{ display?: DisplayChoices; value: { [key: string]: JSON } }> = ({ display, value }) => ( - <> - {Object.entries(value).map(([key, v], i) => ( - - {key}: ,{' '} - - ))} - -) - -type JSONPrimitive = string | number | boolean | null - const DisplayNull: FC = () => { return } @@ -144,7 +182,7 @@ const DisplayDuration: FC<{ value: JSONPrimitive }> = ({ value }) => { // usage as_title('what_ever') > 'What Ever' // eslint-disable-next-line react-refresh/only-export-components -export const as_title = (s: string): string => s.replace(/(_|-)/g, ' ').replace(/(_|\b)\w/g, (l) => l.toUpperCase()) +export const as_title = (s: string): string => s.replace(/[_-]/g, ' ').replace(/(_|\b)\w/g, (l) => l.toUpperCase()) const DisplayAsTitle: FC<{ value: JSONPrimitive }> = ({ value }) => { if (value === null) { diff --git a/demo/src/FastUI/components/index.tsx b/demo/src/FastUI/components/index.tsx index f3819d68..f5e305b8 100644 --- a/demo/src/FastUI/components/index.tsx +++ b/demo/src/FastUI/components/index.tsx @@ -9,6 +9,8 @@ import { ButtonComp, ButtonProps } from './button' import { LinkComp, LinkProps } from './link' import { ModalComp, ModalProps } from './modal' import { TableComp, TableProps } from './table' +import {AllDisplayProps, DisplayArray, DisplayComp, DisplayObject, DisplayPrimitive} from './display' +import {JsonComp, JsonProps} from './Json' export type FastProps = | TextProps @@ -19,6 +21,8 @@ export type FastProps = | ModalProps | TableProps | LinkProps + | AllDisplayProps + | JsonProps export const AnyComp: FC = (props) => { const { DisplayError } = useContext(ErrorContext) @@ -50,6 +54,16 @@ export const AnyComp: FC = (props) => { return case 'Table': return + case 'Display': + return + case 'DisplayArray': + return + case 'DisplayObject': + return + case 'DisplayPrimitive': + return + case 'JSON': + return default: console.log('unknown component type:', type, props) return diff --git a/demo/src/FastUI/components/table.tsx b/demo/src/FastUI/components/table.tsx index ae607d15..186fdff7 100644 --- a/demo/src/FastUI/components/table.tsx +++ b/demo/src/FastUI/components/table.tsx @@ -1,9 +1,9 @@ import { FC } from 'react' import { ClassName, useClassNameGenerator } from '../hooks/className' import { PageEvent, GoToEvent } from '../hooks/event' -import {as_title, DisplayChoices, DisplayComp} from './display' +import {as_title, DisplayChoices, DisplayComp } from './display' import { LinkRender } from './link' -import type { JSON } from './display' +import type { JSON } from './Json' interface ColumnProps { field: string @@ -72,14 +72,14 @@ const Cell: FC = ({ row, column }) => { return ( - + ) } else { return ( - + ) } diff --git a/demo/src/FastUI/hooks/customRender.ts b/demo/src/FastUI/hooks/customRender.ts index 97f44e76..1d44c3ae 100644 --- a/demo/src/FastUI/hooks/customRender.ts +++ b/demo/src/FastUI/hooks/customRender.ts @@ -1,16 +1,14 @@ import { createContext, FC, useContext } from 'react' import { FastProps } from '../components' -export type CustomRender = (props: FastProps) => FC | null +export type CustomRender = (props: FastProps) => FC | void export const CustomRenderContext = createContext(null) -export const useCustomRender = (props: FastProps): FC | null => { +export const useCustomRender = (props: FastProps): FC | void => { const customRender = useContext(CustomRenderContext) if (customRender) { return customRender(props) - } else { - return null } } diff --git a/demo/src/FastUI/index.tsx b/demo/src/FastUI/index.tsx index 7cb6af6a..e3a093a6 100644 --- a/demo/src/FastUI/index.tsx +++ b/demo/src/FastUI/index.tsx @@ -5,8 +5,9 @@ import { ClassNameContext, ClassNameGenerator } from './hooks/className' import { ErrorContextProvider, ErrorDisplayType } from './hooks/error' import { CustomRender, CustomRenderContext } from './hooks/customRender' import { FastProps } from './components' +import { DisplayChoices } from './components/display' -export type { ClassNameGenerator, CustomRender, ErrorDisplayType, FastProps } +export type { ClassNameGenerator, CustomRender, ErrorDisplayType, FastProps, DisplayChoices } export interface FastUIProps { rootUrl: string