-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ - feat: make AttributeTable editable
- Loading branch information
1 parent
459de79
commit f0b312d
Showing
12 changed files
with
303 additions
and
50 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,23 @@ | ||
.mykn-attributetable { | ||
display: table; | ||
|
||
&__row { | ||
display: table-row; | ||
&__body { | ||
display: grid; | ||
grid-template-columns: auto auto; | ||
column-gap: var(--spacing-h); | ||
} | ||
|
||
&__cell { | ||
display: table-cell; | ||
font-family: var(--typography-font-family-body); | ||
display: flex; | ||
align-items: center; | ||
font-family: var(--typography-font-family-body), sans-serif; | ||
font-size: var(--typography-font-size-body-s); | ||
font-weight: var(--typography-font-weight-normal); | ||
line-height: var(--typography-line-height-body-s); | ||
margin: 0; | ||
|
||
&:not(:last-child) { | ||
padding-right: var(--spacing-h); | ||
} | ||
} | ||
|
||
&__key { | ||
&__cell--key { | ||
font-weight: var(--typography-font-weight-bold); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,192 @@ | ||
import React from "react"; | ||
import React, { useId, useState } from "react"; | ||
|
||
import { | ||
Attribute, | ||
AttributeData, | ||
Field, | ||
LabeledAttributeData, | ||
TypedField, | ||
field2Title, | ||
isPrimitive, | ||
typedFieldByFields, | ||
useIntl, | ||
} from "../../../lib"; | ||
import { Button } from "../../button"; | ||
import { Form, FormControl, FormProps } from "../../form"; | ||
import { Value } from "../value"; | ||
import "./attributetable.scss"; | ||
|
||
export type AttributeTableProps = { | ||
editable?: boolean; | ||
formProps?: FormProps; | ||
object?: AttributeData; | ||
labeledObject?: LabeledAttributeData; | ||
fields?: Array<keyof LabeledAttributeData | keyof AttributeData>; | ||
}; | ||
|
||
export type AttributeTableRowProps = { | ||
object?: AttributeData; | ||
labeledObject?: LabeledAttributeData; | ||
field: keyof LabeledAttributeData | keyof AttributeData; | ||
labelEdit?: string; | ||
labelCancel?: string; | ||
fields?: Field[] | TypedField[]; | ||
}; | ||
|
||
export const AttributeTable: React.FC<AttributeTableProps> = ({ | ||
editable = false, | ||
object = {}, | ||
labeledObject = {}, | ||
fields = Object.keys(object).concat(Object.keys(labeledObject)), | ||
formProps, | ||
labelEdit, | ||
labelCancel, | ||
...props | ||
}) => ( | ||
<div className="mykn-attributetable" {...props}> | ||
{fields.map((field) => ( | ||
}) => { | ||
const intl = useIntl(); | ||
const [isFormOpenState, setIsFormOpenState] = useState(false); | ||
const typedFields = typedFieldByFields(fields, [object]); | ||
|
||
const _labelCancel = labelCancel | ||
? labelCancel | ||
: intl.formatMessage({ | ||
id: "mykn.components.AttributeTable.labelCancel", | ||
description: "mykn.components.AttributeTable: The cancel label", | ||
defaultMessage: "Annuleren", | ||
}); | ||
|
||
const renderTable = () => { | ||
return editable ? ( | ||
<Form | ||
fieldsetClassName="mykn-attributetable__body" | ||
showActions={isFormOpenState} | ||
secondaryActions={[ | ||
{ | ||
children: _labelCancel, | ||
variant: "secondary", | ||
onClick: () => setIsFormOpenState(false), | ||
}, | ||
]} | ||
{...formProps} | ||
> | ||
{renderRows()} | ||
</Form> | ||
) : ( | ||
<div className="mykn-attributetable__body">{renderRows()}</div> | ||
); | ||
}; | ||
|
||
const renderRows = () => | ||
typedFields.map((field) => ( | ||
<AttributeTableRow | ||
key={field} | ||
key={field.name} | ||
editable={editable} | ||
field={field} | ||
isFormOpen={isFormOpenState} | ||
object={object} | ||
labeledObject={labeledObject} | ||
labelEdit={labelEdit} | ||
onClick={() => setIsFormOpenState(true)} | ||
/> | ||
))} | ||
</div> | ||
); | ||
)); | ||
|
||
return ( | ||
<div className="mykn-attributetable" {...props}> | ||
{renderTable()} | ||
</div> | ||
); | ||
}; | ||
|
||
export type AttributeTableRowProps = { | ||
editable?: boolean; | ||
object?: AttributeData; | ||
labeledObject?: LabeledAttributeData; | ||
field: TypedField; | ||
isFormOpen: boolean; | ||
labelEdit?: string; | ||
onClick: React.MouseEventHandler; | ||
}; | ||
|
||
export const AttributeTableRow: React.FC<AttributeTableRowProps> = ({ | ||
editable = false, | ||
field, | ||
isFormOpen, | ||
object = {}, | ||
labeledObject = {}, | ||
field, | ||
labelEdit, | ||
onClick, | ||
}) => { | ||
const fieldInObject = Object.keys(object).includes(field); | ||
let value = fieldInObject ? object[field] : labeledObject[field].value; | ||
const id = useId(); | ||
const intl = useIntl(); | ||
const [isEditingState, setIsEditingState] = useState(false); | ||
const name = field.name; | ||
const fieldInObject = Object.keys(object).includes(name); | ||
const label = fieldInObject ? field2Title(name) : labeledObject[name].label; | ||
const rawValue = fieldInObject ? object[name] : labeledObject[name].value; | ||
const isEditing = isFormOpen && isEditingState; | ||
|
||
if (isPrimitive(value) || value === null) { | ||
value = <Value value={value as Attribute} />; | ||
} | ||
const handleCLick: React.MouseEventHandler = (e) => { | ||
e.preventDefault(); | ||
setIsEditingState(true); | ||
onClick(e); | ||
}; | ||
|
||
const label = fieldInObject ? field2Title(field) : labeledObject[field].label; | ||
const _labelEdit = labelEdit | ||
? labelEdit | ||
: intl.formatMessage( | ||
{ | ||
id: "mykn.components.AttributeTable.labelEdit", | ||
description: | ||
"mykn.components.AttributeTable: The edit value (accessible) label", | ||
defaultMessage: 'Bewerk "{label}"', | ||
}, | ||
{ ...field, label: label || field.name }, | ||
); | ||
|
||
/** | ||
* Renders the value (if not already a React.ReactNode). | ||
*/ | ||
const renderValue = () => { | ||
return editable ? ( | ||
<Button | ||
variant="transparent" | ||
pad={false} | ||
onClick={handleCLick} | ||
aria-label={_labelEdit} | ||
> | ||
{renderDisplayValue()} | ||
</Button> | ||
) : ( | ||
renderDisplayValue() | ||
); | ||
}; | ||
|
||
const renderDisplayValue = () => { | ||
if (isPrimitive(rawValue) || rawValue === null) { | ||
return <Value value={rawValue as Attribute} />; | ||
} | ||
|
||
return rawValue; | ||
}; | ||
|
||
const renderInput = () => { | ||
return ( | ||
<FormControl | ||
id={`${id}_input`} | ||
defaultChecked={ | ||
field.type === "boolean" ? Boolean(rawValue) : undefined | ||
} | ||
name={name} | ||
options={field.options} | ||
type={field.type === "number" ? "number" : undefined} | ||
value={rawValue?.toString()} | ||
hidden={!isEditing} | ||
/> | ||
); | ||
}; | ||
|
||
return ( | ||
<div className="mykn-attributetable__row"> | ||
<div className="mykn-attributetable__cell mykn-attributetable__key"> | ||
{label} | ||
<> | ||
<div className="mykn-attributetable__cell mykn-attributetable__cell--key"> | ||
{isEditing ? <label htmlFor={`${id}_input`}>{label}</label> : label} | ||
</div> | ||
<div className="mykn-attributetable__cell">{value}</div> | ||
</div> | ||
<div className="mykn-attributetable__cell mykn-attributetable__cell--value"> | ||
{(!editable || !isEditing) && renderValue()} | ||
{editable && renderInput()} | ||
</div> | ||
</> | ||
); | ||
}; |
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
Oops, something went wrong.