pr comments

This commit is contained in:
Bruno Crosier
2024-09-09 18:42:19 +01:00
parent ef6fe9ca9a
commit 37e181a38d
6 changed files with 98 additions and 25 deletions

View File

@@ -267,7 +267,7 @@ type Admin = {
position?: 'sidebar'
readOnly?: boolean
style?: CSSProperties
width?: `${number}${'%' | 'ch' | 'em' | 'pc' | 'pt' | 'px' | 'rem' | 'vh' | 'vmax' | 'vmin' | 'vw'}`
width?: CSSProperties['width']
}
export type AdminClient = {
@@ -299,8 +299,8 @@ export type AdminClient = {
hidden?: boolean
position?: 'sidebar'
readOnly?: boolean
style?: CSSProperties
width?: string
style?: { '--field-width'?: CSSProperties['width'] } & CSSProperties
width?: CSSProperties['width']
}
export type Labels = {
@@ -805,7 +805,7 @@ export type UIField = {
*/
disableListColumn?: boolean
position?: string
width?: string
width?: CSSProperties['width']
}
/** Extension point to add your custom data. Server only. */
custom?: Record<string, any>

View File

@@ -4,22 +4,19 @@
.row__fields {
display: flex;
flex-wrap: wrap;
row-gap: calc(var(--base) * 0.8);
> * {
flex: 0 1 var(--field-width);
--field-width: 100%;
}
// If there is more than one child, add a gap.
// We ned this because if you use `flex-wrap: wrap` and `gap`
// and only have one child, the gap gets applied regardless
// meaning the child doesn't take up the full width.
// If there is more than one child, add inline-margins to space them out.
&:has(> *:nth-child(2)) {
gap: calc(var(--base) * 0.5);
margin-inline-end: calc(var(--base) * -0.5); // add negative margin to counteract the gap.
margin-inline: calc(var(--base) / -4); // add negative margin to counteract the gap.
> * {
flex: 0 1 calc(var(--field-width) - var(--base) * 0.5);
margin-inline: calc(var(--base) / 4);
}
}
}

View File

@@ -57,8 +57,9 @@ export const RenderField: React.FC<Props> = ({
fieldComponentProps.readOnly = fieldComponentProps?.field?.admin?.readOnly
// if parent field is `readOnly: true`, but this field is `readOnly: false`, the field should still be editable
if (readOnlyFromContext && fieldComponentProps.readOnly !== false)
if (readOnlyFromContext && fieldComponentProps.readOnly !== false) {
fieldComponentProps.readOnly = true
}
// if the user does not have access control to begin with, force it to be read-only
if (permissions?.[operation]?.permission === false) {
@@ -85,18 +86,6 @@ export const RenderField: React.FC<Props> = ({
/>
)
} else {
if ('fields' in fieldComponentProps.field && Array.isArray(fieldComponentProps.field.fields)) {
for (const field of fieldComponentProps.field.fields) {
if (field.admin?.width) {
field.admin.style = {
...field.admin.style,
'--field-width': field.admin.width,
width: undefined, // avoid needlessly adding this to the element's style attribute
} as unknown as { '--field-width': string } & React.CSSProperties
}
}
}
RenderedField = (
<RenderComponent
Component={fieldComponents?.[fieldComponentProps?.field?.type]}

View File

@@ -115,6 +115,22 @@ export const createClientField = ({
const serverProps = { serverProps: { field: incomingField } }
if ('admin' in incomingField && 'width' in incomingField.admin) {
clientField.admin.style = {
...clientField.admin.style,
'--field-width': clientField.admin.width,
width: undefined, // avoid needlessly adding this to the element's style attribute
}
} else {
if (!(clientField.admin instanceof Object)) {
clientField.admin = {}
}
if (!(clientField.admin.style instanceof Object)) {
clientField.admin.style = {}
}
clientField.admin.style.flex = '1 1 auto'
}
switch (incomingField.type) {
case 'array':
case 'group':
@@ -521,7 +537,7 @@ export const createClientFields = ({
})
if (newField) {
newClientFields.push({ ...newField })
newClientFields.push(newField)
}
}

View File

@@ -106,6 +106,37 @@ const RowFields: CollectionConfig = {
},
],
},
{
type: 'row',
fields: [
{
label: 'Explicit 20% width within a row (A)',
type: 'text',
name: '20_percent_width_within_row_a',
admin: {
width: '20%',
},
},
{
label: 'No set width within a row (B)',
type: 'text',
name: 'no_set_width_within_row_b',
},
{
label: 'No set width within a row (C)',
type: 'text',
name: 'no_set_width_within_row_c',
},
{
label: 'Explicit 20% width within a row (D)',
type: 'text',
name: '20_percent_width_within_row_d',
admin: {
width: '20%',
},
},
],
},
],
}

View File

@@ -400,15 +400,40 @@ describe('fields', () => {
'.collapsible-field:has(#field-field_within_collapsible_a)',
)
const field_20_percent_width_within_row_a = page.locator(
'.field-type.text:has(input#field-20_percent_width_within_row_a)',
)
const field_no_set_width_within_row_b = page.locator(
'.field-type.text:has(input#field-no_set_width_within_row_b)',
)
const field_no_set_width_within_row_c = page.locator(
'.field-type.text:has(input#field-no_set_width_within_row_c)',
)
const field_20_percent_width_within_row_d = page.locator(
'.field-type.text:has(input#field-20_percent_width_within_row_a)',
)
await expect(field_30_percent).toBeVisible()
await expect(field_60_percent).toBeVisible()
await expect(field_20_percent).toBeVisible()
await expect(collapsible_30_percent).toBeVisible()
await expect(field_20_percent_width_within_row_a).toBeVisible()
await expect(field_no_set_width_within_row_b).toBeVisible()
await expect(field_no_set_width_within_row_c).toBeVisible()
await expect(field_20_percent_width_within_row_d).toBeVisible()
const field_30_boundingBox = await field_30_percent.boundingBox()
const field_60_boundingBox = await field_60_percent.boundingBox()
const field_20_boundingBox = await field_20_percent.boundingBox()
const collapsible_30_boundingBox = await collapsible_30_percent.boundingBox()
const field_20_percent_width_within_row_a_box =
await field_20_percent_width_within_row_a.boundingBox()
const field_no_set_width_within_row_b_box =
await field_no_set_width_within_row_b.boundingBox()
const field_no_set_width_within_row_c_box =
await field_no_set_width_within_row_c.boundingBox()
const field_20_percent_width_within_row_d_box =
await field_20_percent_width_within_row_d.boundingBox()
await expect(() => {
expect(field_30_boundingBox.y).toEqual(field_60_boundingBox.y)
@@ -416,6 +441,21 @@ describe('fields', () => {
expect(field_30_boundingBox.y).not.toEqual(field_20_boundingBox.y)
expect(field_30_boundingBox.height).toEqual(field_60_boundingBox.height)
expect(collapsible_30_boundingBox.width).toEqual(field_30_boundingBox.width)
expect(field_20_percent_width_within_row_a_box.y).toEqual(
field_no_set_width_within_row_b_box.y,
)
expect(field_no_set_width_within_row_b_box.y).toEqual(field_no_set_width_within_row_c_box.y)
expect(field_no_set_width_within_row_c_box.y).toEqual(
field_20_percent_width_within_row_d_box.y,
)
expect(field_20_percent_width_within_row_a_box.width).toEqual(
field_20_percent_width_within_row_d_box.width,
)
expect(field_no_set_width_within_row_b_box.width).toEqual(
field_no_set_width_within_row_c_box.width,
)
}).toPass()
})