@proef/common-ui 2.6.4 → 2.6.6

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/dist/esm/index.js CHANGED
@@ -19,6 +19,7 @@ import { default as default19, timestampDeData } from "./legacy/components/molec
19
19
  import { DateInput } from "./v1/primitives/forms/DateInput/DateInput.js";
20
20
  import { default as default20, useDialogContainer } from "./v1/components/overlays/Dialog/Dialog.js";
21
21
  import { default as default21, accepts } from "./v1/components/documents/DocumentDropzone/DocumentDropzone.js";
22
+ import { DEFAULT_DROPDOWN_MENU_LABELS, DropdownMenu } from "./v1/components/overlays/DropdownMenu/DropdownMenu.js";
22
23
  import { default as default22 } from "./legacy/components/layout/Error/Error.js";
23
24
  import { default as default23 } from "./legacy/pages/Error/ErrorPage.js";
24
25
  import { default as default24 } from "./legacy/components/ui/Escolha.js";
@@ -73,6 +74,7 @@ import { default as default69 } from "./legacy/components/molecules/Sidebar/Side
73
74
  import { default as default70 } from "./legacy/components/layout/Spinner/Spinner.js";
74
75
  import { default as default71 } from "./legacy/components/atoms/Stack/Stack.js";
75
76
  import { default as default72 } from "./legacy/components/organisms/StatusMatrix/StatusMatrix.js";
77
+ import { DEFAULT_STEPS_LABELS, Steps } from "./v1/primitives/navigation/Steps/Steps.js";
76
78
  import { default as default73 } from "./v1/primitives/forms/Switch/Switch.js";
77
79
  import { default as default74 } from "./legacy/components/atoms/Button/variants/TabButton.js";
78
80
  import { default as default75 } from "./v1/components/tables/Table/Table.js";
@@ -95,7 +97,7 @@ import { AvisosProvider, useAvisos } from "./legacy/components/ui/Avisos.js";
95
97
  import { Badge } from "./v1/primitives/display/Badge/Badge.js";
96
98
  import { BadgeSla, BarraFiltros, Btn, BtnGroup, Campo, CampoInterruptor, CampoPesquisa, CampoSelect, ChipEstadoInterno, Estado, LinhaAlerta, ListaCampos, Modal, SectionGroup } from "./legacy/components/ui/Ui.js";
97
99
  import { BarChart, DonutChart, LineChart, shortDateLabel, useChartPalette } from "./v1/components/data/Charts/Charts.js";
98
- import { BoldIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsUpDownIcon, CloseIcon, ErrorIcon, ExternalLinkIcon, FilterIcon, GlobeIcon, ImageIcon, InfoIcon, ItalicIcon, LayersIcon, ListBulletIcon, ListIcon, ListNumberedIcon, LockIcon, LogOutIcon, MaximizeIcon, MenuIcon, MinimizeIcon, MonitorIcon, MoonIcon, PanelOpenIcon, PrefilledIcon, QrCodeIcon, QuoteIcon, SearchIcon, SlidersIcon, SparklesIcon, StrikethroughIcon, SunIcon, UnderlineIcon, WarningIcon } from "./v1/foundations/icons/icons.js";
100
+ import { BoldIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsUpDownIcon, CloseIcon, ErrorIcon, ExternalLinkIcon, FilterIcon, GlobeIcon, ImageIcon, InfoIcon, ItalicIcon, LayersIcon, ListBulletIcon, ListIcon, ListNumberedIcon, LockIcon, LogOutIcon, MaximizeIcon, MenuIcon, MinimizeIcon, MonitorIcon, MoonIcon, MoreIcon, PanelOpenIcon, PrefilledIcon, QrCodeIcon, QuoteIcon, SearchIcon, SlidersIcon, SparklesIcon, StrikethroughIcon, SunIcon, UnderlineIcon, WarningIcon } from "./v1/foundations/icons/icons.js";
99
101
  import { Card } from "./v1/primitives/display/Card/Card.js";
100
102
  import { DEFAULT_LIST_FINDER_LABELS } from "./v1/components/lists/ListFinder/labels.js";
101
103
  import { DEFAULT_TABLE_LABELS } from "./v1/components/tables/Table/labels.js";
@@ -166,13 +168,16 @@ export {
166
168
  ConfirmProvider,
167
169
  default17 as Confirmacao,
168
170
  default18 as CustomSwitch,
171
+ DEFAULT_DROPDOWN_MENU_LABELS,
169
172
  DEFAULT_LIST_FINDER_LABELS,
173
+ DEFAULT_STEPS_LABELS,
170
174
  DEFAULT_TABLE_LABELS,
171
175
  default19 as DataTable,
172
176
  DateInput,
173
177
  default20 as Dialog,
174
178
  default21 as DocumentDropzone,
175
179
  DonutChart,
180
+ DropdownMenu,
176
181
  default22 as Error,
177
182
  ErrorIcon,
178
183
  default23 as ErrorPage,
@@ -235,6 +240,7 @@ export {
235
240
  default50 as Modal,
236
241
  MonitorIcon,
237
242
  MoonIcon,
243
+ MoreIcon,
238
244
  default51 as MultiTagPicker,
239
245
  default52 as NotFoundPage,
240
246
  Notice,
@@ -277,6 +283,7 @@ export {
277
283
  default70 as Spinner,
278
284
  default71 as Stack,
279
285
  default72 as StatusMatrix,
286
+ Steps,
280
287
  StrikethroughIcon,
281
288
  SunIcon,
282
289
  default73 as Switch,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,222 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import React, { useId, useRef, useMemo, useState, useEffect } from "react";
3
+ import { createPortal } from "react-dom";
4
+ import Button from "../../../primitives/buttons/Button/Button.js";
5
+ import { ChevronDownIcon, MoreIcon, CheckIcon } from "../../../foundations/icons/icons.js";
6
+ import { useFloatingPanel, PANEL_CLASS, itemClass } from "../../../capabilities/overlay/useFloatingPanel.js";
7
+ import { useDialogContainer } from "../Dialog/Dialog.js";
8
+ const DEFAULT_DROPDOWN_MENU_LABELS = {
9
+ more: "More actions",
10
+ search: "Search…",
11
+ noResults: "No results",
12
+ empty: "Nothing here yet"
13
+ };
14
+ const textOf = (item) => item.searchText ?? (typeof item.label === "string" || typeof item.label === "number" ? String(item.label) : "");
15
+ const isTyping = (el) => el instanceof HTMLElement && (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.isContentEditable);
16
+ function DropdownMenu({
17
+ items,
18
+ label,
19
+ icon,
20
+ "aria-label": ariaLabel,
21
+ variant,
22
+ size = "md",
23
+ active,
24
+ align,
25
+ disabled = false,
26
+ header,
27
+ searchable,
28
+ labels,
29
+ panelClassName = "",
30
+ className = "",
31
+ onOpenChange
32
+ }) {
33
+ const L = { ...DEFAULT_DROPDOWN_MENU_LABELS, ...labels };
34
+ const hasText = label !== void 0 && label !== null && label !== false;
35
+ const p = useFloatingPanel(align ?? (hasText ? "left" : "right"));
36
+ const dialogContainer = useDialogContainer();
37
+ const menuId = useId();
38
+ const searchRef = useRef(null);
39
+ const list = useMemo(() => items.filter((i) => !!i), [items]);
40
+ const withSearch = searchable ?? list.length > 10;
41
+ const [query, setQuery] = useState("");
42
+ const visible = useMemo(() => {
43
+ const q = query.trim().toLowerCase();
44
+ return q ? list.filter((i) => textOf(i).toLowerCase().includes(q)) : list;
45
+ }, [list, query]);
46
+ const enabled = visible.map((i, n) => i.disabled ? -1 : n).filter((n) => n >= 0);
47
+ const [activeIndex, setActiveIndex] = useState(-1);
48
+ const changed = useRef(onOpenChange);
49
+ changed.current = onOpenChange;
50
+ const first = useRef(true);
51
+ useEffect(() => {
52
+ if (first.current) {
53
+ first.current = false;
54
+ return;
55
+ }
56
+ changed.current?.(p.open);
57
+ }, [p.open]);
58
+ useEffect(() => {
59
+ if (!p.open) return;
60
+ setQuery("");
61
+ setActiveIndex(-1);
62
+ if (withSearch) setTimeout(() => searchRef.current?.focus(), 0);
63
+ }, [p.open]);
64
+ useEffect(() => {
65
+ if (p.open && activeIndex >= 0) p.panelRef.current?.querySelector(`[data-index="${activeIndex}"]`)?.scrollIntoView?.({ block: "nearest" });
66
+ }, [activeIndex, p.open, p.panelRef]);
67
+ if (list.length === 0 && !header) return null;
68
+ const close = () => {
69
+ p.close();
70
+ p.triggerRef.current?.focus();
71
+ };
72
+ const choose = (item) => {
73
+ if (item.disabled) return;
74
+ if (item.checked === void 0) close();
75
+ item.onSelect?.();
76
+ };
77
+ const move = (step) => {
78
+ if (enabled.length === 0) return;
79
+ const at = enabled.indexOf(activeIndex);
80
+ const next = step === "first" ? enabled[0] : step === "last" ? enabled[enabled.length - 1] : at === -1 ? step === 1 ? enabled[0] : enabled[enabled.length - 1] : enabled[Math.min(enabled.length - 1, Math.max(0, at + step))];
81
+ setActiveIndex(next);
82
+ };
83
+ const keys = (e) => {
84
+ if (!p.open) {
85
+ if (["ArrowDown", "ArrowUp"].includes(e.key)) {
86
+ e.preventDefault();
87
+ p.setOpen(true);
88
+ }
89
+ return;
90
+ }
91
+ if (e.key === "Escape") {
92
+ e.preventDefault();
93
+ e.stopPropagation();
94
+ close();
95
+ return;
96
+ }
97
+ if (e.key === "Tab") {
98
+ p.close();
99
+ return;
100
+ }
101
+ if (isTyping(e.target) && e.target !== searchRef.current) return;
102
+ if (e.key === "ArrowDown") {
103
+ e.preventDefault();
104
+ move(1);
105
+ } else if (e.key === "ArrowUp") {
106
+ e.preventDefault();
107
+ move(-1);
108
+ } else if (e.key === "Home" && e.target !== searchRef.current) {
109
+ e.preventDefault();
110
+ move("first");
111
+ } else if (e.key === "End" && e.target !== searchRef.current) {
112
+ e.preventDefault();
113
+ move("last");
114
+ } else if (e.key === "Enter" || e.key === " " && e.target !== searchRef.current) {
115
+ const item = visible[activeIndex];
116
+ if (item) {
117
+ e.preventDefault();
118
+ choose(item);
119
+ }
120
+ }
121
+ };
122
+ const name = ariaLabel ?? (hasText ? void 0 : L.more);
123
+ return /* @__PURE__ */ jsxs("div", { className: `relative inline-flex ${className}`, onKeyDown: keys, children: [
124
+ /* @__PURE__ */ jsx(
125
+ Button,
126
+ {
127
+ ref: p.triggerRef,
128
+ variant: variant ?? (hasText ? "secondary" : "ghost"),
129
+ size,
130
+ active,
131
+ disabled,
132
+ icon: hasText ? icon : icon ?? /* @__PURE__ */ jsx(MoreIcon, { size: size === "sm" ? 14 : 16 }),
133
+ "aria-label": name,
134
+ "data-tip": hasText ? void 0 : name,
135
+ "aria-haspopup": "menu",
136
+ "aria-expanded": p.open,
137
+ "aria-controls": p.open ? menuId : void 0,
138
+ onClick: (e) => {
139
+ e.stopPropagation();
140
+ p.setOpen((o) => !o);
141
+ },
142
+ children: hasText ? /* @__PURE__ */ jsxs(Fragment, { children: [
143
+ label,
144
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12, className: `shrink-0 transition-transform ${p.open ? "rotate-180" : ""}` })
145
+ ] }) : void 0
146
+ }
147
+ ),
148
+ p.open && createPortal(
149
+ /* @__PURE__ */ jsxs("div", { ref: p.panelRef, style: p.style, className: `${PANEL_CLASS} ${panelClassName}`, onClick: (e) => e.stopPropagation(), children: [
150
+ header && /* @__PURE__ */ jsx("div", { className: "border-b border-slate-100 px-2 pt-1 pb-2 dark:border-slate-800", children: header }),
151
+ withSearch && /* @__PURE__ */ jsx("div", { className: "px-2 pt-1 pb-1", children: /* @__PURE__ */ jsx(
152
+ "input",
153
+ {
154
+ ref: searchRef,
155
+ type: "search",
156
+ value: query,
157
+ onChange: (e) => {
158
+ setQuery(e.target.value);
159
+ setActiveIndex(-1);
160
+ },
161
+ placeholder: L.search,
162
+ "aria-label": L.search,
163
+ className: "h-8 w-full rounded-lg border border-slate-300 bg-white px-2.5 text-sm outline-none focus:border-proef-blue dark:border-slate-600 dark:bg-slate-800 dark:text-slate-100"
164
+ }
165
+ ) }),
166
+ /* @__PURE__ */ jsxs("div", { id: menuId, role: "menu", "aria-label": typeof label === "string" ? label : name, children: [
167
+ visible.length === 0 && /* @__PURE__ */ jsx("p", { className: "m-0 px-3 py-2 text-slate-400", children: list.length === 0 ? L.empty : L.noResults }),
168
+ visible.map((item, i) => {
169
+ const checkable = item.checked !== void 0;
170
+ const mark = checkable ? item.checked : item.selected;
171
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
172
+ item.separator && i > 0 && /* @__PURE__ */ jsx("div", { role: "separator", className: "my-1 border-t border-slate-100 dark:border-slate-800" }),
173
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center", "data-index": i, children: [
174
+ /* @__PURE__ */ jsxs(
175
+ "button",
176
+ {
177
+ type: "button",
178
+ role: checkable ? "menuitemcheckbox" : item.selected !== void 0 ? "menuitemradio" : "menuitem",
179
+ "aria-checked": checkable ? item.checked : item.selected !== void 0 ? item.selected : void 0,
180
+ disabled: item.disabled,
181
+ tabIndex: -1,
182
+ onMouseEnter: () => !item.disabled && setActiveIndex(i),
183
+ onClick: () => choose(item),
184
+ className: `min-w-0 flex-1 appearance-none border-0 ${itemClass(i === activeIndex, item.danger)} disabled:cursor-not-allowed disabled:opacity-40`,
185
+ children: [
186
+ item.icon && /* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-center", children: item.icon }),
187
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
188
+ /* @__PURE__ */ jsx("span", { className: `block truncate ${mark ? "font-semibold" : ""}`, children: item.label }),
189
+ item.description && /* @__PURE__ */ jsx("span", { className: "block truncate text-[11px] text-slate-500 dark:text-slate-400", children: item.description })
190
+ ] }),
191
+ (checkable || item.selected !== void 0) && /* @__PURE__ */ jsx("span", { className: "w-4 shrink-0", children: mark && /* @__PURE__ */ jsx(CheckIcon, { size: 16, strokeWidth: 2.5, className: "text-proef-blue dark:text-sky-300" }) })
192
+ ]
193
+ }
194
+ ),
195
+ item.action && /* @__PURE__ */ jsx(
196
+ Button,
197
+ {
198
+ variant: "ghost",
199
+ size: "sm",
200
+ icon: item.action.icon,
201
+ "aria-label": item.action.label,
202
+ "data-tip": item.action.label,
203
+ tabIndex: -1,
204
+ onClick: item.action.onSelect,
205
+ className: "mr-1 shrink-0"
206
+ }
207
+ )
208
+ ] })
209
+ ] }, i);
210
+ })
211
+ ] })
212
+ ] }),
213
+ dialogContainer ?? document.body
214
+ )
215
+ ] });
216
+ }
217
+ export {
218
+ DEFAULT_DROPDOWN_MENU_LABELS,
219
+ DropdownMenu,
220
+ DropdownMenu as default
221
+ };
222
+ //# sourceMappingURL=DropdownMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DropdownMenu.js","sources":["../../../../../../src/v1/components/overlays/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["import React, { useEffect, useId, useMemo, useRef, useState } from 'react'\r\nimport { createPortal } from 'react-dom'\r\nimport Button, { type ButtonProps } from '../../../primitives/buttons/Button/Button'\r\nimport { CheckIcon, ChevronDownIcon, MoreIcon } from '../../../foundations/icons/icons'\r\nimport { PANEL_CLASS, itemClass, useFloatingPanel } from '../../../capabilities/overlay/useFloatingPanel'\r\nimport { useDialogContainer } from '../Dialog/Dialog'\r\n\r\nexport interface DropdownMenuItemAction {\r\n /** Ícone do botão pequeno (ex: um caixote do lixo). */\r\n icon: React.ReactNode\r\n /** Nome do botão, para o tooltip e leitores de ecrã (ex: \"Apagar vista\"). */\r\n label: string\r\n onSelect: () => void\r\n}\r\n\r\nexport interface DropdownMenuItem {\r\n /** Normalmente texto; aceita JSX. */\r\n label: React.ReactNode\r\n /** Linha pequena por baixo do texto. */\r\n description?: React.ReactNode\r\n /** Ícone à esquerda (ex: um ícone do lucide com `size={14}`). */\r\n icon?: React.ReactNode\r\n /** O que o item faz. Um item normal fecha o menu ao ser escolhido. */\r\n onSelect?: () => void\r\n /**\r\n * Item de marcar (✓ quando `true`). O menu fica aberto para se marcarem\r\n * vários (ex: filtrar por tipos). `false` = por marcar, `undefined` = não é de marcar.\r\n */\r\n checked?: boolean\r\n /** A opção atual numa escolha de uma só (ex: a vista aplicada): ✓, e escolher fecha o menu como uma ação. */\r\n selected?: boolean\r\n /** Apaga ou não se pode desfazer: a vermelho. */\r\n danger?: boolean\r\n disabled?: boolean\r\n /** Linha a separar este item do anterior. */\r\n separator?: boolean\r\n /** Texto para a pesquisa quando o `label` não é texto. */\r\n searchText?: string\r\n /** Botão pequeno à direita do item (ex: apagar uma vista guardada). Não fecha o menu. */\r\n action?: DropdownMenuItemAction\r\n}\r\n\r\nexport interface DropdownMenuLabels {\r\n /** Nome do botão sem texto (⋯). */\r\n more: string\r\n /** Texto da caixa de pesquisa. */\r\n search: string\r\n /** Pesquisa sem resultados. */\r\n noResults: string\r\n /** DropdownMenu sem itens (só aparece com `header`; sem `header` o menu nem se mostra). */\r\n empty: string\r\n}\r\n\r\nexport const DEFAULT_DROPDOWN_MENU_LABELS: DropdownMenuLabels = {\r\n more: 'More actions',\r\n search: 'Search…',\r\n noResults: 'No results',\r\n empty: 'Nothing here yet',\r\n}\r\n\r\nexport interface DropdownMenuProps {\r\n /** Os itens; `false`, `null` e `undefined` são ignorados (para `cond && {...}`). */\r\n items: (DropdownMenuItem | false | null | undefined)[]\r\n /** Texto do botão (com uma seta). Sem texto, o botão é o ⋯ (ações de uma linha ou de um cartão). */\r\n label?: React.ReactNode\r\n /** Ícone antes do texto do botão. Sem `label`, substitui o ⋯. */\r\n icon?: React.ReactNode\r\n /** Nome do botão para leitores de ecrã e tooltip. Sem `label`, por omissão `labels.more`. */\r\n 'aria-label'?: string\r\n /** Aspeto do botão, como no Button. Por omissão `secondary` (com texto) ou `ghost` (⋯). */\r\n variant?: ButtonProps['variant']\r\n size?: ButtonProps['size']\r\n /** Botão ligado (ex: há uma vista ou filtro aplicado). */\r\n active?: boolean\r\n /** Para que lado abre a lista, a partir do botão. Por omissão `left` (com texto) ou `right` (⋯). */\r\n align?: 'left' | 'right'\r\n disabled?: boolean\r\n /** Conteúdo no topo da lista, antes dos itens (ex: campo \"Guardar vista atual\", filtros). */\r\n header?: React.ReactNode\r\n /** Caixa de pesquisa no topo da lista. Por omissão, só com mais de 10 itens. */\r\n searchable?: boolean\r\n labels?: Partial<DropdownMenuLabels>\r\n /** Classes da lista (ex: a largura, `w-64`). */\r\n panelClassName?: string\r\n /** Classes da caixa à volta do botão. */\r\n className?: string\r\n /** Avisa quando a lista abre ou fecha (ex: para limpar um campo do `header`). */\r\n onOpenChange?: (open: boolean) => void\r\n}\r\n\r\nconst textOf = (item: DropdownMenuItem) => item.searchText ?? (typeof item.label === 'string' || typeof item.label === 'number' ? String(item.label) : '')\r\n\r\nconst isTyping = (el: EventTarget | null) =>\r\n el instanceof HTMLElement && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.isContentEditable)\r\n\r\n/**\r\n * Botão que abre uma lista de ações ou opções: o ⋯ de uma linha, \"Ações em massa\", \"Vistas guardadas\",\r\n * um filtro de escolha múltipla. A mesma lista do [SelectInput](?path=/docs/v1-primitives-forms-selectinput--docs).\r\n *\r\n * - **Ações**: escolher executa e fecha.\r\n * - **Marcar** (`checked`): o item leva ✓ e a lista fica aberta para marcar vários.\r\n * - **Escolher um** (`selected`): ✓ na opção atual; escolher fecha.\r\n * - **Ação no item** (`action`): um botão pequeno à direita (ex: apagar uma vista).\r\n * - **Topo livre** (`header`): ex: um campo para guardar a vista atual.\r\n *\r\n * Teclado: ↑/↓, Home/End, Enter escolhe, Esc fecha. Abre por cima de um\r\n * [Dialog](?path=/docs/v1-components-overlays-dialog--docs) e os cliques não chegam a uma linha clicável por baixo.\r\n *\r\n * Substitui o `MenuAcoes` legacy.\r\n */\r\nexport default function DropdownMenu({\r\n items,\r\n label,\r\n icon,\r\n 'aria-label': ariaLabel,\r\n variant,\r\n size = 'md',\r\n active,\r\n align,\r\n disabled = false,\r\n header,\r\n searchable,\r\n labels,\r\n panelClassName = '',\r\n className = '',\r\n onOpenChange,\r\n}: DropdownMenuProps) {\r\n const L = { ...DEFAULT_DROPDOWN_MENU_LABELS, ...labels }\r\n const hasText = label !== undefined && label !== null && label !== false\r\n const p = useFloatingPanel(align ?? (hasText ? 'left' : 'right'))\r\n // Dentro de um Dialog a lista abre na janela (como no SelectInput): no body ficava por baixo dela.\r\n const dialogContainer = useDialogContainer()\r\n const menuId = useId()\r\n const searchRef = useRef<HTMLInputElement>(null)\r\n\r\n const list = useMemo(() => items.filter((i): i is DropdownMenuItem => !!i), [items])\r\n const withSearch = searchable ?? list.length > 10\r\n const [query, setQuery] = useState('')\r\n const visible = useMemo(() => {\r\n const q = query.trim().toLowerCase()\r\n return q ? list.filter((i) => textOf(i).toLowerCase().includes(q)) : list\r\n }, [list, query])\r\n const enabled = visible.map((i, n) => (i.disabled ? -1 : n)).filter((n) => n >= 0)\r\n const [activeIndex, setActiveIndex] = useState(-1)\r\n\r\n const changed = useRef(onOpenChange)\r\n changed.current = onOpenChange\r\n const first = useRef(true)\r\n useEffect(() => {\r\n if (first.current) {\r\n first.current = false\r\n return\r\n }\r\n changed.current?.(p.open)\r\n }, [p.open])\r\n\r\n // Ao abrir: limpa a pesquisa e põe o teclado no primeiro item.\r\n useEffect(() => {\r\n if (!p.open) return\r\n setQuery('')\r\n setActiveIndex(-1)\r\n if (withSearch) setTimeout(() => searchRef.current?.focus(), 0)\r\n }, [p.open]) // eslint-disable-line react-hooks/exhaustive-deps\r\n\r\n useEffect(() => {\r\n if (p.open && activeIndex >= 0) p.panelRef.current?.querySelector<HTMLElement>(`[data-index=\"${activeIndex}\"]`)?.scrollIntoView?.({ block: 'nearest' })\r\n }, [activeIndex, p.open, p.panelRef])\r\n\r\n if (list.length === 0 && !header) return null\r\n\r\n const close = () => {\r\n p.close()\r\n p.triggerRef.current?.focus()\r\n }\r\n\r\n const choose = (item: DropdownMenuItem) => {\r\n if (item.disabled) return\r\n // De marcar: fica aberto para se marcarem vários.\r\n if (item.checked === undefined) close()\r\n item.onSelect?.()\r\n }\r\n\r\n const move = (step: 1 | -1 | 'first' | 'last') => {\r\n if (enabled.length === 0) return\r\n const at = enabled.indexOf(activeIndex)\r\n const next =\r\n step === 'first' ? enabled[0]\r\n : step === 'last' ? enabled[enabled.length - 1]\r\n : at === -1 ? (step === 1 ? enabled[0] : enabled[enabled.length - 1])\r\n : enabled[Math.min(enabled.length - 1, Math.max(0, at + step))]\r\n setActiveIndex(next)\r\n }\r\n\r\n // Um só sítio para o teclado: os eventos da lista (portal) também sobem até aqui.\r\n const keys = (e: React.KeyboardEvent) => {\r\n if (!p.open) {\r\n if (['ArrowDown', 'ArrowUp'].includes(e.key)) {\r\n e.preventDefault()\r\n p.setOpen(true)\r\n }\r\n return\r\n }\r\n if (e.key === 'Escape') {\r\n e.preventDefault()\r\n e.stopPropagation()\r\n close()\r\n return\r\n }\r\n if (e.key === 'Tab') {\r\n p.close()\r\n return\r\n }\r\n // A escrever num campo do topo: as teclas são do campo (a pesquisa deixa passar as setas e o Enter).\r\n if (isTyping(e.target) && e.target !== searchRef.current) return\r\n if (e.key === 'ArrowDown') {\r\n e.preventDefault()\r\n move(1)\r\n } else if (e.key === 'ArrowUp') {\r\n e.preventDefault()\r\n move(-1)\r\n } else if (e.key === 'Home' && e.target !== searchRef.current) {\r\n e.preventDefault()\r\n move('first')\r\n } else if (e.key === 'End' && e.target !== searchRef.current) {\r\n e.preventDefault()\r\n move('last')\r\n } else if (e.key === 'Enter' || (e.key === ' ' && e.target !== searchRef.current)) {\r\n const item = visible[activeIndex]\r\n if (item) {\r\n e.preventDefault()\r\n choose(item)\r\n }\r\n }\r\n }\r\n\r\n const name = ariaLabel ?? (hasText ? undefined : L.more)\r\n\r\n return (\r\n <div className={`relative inline-flex ${className}`} onKeyDown={keys}>\r\n <Button\r\n ref={p.triggerRef}\r\n variant={variant ?? (hasText ? 'secondary' : 'ghost')}\r\n size={size}\r\n active={active}\r\n disabled={disabled}\r\n icon={hasText ? icon : (icon ?? <MoreIcon size={size === 'sm' ? 14 : 16} />)}\r\n aria-label={name}\r\n data-tip={hasText ? undefined : name}\r\n aria-haspopup=\"menu\"\r\n aria-expanded={p.open}\r\n aria-controls={p.open ? menuId : undefined}\r\n onClick={(e) => {\r\n // Dentro de uma linha clicável (tabelas, cartões), abrir o menu não abre a linha.\r\n e.stopPropagation()\r\n p.setOpen((o) => !o)\r\n }}\r\n >\r\n {hasText ? (\r\n <>\r\n {label}\r\n <ChevronDownIcon size={12} className={`shrink-0 transition-transform ${p.open ? 'rotate-180' : ''}`} />\r\n </>\r\n ) : undefined}\r\n </Button>\r\n {p.open &&\r\n createPortal(\r\n <div ref={p.panelRef} style={p.style} className={`${PANEL_CLASS} ${panelClassName}`} onClick={(e) => e.stopPropagation()}>\r\n {header && <div className=\"border-b border-slate-100 px-2 pt-1 pb-2 dark:border-slate-800\">{header}</div>}\r\n {withSearch && (\r\n <div className=\"px-2 pt-1 pb-1\">\r\n <input\r\n ref={searchRef}\r\n type=\"search\"\r\n value={query}\r\n onChange={(e) => {\r\n setQuery(e.target.value)\r\n setActiveIndex(-1)\r\n }}\r\n placeholder={L.search}\r\n aria-label={L.search}\r\n className=\"h-8 w-full rounded-lg border border-slate-300 bg-white px-2.5 text-sm outline-none focus:border-proef-blue dark:border-slate-600 dark:bg-slate-800 dark:text-slate-100\"\r\n />\r\n </div>\r\n )}\r\n <div id={menuId} role=\"menu\" aria-label={typeof label === 'string' ? label : name}>\r\n {visible.length === 0 && (\r\n <p className=\"m-0 px-3 py-2 text-slate-400\">{list.length === 0 ? L.empty : L.noResults}</p>\r\n )}\r\n {visible.map((item, i) => {\r\n const checkable = item.checked !== undefined\r\n const mark = checkable ? item.checked : item.selected\r\n return (\r\n <React.Fragment key={i}>\r\n {item.separator && i > 0 && <div role=\"separator\" className=\"my-1 border-t border-slate-100 dark:border-slate-800\" />}\r\n <div className=\"flex items-center\" data-index={i}>\r\n <button\r\n type=\"button\"\r\n role={checkable ? 'menuitemcheckbox' : item.selected !== undefined ? 'menuitemradio' : 'menuitem'}\r\n aria-checked={checkable ? item.checked : item.selected !== undefined ? item.selected : undefined}\r\n disabled={item.disabled}\r\n tabIndex={-1}\r\n onMouseEnter={() => !item.disabled && setActiveIndex(i)}\r\n onClick={() => choose(item)}\r\n className={`min-w-0 flex-1 appearance-none border-0 ${itemClass(i === activeIndex, item.danger)} disabled:cursor-not-allowed disabled:opacity-40`}\r\n >\r\n {item.icon && <span className=\"flex shrink-0 items-center\">{item.icon}</span>}\r\n <span className=\"min-w-0 flex-1\">\r\n <span className={`block truncate ${mark ? 'font-semibold' : ''}`}>{item.label}</span>\r\n {item.description && <span className=\"block truncate text-[11px] text-slate-500 dark:text-slate-400\">{item.description}</span>}\r\n </span>\r\n {(checkable || item.selected !== undefined) && (\r\n <span className=\"w-4 shrink-0\">\r\n {mark && <CheckIcon size={16} strokeWidth={2.5} className=\"text-proef-blue dark:text-sky-300\" />}\r\n </span>\r\n )}\r\n </button>\r\n {item.action && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n icon={item.action.icon}\r\n aria-label={item.action.label}\r\n data-tip={item.action.label}\r\n tabIndex={-1}\r\n onClick={item.action.onSelect}\r\n className=\"mr-1 shrink-0\"\r\n />\r\n )}\r\n </div>\r\n </React.Fragment>\r\n )\r\n })}\r\n </div>\r\n </div>,\r\n dialogContainer ?? document.body,\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\nexport { DropdownMenu }\r\n"],"names":[],"mappings":"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"}
@@ -185,6 +185,13 @@ function SlidersIcon(props) {
185
185
  /* @__PURE__ */ jsx("circle", { cx: "8", cy: "17", r: "2" })
186
186
  ] });
187
187
  }
188
+ function MoreIcon(props) {
189
+ return /* @__PURE__ */ jsxs(Svg, { ...props, fill: "currentColor", children: [
190
+ /* @__PURE__ */ jsx("circle", { cx: "5", cy: "12", r: "1.8" }),
191
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1.8" }),
192
+ /* @__PURE__ */ jsx("circle", { cx: "19", cy: "12", r: "1.8" })
193
+ ] });
194
+ }
188
195
  export {
189
196
  BoldIcon,
190
197
  CheckIcon,
@@ -212,6 +219,7 @@ export {
212
219
  MinimizeIcon,
213
220
  MonitorIcon,
214
221
  MoonIcon,
222
+ MoreIcon,
215
223
  PanelOpenIcon,
216
224
  PrefilledIcon,
217
225
  QrCodeIcon,
@@ -1 +1 @@
1
- {"version":3,"file":"icons.js","sources":["../../../../../src/v1/foundations/icons/icons.tsx"],"sourcesContent":["import React from 'react'\r\n\r\n/**\r\n * Conjunto de ícones do V1: traço de 1,7 a 1,9 em grelha de 24, cor do texto\r\n * (`currentColor`), sem preenchimento. Decorativos por omissão (`aria-hidden`):\r\n * quem os usa dá o nome acessível ao botão ou etiqueta à volta.\r\n */\r\nexport interface IconProps {\r\n /** Lado em px. */\r\n size?: number\r\n className?: string\r\n /** Espessura do traço. Por omissão 1,8; mais grosso em ícones muito pequenos (ex: o visto de uma caixa). */\r\n strokeWidth?: number\r\n}\r\n\r\nfunction Svg({ size = 16, className, strokeWidth = 1.8, children, fill = 'none' }: IconProps & { children: React.ReactNode; fill?: string }) {\r\n return (\r\n <svg\r\n width={size}\r\n height={size}\r\n viewBox=\"0 0 24 24\"\r\n fill={fill}\r\n stroke={fill === 'none' ? 'currentColor' : 'none'}\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n aria-hidden\r\n >\r\n {children}\r\n </svg>\r\n )\r\n}\r\n\r\n/** Lido de um QR code. */\r\nexport function QrCodeIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"3.5\" y=\"3.5\" width=\"6.5\" height=\"6.5\" rx=\"1.3\" />\r\n <rect x=\"14\" y=\"3.5\" width=\"6.5\" height=\"6.5\" rx=\"1.3\" />\r\n <rect x=\"3.5\" y=\"14\" width=\"6.5\" height=\"6.5\" rx=\"1.3\" />\r\n <path d=\"M14 14h3.3v3.3M20.5 14v.01M14 20.5h.01M17.3 20.5h3.2v-3.2\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Identificado automaticamente (IA). */\r\nexport function SparklesIcon(props: IconProps) {\r\n return (\r\n <Svg {...props} fill=\"currentColor\">\r\n <path d=\"M12 2.5l1.7 4.6 4.6 1.7-4.6 1.7L12 15.1l-1.7-4.6L5.7 8.8l4.6-1.7z\" />\r\n <path d=\"M18.5 13.5l.85 2.35 2.35.85-2.35.85-.85 2.35-.85-2.35-2.35-.85 2.35-.85z\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Pré-preenchido a partir de outro registo (ex: linha de um extrato). */\r\nexport function PrefilledIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"4\" y=\"3.5\" width=\"16\" height=\"17\" rx=\"2\" />\r\n <path d=\"M7.5 8.5h9M7.5 12h9M7.5 15.5h5.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Bloqueado: o valor não se pode alterar. */\r\nexport function LockIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"5\" y=\"10.5\" width=\"14\" height=\"10\" rx=\"2\" />\r\n <path d=\"M8.5 10.5V7.5a3.5 3.5 0 0 1 7 0v3\" />\r\n <circle cx=\"12\" cy=\"15.5\" r=\"1.1\" fill=\"currentColor\" stroke=\"none\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Mais informação. */\r\nexport function InfoIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <circle cx=\"12\" cy=\"12\" r=\"9.5\" />\r\n <path d=\"M12 11v5.5\" />\r\n <circle cx=\"12\" cy=\"7.8\" r=\"1.1\" fill=\"currentColor\" stroke=\"none\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function SearchIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <circle cx=\"10.5\" cy=\"10.5\" r=\"6.5\" />\r\n <path d=\"M15.5 15.5L20 20\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function CheckIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M4.5 12.5l5 5 10-11\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function ChevronDownIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M6 9.5l6 6 6-6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function ChevronUpIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M6 14.5l6-6 6 6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function ChevronLeftIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M14.5 6l-6 6 6 6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function ChevronRightIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M9.5 6l6 6-6 6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Ordenável: ainda sem ordem escolhida. */\r\nexport function ChevronsUpDownIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M7.5 9.5L12 5l4.5 4.5M7.5 14.5L12 19l4.5-4.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Filtro (funil). */\r\nexport function FilterIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M4 5h16l-6.2 7.6v5.6l-3.6 1.8v-7.4z\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Fechar, remover (×). */\r\nexport function CloseIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M6.5 6.5l11 11M17.5 6.5l-11 11\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Abrir o menu (gaveta em ecrãs pequenos). */\r\nexport function MenuIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M4 7h16M4 12h16M4 17h16\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Agrupar (camadas). */\r\nexport function LayersIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M12 3.5l8.5 4.5-8.5 4.5L3.5 8z\" />\r\n <path d=\"M3.5 12l8.5 4.5 8.5-4.5M3.5 16l8.5 4.5 8.5-4.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Expandir o menu lateral recolhido. */\r\nexport function PanelOpenIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"3.5\" y=\"4\" width=\"17\" height=\"16\" rx=\"2\" />\r\n <path d=\"M9 4v16M13 10l2 2-2 2\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Lista de valores. */\r\nexport function ListIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M9 6.5h11M9 12h11M9 17.5h11M4.5 6.5h.01M4.5 12h.01M4.5 17.5h.01\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Texto: negrito. */\r\nexport function BoldIcon(props: IconProps) {\r\n return (\r\n <Svg strokeWidth={2.2} {...props}>\r\n <path d=\"M7 5h6a3.5 3.5 0 0 1 0 7H7zM7 12h7a3.5 3.5 0 0 1 0 7H7z\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Texto: itálico. */\r\nexport function ItalicIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M10 5h8M6 19h8M14.5 5l-5 14\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Texto: sublinhado. */\r\nexport function UnderlineIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M7 4.5v6a5 5 0 0 0 10 0v-6M5.5 20h13\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Texto: riscado. */\r\nexport function StrikethroughIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M4.5 12h15M16.5 6.5A4.5 3.5 0 0 0 12 5c-2.5 0-4.5 1.3-4.5 3.2 0 1.4 1 2.4 2.7 2.9M8 17.3A5 3.6 0 0 0 12 19c2.6 0 4.6-1.4 4.6-3.3 0-.8-.3-1.5-.9-2\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Lista com marcas (no texto). */\r\nexport function ListBulletIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M9.5 6.5h10M9.5 12h10M9.5 17.5h10\" />\r\n <circle cx=\"5\" cy=\"6.5\" r=\"1\" fill=\"currentColor\" />\r\n <circle cx=\"5\" cy=\"12\" r=\"1\" fill=\"currentColor\" />\r\n <circle cx=\"5\" cy=\"17.5\" r=\"1\" fill=\"currentColor\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Lista numerada (no texto). */\r\nexport function ListNumberedIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M10 6.5h10M10 12h10M10 17.5h10M4 5.5l1.3-.8v4M3.8 15.2c.3-.6.9-.9 1.5-.9.8 0 1.4.5 1.4 1.2 0 1-1.6 1.6-2.9 2.8h3\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Citação. */\r\nexport function QuoteIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M5 18V12.5C5 9 6.5 7 9.5 6M14 18v-5.5C14 9 15.5 7 18.5 6M5 12.5h4.5V18H5M14 12.5h4.5V18H14\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Imagem. */\r\nexport function ImageIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"3.5\" y=\"4.5\" width=\"17\" height=\"15\" rx=\"2\" />\r\n <circle cx=\"9\" cy=\"10\" r=\"1.6\" />\r\n <path d=\"M20.5 15.5l-4.5-4.5-8.5 8.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Abrir em ecrã quase inteiro. */\r\nexport function MaximizeIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M14 4.5h5.5V10M10 19.5H4.5V14M19.5 4.5L13.5 10.5M4.5 19.5l6-6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Voltar ao tamanho normal. */\r\nexport function MinimizeIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M19.5 10H14V4.5M4.5 14H10v5.5M14 10l6-6M4 20l6-6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Tema claro. */\r\nexport function SunIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\r\n <path d=\"M12 2.5v2M12 19.5v2M4.6 4.6L6 6M18 18l1.4 1.4M2.5 12h2M19.5 12h2M4.6 19.4L6 18M18 6l1.4-1.4\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Tema escuro. */\r\nexport function MoonIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Tema do sistema. */\r\nexport function MonitorIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"12.5\" rx=\"2\" />\r\n <path d=\"M8.5 20.5h7M12 16.5v4\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Idioma. */\r\nexport function GlobeIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\r\n <path d=\"M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Terminar sessão. */\r\nexport function LogOutIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M9.5 20.5H6a2 2 0 0 1-2-2v-13a2 2 0 0 1 2-2h3.5M15.5 16.5L20 12l-4.5-4.5M20 12H9.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Abre fora da aplicação (separador novo). */\r\nexport function ExternalLinkIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M14 4h6v6M20 4l-9 9M18 13.5V18a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Atenção (avisos, confirmações perigosas). */\r\nexport function WarningIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M10.3 4.3L2.8 17.5A2 2 0 0 0 4.5 20.5h15a2 2 0 0 0 1.7-3L13.7 4.3a2 2 0 0 0-3.4 0z\" />\r\n <path d=\"M12 9.5v4.5\" />\r\n <circle cx=\"12\" cy=\"17\" r=\"1.1\" fill=\"currentColor\" stroke=\"none\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Erro. */\r\nexport function ErrorIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <circle cx=\"12\" cy=\"12\" r=\"9.5\" />\r\n <path d=\"M9 9l6 6M15 9l-6 6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Intervalo (mínimo e máximo). */\r\nexport function SlidersIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M4 7h10M18 7h2M4 17h2M10 17h10\" />\r\n <circle cx=\"16\" cy=\"7\" r=\"2\" />\r\n <circle cx=\"8\" cy=\"17\" r=\"2\" />\r\n </Svg>\r\n )\r\n}\r\n"],"names":[],"mappings":";AAeA,SAAS,IAAI,EAAE,OAAO,IAAI,WAAW,cAAc,KAAK,UAAU,OAAO,UAAoE;AAC3I,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAQ;AAAA,MACR;AAAA,MACA,QAAQ,SAAS,SAAS,iBAAiB;AAAA,MAC3C;AAAA,MACA,eAAc;AAAA,MACd,gBAAe;AAAA,MACf;AAAA,MACA,eAAW;AAAA,MAEV;AAAA,IAAA;AAAA,EAAA;AAGP;AAGO,SAAS,WAAW,OAAkB;AAC3C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,OAAM,GAAE,OAAM,OAAM,OAAM,QAAO,OAAM,IAAG,MAAA,CAAM;AAAA,IACxD,oBAAC,QAAA,EAAK,GAAE,MAAK,GAAE,OAAM,OAAM,OAAM,QAAO,OAAM,IAAG,MAAA,CAAM;AAAA,IACvD,oBAAC,QAAA,EAAK,GAAE,OAAM,GAAE,MAAK,OAAM,OAAM,QAAO,OAAM,IAAG,MAAA,CAAM;AAAA,IACvD,oBAAC,QAAA,EAAK,GAAE,4DAAA,CAA4D;AAAA,EAAA,GACtE;AAEJ;AAGO,SAAS,aAAa,OAAkB;AAC7C,SACE,qBAAC,KAAA,EAAK,GAAG,OAAO,MAAK,gBACnB,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,oEAAA,CAAoE;AAAA,IAC5E,oBAAC,QAAA,EAAK,GAAE,2EAAA,CAA2E;AAAA,EAAA,GACrF;AAEJ;AAGO,SAAS,cAAc,OAAkB;AAC9C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,OAAM,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,IAClD,oBAAC,QAAA,EAAK,GAAE,mCAAA,CAAmC;AAAA,EAAA,GAC7C;AAEJ;AAGO,SAAS,SAAS,OAAkB;AACzC,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,QAAO,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,IACnD,oBAAC,QAAA,EAAK,GAAE,oCAAA,CAAoC;AAAA,IAC5C,oBAAC,UAAA,EAAO,IAAG,MAAK,IAAG,QAAO,GAAE,OAAM,MAAK,gBAAe,QAAO,OAAA,CAAO;AAAA,EAAA,GACtE;AAEJ;AAGO,SAAS,SAAS,OAAkB;AACzC,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,OAAM;AAAA,IAChC,oBAAC,QAAA,EAAK,GAAE,aAAA,CAAa;AAAA,IACrB,oBAAC,UAAA,EAAO,IAAG,MAAK,IAAG,OAAM,GAAE,OAAM,MAAK,gBAAe,QAAO,OAAA,CAAO;AAAA,EAAA,GACrE;AAEJ;AAEO,SAAS,WAAW,OAAkB;AAC3C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,YAAO,IAAG,QAAO,IAAG,QAAO,GAAE,OAAM;AAAA,IACpC,oBAAC,QAAA,EAAK,GAAE,mBAAA,CAAmB;AAAA,EAAA,GAC7B;AAEJ;AAEO,SAAS,UAAU,OAAkB;AAC1C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,uBAAsB,EAAA,CAChC;AAEJ;AAEO,SAAS,gBAAgB,OAAkB;AAChD,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,kBAAiB,EAAA,CAC3B;AAEJ;AAEO,SAAS,cAAc,OAAkB;AAC9C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,mBAAkB,EAAA,CAC5B;AAEJ;AAEO,SAAS,gBAAgB,OAAkB;AAChD,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,oBAAmB,EAAA,CAC7B;AAEJ;AAEO,SAAS,iBAAiB,OAAkB;AACjD,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,kBAAiB,EAAA,CAC3B;AAEJ;AAGO,SAAS,mBAAmB,OAAkB;AACnD,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,gDAA+C,EAAA,CACzD;AAEJ;AAGO,SAAS,WAAW,OAAkB;AAC3C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,uCAAsC,EAAA,CAChD;AAEJ;AAGO,SAAS,UAAU,OAAkB;AAC1C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,kCAAiC,EAAA,CAC3C;AAEJ;AAGO,SAAS,SAAS,OAAkB;AACzC,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,2BAA0B,EAAA,CACpC;AAEJ;AAGO,SAAS,WAAW,OAAkB;AAC3C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,iCAAA,CAAiC;AAAA,IACzC,oBAAC,QAAA,EAAK,GAAE,iDAAA,CAAiD;AAAA,EAAA,GAC3D;AAEJ;AAGO,SAAS,cAAc,OAAkB;AAC9C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,OAAM,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,IAClD,oBAAC,QAAA,EAAK,GAAE,wBAAA,CAAwB;AAAA,EAAA,GAClC;AAEJ;AAGO,SAAS,SAAS,OAAkB;AACzC,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,mEAAkE,EAAA,CAC5E;AAEJ;AAGO,SAAS,SAAS,OAAkB;AACzC,SACE,oBAAC,KAAA,EAAI,aAAa,KAAM,GAAG,OACzB,UAAA,oBAAC,QAAA,EAAK,GAAE,0DAAA,CAA0D,EAAA,CACpE;AAEJ;AAGO,SAAS,WAAW,OAAkB;AAC3C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,+BAA8B,EAAA,CACxC;AAEJ;AAGO,SAAS,cAAc,OAAkB;AAC9C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,wCAAuC,EAAA,CACjD;AAEJ;AAGO,SAAS,kBAAkB,OAAkB;AAClD,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,qJAAoJ,EAAA,CAC9J;AAEJ;AAGO,SAAS,eAAe,OAAkB;AAC/C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,oCAAA,CAAoC;AAAA,IAC5C,oBAAC,YAAO,IAAG,KAAI,IAAG,OAAM,GAAE,KAAI,MAAK,eAAA,CAAe;AAAA,IAClD,oBAAC,YAAO,IAAG,KAAI,IAAG,MAAK,GAAE,KAAI,MAAK,eAAA,CAAe;AAAA,IACjD,oBAAC,YAAO,IAAG,KAAI,IAAG,QAAO,GAAE,KAAI,MAAK,eAAA,CAAe;AAAA,EAAA,GACrD;AAEJ;AAGO,SAAS,iBAAiB,OAAkB;AACjD,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,oHAAmH,EAAA,CAC7H;AAEJ;AAGO,SAAS,UAAU,OAAkB;AAC1C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,8FAA6F,EAAA,CACvG;AAEJ;AAGO,SAAS,UAAU,OAAkB;AAC1C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,OAAM,GAAE,OAAM,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,wBACnD,UAAA,EAAO,IAAG,KAAI,IAAG,MAAK,GAAE,OAAM;AAAA,IAC/B,oBAAC,QAAA,EAAK,GAAE,8BAAA,CAA8B;AAAA,EAAA,GACxC;AAEJ;AAGO,SAAS,aAAa,OAAkB;AAC7C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,iEAAgE,EAAA,CAC1E;AAEJ;AAGO,SAAS,aAAa,OAAkB;AAC7C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,oDAAmD,EAAA,CAC7D;AAEJ;AAGO,SAAS,QAAQ,OAAkB;AACxC,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI;AAAA,IAC9B,oBAAC,QAAA,EAAK,GAAE,8FAAA,CAA8F;AAAA,EAAA,GACxG;AAEJ;AAGO,SAAS,SAAS,OAAkB;AACzC,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,iDAAgD,EAAA,CAC1D;AAEJ;AAGO,SAAS,YAAY,OAAkB;AAC5C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,QAAO,IAAG,IAAA,CAAI;AAAA,IAClD,oBAAC,QAAA,EAAK,GAAE,wBAAA,CAAwB;AAAA,EAAA,GAClC;AAEJ;AAGO,SAAS,UAAU,OAAkB;AAC1C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI;AAAA,IAC9B,oBAAC,QAAA,EAAK,GAAE,uDAAA,CAAuD;AAAA,EAAA,GACjE;AAEJ;AAGO,SAAS,WAAW,OAAkB;AAC3C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,sFAAqF,EAAA,CAC/F;AAEJ;AAGO,SAAS,iBAAiB,OAAkB;AACjD,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,oFAAmF,EAAA,CAC7F;AAEJ;AAGO,SAAS,YAAY,OAAkB;AAC5C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,qFAAA,CAAqF;AAAA,IAC7F,oBAAC,QAAA,EAAK,GAAE,cAAA,CAAc;AAAA,IACtB,oBAAC,UAAA,EAAO,IAAG,MAAK,IAAG,MAAK,GAAE,OAAM,MAAK,gBAAe,QAAO,OAAA,CAAO;AAAA,EAAA,GACpE;AAEJ;AAGO,SAAS,UAAU,OAAkB;AAC1C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,OAAM;AAAA,IAChC,oBAAC,QAAA,EAAK,GAAE,qBAAA,CAAqB;AAAA,EAAA,GAC/B;AAEJ;AAGO,SAAS,YAAY,OAAkB;AAC5C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,iCAAA,CAAiC;AAAA,wBACxC,UAAA,EAAO,IAAG,MAAK,IAAG,KAAI,GAAE,KAAI;AAAA,wBAC5B,UAAA,EAAO,IAAG,KAAI,IAAG,MAAK,GAAE,IAAA,CAAI;AAAA,EAAA,GAC/B;AAEJ;"}
1
+ {"version":3,"file":"icons.js","sources":["../../../../../src/v1/foundations/icons/icons.tsx"],"sourcesContent":["import React from 'react'\r\n\r\n/**\r\n * Conjunto de ícones do V1: traço de 1,7 a 1,9 em grelha de 24, cor do texto\r\n * (`currentColor`), sem preenchimento. Decorativos por omissão (`aria-hidden`):\r\n * quem os usa dá o nome acessível ao botão ou etiqueta à volta.\r\n */\r\nexport interface IconProps {\r\n /** Lado em px. */\r\n size?: number\r\n className?: string\r\n /** Espessura do traço. Por omissão 1,8; mais grosso em ícones muito pequenos (ex: o visto de uma caixa). */\r\n strokeWidth?: number\r\n}\r\n\r\nfunction Svg({ size = 16, className, strokeWidth = 1.8, children, fill = 'none' }: IconProps & { children: React.ReactNode; fill?: string }) {\r\n return (\r\n <svg\r\n width={size}\r\n height={size}\r\n viewBox=\"0 0 24 24\"\r\n fill={fill}\r\n stroke={fill === 'none' ? 'currentColor' : 'none'}\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n aria-hidden\r\n >\r\n {children}\r\n </svg>\r\n )\r\n}\r\n\r\n/** Lido de um QR code. */\r\nexport function QrCodeIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"3.5\" y=\"3.5\" width=\"6.5\" height=\"6.5\" rx=\"1.3\" />\r\n <rect x=\"14\" y=\"3.5\" width=\"6.5\" height=\"6.5\" rx=\"1.3\" />\r\n <rect x=\"3.5\" y=\"14\" width=\"6.5\" height=\"6.5\" rx=\"1.3\" />\r\n <path d=\"M14 14h3.3v3.3M20.5 14v.01M14 20.5h.01M17.3 20.5h3.2v-3.2\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Identificado automaticamente (IA). */\r\nexport function SparklesIcon(props: IconProps) {\r\n return (\r\n <Svg {...props} fill=\"currentColor\">\r\n <path d=\"M12 2.5l1.7 4.6 4.6 1.7-4.6 1.7L12 15.1l-1.7-4.6L5.7 8.8l4.6-1.7z\" />\r\n <path d=\"M18.5 13.5l.85 2.35 2.35.85-2.35.85-.85 2.35-.85-2.35-2.35-.85 2.35-.85z\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Pré-preenchido a partir de outro registo (ex: linha de um extrato). */\r\nexport function PrefilledIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"4\" y=\"3.5\" width=\"16\" height=\"17\" rx=\"2\" />\r\n <path d=\"M7.5 8.5h9M7.5 12h9M7.5 15.5h5.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Bloqueado: o valor não se pode alterar. */\r\nexport function LockIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"5\" y=\"10.5\" width=\"14\" height=\"10\" rx=\"2\" />\r\n <path d=\"M8.5 10.5V7.5a3.5 3.5 0 0 1 7 0v3\" />\r\n <circle cx=\"12\" cy=\"15.5\" r=\"1.1\" fill=\"currentColor\" stroke=\"none\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Mais informação. */\r\nexport function InfoIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <circle cx=\"12\" cy=\"12\" r=\"9.5\" />\r\n <path d=\"M12 11v5.5\" />\r\n <circle cx=\"12\" cy=\"7.8\" r=\"1.1\" fill=\"currentColor\" stroke=\"none\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function SearchIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <circle cx=\"10.5\" cy=\"10.5\" r=\"6.5\" />\r\n <path d=\"M15.5 15.5L20 20\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function CheckIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M4.5 12.5l5 5 10-11\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function ChevronDownIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M6 9.5l6 6 6-6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function ChevronUpIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M6 14.5l6-6 6 6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function ChevronLeftIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M14.5 6l-6 6 6 6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function ChevronRightIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M9.5 6l6 6-6 6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Ordenável: ainda sem ordem escolhida. */\r\nexport function ChevronsUpDownIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M7.5 9.5L12 5l4.5 4.5M7.5 14.5L12 19l4.5-4.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Filtro (funil). */\r\nexport function FilterIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M4 5h16l-6.2 7.6v5.6l-3.6 1.8v-7.4z\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Fechar, remover (×). */\r\nexport function CloseIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M6.5 6.5l11 11M17.5 6.5l-11 11\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Abrir o menu (gaveta em ecrãs pequenos). */\r\nexport function MenuIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M4 7h16M4 12h16M4 17h16\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Agrupar (camadas). */\r\nexport function LayersIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M12 3.5l8.5 4.5-8.5 4.5L3.5 8z\" />\r\n <path d=\"M3.5 12l8.5 4.5 8.5-4.5M3.5 16l8.5 4.5 8.5-4.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Expandir o menu lateral recolhido. */\r\nexport function PanelOpenIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"3.5\" y=\"4\" width=\"17\" height=\"16\" rx=\"2\" />\r\n <path d=\"M9 4v16M13 10l2 2-2 2\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Lista de valores. */\r\nexport function ListIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M9 6.5h11M9 12h11M9 17.5h11M4.5 6.5h.01M4.5 12h.01M4.5 17.5h.01\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Texto: negrito. */\r\nexport function BoldIcon(props: IconProps) {\r\n return (\r\n <Svg strokeWidth={2.2} {...props}>\r\n <path d=\"M7 5h6a3.5 3.5 0 0 1 0 7H7zM7 12h7a3.5 3.5 0 0 1 0 7H7z\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Texto: itálico. */\r\nexport function ItalicIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M10 5h8M6 19h8M14.5 5l-5 14\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Texto: sublinhado. */\r\nexport function UnderlineIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M7 4.5v6a5 5 0 0 0 10 0v-6M5.5 20h13\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Texto: riscado. */\r\nexport function StrikethroughIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M4.5 12h15M16.5 6.5A4.5 3.5 0 0 0 12 5c-2.5 0-4.5 1.3-4.5 3.2 0 1.4 1 2.4 2.7 2.9M8 17.3A5 3.6 0 0 0 12 19c2.6 0 4.6-1.4 4.6-3.3 0-.8-.3-1.5-.9-2\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Lista com marcas (no texto). */\r\nexport function ListBulletIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M9.5 6.5h10M9.5 12h10M9.5 17.5h10\" />\r\n <circle cx=\"5\" cy=\"6.5\" r=\"1\" fill=\"currentColor\" />\r\n <circle cx=\"5\" cy=\"12\" r=\"1\" fill=\"currentColor\" />\r\n <circle cx=\"5\" cy=\"17.5\" r=\"1\" fill=\"currentColor\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Lista numerada (no texto). */\r\nexport function ListNumberedIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M10 6.5h10M10 12h10M10 17.5h10M4 5.5l1.3-.8v4M3.8 15.2c.3-.6.9-.9 1.5-.9.8 0 1.4.5 1.4 1.2 0 1-1.6 1.6-2.9 2.8h3\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Citação. */\r\nexport function QuoteIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M5 18V12.5C5 9 6.5 7 9.5 6M14 18v-5.5C14 9 15.5 7 18.5 6M5 12.5h4.5V18H5M14 12.5h4.5V18H14\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Imagem. */\r\nexport function ImageIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"3.5\" y=\"4.5\" width=\"17\" height=\"15\" rx=\"2\" />\r\n <circle cx=\"9\" cy=\"10\" r=\"1.6\" />\r\n <path d=\"M20.5 15.5l-4.5-4.5-8.5 8.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Abrir em ecrã quase inteiro. */\r\nexport function MaximizeIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M14 4.5h5.5V10M10 19.5H4.5V14M19.5 4.5L13.5 10.5M4.5 19.5l6-6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Voltar ao tamanho normal. */\r\nexport function MinimizeIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M19.5 10H14V4.5M4.5 14H10v5.5M14 10l6-6M4 20l6-6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Tema claro. */\r\nexport function SunIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\r\n <path d=\"M12 2.5v2M12 19.5v2M4.6 4.6L6 6M18 18l1.4 1.4M2.5 12h2M19.5 12h2M4.6 19.4L6 18M18 6l1.4-1.4\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Tema escuro. */\r\nexport function MoonIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Tema do sistema. */\r\nexport function MonitorIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"12.5\" rx=\"2\" />\r\n <path d=\"M8.5 20.5h7M12 16.5v4\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Idioma. */\r\nexport function GlobeIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\r\n <path d=\"M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Terminar sessão. */\r\nexport function LogOutIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M9.5 20.5H6a2 2 0 0 1-2-2v-13a2 2 0 0 1 2-2h3.5M15.5 16.5L20 12l-4.5-4.5M20 12H9.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Abre fora da aplicação (separador novo). */\r\nexport function ExternalLinkIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M14 4h6v6M20 4l-9 9M18 13.5V18a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Atenção (avisos, confirmações perigosas). */\r\nexport function WarningIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M10.3 4.3L2.8 17.5A2 2 0 0 0 4.5 20.5h15a2 2 0 0 0 1.7-3L13.7 4.3a2 2 0 0 0-3.4 0z\" />\r\n <path d=\"M12 9.5v4.5\" />\r\n <circle cx=\"12\" cy=\"17\" r=\"1.1\" fill=\"currentColor\" stroke=\"none\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Erro. */\r\nexport function ErrorIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <circle cx=\"12\" cy=\"12\" r=\"9.5\" />\r\n <path d=\"M9 9l6 6M15 9l-6 6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Intervalo (mínimo e máximo). */\r\nexport function SlidersIcon(props: IconProps) {\r\n return (\r\n <Svg {...props}>\r\n <path d=\"M4 7h10M18 7h2M4 17h2M10 17h10\" />\r\n <circle cx=\"16\" cy=\"7\" r=\"2\" />\r\n <circle cx=\"8\" cy=\"17\" r=\"2\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** Mais ações (⋯), ex: o botão do Menu sem texto. */\r\nexport function MoreIcon(props: IconProps) {\r\n return (\r\n <Svg {...props} fill=\"currentColor\">\r\n <circle cx=\"5\" cy=\"12\" r=\"1.8\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"1.8\" />\r\n <circle cx=\"19\" cy=\"12\" r=\"1.8\" />\r\n </Svg>\r\n )\r\n}\r\n"],"names":[],"mappings":"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"}
@@ -3,12 +3,19 @@ import React, { forwardRef, useImperativeHandle, useState, useMemo, useRef, useE
3
3
  import { createPortal } from "react-dom";
4
4
  import { ChevronDownIcon } from "../../../foundations/icons/icons.js";
5
5
  import { useField, fieldBoxClasses } from "../field.js";
6
+ import Checkbox from "../Checkbox/Checkbox.js";
6
7
  import { useFloatingPanel, PANEL_CLASS, itemClass } from "../../../capabilities/overlay/useFloatingPanel.js";
7
8
  import { useDialogContainer } from "../../../components/overlays/Dialog/Dialog.js";
8
9
  const DEFAULT_SELECT_LABELS = {
9
10
  search: "Search…",
10
11
  searchIn: "Search in {label}",
11
- noResults: "No results"
12
+ noResults: "No results",
13
+ selectAll: "Select all",
14
+ selectResults: "Select all (results)",
15
+ clear: "Clear"
16
+ };
17
+ const plain = (text) => text.normalize("NFD").replace(new RegExp("\\p{M}", "gu"), "").toLowerCase();
18
+ const noop = () => {
12
19
  };
13
20
  const Check = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4 shrink-0 text-proef-blue dark:text-sky-300", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
14
21
  function optionsFromChildren(children) {
@@ -50,7 +57,9 @@ const SelectInput = forwardRef(function SelectInput2({
50
57
  values: controlledValues,
51
58
  defaultValues = [],
52
59
  onValuesChange,
53
- allLabel
60
+ allLabel,
61
+ selectionActions = false,
62
+ checkboxes = false
54
63
  }, ref) {
55
64
  const L = { ...DEFAULT_SELECT_LABELS, ...labels };
56
65
  const field = useField();
@@ -70,8 +79,8 @@ const SelectInput = forwardRef(function SelectInput2({
70
79
  const [query, setQuery] = useState("");
71
80
  const withSearch = searchable ?? list.length > 10;
72
81
  const visible = useMemo(() => {
73
- const q = query.trim().toLowerCase();
74
- return q ? list.filter((o) => o.label.toLowerCase().includes(q) || o.description?.toLowerCase().includes(q)) : list;
82
+ const q = plain(query.trim());
83
+ return q ? list.filter((o) => plain(o.label).includes(q) || (o.description ? plain(o.description).includes(q) : false)) : list;
75
84
  }, [list, query]);
76
85
  const [active, setActive] = useState(0);
77
86
  const searchRef = useRef(null);
@@ -85,6 +94,10 @@ const SelectInput = forwardRef(function SelectInput2({
85
94
  useEffect(() => {
86
95
  if (p.open) p.panelRef.current?.querySelector(`[data-index="${active}"]`)?.scrollIntoView?.({ block: "nearest" });
87
96
  }, [active, p.open, p.panelRef]);
97
+ const setPicked = (next) => {
98
+ if (controlledValues === void 0) setOwnValues(next);
99
+ onValuesChange?.(next);
100
+ };
88
101
  const choose = (o) => {
89
102
  if (o.disabled) return;
90
103
  if (multiple) {
@@ -143,8 +156,9 @@ const SelectInput = forwardRef(function SelectInput2({
143
156
  }
144
157
  };
145
158
  const pill = variant === "pill";
159
+ const withBoxes = multiple && checkboxes;
146
160
  const pickedOptions = list.filter((o) => picked.includes(o.value));
147
- const multiText = allLabel && list.length > 0 && pickedOptions.length === list.length ? allLabel : pickedOptions.map((o) => o.label).join(", ");
161
+ const multiText = allLabel && list.length > 0 && pickedOptions.length === list.length ? allLabel : L.selectedCount && pickedOptions.length > 1 ? L.selectedCount.replace("{n}", String(pickedOptions.length)) : pickedOptions.map((o) => o.label).join(", ");
148
162
  const showsPlaceholder = multiple ? pickedOptions.length === 0 : !chosen || chosen.value === "" && placeholder !== void 0 && emptyOption === void 0;
149
163
  const buttonText = multiple ? showsPlaceholder ? placeholder ?? "" : multiText : showsPlaceholder ? placeholder ?? chosen?.label ?? "" : chosen?.label;
150
164
  return /* @__PURE__ */ jsxs("div", { className: `relative min-w-0 ${className}`, onKeyDown: keys, children: [
@@ -190,6 +204,32 @@ const SelectInput = forwardRef(function SelectInput2({
190
204
  className: "h-8 w-full rounded-lg border border-slate-300 bg-white px-2.5 text-sm outline-none focus:border-proef-blue dark:border-slate-600 dark:bg-slate-800 dark:text-slate-100"
191
205
  }
192
206
  ) }),
207
+ multiple && selectionActions && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-3 pb-1 text-xs", children: [
208
+ /* @__PURE__ */ jsx(
209
+ "button",
210
+ {
211
+ type: "button",
212
+ disabled: !visible.some((o) => !o.disabled),
213
+ onClick: () => {
214
+ const add = visible.filter((o) => !o.disabled).map((o) => o.value);
215
+ const set = /* @__PURE__ */ new Set([...picked, ...add]);
216
+ setPicked(list.filter((x) => set.has(x.value)).map((x) => x.value));
217
+ },
218
+ className: "text-proef-blue hover:underline disabled:opacity-40 dark:text-sky-300",
219
+ children: query.trim() ? L.selectResults : L.selectAll
220
+ }
221
+ ),
222
+ /* @__PURE__ */ jsx(
223
+ "button",
224
+ {
225
+ type: "button",
226
+ disabled: picked.length === 0,
227
+ onClick: () => setPicked([]),
228
+ className: "text-proef-blue hover:underline disabled:opacity-40 dark:text-sky-300",
229
+ children: L.clear
230
+ }
231
+ )
232
+ ] }),
193
233
  /* @__PURE__ */ jsxs("ul", { role: "listbox", "aria-label": ariaLabel, "aria-multiselectable": multiple || void 0, children: [
194
234
  visible.length === 0 && /* @__PURE__ */ jsx("li", { className: "px-3 py-2 text-slate-400", children: L.noResults }),
195
235
  visible.map((o, i) => {
@@ -205,11 +245,13 @@ const SelectInput = forwardRef(function SelectInput2({
205
245
  onClick: () => choose(o),
206
246
  className: `${itemClass(i === active)} ${o.disabled ? "cursor-not-allowed opacity-50" : ""}`,
207
247
  children: [
248
+ withBoxes && /* @__PURE__ */ jsx(Checkbox, { checked: selected, onChange: noop, tabIndex: -1, "aria-hidden": true, className: "pointer-events-none" }),
208
249
  /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
209
250
  /* @__PURE__ */ jsx("span", { className: `block truncate ${selected ? "font-semibold" : ""} ${o.value === "" ? "text-slate-500 dark:text-slate-400" : ""}`, children: o.label }),
210
251
  o.description && /* @__PURE__ */ jsx("span", { className: "block truncate text-[11px] text-slate-500 dark:text-slate-400", children: o.description })
211
252
  ] }),
212
- /* @__PURE__ */ jsx("span", { className: "w-4 shrink-0", children: selected && /* @__PURE__ */ jsx(Check, {}) })
253
+ o.count !== void 0 && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs tabular-nums text-slate-500 dark:text-slate-400", children: o.count.toLocaleString() }),
254
+ !withBoxes && /* @__PURE__ */ jsx("span", { className: "w-4 shrink-0", children: selected && /* @__PURE__ */ jsx(Check, {}) })
213
255
  ]
214
256
  },
215
257
  o.value || "__empty"