@asteby/metacore-runtime-react 49.9.0 → 49.9.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @asteby/metacore-runtime-react
2
2
 
3
+ ## 49.9.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 6956adf: DocumentEditor: el buscador del renglón vacío ocupa SOLO la celda «Descripción», como cualquier renglón; ya no invade Cant., Precio ni Desc. Se quita el tooltip nativo del navegador del buscador: la ayuda larga sigue en el estado sin coincidencias.
8
+
3
9
  ## 49.9.0
4
10
 
5
11
  ### Minor Changes
@@ -210,7 +210,7 @@ function toNum(n) {
210
210
  function DraftRow({ search, warehouseId, currency, onPick, onFree, onAddBlank, onCreate, entityLabel, span, }) {
211
211
  const { t } = useTranslation();
212
212
  const [text, setText] = useState('');
213
- return (_jsxs("tr", { className: "border-t border-dashed", "data-slot": "line-draft-row", children: [_jsx("td", { className: CELL, colSpan: span, children: _jsx(LineProductCell, { search: search, text: text, onTextChange: setText, onPick: (p, v) => {
213
+ return (_jsxs("tr", { className: "border-t border-dashed", "data-slot": "line-draft-row", children: [_jsx("td", { className: CELL, children: _jsx(LineProductCell, { search: search, text: text, onTextChange: setText, onPick: (p, v) => {
214
214
  setText('');
215
215
  onPick(p, v);
216
216
  }, onKeyDownClosed: (e) => {
@@ -228,7 +228,7 @@ function DraftRow({ search, warehouseId, currency, onPick, onFree, onAddBlank, o
228
228
  setText('');
229
229
  onCreate(q);
230
230
  }
231
- : undefined, entityLabel: entityLabel }) }), _jsx("td", { "aria-hidden": true }), _jsx("td", { "aria-hidden": true })] }));
231
+ : undefined, entityLabel: entityLabel }) }), Array.from({ length: Math.max(0, span - 1) }, (_, i) => (_jsx("td", { "aria-hidden": true }, i))), _jsx("td", { "aria-hidden": true }), _jsx("td", { "aria-hidden": true })] }));
232
232
  }
233
233
  /** Fila de totales alineada a la columna «Importe». */
234
234
  function TotalRow({ span, label, value, slot, strong }) {
@@ -25,5 +25,5 @@ export const LineProductCell = forwardRef(function LineProductCell({ search, tex
25
25
  const { hits, loading, minChars } = useProductSearch(typing ? text : '', search, typing);
26
26
  const entity = entityLabel ?? t('lineItems.productEntity', { defaultValue: 'producto' });
27
27
  const searchHint = hint ?? t('lineItems.searchHint', { defaultValue: 'Busca por nombre, SKU o código de barras' });
28
- return (_jsx(RecordPicker, { trigger: "input", variant: "cell", freeText: true, anchorSlot: "line-product-cell", contentSlot: "line-product-results", minListWidth: "26.25rem", maxListWidth: "35rem", items: hits, loading: loading, minChars: minChars, query: text, onQueryChange: onTextChange, open: typing, onOpenChange: setTyping, getKey: productHitKey, getLabel: productHitLabel, renderItem: (hit) => _jsx(ProductHitRow, { hit: hit, warehouseId: warehouseId, currency: currency, compact: true }), onSelect: (hit) => onPick(hit.product, hit.variant), onUnhandledKeyDown: onKeyDownClosed, inputRef: ref, ariaLabel: ariaLabel, listLabel: ariaLabel, disabled: disabled, invalid: invalid, triggerClassName: className, triggerProps: { 'data-cell': dataCell, title: searchHint }, placeholder: placeholder ?? t('lineItems.searchPlaceholderShort', { defaultValue: 'Buscar producto…' }), loadingText: t('common.searching', { defaultValue: 'Buscando…' }), emptyText: _jsxs("span", { className: "block space-y-1", children: [_jsx("span", { className: "block", children: t('lineItems.noProduct', { defaultValue: 'Sin coincidencias. Se usará como descripción libre.' }) }), _jsx("span", { className: "block text-xs", children: searchHint })] }), onCreate: onCreate, entityLabel: entity, createLabel: t('lineItems.createProduct', { defaultValue: 'Crear {{entity}}', entity }), createFooterLabel: (q) => (_jsxs(_Fragment, { children: [t('lineItems.createProduct', { defaultValue: 'Crear {{entity}}', entity }), q ? _jsxs("span", { className: "text-muted-foreground", children: [" \u00AB", q, "\u00BB"] }) : null] })) }));
28
+ return (_jsx(RecordPicker, { trigger: "input", variant: "cell", freeText: true, anchorSlot: "line-product-cell", contentSlot: "line-product-results", minListWidth: "26.25rem", maxListWidth: "35rem", items: hits, loading: loading, minChars: minChars, query: text, onQueryChange: onTextChange, open: typing, onOpenChange: setTyping, getKey: productHitKey, getLabel: productHitLabel, renderItem: (hit) => _jsx(ProductHitRow, { hit: hit, warehouseId: warehouseId, currency: currency, compact: true }), onSelect: (hit) => onPick(hit.product, hit.variant), onUnhandledKeyDown: onKeyDownClosed, inputRef: ref, ariaLabel: ariaLabel, listLabel: ariaLabel, disabled: disabled, invalid: invalid, triggerClassName: className, triggerProps: { 'data-cell': dataCell }, placeholder: placeholder ?? t('lineItems.searchPlaceholderShort', { defaultValue: 'Buscar producto…' }), loadingText: t('common.searching', { defaultValue: 'Buscando…' }), emptyText: _jsxs("span", { className: "block space-y-1", children: [_jsx("span", { className: "block", children: t('lineItems.noProduct', { defaultValue: 'Sin coincidencias. Se usará como descripción libre.' }) }), _jsx("span", { className: "block text-xs", children: searchHint })] }), onCreate: onCreate, entityLabel: entity, createLabel: t('lineItems.createProduct', { defaultValue: 'Crear {{entity}}', entity }), createFooterLabel: (q) => (_jsxs(_Fragment, { children: [t('lineItems.createProduct', { defaultValue: 'Crear {{entity}}', entity }), q ? _jsxs("span", { className: "text-muted-foreground", children: [" \u00AB", q, "\u00BB"] }) : null] })) }));
29
29
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "49.9.0",
3
+ "version": "49.9.1",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -47,17 +47,17 @@ describe('DocumentLinesGrid — select de producto en la celda', () => {
47
47
  const input = screen.getByRole('combobox', { name: 'Buscar producto' })
48
48
  const td = input.closest('td')!
49
49
  expect(td).toBeTruthy()
50
- // No es una barra a todo lo ancho: el renglón vacío conserva las celdas
51
- // de «Importe» y acciones; el buscador usa el ancho de las columnas que
52
- // ese renglón aún no llena (cantidad, precio…), así no se corta.
50
+ // Ocupa SOLO su columna: no invade Cant./Precio/Desc.; el renglón vacío
51
+ // tiene una celda por columna del encabezado.
53
52
  const row = td.closest('tr')!
54
53
  expect(row.getAttribute('data-slot')).toBe('line-draft-row')
55
54
  const columns = document.querySelectorAll('[data-slot="line-items-editor"] thead th').length
56
- expect(td.colSpan).toBe(columns - 2)
57
- expect(row.children.length).toBe(3)
58
- // Placeholder corto que cabe; el detalle va como ayuda.
55
+ expect(td.colSpan).toBe(1)
56
+ expect(row.children.length).toBe(columns)
57
+ expect(row.firstElementChild).toBe(td)
58
+ // Placeholder corto que cabe, sin tooltip nativo del navegador.
59
59
  expect(input.getAttribute('placeholder')).toBe('Buscar producto…')
60
- expect(input.getAttribute('title')).toMatch(/SKU o código de barras/)
60
+ expect(input.hasAttribute('title')).toBe(false)
61
61
  })
62
62
 
63
63
  it('la lista sale en un portal fuera del contenedor con overflow y Enter elige y pasa a «Cant.»', async () => {
@@ -675,7 +675,7 @@ function DraftRow({
675
675
  entityLabel,
676
676
  span,
677
677
  }: {
678
- /** Columnas que ocupa el buscador (todas menos «Importe» y acciones). */
678
+ /** Columnas antes de «Importe» y acciones; el buscador ocupa solo la primera. */
679
679
  span: number
680
680
  onCreate?: (query: string) => void
681
681
  entityLabel?: string
@@ -690,10 +690,10 @@ function DraftRow({
690
690
  const [text, setText] = useState('')
691
691
  return (
692
692
  <tr className="border-t border-dashed" data-slot="line-draft-row">
693
- {/* El renglón vacío no tiene cantidad ni precio todavía: el buscador
694
- usa ese ancho (antes medía solo la columna «Descripción» y el
695
- texto de ayuda se cortaba). */}
696
- <td className={CELL} colSpan={span}>
693
+ {/* El buscador vive SOLO en la celda «Descripción», como cualquier
694
+ renglón: no invade Cant./Precio/Desc. (esas celdas quedan vacías
695
+ hasta elegir producto). */}
696
+ <td className={CELL}>
697
697
  <LineProductCell
698
698
  search={search}
699
699
  text={text}
@@ -726,6 +726,9 @@ function DraftRow({
726
726
  entityLabel={entityLabel}
727
727
  />
728
728
  </td>
729
+ {Array.from({ length: Math.max(0, span - 1) }, (_, i) => (
730
+ <td key={i} aria-hidden />
731
+ ))}
729
732
  <td aria-hidden />
730
733
  <td aria-hidden />
731
734
  </tr>
@@ -98,7 +98,7 @@ export const LineProductCell = forwardRef<HTMLInputElement, LineProductCellProps
98
98
  disabled={disabled}
99
99
  invalid={invalid}
100
100
  triggerClassName={className}
101
- triggerProps={{ 'data-cell': dataCell, title: searchHint }}
101
+ triggerProps={{ 'data-cell': dataCell }}
102
102
  placeholder={placeholder ?? t('lineItems.searchPlaceholderShort', { defaultValue: 'Buscar producto…' })}
103
103
  loadingText={t('common.searching', { defaultValue: 'Buscando…' })}
104
104
  emptyText={