@aurea-uds/react 0.1.0 → 0.3.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/README.md +34 -2
- package/dist/actions.d.ts +20 -0
- package/dist/actions.js +59 -5
- package/dist/agents.d.ts +209 -0
- package/dist/agents.js +302 -0
- package/dist/calendar.d.ts +6 -0
- package/dist/calendar.js +27 -0
- package/dist/chart.d.ts +10 -0
- package/dist/chart.js +53 -0
- package/dist/code-client.d.ts +6 -0
- package/dist/code-client.js +24 -0
- package/dist/code-editor.js +1 -0
- package/dist/code.d.ts +2 -13
- package/dist/code.js +5 -18
- package/dist/communication.js +1 -0
- package/dist/data-display-client.d.ts +14 -0
- package/dist/data-display-client.js +22 -0
- package/dist/data-display.d.ts +2 -23
- package/dist/data-display.js +5 -13
- package/dist/data-grid.d.ts +52 -3
- package/dist/data-grid.js +205 -25
- package/dist/feedback-client.d.ts +64 -0
- package/dist/feedback-client.js +110 -0
- package/dist/feedback.d.ts +2 -53
- package/dist/feedback.js +5 -71
- package/dist/file-input.d.ts +21 -2
- package/dist/file-input.js +202 -21
- package/dist/graph.d.ts +33 -0
- package/dist/graph.js +178 -0
- package/dist/identity-client.d.ts +9 -0
- package/dist/identity-client.js +12 -0
- package/dist/identity.d.ts +2 -8
- package/dist/identity.js +5 -3
- package/dist/index.d.ts +4 -1
- package/dist/index.js +33 -3
- package/dist/inputs-client.d.ts +105 -0
- package/dist/inputs-client.js +264 -0
- package/dist/inputs.d.ts +2 -65
- package/dist/inputs.js +9 -61
- package/dist/internal.d.ts +23 -70
- package/dist/internal.js +115 -23
- package/dist/layout-client.d.ts +9 -0
- package/dist/layout-client.js +72 -0
- package/dist/layout.d.ts +2 -14
- package/dist/layout.js +5 -22
- package/dist/markup.d.ts +72 -0
- package/dist/markup.js +87 -0
- package/dist/media-client.d.ts +36 -0
- package/dist/media-client.js +239 -0
- package/dist/media.d.ts +2 -9
- package/dist/media.js +5 -98
- package/dist/navigation-client.d.ts +94 -0
- package/dist/navigation-client.js +154 -0
- package/dist/navigation.d.ts +2 -59
- package/dist/navigation.js +5 -113
- package/dist/overlays.d.ts +28 -0
- package/dist/overlays.js +66 -10
- package/dist/pure.d.ts +196 -0
- package/dist/pure.js +111 -0
- package/dist/qrcode.d.ts +2 -1
- package/dist/qrcode.js +3 -2
- package/dist/system.d.ts +11 -1
- package/dist/system.js +59 -4
- package/package.json +40 -4
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// Fase 9 (achado A5): este arquivo saiu do index.tsx de 970 linhas. Um módulo por categoria
|
|
4
|
+
// do registry — a taxonomia já existia e é gateada. A ordem de import entre eles é um DAG:
|
|
5
|
+
// internal → system → actions → feedback → inputs → navigation → layout → data-display → resto.
|
|
6
|
+
import React, { forwardRef } from "react";
|
|
7
|
+
import { Combobox as BaseCombobox } from "@base-ui/react/combobox";
|
|
8
|
+
import { Form as BaseForm } from "@base-ui/react/form";
|
|
9
|
+
import { Field as BaseField } from "@base-ui/react/field";
|
|
10
|
+
import { NumberField as BaseNumberField } from "@base-ui/react/number-field";
|
|
11
|
+
import { OTPField as BaseOTPField } from "@base-ui/react/otp-field";
|
|
12
|
+
import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group";
|
|
13
|
+
import { Radio as BaseRadio } from "@base-ui/react/radio";
|
|
14
|
+
import { cx, useAureaStrings, usePortalContainer, useReorder } from "./internal.js";
|
|
15
|
+
// Os seis controles abaixo saíram deste arquivo no item O1 e moram no `markup.tsx`, sem a
|
|
16
|
+
// diretiva — são marcação, e quem escuta `onChange` é o consumidor. Voltam IMPORTADOS e não só
|
|
17
|
+
// reexportados porque o `ehControle` do `Field` compara por IDENTIDADE de referência: dois
|
|
18
|
+
// objetos diferentes com o mesmo nome quebrariam o rótulo do campo em silêncio.
|
|
19
|
+
import { Select, Textarea, Checkbox, Radio, Switch, Range } from "./markup.js";
|
|
20
|
+
import { Icon } from "./system.js";
|
|
21
|
+
import { IconButton } from "./actions.js";
|
|
22
|
+
// FileInput mora em arquivo próprio (132 linhas — upload real, aborto, progresso) e é público
|
|
23
|
+
// por aqui: a categoria dele é Inputs.
|
|
24
|
+
export { FileInput, matchesAccept } from "./file-input.js";
|
|
25
|
+
// hint e error são DESCRIÇÃO (aria-describedby), nunca parte do NOME. Nome é o que o campo É;
|
|
26
|
+
// hint e erro são sobre o VALOR.
|
|
27
|
+
//
|
|
28
|
+
// ISTO JÁ ESTAVA ESCRITO AQUI E ERA MENTIRA — reaberto como AUD-0001 em 12/08/2026, e o achado
|
|
29
|
+
// A12 volta com ele. O comentário anterior dizia "medido em 30/07/2026, corrigido", e a marcação
|
|
30
|
+
// logo abaixo mantinha `hint` e `error` DENTRO do `<label>` externo. Nome acessível medido:
|
|
31
|
+
// "E-mail Usamos para entrar Endereço inválido" — os três grudados —, e a descrição repetindo o
|
|
32
|
+
// que já estava no nome. Quinta vez neste repositório que comentário passou por código; a
|
|
33
|
+
// diferença é que aqui ele passou por CORREÇÃO. O teste que devia pegar aceitava `/E-mail/`, que
|
|
34
|
+
// casa com a frase inteira: regex frouxa é gate que dorme.
|
|
35
|
+
//
|
|
36
|
+
// O contêiner é `<div>` e não `<label>`, e isso resolve três coisas de uma vez: hint e erro saem
|
|
37
|
+
// da árvore de nome; `Checkbox`/`Radio`/`Switch`, que trazem `<label>` próprio, param de produzir
|
|
38
|
+
// `<label>` dentro de `<label>` (HTML inválido); e a ligação passa a ser explícita.
|
|
39
|
+
//
|
|
40
|
+
// DUAS FORMAS, e a regra que escolhe entre elas é UMA: o Field só é dono do NOME quando há um
|
|
41
|
+
// filho único que não se nomeia sozinho.
|
|
42
|
+
// • dono do nome → `<label htmlFor>`, e o filho recebe `id`/`aria-describedby`/`aria-invalid`;
|
|
43
|
+
// • não dono → `role="group"` + `aria-labelledby`, sem `htmlFor`.
|
|
44
|
+
// Os dois casos de "não dono" foram medidos, não imaginados:
|
|
45
|
+
// 1. VÁRIOS FILHOS — o catálogo já faz isso (um grupo de rádios sob um rótulo). Aqui `htmlFor`
|
|
46
|
+
// apontaria para um id que não existe, o que é pior que não ligar.
|
|
47
|
+
// 2. FILHO COM RÓTULO PRÓPRIO — `Switch`, `Checkbox`, `Radio` trazem `<label>` deles. Somar um
|
|
48
|
+
// `<label for>` daria DOIS rótulos ao mesmo controle, e o nome acessível vira a concatenação
|
|
49
|
+
// dos dois ("Notificações Ativo"). A detecção é a prop `label` do filho: é prop NOSSA, não
|
|
50
|
+
// é farejar tipo — todo controle que se nomeia declara ela.
|
|
51
|
+
// O `role="group"` não é invenção: é o que a ficha do Field sempre declarou.
|
|
52
|
+
//
|
|
53
|
+
// LIMITE DECLARADO, e é o que faz o clone falhar em silêncio: componente que destrincha uma
|
|
54
|
+
// lista fixa de props DESCARTA o que for injetado. `Input`, `Select`, `Textarea`, `Range` e
|
|
55
|
+
// `Switch` espalham `...props` e recebem tudo. `Combobox` e `MultiCombobox` não espalhavam, e
|
|
56
|
+
// por isso ganharam `aria-describedby`/`aria-invalid` explícitos abaixo. Os outros
|
|
57
|
+
// (`NumberField`, `OTPField`, `SegmentedControl`, `Toggle`) têm rótulo próprio e não são filhos
|
|
58
|
+
// de `Field` — a ficha diz quais são.
|
|
59
|
+
// As tags que o HTML permite associar a um `<label>`. Fora desta lista (e fora dos nossos
|
|
60
|
+
// componentes), o filho é layout e o Field vira grupo — ver o comentário dentro da função.
|
|
61
|
+
const TAGS_ROTULAVEIS = new Set(["input", "select", "textarea", "button", "meter", "output", "progress"]);
|
|
62
|
+
function filhoUnico(children) {
|
|
63
|
+
const filhos = React.Children.toArray(children);
|
|
64
|
+
if (filhos.length !== 1 || !React.isValidElement(filhos[0]))
|
|
65
|
+
return null;
|
|
66
|
+
const filho = filhos[0];
|
|
67
|
+
return filho.type === React.Fragment ? filhoUnico(filho.props.children) : filho;
|
|
68
|
+
}
|
|
69
|
+
function elementoRotulavel(tipo) {
|
|
70
|
+
if (typeof tipo === "string")
|
|
71
|
+
return TAGS_ROTULAVEIS.has(tipo);
|
|
72
|
+
// Componente React arbitrário pode consumir as props no wrapper e nunca entregá-las ao nó
|
|
73
|
+
// focal. Só os controles Aurea cujo encaminhamento é parte do contrato entram aqui.
|
|
74
|
+
return [Input, Select, Textarea, SearchField, Checkbox, Radio, Switch, Range, Combobox, MultiCombobox].includes(tipo);
|
|
75
|
+
}
|
|
76
|
+
export function Field({ label, hint, error, children, className, id, name, ...props }) {
|
|
77
|
+
const auto = React.useId();
|
|
78
|
+
// Fragment não cria nó no DOM. Um Fragment com um só controle é só sintaxe; com vários,
|
|
79
|
+
// Field precisa voltar para grupo em vez de pendurar `htmlFor` num id que nunca existirá.
|
|
80
|
+
const unico = filhoUnico(children);
|
|
81
|
+
// e o TERCEIRO caso de "não dono", que o gate achou e eu não tinha previsto: o filho único pode
|
|
82
|
+
// ser um `<div>` de LAYOUT com os controles dentro — o catálogo faz isso no `Range` ("With the
|
|
83
|
+
// number": um slider e um campo numérico lado a lado). `htmlFor` apontando para um `<div>` não
|
|
84
|
+
// nomeia nada, e o `catalog-sweep` reprovou `range.html` com duas violações de `label` no axe.
|
|
85
|
+
// A leitura é do TIPO do elemento JSX, que é API estável do React. Para tag nativa vale a lista
|
|
86
|
+
// do HTML; para componente vale a lista explícita dos controles Aurea que repassam a ligação ao
|
|
87
|
+
// nó focal. Componente arbitrário vira grupo — presumir forwarding recria o id sem alvo.
|
|
88
|
+
const rotulavel = !!unico && elementoRotulavel(unico.type);
|
|
89
|
+
// `label` é a API dos controles compostos; aria-label/labelledby são a API universal. Se uma
|
|
90
|
+
// delas já nomeia o filho, acrescentar `<label for>` daria dois donos para o mesmo nome.
|
|
91
|
+
const nomeProprio = rotulavel && (unico.props.label !== undefined || [unico.props["aria-label"], unico.props["aria-labelledby"]].some(v => typeof v === "string" && v.trim().length > 0));
|
|
92
|
+
const nomeAqui = rotulavel && !nomeProprio;
|
|
93
|
+
// o id que o filho já declara VENCE: sobrescrevê-lo quebraria uma ligação que o consumidor fez.
|
|
94
|
+
const idControle = unico?.props.id ?? id ?? `${auto}-control`;
|
|
95
|
+
const idRotulo = `${auto}-label`;
|
|
96
|
+
const idHint = hint ? `${auto}-hint` : undefined;
|
|
97
|
+
const idErro = error ? `${auto}-error` : undefined;
|
|
98
|
+
const descrito = [idHint, idErro].filter(Boolean).join(" ") || undefined;
|
|
99
|
+
// As chaves de aria só entram quando têm VALOR. Passar `undefined` explícito não é o mesmo que
|
|
100
|
+
// não passar: quando o filho vira `Field.Control` do motor (ramo do `name`), a prop explícita
|
|
101
|
+
// do elemento vence a mesclagem, e o `aria-invalid` que o motor calculou a partir do erro
|
|
102
|
+
// externo era apagado por um `undefined` nosso. Medido em 13/08/2026: o input saía com
|
|
103
|
+
// `data-invalid` e SEM `aria-invalid`, ou seja, vermelho na tela e válido para o leitor de
|
|
104
|
+
// tela — que é o pior dos dois mundos.
|
|
105
|
+
const injecao = { id: idControle };
|
|
106
|
+
const descritoFinal = [unico?.props["aria-describedby"], descrito].filter(Boolean).join(" ");
|
|
107
|
+
if (descritoFinal)
|
|
108
|
+
injecao["aria-describedby"] = descritoFinal;
|
|
109
|
+
const invalidoFinal = error ? true : unico?.props["aria-invalid"];
|
|
110
|
+
if (invalidoFinal !== undefined)
|
|
111
|
+
injecao["aria-invalid"] = invalidoFinal;
|
|
112
|
+
const controle = rotulavel ? React.cloneElement(unico, injecao) : children;
|
|
113
|
+
// a descrição mora no nó FOCAL quando existe um; sem filho único, no grupo — que é o que sobra
|
|
114
|
+
// para anunciar. Nos dois lugares seria anunciar duas vezes.
|
|
115
|
+
// Com `name`, o filho passa a ser o CONTROLE do motor: é isso que faz o `aria-invalid` e o
|
|
116
|
+
// `aria-describedby` do erro externo chegarem ao nó focal. Medido em 13/08/2026 — sem este
|
|
117
|
+
// embrulho o `Field.Root` recebe o erro e não tem a quem entregá-lo, e o campo fica válido na
|
|
118
|
+
// árvore de acessibilidade enquanto a frase de erro aparece na tela. Pior que não mostrar.
|
|
119
|
+
const controleFinal = name ? _jsx(BaseField.Control, { render: controle }) : controle;
|
|
120
|
+
const corpo = _jsxs("div", { className: cx("field", className), ...(nomeAqui ? {} : { role: "group", "aria-labelledby": idRotulo, ...(rotulavel ? {} : { "aria-describedby": descrito }) }), ...props, children: [_jsxs("span", { className: "label", children: [nomeAqui ? _jsx("label", { htmlFor: idControle, children: label }) : _jsx("span", { id: idRotulo, children: label }), hint && _jsx("span", { className: "hint", id: idHint, children: hint })] }), controleFinal, error && _jsx("span", { className: "field-error", id: idErro, children: error }), name && _jsx(BaseField.Error, { className: "field-error" })] });
|
|
121
|
+
// `Field.Root` do motor entra SÓ quando há `name`: é ele que liga o campo à chave de `errors`
|
|
122
|
+
// do formulário. Ele não desenha nada — é contexto — então a pele não muda.
|
|
123
|
+
return name ? _jsx(BaseField.Root, { name: name, invalid: error ? true : undefined, render: corpo }) : corpo;
|
|
124
|
+
}
|
|
125
|
+
// Form (M1): o formulário que EXIBE erro, e não o que decide o que é erro.
|
|
126
|
+
//
|
|
127
|
+
// A divisão saiu de pesquisa e da medição dos consumidores (13/08/2026). O padrão de mercado é
|
|
128
|
+
// `react-hook-form` + `zod`, e é o que o shadcn embrulha — mas embrulhar isso aqui obrigaria TODO
|
|
129
|
+
// projeto que usa a Aurea a usar react-hook-form, inclusive os que já validam de outro jeito (um
|
|
130
|
+
// consumidor real valida com zod em server action, sem biblioteca de formulário no cliente).
|
|
131
|
+
// Dependência nova também é decisão do Victor pelo BUILDING.md §3.3, e ela não foi necessária:
|
|
132
|
+
// o `Form` do Base UI — motor que a Aurea JÁ paga desde a Fase 2 — declara no próprio tipo que
|
|
133
|
+
// `errors` são "validation errors returned externally, typically after submission by a server or
|
|
134
|
+
// a form action". Ou seja, a divisão que eu ia propor já é a do motor.
|
|
135
|
+
//
|
|
136
|
+
// O que a Aurea entrega: a pele, o `name` ligando campo a erro, e o envio com os valores já
|
|
137
|
+
// coletados. O que ela NÃO entrega, e não vai: schema, regra, resolver, estado de campo.
|
|
138
|
+
export function Form({ errors, onSubmit, children, className, ...props }) {
|
|
139
|
+
return _jsx(BaseForm, { errors: errors, onFormSubmit: onSubmit ? (v) => onSubmit(v) : undefined, className: cx("form", className), ...props, children: children });
|
|
140
|
+
}
|
|
141
|
+
export const Input = forwardRef(function Input({ className, formatOnBlur, onBlur, onChange, ...props }, ref) {
|
|
142
|
+
return _jsx("input", { ref: ref, className: cx("input", className), onChange: onChange, onBlur: e => {
|
|
143
|
+
if (formatOnBlur) {
|
|
144
|
+
const formatado = formatOnBlur(e.currentTarget.value);
|
|
145
|
+
if (formatado !== e.currentTarget.value) {
|
|
146
|
+
e.currentTarget.value = formatado;
|
|
147
|
+
onChange?.(e);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
onBlur?.(e);
|
|
151
|
+
}, ...props });
|
|
152
|
+
});
|
|
153
|
+
export function SearchField({ icon = "search", className, ...props }) { return _jsxs("div", { className: cx("input-wrap", className), children: [_jsx(Icon, { name: icon }), _jsx(Input, { type: "search", ...props })] }); }
|
|
154
|
+
// labelHidden: coluna de seleção de tabela precisa do rótulo POR LINHA para o leitor de
|
|
155
|
+
// tela ("Select Analyst"), mas mostrá-lo engorda a coluna. O rótulo continua no DOM, só
|
|
156
|
+
// sai da tela (.sr-only) — nunca trocar por aria-label solto num <label> visível vazio.
|
|
157
|
+
// NumberField (Lote 1 do BUILDING.md). Um `<input type="number">` cru tem três problemas que
|
|
158
|
+
// este resolve, e todos vieram do motor, não de nós: as setas nativas são alvos minúsculos e
|
|
159
|
+
// somem no Safari; a roda do mouse altera o valor por acidente sobre o campo focado; e o valor
|
|
160
|
+
// digitado não é formatado por locale. O Base UI trata os três.
|
|
161
|
+
// A anatomia (menos · campo · mais numa peça só) é a que as referências convergem.
|
|
162
|
+
// Fora de propósito: o ScrubArea do Base UI — arrastar o rótulo para variar o número. É gesto
|
|
163
|
+
// que ninguém descobre sozinho e que não tem equivalente por teclado.
|
|
164
|
+
// `format`/`locale`/`name` são a metade de MOEDA do item L6, e não custaram componente nenhum: o
|
|
165
|
+
// comentário acima já dizia que o motor formata por locale, e a nossa casca simplesmente não
|
|
166
|
+
// repassava a opção. Medido no `@base-ui/react@1.6.0`: `NumberFieldRoot` aceita
|
|
167
|
+
// `format?: Intl.NumberFormatOptions` e `locale?`, e formata no BLUR — que é exatamente o momento
|
|
168
|
+
// que a pesquisa de acessibilidade recomenda, e o oposto da máscara ao vivo.
|
|
169
|
+
// Com isso, `<NumberField format={{style:"currency",currency:"BRL"}} locale="pt-BR"/>` substitui a
|
|
170
|
+
// biblioteca de moeda que um consumidor carrega só para isso. Quem formata é o `Intl` da
|
|
171
|
+
// plataforma; a Aurea não escreve formatador de dinheiro, e nem deveria.
|
|
172
|
+
// `name` entra junto porque é ele que faz o motor renderizar o input escondido com o valor CRU —
|
|
173
|
+
// é a trava do item ("o valor mascarado continua no DOM") entregue pelo motor, e o teste a cobra.
|
|
174
|
+
export function NumberField({ value, defaultValue, onValueChange, min, max, step, disabled, readOnly, required, label, id, name, format, locale, className }) {
|
|
175
|
+
const s = useAureaStrings();
|
|
176
|
+
return _jsx(BaseNumberField.Root, { id: id, name: name, value: value, defaultValue: defaultValue, onValueChange: onValueChange, min: min, max: max, step: step, format: format, locale: locale, disabled: disabled, readOnly: readOnly, required: required, className: cx("number-field", className), children: _jsxs(BaseNumberField.Group, { className: "number-field-group", children: [_jsx(BaseNumberField.Decrement, { className: "btn btn-ghost btn-icon", "aria-label": s.decrement, children: _jsx(Icon, { name: "subtract" }) }), _jsx(BaseNumberField.Input, { className: "input number-field-input", "aria-label": label }), _jsx(BaseNumberField.Increment, { className: "btn btn-ghost btn-icon", "aria-label": s.increment, children: _jsx(Icon, { name: "add" }) })] }) });
|
|
177
|
+
}
|
|
178
|
+
// OTPField (Lote 1 do BUILDING.md). Um campo por dígito, com o comportamento que ninguém acerta
|
|
179
|
+
// à mão: colar o código inteiro distribui pelos campos, Backspace volta um, e o
|
|
180
|
+
// `autocomplete="one-time-code"` deixa o iOS oferecer o código do SMS. Tudo do motor.
|
|
181
|
+
// Uma referência resolve isto com um pacote npm separado; aqui não entra dependência nova —
|
|
182
|
+
// o `@base-ui/react`, que já é a única dependência de runtime da biblioteca, tem `otp-field`.
|
|
183
|
+
// `length` é obrigatório de propósito: sem ele o campo não sabe quando está completo.
|
|
184
|
+
// CADA caixa leva nome próprio, e não só o grupo. O `catalog-sweep` pegou isto no primeiro
|
|
185
|
+
// lote: com `aria-label` só na raiz, o axe acusou `label` em todas as seis — seis campos de
|
|
186
|
+
// formulário anônimos. Um leitor de tela anunciaria "editar texto" seis vezes seguidas sem
|
|
187
|
+
// dizer qual é qual. O grupo continua nomeado (`role="group"`), que é o que diz para que serve
|
|
188
|
+
// o código; o nome de cada caixa é o que diz onde você está.
|
|
189
|
+
export function OTPField({ length, value, defaultValue, onValueChange, mask, disabled, required, label, id, className }) {
|
|
190
|
+
const s = useAureaStrings();
|
|
191
|
+
return _jsx(BaseOTPField.Root, { id: id, length: length, value: value, defaultValue: defaultValue, onValueChange: onValueChange, mask: mask, disabled: disabled, required: required, role: "group", "aria-label": label, className: cx("otp-field", className), children: Array.from({ length }, (_, i) => _jsx(BaseOTPField.Input, { render: _jsx("input", { "aria-label": `${s.otpDigit} ${i + 1}` }), className: "input otp-slot" }, i)) });
|
|
192
|
+
}
|
|
193
|
+
// SegmentedControl — achado M20, fechado na Parte C do PLANO-1.0 em 07/08/2026.
|
|
194
|
+
//
|
|
195
|
+
// O DEFEITO: era `role="group"` com N botões de `aria-pressed`. Isso descreve N alternâncias
|
|
196
|
+
// INDEPENDENTES — cada botão anuncia "pressionado/não pressionado", nada diz que só um pode
|
|
197
|
+
// valer, e nunca se ouve "1 de 2". Para escolha única entre poucas opções o padrão APG é
|
|
198
|
+
// `radiogroup`, e a diferença é o que o leitor de tela consegue prometer.
|
|
199
|
+
// A troca mudou a semântica de um componente publicado, então foi registrada: ADR-0016.
|
|
200
|
+
//
|
|
201
|
+
// O MOTOR ENTREGA, ENTÃO NÃO ESCREVEMOS (BUILDING.md §1). O `RadioGroup` do Base UI 1.6 traz o
|
|
202
|
+
// padrão inteiro: roving tabindex, setas que movem E selecionam, Home/End, e `aria-checked`.
|
|
203
|
+
// Escrever isso à mão seria reimplementar um composite que já está testado.
|
|
204
|
+
//
|
|
205
|
+
// `render={<button type="button"/>}` não é enfeite, e a medição de 07/08 é que disse: o
|
|
206
|
+
// `Radio.Root` renderiza um `<span>` por padrão, e a pele da Aurea é `.segmented button`. Sem
|
|
207
|
+
// isso o componente perderia a pele inteira — e o check 18 não veria, porque ele olha CLASSE.
|
|
208
|
+
// O motor também emite um `<input type="radio">` escondido por item (para envio de formulário);
|
|
209
|
+
// ele é `position:fixed` e `aria-hidden`, então não entra no flex nem na árvore de acessibilidade.
|
|
210
|
+
//
|
|
211
|
+
// E `nativeButton` é o par obrigatório do `render` acima — medido em 11/08/2026. O `Radio.Root`
|
|
212
|
+
// declara `nativeButton = false` por padrão (é o valor certo para o `<span>` que ele renderiza
|
|
213
|
+
// sozinho), e o `useButton` do motor CONFERE isso no DOM montado, dentro de um efeito: sem esta
|
|
214
|
+
// palavra sai um `console.error` do Base UI a cada montagem de CLIENTE. Não no catálogo, que é
|
|
215
|
+
// HTML estático — no console de quem INSTALA.
|
|
216
|
+
// O DOM foi medido nos dois lados antes da troca. O `role="button"` que a mensagem ameaça NÃO
|
|
217
|
+
// aparecia (o `role="radio"` do motor já vencia a fusão); o que muda de fato é o `<input>`
|
|
218
|
+
// escondido perder o `id`, que migra para este botão — e migra para o lado certo, porque o botão
|
|
219
|
+
// é o rádio e o input é `aria-hidden`. Comportamento idêntico: Enter não seleciona, Espaço
|
|
220
|
+
// seleciona, a seta move E seleciona. O que sai é a camada sintética que o motor punha por cima
|
|
221
|
+
// da ativação nativa do `<button>`.
|
|
222
|
+
export function SegmentedControl({ items, value, onChange, label }) {
|
|
223
|
+
const s = useAureaStrings();
|
|
224
|
+
return _jsx(BaseRadioGroup, { className: "segmented", "aria-label": label ?? s.optionsLabel, value: value, onValueChange: v => onChange(String(v)), children: items.map(i => _jsx(BaseRadio.Root, { value: i.value, className: i.value === value ? "active" : undefined, nativeButton: true, render: _jsx("button", { type: "button" }), children: i.label }, i.value)) });
|
|
225
|
+
}
|
|
226
|
+
// `aria-describedby` e `aria-invalid` são explícitos e não caem em `...props` por acidente: este
|
|
227
|
+
// componente destrincha uma lista fixa, então o que não está aqui é DESCARTADO em silêncio — e era
|
|
228
|
+
// exatamente isso que fazia o `Field` não alcançar o input do Combobox (AUD-0001, 12/08/2026).
|
|
229
|
+
// Vão para o `Input`, que é o nó focal: no contêiner eles não seriam anunciados.
|
|
230
|
+
// `disabled` vai na ROOT, não no Input: `Input`, `Trigger`, `Clear` e `ChipRemove` leem todos o
|
|
231
|
+
// mesmo `selectors.disabled` do store do Base UI (@base-ui/react 1.6.0). Desabilitar o Input
|
|
232
|
+
// deixaria os dois botões vivos — abrir a lista de um campo desabilitado é o defeito, não o texto.
|
|
233
|
+
export function Combobox({ items, value, onValueChange, placeholder, label, disabled, id, className, "aria-describedby": descrito, "aria-invalid": invalido }) {
|
|
234
|
+
const s = useAureaStrings();
|
|
235
|
+
const portal = usePortalContainer();
|
|
236
|
+
const autoId = React.useId();
|
|
237
|
+
const inputId = id ?? autoId;
|
|
238
|
+
return _jsxs(BaseCombobox.Root, { items: items, value: value, onValueChange: onValueChange, disabled: disabled, itemToStringLabel: (i) => i.label, children: [_jsxs("div", { className: cx("field", className), children: [label && _jsx("label", { className: "label", htmlFor: inputId, children: label }), _jsxs(BaseCombobox.InputGroup, { className: "combobox-group", children: [_jsx(BaseCombobox.Input, { id: inputId, placeholder: placeholder, className: "input", "aria-describedby": descrito, "aria-invalid": invalido }), _jsxs("span", { className: "combobox-actions", children: [_jsx(BaseCombobox.Clear, { render: _jsx(IconButton, { variant: "ghost", size: "sm", icon: "close", label: s.comboboxClear }) }), _jsx(BaseCombobox.Trigger, { render: _jsx(IconButton, { variant: "ghost", size: "sm", icon: "chevron--down", label: s.comboboxOpen }) })] })] })] }), _jsx(BaseCombobox.Portal, { container: portal, children: _jsx(BaseCombobox.Positioner, { sideOffset: 6, children: _jsxs(BaseCombobox.Popup, { className: "menu combobox-popup", children: [_jsx(BaseCombobox.Empty, { className: "combobox-empty", children: s.comboboxEmpty }), _jsx(BaseCombobox.List, { children: (item) => _jsxs(BaseCombobox.Item, { value: item, className: "menu-item combobox-item", children: [_jsx(BaseCombobox.ItemIndicator, { className: "combobox-check", children: _jsx(Icon, { name: "checkmark", size: "sm" }) }), _jsx("span", { children: item.label })] }, item.value) })] }) }) })] });
|
|
239
|
+
}
|
|
240
|
+
const isGrouped = (items) => items.length > 0 && "items" in items[0];
|
|
241
|
+
export function MultiCombobox({ items, value, onValueChange, onInputChange, loading, placeholder, label, disabled, id, className, "aria-describedby": descrito, "aria-invalid": invalido }) {
|
|
242
|
+
const s = useAureaStrings();
|
|
243
|
+
const portal = usePortalContainer();
|
|
244
|
+
const autoId = React.useId();
|
|
245
|
+
const inputId = id ?? autoId;
|
|
246
|
+
const renderItem = (item) => _jsxs(BaseCombobox.Item, { value: item, className: "menu-item combobox-item", children: [_jsx(BaseCombobox.ItemIndicator, { className: "combobox-check", children: _jsx(Icon, { name: "checkmark", size: "sm" }) }), _jsx("span", { children: item.label })] }, item.value);
|
|
247
|
+
return _jsxs(BaseCombobox.Root, { multiple: true, items: items, value: value, onValueChange: onValueChange, disabled: disabled, itemToStringLabel: (i) => i.label, filter: onInputChange ? null : undefined, onInputValueChange: onInputChange ? ((v, d) => { if (d.reason !== "item-press")
|
|
248
|
+
onInputChange(v); }) : undefined, children: [_jsxs("div", { className: cx("field", className), children: [label && _jsx("label", { className: "label", htmlFor: inputId, children: label }), _jsxs(BaseCombobox.InputGroup, { className: "combobox-multi", children: [_jsx(BaseCombobox.Chips, { className: "combobox-chips", children: _jsx(BaseCombobox.Value, { children: (selected) => _jsxs(_Fragment, { children: [selected.map((item) => _jsxs(BaseCombobox.Chip, { className: "combobox-chip", children: [item.label, _jsx(BaseCombobox.ChipRemove, { className: "combobox-chip-remove", "aria-label": `${s.comboboxRemove} ${item.label}`, children: _jsx(Icon, { name: "close", size: "sm" }) })] }, item.value)), _jsx(BaseCombobox.Input, { id: inputId, placeholder: selected.length ? undefined : placeholder, className: "combobox-chip-input", "aria-describedby": descrito, "aria-invalid": invalido })] }) }) }), _jsxs("span", { className: "combobox-actions", children: [_jsx(BaseCombobox.Clear, { render: _jsx(IconButton, { variant: "ghost", size: "sm", icon: "close", label: s.comboboxClear }) }), _jsx(BaseCombobox.Trigger, { render: _jsx(IconButton, { variant: "ghost", size: "sm", icon: "chevron--down", label: s.comboboxOpen }) })] })] })] }), _jsx(BaseCombobox.Portal, { container: portal, children: _jsx(BaseCombobox.Positioner, { sideOffset: 6, children: _jsxs(BaseCombobox.Popup, { className: "menu combobox-popup", children: [_jsx(BaseCombobox.Empty, { className: "combobox-empty", children: loading ? s.comboboxLoading : s.comboboxEmpty }), _jsx(BaseCombobox.List, { children: isGrouped(items)
|
|
249
|
+
? (group) => _jsxs(BaseCombobox.Group, { items: group.items, className: "combobox-section", children: [_jsx(BaseCombobox.GroupLabel, { className: "combobox-group-label", children: group.label }), _jsx(BaseCombobox.Collection, { children: renderItem })] }, group.label)
|
|
250
|
+
: renderItem })] }) }) })] });
|
|
251
|
+
}
|
|
252
|
+
export function BlockEditor({ blocks, onReorder, onRemove, label, className, ...props }) {
|
|
253
|
+
const s = useAureaStrings();
|
|
254
|
+
const bid = React.useId();
|
|
255
|
+
const n = blocks.length;
|
|
256
|
+
// O protocolo de arrasto acessível é o MESMO da `SortableList` — extraído para o `internal` em
|
|
257
|
+
// vez de copiado, porque duas cópias garantem que a próxima correção entre em uma só.
|
|
258
|
+
const r = useReorder({ count: n, order: blocks, onReorder,
|
|
259
|
+
rowSelector: ".block-item", handleSelector: ".block-handle" });
|
|
260
|
+
return _jsxs(_Fragment, { children: [_jsx("ol", { ref: r.ref, className: cx("block-editor", className), "aria-label": label ?? s.blockEditorLabel, ...props, children: blocks.map((b, i) => {
|
|
261
|
+
const kid = `${bid}k${i}`, hid = `${bid}h${i}`, rid = `${bid}r${i}`;
|
|
262
|
+
return _jsxs("li", { className: "block-item", "data-grabbed": r.pego === i || undefined, children: [_jsxs("div", { className: "block-rail", children: [_jsxs("button", { type: "button", id: hid, className: "block-handle", "aria-labelledby": `${hid} ${kid}`, "aria-describedby": `${bid}ajuda`, "aria-pressed": r.pego === i, onKeyDown: e => r.teclado(e, i), onPointerDown: e => r.ponteiroBaixo(e, i), onPointerMove: r.ponteiroMove, onPointerUp: r.ponteiroSolta, onPointerCancel: r.ponteiroSolta, children: [_jsx(Icon, { name: "drag--horizontal" }), _jsx("span", { className: "sr-only", children: s.sortableHandle })] }), onRemove && _jsxs("button", { type: "button", id: rid, className: "block-remove", "aria-labelledby": `${rid} ${kid}`, onClick: () => onRemove(i), children: [_jsx(Icon, { name: "trash-can" }), _jsx("span", { className: "sr-only", children: s.blockRemove })] })] }), _jsx("div", { className: "block-body", children: b.children }), _jsxs("span", { id: kid, className: "sr-only", children: [b.kind ?? s.blockLabel, " ", i + 1, " ", s.positionOf, " ", n] })] }, b.id);
|
|
263
|
+
}) }), _jsx("span", { id: `${bid}ajuda`, className: "sr-only", children: s.sortableHelp }), _jsx("div", { role: "status", "aria-live": "polite", className: "sr-only", children: r.aviso })] });
|
|
264
|
+
}
|
package/dist/inputs.d.ts
CHANGED
|
@@ -1,65 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export { FileInput, matchesAccept, type FileRejection, type UploadContext, type UploadFn } from "./file-input.js";
|
|
4
|
-
export interface FieldProps extends HTMLAttributes<HTMLLabelElement>, RefAttributes<HTMLLabelElement> {
|
|
5
|
-
label: string;
|
|
6
|
-
hint?: ReactNode;
|
|
7
|
-
error?: ReactNode;
|
|
8
|
-
htmlFor?: string;
|
|
9
|
-
}
|
|
10
|
-
export declare function Field({ label, hint, error, children, className, id, ...props }: FieldProps): React.JSX.Element;
|
|
11
|
-
export declare const Input: React.ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement> & RefAttributes<HTMLInputElement>, "ref"> & RefAttributes<HTMLInputElement>>;
|
|
12
|
-
export declare const Select: React.ForwardRefExoticComponent<Omit<SelectHTMLAttributes<HTMLSelectElement> & RefAttributes<HTMLSelectElement>, "ref"> & RefAttributes<HTMLSelectElement>>;
|
|
13
|
-
export declare const Textarea: React.ForwardRefExoticComponent<Omit<TextareaHTMLAttributes<HTMLTextAreaElement> & RefAttributes<HTMLTextAreaElement>, "ref"> & RefAttributes<HTMLTextAreaElement>>;
|
|
14
|
-
export declare function SearchField({ icon, className, ...props }: InputHTMLAttributes<HTMLInputElement> & RefAttributes<HTMLInputElement> & {
|
|
15
|
-
icon?: IconName;
|
|
16
|
-
}): React.JSX.Element;
|
|
17
|
-
export declare function Checkbox({ label, labelHidden, description, className, ...props }: InputHTMLAttributes<HTMLInputElement> & RefAttributes<HTMLInputElement> & {
|
|
18
|
-
label: ReactNode;
|
|
19
|
-
labelHidden?: boolean;
|
|
20
|
-
description?: ReactNode;
|
|
21
|
-
}): React.JSX.Element;
|
|
22
|
-
export declare function Radio({ label, className, ...props }: InputHTMLAttributes<HTMLInputElement> & RefAttributes<HTMLInputElement> & {
|
|
23
|
-
label: ReactNode;
|
|
24
|
-
}): React.JSX.Element;
|
|
25
|
-
export declare function Switch({ label, className, ...props }: InputHTMLAttributes<HTMLInputElement> & RefAttributes<HTMLInputElement> & {
|
|
26
|
-
label: ReactNode;
|
|
27
|
-
}): React.JSX.Element;
|
|
28
|
-
export declare function Range(props: InputHTMLAttributes<HTMLInputElement> & RefAttributes<HTMLInputElement>): React.JSX.Element;
|
|
29
|
-
export declare function SegmentedControl({ items, value, onChange, label }: {
|
|
30
|
-
items: Array<{
|
|
31
|
-
value: string;
|
|
32
|
-
label: ReactNode;
|
|
33
|
-
}>;
|
|
34
|
-
value: string;
|
|
35
|
-
onChange: (v: string) => void;
|
|
36
|
-
label?: string;
|
|
37
|
-
}): React.JSX.Element;
|
|
38
|
-
export interface ComboboxOption {
|
|
39
|
-
value: string;
|
|
40
|
-
label: string;
|
|
41
|
-
}
|
|
42
|
-
export declare function Combobox({ items, value, onValueChange, placeholder, label, id, className }: {
|
|
43
|
-
items: ComboboxOption[];
|
|
44
|
-
value?: ComboboxOption | null;
|
|
45
|
-
onValueChange?: (v: ComboboxOption | null) => void;
|
|
46
|
-
placeholder?: string;
|
|
47
|
-
label?: ReactNode;
|
|
48
|
-
id?: string;
|
|
49
|
-
className?: string;
|
|
50
|
-
}): React.JSX.Element;
|
|
51
|
-
export interface ComboboxOptGroup {
|
|
52
|
-
label: string;
|
|
53
|
-
items: ComboboxOption[];
|
|
54
|
-
}
|
|
55
|
-
export declare function MultiCombobox({ items, value, onValueChange, onInputChange, loading, placeholder, label, id, className }: {
|
|
56
|
-
items: ComboboxOption[] | ComboboxOptGroup[];
|
|
57
|
-
value?: ComboboxOption[];
|
|
58
|
-
onValueChange?: (v: ComboboxOption[]) => void;
|
|
59
|
-
onInputChange?: (query: string) => void;
|
|
60
|
-
loading?: boolean;
|
|
61
|
-
placeholder?: string;
|
|
62
|
-
label?: ReactNode;
|
|
63
|
-
id?: string;
|
|
64
|
-
className?: string;
|
|
65
|
-
}): React.JSX.Element;
|
|
1
|
+
export * from "./inputs-client.js";
|
|
2
|
+
export { Select, Textarea, Checkbox, Radio, Switch, Range } from "./markup.js";
|
package/dist/inputs.js
CHANGED
|
@@ -1,61 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// FileInput mora em arquivo próprio (132 linhas — upload real, aborto, progresso) e é público
|
|
11
|
-
// por aqui: a categoria dele é Inputs.
|
|
12
|
-
export { FileInput, matchesAccept } from "./file-input.js";
|
|
13
|
-
// hint e error entram como DESCRIÇÃO (aria-describedby) e não como parte do nome. Medido em
|
|
14
|
-
// 30/07/2026: por estarem dentro do <label>, o nome acessível do campo virava "E-mail Usamos
|
|
15
|
-
// para entrar Endereço inválido" — tudo grudado — e nada dizia ao leitor de tela que o valor
|
|
16
|
-
// era inválido. Nome é o que o campo É; hint e erro são sobre o valor.
|
|
17
|
-
// O controle vem como children, então a ligação é feita clonando-o: é a única forma de pôr
|
|
18
|
-
// aria-describedby/aria-invalid no elemento certo sem obrigar o consumidor a repetir ids.
|
|
19
|
-
export function Field({ label, hint, error, children, className, id, ...props }) {
|
|
20
|
-
const auto = React.useId();
|
|
21
|
-
const base = id ?? auto;
|
|
22
|
-
const idHint = hint ? `${base}-hint` : undefined;
|
|
23
|
-
const idErro = error ? `${base}-error` : undefined;
|
|
24
|
-
const descrito = [idHint, idErro].filter(Boolean).join(" ") || undefined;
|
|
25
|
-
const controle = React.isValidElement(children)
|
|
26
|
-
? React.cloneElement(children, {
|
|
27
|
-
"aria-describedby": [children.props["aria-describedby"], descrito].filter(Boolean).join(" ") || undefined,
|
|
28
|
-
"aria-invalid": error ? true : children.props["aria-invalid"],
|
|
29
|
-
})
|
|
30
|
-
: children;
|
|
31
|
-
return _jsxs("label", { className: cx("field", className), id: id, ...props, children: [_jsxs("span", { className: "label", children: [label, hint && _jsx("span", { className: "hint", id: idHint, children: hint })] }), controle, error && _jsx("span", { className: "field-error", id: idErro, children: error })] });
|
|
32
|
-
}
|
|
33
|
-
export const Input = forwardRef(function Input({ className, ...props }, ref) { return _jsx("input", { ref: ref, className: cx("input", className), ...props }); });
|
|
34
|
-
export const Select = forwardRef(function Select({ className, ...props }, ref) { return _jsx("select", { ref: ref, className: cx("select", className), ...props }); });
|
|
35
|
-
export const Textarea = forwardRef(function Textarea({ className, ...props }, ref) { return _jsx("textarea", { ref: ref, className: cx("textarea", className), ...props }); });
|
|
36
|
-
export function SearchField({ icon = "search", className, ...props }) { return _jsxs("div", { className: cx("input-wrap", className), children: [_jsx(Icon, { name: icon }), _jsx(Input, { type: "search", ...props })] }); }
|
|
37
|
-
// labelHidden: coluna de seleção de tabela precisa do rótulo POR LINHA para o leitor de
|
|
38
|
-
// tela ("Select Analyst"), mas mostrá-lo engorda a coluna. O rótulo continua no DOM, só
|
|
39
|
-
// sai da tela (.sr-only) — nunca trocar por aria-label solto num <label> visível vazio.
|
|
40
|
-
export function Checkbox({ label, labelHidden, description, className, ...props }) { return _jsxs("label", { className: cx("checkbox", labelHidden && "checkbox-bare", className), children: [_jsx("input", { type: "checkbox", ...props }), _jsx("span", { className: "control-mark" }), _jsxs("span", { className: labelHidden ? "sr-only" : undefined, children: [_jsx("strong", { children: label }), description && _jsxs(_Fragment, { children: [_jsx("br", {}), _jsx("span", { className: "muted", children: description })] })] })] }); }
|
|
41
|
-
export function Radio({ label, className, ...props }) { return _jsxs("label", { className: cx("radio", className), children: [_jsx("input", { type: "radio", ...props }), _jsx("span", { className: "control-mark" }), label] }); }
|
|
42
|
-
export function Switch({ label, className, ...props }) { return _jsxs("label", { className: cx("switch", className), children: [_jsx("input", { type: "checkbox", role: "switch", ...props }), _jsx("span", { className: "switch-track" }), _jsx("span", { children: label })] }); }
|
|
43
|
-
export function Range(props) { return _jsx("input", { className: cx("range", props.className), type: "range", ...props }); }
|
|
44
|
-
export function SegmentedControl({ items, value, onChange, label }) { const s = useAureaStrings(); return _jsx("div", { className: "segmented", role: "group", "aria-label": label ?? s.optionsLabel, children: items.map(i => _jsx("button", { className: i.value === value ? "active" : undefined, "aria-pressed": i.value === value, onClick: () => onChange(i.value), children: i.label }, i.value)) }); }
|
|
45
|
-
export function Combobox({ items, value, onValueChange, placeholder, label, id, className }) {
|
|
46
|
-
const s = useAureaStrings();
|
|
47
|
-
const autoId = React.useId();
|
|
48
|
-
const inputId = id ?? autoId;
|
|
49
|
-
return _jsxs(BaseCombobox.Root, { items: items, value: value, onValueChange: onValueChange, itemToStringLabel: (i) => i.label, children: [_jsxs("div", { className: cx("field", className), children: [label && _jsx("label", { className: "label", htmlFor: inputId, children: label }), _jsxs(BaseCombobox.InputGroup, { className: "combobox-group", children: [_jsx(BaseCombobox.Input, { id: inputId, placeholder: placeholder, className: "input" }), _jsxs("span", { className: "combobox-actions", children: [_jsx(BaseCombobox.Clear, { render: _jsx(IconButton, { variant: "ghost", size: "sm", icon: "close", label: s.comboboxClear }) }), _jsx(BaseCombobox.Trigger, { render: _jsx(IconButton, { variant: "ghost", size: "sm", icon: "chevron--down", label: s.comboboxOpen }) })] })] })] }), _jsx(BaseCombobox.Portal, { children: _jsx(BaseCombobox.Positioner, { sideOffset: 6, children: _jsxs(BaseCombobox.Popup, { className: "menu combobox-popup", children: [_jsx(BaseCombobox.Empty, { className: "combobox-empty", children: s.comboboxEmpty }), _jsx(BaseCombobox.List, { children: (item) => _jsxs(BaseCombobox.Item, { value: item, className: "menu-item combobox-item", children: [_jsx(BaseCombobox.ItemIndicator, { className: "combobox-check", children: _jsx(Icon, { name: "checkmark", size: "sm" }) }), _jsx("span", { children: item.label })] }, item.value) })] }) }) })] });
|
|
50
|
-
}
|
|
51
|
-
const isGrouped = (items) => items.length > 0 && "items" in items[0];
|
|
52
|
-
export function MultiCombobox({ items, value, onValueChange, onInputChange, loading, placeholder, label, id, className }) {
|
|
53
|
-
const s = useAureaStrings();
|
|
54
|
-
const autoId = React.useId();
|
|
55
|
-
const inputId = id ?? autoId;
|
|
56
|
-
const renderItem = (item) => _jsxs(BaseCombobox.Item, { value: item, className: "menu-item combobox-item", children: [_jsx(BaseCombobox.ItemIndicator, { className: "combobox-check", children: _jsx(Icon, { name: "checkmark", size: "sm" }) }), _jsx("span", { children: item.label })] }, item.value);
|
|
57
|
-
return _jsxs(BaseCombobox.Root, { multiple: true, items: items, value: value, onValueChange: onValueChange, itemToStringLabel: (i) => i.label, filter: onInputChange ? null : undefined, onInputValueChange: onInputChange ? ((v, d) => { if (d.reason !== "item-press")
|
|
58
|
-
onInputChange(v); }) : undefined, children: [_jsxs("div", { className: cx("field", className), children: [label && _jsx("label", { className: "label", htmlFor: inputId, children: label }), _jsxs(BaseCombobox.InputGroup, { className: "combobox-multi", children: [_jsx(BaseCombobox.Chips, { className: "combobox-chips", children: _jsx(BaseCombobox.Value, { children: (selected) => _jsxs(_Fragment, { children: [selected.map((item) => _jsxs(BaseCombobox.Chip, { className: "combobox-chip", children: [item.label, _jsx(BaseCombobox.ChipRemove, { className: "combobox-chip-remove", "aria-label": `${s.comboboxRemove} ${item.label}`, children: _jsx(Icon, { name: "close", size: "sm" }) })] }, item.value)), _jsx(BaseCombobox.Input, { id: inputId, placeholder: selected.length ? undefined : placeholder, className: "combobox-chip-input" })] }) }) }), _jsxs("span", { className: "combobox-actions", children: [_jsx(BaseCombobox.Clear, { render: _jsx(IconButton, { variant: "ghost", size: "sm", icon: "close", label: s.comboboxClear }) }), _jsx(BaseCombobox.Trigger, { render: _jsx(IconButton, { variant: "ghost", size: "sm", icon: "chevron--down", label: s.comboboxOpen }) })] })] })] }), _jsx(BaseCombobox.Portal, { children: _jsx(BaseCombobox.Positioner, { sideOffset: 6, children: _jsxs(BaseCombobox.Popup, { className: "menu combobox-popup", children: [_jsx(BaseCombobox.Empty, { className: "combobox-empty", children: loading ? s.comboboxLoading : s.comboboxEmpty }), _jsx(BaseCombobox.List, { children: isGrouped(items)
|
|
59
|
-
? (group) => _jsxs(BaseCombobox.Group, { items: group.items, className: "combobox-section", children: [_jsx(BaseCombobox.GroupLabel, { className: "combobox-group-label", children: group.label }), _jsx(BaseCombobox.Collection, { children: renderItem })] }, group.label)
|
|
60
|
-
: renderItem })] }) }) })] });
|
|
61
|
-
}
|
|
1
|
+
// VITRINE da categoria — é este arquivo que `@aurea-uds/react/inputs` resolve. Sem `"use client"`
|
|
2
|
+
// de propósito: a diretiva contamina o módulo inteiro e faria a marcação pura chegar como cliente
|
|
3
|
+
// por vizinhança (ADR-0026; o check 26b reprova quem a puser de volta aqui).
|
|
4
|
+
//
|
|
5
|
+
// Os seis controles continuam IMPORTADOS pelo irmão de cliente, e não só reexportados aqui: o
|
|
6
|
+
// `ehControle` do `Field` compara por IDENTIDADE de referência, e dois objetos com o mesmo nome
|
|
7
|
+
// quebrariam o rótulo do campo em silêncio. Um caminho de import, um objeto.
|
|
8
|
+
export * from "./inputs-client.js";
|
|
9
|
+
export { Select, Textarea, Checkbox, Radio, Switch, Range } from "./markup.js";
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,72 +1,25 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
paginationLabel: string;
|
|
6
|
-
previous: string;
|
|
7
|
-
next: string;
|
|
8
|
-
breadcrumbLabel: string;
|
|
9
|
-
tabsLabel: string;
|
|
10
|
-
optionsLabel: string;
|
|
11
|
-
tableLabel: string;
|
|
12
|
-
commandLabel: string;
|
|
13
|
-
commandPlaceholder: string;
|
|
14
|
-
dismissNotification: string;
|
|
15
|
-
toolbarLabel: string;
|
|
16
|
-
comboboxEmpty: string;
|
|
17
|
-
comboboxClear: string;
|
|
18
|
-
comboboxOpen: string;
|
|
19
|
-
comboboxRemove: string;
|
|
20
|
-
comboboxLoading: string;
|
|
21
|
-
fileDropPrompt: string;
|
|
22
|
-
fileAdded: string;
|
|
23
|
-
fileRemoved: string;
|
|
24
|
-
fileRemove: string;
|
|
25
|
-
fileTooLarge: string;
|
|
26
|
-
fileWrongType: string;
|
|
27
|
-
treeLabel: string;
|
|
28
|
-
notificationsLabel: string;
|
|
29
|
-
notificationMarkAll: string;
|
|
30
|
-
notificationEmpty: string;
|
|
31
|
-
notificationUnread: string;
|
|
32
|
-
notificationNew: string;
|
|
33
|
-
dataGridFilter: string;
|
|
34
|
-
dataGridEmpty: string;
|
|
35
|
-
dataGridSelectAll: string;
|
|
36
|
-
dataGridSelectRow: string;
|
|
37
|
-
mediaPlayer: string;
|
|
38
|
-
mediaPlay: string;
|
|
39
|
-
mediaPause: string;
|
|
40
|
-
mediaMute: string;
|
|
41
|
-
mediaUnmute: string;
|
|
42
|
-
mediaSeek: string;
|
|
43
|
-
mediaVolume: string;
|
|
44
|
-
mediaCaptionsShow: string;
|
|
45
|
-
mediaCaptionsHide: string;
|
|
46
|
-
mediaSkipBack: string;
|
|
47
|
-
mediaSkipForward: string;
|
|
48
|
-
mediaFullscreenEnter: string;
|
|
49
|
-
mediaFullscreenExit: string;
|
|
50
|
-
uploadSending: string;
|
|
51
|
-
uploadCancel: string;
|
|
52
|
-
uploadRetry: string;
|
|
53
|
-
uploadError: string;
|
|
54
|
-
uploadCanceled: string;
|
|
55
|
-
uploadComplete: string;
|
|
56
|
-
codeEditor: string;
|
|
57
|
-
chatLabel: string;
|
|
58
|
-
chatMessage: string;
|
|
59
|
-
chatSend: string;
|
|
60
|
-
qrCode: string;
|
|
61
|
-
copyCode: string;
|
|
62
|
-
tocLabel: string;
|
|
63
|
-
navigationToggle: string;
|
|
64
|
-
}
|
|
65
|
-
export declare const defaultStrings: AureaStrings;
|
|
66
|
-
export declare const ptBR: AureaStrings;
|
|
67
|
-
export declare const StringsContext: import("react").Context<AureaStrings>;
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type AureaStrings } from "./pure.js";
|
|
3
|
+
export { cx, defaultStrings, ptBR, defaultSpriteUrl, universalStates, stateSeverity, type AureaStrings, type UniversalState } from "./pure.js";
|
|
4
|
+
export declare const StringsContext: React.Context<AureaStrings>;
|
|
68
5
|
export declare const useAureaStrings: () => AureaStrings;
|
|
69
|
-
export declare const
|
|
70
|
-
export declare const SpriteContext: import("react").Context<string>;
|
|
6
|
+
export declare const SpriteContext: React.Context<string>;
|
|
71
7
|
export declare const useSpriteUrl: () => string;
|
|
72
|
-
export declare
|
|
8
|
+
export declare const PortalContext: React.Context<HTMLElement | null | undefined>;
|
|
9
|
+
export declare const usePortalContainer: () => HTMLElement | null | undefined;
|
|
10
|
+
export interface Reordenavel<E extends HTMLElement> {
|
|
11
|
+
ref: React.RefObject<E | null>;
|
|
12
|
+
pego: number | null;
|
|
13
|
+
aviso: string;
|
|
14
|
+
teclado: (e: React.KeyboardEvent<HTMLButtonElement>, i: number) => void;
|
|
15
|
+
ponteiroBaixo: (e: React.PointerEvent<HTMLButtonElement>, i: number) => void;
|
|
16
|
+
ponteiroMove: (e: React.PointerEvent) => void;
|
|
17
|
+
ponteiroSolta: () => void;
|
|
18
|
+
}
|
|
19
|
+
export declare function useReorder<E extends HTMLElement>({ count, order, onReorder, rowSelector, handleSelector }: {
|
|
20
|
+
count: number;
|
|
21
|
+
order: unknown;
|
|
22
|
+
onReorder: (from: number, to: number) => void;
|
|
23
|
+
rowSelector: string;
|
|
24
|
+
handleSelector: string;
|
|
25
|
+
}): Reordenavel<E>;
|