@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.
Files changed (211) hide show
  1. package/dist/dnd/draggable-sortable/demo/draggable-list-demo.js +1 -1
  2. package/dist/react.d.ts +18 -54
  3. package/dist/react.js +0 -35
  4. package/dist/uikit.d.ts +1 -0
  5. package/dist/uikit.js +1 -0
  6. package/package.json +2 -8
  7. package/src/dnd/draggable-sortable/demo/draggable-list-demo.tsx +1 -1
  8. package/src/react.ts +20 -68
  9. package/src/uikit.ts +1 -0
  10. package/dist/admin/group.d.ts +0 -27
  11. package/dist/admin/group.js +0 -14
  12. package/dist/admin/group.module.js +0 -6
  13. package/dist/admin/group_module.css +0 -19
  14. package/dist/admin/row.d.ts +0 -25
  15. package/dist/admin/row.js +0 -8
  16. package/dist/admin/row.module.js +0 -5
  17. package/dist/admin/row_module.css +0 -18
  18. package/dist/admin/tabs.d.ts +0 -25
  19. package/dist/admin/tabs.js +0 -35
  20. package/dist/admin/tabs.module.js +0 -10
  21. package/dist/admin/tabs_module.css +0 -68
  22. package/dist/fields/array/array-field.d.ts +0 -14
  23. package/dist/fields/array/array-field.js +0 -176
  24. package/dist/fields/array/array-field.module.js +0 -11
  25. package/dist/fields/array/array-field_module.css +0 -32
  26. package/dist/fields/blocks/blocks-field.d.ts +0 -13
  27. package/dist/fields/blocks/blocks-field.js +0 -244
  28. package/dist/fields/blocks/blocks-field.module.js +0 -26
  29. package/dist/fields/blocks/blocks-field_module.css +0 -107
  30. package/dist/fields/checkbox/checkbox-field.d.ts +0 -16
  31. package/dist/fields/checkbox/checkbox-field.js +0 -28
  32. package/dist/fields/checkbox/checkbox-field.module.js +0 -6
  33. package/dist/fields/checkbox/checkbox-field_module.css +0 -4
  34. package/dist/fields/column-formatter.d.ts +0 -20
  35. package/dist/fields/column-formatter.js +0 -15
  36. package/dist/fields/date-time-formatter.d.ts +0 -16
  37. package/dist/fields/date-time-formatter.js +0 -8
  38. package/dist/fields/datetime/datetime-field.d.ts +0 -16
  39. package/dist/fields/datetime/datetime-field.js +0 -37
  40. package/dist/fields/datetime/datetime-field.module.js +0 -5
  41. package/dist/fields/datetime/datetime-field_module.css +0 -4
  42. package/dist/fields/draggable-context-menu.d.ts +0 -6
  43. package/dist/fields/draggable-context-menu.js +0 -83
  44. package/dist/fields/draggable-context-menu.module.js +0 -15
  45. package/dist/fields/draggable-context-menu_module.css +0 -91
  46. package/dist/fields/field-helpers.d.ts +0 -26
  47. package/dist/fields/field-helpers.js +0 -50
  48. package/dist/fields/field-renderer.d.ts +0 -37
  49. package/dist/fields/field-renderer.js +0 -206
  50. package/dist/fields/field-renderer.module.js +0 -8
  51. package/dist/fields/field-renderer_module.css +0 -11
  52. package/dist/fields/file/file-field.d.ts +0 -19
  53. package/dist/fields/file/file-field.js +0 -226
  54. package/dist/fields/file/file-field.module.js +0 -18
  55. package/dist/fields/file/file-field_module.css +0 -131
  56. package/dist/fields/file/file-upload-field.d.ts +0 -21
  57. package/dist/fields/file/file-upload-field.js +0 -128
  58. package/dist/fields/file/file-upload-field.module.js +0 -15
  59. package/dist/fields/file/file-upload-field_module.css +0 -74
  60. package/dist/fields/group/group-field.d.ts +0 -15
  61. package/dist/fields/group/group-field.js +0 -59
  62. package/dist/fields/group/group-field.module.js +0 -9
  63. package/dist/fields/group/group-field_module.css +0 -27
  64. package/dist/fields/image/image-field.d.ts +0 -19
  65. package/dist/fields/image/image-field.js +0 -242
  66. package/dist/fields/image/image-field.module.js +0 -22
  67. package/dist/fields/image/image-field_module.css +0 -121
  68. package/dist/fields/image/image-upload-field.d.ts +0 -21
  69. package/dist/fields/image/image-upload-field.js +0 -187
  70. package/dist/fields/image/image-upload-field.module.js +0 -19
  71. package/dist/fields/image/image-upload-field_module.css +0 -92
  72. package/dist/fields/local-date-time.d.ts +0 -27
  73. package/dist/fields/local-date-time.js +0 -49
  74. package/dist/fields/locale-badge.d.ts +0 -18
  75. package/dist/fields/locale-badge.js +0 -10
  76. package/dist/fields/locale-badge.module.js +0 -5
  77. package/dist/fields/locale-badge_module.css +0 -27
  78. package/dist/fields/numerical/numerical-field.d.ts +0 -18
  79. package/dist/fields/numerical/numerical-field.js +0 -74
  80. package/dist/fields/relation/relation-display.d.ts +0 -40
  81. package/dist/fields/relation/relation-display.js +0 -58
  82. package/dist/fields/relation/relation-display.module.js +0 -9
  83. package/dist/fields/relation/relation-display_module.css +0 -21
  84. package/dist/fields/relation/relation-field.d.ts +0 -18
  85. package/dist/fields/relation/relation-field.js +0 -146
  86. package/dist/fields/relation/relation-field.module.js +0 -13
  87. package/dist/fields/relation/relation-field_module.css +0 -62
  88. package/dist/fields/relation/relation-picker.d.ts +0 -49
  89. package/dist/fields/relation/relation-picker.js +0 -233
  90. package/dist/fields/relation/relation-picker.module.js +0 -26
  91. package/dist/fields/relation/relation-picker_module.css +0 -124
  92. package/dist/fields/relation/relation-summary.d.ts +0 -31
  93. package/dist/fields/relation/relation-summary.js +0 -50
  94. package/dist/fields/relation/relation-summary.module.js +0 -11
  95. package/dist/fields/relation/relation-summary_module.css +0 -37
  96. package/dist/fields/select/select-field.d.ts +0 -16
  97. package/dist/fields/select/select-field.js +0 -50
  98. package/dist/fields/select/select-field.module.js +0 -5
  99. package/dist/fields/select/select-field_module.css +0 -4
  100. package/dist/fields/sortable-item.d.ts +0 -15
  101. package/dist/fields/sortable-item.js +0 -80
  102. package/dist/fields/sortable-item.module.js +0 -22
  103. package/dist/fields/sortable-item_module.css +0 -124
  104. package/dist/fields/text/text-field.d.ts +0 -20
  105. package/dist/fields/text/text-field.js +0 -104
  106. package/dist/fields/text/text-field.module.js +0 -6
  107. package/dist/fields/text/text-field_module.css +0 -5
  108. package/dist/fields/text-area/text-area-field.d.ts +0 -20
  109. package/dist/fields/text-area/text-area-field.js +0 -105
  110. package/dist/fields/text-area/text-area-field.module.js +0 -6
  111. package/dist/fields/text-area/text-area-field_module.css +0 -5
  112. package/dist/fields/use-field-change-handler.d.ts +0 -23
  113. package/dist/fields/use-field-change-handler.js +0 -52
  114. package/dist/forms/document-actions.d.ts +0 -48
  115. package/dist/forms/document-actions.js +0 -469
  116. package/dist/forms/document-actions.module.js +0 -34
  117. package/dist/forms/document-actions_module.css +0 -118
  118. package/dist/forms/form-context.d.ts +0 -89
  119. package/dist/forms/form-context.js +0 -466
  120. package/dist/forms/form-renderer.d.ts +0 -98
  121. package/dist/forms/form-renderer.js +0 -591
  122. package/dist/forms/form-renderer.module.js +0 -46
  123. package/dist/forms/form-renderer_module.css +0 -245
  124. package/dist/forms/navigation-guard.d.ts +0 -54
  125. package/dist/forms/navigation-guard.js +0 -22
  126. package/dist/forms/path-widget.d.ts +0 -36
  127. package/dist/forms/path-widget.js +0 -107
  128. package/dist/forms/path-widget.module.js +0 -8
  129. package/dist/forms/path-widget_module.css +0 -29
  130. package/dist/forms/upload-executor.d.ts +0 -57
  131. package/dist/forms/upload-executor.js +0 -92
  132. package/dist/services/field-services-context.d.ts +0 -16
  133. package/dist/services/field-services-context.js +0 -13
  134. package/dist/services/field-services-types.d.ts +0 -63
  135. package/dist/services/field-services-types.js +0 -1
  136. package/dist/widgets/diff-viewer/diff-modal.d.ts +0 -22
  137. package/dist/widgets/diff-viewer/diff-modal.js +0 -146
  138. package/dist/widgets/diff-viewer/diff-modal.module.js +0 -14
  139. package/dist/widgets/diff-viewer/diff-modal_module.css +0 -56
  140. package/dist/widgets/status-badge/status-badge.d.ts +0 -25
  141. package/dist/widgets/status-badge/status-badge.js +0 -35
  142. package/dist/widgets/status-badge/status-badge.module.js +0 -7
  143. package/dist/widgets/status-badge/status-badge_module.css +0 -20
  144. package/src/admin/group.module.css +0 -41
  145. package/src/admin/group.tsx +0 -40
  146. package/src/admin/row.module.css +0 -32
  147. package/src/admin/row.tsx +0 -33
  148. package/src/admin/tabs.module.css +0 -107
  149. package/src/admin/tabs.tsx +0 -82
  150. package/src/fields/array/array-field.module.css +0 -48
  151. package/src/fields/array/array-field.tsx +0 -266
  152. package/src/fields/blocks/blocks-field.module.css +0 -148
  153. package/src/fields/blocks/blocks-field.tsx +0 -312
  154. package/src/fields/checkbox/checkbox-field.module.css +0 -4
  155. package/src/fields/checkbox/checkbox-field.tsx +0 -54
  156. package/src/fields/column-formatter.tsx +0 -31
  157. package/src/fields/date-time-formatter.tsx +0 -22
  158. package/src/fields/datetime/datetime-field.module.css +0 -13
  159. package/src/fields/datetime/datetime-field.tsx +0 -54
  160. package/src/fields/draggable-context-menu.module.css +0 -127
  161. package/src/fields/draggable-context-menu.tsx +0 -85
  162. package/src/fields/field-helpers.ts +0 -69
  163. package/src/fields/field-renderer.module.css +0 -22
  164. package/src/fields/field-renderer.tsx +0 -288
  165. package/src/fields/file/file-field.module.css +0 -153
  166. package/src/fields/file/file-field.tsx +0 -271
  167. package/src/fields/file/file-upload-field.module.css +0 -101
  168. package/src/fields/file/file-upload-field.tsx +0 -183
  169. package/src/fields/group/group-field.module.css +0 -43
  170. package/src/fields/group/group-field.tsx +0 -84
  171. package/src/fields/image/image-field.module.css +0 -155
  172. package/src/fields/image/image-field.tsx +0 -291
  173. package/src/fields/image/image-upload-field.module.css +0 -123
  174. package/src/fields/image/image-upload-field.tsx +0 -270
  175. package/src/fields/local-date-time.tsx +0 -88
  176. package/src/fields/locale-badge.module.css +0 -37
  177. package/src/fields/locale-badge.tsx +0 -32
  178. package/src/fields/numerical/numerical-field.tsx +0 -114
  179. package/src/fields/relation/relation-display.module.css +0 -36
  180. package/src/fields/relation/relation-display.tsx +0 -130
  181. package/src/fields/relation/relation-field.module.css +0 -83
  182. package/src/fields/relation/relation-field.tsx +0 -206
  183. package/src/fields/relation/relation-picker.module.css +0 -168
  184. package/src/fields/relation/relation-picker.tsx +0 -325
  185. package/src/fields/relation/relation-summary.module.css +0 -55
  186. package/src/fields/relation/relation-summary.tsx +0 -123
  187. package/src/fields/select/select-field.module.css +0 -13
  188. package/src/fields/select/select-field.tsx +0 -61
  189. package/src/fields/sortable-item.module.css +0 -167
  190. package/src/fields/sortable-item.tsx +0 -101
  191. package/src/fields/text/text-field.module.css +0 -13
  192. package/src/fields/text/text-field.tsx +0 -146
  193. package/src/fields/text-area/text-area-field.module.css +0 -13
  194. package/src/fields/text-area/text-area-field.tsx +0 -147
  195. package/src/fields/use-field-change-handler.ts +0 -112
  196. package/src/forms/document-actions.module.css +0 -160
  197. package/src/forms/document-actions.tsx +0 -487
  198. package/src/forms/form-context.tsx +0 -704
  199. package/src/forms/form-renderer.module.css +0 -321
  200. package/src/forms/form-renderer.tsx +0 -888
  201. package/src/forms/navigation-guard.tsx +0 -98
  202. package/src/forms/path-widget.module.css +0 -41
  203. package/src/forms/path-widget.test.tsx +0 -217
  204. package/src/forms/path-widget.tsx +0 -181
  205. package/src/forms/upload-executor.ts +0 -190
  206. package/src/services/field-services-context.tsx +0 -35
  207. package/src/services/field-services-types.ts +0 -68
  208. package/src/widgets/diff-viewer/diff-modal.module.css +0 -79
  209. package/src/widgets/diff-viewer/diff-modal.tsx +0 -184
  210. package/src/widgets/status-badge/status-badge.module.css +0 -31
  211. package/src/widgets/status-badge/status-badge.tsx +0 -69
@@ -1,82 +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 { Badge } from '../uikit.js'
14
- import styles from './tabs.module.css'
15
-
16
- export interface AdminTabItem {
17
- name: string
18
- label: string
19
- }
20
-
21
- interface AdminTabsProps {
22
- tabs: AdminTabItem[]
23
- activeTab: string
24
- onChange: (name: string) => void
25
- /** Error counts keyed by tab name — shows a danger badge when > 0. */
26
- errorCounts?: Record<string, number>
27
- className?: string
28
- }
29
-
30
- /**
31
- * Tabs navigation bar for admin form layouts.
32
- *
33
- * Used by FormRenderer when a CollectionAdminConfig declares a `tabs` array.
34
- * Each tab is a simple button with a bottom-border active indicator.
35
- * Inactive tabs show a subtle hover state. Fully dark-mode aware.
36
- *
37
- * Stable override handles: `.byline-admin-tabs`, `.byline-admin-tab`,
38
- * `.byline-admin-tab-active`, `.byline-admin-tab-label`,
39
- * `.byline-admin-tab-badge`.
40
- */
41
- export const AdminTabs = ({
42
- tabs,
43
- activeTab,
44
- onChange,
45
- errorCounts,
46
- className,
47
- }: AdminTabsProps) => {
48
- return (
49
- <div
50
- role="tablist"
51
- aria-label="Form tabs"
52
- className={cx('byline-admin-tabs', styles.tabs, className)}
53
- >
54
- {tabs.map((tab) => {
55
- const isActive = tab.name === activeTab
56
- return (
57
- <button
58
- key={tab.name}
59
- type="button"
60
- role="tab"
61
- aria-selected={isActive}
62
- onClick={() => onChange(tab.name)}
63
- className={cx(
64
- 'byline-admin-tab',
65
- styles.tab,
66
- isActive && ['byline-admin-tab-active', styles['tab-active']]
67
- )}
68
- >
69
- <span className={cx('byline-admin-tab-label', styles.label)}>
70
- {tab.label}
71
- {(errorCounts?.[tab.name] ?? 0) > 0 && (
72
- <Badge intent="danger" className={cx('byline-admin-tab-badge', styles.badge)}>
73
- {errorCounts?.[tab.name]}
74
- </Badge>
75
- )}
76
- </span>
77
- </button>
78
- )
79
- })}
80
- </div>
81
- )
82
- }
@@ -1,48 +0,0 @@
1
- /**
2
- * ArrayField — homogeneous array of child fields with optional D&D.
3
- *
4
- * Override handles:
5
- * .byline-field-array — outer wrapper
6
- * .byline-field-array-title — array label heading
7
- * .byline-field-array-stack — vertical layout for items + add row
8
- * .byline-field-array-card — disable-sorting fallback card per item
9
- * .byline-field-array-group-header — sub-group title above grouped fields
10
- * .byline-field-array-group-fields — vertical stack of fields inside an item
11
- */
12
-
13
- .title,
14
- :global(.byline-field-array-title) {
15
- margin-bottom: 0.25rem;
16
- font-size: 1rem;
17
- font-weight: var(--font-weight-medium);
18
- }
19
-
20
- .stack,
21
- :global(.byline-field-array-stack) {
22
- display: flex;
23
- flex-direction: column;
24
- gap: var(--spacing-16);
25
- }
26
-
27
- .card,
28
- :global(.byline-field-array-card) {
29
- display: flex;
30
- flex-direction: column;
31
- gap: var(--spacing-16);
32
- padding: var(--spacing-16);
33
- border: var(--border-width-thin) dashed var(--gray-600);
34
- border-radius: var(--border-radius-md);
35
- }
36
-
37
- .group-header,
38
- :global(.byline-field-array-group-header) {
39
- font-size: 0.9rem;
40
- font-weight: var(--font-weight-medium);
41
- }
42
-
43
- .group-fields,
44
- :global(.byline-field-array-group-fields) {
45
- display: flex;
46
- flex-direction: column;
47
- gap: var(--spacing-16);
48
- }
@@ -1,266 +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 { useEffect, useState } from 'react'
10
-
11
- import type { ArrayField as ArrayFieldType, Field } from '@byline/core'
12
- import cx from 'classnames'
13
-
14
- import { DraggableSortable, moveItem } from '../../dnd/draggable-sortable'
15
- import { defaultScalarForField } from '../../fields/field-helpers'
16
- import { FieldRenderer } from '../../fields/field-renderer'
17
- import { SortableItem } from '../../fields/sortable-item'
18
- import { useFormContext } from '../../forms/form-context'
19
- import { IconButton, PlusIcon } from '../../uikit.js'
20
- import styles from './array-field.module.css'
21
-
22
- // ---------------------------------------------------------------------------
23
- // ArrayField — renders `type: 'array'` fields. Children are homogeneous:
24
- // either single value fields or a single group definition. Supports D&D.
25
- // ---------------------------------------------------------------------------
26
-
27
- export const ArrayField = ({
28
- field,
29
- defaultValue,
30
- path,
31
- disableSorting = false,
32
- }: {
33
- field: ArrayFieldType
34
- defaultValue: any
35
- path: string
36
- disableSorting?: boolean
37
- }) => {
38
- const { appendPatch, getFieldValue, getFieldValues, setFieldStore } = useFormContext()
39
- const [items, setItems] = useState<{ id: string; data: any }[]>([])
40
-
41
- useEffect(() => {
42
- if (Array.isArray(defaultValue)) {
43
- setItems(
44
- defaultValue.map((item: any) => ({
45
- id:
46
- item && typeof item === 'object' && 'id' in item
47
- ? String((item as { id: string }).id)
48
- : item && typeof item === 'object' && '_id' in item
49
- ? String((item as { _id: string })._id)
50
- : crypto.randomUUID(),
51
- data: item,
52
- }))
53
- )
54
- } else {
55
- setItems([])
56
- }
57
- }, [defaultValue])
58
-
59
- const handleDragEnd = ({
60
- moveFromIndex,
61
- moveToIndex,
62
- }: {
63
- moveFromIndex: number
64
- moveToIndex: number
65
- }) => {
66
- setItems((prev) => moveItem(prev, moveFromIndex, moveToIndex))
67
- const currentArray = (getFieldValue(path) ?? defaultValue) as any[]
68
-
69
- if (Array.isArray(currentArray)) {
70
- const clampedFrom = Math.max(0, Math.min(moveFromIndex, currentArray.length - 1))
71
- const clampedTo = Math.max(0, Math.min(moveToIndex, currentArray.length - 1))
72
- if (clampedFrom === clampedTo) return
73
-
74
- const item = currentArray[clampedFrom]
75
- const itemId =
76
- item && typeof item === 'object' && 'id' in item
77
- ? String((item as { id: string }).id)
78
- : String(clampedFrom)
79
-
80
- appendPatch({
81
- kind: 'array.move',
82
- path: path,
83
- itemId,
84
- toIndex: clampedTo,
85
- })
86
- }
87
- }
88
-
89
- const handleAddItem = async (atIndex?: number) => {
90
- const childFields = field.fields ?? []
91
- if (childFields.length === 0) return
92
-
93
- const newId = crypto.randomUUID()
94
-
95
- // Build a new item with default values for ALL child fields
96
- const newItem: Record<string, any> = {}
97
- for (const childField of childFields) {
98
- if (childField.type === 'group' && childField.fields && childField.fields.length > 0) {
99
- // Group child — build a nested object with defaults for each inner field
100
- const groupObj: Record<string, any> = {}
101
- for (const innerField of childField.fields as Field[]) {
102
- groupObj[innerField.name] = await defaultScalarForField(innerField, getFieldValues)
103
- }
104
- newItem[childField.name] = groupObj
105
- } else {
106
- newItem[childField.name] = await defaultScalarForField(childField, getFieldValues)
107
- }
108
- }
109
-
110
- const currentArray = (getFieldValue(path) ?? defaultValue) as any[]
111
- const insertAt = atIndex != null ? atIndex : currentArray ? currentArray.length : 0
112
-
113
- const newItemWrapper = { id: newId, data: newItem }
114
- setItems((prev) => {
115
- const next = [...prev]
116
- next.splice(insertAt, 0, newItemWrapper)
117
- return next
118
- })
119
-
120
- appendPatch({
121
- kind: 'array.insert',
122
- path: path,
123
- index: insertAt,
124
- item: newItem,
125
- })
126
-
127
- const newArrayValue = currentArray ? [...currentArray] : []
128
- newArrayValue.splice(insertAt, 0, newItem)
129
- setFieldStore(path, newArrayValue)
130
- }
131
-
132
- const handleRemoveItem = (index: number) => {
133
- const currentArray = (getFieldValue(path) ?? defaultValue) as any[]
134
- if (!Array.isArray(currentArray) || index < 0 || index >= currentArray.length) return
135
-
136
- const item = currentArray[index]
137
- const itemId =
138
- item && typeof item === 'object' && 'id' in item
139
- ? String((item as { id: string }).id)
140
- : String(index)
141
-
142
- setItems((prev) => prev.filter((_, i) => i !== index))
143
-
144
- appendPatch({
145
- kind: 'array.remove',
146
- path: path,
147
- itemId,
148
- })
149
-
150
- const newArrayValue = [...currentArray]
151
- newArrayValue.splice(index, 1)
152
- setFieldStore(path, newArrayValue)
153
- }
154
-
155
- const handleInsertBelow = (index: number) => {
156
- void handleAddItem(index + 1)
157
- }
158
-
159
- const renderItem = (itemWrapper: { id: string; data: any }, index: number) => {
160
- const item = itemWrapper.data
161
- const arrayElementPath = `${path}[${index}]`
162
-
163
- if (!item || typeof item !== 'object') return null
164
-
165
- const childFields = field.fields ?? []
166
- if (childFields.length === 0) return null
167
-
168
- // Render ALL child fields defined in the array's field schema
169
- const innerBody = childFields.map((childField) => {
170
- const initial = item[childField.name]
171
-
172
- if (childField.type === 'group' && childField.fields && childField.fields.length > 0) {
173
- // Group child — render its inner fields with the group's sub-object
174
- const groupData = initial && typeof initial === 'object' ? initial : {}
175
- return (
176
- <div
177
- key={childField.name}
178
- className={cx('byline-field-array-group-fields', styles['group-fields'])}
179
- >
180
- {childField.label && (
181
- <h4 className={cx('byline-field-array-group-header', styles['group-header'])}>
182
- {childField.label}
183
- </h4>
184
- )}
185
- {(childField.fields as Field[]).map((innerField) => (
186
- <FieldRenderer
187
- key={innerField.name}
188
- field={innerField}
189
- defaultValue={groupData[innerField.name]}
190
- basePath={`${arrayElementPath}.${childField.name}`}
191
- disableSorting={true}
192
- />
193
- ))}
194
- </div>
195
- )
196
- }
197
-
198
- return (
199
- <FieldRenderer
200
- key={childField.name}
201
- field={childField}
202
- defaultValue={initial}
203
- basePath={arrayElementPath}
204
- disableSorting={true}
205
- />
206
- )
207
- })
208
-
209
- const label = field.label ?? field.name
210
-
211
- if (disableSorting) {
212
- return (
213
- <div key={itemWrapper.id} className={cx('byline-field-array-card', styles.card)}>
214
- <div className={cx('byline-field-array-group-fields', styles['group-fields'])}>
215
- {innerBody}
216
- </div>
217
- </div>
218
- )
219
- }
220
-
221
- return (
222
- <SortableItem
223
- key={itemWrapper.id}
224
- id={itemWrapper.id}
225
- label={label}
226
- onAddBelow={() => handleInsertBelow(index)}
227
- onRemove={() => handleRemoveItem(index)}
228
- >
229
- <div className={cx('byline-field-array-group-fields', styles['group-fields'])}>
230
- {innerBody}
231
- </div>
232
- </SortableItem>
233
- )
234
- }
235
-
236
- return (
237
- <div className={`byline-field-array ${field.name}`}>
238
- {!disableSorting && field.label && (
239
- <h3 className={cx('byline-field-array-title', styles.title)}>{field.label}</h3>
240
- )}
241
- {disableSorting ? (
242
- <div className={cx('byline-field-array-stack', styles.stack)}>
243
- {items.map((item, index) => renderItem(item, index))}
244
- </div>
245
- ) : (
246
- <DraggableSortable
247
- ids={items.map((i) => i.id)}
248
- onDragEnd={handleDragEnd}
249
- className={cx('byline-field-array-stack', styles.stack)}
250
- >
251
- {items.map((item, index) => renderItem(item, index))}
252
- <span>
253
- <IconButton
254
- onClick={() => {
255
- void handleAddItem()
256
- }}
257
- aria-label="Add item"
258
- >
259
- <PlusIcon />
260
- </IconButton>
261
- </span>
262
- </DraggableSortable>
263
- )}
264
- </div>
265
- )
266
- }
@@ -1,148 +0,0 @@
1
- /**
2
- * BlocksField — heterogeneous array picked from a modal of block variants.
3
- *
4
- * Override handles:
5
- * .byline-field-blocks — outer wrapper
6
- * .byline-field-blocks-title — block-list label heading
7
- * .byline-field-blocks-stack — vertical stack of blocks + add row
8
- * .byline-field-blocks-add-row — add-button row at the bottom
9
- * .byline-field-blocks-modal-head — picker modal header
10
- * .byline-field-blocks-modal-title — picker modal title
11
- * .byline-field-blocks-grid — grid of variant cards
12
- * .byline-field-blocks-card — variant card wrapper
13
- * .byline-field-blocks-card-head — card title row
14
- * .byline-field-blocks-card-title — card title text
15
- * .byline-field-blocks-card-index — small numeric index pill
16
- * .byline-field-blocks-card-code — variant blockType code line
17
- * .byline-field-blocks-card-body — variant description text
18
- * .byline-field-blocks-card-cursor — cursor: pointer hint on the modal content
19
- */
20
-
21
- .title,
22
- :global(.byline-field-blocks-title) {
23
- margin-bottom: 0.25rem;
24
- font-size: 1rem;
25
- font-weight: var(--font-weight-medium);
26
- }
27
-
28
- .stack,
29
- :global(.byline-field-blocks-stack) {
30
- display: flex;
31
- flex-direction: column;
32
- gap: var(--spacing-16);
33
- }
34
-
35
- .add-row,
36
- :global(.byline-field-blocks-add-row) {
37
- display: flex;
38
- align-items: center;
39
- gap: var(--spacing-8);
40
- }
41
-
42
- .modal-head,
43
- :global(.byline-field-blocks-modal-head) {
44
- padding-top: 1rem;
45
- margin-bottom: var(--spacing-8);
46
- }
47
-
48
- .modal-title,
49
- :global(.byline-field-blocks-modal-title) {
50
- margin: 0 0 var(--spacing-8) 0;
51
- font-size: var(--font-size-2xl);
52
- }
53
-
54
- .modal-content,
55
- :global(.byline-field-blocks-card-cursor) {
56
- cursor: pointer;
57
- }
58
-
59
- .grid,
60
- :global(.byline-field-blocks-grid) {
61
- display: grid;
62
- grid-template-columns: 1fr;
63
- gap: var(--spacing-16);
64
- }
65
-
66
- @media (min-width: 40rem) {
67
- .grid,
68
- :global(.byline-field-blocks-grid) {
69
- grid-template-columns: repeat(2, 1fr);
70
- }
71
- }
72
-
73
- @media (min-width: 48rem) {
74
- .grid,
75
- :global(.byline-field-blocks-grid) {
76
- grid-template-columns: repeat(3, 1fr);
77
- }
78
- }
79
-
80
- .card,
81
- :global(.byline-field-blocks-card) {
82
- margin-bottom: var(--spacing-8);
83
- }
84
-
85
- .card-head,
86
- :global(.byline-field-blocks-card-head) {
87
- display: flex;
88
- align-items: flex-start;
89
- justify-content: space-between;
90
- gap: var(--spacing-8);
91
- }
92
-
93
- .card-title,
94
- :global(.byline-field-blocks-card-title) {
95
- font-size: 1.3rem;
96
- line-height: var(--line-height-tight);
97
- }
98
-
99
- .card-index,
100
- :global(.byline-field-blocks-card-index) {
101
- flex-shrink: 0;
102
- display: inline-flex;
103
- align-items: center;
104
- justify-content: center;
105
- width: 1.25rem;
106
- height: 1.25rem;
107
- margin-top: 0.125rem;
108
- border: var(--border-width-thin) var(--border-style-solid) var(--gray-100);
109
- border-radius: var(--border-radius-full);
110
- color: var(--gray-400);
111
- font-size: 10px;
112
- font-weight: var(--font-weight-semibold);
113
- font-variant-numeric: tabular-nums;
114
- }
115
-
116
- .card-code,
117
- :global(.byline-field-blocks-card-code) {
118
- display: block;
119
- margin-top: 0;
120
- color: var(--gray-400);
121
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
122
- font-size: 12px;
123
- }
124
-
125
- .card-body,
126
- :global(.byline-field-blocks-card-body) {
127
- color: var(--gray-500);
128
- font-size: var(--font-size-sm);
129
- }
130
-
131
- /* ─── Dark theme variants ───────────────────────────────────── */
132
-
133
- :is([data-theme="dark"], :global(.dark)) {
134
- .card-index,
135
- :global(.byline-field-blocks-card-index) {
136
- border-color: var(--gray-700);
137
- }
138
-
139
- .card-code,
140
- :global(.byline-field-blocks-card-code) {
141
- color: var(--gray-500);
142
- }
143
-
144
- .card-body,
145
- :global(.byline-field-blocks-card-body) {
146
- color: var(--gray-200);
147
- }
148
- }