@byline/ui 2.5.2 → 2.6.1

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 (218) hide show
  1. package/dist/components/shimmer/shimmer.d.ts +13 -1
  2. package/dist/components/shimmer/shimmer.js +29 -20
  3. package/dist/components/shimmer/shimmer_module.css +4 -4
  4. package/dist/dnd/draggable-sortable/demo/draggable-list-demo.js +1 -1
  5. package/dist/react.d.ts +18 -54
  6. package/dist/react.js +0 -35
  7. package/dist/styles/styles.css +3 -0
  8. package/dist/uikit.d.ts +1 -0
  9. package/dist/uikit.js +1 -0
  10. package/package.json +2 -8
  11. package/src/components/shimmer/shimmer.module.css +8 -4
  12. package/src/components/shimmer/shimmer.tsx +34 -9
  13. package/src/dnd/draggable-sortable/demo/draggable-list-demo.tsx +1 -1
  14. package/src/react.ts +20 -68
  15. package/src/styles/functional/surfaces.css +13 -1
  16. package/src/uikit.ts +1 -0
  17. package/dist/admin/group.d.ts +0 -27
  18. package/dist/admin/group.js +0 -14
  19. package/dist/admin/group.module.js +0 -6
  20. package/dist/admin/group_module.css +0 -19
  21. package/dist/admin/row.d.ts +0 -25
  22. package/dist/admin/row.js +0 -8
  23. package/dist/admin/row.module.js +0 -5
  24. package/dist/admin/row_module.css +0 -18
  25. package/dist/admin/tabs.d.ts +0 -25
  26. package/dist/admin/tabs.js +0 -35
  27. package/dist/admin/tabs.module.js +0 -10
  28. package/dist/admin/tabs_module.css +0 -68
  29. package/dist/fields/array/array-field.d.ts +0 -14
  30. package/dist/fields/array/array-field.js +0 -176
  31. package/dist/fields/array/array-field.module.js +0 -11
  32. package/dist/fields/array/array-field_module.css +0 -32
  33. package/dist/fields/blocks/blocks-field.d.ts +0 -13
  34. package/dist/fields/blocks/blocks-field.js +0 -244
  35. package/dist/fields/blocks/blocks-field.module.js +0 -26
  36. package/dist/fields/blocks/blocks-field_module.css +0 -107
  37. package/dist/fields/checkbox/checkbox-field.d.ts +0 -16
  38. package/dist/fields/checkbox/checkbox-field.js +0 -28
  39. package/dist/fields/checkbox/checkbox-field.module.js +0 -6
  40. package/dist/fields/checkbox/checkbox-field_module.css +0 -4
  41. package/dist/fields/column-formatter.d.ts +0 -20
  42. package/dist/fields/column-formatter.js +0 -15
  43. package/dist/fields/date-time-formatter.d.ts +0 -16
  44. package/dist/fields/date-time-formatter.js +0 -8
  45. package/dist/fields/datetime/datetime-field.d.ts +0 -16
  46. package/dist/fields/datetime/datetime-field.js +0 -37
  47. package/dist/fields/datetime/datetime-field.module.js +0 -5
  48. package/dist/fields/datetime/datetime-field_module.css +0 -4
  49. package/dist/fields/draggable-context-menu.d.ts +0 -6
  50. package/dist/fields/draggable-context-menu.js +0 -83
  51. package/dist/fields/draggable-context-menu.module.js +0 -15
  52. package/dist/fields/draggable-context-menu_module.css +0 -91
  53. package/dist/fields/field-helpers.d.ts +0 -26
  54. package/dist/fields/field-helpers.js +0 -50
  55. package/dist/fields/field-renderer.d.ts +0 -37
  56. package/dist/fields/field-renderer.js +0 -206
  57. package/dist/fields/field-renderer.module.js +0 -8
  58. package/dist/fields/field-renderer_module.css +0 -11
  59. package/dist/fields/file/file-field.d.ts +0 -19
  60. package/dist/fields/file/file-field.js +0 -226
  61. package/dist/fields/file/file-field.module.js +0 -18
  62. package/dist/fields/file/file-field_module.css +0 -131
  63. package/dist/fields/file/file-upload-field.d.ts +0 -21
  64. package/dist/fields/file/file-upload-field.js +0 -128
  65. package/dist/fields/file/file-upload-field.module.js +0 -15
  66. package/dist/fields/file/file-upload-field_module.css +0 -74
  67. package/dist/fields/group/group-field.d.ts +0 -15
  68. package/dist/fields/group/group-field.js +0 -59
  69. package/dist/fields/group/group-field.module.js +0 -9
  70. package/dist/fields/group/group-field_module.css +0 -27
  71. package/dist/fields/image/image-field.d.ts +0 -19
  72. package/dist/fields/image/image-field.js +0 -242
  73. package/dist/fields/image/image-field.module.js +0 -22
  74. package/dist/fields/image/image-field_module.css +0 -121
  75. package/dist/fields/image/image-upload-field.d.ts +0 -21
  76. package/dist/fields/image/image-upload-field.js +0 -187
  77. package/dist/fields/image/image-upload-field.module.js +0 -19
  78. package/dist/fields/image/image-upload-field_module.css +0 -92
  79. package/dist/fields/local-date-time.d.ts +0 -27
  80. package/dist/fields/local-date-time.js +0 -49
  81. package/dist/fields/locale-badge.d.ts +0 -18
  82. package/dist/fields/locale-badge.js +0 -10
  83. package/dist/fields/locale-badge.module.js +0 -5
  84. package/dist/fields/locale-badge_module.css +0 -27
  85. package/dist/fields/numerical/numerical-field.d.ts +0 -18
  86. package/dist/fields/numerical/numerical-field.js +0 -74
  87. package/dist/fields/relation/relation-display.d.ts +0 -40
  88. package/dist/fields/relation/relation-display.js +0 -58
  89. package/dist/fields/relation/relation-display.module.js +0 -9
  90. package/dist/fields/relation/relation-display_module.css +0 -21
  91. package/dist/fields/relation/relation-field.d.ts +0 -18
  92. package/dist/fields/relation/relation-field.js +0 -146
  93. package/dist/fields/relation/relation-field.module.js +0 -13
  94. package/dist/fields/relation/relation-field_module.css +0 -62
  95. package/dist/fields/relation/relation-picker.d.ts +0 -49
  96. package/dist/fields/relation/relation-picker.js +0 -233
  97. package/dist/fields/relation/relation-picker.module.js +0 -26
  98. package/dist/fields/relation/relation-picker_module.css +0 -124
  99. package/dist/fields/relation/relation-summary.d.ts +0 -31
  100. package/dist/fields/relation/relation-summary.js +0 -50
  101. package/dist/fields/relation/relation-summary.module.js +0 -11
  102. package/dist/fields/relation/relation-summary_module.css +0 -37
  103. package/dist/fields/select/select-field.d.ts +0 -16
  104. package/dist/fields/select/select-field.js +0 -50
  105. package/dist/fields/select/select-field.module.js +0 -5
  106. package/dist/fields/select/select-field_module.css +0 -4
  107. package/dist/fields/sortable-item.d.ts +0 -15
  108. package/dist/fields/sortable-item.js +0 -80
  109. package/dist/fields/sortable-item.module.js +0 -22
  110. package/dist/fields/sortable-item_module.css +0 -124
  111. package/dist/fields/text/text-field.d.ts +0 -20
  112. package/dist/fields/text/text-field.js +0 -104
  113. package/dist/fields/text/text-field.module.js +0 -6
  114. package/dist/fields/text/text-field_module.css +0 -5
  115. package/dist/fields/text-area/text-area-field.d.ts +0 -20
  116. package/dist/fields/text-area/text-area-field.js +0 -105
  117. package/dist/fields/text-area/text-area-field.module.js +0 -6
  118. package/dist/fields/text-area/text-area-field_module.css +0 -5
  119. package/dist/fields/use-field-change-handler.d.ts +0 -23
  120. package/dist/fields/use-field-change-handler.js +0 -52
  121. package/dist/forms/document-actions.d.ts +0 -48
  122. package/dist/forms/document-actions.js +0 -469
  123. package/dist/forms/document-actions.module.js +0 -34
  124. package/dist/forms/document-actions_module.css +0 -118
  125. package/dist/forms/form-context.d.ts +0 -89
  126. package/dist/forms/form-context.js +0 -466
  127. package/dist/forms/form-renderer.d.ts +0 -98
  128. package/dist/forms/form-renderer.js +0 -591
  129. package/dist/forms/form-renderer.module.js +0 -46
  130. package/dist/forms/form-renderer_module.css +0 -245
  131. package/dist/forms/navigation-guard.d.ts +0 -54
  132. package/dist/forms/navigation-guard.js +0 -22
  133. package/dist/forms/path-widget.d.ts +0 -36
  134. package/dist/forms/path-widget.js +0 -107
  135. package/dist/forms/path-widget.module.js +0 -8
  136. package/dist/forms/path-widget_module.css +0 -29
  137. package/dist/forms/upload-executor.d.ts +0 -57
  138. package/dist/forms/upload-executor.js +0 -92
  139. package/dist/services/field-services-context.d.ts +0 -16
  140. package/dist/services/field-services-context.js +0 -13
  141. package/dist/services/field-services-types.d.ts +0 -63
  142. package/dist/services/field-services-types.js +0 -1
  143. package/dist/widgets/diff-viewer/diff-modal.d.ts +0 -22
  144. package/dist/widgets/diff-viewer/diff-modal.js +0 -146
  145. package/dist/widgets/diff-viewer/diff-modal.module.js +0 -14
  146. package/dist/widgets/diff-viewer/diff-modal_module.css +0 -56
  147. package/dist/widgets/status-badge/status-badge.d.ts +0 -25
  148. package/dist/widgets/status-badge/status-badge.js +0 -35
  149. package/dist/widgets/status-badge/status-badge.module.js +0 -7
  150. package/dist/widgets/status-badge/status-badge_module.css +0 -20
  151. package/src/admin/group.module.css +0 -41
  152. package/src/admin/group.tsx +0 -40
  153. package/src/admin/row.module.css +0 -32
  154. package/src/admin/row.tsx +0 -33
  155. package/src/admin/tabs.module.css +0 -107
  156. package/src/admin/tabs.tsx +0 -82
  157. package/src/fields/array/array-field.module.css +0 -48
  158. package/src/fields/array/array-field.tsx +0 -266
  159. package/src/fields/blocks/blocks-field.module.css +0 -148
  160. package/src/fields/blocks/blocks-field.tsx +0 -312
  161. package/src/fields/checkbox/checkbox-field.module.css +0 -4
  162. package/src/fields/checkbox/checkbox-field.tsx +0 -54
  163. package/src/fields/column-formatter.tsx +0 -31
  164. package/src/fields/date-time-formatter.tsx +0 -22
  165. package/src/fields/datetime/datetime-field.module.css +0 -13
  166. package/src/fields/datetime/datetime-field.tsx +0 -54
  167. package/src/fields/draggable-context-menu.module.css +0 -127
  168. package/src/fields/draggable-context-menu.tsx +0 -85
  169. package/src/fields/field-helpers.ts +0 -69
  170. package/src/fields/field-renderer.module.css +0 -22
  171. package/src/fields/field-renderer.tsx +0 -288
  172. package/src/fields/file/file-field.module.css +0 -153
  173. package/src/fields/file/file-field.tsx +0 -271
  174. package/src/fields/file/file-upload-field.module.css +0 -101
  175. package/src/fields/file/file-upload-field.tsx +0 -183
  176. package/src/fields/group/group-field.module.css +0 -43
  177. package/src/fields/group/group-field.tsx +0 -84
  178. package/src/fields/image/image-field.module.css +0 -155
  179. package/src/fields/image/image-field.tsx +0 -291
  180. package/src/fields/image/image-upload-field.module.css +0 -123
  181. package/src/fields/image/image-upload-field.tsx +0 -270
  182. package/src/fields/local-date-time.tsx +0 -88
  183. package/src/fields/locale-badge.module.css +0 -37
  184. package/src/fields/locale-badge.tsx +0 -32
  185. package/src/fields/numerical/numerical-field.tsx +0 -114
  186. package/src/fields/relation/relation-display.module.css +0 -36
  187. package/src/fields/relation/relation-display.tsx +0 -130
  188. package/src/fields/relation/relation-field.module.css +0 -83
  189. package/src/fields/relation/relation-field.tsx +0 -206
  190. package/src/fields/relation/relation-picker.module.css +0 -168
  191. package/src/fields/relation/relation-picker.tsx +0 -325
  192. package/src/fields/relation/relation-summary.module.css +0 -55
  193. package/src/fields/relation/relation-summary.tsx +0 -123
  194. package/src/fields/select/select-field.module.css +0 -13
  195. package/src/fields/select/select-field.tsx +0 -61
  196. package/src/fields/sortable-item.module.css +0 -167
  197. package/src/fields/sortable-item.tsx +0 -101
  198. package/src/fields/text/text-field.module.css +0 -13
  199. package/src/fields/text/text-field.tsx +0 -146
  200. package/src/fields/text-area/text-area-field.module.css +0 -13
  201. package/src/fields/text-area/text-area-field.tsx +0 -147
  202. package/src/fields/use-field-change-handler.ts +0 -112
  203. package/src/forms/document-actions.module.css +0 -160
  204. package/src/forms/document-actions.tsx +0 -487
  205. package/src/forms/form-context.tsx +0 -704
  206. package/src/forms/form-renderer.module.css +0 -321
  207. package/src/forms/form-renderer.tsx +0 -888
  208. package/src/forms/navigation-guard.tsx +0 -98
  209. package/src/forms/path-widget.module.css +0 -41
  210. package/src/forms/path-widget.test.tsx +0 -217
  211. package/src/forms/path-widget.tsx +0 -181
  212. package/src/forms/upload-executor.ts +0 -190
  213. package/src/services/field-services-context.tsx +0 -35
  214. package/src/services/field-services-types.ts +0 -68
  215. package/src/widgets/diff-viewer/diff-modal.module.css +0 -79
  216. package/src/widgets/diff-viewer/diff-modal.tsx +0 -184
  217. package/src/widgets/status-badge/status-badge.module.css +0 -31
  218. 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
- }