@softize/opus 8.6.7 → 8.6.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softize/opus",
3
- "version": "8.6.7",
3
+ "version": "8.6.9",
4
4
  "description": "End-to-end action protocol for TypeScript. Single package with subpath exports (core + adapters).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -361,6 +361,12 @@ export function ActionFormField({ name, options: optionsProp, className }: Actio
361
361
  value={(formValues[name] as string | undefined) ?? ''}
362
362
  onChange={(v) => setValue(v)}
363
363
  options={options}
364
+ // A régua do próprio Select: lista curta e conhecida se percorre com o olho;
365
+ // lista longa se ACHA digitando. O corte é por TAMANHO e não por call site
366
+ // porque o form é contract-driven — quem declara o campo não deveria precisar
367
+ // saber se o dicionário dele cresceu. (Veio de patch da Grand Brasil; subiu em
368
+ // 8.6.9 porque patch local morre calado a cada bump.)
369
+ searchable={options.length > 6}
364
370
  placeholder={spec.placeholder ?? 'Selecione…'}
365
371
  className="w-full"
366
372
  />
@@ -220,6 +220,16 @@ export interface ActionListProps<TInput, TItem> {
220
220
  /** Ações POR LINHA (coluna final, alinhada à direita) — apresentação de quem chama,
221
221
  * como `cells`. Cliques ali não disparam o onRowClick. Só na tabela. */
222
222
  rowActions?: (item: TItem) => ReactNode
223
+ /**
224
+ * Conteúdo entre a toolbar e o corpo da listagem — ex.: o resumo do recorte atual
225
+ * ("12 itens, R$ 4.300 no período"), que precisa reagir ao filtro e por isso não cabe
226
+ * fora do componente.
227
+ *
228
+ * Veio de um patch que a Grand Brasil carregava sobre o pacote. Patch local é sinal:
229
+ * enquanto viveu assim, todo bump do Opus o descartava em silêncio e o app parava de
230
+ * compilar sem ninguém entender por quê. Subiu pra cá em 8.6.9.
231
+ */
232
+ beforeContent?: ReactNode
223
233
  /** Modo COMPOSIÇÃO: layout livre ÚNICO (sem segment); toolbar e estados seguem. */
224
234
  children?: (items: TItem[], refetch: () => Promise<void>) => ReactNode
225
235
  /** Estado da toolbar CONTROLADO (URL sync de quem embala). Default: interno. */
@@ -693,6 +703,7 @@ export function ActionList<TInput, TItem>({
693
703
  loading: extraLoading,
694
704
  onRowClick,
695
705
  rowActions,
706
+ beforeContent,
696
707
  children,
697
708
  state: controlledState,
698
709
  onStateChange,
@@ -1369,6 +1380,7 @@ export function ActionList<TInput, TItem>({
1369
1380
  <TooltipProvider>
1370
1381
  <div data-action={action.name} className="space-y-3">
1371
1382
  {toolbar}
1383
+ {beforeContent}
1372
1384
  {selectionBar}
1373
1385
  {/* Refetch com a lista já na tela: esmaece e trava interação até chegar. */}
1374
1386
  <div aria-busy={busy} className={cn(busy && items.length > 0 && 'pointer-events-none opacity-60')}>
@@ -223,6 +223,23 @@ function CustomSelect(props: Exclude<SelectProps, SelectNativeProps>): React.Rea
223
223
  setQuery(selectedOption?.label ?? '')
224
224
  }, [singleValue, selectedOption, open])
225
225
 
226
+ /**
227
+ * ABRIR limpa a busca.
228
+ *
229
+ * O rótulo do item escolhido vive no mesmo estado que o termo de busca (é o mesmo
230
+ * input). Sem isto, abrir o seletor herda esse rótulo como CONSULTA: a lista nasce
231
+ * filtrada pelo nome do que já está selecionado — e some justamente quando a pessoa
232
+ * abriu pra trocar. Com `onSearch`, o efeito abaixo ainda dispara uma busca remota por
233
+ * essa frase, que quase nunca casa com outra coisa.
234
+ *
235
+ * Visto em produção duas vezes no mesmo dia: o seletor de task da cabine buscando
236
+ * "Sem task", e o de modelo de IA buscando o nome do modelo corrente. Nos dois, a
237
+ * pessoa via lista vazia com dados no servidor.
238
+ */
239
+ React.useEffect(() => {
240
+ if (open) setQuery('')
241
+ }, [open])
242
+
226
243
  // O cmdk carimba o id DELE no input (a11y interna) e descarta o nosso — reaplicamos por
227
244
  // ref, senão o `htmlFor` do Label não acha campo nenhum (clicar no rótulo não focaria).
228
245
  React.useEffect(() => {