@open-mercato/ui 0.6.2-develop.3381.1.8461b312a9 → 0.6.2-develop.3400.2.d948268f50
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/ui",
|
|
3
|
-
"version": "0.6.2-develop.
|
|
3
|
+
"version": "0.6.2-develop.3400.2.d948268f50",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -141,13 +141,13 @@
|
|
|
141
141
|
"remark-gfm": "^4.0.1"
|
|
142
142
|
},
|
|
143
143
|
"peerDependencies": {
|
|
144
|
-
"@open-mercato/shared": "0.6.2-develop.
|
|
144
|
+
"@open-mercato/shared": "0.6.2-develop.3400.2.d948268f50",
|
|
145
145
|
"react": ">=18.0.0",
|
|
146
146
|
"react-dom": ">=18.0.0",
|
|
147
147
|
"react-is": ">=18.0.0"
|
|
148
148
|
},
|
|
149
149
|
"devDependencies": {
|
|
150
|
-
"@open-mercato/shared": "0.6.2-develop.
|
|
150
|
+
"@open-mercato/shared": "0.6.2-develop.3400.2.d948268f50",
|
|
151
151
|
"@testing-library/dom": "^10.4.1",
|
|
152
152
|
"@testing-library/jest-dom": "^6.9.1",
|
|
153
153
|
"@testing-library/react": "^16.3.1",
|
package/src/backend/CrudForm.tsx
CHANGED
|
@@ -117,6 +117,14 @@ const CRUDFORM_EXTENDED_EVENTS_ENABLED = parseBooleanWithDefault(
|
|
|
117
117
|
true,
|
|
118
118
|
)
|
|
119
119
|
|
|
120
|
+
function evaluateFieldVisibility(
|
|
121
|
+
visibleWhen: { field: string; equals: string | number | boolean } | undefined,
|
|
122
|
+
values: Record<string, unknown>,
|
|
123
|
+
): boolean {
|
|
124
|
+
if (!visibleWhen) return true
|
|
125
|
+
return values[visibleWhen.field] === visibleWhen.equals
|
|
126
|
+
}
|
|
127
|
+
|
|
120
128
|
function isFormControlTarget(target: EventTarget | null): boolean {
|
|
121
129
|
if (!target || typeof (target as Element).tagName !== 'string') return false
|
|
122
130
|
const el = target as HTMLElement
|
|
@@ -180,6 +188,11 @@ export type CrudFieldBase = {
|
|
|
180
188
|
placeholder?: string
|
|
181
189
|
description?: React.ReactNode // inline field-level help
|
|
182
190
|
required?: boolean
|
|
191
|
+
/**
|
|
192
|
+
* Simple conditional visibility for base fields.
|
|
193
|
+
* When not satisfied, the field is not rendered and is excluded from blur validation.
|
|
194
|
+
*/
|
|
195
|
+
visibleWhen?: { field: string; equals: string | number | boolean }
|
|
183
196
|
layout?: 'full' | 'half' | 'third'
|
|
184
197
|
disabled?: boolean
|
|
185
198
|
readOnly?: boolean
|
|
@@ -1082,7 +1095,9 @@ export function CrudForm<TValues extends Record<string, unknown>>({
|
|
|
1082
1095
|
const dialogFooterClass = isInDialog
|
|
1083
1096
|
? 'sticky bottom-0 left-0 right-0 z-20 -mx-6 px-6 bg-card border-t border-border/70 py-2 sm:-mx-6 sm:px-6'
|
|
1084
1097
|
: ''
|
|
1085
|
-
|
|
1098
|
+
// When CrudForm renders inside a Dialog, the sticky footer can overlap the last fields.
|
|
1099
|
+
// Give the form enough bottom padding so inputs (esp. Radix Select triggers) remain clickable.
|
|
1100
|
+
const dialogFormPadding = isInDialog ? 'pb-20' : ''
|
|
1086
1101
|
|
|
1087
1102
|
const buildCustomFieldsManageHref = React.useCallback(
|
|
1088
1103
|
(targetEntityId: string | null) => {
|
|
@@ -1545,6 +1560,17 @@ export function CrudForm<TValues extends Record<string, unknown>>({
|
|
|
1545
1560
|
}
|
|
1546
1561
|
}, [values])
|
|
1547
1562
|
|
|
1563
|
+
const hiddenBaseFieldIds = React.useMemo(() => {
|
|
1564
|
+
const hidden = new Set<string>()
|
|
1565
|
+
const recordValues = values as Record<string, unknown>
|
|
1566
|
+
for (const field of fields) {
|
|
1567
|
+
if (!evaluateFieldVisibility(field.visibleWhen, recordValues)) {
|
|
1568
|
+
hidden.add(field.id)
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
return hidden
|
|
1572
|
+
}, [fields, values])
|
|
1573
|
+
|
|
1548
1574
|
const hiddenInjectedFieldIds = React.useMemo(() => {
|
|
1549
1575
|
const hidden = new Set<string>()
|
|
1550
1576
|
for (const definition of injectedFieldDefinitions) {
|
|
@@ -1610,7 +1636,7 @@ export function CrudForm<TValues extends Record<string, unknown>>({
|
|
|
1610
1636
|
if (formReadOnly) return
|
|
1611
1637
|
const field = fieldById.get(fieldId)
|
|
1612
1638
|
if (!field || field.disabled) return
|
|
1613
|
-
if (hiddenInjectedFieldIds.has(fieldId)) return
|
|
1639
|
+
if (hiddenBaseFieldIds.has(fieldId) || hiddenInjectedFieldIds.has(fieldId)) return
|
|
1614
1640
|
|
|
1615
1641
|
const nextValues = sourceValues ?? valuesRef.current
|
|
1616
1642
|
const nextFieldErrors: Record<string, string> = {}
|
|
@@ -1717,6 +1743,7 @@ export function CrudForm<TValues extends Record<string, unknown>>({
|
|
|
1717
1743
|
customEntity,
|
|
1718
1744
|
fieldById,
|
|
1719
1745
|
formReadOnly,
|
|
1746
|
+
hiddenBaseFieldIds,
|
|
1720
1747
|
hiddenInjectedFieldIds,
|
|
1721
1748
|
injectedFieldIdSet,
|
|
1722
1749
|
mapDefsForValidation,
|
|
@@ -2291,7 +2318,7 @@ export function CrudForm<TValues extends Record<string, unknown>>({
|
|
|
2291
2318
|
for (const field of allFields) {
|
|
2292
2319
|
if (!field.required) continue
|
|
2293
2320
|
if (field.disabled) continue
|
|
2294
|
-
if (hiddenInjectedFieldIds.has(field.id)) continue
|
|
2321
|
+
if (hiddenBaseFieldIds.has(field.id) || hiddenInjectedFieldIds.has(field.id)) continue
|
|
2295
2322
|
const v = values[field.id]
|
|
2296
2323
|
const isArray = Array.isArray(v)
|
|
2297
2324
|
const isString = typeof v === 'string'
|
|
@@ -3257,6 +3284,7 @@ export function CrudForm<TValues extends Record<string, unknown>>({
|
|
|
3257
3284
|
) : null}
|
|
3258
3285
|
<div className={grid}>
|
|
3259
3286
|
{allFields.map((f) => {
|
|
3287
|
+
if (hiddenBaseFieldIds.has(f.id) || hiddenInjectedFieldIds.has(f.id)) return null
|
|
3260
3288
|
const layout = f.layout ?? 'full'
|
|
3261
3289
|
const wrapperClassName = usesResponsiveLayout ? resolveLayoutClass(layout) : undefined
|
|
3262
3290
|
return (
|