@asteby/metacore-runtime-react 49.5.0 → 49.7.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/business/customer-picker.d.ts +8 -2
  3. package/dist/business/customer-picker.d.ts.map +1 -1
  4. package/dist/business/customer-picker.js +30 -27
  5. package/dist/business/index.d.ts +1 -0
  6. package/dist/business/index.d.ts.map +1 -1
  7. package/dist/business/index.js +1 -0
  8. package/dist/business/line-product-cell.d.ts +8 -10
  9. package/dist/business/line-product-cell.d.ts.map +1 -1
  10. package/dist/business/line-product-cell.js +13 -90
  11. package/dist/business/product-options.d.ts +41 -0
  12. package/dist/business/product-options.d.ts.map +1 -0
  13. package/dist/business/product-options.js +58 -0
  14. package/dist/business/product-picker.d.ts +5 -1
  15. package/dist/business/product-picker.d.ts.map +1 -1
  16. package/dist/business/product-picker.js +26 -35
  17. package/dist/business/relate-documents.d.ts +1 -1
  18. package/dist/business/relate-documents.d.ts.map +1 -1
  19. package/dist/business/relate-documents.js +6 -8
  20. package/dist/business/vehicle-picker.d.ts +8 -2
  21. package/dist/business/vehicle-picker.d.ts.map +1 -1
  22. package/dist/business/vehicle-picker.js +28 -28
  23. package/dist/dialogs/dynamic-record.d.ts.map +1 -1
  24. package/dist/dialogs/dynamic-record.js +28 -43
  25. package/dist/dynamic-multi-select-field.d.ts.map +1 -1
  26. package/dist/dynamic-multi-select-field.js +36 -6
  27. package/dist/dynamic-select-field.d.ts +9 -23
  28. package/dist/dynamic-select-field.d.ts.map +1 -1
  29. package/dist/dynamic-select-field.js +105 -172
  30. package/dist/entity-select.d.ts +5 -2
  31. package/dist/entity-select.d.ts.map +1 -1
  32. package/dist/entity-select.js +23 -116
  33. package/dist/index.d.ts +9 -2
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +10 -1
  36. package/dist/query-batch.d.ts.map +1 -1
  37. package/dist/query-batch.js +4 -0
  38. package/dist/record-picker-actions.d.ts +40 -2
  39. package/dist/record-picker-actions.d.ts.map +1 -1
  40. package/dist/record-picker-actions.js +44 -4
  41. package/dist/record-picker-dialog.d.ts +23 -0
  42. package/dist/record-picker-dialog.d.ts.map +1 -0
  43. package/dist/record-picker-dialog.js +37 -0
  44. package/dist/record-picker-option.d.ts +25 -0
  45. package/dist/record-picker-option.d.ts.map +1 -0
  46. package/dist/record-picker-option.js +55 -0
  47. package/dist/record-picker.d.ts +149 -0
  48. package/dist/record-picker.d.ts.map +1 -0
  49. package/dist/record-picker.js +372 -0
  50. package/dist/use-option-ids.d.ts +34 -0
  51. package/dist/use-option-ids.d.ts.map +1 -0
  52. package/dist/use-option-ids.js +138 -0
  53. package/dist/use-options-resolver.d.ts +4 -0
  54. package/dist/use-options-resolver.d.ts.map +1 -1
  55. package/dist/use-options-resolver.js +10 -1
  56. package/package.json +1 -1
  57. package/src/__tests__/business-pickers.test.tsx +6 -3
  58. package/src/__tests__/document-editor-inline-selects.test.tsx +2 -1
  59. package/src/__tests__/document-form-dialog.test.tsx +4 -3
  60. package/src/__tests__/document-lines-grid.test.tsx +2 -1
  61. package/src/__tests__/edit-field-polish.test.tsx +6 -3
  62. package/src/__tests__/option-ids.test.tsx +181 -0
  63. package/src/__tests__/record-picker.test.tsx +469 -0
  64. package/src/business/customer-picker.tsx +87 -98
  65. package/src/business/index.ts +1 -0
  66. package/src/business/line-product-cell.tsx +55 -180
  67. package/src/business/product-options.tsx +119 -0
  68. package/src/business/product-picker.tsx +63 -126
  69. package/src/business/relate-documents.tsx +36 -45
  70. package/src/business/vehicle-picker.tsx +76 -99
  71. package/src/dialogs/dynamic-record.tsx +44 -97
  72. package/src/dynamic-multi-select-field.tsx +53 -15
  73. package/src/dynamic-select-field.tsx +188 -379
  74. package/src/entity-select.tsx +53 -202
  75. package/src/index.ts +35 -2
  76. package/src/query-batch.ts +3 -0
  77. package/src/record-picker-actions.tsx +101 -8
  78. package/src/record-picker-dialog.tsx +80 -0
  79. package/src/record-picker-option.tsx +96 -0
  80. package/src/record-picker.tsx +971 -0
  81. package/src/use-option-ids.ts +168 -0
  82. package/src/use-options-resolver.ts +11 -1
  83. package/dist/business/use-async-search.d.ts +0 -10
  84. package/dist/business/use-async-search.d.ts.map +0 -1
  85. package/dist/business/use-async-search.js +0 -38
  86. package/src/business/use-async-search.ts +0 -43
@@ -6,17 +6,18 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
6
  // (p. ej. SAT 01/03/04) llegan por la prop `relationTypes`.
7
7
  import { useState } from 'react';
8
8
  import { useTranslation } from 'react-i18next';
9
- import { Link2, Search, X } from 'lucide-react';
10
- import { Badge, Button, Input } from '@asteby/metacore-ui';
11
- import { useAsyncSearch } from './use-async-search';
9
+ import { Link2, X } from 'lucide-react';
10
+ import { Badge, Button } from '@asteby/metacore-ui';
11
+ import { RecordPicker, useLatestSearch } from '../record-picker';
12
12
  function docTitle(d) {
13
13
  return d.label || d.folio || d.uuid || d.id || '';
14
14
  }
15
15
  export function RelateDocuments({ value, onChange, relationTypes, search, defaultRelationType, max, disabled, placeholder, }) {
16
16
  const { t } = useTranslation();
17
17
  const [text, setText] = useState('');
18
+ const [open, setOpen] = useState(false);
18
19
  const [pendingType, setPendingType] = useState(defaultRelationType ?? relationTypes[0]?.value ?? '');
19
- const { results, loading, error } = useAsyncSearch(text, search, { minChars: 2 });
20
+ const searchFn = useLatestSearch(search);
20
21
  const full = max != null && value.length >= max;
21
22
  const typeLabel = (v) => relationTypes.find((r) => r.value === v)?.label ?? v;
22
23
  const add = (d) => {
@@ -31,10 +32,7 @@ export function RelateDocuments({ value, onChange, relationTypes, search, defaul
31
32
  const remove = (id) => onChange(value.filter((x) => x.related_document_id !== id));
32
33
  const setType = (id, relation_type) => onChange(value.map((x) => (x.related_document_id === id ? { ...x, relation_type } : x)));
33
34
  const selectCls = 'h-9 rounded-md border bg-background px-2 text-sm';
34
- return (_jsxs("div", { "data-slot": "relate-documents", className: "space-y-2", children: [value.length > 0 && (_jsx("ul", { className: "divide-y rounded-md border", children: value.map((d) => (_jsxs("li", { className: "flex flex-wrap items-center gap-2 px-2 py-1.5", children: [_jsx(Link2, { className: "size-4 text-muted-foreground", "aria-hidden": true }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "truncate text-sm font-medium", children: docTitle({ folio: d.folio, label: d.label, id: d.related_document_id }) }), d.uuid && _jsx("p", { className: "break-all font-mono text-xs text-muted-foreground", children: d.uuid })] }), _jsxs("select", { className: selectCls, disabled: disabled, value: d.relation_type, "aria-label": t('relateDocuments.type', { defaultValue: 'Tipo de relación' }), onChange: (e) => setType(d.related_document_id, e.target.value), children: [!relationTypes.some((r) => r.value === d.relation_type) && (_jsx("option", { value: d.relation_type, children: typeLabel(d.relation_type) })), relationTypes.map((r) => (_jsx("option", { value: r.value, children: r.label }, r.value)))] }), !disabled && (_jsx(Button, { type: "button", size: "icon", variant: "ghost", onClick: () => remove(d.related_document_id), "aria-label": t('relateDocuments.remove', { defaultValue: 'Quitar relación' }), children: _jsx(X, { className: "size-4" }) }))] }, d.related_document_id))) })), !full && !disabled && (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(Search, { className: "pointer-events-none absolute left-2.5 top-2.5 size-4 text-muted-foreground", "aria-hidden": true }), _jsx(Input, { className: "pl-8", value: text, placeholder: placeholder ?? t('relateDocuments.placeholder', { defaultValue: 'Buscar por folio o UUID' }), onChange: (e) => setText(e.target.value) })] }), _jsx("select", { className: selectCls, value: pendingType, "aria-label": t('relateDocuments.newType', { defaultValue: 'Tipo para el documento nuevo' }), onChange: (e) => setPendingType(e.target.value), children: relationTypes.map((r) => (_jsx("option", { value: r.value, children: r.label }, r.value))) })] }), loading && _jsx("p", { className: "text-sm text-muted-foreground", children: t('common.searching', { defaultValue: 'Buscando…' }) }), error && !loading && (_jsx("p", { role: "alert", className: "text-sm text-destructive", children: t('relateDocuments.error', { defaultValue: 'No se pudo buscar documentos. Inténtalo de nuevo.' }) })), !loading && !error && text.trim().length >= 2 && results.length === 0 && (_jsx("p", { className: "text-sm text-muted-foreground", children: t('relateDocuments.empty', { defaultValue: 'No encontramos ese documento.' }) })), results.length > 0 && (_jsx("ul", { role: "listbox", className: "max-h-64 divide-y overflow-auto rounded-md border", children: results.map((d) => {
35
- const already = value.some((x) => x.related_document_id === d.id);
36
- return (_jsx("li", { role: "option", "aria-selected": already, children: _jsxs("button", { type: "button", disabled: already, className: "flex w-full items-center justify-between gap-2 px-2 py-1.5 text-left hover:bg-accent disabled:opacity-50", onClick: () => add(d), children: [_jsxs("span", { children: [_jsx("span", { className: "block text-sm font-medium", children: docTitle(d) }), d.uuid && _jsx("span", { className: "block break-all font-mono text-xs text-muted-foreground", children: d.uuid })] }), already && _jsx(Badge, { variant: "muted", children: t('relateDocuments.added', { defaultValue: 'Agregado' }) })] }) }, d.id));
37
- }) }))] }))] }));
35
+ return (_jsxs("div", { "data-slot": "relate-documents", className: "space-y-2", children: [value.length > 0 && (_jsx("ul", { className: "divide-y rounded-md border", children: value.map((d) => (_jsxs("li", { className: "flex flex-wrap items-center gap-2 px-2 py-1.5", children: [_jsx(Link2, { className: "size-4 text-muted-foreground", "aria-hidden": true }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "truncate text-sm font-medium", children: docTitle({ folio: d.folio, label: d.label, id: d.related_document_id }) }), d.uuid && _jsx("p", { className: "break-all font-mono text-xs text-muted-foreground", children: d.uuid })] }), _jsxs("select", { className: selectCls, disabled: disabled, value: d.relation_type, "aria-label": t('relateDocuments.type', { defaultValue: 'Tipo de relación' }), onChange: (e) => setType(d.related_document_id, e.target.value), children: [!relationTypes.some((r) => r.value === d.relation_type) && (_jsx("option", { value: d.relation_type, children: typeLabel(d.relation_type) })), relationTypes.map((r) => (_jsx("option", { value: r.value, children: r.label }, r.value)))] }), !disabled && (_jsx(Button, { type: "button", size: "icon", variant: "ghost", onClick: () => remove(d.related_document_id), "aria-label": t('relateDocuments.remove', { defaultValue: 'Quitar relación' }), children: _jsx(X, { className: "size-4" }) }))] }, d.related_document_id))) })), !full && !disabled && (_jsx(RecordPicker, { trigger: "input", search: searchFn, minChars: 2, query: text, onQueryChange: setText, open: open, onOpenChange: setOpen, getKey: (d) => d.id, getLabel: docTitle, isItemDisabled: (d) => value.some((x) => x.related_document_id === d.id), renderItem: (d, { disabled: already }) => (_jsxs("span", { className: "flex w-full min-w-0 items-center justify-between gap-2", children: [_jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "block truncate text-sm font-medium", children: docTitle(d) }), d.uuid && _jsx("span", { className: "block break-all font-mono text-xs text-muted-foreground", children: d.uuid })] }), already && _jsx(Badge, { variant: "muted", children: t('relateDocuments.added', { defaultValue: 'Agregado' }) })] })), onSelect: add, placeholder: placeholder ?? t('relateDocuments.placeholder', { defaultValue: 'Buscar por folio o UUID' }), loadingText: t('common.searching', { defaultValue: 'Buscando…' }), errorText: t('relateDocuments.error', { defaultValue: 'No se pudo buscar documentos. Inténtalo de nuevo.' }), emptyText: t('relateDocuments.empty', { defaultValue: 'No encontramos ese documento.' }), after: _jsx("select", { className: selectCls, value: pendingType, "aria-label": t('relateDocuments.newType', { defaultValue: 'Tipo para el documento nuevo' }), onChange: (e) => setPendingType(e.target.value), children: relationTypes.map((r) => (_jsx("option", { value: r.value, children: r.label }, r.value))) }) }))] }));
38
36
  }
39
37
  /** Valor a enviar al servidor: solo los datos, sin los campos de visualización. */
40
38
  export function serializeRelatedDocuments(value) {
@@ -15,7 +15,7 @@ export interface VehiclePickerProps {
15
15
  value: VehicleResult | null;
16
16
  /** Evento único de cambio: vehículo elegido/creado, o `null` al limpiar. */
17
17
  onChange: (vehicle: VehicleResult | null) => void;
18
- /** Búsqueda por placa o VIN. Estable (useCallback). */
18
+ /** Búsqueda por placa o VIN. */
19
19
  search: (q: string, signal: AbortSignal) => Promise<VehicleResult[]>;
20
20
  /** Modelo del kernel para el alta rápida. Default `Vehicle`. */
21
21
  model?: string;
@@ -25,6 +25,8 @@ export interface VehiclePickerProps {
25
25
  mapRecord?: (rec: Record<string, unknown>) => VehicleResult;
26
26
  /** Override de permiso (default `<model>.create` con useCan). */
27
27
  canCreate?: boolean;
28
+ /** Override de permiso para editar al elegido (default `<model>.update`). */
29
+ canEdit?: boolean;
28
30
  /** Valores iniciales del alta (p. ej. `customer_id` del cliente ya elegido). */
29
31
  createDefaults?: Record<string, unknown>;
30
32
  disabled?: boolean;
@@ -32,5 +34,9 @@ export interface VehiclePickerProps {
32
34
  }
33
35
  /** Línea corta de un vehículo: «Nissan Versa 2019 · ABC-123 · VIN…». */
34
36
  export declare function describeVehicle(v: VehicleResult): string;
35
- export declare function VehiclePicker({ value, onChange, search, model, endpoint, mapRecord, canCreate, createDefaults, disabled, placeholder, }: VehiclePickerProps): import("react").JSX.Element;
37
+ /**
38
+ * @deprecated Configuración fina de {@link RecordPicker}; se conserva para no
39
+ * romper consumidores.
40
+ */
41
+ export declare function VehiclePicker({ value, onChange, search, model, endpoint, mapRecord, canCreate, canEdit, createDefaults, disabled, placeholder, }: VehiclePickerProps): import("react").JSX.Element;
36
42
  //# sourceMappingURL=vehicle-picker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vehicle-picker.d.ts","sourceRoot":"","sources":["../../src/business/vehicle-picker.tsx"],"names":[],"mappings":"AAeA,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,aAAa,GAAG,IAAI,CAAA;IAC3B,4EAA4E;IAC5E,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,KAAK,IAAI,CAAA;IACjD,uDAAuD;IACvD,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;IACpE,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qGAAqG;IACrG,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,aAAa,CAAA;IAC3D,iEAAiE;IACjE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAQD,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAGxD;AAED,wBAAgB,aAAa,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,MAAM,EACN,KAAiB,EACjB,QAAQ,EACR,SAAS,EACT,SAAS,EACT,cAAc,EACd,QAAQ,EACR,WAAW,GACd,EAAE,kBAAkB,+BAmHpB"}
1
+ {"version":3,"file":"vehicle-picker.d.ts","sourceRoot":"","sources":["../../src/business/vehicle-picker.tsx"],"names":[],"mappings":"AAaA,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,aAAa,GAAG,IAAI,CAAA;IAC3B,4EAA4E;IAC5E,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,KAAK,IAAI,CAAA;IACjD,gCAAgC;IAChC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;IACpE,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qGAAqG;IACrG,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,aAAa,CAAA;IAC3D,iEAAiE;IACjE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAQD,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAGxD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,MAAM,EACN,KAAiB,EACjB,QAAQ,EACR,SAAS,EACT,SAAS,EACT,OAAO,EACP,cAAc,EACd,QAAQ,EACR,WAAW,GACd,EAAE,kBAAkB,+BAuFpB"}
@@ -1,18 +1,16 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  // VehiclePicker + alta rápida — busca por placa o VIN (y marca/modelo/cliente que
3
- // el host decida indexar) y reutiliza el <CreateRecordDialog> dinámico del modelo
4
- // vehículo para el alta rápida. Mismo contrato que <CustomerPicker>: controlado
3
+ // el host decida indexar). Configuración del <RecordPicker> compartido: el alta
4
+ // rápida (y la edición del elegido) reutiliza el <CreateRecordDialog> dinámico
5
+ // del modelo vehículo. Mismo contrato que <CustomerPicker>: controlado
5
6
  // (`value` / `onChange`), `search` inyectado por el host, permisos con useCan
6
7
  // (sin <PermissionsProvider> no bloquea nada: el backend autoriza).
7
8
  import { useCallback, useState } from 'react';
8
9
  import { useTranslation } from 'react-i18next';
9
- import { Car, Plus, Search, X } from 'lucide-react';
10
- import { Button, Input } from '@asteby/metacore-ui';
11
- import { CreateRecordDialog } from '../dialogs/create-record-dialog';
12
- import { useApi } from '../api-context';
10
+ import { Car } from 'lucide-react';
11
+ import { RecordPicker, useLatestSearch } from '../record-picker';
12
+ import { useRecordPickerDialog } from '../record-picker-dialog';
13
13
  import { useCan } from '../permissions-context';
14
- import { useAsyncSearch } from './use-async-search';
15
- import { EmptyState } from './feedback';
16
14
  function snake(model) {
17
15
  return model.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();
18
16
  }
@@ -22,19 +20,18 @@ export function describeVehicle(v) {
22
20
  const unit = [v.make, v.model, v.year].filter((x) => x != null && x !== '').join(' ');
23
21
  return [unit, v.plate, v.vin].filter(Boolean).join(' · ');
24
22
  }
25
- export function VehiclePicker({ value, onChange, search, model = 'Vehicle', endpoint, mapRecord, canCreate, createDefaults, disabled, placeholder, }) {
23
+ /**
24
+ * @deprecated Configuración fina de {@link RecordPicker}; se conserva para no
25
+ * romper consumidores.
26
+ */
27
+ export function VehiclePicker({ value, onChange, search, model = 'Vehicle', endpoint, mapRecord, canCreate, canEdit, createDefaults, disabled, placeholder, }) {
26
28
  const { t } = useTranslation();
27
- const api = useApi();
28
29
  const can = useCan();
29
30
  const [text, setText] = useState('');
30
- const [creating, setCreating] = useState(false);
31
- const { results, loading, error } = useAsyncSearch(text, search, { minChars: 2 });
31
+ const [open, setOpen] = useState(false);
32
+ const searchFn = useLatestSearch(search);
32
33
  const mayCreate = canCreate ?? can(`${snake(model)}.create`);
33
- const base = endpoint ?? `/data/${model}/me`;
34
- const pick = (v) => {
35
- onChange(v);
36
- setText('');
37
- };
34
+ const mayEdit = canEdit ?? can(`${snake(model)}.update`);
38
35
  const toResult = useCallback((rec) => mapRecord
39
36
  ? mapRecord(rec)
40
37
  : {
@@ -47,15 +44,18 @@ export function VehiclePicker({ value, onChange, search, model = 'Vehicle', endp
47
44
  color: str(rec.color),
48
45
  customer_id: str(rec.customer_id),
49
46
  }, [mapRecord]);
50
- if (value) {
51
- return (_jsxs("div", { "data-slot": "vehicle-picker", className: "flex items-start justify-between gap-2 rounded-md border p-2", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Car, { className: "mt-0.5 size-4 text-muted-foreground", "aria-hidden": true }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: value.plate || value.vin || t('vehiclePicker.noPlate', { defaultValue: 'Sin placa' }) }), _jsx("p", { className: "text-xs text-muted-foreground", children: [[value.make, value.model, value.year].filter((x) => x != null && x !== '').join(' '), value.vin && value.plate ? value.vin : '', value.customer_name]
47
+ const { openCreate, openEdit, dialog } = useRecordPickerDialog({
48
+ model,
49
+ endpoint,
50
+ prefillField: 'plate',
51
+ createDefaults,
52
+ onSaved: (rec, kind) => {
53
+ const next = toResult(rec);
54
+ onChange(kind === 'edit' && value ? { ...value, ...next } : next);
55
+ setText('');
56
+ },
57
+ });
58
+ return (_jsxs(_Fragment, { children: [_jsx(RecordPicker, { trigger: "input", slot: "vehicle-picker", search: searchFn, minChars: 2, query: text, onQueryChange: setText, open: open, onOpenChange: setOpen, getKey: (v) => v.id, getLabel: (v) => v.plate || v.vin || v.id, getDescription: (v) => [describeVehicle({ ...v, plate: undefined }), v.customer_name].filter(Boolean).join(' · '), value: value?.id ?? null, selected: value, onSelect: (v) => onChange(v), onClear: disabled ? undefined : () => onChange(null), clearLabel: t('vehiclePicker.clear', { defaultValue: 'Quitar vehículo' }), renderValue: (v) => v ? (_jsxs("span", { className: "flex min-w-0 items-start gap-2", children: [_jsx(Car, { className: "mt-0.5 size-4 shrink-0 text-muted-foreground", "aria-hidden": true }), _jsxs("span", { className: "block min-w-0", children: [_jsx("span", { className: "block truncate text-sm font-medium", children: v.plate || v.vin || t('vehiclePicker.noPlate', { defaultValue: 'Sin placa' }) }), _jsx("span", { className: "block truncate text-xs text-muted-foreground", children: [[v.make, v.model, v.year].filter((x) => x != null && x !== '').join(' '), v.vin && v.plate ? v.vin : '', v.customer_name]
52
59
  .filter(Boolean)
53
- .join(' · ') })] })] }), !disabled && (_jsx(Button, { type: "button", size: "icon", variant: "ghost", onClick: () => onChange(null), "aria-label": t('vehiclePicker.clear', { defaultValue: 'Quitar vehículo' }), children: _jsx(X, { className: "size-4" }) }))] }));
54
- }
55
- return (_jsxs("div", { "data-slot": "vehicle-picker", className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(Search, { className: "pointer-events-none absolute left-2.5 top-2.5 size-4 text-muted-foreground", "aria-hidden": true }), _jsx(Input, { className: "pl-8", disabled: disabled, value: text, placeholder: placeholder ?? t('vehiclePicker.placeholder', { defaultValue: 'Placa o VIN' }), onChange: (e) => setText(e.target.value) })] }), mayCreate && (_jsx(Button, { type: "button", variant: "outline", size: "icon", disabled: disabled, onClick: () => setCreating(true), "aria-label": t('vehiclePicker.create', { defaultValue: 'Nuevo vehículo' }), children: _jsx(Plus, { className: "size-4" }) }))] }), loading && _jsx("p", { className: "text-sm text-muted-foreground", children: t('common.searching', { defaultValue: 'Buscando…' }) }), error && !loading && (_jsx("p", { role: "alert", className: "text-sm text-destructive", children: t('vehiclePicker.error', { defaultValue: 'No se pudo buscar vehículos. Inténtalo de nuevo.' }) })), !loading && !error && text.trim().length >= 2 && results.length === 0 && (_jsx(EmptyState, { title: t('vehiclePicker.empty', { defaultValue: 'No encontramos ese vehículo' }), action: mayCreate ? { label: t('vehiclePicker.createAction', { defaultValue: 'Crear vehículo' }), onClick: () => setCreating(true) } : undefined })), results.length > 0 && (_jsx("ul", { role: "listbox", className: "max-h-64 divide-y overflow-auto rounded-md border", children: results.map((v) => (_jsx("li", { role: "option", "aria-selected": false, children: _jsxs("button", { type: "button", className: "flex w-full flex-col px-2 py-1.5 text-left hover:bg-accent", onClick: () => pick(v), children: [_jsx("span", { className: "text-sm font-medium", children: v.plate || v.vin || v.id }), _jsx("span", { className: "text-xs text-muted-foreground", children: [describeVehicle({ ...v, plate: undefined }), v.customer_name].filter(Boolean).join(' · ') })] }) }, v.id))) })), creating && (_jsx(CreateRecordDialog, { modelKey: model, open: creating, onOpenChange: setCreating, endpoint: base, defaults: createDefaults ?? (text.trim() ? { plate: text.trim() } : undefined), onCreate: async (data) => {
56
- const res = await api.post(base, data);
57
- const rec = (res.data?.data ?? res.data);
58
- pick(toResult(rec));
59
- return rec.id != null ? { id: String(rec.id) } : undefined;
60
- } }))] }));
60
+ .join(' · ') })] })] })) : null, disabled: disabled, placeholder: placeholder ?? t('vehiclePicker.placeholder', { defaultValue: 'Placa o VIN' }), loadingText: t('common.searching', { defaultValue: 'Buscando…' }), errorText: t('vehiclePicker.error', { defaultValue: 'No se pudo buscar vehículos. Inténtalo de nuevo.' }), emptyText: t('vehiclePicker.empty', { defaultValue: 'No encontramos ese vehículo' }), entityLabel: t('vehiclePicker.entity', { defaultValue: 'vehículo' }), createLabel: t('vehiclePicker.create', { defaultValue: 'Nuevo vehículo' }), editLabel: t('vehiclePicker.edit', { defaultValue: 'Editar vehículo' }), createFooter: "empty", createFooterLabel: () => t('vehiclePicker.createAction', { defaultValue: 'Crear vehículo' }), onCreate: mayCreate ? (q) => openCreate(q) : undefined, onEdit: mayEdit && value ? () => openEdit(value.id) : undefined }), dialog] }));
61
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAkD1C,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAsB3C,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEnE,OAAO,EAAqC,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAK1F,YAAY,EAAE,WAAW,EAAE,CAAA;AAE3B,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,QAAQ;IACrB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAA;IACpH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,WAAW,EAAE,CAAA;IACvB,YAAY,CAAC,EAAE,GAAG,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;OAQG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACjC;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,SAAS,EAAE,CAAA;IACxB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,SAAS,EAAE,CAAA;IACzB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,WAAW,CAAA;IAC1B,0CAA0C;IAC1C,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB;AAkDD,MAAM,WAAW,wBAAwB;IACrC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC;;;;OAIG;IACH,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAA;IACzB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAA;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;2DAEuD;IACvD,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IAClF;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IACpG;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC9B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAA;IAC1C;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACxB;AASD,wBAAgB,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS,CAK1D;AAaD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAG,GAAG,CAgBtE;AAID,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,EAAE,GAAG,SAAS,CAExE;AAQD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAerE;AASD,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,cAAc,GAAG,IAAI,CAa5F;AA+GD,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAUjE;AAaD,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,EAC9B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,EAChC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChC,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC5B,QAAQ,EAAE,CAQZ;AAUD,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,EAC9B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,EAChC,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CASrB;AAiBD,wBAAgB,mBAAmB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,sBAAsB,EACtB,YAAY,EACZ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,MAAM,EACN,cAAc,EACd,aAAa,EACb,WAA8B,EAC9B,QAAQ,EACR,QAAQ,EACR,QAAQ,GACX,EAAE,wBAAwB,+BAgpB1B;AAwED,wBAAgB,iBAAiB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE,+BAelF;AA+GD,wBAAgB,SAAS,CAAC,EACtB,KAAK,EACL,KAAK,EAAE,QAAQ,EACf,MAAM,EACN,WAAW,EAAE,eAAe,EAC5B,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,YAAY,GACzB,EAAE;IACC,KAAK,EAAE,QAAQ,CAAA;IACf,KAAK,EAAE,GAAG,CAAA;IACV,MAAM,EAAE,GAAG,CAAA;IACX,mFAAmF;IACnF,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB,+BA6SA;AAwLD,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;IACnE,KAAK,EAAE,QAAQ,CAAA;IACf,KAAK,EAAE,GAAG,CAAA;IACV,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC5B,iFAAiF;IACjF,MAAM,CAAC,EAAE,GAAG,CAAA;IACZ,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAA;CACpB,+BAmOA"}
1
+ {"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"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"}
@@ -16,18 +16,19 @@ import { useTranslation } from 'react-i18next';
16
16
  /** Model key of the open create/edit dialog — used to hide "+" on self-FK pickers
17
17
  * (e.g. Customer.parent_id) so they don't nest another "Crear Cliente" modal. */
18
18
  const RecordDialogModelContext = createContext(undefined);
19
- import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, Button, Input, Textarea, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Switch, Skeleton, Badge, Popover, PopoverContent, PopoverTrigger, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Calendar, } from '@asteby/metacore-ui/primitives';
19
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, Button, Input, Textarea, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Switch, Skeleton, Badge, Popover, PopoverContent, PopoverTrigger, Calendar, } from '@asteby/metacore-ui/primitives';
20
20
  import { cn } from '@asteby/metacore-ui/lib';
21
21
  import { toast } from 'sonner';
22
22
  import { format, parseISO } from 'date-fns';
23
23
  import { parseCalendarDate } from '../calendar-date';
24
24
  import { es } from 'date-fns/locale';
25
- import { ExternalLink, Loader2, CalendarIcon, ChevronDown, Check, Upload, X as XIcon, ScanLine } from 'lucide-react';
25
+ import { ExternalLink, Loader2, CalendarIcon, Upload, X as XIcon, ScanLine } from 'lucide-react';
26
26
  import { BarcodeScanner } from '../barcode-scanner';
27
27
  import { useApi } from '../api-context';
28
28
  import { useBranchCreateGate } from '../branch-create-gate';
29
29
  import { toastServerError, extractFieldErrors, localizeFieldIssue, localizeFieldErrorMap } from '../server-error';
30
30
  import { DynamicSelectField, OptionLead, OptionThumb } from '../dynamic-select-field';
31
+ import { RecordPicker } from '../record-picker';
31
32
  import { DynamicMultiSelectField } from '../dynamic-multi-select-field';
32
33
  import { DynamicRelations } from '../dynamic-relations';
33
34
  import { AuditInfo, readAuditMeta } from '../audit-info';
@@ -1305,15 +1306,12 @@ function extractArray(res) {
1305
1306
  const searchCache = new Map();
1306
1307
  function SearchField({ field, value, onChange }) {
1307
1308
  const api = useApi();
1308
- const [open, setOpen] = useState(false);
1309
- const [query, setQuery] = useState('');
1310
- const [results, setResults] = useState([]);
1311
- const [loading, setLoading] = useState(false);
1312
1309
  const [selectedLabel, setSelectedLabel] = useState('');
1310
+ const ep = field.searchEndpoint;
1313
1311
  useEffect(() => {
1314
- if (!value || !field.searchEndpoint)
1312
+ if (!value || !ep)
1315
1313
  return;
1316
- const cached = searchCache.get(field.searchEndpoint);
1314
+ const cached = searchCache.get(ep);
1317
1315
  if (cached) {
1318
1316
  const match = cached.find((item) => item.value === value || item.id === value);
1319
1317
  if (match) {
@@ -1321,45 +1319,32 @@ function SearchField({ field, value, onChange }) {
1321
1319
  return;
1322
1320
  }
1323
1321
  }
1324
- api.get(field.searchEndpoint, { params: { search: '', limit: 50 } }).then(res => {
1322
+ api.get(ep, { params: { search: '', limit: 50 } }).then(res => {
1325
1323
  const items = extractArray(res);
1326
- searchCache.set(field.searchEndpoint, items);
1324
+ searchCache.set(ep, items);
1327
1325
  const match = items.find((item) => item.value === value || item.id === value);
1328
1326
  if (match)
1329
1327
  setSelectedLabel(match.label || match.name || '');
1330
1328
  }).catch(() => { });
1331
- }, [value, field.searchEndpoint, api]);
1332
- useEffect(() => {
1333
- if (!open || !field.searchEndpoint)
1334
- return;
1335
- if (!query) {
1336
- const cached = searchCache.get(field.searchEndpoint);
1337
- if (cached) {
1338
- setResults(cached);
1339
- return;
1340
- }
1329
+ }, [value, ep, api]);
1330
+ // Legacy `type: search` + searchEndpoint — same <RecordPicker> as every
1331
+ // relation field; the empty query is served from the per-endpoint cache.
1332
+ const search = useCallback(async (q) => {
1333
+ if (!q) {
1334
+ const cached = searchCache.get(ep);
1335
+ if (cached)
1336
+ return cached;
1341
1337
  }
1342
- setLoading(true);
1343
- const timer = setTimeout(() => {
1344
- api.get(field.searchEndpoint, { params: { search: query, limit: 20 } }).then(res => {
1345
- const items = extractArray(res);
1346
- if (!query)
1347
- searchCache.set(field.searchEndpoint, items);
1348
- setResults(items);
1349
- }).catch(() => setResults([]))
1350
- .finally(() => setLoading(false));
1351
- }, query ? 250 : 0);
1352
- return () => clearTimeout(timer);
1353
- }, [query, open, field.searchEndpoint, api]);
1354
- return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", role: "combobox", className: cn("w-full justify-between font-normal h-9", !value && "text-muted-foreground"), children: [_jsx("span", { className: "truncate", children: selectedLabel || `Seleccionar ${field.label?.toLowerCase() || ''}...` }), _jsx(ChevronDown, { className: "ml-auto h-4 w-4 shrink-0 opacity-50" })] }) }), _jsx(PopoverContent, { className: "w-[--radix-popover-trigger-width] p-0", align: "start", side: "bottom", sideOffset: 4, children: _jsxs(Command, { shouldFilter: false, children: [_jsx(CommandInput, { placeholder: `Buscar ${field.label?.toLowerCase() || ''}...`, value: query, onValueChange: setQuery }), _jsx(CommandList, { className: "max-h-[200px]", children: loading ? (_jsxs("div", { className: "py-6 text-center text-sm", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin mx-auto mb-1 text-muted-foreground" }), _jsx("span", { className: "text-muted-foreground text-xs", children: "Buscando..." })] })) : results.length === 0 ? (_jsx(CommandEmpty, { children: "Sin resultados." })) : (_jsx(CommandGroup, { children: results.map((item) => {
1355
- const itemValue = item.value ?? item.id;
1356
- const itemLabel = item.label ?? item.name ?? '';
1357
- const isSelected = value === itemValue;
1358
- return (_jsxs(CommandItem, { value: String(itemValue), onSelect: () => {
1359
- onChange(itemValue);
1360
- setSelectedLabel(itemLabel);
1361
- setOpen(false);
1362
- setQuery('');
1363
- }, children: [isSelected && _jsx(Check, { className: "mr-2 h-3.5 w-3.5 shrink-0 text-primary" }), _jsx(OptionThumb, { image: item.image, name: itemLabel, size: 20 }), _jsxs("div", { className: "flex flex-col min-w-0 ml-2", children: [_jsx("span", { className: "truncate", children: itemLabel }), item.description && (_jsx("span", { className: "text-[11px] text-muted-foreground truncate", children: item.description }))] })] }, itemValue));
1364
- }) })) })] }) })] }));
1338
+ const items = extractArray(await api.get(ep, { params: { search: q, limit: 20 } }));
1339
+ if (!q)
1340
+ searchCache.set(ep, items);
1341
+ return items;
1342
+ }, [api, ep]);
1343
+ const itemValue = (item) => item.value ?? item.id;
1344
+ const itemLabel = (item) => item.label ?? item.name ?? '';
1345
+ const what = field.label?.toLowerCase() || '';
1346
+ return (_jsx(RecordPicker, { search: search, minChars: 0, getKey: (item) => String(itemValue(item)), getLabel: itemLabel, getDescription: (item) => item.description, renderLead: (item) => _jsx(OptionThumb, { image: item.image, name: itemLabel(item), size: 20 }), value: value, selected: value ? { value, label: selectedLabel } : null, renderValue: () => (_jsx("span", { className: cn('min-w-0 flex-1 truncate', !selectedLabel && 'text-muted-foreground'), children: selectedLabel || `Seleccionar ${what}...` })), onSelect: (item) => {
1347
+ onChange(itemValue(item));
1348
+ setSelectedLabel(itemLabel(item));
1349
+ }, searchPlaceholder: `Buscar ${what}...`, emptyText: "Sin resultados." }));
1365
1350
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-multi-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-multi-select-field.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,MAAM,WAAW,4BAA4B;IACzC,KAAK,EAAE,cAAc,CAAA;IACrB,qFAAqF;IACrF,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CACtC;AAED,wBAAgB,uBAAuB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,4BAA4B,+BA2B/F"}
1
+ {"version":3,"file":"dynamic-multi-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-multi-select-field.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,MAAM,WAAW,4BAA4B;IACzC,KAAK,EAAE,cAAc,CAAA;IACrB,qFAAqF;IACrF,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CACtC;AAED,wBAAgB,uBAAuB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,4BAA4B,+BA0D/F"}
@@ -13,19 +13,27 @@ import { jsx as _jsx } from "react/jsx-runtime";
13
13
  //
14
14
  // Options are resolved once (a single page, not per-keystroke) through the
15
15
  // same canonical `/api/options/<ref>?field=id` endpoint DynamicSelectField
16
- // uses — the MultiSelect primitive then filters that page client-side as the
16
+ // uses — the shared <RecordPicker multiple> then filters that page client-side as the
17
17
  // user types. That's the right tradeoff for the FK sets this targets
18
18
  // (segments, tags, categories — tens, not thousands of rows); a field with a
19
19
  // genuinely large option set should keep using a single dynamic_select per
20
20
  // value instead.
21
- import { useMemo } from 'react';
22
- import { MultiSelect } from '@asteby/metacore-ui/primitives';
21
+ //
22
+ // Selected ids outside that page (or hidden by an option_filter) are labelled
23
+ // with ONE `?ids=` lookup (useResolveOptionIds): a chip reads "Cargando…" while
24
+ // it resolves and "(registro eliminado)" when the record is gone — never the id.
25
+ import { useMemo, useState } from 'react';
23
26
  import { getOptionFilter } from './option-filter';
27
+ import { RecordPicker } from './record-picker';
28
+ import { OptionLead } from './record-picker-option';
24
29
  import { useOptionsResolver } from './use-options-resolver';
30
+ import { useResolveOptionIds } from './use-option-ids';
31
+ import { DELETED_RECORD_LABEL } from './dynamic-select-field';
25
32
  import { getFieldRef } from './dynamic-form-schema';
26
33
  export function DynamicMultiSelectField({ field, value, onChange }) {
27
34
  const ref = getFieldRef(field);
28
- const { options, loading } = useOptionsResolver({
35
+ const [query, setQuery] = useState('');
36
+ const { options, loading, meta, error } = useOptionsResolver({
29
37
  modelKey: '',
30
38
  fieldKey: 'id',
31
39
  ref,
@@ -34,6 +42,28 @@ export function DynamicMultiSelectField({ field, value, onChange }) {
34
42
  optionFilter: getOptionFilter(field),
35
43
  });
36
44
  const selected = useMemo(() => (Array.isArray(value) ? value.map(String) : []), [value]);
37
- const uiOptions = useMemo(() => options.map((o) => ({ value: String(o.id), label: o.label })), [options]);
38
- return (_jsx(MultiSelect, { options: uiOptions, selected: selected, onChange: onChange, placeholder: loading ? 'Cargando…' : (field.placeholder || 'Seleccionar...'), searchPlaceholder: "Buscar...", emptyMessage: "Sin resultados." }));
45
+ const endpoint = !ref && field.searchEndpoint ? field.searchEndpoint : undefined;
46
+ // Ask for the ids the loaded page does not cover — only once it is in.
47
+ const pageSettled = !loading && (meta !== null || error !== null);
48
+ const unresolved = pageSettled ? selected.filter((id) => !options.some((o) => String(o.id) === id)) : [];
49
+ const { resolved } = useResolveOptionIds({ ref, endpoint, field: 'id', ids: unresolved, enabled: unresolved.length > 0 });
50
+ const selectedItems = selected.map((id) => {
51
+ const loaded = options.find((o) => String(o.id) === id);
52
+ if (loaded)
53
+ return loaded;
54
+ const r = pageSettled ? resolved.get(id) : undefined;
55
+ if (r?.status === 'found')
56
+ return r.option;
57
+ const label = !r ? 'Cargando…' : r.status === 'missing' ? DELETED_RECORD_LABEL : id;
58
+ return { id, value: id, label, name: label };
59
+ });
60
+ const shown = useMemo(() => {
61
+ const q = query.trim().toLowerCase();
62
+ return q ? options.filter((o) => String(o.label ?? '').toLowerCase().includes(q)) : options;
63
+ }, [options, query]);
64
+ const toggle = (o) => {
65
+ const id = String(o.id);
66
+ onChange(selected.includes(id) ? selected.filter((x) => x !== id) : [...selected, id]);
67
+ };
68
+ return (_jsx(RecordPicker, { multiple: true, slot: "dynamic-multi-select", id: field.key, items: shown, loading: loading, getKey: (o) => String(o.id), getLabel: (o) => o.label, renderLead: (o) => _jsx(OptionLead, { option: o, size: 20 }), getDescription: (o) => o.description, value: selected, selected: selectedItems, onSelect: toggle, onRemove: toggle, query: query, onQueryChange: setQuery, placeholder: loading ? 'Cargando…' : field.placeholder || 'Seleccionar...', searchPlaceholder: "Buscar...", emptyText: "Sin resultados." }));
39
69
  }
@@ -1,34 +1,14 @@
1
1
  import { type ResolvedOption } from './use-options-resolver';
2
2
  import type { ActionFieldDef } from './types';
3
+ export { OptionLead, OptionThumb } from './record-picker-option';
3
4
  /**
4
5
  * Default hint shown when a cascading picker's depended-on field is still
5
6
  * empty. Domain-neutral on purpose; a caller may override it per field via
6
7
  * `dependsHint`.
7
8
  */
8
9
  export declare const DEFAULT_DEPENDS_HINT = "Selecciona primero el campo del que depende";
9
- /**
10
- * Small square thumbnail for an option's `image`. When the option has no image
11
- * it falls back to a deterministic initials avatar (shared `InitialsAvatar`)
12
- * derived from `name`, so an imageless reference reads as a colored badge rather
13
- * than an empty placeholder — and rows/triggers stay aligned. `size` is in
14
- * pixels (kept small — 20–24px — so the picker reads as a list, not a gallery).
15
- * Inline style for the box dimensions: arbitrary Tailwind classes from a
16
- * federated addon don't always survive the host's class scan.
17
- */
18
- export declare function OptionThumb({ image, name, size, }: {
19
- image?: string | null;
20
- name?: string | null;
21
- size?: number;
22
- }): import("react").JSX.Element;
23
- /**
24
- * Leading visual for an option: a photo thumbnail (FK relations with an image),
25
- * else a declared icon, else a color dot (enum/status options with a color).
26
- * Returns null when the option carries none, so plain text options stay plain.
27
- */
28
- export declare function OptionLead({ option, size, }: {
29
- option?: Pick<ResolvedOption, 'image' | 'color' | 'icon' | 'label'> | null;
30
- size?: number;
31
- }): import("react").JSX.Element | null;
10
+ /** Label of a held value whose record no longer exists (or is not visible). */
11
+ export declare const DELETED_RECORD_LABEL = "(registro eliminado)";
32
12
  export interface DynamicSelectFieldProps {
33
13
  field: ActionFieldDef;
34
14
  value: any;
@@ -94,6 +74,12 @@ export interface DynamicSelectFieldProps {
94
74
  /** Paint trigger with destructive border when validation failed. */
95
75
  invalid?: boolean;
96
76
  }
77
+ /**
78
+ * Declarative `dynamic_select` (manifest `ref` / `optionsConfig.source`) on top
79
+ * of the shared {@link RecordPicker}: options from the canonical options
80
+ * endpoint (`useOptionsResolver`: option_filter, options[].when keep-value,
81
+ * cascade `filter_value`), inline create/edit through the host modal events.
82
+ */
97
83
  export declare function DynamicSelectField({ field, value, onChange, onPick, seedOption, dependsValue, dependsHint, readonly, staticOptions, descriptionAsBadge, hideCreate, createDefaults, createLockedFields, invalid, }: DynamicSelectFieldProps): import("react").JSX.Element;
98
84
  export default DynamicSelectField;
99
85
  //# sourceMappingURL=dynamic-select-field.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-select-field.tsx"],"names":[],"mappings":"AA6CA,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,+BA4BA;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;AAMD,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,GAAG,CAAA;IACV,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;IAC1B,yFAAyF;IACzF,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAA;IACtC;;;;;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;IAClB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAAA;IAChD;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC7B,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,wBAAgB,kBAAkB,CAAC,EAC/B,KAAK,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAgB,EAChB,aAAoB,EACpB,kBAA0B,EAC1B,UAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,OAAe,GAClB,EAAE,uBAAuB,+BA0VzB;AAED,eAAe,kBAAkB,CAAA"}
1
+ {"version":3,"file":"dynamic-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-select-field.tsx"],"names":[],"mappings":"AAkCA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAIhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEhE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,gDAAgD,CAAA;AAEjF,+EAA+E;AAC/E,eAAO,MAAM,oBAAoB,yBAAyB,CAAA;AAE1D,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,GAAG,CAAA;IACV,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;IAC1B,yFAAyF;IACzF,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAA;IACtC;;;;;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;IAClB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAAA;IAChD;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC7B,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAA;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAC/B,KAAK,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAgB,EAChB,aAAoB,EACpB,kBAA0B,EAC1B,UAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,OAAe,GAClB,EAAE,uBAAuB,+BAqPzB;AAED,eAAe,kBAAkB,CAAA"}