@byline/ui 2.5.2 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dnd/draggable-sortable/demo/draggable-list-demo.js +1 -1
- package/dist/react.d.ts +18 -54
- package/dist/react.js +0 -35
- package/dist/uikit.d.ts +1 -0
- package/dist/uikit.js +1 -0
- package/package.json +2 -8
- package/src/dnd/draggable-sortable/demo/draggable-list-demo.tsx +1 -1
- package/src/react.ts +20 -68
- package/src/uikit.ts +1 -0
- package/dist/admin/group.d.ts +0 -27
- package/dist/admin/group.js +0 -14
- package/dist/admin/group.module.js +0 -6
- package/dist/admin/group_module.css +0 -19
- package/dist/admin/row.d.ts +0 -25
- package/dist/admin/row.js +0 -8
- package/dist/admin/row.module.js +0 -5
- package/dist/admin/row_module.css +0 -18
- package/dist/admin/tabs.d.ts +0 -25
- package/dist/admin/tabs.js +0 -35
- package/dist/admin/tabs.module.js +0 -10
- package/dist/admin/tabs_module.css +0 -68
- package/dist/fields/array/array-field.d.ts +0 -14
- package/dist/fields/array/array-field.js +0 -176
- package/dist/fields/array/array-field.module.js +0 -11
- package/dist/fields/array/array-field_module.css +0 -32
- package/dist/fields/blocks/blocks-field.d.ts +0 -13
- package/dist/fields/blocks/blocks-field.js +0 -244
- package/dist/fields/blocks/blocks-field.module.js +0 -26
- package/dist/fields/blocks/blocks-field_module.css +0 -107
- package/dist/fields/checkbox/checkbox-field.d.ts +0 -16
- package/dist/fields/checkbox/checkbox-field.js +0 -28
- package/dist/fields/checkbox/checkbox-field.module.js +0 -6
- package/dist/fields/checkbox/checkbox-field_module.css +0 -4
- package/dist/fields/column-formatter.d.ts +0 -20
- package/dist/fields/column-formatter.js +0 -15
- package/dist/fields/date-time-formatter.d.ts +0 -16
- package/dist/fields/date-time-formatter.js +0 -8
- package/dist/fields/datetime/datetime-field.d.ts +0 -16
- package/dist/fields/datetime/datetime-field.js +0 -37
- package/dist/fields/datetime/datetime-field.module.js +0 -5
- package/dist/fields/datetime/datetime-field_module.css +0 -4
- package/dist/fields/draggable-context-menu.d.ts +0 -6
- package/dist/fields/draggable-context-menu.js +0 -83
- package/dist/fields/draggable-context-menu.module.js +0 -15
- package/dist/fields/draggable-context-menu_module.css +0 -91
- package/dist/fields/field-helpers.d.ts +0 -26
- package/dist/fields/field-helpers.js +0 -50
- package/dist/fields/field-renderer.d.ts +0 -37
- package/dist/fields/field-renderer.js +0 -206
- package/dist/fields/field-renderer.module.js +0 -8
- package/dist/fields/field-renderer_module.css +0 -11
- package/dist/fields/file/file-field.d.ts +0 -19
- package/dist/fields/file/file-field.js +0 -226
- package/dist/fields/file/file-field.module.js +0 -18
- package/dist/fields/file/file-field_module.css +0 -131
- package/dist/fields/file/file-upload-field.d.ts +0 -21
- package/dist/fields/file/file-upload-field.js +0 -128
- package/dist/fields/file/file-upload-field.module.js +0 -15
- package/dist/fields/file/file-upload-field_module.css +0 -74
- package/dist/fields/group/group-field.d.ts +0 -15
- package/dist/fields/group/group-field.js +0 -59
- package/dist/fields/group/group-field.module.js +0 -9
- package/dist/fields/group/group-field_module.css +0 -27
- package/dist/fields/image/image-field.d.ts +0 -19
- package/dist/fields/image/image-field.js +0 -242
- package/dist/fields/image/image-field.module.js +0 -22
- package/dist/fields/image/image-field_module.css +0 -121
- package/dist/fields/image/image-upload-field.d.ts +0 -21
- package/dist/fields/image/image-upload-field.js +0 -187
- package/dist/fields/image/image-upload-field.module.js +0 -19
- package/dist/fields/image/image-upload-field_module.css +0 -92
- package/dist/fields/local-date-time.d.ts +0 -27
- package/dist/fields/local-date-time.js +0 -49
- package/dist/fields/locale-badge.d.ts +0 -18
- package/dist/fields/locale-badge.js +0 -10
- package/dist/fields/locale-badge.module.js +0 -5
- package/dist/fields/locale-badge_module.css +0 -27
- package/dist/fields/numerical/numerical-field.d.ts +0 -18
- package/dist/fields/numerical/numerical-field.js +0 -74
- package/dist/fields/relation/relation-display.d.ts +0 -40
- package/dist/fields/relation/relation-display.js +0 -58
- package/dist/fields/relation/relation-display.module.js +0 -9
- package/dist/fields/relation/relation-display_module.css +0 -21
- package/dist/fields/relation/relation-field.d.ts +0 -18
- package/dist/fields/relation/relation-field.js +0 -146
- package/dist/fields/relation/relation-field.module.js +0 -13
- package/dist/fields/relation/relation-field_module.css +0 -62
- package/dist/fields/relation/relation-picker.d.ts +0 -49
- package/dist/fields/relation/relation-picker.js +0 -233
- package/dist/fields/relation/relation-picker.module.js +0 -26
- package/dist/fields/relation/relation-picker_module.css +0 -124
- package/dist/fields/relation/relation-summary.d.ts +0 -31
- package/dist/fields/relation/relation-summary.js +0 -50
- package/dist/fields/relation/relation-summary.module.js +0 -11
- package/dist/fields/relation/relation-summary_module.css +0 -37
- package/dist/fields/select/select-field.d.ts +0 -16
- package/dist/fields/select/select-field.js +0 -50
- package/dist/fields/select/select-field.module.js +0 -5
- package/dist/fields/select/select-field_module.css +0 -4
- package/dist/fields/sortable-item.d.ts +0 -15
- package/dist/fields/sortable-item.js +0 -80
- package/dist/fields/sortable-item.module.js +0 -22
- package/dist/fields/sortable-item_module.css +0 -124
- package/dist/fields/text/text-field.d.ts +0 -20
- package/dist/fields/text/text-field.js +0 -104
- package/dist/fields/text/text-field.module.js +0 -6
- package/dist/fields/text/text-field_module.css +0 -5
- package/dist/fields/text-area/text-area-field.d.ts +0 -20
- package/dist/fields/text-area/text-area-field.js +0 -105
- package/dist/fields/text-area/text-area-field.module.js +0 -6
- package/dist/fields/text-area/text-area-field_module.css +0 -5
- package/dist/fields/use-field-change-handler.d.ts +0 -23
- package/dist/fields/use-field-change-handler.js +0 -52
- package/dist/forms/document-actions.d.ts +0 -48
- package/dist/forms/document-actions.js +0 -469
- package/dist/forms/document-actions.module.js +0 -34
- package/dist/forms/document-actions_module.css +0 -118
- package/dist/forms/form-context.d.ts +0 -89
- package/dist/forms/form-context.js +0 -466
- package/dist/forms/form-renderer.d.ts +0 -98
- package/dist/forms/form-renderer.js +0 -591
- package/dist/forms/form-renderer.module.js +0 -46
- package/dist/forms/form-renderer_module.css +0 -245
- package/dist/forms/navigation-guard.d.ts +0 -54
- package/dist/forms/navigation-guard.js +0 -22
- package/dist/forms/path-widget.d.ts +0 -36
- package/dist/forms/path-widget.js +0 -107
- package/dist/forms/path-widget.module.js +0 -8
- package/dist/forms/path-widget_module.css +0 -29
- package/dist/forms/upload-executor.d.ts +0 -57
- package/dist/forms/upload-executor.js +0 -92
- package/dist/services/field-services-context.d.ts +0 -16
- package/dist/services/field-services-context.js +0 -13
- package/dist/services/field-services-types.d.ts +0 -63
- package/dist/services/field-services-types.js +0 -1
- package/dist/widgets/diff-viewer/diff-modal.d.ts +0 -22
- package/dist/widgets/diff-viewer/diff-modal.js +0 -146
- package/dist/widgets/diff-viewer/diff-modal.module.js +0 -14
- package/dist/widgets/diff-viewer/diff-modal_module.css +0 -56
- package/dist/widgets/status-badge/status-badge.d.ts +0 -25
- package/dist/widgets/status-badge/status-badge.js +0 -35
- package/dist/widgets/status-badge/status-badge.module.js +0 -7
- package/dist/widgets/status-badge/status-badge_module.css +0 -20
- package/src/admin/group.module.css +0 -41
- package/src/admin/group.tsx +0 -40
- package/src/admin/row.module.css +0 -32
- package/src/admin/row.tsx +0 -33
- package/src/admin/tabs.module.css +0 -107
- package/src/admin/tabs.tsx +0 -82
- package/src/fields/array/array-field.module.css +0 -48
- package/src/fields/array/array-field.tsx +0 -266
- package/src/fields/blocks/blocks-field.module.css +0 -148
- package/src/fields/blocks/blocks-field.tsx +0 -312
- package/src/fields/checkbox/checkbox-field.module.css +0 -4
- package/src/fields/checkbox/checkbox-field.tsx +0 -54
- package/src/fields/column-formatter.tsx +0 -31
- package/src/fields/date-time-formatter.tsx +0 -22
- package/src/fields/datetime/datetime-field.module.css +0 -13
- package/src/fields/datetime/datetime-field.tsx +0 -54
- package/src/fields/draggable-context-menu.module.css +0 -127
- package/src/fields/draggable-context-menu.tsx +0 -85
- package/src/fields/field-helpers.ts +0 -69
- package/src/fields/field-renderer.module.css +0 -22
- package/src/fields/field-renderer.tsx +0 -288
- package/src/fields/file/file-field.module.css +0 -153
- package/src/fields/file/file-field.tsx +0 -271
- package/src/fields/file/file-upload-field.module.css +0 -101
- package/src/fields/file/file-upload-field.tsx +0 -183
- package/src/fields/group/group-field.module.css +0 -43
- package/src/fields/group/group-field.tsx +0 -84
- package/src/fields/image/image-field.module.css +0 -155
- package/src/fields/image/image-field.tsx +0 -291
- package/src/fields/image/image-upload-field.module.css +0 -123
- package/src/fields/image/image-upload-field.tsx +0 -270
- package/src/fields/local-date-time.tsx +0 -88
- package/src/fields/locale-badge.module.css +0 -37
- package/src/fields/locale-badge.tsx +0 -32
- package/src/fields/numerical/numerical-field.tsx +0 -114
- package/src/fields/relation/relation-display.module.css +0 -36
- package/src/fields/relation/relation-display.tsx +0 -130
- package/src/fields/relation/relation-field.module.css +0 -83
- package/src/fields/relation/relation-field.tsx +0 -206
- package/src/fields/relation/relation-picker.module.css +0 -168
- package/src/fields/relation/relation-picker.tsx +0 -325
- package/src/fields/relation/relation-summary.module.css +0 -55
- package/src/fields/relation/relation-summary.tsx +0 -123
- package/src/fields/select/select-field.module.css +0 -13
- package/src/fields/select/select-field.tsx +0 -61
- package/src/fields/sortable-item.module.css +0 -167
- package/src/fields/sortable-item.tsx +0 -101
- package/src/fields/text/text-field.module.css +0 -13
- package/src/fields/text/text-field.tsx +0 -146
- package/src/fields/text-area/text-area-field.module.css +0 -13
- package/src/fields/text-area/text-area-field.tsx +0 -147
- package/src/fields/use-field-change-handler.ts +0 -112
- package/src/forms/document-actions.module.css +0 -160
- package/src/forms/document-actions.tsx +0 -487
- package/src/forms/form-context.tsx +0 -704
- package/src/forms/form-renderer.module.css +0 -321
- package/src/forms/form-renderer.tsx +0 -888
- package/src/forms/navigation-guard.tsx +0 -98
- package/src/forms/path-widget.module.css +0 -41
- package/src/forms/path-widget.test.tsx +0 -217
- package/src/forms/path-widget.tsx +0 -181
- package/src/forms/upload-executor.ts +0 -190
- package/src/services/field-services-context.tsx +0 -35
- package/src/services/field-services-types.ts +0 -68
- package/src/widgets/diff-viewer/diff-modal.module.css +0 -79
- package/src/widgets/diff-viewer/diff-modal.tsx +0 -184
- package/src/widgets/status-badge/status-badge.module.css +0 -31
- package/src/widgets/status-badge/status-badge.tsx +0 -69
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* This Source Code is subject to the terms of the Mozilla Public
|
|
5
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
6
|
-
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
7
|
-
*
|
|
8
|
-
* Copyright (c) Infonomic Company Limited
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import cx from 'classnames'
|
|
12
|
-
|
|
13
|
-
import {
|
|
14
|
-
DeleteIcon,
|
|
15
|
-
Dropdown as DropdownMenu,
|
|
16
|
-
EllipsisIcon,
|
|
17
|
-
IconButton,
|
|
18
|
-
PlusIcon,
|
|
19
|
-
} from '../uikit.js'
|
|
20
|
-
import styles from './draggable-context-menu.module.css'
|
|
21
|
-
|
|
22
|
-
interface DraggableContextMenuProps {
|
|
23
|
-
onAddBelow?: () => void
|
|
24
|
-
onRemove?: () => void
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function DraggableContextMenu({
|
|
28
|
-
onAddBelow,
|
|
29
|
-
onRemove,
|
|
30
|
-
}: DraggableContextMenuProps): React.JSX.Element {
|
|
31
|
-
const itemClass = cx('byline-draggable-menu-item', styles.item)
|
|
32
|
-
const rowClass = cx('byline-draggable-menu-row', styles.row)
|
|
33
|
-
const iconSlotClass = cx('byline-draggable-menu-icon-slot', styles['icon-slot'])
|
|
34
|
-
const labelClass = cx('byline-draggable-menu-label', styles.label)
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<DropdownMenu.Root modal={false}>
|
|
38
|
-
<DropdownMenu.Trigger render={<IconButton variant="text" size="sm" />}>
|
|
39
|
-
<EllipsisIcon width="16px" height="16px" />
|
|
40
|
-
</DropdownMenu.Trigger>
|
|
41
|
-
|
|
42
|
-
<DropdownMenu.Portal>
|
|
43
|
-
<DropdownMenu.Content
|
|
44
|
-
align="end"
|
|
45
|
-
sideOffset={0}
|
|
46
|
-
className={cx('byline-draggable-menu', styles.menu)}
|
|
47
|
-
>
|
|
48
|
-
<DropdownMenu.Item className={itemClass} onClick={onAddBelow}>
|
|
49
|
-
<div className={rowClass}>
|
|
50
|
-
<span className={iconSlotClass}>
|
|
51
|
-
<PlusIcon width="18px" height="18px" />
|
|
52
|
-
</span>
|
|
53
|
-
<span className={labelClass}>Add Below</span>
|
|
54
|
-
</div>
|
|
55
|
-
</DropdownMenu.Item>
|
|
56
|
-
<DropdownMenu.Separator
|
|
57
|
-
className={cx('byline-draggable-menu-separator', styles.separator)}
|
|
58
|
-
/>
|
|
59
|
-
<DropdownMenu.Item className={itemClass} onClick={onRemove}>
|
|
60
|
-
<div className={rowClass}>
|
|
61
|
-
<div className={rowClass}>
|
|
62
|
-
<span className={iconSlotClass}>
|
|
63
|
-
<DeleteIcon
|
|
64
|
-
width="18px"
|
|
65
|
-
height="18px"
|
|
66
|
-
svgClassName={cx('byline-draggable-menu-delete-icon', styles['delete-icon'])}
|
|
67
|
-
/>
|
|
68
|
-
</span>
|
|
69
|
-
<span
|
|
70
|
-
className={cx(
|
|
71
|
-
'byline-draggable-menu-label byline-draggable-menu-label-danger',
|
|
72
|
-
styles.label,
|
|
73
|
-
styles['label-danger']
|
|
74
|
-
)}
|
|
75
|
-
>
|
|
76
|
-
Remove
|
|
77
|
-
</span>
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
</DropdownMenu.Item>
|
|
81
|
-
</DropdownMenu.Content>
|
|
82
|
-
</DropdownMenu.Portal>
|
|
83
|
-
</DropdownMenu.Root>
|
|
84
|
-
)
|
|
85
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
-
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
-
*
|
|
6
|
-
* Copyright (c) Infonomic Company Limited
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { Field } from '@byline/core'
|
|
10
|
-
import { resolveFieldDefaultValue } from '@byline/core'
|
|
11
|
-
|
|
12
|
-
export const placeholderStoredFileValue = {
|
|
13
|
-
fileId: crypto.randomUUID(),
|
|
14
|
-
filename: 'placeholder',
|
|
15
|
-
originalFilename: 'placeholder',
|
|
16
|
-
mimeType: 'application/octet-stream',
|
|
17
|
-
fileSize: 0,
|
|
18
|
-
storageProvider: 'placeholder',
|
|
19
|
-
storagePath: 'pending',
|
|
20
|
-
storageUrl: null,
|
|
21
|
-
fileHash: null,
|
|
22
|
-
imageWidth: null,
|
|
23
|
-
imageHeight: null,
|
|
24
|
-
imageFormat: null,
|
|
25
|
-
processingStatus: 'pending',
|
|
26
|
-
thumbnailGenerated: false,
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export const placeholderForField = (f: Field): any => {
|
|
30
|
-
switch (f.type) {
|
|
31
|
-
case 'text':
|
|
32
|
-
case 'textArea':
|
|
33
|
-
return ''
|
|
34
|
-
case 'checkbox':
|
|
35
|
-
return false
|
|
36
|
-
case 'integer':
|
|
37
|
-
return 0
|
|
38
|
-
case 'counter':
|
|
39
|
-
// Allocator-assigned in the lifecycle layer; absent at form-init time.
|
|
40
|
-
return undefined
|
|
41
|
-
case 'richText':
|
|
42
|
-
case 'datetime':
|
|
43
|
-
return undefined
|
|
44
|
-
case 'select':
|
|
45
|
-
return ''
|
|
46
|
-
case 'file':
|
|
47
|
-
case 'image':
|
|
48
|
-
return placeholderStoredFileValue
|
|
49
|
-
default:
|
|
50
|
-
return null
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export const defaultScalarForField = async (
|
|
55
|
-
f: Field,
|
|
56
|
-
getFieldValues: () => Record<string, any>
|
|
57
|
-
): Promise<any> => {
|
|
58
|
-
const schemaDefault = await resolveFieldDefaultValue(f, {
|
|
59
|
-
data: getFieldValues(),
|
|
60
|
-
now: () => new Date(),
|
|
61
|
-
uuid: () => crypto.randomUUID(),
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
if (schemaDefault !== undefined) {
|
|
65
|
-
return schemaDefault
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return placeholderForField(f)
|
|
69
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FieldRenderer — main field-type switch wrapper.
|
|
3
|
-
*
|
|
4
|
-
* Override handles:
|
|
5
|
-
* .byline-field-localized-wrap — wrapper added when a non-self-badging
|
|
6
|
-
* field needs an absolutely-positioned
|
|
7
|
-
* locale badge in the corner
|
|
8
|
-
* .byline-field-localized-badge — the absolutely-positioned badge slot
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
.localized-wrap,
|
|
12
|
-
:global(.byline-field-localized-wrap) {
|
|
13
|
-
position: relative;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.localized-badge,
|
|
17
|
-
:global(.byline-field-localized-badge) {
|
|
18
|
-
position: absolute;
|
|
19
|
-
top: 0;
|
|
20
|
-
right: 0;
|
|
21
|
-
line-height: 1;
|
|
22
|
-
}
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
-
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
-
*
|
|
6
|
-
* Copyright (c) Infonomic Company Limited
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type {
|
|
10
|
-
ArrayField as ArrayFieldType,
|
|
11
|
-
BlocksField as BlocksFieldType,
|
|
12
|
-
Field,
|
|
13
|
-
FieldComponentSlots,
|
|
14
|
-
GroupField as GroupFieldType,
|
|
15
|
-
RichTextEditorComponent,
|
|
16
|
-
} from '@byline/core'
|
|
17
|
-
import { getClientConfig } from '@byline/core'
|
|
18
|
-
import cx from 'classnames'
|
|
19
|
-
|
|
20
|
-
import { ArrayField } from './array/array-field'
|
|
21
|
-
import { BlocksField } from './blocks/blocks-field'
|
|
22
|
-
import { CheckboxField } from './checkbox/checkbox-field'
|
|
23
|
-
import { DateTimeField } from './datetime/datetime-field'
|
|
24
|
-
import styles from './field-renderer.module.css'
|
|
25
|
-
import { FileField } from './file/file-field'
|
|
26
|
-
import { GroupField } from './group/group-field'
|
|
27
|
-
import { ImageField } from './image/image-field'
|
|
28
|
-
import { LocaleBadge } from './locale-badge'
|
|
29
|
-
import { NumericalField } from './numerical/numerical-field'
|
|
30
|
-
import { RelationField } from './relation/relation-field'
|
|
31
|
-
import { SelectField } from './select/select-field'
|
|
32
|
-
import { TextField } from './text/text-field'
|
|
33
|
-
import { TextAreaField } from './text-area/text-area-field'
|
|
34
|
-
import { useFieldChangeHandler } from './use-field-change-handler'
|
|
35
|
-
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
// FieldRenderer — the main field type switch. Delegates to the appropriate
|
|
38
|
-
// field widget based on `field.type`.
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
|
|
41
|
-
interface FieldRendererProps {
|
|
42
|
-
field: Field
|
|
43
|
-
defaultValue?: any
|
|
44
|
-
basePath?: string
|
|
45
|
-
disableSorting?: boolean
|
|
46
|
-
hideLabel?: boolean
|
|
47
|
-
/** Collection path (e.g. `'media'`) forwarded to upload-capable fields. */
|
|
48
|
-
collectionPath?: string
|
|
49
|
-
/**
|
|
50
|
-
* The active content locale (e.g. `'en'`, `'fr'`). When provided and
|
|
51
|
-
* `field.localized === true`, a small locale badge is shown so the editor
|
|
52
|
-
* knows they are working on a localised field in the current language.
|
|
53
|
-
*/
|
|
54
|
-
contentLocale?: string
|
|
55
|
-
/**
|
|
56
|
-
* Optional UI component slot overrides from the admin config.
|
|
57
|
-
* Forwarded to value-field widgets that support custom slots.
|
|
58
|
-
*/
|
|
59
|
-
components?: FieldComponentSlots
|
|
60
|
-
/**
|
|
61
|
-
* Per-field rich-text editor component override from the admin config.
|
|
62
|
-
* Takes precedence over the globally registered
|
|
63
|
-
* `ClientConfig.fields.richText.editor` for this single field.
|
|
64
|
-
* Ignored when `field.type !== 'richText'`.
|
|
65
|
-
*/
|
|
66
|
-
editor?: RichTextEditorComponent
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export const FieldRenderer = ({
|
|
70
|
-
field,
|
|
71
|
-
defaultValue,
|
|
72
|
-
basePath,
|
|
73
|
-
disableSorting,
|
|
74
|
-
hideLabel,
|
|
75
|
-
collectionPath,
|
|
76
|
-
contentLocale,
|
|
77
|
-
components,
|
|
78
|
-
editor,
|
|
79
|
-
}: FieldRendererProps) => {
|
|
80
|
-
const path = basePath ? `${basePath}.${field.name}` : field.name
|
|
81
|
-
const htmlId = path.replace(/[[\].]/g, '-')
|
|
82
|
-
|
|
83
|
-
const handleChange = useFieldChangeHandler(field, path)
|
|
84
|
-
|
|
85
|
-
// When a locale is active and the field is localised, inject a badge into
|
|
86
|
-
// the field label so the editor knows they are editing locale-specific content.
|
|
87
|
-
const isLocalised = (field as any).localized === true
|
|
88
|
-
|
|
89
|
-
const badge =
|
|
90
|
-
isLocalised && contentLocale && !hideLabel ? <LocaleBadge locale={contentLocale} /> : null
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Render the underlying field widget. If the field is localised, we wrap it
|
|
94
|
-
* so we can append the locale badge after the label.
|
|
95
|
-
*/
|
|
96
|
-
const renderField = () => {
|
|
97
|
-
switch (field.type) {
|
|
98
|
-
case 'text':
|
|
99
|
-
return (
|
|
100
|
-
<TextField
|
|
101
|
-
field={hideLabel ? { ...field, label: undefined } : field}
|
|
102
|
-
defaultValue={defaultValue}
|
|
103
|
-
onChange={handleChange}
|
|
104
|
-
path={path}
|
|
105
|
-
id={htmlId}
|
|
106
|
-
locale={isLocalised ? contentLocale : undefined}
|
|
107
|
-
components={components}
|
|
108
|
-
/>
|
|
109
|
-
)
|
|
110
|
-
case 'textArea':
|
|
111
|
-
return (
|
|
112
|
-
<TextAreaField
|
|
113
|
-
field={hideLabel ? { ...field, label: undefined } : field}
|
|
114
|
-
defaultValue={defaultValue}
|
|
115
|
-
onChange={handleChange}
|
|
116
|
-
path={path}
|
|
117
|
-
id={htmlId}
|
|
118
|
-
locale={isLocalised ? contentLocale : undefined}
|
|
119
|
-
components={components}
|
|
120
|
-
/>
|
|
121
|
-
)
|
|
122
|
-
case 'checkbox':
|
|
123
|
-
return (
|
|
124
|
-
<CheckboxField
|
|
125
|
-
field={hideLabel ? { ...field, label: undefined } : field}
|
|
126
|
-
defaultValue={defaultValue}
|
|
127
|
-
onChange={handleChange}
|
|
128
|
-
path={path}
|
|
129
|
-
id={htmlId}
|
|
130
|
-
/>
|
|
131
|
-
)
|
|
132
|
-
case 'select':
|
|
133
|
-
return (
|
|
134
|
-
<SelectField
|
|
135
|
-
field={hideLabel ? { ...field, label: undefined } : field}
|
|
136
|
-
defaultValue={defaultValue}
|
|
137
|
-
onChange={handleChange}
|
|
138
|
-
path={path}
|
|
139
|
-
id={htmlId}
|
|
140
|
-
/>
|
|
141
|
-
)
|
|
142
|
-
case 'richText': {
|
|
143
|
-
// Admin-side per-field override takes precedence over the globally
|
|
144
|
-
// registered editor (`ClientConfig.fields.richText.editor`). The
|
|
145
|
-
// override travels via `FieldAdminConfig.fields.<name>.editor` —
|
|
146
|
-
// see admin-types — so React component references stay out of the
|
|
147
|
-
// schema graph that's loaded by the server bootstrap.
|
|
148
|
-
const RichTextEditor = editor ?? getClientConfig().fields?.richText?.editor
|
|
149
|
-
if (!RichTextEditor) {
|
|
150
|
-
throw new Error(
|
|
151
|
-
'No richText editor registered. Install @byline/richtext-lexical and set ' +
|
|
152
|
-
'`fields.richText.editor` in your admin config.'
|
|
153
|
-
)
|
|
154
|
-
}
|
|
155
|
-
return (
|
|
156
|
-
<RichTextEditor
|
|
157
|
-
field={hideLabel ? { ...field, label: undefined } : field}
|
|
158
|
-
defaultValue={defaultValue}
|
|
159
|
-
onChange={handleChange}
|
|
160
|
-
path={path}
|
|
161
|
-
instanceKey={htmlId}
|
|
162
|
-
locale={isLocalised ? contentLocale : undefined}
|
|
163
|
-
/>
|
|
164
|
-
)
|
|
165
|
-
}
|
|
166
|
-
case 'datetime':
|
|
167
|
-
return (
|
|
168
|
-
<DateTimeField
|
|
169
|
-
field={hideLabel ? { ...field, label: undefined } : field}
|
|
170
|
-
defaultValue={defaultValue}
|
|
171
|
-
onChange={handleChange}
|
|
172
|
-
path={path}
|
|
173
|
-
id={htmlId}
|
|
174
|
-
/>
|
|
175
|
-
)
|
|
176
|
-
case 'integer':
|
|
177
|
-
return (
|
|
178
|
-
<NumericalField
|
|
179
|
-
field={hideLabel ? { ...field, label: undefined } : field}
|
|
180
|
-
defaultValue={defaultValue}
|
|
181
|
-
onChange={handleChange}
|
|
182
|
-
path={path}
|
|
183
|
-
id={htmlId}
|
|
184
|
-
components={components}
|
|
185
|
-
/>
|
|
186
|
-
)
|
|
187
|
-
case 'counter':
|
|
188
|
-
// Counter values are allocator-assigned; force readOnly at the
|
|
189
|
-
// renderer level so the widget is always non-editable regardless
|
|
190
|
-
// of whether the developer set `field.readOnly` explicitly.
|
|
191
|
-
return (
|
|
192
|
-
<NumericalField
|
|
193
|
-
field={
|
|
194
|
-
hideLabel
|
|
195
|
-
? { ...field, label: undefined, readOnly: true }
|
|
196
|
-
: { ...field, readOnly: true }
|
|
197
|
-
}
|
|
198
|
-
defaultValue={defaultValue}
|
|
199
|
-
onChange={handleChange}
|
|
200
|
-
path={path}
|
|
201
|
-
id={htmlId}
|
|
202
|
-
components={components}
|
|
203
|
-
/>
|
|
204
|
-
)
|
|
205
|
-
case 'file':
|
|
206
|
-
return (
|
|
207
|
-
<FileField
|
|
208
|
-
field={hideLabel ? { ...field, label: undefined } : field}
|
|
209
|
-
defaultValue={defaultValue}
|
|
210
|
-
onChange={handleChange}
|
|
211
|
-
path={path}
|
|
212
|
-
collectionPath={collectionPath}
|
|
213
|
-
/>
|
|
214
|
-
)
|
|
215
|
-
case 'image':
|
|
216
|
-
return (
|
|
217
|
-
<ImageField
|
|
218
|
-
field={hideLabel ? { ...field, label: undefined } : field}
|
|
219
|
-
defaultValue={defaultValue}
|
|
220
|
-
onChange={handleChange}
|
|
221
|
-
path={path}
|
|
222
|
-
collectionPath={collectionPath}
|
|
223
|
-
/>
|
|
224
|
-
)
|
|
225
|
-
case 'relation':
|
|
226
|
-
return (
|
|
227
|
-
<RelationField
|
|
228
|
-
field={hideLabel ? { ...field, label: undefined } : field}
|
|
229
|
-
defaultValue={defaultValue}
|
|
230
|
-
onChange={handleChange}
|
|
231
|
-
path={path}
|
|
232
|
-
id={htmlId}
|
|
233
|
-
/>
|
|
234
|
-
)
|
|
235
|
-
case 'group':
|
|
236
|
-
// Render a group field as a fixed-order inline field group.
|
|
237
|
-
return (
|
|
238
|
-
<GroupField
|
|
239
|
-
field={
|
|
240
|
-
hideLabel
|
|
241
|
-
? ({ ...field, label: undefined } as unknown as GroupFieldType)
|
|
242
|
-
: (field as unknown as GroupFieldType)
|
|
243
|
-
}
|
|
244
|
-
defaultValue={defaultValue}
|
|
245
|
-
path={path}
|
|
246
|
-
/>
|
|
247
|
-
)
|
|
248
|
-
case 'blocks':
|
|
249
|
-
if (!field.blocks) return null
|
|
250
|
-
return (
|
|
251
|
-
<BlocksField
|
|
252
|
-
field={field as unknown as BlocksFieldType}
|
|
253
|
-
defaultValue={defaultValue}
|
|
254
|
-
path={path}
|
|
255
|
-
/>
|
|
256
|
-
)
|
|
257
|
-
case 'array':
|
|
258
|
-
if (!field.fields) return null
|
|
259
|
-
return (
|
|
260
|
-
<ArrayField
|
|
261
|
-
field={field as unknown as ArrayFieldType}
|
|
262
|
-
defaultValue={defaultValue}
|
|
263
|
-
path={path}
|
|
264
|
-
disableSorting={disableSorting}
|
|
265
|
-
/>
|
|
266
|
-
)
|
|
267
|
-
default:
|
|
268
|
-
return null
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// text and textArea render the badge inside their own Label row;
|
|
273
|
-
// the outer wrapper is only needed for other field types.
|
|
274
|
-
const selfBadge = field.type === 'text' || field.type === 'textArea' || field.type === 'richText'
|
|
275
|
-
|
|
276
|
-
if (badge && !selfBadge) {
|
|
277
|
-
return (
|
|
278
|
-
<div className={cx('byline-field-localized-wrap', styles['localized-wrap'])}>
|
|
279
|
-
{renderField()}
|
|
280
|
-
<span className={cx('byline-field-localized-badge', styles['localized-badge'])}>
|
|
281
|
-
{badge}
|
|
282
|
-
</span>
|
|
283
|
-
</div>
|
|
284
|
-
)
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return renderField()
|
|
288
|
-
}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FileField — metadata tile + remove/upload affordances for arbitrary file
|
|
3
|
-
* uploads (non-image). Mirrors `image-field.module.css` structurally; the
|
|
4
|
-
* image-only preview / SVG-shape / pending-badge rules are dropped.
|
|
5
|
-
*
|
|
6
|
-
* Override handles:
|
|
7
|
-
* .byline-field-file — wrapper div
|
|
8
|
-
* .byline-field-file-header — label row
|
|
9
|
-
* .byline-field-file-actions — top-right icon-button group (download + remove)
|
|
10
|
-
* .byline-field-file-empty — empty-state hint text
|
|
11
|
-
* .byline-field-file-tile — bordered metadata tile
|
|
12
|
-
* .byline-field-file-uploading — centered overlay shown while uploading
|
|
13
|
-
* .byline-field-file-icon-wrap — left-aligned document-icon wrapper
|
|
14
|
-
* .byline-field-file-icon — the document glyph itself
|
|
15
|
-
* .byline-field-file-pending — yellow "pending upload" pill
|
|
16
|
-
* .byline-field-file-meta — metadata list
|
|
17
|
-
* .byline-field-file-meta-key — metadata field-name span
|
|
18
|
-
* .byline-field-file-meta-pending — yellow text inside pending status
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
.header,
|
|
22
|
-
:global(.byline-field-file-header) {
|
|
23
|
-
display: flex;
|
|
24
|
-
align-items: baseline;
|
|
25
|
-
gap: var(--spacing-8);
|
|
26
|
-
margin-bottom: 0.25rem;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.actions,
|
|
30
|
-
:global(.byline-field-file-actions) {
|
|
31
|
-
position: absolute;
|
|
32
|
-
top: var(--spacing-6);
|
|
33
|
-
right: var(--spacing-6);
|
|
34
|
-
z-index: 1;
|
|
35
|
-
display: flex;
|
|
36
|
-
align-items: center;
|
|
37
|
-
gap: var(--spacing-4);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
:global(.byline-field-file-actions .byline-button) {
|
|
41
|
-
color: var(--gray-900);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
:global(.dark .byline-field-file-actions .byline-button),
|
|
45
|
-
:global([data-theme="dark"] .byline-field-file-actions .byline-button) {
|
|
46
|
-
color: var(--gray-200);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.empty,
|
|
50
|
-
:global(.byline-field-file-empty) {
|
|
51
|
-
color: var(--gray-500);
|
|
52
|
-
font-size: var(--font-size-xs);
|
|
53
|
-
font-style: italic;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.tile,
|
|
57
|
-
:global(.byline-field-file-tile) {
|
|
58
|
-
position: relative;
|
|
59
|
-
display: flex;
|
|
60
|
-
gap: var(--spacing-16);
|
|
61
|
-
margin-top: 0.25rem;
|
|
62
|
-
padding: var(--spacing-8);
|
|
63
|
-
border: var(--border-width-thin) var(--border-style-solid) var(--primary-500);
|
|
64
|
-
border-radius: var(--border-radius-md);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.uploading,
|
|
68
|
-
:global(.byline-field-file-uploading) {
|
|
69
|
-
position: absolute;
|
|
70
|
-
inset: 0;
|
|
71
|
-
z-index: 2;
|
|
72
|
-
display: flex;
|
|
73
|
-
align-items: center;
|
|
74
|
-
justify-content: center;
|
|
75
|
-
background-color: oklch(from var(--gray-950) l c h / 0.5);
|
|
76
|
-
border-radius: var(--border-radius-md);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.icon-wrap,
|
|
80
|
-
:global(.byline-field-file-icon-wrap) {
|
|
81
|
-
position: relative;
|
|
82
|
-
flex-shrink: 0;
|
|
83
|
-
align-self: flex-start;
|
|
84
|
-
display: flex;
|
|
85
|
-
align-items: center;
|
|
86
|
-
justify-content: center;
|
|
87
|
-
width: 4rem;
|
|
88
|
-
height: 4rem;
|
|
89
|
-
border: var(--border-width-thin) var(--border-style-solid) var(--gray-600);
|
|
90
|
-
border-radius: var(--border-radius-sm);
|
|
91
|
-
color: var(--gray-300);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/* Interactive affordance when the wrap is rendered as a link
|
|
95
|
-
(file is stored — clicking opens the asset in a new tab). */
|
|
96
|
-
a.icon-wrap,
|
|
97
|
-
:global(a.byline-field-file-icon-wrap) {
|
|
98
|
-
cursor: pointer;
|
|
99
|
-
text-decoration: none;
|
|
100
|
-
transition:
|
|
101
|
-
border-color 120ms ease,
|
|
102
|
-
color 120ms ease;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
a.icon-wrap:hover,
|
|
106
|
-
:global(a.byline-field-file-icon-wrap):hover {
|
|
107
|
-
border-color: var(--primary-500);
|
|
108
|
-
color: var(--primary-400);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
a.icon-wrap:focus-visible,
|
|
112
|
-
:global(a.byline-field-file-icon-wrap):focus-visible {
|
|
113
|
-
outline: 2px solid var(--primary-500);
|
|
114
|
-
outline-offset: 2px;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.icon,
|
|
118
|
-
:global(.byline-field-file-icon) {
|
|
119
|
-
opacity: 0.85;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
.pending,
|
|
123
|
-
:global(.byline-field-file-pending) {
|
|
124
|
-
position: absolute;
|
|
125
|
-
top: 0.25rem;
|
|
126
|
-
left: 0.25rem;
|
|
127
|
-
padding: 0.125rem 0.375rem;
|
|
128
|
-
background-color: oklch(from var(--yellow-600) l c h / 0.9);
|
|
129
|
-
color: var(--yellow-100);
|
|
130
|
-
font-size: 0.6rem;
|
|
131
|
-
font-weight: var(--font-weight-medium);
|
|
132
|
-
border-radius: var(--border-radius-sm);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
.meta,
|
|
136
|
-
:global(.byline-field-file-meta) {
|
|
137
|
-
display: flex;
|
|
138
|
-
flex-direction: column;
|
|
139
|
-
gap: 0.125rem;
|
|
140
|
-
padding-right: var(--spacing-32);
|
|
141
|
-
color: var(--gray-200);
|
|
142
|
-
font-size: var(--font-size-xs);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
.meta-key,
|
|
146
|
-
:global(.byline-field-file-meta-key) {
|
|
147
|
-
font-weight: var(--font-weight-semibold);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.meta-pending,
|
|
151
|
-
:global(.byline-field-file-meta-pending) {
|
|
152
|
-
color: var(--yellow-400);
|
|
153
|
-
}
|