@1doc/1ds-react 2.8.0 → 2.9.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 (213) hide show
  1. package/CHANGELOG.md +1106 -0
  2. package/dist/components/AILabel/AILabel.js +1 -1
  3. package/dist/components/Accordion/Accordion.d.ts +6 -2
  4. package/dist/components/AttachmentCard/AttachmentCard.css +16 -0
  5. package/dist/components/AttachmentCard/AttachmentCard.d.ts +19 -2
  6. package/dist/components/AttachmentCard/AttachmentCard.js +40 -3
  7. package/dist/components/Avatar/Avatar.css +7 -2
  8. package/dist/components/Avatar/AvatarGroup.d.ts +17 -0
  9. package/dist/components/Avatar/AvatarGroup.js +22 -8
  10. package/dist/components/Badge/Badge.css +54 -2
  11. package/dist/components/Badge/Badge.d.ts +14 -4
  12. package/dist/components/Badge/Badge.js +1 -0
  13. package/dist/components/Box/Box.css +83 -0
  14. package/dist/components/Box/Box.d.ts +82 -2
  15. package/dist/components/Box/Box.js +42 -2
  16. package/dist/components/Button/Button.css +29 -0
  17. package/dist/components/Button/Button.d.ts +4 -4
  18. package/dist/components/Button/Button.js +4 -1
  19. package/dist/components/Calendar/Calendar.css +245 -0
  20. package/dist/components/Calendar/Calendar.d.ts +125 -0
  21. package/dist/components/Calendar/Calendar.js +320 -0
  22. package/dist/components/Chips/Chips.css +38 -0
  23. package/dist/components/Chips/Chips.d.ts +5 -2
  24. package/dist/components/Chips/Chips.js +2 -1
  25. package/dist/components/Coachmark/Coachmark.css +118 -0
  26. package/dist/components/Coachmark/Coachmark.d.ts +75 -0
  27. package/dist/components/Coachmark/Coachmark.js +321 -0
  28. package/dist/components/CodeBlock/CodeBlock.css +96 -0
  29. package/dist/components/CodeBlock/CodeBlock.d.ts +47 -0
  30. package/dist/components/CodeBlock/CodeBlock.js +103 -0
  31. package/dist/components/ColorPicker/ColorPicker.css +133 -0
  32. package/dist/components/ColorPicker/ColorPicker.d.ts +73 -0
  33. package/dist/components/ColorPicker/ColorPicker.js +219 -0
  34. package/dist/components/Combobox/Combobox.css +8 -0
  35. package/dist/components/DataTable/DataTable.css +80 -0
  36. package/dist/components/DataTable/DataTable.d.ts +19 -4
  37. package/dist/components/DataTable/DataTable.js +59 -15
  38. package/dist/components/DatePicker/DatePicker.css +8 -0
  39. package/dist/components/DatePicker/DatePicker.js +10 -1
  40. package/dist/components/DescriptionList/DescriptionList.css +113 -0
  41. package/dist/components/DescriptionList/DescriptionList.d.ts +59 -0
  42. package/dist/components/DescriptionList/DescriptionList.js +51 -0
  43. package/dist/components/FileInput/FileInput.css +16 -0
  44. package/dist/components/FileInput/FileInput.d.ts +4 -2
  45. package/dist/components/FileInput/FileInput.js +8 -2
  46. package/dist/components/Grid/Grid.js +5 -5
  47. package/dist/components/IconPicker/IconPicker.css +107 -0
  48. package/dist/components/IconPicker/IconPicker.d.ts +74 -0
  49. package/dist/components/IconPicker/IconPicker.js +194 -0
  50. package/dist/components/Input/Input.css +38 -0
  51. package/dist/components/Input/Input.d.ts +10 -1
  52. package/dist/components/Input/Input.js +66 -5
  53. package/dist/components/Kanban/Kanban.css +4 -0
  54. package/dist/components/Kbd/Kbd.css +66 -0
  55. package/dist/components/Kbd/Kbd.d.ts +32 -0
  56. package/dist/components/Kbd/Kbd.js +40 -0
  57. package/dist/components/List/List.css +136 -0
  58. package/dist/components/List/List.d.ts +82 -0
  59. package/dist/components/List/List.js +53 -0
  60. package/dist/components/List/ListItem.d.ts +85 -0
  61. package/dist/components/List/ListItem.js +81 -0
  62. package/dist/components/Modal/Modal.css +80 -0
  63. package/dist/components/Modal/Modal.d.ts +33 -6
  64. package/dist/components/Modal/Modal.js +101 -6
  65. package/dist/components/MultiSelect/MultiSelect.css +8 -0
  66. package/dist/components/MultiSelect/MultiSelect.js +10 -1
  67. package/dist/components/OrgChart/OrgChart.css +149 -0
  68. package/dist/components/OrgChart/OrgChart.d.ts +83 -0
  69. package/dist/components/OrgChart/OrgChart.js +297 -0
  70. package/dist/components/OtpInput/OtpInput.css +93 -0
  71. package/dist/components/OtpInput/OtpInput.d.ts +60 -0
  72. package/dist/components/OtpInput/OtpInput.js +215 -0
  73. package/dist/components/PhoneInput/PhoneInput.css +8 -0
  74. package/dist/components/Popover/Popover.d.ts +7 -0
  75. package/dist/components/Popover/Popover.js +11 -1
  76. package/dist/components/RichTextEditor/RichTextEditor.css +203 -0
  77. package/dist/components/RichTextEditor/RichTextEditor.d.ts +83 -0
  78. package/dist/components/RichTextEditor/RichTextEditor.js +494 -0
  79. package/dist/components/SegmentedControl/SegmentedControl.js +7 -2
  80. package/dist/components/Select/Select.css +70 -0
  81. package/dist/components/Select/Select.d.ts +12 -0
  82. package/dist/components/Select/Select.js +59 -4
  83. package/dist/components/Stack/Stack.css +49 -0
  84. package/dist/components/Stack/Stack.d.ts +65 -7
  85. package/dist/components/Stack/Stack.js +30 -2
  86. package/dist/components/StatCard/StatCard.css +73 -0
  87. package/dist/components/StatCard/StatCard.d.ts +17 -0
  88. package/dist/components/StatCard/StatCard.js +4 -1
  89. package/dist/components/Tabs/Tab.d.ts +15 -0
  90. package/dist/components/Tabs/Tab.js +30 -1
  91. package/dist/components/Tabs/Tabs.css +132 -0
  92. package/dist/components/Tabs/Tabs.d.ts +7 -0
  93. package/dist/components/Tabs/Tabs.js +13 -2
  94. package/dist/components/Tag/Tag.css +85 -2
  95. package/dist/components/Tag/Tag.d.ts +13 -6
  96. package/dist/components/Tag/Tag.js +1 -0
  97. package/dist/components/Text/Text.js +2 -2
  98. package/dist/components/Textarea/Textarea.css +8 -0
  99. package/dist/components/TimePicker/TimePicker.css +8 -0
  100. package/dist/components/Tooltip/Tooltip.css +25 -0
  101. package/dist/components/Tooltip/Tooltip.d.ts +11 -0
  102. package/dist/components/Tooltip/Tooltip.js +18 -3
  103. package/dist/index.d.ts +25 -0
  104. package/dist/index.js +14 -0
  105. package/dist/teste/AILabel.test.d.ts +1 -0
  106. package/dist/teste/AILabel.test.js +33 -0
  107. package/dist/teste/AccordionConteudoLivre.test.d.ts +1 -0
  108. package/dist/teste/AccordionConteudoLivre.test.js +29 -0
  109. package/dist/teste/AtributosRepassados.test.d.ts +1 -0
  110. package/dist/teste/AtributosRepassados.test.js +52 -0
  111. package/dist/teste/AttachmentCardIA.test.d.ts +1 -0
  112. package/dist/teste/AttachmentCardIA.test.js +89 -0
  113. package/dist/teste/AvatarGroupOverlap.test.d.ts +1 -0
  114. package/dist/teste/AvatarGroupOverlap.test.js +56 -0
  115. package/dist/teste/BadgeTag.test.d.ts +1 -0
  116. package/dist/teste/BadgeTag.test.js +42 -0
  117. package/dist/teste/BoxItemFlex.test.d.ts +1 -0
  118. package/dist/teste/BoxItemFlex.test.js +54 -0
  119. package/dist/teste/BoxLayout.test.d.ts +1 -0
  120. package/dist/teste/BoxLayout.test.js +35 -0
  121. package/dist/teste/Button.test.d.ts +1 -0
  122. package/dist/teste/Button.test.js +27 -0
  123. package/dist/teste/Calendar.test.d.ts +1 -0
  124. package/dist/teste/Calendar.test.js +221 -0
  125. package/dist/teste/ChipsXs.test.d.ts +1 -0
  126. package/dist/teste/ChipsXs.test.js +31 -0
  127. package/dist/teste/Coachmark.test.d.ts +1 -0
  128. package/dist/teste/Coachmark.test.js +149 -0
  129. package/dist/teste/ColorPicker.test.d.ts +1 -0
  130. package/dist/teste/ColorPicker.test.js +132 -0
  131. package/dist/teste/DataTableCelulaLivre.test.d.ts +1 -0
  132. package/dist/teste/DataTableCelulaLivre.test.js +76 -0
  133. package/dist/teste/DataTableDocumento.test.d.ts +1 -0
  134. package/dist/teste/DataTableDocumento.test.js +92 -0
  135. package/dist/teste/DatePicker.test.js +23 -0
  136. package/dist/teste/FileInputTrigger.test.d.ts +1 -0
  137. package/dist/teste/FileInputTrigger.test.js +53 -0
  138. package/dist/teste/IconPicker.test.d.ts +1 -0
  139. package/dist/teste/IconPicker.test.js +130 -0
  140. package/dist/teste/InputMascaraEAfins.test.d.ts +1 -0
  141. package/dist/teste/InputMascaraEAfins.test.js +99 -0
  142. package/dist/teste/KbdCodeBlock.test.d.ts +1 -0
  143. package/dist/teste/KbdCodeBlock.test.js +95 -0
  144. package/dist/teste/List.test.d.ts +1 -0
  145. package/dist/teste/List.test.js +153 -0
  146. package/dist/teste/ModalVariantes.test.d.ts +1 -0
  147. package/dist/teste/ModalVariantes.test.js +151 -0
  148. package/dist/teste/NomeAcessivelSsr.test.d.ts +1 -0
  149. package/dist/teste/NomeAcessivelSsr.test.js +88 -0
  150. package/dist/teste/OrgChart.test.d.ts +1 -0
  151. package/dist/teste/OrgChart.test.js +162 -0
  152. package/dist/teste/OtpInput.test.d.ts +1 -0
  153. package/dist/teste/OtpInput.test.js +143 -0
  154. package/dist/teste/PopoverMaxHeight.test.d.ts +1 -0
  155. package/dist/teste/PopoverMaxHeight.test.js +38 -0
  156. package/dist/teste/RichTextEditor.test.d.ts +1 -0
  157. package/dist/teste/RichTextEditor.test.js +287 -0
  158. package/dist/teste/SelectPlacementFiltro.test.d.ts +1 -0
  159. package/dist/teste/SelectPlacementFiltro.test.js +88 -0
  160. package/dist/teste/Stack.test.d.ts +1 -0
  161. package/dist/teste/Stack.test.js +57 -0
  162. package/dist/teste/StatCardRotuloTopo.test.d.ts +1 -0
  163. package/dist/teste/StatCardRotuloTopo.test.js +34 -0
  164. package/dist/teste/TabsContadorFechavel.test.d.ts +1 -0
  165. package/dist/teste/TabsContadorFechavel.test.js +79 -0
  166. package/dist/teste/TooltipDark.test.d.ts +1 -0
  167. package/dist/teste/TooltipDark.test.js +31 -0
  168. package/dist/utils/calendario.d.ts +28 -0
  169. package/dist/utils/calendario.js +73 -0
  170. package/dist/utils/html-seguro.d.ts +27 -0
  171. package/dist/utils/html-seguro.js +97 -0
  172. package/dist/utils/paleta-de-cores.d.ts +26 -0
  173. package/dist/utils/paleta-de-cores.js +10 -0
  174. package/dist/utils/texto.d.ts +5 -0
  175. package/dist/utils/texto.js +5 -0
  176. package/package.json +3 -3
  177. package/src/index.ts +26 -0
  178. package/src/teste/AILabel.test.tsx +41 -0
  179. package/src/teste/AccordionConteudoLivre.test.tsx +39 -0
  180. package/src/teste/AtributosRepassados.test.tsx +73 -0
  181. package/src/teste/AttachmentCardIA.test.tsx +126 -0
  182. package/src/teste/AvatarGroupOverlap.test.tsx +74 -0
  183. package/src/teste/BadgeTag.test.tsx +64 -0
  184. package/src/teste/BoxItemFlex.test.tsx +81 -0
  185. package/src/teste/BoxLayout.test.tsx +50 -0
  186. package/src/teste/Button.test.tsx +39 -0
  187. package/src/teste/Calendar.test.tsx +282 -0
  188. package/src/teste/ChipsXs.test.tsx +41 -0
  189. package/src/teste/Coachmark.test.tsx +198 -0
  190. package/src/teste/ColorPicker.test.tsx +153 -0
  191. package/src/teste/DataTableCelulaLivre.test.tsx +103 -0
  192. package/src/teste/DataTableDocumento.test.tsx +102 -0
  193. package/src/teste/DatePicker.test.tsx +38 -0
  194. package/src/teste/FileInputTrigger.test.tsx +89 -0
  195. package/src/teste/IconPicker.test.tsx +145 -0
  196. package/src/teste/InputMascaraEAfins.test.tsx +124 -0
  197. package/src/teste/KbdCodeBlock.test.tsx +106 -0
  198. package/src/teste/List.test.tsx +269 -0
  199. package/src/teste/ModalVariantes.test.tsx +173 -0
  200. package/src/teste/NomeAcessivelSsr.test.tsx +110 -0
  201. package/src/teste/OrgChart.test.tsx +183 -0
  202. package/src/teste/OtpInput.test.tsx +163 -0
  203. package/src/teste/PopoverMaxHeight.test.tsx +47 -0
  204. package/src/teste/RichTextEditor.test.tsx +329 -0
  205. package/src/teste/SelectPlacementFiltro.test.tsx +110 -0
  206. package/src/teste/Stack.test.tsx +80 -0
  207. package/src/teste/StatCardRotuloTopo.test.tsx +44 -0
  208. package/src/teste/TabsContadorFechavel.test.tsx +144 -0
  209. package/src/teste/TooltipDark.test.tsx +51 -0
  210. package/src/utils/calendario.ts +78 -0
  211. package/src/utils/html-seguro.ts +94 -0
  212. package/src/utils/paleta-de-cores.ts +34 -0
  213. package/src/utils/texto.ts +5 -0
@@ -0,0 +1,297 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import './OrgChart.css';
4
+ import { useState, useRef, useEffect } from "react";
5
+ function OrgChart(props) {
6
+ const rootRef = useRef(null);
7
+ const focoPendenteRef = useRef("");
8
+ const [internalCollapsed, setInternalCollapsed] = useState(() => props.defaultCollapsedIds || []);
9
+ const [focusId, setFocusId] = useState(() => "");
10
+ function widthPx() {
11
+ return props.nodeWidth && props.nodeWidth > 0 ? props.nodeWidth : 176;
12
+ }
13
+ function heightPx() {
14
+ return props.nodeHeight && props.nodeHeight > 0 ? props.nodeHeight : 64;
15
+ }
16
+ function gapXPx() {
17
+ return props.gapX !== undefined && props.gapX >= 0 ? props.gapX : 16;
18
+ }
19
+ function gapYPx() {
20
+ return props.gapY !== undefined && props.gapY >= 0 ? props.gapY : 40;
21
+ }
22
+ function collapsed() {
23
+ return props.collapsedIds !== undefined
24
+ ? props.collapsedIds
25
+ : internalCollapsed;
26
+ }
27
+ function treeName() {
28
+ return props.ariaLabel || "Organograma";
29
+ }
30
+ function classes() {
31
+ return ["umds-org-chart", props.className].filter(Boolean).join(" ");
32
+ }
33
+ function layout() {
34
+ const raizes = props.nodes || [];
35
+ const larg = widthPx();
36
+ const alt = heightPx();
37
+ const passoX = larg + gapXPx();
38
+ const passoY = alt + gapYPx();
39
+ const fechados = collapsed();
40
+ const lista = [];
41
+ const caminhos = [];
42
+ let folha = 0;
43
+ let maxNivel = 0;
44
+ const visitar = (no, nivel, paiId, pos, total) => {
45
+ const filhos = no.children || [];
46
+ const temFilhos = filhos.length > 0;
47
+ const aberto = temFilhos && fechados.indexOf(no.id) === -1;
48
+ const item = {
49
+ id: no.id,
50
+ node: no,
51
+ level: nivel,
52
+ parentId: paiId,
53
+ position: pos,
54
+ setSize: total,
55
+ hasChildren: temFilhos,
56
+ expanded: aberto,
57
+ childIds: [],
58
+ x: 0,
59
+ y: nivel * passoY,
60
+ };
61
+ if (nivel > maxNivel)
62
+ maxNivel = nivel;
63
+ lista.push(item);
64
+ if (aberto) {
65
+ const acima = [];
66
+ for (let i = 0; i < filhos.length; i++) {
67
+ const filho = visitar(filhos[i], nivel + 1, no.id, i + 1, filhos.length);
68
+ acima.push(filho);
69
+ item.childIds.push(filho.id);
70
+ }
71
+ item.x = (acima[0].x + acima[acima.length - 1].x) / 2;
72
+ // Conector: desce do pai até o meio do espaço, corre na horizontal e desce a cada filho.
73
+ const paiCentro = item.x + larg / 2;
74
+ const baseDoPai = item.y + alt;
75
+ const meio = baseDoPai + gapYPx() / 2;
76
+ let d = "M" + paiCentro + " " + baseDoPai + " V" + meio;
77
+ const primeiro = acima[0].x + larg / 2;
78
+ const ultimo = acima[acima.length - 1].x + larg / 2;
79
+ if (acima.length > 1)
80
+ d += " M" + primeiro + " " + meio + " H" + ultimo;
81
+ for (let j = 0; j < acima.length; j++) {
82
+ const cx = acima[j].x + larg / 2;
83
+ d += " M" + cx + " " + meio + " V" + acima[j].y;
84
+ }
85
+ caminhos.push(d);
86
+ }
87
+ else {
88
+ item.x = folha * passoX;
89
+ folha = folha + 1;
90
+ }
91
+ return item;
92
+ };
93
+ for (let r = 0; r < raizes.length; r++) {
94
+ visitar(raizes[r], 0, "", r + 1, raizes.length);
95
+ }
96
+ return {
97
+ items: lista,
98
+ paths: caminhos,
99
+ width: Math.max(folha * passoX - gapXPx(), larg),
100
+ height: (maxNivel + 1) * passoY - gapYPx(),
101
+ };
102
+ }
103
+ function itemList() {
104
+ return layout().items;
105
+ }
106
+ function toggleList() {
107
+ return itemList().filter((item) => item.hasChildren);
108
+ }
109
+ function pathList() {
110
+ return layout().paths;
111
+ }
112
+ function surfaceStyle() {
113
+ return {
114
+ width: layout().width + "px",
115
+ height: layout().height + "px",
116
+ };
117
+ }
118
+ function hasNodes() {
119
+ return itemList().length > 0;
120
+ }
121
+ function tabId() {
122
+ const lista = itemList();
123
+ for (let i = 0; i < lista.length; i++) {
124
+ if (lista[i].id === focusId)
125
+ return focusId;
126
+ }
127
+ return lista.length ? lista[0].id : "";
128
+ }
129
+ function nodeClasses(item) {
130
+ return [
131
+ "umds-org-chart__node",
132
+ item.level === 0 ? "umds-org-chart__node--root" : "",
133
+ item.id === props.selectedId ? "umds-org-chart__node--selected" : "",
134
+ ]
135
+ .filter(Boolean)
136
+ .join(" ");
137
+ }
138
+ function nodeStyle(item) {
139
+ return {
140
+ left: item.x + "px",
141
+ top: item.y + "px",
142
+ width: widthPx() + "px",
143
+ height: heightPx() + "px",
144
+ };
145
+ }
146
+ function toggleStyle(item) {
147
+ return {
148
+ left: item.x + widthPx() / 2 + "px",
149
+ top: item.y + heightPx() + "px",
150
+ };
151
+ }
152
+ function expandedText(item) {
153
+ return item.hasChildren ? (item.expanded ? "true" : "false") : undefined;
154
+ }
155
+ function selectedText(item) {
156
+ return item.id === props.selectedId ? "true" : undefined;
157
+ }
158
+ function toggleGlyph(item) {
159
+ return item.expanded ? "−" : "+";
160
+ }
161
+ function toggleName(item) {
162
+ return item.expanded
163
+ ? props.collapseLabel || "Recolher"
164
+ : props.expandLabel || "Expandir";
165
+ }
166
+ function subtitleOf(item) {
167
+ return item.node.subtitle || "";
168
+ }
169
+ function customContent(item) {
170
+ if (props.renderNode)
171
+ return props.renderNode(item.node, {
172
+ level: item.level,
173
+ expanded: item.expanded,
174
+ });
175
+ return "";
176
+ }
177
+ function hasCustomContent() {
178
+ return !!props.renderNode;
179
+ }
180
+ function plainContent() {
181
+ return !props.renderNode;
182
+ }
183
+ function mudarRecolhidos(proximos) {
184
+ setInternalCollapsed(proximos);
185
+ if (props.onCollapsedChange)
186
+ props.onCollapsedChange(proximos);
187
+ }
188
+ function alternar(item) {
189
+ if (!item.hasChildren)
190
+ return;
191
+ const atuais = collapsed();
192
+ mudarRecolhidos(item.expanded
193
+ ? atuais.concat([item.id])
194
+ : atuais.filter((id) => id !== item.id));
195
+ }
196
+ function acharItem(id) {
197
+ const lista = itemList();
198
+ for (let i = 0; i < lista.length; i++) {
199
+ if (lista[i].id === id)
200
+ return lista[i];
201
+ }
202
+ return null;
203
+ }
204
+ function irPara(id) {
205
+ if (!id)
206
+ return;
207
+ setFocusId(id);
208
+ focoPendenteRef.current = id;
209
+ }
210
+ function focarNo(id) {
211
+ if (!rootRef.current)
212
+ return;
213
+ const alvo = rootRef.current.querySelector('[data-node-id="' + id + '"]');
214
+ if (alvo)
215
+ alvo.focus();
216
+ }
217
+ function handleNodeClick(item) {
218
+ setFocusId(item.id);
219
+ if (props.onNodeClick)
220
+ props.onNodeClick(item.node);
221
+ }
222
+ function handleToggleClick(event, item) {
223
+ if (event && event.stopPropagation)
224
+ event.stopPropagation();
225
+ alternar(item);
226
+ }
227
+ function irmaosDe(item) {
228
+ return itemList().filter((outro) => outro.parentId === item.parentId);
229
+ }
230
+ function handleKeyDown(event, item) {
231
+ if (!event || event.altKey || event.ctrlKey || event.metaKey)
232
+ return;
233
+ if (event.target !== event.currentTarget)
234
+ return;
235
+ const tecla = event.key;
236
+ const irmaos = irmaosDe(item);
237
+ // Por id: o desenho é recalculado a cada leitura, então os objetos mudam e a identidade não vale.
238
+ let indice = -1;
239
+ for (let i = 0; i < irmaos.length; i++) {
240
+ if (irmaos[i].id === item.id)
241
+ indice = i;
242
+ }
243
+ if (tecla === "ArrowLeft" || tecla === "ArrowRight") {
244
+ event.preventDefault();
245
+ const alvo = irmaos[indice + (tecla === "ArrowRight" ? 1 : -1)];
246
+ if (alvo)
247
+ irPara(alvo.id);
248
+ }
249
+ else if (tecla === "Home") {
250
+ event.preventDefault();
251
+ irPara(irmaos[0].id);
252
+ }
253
+ else if (tecla === "End") {
254
+ event.preventDefault();
255
+ irPara(irmaos[irmaos.length - 1].id);
256
+ }
257
+ else if (tecla === "ArrowUp") {
258
+ event.preventDefault();
259
+ if (item.parentId)
260
+ irPara(item.parentId);
261
+ }
262
+ else if (tecla === "ArrowDown") {
263
+ event.preventDefault();
264
+ if (!item.hasChildren)
265
+ return;
266
+ if (!item.expanded) {
267
+ // Recolhido: o primeiro Baixo abre; o foco desce no seguinte.
268
+ alternar(item);
269
+ return;
270
+ }
271
+ irPara(item.childIds[0]);
272
+ }
273
+ else if (tecla === " ") {
274
+ event.preventDefault();
275
+ alternar(item);
276
+ }
277
+ else if (tecla === "Enter") {
278
+ event.preventDefault();
279
+ handleNodeClick(item);
280
+ }
281
+ }
282
+ function handleFocus(event, item) {
283
+ if (event && event.target !== event.currentTarget)
284
+ return;
285
+ if (focusId !== item.id)
286
+ setFocusId(item.id);
287
+ }
288
+ useEffect(() => {
289
+ if (focoPendenteRef.current) {
290
+ const alvo = focoPendenteRef.current;
291
+ focoPendenteRef.current = "";
292
+ focarNo(alvo);
293
+ }
294
+ });
295
+ return (_jsx("div", { ref: rootRef, className: classes(), children: hasNodes() ? (_jsx("div", { role: "tree", className: "umds-org-chart__scroller", "aria-label": treeName(), children: _jsxs("div", { className: "umds-org-chart__surface", style: surfaceStyle(), children: [_jsx("svg", { "aria-hidden": "true", focusable: "false", className: "umds-org-chart__lines", width: layout().width, height: layout().height, children: pathList()?.map((caminho, posicao) => (_jsx("path", { className: "umds-org-chart__line", d: caminho }, posicao))) }), itemList()?.map((item) => (_jsxs("div", { role: "treeitem", style: nodeStyle(item), "data-node-id": item.id, "aria-level": item.level + 1, "aria-posinset": item.position, "aria-setsize": item.setSize, "aria-expanded": expandedText(item), "aria-selected": selectedText(item), tabIndex: item.id === tabId() ? 0 : -1, onClick: (event) => handleNodeClick(item), onKeyDown: (event) => handleKeyDown(event, item), onFocus: (event) => handleFocus(event, item), className: nodeClasses(item), children: [hasCustomContent() ? (_jsx("div", { className: "umds-org-chart__custom", children: customContent(item) })) : null, plainContent() ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "umds-org-chart__title", title: item.node.title, children: item.node.title }), item.node.subtitle ? (_jsx("span", { className: "umds-org-chart__subtitle", title: subtitleOf(item), children: item.node.subtitle })) : null] })) : null] }, item.id))), toggleList()?.map((item) => (_jsx("button", { type: "button", "aria-hidden": "true", className: "umds-org-chart__toggle", style: toggleStyle(item), tabIndex: -1, title: toggleName(item), onClick: (event) => handleToggleClick(event, item), children: toggleGlyph(item) }, item.id)))] }) })) : null }));
296
+ }
297
+ export default OrgChart;
@@ -0,0 +1,93 @@
1
+ /* ─────────────────────────────────────────────
2
+ OTP INPUT
3
+ Código de verificação em caixas de um caractere.
4
+
5
+ A caixa segue a família de campos: borda de repouso, hover, foco (borda +
6
+ anel) e erro vêm dos tokens `--umds-semantic-field-*`. O que muda é a
7
+ geometria: caixa alta, número grande e centralizado.
8
+
9
+ Cores: semânticos · Medidas: primitivos
10
+ ───────────────────────────────────────────── */
11
+
12
+ .umds-otp {
13
+ display: inline-flex;
14
+ flex-direction: column;
15
+ gap: var(--umds-primitive-spacing-quarck); /* 4px */
16
+ font-family: var(--umds-semantic-font-family-base);
17
+ }
18
+
19
+ .umds-otp__label {
20
+ font-size: var(--umds-semantic-field-label-size);
21
+ font-weight: var(--umds-semantic-field-label-weight);
22
+ color: var(--umds-semantic-field-label-color);
23
+ }
24
+
25
+ .umds-otp__digits {
26
+ display: flex;
27
+ gap: var(--umds-primitive-spacing-nano); /* 8px */
28
+ }
29
+
30
+ .umds-otp__digit {
31
+ box-sizing: border-box;
32
+ margin: 0;
33
+ padding: 0;
34
+ text-align: center;
35
+ font-family: inherit;
36
+ font-weight: var(--umds-primitive-font-weight-bold);
37
+ color: var(--umds-semantic-field-text-color);
38
+ background: var(--umds-semantic-color-background-white);
39
+ border: var(--umds-primitive-border-width-hairline) solid var(--umds-semantic-field-border-default);
40
+ border-radius: var(--umds-primitive-border-radius-sm);
41
+ caret-color: var(--umds-semantic-color-primary-pure);
42
+ transition:
43
+ border-color var(--umds-semantic-motion-duration-fast) var(--umds-semantic-motion-easing-standard),
44
+ box-shadow var(--umds-semantic-motion-duration-fast) var(--umds-semantic-motion-easing-standard);
45
+ }
46
+
47
+ .umds-otp--md .umds-otp__digit {
48
+ width: var(--umds-primitive-spacing-md); /* 48px */
49
+ height: var(--umds-primitive-spacing-lg); /* 56px */
50
+ font-size: var(--umds-primitive-font-size-md); /* 24px */
51
+ }
52
+
53
+ .umds-otp--sm .umds-otp__digit {
54
+ width: var(--umds-primitive-spacing-sm); /* 40px */
55
+ height: var(--umds-primitive-spacing-md); /* 48px */
56
+ font-size: var(--umds-primitive-font-size-sm); /* 20px */
57
+ }
58
+
59
+ .umds-otp__digit:hover:not(:disabled) {
60
+ border-color: var(--umds-semantic-field-border-hover);
61
+ }
62
+
63
+ .umds-otp__digit:focus,
64
+ .umds-otp__digit:focus-visible {
65
+ outline: none;
66
+ border-color: var(--umds-semantic-field-border-focus);
67
+ box-shadow: var(--umds-semantic-field-ring-focus);
68
+ }
69
+
70
+ .umds-otp--invalid .umds-otp__digit,
71
+ .umds-otp--invalid .umds-otp__digit:hover:not(:disabled) {
72
+ border-color: var(--umds-semantic-field-border-error);
73
+ }
74
+
75
+ .umds-otp--invalid .umds-otp__digit:focus,
76
+ .umds-otp--invalid .umds-otp__digit:focus-visible {
77
+ box-shadow: var(--umds-semantic-field-ring-error);
78
+ }
79
+
80
+ .umds-otp__digit:disabled {
81
+ cursor: not-allowed;
82
+ background: var(--umds-semantic-field-disabled-background);
83
+ opacity: var(--umds-semantic-field-disabled-opacity);
84
+ }
85
+
86
+ /* Alto contraste: o anel de foco de sombra some, o contorno do sistema fica. */
87
+ @media (forced-colors: active) {
88
+ .umds-otp__digit:focus,
89
+ .umds-otp__digit:focus-visible {
90
+ outline: var(--umds-primitive-border-width-thin) solid Highlight;
91
+ outline-offset: var(--umds-primitive-border-width-thin);
92
+ }
93
+ }
@@ -0,0 +1,60 @@
1
+ import './OtpInput.css';
2
+ /**
3
+ * OtpInput — código de verificação em caixas de um caractere (SMS, e-mail,
4
+ * app autenticador).
5
+ *
6
+ * `length` caixas (6 por padrão). O foco anda sozinho: digitar avança, Backspace
7
+ * apaga e volta, as setas, Home e End movem. Colar o código inteiro em qualquer
8
+ * caixa distribui os caracteres; o preenchimento automático do navegador (SMS)
9
+ * também, porque a primeira caixa leva `autocomplete="one-time-code"`.
10
+ * Clicar numa caixa à frente da primeira vazia manda o foco de volta a ela: o
11
+ * código nunca fica com buraco no meio.
12
+ *
13
+ * O valor é uma string. `onChange` recebe o código a cada mudança e `onComplete`
14
+ * recebe quando as `length` caixas ficam cheias (uma vez por código completo).
15
+ * Aceita só dígitos (`type="numeric"`, padrão, com teclado numérico no celular)
16
+ * ou letras e dígitos (`type="alphanumeric"`, que sai em maiúsculas).
17
+ *
18
+ * Acessibilidade: o conjunto é um `role="group"` nomeado por `label` ou
19
+ * `ariaLabel`, e cada caixa tem nome próprio ("Dígito 3 de 6"). Troque
20
+ * `digitLabel` para traduzir; `{n}` e `{total}` viram a posição e o tamanho.
21
+ * Erro por `invalid` e `errorMessage` (ligado às caixas por `aria-describedby`).
22
+ * @property {number} length - Quantidade de caixas (padrão 6)
23
+ * @property {string} value - Código (controlado)
24
+ * @property {string} defaultValue - Código inicial (não controlado)
25
+ * @property {string} type - 'numeric' (padrão) | 'alphanumeric'
26
+ * @property {string} label - Rótulo visível do conjunto
27
+ * @property {string} ariaLabel - Nome acessível quando não há `label` visível
28
+ * @property {string} digitLabel - Nome de cada caixa; `{n}` e `{total}` são trocados (padrão: "Dígito {n} de {total}")
29
+ * @property {boolean} invalid - Estado de erro
30
+ * @property {string} errorMessage - Mensagem de erro (liga o estado de erro)
31
+ * @property {boolean} disabled - Desabilita todas as caixas
32
+ * @property {boolean} autoFocus - Foca a primeira caixa vazia ao montar
33
+ * @property {string} size - 'sm' | 'md' (padrão)
34
+ * @property {string} id - Base dos ids internos; passe em SSR para os ids já saírem no HTML do servidor
35
+ * @property {string} className - Classes CSS adicionais
36
+ * @property {function} onChange - Chamado com o código a cada mudança
37
+ * @property {function} onComplete - Chamado com o código quando todas as caixas ficam cheias
38
+ * @quandoUsar Confirmar um código curto que a pessoa recebeu por outro canal: autenticação em duas etapas, confirmação de e-mail ou de telefone.
39
+ * @quandoNaoUsar Para texto livre ou código de tamanho variável, use `Input`. Para senha, use `Input type="password"`. Para número com máscara (CPF, CEP), use `Input mask`.
40
+ */
41
+ export interface OtpInputProps {
42
+ length?: number;
43
+ value?: string;
44
+ defaultValue?: string;
45
+ type?: "numeric" | "alphanumeric";
46
+ label?: string;
47
+ ariaLabel?: string;
48
+ digitLabel?: string;
49
+ invalid?: boolean;
50
+ errorMessage?: string;
51
+ disabled?: boolean;
52
+ autoFocus?: boolean;
53
+ size?: "sm" | "md";
54
+ id?: string;
55
+ className?: string;
56
+ onChange?: (value: string) => void;
57
+ onComplete?: (value: string) => void;
58
+ }
59
+ declare function OtpInput(props: OtpInputProps): import("react/jsx-runtime").JSX.Element;
60
+ export default OtpInput;
@@ -0,0 +1,215 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import './OtpInput.css';
4
+ import { useState, useRef, useEffect } from "react";
5
+ import Text from "../Text/Text";
6
+ import { gerarId } from "../../utils/id";
7
+ function OtpInput(props) {
8
+ const groupRef = useRef(null);
9
+ const ultimoEventoRef = useRef(null);
10
+ const focoPendenteRef = useRef(-1);
11
+ const [internalValue, setInternalValue] = useState(() => props.defaultValue || "");
12
+ const [uid, setUid] = useState(() => "");
13
+ function baseId() {
14
+ return props.id || uid;
15
+ }
16
+ function codeLength() {
17
+ const n = props.length || 6;
18
+ return n < 1 ? 1 : n;
19
+ }
20
+ function positions() {
21
+ return Array.from({
22
+ length: codeLength(),
23
+ }, (_, i) => i);
24
+ }
25
+ function isAlpha() {
26
+ return props.type === "alphanumeric";
27
+ }
28
+ function limpar(texto) {
29
+ const bruto = texto || "";
30
+ const aceito = isAlpha()
31
+ ? bruto.replace(/[^0-9a-zA-Z]/g, "").toUpperCase()
32
+ : bruto.replace(/[^0-9]/g, "");
33
+ return aceito;
34
+ }
35
+ function currentValue() {
36
+ const bruto = props.value !== undefined ? props.value : internalValue;
37
+ return limpar(bruto).slice(0, codeLength());
38
+ }
39
+ function charAt(index) {
40
+ return currentValue().charAt(index);
41
+ }
42
+ function isInvalid() {
43
+ return !!props.invalid || !!props.errorMessage;
44
+ }
45
+ function labelId() {
46
+ return baseId() && props.label ? baseId() + "-label" : undefined;
47
+ }
48
+ function errorId() {
49
+ return baseId() && props.errorMessage ? baseId() + "-error" : undefined;
50
+ }
51
+ function groupAriaLabel() {
52
+ if (props.ariaLabel)
53
+ return props.ariaLabel;
54
+ return props.label && !labelId() ? props.label : undefined;
55
+ }
56
+ function ariaInvalidText() {
57
+ return isInvalid() ? "true" : undefined;
58
+ }
59
+ function classes() {
60
+ return [
61
+ "umds-otp",
62
+ `umds-otp--${props.size || "md"}`,
63
+ isInvalid() ? "umds-otp--invalid" : "",
64
+ props.disabled ? "umds-otp--disabled" : "",
65
+ props.className,
66
+ ]
67
+ .filter(Boolean)
68
+ .join(" ");
69
+ }
70
+ function digitName(index) {
71
+ const modelo = props.digitLabel || "Dígito {n} de {total}";
72
+ return modelo
73
+ .replace("{n}", String(index + 1))
74
+ .replace("{total}", String(codeLength()));
75
+ }
76
+ function inputMode() {
77
+ return isAlpha() ? "text" : "numeric";
78
+ }
79
+ function autoComplete(index) {
80
+ return index === 0 ? "one-time-code" : "off";
81
+ }
82
+ function digitId(index) {
83
+ return baseId() ? baseId() + "-" + index : undefined;
84
+ }
85
+ function definir(proximo) {
86
+ const novo = limpar(proximo).slice(0, codeLength());
87
+ const antigo = currentValue();
88
+ if (novo === antigo)
89
+ return false;
90
+ setInternalValue(novo);
91
+ if (props.onChange)
92
+ props.onChange(novo);
93
+ if (novo.length === codeLength() && props.onComplete)
94
+ props.onComplete(novo);
95
+ return true;
96
+ }
97
+ function focarDepois(index, mudou) {
98
+ if (mudou)
99
+ focoPendenteRef.current = index;
100
+ else
101
+ focarEm(index);
102
+ }
103
+ function focarEm(index) {
104
+ if (!groupRef.current)
105
+ return;
106
+ const caixas = groupRef.current.querySelectorAll("input");
107
+ const alvo = caixas[Math.max(0, Math.min(index, codeLength() - 1))];
108
+ if (alvo)
109
+ alvo.focus();
110
+ }
111
+ function limiteDoFoco() {
112
+ return Math.min(currentValue().length, codeLength() - 1);
113
+ }
114
+ function handleInput(event, index) {
115
+ const nativo = event.nativeEvent || event;
116
+ if (nativo === ultimoEventoRef.current)
117
+ return;
118
+ ultimoEventoRef.current = nativo;
119
+ const alvo = event.target;
120
+ const bruto = alvo.value || "";
121
+ const atual = charAt(index);
122
+ const valor = currentValue();
123
+ // Apagou: o código fecha o buraco (os de trás andam um para a frente).
124
+ if (bruto === "") {
125
+ const sem = atual
126
+ ? valor.slice(0, index) + valor.slice(index + 1)
127
+ : valor;
128
+ if (atual)
129
+ definir(sem);
130
+ alvo.value = sem.charAt(index);
131
+ return;
132
+ }
133
+ let texto = bruto;
134
+ // Digitou numa caixa que já tinha caractere: vale o que é novo.
135
+ if (atual && bruto.length === 2) {
136
+ texto = bruto.charAt(0) === atual ? bruto.charAt(1) : bruto.charAt(0);
137
+ }
138
+ const limpo = limpar(texto);
139
+ if (!limpo) {
140
+ alvo.value = atual;
141
+ return;
142
+ }
143
+ // O que sobra de um código colado ou autopreenchido segue para as próximas caixas.
144
+ const proximo = valor.slice(0, index) + limpo + valor.slice(index + limpo.length);
145
+ const mudou = definir(proximo);
146
+ // A caixa mostra já o que o código passa a ter (o React só relê a prop no próximo render).
147
+ alvo.value = limpar(proximo).slice(0, codeLength()).charAt(index);
148
+ focarDepois(Math.min(index + limpo.length, codeLength() - 1), mudou);
149
+ }
150
+ function handlePaste(event, index) {
151
+ if (!event || !event.clipboardData)
152
+ return;
153
+ const texto = limpar(event.clipboardData.getData("text"));
154
+ event.preventDefault();
155
+ if (!texto)
156
+ return;
157
+ // Código inteiro: substitui tudo. Pedaço: entra a partir da caixa em que se colou.
158
+ const inicio = texto.length >= codeLength() ? 0 : index;
159
+ const valor = currentValue();
160
+ const mudou = definir(valor.slice(0, inicio) + texto + valor.slice(inicio + texto.length));
161
+ focarDepois(Math.min(inicio + texto.length, codeLength() - 1), mudou);
162
+ }
163
+ function handleKeyDown(event, index) {
164
+ if (!event || event.altKey || event.ctrlKey || event.metaKey)
165
+ return;
166
+ const tecla = event.key;
167
+ if (tecla === "Backspace" && !charAt(index) && index > 0) {
168
+ event.preventDefault();
169
+ const valor = currentValue();
170
+ const mudou = definir(valor.slice(0, index - 1) + valor.slice(index));
171
+ focarDepois(index - 1, mudou);
172
+ }
173
+ else if (tecla === "ArrowLeft") {
174
+ event.preventDefault();
175
+ focarEm(index - 1);
176
+ }
177
+ else if (tecla === "ArrowRight") {
178
+ event.preventDefault();
179
+ focarEm(Math.min(index + 1, limiteDoFoco()));
180
+ }
181
+ else if (tecla === "Home") {
182
+ event.preventDefault();
183
+ focarEm(0);
184
+ }
185
+ else if (tecla === "End") {
186
+ event.preventDefault();
187
+ focarEm(limiteDoFoco());
188
+ }
189
+ }
190
+ function handleFocus(event, index) {
191
+ // Sem buraco: foco à frente da primeira vazia volta para ela.
192
+ const limite = limiteDoFoco();
193
+ if (index > limite) {
194
+ focarEm(limite);
195
+ return;
196
+ }
197
+ if (event && event.target && event.target.select)
198
+ event.target.select();
199
+ }
200
+ useEffect(() => {
201
+ if (!props.id)
202
+ setUid(gerarId("umds-otp"));
203
+ if (props.autoFocus)
204
+ focarEm(limiteDoFoco());
205
+ }, []);
206
+ useEffect(() => {
207
+ if (focoPendenteRef.current >= 0) {
208
+ const alvo = focoPendenteRef.current;
209
+ focoPendenteRef.current = -1;
210
+ focarEm(alvo);
211
+ }
212
+ });
213
+ return (_jsxs("div", { className: classes(), children: [props.label ? (_jsx("span", { className: "umds-otp__label", id: labelId(), children: props.label })) : null, _jsx("div", { role: "group", className: "umds-otp__digits", ref: groupRef, "aria-label": groupAriaLabel(), "aria-labelledby": labelId(), children: positions()?.map((caixa) => (_jsx("input", { type: "text", autoCapitalize: "off", className: "umds-otp__digit", id: digitId(caixa), inputMode: inputMode(), autoComplete: autoComplete(caixa), spellCheck: false, value: charAt(caixa), disabled: props.disabled, "aria-label": digitName(caixa), "aria-invalid": ariaInvalidText(), "aria-describedby": errorId(), onInput: (event) => handleInput(event, caixa), onChange: (event) => handleInput(event, caixa), onKeyDown: (event) => handleKeyDown(event, caixa), onPaste: (event) => handlePaste(event, caixa), onFocus: (event) => handleFocus(event, caixa) }, caixa))) }), props.errorMessage ? (_jsx(Text, { as: "span", variant: "caption", color: "negative", id: errorId(), children: props.errorMessage })) : null] }));
214
+ }
215
+ export default OtpInput;
@@ -99,6 +99,14 @@
99
99
  border-color: var(--umds-semantic-field-border-default);
100
100
  }
101
101
 
102
+ /* Somente leitura não é desabilitado: o texto segue lido e a WCAG 1.4.3 vale
103
+ sem isenção. O placeholder padrão foi calibrado para fundo branco e cai para
104
+ ~4,2:1 sobre o fundo de somente leitura; neutral-dark-down passa 4,5:1 em
105
+ todos os temas (1doc 6,78:1 · 1doc-dark 10,83:1 · alto contraste 16,48:1). */
106
+ .umds-phone-input--readonly .umds-phone-input__field::placeholder {
107
+ color: var(--umds-semantic-color-neutral-dark-down);
108
+ }
109
+
102
110
  /* ── Flag selector pill ── */
103
111
  .umds-phone-input__flag-btn {
104
112
  display: inline-flex;