@proef/common-ui 2.6.5 → 2.6.7
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 +42 -33
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/legacy/components/layout/Spinner/Spinner.js +1 -15
- package/dist/esm/legacy/components/layout/Spinner/Spinner.js.map +1 -1
- package/dist/esm/legacy/components/molecules/ConfirmModal/ConfirmModal.js +1 -1
- package/dist/esm/legacy/components/molecules/MultiTagPicker/MultiTagPicker.js +1 -1
- package/dist/esm/legacy/components/organisms/LazyLoader/LazyLoader.js +1 -1
- package/dist/esm/legacy/components/organisms/Selector/Selector.js +1 -1
- package/dist/esm/v1/components/data/MonthCalendar/MonthCalendar.js +83 -0
- package/dist/esm/v1/components/data/MonthCalendar/MonthCalendar.js.map +1 -0
- package/dist/esm/v1/components/overlays/DropdownMenu/DropdownMenu.js +222 -0
- package/dist/esm/v1/components/overlays/DropdownMenu/DropdownMenu.js.map +1 -0
- package/dist/esm/v1/foundations/icons/icons.js +8 -0
- package/dist/esm/v1/foundations/icons/icons.js.map +1 -1
- package/dist/esm/v1/primitives/display/Badge/Badge.js +3 -2
- package/dist/esm/v1/primitives/display/Badge/Badge.js.map +1 -1
- package/dist/esm/v1/primitives/display/DescriptionList/DescriptionList.js +31 -0
- package/dist/esm/v1/primitives/display/DescriptionList/DescriptionList.js.map +1 -0
- package/dist/esm/v1/primitives/feedback/Spinner/Spinner.js +24 -0
- package/dist/esm/v1/primitives/feedback/Spinner/Spinner.js.map +1 -0
- package/dist/esm/v1/primitives/forms/DateInput/DateInput.js +3 -1
- package/dist/esm/v1/primitives/forms/DateInput/DateInput.js.map +1 -1
- package/dist/esm/v1/primitives/navigation/Steps/Steps.js +68 -0
- package/dist/esm/v1/primitives/navigation/Steps/Steps.js.map +1 -0
- package/dist/style.components.css +1 -1
- package/dist/style.css +1 -1
- package/dist/style.layered.css +1 -1
- package/dist/types/legacy/components/layout/Spinner/Spinner.d.ts +1 -4
- package/dist/types/v1/components/data/MonthCalendar/MonthCalendar.d.ts +37 -0
- package/dist/types/v1/components/overlays/DropdownMenu/DropdownMenu.d.ts +92 -0
- package/dist/types/v1/foundations/icons/icons.d.ts +2 -0
- package/dist/types/v1/index.d.ts +11 -1
- package/dist/types/v1/primitives/display/Badge/Badge.d.ts +2 -0
- package/dist/types/v1/primitives/display/DescriptionList/DescriptionList.d.ts +29 -0
- package/dist/types/v1/primitives/feedback/Spinner/Spinner.d.ts +20 -0
- package/dist/types/v1/primitives/navigation/Steps/Steps.d.ts +49 -0
- package/package.json +1 -1
- package/dist/esm/legacy/components/layout/Spinner/Spinner.css +0 -10
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";
|
|
@@ -70,22 +71,22 @@ import { default as default66 } from "./legacy/components/molecules/SeletorPesqu
|
|
|
70
71
|
import { default as default67 } from "./legacy/components/ui/Separadores.js";
|
|
71
72
|
import { default as default68 } from "./v1/components/layout/SideNav/SideNav.js";
|
|
72
73
|
import { default as default69 } from "./legacy/components/molecules/Sidebar/Sidebar.js";
|
|
73
|
-
import { default as default70 } from "./legacy/components/
|
|
74
|
-
import { default as default71 } from "./legacy/components/
|
|
75
|
-
import {
|
|
76
|
-
import { default as
|
|
77
|
-
import { default as
|
|
78
|
-
import { default as
|
|
79
|
-
import { default as
|
|
80
|
-
import { default as
|
|
81
|
-
import { default as
|
|
82
|
-
import { default as
|
|
83
|
-
import { default as
|
|
84
|
-
import { default as
|
|
85
|
-
import { default as
|
|
86
|
-
import { default as
|
|
87
|
-
import { default as
|
|
88
|
-
import { default as
|
|
74
|
+
import { default as default70 } from "./legacy/components/atoms/Stack/Stack.js";
|
|
75
|
+
import { default as default71 } from "./legacy/components/organisms/StatusMatrix/StatusMatrix.js";
|
|
76
|
+
import { DEFAULT_STEPS_LABELS, Steps } from "./v1/primitives/navigation/Steps/Steps.js";
|
|
77
|
+
import { default as default72 } from "./v1/primitives/forms/Switch/Switch.js";
|
|
78
|
+
import { default as default73 } from "./legacy/components/atoms/Button/variants/TabButton.js";
|
|
79
|
+
import { default as default74 } from "./v1/components/tables/Table/Table.js";
|
|
80
|
+
import { default as default75 } from "./v1/primitives/navigation/Tabs/Tabs.js";
|
|
81
|
+
import { default as default76 } from "./v1/primitives/forms/TextArea/TextArea.js";
|
|
82
|
+
import { default as default77 } from "./v1/primitives/forms/TextInput/TextInput.js";
|
|
83
|
+
import { default as default78 } from "./legacy/components/ui/TextoAuto.js";
|
|
84
|
+
import { default as default79, useToast } from "./v1/components/feedback/Toast/Toast.js";
|
|
85
|
+
import { default as default80 } from "./v1/components/overlays/Tooltip/Tooltip.js";
|
|
86
|
+
import { default as default81 } from "./v1/components/overlays/Tooltip/TooltipLayer.js";
|
|
87
|
+
import { default as default82 } from "./legacy/components/layout/TopBar/TopBar.js";
|
|
88
|
+
import { default as default83 } from "./legacy/components/layout/TopNavLayout/TopNavLayout.js";
|
|
89
|
+
import { default as default84 } from "./legacy/components/molecules/UserAvatar/UserAvatar.js";
|
|
89
90
|
import { Anel, Barras, BarrasEmpilhadas, BarrasHorizontais, Bolhas, Linha, Linhas, PALETA, cor } from "./legacy/components/charts/Charts.js";
|
|
90
91
|
import { ApiProvider } from "./legacy/contexts/apiContext.js";
|
|
91
92
|
import { AuthProvider, useAuth } from "./legacy/contexts/authContext.js";
|
|
@@ -95,15 +96,17 @@ import { AvisosProvider, useAvisos } from "./legacy/components/ui/Avisos.js";
|
|
|
95
96
|
import { Badge } from "./v1/primitives/display/Badge/Badge.js";
|
|
96
97
|
import { BadgeSla, BarraFiltros, Btn, BtnGroup, Campo, CampoInterruptor, CampoPesquisa, CampoSelect, ChipEstadoInterno, Estado, LinhaAlerta, ListaCampos, Modal, SectionGroup } from "./legacy/components/ui/Ui.js";
|
|
97
98
|
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";
|
|
99
|
+
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
100
|
import { Card } from "./v1/primitives/display/Card/Card.js";
|
|
100
101
|
import { DEFAULT_LIST_FINDER_LABELS } from "./v1/components/lists/ListFinder/labels.js";
|
|
101
102
|
import { DEFAULT_TABLE_LABELS } from "./v1/components/tables/Table/labels.js";
|
|
103
|
+
import { DescriptionList } from "./v1/primitives/display/DescriptionList/DescriptionList.js";
|
|
102
104
|
import { FilterChips } from "./v1/primitives/display/FilterChips/FilterChips.js";
|
|
103
105
|
import { FontWeight } from "./legacy/constants/FontWeight.js";
|
|
104
106
|
import { InputData, InputHora } from "./legacy/components/atoms/InputData/InputData.js";
|
|
105
107
|
import { Kpi } from "./v1/primitives/display/Kpi/Kpi.js";
|
|
106
108
|
import { LazyLoader } from "./legacy/components/organisms/LazyLoader/LazyLoader.js";
|
|
109
|
+
import { MonthCalendar } from "./v1/components/data/MonthCalendar/MonthCalendar.js";
|
|
107
110
|
import { Notice } from "./v1/primitives/display/Notice/Notice.js";
|
|
108
111
|
import { Pagination } from "./v1/components/data/Pagination/Pagination.js";
|
|
109
112
|
import { PeopleFilter } from "./v1/primitives/display/PeopleFilter/PeopleFilter.js";
|
|
@@ -166,13 +169,17 @@ export {
|
|
|
166
169
|
ConfirmProvider,
|
|
167
170
|
default17 as Confirmacao,
|
|
168
171
|
default18 as CustomSwitch,
|
|
172
|
+
DEFAULT_DROPDOWN_MENU_LABELS,
|
|
169
173
|
DEFAULT_LIST_FINDER_LABELS,
|
|
174
|
+
DEFAULT_STEPS_LABELS,
|
|
170
175
|
DEFAULT_TABLE_LABELS,
|
|
171
176
|
default19 as DataTable,
|
|
172
177
|
DateInput,
|
|
178
|
+
DescriptionList,
|
|
173
179
|
default20 as Dialog,
|
|
174
180
|
default21 as DocumentDropzone,
|
|
175
181
|
DonutChart,
|
|
182
|
+
DropdownMenu,
|
|
176
183
|
default22 as Error,
|
|
177
184
|
ErrorIcon,
|
|
178
185
|
default23 as ErrorPage,
|
|
@@ -234,7 +241,9 @@ export {
|
|
|
234
241
|
MinimizeIcon,
|
|
235
242
|
default50 as Modal,
|
|
236
243
|
MonitorIcon,
|
|
244
|
+
MonthCalendar,
|
|
237
245
|
MoonIcon,
|
|
246
|
+
MoreIcon,
|
|
238
247
|
default51 as MultiTagPicker,
|
|
239
248
|
default52 as NotFoundPage,
|
|
240
249
|
Notice,
|
|
@@ -274,26 +283,26 @@ export {
|
|
|
274
283
|
SlidersIcon,
|
|
275
284
|
SocketProvider,
|
|
276
285
|
SparklesIcon,
|
|
277
|
-
default70 as
|
|
278
|
-
default71 as
|
|
279
|
-
|
|
286
|
+
default70 as Stack,
|
|
287
|
+
default71 as StatusMatrix,
|
|
288
|
+
Steps,
|
|
280
289
|
StrikethroughIcon,
|
|
281
290
|
SunIcon,
|
|
282
|
-
|
|
291
|
+
default72 as Switch,
|
|
283
292
|
THEME_STORAGE_KEY,
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
293
|
+
default73 as TabButton,
|
|
294
|
+
default74 as Table,
|
|
295
|
+
default75 as Tabs,
|
|
296
|
+
default76 as TextArea,
|
|
297
|
+
default77 as TextInput,
|
|
298
|
+
default78 as TextoAuto,
|
|
299
|
+
default79 as ToastProvider,
|
|
300
|
+
default80 as Tooltip,
|
|
301
|
+
default81 as TooltipLayer,
|
|
302
|
+
default82 as TopBar,
|
|
303
|
+
default83 as TopNavLayout,
|
|
295
304
|
UnderlineIcon,
|
|
296
|
-
|
|
305
|
+
default84 as UserAvatar,
|
|
297
306
|
WarningIcon,
|
|
298
307
|
applyColumnLayout,
|
|
299
308
|
applyTheme,
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,18 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
3
|
-
import { faSpinner } from "@fortawesome/free-solid-svg-icons";
|
|
4
|
-
import './Spinner.css';/* empty css */
|
|
5
|
-
const Spinner = () => {
|
|
6
|
-
return /* @__PURE__ */ jsx("div", { className: "cui-spinner", children: /* @__PURE__ */ jsx(
|
|
7
|
-
FontAwesomeIcon,
|
|
8
|
-
{
|
|
9
|
-
icon: faSpinner,
|
|
10
|
-
className: "cui-icon",
|
|
11
|
-
spin: true,
|
|
12
|
-
"aria-hidden": "true"
|
|
13
|
-
}
|
|
14
|
-
) });
|
|
15
|
-
};
|
|
1
|
+
import { Spinner } from "../../../../v1/primitives/feedback/Spinner/Spinner.js";
|
|
16
2
|
export {
|
|
17
3
|
Spinner as default
|
|
18
4
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Spinner.js","sources":[
|
|
1
|
+
{"version":3,"file":"Spinner.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -2,7 +2,7 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { faCheck } from "@fortawesome/free-solid-svg-icons";
|
|
3
3
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
4
4
|
import Modal from "../Modal/Modal.js";
|
|
5
|
-
import Spinner from "
|
|
5
|
+
import { Spinner } from "../../../../v1/primitives/feedback/Spinner/Spinner.js";
|
|
6
6
|
import { ActionButtonThemeStyled } from "../../../styles/themes/ButtonThemes.js";
|
|
7
7
|
import './ConfirmModal.css';/* empty css */
|
|
8
8
|
import ActionButton from "../../atoms/Button/variants/ActionButton.js";
|
|
@@ -5,7 +5,7 @@ import { faCircleMinus, faMagnifyingGlass } from "@fortawesome/free-solid-svg-ic
|
|
|
5
5
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
6
6
|
import { Color } from "../../../constants/Colors.js";
|
|
7
7
|
import Select from "../../atoms/MultiTagPickerTag/MultiTagPickerTag.js";
|
|
8
|
-
import Spinner from "
|
|
8
|
+
import { Spinner } from "../../../../v1/primitives/feedback/Spinner/Spinner.js";
|
|
9
9
|
import './MultiTagPicker.css';/* empty css */
|
|
10
10
|
const MultiTagPicker = (props) => {
|
|
11
11
|
const {
|
|
@@ -2,7 +2,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState, useRef, useEffect } from "react";
|
|
3
3
|
import InfiniteScroll from "react-infinite-scroll-component";
|
|
4
4
|
import { useApi } from "../../../hooks/useApi.js";
|
|
5
|
-
import Spinner from "
|
|
5
|
+
import { Spinner } from "../../../../v1/primitives/feedback/Spinner/Spinner.js";
|
|
6
6
|
const LazyLoader = ({
|
|
7
7
|
endpoint,
|
|
8
8
|
params = {},
|
|
@@ -6,7 +6,7 @@ import Modal from "../../molecules/Modal/Modal.js";
|
|
|
6
6
|
import SearchInput from "../../../../v1/primitives/forms/SearchInput/SearchInput.js";
|
|
7
7
|
import { LazyLoader } from "../LazyLoader/LazyLoader.js";
|
|
8
8
|
import './Selector.css';/* empty css */
|
|
9
|
-
import Spinner from "
|
|
9
|
+
import { Spinner } from "../../../../v1/primitives/feedback/Spinner/Spinner.js";
|
|
10
10
|
import Tooltip from "../../../../v1/components/overlays/Tooltip/Tooltip.js";
|
|
11
11
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
12
12
|
import ActionButton from "../../atoms/Button/variants/ActionButton.js";
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { BADGE_TONE_CLASSES } from "../../../primitives/display/Badge/Badge.js";
|
|
4
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
5
|
+
const hoje = () => {
|
|
6
|
+
const d = /* @__PURE__ */ new Date();
|
|
7
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
8
|
+
};
|
|
9
|
+
function MonthCalendar({
|
|
10
|
+
year,
|
|
11
|
+
month,
|
|
12
|
+
days = [],
|
|
13
|
+
title,
|
|
14
|
+
locale = "pt-PT",
|
|
15
|
+
weekStartsOn = 1,
|
|
16
|
+
today,
|
|
17
|
+
className = "",
|
|
18
|
+
...props
|
|
19
|
+
}) {
|
|
20
|
+
const prefixo = `${year}-${pad(month)}-`;
|
|
21
|
+
const marcados = React.useMemo(() => {
|
|
22
|
+
const m = /* @__PURE__ */ new Map();
|
|
23
|
+
for (const d of days) {
|
|
24
|
+
if (!d.date.startsWith(prefixo)) continue;
|
|
25
|
+
const atual = m.get(d.date);
|
|
26
|
+
if (atual) {
|
|
27
|
+
if (d.label) atual.labels.push(d.label);
|
|
28
|
+
} else {
|
|
29
|
+
m.set(d.date, { tone: d.tone, labels: d.label ? [d.label] : [] });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return m;
|
|
33
|
+
}, [days, prefixo]);
|
|
34
|
+
const nomes = React.useMemo(() => {
|
|
35
|
+
const utc = { timeZone: "UTC" };
|
|
36
|
+
const primeiro = weekStartsOn === 1 ? 5 : 4;
|
|
37
|
+
const semana = new Intl.DateTimeFormat(locale, { ...utc, weekday: "narrow" });
|
|
38
|
+
return {
|
|
39
|
+
mes: new Intl.DateTimeFormat(locale, { ...utc, month: "long" }).format(new Date(Date.UTC(year, month - 1, 1))),
|
|
40
|
+
semana: Array.from({ length: 7 }, (_, i) => semana.format(new Date(Date.UTC(2026, 0, primeiro + i)))),
|
|
41
|
+
longo: new Intl.DateTimeFormat(locale, { ...utc, day: "numeric", month: "long" })
|
|
42
|
+
};
|
|
43
|
+
}, [locale, weekStartsOn, year, month]);
|
|
44
|
+
const total = new Date(Date.UTC(year, month, 0)).getUTCDate();
|
|
45
|
+
const inicio = (new Date(Date.UTC(year, month - 1, 1)).getUTCDay() - weekStartsOn + 7) % 7;
|
|
46
|
+
const diaHoje = today === void 0 ? hoje() : today;
|
|
47
|
+
const cabecalho = title === void 0 ? nomes.mes : title;
|
|
48
|
+
return /* @__PURE__ */ jsxs("section", { ...props, "aria-label": `${nomes.mes} ${year}`, className: `min-w-[16rem] rounded-lg border border-border bg-card p-3 ${className}`, children: [
|
|
49
|
+
cabecalho !== null && /* @__PURE__ */ jsx("h3", { className: "mb-2 text-center text-sm font-semibold capitalize text-foreground", children: cabecalho }),
|
|
50
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[repeat(7,minmax(2rem,1fr))] gap-0.5 text-center text-xs tabular-nums", children: [
|
|
51
|
+
nomes.semana.map((s, i) => /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "pb-1 font-medium uppercase text-muted-foreground", children: s }, i)),
|
|
52
|
+
Array.from({ length: inicio }, (_, i) => /* @__PURE__ */ jsx("span", { "aria-hidden": true }, `v${i}`)),
|
|
53
|
+
Array.from({ length: total }, (_, i) => {
|
|
54
|
+
const dia = i + 1;
|
|
55
|
+
const data = `${prefixo}${pad(dia)}`;
|
|
56
|
+
const coluna = (inicio + i) % 7;
|
|
57
|
+
const fimDeSemana = weekStartsOn === 1 ? coluna >= 5 : coluna === 0 || coluna === 6;
|
|
58
|
+
const marca = marcados.get(data);
|
|
59
|
+
const texto = marca?.labels.join(" · ");
|
|
60
|
+
return /* @__PURE__ */ jsx(
|
|
61
|
+
"span",
|
|
62
|
+
{
|
|
63
|
+
"data-date": data,
|
|
64
|
+
"data-tip": texto || void 0,
|
|
65
|
+
"aria-label": texto ? `${nomes.longo.format(new Date(Date.UTC(year, month - 1, dia)))}: ${texto}` : void 0,
|
|
66
|
+
className: [
|
|
67
|
+
"flex h-7 items-center justify-center rounded-md",
|
|
68
|
+
marca ? `${BADGE_TONE_CLASSES[marca.tone]} font-semibold` : fimDeSemana ? "text-muted-foreground" : "text-foreground",
|
|
69
|
+
data === diaHoje ? "ring-1 ring-primary dark:ring-sky-300" : "",
|
|
70
|
+
texto ? "cursor-help" : ""
|
|
71
|
+
].join(" "),
|
|
72
|
+
children: dia
|
|
73
|
+
},
|
|
74
|
+
data
|
|
75
|
+
);
|
|
76
|
+
})
|
|
77
|
+
] })
|
|
78
|
+
] });
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
MonthCalendar
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=MonthCalendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MonthCalendar.js","sources":["../../../../../../src/v1/components/data/MonthCalendar/MonthCalendar.tsx"],"sourcesContent":["import React from 'react'\r\nimport { BADGE_TONE_CLASSES, type BadgeTone } from '../../../primitives/display/Badge/Badge'\r\n\r\n/** Os mesmos tons do `Badge`: estados (`ok`, `risco`, `incumprido`, `neutral`, `accent`) e classificações. */\r\nexport type MonthCalendarTone = BadgeTone\r\n\r\nexport interface MonthCalendarDay {\r\n /** `YYYY-MM-DD`. Os dias de outros meses são ignorados, por isso pode passar-se a lista do ano inteiro. */\r\n date: string\r\n tone: MonthCalendarTone\r\n /** O que o dia tem (ex: \"Férias · Autorizado\"); vai para o `data-tip` e para os leitores de ecrã. */\r\n label?: string\r\n}\r\n\r\nexport interface MonthCalendarProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children' | 'title'> {\r\n year: number\r\n /** 1 = janeiro … 12 = dezembro. */\r\n month: number\r\n /** Dias marcados. Vários na mesma data: fica a cor do primeiro e juntam-se as etiquetas. */\r\n days?: MonthCalendarDay[]\r\n /** Título por cima dos dias. Por omissão o nome do mês; `null` para nenhum. */\r\n title?: React.ReactNode | null\r\n /** Nomes do mês e dos dias da semana. */\r\n locale?: string\r\n /** 1 = segunda (Portugal), 0 = domingo. */\r\n weekStartsOn?: 0 | 1\r\n /** Dia com contorno. Por omissão o de hoje; `null` para nenhum. */\r\n today?: string | null\r\n}\r\n\r\nconst pad = (n: number) => String(n).padStart(2, '0')\r\nconst hoje = () => {\r\n const d = new Date()\r\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`\r\n}\r\n\r\n/**\r\n * Um mês, com os dias pintados por tom (ex: férias, feriados, ausências).\r\n * Para o ano inteiro, um por mês numa grelha (ver a story \"Ano inteiro\").\r\n *\r\n * Genérico: não sabe o que são férias. A app decide a cor e a etiqueta de cada\r\n * dia; o calendário só desenha. A legenda faz-se com `Badge`, nos mesmos tons.\r\n *\r\n * **Aceita os atributos HTML do `<section>`** (ex: `id`, `className`).\r\n */\r\nexport default function MonthCalendar({\r\n year,\r\n month,\r\n days = [],\r\n title,\r\n locale = 'pt-PT',\r\n weekStartsOn = 1,\r\n today,\r\n className = '',\r\n ...props\r\n}: MonthCalendarProps) {\r\n const prefixo = `${year}-${pad(month)}-`\r\n\r\n const marcados = React.useMemo(() => {\r\n const m = new Map<string, { tone: MonthCalendarTone; labels: string[] }>()\r\n for (const d of days) {\r\n if (!d.date.startsWith(prefixo)) continue\r\n const atual = m.get(d.date)\r\n if (atual) {\r\n if (d.label) atual.labels.push(d.label)\r\n } else {\r\n m.set(d.date, { tone: d.tone, labels: d.label ? [d.label] : [] })\r\n }\r\n }\r\n return m\r\n }, [days, prefixo])\r\n\r\n const nomes = React.useMemo(() => {\r\n const utc = { timeZone: 'UTC' } as const\r\n // 05/01/2026 é segunda; 04/01/2026 domingo.\r\n const primeiro = weekStartsOn === 1 ? 5 : 4\r\n const semana = new Intl.DateTimeFormat(locale, { ...utc, weekday: 'narrow' })\r\n return {\r\n mes: new Intl.DateTimeFormat(locale, { ...utc, month: 'long' }).format(new Date(Date.UTC(year, month - 1, 1))),\r\n semana: Array.from({ length: 7 }, (_, i) => semana.format(new Date(Date.UTC(2026, 0, primeiro + i)))),\r\n longo: new Intl.DateTimeFormat(locale, { ...utc, day: 'numeric', month: 'long' }),\r\n }\r\n }, [locale, weekStartsOn, year, month])\r\n\r\n const total = new Date(Date.UTC(year, month, 0)).getUTCDate()\r\n const inicio = (new Date(Date.UTC(year, month - 1, 1)).getUTCDay() - weekStartsOn + 7) % 7\r\n const diaHoje = today === undefined ? hoje() : today\r\n const cabecalho = title === undefined ? nomes.mes : title\r\n\r\n // Mínimo de 7 dias × 2rem: num sítio estreito o mês não encolhe ao ponto de os números se sobreporem.\r\n return (\r\n <section {...props} aria-label={`${nomes.mes} ${year}`} className={`min-w-[16rem] rounded-lg border border-border bg-card p-3 ${className}`}>\r\n {cabecalho !== null && (\r\n <h3 className=\"mb-2 text-center text-sm font-semibold capitalize text-foreground\">{cabecalho}</h3>\r\n )}\r\n <div className=\"grid grid-cols-[repeat(7,minmax(2rem,1fr))] gap-0.5 text-center text-xs tabular-nums\">\r\n {nomes.semana.map((s, i) => (\r\n <span key={i} aria-hidden className=\"pb-1 font-medium uppercase text-muted-foreground\">{s}</span>\r\n ))}\r\n {Array.from({ length: inicio }, (_, i) => <span key={`v${i}`} aria-hidden />)}\r\n {Array.from({ length: total }, (_, i) => {\r\n const dia = i + 1\r\n const data = `${prefixo}${pad(dia)}`\r\n const coluna = (inicio + i) % 7\r\n const fimDeSemana = weekStartsOn === 1 ? coluna >= 5 : coluna === 0 || coluna === 6\r\n const marca = marcados.get(data)\r\n const texto = marca?.labels.join(' · ')\r\n return (\r\n <span\r\n key={data}\r\n data-date={data}\r\n data-tip={texto || undefined}\r\n aria-label={texto ? `${nomes.longo.format(new Date(Date.UTC(year, month - 1, dia)))}: ${texto}` : undefined}\r\n className={[\r\n 'flex h-7 items-center justify-center rounded-md',\r\n marca ? `${BADGE_TONE_CLASSES[marca.tone]} font-semibold` : fimDeSemana ? 'text-muted-foreground' : 'text-foreground',\r\n data === diaHoje ? 'ring-1 ring-primary dark:ring-sky-300' : '',\r\n texto ? 'cursor-help' : '',\r\n ].join(' ')}\r\n >\r\n {dia}\r\n </span>\r\n )\r\n })}\r\n </div>\r\n </section>\r\n )\r\n}\r\n\r\nexport { MonthCalendar }\r\n"],"names":[],"mappings":"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"}
|
|
@@ -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":";;;;;;;AAqDO,MAAM,+BAAmD;AAAA,EAC9D,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AACT;AAgCA,MAAM,SAAS,CAAC,SAA2B,KAAK,eAAe,OAAO,KAAK,UAAU,YAAY,OAAO,KAAK,UAAU,WAAW,OAAO,KAAK,KAAK,IAAI;AAEvJ,MAAM,WAAW,CAAC,OAChB,cAAc,gBAAgB,GAAG,YAAY,WAAW,GAAG,YAAY,cAAc,GAAG;AAiB1F,SAAwB,aAAa;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ;AACF,GAAsB;AACpB,QAAM,IAAI,EAAE,GAAG,8BAA8B,GAAG,OAAA;AAChD,QAAM,UAAU,UAAU,UAAa,UAAU,QAAQ,UAAU;AACnE,QAAM,IAAI,iBAAiB,UAAU,UAAU,SAAS,QAAQ;AAEhE,QAAM,kBAAkB,mBAAA;AACxB,QAAM,SAAS,MAAA;AACf,QAAM,YAAY,OAAyB,IAAI;AAE/C,QAAM,OAAO,QAAQ,MAAM,MAAM,OAAO,CAAC,MAA6B,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;AACnF,QAAM,aAAa,cAAc,KAAK,SAAS;AAC/C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,UAAU,QAAQ,MAAM;AAC5B,UAAM,IAAI,MAAM,KAAA,EAAO,YAAA;AACvB,WAAO,IAAI,KAAK,OAAO,CAAC,MAAM,OAAO,CAAC,EAAE,YAAA,EAAc,SAAS,CAAC,CAAC,IAAI;AAAA,EACvE,GAAG,CAAC,MAAM,KAAK,CAAC;AAChB,QAAM,UAAU,QAAQ,IAAI,CAAC,GAAG,MAAO,EAAE,WAAW,KAAK,CAAE,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC;AACjF,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,EAAE;AAEjD,QAAM,UAAU,OAAO,YAAY;AACnC,UAAQ,UAAU;AAClB,QAAM,QAAQ,OAAO,IAAI;AACzB,YAAU,MAAM;AACd,QAAI,MAAM,SAAS;AACjB,YAAM,UAAU;AAChB;AAAA,IACF;AACA,YAAQ,UAAU,EAAE,IAAI;AAAA,EAC1B,GAAG,CAAC,EAAE,IAAI,CAAC;AAGX,YAAU,MAAM;AACd,QAAI,CAAC,EAAE,KAAM;AACb,aAAS,EAAE;AACX,mBAAe,EAAE;AACjB,QAAI,WAAY,YAAW,MAAM,UAAU,SAAS,MAAA,GAAS,CAAC;AAAA,EAChE,GAAG,CAAC,EAAE,IAAI,CAAC;AAEX,YAAU,MAAM;AACd,QAAI,EAAE,QAAQ,eAAe,EAAG,GAAE,SAAS,SAAS,cAA2B,gBAAgB,WAAW,IAAI,GAAG,iBAAiB,EAAE,OAAO,WAAW;AAAA,EACxJ,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,CAAC;AAEpC,MAAI,KAAK,WAAW,KAAK,CAAC,OAAQ,QAAO;AAEzC,QAAM,QAAQ,MAAM;AAClB,MAAE,MAAA;AACF,MAAE,WAAW,SAAS,MAAA;AAAA,EACxB;AAEA,QAAM,SAAS,CAAC,SAA2B;AACzC,QAAI,KAAK,SAAU;AAEnB,QAAI,KAAK,YAAY,OAAW,OAAA;AAChC,SAAK,WAAA;AAAA,EACP;AAEA,QAAM,OAAO,CAAC,SAAoC;AAChD,QAAI,QAAQ,WAAW,EAAG;AAC1B,UAAM,KAAK,QAAQ,QAAQ,WAAW;AACtC,UAAM,OACJ,SAAS,UAAU,QAAQ,CAAC,IACxB,SAAS,SAAS,QAAQ,QAAQ,SAAS,CAAC,IAC1C,OAAO,KAAM,SAAS,IAAI,QAAQ,CAAC,IAAI,QAAQ,QAAQ,SAAS,CAAC,IAC/D,QAAQ,KAAK,IAAI,QAAQ,SAAS,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC;AACtE,mBAAe,IAAI;AAAA,EACrB;AAGA,QAAM,OAAO,CAAC,MAA2B;AACvC,QAAI,CAAC,EAAE,MAAM;AACX,UAAI,CAAC,aAAa,SAAS,EAAE,SAAS,EAAE,GAAG,GAAG;AAC5C,UAAE,eAAA;AACF,UAAE,QAAQ,IAAI;AAAA,MAChB;AACA;AAAA,IACF;AACA,QAAI,EAAE,QAAQ,UAAU;AACtB,QAAE,eAAA;AACF,QAAE,gBAAA;AACF,YAAA;AACA;AAAA,IACF;AACA,QAAI,EAAE,QAAQ,OAAO;AACnB,QAAE,MAAA;AACF;AAAA,IACF;AAEA,QAAI,SAAS,EAAE,MAAM,KAAK,EAAE,WAAW,UAAU,QAAS;AAC1D,QAAI,EAAE,QAAQ,aAAa;AACzB,QAAE,eAAA;AACF,WAAK,CAAC;AAAA,IACR,WAAW,EAAE,QAAQ,WAAW;AAC9B,QAAE,eAAA;AACF,WAAK,EAAE;AAAA,IACT,WAAW,EAAE,QAAQ,UAAU,EAAE,WAAW,UAAU,SAAS;AAC7D,QAAE,eAAA;AACF,WAAK,OAAO;AAAA,IACd,WAAW,EAAE,QAAQ,SAAS,EAAE,WAAW,UAAU,SAAS;AAC5D,QAAE,eAAA;AACF,WAAK,MAAM;AAAA,IACb,WAAW,EAAE,QAAQ,WAAY,EAAE,QAAQ,OAAO,EAAE,WAAW,UAAU,SAAU;AACjF,YAAM,OAAO,QAAQ,WAAW;AAChC,UAAI,MAAM;AACR,UAAE,eAAA;AACF,eAAO,IAAI;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,cAAc,UAAU,SAAY,EAAE;AAEnD,8BACG,OAAA,EAAI,WAAW,wBAAwB,SAAS,IAAI,WAAW,MAC9D,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK,EAAE;AAAA,QACP,SAAS,YAAY,UAAU,cAAc;AAAA,QAC7C;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM,UAAU,OAAQ,QAAQ,oBAAC,YAAS,MAAM,SAAS,OAAO,KAAK,GAAA,CAAI;AAAA,QACzE,cAAY;AAAA,QACZ,YAAU,UAAU,SAAY;AAAA,QAChC,iBAAc;AAAA,QACd,iBAAe,EAAE;AAAA,QACjB,iBAAe,EAAE,OAAO,SAAS;AAAA,QACjC,SAAS,CAAC,MAAM;AAEd,YAAE,gBAAA;AACF,YAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;AAAA,QACrB;AAAA,QAEC,oBACC,qBAAA,UAAA,EACG,UAAA;AAAA,UAAA;AAAA,UACD,oBAAC,iBAAA,EAAgB,MAAM,IAAI,WAAW,iCAAiC,EAAE,OAAO,eAAe,EAAE,GAAA,CAAI;AAAA,QAAA,EAAA,CACvG,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,IAEL,EAAE,QACD;AAAA,2BACG,OAAA,EAAI,KAAK,EAAE,UAAU,OAAO,EAAE,OAAO,WAAW,GAAG,WAAW,IAAI,cAAc,IAAI,SAAS,CAAC,MAAM,EAAE,mBACpG,UAAA;AAAA,QAAA,UAAU,oBAAC,OAAA,EAAI,WAAU,kEAAkE,UAAA,QAAO;AAAA,QAClG,cACC,oBAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL,OAAO;AAAA,YACP,UAAU,CAAC,MAAM;AACf,uBAAS,EAAE,OAAO,KAAK;AACvB,6BAAe,EAAE;AAAA,YACnB;AAAA,YACA,aAAa,EAAE;AAAA,YACf,cAAY,EAAE;AAAA,YACd,WAAU;AAAA,UAAA;AAAA,QAAA,GAEd;AAAA,QAEF,qBAAC,OAAA,EAAI,IAAI,QAAQ,MAAK,QAAO,cAAY,OAAO,UAAU,WAAW,QAAQ,MAC1E,UAAA;AAAA,UAAA,QAAQ,WAAW,KAClB,oBAAC,KAAA,EAAE,WAAU,gCAAgC,UAAA,KAAK,WAAW,IAAI,EAAE,QAAQ,EAAE,WAAU;AAAA,UAExF,QAAQ,IAAI,CAAC,MAAM,MAAM;AACxB,kBAAM,YAAY,KAAK,YAAY;AACnC,kBAAM,OAAO,YAAY,KAAK,UAAU,KAAK;AAC7C,mBACE,qBAAC,MAAM,UAAN,EACE,UAAA;AAAA,cAAA,KAAK,aAAa,IAAI,KAAK,oBAAC,SAAI,MAAK,aAAY,WAAU,uDAAA,CAAuD;AAAA,cACnH,qBAAC,OAAA,EAAI,WAAU,qBAAoB,cAAY,GAC7C,UAAA;AAAA,gBAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,MAAM,YAAY,qBAAqB,KAAK,aAAa,SAAY,kBAAkB;AAAA,oBACvF,gBAAc,YAAY,KAAK,UAAU,KAAK,aAAa,SAAY,KAAK,WAAW;AAAA,oBACvF,UAAU,KAAK;AAAA,oBACf,UAAU;AAAA,oBACV,cAAc,MAAM,CAAC,KAAK,YAAY,eAAe,CAAC;AAAA,oBACtD,SAAS,MAAM,OAAO,IAAI;AAAA,oBAC1B,WAAW,2CAA2C,UAAU,MAAM,aAAa,KAAK,MAAM,CAAC;AAAA,oBAE9F,UAAA;AAAA,sBAAA,KAAK,QAAQ,oBAAC,QAAA,EAAK,WAAU,8BAA8B,eAAK,MAAK;AAAA,sBACtE,qBAAC,QAAA,EAAK,WAAU,kBACd,UAAA;AAAA,wBAAA,oBAAC,QAAA,EAAK,WAAW,kBAAkB,OAAO,kBAAkB,EAAE,IAAK,eAAK,MAAA,CAAM;AAAA,wBAC7E,KAAK,eAAe,oBAAC,UAAK,WAAU,iEAAiE,eAAK,YAAA,CAAY;AAAA,sBAAA,GACzH;AAAA,uBACE,aAAa,KAAK,aAAa,WAC/B,oBAAC,UAAK,WAAU,gBACb,UAAA,QAAQ,oBAAC,aAAU,MAAM,IAAI,aAAa,KAAK,WAAU,qCAAoC,EAAA,CAChG;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAGH,KAAK,UACJ;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,SAAQ;AAAA,oBACR,MAAK;AAAA,oBACL,MAAM,KAAK,OAAO;AAAA,oBAClB,cAAY,KAAK,OAAO;AAAA,oBACxB,YAAU,KAAK,OAAO;AAAA,oBACtB,UAAU;AAAA,oBACV,SAAS,KAAK,OAAO;AAAA,oBACrB,WAAU;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACZ,EAAA,CAEJ;AAAA,YAAA,EAAA,GApCmB,CAqCrB;AAAA,UAEJ,CAAC;AAAA,QAAA,EAAA,CACH;AAAA,MAAA,GACF;AAAA,MACA,mBAAmB,SAAS;AAAA,IAAA;AAAA,EAC9B,GACJ;AAEJ;"}
|
|
@@ -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,
|