-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ds-material new base components for GenericList #178; store action ty…
…pings #163 and normalize/optimize the GenericList widget html-structure and a bit of styling, very small sizing/gutter adjustments and better support for e,g. footer
- Loading branch information
1 parent
3284b0e
commit babf3e7
Showing
32 changed files
with
671 additions
and
267 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
packages/docs/src/content/docs/ds-material/GenericList.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# DS Material GenericList | ||
|
||
Base components for the `GenericList` widget, to easily configure and re-wire the widget parts, see also the [widget docs here](/docs/widgets/GenericList). | ||
|
||
```typescript jsx | ||
import React from 'react' | ||
import { List } from 'immutable' | ||
import { memo } from '@ui-schema/ui-schema/Utils/memo' | ||
import { WidgetProps } from '@ui-schema/ui-schema/Widget' | ||
import { useUIStore, WithOnChange } from '@ui-schema/ui-schema/UIStore' | ||
import { | ||
GenericListContent, GenericListFooter, | ||
GenericListItem, | ||
GenericListItemMore, GenericListItemPos, | ||
} from '@ui-schema/ds-material/BaseComponents/GenericList' | ||
import { MuiWidgetBinding } from '@ui-schema/ds-material/widgetsBinding' | ||
|
||
// it is important to use `memo` from `@ui-schema/ui-schema` for the content component, | ||
// as the generic list will re-render on each change of anything in the store, | ||
// with passing down `listSize` and not other data, the `GenericListContent` will only re-render when the `listSize` changes | ||
export const GenericListContentMemo = memo(GenericListContent) | ||
|
||
export const GenericList = (props: WidgetProps<MuiWidgetBinding> & WithOnChange): React.ReactElement => { | ||
const {store} = useUIStore() | ||
// info: `store?.extractValues` is new since `0.3.0-alpha.11` and can be used instead of the `extractValue` HOC | ||
const {value} = store?.extractValues<List<any>>(props.storeKeys) || {} | ||
// extracting and calculating the list size here, not passing down the actual list for performance reasons | ||
// https://github.com/ui-schema/ui-schema/issues/133 | ||
return <GenericListContentMemo | ||
{...props} | ||
listSize={value?.size || 0} | ||
ComponentItemPos={GenericListItemPos} | ||
ComponentItemMore={GenericListItemMore} | ||
ComponentItem={GenericListItem} | ||
ComponentFooter={GenericListFooter} | ||
// e.g. use `Button` instead of `IconButton` for `add-item` | ||
//btnAddShowLabel | ||
/> | ||
} | ||
``` | ||
|
||
Easily define own schema keywords, for options which are only supported by `props`: | ||
|
||
```typescript jsx | ||
export const GenericList = (props: WidgetProps<MuiWidgetBinding> & WithOnChange): React.ReactElement => { | ||
const {store} = useUIStore() | ||
const {value} = store?.extractValues<List<any>>(props.storeKeys) || {} | ||
// extracting and calculating the list size here, not passing down the actual list for performance reasons | ||
// https://github.com/ui-schema/ui-schema/issues/133 | ||
return <GenericListContentMemo | ||
{...props} | ||
listSize={value?.size || 0} | ||
ComponentItemPos={GenericListItemPos} | ||
ComponentItemMore={GenericListItemMore} | ||
ComponentItem={GenericListItem} | ||
ComponentFooter={GenericListFooter} | ||
btnAddShowLabel={Boolean(schema.getIn(['view', 'btnAsLabel']))} | ||
/> | ||
} | ||
``` | ||
|
||
Use the [GenericListContent.tsx](https://github.com/ui-schema/ui-schema/tree/master/packages/ds-material/src/BaseComponents/GenericList/GenericListContent.tsx) as a starting point if you need to further adjust the widget parts. | ||
|
||
## Translation / Labels | ||
|
||
- `labels.add-item` used by `GenericListFooter` for the add-button, supports named-labels key `add` | ||
- `labels.remove-item` used by `GenericListItemMore` for the delete-button, supports named-labels key `remove` | ||
- `labels.move-to-position` used by `GenericListItemPos` to render the up/down buttons, adds the context `nextIndex` to render to-which-position it will be moved | ||
- `labels.entry` used by `GenericListItemPos` as `sr-only` for the nth-label | ||
|
||
**Notices:** | ||
|
||
- `sr-only` = `screen-reader-only` text `span` for a11y | ||
- supports named-label: uses the `context` to pass down `actionLabels` for a not-generic-labelling, the given key is the intended action-key for the label | ||
|
||
For `actionLabels` handling, see [dictionary/en/labels](https://github.com/ui-schema/ui-schema/tree/master/packages/dictionary/en/labels.js) as an example. | ||
|
||
Example schema structure that activates `actionLabels`, with support for multiple languages and different buttons: | ||
|
||
```json | ||
{ | ||
"type": "object", | ||
"widget": "GenericList", | ||
"listActionLabels": { | ||
"en": { | ||
"add": "New event", | ||
"remove": "Remove event" | ||
}, | ||
"de": { | ||
"add": "Neue Veranstaltung", | ||
"remove": "Lösche Veranstaltung" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
## Components | ||
|
||
### GenericListContent | ||
|
||
The list renderer component, uses the components passed down per `props` to build the needed list out of the `listSize` - it does not receive any data from the list. | ||
|
||
`GenericListContentProps`: | ||
|
||
- `btnAddShowLabel`: `boolean`, for the add-item button, when `true` displays a normal button and not only an icon-button | ||
- `btnAddStyle`: `React.CSSProperties`, for the add-item button, custom react styles | ||
- `ComponentItemPos`: `React.ComponentType<GenericListItemSharedProps>`, will be rendered in `ComponentItem`, contains the position and up/down buttons | ||
- `ComponentItemMore`: `React.ComponentType<GenericListItemSharedProps>`, will be rendered in `ComponentItem`, contains the delete button | ||
- `ComponentItem`: `React.ComponentType<GenericListItemProps>`, is rendered per item in the list, responsible to further render nested schema, also uses component props | ||
- `ComponentFooter`: `React.ComponentType<GenericListFooterProps>`, will be rendered in `GenericListContent`, contains the add-button | ||
- `listSize`: `number`, the size of the list | ||
- `schemaKeys`: `StoreKeys`, experimental [#104](https://github.com/ui-schema/ui-schema/issues/104) | ||
- `listSpacing`: `GridSpacing`, used as the spacing for the item-list | ||
|
||
### GenericListItem | ||
|
||
For props check typings. | ||
|
||
### GenericListItemPos | ||
|
||
For props check typings. | ||
|
||
### GenericListItemMore | ||
|
||
For props check typings. | ||
|
||
### GenericListFooter | ||
|
||
For props check typings. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
packages/ds-material/src/BaseComponents/GenericList/GenericListContent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import React from 'react' | ||
import FormControl from '@material-ui/core/FormControl' | ||
import Grid from '@material-ui/core/Grid' | ||
import FormLabel from '@material-ui/core/FormLabel' | ||
import { TransTitle, StoreKeys, WidgetProps, WithOnChange } from '@ui-schema/ui-schema' | ||
import { ListButtonOverwrites } from '@ui-schema/ds-material/Component/ListButton' | ||
import { MuiWidgetBinding } from '@ui-schema/ds-material/widgetsBinding' | ||
import { GenericListFooterProps, GenericListItemProps, GenericListItemSharedProps } from '@ui-schema/ds-material/BaseComponents' | ||
import Box from '@material-ui/core/Box' | ||
import { GridSpacing } from '@material-ui/core/Grid/Grid' | ||
|
||
export interface GenericListContentProps extends ListButtonOverwrites { | ||
btnAddShowLabel?: boolean | ||
btnAddStyle?: React.CSSProperties | ||
ComponentItemPos?: React.ComponentType<GenericListItemSharedProps> | ||
ComponentItemMore?: React.ComponentType<GenericListItemSharedProps> | ||
ComponentItem: React.ComponentType<GenericListItemProps> | ||
ComponentFooter?: React.ComponentType<GenericListFooterProps> | ||
listSize: number | ||
schemaKeys?: StoreKeys | ||
listSpacing?: GridSpacing | ||
} | ||
|
||
export const GenericListContent = <P extends WidgetProps<MuiWidgetBinding>>( | ||
{ | ||
storeKeys, schemaKeys, ownKey, schema, listSize, onChange, | ||
showValidity, valid, errors, required, level, widgets, | ||
ComponentItemMore, ComponentItemPos, | ||
ComponentItem, ComponentFooter, | ||
btnAddShowLabel, btnAddStyle, | ||
btnSize: btnSizeProp, | ||
btnVariant: btnVariantProp, | ||
btnColor: btnColorProp, | ||
listSpacing = 3, | ||
}: P & WithOnChange & GenericListContentProps, | ||
): React.ReactElement => { | ||
const btnSize = (schema.getIn(['view', 'btnSize']) || btnSizeProp || 'small') as ListButtonOverwrites['btnSize'] | ||
const deleteBtnSize = (schema.getIn(['view', 'deleteBtnSize']) || btnSizeProp || 'small') as ListButtonOverwrites['btnSize'] | ||
const btnVariant = (schema.getIn(['view', 'btnVariant']) || btnVariantProp || undefined) as ListButtonOverwrites['btnVariant'] | ||
const btnColor = (schema.getIn(['view', 'btnColor']) || btnColorProp || undefined) as ListButtonOverwrites['btnColor'] | ||
const notSortable = schema.get('notSortable') as boolean | undefined | ||
const notAddable = schema.get('notAddable') as boolean | undefined | ||
const notDeletable = schema.get('notDeletable') as boolean | undefined | ||
const InfoRenderer = widgets?.InfoRenderer | ||
|
||
const info = InfoRenderer && schema?.get('info') ? | ||
<InfoRenderer | ||
schema={schema} variant={'preview'} openAs={'embed'} | ||
storeKeys={storeKeys} valid={valid} errors={errors} | ||
/> : null | ||
|
||
return <FormControl required={required} error={!valid && showValidity} component="fieldset" style={{width: '100%'}}> | ||
{!schema.getIn(['view', 'hideTitle']) ? | ||
<Box mb={1}> | ||
<Box mb={1}> | ||
<FormLabel component="legend"> | ||
<TransTitle schema={schema} storeKeys={storeKeys} ownKey={ownKey}/> | ||
</FormLabel> | ||
</Box> | ||
|
||
{info} | ||
</Box> : null} | ||
|
||
{schema.getIn(['view', 'hideTitle']) ? | ||
<Box mb={1}>{info}</Box> : null} | ||
|
||
<Grid container spacing={listSpacing}> | ||
{Array(listSize).fill(null).map((_val, i) => | ||
<ComponentItem | ||
key={i} index={i} listSize={listSize} | ||
storeKeys={storeKeys} | ||
schemaKeys={schemaKeys} | ||
schema={schema} onChange={onChange} | ||
level={level} | ||
listRequired={required} | ||
btnSize={deleteBtnSize} | ||
notSortable={notSortable} | ||
notDeletable={notDeletable} | ||
showValidity={showValidity} | ||
ComponentPos={ComponentItemPos} | ||
ComponentMore={ComponentItemMore} | ||
/>, | ||
)} | ||
</Grid> | ||
|
||
{ComponentFooter ? | ||
<ComponentFooter | ||
schema={schema} | ||
required={required} | ||
storeKeys={storeKeys} | ||
onChange={onChange} | ||
errors={errors} | ||
showValidity={showValidity} | ||
btnSize={btnSize} | ||
btnAddShowLabel={btnAddShowLabel} | ||
btnAddStyle={btnAddStyle} | ||
btnColor={btnColor} | ||
btnVariant={btnVariant} | ||
notAddable={notAddable} | ||
notSortable={notSortable} | ||
notDeletable={notDeletable} | ||
/> : null} | ||
</FormControl> | ||
} |
Oops, something went wrong.