@nextelco/common-ui 2.1.98 → 2.1.100
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 +222 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/legacy/assets/svgs/proef-footer-logo.svg.js +5 -0
- package/dist/esm/legacy/assets/svgs/proef-footer-logo.svg.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Acronym/Acronym.css +43 -0
- package/dist/esm/legacy/components/atoms/Acronym/Acronym.js +31 -0
- package/dist/esm/legacy/components/atoms/Acronym/Acronym.js.map +1 -0
- package/dist/esm/legacy/components/atoms/BreadCrumb/BreadCrumb.css +36 -0
- package/dist/esm/legacy/components/atoms/BreadCrumb/BreadCrumb.js +57 -0
- package/dist/esm/legacy/components/atoms/BreadCrumb/BreadCrumb.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Button/variants/ActionButton.css +218 -0
- package/dist/esm/legacy/components/atoms/Button/variants/ActionButton.js +50 -0
- package/dist/esm/legacy/components/atoms/Button/variants/ActionButton.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Button/variants/FilterButton.css +56 -0
- package/dist/esm/legacy/components/atoms/Button/variants/FilterButton.js +34 -0
- package/dist/esm/legacy/components/atoms/Button/variants/FilterButton.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Button/variants/IconButton.css +74 -0
- package/dist/esm/legacy/components/atoms/Button/variants/IconButton.js +29 -0
- package/dist/esm/legacy/components/atoms/Button/variants/IconButton.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Button/variants/MainButton.css +99 -0
- package/dist/esm/legacy/components/atoms/Button/variants/MainButton.js +36 -0
- package/dist/esm/legacy/components/atoms/Button/variants/MainButton.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Button/variants/TabButton.css +63 -0
- package/dist/esm/legacy/components/atoms/Button/variants/TabButton.js +21 -0
- package/dist/esm/legacy/components/atoms/Button/variants/TabButton.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Field/Field.css +171 -0
- package/dist/esm/legacy/components/atoms/Field/Field.js +70 -0
- package/dist/esm/legacy/components/atoms/Field/Field.js.map +1 -0
- package/dist/esm/legacy/components/atoms/IconText/IconText.css +10 -0
- package/dist/esm/legacy/components/atoms/IconText/IconText.js +25 -0
- package/dist/esm/legacy/components/atoms/IconText/IconText.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Icone/Icone.js +24 -0
- package/dist/esm/legacy/components/atoms/Icone/Icone.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Input/Input.css +12 -0
- package/dist/esm/legacy/components/atoms/Input/Input.js +28 -0
- package/dist/esm/legacy/components/atoms/Input/Input.js.map +1 -0
- package/dist/esm/legacy/components/atoms/InputData/InputData.js +36 -0
- package/dist/esm/legacy/components/atoms/InputData/InputData.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Label/Label.css +192 -0
- package/dist/esm/legacy/components/atoms/Label/Label.js +13 -0
- package/dist/esm/legacy/components/atoms/Label/Label.js.map +1 -0
- package/dist/esm/legacy/components/atoms/MultiTagPickerTag/MultiTagPickerTag.css +40 -0
- package/dist/esm/legacy/components/atoms/MultiTagPickerTag/MultiTagPickerTag.js +21 -0
- package/dist/esm/legacy/components/atoms/MultiTagPickerTag/MultiTagPickerTag.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Select/Select.css +16 -0
- package/dist/esm/legacy/components/atoms/Select/Select.js +27 -0
- package/dist/esm/legacy/components/atoms/Select/Select.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Stack/Stack.js +20 -0
- package/dist/esm/legacy/components/atoms/Stack/Stack.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Switch/CustomSwitch.css +36 -0
- package/dist/esm/legacy/components/atoms/Switch/CustomSwitch.js +29 -0
- package/dist/esm/legacy/components/atoms/Switch/CustomSwitch.js.map +1 -0
- package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.css +17 -0
- package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.js +41 -0
- package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.js.map +1 -0
- package/dist/esm/legacy/components/charts/Charts.js +259 -0
- package/dist/esm/legacy/components/charts/Charts.js.map +1 -0
- package/dist/esm/legacy/components/layout/AppLauncher/AppLauncher.js +100 -0
- package/dist/esm/legacy/components/layout/AppLauncher/AppLauncher.js.map +1 -0
- package/dist/esm/legacy/components/layout/Error/Error.css +20 -0
- package/dist/esm/legacy/components/layout/Error/Error.js +12 -0
- package/dist/esm/legacy/components/layout/Error/Error.js.map +1 -0
- package/dist/esm/legacy/components/layout/Footer/Footer.css +42 -0
- package/dist/esm/legacy/components/layout/Footer/Footer.js +23 -0
- package/dist/esm/legacy/components/layout/Footer/Footer.js.map +1 -0
- package/dist/esm/legacy/components/layout/Header/Header.css +66 -0
- package/dist/esm/legacy/components/layout/Header/Header.js +37 -0
- package/dist/esm/legacy/components/layout/Header/Header.js.map +1 -0
- package/dist/esm/legacy/components/layout/Layout/Layout.js +92 -0
- package/dist/esm/legacy/components/layout/Layout/Layout.js.map +1 -0
- package/dist/esm/legacy/components/layout/Sidebar/Sidebar.js +227 -0
- package/dist/esm/legacy/components/layout/Sidebar/Sidebar.js.map +1 -0
- package/dist/esm/legacy/components/layout/Spinner/Spinner.css +10 -0
- package/dist/esm/legacy/components/layout/Spinner/Spinner.js +19 -0
- package/dist/esm/legacy/components/layout/Spinner/Spinner.js.map +1 -0
- package/dist/esm/legacy/components/layout/TopBar/TopBar.js +34 -0
- package/dist/esm/legacy/components/layout/TopBar/TopBar.js.map +1 -0
- package/dist/esm/legacy/components/layout/TopNavLayout/TopNavLayout.js +82 -0
- package/dist/esm/legacy/components/layout/TopNavLayout/TopNavLayout.js.map +1 -0
- package/dist/esm/legacy/components/molecules/BarraValor/BarraValor.js +25 -0
- package/dist/esm/legacy/components/molecules/BarraValor/BarraValor.js.map +1 -0
- package/dist/esm/legacy/components/molecules/ColumnPicker/ColumnPicker.js +179 -0
- package/dist/esm/legacy/components/molecules/ColumnPicker/ColumnPicker.js.map +1 -0
- package/dist/esm/legacy/components/molecules/ConfirmModal/ConfirmModal.css +3 -0
- package/dist/esm/legacy/components/molecules/ConfirmModal/ConfirmModal.js +33 -0
- package/dist/esm/legacy/components/molecules/ConfirmModal/ConfirmModal.js.map +1 -0
- package/dist/esm/legacy/components/molecules/DataTable/DataTable.js +1145 -0
- package/dist/esm/legacy/components/molecules/DataTable/DataTable.js.map +1 -0
- package/dist/esm/legacy/components/molecules/FileDropzone/FileDropzone.js +68 -0
- package/dist/esm/legacy/components/molecules/FileDropzone/FileDropzone.js.map +1 -0
- package/dist/esm/legacy/components/molecules/LanguageSwitcher/LanguageSwitcher.js +96 -0
- package/dist/esm/legacy/components/molecules/LanguageSwitcher/LanguageSwitcher.js.map +1 -0
- package/dist/esm/legacy/components/molecules/Modal/Modal.css +54 -0
- package/dist/esm/legacy/components/molecules/Modal/Modal.js +64 -0
- package/dist/esm/legacy/components/molecules/Modal/Modal.js.map +1 -0
- package/dist/esm/legacy/components/molecules/MultiTagPicker/MultiTagPicker.css +97 -0
- package/dist/esm/legacy/components/molecules/MultiTagPicker/MultiTagPicker.js +113 -0
- package/dist/esm/legacy/components/molecules/MultiTagPicker/MultiTagPicker.js.map +1 -0
- package/dist/esm/legacy/components/molecules/PhotoAvatar/PhotoAvatar.js +107 -0
- package/dist/esm/legacy/components/molecules/PhotoAvatar/PhotoAvatar.js.map +1 -0
- package/dist/esm/legacy/components/molecules/Search/Search.css +18 -0
- package/dist/esm/legacy/components/molecules/Search/Search.js +30 -0
- package/dist/esm/legacy/components/molecules/Search/Search.js.map +1 -0
- package/dist/esm/legacy/components/molecules/SeletorPesquisa/SeletorPesquisa.js +116 -0
- package/dist/esm/legacy/components/molecules/SeletorPesquisa/SeletorPesquisa.js.map +1 -0
- package/dist/esm/legacy/components/molecules/Sidebar/Sidebar.css +69 -0
- package/dist/esm/legacy/components/molecules/Sidebar/Sidebar.js +62 -0
- package/dist/esm/legacy/components/molecules/Sidebar/Sidebar.js.map +1 -0
- package/dist/esm/legacy/components/molecules/UserAvatar/UserAvatar.js +105 -0
- package/dist/esm/legacy/components/molecules/UserAvatar/UserAvatar.js.map +1 -0
- package/dist/esm/legacy/components/organisms/GanttChart/GanttChart.js +162 -0
- package/dist/esm/legacy/components/organisms/GanttChart/GanttChart.js.map +1 -0
- package/dist/esm/legacy/components/organisms/Kanban/Kanban.js +88 -0
- package/dist/esm/legacy/components/organisms/Kanban/Kanban.js.map +1 -0
- package/dist/esm/legacy/components/organisms/LazyLoader/LazyLoader.js +87 -0
- package/dist/esm/legacy/components/organisms/LazyLoader/LazyLoader.js.map +1 -0
- package/dist/esm/legacy/components/organisms/MapaPontos/MapaPontos.js +427 -0
- package/dist/esm/legacy/components/organisms/MapaPontos/MapaPontos.js.map +1 -0
- package/dist/esm/legacy/components/organisms/PainelFiltros/PainelFiltros.js +206 -0
- package/dist/esm/legacy/components/organisms/PainelFiltros/PainelFiltros.js.map +1 -0
- package/dist/esm/legacy/components/organisms/PesquisaRapida/PesquisaRapida.js +147 -0
- package/dist/esm/legacy/components/organisms/PesquisaRapida/PesquisaRapida.js.map +1 -0
- package/dist/esm/legacy/components/organisms/Profile/Profile.css +26 -0
- package/dist/esm/legacy/components/organisms/Profile/Profile.js +26 -0
- package/dist/esm/legacy/components/organisms/Profile/Profile.js.map +1 -0
- package/dist/esm/legacy/components/organisms/RoleGuard/RoleGuard.js +68 -0
- package/dist/esm/legacy/components/organisms/RoleGuard/RoleGuard.js.map +1 -0
- package/dist/esm/legacy/components/organisms/Selector/Selector.css +87 -0
- package/dist/esm/legacy/components/organisms/Selector/Selector.js +181 -0
- package/dist/esm/legacy/components/organisms/Selector/Selector.js.map +1 -0
- package/dist/esm/legacy/components/organisms/StatusMatrix/StatusMatrix.js +115 -0
- package/dist/esm/legacy/components/organisms/StatusMatrix/StatusMatrix.js.map +1 -0
- package/dist/esm/legacy/components/ui/Avisos.js +86 -0
- package/dist/esm/legacy/components/ui/Avisos.js.map +1 -0
- package/dist/esm/legacy/components/ui/BarraAcoes.js +19 -0
- package/dist/esm/legacy/components/ui/BarraAcoes.js.map +1 -0
- package/dist/esm/legacy/components/ui/CabecalhoPagina.js +32 -0
- package/dist/esm/legacy/components/ui/CabecalhoPagina.js.map +1 -0
- package/dist/esm/legacy/components/ui/CaixaPesquisa.js +57 -0
- package/dist/esm/legacy/components/ui/CaixaPesquisa.js.map +1 -0
- package/dist/esm/legacy/components/ui/Confirmacao.js +52 -0
- package/dist/esm/legacy/components/ui/Confirmacao.js.map +1 -0
- package/dist/esm/legacy/components/ui/Escolha.js +157 -0
- package/dist/esm/legacy/components/ui/Escolha.js.map +1 -0
- package/dist/esm/legacy/components/ui/FaixaAviso.js +17 -0
- package/dist/esm/legacy/components/ui/FaixaAviso.js.map +1 -0
- package/dist/esm/legacy/components/ui/MenuAcoes.js +116 -0
- package/dist/esm/legacy/components/ui/MenuAcoes.js.map +1 -0
- package/dist/esm/legacy/components/ui/Passos.js +32 -0
- package/dist/esm/legacy/components/ui/Passos.js.map +1 -0
- package/dist/esm/legacy/components/ui/Separadores.js +52 -0
- package/dist/esm/legacy/components/ui/Separadores.js.map +1 -0
- package/dist/esm/legacy/components/ui/TextoAuto.js +33 -0
- package/dist/esm/legacy/components/ui/TextoAuto.js.map +1 -0
- package/dist/esm/legacy/components/ui/Ui.js +360 -0
- package/dist/esm/legacy/components/ui/Ui.js.map +1 -0
- package/dist/esm/legacy/components/ui/painelFlutuante.js +52 -0
- package/dist/esm/legacy/components/ui/painelFlutuante.js.map +1 -0
- package/dist/esm/legacy/constants/Colors.js +33 -0
- package/dist/esm/legacy/constants/Colors.js.map +1 -0
- package/dist/esm/legacy/constants/FontWeight.js +35 -0
- package/dist/esm/legacy/constants/FontWeight.js.map +1 -0
- package/dist/esm/legacy/contexts/apiContext.js +25 -0
- package/dist/esm/legacy/contexts/apiContext.js.map +1 -0
- package/dist/esm/legacy/contexts/authContext.js +85 -0
- package/dist/esm/legacy/contexts/authContext.js.map +1 -0
- package/dist/esm/legacy/contexts/socketContext.js +34 -0
- package/dist/esm/legacy/contexts/socketContext.js.map +1 -0
- package/dist/esm/legacy/hooks/useApi.js +62 -0
- package/dist/esm/legacy/hooks/useApi.js.map +1 -0
- package/dist/esm/legacy/hooks/useTheme.js +39 -0
- package/dist/esm/legacy/hooks/useTheme.js.map +1 -0
- package/dist/esm/legacy/pages/Error/ErrorPage.css +18 -0
- package/dist/esm/legacy/pages/Error/ErrorPage.js +50 -0
- package/dist/esm/legacy/pages/Error/ErrorPage.js.map +1 -0
- package/dist/esm/legacy/pages/Loading/Loading.css +46 -0
- package/dist/esm/legacy/pages/Loading/Loading.js +9 -0
- package/dist/esm/legacy/pages/Loading/Loading.js.map +1 -0
- package/dist/esm/legacy/pages/Login/LoginScreen.js +46 -0
- package/dist/esm/legacy/pages/Login/LoginScreen.js.map +1 -0
- package/dist/esm/legacy/pages/NotFound/NotFound.css +21 -0
- package/dist/esm/legacy/pages/NotFound/NotFound.js +24 -0
- package/dist/esm/legacy/pages/NotFound/NotFound.js.map +1 -0
- package/dist/esm/legacy/styles/themes/ButtonThemes.js +28 -0
- package/dist/esm/legacy/styles/themes/ButtonThemes.js.map +1 -0
- package/dist/esm/legacy/styles/utils/utils.js +7 -0
- package/dist/esm/legacy/styles/utils/utils.js.map +1 -0
- package/dist/esm/legacy/utils/stringUtils.js +35 -0
- package/dist/esm/legacy/utils/stringUtils.js.map +1 -0
- package/dist/esm/v1/capabilities/documents/QRScanning/scanQRCodes.js +157 -0
- package/dist/esm/v1/capabilities/documents/QRScanning/scanQRCodes.js.map +1 -0
- package/dist/esm/v1/components/documents/DocumentDropzone/DocumentDropzone.js +307 -0
- package/dist/esm/v1/components/documents/DocumentDropzone/DocumentDropzone.js.map +1 -0
- package/dist/esm/v1/components/forms/FormField/FormField.js +59 -0
- package/dist/esm/v1/components/forms/FormField/FormField.js.map +1 -0
- package/dist/esm/v1/components/forms/FormGrid/FormGrid.js +20 -0
- package/dist/esm/v1/components/forms/FormGrid/FormGrid.js.map +1 -0
- package/dist/esm/v1/components/overlays/Dialog/Dialog.js +87 -0
- package/dist/esm/v1/components/overlays/Dialog/Dialog.js.map +1 -0
- package/dist/esm/v1/foundations/icons/icons.js +76 -0
- package/dist/esm/v1/foundations/icons/icons.js.map +1 -0
- package/dist/esm/v1/primitives/buttons/Button/Button.js +27 -0
- package/dist/esm/v1/primitives/buttons/Button/Button.js.map +1 -0
- package/dist/esm/v1/primitives/documents/PdfPreview/PdfPreview.js +137 -0
- package/dist/esm/v1/primitives/documents/PdfPreview/PdfPreview.js.map +1 -0
- package/dist/esm/v1/primitives/documents/PdfPreview/pdfjs.js +26 -0
- package/dist/esm/v1/primitives/documents/PdfPreview/pdfjs.js.map +1 -0
- package/dist/esm/v1/primitives/forms/LookupInput/LookupInput.js +37 -0
- package/dist/esm/v1/primitives/forms/LookupInput/LookupInput.js.map +1 -0
- package/dist/esm/v1/primitives/forms/SelectInput/SelectInput.js +29 -0
- package/dist/esm/v1/primitives/forms/SelectInput/SelectInput.js.map +1 -0
- package/dist/esm/v1/primitives/forms/TextArea/TextArea.js +75 -0
- package/dist/esm/v1/primitives/forms/TextArea/TextArea.js.map +1 -0
- package/dist/esm/v1/primitives/forms/TextInput/TextInput.js +21 -0
- package/dist/esm/v1/primitives/forms/TextInput/TextInput.js.map +1 -0
- package/dist/esm/v1/primitives/forms/field.js +12 -0
- package/dist/esm/v1/primitives/forms/field.js.map +1 -0
- package/dist/style.css +1 -1
- package/dist/style.layered.css +1 -1
- package/dist/types/index.d.ts +14 -13
- package/dist/types/{components → legacy/components}/atoms/Acronym/Acronym.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/BreadCrumb/BreadCrumb.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Button/variants/ActionButton.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Button/variants/FilterButton.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Button/variants/IconButton.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Button/variants/MainButton.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Button/variants/TabButton.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Field/Field.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/IconText/IconText.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Icone/Icone.d.ts +2 -0
- package/dist/types/{components → legacy/components}/atoms/Input/Input.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/InputData/InputData.d.ts +4 -0
- package/dist/types/{components → legacy/components}/atoms/Label/Label.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Select/Select.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Stack/Stack.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Switch/CustomSwitch.d.ts +1 -0
- package/dist/types/{components → legacy/components}/atoms/Tooltip/Tooltip.d.ts +1 -0
- package/dist/types/{components → legacy/components}/charts/Charts.d.ts +29 -6
- package/dist/types/{components → legacy/components}/layout/AppLauncher/AppLauncher.d.ts +3 -0
- package/dist/types/{components → legacy/components}/layout/Error/Error.d.ts +1 -0
- package/dist/types/{components → legacy/components}/layout/Footer/Footer.d.ts +1 -0
- package/dist/types/{components → legacy/components}/layout/Header/Header.d.ts +1 -0
- package/dist/types/{components → legacy/components}/layout/Layout/Layout.d.ts +2 -0
- package/dist/types/{components → legacy/components}/layout/Sidebar/Sidebar.d.ts +5 -0
- package/dist/types/{components → legacy/components}/layout/Spinner/Spinner.d.ts +1 -0
- package/dist/types/{components → legacy/components}/layout/TopBar/TopBar.d.ts +2 -0
- package/dist/types/{components → legacy/components}/layout/TopNavLayout/TopNavLayout.d.ts +3 -0
- package/dist/types/{components → legacy/components}/molecules/BarraValor/BarraValor.d.ts +3 -0
- package/dist/types/{components → legacy/components}/molecules/ColumnPicker/ColumnPicker.d.ts +8 -1
- package/dist/types/{components → legacy/components}/molecules/ConfirmModal/ConfirmModal.d.ts +2 -0
- package/dist/types/{components → legacy/components}/molecules/DataTable/DataTable.d.ts +6 -0
- package/dist/types/{components → legacy/components}/molecules/FileDropzone/FileDropzone.d.ts +3 -0
- package/dist/types/{components → legacy/components}/molecules/LanguageSwitcher/LanguageSwitcher.d.ts +3 -0
- package/dist/types/{components → legacy/components}/molecules/Modal/Modal.d.ts +2 -0
- package/dist/types/{components → legacy/components}/molecules/MultiTagPicker/MultiTagPicker.d.ts +2 -0
- package/dist/types/{components → legacy/components}/molecules/PhotoAvatar/PhotoAvatar.d.ts +1 -0
- package/dist/types/{components → legacy/components}/molecules/SeletorPesquisa/SeletorPesquisa.d.ts +3 -0
- package/dist/types/{components → legacy/components}/molecules/Sidebar/Sidebar.d.ts +1 -0
- package/dist/types/{components → legacy/components}/molecules/UserAvatar/UserAvatar.d.ts +1 -0
- package/dist/types/{components → legacy/components}/organisms/GanttChart/GanttChart.d.ts +8 -1
- package/dist/types/{components → legacy/components}/organisms/Kanban/Kanban.d.ts +3 -0
- package/dist/types/{components → legacy/components}/organisms/LazyLoader/LazyLoader.d.ts +1 -0
- package/dist/types/{components → legacy/components}/organisms/MapaPontos/MapaPontos.d.ts +12 -2
- package/dist/types/{components → legacy/components}/organisms/PainelFiltros/PainelFiltros.d.ts +7 -0
- package/dist/types/{components → legacy/components}/organisms/PesquisaRapida/PesquisaRapida.d.ts +5 -0
- package/dist/types/{components → legacy/components}/organisms/Profile/Profile.d.ts +1 -0
- package/dist/types/{components → legacy/components}/organisms/RoleGuard/RoleGuard.d.ts +6 -1
- package/dist/types/{components → legacy/components}/organisms/Selector/Selector.d.ts +1 -0
- package/dist/types/{components → legacy/components}/organisms/StatusMatrix/StatusMatrix.d.ts +6 -0
- package/dist/types/{components → legacy/components}/ui/Avisos.d.ts +9 -1
- package/dist/types/{components → legacy/components}/ui/BarraAcoes.d.ts +2 -0
- package/dist/types/{components → legacy/components}/ui/CabecalhoPagina.d.ts +6 -1
- package/dist/types/{components → legacy/components}/ui/Confirmacao.d.ts +2 -0
- package/dist/types/{components → legacy/components}/ui/FaixaAviso.d.ts +3 -0
- package/dist/types/{components → legacy/components}/ui/Passos.d.ts +3 -0
- package/dist/types/{components → legacy/components}/ui/Separadores.d.ts +3 -0
- package/dist/types/{components → legacy/components}/ui/TextoAuto.d.ts +2 -0
- package/dist/types/{components → legacy/components}/ui/Ui.d.ts +41 -7
- package/dist/types/{constants → legacy/constants}/FontWeight.d.ts +1 -0
- package/dist/types/{contexts → legacy/contexts}/apiContext.d.ts +1 -0
- package/dist/types/{contexts → legacy/contexts}/authContext.d.ts +2 -0
- package/dist/types/{contexts → legacy/contexts}/socketContext.d.ts +2 -0
- package/dist/types/{exports → legacy/exports}/hooks.d.ts +1 -1
- package/dist/types/{exports → legacy/exports}/molecules.d.ts +2 -1
- package/dist/types/legacy/exports/types.d.ts +7 -0
- package/dist/types/{hooks → legacy/hooks}/useApi.d.ts +2 -0
- package/dist/types/{hooks → legacy/hooks}/useTheme.d.ts +2 -0
- package/dist/types/{pages → legacy/pages}/Error/ErrorPage.d.ts +1 -0
- package/dist/types/{pages → legacy/pages}/Loading/Loading.d.ts +1 -0
- package/dist/types/{pages → legacy/pages}/Login/LoginScreen.d.ts +2 -0
- package/dist/types/{pages → legacy/pages}/NotFound/NotFound.d.ts +1 -0
- package/dist/types/legacy/styles/utils/utils.d.ts +2 -0
- package/dist/types/{types → legacy/types}/Fetcher.d.ts +1 -0
- package/dist/types/{types → legacy/types}/LoggedUser.d.ts +1 -0
- package/dist/types/{types → legacy/types}/SidebarMenu.d.ts +2 -0
- package/dist/types/legacy/types/themes/AcronymThemes.d.ts +4 -0
- package/dist/types/{types → legacy/types}/themes/ButtonThemes.d.ts +3 -0
- package/dist/types/legacy/types/themes/CustomSwitchThemes.d.ts +4 -0
- package/dist/types/{types → legacy/types}/themes/IconTextThemes.d.ts +1 -0
- package/dist/types/legacy/utils/stringUtils.d.ts +6 -0
- package/dist/types/v1/capabilities/documents/QRScanning/scanQRCodes.d.ts +25 -0
- package/dist/types/v1/components/documents/DocumentDropzone/DocumentDropzone.d.ts +60 -0
- package/dist/types/v1/components/forms/FormField/FormField.d.ts +44 -0
- package/dist/types/v1/components/forms/FormGrid/FormGrid.d.ts +21 -0
- package/dist/types/v1/components/overlays/Dialog/Dialog.d.ts +55 -0
- package/dist/types/v1/foundations/icons/icons.d.ts +24 -0
- package/dist/types/v1/index.d.ts +25 -0
- package/dist/types/v1/primitives/buttons/Button/Button.d.ts +18 -0
- package/dist/types/v1/primitives/documents/PdfPreview/PdfPreview.d.ts +17 -0
- package/dist/types/v1/primitives/documents/PdfPreview/pdfjs.d.ts +11 -0
- package/dist/types/v1/primitives/forms/LookupInput/LookupInput.d.ts +25 -0
- package/dist/types/v1/primitives/forms/SelectInput/SelectInput.d.ts +19 -0
- package/dist/types/v1/primitives/forms/TextArea/TextArea.d.ts +37 -0
- package/dist/types/v1/primitives/forms/TextInput/TextInput.d.ts +16 -0
- package/dist/types/v1/primitives/forms/field.d.ts +20 -0
- package/package.json +38 -33
- package/dist/bundle.js +0 -2
- package/dist/bundle.js.LICENSE.txt +0 -80
- package/dist/types/components/atoms/Icone/Icone.test.d.ts +0 -1
- package/dist/types/components/layout/Sidebar/Sidebar.test.d.ts +0 -1
- package/dist/types/components/molecules/BarraValor/BarraValor.test.d.ts +0 -1
- package/dist/types/components/molecules/DataTable/DataTable.test.d.ts +0 -1
- package/dist/types/components/molecules/SeletorPesquisa/SeletorPesquisa.test.d.ts +0 -1
- package/dist/types/components/organisms/Kanban/Kanban.test.d.ts +0 -1
- package/dist/types/components/organisms/RoleGuard/RoleGuard.test.d.ts +0 -1
- package/dist/types/components/ui/CaixaPesquisa.test.d.ts +0 -1
- package/dist/types/components/ui/Escolha.test.d.ts +0 -1
- package/dist/types/components/ui/Paginas.test.d.ts +0 -1
- package/dist/types/exports/types.d.ts +0 -7
- package/dist/types/styles/utils/utils.d.ts +0 -1
- package/dist/types/test/setup.d.ts +0 -1
- package/dist/types/types/themes/AcronymThemes.d.ts +0 -3
- package/dist/types/types/themes/CustomSwitchThemes.d.ts +0 -3
- package/dist/types/utils/stringUtils.d.ts +0 -3
- /package/dist/types/{components → legacy/components}/atoms/MultiTagPickerTag/MultiTagPickerTag.d.ts +0 -0
- /package/dist/types/{components → legacy/components}/atoms/SearchSelect/SearchSelect.d.ts +0 -0
- /package/dist/types/{components → legacy/components}/molecules/Search/Search.d.ts +0 -0
- /package/dist/types/{components → legacy/components}/ui/CaixaPesquisa.d.ts +0 -0
- /package/dist/types/{components → legacy/components}/ui/Escolha.d.ts +0 -0
- /package/dist/types/{components → legacy/components}/ui/MenuAcoes.d.ts +0 -0
- /package/dist/types/{components → legacy/components}/ui/painelFlutuante.d.ts +0 -0
- /package/dist/types/{constants → legacy/constants}/Colors.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/assets.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/atoms.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/charts.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/constants.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/contexts.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/layout.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/organisms.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/pages.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/styles.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/ui.d.ts +0 -0
- /package/dist/types/{exports → legacy/exports}/utils.d.ts +0 -0
- /package/dist/types/{styles → legacy/styles}/themes/ButtonThemes.d.ts +0 -0
- /package/dist/types/{types → legacy/types}/SelectableElement.d.ts +0 -0
- /package/dist/types/{utils → legacy/utils}/keycloak.d.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DocumentDropzone.js","sources":["../../../../../../src/v1/components/documents/DocumentDropzone/DocumentDropzone.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react'\r\nimport PdfPreview from '../../../primitives/documents/PdfPreview/PdfPreview'\r\n\r\nexport interface DocumentDropzoneLabels {\r\n title: string\r\n hint?: string\r\n change: string\r\n remove: string\r\n /** Texto enquanto procura QR codes (só com `onQRCodes`), ex: \"A procurar QR codes…\". */\r\n scanningQR?: string\r\n /**\r\n * Mensagem quando um ficheiro não é permitido pelo `accept`, ex: \"Formato não\r\n * permitido. Aceita PDF, JPG ou PNG.\" Aparece logo ao arrastar e depois de largar.\r\n */\r\n rejected: string\r\n}\r\n\r\nexport interface DocumentDropzoneProps {\r\n file: File | null\r\n onFileChange: (file: File | null) => void\r\n /**\r\n * Tipos permitidos: extensões e/ou tipos MIME, separados por vírgulas, ex:\r\n * \".pdf,.jpg,.jpeg,.png\". Os restantes são recusados (ver `labels.rejected` e\r\n * `onReject`). Sem `accept`, aceita qualquer ficheiro.\r\n *\r\n * - `image/*` inclui SVG (que pode conter código) e HEIC (sem pré-visualização\r\n * na maioria dos browsers). Para documentos, prefira uma lista explícita.\r\n * - Só se verificam o nome e o tipo declarado, não o conteúdo: um ficheiro\r\n * renomeado passa. O servidor deve validar o que recebe.\r\n */\r\n accept?: string\r\n disabled?: boolean\r\n labels: DocumentDropzoneLabels\r\n /** Pré-visualização própria. Se devolver null/undefined, usa a de omissão (imagem, PDF ou ícone). */\r\n renderPreview?: (file: File, url: string) => React.ReactNode\r\n /**\r\n * Procura QR codes em cada ficheiro escolhido (imagem ou 1.ª página do PDF) e\r\n * entrega o texto de todos os encontrados (vazio se nenhum). Sem esta prop não\r\n * se procura nada. Usa a capacidade [QR Scanning](?path=/docs/v1-capabilities-documents-qr-scanning--docs).\r\n */\r\n onQRCodes?: (codes: string[], file: File) => void\r\n /** Chamado com os ficheiros recusados pelo `accept` (quando nenhum dos largados/escolhidos serve). */\r\n onReject?: (files: File[]) => void\r\n /** Continuar a procurar até um QR code satisfazer isto (ex: ser o QR de uma fatura). Por omissão, pára no primeiro. */\r\n qrCodeWanted?: (code: string) => boolean\r\n className?: string\r\n}\r\n\r\n// Tipos MIME das extensões mais comuns. Ao arrastar, o browser só revela o tipo\r\n// do ficheiro (não o nome), por isso as regras \".ext\" são traduzidas por aqui.\r\nconst EXT_TYPES: Record<string, string[]> = {\r\n '.pdf': ['application/pdf'],\r\n '.jpg': ['image/jpeg'],\r\n '.jpeg': ['image/jpeg'],\r\n '.png': ['image/png'],\r\n '.webp': ['image/webp'],\r\n '.gif': ['image/gif'],\r\n '.heic': ['image/heic'],\r\n '.svg': ['image/svg+xml'],\r\n '.doc': ['application/msword'],\r\n '.docx': ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],\r\n '.xls': ['application/vnd.ms-excel'],\r\n '.xlsx': ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],\r\n '.csv': ['text/csv', 'application/vnd.ms-excel'],\r\n '.txt': ['text/plain'],\r\n '.zip': ['application/zip', 'application/x-zip-compressed'],\r\n}\r\n\r\n/**\r\n * Se um ficheiro deste tipo é permitido, sabendo só o tipo (durante o arrastar).\r\n * `null` quando não dá para saber (tipo desconhecido, ou extensão fora da tabela).\r\n */\r\nexport function acceptsType(type: string, accept?: string): boolean | null {\r\n const rules = (accept ?? '')\r\n .split(',')\r\n .map((s) => s.trim().toLowerCase())\r\n .filter(Boolean)\r\n if (rules.length === 0) return true\r\n const t = type.toLowerCase()\r\n if (!t) return null\r\n let unknown = false\r\n for (const rule of rules) {\r\n if (rule.startsWith('.')) {\r\n const types = EXT_TYPES[rule]\r\n if (!types) unknown = true\r\n else if (types.includes(t)) return true\r\n } else if (rule.endsWith('/*')) {\r\n if (t.startsWith(rule.slice(0, -1))) return true\r\n } else if (t === rule) return true\r\n }\r\n return unknown ? null : false\r\n}\r\n\r\nexport function accepts(file: File, accept?: string): boolean {\r\n if (!accept) return true\r\n const name = file.name.toLowerCase()\r\n const type = file.type.toLowerCase()\r\n // Regras vazias (ex: vírgula a mais em \".pdf,\") são ignoradas: senão aceitavam\r\n // qualquer ficheiro cujo tipo o browser não conhece (type === '').\r\n const rules = accept\r\n .split(',')\r\n .map((s) => s.trim().toLowerCase())\r\n .filter(Boolean)\r\n if (rules.length === 0) return true\r\n return rules.some((rule) => {\r\n if (rule.startsWith('.')) return name.endsWith(rule)\r\n if (rule.endsWith('/*')) return type.startsWith(rule.slice(0, -1))\r\n return type === rule\r\n })\r\n}\r\n\r\nfunction UploadIcon() {\r\n return (\r\n <svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.9\" aria-hidden>\r\n <path d=\"M12 15V4M7.5 8.5L12 4l4.5 4.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n <path d=\"M4.5 14v3.5a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V14\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n )\r\n}\r\n\r\nfunction DocumentIcon({ size }: { size: number }) {\r\n return (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" aria-hidden>\r\n <path d=\"M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7z\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n <path d=\"M14 2v5h5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n )\r\n}\r\n\r\nfunction ImageIcon() {\r\n return (\r\n <svg width=\"17\" height=\"17\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" aria-hidden>\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\r\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" />\r\n <path d=\"M21 15l-5-5L4 20\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n )\r\n}\r\n\r\n// Documento com etiqueta do formato (PDF, XLS, CSV). As letras são recortadas\r\n// da etiqueta (máscara), para lerem bem sobre qualquer fundo, claro ou escuro.\r\nfunction FileTypeIcon({ label, size = 20 }: { label: string; size?: number }) {\r\n const id = React.useId()\r\n return (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.7\" aria-hidden>\r\n <mask id={`${id}-doc`} stroke=\"none\">\r\n <rect width=\"24\" height=\"24\" fill=\"#fff\" />\r\n <rect x=\"1\" y=\"11\" width=\"17\" height=\"9.5\" rx=\"2\" fill=\"#000\" />\r\n </mask>\r\n <mask id={`${id}-label`} stroke=\"none\">\r\n <rect x=\"2\" y=\"12\" width=\"15\" height=\"7.5\" rx=\"1.6\" fill=\"#fff\" />\r\n <text x=\"9.5\" y=\"17.9\" textAnchor=\"middle\" fontFamily=\"Arial, Helvetica, sans-serif\" fontWeight=\"700\" fontSize=\"6\" fill=\"#000\">\r\n {label}\r\n </text>\r\n </mask>\r\n <g mask={`url(#${id}-doc)`}>\r\n <path d=\"M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7z\" strokeLinejoin=\"round\" />\r\n <path d=\"M14 2v5h5\" strokeLinejoin=\"round\" />\r\n </g>\r\n <rect x=\"2\" y=\"12\" width=\"15\" height=\"7.5\" rx=\"1.6\" fill=\"currentColor\" stroke=\"none\" mask={`url(#${id}-label)`} />\r\n </svg>\r\n )\r\n}\r\n\r\nconst spreadsheetLabel = (file: File) => (/.csv$/i.test(file.name) || file.type.toLowerCase() === 'text/csv' ? 'CSV' : 'XLS')\r\n\r\nconst isPdf = (file: File) => file.type === 'application/pdf'\r\n\r\nconst SPREADSHEET_TYPES = [\r\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\r\n 'application/vnd.ms-excel.sheet.macroenabled.12',\r\n 'application/vnd.ms-excel',\r\n 'text/csv',\r\n]\r\n/** Folhas de cálculo (Excel, CSV): pela extensão ou pelo tipo, que o browser às vezes não conhece. */\r\nexport const isSpreadsheet = (file: File) => /\\.(xlsx|xlsm|xls|csv)$/i.test(file.name) || SPREADSHEET_TYPES.includes(file.type.toLowerCase())\r\n\r\nfunction DefaultPreview({ file, url }: { file: File; url: string }) {\r\n if (file.type.startsWith('image/')) {\r\n return <img src={url} alt={file.name} className=\"block max-h-full max-w-full object-contain p-3\" />\r\n }\r\n if (isPdf(file)) {\r\n return <PdfPreview file={file} label={file.name} />\r\n }\r\n return (\r\n <div className=\"flex h-24 w-24 items-center justify-center rounded-3xl bg-primary text-primary-foreground shadow-tile\">\r\n {isSpreadsheet(file) ? <FileTypeIcon label={spreadsheetLabel(file)} size={42} /> : <DocumentIcon size={42} />}\r\n </div>\r\n )\r\n}\r\n\r\n/**\r\n * Caixa para anexar um ficheiro a um formulário: arrastar ou clicar para\r\n * escolher. Mostra o nome, o tamanho e uma pré-visualização do ficheiro.\r\n *\r\n * **Usa:** [PdfPreview](?path=/docs/v1-primitives-documents-pdfpreview--docs) para mostrar PDFs; imagens com `<img>`.\r\n * Com `onQRCodes`, a capacidade [QR Scanning](?path=/docs/v1-capabilities-documents-qr-scanning--docs).\r\n */\r\nexport default function DocumentDropzone({\r\n file,\r\n onFileChange,\r\n accept,\r\n disabled = false,\r\n labels,\r\n renderPreview,\r\n onQRCodes,\r\n qrCodeWanted,\r\n onReject,\r\n className = '',\r\n}: DocumentDropzoneProps) {\r\n const input = useRef<HTMLInputElement>(null)\r\n // Durante o arrastar: 'ok' se o ficheiro serve (ou não dá para saber), 'rejected' se não.\r\n const [drag, setDrag] = useState<'none' | 'ok' | 'rejected'>('none')\r\n const [url, setUrl] = useState('')\r\n const [scanning, setScanning] = useState(false)\r\n const [rejected, setRejected] = useState(false)\r\n\r\n // A mensagem de recusa desaparece sozinha passado uns segundos.\r\n useEffect(() => {\r\n if (!rejected) return\r\n const t = window.setTimeout(() => setRejected(false), 5000)\r\n return () => window.clearTimeout(t)\r\n }, [rejected])\r\n\r\n // Sempre a versão mais recente das funções da app, sem recomeçar a leitura\r\n // quando a app passa uma função nova em cada render.\r\n const onQRCodesRef = useRef(onQRCodes)\r\n const qrCodeWantedRef = useRef(qrCodeWanted)\r\n onQRCodesRef.current = onQRCodes\r\n qrCodeWantedRef.current = qrCodeWanted\r\n const scanQR = Boolean(onQRCodes)\r\n\r\n useEffect(() => {\r\n if (!file || !scanQR) {\r\n setScanning(false)\r\n return\r\n }\r\n let alive = true\r\n setScanning(true)\r\n import('../../../capabilities/documents/QRScanning/scanQRCodes')\r\n .then(({ scanQRCodes }) => scanQRCodes(file, { until: (code) => qrCodeWantedRef.current?.(code) ?? true }))\r\n .catch(() => [] as string[])\r\n .then((codes) => {\r\n // Um resultado de um ficheiro que entretanto mudou é descartado.\r\n if (!alive) return\r\n setScanning(false)\r\n onQRCodesRef.current?.(codes, file)\r\n })\r\n return () => {\r\n alive = false\r\n }\r\n }, [file, scanQR])\r\n\r\n useEffect(() => {\r\n if (!file) {\r\n setUrl('')\r\n return\r\n }\r\n const created = URL.createObjectURL(file)\r\n setUrl(created)\r\n return () => URL.revokeObjectURL(created)\r\n }, [file])\r\n\r\n const pick = () => {\r\n if (!disabled) input.current?.click()\r\n }\r\n\r\n const receive = (list: FileList | null) => {\r\n if (disabled || !list || list.length === 0) return\r\n const files = Array.from(list)\r\n const first = files.find((f) => accepts(f, accept))\r\n if (first) {\r\n setRejected(false)\r\n onFileChange(first)\r\n return\r\n }\r\n setRejected(true)\r\n onReject?.(files)\r\n }\r\n\r\n const onKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key !== 'Enter' && e.key !== ' ') return\r\n e.preventDefault()\r\n pick()\r\n }\r\n\r\n let frame = 'border-2 border-dashed border-primary/30 bg-card shadow-card hover:border-primary hover:bg-muted hover:shadow-card-hover'\r\n if (file) frame = 'border border-border bg-card shadow-card'\r\n if (drag === 'ok') frame = 'border-2 border-dashed border-primary bg-primary/5 shadow-card-active'\r\n if (drag === 'rejected') frame = 'border-2 border-dashed border-destructive bg-destructive/5 shadow-card'\r\n if (disabled) frame += ' cursor-not-allowed opacity-60'\r\n\r\n const sizeMb = file ? (file.size / 1024 / 1024).toFixed(2) : ''\r\n const custom = file && url && renderPreview ? renderPreview(file, url) : null\r\n const preview = file && url ? custom ?? <DefaultPreview file={file} url={url} /> : null\r\n\r\n return (\r\n <div\r\n onDragOver={(e) => {\r\n e.preventDefault()\r\n if (disabled) {\r\n e.dataTransfer.dropEffect = 'none'\r\n return\r\n }\r\n const types = Array.from(e.dataTransfer.items ?? [])\r\n .filter((item) => item.kind === 'file')\r\n .map((item) => item.type)\r\n const verdict = types.length && types.every((t) => acceptsType(t, accept) === false) ? 'rejected' : 'ok'\r\n e.dataTransfer.dropEffect = verdict === 'rejected' ? 'none' : 'copy'\r\n setDrag(verdict)\r\n }}\r\n onDragLeave={(e) => {\r\n // Passar por cima do ícone ou do texto da caixa não é sair dela.\r\n if (e.currentTarget.contains(e.relatedTarget as Node | null)) return\r\n // Ficheiro não permitido: a mensagem fica uns segundos depois de largar/sair.\r\n if (drag === 'rejected') setRejected(true)\r\n setDrag('none')\r\n }}\r\n onDrop={(e) => {\r\n e.preventDefault()\r\n setDrag('none')\r\n receive(e.dataTransfer.files)\r\n }}\r\n className={`group relative flex overflow-hidden rounded-2xl transition-[border-color,background-color,box-shadow] duration-200 ${frame} ${className}`}\r\n >\r\n {!file && (\r\n <div\r\n role=\"button\"\r\n tabIndex={disabled ? -1 : 0}\r\n aria-disabled={disabled}\r\n onClick={pick}\r\n onKeyDown={onKeyDown}\r\n className=\"flex h-full w-full cursor-pointer flex-col items-center justify-center gap-[18px] px-6 py-7 text-center outline-none focus-visible:ring-2 focus-visible:ring-ring\"\r\n >\r\n <div className=\"flex h-[78px] w-[78px] items-center justify-center rounded-[22px] bg-primary/5 text-primary transition-transform duration-200 group-hover:-translate-y-0.5\">\r\n <UploadIcon />\r\n </div>\r\n <div>\r\n <div className=\"mb-1.5 text-title font-semibold text-foreground\">{labels.title}</div>\r\n {labels.hint && <div className=\"text-control text-muted-foreground\">{labels.hint}</div>}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {file && (\r\n <div className=\"flex h-full min-h-0 w-full flex-col\">\r\n <div className=\"flex flex-none items-center gap-[11px] border-b border-border bg-card py-2.5 pr-3 pl-3.5\">\r\n <span className=\"flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg bg-primary/5 text-primary\">\r\n {isPdf(file) ? (\r\n <FileTypeIcon label=\"PDF\" />\r\n ) : isSpreadsheet(file) ? (\r\n <FileTypeIcon label={spreadsheetLabel(file)} />\r\n ) : file.type.startsWith('image/') ? (\r\n <ImageIcon />\r\n ) : (\r\n <DocumentIcon size={17} />\r\n )}\r\n </span>\r\n <div className=\"min-w-0 flex-1 text-left\">\r\n <div className=\"truncate text-control font-semibold text-primary\">{file.name}</div>\r\n <div className=\"mt-px flex items-center gap-1.5 text-caption text-muted-foreground\">\r\n <span>{sizeMb} MB</span>\r\n {scanning && (\r\n <span role=\"status\" className=\"inline-flex items-center gap-1.5\">\r\n <span aria-hidden className=\"inline-block h-2.5 w-2.5 animate-spin rounded-full border-[1.5px] border-primary/20 border-t-primary\" />\r\n {labels.scanningQR}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n <button\r\n type=\"button\"\r\n disabled={disabled}\r\n onClick={pick}\r\n className=\"inline-flex flex-none cursor-pointer items-center gap-1.5 rounded-lg border border-border bg-card px-[11px] py-1.5 text-caption font-bold tracking-[0.02em] text-primary transition-colors duration-150 hover:border-primary/30 hover:bg-primary/5 focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none\"\r\n >\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.2\" aria-hidden>\r\n <path d=\"M21 12a9 9 0 1 1-2.64-6.36\" strokeLinecap=\"round\" />\r\n <path d=\"M21 3v5h-5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n {labels.change}\r\n </button>\r\n <button\r\n type=\"button\"\r\n title={labels.remove}\r\n aria-label={labels.remove}\r\n disabled={disabled}\r\n onClick={() => onFileChange(null)}\r\n className=\"inline-flex h-8 w-8 flex-none cursor-pointer items-center justify-center rounded-lg border border-border bg-card p-0 text-muted-foreground transition-colors duration-150 hover:border-destructive/30 hover:bg-destructive/10 hover:text-destructive\"\r\n >\r\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.9\" aria-hidden>\r\n <path d=\"M4 7h16M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2M6 7l1 13a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1l1-13\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </div>\r\n <div className=\"flex min-h-0 flex-1 basis-0 items-center justify-center overflow-hidden bg-card\">\r\n {preview}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {(rejected || drag === 'rejected') && (\r\n <div\r\n role=\"alert\"\r\n className=\"absolute inset-x-3 bottom-3 rounded-lg border border-destructive/30 bg-card px-3 py-2 text-center text-xs font-medium text-destructive shadow-popover\"\r\n >\r\n {labels.rejected}\r\n </div>\r\n )}\r\n\r\n <input\r\n ref={input}\r\n type=\"file\"\r\n accept={accept}\r\n className=\"hidden\"\r\n onChange={(e) => {\r\n receive(e.target.files)\r\n e.target.value = ''\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useId } from "react";
|
|
3
|
+
import { FieldContext } from "../../../primitives/forms/field.js";
|
|
4
|
+
import { useFormGrid } from "../FormGrid/FormGrid.js";
|
|
5
|
+
const MARK = 17;
|
|
6
|
+
const MARK_GAP = 4;
|
|
7
|
+
function FormField({ label, required, hint, marks, markSlots, aside, end, wide, alignTop, children }) {
|
|
8
|
+
const id = useId();
|
|
9
|
+
const { columns } = useFormGrid();
|
|
10
|
+
const marksCount = React.Children.count(marks);
|
|
11
|
+
const slots = Math.max(markSlots ?? 0, marksCount);
|
|
12
|
+
return /* @__PURE__ */ jsxs(FieldContext.Provider, { value: { id, required }, children: [
|
|
13
|
+
/* @__PURE__ */ jsxs(
|
|
14
|
+
"div",
|
|
15
|
+
{
|
|
16
|
+
className: `flex flex-col items-end pr-3 text-right @max-form-sm:items-start @max-form-sm:pr-0 @max-form-sm:pt-0 @max-form-sm:text-left ${alignTop ? "self-start pt-[7px]" : ""}`,
|
|
17
|
+
children: [
|
|
18
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end @max-form-sm:justify-start", children: [
|
|
19
|
+
slots > 0 && /* @__PURE__ */ jsx("span", { className: "mr-[5px] inline-flex flex-none items-center justify-end gap-1", style: { width: slots * MARK + (slots - 1) * MARK_GAP }, children: marks }),
|
|
20
|
+
aside && /* @__PURE__ */ jsx("span", { className: "mr-1.5 flex-none", children: aside }),
|
|
21
|
+
/* @__PURE__ */ jsxs(
|
|
22
|
+
"label",
|
|
23
|
+
{
|
|
24
|
+
htmlFor: id,
|
|
25
|
+
className: "m-0 text-xs leading-[18px] font-medium whitespace-nowrap text-muted-foreground @max-form-md:whitespace-normal",
|
|
26
|
+
children: [
|
|
27
|
+
label,
|
|
28
|
+
required && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "ml-0.5 text-destructive", children: "*" })
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
] }),
|
|
33
|
+
hint && /* @__PURE__ */ jsx("span", { className: "text-micro text-muted-foreground", children: hint })
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
),
|
|
37
|
+
/* @__PURE__ */ jsxs("div", { className: `min-w-0 ${wide && columns === 2 ? "col-span-3 @max-form-sm:col-span-1" : ""} ${end ? "flex items-center gap-1.5" : ""}`, children: [
|
|
38
|
+
children,
|
|
39
|
+
end
|
|
40
|
+
] })
|
|
41
|
+
] });
|
|
42
|
+
}
|
|
43
|
+
function FieldMark({ title, icon }) {
|
|
44
|
+
return /* @__PURE__ */ jsx(
|
|
45
|
+
"span",
|
|
46
|
+
{
|
|
47
|
+
role: "img",
|
|
48
|
+
"aria-label": title,
|
|
49
|
+
title,
|
|
50
|
+
className: "inline-flex h-[17px] w-[17px] flex-none cursor-help items-center justify-center rounded-[5px] border border-primary/20 bg-primary/5 text-primary",
|
|
51
|
+
children: icon
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
FieldMark,
|
|
57
|
+
FormField as default
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=FormField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormField.js","sources":["../../../../../../src/v1/components/forms/FormField/FormField.tsx"],"sourcesContent":["import React, { useId } from 'react'\r\nimport { FieldContext } from '../../../primitives/forms/field'\r\nimport { useFormGrid } from '../FormGrid/FormGrid'\r\n\r\nexport interface FormFieldProps {\r\n label: string\r\n /** Asterisco vermelho na etiqueta; o campo lá dentro fica `required`. */\r\n required?: boolean\r\n /** Texto pequeno por baixo da etiqueta. */\r\n hint?: string\r\n /**\r\n * Marcas antes da etiqueta, a dizer de onde veio o valor (ex: lido do QR,\r\n * identificado pela IA). Usar [FieldMark](#fieldmark).\r\n */\r\n marks?: React.ReactNode\r\n /**\r\n * Lugares reservados para marcas, mesmo sem nenhuma. Assim a etiqueta não\r\n * salta quando uma marca aparece depois (ex: ao ler o QR).\r\n */\r\n markSlots?: number\r\n /** Algo junto à etiqueta, depois das marcas (ex: o valor máximo permitido). */\r\n aside?: React.ReactNode\r\n /** Depois do campo, na mesma linha (ex: cadeado, ícone de informação). */\r\n end?: React.ReactNode\r\n /** Ocupa a linha toda (ex: observações, anexo). */\r\n wide?: boolean\r\n /** Etiqueta alinhada ao topo em vez de ao meio (campos altos, como o TextArea). */\r\n alignTop?: boolean\r\n /** O campo: TextInput, SelectInput, TextArea ou outro. */\r\n children: React.ReactNode\r\n}\r\n\r\nconst MARK = 17\r\nconst MARK_GAP = 4\r\n\r\n/**\r\n * Uma linha do formulário: etiqueta e campo. Vai dentro de um\r\n * [FormGrid](?path=/docs/v1-components-forms-formgrid--docs).\r\n *\r\n * Liga a etiqueta ao campo (clicar na etiqueta foca o campo) e passa-lhe o\r\n * `required`, se o campo for TextInput, SelectInput ou TextArea.\r\n */\r\nexport default function FormField({ label, required, hint, marks, markSlots, aside, end, wide, alignTop, children }: FormFieldProps) {\r\n const id = useId()\r\n const { columns } = useFormGrid()\r\n const marksCount = React.Children.count(marks)\r\n const slots = Math.max(markSlots ?? 0, marksCount)\r\n\r\n return (\r\n <FieldContext.Provider value={{ id, required }}>\r\n <div\r\n className={`flex flex-col items-end pr-3 text-right @max-form-sm:items-start @max-form-sm:pr-0 @max-form-sm:pt-0 @max-form-sm:text-left ${alignTop ? 'self-start pt-[7px]' : ''}`}\r\n >\r\n {/* As marcas ficam fora do <label>, para não entrarem no nome do campo lido pelos leitores de ecrã. */}\r\n <div className=\"flex items-center justify-end @max-form-sm:justify-start\">\r\n {slots > 0 && (\r\n <span className=\"mr-[5px] inline-flex flex-none items-center justify-end gap-1\" style={{ width: slots * MARK + (slots - 1) * MARK_GAP }}>\r\n {marks}\r\n </span>\r\n )}\r\n {aside && <span className=\"mr-1.5 flex-none\">{aside}</span>}\r\n <label\r\n htmlFor={id}\r\n className=\"m-0 text-xs leading-[18px] font-medium whitespace-nowrap text-muted-foreground @max-form-md:whitespace-normal\"\r\n >\r\n {label}\r\n {required && (\r\n <span aria-hidden className=\"ml-0.5 text-destructive\">\r\n *\r\n </span>\r\n )}\r\n </label>\r\n </div>\r\n {hint && <span className=\"text-micro text-muted-foreground\">{hint}</span>}\r\n </div>\r\n <div className={`min-w-0 ${wide && columns === 2 ? 'col-span-3 @max-form-sm:col-span-1' : ''} ${end ? 'flex items-center gap-1.5' : ''}`}>\r\n {children}\r\n {end}\r\n </div>\r\n </FieldContext.Provider>\r\n )\r\n}\r\n\r\nexport interface FieldMarkProps {\r\n /** De onde veio o valor (ex: \"Lido do QR Code\"). Mostrado ao passar o rato e lido pelos leitores de ecrã. */\r\n title: string\r\n /** O ícone, a 11 px (ex: `<QrCodeIcon size={11} />`). */\r\n icon: React.ReactNode\r\n}\r\n\r\n/** Marca pequena antes da etiqueta de um FormField, a dizer de onde veio o valor. */\r\nexport function FieldMark({ title, icon }: FieldMarkProps) {\r\n return (\r\n <span\r\n role=\"img\"\r\n aria-label={title}\r\n title={title}\r\n className=\"inline-flex h-[17px] w-[17px] flex-none cursor-help items-center justify-center rounded-[5px] border border-primary/20 bg-primary/5 text-primary\"\r\n >\r\n {icon}\r\n </span>\r\n )\r\n}\r\n"],"names":[],"mappings":";;;;AAgCA,MAAM,OAAO;AACb,MAAM,WAAW;AASjB,SAAwB,UAAU,EAAE,OAAO,UAAU,MAAM,OAAO,WAAW,OAAO,KAAK,MAAM,UAAU,SAAA,GAA4B;AACnI,QAAM,KAAK,MAAA;AACX,QAAM,EAAE,QAAA,IAAY,YAAA;AACpB,QAAM,aAAa,MAAM,SAAS,MAAM,KAAK;AAC7C,QAAM,QAAQ,KAAK,IAAI,aAAa,GAAG,UAAU;AAEjD,SACE,qBAAC,aAAa,UAAb,EAAsB,OAAO,EAAE,IAAI,YAClC,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,+HAA+H,WAAW,wBAAwB,EAAE;AAAA,QAG/K,UAAA;AAAA,UAAA,qBAAC,OAAA,EAAI,WAAU,4DACZ,UAAA;AAAA,YAAA,QAAQ,KACP,oBAAC,QAAA,EAAK,WAAU,iEAAgE,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,KAAK,YAC1H,UAAA,OACH;AAAA,YAED,SAAS,oBAAC,QAAA,EAAK,WAAU,oBAAoB,UAAA,OAAM;AAAA,YACpD;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS;AAAA,gBACT,WAAU;AAAA,gBAET,UAAA;AAAA,kBAAA;AAAA,kBACA,YACC,oBAAC,QAAA,EAAK,eAAW,MAAC,WAAU,2BAA0B,UAAA,IAAA,CAEtD;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UAEJ,GACF;AAAA,UACC,QAAQ,oBAAC,QAAA,EAAK,WAAU,oCAAoC,UAAA,KAAA,CAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAEpE,qBAAC,OAAA,EAAI,WAAW,WAAW,QAAQ,YAAY,IAAI,uCAAuC,EAAE,IAAI,MAAM,8BAA8B,EAAE,IACnI,UAAA;AAAA,MAAA;AAAA,MACA;AAAA,IAAA,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAUO,SAAS,UAAU,EAAE,OAAO,QAAwB;AACzD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ;AAAA,MACA,WAAU;AAAA,MAET,UAAA;AAAA,IAAA;AAAA,EAAA;AAGP;"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useContext, createContext } from "react";
|
|
3
|
+
const GridContext = createContext({ columns: 2 });
|
|
4
|
+
const useFormGrid = () => useContext(GridContext);
|
|
5
|
+
const COLUMNS = {
|
|
6
|
+
2: "grid-cols-[var(--spacing-form-label)_minmax(0,1fr)_var(--spacing-form-label)_minmax(0,1fr)] @max-form-md:grid-cols-[var(--spacing-form-label-narrow)_minmax(0,1fr)_var(--spacing-form-label-narrow)_minmax(0,1fr)]",
|
|
7
|
+
1: "grid-cols-[var(--spacing-form-label)_minmax(0,1fr)] @max-form-md:grid-cols-[var(--spacing-form-label-narrow)_minmax(0,1fr)]"
|
|
8
|
+
};
|
|
9
|
+
function FormGrid({ columns = 2, className = "", children }) {
|
|
10
|
+
return /* @__PURE__ */ jsx(GridContext.Provider, { value: { columns }, children: /* @__PURE__ */ jsx("div", { className: `@container ${className}`, children: /* @__PURE__ */ jsx("div", { className: `grid items-center gap-x-3.5 gap-y-[13px] @max-form-sm:grid-cols-1 @max-form-sm:gap-y-1.5 ${COLUMNS[columns]}`, children }) }) });
|
|
11
|
+
}
|
|
12
|
+
function FormDivider() {
|
|
13
|
+
return /* @__PURE__ */ jsx("div", { role: "separator", className: "col-span-full my-0.5 h-px bg-border @max-form-sm:my-2" });
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
FormDivider,
|
|
17
|
+
FormGrid as default,
|
|
18
|
+
useFormGrid
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=FormGrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormGrid.js","sources":["../../../../../../src/v1/components/forms/FormGrid/FormGrid.tsx"],"sourcesContent":["import React, { createContext, useContext } from 'react'\r\n\r\nexport interface FormGridProps {\r\n /** Campos por linha: 2 (etiqueta · campo · etiqueta · campo) ou 1. */\r\n columns?: 1 | 2\r\n className?: string\r\n children: React.ReactNode\r\n}\r\n\r\nconst GridContext = createContext<{ columns: 1 | 2 }>({ columns: 2 })\r\nexport const useFormGrid = () => useContext(GridContext)\r\n\r\nconst COLUMNS = {\r\n 2: 'grid-cols-[var(--spacing-form-label)_minmax(0,1fr)_var(--spacing-form-label)_minmax(0,1fr)] @max-form-md:grid-cols-[var(--spacing-form-label-narrow)_minmax(0,1fr)_var(--spacing-form-label-narrow)_minmax(0,1fr)]',\r\n 1: 'grid-cols-[var(--spacing-form-label)_minmax(0,1fr)] @max-form-md:grid-cols-[var(--spacing-form-label-narrow)_minmax(0,1fr)]',\r\n}\r\n\r\n/**\r\n * Grelha de um formulário: etiquetas à esquerda, alinhadas à direita, e os\r\n * campos ao lado. Os filhos são [FormField](?path=/docs/v1-components-forms-formfield--docs)\r\n * e, entre grupos, `FormDivider`.\r\n *\r\n * Adapta-se à largura do sítio onde está (não à do ecrã): abaixo de 680 px as\r\n * etiquetas estreitam; abaixo de 500 px cada etiqueta fica por cima do campo.\r\n */\r\nexport default function FormGrid({ columns = 2, className = '', children }: FormGridProps) {\r\n return (\r\n <GridContext.Provider value={{ columns }}>\r\n <div className={`@container ${className}`}>\r\n <div className={`grid items-center gap-x-3.5 gap-y-[13px] @max-form-sm:grid-cols-1 @max-form-sm:gap-y-1.5 ${COLUMNS[columns]}`}>{children}</div>\r\n </div>\r\n </GridContext.Provider>\r\n )\r\n}\r\n\r\n/** Linha de separação entre grupos de campos, a toda a largura. */\r\nexport function FormDivider() {\r\n return <div role=\"separator\" className=\"col-span-full my-0.5 h-px bg-border @max-form-sm:my-2\" />\r\n}\r\n"],"names":[],"mappings":";;AASA,MAAM,cAAc,cAAkC,EAAE,SAAS,GAAG;AAC7D,MAAM,cAAc,MAAM,WAAW,WAAW;AAEvD,MAAM,UAAU;AAAA,EACd,GAAG;AAAA,EACH,GAAG;AACL;AAUA,SAAwB,SAAS,EAAE,UAAU,GAAG,YAAY,IAAI,YAA2B;AACzF,SACE,oBAAC,YAAY,UAAZ,EAAqB,OAAO,EAAE,WAC7B,UAAA,oBAAC,OAAA,EAAI,WAAW,cAAc,SAAS,IACrC,UAAA,oBAAC,OAAA,EAAI,WAAW,4FAA4F,QAAQ,OAAO,CAAC,IAAK,SAAA,CAAS,EAAA,CAC5I,EAAA,CACF;AAEJ;AAGO,SAAS,cAAc;AAC5B,SAAO,oBAAC,OAAA,EAAI,MAAK,aAAY,WAAU,yDAAwD;AACjG;"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState, useId, useEffect, createContext, useContext } from "react";
|
|
3
|
+
const DialogContainerContext = createContext(null);
|
|
4
|
+
const useDialogContainer = () => useContext(DialogContainerContext);
|
|
5
|
+
const WIDTHS = { sm: "max-w-dialog-sm", md: "max-w-dialog-md", lg: "max-w-dialog-lg" };
|
|
6
|
+
function Dialog({
|
|
7
|
+
open,
|
|
8
|
+
onClose,
|
|
9
|
+
title,
|
|
10
|
+
subtitle,
|
|
11
|
+
footer,
|
|
12
|
+
size = "md",
|
|
13
|
+
height = "auto",
|
|
14
|
+
closeOnBackdrop = true,
|
|
15
|
+
closeLabel = "Fechar",
|
|
16
|
+
flush = false,
|
|
17
|
+
children
|
|
18
|
+
}) {
|
|
19
|
+
const ref = useRef(null);
|
|
20
|
+
const [container, setContainer] = useState(null);
|
|
21
|
+
const titleId = useId();
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
setContainer(ref.current);
|
|
24
|
+
}, []);
|
|
25
|
+
const pressedBackdrop = useRef(false);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
const dialog = ref.current;
|
|
28
|
+
if (!dialog) return;
|
|
29
|
+
if (open && !dialog.open) dialog.showModal();
|
|
30
|
+
if (!open && dialog.open) dialog.close();
|
|
31
|
+
}, [open]);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!open) return;
|
|
34
|
+
const html = document.documentElement;
|
|
35
|
+
const before = html.style.overflow;
|
|
36
|
+
html.style.overflow = "hidden";
|
|
37
|
+
return () => {
|
|
38
|
+
html.style.overflow = before;
|
|
39
|
+
};
|
|
40
|
+
}, [open]);
|
|
41
|
+
return /* @__PURE__ */ jsxs(
|
|
42
|
+
"dialog",
|
|
43
|
+
{
|
|
44
|
+
ref,
|
|
45
|
+
"aria-labelledby": titleId,
|
|
46
|
+
onCancel: (e) => {
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
onClose();
|
|
49
|
+
},
|
|
50
|
+
onPointerDown: (e) => {
|
|
51
|
+
pressedBackdrop.current = e.target === e.currentTarget;
|
|
52
|
+
},
|
|
53
|
+
onClick: (e) => {
|
|
54
|
+
if (closeOnBackdrop && pressedBackdrop.current && e.target === e.currentTarget) onClose();
|
|
55
|
+
},
|
|
56
|
+
className: `m-auto w-[calc(100vw-2*var(--spacing-dialog-margin))] ${WIDTHS[size]} max-h-[calc(100dvh-2*var(--spacing-dialog-margin))] overflow-hidden rounded-2xl border-0 bg-card p-0 text-foreground shadow-modal open:flex open:flex-col ${height === "full" ? "h-[calc(100dvh-2*var(--spacing-dialog-margin))]" : ""} backdrop:bg-black/40 motion-safe:open:animate-dialog-in motion-safe:backdrop:animate-backdrop-in`,
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsxs("header", { className: "flex flex-none items-center justify-between gap-3 bg-gradient-to-br from-primary to-primary-strong px-5 py-3.5", children: [
|
|
59
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
60
|
+
/* @__PURE__ */ jsx("h2", { id: titleId, className: "m-0 truncate text-title font-bold text-primary-foreground", children: title }),
|
|
61
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "m-0 mt-0.5 truncate text-caption text-primary-foreground/75", children: subtitle })
|
|
62
|
+
] }),
|
|
63
|
+
/* @__PURE__ */ jsx(
|
|
64
|
+
"button",
|
|
65
|
+
{
|
|
66
|
+
type: "button",
|
|
67
|
+
"aria-label": closeLabel,
|
|
68
|
+
title: closeLabel,
|
|
69
|
+
onClick: onClose,
|
|
70
|
+
className: "flex h-7 w-7 flex-none cursor-pointer items-center justify-center rounded-md border border-primary-foreground/25 bg-primary-foreground/15 text-base leading-none text-primary-foreground transition-colors hover:bg-primary-foreground/25 focus-visible:ring-2 focus-visible:ring-primary-foreground/60 focus-visible:outline-none",
|
|
71
|
+
children: "×"
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
] }),
|
|
75
|
+
/* @__PURE__ */ jsxs(DialogContainerContext.Provider, { value: container, children: [
|
|
76
|
+
/* @__PURE__ */ jsx("div", { className: flush ? "flex min-h-0 flex-1 flex-col overflow-hidden bg-canvas" : "min-h-0 flex-1 overflow-y-auto bg-canvas px-5 py-4", children }),
|
|
77
|
+
footer && /* @__PURE__ */ jsx("footer", { className: "flex flex-none flex-wrap justify-end gap-2 border-t border-border bg-muted/40 px-5 py-[18px]", children: footer })
|
|
78
|
+
] })
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
export {
|
|
84
|
+
Dialog as default,
|
|
85
|
+
useDialogContainer
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=Dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dialog.js","sources":["../../../../../../src/v1/components/overlays/Dialog/Dialog.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useId, useRef, useState } from 'react'\r\n\r\nconst DialogContainerContext = createContext<HTMLElement | null>(null)\r\n\r\n/**\r\n * O elemento da janela aberta, para usar como destino de `createPortal` (ex:\r\n * avisos, confirmações, sobreposições). Com a janela aberta, tudo o que está\r\n * fora dela fica por baixo e não responde; um portal para `document.body` fica\r\n * escondido atrás. Fora de um Dialog devolve `null`.\r\n *\r\n * `createPortal(conteudo, useDialogContainer() ?? document.body)`\r\n */\r\nexport const useDialogContainer = () => useContext(DialogContainerContext)\r\n\r\nexport interface DialogProps {\r\n /** Aberta ou fechada. A app guarda este estado. */\r\n open: boolean\r\n /** Pedido para fechar (×, Esc ou clique fora): a app põe `open` a `false`. */\r\n onClose: () => void\r\n title: string\r\n /** Linha por baixo do título (ex: nome · departamento). */\r\n subtitle?: string\r\n /** Botões no rodapé, sempre visíveis (ex: Confirmar, Fechar). */\r\n footer?: React.ReactNode\r\n /** Largura máxima: `sm` 480px, `md` 720px, `lg` 1000px. Nunca passa o ecrã. */\r\n size?: 'sm' | 'md' | 'lg'\r\n /**\r\n * Altura: `auto` (por omissão) cresce com o conteúdo; `full` ocupa sempre a\r\n * altura disponível (útil quando o conteúdo muda de tamanho e a janela não\r\n * deve saltar). Em ambos, se o conteúdo não couber, o corpo faz scroll.\r\n */\r\n height?: 'auto' | 'full'\r\n /** Fechar ao clicar fora da janela. Por omissão sim; num formulário longo pode valer a pena desligar. */\r\n closeOnBackdrop?: boolean\r\n /** Nome do botão ×, para leitores de ecrã. Por omissão: \"Fechar\". */\r\n closeLabel?: string\r\n /**\r\n * Corpo sem margens e sem scroll: o conteúdo ocupa-o todo e gere o seu próprio\r\n * scroll (ex: passos que deslizam, rodapé próprio de cada passo).\r\n */\r\n flush?: boolean\r\n children: React.ReactNode\r\n}\r\n\r\nconst WIDTHS = { sm: 'max-w-dialog-sm', md: 'max-w-dialog-md', lg: 'max-w-dialog-lg' }\r\n\r\n/**\r\n * Janela por cima da página: cabeçalho navy com título, corpo que faz scroll e\r\n * rodapé com os botões.\r\n *\r\n * É a janela modal da V1 (substitui o `Modal` legacy).\r\n *\r\n * Usa o [<dialog>](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog)\r\n * do browser: fundo escurecido, Esc para fechar, o teclado fica dentro da\r\n * janela e, ao fechar, volta ao sítio onde estava.\r\n *\r\n * O tamanho adapta-se ao ecrã só com CSS: nunca passa a largura nem a altura\r\n * da janela do browser (com uma margem), e acompanha-a quando é\r\n * redimensionada. O que não couber faz scroll no corpo; o cabeçalho e o\r\n * rodapé ficam sempre visíveis.\r\n */\r\nexport default function Dialog({\r\n open,\r\n onClose,\r\n title,\r\n subtitle,\r\n footer,\r\n size = 'md',\r\n height = 'auto',\r\n closeOnBackdrop = true,\r\n closeLabel = 'Fechar',\r\n flush = false,\r\n children,\r\n}: DialogProps) {\r\n const ref = useRef<HTMLDialogElement>(null)\r\n const [container, setContainer] = useState<HTMLDialogElement | null>(null)\r\n const titleId = useId()\r\n\r\n useEffect(() => {\r\n setContainer(ref.current)\r\n }, [])\r\n // Clique fora: só conta se começou e acabou no fundo (arrastar a partir de um\r\n // campo para fora não fecha a janela).\r\n const pressedBackdrop = useRef(false)\r\n\r\n useEffect(() => {\r\n const dialog = ref.current\r\n if (!dialog) return\r\n if (open && !dialog.open) dialog.showModal()\r\n if (!open && dialog.open) dialog.close()\r\n }, [open])\r\n\r\n // A página por trás não faz scroll enquanto a janela está aberta.\r\n useEffect(() => {\r\n if (!open) return\r\n const html = document.documentElement\r\n const before = html.style.overflow\r\n html.style.overflow = 'hidden'\r\n return () => {\r\n html.style.overflow = before\r\n }\r\n }, [open])\r\n\r\n return (\r\n <dialog\r\n ref={ref}\r\n aria-labelledby={titleId}\r\n // Esc: o browser fecharia sozinho; quem decide é a app.\r\n onCancel={(e) => {\r\n e.preventDefault()\r\n onClose()\r\n }}\r\n onPointerDown={(e) => {\r\n pressedBackdrop.current = e.target === e.currentTarget\r\n }}\r\n onClick={(e) => {\r\n if (closeOnBackdrop && pressedBackdrop.current && e.target === e.currentTarget) onClose()\r\n }}\r\n className={\r\n `m-auto w-[calc(100vw-2*var(--spacing-dialog-margin))] ${WIDTHS[size]} ` +\r\n 'max-h-[calc(100dvh-2*var(--spacing-dialog-margin))] overflow-hidden rounded-2xl border-0 bg-card p-0 text-foreground shadow-modal ' +\r\n `open:flex open:flex-col ${height === 'full' ? 'h-[calc(100dvh-2*var(--spacing-dialog-margin))]' : ''} ` +\r\n 'backdrop:bg-black/40 motion-safe:open:animate-dialog-in motion-safe:backdrop:animate-backdrop-in'\r\n }\r\n >\r\n <header className=\"flex flex-none items-center justify-between gap-3 bg-gradient-to-br from-primary to-primary-strong px-5 py-3.5\">\r\n <div className=\"min-w-0\">\r\n <h2 id={titleId} className=\"m-0 truncate text-title font-bold text-primary-foreground\">\r\n {title}\r\n </h2>\r\n {subtitle && <p className=\"m-0 mt-0.5 truncate text-caption text-primary-foreground/75\">{subtitle}</p>}\r\n </div>\r\n <button\r\n type=\"button\"\r\n aria-label={closeLabel}\r\n title={closeLabel}\r\n onClick={onClose}\r\n className=\"flex h-7 w-7 flex-none cursor-pointer items-center justify-center rounded-md border border-primary-foreground/25 bg-primary-foreground/15 text-base leading-none text-primary-foreground transition-colors hover:bg-primary-foreground/25 focus-visible:ring-2 focus-visible:ring-primary-foreground/60 focus-visible:outline-none\"\r\n >\r\n ×\r\n </button>\r\n </header>\r\n\r\n <DialogContainerContext.Provider value={container}>\r\n <div className={flush ? 'flex min-h-0 flex-1 flex-col overflow-hidden bg-canvas' : 'min-h-0 flex-1 overflow-y-auto bg-canvas px-5 py-4'}>{children}</div>\r\n\r\n {footer && <footer className=\"flex flex-none flex-wrap justify-end gap-2 border-t border-border bg-muted/40 px-5 py-[18px]\">{footer}</footer>}\r\n </DialogContainerContext.Provider>\r\n </dialog>\r\n )\r\n}\r\n"],"names":[],"mappings":";;AAEA,MAAM,yBAAyB,cAAkC,IAAI;AAU9D,MAAM,qBAAqB,MAAM,WAAW,sBAAsB;AAgCzE,MAAM,SAAS,EAAE,IAAI,mBAAmB,IAAI,mBAAmB,IAAI,kBAAA;AAiBnE,SAAwB,OAAO;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,SAAS;AAAA,EACT,kBAAkB;AAAA,EAClB,aAAa;AAAA,EACb,QAAQ;AAAA,EACR;AACF,GAAgB;AACd,QAAM,MAAM,OAA0B,IAAI;AAC1C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAmC,IAAI;AACzE,QAAM,UAAU,MAAA;AAEhB,YAAU,MAAM;AACd,iBAAa,IAAI,OAAO;AAAA,EAC1B,GAAG,CAAA,CAAE;AAGL,QAAM,kBAAkB,OAAO,KAAK;AAEpC,YAAU,MAAM;AACd,UAAM,SAAS,IAAI;AACnB,QAAI,CAAC,OAAQ;AACb,QAAI,QAAQ,CAAC,OAAO,aAAa,UAAA;AACjC,QAAI,CAAC,QAAQ,OAAO,aAAa,MAAA;AAAA,EACnC,GAAG,CAAC,IAAI,CAAC;AAGT,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,OAAO,SAAS;AACtB,UAAM,SAAS,KAAK,MAAM;AAC1B,SAAK,MAAM,WAAW;AACtB,WAAO,MAAM;AACX,WAAK,MAAM,WAAW;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAET,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,mBAAiB;AAAA,MAEjB,UAAU,CAAC,MAAM;AACf,UAAE,eAAA;AACF,gBAAA;AAAA,MACF;AAAA,MACA,eAAe,CAAC,MAAM;AACpB,wBAAgB,UAAU,EAAE,WAAW,EAAE;AAAA,MAC3C;AAAA,MACA,SAAS,CAAC,MAAM;AACd,YAAI,mBAAmB,gBAAgB,WAAW,EAAE,WAAW,EAAE,cAAe,SAAA;AAAA,MAClF;AAAA,MACA,WACE,yDAAyD,OAAO,IAAI,CAAC,8JAE1C,WAAW,SAAS,oDAAoD,EAAE;AAAA,MAIvG,UAAA;AAAA,QAAA,qBAAC,UAAA,EAAO,WAAU,kHAChB,UAAA;AAAA,UAAA,qBAAC,OAAA,EAAI,WAAU,WACb,UAAA;AAAA,YAAA,oBAAC,MAAA,EAAG,IAAI,SAAS,WAAU,6DACxB,UAAA,OACH;AAAA,YACC,YAAY,oBAAC,KAAA,EAAE,WAAU,+DAA+D,UAAA,SAAA,CAAS;AAAA,UAAA,GACpG;AAAA,UACA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY;AAAA,cACZ,OAAO;AAAA,cACP,SAAS;AAAA,cACT,WAAU;AAAA,cACX,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED,GACF;AAAA,QAEA,qBAAC,uBAAuB,UAAvB,EAAgC,OAAO,WACtC,UAAA;AAAA,UAAA,oBAAC,OAAA,EAAI,WAAW,QAAQ,2DAA2D,sDAAuD,UAAS;AAAA,UAElJ,UAAU,oBAAC,UAAA,EAAO,WAAU,gGAAgG,UAAA,OAAA,CAAO;AAAA,QAAA,EAAA,CACtI;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
function Svg({ size = 16, className, children, fill = "none" }) {
|
|
3
|
+
return /* @__PURE__ */ jsx(
|
|
4
|
+
"svg",
|
|
5
|
+
{
|
|
6
|
+
width: size,
|
|
7
|
+
height: size,
|
|
8
|
+
viewBox: "0 0 24 24",
|
|
9
|
+
fill,
|
|
10
|
+
stroke: fill === "none" ? "currentColor" : "none",
|
|
11
|
+
strokeWidth: "1.8",
|
|
12
|
+
strokeLinecap: "round",
|
|
13
|
+
strokeLinejoin: "round",
|
|
14
|
+
className,
|
|
15
|
+
"aria-hidden": true,
|
|
16
|
+
children
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
function QrCodeIcon(props) {
|
|
21
|
+
return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
|
|
22
|
+
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "3.5", width: "6.5", height: "6.5", rx: "1.3" }),
|
|
23
|
+
/* @__PURE__ */ jsx("rect", { x: "14", y: "3.5", width: "6.5", height: "6.5", rx: "1.3" }),
|
|
24
|
+
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "14", width: "6.5", height: "6.5", rx: "1.3" }),
|
|
25
|
+
/* @__PURE__ */ jsx("path", { d: "M14 14h3.3v3.3M20.5 14v.01M14 20.5h.01M17.3 20.5h3.2v-3.2" })
|
|
26
|
+
] });
|
|
27
|
+
}
|
|
28
|
+
function SparklesIcon(props) {
|
|
29
|
+
return /* @__PURE__ */ jsxs(Svg, { ...props, fill: "currentColor", children: [
|
|
30
|
+
/* @__PURE__ */ jsx("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" }),
|
|
31
|
+
/* @__PURE__ */ jsx("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" })
|
|
32
|
+
] });
|
|
33
|
+
}
|
|
34
|
+
function PrefilledIcon(props) {
|
|
35
|
+
return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
|
|
36
|
+
/* @__PURE__ */ jsx("rect", { x: "4", y: "3.5", width: "16", height: "17", rx: "2" }),
|
|
37
|
+
/* @__PURE__ */ jsx("path", { d: "M7.5 8.5h9M7.5 12h9M7.5 15.5h5.5" })
|
|
38
|
+
] });
|
|
39
|
+
}
|
|
40
|
+
function LockIcon(props) {
|
|
41
|
+
return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
|
|
42
|
+
/* @__PURE__ */ jsx("rect", { x: "5", y: "10.5", width: "14", height: "10", rx: "2" }),
|
|
43
|
+
/* @__PURE__ */ jsx("path", { d: "M8.5 10.5V7.5a3.5 3.5 0 0 1 7 0v3" }),
|
|
44
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "15.5", r: "1.1", fill: "currentColor", stroke: "none" })
|
|
45
|
+
] });
|
|
46
|
+
}
|
|
47
|
+
function InfoIcon(props) {
|
|
48
|
+
return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
|
|
49
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9.5" }),
|
|
50
|
+
/* @__PURE__ */ jsx("path", { d: "M12 11v5.5" }),
|
|
51
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "7.8", r: "1.1", fill: "currentColor", stroke: "none" })
|
|
52
|
+
] });
|
|
53
|
+
}
|
|
54
|
+
function SearchIcon(props) {
|
|
55
|
+
return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
|
|
56
|
+
/* @__PURE__ */ jsx("circle", { cx: "10.5", cy: "10.5", r: "6.5" }),
|
|
57
|
+
/* @__PURE__ */ jsx("path", { d: "M15.5 15.5L20 20" })
|
|
58
|
+
] });
|
|
59
|
+
}
|
|
60
|
+
function CheckIcon(props) {
|
|
61
|
+
return /* @__PURE__ */ jsx(Svg, { ...props, children: /* @__PURE__ */ jsx("path", { d: "M4.5 12.5l5 5 10-11" }) });
|
|
62
|
+
}
|
|
63
|
+
function ChevronDownIcon(props) {
|
|
64
|
+
return /* @__PURE__ */ jsx(Svg, { ...props, children: /* @__PURE__ */ jsx("path", { d: "M6 9.5l6 6 6-6" }) });
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
CheckIcon,
|
|
68
|
+
ChevronDownIcon,
|
|
69
|
+
InfoIcon,
|
|
70
|
+
LockIcon,
|
|
71
|
+
PrefilledIcon,
|
|
72
|
+
QrCodeIcon,
|
|
73
|
+
SearchIcon,
|
|
74
|
+
SparklesIcon
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=icons.js.map
|
|
@@ -0,0 +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}\r\n\r\nfunction Svg({ size = 16, className, 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=\"1.8\"\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"],"names":[],"mappings":";AAaA,SAAS,IAAI,EAAE,OAAO,IAAI,WAAW,UAAU,OAAO,UAAoE;AACxH,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAQ;AAAA,MACR;AAAA,MACA,QAAQ,SAAS,SAAS,iBAAiB;AAAA,MAC3C,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA,MACf;AAAA,MACA,eAAW;AAAA,MAEV;AAAA,IAAA;AAAA,EAAA;AAGP;AAGO,SAAS,WAAW,OAAkB;AAC3C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,OAAM,GAAE,OAAM,OAAM,OAAM,QAAO,OAAM,IAAG,MAAA,CAAM;AAAA,IACxD,oBAAC,QAAA,EAAK,GAAE,MAAK,GAAE,OAAM,OAAM,OAAM,QAAO,OAAM,IAAG,MAAA,CAAM;AAAA,IACvD,oBAAC,QAAA,EAAK,GAAE,OAAM,GAAE,MAAK,OAAM,OAAM,QAAO,OAAM,IAAG,MAAA,CAAM;AAAA,IACvD,oBAAC,QAAA,EAAK,GAAE,4DAAA,CAA4D;AAAA,EAAA,GACtE;AAEJ;AAGO,SAAS,aAAa,OAAkB;AAC7C,SACE,qBAAC,KAAA,EAAK,GAAG,OAAO,MAAK,gBACnB,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,oEAAA,CAAoE;AAAA,IAC5E,oBAAC,QAAA,EAAK,GAAE,2EAAA,CAA2E;AAAA,EAAA,GACrF;AAEJ;AAGO,SAAS,cAAc,OAAkB;AAC9C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,OAAM,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,IAClD,oBAAC,QAAA,EAAK,GAAE,mCAAA,CAAmC;AAAA,EAAA,GAC7C;AAEJ;AAGO,SAAS,SAAS,OAAkB;AACzC,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,QAAO,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,IACnD,oBAAC,QAAA,EAAK,GAAE,oCAAA,CAAoC;AAAA,IAC5C,oBAAC,UAAA,EAAO,IAAG,MAAK,IAAG,QAAO,GAAE,OAAM,MAAK,gBAAe,QAAO,OAAA,CAAO;AAAA,EAAA,GACtE;AAEJ;AAGO,SAAS,SAAS,OAAkB;AACzC,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,OAAM;AAAA,IAChC,oBAAC,QAAA,EAAK,GAAE,aAAA,CAAa;AAAA,IACrB,oBAAC,UAAA,EAAO,IAAG,MAAK,IAAG,OAAM,GAAE,OAAM,MAAK,gBAAe,QAAO,OAAA,CAAO;AAAA,EAAA,GACrE;AAEJ;AAEO,SAAS,WAAW,OAAkB;AAC3C,SACE,qBAAC,KAAA,EAAK,GAAG,OACP,UAAA;AAAA,IAAA,oBAAC,YAAO,IAAG,QAAO,IAAG,QAAO,GAAE,OAAM;AAAA,IACpC,oBAAC,QAAA,EAAK,GAAE,mBAAA,CAAmB;AAAA,EAAA,GAC7B;AAEJ;AAEO,SAAS,UAAU,OAAkB;AAC1C,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,uBAAsB,EAAA,CAChC;AAEJ;AAEO,SAAS,gBAAgB,OAAkB;AAChD,SACE,oBAAC,OAAK,GAAG,OACP,8BAAC,QAAA,EAAK,GAAE,kBAAiB,EAAA,CAC3B;AAEJ;"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
const VARIANTS = {
|
|
4
|
+
primary: "min-w-[120px] border-transparent bg-primary font-semibold text-primary-foreground hover:bg-primary/90",
|
|
5
|
+
secondary: "min-w-[100px] border-border bg-card font-medium text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
6
|
+
};
|
|
7
|
+
const Button = forwardRef(function Button2({ variant = "primary", icon, loading, disabled, type = "button", className = "", children, ...props }, ref) {
|
|
8
|
+
return /* @__PURE__ */ jsxs(
|
|
9
|
+
"button",
|
|
10
|
+
{
|
|
11
|
+
ref,
|
|
12
|
+
type,
|
|
13
|
+
disabled: disabled || loading,
|
|
14
|
+
"aria-busy": loading || void 0,
|
|
15
|
+
className: `inline-flex h-9 cursor-pointer items-center justify-center gap-1.5 rounded-lg border px-5 text-control transition-colors duration-150 focus-visible:ring-3 focus-visible:ring-primary/20 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 ${VARIANTS[variant]} ${className}`,
|
|
16
|
+
...props,
|
|
17
|
+
children: [
|
|
18
|
+
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,
|
|
19
|
+
children
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
export {
|
|
25
|
+
Button as default
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=Button.js.map
|
|
@@ -0,0 +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 /** `primary`: a ação principal (navy, uma por ecrã). `secondary`: as outras (ex: Fechar). */\r\n variant?: 'primary' | 'secondary'\r\n /** Ícone antes do texto (ex: `<CheckIcon size={13} />`). */\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: 'min-w-[120px] border-transparent bg-primary font-semibold text-primary-foreground hover:bg-primary/90',\r\n secondary: 'min-w-[100px] border-border bg-card font-medium text-muted-foreground hover:bg-muted hover:text-foreground',\r\n}\r\n\r\n/**\r\n * Botão de ação (ex: Confirmar, Fechar). Por omissão não submete formulários\r\n * (`type=\"button\"`); para submeter, passar `type=\"submit\"`.\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\nconst Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(\r\n { variant = 'primary', icon, loading, disabled, type = 'button', className = '', children, ...props },\r\n ref,\r\n) {\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 className={\r\n 'inline-flex h-9 cursor-pointer items-center justify-center gap-1.5 rounded-lg border px-5 text-control transition-colors duration-150 ' +\r\n 'focus-visible:ring-3 focus-visible:ring-primary/20 focus-visible:outline-none ' +\r\n `disabled:cursor-not-allowed disabled:opacity-50 ${VARIANTS[variant]} ${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":";;AAWA,MAAM,WAAW;AAAA,EACf,SAAS;AAAA,EACT,WAAW;AACb;AASA,MAAM,SAAS,WAA2C,SAASA,QACjE,EAAE,UAAU,WAAW,MAAM,SAAS,UAAU,OAAO,UAAU,YAAY,IAAI,UAAU,GAAG,MAAA,GAC9F,KACA;AACA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,UAAU,YAAY;AAAA,MACtB,aAAW,WAAW;AAAA,MACtB,WACE,uQAEmD,SAAS,OAAO,CAAC,IAAI,SAAS;AAAA,MAElF,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,137 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useRef, useEffect, useCallback } from "react";
|
|
3
|
+
import { loadPdfjs } from "./pdfjs.js";
|
|
4
|
+
const DEFAULT_ASPECT = 0.707;
|
|
5
|
+
async function renderPage(pdf, pageNum, maxSide = 1200) {
|
|
6
|
+
const page = await pdf.getPage(pageNum);
|
|
7
|
+
const base = page.getViewport({ scale: 1 });
|
|
8
|
+
const scale = Math.min(3, Math.max(1, maxSide / Math.max(base.width, base.height)));
|
|
9
|
+
const viewport = page.getViewport({ scale });
|
|
10
|
+
const canvas = document.createElement("canvas");
|
|
11
|
+
canvas.width = Math.ceil(viewport.width);
|
|
12
|
+
canvas.height = Math.ceil(viewport.height);
|
|
13
|
+
const ctx = canvas.getContext("2d");
|
|
14
|
+
ctx.fillStyle = "#fff";
|
|
15
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
16
|
+
await page.render({ canvasContext: ctx, viewport }).promise;
|
|
17
|
+
return canvas.toDataURL("image/jpeg", 0.85);
|
|
18
|
+
}
|
|
19
|
+
function PdfPreview({ file, label, initialFirstPage, className = "" }) {
|
|
20
|
+
const [pdf, setPdf] = useState(null);
|
|
21
|
+
const [numPages, setNumPages] = useState(0);
|
|
22
|
+
const [aspect, setAspect] = useState(null);
|
|
23
|
+
const [imgByPage, setImgByPage] = useState(initialFirstPage ? { 1: initialFirstPage } : {});
|
|
24
|
+
const [failed, setFailed] = useState(false);
|
|
25
|
+
const scrollRef = useRef(null);
|
|
26
|
+
const slotRefs = useRef([]);
|
|
27
|
+
const requested = useRef(new Set(initialFirstPage ? [1] : []));
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
let alive = true;
|
|
30
|
+
let opened = null;
|
|
31
|
+
let idleId = 0;
|
|
32
|
+
setPdf(null);
|
|
33
|
+
setNumPages(0);
|
|
34
|
+
setAspect(null);
|
|
35
|
+
setFailed(false);
|
|
36
|
+
setImgByPage({});
|
|
37
|
+
requested.current = /* @__PURE__ */ new Set();
|
|
38
|
+
slotRefs.current = [];
|
|
39
|
+
const open = async () => {
|
|
40
|
+
try {
|
|
41
|
+
const { getDocument } = await loadPdfjs();
|
|
42
|
+
const data = new Uint8Array(await file.arrayBuffer());
|
|
43
|
+
const doc = await getDocument({ data }).promise;
|
|
44
|
+
if (!alive) {
|
|
45
|
+
doc.destroy();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
opened = doc;
|
|
49
|
+
setPdf(doc);
|
|
50
|
+
setNumPages(doc.numPages);
|
|
51
|
+
const { width, height } = (await doc.getPage(1)).getViewport({ scale: 1 });
|
|
52
|
+
if (alive && height > 0) setAspect(width / height);
|
|
53
|
+
} catch {
|
|
54
|
+
if (alive) setFailed(true);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const timer = window.setTimeout(() => {
|
|
58
|
+
if (typeof requestIdleCallback === "function") idleId = requestIdleCallback(open, { timeout: 1200 });
|
|
59
|
+
else open();
|
|
60
|
+
}, 500);
|
|
61
|
+
return () => {
|
|
62
|
+
alive = false;
|
|
63
|
+
opened?.destroy();
|
|
64
|
+
window.clearTimeout(timer);
|
|
65
|
+
if (idleId && typeof cancelIdleCallback === "function") cancelIdleCallback(idleId);
|
|
66
|
+
};
|
|
67
|
+
}, [file]);
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (!initialFirstPage) return;
|
|
70
|
+
requested.current.add(1);
|
|
71
|
+
setImgByPage((cur) => cur[1] ? cur : { ...cur, 1: initialFirstPage });
|
|
72
|
+
}, [initialFirstPage]);
|
|
73
|
+
const requestPage = useCallback(
|
|
74
|
+
(p) => {
|
|
75
|
+
if (!pdf || requested.current.has(p)) return;
|
|
76
|
+
requested.current.add(p);
|
|
77
|
+
renderPage(pdf, p).then((url) => setImgByPage((cur) => ({ ...cur, [p]: url }))).catch(() => {
|
|
78
|
+
requested.current.delete(p);
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
[pdf]
|
|
82
|
+
);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (!pdf || !numPages) return;
|
|
85
|
+
const io = new IntersectionObserver(
|
|
86
|
+
(entries) => {
|
|
87
|
+
for (const e of entries) {
|
|
88
|
+
if (!e.isIntersecting) continue;
|
|
89
|
+
requestPage(Number(e.target.dataset.page));
|
|
90
|
+
io.unobserve(e.target);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
{ root: scrollRef.current, rootMargin: "400px 0px" }
|
|
94
|
+
);
|
|
95
|
+
slotRefs.current.forEach((el) => el && io.observe(el));
|
|
96
|
+
return () => io.disconnect();
|
|
97
|
+
}, [pdf, numPages, requestPage]);
|
|
98
|
+
const count = numPages || 1;
|
|
99
|
+
const slotAspect = aspect ?? DEFAULT_ASPECT;
|
|
100
|
+
if (failed) {
|
|
101
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex h-full w-full flex-col items-center justify-center gap-2.5 bg-card text-muted-foreground ${className}`, children: [
|
|
102
|
+
/* @__PURE__ */ jsxs("svg", { width: "44", height: "44", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", "aria-hidden": true, children: [
|
|
103
|
+
/* @__PURE__ */ jsx("path", { d: "M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7z", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
104
|
+
/* @__PURE__ */ jsx("path", { d: "M14 2v5h5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
105
|
+
] }),
|
|
106
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", children: label })
|
|
107
|
+
] });
|
|
108
|
+
}
|
|
109
|
+
return /* @__PURE__ */ jsx(
|
|
110
|
+
"div",
|
|
111
|
+
{
|
|
112
|
+
ref: scrollRef,
|
|
113
|
+
className: `flex h-full min-h-0 w-full flex-col items-center gap-3.5 overflow-x-hidden overflow-y-auto bg-card px-4 pt-3.5 pb-[18px] [&::-webkit-scrollbar]:w-2.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:border-2 [&::-webkit-scrollbar-thumb]:border-solid [&::-webkit-scrollbar-thumb]:border-transparent [&::-webkit-scrollbar-thumb]:bg-scrollbar [&::-webkit-scrollbar-thumb]:bg-clip-padding [&::-webkit-scrollbar-thumb:hover]:bg-scrollbar-hover ${className}`,
|
|
114
|
+
children: Array.from({ length: count }, (_, i) => {
|
|
115
|
+
const p = i + 1;
|
|
116
|
+
const url = imgByPage[p];
|
|
117
|
+
return /* @__PURE__ */ jsx(
|
|
118
|
+
"div",
|
|
119
|
+
{
|
|
120
|
+
ref: (el) => {
|
|
121
|
+
slotRefs.current[i] = el;
|
|
122
|
+
},
|
|
123
|
+
"data-page": p,
|
|
124
|
+
style: { aspectRatio: String(slotAspect) },
|
|
125
|
+
className: "flex w-full flex-none items-center justify-center overflow-hidden rounded border border-border bg-white shadow-page",
|
|
126
|
+
children: url ? /* @__PURE__ */ jsx("img", { src: url, alt: `${label} — ${p}/${count}`, className: "block h-full w-full object-contain" }) : /* @__PURE__ */ jsx("span", { role: "status", "aria-label": label, className: "inline-block h-[22px] w-[22px] animate-spin rounded-full border-[2.5px] border-primary/20 border-t-primary" })
|
|
127
|
+
},
|
|
128
|
+
p
|
|
129
|
+
);
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
export {
|
|
135
|
+
PdfPreview as default
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=PdfPreview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PdfPreview.js","sources":["../../../../../../src/v1/primitives/documents/PdfPreview/PdfPreview.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react'\r\nimport type { PDFDocumentProxy } from 'pdfjs-dist'\r\nimport { loadPdfjs } from './pdfjs'\r\n\r\nexport interface PdfPreviewProps {\r\n file: File\r\n /** Texto alternativo das páginas e mensagem quando o PDF não abre. */\r\n label: string\r\n /** Imagem da 1.ª página já renderizada pela app, para aparecer de imediato. */\r\n initialFirstPage?: string\r\n className?: string\r\n}\r\n\r\n// Proporção A4 vertical, usada até se saber o tamanho real da página.\r\nconst DEFAULT_ASPECT = 0.707\r\n\r\nasync function renderPage(pdf: PDFDocumentProxy, pageNum: number, maxSide = 1200): Promise<string> {\r\n const page = await pdf.getPage(pageNum)\r\n const base = page.getViewport({ scale: 1 })\r\n const scale = Math.min(3, Math.max(1, maxSide / Math.max(base.width, base.height)))\r\n const viewport = page.getViewport({ scale })\r\n const canvas = document.createElement('canvas')\r\n canvas.width = Math.ceil(viewport.width)\r\n canvas.height = Math.ceil(viewport.height)\r\n const ctx = canvas.getContext('2d')!\r\n ctx.fillStyle = '#fff'\r\n ctx.fillRect(0, 0, canvas.width, canvas.height)\r\n await page.render({ canvasContext: ctx, viewport }).promise\r\n return canvas.toDataURL('image/jpeg', 0.85)\r\n}\r\n\r\n/**\r\n * Pré-visualização de PDF com pdf.js: as páginas em coluna, com scroll vertical\r\n * e sem a barra de ferramentas do visualizador nativo (que transborda em caixas\r\n * estreitas). Cada página só é renderizada quando se aproxima da área visível.\r\n *\r\n * **Usado por:** [DocumentDropzone](?path=/docs/v1-components-documents-documentdropzone--docs) (quando o ficheiro é um PDF).\r\n */\r\nexport default function PdfPreview({ file, label, initialFirstPage, className = '' }: PdfPreviewProps) {\r\n const [pdf, setPdf] = useState<PDFDocumentProxy | null>(null)\r\n const [numPages, setNumPages] = useState(0)\r\n const [aspect, setAspect] = useState<number | null>(null)\r\n const [imgByPage, setImgByPage] = useState<Record<number, string>>(initialFirstPage ? { 1: initialFirstPage } : {})\r\n const [failed, setFailed] = useState(false)\r\n\r\n const scrollRef = useRef<HTMLDivElement>(null)\r\n const slotRefs = useRef<(HTMLDivElement | null)[]>([])\r\n const requested = useRef<Set<number>>(new Set(initialFirstPage ? [1] : []))\r\n\r\n useEffect(() => {\r\n let alive = true\r\n let opened: PDFDocumentProxy | null = null\r\n let idleId = 0\r\n setPdf(null)\r\n setNumPages(0)\r\n setAspect(null)\r\n setFailed(false)\r\n // Não semear a página 1 com initialFirstPage aqui: ao mudar de ficheiro, a\r\n // prop ainda traz a imagem do anterior. O efeito seguinte adota-a quando chegar.\r\n setImgByPage({})\r\n requested.current = new Set()\r\n slotRefs.current = []\r\n\r\n const open = async () => {\r\n try {\r\n const { getDocument } = await loadPdfjs()\r\n const data = new Uint8Array(await file.arrayBuffer())\r\n const doc = await getDocument({ data }).promise\r\n if (!alive) {\r\n doc.destroy()\r\n return\r\n }\r\n opened = doc\r\n setPdf(doc)\r\n setNumPages(doc.numPages)\r\n const { width, height } = (await doc.getPage(1)).getViewport({ scale: 1 })\r\n if (alive && height > 0) setAspect(width / height)\r\n } catch {\r\n if (alive) setFailed(true)\r\n }\r\n }\r\n\r\n // O parse corre na thread principal: espera que a animação de entrada acabe\r\n // e que a página fique livre, com um limite para nunca ficar parado.\r\n const timer = window.setTimeout(() => {\r\n if (typeof requestIdleCallback === 'function') idleId = requestIdleCallback(open, { timeout: 1200 })\r\n else open()\r\n }, 500)\r\n\r\n return () => {\r\n alive = false\r\n opened?.destroy()\r\n window.clearTimeout(timer)\r\n if (idleId && typeof cancelIdleCallback === 'function') cancelIdleCallback(idleId)\r\n }\r\n }, [file])\r\n\r\n useEffect(() => {\r\n if (!initialFirstPage) return\r\n requested.current.add(1)\r\n setImgByPage((cur) => (cur[1] ? cur : { ...cur, 1: initialFirstPage }))\r\n }, [initialFirstPage])\r\n\r\n const requestPage = useCallback(\r\n (p: number) => {\r\n if (!pdf || requested.current.has(p)) return\r\n requested.current.add(p)\r\n renderPage(pdf, p)\r\n .then((url) => setImgByPage((cur) => ({ ...cur, [p]: url })))\r\n .catch(() => {\r\n requested.current.delete(p)\r\n })\r\n },\r\n [pdf],\r\n )\r\n\r\n useEffect(() => {\r\n if (!pdf || !numPages) return\r\n const io = new IntersectionObserver(\r\n (entries) => {\r\n for (const e of entries) {\r\n if (!e.isIntersecting) continue\r\n requestPage(Number((e.target as HTMLElement).dataset.page))\r\n io.unobserve(e.target)\r\n }\r\n },\r\n { root: scrollRef.current, rootMargin: '400px 0px' },\r\n )\r\n slotRefs.current.forEach((el) => el && io.observe(el))\r\n return () => io.disconnect()\r\n }, [pdf, numPages, requestPage])\r\n\r\n const count = numPages || 1\r\n const slotAspect = aspect ?? DEFAULT_ASPECT\r\n\r\n if (failed) {\r\n return (\r\n <div className={`flex h-full w-full flex-col items-center justify-center gap-2.5 bg-card text-muted-foreground ${className}`}>\r\n <svg width=\"44\" height=\"44\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" aria-hidden>\r\n <path d=\"M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7z\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n <path d=\"M14 2v5h5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n <span className=\"text-xs\">{label}</span>\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div\r\n ref={scrollRef}\r\n className={`flex h-full min-h-0 w-full flex-col items-center gap-3.5 overflow-x-hidden overflow-y-auto bg-card px-4 pt-3.5 pb-[18px] [&::-webkit-scrollbar]:w-2.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:border-2 [&::-webkit-scrollbar-thumb]:border-solid [&::-webkit-scrollbar-thumb]:border-transparent [&::-webkit-scrollbar-thumb]:bg-scrollbar [&::-webkit-scrollbar-thumb]:bg-clip-padding [&::-webkit-scrollbar-thumb:hover]:bg-scrollbar-hover ${className}`}\r\n >\r\n {Array.from({ length: count }, (_, i) => {\r\n const p = i + 1\r\n const url = imgByPage[p]\r\n return (\r\n <div\r\n key={p}\r\n ref={(el) => {\r\n slotRefs.current[i] = el\r\n }}\r\n data-page={p}\r\n style={{ aspectRatio: String(slotAspect) }}\r\n className=\"flex w-full flex-none items-center justify-center overflow-hidden rounded border border-border bg-white shadow-page\"\r\n >\r\n {url ? (\r\n <img src={url} alt={`${label} — ${p}/${count}`} className=\"block h-full w-full object-contain\" />\r\n ) : (\r\n <span role=\"status\" aria-label={label} className=\"inline-block h-[22px] w-[22px] animate-spin rounded-full border-[2.5px] border-primary/20 border-t-primary\" />\r\n )}\r\n </div>\r\n )\r\n })}\r\n </div>\r\n )\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
let workerSrc = null;
|
|
2
|
+
let loaded = null;
|
|
3
|
+
let loading = null;
|
|
4
|
+
function configurePdfWorker(src) {
|
|
5
|
+
workerSrc = src;
|
|
6
|
+
if (loaded) loaded.GlobalWorkerOptions.workerSrc = src;
|
|
7
|
+
}
|
|
8
|
+
function loadPdfjs() {
|
|
9
|
+
if (!loading) {
|
|
10
|
+
loading = import("pdfjs-dist").then((pdfjs) => {
|
|
11
|
+
if (typeof pdfjs.getDocument !== "function") throw new Error("pdfjs-dist indisponível");
|
|
12
|
+
if (workerSrc) pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;
|
|
13
|
+
loaded = pdfjs;
|
|
14
|
+
return pdfjs;
|
|
15
|
+
}).catch((e) => {
|
|
16
|
+
loading = null;
|
|
17
|
+
throw e;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return loading;
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
configurePdfWorker,
|
|
24
|
+
loadPdfjs
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=pdfjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdfjs.js","sources":["../../../../../../src/v1/primitives/documents/PdfPreview/pdfjs.ts"],"sourcesContent":["import type * as PdfJs from 'pdfjs-dist'\r\n\r\ntype PdfJsModule = typeof PdfJs\r\n\r\nlet workerSrc: string | null = null\r\nlet loaded: PdfJsModule | null = null\r\nlet loading: Promise<PdfJsModule> | null = null\r\n\r\n/**\r\n * Indica ao pdf.js onde está o worker (`pdf.worker.min.mjs`) servido pela app.\r\n * Chamar uma vez no arranque. Se a app já define `GlobalWorkerOptions.workerSrc`\r\n * pela sua própria cópia do pdf.js (a mesma, quando deduplicada), não é preciso.\r\n */\r\nexport function configurePdfWorker(src: string) {\r\n workerSrc = src\r\n if (loaded) loaded.GlobalWorkerOptions.workerSrc = src\r\n}\r\n\r\n/** Carrega o pdf.js só quando há um PDF para mostrar; depois fica em cache. */\r\nexport function loadPdfjs(): Promise<PdfJsModule> {\r\n if (!loading) {\r\n loading = import('pdfjs-dist')\r\n .then((pdfjs) => {\r\n // Salvaguarda: se o pdf.js não chegar (ex: ambiente sem ele), cai no ícone.\r\n if (typeof pdfjs.getDocument !== 'function') throw new Error('pdfjs-dist indisponível')\r\n if (workerSrc) pdfjs.GlobalWorkerOptions.workerSrc = workerSrc\r\n loaded = pdfjs\r\n return pdfjs\r\n })\r\n .catch((e) => {\r\n loading = null\r\n throw e\r\n })\r\n }\r\n return loading\r\n}\r\n"],"names":[],"mappings":"AAIA,IAAI,YAA2B;AAC/B,IAAI,SAA6B;AACjC,IAAI,UAAuC;AAOpC,SAAS,mBAAmB,KAAa;AAC9C,cAAY;AACZ,MAAI,OAAQ,QAAO,oBAAoB,YAAY;AACrD;AAGO,SAAS,YAAkC;AAChD,MAAI,CAAC,SAAS;AACZ,cAAU,OAAO,YAAY,EAC1B,KAAK,CAAC,UAAU;AAEf,UAAI,OAAO,MAAM,gBAAgB,WAAY,OAAM,IAAI,MAAM,yBAAyB;AACtF,UAAI,UAAW,OAAM,oBAAoB,YAAY;AACrD,eAAS;AACT,aAAO;AAAA,IACT,CAAC,EACA,MAAM,CAAC,MAAM;AACZ,gBAAU;AACV,YAAM;AAAA,IACR,CAAC;AAAA,EACL;AACA,SAAO;AACT;"}
|