@nextelco/common-ui 2.1.106 → 2.1.107
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 +201 -145
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/legacy/components/atoms/InputData/InputData.js +2 -13
- package/dist/esm/legacy/components/atoms/InputData/InputData.js.map +1 -1
- package/dist/esm/legacy/components/charts/Charts.js +147 -57
- package/dist/esm/legacy/components/charts/Charts.js.map +1 -1
- package/dist/esm/legacy/components/layout/Layout/Layout.js +21 -82
- package/dist/esm/legacy/components/layout/Layout/Layout.js.map +1 -1
- package/dist/esm/legacy/components/layout/Sidebar/Sidebar.js +29 -218
- package/dist/esm/legacy/components/layout/Sidebar/Sidebar.js.map +1 -1
- package/dist/esm/legacy/components/molecules/ColumnPicker/ColumnPicker.js +77 -10
- package/dist/esm/legacy/components/molecules/ColumnPicker/ColumnPicker.js.map +1 -1
- package/dist/esm/legacy/components/molecules/DataTable/DataTable.js +445 -337
- package/dist/esm/legacy/components/molecules/DataTable/DataTable.js.map +1 -1
- package/dist/esm/legacy/components/molecules/UserAvatar/UserAvatar.js +15 -97
- package/dist/esm/legacy/components/molecules/UserAvatar/UserAvatar.js.map +1 -1
- package/dist/esm/legacy/components/organisms/MapaPontos/MapaPontos.js +3 -3
- package/dist/esm/legacy/components/organisms/MapaPontos/MapaPontos.js.map +1 -1
- package/dist/esm/legacy/components/organisms/PainelFiltros/PainelFiltros.js +15 -3
- package/dist/esm/legacy/components/organisms/PainelFiltros/PainelFiltros.js.map +1 -1
- package/dist/esm/legacy/components/organisms/Selector/Selector.js +4 -4
- package/dist/esm/legacy/components/organisms/Selector/Selector.js.map +1 -1
- package/dist/esm/legacy/components/ui/Avisos.js +23 -76
- package/dist/esm/legacy/components/ui/Avisos.js.map +1 -1
- package/dist/esm/legacy/components/ui/CabecalhoPagina.js +14 -27
- package/dist/esm/legacy/components/ui/CabecalhoPagina.js.map +1 -1
- package/dist/esm/legacy/components/ui/CaixaPesquisa.js +3 -51
- package/dist/esm/legacy/components/ui/CaixaPesquisa.js.map +1 -1
- package/dist/esm/legacy/components/ui/Confirmacao.js +13 -31
- package/dist/esm/legacy/components/ui/Confirmacao.js.map +1 -1
- package/dist/esm/legacy/components/ui/Escolha.js +21 -137
- package/dist/esm/legacy/components/ui/Escolha.js.map +1 -1
- package/dist/esm/legacy/components/ui/FaixaAviso.js +13 -11
- package/dist/esm/legacy/components/ui/FaixaAviso.js.map +1 -1
- package/dist/esm/legacy/components/ui/Separadores.js +11 -46
- package/dist/esm/legacy/components/ui/Separadores.js.map +1 -1
- package/dist/esm/legacy/components/ui/Ui.js +18 -115
- package/dist/esm/legacy/components/ui/Ui.js.map +1 -1
- package/dist/esm/legacy/components/ui/painelFlutuante.js +5 -44
- package/dist/esm/legacy/components/ui/painelFlutuante.js.map +1 -1
- package/dist/esm/v1/capabilities/overlay/useFloatingPanel.js +52 -0
- package/dist/esm/v1/capabilities/overlay/useFloatingPanel.js.map +1 -0
- package/dist/esm/v1/capabilities/theme/useIsDark.js +15 -0
- package/dist/esm/v1/capabilities/theme/useIsDark.js.map +1 -0
- package/dist/esm/v1/capabilities/theme/useTheme.js +66 -0
- package/dist/esm/v1/capabilities/theme/useTheme.js.map +1 -0
- package/dist/esm/v1/components/data/Pagination/Pagination.js +66 -0
- package/dist/esm/v1/components/data/Pagination/Pagination.js.map +1 -0
- package/dist/esm/v1/components/feedback/Toast/Toast.js +105 -0
- package/dist/esm/v1/components/feedback/Toast/Toast.js.map +1 -0
- package/dist/esm/v1/components/layout/AppShell/AppShell.js +89 -0
- package/dist/esm/v1/components/layout/AppShell/AppShell.js.map +1 -0
- package/dist/esm/v1/components/layout/Page/Page.js +16 -0
- package/dist/esm/v1/components/layout/Page/Page.js.map +1 -0
- package/dist/esm/v1/components/layout/PageHeader/PageHeader.js +26 -0
- package/dist/esm/v1/components/layout/PageHeader/PageHeader.js.map +1 -0
- package/dist/esm/v1/components/layout/SideNav/SideNav.js +277 -0
- package/dist/esm/v1/components/layout/SideNav/SideNav.js.map +1 -0
- package/dist/esm/v1/components/layout/navTrail.js +19 -0
- package/dist/esm/v1/components/layout/navTrail.js.map +1 -0
- package/dist/esm/v1/components/overlays/ConfirmDialog/ConfirmDialog.js +95 -0
- package/dist/esm/v1/components/overlays/ConfirmDialog/ConfirmDialog.js.map +1 -0
- package/dist/esm/v1/components/overlays/Dialog/Dialog.js.map +1 -1
- package/dist/esm/v1/components/overlays/Tooltip/Tooltip.js +98 -0
- package/dist/esm/v1/components/overlays/Tooltip/Tooltip.js.map +1 -0
- package/dist/esm/v1/components/overlays/Tooltip/TooltipLayer.js +84 -0
- package/dist/esm/v1/components/overlays/Tooltip/TooltipLayer.js.map +1 -0
- package/dist/esm/v1/components/overlays/Tooltip/TooltipPanel.js +33 -0
- package/dist/esm/v1/components/overlays/Tooltip/TooltipPanel.js.map +1 -0
- package/dist/esm/v1/components/overlays/topLayer.js +28 -0
- package/dist/esm/v1/components/overlays/topLayer.js.map +1 -0
- package/dist/esm/v1/foundations/icons/icons.js +61 -2
- package/dist/esm/v1/foundations/icons/icons.js.map +1 -1
- package/dist/esm/v1/primitives/buttons/Button/Button.js +18 -4
- package/dist/esm/v1/primitives/buttons/Button/Button.js.map +1 -1
- package/dist/esm/v1/primitives/buttons/SegmentedControl/SegmentedControl.js +65 -0
- package/dist/esm/v1/primitives/buttons/SegmentedControl/SegmentedControl.js.map +1 -0
- package/dist/esm/v1/primitives/buttons/SegmentedControl/segmentedStyles.js +10 -0
- package/dist/esm/v1/primitives/buttons/SegmentedControl/segmentedStyles.js.map +1 -0
- package/dist/esm/v1/primitives/display/Avatar/Avatar.js +120 -0
- package/dist/esm/v1/primitives/display/Avatar/Avatar.js.map +1 -0
- package/dist/esm/v1/primitives/display/Badge/Badge.js +23 -0
- package/dist/esm/v1/primitives/display/Badge/Badge.js.map +1 -0
- package/dist/esm/v1/primitives/display/Card/Card.js +22 -0
- package/dist/esm/v1/primitives/display/Card/Card.js.map +1 -0
- package/dist/esm/v1/primitives/display/FilterChips/FilterChips.js +45 -0
- package/dist/esm/v1/primitives/display/FilterChips/FilterChips.js.map +1 -0
- package/dist/esm/v1/primitives/display/Kpi/Kpi.js +103 -0
- package/dist/esm/v1/primitives/display/Kpi/Kpi.js.map +1 -0
- package/dist/esm/v1/primitives/display/Notice/Notice.js +71 -0
- package/dist/esm/v1/primitives/display/Notice/Notice.js.map +1 -0
- package/dist/esm/v1/primitives/display/Person/Person.js +14 -0
- package/dist/esm/v1/primitives/display/Person/Person.js.map +1 -0
- package/dist/esm/v1/primitives/forms/Checkbox/Checkbox.js +1 -1
- package/dist/esm/v1/primitives/forms/Checkbox/Checkbox.js.map +1 -1
- package/dist/esm/v1/primitives/forms/DateInput/DateInput.js +150 -0
- package/dist/esm/v1/primitives/forms/DateInput/DateInput.js.map +1 -0
- package/dist/esm/v1/primitives/forms/SearchInput/SearchInput.js +43 -0
- package/dist/esm/v1/primitives/forms/SearchInput/SearchInput.js.map +1 -0
- package/dist/esm/v1/primitives/forms/SelectInput/SelectInput.js +190 -12
- package/dist/esm/v1/primitives/forms/SelectInput/SelectInput.js.map +1 -1
- package/dist/esm/v1/primitives/forms/field.js +4 -2
- package/dist/esm/v1/primitives/forms/field.js.map +1 -1
- package/dist/esm/v1/primitives/navigation/Tabs/Tabs.js +96 -0
- package/dist/esm/v1/primitives/navigation/Tabs/Tabs.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/tailwind.css +24 -0
- package/dist/theme-boot.js +1 -0
- package/dist/theme.css +10 -3
- package/dist/tokens.css +119 -0
- package/dist/types/legacy/components/atoms/InputData/InputData.d.ts +4 -1
- package/dist/types/legacy/components/charts/Charts.d.ts +58 -5
- package/dist/types/legacy/components/layout/Layout/Layout.d.ts +7 -20
- package/dist/types/legacy/components/layout/Sidebar/Sidebar.d.ts +13 -26
- package/dist/types/legacy/components/molecules/ColumnPicker/ColumnPicker.d.ts +56 -3
- package/dist/types/legacy/components/molecules/DataTable/DataTable.d.ts +72 -7
- package/dist/types/legacy/components/molecules/UserAvatar/UserAvatar.d.ts +4 -5
- package/dist/types/legacy/components/ui/Avisos.d.ts +6 -16
- package/dist/types/legacy/components/ui/CabecalhoPagina.d.ts +6 -20
- package/dist/types/legacy/components/ui/CaixaPesquisa.d.ts +2 -4
- package/dist/types/legacy/components/ui/Confirmacao.d.ts +3 -10
- package/dist/types/legacy/components/ui/Escolha.d.ts +5 -15
- package/dist/types/legacy/components/ui/FaixaAviso.d.ts +2 -6
- package/dist/types/legacy/components/ui/Separadores.d.ts +3 -10
- package/dist/types/legacy/components/ui/Ui.d.ts +12 -54
- package/dist/types/legacy/components/ui/painelFlutuante.d.ts +6 -10
- package/dist/types/legacy/exports/atoms.d.ts +1 -1
- package/dist/types/legacy/exports/charts.d.ts +2 -2
- package/dist/types/legacy/exports/hooks.d.ts +2 -2
- package/dist/types/legacy/exports/molecules.d.ts +2 -2
- package/dist/types/v1/capabilities/overlay/useFloatingPanel.d.ts +20 -0
- package/dist/types/v1/capabilities/theme/useIsDark.d.ts +10 -0
- package/dist/types/v1/capabilities/theme/useTheme.d.ts +29 -0
- package/dist/types/v1/components/data/Pagination/Pagination.d.ts +33 -0
- package/dist/types/v1/components/feedback/Toast/Toast.d.ts +51 -0
- package/dist/types/v1/components/layout/AppShell/AppShell.d.ts +35 -0
- package/dist/types/v1/components/layout/Page/Page.d.ts +23 -0
- package/dist/types/v1/components/layout/PageHeader/PageHeader.d.ts +35 -0
- package/dist/types/v1/components/layout/SideNav/SideNav.d.ts +92 -0
- package/dist/types/v1/components/layout/navTrail.d.ts +15 -0
- package/dist/types/v1/components/overlays/ConfirmDialog/ConfirmDialog.d.ts +59 -0
- package/dist/types/v1/components/overlays/Dialog/Dialog.d.ts +3 -2
- package/dist/types/v1/components/overlays/Tooltip/Tooltip.d.ts +34 -0
- package/dist/types/v1/components/overlays/Tooltip/TooltipLayer.d.ts +18 -0
- package/dist/types/v1/components/overlays/Tooltip/TooltipPanel.d.ts +23 -0
- package/dist/types/v1/components/overlays/topLayer.d.ts +23 -0
- package/dist/types/v1/foundations/icons/icons.d.ts +20 -0
- package/dist/types/v1/index.d.ts +43 -1
- package/dist/types/v1/primitives/buttons/Button/Button.d.ts +20 -5
- package/dist/types/v1/primitives/buttons/SegmentedControl/SegmentedControl.d.ts +28 -0
- package/dist/types/v1/primitives/buttons/SegmentedControl/segmentedStyles.d.ts +16 -0
- package/dist/types/v1/primitives/display/Avatar/Avatar.d.ts +30 -0
- package/dist/types/v1/primitives/display/Badge/Badge.d.ts +25 -0
- package/dist/types/v1/primitives/display/Card/Card.d.ts +22 -0
- package/dist/types/v1/primitives/display/FilterChips/FilterChips.d.ts +33 -0
- package/dist/types/v1/primitives/display/Kpi/Kpi.d.ts +68 -0
- package/dist/types/v1/primitives/display/Notice/Notice.d.ts +29 -0
- package/dist/types/v1/primitives/display/Person/Person.d.ts +15 -0
- package/dist/types/v1/primitives/forms/DateInput/DateInput.d.ts +43 -0
- package/dist/types/v1/primitives/forms/SearchInput/SearchInput.d.ts +23 -0
- package/dist/types/v1/primitives/forms/SelectInput/SelectInput.d.ts +60 -12
- package/dist/types/v1/primitives/forms/field.d.ts +2 -0
- package/dist/types/v1/primitives/navigation/Tabs/Tabs.d.ts +58 -0
- package/package.json +3 -3
- package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.css +0 -17
- package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.js +0 -41
- package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.js.map +0 -1
- package/dist/esm/legacy/components/molecules/Search/Search.css +0 -18
- package/dist/esm/legacy/components/molecules/Search/Search.js +0 -30
- package/dist/esm/legacy/components/molecules/Search/Search.js.map +0 -1
- package/dist/esm/legacy/hooks/useTheme.js +0 -39
- package/dist/esm/legacy/hooks/useTheme.js.map +0 -1
- package/dist/types/legacy/components/atoms/Tooltip/Tooltip.d.ts +0 -13
- package/dist/types/legacy/components/molecules/Search/Search.d.ts +0 -7
- package/dist/types/legacy/hooks/useTheme.d.ts +0 -17
|
@@ -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/** 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/** 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/** 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":"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"}
|
|
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/** 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":"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"}
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
const VARIANTS = {
|
|
4
|
-
primary: "
|
|
5
|
-
secondary: "
|
|
4
|
+
primary: "border-primary bg-primary text-primary-foreground hover:border-proef-blue hover:bg-proef-blue dark:border-proef-blue dark:bg-proef-blue dark:hover:bg-sky-500",
|
|
5
|
+
secondary: "border-border bg-card text-muted-foreground hover:border-primary hover:text-primary dark:hover:border-foreground dark:hover:text-foreground",
|
|
6
|
+
active: "border-primary bg-primary text-primary-foreground dark:border-proef-blue dark:bg-proef-blue",
|
|
7
|
+
success: "border-ok bg-ok text-white hover:opacity-90 dark:border-emerald-600 dark:bg-emerald-600",
|
|
8
|
+
danger: "border-incumprido bg-incumprido text-white hover:opacity-90 dark:border-red-600 dark:bg-red-600",
|
|
9
|
+
ghost: "border-transparent bg-transparent text-muted-foreground hover:text-primary dark:hover:text-foreground",
|
|
10
|
+
inverse: "border-white/30 bg-white/10 text-white hover:border-white/60 hover:bg-white/20",
|
|
11
|
+
accent: "border-proef-turquoise bg-proef-turquoise text-proef-navy hover:opacity-90"
|
|
6
12
|
};
|
|
7
|
-
const
|
|
13
|
+
const SIZES = {
|
|
14
|
+
md: { box: "h-control text-[11px]", text: "px-3.5", icon: "w-control px-0" },
|
|
15
|
+
sm: { box: "h-7 text-[10px]", text: "px-2.5", icon: "w-7 px-0" }
|
|
16
|
+
};
|
|
17
|
+
const Button = forwardRef(function Button2({ variant = "primary", size = "md", active, icon, loading, disabled, type = "button", className = "", children, ...props }, ref) {
|
|
18
|
+
const look = variant === "secondary" && active ? VARIANTS.active : VARIANTS[variant];
|
|
19
|
+
const iconOnly = children === void 0 || children === null || children === false;
|
|
20
|
+
const dims = SIZES[size];
|
|
8
21
|
return /* @__PURE__ */ jsxs(
|
|
9
22
|
"button",
|
|
10
23
|
{
|
|
@@ -12,7 +25,8 @@ const Button = forwardRef(function Button2({ variant = "primary", icon, loading,
|
|
|
12
25
|
type,
|
|
13
26
|
disabled: disabled || loading,
|
|
14
27
|
"aria-busy": loading || void 0,
|
|
15
|
-
|
|
28
|
+
"aria-pressed": active === void 0 ? void 0 : active,
|
|
29
|
+
className: `inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-lg border font-black tracking-widest whitespace-nowrap uppercase transition-colors duration-150 ${dims.box} ${iconOnly ? dims.icon : dims.text} focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 ${look} ${className}`,
|
|
16
30
|
...props,
|
|
17
31
|
children: [
|
|
18
32
|
loading ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "inline-block h-[13px] w-[13px] animate-spin rounded-full border-2 border-current border-t-transparent opacity-80" }) : icon,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sources":["../../../../../../src/v1/primitives/buttons/Button/Button.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\r\n\r\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n
|
|
1
|
+
{"version":3,"file":"Button.js","sources":["../../../../../../src/v1/primitives/buttons/Button/Button.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\r\n\r\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n /**\r\n * `primary`: a ação principal (navy, uma por ecrã). `secondary` (contorno): as\r\n * outras (ex: Fechar, Exportar). `success` (verde): aprovar, aceitar, concluir.\r\n * `danger`: apaga ou não se pode desfazer (ex: Apagar). `ghost`: sem contorno,\r\n * para ações discretas.\r\n *\r\n * Sobre fundo escuro (ex: uma barra navy): `inverse` (contorno branco) para as\r\n * ações normais e `accent` (turquesa) para a principal.\r\n */\r\n variant?: 'primary' | 'secondary' | 'success' | 'danger' | 'ghost' | 'inverse' | 'accent'\r\n /** `sm`: mais pequeno (28px), para ícones dentro de linhas de tabelas e cartões. */\r\n size?: 'md' | 'sm'\r\n /** Ligado (ex: um filtro ativo): o `secondary` fica navy. Dá `aria-pressed`. */\r\n active?: boolean\r\n /** Ícone antes do texto (ex: `<CheckIcon size={13} />`). Sem texto, o botão fica quadrado (dar `aria-label`). */\r\n icon?: React.ReactNode\r\n /** A guardar/enviar: mostra uma roda no lugar do ícone e fica desativado. */\r\n loading?: boolean\r\n}\r\n\r\nconst VARIANTS = {\r\n primary: 'border-primary bg-primary text-primary-foreground hover:border-proef-blue hover:bg-proef-blue dark:border-proef-blue dark:bg-proef-blue dark:hover:bg-sky-500',\r\n secondary: 'border-border bg-card text-muted-foreground hover:border-primary hover:text-primary dark:hover:border-foreground dark:hover:text-foreground',\r\n active: 'border-primary bg-primary text-primary-foreground dark:border-proef-blue dark:bg-proef-blue',\r\n success: 'border-ok bg-ok text-white hover:opacity-90 dark:border-emerald-600 dark:bg-emerald-600',\r\n danger: 'border-incumprido bg-incumprido text-white hover:opacity-90 dark:border-red-600 dark:bg-red-600',\r\n ghost: 'border-transparent bg-transparent text-muted-foreground hover:text-primary dark:hover:text-foreground',\r\n inverse: 'border-white/30 bg-white/10 text-white hover:border-white/60 hover:bg-white/20',\r\n accent: 'border-proef-turquoise bg-proef-turquoise text-proef-navy hover:opacity-90',\r\n}\r\n\r\nconst SIZES = {\r\n md: { box: 'h-control text-[11px]', text: 'px-3.5', icon: 'w-control px-0' },\r\n sm: { box: 'h-7 text-[10px]', text: 'px-2.5', icon: 'w-7 px-0' },\r\n}\r\n\r\n/**\r\n * Botão de ação (ex: Confirmar, Novo projeto). Por omissão não submete\r\n * formulários (`type=\"button\"`); para submeter, passar `type=\"submit\"`.\r\n *\r\n * O aspeto dos portais proef: MAIÚSCULAS, letra grossa e espaçada, a mesma\r\n * altura dos outros controlos (32px).\r\n *\r\n * **Aceita os atributos HTML do [<button>](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/button)**, com o mesmo comportamento: `onClick`, `disabled`, `type`, `name`, `form`, `ref`, ...\r\n * Só os próprios do V1 aparecem na tabela abaixo.\r\n *\r\n * **Onde aparece:** no rodapé de um [Dialog](?path=/docs/v1-components-overlays-dialog--docs) (ver [Formulário em modal](?path=/docs/v1-patterns-forms-formulário-em-modal--docs)).\r\n */\r\nconst Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(\r\n { variant = 'primary', size = 'md', active, icon, loading, disabled, type = 'button', className = '', children, ...props },\r\n ref,\r\n) {\r\n const look = variant === 'secondary' && active ? VARIANTS.active : VARIANTS[variant]\r\n const iconOnly = children === undefined || children === null || children === false\r\n const dims = SIZES[size]\r\n return (\r\n <button\r\n ref={ref}\r\n type={type}\r\n disabled={disabled || loading}\r\n aria-busy={loading || undefined}\r\n aria-pressed={active === undefined ? undefined : active}\r\n className={\r\n `inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-lg border font-black tracking-widest whitespace-nowrap uppercase transition-colors duration-150 ${dims.box} ${iconOnly ? dims.icon : dims.text} ` +\r\n 'focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:outline-none ' +\r\n // aria-disabled: parece desativado mas continua clicável (ex: Guardar que, ao\r\n // clicar, explica o que falta preencher).\r\n `disabled:cursor-not-allowed disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 ${look} ${className}`\r\n }\r\n {...props}\r\n >\r\n {loading ? (\r\n <span aria-hidden className=\"inline-block h-[13px] w-[13px] animate-spin rounded-full border-2 border-current border-t-transparent opacity-80\" />\r\n ) : (\r\n icon\r\n )}\r\n {children}\r\n </button>\r\n )\r\n})\r\n\r\nexport default Button\r\n"],"names":["Button"],"mappings":";;AAuBA,MAAM,WAAW;AAAA,EACf,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AACV;AAEA,MAAM,QAAQ;AAAA,EACZ,IAAI,EAAE,KAAK,yBAAyB,MAAM,UAAU,MAAM,iBAAA;AAAA,EAC1D,IAAI,EAAE,KAAK,mBAAmB,MAAM,UAAU,MAAM,WAAA;AACtD;AAcA,MAAM,SAAS,WAA2C,SAASA,QACjE,EAAE,UAAU,WAAW,OAAO,MAAM,QAAQ,MAAM,SAAS,UAAU,OAAO,UAAU,YAAY,IAAI,UAAU,GAAG,MAAA,GACnH,KACA;AACA,QAAM,OAAO,YAAY,eAAe,SAAS,SAAS,SAAS,SAAS,OAAO;AACnF,QAAM,WAAW,aAAa,UAAa,aAAa,QAAQ,aAAa;AAC7E,QAAM,OAAO,MAAM,IAAI;AACvB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,UAAU,YAAY;AAAA,MACtB,aAAW,WAAW;AAAA,MACtB,gBAAc,WAAW,SAAY,SAAY;AAAA,MACjD,WACE,0KAA0K,KAAK,GAAG,IAAI,WAAW,KAAK,OAAO,KAAK,IAAI,4LAIzG,IAAI,IAAI,SAAS;AAAA,MAE/H,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA,8BACE,QAAA,EAAK,eAAW,MAAC,WAAU,oHAAmH,IAE/I;AAAA,QAED;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef } from "react";
|
|
3
|
+
import { SEGMENTED } from "./segmentedStyles.js";
|
|
4
|
+
function SegmentedControl({
|
|
5
|
+
value,
|
|
6
|
+
options,
|
|
7
|
+
onChange,
|
|
8
|
+
label,
|
|
9
|
+
ariaLabel,
|
|
10
|
+
className = ""
|
|
11
|
+
}) {
|
|
12
|
+
const refs = useRef([]);
|
|
13
|
+
const move = (from, step) => {
|
|
14
|
+
const n = options.length;
|
|
15
|
+
for (let i = 1; i <= n; i++) {
|
|
16
|
+
const next = ((from + step * i) % n + n) % n;
|
|
17
|
+
if (!options[next].disabled) {
|
|
18
|
+
onChange(options[next].value);
|
|
19
|
+
refs.current[next]?.focus();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const onKeyDown = (e, index) => {
|
|
25
|
+
if (e.key === "ArrowRight" || e.key === "ArrowDown") move(index, 1);
|
|
26
|
+
else if (e.key === "ArrowLeft" || e.key === "ArrowUp") move(index, -1);
|
|
27
|
+
else return;
|
|
28
|
+
e.preventDefault();
|
|
29
|
+
};
|
|
30
|
+
const focusIndex = Math.max(
|
|
31
|
+
0,
|
|
32
|
+
options.findIndex((o) => o.value === value)
|
|
33
|
+
);
|
|
34
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex flex-wrap items-center gap-3 ${className}`, children: [
|
|
35
|
+
label && /* @__PURE__ */ jsx("span", { className: "text-[10px] font-black tracking-wider whitespace-nowrap text-muted-foreground uppercase", children: label }),
|
|
36
|
+
/* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": label ?? ariaLabel, className: SEGMENTED.list, children: options.map((o, i) => {
|
|
37
|
+
const active = o.value === value;
|
|
38
|
+
return /* @__PURE__ */ jsxs(
|
|
39
|
+
"button",
|
|
40
|
+
{
|
|
41
|
+
ref: (el) => {
|
|
42
|
+
refs.current[i] = el;
|
|
43
|
+
},
|
|
44
|
+
type: "button",
|
|
45
|
+
role: "radio",
|
|
46
|
+
"aria-checked": active,
|
|
47
|
+
tabIndex: i === focusIndex ? 0 : -1,
|
|
48
|
+
disabled: o.disabled,
|
|
49
|
+
onClick: () => onChange(o.value),
|
|
50
|
+
onKeyDown: (e) => onKeyDown(e, i),
|
|
51
|
+
className: `${SEGMENTED.item} ${active ? SEGMENTED.active : SEGMENTED.idle}`,
|
|
52
|
+
children: [
|
|
53
|
+
o.icon,
|
|
54
|
+
o.label
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
o.value
|
|
58
|
+
);
|
|
59
|
+
}) })
|
|
60
|
+
] });
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
SegmentedControl as default
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=SegmentedControl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedControl.js","sources":["../../../../../../src/v1/primitives/buttons/SegmentedControl/SegmentedControl.tsx"],"sourcesContent":["import React, { useRef } from 'react'\r\nimport { SEGMENTED } from './segmentedStyles'\r\n\r\nexport interface SegmentedOption<V extends string = string> {\r\n value: V\r\n label: React.ReactNode\r\n /** Ícone antes do texto (ex: um ícone do lucide com `size={12}`). */\r\n icon?: React.ReactNode\r\n disabled?: boolean\r\n}\r\n\r\nexport interface SegmentedControlProps<V extends string = string> {\r\n /** A opção escolhida. A app guarda este estado. */\r\n value: V\r\n options: SegmentedOption<V>[]\r\n onChange: (value: V) => void\r\n /** Rótulo visível à esquerda (ex: \"Situação\"). Também é o nome do grupo para leitores de ecrã. */\r\n label?: string\r\n /** Nome do grupo para leitores de ecrã, quando não há `label` visível. */\r\n ariaLabel?: string\r\n className?: string\r\n}\r\n\r\n/**\r\n * Escolha de uma opção entre poucas, em botões lado a lado (ex: Dia · Semana ·\r\n * Mês, ou Todos · Atribuição · Devolução). Para filtros e modos de vista numa\r\n * barra; para trocar de vista com conteúdo próprio, usar `Tabs`.\r\n *\r\n * Mesmo aspeto dos `Tabs` segmentados: botões juntos numa caixa, o escolhido\r\n * a navy. Setas ← → mudam de opção.\r\n */\r\nexport default function SegmentedControl<V extends string = string>({\r\n value,\r\n options,\r\n onChange,\r\n label,\r\n ariaLabel,\r\n className = '',\r\n}: SegmentedControlProps<V>) {\r\n const refs = useRef<(HTMLButtonElement | null)[]>([])\r\n\r\n const move = (from: number, step: number) => {\r\n const n = options.length\r\n for (let i = 1; i <= n; i++) {\r\n const next = (((from + step * i) % n) + n) % n\r\n if (!options[next].disabled) {\r\n onChange(options[next].value)\r\n refs.current[next]?.focus()\r\n return\r\n }\r\n }\r\n }\r\n\r\n const onKeyDown = (e: React.KeyboardEvent, index: number) => {\r\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') move(index, 1)\r\n else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') move(index, -1)\r\n else return\r\n e.preventDefault()\r\n }\r\n\r\n const focusIndex = Math.max(\r\n 0,\r\n options.findIndex((o) => o.value === value),\r\n )\r\n\r\n return (\r\n <div className={`flex flex-wrap items-center gap-3 ${className}`}>\r\n {label && <span className=\"text-[10px] font-black tracking-wider whitespace-nowrap text-muted-foreground uppercase\">{label}</span>}\r\n <div role=\"radiogroup\" aria-label={label ?? ariaLabel} className={SEGMENTED.list}>\r\n {options.map((o, i) => {\r\n const active = o.value === value\r\n return (\r\n <button\r\n key={o.value}\r\n ref={(el) => {\r\n refs.current[i] = el\r\n }}\r\n type=\"button\"\r\n role=\"radio\"\r\n aria-checked={active}\r\n tabIndex={i === focusIndex ? 0 : -1}\r\n disabled={o.disabled}\r\n onClick={() => onChange(o.value)}\r\n onKeyDown={(e) => onKeyDown(e, i)}\r\n className={`${SEGMENTED.item} ${active ? SEGMENTED.active : SEGMENTED.idle}`}\r\n >\r\n {o.icon}\r\n {o.label}\r\n </button>\r\n )\r\n })}\r\n </div>\r\n </div>\r\n )\r\n}\r\n"],"names":[],"mappings":";;;AA+BA,SAAwB,iBAA4C;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AACd,GAA6B;AAC3B,QAAM,OAAO,OAAqC,EAAE;AAEpD,QAAM,OAAO,CAAC,MAAc,SAAiB;AAC3C,UAAM,IAAI,QAAQ;AAClB,aAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,YAAM,SAAU,OAAO,OAAO,KAAK,IAAK,KAAK;AAC7C,UAAI,CAAC,QAAQ,IAAI,EAAE,UAAU;AAC3B,iBAAS,QAAQ,IAAI,EAAE,KAAK;AAC5B,aAAK,QAAQ,IAAI,GAAG,MAAA;AACpB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,CAAC,GAAwB,UAAkB;AAC3D,QAAI,EAAE,QAAQ,gBAAgB,EAAE,QAAQ,YAAa,MAAK,OAAO,CAAC;AAAA,aACzD,EAAE,QAAQ,eAAe,EAAE,QAAQ,UAAW,MAAK,OAAO,EAAE;AAAA,QAChE;AACL,MAAE,eAAA;AAAA,EACJ;AAEA,QAAM,aAAa,KAAK;AAAA,IACtB;AAAA,IACA,QAAQ,UAAU,CAAC,MAAM,EAAE,UAAU,KAAK;AAAA,EAAA;AAG5C,SACE,qBAAC,OAAA,EAAI,WAAW,qCAAqC,SAAS,IAC3D,UAAA;AAAA,IAAA,SAAS,oBAAC,QAAA,EAAK,WAAU,2FAA2F,UAAA,OAAM;AAAA,IAC3H,oBAAC,OAAA,EAAI,MAAK,cAAa,cAAY,SAAS,WAAW,WAAW,UAAU,MACzE,UAAA,QAAQ,IAAI,CAAC,GAAG,MAAM;AACrB,YAAM,SAAS,EAAE,UAAU;AAC3B,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,KAAK,CAAC,OAAO;AACX,iBAAK,QAAQ,CAAC,IAAI;AAAA,UACpB;AAAA,UACA,MAAK;AAAA,UACL,MAAK;AAAA,UACL,gBAAc;AAAA,UACd,UAAU,MAAM,aAAa,IAAI;AAAA,UACjC,UAAU,EAAE;AAAA,UACZ,SAAS,MAAM,SAAS,EAAE,KAAK;AAAA,UAC/B,WAAW,CAAC,MAAM,UAAU,GAAG,CAAC;AAAA,UAChC,WAAW,GAAG,UAAU,IAAI,IAAI,SAAS,UAAU,SAAS,UAAU,IAAI;AAAA,UAEzE,UAAA;AAAA,YAAA,EAAE;AAAA,YACF,EAAE;AAAA,UAAA;AAAA,QAAA;AAAA,QAdE,EAAE;AAAA,MAAA;AAAA,IAiBb,CAAC,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const SEGMENTED = {
|
|
2
|
+
list: "inline-flex max-w-full min-h-control flex-wrap items-center gap-0.5 rounded-lg border border-border bg-card p-0.5 dark:border-slate-600 dark:bg-slate-900",
|
|
3
|
+
item: "inline-flex h-[26px] cursor-pointer items-center justify-center gap-1.5 rounded-md border-0 px-3 text-[11px] font-black tracking-widest whitespace-nowrap uppercase transition-colors focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-40",
|
|
4
|
+
active: "bg-primary text-primary-foreground dark:bg-proef-blue dark:text-white",
|
|
5
|
+
idle: "bg-transparent text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
6
|
+
};
|
|
7
|
+
export {
|
|
8
|
+
SEGMENTED
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=segmentedStyles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segmentedStyles.js","sources":["../../../../../../src/v1/primitives/buttons/SegmentedControl/segmentedStyles.ts"],"sourcesContent":["/**\r\n * Aspeto \"segmentado\": botões juntos numa caixa, o escolhido a navy.\r\n *\r\n * Partilhado pelo `SegmentedControl` (escolher um valor, ex: 7D · 30D) e pelos\r\n * `Tabs` com `variant=\"segmented\"` (trocar de vista): fazem coisas diferentes\r\n * mas têm de parecer o mesmo controlo.\r\n *\r\n * A caixa tem a altura dos outros controlos (`--spacing-control`), para ficar\r\n * alinhada com botões, pesquisa e campos na mesma barra.\r\n */\r\nexport const SEGMENTED = {\r\n list: 'inline-flex max-w-full min-h-control flex-wrap items-center gap-0.5 rounded-lg border border-border bg-card p-0.5 dark:border-slate-600 dark:bg-slate-900',\r\n item:\r\n 'inline-flex h-[26px] cursor-pointer items-center justify-center gap-1.5 rounded-md border-0 px-3 text-[11px] font-black tracking-widest whitespace-nowrap uppercase transition-colors ' +\r\n 'focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-40',\r\n active: 'bg-primary text-primary-foreground dark:bg-proef-blue dark:text-white',\r\n idle: 'bg-transparent text-muted-foreground hover:bg-muted hover:text-foreground',\r\n}\r\n"],"names":[],"mappings":"AAUO,MAAM,YAAY;AAAA,EACvB,MAAM;AAAA,EACN,MACE;AAAA,EAEF,QAAQ;AAAA,EACR,MAAM;AACR;"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState, useEffect } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
4
|
+
function initials(fullName) {
|
|
5
|
+
const parts = (fullName ?? "").trim().split(/\s+/).filter(Boolean);
|
|
6
|
+
if (parts.length === 0) return "?";
|
|
7
|
+
const first = parts[0].charAt(0);
|
|
8
|
+
const last = parts.length > 1 ? parts[parts.length - 1].charAt(0) : "";
|
|
9
|
+
return (first + last).toUpperCase();
|
|
10
|
+
}
|
|
11
|
+
const SIZES = {
|
|
12
|
+
none: "",
|
|
13
|
+
sm: "h-6 w-6 text-[9px]",
|
|
14
|
+
md: "h-7 w-7 text-[10px]",
|
|
15
|
+
lg: "h-8 w-8 text-[11px]"
|
|
16
|
+
};
|
|
17
|
+
const INITIALS = "rounded-full bg-gradient-to-br from-sky-400 to-sky-600 font-black text-white";
|
|
18
|
+
function Avatar({
|
|
19
|
+
name,
|
|
20
|
+
photo,
|
|
21
|
+
photoLarge,
|
|
22
|
+
email,
|
|
23
|
+
company,
|
|
24
|
+
department,
|
|
25
|
+
jobTitle,
|
|
26
|
+
size = "sm",
|
|
27
|
+
card = true,
|
|
28
|
+
className = ""
|
|
29
|
+
}) {
|
|
30
|
+
const ref = useRef(null);
|
|
31
|
+
const [pos, setPos] = useState(null);
|
|
32
|
+
const [pinned, setPinned] = useState(false);
|
|
33
|
+
const [failed, setFailed] = useState(false);
|
|
34
|
+
const pointer = useRef("mouse");
|
|
35
|
+
const large = photoLarge ?? photo;
|
|
36
|
+
useEffect(() => setFailed(false), [photo]);
|
|
37
|
+
const open = () => {
|
|
38
|
+
if (!card || !ref.current) return;
|
|
39
|
+
const r = ref.current.getBoundingClientRect();
|
|
40
|
+
const W = 200;
|
|
41
|
+
const H = email || company || jobTitle || department ? 280 : 196;
|
|
42
|
+
let left = r.right + 10;
|
|
43
|
+
let top = r.top + r.height / 2 - H / 2;
|
|
44
|
+
if (left + W > window.innerWidth - 8) left = r.left - W - 10;
|
|
45
|
+
if (top + H > window.innerHeight - 8) top = window.innerHeight - H - 8;
|
|
46
|
+
if (top < 8) top = 8;
|
|
47
|
+
setPos({ top, left });
|
|
48
|
+
};
|
|
49
|
+
const close = () => {
|
|
50
|
+
setPos(null);
|
|
51
|
+
setPinned(false);
|
|
52
|
+
};
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (!pinned) return;
|
|
55
|
+
const dismiss = (e) => {
|
|
56
|
+
if (e.type === "pointerdown" && ref.current?.contains(e.target)) return;
|
|
57
|
+
close();
|
|
58
|
+
};
|
|
59
|
+
document.addEventListener("pointerdown", dismiss);
|
|
60
|
+
window.addEventListener("scroll", dismiss, true);
|
|
61
|
+
window.addEventListener("resize", dismiss);
|
|
62
|
+
return () => {
|
|
63
|
+
document.removeEventListener("pointerdown", dismiss);
|
|
64
|
+
window.removeEventListener("scroll", dismiss, true);
|
|
65
|
+
window.removeEventListener("resize", dismiss);
|
|
66
|
+
};
|
|
67
|
+
}, [pinned]);
|
|
68
|
+
const showPhoto = !!photo && !failed;
|
|
69
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
70
|
+
/* @__PURE__ */ jsx(
|
|
71
|
+
"span",
|
|
72
|
+
{
|
|
73
|
+
ref,
|
|
74
|
+
className: `inline-flex shrink-0 items-center justify-center overflow-hidden ${SIZES[size]} ${showPhoto ? "rounded-full" : size === "none" ? "" : INITIALS} ${card ? "cursor-pointer" : ""} ${className}`,
|
|
75
|
+
onPointerEnter: (e) => e.pointerType === "mouse" && open(),
|
|
76
|
+
onPointerLeave: (e) => e.pointerType === "mouse" && !pinned && close(),
|
|
77
|
+
onPointerDown: (e) => {
|
|
78
|
+
pointer.current = e.pointerType;
|
|
79
|
+
},
|
|
80
|
+
onClick: (e) => {
|
|
81
|
+
if (!card || pointer.current === "mouse") return;
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
e.stopPropagation();
|
|
84
|
+
if (pinned) return close();
|
|
85
|
+
open();
|
|
86
|
+
setPinned(true);
|
|
87
|
+
},
|
|
88
|
+
children: showPhoto ? /* @__PURE__ */ jsx("img", { src: photo, alt: name ?? "", className: "h-full w-full object-cover", onError: () => setFailed(true) }) : initials(name)
|
|
89
|
+
}
|
|
90
|
+
),
|
|
91
|
+
pos && createPortal(
|
|
92
|
+
/* @__PURE__ */ jsxs(
|
|
93
|
+
"div",
|
|
94
|
+
{
|
|
95
|
+
style: { position: "fixed", top: pos.top, left: pos.left, zIndex: 9999, width: 200 },
|
|
96
|
+
className: "pointer-events-none overflow-hidden rounded-2xl border border-border bg-card shadow-2xl ring-4 ring-white dark:border-slate-700 dark:bg-slate-900 dark:ring-slate-800",
|
|
97
|
+
children: [
|
|
98
|
+
/* @__PURE__ */ jsx("div", { className: "h-48 w-48 overflow-hidden rounded-xl", children: large && !failed ? /* @__PURE__ */ jsx("img", { src: large, alt: name ?? "", className: "h-full w-full object-cover", onError: () => setFailed(true) }) : /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center bg-gradient-to-br from-sky-400 to-sky-600 text-4xl font-black text-white", children: initials(name) }) }),
|
|
99
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1 px-3 py-2.5", children: [
|
|
100
|
+
name && /* @__PURE__ */ jsx("p", { className: "text-[12px] leading-tight font-black tracking-tight break-words text-foreground", children: name }),
|
|
101
|
+
email && /* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-muted-foreground", children: email }),
|
|
102
|
+
(company || department || jobTitle) && /* @__PURE__ */ jsxs("div", { className: "mt-1 space-y-0.5 border-t border-border pt-1 dark:border-slate-700", children: [
|
|
103
|
+
company && /* @__PURE__ */ jsx("p", { className: "truncate text-[10px] font-semibold text-foreground", children: company }),
|
|
104
|
+
department && /* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-muted-foreground", children: department }),
|
|
105
|
+
jobTitle && /* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-muted-foreground italic", children: jobTitle })
|
|
106
|
+
] })
|
|
107
|
+
] })
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
),
|
|
111
|
+
document.body
|
|
112
|
+
)
|
|
113
|
+
] });
|
|
114
|
+
}
|
|
115
|
+
export {
|
|
116
|
+
Avatar,
|
|
117
|
+
Avatar as default,
|
|
118
|
+
initials
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=Avatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Avatar.js","sources":["../../../../../../src/v1/primitives/display/Avatar/Avatar.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react'\r\nimport { createPortal } from 'react-dom'\r\n\r\n/** Iniciais a partir do nome completo (primeira + última). Sem nome: \"?\". */\r\nexport function initials(fullName?: string | null): string {\r\n const parts = (fullName ?? '').trim().split(/\\s+/).filter(Boolean)\r\n if (parts.length === 0) return '?'\r\n const first = parts[0]!.charAt(0)\r\n const last = parts.length > 1 ? parts[parts.length - 1]!.charAt(0) : ''\r\n return (first + last).toUpperCase()\r\n}\r\n\r\n/** `none`: sem tamanho nem cores das iniciais — quem usa põe as classes (ex: o UserAvatar da Legacy). */\r\nexport type AvatarSize = 'sm' | 'md' | 'lg' | 'none'\r\n\r\nexport interface AvatarProps {\r\n name?: string | null\r\n /** URL da fotografia. Sem ela (ou se falhar) ficam as iniciais. */\r\n photo?: string | null\r\n /** Fotografia maior para o cartão (por omissão, a mesma). */\r\n photoLarge?: string | null\r\n email?: string | null\r\n company?: string | null\r\n department?: string | null\r\n jobTitle?: string | null\r\n /** `sm` 24px (tabelas e listas), `md` 28px, `lg` 32px (formulários, cabeçalhos). */\r\n size?: AvatarSize\r\n /** Cartão com a fotografia grande e os dados ao passar o rato (no toque, ao tocar). */\r\n card?: boolean\r\n className?: string\r\n}\r\n\r\nconst SIZES: Record<AvatarSize, string> = {\r\n none: '',\r\n sm: 'h-6 w-6 text-[9px]',\r\n md: 'h-7 w-7 text-[10px]',\r\n lg: 'h-8 w-8 text-[11px]',\r\n}\r\n\r\n// Iniciais (sem fotografia): o mesmo azul em todos os portais.\r\nconst INITIALS = 'rounded-full bg-gradient-to-br from-sky-400 to-sky-600 font-black text-white'\r\n\r\n/**\r\n * A fotografia de uma pessoa (ou as iniciais), redonda. Com `card`, mostra a\r\n * fotografia grande, o email, a empresa, o departamento e a função ao passar o rato;\r\n * no toque abre e fecha ao tocar, sem passar o toque à linha por baixo.\r\n *\r\n * Para uma pessoa com o nome ao lado (ex: numa tabela), usar o `Person`.\r\n */\r\nexport default function Avatar({\r\n name,\r\n photo,\r\n photoLarge,\r\n email,\r\n company,\r\n department,\r\n jobTitle,\r\n size = 'sm',\r\n card = true,\r\n className = '',\r\n}: AvatarProps) {\r\n const ref = useRef<HTMLSpanElement>(null)\r\n const [pos, setPos] = useState<{ top: number; left: number } | null>(null)\r\n const [pinned, setPinned] = useState(false)\r\n const [failed, setFailed] = useState(false)\r\n const pointer = useRef('mouse')\r\n const large = photoLarge ?? photo\r\n\r\n // Uma falha (ex: API em baixo) não pode marcar \"sem foto\" para sempre: em listas a\r\n // mesma instância passa a ser outra pessoa.\r\n useEffect(() => setFailed(false), [photo])\r\n\r\n const open = () => {\r\n if (!card || !ref.current) return\r\n const r = ref.current.getBoundingClientRect()\r\n const W = 200\r\n const H = email || company || jobTitle || department ? 280 : 196\r\n let left = r.right + 10\r\n let top = r.top + r.height / 2 - H / 2\r\n if (left + W > window.innerWidth - 8) left = r.left - W - 10\r\n if (top + H > window.innerHeight - 8) top = window.innerHeight - H - 8\r\n if (top < 8) top = 8\r\n setPos({ top, left })\r\n }\r\n const close = () => {\r\n setPos(null)\r\n setPinned(false)\r\n }\r\n\r\n // Aberto por toque: fecha ao tocar fora, ao deslocar ou ao redimensionar.\r\n useEffect(() => {\r\n if (!pinned) return\r\n const dismiss = (e: Event) => {\r\n if (e.type === 'pointerdown' && ref.current?.contains(e.target as Node)) return\r\n close()\r\n }\r\n document.addEventListener('pointerdown', dismiss)\r\n window.addEventListener('scroll', dismiss, true)\r\n window.addEventListener('resize', dismiss)\r\n return () => {\r\n document.removeEventListener('pointerdown', dismiss)\r\n window.removeEventListener('scroll', dismiss, true)\r\n window.removeEventListener('resize', dismiss)\r\n }\r\n }, [pinned])\r\n\r\n const showPhoto = !!photo && !failed\r\n\r\n return (\r\n <>\r\n <span\r\n ref={ref}\r\n className={`inline-flex shrink-0 items-center justify-center overflow-hidden ${SIZES[size]} ${showPhoto ? 'rounded-full' : size === 'none' ? '' : INITIALS} ${card ? 'cursor-pointer' : ''} ${className}`}\r\n onPointerEnter={(e) => e.pointerType === 'mouse' && open()}\r\n onPointerLeave={(e) => e.pointerType === 'mouse' && !pinned && close()}\r\n onPointerDown={(e) => {\r\n pointer.current = e.pointerType\r\n }}\r\n onClick={(e) => {\r\n if (!card || pointer.current === 'mouse') return\r\n e.preventDefault()\r\n e.stopPropagation()\r\n if (pinned) return close()\r\n open()\r\n setPinned(true)\r\n }}\r\n >\r\n {showPhoto ? (\r\n <img src={photo!} alt={name ?? ''} className=\"h-full w-full object-cover\" onError={() => setFailed(true)} />\r\n ) : (\r\n initials(name)\r\n )}\r\n </span>\r\n {pos &&\r\n createPortal(\r\n <div\r\n style={{ position: 'fixed', top: pos.top, left: pos.left, zIndex: 9999, width: 200 }}\r\n className=\"pointer-events-none overflow-hidden rounded-2xl border border-border bg-card shadow-2xl ring-4 ring-white dark:border-slate-700 dark:bg-slate-900 dark:ring-slate-800\"\r\n >\r\n <div className=\"h-48 w-48 overflow-hidden rounded-xl\">\r\n {large && !failed ? (\r\n <img src={large} alt={name ?? ''} className=\"h-full w-full object-cover\" onError={() => setFailed(true)} />\r\n ) : (\r\n <div className=\"flex h-full w-full items-center justify-center bg-gradient-to-br from-sky-400 to-sky-600 text-4xl font-black text-white\">\r\n {initials(name)}\r\n </div>\r\n )}\r\n </div>\r\n <div className=\"space-y-1 px-3 py-2.5\">\r\n {name && <p className=\"text-[12px] leading-tight font-black tracking-tight break-words text-foreground\">{name}</p>}\r\n {email && <p className=\"truncate text-[10px] text-muted-foreground\">{email}</p>}\r\n {(company || department || jobTitle) && (\r\n <div className=\"mt-1 space-y-0.5 border-t border-border pt-1 dark:border-slate-700\">\r\n {company && <p className=\"truncate text-[10px] font-semibold text-foreground\">{company}</p>}\r\n {department && <p className=\"truncate text-[10px] text-muted-foreground\">{department}</p>}\r\n {jobTitle && <p className=\"truncate text-[10px] text-muted-foreground italic\">{jobTitle}</p>}\r\n </div>\r\n )}\r\n </div>\r\n </div>,\r\n document.body,\r\n )}\r\n </>\r\n )\r\n}\r\n\r\nexport { Avatar }\r\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
const TONES = {
|
|
3
|
+
ok: "bg-ok-bg text-ok",
|
|
4
|
+
risco: "bg-risco-bg text-risco",
|
|
5
|
+
incumprido: "bg-incumprido-bg text-incumprido",
|
|
6
|
+
neutral: "bg-neutral-bg text-neutral",
|
|
7
|
+
accent: "bg-proef-blue/10 text-proef-navy dark:bg-sky-500/15 dark:text-sky-300",
|
|
8
|
+
blue: "bg-blue-50 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300",
|
|
9
|
+
violet: "bg-violet-50 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300",
|
|
10
|
+
cyan: "bg-cyan-50 text-cyan-700 dark:bg-cyan-500/15 dark:text-cyan-300",
|
|
11
|
+
orange: "bg-orange-50 text-orange-700 dark:bg-orange-500/15 dark:text-orange-300",
|
|
12
|
+
pink: "bg-pink-50 text-pink-700 dark:bg-pink-500/15 dark:text-pink-300"
|
|
13
|
+
};
|
|
14
|
+
function Badge({ tone = "neutral", dot = true, icon, children, className = "", ...props }) {
|
|
15
|
+
return /* @__PURE__ */ jsxs("span", { ...props, className: `inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium whitespace-nowrap ${TONES[tone]} ${className}`, children: [
|
|
16
|
+
icon ?? (dot && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-1.5 w-1.5 rounded-full bg-current" })),
|
|
17
|
+
children
|
|
18
|
+
] });
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
Badge
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=Badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Badge.js","sources":["../../../../../../src/v1/primitives/display/Badge/Badge.tsx"],"sourcesContent":["import React from 'react'\r\n\r\n/**\r\n * Estados com significado: `ok` (verde), `risco` (âmbar), `incumprido` (vermelho).\r\n * Sem estado: `neutral` (cinzento) e `accent` (azul).\r\n * Classificações (distinguir valores que não são bons nem maus, ex: origem, tipo,\r\n * área): `blue`, `violet`, `cyan`, `orange`, `pink` — sem significado, só para os\r\n * valores se reconhecerem de relance. Não usar verde/âmbar/vermelho para isto.\r\n */\r\nexport type BadgeTone = 'ok' | 'risco' | 'incumprido' | 'neutral' | 'accent' | 'blue' | 'violet' | 'cyan' | 'orange' | 'pink'\r\n\r\n/** Aceita os atributos do `<span>` (ex: `data-tip`, `title`, `aria-label`). */\r\nexport interface BadgeProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {\r\n tone?: BadgeTone\r\n /** Ponto à esquerda. Por omissão sim; sem ponto para etiquetas que não são um estado (ex: categoria). */\r\n dot?: boolean\r\n /** Ícone no lugar do ponto (ex: `<Eye size={11} />`). */\r\n icon?: React.ReactNode\r\n children: React.ReactNode\r\n}\r\n\r\nconst TONES: Record<BadgeTone, string> = {\r\n ok: 'bg-ok-bg text-ok',\r\n risco: 'bg-risco-bg text-risco',\r\n incumprido: 'bg-incumprido-bg text-incumprido',\r\n neutral: 'bg-neutral-bg text-neutral',\r\n accent: 'bg-proef-blue/10 text-proef-navy dark:bg-sky-500/15 dark:text-sky-300',\r\n blue: 'bg-blue-50 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300',\r\n violet: 'bg-violet-50 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300',\r\n cyan: 'bg-cyan-50 text-cyan-700 dark:bg-cyan-500/15 dark:text-cyan-300',\r\n orange: 'bg-orange-50 text-orange-700 dark:bg-orange-500/15 dark:text-orange-300',\r\n pink: 'bg-pink-50 text-pink-700 dark:bg-pink-500/15 dark:text-pink-300',\r\n}\r\n\r\n/**\r\n * Etiqueta em pílula: o estado de um registo (ex: \"Publicado\", \"Em atraso\") ou\r\n * uma classificação (ex: a categoria, a origem). As cores dos estados vêm dos\r\n * tokens, por isso acompanham o tema escuro.\r\n */\r\nexport default function Badge({ tone = 'neutral', dot = true, icon, children, className = '', ...props }: BadgeProps) {\r\n return (\r\n <span {...props} className={`inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium whitespace-nowrap ${TONES[tone]} ${className}`}>\r\n {icon ?? (dot && <span aria-hidden className=\"h-1.5 w-1.5 rounded-full bg-current\" />)}\r\n {children}\r\n </span>\r\n )\r\n}\r\n\r\nexport { Badge }\r\n"],"names":[],"mappings":";AAqBA,MAAM,QAAmC;AAAA,EACvC,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,MAAM;AACR;AAOA,SAAwB,MAAM,EAAE,OAAO,WAAW,MAAM,MAAM,MAAM,UAAU,YAAY,IAAI,GAAG,MAAA,GAAqB;AACpH,SACE,qBAAC,QAAA,EAAM,GAAG,OAAO,WAAW,qGAAqG,MAAM,IAAI,CAAC,IAAI,SAAS,IACtJ,UAAA;AAAA,IAAA,SAAS,OAAO,oBAAC,QAAA,EAAK,eAAW,MAAC,WAAU,sCAAA,CAAsC;AAAA,IAClF;AAAA,EAAA,GACH;AAEJ;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
function Card({ title, actions, extra, padding = "md", className = "", children, ...props }) {
|
|
3
|
+
const headerActions = actions ?? extra;
|
|
4
|
+
return /* @__PURE__ */ jsxs(
|
|
5
|
+
"div",
|
|
6
|
+
{
|
|
7
|
+
...props,
|
|
8
|
+
className: `min-w-0 rounded-xl border border-border bg-card text-foreground dark:border-slate-700 dark:bg-slate-900 ${padding === "md" ? "p-4 sm:p-5" : "overflow-hidden"} ${className}`,
|
|
9
|
+
children: [
|
|
10
|
+
(title || headerActions) && /* @__PURE__ */ jsxs("div", { className: `flex items-start justify-between gap-3 ${padding === "md" ? "mb-3.5" : "px-4 pt-4 pb-3 sm:px-5 sm:pt-5"}`, children: [
|
|
11
|
+
title && /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-foreground", children: title }),
|
|
12
|
+
headerActions
|
|
13
|
+
] }),
|
|
14
|
+
children
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
Card
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=Card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Card.js","sources":["../../../../../../src/v1/primitives/display/Card/Card.tsx"],"sourcesContent":["import React from 'react'\r\n\r\nexport interface CardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\r\n /** Título no topo (ex: \"Por estado\"). */\r\n title?: React.ReactNode\r\n /** Ações à direita do título (ex: um botão, um seletor). */\r\n actions?: React.ReactNode\r\n /** `none`: sem margem interior, para tabelas ou listas que vão até à borda. */\r\n padding?: 'md' | 'none'\r\n /** @deprecated Nome antigo (Legacy) de `actions`. */\r\n extra?: React.ReactNode\r\n}\r\n\r\n/**\r\n * Cartão: agrupa um bloco de conteúdo (um gráfico, uma lista, um resumo) num\r\n * fundo próprio com cantos redondos, com título opcional.\r\n *\r\n * Os indicadores soltos usam o `Kpi`; as tabelas da biblioteca já trazem o seu\r\n * contorno e não vão dentro de um cartão.\r\n *\r\n * **Aceita os atributos HTML do `<div>`** (ex: `id`, `data-*`, `onClick`).\r\n */\r\nexport default function Card({ title, actions, extra, padding = 'md', className = '', children, ...props }: CardProps) {\r\n const headerActions = actions ?? extra\r\n return (\r\n <div\r\n {...props}\r\n className={`min-w-0 rounded-xl border border-border bg-card text-foreground dark:border-slate-700 dark:bg-slate-900 ${padding === 'md' ? 'p-4 sm:p-5' : 'overflow-hidden'} ${className}`}\r\n >\r\n {(title || headerActions) && (\r\n <div className={`flex items-start justify-between gap-3 ${padding === 'md' ? 'mb-3.5' : 'px-4 pt-4 pb-3 sm:px-5 sm:pt-5'}`}>\r\n {title && <div className=\"text-sm font-semibold text-foreground\">{title}</div>}\r\n {headerActions}\r\n </div>\r\n )}\r\n {children}\r\n </div>\r\n )\r\n}\r\n\r\nexport { Card }\r\n"],"names":[],"mappings":";AAsBA,SAAwB,KAAK,EAAE,OAAO,SAAS,OAAO,UAAU,MAAM,YAAY,IAAI,UAAU,GAAG,MAAA,GAAoB;AACrH,QAAM,gBAAgB,WAAW;AACjC,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAG;AAAA,MACJ,WAAW,2GAA2G,YAAY,OAAO,eAAe,iBAAiB,IAAI,SAAS;AAAA,MAEpL,UAAA;AAAA,SAAA,SAAS,uCACR,OAAA,EAAI,WAAW,0CAA0C,YAAY,OAAO,WAAW,gCAAgC,IACrH,UAAA;AAAA,UAAA,SAAS,oBAAC,OAAA,EAAI,WAAU,yCAAyC,UAAA,OAAM;AAAA,UACvE;AAAA,QAAA,GACH;AAAA,QAED;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGP;"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
const TONES = {
|
|
3
|
+
filter: "bg-proef-turquoise/15 text-proef-navy dark:text-proef-turquoise",
|
|
4
|
+
group: "bg-violet-100 text-violet-800 dark:bg-violet-500/20 dark:text-violet-200"
|
|
5
|
+
};
|
|
6
|
+
function FilterChips({ items, onClearAll, clearAllLabel = "Clear all", removeLabel = "Remove", className = "" }) {
|
|
7
|
+
if (items.length === 0) return null;
|
|
8
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex flex-wrap items-center gap-2 ${className}`, children: [
|
|
9
|
+
items.map((it) => /* @__PURE__ */ jsxs(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
className: `flex items-center gap-1.5 px-2.5 py-1 text-[10px] font-black uppercase tracking-wider ${it.colorClassName ?? TONES[it.tone ?? "filter"]}`,
|
|
13
|
+
children: [
|
|
14
|
+
it.icon,
|
|
15
|
+
/* @__PURE__ */ jsx("span", { children: it.label }),
|
|
16
|
+
/* @__PURE__ */ jsx(
|
|
17
|
+
"button",
|
|
18
|
+
{
|
|
19
|
+
type: "button",
|
|
20
|
+
onClick: it.onRemove,
|
|
21
|
+
"aria-label": typeof it.label === "string" ? `${removeLabel}: ${it.label}` : removeLabel,
|
|
22
|
+
className: "ml-0.5 cursor-pointer appearance-none border-0 bg-transparent p-0 text-current hover:opacity-70",
|
|
23
|
+
children: "✕"
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
it.key
|
|
29
|
+
)),
|
|
30
|
+
onClearAll && /* @__PURE__ */ jsx(
|
|
31
|
+
"button",
|
|
32
|
+
{
|
|
33
|
+
type: "button",
|
|
34
|
+
onClick: onClearAll,
|
|
35
|
+
className: "cursor-pointer appearance-none border-0 bg-transparent p-0 text-[10px] font-black uppercase tracking-wider text-slate-400 transition-colors hover:text-red-500",
|
|
36
|
+
children: clearAllLabel
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
] });
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
FilterChips,
|
|
43
|
+
FilterChips as default
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=FilterChips.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterChips.js","sources":["../../../../../../src/v1/primitives/display/FilterChips/FilterChips.tsx"],"sourcesContent":["import React from 'react'\r\n\r\nexport interface FilterChipItem {\r\n /** Identificador único da etiqueta. */\r\n key: string\r\n /** Texto (ex: \"Estado: Cancelado\"). */\r\n label: React.ReactNode\r\n /** Tira este filtro. */\r\n onRemove: () => void\r\n /** Ícone antes do texto (ex: o de agrupar). */\r\n icon?: React.ReactNode\r\n /** `filter` (turquesa): um filtro. `group` (violeta): um agrupamento. */\r\n tone?: 'filter' | 'group'\r\n /** Cores próprias (classes), em vez das do `tone` — ex: a cor do estado. */\r\n colorClassName?: string\r\n}\r\n\r\nexport interface FilterChipsProps {\r\n items: FilterChipItem[]\r\n /** Tira todos. Sem isto não aparece o \"Limpar tudo\". */\r\n onClearAll?: () => void\r\n clearAllLabel?: string\r\n /** Nome do botão × para leitores de ecrã (recebe o texto da etiqueta, quando é texto). */\r\n removeLabel?: string\r\n className?: string\r\n}\r\n\r\nconst TONES = {\r\n filter: 'bg-proef-turquoise/15 text-proef-navy dark:text-proef-turquoise',\r\n group: 'bg-violet-100 text-violet-800 dark:bg-violet-500/20 dark:text-violet-200',\r\n}\r\n\r\n/**\r\n * Etiquetas dos filtros ativos, cada uma com × para o tirar, e \"Limpar tudo\".\r\n *\r\n * É o mesmo que a `DataTable` mostra por cima da tabela: usar este sempre que\r\n * um ecrã mostra os filtros escolhidos (ex: ao clicar num gráfico), para se\r\n * reconhecerem como a mesma coisa em todo o lado. Sem itens não desenha nada.\r\n */\r\nexport default function FilterChips({ items, onClearAll, clearAllLabel = 'Clear all', removeLabel = 'Remove', className = '' }: FilterChipsProps) {\r\n if (items.length === 0) return null\r\n return (\r\n <div className={`flex flex-wrap items-center gap-2 ${className}`}>\r\n {items.map((it) => (\r\n <div\r\n key={it.key}\r\n className={`flex items-center gap-1.5 px-2.5 py-1 text-[10px] font-black uppercase tracking-wider ${it.colorClassName ?? TONES[it.tone ?? 'filter']}`}\r\n >\r\n {it.icon}\r\n <span>{it.label}</span>\r\n <button\r\n type=\"button\"\r\n onClick={it.onRemove}\r\n aria-label={typeof it.label === 'string' ? `${removeLabel}: ${it.label}` : removeLabel}\r\n className=\"ml-0.5 cursor-pointer appearance-none border-0 bg-transparent p-0 text-current hover:opacity-70\"\r\n >\r\n ✕\r\n </button>\r\n </div>\r\n ))}\r\n {onClearAll && (\r\n <button\r\n type=\"button\"\r\n onClick={onClearAll}\r\n className=\"cursor-pointer appearance-none border-0 bg-transparent p-0 text-[10px] font-black uppercase tracking-wider text-slate-400 transition-colors hover:text-red-500\"\r\n >\r\n {clearAllLabel}\r\n </button>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\nexport { FilterChips }\r\n"],"names":[],"mappings":";AA2BA,MAAM,QAAQ;AAAA,EACZ,QAAQ;AAAA,EACR,OAAO;AACT;AASA,SAAwB,YAAY,EAAE,OAAO,YAAY,gBAAgB,aAAa,cAAc,UAAU,YAAY,MAAwB;AAChJ,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SACE,qBAAC,OAAA,EAAI,WAAW,qCAAqC,SAAS,IAC3D,UAAA;AAAA,IAAA,MAAM,IAAI,CAAC,OACV;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,WAAW,yFAAyF,GAAG,kBAAkB,MAAM,GAAG,QAAQ,QAAQ,CAAC;AAAA,QAElJ,UAAA;AAAA,UAAA,GAAG;AAAA,UACJ,oBAAC,QAAA,EAAM,UAAA,GAAG,MAAA,CAAM;AAAA,UAChB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,GAAG;AAAA,cACZ,cAAY,OAAO,GAAG,UAAU,WAAW,GAAG,WAAW,KAAK,GAAG,KAAK,KAAK;AAAA,cAC3E,WAAU;AAAA,cACX,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED;AAAA,MAAA;AAAA,MAZK,GAAG;AAAA,IAAA,CAcX;AAAA,IACA,cACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS;AAAA,QACT,WAAU;AAAA,QAET,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GAEJ;AAEJ;"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
const VALUE_TONES = {
|
|
3
|
+
default: "text-slate-800 dark:text-slate-100",
|
|
4
|
+
brand: "text-proef-blue dark:text-sky-300",
|
|
5
|
+
ok: "text-ok",
|
|
6
|
+
risco: "text-risco",
|
|
7
|
+
incumprido: "text-incumprido"
|
|
8
|
+
};
|
|
9
|
+
const TINTS = {
|
|
10
|
+
default: "bg-white border-slate-200 dark:bg-slate-900 dark:border-slate-700",
|
|
11
|
+
brand: "bg-proef-blue/10 border-transparent dark:bg-sky-500/15",
|
|
12
|
+
ok: "bg-ok-bg border-transparent",
|
|
13
|
+
risco: "bg-risco-bg border-transparent",
|
|
14
|
+
incumprido: "bg-incumprido-bg border-transparent"
|
|
15
|
+
};
|
|
16
|
+
function OpenIcon({ className }) {
|
|
17
|
+
return /* @__PURE__ */ jsx("svg", { "aria-hidden": true, viewBox: "0 0 24 24", className, fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M7 17 17 7M7 7h10v10" }) });
|
|
18
|
+
}
|
|
19
|
+
function FunnelIcon({ className }) {
|
|
20
|
+
return /* @__PURE__ */ jsx(
|
|
21
|
+
"svg",
|
|
22
|
+
{
|
|
23
|
+
"aria-hidden": true,
|
|
24
|
+
viewBox: "0 0 24 24",
|
|
25
|
+
className,
|
|
26
|
+
fill: "none",
|
|
27
|
+
stroke: "currentColor",
|
|
28
|
+
strokeWidth: 2,
|
|
29
|
+
strokeLinecap: "round",
|
|
30
|
+
strokeLinejoin: "round",
|
|
31
|
+
children: /* @__PURE__ */ jsx("path", { d: "M3 4h18l-7 8.5V19l-4 2v-8.5L3 4z" })
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
function Kpi({
|
|
36
|
+
label,
|
|
37
|
+
value,
|
|
38
|
+
tone = "default",
|
|
39
|
+
detail: detailProp,
|
|
40
|
+
icon,
|
|
41
|
+
dot,
|
|
42
|
+
bar: barProp,
|
|
43
|
+
footer: footerProp,
|
|
44
|
+
dense: denseProp,
|
|
45
|
+
tinted: tintedProp,
|
|
46
|
+
onClick,
|
|
47
|
+
clickAction = "filter",
|
|
48
|
+
active = false,
|
|
49
|
+
hint,
|
|
50
|
+
className = "",
|
|
51
|
+
delta,
|
|
52
|
+
bgTint,
|
|
53
|
+
barra,
|
|
54
|
+
rodape,
|
|
55
|
+
denso
|
|
56
|
+
}) {
|
|
57
|
+
const detail = detailProp ?? delta;
|
|
58
|
+
const footer = footerProp ?? rodape;
|
|
59
|
+
const dense = denseProp ?? denso ?? false;
|
|
60
|
+
const tinted = tintedProp ?? bgTint ?? false;
|
|
61
|
+
const bar = barProp ?? (Array.isArray(barra) ? barra.map((x) => ({ weight: x.peso, color: x.cor })) : barra);
|
|
62
|
+
const surface = tinted ? TINTS[tone] : TINTS.default;
|
|
63
|
+
const layout = dense ? "rounded-lg px-2.5 py-1.5 flex flex-col justify-center text-left gap-0.5" : "rounded-xl px-4 py-3 min-h-[88px] flex flex-col items-center justify-center text-center gap-1.5";
|
|
64
|
+
const base = `relative border ${surface} ${layout} ${className}`;
|
|
65
|
+
const totalBar = Array.isArray(bar) ? bar.reduce((s, x) => s + x.weight, 0) : 0;
|
|
66
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
67
|
+
/* @__PURE__ */ jsxs("div", { className: `${dense ? "text-[10px] uppercase tracking-wide" : "text-xs"} text-slate-500 dark:text-slate-400 flex items-center gap-1.5 max-w-full`, children: [
|
|
68
|
+
icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "shrink-0 flex", children: icon }) : dot && /* @__PURE__ */ jsx("i", { "aria-hidden": true, className: "w-2 h-2 rounded-full inline-block shrink-0", style: { background: dot } }),
|
|
69
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: label })
|
|
70
|
+
] }),
|
|
71
|
+
/* @__PURE__ */ jsxs("div", { className: dense ? "flex items-baseline gap-1.5" : "", children: [
|
|
72
|
+
/* @__PURE__ */ jsx("span", { className: `${dense ? "text-xl" : "text-2xl"} font-semibold ${VALUE_TONES[tone]}`, children: value }),
|
|
73
|
+
detail && dense && /* @__PURE__ */ jsx("span", { className: "text-[11px] text-slate-400 truncate", children: detail })
|
|
74
|
+
] }),
|
|
75
|
+
detail && !dense && /* @__PURE__ */ jsx("div", { className: "text-[11.5px] text-slate-400", children: detail }),
|
|
76
|
+
bar != null && /* @__PURE__ */ jsx("div", { className: "w-full h-1 bg-slate-100 dark:bg-slate-800 rounded overflow-hidden flex", children: Array.isArray(bar) ? bar.map((x, i) => /* @__PURE__ */ jsx("i", { style: { width: totalBar ? `${x.weight / totalBar * 100}%` : 0, background: x.color } }, i)) : /* @__PURE__ */ jsx("i", { style: { width: `${Math.min(100, Math.max(0, bar))}%`, background: "currentColor" }, className: VALUE_TONES[tone] }) }),
|
|
77
|
+
footer && /* @__PURE__ */ jsx("div", { className: "text-[11px] text-slate-400", children: footer })
|
|
78
|
+
] });
|
|
79
|
+
if (!onClick) {
|
|
80
|
+
return /* @__PURE__ */ jsx("div", { "data-tip": hint, className: `${base} ${hint ? "cursor-help" : ""}`, children: content });
|
|
81
|
+
}
|
|
82
|
+
return /* @__PURE__ */ jsxs(
|
|
83
|
+
"button",
|
|
84
|
+
{
|
|
85
|
+
type: "button",
|
|
86
|
+
onClick,
|
|
87
|
+
"data-tip": hint,
|
|
88
|
+
"aria-pressed": active,
|
|
89
|
+
className: `${base} w-full cursor-pointer shadow-sm transition hover:-translate-y-0.5 hover:border-proef-blue dark:hover:border-sky-400 hover:shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-proef-blue ${active ? "ring-2 ring-proef-blue border-proef-blue dark:border-sky-400" : ""}`,
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ (() => {
|
|
92
|
+
const cls = `absolute right-2.5 top-2.5 h-3.5 w-3.5 ${active ? "text-proef-blue dark:text-sky-300" : "text-slate-300 dark:text-slate-600"}`;
|
|
93
|
+
return clickAction === "open" ? /* @__PURE__ */ jsx(OpenIcon, { className: cls }) : /* @__PURE__ */ jsx(FunnelIcon, { className: cls });
|
|
94
|
+
})(),
|
|
95
|
+
content
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
export {
|
|
101
|
+
Kpi
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=Kpi.js.map
|