@asteby/metacore-runtime-react 27.1.1 → 27.2.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.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 27.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 27edd94: Las opciones del picker de referencias SIEMPRE llevan lead visual. El gate
|
|
8
|
+
`optionsHaveVisual` suprimía el avatar de toda la lista cuando ninguna opción
|
|
9
|
+
traía imagen/icono/color — un select de almacenes quedaba como texto pelado
|
|
10
|
+
mientras el de productos (una opción con foto) mostraba avatares. Ahora cada
|
|
11
|
+
opción renderiza su `OptionLead`, que cae a la inicial neutra cuando no hay
|
|
12
|
+
imagen, en el dropdown y en el trigger.
|
|
13
|
+
|
|
3
14
|
## 27.1.1
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-select-field.tsx"],"names":[],"mappings":"AAwCA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAEhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,gDAAgD,CAAA;AAEjF;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EACxB,KAAK,EACL,IAAI,EACJ,IAAS,GACZ,EAAE;IACC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB,+BAoBA;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EACvB,MAAM,EACN,IAAS,GACZ,EAAE;IACC,MAAM,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,CAAA;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB,sCA4BA;
|
|
1
|
+
{"version":3,"file":"dynamic-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-select-field.tsx"],"names":[],"mappings":"AAwCA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAEhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,gDAAgD,CAAA;AAEjF;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EACxB,KAAK,EACL,IAAI,EACJ,IAAS,GACZ,EAAE;IACC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB,+BAoBA;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EACvB,MAAM,EACN,IAAS,GACZ,EAAE;IACC,MAAM,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,CAAA;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB,sCA4BA;AAWD,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,GAAG,CAAA;IACV,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;IAC1B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAA;IAClC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,kBAAkB,CAAC,EAC/B,KAAK,EACL,KAAK,EACL,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAgB,GACnB,EAAE,uBAAuB,+BAqOzB;AAED,eAAe,kBAAkB,CAAA"}
|
|
@@ -79,11 +79,6 @@ export function OptionLead({ option, size = 20, }) {
|
|
|
79
79
|
return _jsx(InitialsAvatar, { name: option.label, size: size, rounded: "sm", tone: "neutral" });
|
|
80
80
|
return null;
|
|
81
81
|
}
|
|
82
|
-
/** True when any option (or the selected one) carries a renderable visual. */
|
|
83
|
-
function optionsHaveVisual(options, selected) {
|
|
84
|
-
const has = (o) => !!(o && (o.image || o.color || o.icon));
|
|
85
|
-
return has(selected) || options.some(has);
|
|
86
|
-
}
|
|
87
82
|
function useDebounced(value, ms) {
|
|
88
83
|
const [debounced, setDebounced] = useState(value);
|
|
89
84
|
useEffect(() => {
|
|
@@ -155,7 +150,6 @@ export function DynamicSelectField({ field, value, onChange, seedOption, depends
|
|
|
155
150
|
// Only switch the picker into "with thumbnails" mode when the data actually
|
|
156
151
|
// carries images — a relation whose options have no `image` keeps the plain
|
|
157
152
|
// text list it had before (no empty placeholder column).
|
|
158
|
-
const hasVisual = optionsHaveVisual(options, selectedOption);
|
|
159
153
|
const handlePick = (opt) => {
|
|
160
154
|
setPicked(opt);
|
|
161
155
|
onChange(String(opt.id));
|
|
@@ -195,14 +189,14 @@ export function DynamicSelectField({ field, value, onChange, seedOption, depends
|
|
|
195
189
|
// (the long empty-state placeholder) and overflows the column, pushing the
|
|
196
190
|
// "+" off-screen — it only "fit" once a short value was selected.
|
|
197
191
|
return (_jsxs("div", { className: "flex w-full min-w-0 items-center gap-1.5", children: [_jsxs(Popover, { open: open && !blockedByDependency, onOpenChange: (o) => { if (!blockedByDependency)
|
|
198
|
-
setOpen(o); }, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "outline", role: "combobox", "aria-expanded": open, id: field.key, disabled: blockedByDependency, className: "min-w-0 flex-1 justify-between font-normal", "data-empty": !value, "data-depends-blocked": blockedByDependency ? '' : undefined, children: [_jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2 text-left", children: [
|
|
192
|
+
setOpen(o); }, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "outline", role: "combobox", "aria-expanded": open, id: field.key, disabled: blockedByDependency, className: "min-w-0 flex-1 justify-between font-normal", "data-empty": !value, "data-depends-blocked": blockedByDependency ? '' : undefined, children: [_jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2 text-left", children: [value && selectedOption ? (_jsx(OptionLead, { option: selectedOption, size: 20 })) : null, _jsx("span", { className: 'min-w-0 flex-1 truncate ' + (selectedLabel ? '' : 'text-muted-foreground'), children: blockedByDependency
|
|
199
193
|
? (dependsHint || DEFAULT_DEPENDS_HINT)
|
|
200
194
|
: selectedLabel || field.placeholder || 'Buscar…' })] }), _jsx(ChevronsUpDown, { className: "ml-2 size-4 shrink-0 opacity-50" })] }) }), _jsx(PopoverContent, { className: "p-0", align: "start",
|
|
201
195
|
// Match the trigger width without an arbitrary Tailwind class
|
|
202
196
|
// (those don't always survive a consuming app's Tailwind scan).
|
|
203
197
|
style: { width: 'var(--radix-popover-trigger-width)' }, children: _jsxs(Command, { shouldFilter: false, children: [_jsx(CommandInput, { placeholder: field.placeholder || 'Buscar…', value: search, onValueChange: setSearch }), _jsxs(CommandList, { children: [loading && (_jsxs("div", { className: "text-muted-foreground flex items-center justify-center gap-2 py-6 text-sm", children: [_jsx(Loader2, { className: "size-4 animate-spin" }), "Buscando\u2026"] })), !loading && options.length === 0 && (_jsx(CommandEmpty, { children: debounced ? 'Sin resultados' : 'Escribí para buscar…' })), !loading && options.length > 0 && (_jsx(CommandGroup, { className: "max-h-64 overflow-auto", children: options.map((opt) => {
|
|
204
198
|
const isSel = String(opt.id) === String(value);
|
|
205
|
-
return (_jsxs(CommandItem, { value: String(opt.id), onSelect: () => handlePick(opt), children: [_jsx(Check, { className: 'mr-2 size-4 shrink-0 ' + (isSel ? 'opacity-100' : 'opacity-0') }),
|
|
199
|
+
return (_jsxs(CommandItem, { value: String(opt.id), onSelect: () => handlePick(opt), children: [_jsx(Check, { className: 'mr-2 size-4 shrink-0 ' + (isSel ? 'opacity-100' : 'opacity-0') }), _jsx(OptionLead, { option: opt, size: 24 }), _jsxs("div", { className: "ml-2 flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate", children: opt.label }), opt.description && (_jsx("span", { className: "text-muted-foreground truncate text-xs", children: opt.description }))] })] }, String(opt.id)));
|
|
206
200
|
}) }))] })] }) })] }), fieldRef && (_jsx(Button, { type: "button", variant: "outline", size: "icon", className: "size-9 shrink-0", onClick: openCreate, title: `Crear ${field.label ?? fieldRef}`, "aria-label": `Crear ${field.label ?? fieldRef}`, children: _jsx(Plus, { className: "size-4" }) }))] }));
|
|
207
201
|
}
|
|
208
202
|
export default DynamicSelectField;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteby/metacore-runtime-react",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.2.0",
|
|
4
4
|
"description": "React runtime for metacore hosts — renders addon contributions dynamically",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"react-i18next": ">=13",
|
|
38
38
|
"sonner": ">=1.7",
|
|
39
39
|
"zustand": ">=5",
|
|
40
|
-
"@asteby/metacore-
|
|
41
|
-
"@asteby/metacore-
|
|
40
|
+
"@asteby/metacore-sdk": "^3.3.0",
|
|
41
|
+
"@asteby/metacore-ui": "^2.12.1"
|
|
42
42
|
},
|
|
43
43
|
"peerDependenciesMeta": {
|
|
44
44
|
"@tanstack/react-router": {
|
|
@@ -129,16 +129,6 @@ export function OptionLead({
|
|
|
129
129
|
return null
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
/** True when any option (or the selected one) carries a renderable visual. */
|
|
133
|
-
function optionsHaveVisual(
|
|
134
|
-
options: ReadonlyArray<Pick<ResolvedOption, 'image' | 'color' | 'icon'>>,
|
|
135
|
-
selected?: Pick<ResolvedOption, 'image' | 'color' | 'icon'> | null,
|
|
136
|
-
): boolean {
|
|
137
|
-
const has = (o?: Pick<ResolvedOption, 'image' | 'color' | 'icon'> | null) =>
|
|
138
|
-
!!(o && (o.image || o.color || o.icon))
|
|
139
|
-
return has(selected) || options.some(has)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
132
|
function useDebounced<T>(value: T, ms: number): T {
|
|
143
133
|
const [debounced, setDebounced] = useState(value)
|
|
144
134
|
useEffect(() => {
|
|
@@ -257,7 +247,6 @@ export function DynamicSelectField({
|
|
|
257
247
|
// Only switch the picker into "with thumbnails" mode when the data actually
|
|
258
248
|
// carries images — a relation whose options have no `image` keeps the plain
|
|
259
249
|
// text list it had before (no empty placeholder column).
|
|
260
|
-
const hasVisual = optionsHaveVisual(options, selectedOption)
|
|
261
250
|
|
|
262
251
|
const handlePick = (opt: ResolvedOption) => {
|
|
263
252
|
setPicked(opt)
|
|
@@ -336,7 +325,7 @@ export function DynamicSelectField({
|
|
|
336
325
|
data-depends-blocked={blockedByDependency ? '' : undefined}
|
|
337
326
|
>
|
|
338
327
|
<span className="flex min-w-0 flex-1 items-center gap-2 text-left">
|
|
339
|
-
{
|
|
328
|
+
{value && selectedOption ? (
|
|
340
329
|
<OptionLead option={selectedOption} size={20} />
|
|
341
330
|
) : null}
|
|
342
331
|
<span className={'min-w-0 flex-1 truncate ' + (selectedLabel ? '' : 'text-muted-foreground')}>
|
|
@@ -384,9 +373,7 @@ export function DynamicSelectField({
|
|
|
384
373
|
onSelect={() => handlePick(opt)}
|
|
385
374
|
>
|
|
386
375
|
<Check className={'mr-2 size-4 shrink-0 ' + (isSel ? 'opacity-100' : 'opacity-0')} />
|
|
387
|
-
{
|
|
388
|
-
<OptionLead option={opt} size={24} />
|
|
389
|
-
)}
|
|
376
|
+
<OptionLead option={opt} size={24} />
|
|
390
377
|
<div className="ml-2 flex min-w-0 flex-col">
|
|
391
378
|
<span className="truncate">{opt.label}</span>
|
|
392
379
|
{opt.description && (
|