@asteby/metacore-runtime-react 37.4.0 → 37.5.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.
- package/CHANGELOG.md +12 -0
- package/dist/dialogs/dynamic-record.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.js +15 -0
- package/dist/dynamic-columns.d.ts.map +1 -1
- package/dist/dynamic-columns.js +26 -0
- package/package.json +3 -3
- package/src/dialogs/dynamic-record.tsx +21 -0
- package/src/dynamic-columns.tsx +34 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 37.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 2582a3a: El multi-select declarativo (`field.multiple: true`, ver #881/#883) no se veía en el modal REAL de editar/crear registro (`dialogs/dynamic-record.tsx`, usado por la tabla genérica del host) — nunca se había cableado ahí, solo en `DynamicForm` (dynamic-form.tsx, usado por acciones). Además, `isLineItemsField` trataba CUALQUIER valor array (incluido el `[]` default de un campo `multiple` recién creado) como un documento de line-items y lo renderizaba "Solo lectura". Se agrega el branch de `DynamicMultiSelectField` antes del picker single-value y se excluye `field.multiple` de la heurística de line-items.
|
|
8
|
+
|
|
9
|
+
## 37.5.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 453b82b: Contraparte de lectura de `DynamicMultiSelectField`: una columna `ref` cuyo valor es un array jsonb de ids (campo declarado con `multiple: true` al escribir) ahora se renderiza como una lista de badges resueltos por id (`RelationIdListCell`) en vez de intentar leer el sibling `{value,label}` de una FK simple — antes ese caso caía sin manejar en `RelationCell` y mostraba vacío/roto.
|
|
14
|
+
|
|
3
15
|
## 37.4.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,7 @@ import { useApi } from '../api-context';
|
|
|
26
26
|
import { useBranchCreateGate } from '../branch-create-gate';
|
|
27
27
|
import { toastServerError, extractFieldErrors, localizeFieldIssue, localizeFieldErrorMap } from '../server-error';
|
|
28
28
|
import { DynamicSelectField, OptionLead, OptionThumb } from '../dynamic-select-field';
|
|
29
|
+
import { DynamicMultiSelectField } from '../dynamic-multi-select-field';
|
|
29
30
|
import { DynamicRelations } from '../dynamic-relations';
|
|
30
31
|
import { useOptionsResolver } from '../use-options-resolver';
|
|
31
32
|
import { getFieldRef, getVisibleWhen, evaluateVisibleWhen } from '../dynamic-form-schema';
|
|
@@ -114,6 +115,13 @@ export function fieldItemFields(field) {
|
|
|
114
115
|
export function isLineItemsField(field, value) {
|
|
115
116
|
if (field.type === 'image' || field.widget === 'upload')
|
|
116
117
|
return false;
|
|
118
|
+
// A `ref` field declared `multiple: true` (DynamicMultiSelectField) is a
|
|
119
|
+
// plain array of target ids, not a structured line-items document — it
|
|
120
|
+
// has its own editable picker and must not fall into the read-only
|
|
121
|
+
// inline-table branch just because its current value is an array
|
|
122
|
+
// (including the [] default on a freshly-created record).
|
|
123
|
+
if (field.multiple)
|
|
124
|
+
return false;
|
|
117
125
|
if (fieldItemFields(field)?.length)
|
|
118
126
|
return true;
|
|
119
127
|
if (Array.isArray(value))
|
|
@@ -1133,6 +1141,13 @@ export function EditField({ field, value, onChange, record, invalid }) {
|
|
|
1133
1141
|
// else optionsConfig.source → /api/options/<source>). Without the `type`
|
|
1134
1142
|
// check a source-backed picker with no `ref` silently degraded to a raw text
|
|
1135
1143
|
// input. Static inline `options` are handled by the enum <Select> branch below.
|
|
1144
|
+
// Multi-value ref field (field.multiple:true — see DynamicMultiSelectField):
|
|
1145
|
+
// checked BEFORE the single-value dynamic_select branch below, which would
|
|
1146
|
+
// otherwise claim it too (both trigger on the same `ref`/`getFieldRef`
|
|
1147
|
+
// check) and render a picker that stores a single id instead of an array.
|
|
1148
|
+
if (getFieldRef(field) && field.multiple) {
|
|
1149
|
+
return (_jsx(DynamicMultiSelectField, { field: field, value: value, onChange: onChange }));
|
|
1150
|
+
}
|
|
1136
1151
|
if ((getFieldRef(field) ||
|
|
1137
1152
|
field.type === 'dynamic_select' ||
|
|
1138
1153
|
field.widget === 'dynamic_select') &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;AA2C9C,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE9D,OAAO,KAAK,EAER,iBAAiB,EACpB,MAAM,wBAAwB,CAAA;AAE/B,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AA0BD;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,gBAAgB,EAAE,cAAc,MAAM,KAAG,MACzB,CAAA;AAQrD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,gBAAgB,KAAG,MAAM,GAAG,SAG5D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC7B,KAAK,gBAAgB,EACrB,OAAO,OAAO,EACd,WAAW,MAAM,EACjB,SAAS,MAAM,KAChB,MAyBF,CAAA;AAsDD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,0BAA0B,GAAI,QAAQ,GAAG,EAAE,KAAK,GAAG,KAAG,OAMlE,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,GAAG,EAAE,KAAK,GAAG,KAAG,OA0C5D,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,GAAG,EAAE,KAAK,GAAG,KAAG,OACqB,CAAA;AAkHhF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,KAAG,MAGnE,CAAA;AAED,6EAA6E;AAC7E,eAAO,MAAM,eAAe,2DAA4D,CAAA;AAExF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAC1B,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAClB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA6C5C;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,gBAAgB,EAAE,KAAK,GAAG,KAAG,MAWtE,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,gBAAgB,EAAE,KAAK,GAAG,KAAG,MAOtE,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACpC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,GACjE,MAAM,CAcR;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOxE;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,GACzB,KAAK,gBAAgB,EACrB,KAAK,GAAG,EACR,OAAO,GAAG,EACV,mBAAe,KAChB,MAAM,GAAG,SAcX,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GAAI,KAAK,gBAAgB,EAAE,KAAK,GAAG,KAAG,MAOzE,CAAA;AAgKD;;;;GAIG;AACH;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAA;IACd,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACrC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,CAAA;CAClB,CAgCA,CAAA;AAED,wBAAgB,4BAA4B,CACxC,OAAO,GAAE,qBAA0B,GACpC,iBAAiB,CAirBnB;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBACL,CAAA"}
|
package/dist/dynamic-columns.js
CHANGED
|
@@ -29,6 +29,7 @@ import { OptionsContext } from './options-context';
|
|
|
29
29
|
import { DynamicIcon, isLucideIconName } from './dynamic-icon';
|
|
30
30
|
import { CollectionCell } from './collection-cell';
|
|
31
31
|
import { isNilUuid, normalizeNilUuid } from './nil-uuid';
|
|
32
|
+
import { useOptionsResolver } from './use-options-resolver';
|
|
32
33
|
import { isColumnVisibleInTable } from './column-visibility';
|
|
33
34
|
const defaultGetImageUrl = (path) => path;
|
|
34
35
|
const getNestedValue = (obj, path) => path.split('.').reduce((acc, part) => acc && acc[part], obj);
|
|
@@ -265,6 +266,24 @@ const renderRelationBadges = (items, col) => {
|
|
|
265
266
|
return (_jsxs(Badge, { variant: "outline", className: "flex items-center gap-1", children: [iconValue && (_jsx(DynamicIcon, { name: iconValue, className: "h-3 w-3" })), _jsx("span", { children: label })] }, `${col.key}-${idx}`));
|
|
266
267
|
}) }));
|
|
267
268
|
};
|
|
269
|
+
/**
|
|
270
|
+
* Read-side counterpart of `DynamicMultiSelectField` (dynamic-multi-select-
|
|
271
|
+
* field.tsx): a `ref` column whose value is a plain jsonb array of target ids
|
|
272
|
+
* (field.multiple:true at write time) rather than the single-FK sibling
|
|
273
|
+
* `{value,label}` object `RelationCell` expects. There is no per-row backend
|
|
274
|
+
* resolution for this shape, so this cell resolves labels itself — one
|
|
275
|
+
* `useOptionsResolver` page (id → label) shared across every row of the
|
|
276
|
+
* column via `OptionsContext` — and renders each id as a badge.
|
|
277
|
+
*/
|
|
278
|
+
const RelationIdListCell = ({ ids, ref: relTarget }) => {
|
|
279
|
+
const { options } = useOptionsResolver({ modelKey: '', fieldKey: 'id', ref: relTarget, limit: 200 });
|
|
280
|
+
if (ids.length === 0)
|
|
281
|
+
return _jsx(EmptyCell, {});
|
|
282
|
+
return (_jsx("div", { className: "flex flex-wrap gap-1", children: ids.map((id) => {
|
|
283
|
+
const opt = options.find((o) => String(o.id) === String(id));
|
|
284
|
+
return (_jsx(Badge, { variant: "outline", children: opt ? opt.label : id.slice(0, 8) }, id));
|
|
285
|
+
}) }));
|
|
286
|
+
};
|
|
268
287
|
const BadgeWithEndpointOptions = ({ endpoint, value, getImageUrl }) => {
|
|
269
288
|
const { optionsMap } = React.useContext(OptionsContext);
|
|
270
289
|
const options = optionsMap.get(endpoint) || [];
|
|
@@ -711,6 +730,13 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
|
|
|
711
730
|
// `row[<key w/o _id>] = { value, label }` sibling.
|
|
712
731
|
if (renderAs === 'relation' ||
|
|
713
732
|
(col.ref && !col.options?.length && renderAs !== 'badge' && renderAs !== 'status')) {
|
|
733
|
+
// A `ref` column backed by a jsonb array (field.multiple:
|
|
734
|
+
// true at write time — see DynamicMultiSelectField) has no
|
|
735
|
+
// resolved sibling object; RelationCell expects one. Route
|
|
736
|
+
// it to the id-list cell instead.
|
|
737
|
+
if (Array.isArray(value)) {
|
|
738
|
+
return _jsx(RelationIdListCell, { ids: value.map(String), ref: col.ref });
|
|
739
|
+
}
|
|
714
740
|
return _jsx(RelationCell, { col: col, row: row.original, getImageUrl: getImageUrl });
|
|
715
741
|
}
|
|
716
742
|
// Option/type column: a `select`-style column ships its
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteby/metacore-runtime-react",
|
|
3
|
-
"version": "37.
|
|
3
|
+
"version": "37.5.1",
|
|
4
4
|
"description": "React runtime for metacore hosts — renders addon contributions dynamically",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"typescript": "^6.0.0",
|
|
68
68
|
"vitest": "^4.0.0",
|
|
69
69
|
"zustand": "^5.0.0",
|
|
70
|
-
"@asteby/metacore-
|
|
71
|
-
"@asteby/metacore-
|
|
70
|
+
"@asteby/metacore-sdk": "3.7.0",
|
|
71
|
+
"@asteby/metacore-ui": "2.17.3"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
74
|
"build": "tsc -p tsconfig.json",
|
|
@@ -56,6 +56,7 @@ import { useApi } from '../api-context'
|
|
|
56
56
|
import { useBranchCreateGate } from '../branch-create-gate'
|
|
57
57
|
import { toastServerError, extractFieldErrors, localizeFieldIssue, localizeFieldErrorMap } from '../server-error'
|
|
58
58
|
import { DynamicSelectField, OptionLead, OptionThumb } from '../dynamic-select-field'
|
|
59
|
+
import { DynamicMultiSelectField } from '../dynamic-multi-select-field'
|
|
59
60
|
import { DynamicRelations } from '../dynamic-relations'
|
|
60
61
|
import { useOptionsResolver, type ResolvedOption } from '../use-options-resolver'
|
|
61
62
|
import { getFieldRef, getVisibleWhen, evaluateVisibleWhen } from '../dynamic-form-schema'
|
|
@@ -376,6 +377,12 @@ export function fieldItemFields(field: FieldDef): ItemField[] | undefined {
|
|
|
376
377
|
// editable widgets (media/upload, color, dates) are NOT line-items.
|
|
377
378
|
export function isLineItemsField(field: FieldDef, value: any): boolean {
|
|
378
379
|
if (field.type === 'image' || field.widget === 'upload') return false
|
|
380
|
+
// A `ref` field declared `multiple: true` (DynamicMultiSelectField) is a
|
|
381
|
+
// plain array of target ids, not a structured line-items document — it
|
|
382
|
+
// has its own editable picker and must not fall into the read-only
|
|
383
|
+
// inline-table branch just because its current value is an array
|
|
384
|
+
// (including the [] default on a freshly-created record).
|
|
385
|
+
if ((field as ActionFieldDef).multiple) return false
|
|
379
386
|
if (fieldItemFields(field)?.length) return true
|
|
380
387
|
if (Array.isArray(value)) return true
|
|
381
388
|
return (
|
|
@@ -1990,6 +1997,20 @@ export function EditField({ field, value, onChange, record, invalid }: {
|
|
|
1990
1997
|
// else optionsConfig.source → /api/options/<source>). Without the `type`
|
|
1991
1998
|
// check a source-backed picker with no `ref` silently degraded to a raw text
|
|
1992
1999
|
// input. Static inline `options` are handled by the enum <Select> branch below.
|
|
2000
|
+
// Multi-value ref field (field.multiple:true — see DynamicMultiSelectField):
|
|
2001
|
+
// checked BEFORE the single-value dynamic_select branch below, which would
|
|
2002
|
+
// otherwise claim it too (both trigger on the same `ref`/`getFieldRef`
|
|
2003
|
+
// check) and render a picker that stores a single id instead of an array.
|
|
2004
|
+
if (getFieldRef(field as ActionFieldDef) && (field as ActionFieldDef).multiple) {
|
|
2005
|
+
return (
|
|
2006
|
+
<DynamicMultiSelectField
|
|
2007
|
+
field={field as ActionFieldDef}
|
|
2008
|
+
value={value}
|
|
2009
|
+
onChange={onChange}
|
|
2010
|
+
/>
|
|
2011
|
+
)
|
|
2012
|
+
}
|
|
2013
|
+
|
|
1993
2014
|
if (
|
|
1994
2015
|
(getFieldRef(field as ActionFieldDef) ||
|
|
1995
2016
|
field.type === 'dynamic_select' ||
|
package/src/dynamic-columns.tsx
CHANGED
|
@@ -56,6 +56,7 @@ import { OptionsContext } from './options-context'
|
|
|
56
56
|
import { DynamicIcon, isLucideIconName } from './dynamic-icon'
|
|
57
57
|
import { CollectionCell } from './collection-cell'
|
|
58
58
|
import { isNilUuid, normalizeNilUuid } from './nil-uuid'
|
|
59
|
+
import { useOptionsResolver } from './use-options-resolver'
|
|
59
60
|
import type { TableMetadata, ColumnDefinition } from './types'
|
|
60
61
|
import { isColumnVisibleInTable } from './column-visibility'
|
|
61
62
|
import type {
|
|
@@ -381,6 +382,32 @@ const renderRelationBadges = (items: any, col: ColumnDefinition) => {
|
|
|
381
382
|
)
|
|
382
383
|
}
|
|
383
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Read-side counterpart of `DynamicMultiSelectField` (dynamic-multi-select-
|
|
387
|
+
* field.tsx): a `ref` column whose value is a plain jsonb array of target ids
|
|
388
|
+
* (field.multiple:true at write time) rather than the single-FK sibling
|
|
389
|
+
* `{value,label}` object `RelationCell` expects. There is no per-row backend
|
|
390
|
+
* resolution for this shape, so this cell resolves labels itself — one
|
|
391
|
+
* `useOptionsResolver` page (id → label) shared across every row of the
|
|
392
|
+
* column via `OptionsContext` — and renders each id as a badge.
|
|
393
|
+
*/
|
|
394
|
+
const RelationIdListCell: React.FC<{ ids: string[]; ref: string }> = ({ ids, ref: relTarget }) => {
|
|
395
|
+
const { options } = useOptionsResolver({ modelKey: '', fieldKey: 'id', ref: relTarget, limit: 200 })
|
|
396
|
+
if (ids.length === 0) return <EmptyCell />
|
|
397
|
+
return (
|
|
398
|
+
<div className="flex flex-wrap gap-1">
|
|
399
|
+
{ids.map((id) => {
|
|
400
|
+
const opt = options.find((o) => String(o.id) === String(id))
|
|
401
|
+
return (
|
|
402
|
+
<Badge key={id} variant="outline">
|
|
403
|
+
{opt ? opt.label : id.slice(0, 8)}
|
|
404
|
+
</Badge>
|
|
405
|
+
)
|
|
406
|
+
})}
|
|
407
|
+
</div>
|
|
408
|
+
)
|
|
409
|
+
}
|
|
410
|
+
|
|
384
411
|
const BadgeWithEndpointOptions: React.FC<{
|
|
385
412
|
endpoint: string
|
|
386
413
|
value: any
|
|
@@ -1016,6 +1043,13 @@ export function makeDefaultGetDynamicColumns(
|
|
|
1016
1043
|
renderAs === 'relation' ||
|
|
1017
1044
|
(col.ref && !col.options?.length && renderAs !== 'badge' && renderAs !== 'status')
|
|
1018
1045
|
) {
|
|
1046
|
+
// A `ref` column backed by a jsonb array (field.multiple:
|
|
1047
|
+
// true at write time — see DynamicMultiSelectField) has no
|
|
1048
|
+
// resolved sibling object; RelationCell expects one. Route
|
|
1049
|
+
// it to the id-list cell instead.
|
|
1050
|
+
if (Array.isArray(value)) {
|
|
1051
|
+
return <RelationIdListCell ids={value.map(String)} ref={col.ref!} />
|
|
1052
|
+
}
|
|
1019
1053
|
return <RelationCell col={col} row={row.original} getImageUrl={getImageUrl} />
|
|
1020
1054
|
}
|
|
1021
1055
|
|