@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.3381.1.8461b312a9",
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.3381.1.8461b312a9",
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.3381.1.8461b312a9",
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",
@@ -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
- const dialogFormPadding = isInDialog ? 'pb-4' : ''
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 (