@asteby/metacore-runtime-react 13.7.0 → 13.8.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,11 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 13.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- ab80937: feat(dynamic-select): inline "+" to create the referenced record. A dynamic_select with a `ref` now shows a "+" button that opens the referenced model's OWN create modal (via a decoupled `metacore:create-record` window event the host handles) and auto-selects the newly created record. Lets users add a missing Category/Brand/etc. without leaving the form.
|
|
8
|
+
|
|
3
9
|
## 13.7.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-select-field.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAW7C,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,GAAG,CAAA;IACV,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;CAC7B;AAED,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"dynamic-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-select-field.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAW7C,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,GAAG,CAAA;IACV,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;CAC7B;AAED,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,uBAAuB,2CAgJrF;AAED,eAAe,kBAAkB,CAAA"}
|
|
@@ -24,7 +24,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
24
24
|
// case — start empty and never hit this.
|
|
25
25
|
import { useEffect, useState } from 'react';
|
|
26
26
|
import { Button, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Popover, PopoverContent, PopoverTrigger, } from '@asteby/metacore-ui/primitives';
|
|
27
|
-
import { Check, ChevronsUpDown, Loader2 } from 'lucide-react';
|
|
27
|
+
import { Check, ChevronsUpDown, Loader2, Plus } from 'lucide-react';
|
|
28
28
|
import { useOptionsResolver } from './use-options-resolver';
|
|
29
29
|
function useDebounced(value, ms) {
|
|
30
30
|
const [debounced, setDebounced] = useState(value);
|
|
@@ -63,12 +63,33 @@ export function DynamicSelectField({ field, value, onChange }) {
|
|
|
63
63
|
setOpen(false);
|
|
64
64
|
setSearch('');
|
|
65
65
|
};
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
// Inline-create: the "+" opens the REFERENCED model's own create modal (the
|
|
67
|
+
// real one the host renders for that model — full fields, not a duplicate),
|
|
68
|
+
// via a decoupled window event the host listens for. On success the host
|
|
69
|
+
// hands back the new record and we select it immediately. No host import →
|
|
70
|
+
// no circular dependency; works for ANY dynamic_select with a `ref`.
|
|
71
|
+
const openCreate = () => {
|
|
72
|
+
if (!field.ref || typeof window === 'undefined')
|
|
73
|
+
return;
|
|
74
|
+
window.dispatchEvent(new CustomEvent('metacore:create-record', {
|
|
75
|
+
detail: {
|
|
76
|
+
model: field.ref,
|
|
77
|
+
onCreated: (rec) => {
|
|
78
|
+
if (rec && rec.id != null) {
|
|
79
|
+
const id = String(rec.id);
|
|
80
|
+
const label = String(rec.name ?? rec.label ?? rec.title ?? rec.id);
|
|
81
|
+
handlePick({ id, value: id, label, name: label });
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
}));
|
|
86
|
+
};
|
|
87
|
+
return (_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "outline", role: "combobox", "aria-expanded": open, id: field.key, className: "w-full justify-between font-normal", "data-empty": !value, children: [_jsx("span", { className: 'truncate ' + (selectedLabel ? '' : 'text-muted-foreground'), children: selectedLabel || field.placeholder || 'Buscar…' }), _jsx(ChevronsUpDown, { className: "ml-2 size-4 shrink-0 opacity-50" })] }) }), _jsx(PopoverContent, { className: "p-0", align: "start",
|
|
88
|
+
// Match the trigger width without an arbitrary Tailwind class
|
|
89
|
+
// (those don't always survive a consuming app's Tailwind scan).
|
|
90
|
+
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) => {
|
|
91
|
+
const isSel = String(opt.id) === String(value);
|
|
92
|
+
return (_jsxs(CommandItem, { value: String(opt.id), onSelect: () => handlePick(opt), children: [_jsx(Check, { className: 'mr-2 size-4 ' + (isSel ? 'opacity-100' : 'opacity-0') }), _jsxs("div", { className: "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)));
|
|
93
|
+
}) }))] })] }) })] }), field.ref && (_jsx(Button, { type: "button", variant: "outline", size: "icon", className: "size-9 shrink-0", onClick: openCreate, title: `Crear ${field.label ?? field.ref}`, "aria-label": `Crear ${field.label ?? field.ref}`, children: _jsx(Plus, { className: "size-4" }) }))] }));
|
|
73
94
|
}
|
|
74
95
|
export default DynamicSelectField;
|
package/package.json
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
PopoverContent,
|
|
35
35
|
PopoverTrigger,
|
|
36
36
|
} from '@asteby/metacore-ui/primitives'
|
|
37
|
-
import { Check, ChevronsUpDown, Loader2 } from 'lucide-react'
|
|
37
|
+
import { Check, ChevronsUpDown, Loader2, Plus } from 'lucide-react'
|
|
38
38
|
import { useOptionsResolver, type ResolvedOption } from './use-options-resolver'
|
|
39
39
|
import type { ActionFieldDef } from './types'
|
|
40
40
|
|
|
@@ -87,8 +87,32 @@ export function DynamicSelectField({ field, value, onChange }: DynamicSelectFiel
|
|
|
87
87
|
setSearch('')
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
// Inline-create: the "+" opens the REFERENCED model's own create modal (the
|
|
91
|
+
// real one the host renders for that model — full fields, not a duplicate),
|
|
92
|
+
// via a decoupled window event the host listens for. On success the host
|
|
93
|
+
// hands back the new record and we select it immediately. No host import →
|
|
94
|
+
// no circular dependency; works for ANY dynamic_select with a `ref`.
|
|
95
|
+
const openCreate = () => {
|
|
96
|
+
if (!field.ref || typeof window === 'undefined') return
|
|
97
|
+
window.dispatchEvent(
|
|
98
|
+
new CustomEvent('metacore:create-record', {
|
|
99
|
+
detail: {
|
|
100
|
+
model: field.ref,
|
|
101
|
+
onCreated: (rec: any) => {
|
|
102
|
+
if (rec && rec.id != null) {
|
|
103
|
+
const id = String(rec.id)
|
|
104
|
+
const label = String(rec.name ?? rec.label ?? rec.title ?? rec.id)
|
|
105
|
+
handlePick({ id, value: id, label, name: label })
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
90
113
|
return (
|
|
91
|
-
<
|
|
114
|
+
<div className="flex items-center gap-1.5">
|
|
115
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
92
116
|
<PopoverTrigger asChild>
|
|
93
117
|
<Button
|
|
94
118
|
type="button"
|
|
@@ -157,7 +181,21 @@ export function DynamicSelectField({ field, value, onChange }: DynamicSelectFiel
|
|
|
157
181
|
</CommandList>
|
|
158
182
|
</Command>
|
|
159
183
|
</PopoverContent>
|
|
160
|
-
|
|
184
|
+
</Popover>
|
|
185
|
+
{field.ref && (
|
|
186
|
+
<Button
|
|
187
|
+
type="button"
|
|
188
|
+
variant="outline"
|
|
189
|
+
size="icon"
|
|
190
|
+
className="size-9 shrink-0"
|
|
191
|
+
onClick={openCreate}
|
|
192
|
+
title={`Crear ${field.label ?? field.ref}`}
|
|
193
|
+
aria-label={`Crear ${field.label ?? field.ref}`}
|
|
194
|
+
>
|
|
195
|
+
<Plus className="size-4" />
|
|
196
|
+
</Button>
|
|
197
|
+
)}
|
|
198
|
+
</div>
|
|
161
199
|
)
|
|
162
200
|
}
|
|
163
201
|
|