| 1 |
import React from 'react' |
| 2 |
import { __ } from '@wordpress/i18n' |
| 3 |
import classnames from 'classnames' |
| 4 |
import type { DemoField, DemoRepeater, DemoSection } from './types' |
| 5 |
|
| 6 |
/** |
| 7 |
* Every control is presented in its native form but held read-only — the |
| 8 |
* walkthrough supplies the values, so nothing here accepts input. |
| 9 |
*/ |
| 10 |
const ReadOnlyControl: React.FC<{ field: DemoField, id: string }> = ({ field, id }) => { |
| 11 |
switch (field.type) { |
| 12 |
case 'textarea': |
| 13 |
return <textarea |
| 14 |
id={id} |
| 15 |
aria-label={field.label} |
| 16 |
className="widefat" |
| 17 |
rows={5} |
| 18 |
readOnly |
| 19 |
value={field.value} |
| 20 |
/> |
| 21 |
|
| 22 |
case 'select': |
| 23 |
return ( |
| 24 |
<select id={id} aria-label={field.label} disabled value={field.value}> |
| 25 |
<option value={field.value}>{field.value}</option> |
| 26 |
</select> |
| 27 |
) |
| 28 |
|
| 29 |
default: |
| 30 |
return <input type="text" id={id} aria-label={field.label} readOnly value={field.value} /> |
| 31 |
} |
| 32 |
} |
| 33 |
|
| 34 |
const FormField: React.FC<{ field: DemoField }> = ({ field }) => |
| 35 |
<div className="blueprint-form-field"> |
| 36 |
<label htmlFor={field.name}> |
| 37 |
{field.label} {field.required && <span className="required">*</span>} |
| 38 |
</label> |
| 39 |
|
| 40 |
<ReadOnlyControl field={field} id={field.name} /> |
| 41 |
|
| 42 |
{field.description && <p className="description">{field.description}</p>} |
| 43 |
</div> |
| 44 |
|
| 45 |
const FieldRepeater: React.FC<{ repeater: DemoRepeater }> = ({ repeater }) => |
| 46 |
<div className="blueprint-form-field blueprint-form-repeater"> |
| 47 |
<label htmlFor={`${repeater.columns[0].name}-0`}>{repeater.label}</label> |
| 48 |
|
| 49 |
<div className="blueprint-form-repeater"> |
| 50 |
{repeater.rows.map((row, rowIndex) => |
| 51 |
<div key={row.id} className="blueprint-form-repeater__row"> |
| 52 |
{repeater.columns.map((column, columnIndex) => { |
| 53 |
const id = `${column.name}-${rowIndex}` |
| 54 |
|
| 55 |
return ( |
| 56 |
<div key={column.name} className="blueprint-form-field blueprint-form-repeater__cell"> |
| 57 |
<label htmlFor={id}>{column.label}</label> |
| 58 |
<ReadOnlyControl field={{ ...column, value: row.values[columnIndex] }} id={id} /> |
| 59 |
{column.description && <p className="description">{column.description}</p>} |
| 60 |
</div> |
| 61 |
) |
| 62 |
})} |
| 63 |
|
| 64 |
<div className="blueprint-form-repeater__actions"> |
| 65 |
<button type="button" className="button button-secondary button-small" disabled> |
| 66 |
{__('Remove', 'code-snippets')} |
| 67 |
</button> |
| 68 |
</div> |
| 69 |
</div>)} |
| 70 |
|
| 71 |
<button type="button" className="button button-secondary blueprint-form-repeater__add" disabled> |
| 72 |
{repeater.addLabel} |
| 73 |
</button> |
| 74 |
</div> |
| 75 |
</div> |
| 76 |
|
| 77 |
interface BlueprintFormPanelProps { |
| 78 |
section: DemoSection |
| 79 |
isFading: boolean |
| 80 |
} |
| 81 |
|
| 82 |
export const BlueprintFormPanel: React.FC<BlueprintFormPanelProps> = ({ section, isFading }) => |
| 83 |
<div className={classnames('blueprint-form-content', { 'is-fading': isFading })}> |
| 84 |
<h3>{section.title}</h3> |
| 85 |
|
| 86 |
{section.description && <p className="blueprint-form-section-description">{section.description}</p>} |
| 87 |
|
| 88 |
<div className="blueprint-form-fields"> |
| 89 |
{section.fields.map(field => <FormField key={field.name} field={field} />)} |
| 90 |
{section.repeater && <FieldRepeater repeater={section.repeater} />} |
| 91 |
</div> |
| 92 |
</div> |
| 93 |
|