@12-apps/ui 6.6.0 → 6.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-QLBYAYUG.js → chunk-KR2BP7NK.js} +4 -4
- package/dist/chunk-KR2BP7NK.js.map +1 -0
- package/dist/{chunk-DFVRZ3UK.js → chunk-KXARS46L.js} +3 -3
- package/dist/chunk-KXARS46L.js.map +1 -0
- package/dist/{chunk-JP55QWVR.js → chunk-L7L6SX64.js} +5 -2
- package/dist/chunk-L7L6SX64.js.map +1 -0
- package/dist/{chunk-QZZVHY6U.js → chunk-PVLDKXKR.js} +7 -3
- package/dist/chunk-PVLDKXKR.js.map +1 -0
- package/dist/{chunk-3KWD5Y5O.js → chunk-RXE5CUUE.js} +8 -4
- package/dist/chunk-RXE5CUUE.js.map +1 -0
- package/dist/{chunk-H7UAGTVW.js → chunk-TSG5C7MP.js} +4 -3
- package/dist/chunk-TSG5C7MP.js.map +1 -0
- package/dist/{chunk-NUCLEOHF.js → chunk-UNM7KFDX.js} +44 -14
- package/dist/chunk-UNM7KFDX.js.map +1 -0
- package/dist/{chunk-CEKPLUQV.js → chunk-UY7UF7IN.js} +19 -13
- package/dist/chunk-UY7UF7IN.js.map +1 -0
- package/dist/data-display/Alert.js +1 -1
- package/dist/data-display/AsyncStateContainer.js +2 -1
- package/dist/data-display/AsyncStateContainer.js.map +1 -1
- package/dist/data-display/Banner.js +4 -2
- package/dist/data-display/Banner.js.map +1 -1
- package/dist/data-display/CardKit.js +3 -1
- package/dist/data-display/CardKit.js.map +1 -1
- package/dist/data-display/Carousel.js +5 -2
- package/dist/data-display/Carousel.js.map +1 -1
- package/dist/data-display/DataGrid.js +1 -1
- package/dist/data-display/DataViews.js +90 -66
- package/dist/data-display/DataViews.js.map +1 -1
- package/dist/data-display/HoverCard.js +4 -1
- package/dist/data-display/HoverCard.js.map +1 -1
- package/dist/data-display/Lightbox.js +147 -117
- package/dist/data-display/Lightbox.js.map +1 -1
- package/dist/data-display/MapPreview.js +14 -10
- package/dist/data-display/MapPreview.js.map +1 -1
- package/dist/data-display/Table.js +4 -2
- package/dist/data-display/Table.js.map +1 -1
- package/dist/data-display/TimingDiagram.js +3 -2
- package/dist/data-display/TimingDiagram.js.map +1 -1
- package/dist/feedback/Sonner.js +5 -4
- package/dist/feedback/Sonner.js.map +1 -1
- package/dist/feedback/StackedModal.js +1 -1
- package/dist/feedback/TutorialOverlay.js +19 -5
- package/dist/feedback/TutorialOverlay.js.map +1 -1
- package/dist/form/AddressAutocomplete.js +16 -8
- package/dist/form/AddressAutocomplete.js.map +1 -1
- package/dist/form/Autocomplete.js +9 -7
- package/dist/form/Autocomplete.js.map +1 -1
- package/dist/form/Calendar.js +1 -1
- package/dist/form/CodeEditor.js +14 -9
- package/dist/form/CodeEditor.js.map +1 -1
- package/dist/form/DateRangePicker.js +10 -3
- package/dist/form/DateRangePicker.js.map +1 -1
- package/dist/form/Menubar.js +4 -1
- package/dist/form/Menubar.js.map +1 -1
- package/dist/form/PasswordStrength.js +48 -28
- package/dist/form/PasswordStrength.js.map +1 -1
- package/dist/form/PhoneInput.js +11 -5
- package/dist/form/PhoneInput.js.map +1 -1
- package/dist/form/SearchPalette.js +4 -1
- package/dist/form/SearchPalette.js.map +1 -1
- package/dist/form/Textarea.js +21 -19
- package/dist/form/Textarea.js.map +1 -1
- package/dist/form/UploadButton.js +16 -11
- package/dist/form/UploadButton.js.map +1 -1
- package/dist/layout/ContentToolbar.js +1 -1
- package/dist/layout/Dashboard.js +2 -1
- package/dist/layout/Dashboard.js.map +1 -1
- package/dist/layout/ScrollArea.js +9 -3
- package/dist/layout/ScrollArea.js.map +1 -1
- package/dist/layout/TableFilter.js +1 -1
- package/dist/navigation/Breadcrumbs.js +9 -3
- package/dist/navigation/Breadcrumbs.js.map +1 -1
- package/dist/navigation/CommandPalette.js +20 -7
- package/dist/navigation/CommandPalette.js.map +1 -1
- package/dist/navigation/Pagination.js +1 -1
- package/dist/navigation/Tabs.js +7 -3
- package/dist/navigation/Tabs.js.map +1 -1
- package/dist/pt-BR.js +192 -5
- package/dist/pt-BR.js.map +1 -1
- package/dist/types/components/data-display/Alert/Alert.d.ts +9 -2
- package/dist/types/components/data-display/Alert/Alert.d.ts.map +1 -1
- package/dist/types/components/data-display/Alert/Alert.types.d.ts +25 -9
- package/dist/types/components/data-display/Alert/Alert.types.d.ts.map +1 -1
- package/dist/types/components/data-display/AsyncStateContainer/AsyncStateContainer.d.ts.map +1 -1
- package/dist/types/components/data-display/AsyncStateContainer/AsyncStateContainer.types.d.ts +6 -0
- package/dist/types/components/data-display/AsyncStateContainer/AsyncStateContainer.types.d.ts.map +1 -1
- package/dist/types/components/data-display/Banner/Banner.d.ts.map +1 -1
- package/dist/types/components/data-display/Banner/Banner.types.d.ts +2 -0
- package/dist/types/components/data-display/Banner/Banner.types.d.ts.map +1 -1
- package/dist/types/components/data-display/CardKit/card-actions-context.d.ts +3 -1
- package/dist/types/components/data-display/CardKit/card-actions-context.d.ts.map +1 -1
- package/dist/types/components/data-display/Carousel/Carousel.chrome.d.ts +3 -0
- package/dist/types/components/data-display/Carousel/Carousel.chrome.d.ts.map +1 -1
- package/dist/types/components/data-display/Carousel/Carousel.parts.d.ts.map +1 -1
- package/dist/types/components/data-display/Carousel/Carousel.types.d.ts +7 -0
- package/dist/types/components/data-display/Carousel/Carousel.types.d.ts.map +1 -1
- package/dist/types/components/data-display/DataGrid/DataGrid.states.d.ts +1 -0
- package/dist/types/components/data-display/DataGrid/DataGrid.states.d.ts.map +1 -1
- package/dist/types/components/data-display/DataGrid/DataGrid.types.d.ts +5 -0
- package/dist/types/components/data-display/DataGrid/DataGrid.types.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-category-pill.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-copy.d.ts +29 -1
- package/dist/types/components/data-display/DataViews/data-views-copy.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-day-input.d.ts +12 -1
- package/dist/types/components/data-display/DataViews/data-views-day-input.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-filter-panel.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-grid-bodies.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-grid-parts.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-more-fields.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-pagination.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-range-pill.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-table-parts.d.ts.map +1 -1
- package/dist/types/components/data-display/DataViews/data-views-toolbar.d.ts.map +1 -1
- package/dist/types/components/data-display/HoverCard/HoverCard.content.d.ts +1 -1
- package/dist/types/components/data-display/HoverCard/HoverCard.content.d.ts.map +1 -1
- package/dist/types/components/data-display/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/types/components/data-display/HoverCard/HoverCard.types.d.ts +2 -0
- package/dist/types/components/data-display/HoverCard/HoverCard.types.d.ts.map +1 -1
- package/dist/types/components/data-display/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/types/components/data-display/Lightbox/Lightbox.types.d.ts +9 -0
- package/dist/types/components/data-display/Lightbox/Lightbox.types.d.ts.map +1 -1
- package/dist/types/components/data-display/Lightbox/LightboxControls.d.ts.map +1 -1
- package/dist/types/components/data-display/Lightbox/lightbox-copy-context.d.ts +17 -0
- package/dist/types/components/data-display/Lightbox/lightbox-copy-context.d.ts.map +1 -0
- package/dist/types/components/data-display/MapPreview/MapControlBar.d.ts +7 -0
- package/dist/types/components/data-display/MapPreview/MapControlBar.d.ts.map +1 -1
- package/dist/types/components/data-display/MapPreview/MapLayers.d.ts.map +1 -1
- package/dist/types/components/data-display/MapPreview/MapPreview.types.d.ts +9 -0
- package/dist/types/components/data-display/MapPreview/MapPreview.types.d.ts.map +1 -1
- package/dist/types/components/data-display/MapPreview/MapSearchBar.d.ts +2 -0
- package/dist/types/components/data-display/MapPreview/MapSearchBar.d.ts.map +1 -1
- package/dist/types/components/data-display/Table/Table.d.ts.map +1 -1
- package/dist/types/components/data-display/Table/Table.types.d.ts +5 -0
- package/dist/types/components/data-display/Table/Table.types.d.ts.map +1 -1
- package/dist/types/components/data-display/Table/TableStates.d.ts +3 -1
- package/dist/types/components/data-display/Table/TableStates.d.ts.map +1 -1
- package/dist/types/components/data-display/TimingDiagram/TimingDiagram.d.ts.map +1 -1
- package/dist/types/components/data-display/TimingDiagram/TimingDiagram.types.d.ts +3 -0
- package/dist/types/components/data-display/TimingDiagram/TimingDiagram.types.d.ts.map +1 -1
- package/dist/types/components/feedback/Sonner/Sonner.d.ts +8 -0
- package/dist/types/components/feedback/Sonner/Sonner.d.ts.map +1 -1
- package/dist/types/components/feedback/Sonner/Sonner.types.d.ts +2 -0
- package/dist/types/components/feedback/Sonner/Sonner.types.d.ts.map +1 -1
- package/dist/types/components/feedback/Sonner/SonnerToast.d.ts.map +1 -1
- package/dist/types/components/feedback/StackedModal/StackedModal.d.ts.map +1 -1
- package/dist/types/components/feedback/StackedModal/StackedModal.parts.d.ts +2 -0
- package/dist/types/components/feedback/StackedModal/StackedModal.parts.d.ts.map +1 -1
- package/dist/types/components/feedback/StackedModal/StackedModal.types.d.ts +2 -0
- package/dist/types/components/feedback/StackedModal/StackedModal.types.d.ts.map +1 -1
- package/dist/types/components/feedback/TutorialOverlay/TutorialOverlay.d.ts.map +1 -1
- package/dist/types/components/feedback/TutorialOverlay/TutorialOverlay.types.d.ts +3 -0
- package/dist/types/components/feedback/TutorialOverlay/TutorialOverlay.types.d.ts.map +1 -1
- package/dist/types/components/feedback/TutorialOverlay/TutorialStepBody.d.ts +2 -0
- package/dist/types/components/feedback/TutorialOverlay/TutorialStepBody.d.ts.map +1 -1
- package/dist/types/components/form/AddressAutocomplete/AddressAutocomplete.types.d.ts +7 -0
- package/dist/types/components/form/AddressAutocomplete/AddressAutocomplete.types.d.ts.map +1 -1
- package/dist/types/components/form/AddressAutocomplete/AddressAutocompleteField.d.ts.map +1 -1
- package/dist/types/components/form/AddressAutocomplete/AddressFallbackField.d.ts +1 -0
- package/dist/types/components/form/AddressAutocomplete/AddressFallbackField.d.ts.map +1 -1
- package/dist/types/components/form/AddressAutocomplete/AddressInputField.d.ts +1 -0
- package/dist/types/components/form/AddressAutocomplete/AddressInputField.d.ts.map +1 -1
- package/dist/types/components/form/Autocomplete/Autocomplete.d.ts.map +1 -1
- package/dist/types/components/form/Autocomplete/Autocomplete.parts.d.ts +9 -3
- package/dist/types/components/form/Autocomplete/Autocomplete.parts.d.ts.map +1 -1
- package/dist/types/components/form/Autocomplete/Autocomplete.types.d.ts +7 -0
- package/dist/types/components/form/Autocomplete/Autocomplete.types.d.ts.map +1 -1
- package/dist/types/components/form/Calendar/Calendar.types.d.ts +6 -0
- package/dist/types/components/form/Calendar/Calendar.types.d.ts.map +1 -1
- package/dist/types/components/form/CodeEditor/CodeEditor.d.ts.map +1 -1
- package/dist/types/components/form/CodeEditor/CodeEditor.types.d.ts +7 -0
- package/dist/types/components/form/CodeEditor/CodeEditor.types.d.ts.map +1 -1
- package/dist/types/components/form/CodeEditor/CodeEditorToolbar.d.ts +2 -0
- package/dist/types/components/form/CodeEditor/CodeEditorToolbar.d.ts.map +1 -1
- package/dist/types/components/form/DateRangePicker/DateRangePicker.d.ts.map +1 -1
- package/dist/types/components/form/DateRangePicker/DateRangePicker.range.d.ts.map +1 -1
- package/dist/types/components/form/DateRangePicker/DateRangePicker.types.d.ts +11 -0
- package/dist/types/components/form/DateRangePicker/DateRangePicker.types.d.ts.map +1 -1
- package/dist/types/components/form/DateRangePicker/DateRangePickerFields.d.ts.map +1 -1
- package/dist/types/components/form/Menubar/Menubar.d.ts.map +1 -1
- package/dist/types/components/form/Menubar/Menubar.toolbar.d.ts +1 -0
- package/dist/types/components/form/Menubar/Menubar.toolbar.d.ts.map +1 -1
- package/dist/types/components/form/Menubar/Menubar.types.d.ts +5 -0
- package/dist/types/components/form/Menubar/Menubar.types.d.ts.map +1 -1
- package/dist/types/components/form/PasswordStrength/PasswordStrength.d.ts.map +1 -1
- package/dist/types/components/form/PasswordStrength/PasswordStrength.helpers.d.ts +4 -2
- package/dist/types/components/form/PasswordStrength/PasswordStrength.helpers.d.ts.map +1 -1
- package/dist/types/components/form/PasswordStrength/PasswordStrength.types.d.ts +8 -0
- package/dist/types/components/form/PasswordStrength/PasswordStrength.types.d.ts.map +1 -1
- package/dist/types/components/form/PhoneInput/PhoneInput.d.ts.map +1 -1
- package/dist/types/components/form/PhoneInput/PhoneInput.types.d.ts +7 -0
- package/dist/types/components/form/PhoneInput/PhoneInput.types.d.ts.map +1 -1
- package/dist/types/components/form/SearchPalette/SearchPalette.d.ts.map +1 -1
- package/dist/types/components/form/SearchPalette/SearchPalette.parts.d.ts +2 -0
- package/dist/types/components/form/SearchPalette/SearchPalette.parts.d.ts.map +1 -1
- package/dist/types/components/form/SearchPalette/SearchPalette.types.d.ts +6 -0
- package/dist/types/components/form/SearchPalette/SearchPalette.types.d.ts.map +1 -1
- package/dist/types/components/form/Textarea/Textarea.d.ts.map +1 -1
- package/dist/types/components/form/Textarea/Textarea.types.d.ts +16 -1
- package/dist/types/components/form/Textarea/Textarea.types.d.ts.map +1 -1
- package/dist/types/components/form/Textarea/TextareaRichEditor.d.ts +7 -0
- package/dist/types/components/form/Textarea/TextareaRichEditor.d.ts.map +1 -1
- package/dist/types/components/form/UploadButton/UploadButton.d.ts.map +1 -1
- package/dist/types/components/form/UploadButton/UploadButton.parts.d.ts +6 -3
- package/dist/types/components/form/UploadButton/UploadButton.parts.d.ts.map +1 -1
- package/dist/types/components/form/UploadButton/UploadButton.types.d.ts +7 -0
- package/dist/types/components/form/UploadButton/UploadButton.types.d.ts.map +1 -1
- package/dist/types/components/layout/ContentToolbar/ContentToolbar.d.ts +1 -1
- package/dist/types/components/layout/ContentToolbar/ContentToolbar.d.ts.map +1 -1
- package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts +12 -0
- package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts.map +1 -1
- package/dist/types/components/layout/ContentToolbar/MultiSelectDropdown.d.ts +1 -1
- package/dist/types/components/layout/ContentToolbar/MultiSelectDropdown.d.ts.map +1 -1
- package/dist/types/components/layout/ContentToolbar/SortByDropdown.d.ts +1 -1
- package/dist/types/components/layout/ContentToolbar/SortByDropdown.d.ts.map +1 -1
- package/dist/types/components/layout/ContentToolbar/ViewSelector.d.ts +1 -1
- package/dist/types/components/layout/ContentToolbar/ViewSelector.d.ts.map +1 -1
- package/dist/types/components/layout/Dashboard/Dashboard.d.ts +1 -1
- package/dist/types/components/layout/Dashboard/Dashboard.types.d.ts +4 -0
- package/dist/types/components/layout/Dashboard/Dashboard.types.d.ts.map +1 -1
- package/dist/types/components/layout/Dashboard/DashboardParts.d.ts +1 -1
- package/dist/types/components/layout/Dashboard/DashboardParts.d.ts.map +1 -1
- package/dist/types/components/layout/ScrollArea/ScrollArea.d.ts.map +1 -1
- package/dist/types/components/layout/ScrollArea/ScrollArea.types.d.ts +21 -3
- package/dist/types/components/layout/ScrollArea/ScrollArea.types.d.ts.map +1 -1
- package/dist/types/components/layout/ScrollArea/ScrollViewport.d.ts +2 -0
- package/dist/types/components/layout/ScrollArea/ScrollViewport.d.ts.map +1 -1
- package/dist/types/components/layout/TableFilter/TableFilter.d.ts +1 -1
- package/dist/types/components/layout/TableFilter/TableFilter.d.ts.map +1 -1
- package/dist/types/components/layout/TableFilter/TableFilter.types.d.ts +7 -0
- package/dist/types/components/layout/TableFilter/TableFilter.types.d.ts.map +1 -1
- package/dist/types/components/layout/TableFilter/TableFilterContext.d.ts +9 -0
- package/dist/types/components/layout/TableFilter/TableFilterContext.d.ts.map +1 -1
- package/dist/types/components/navigation/Breadcrumbs/BreadcrumbEntry.d.ts +2 -0
- package/dist/types/components/navigation/Breadcrumbs/BreadcrumbEntry.d.ts.map +1 -1
- package/dist/types/components/navigation/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
- package/dist/types/components/navigation/Breadcrumbs/Breadcrumbs.types.d.ts +3 -0
- package/dist/types/components/navigation/Breadcrumbs/Breadcrumbs.types.d.ts.map +1 -1
- package/dist/types/components/navigation/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/types/components/navigation/CommandPalette/CommandPalette.types.d.ts +3 -0
- package/dist/types/components/navigation/CommandPalette/CommandPalette.types.d.ts.map +1 -1
- package/dist/types/components/navigation/CommandPalette/CommandPaletteResults.d.ts +2 -0
- package/dist/types/components/navigation/CommandPalette/CommandPaletteResults.d.ts.map +1 -1
- package/dist/types/components/navigation/Pagination/Pagination.d.ts.map +1 -1
- package/dist/types/components/navigation/Pagination/Pagination.types.d.ts +2 -0
- package/dist/types/components/navigation/Pagination/Pagination.types.d.ts.map +1 -1
- package/dist/types/components/navigation/Pagination/PaginationParts.d.ts +2 -0
- package/dist/types/components/navigation/Pagination/PaginationParts.d.ts.map +1 -1
- package/dist/types/components/navigation/Tabs/Tabs.d.ts.map +1 -1
- package/dist/types/components/navigation/Tabs/Tabs.types.d.ts +2 -0
- package/dist/types/components/navigation/Tabs/Tabs.types.d.ts.map +1 -1
- package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.d.ts.map +1 -1
- package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.parts.d.ts +6 -2
- package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.parts.d.ts.map +1 -1
- package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.types.d.ts +6 -0
- package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.types.d.ts.map +1 -1
- package/dist/types/components/utility/InstallPrompt/InstallPrompt.d.ts +4 -2
- package/dist/types/components/utility/InstallPrompt/InstallPrompt.d.ts.map +1 -1
- package/dist/types/components/utility/InstallPrompt/InstallPrompt.types.d.ts +8 -7
- package/dist/types/components/utility/InstallPrompt/InstallPrompt.types.d.ts.map +1 -1
- package/dist/types/copy/data-display.d.ts +56 -0
- package/dist/types/copy/data-display.d.ts.map +1 -0
- package/dist/types/copy/feedback.d.ts +38 -0
- package/dist/types/copy/feedback.d.ts.map +1 -0
- package/dist/types/copy/form.d.ts +146 -0
- package/dist/types/copy/form.d.ts.map +1 -0
- package/dist/types/copy/layout.d.ts +18 -0
- package/dist/types/copy/layout.d.ts.map +1 -0
- package/dist/types/copy/navigation.d.ts +24 -0
- package/dist/types/copy/navigation.d.ts.map +1 -0
- package/dist/types/copy/shared.d.ts +119 -0
- package/dist/types/copy/shared.d.ts.map +1 -0
- package/dist/types/copy/utility.d.ts +35 -0
- package/dist/types/copy/utility.d.ts.map +1 -0
- package/dist/types/copy.d.ts +13 -113
- package/dist/types/copy.d.ts.map +1 -1
- package/dist/types/pt-BR.d.ts +15 -18
- package/dist/types/pt-BR.d.ts.map +1 -1
- package/dist/types/pt-BR.data-display.d.ts +13 -0
- package/dist/types/pt-BR.data-display.d.ts.map +1 -0
- package/dist/types/pt-BR.feedback.d.ts +8 -0
- package/dist/types/pt-BR.feedback.d.ts.map +1 -0
- package/dist/types/pt-BR.form.d.ts +13 -0
- package/dist/types/pt-BR.form.d.ts.map +1 -0
- package/dist/types/pt-BR.layout.d.ts +7 -0
- package/dist/types/pt-BR.layout.d.ts.map +1 -0
- package/dist/types/pt-BR.navigation.d.ts +8 -0
- package/dist/types/pt-BR.navigation.d.ts.map +1 -0
- package/dist/types/pt-BR.shared.d.ts +21 -0
- package/dist/types/pt-BR.shared.d.ts.map +1 -0
- package/dist/types/pt-BR.utility.d.ts +8 -0
- package/dist/types/pt-BR.utility.d.ts.map +1 -0
- package/dist/types/user-avatar/user-avatar.d.ts +7 -1
- package/dist/types/user-avatar/user-avatar.d.ts.map +1 -1
- package/dist/user-avatar.js +2 -2
- package/dist/user-avatar.js.map +1 -1
- package/dist/utility/InfiniteScroll.js +7 -5
- package/dist/utility/InfiniteScroll.js.map +1 -1
- package/dist/utility/InstallPrompt.js +14 -13
- package/dist/utility/InstallPrompt.js.map +1 -1
- package/package.json +1 -1
- package/src/components/data-display/Alert/Alert.tsx +22 -5
- package/src/components/data-display/Alert/Alert.types.ts +20 -10
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.tsx +2 -1
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.types.ts +6 -0
- package/src/components/data-display/Banner/Banner.tsx +5 -2
- package/src/components/data-display/Banner/Banner.types.ts +2 -0
- package/src/components/data-display/CardKit/card-actions-context.tsx +4 -0
- package/src/components/data-display/Carousel/Carousel.chrome.tsx +5 -0
- package/src/components/data-display/Carousel/Carousel.parts.tsx +4 -3
- package/src/components/data-display/Carousel/Carousel.types.ts +7 -0
- package/src/components/data-display/DataGrid/DataGrid.states.tsx +3 -3
- package/src/components/data-display/DataGrid/DataGrid.tsx +1 -1
- package/src/components/data-display/DataGrid/DataGrid.types.ts +5 -0
- package/src/components/data-display/DataViews/data-views-category-pill.tsx +2 -0
- package/src/components/data-display/DataViews/data-views-copy.ts +29 -1
- package/src/components/data-display/DataViews/data-views-day-input.tsx +14 -3
- package/src/components/data-display/DataViews/data-views-filter-panel.tsx +2 -1
- package/src/components/data-display/DataViews/data-views-grid-bodies.tsx +3 -0
- package/src/components/data-display/DataViews/data-views-grid-parts.tsx +9 -10
- package/src/components/data-display/DataViews/data-views-more-fields.tsx +3 -1
- package/src/components/data-display/DataViews/data-views-pagination.tsx +3 -0
- package/src/components/data-display/DataViews/data-views-range-pill.tsx +3 -1
- package/src/components/data-display/DataViews/data-views-table-parts.tsx +1 -0
- package/src/components/data-display/DataViews/data-views-toolbar.tsx +2 -0
- package/src/components/data-display/HoverCard/HoverCard.content.tsx +10 -2
- package/src/components/data-display/HoverCard/HoverCard.tsx +2 -3
- package/src/components/data-display/HoverCard/HoverCard.types.ts +2 -0
- package/src/components/data-display/Lightbox/Lightbox.tsx +3 -0
- package/src/components/data-display/Lightbox/Lightbox.types.ts +9 -0
- package/src/components/data-display/Lightbox/LightboxControls.tsx +28 -15
- package/src/components/data-display/Lightbox/lightbox-copy-context.tsx +42 -0
- package/src/components/data-display/MapPreview/MapControlBar.tsx +17 -9
- package/src/components/data-display/MapPreview/MapLayers.tsx +2 -0
- package/src/components/data-display/MapPreview/MapPreview.types.ts +10 -0
- package/src/components/data-display/MapPreview/MapSearchBar.tsx +4 -1
- package/src/components/data-display/Table/Table.tsx +7 -2
- package/src/components/data-display/Table/Table.types.ts +5 -0
- package/src/components/data-display/Table/TableStates.tsx +2 -2
- package/src/components/data-display/TimingDiagram/TimingDiagram.tsx +3 -2
- package/src/components/data-display/TimingDiagram/TimingDiagram.types.ts +3 -0
- package/src/components/feedback/Sonner/Sonner.tsx +15 -3
- package/src/components/feedback/Sonner/Sonner.types.ts +2 -0
- package/src/components/feedback/Sonner/SonnerToast.tsx +2 -1
- package/src/components/feedback/StackedModal/StackedModal.parts.tsx +10 -3
- package/src/components/feedback/StackedModal/StackedModal.tsx +2 -1
- package/src/components/feedback/StackedModal/StackedModal.types.ts +2 -0
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.tsx +13 -1
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.types.ts +3 -0
- package/src/components/feedback/TutorialOverlay/TutorialStepBody.tsx +10 -4
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.types.ts +7 -0
- package/src/components/form/AddressAutocomplete/AddressAutocompleteField.tsx +2 -0
- package/src/components/form/AddressAutocomplete/AddressFallbackField.tsx +4 -2
- package/src/components/form/AddressAutocomplete/AddressInputField.tsx +13 -6
- package/src/components/form/Autocomplete/Autocomplete.parts.tsx +9 -6
- package/src/components/form/Autocomplete/Autocomplete.tsx +2 -1
- package/src/components/form/Autocomplete/Autocomplete.types.ts +7 -0
- package/src/components/form/Calendar/Calendar.tsx +2 -2
- package/src/components/form/Calendar/Calendar.types.ts +7 -0
- package/src/components/form/CodeEditor/CodeEditor.tsx +6 -4
- package/src/components/form/CodeEditor/CodeEditor.types.ts +7 -0
- package/src/components/form/CodeEditor/CodeEditorToolbar.tsx +12 -5
- package/src/components/form/DateRangePicker/DateRangePicker.range.ts +2 -0
- package/src/components/form/DateRangePicker/DateRangePicker.tsx +4 -0
- package/src/components/form/DateRangePicker/DateRangePicker.types.ts +11 -0
- package/src/components/form/DateRangePicker/DateRangePickerFields.tsx +2 -0
- package/src/components/form/Menubar/Menubar.toolbar.tsx +3 -1
- package/src/components/form/Menubar/Menubar.tsx +2 -1
- package/src/components/form/Menubar/Menubar.types.ts +5 -0
- package/src/components/form/PasswordStrength/PasswordStrength.helpers.tsx +33 -17
- package/src/components/form/PasswordStrength/PasswordStrength.tsx +29 -13
- package/src/components/form/PasswordStrength/PasswordStrength.types.ts +9 -0
- package/src/components/form/PhoneInput/PhoneInput.tsx +15 -5
- package/src/components/form/PhoneInput/PhoneInput.types.ts +7 -0
- package/src/components/form/SearchPalette/SearchPalette.parts.tsx +4 -1
- package/src/components/form/SearchPalette/SearchPalette.tsx +4 -1
- package/src/components/form/SearchPalette/SearchPalette.types.ts +6 -0
- package/src/components/form/Textarea/Textarea.tsx +6 -1
- package/src/components/form/Textarea/Textarea.types.ts +14 -1
- package/src/components/form/Textarea/TextareaRichEditor.tsx +28 -18
- package/src/components/form/UploadButton/UploadButton.parts.tsx +16 -7
- package/src/components/form/UploadButton/UploadButton.tsx +4 -1
- package/src/components/form/UploadButton/UploadButton.types.ts +8 -0
- package/src/components/layout/ContentToolbar/ContentToolbar.tsx +10 -2
- package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +12 -0
- package/src/components/layout/ContentToolbar/MultiSelectDropdown.tsx +15 -4
- package/src/components/layout/ContentToolbar/SortByDropdown.tsx +12 -3
- package/src/components/layout/ContentToolbar/ViewSelector.tsx +2 -1
- package/src/components/layout/Dashboard/Dashboard.types.ts +4 -0
- package/src/components/layout/Dashboard/DashboardParts.tsx +2 -1
- package/src/components/layout/ScrollArea/ScrollArea.tsx +16 -3
- package/src/components/layout/ScrollArea/ScrollArea.types.ts +19 -4
- package/src/components/layout/ScrollArea/ScrollViewport.tsx +4 -1
- package/src/components/layout/TableFilter/TableFilter.tsx +19 -11
- package/src/components/layout/TableFilter/TableFilter.types.ts +8 -0
- package/src/components/layout/TableFilter/TableFilterContext.tsx +10 -0
- package/src/components/navigation/Breadcrumbs/BreadcrumbEntry.tsx +11 -4
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +2 -0
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.types.ts +3 -0
- package/src/components/navigation/CommandPalette/CommandPalette.tsx +15 -5
- package/src/components/navigation/CommandPalette/CommandPalette.types.ts +3 -0
- package/src/components/navigation/CommandPalette/CommandPaletteResults.tsx +5 -2
- package/src/components/navigation/Pagination/Pagination.tsx +2 -0
- package/src/components/navigation/Pagination/Pagination.types.ts +2 -0
- package/src/components/navigation/Pagination/PaginationParts.tsx +4 -1
- package/src/components/navigation/Tabs/Tabs.tsx +8 -3
- package/src/components/navigation/Tabs/Tabs.types.ts +2 -0
- package/src/components/utility/InfiniteScroll/InfiniteScroll.parts.tsx +4 -4
- package/src/components/utility/InfiniteScroll/InfiniteScroll.tsx +4 -2
- package/src/components/utility/InfiniteScroll/InfiniteScroll.types.ts +6 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.tsx +18 -13
- package/src/components/utility/InstallPrompt/InstallPrompt.types.ts +9 -7
- package/src/copy/data-display.ts +60 -0
- package/src/copy/feedback.ts +39 -0
- package/src/copy/form.ts +154 -0
- package/src/copy/layout.ts +18 -0
- package/src/copy/navigation.ts +25 -0
- package/src/copy/shared.ts +122 -0
- package/src/copy/utility.ts +36 -0
- package/src/copy.ts +13 -117
- package/src/pt-BR.data-display.ts +236 -0
- package/src/pt-BR.feedback.ts +25 -0
- package/src/pt-BR.form.ts +96 -0
- package/src/pt-BR.layout.ts +15 -0
- package/src/pt-BR.navigation.ts +21 -0
- package/src/pt-BR.shared.ts +94 -0
- package/src/pt-BR.ts +15 -267
- package/src/pt-BR.utility.ts +21 -0
- package/src/user-avatar/user-avatar.tsx +8 -2
- package/dist/chunk-3KWD5Y5O.js.map +0 -1
- package/dist/chunk-CEKPLUQV.js.map +0 -1
- package/dist/chunk-DFVRZ3UK.js.map +0 -1
- package/dist/chunk-H7UAGTVW.js.map +0 -1
- package/dist/chunk-JP55QWVR.js.map +0 -1
- package/dist/chunk-NUCLEOHF.js.map +0 -1
- package/dist/chunk-QLBYAYUG.js.map +0 -1
- package/dist/chunk-QZZVHY6U.js.map +0 -1
package/dist/form/Textarea.js
CHANGED
|
@@ -282,8 +282,8 @@ var useRichEditorState = ({
|
|
|
282
282
|
updateActiveFormats
|
|
283
283
|
};
|
|
284
284
|
};
|
|
285
|
-
var InlineFormatButtons = ({ activeFormats, onCommand }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
286
|
-
/* @__PURE__ */ jsx(Tooltip, { title:
|
|
285
|
+
var InlineFormatButtons = ({ copy, activeFormats, onCommand }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
286
|
+
/* @__PURE__ */ jsx(Tooltip, { title: copy.bold, arrow: true, children: /* @__PURE__ */ jsx(
|
|
287
287
|
ToolbarButton,
|
|
288
288
|
{
|
|
289
289
|
size: "small",
|
|
@@ -292,7 +292,7 @@ var InlineFormatButtons = ({ activeFormats, onCommand }) => /* @__PURE__ */ jsxs
|
|
|
292
292
|
children: /* @__PURE__ */ jsx(FormatBold, { fontSize: "small" })
|
|
293
293
|
}
|
|
294
294
|
) }),
|
|
295
|
-
/* @__PURE__ */ jsx(Tooltip, { title:
|
|
295
|
+
/* @__PURE__ */ jsx(Tooltip, { title: copy.italic, arrow: true, children: /* @__PURE__ */ jsx(
|
|
296
296
|
ToolbarButton,
|
|
297
297
|
{
|
|
298
298
|
size: "small",
|
|
@@ -301,7 +301,7 @@ var InlineFormatButtons = ({ activeFormats, onCommand }) => /* @__PURE__ */ jsxs
|
|
|
301
301
|
children: /* @__PURE__ */ jsx(FormatItalic, { fontSize: "small" })
|
|
302
302
|
}
|
|
303
303
|
) }),
|
|
304
|
-
/* @__PURE__ */ jsx(Tooltip, { title:
|
|
304
|
+
/* @__PURE__ */ jsx(Tooltip, { title: copy.underline, arrow: true, children: /* @__PURE__ */ jsx(
|
|
305
305
|
ToolbarButton,
|
|
306
306
|
{
|
|
307
307
|
size: "small",
|
|
@@ -311,9 +311,9 @@ var InlineFormatButtons = ({ activeFormats, onCommand }) => /* @__PURE__ */ jsxs
|
|
|
311
311
|
}
|
|
312
312
|
) })
|
|
313
313
|
] });
|
|
314
|
-
var BlockFormatButtons = ({ activeFormats, onCommand }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
314
|
+
var BlockFormatButtons = ({ copy, activeFormats, onCommand }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
315
315
|
/* @__PURE__ */ jsx(Divider, { orientation: "vertical", flexItem: true }),
|
|
316
|
-
/* @__PURE__ */ jsx(Tooltip, { title:
|
|
316
|
+
/* @__PURE__ */ jsx(Tooltip, { title: copy.bulletList, arrow: true, children: /* @__PURE__ */ jsx(
|
|
317
317
|
ToolbarButton,
|
|
318
318
|
{
|
|
319
319
|
size: "small",
|
|
@@ -322,7 +322,7 @@ var BlockFormatButtons = ({ activeFormats, onCommand }) => /* @__PURE__ */ jsxs(
|
|
|
322
322
|
children: /* @__PURE__ */ jsx(FormatListBulleted, { fontSize: "small" })
|
|
323
323
|
}
|
|
324
324
|
) }),
|
|
325
|
-
/* @__PURE__ */ jsx(Tooltip, { title:
|
|
325
|
+
/* @__PURE__ */ jsx(Tooltip, { title: copy.numberedList, arrow: true, children: /* @__PURE__ */ jsx(
|
|
326
326
|
ToolbarButton,
|
|
327
327
|
{
|
|
328
328
|
size: "small",
|
|
@@ -332,28 +332,28 @@ var BlockFormatButtons = ({ activeFormats, onCommand }) => /* @__PURE__ */ jsxs(
|
|
|
332
332
|
}
|
|
333
333
|
) }),
|
|
334
334
|
/* @__PURE__ */ jsx(Divider, { orientation: "vertical", flexItem: true }),
|
|
335
|
-
/* @__PURE__ */ jsx(Tooltip, { title:
|
|
336
|
-
/* @__PURE__ */ jsx(Tooltip, { title:
|
|
335
|
+
/* @__PURE__ */ jsx(Tooltip, { title: copy.quote, arrow: true, children: /* @__PURE__ */ jsx(ToolbarButton, { size: "small", onClick: () => onCommand("formatBlock", "blockquote"), children: /* @__PURE__ */ jsx(FormatQuote, { fontSize: "small" }) }) }),
|
|
336
|
+
/* @__PURE__ */ jsx(Tooltip, { title: copy.code, arrow: true, children: /* @__PURE__ */ jsx(ToolbarButton, { size: "small", onClick: () => onCommand("formatBlock", "pre"), children: /* @__PURE__ */ jsx(Code, { fontSize: "small" }) }) }),
|
|
337
337
|
/* @__PURE__ */ jsx(Divider, { orientation: "vertical", flexItem: true }),
|
|
338
|
-
/* @__PURE__ */ jsx(Tooltip, { title:
|
|
338
|
+
/* @__PURE__ */ jsx(Tooltip, { title: copy.insertLink, arrow: true, children: /* @__PURE__ */ jsx(
|
|
339
339
|
ToolbarButton,
|
|
340
340
|
{
|
|
341
341
|
size: "small",
|
|
342
342
|
onClick: () => {
|
|
343
|
-
const url = window.prompt(
|
|
343
|
+
const url = window.prompt(copy.linkPrompt);
|
|
344
344
|
if (url) onCommand("createLink", url);
|
|
345
345
|
},
|
|
346
346
|
children: /* @__PURE__ */ jsx(Link, { fontSize: "small" })
|
|
347
347
|
}
|
|
348
348
|
) }),
|
|
349
|
-
/* @__PURE__ */ jsx(Tooltip, { title:
|
|
350
|
-
/* @__PURE__ */ jsx(Tooltip, { title:
|
|
349
|
+
/* @__PURE__ */ jsx(Tooltip, { title: copy.textColor, arrow: true, children: /* @__PURE__ */ jsx(ToolbarButton, { size: "small", children: /* @__PURE__ */ jsx(FormatColorText, { fontSize: "small" }) }) }),
|
|
350
|
+
/* @__PURE__ */ jsx(Tooltip, { title: copy.backgroundColor, arrow: true, children: /* @__PURE__ */ jsx(ToolbarButton, { size: "small", children: /* @__PURE__ */ jsx(FormatColorFill, { fontSize: "small" }) }) })
|
|
351
351
|
] });
|
|
352
|
-
var EditorToolbar = ({ glass, activeFormats, onCommand }) => /* @__PURE__ */ jsxs(RichToolbar, { glass, children: [
|
|
353
|
-
/* @__PURE__ */ jsx(InlineFormatButtons, { activeFormats, onCommand }),
|
|
354
|
-
/* @__PURE__ */ jsx(BlockFormatButtons, { activeFormats, onCommand })
|
|
352
|
+
var EditorToolbar = ({ copy, glass, activeFormats, onCommand }) => /* @__PURE__ */ jsxs(RichToolbar, { glass, children: [
|
|
353
|
+
/* @__PURE__ */ jsx(InlineFormatButtons, { copy, activeFormats, onCommand }),
|
|
354
|
+
/* @__PURE__ */ jsx(BlockFormatButtons, { copy, activeFormats, onCommand })
|
|
355
355
|
] });
|
|
356
|
-
var TextareaRichEditor = ({ value, onChange, placeholder, error, glass, color, characterLimit }) => {
|
|
356
|
+
var TextareaRichEditor = ({ copy, value, onChange, placeholder, error, glass, color, characterLimit }) => {
|
|
357
357
|
const {
|
|
358
358
|
focused,
|
|
359
359
|
setFocused,
|
|
@@ -365,7 +365,7 @@ var TextareaRichEditor = ({ value, onChange, placeholder, error, glass, color, c
|
|
|
365
365
|
updateActiveFormats
|
|
366
366
|
} = useRichEditorState({ value, onChange });
|
|
367
367
|
return /* @__PURE__ */ jsxs(Box, { sx: { position: "relative" }, children: [
|
|
368
|
-
/* @__PURE__ */ jsx(EditorToolbar, { glass, activeFormats, onCommand: handleFormat }),
|
|
368
|
+
/* @__PURE__ */ jsx(EditorToolbar, { copy, glass, activeFormats, onCommand: handleFormat }),
|
|
369
369
|
/* @__PURE__ */ jsx(
|
|
370
370
|
ContentEditableDiv,
|
|
371
371
|
{
|
|
@@ -527,6 +527,7 @@ var Textarea = (textareaProps) => {
|
|
|
527
527
|
dataTestId: dataTestIdCamelCase,
|
|
528
528
|
...props
|
|
529
529
|
} = { ...TEXTAREA_DEFAULTS, ...definedProps(textareaProps) };
|
|
530
|
+
const { richEditorCopy } = textareaProps;
|
|
530
531
|
const [richTextValue, setRichTextValue] = useState2("");
|
|
531
532
|
const hasIcon = Boolean(icon);
|
|
532
533
|
const testId = dataTestId || dataTestIdCamelCase;
|
|
@@ -539,10 +540,11 @@ var Textarea = (textareaProps) => {
|
|
|
539
540
|
[iconPosition === "start" ? "paddingLeft" : "paddingRight"]: ICON_GUTTER
|
|
540
541
|
}
|
|
541
542
|
};
|
|
542
|
-
if (variant === "rich") {
|
|
543
|
+
if (variant === "rich" && richEditorCopy) {
|
|
543
544
|
return /* @__PURE__ */ jsx2(TextareaShell, { testId, label, glassLabel, error, helperText, children: /* @__PURE__ */ jsx2(
|
|
544
545
|
TextareaRichEditor,
|
|
545
546
|
{
|
|
547
|
+
copy: richEditorCopy,
|
|
546
548
|
value: richTextValue,
|
|
547
549
|
onChange: setRichTextValue,
|
|
548
550
|
placeholder: props.placeholder,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/form/Textarea/Textarea.tsx","../../src/components/form/Textarea/Textarea.styles.ts","../../src/components/form/Textarea/TextareaRichEditor.tsx"],"sourcesContent":["import {\n alpha,\n Box,\n FormHelperText,\n InputLabel,\n TextareaAutosize } from '@mui/material';\nimport type { Theme } from '@mui/material';\nimport { styled } from '@mui/material';\nimport React, { useState } from 'react';\n\nimport {\n getColorFromTheme,\n textareaEmphasisStyles } from './Textarea.styles';\nimport { TextareaRichEditor } from './TextareaRichEditor';\nimport type { TextareaProps } from './Textarea.types';\n\n// Interface for styled component props\ninterface StyledTextareaProps {\n customVariant?: string;\n customColor?: string;\n customSize?: string;\n glow?: boolean;\n glass?: boolean;\n gradient?: boolean;\n error?: boolean;\n theme?: Theme;\n}\n\n// Glow animation for enhanced visual effects\nconst StyledTextarea = styled(TextareaAutosize, {\n shouldForwardProp: (prop) =>\n !['customVariant', 'customColor', 'customSize', 'glow', 'glass', 'gradient', 'error'].includes(\n prop as string,\n ) })<StyledTextareaProps>(({\n theme,\n customVariant,\n customColor = 'primary',\n customSize = 'md',\n glow,\n glass,\n gradient,\n error }) => {\n if (!theme) return {};\n const colorPalette = getColorFromTheme(theme, customColor);\n const errorColor = theme.palette.error;\n\n const sizeMap = {\n xs: { padding: '6px 8px', fontSize: '0.75rem', minHeight: '60px' },\n sm: { padding: '8px 10px', fontSize: '0.875rem', minHeight: '80px' },\n md: { padding: '10px 12px', fontSize: '1rem', minHeight: '100px' },\n lg: { padding: '12px 14px', fontSize: '1.125rem', minHeight: '120px' },\n xl: { padding: '14px 16px', fontSize: '1.25rem', minHeight: '140px' } };\n\n const baseStyles = {\n width: '100%',\n fontFamily: theme.typography.fontFamily,\n borderRadius: theme.spacing(1),\n border: `2px solid ${error ? errorColor.main : theme.palette.divider}`,\n backgroundColor: theme.palette.background.paper,\n color: theme.palette.text.primary,\n transition: 'all 0.3s ease',\n resize: customVariant === 'resizable' ? 'vertical' : 'none',\n outline: 'none',\n ...sizeMap[customSize as keyof typeof sizeMap],\n\n '&::placeholder': {\n color: theme.palette.text.secondary,\n opacity: 0.7 },\n\n '&:hover': {\n borderColor: error ? errorColor.dark : colorPalette.main,\n backgroundColor: alpha(theme.palette.background.paper, 0.8) },\n\n '&:focus': {\n borderColor: error ? errorColor.main : colorPalette.main,\n backgroundColor: theme.palette.background.paper,\n boxShadow: `0 0 0 3px ${alpha(error ? errorColor.main : colorPalette.main, 0.1)}` } };\n\n // Glass morphism effect\n return {\n ...baseStyles,\n ...textareaEmphasisStyles({ theme, colorPalette, glass, gradient, glow }) };\n});\n\nconst StyledLabel = styled(InputLabel, {\n shouldForwardProp: (prop) => !['glass', 'error'].includes(prop as string) })<{ glass?: boolean; error?: boolean }>(({ theme, glass, error }) => ({\n marginBottom: theme.spacing(1),\n fontWeight: 500,\n color: error ? theme.palette.error.main : theme.palette.text.primary,\n ...(glass && {\n backgroundColor: alpha(theme.palette.background.paper, 0.1),\n backdropFilter: 'blur(10px)',\n padding: '4px 8px',\n borderRadius: '4px',\n border: `1px solid ${alpha(theme.palette.divider, 0.2)}`,\n display: 'inline-block' }) }));\n\n// IconWrapper - replaced with inline Box component for better TypeScript compatibility\n// const IconWrapper = styled(Box)<{ position: 'start' | 'end' }>(({ theme, position }) => {\n// const positionStyles = position === 'start' ? { left: '12px' } : { right: '12px' };\n// return {\n// position: 'absolute' as const,\n// top: '12px',\n// ...positionStyles,\n// color: theme.palette.text.secondary,\n// pointerEvents: 'none' as const,\n// zIndex: 1,\n// };\n// });\n\n// Rich text toolbar styling\n\nconst ICON_GUTTER = '40px';\n\nconst TEXTAREA_DEFAULTS = {\n variant: 'default',\n color: 'primary',\n size: 'md',\n error: false,\n glassLabel: false,\n glow: false,\n glass: false,\n gradient: false,\n iconPosition: 'start',\n minRows: 3 } satisfies Partial<TextareaProps>;\n\n// Strips explicitly-undefined props before the merge, so `prop={undefined}`\n// still falls back to the default as a destructuring default would.\nconst definedProps = (props: TextareaProps): Partial<TextareaProps> =>\n Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<TextareaProps>;\n\n// Label above, helper text below — identical for the plain and rich variants,\n// which previously duplicated both.\nconst TextareaShell: React.FC<{\n testId?: string;\n label?: React.ReactNode;\n glassLabel: boolean;\n error: boolean;\n helperText?: React.ReactNode;\n children: React.ReactNode;\n}> = ({ testId, label, glassLabel, error, helperText, children }) => (\n <Box\n sx={{ position: 'relative', width: '100%' }}\n data-testid={testId ? `${testId}-wrapper` : undefined}\n >\n {label && (\n <StyledLabel glass={glassLabel} error={error}>\n {label}\n </StyledLabel>\n )}\n\n {children}\n\n {helperText && (\n <FormHelperText error={error} sx={{ mt: 1 }}>\n {helperText}\n </FormHelperText>\n )}\n </Box>\n);\n\nconst TextareaIcon: React.FC<{\n icon?: React.ReactNode;\n iconPosition: 'start' | 'end';\n}> = ({ icon, iconPosition }) => (\n <Box\n sx={{\n position: 'absolute',\n top: '12px',\n ...(iconPosition === 'start' ? { left: '12px' } : { right: '12px' }),\n color: 'text.secondary',\n pointerEvents: 'none',\n zIndex: 1 }}\n >\n {icon}\n </Box>\n);\n\nexport const Textarea: React.FC<TextareaProps> = (textareaProps) => {\n const {\n variant,\n color,\n size,\n error,\n helperText,\n label,\n glassLabel,\n glow,\n glass,\n gradient,\n icon,\n iconPosition,\n minRows,\n maxRows,\n style,\n 'data-testid': dataTestId,\n dataTestId: dataTestIdCamelCase,\n ...props\n } = { ...TEXTAREA_DEFAULTS, ...definedProps(textareaProps) };\n\n const [richTextValue, setRichTextValue] = useState('');\n const hasIcon = Boolean(icon);\n const testId = dataTestId || dataTestIdCamelCase;\n\n const textareaStyle = {\n ...style,\n // Same gap either side; only which side it applies to changes. The previous\n // version had `iconPosition === 'start' ? '40px' : '40px'`, a ternary whose\n // two branches were identical.\n ...(hasIcon && {\n [iconPosition === 'start' ? 'paddingLeft' : 'paddingRight']: ICON_GUTTER }) };\n\n // If rich text variant, use the rich text editor\n if (variant === 'rich') {\n return (\n <TextareaShell testId={testId} label={label} glassLabel={glassLabel} error={error} helperText={helperText}>\n <TextareaRichEditor\n value={richTextValue}\n onChange={setRichTextValue}\n placeholder={props.placeholder}\n error={error}\n glass={glass}\n color={color}\n characterLimit={props.maxLength}\n />\n </TextareaShell>\n );\n }\n\n return (\n <TextareaShell testId={testId} label={label} glassLabel={glassLabel} error={error} helperText={helperText}>\n <Box sx={{ position: 'relative' }}>\n {hasIcon && <TextareaIcon icon={icon} iconPosition={iconPosition} />}\n\n <StyledTextarea\n customVariant={variant}\n customColor={color}\n customSize={size}\n glow={glow}\n glass={glass}\n gradient={gradient}\n error={error}\n minRows={variant === 'autosize' ? minRows : undefined}\n maxRows={variant === 'autosize' ? maxRows : undefined}\n style={textareaStyle}\n aria-label={label || props['aria-label']}\n data-testid={testId}\n {...props}\n />\n </Box>\n </TextareaShell>\n );\n};\n\nTextarea.displayName = 'Textarea';\n","import { alpha, keyframes } from '@mui/material';\nimport type { CSSObject, Theme } from '@mui/material';\n\nconst glowAnimation = keyframes`\n 0% {\n box-shadow: 0 0 5px currentColor;\n }\n 50% {\n box-shadow: 0 0 20px currentColor, 0 0 30px currentColor;\n }\n 100% {\n box-shadow: 0 0 5px currentColor;\n }\n`;\n\n// Ripple animation for buttons (commented out - not currently used)\n// const rippleAnimation = keyframes`\n// 0% {\n// transform: scale(0);\n// opacity: 1;\n// }\n// 100% {\n// transform: scale(4);\n// opacity: 0;\n// }\n// `;\n\n// Float animation for rich text toolbar\nexport const floatAnimation = keyframes`\n 0% {\n transform: translateY(0px);\n }\n 50% {\n transform: translateY(-3px);\n }\n 100% {\n transform: translateY(0px);\n }\n`;\n\ntype ResolvedPalette = {\n main: string;\n dark: string;\n light: string;\n contrastText: string;\n};\n\ntype PartialPalette = { main: string; dark?: string; light?: string; contrastText?: string };\n\n// grey is indexed by weight rather than main/dark/light, so neutral is built by\n// hand. The literals are the MUI grey values, used if the theme omits a weight.\nconst neutralPalette = (theme: Theme): ResolvedPalette => {\n const grey = theme.palette.grey as unknown as Record<number, string>;\n\n return {\n main: grey?.[700] || '#616161',\n dark: grey?.[800] || '#424242',\n light: grey?.[500] || '#9e9e9e',\n contrastText: '#fff',\n };\n};\n\n// Each slot falls back to the palette's own main, then to primary — a custom\n// theme can define main without dark or light.\nconst pick = (...candidates: Array<string | undefined>): string =>\n candidates.find(Boolean) ?? '';\n\nconst withFallbacks = (theme: Theme, palette: PartialPalette): ResolvedPalette => ({\n main: pick(palette?.main, theme.palette.primary.main),\n dark: pick(palette?.dark, palette?.main, theme.palette.primary.dark),\n light: pick(palette?.light, palette?.main, theme.palette.primary.light),\n contrastText: pick(palette?.contrastText, '#fff'),\n});\n\nexport const getColorFromTheme = (theme: Theme, color: string): ResolvedPalette => {\n if (color === 'neutral') return neutralPalette(theme);\n\n const colorMap: Record<string, PartialPalette> = {\n primary: theme.palette.primary,\n secondary: theme.palette.secondary,\n success: theme.palette.success,\n warning: theme.palette.warning,\n info: theme.palette.info,\n danger: theme.palette.error,\n };\n\n return withFallbacks(theme, colorMap[color] || theme.palette.primary);\n};\n\n// glass, gradient and glow are independent flags that each layer styles onto the\n// base. Spelled out here rather than inline so the styled() callback keeps one\n// branch instead of three.\nexport const textareaEmphasisStyles = ({\n theme,\n colorPalette,\n glass,\n gradient,\n glow,\n}: {\n theme: Theme;\n colorPalette: { main: string; light?: string; dark?: string };\n glass?: boolean;\n gradient?: boolean;\n glow?: boolean;\n}): CSSObject => {\nconst glassStyles = glass\n ? {\n backgroundColor: alpha(theme.palette.background.paper, 0.1),\n backdropFilter: 'blur(20px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.2)}`,\n '&:hover': {\n backgroundColor: alpha(theme.palette.background.paper, 0.15),\n backdropFilter: 'blur(25px)',\n },\n '&:focus': {\n backgroundColor: alpha(theme.palette.background.paper, 0.2),\n backdropFilter: 'blur(30px)',\n },\n }\n : {};\n\n// Gradient border effect\nconst gradientStyles = gradient\n ? {\n background: `linear-gradient(${theme.palette.background.paper}, ${theme.palette.background.paper}) padding-box,\n linear-gradient(135deg, ${colorPalette.main}, ${colorPalette.light}) border-box`,\n border: '2px solid transparent',\n '&:focus': {\n background: `linear-gradient(${theme.palette.background.paper}, ${theme.palette.background.paper}) padding-box,\n linear-gradient(135deg, ${colorPalette.main}, ${colorPalette.dark}) border-box`,\n },\n }\n : {};\n\n// Glow effect\nconst glowStyles = glow\n ? {\n animation: `${glowAnimation} 2s ease-in-out infinite`,\n boxShadow: `0 0 10px ${alpha(colorPalette.main, 0.3)}`,\n }\n : {};\n\n return { ...glassStyles, ...gradientStyles, ...glowStyles };\n};\n","import Code from '@mui/icons-material/Code';\nimport FormatBold from '@mui/icons-material/FormatBold';\nimport FormatColorFill from '@mui/icons-material/FormatColorFill';\nimport FormatColorText from '@mui/icons-material/FormatColorText';\nimport FormatItalic from '@mui/icons-material/FormatItalic';\nimport FormatListBulleted from '@mui/icons-material/FormatListBulleted';\nimport FormatListNumbered from '@mui/icons-material/FormatListNumbered';\nimport FormatQuote from '@mui/icons-material/FormatQuote';\nimport FormatUnderlined from '@mui/icons-material/FormatUnderlined';\nimport Link from '@mui/icons-material/Link';\nimport { alpha, Box, Divider, IconButton, Tooltip } from '@mui/material';\nimport type { Theme } from '@mui/material';\nimport { styled } from '@mui/material';\nimport React, { useEffect, useRef, useState } from 'react';\n\nimport { floatAnimation, getColorFromTheme } from './Textarea.styles';\n\nconst RichToolbar = styled(Box)<{ glass?: boolean }>(({ theme, glass }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n padding: theme.spacing(1),\n borderRadius: `${theme.spacing(1)} ${theme.spacing(1)} 0 0`,\n borderBottom: `1px solid ${theme.palette.divider}`,\n background: glass ? alpha(theme.palette.background.paper, 0.1) : theme.palette.background.paper,\n ...(glass && {\n backdropFilter: 'blur(15px)' }),\n '& .MuiDivider-root': {\n height: 24,\n margin: `0 ${theme.spacing(1)}` } }));\n\nconst ToolbarButton = styled(IconButton, {\n shouldForwardProp: (prop) => prop !== 'active' })<{ active?: boolean }>(({ theme, active }) => ({\n padding: theme.spacing(0.75),\n borderRadius: theme.spacing(0.5),\n color: active ? theme.palette.primary.main : theme.palette.text.secondary,\n backgroundColor: active ? alpha(theme.palette.primary.main, 0.1) : 'transparent',\n transition: 'all 0.2s ease',\n position: 'relative',\n overflow: 'hidden',\n\n '&::before': {\n content: '\"\"',\n position: 'absolute',\n top: '50%',\n left: '50%',\n width: 0,\n height: 0,\n borderRadius: '50%',\n backgroundColor: alpha(theme.palette.primary.main, 0.3),\n transform: 'translate(-50%, -50%)',\n transition: 'width 0.3s, height 0.3s' },\n\n '&:hover': {\n color: theme.palette.primary.main,\n backgroundColor: alpha(theme.palette.primary.main, 0.15),\n transform: 'translateY(-1px)',\n animation: `${floatAnimation} 1.5s ease-in-out infinite`,\n\n '&::before': {\n width: '100%',\n height: '100%' } },\n\n '&:active': {\n transform: 'scale(0.95)' } }));\n\nconst CharacterCount = styled(Box)<{ limit?: number; count: number }>(({ theme, limit, count }) => {\n const isWarning = limit && count > limit * 0.8;\n const isError = limit && count > limit;\n\n return {\n position: 'absolute',\n bottom: theme.spacing(1),\n right: theme.spacing(1),\n fontSize: '0.75rem',\n color: isError\n ? theme.palette.error.main\n : isWarning\n ? theme.palette.warning.main\n : theme.palette.text.secondary,\n padding: '2px 6px',\n borderRadius: theme.spacing(0.5),\n backgroundColor: alpha(theme.palette.background.paper, 0.8),\n backdropFilter: 'blur(10px)',\n transition: 'all 0.3s ease' };\n});\n\nconst ContentEditableDiv = styled('div')<{\n error?: boolean;\n focused?: boolean;\n glass?: boolean;\n customColor?: string;\n theme?: Theme;\n}>(({ theme, error, focused, glass, customColor = 'primary' }) => {\n if (!theme) return {};\n const colorPalette = getColorFromTheme(theme, customColor);\n const errorColor = theme.palette.error;\n\n return {\n minHeight: '120px',\n padding: theme.spacing(1.5),\n borderRadius: `0 0 ${theme.spacing(1)} ${theme.spacing(1)}`,\n border: `2px solid ${error ? errorColor.main : focused ? colorPalette.main : theme.palette.divider}`,\n borderTop: 'none',\n backgroundColor: glass\n ? alpha(theme.palette.background.paper, 0.1)\n : theme.palette.background.paper,\n color: theme.palette.text.primary,\n fontFamily: theme.typography.fontFamily,\n fontSize: '1rem',\n lineHeight: 1.5,\n outline: 'none',\n transition: 'all 0.3s ease',\n cursor: 'text',\n\n ...(glass && {\n backdropFilter: 'blur(20px)' }),\n\n '&:hover': {\n backgroundColor: glass\n ? alpha(theme.palette.background.paper, 0.15)\n : alpha(theme.palette.background.paper, 0.9) },\n\n '&:focus': {\n borderColor: error ? errorColor.main : colorPalette.main,\n boxShadow: `0 0 0 3px ${alpha(error ? errorColor.main : colorPalette.main, 0.1)}` },\n\n '& > *': {\n margin: '0.5em 0' },\n\n '&[contenteditable=\"true\"]:empty::before': {\n content: 'attr(data-placeholder)',\n color: theme.palette.text.secondary,\n opacity: 0.6 } };\n});\n\n// Rich text formatting functions\nconst formatText = (command: string, value?: string) => {\n document.execCommand(command, false, value);\n};\n\n// Editable state: what is typed, how long it is, and which formats apply at the\n// caret. Kept apart from the markup below.\nconst useRichEditorState = ({\n value,\n onChange }: {\n value?: string;\n onChange?: (html: string) => void;\n}) => {\n const [focused, setFocused] = useState(false);\n const [characterCount, setCharacterCount] = useState(0);\n const [activeFormats, setActiveFormats] = useState({\n bold: false,\n italic: false,\n underline: false,\n list: false,\n orderedList: false,\n quote: false,\n code: false });\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (contentRef.current && value !== undefined) {\n if (contentRef.current.innerHTML !== value) {\n contentRef.current.innerHTML = value;\n }\n setCharacterCount(contentRef.current.innerText.length);\n }\n }, [value]);\n\n const handleInput = () => {\n if (contentRef.current) {\n const html = contentRef.current.innerHTML;\n onChange?.(html);\n setCharacterCount(contentRef.current.innerText.length);\n updateActiveFormats();\n }\n };\n\n const updateActiveFormats = () => {\n setActiveFormats({\n bold: document.queryCommandState('bold'),\n italic: document.queryCommandState('italic'),\n underline: document.queryCommandState('underline'),\n list: document.queryCommandState('insertUnorderedList'),\n orderedList: document.queryCommandState('insertOrderedList'),\n quote: false,\n code: false });\n };\n\n const handleFormat = (command: string, value?: string) => {\n formatText(command, value);\n updateActiveFormats();\n contentRef.current?.focus();\n };\n\n return {\n focused,\n setFocused,\n characterCount,\n activeFormats,\n contentRef,\n handleInput,\n handleFormat,\n updateActiveFormats };\n};\n\nconst InlineFormatButtons: React.FC<{\n activeFormats: Record<string, boolean>;\n onCommand: (command: string, value?: string) => void;\n}> = ({ activeFormats, onCommand }) => (\n <>\n <Tooltip title=\"Bold\" arrow>\n <ToolbarButton\n size=\"small\"\n active={activeFormats.bold}\n onClick={() => onCommand('bold')}\n >\n <FormatBold fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title=\"Italic\" arrow>\n <ToolbarButton\n size=\"small\"\n active={activeFormats.italic}\n onClick={() => onCommand('italic')}\n >\n <FormatItalic fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title=\"Underline\" arrow>\n <ToolbarButton\n size=\"small\"\n active={activeFormats.underline}\n onClick={() => onCommand('underline')}\n >\n <FormatUnderlined fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n </>\n);\n\nconst BlockFormatButtons: React.FC<{\n activeFormats: Record<string, boolean>;\n onCommand: (command: string, value?: string) => void;\n}> = ({ activeFormats, onCommand }) => (\n <>\n <Divider orientation=\"vertical\" flexItem />\n\n <Tooltip title=\"Bullet List\" arrow>\n <ToolbarButton\n size=\"small\"\n active={activeFormats.list}\n onClick={() => onCommand('insertUnorderedList')}\n >\n <FormatListBulleted fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title=\"Numbered List\" arrow>\n <ToolbarButton\n size=\"small\"\n active={activeFormats.orderedList}\n onClick={() => onCommand('insertOrderedList')}\n >\n <FormatListNumbered fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Divider orientation=\"vertical\" flexItem />\n\n <Tooltip title=\"Quote\" arrow>\n <ToolbarButton size=\"small\" onClick={() => onCommand('formatBlock', 'blockquote')}>\n <FormatQuote fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title=\"Code\" arrow>\n <ToolbarButton size=\"small\" onClick={() => onCommand('formatBlock', 'pre')}>\n <Code fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Divider orientation=\"vertical\" flexItem />\n\n <Tooltip title=\"Insert Link\" arrow>\n <ToolbarButton\n size=\"small\"\n onClick={() => {\n const url = window.prompt('Enter URL:');\n if (url) onCommand('createLink', url);\n }}\n >\n <Link fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title=\"Text Color\" arrow>\n <ToolbarButton size=\"small\">\n <FormatColorText fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title=\"Background Color\" arrow>\n <ToolbarButton size=\"small\">\n <FormatColorFill fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n </>\n);\n\n// The formatting buttons. Split out so the editor body is state, handlers and\n// the editable region.\nconst EditorToolbar: React.FC<{\n glass?: boolean;\n activeFormats: Record<string, boolean>;\n onCommand: (command: string, value?: string) => void;\n}> = ({ glass, activeFormats, onCommand }) => (\n <RichToolbar glass={glass}>\n <InlineFormatButtons activeFormats={activeFormats} onCommand={onCommand} />\n <BlockFormatButtons activeFormats={activeFormats} onCommand={onCommand} />\n </RichToolbar>\n);\n\nexport const TextareaRichEditor: React.FC<{\n value?: string;\n onChange?: (html: string) => void;\n placeholder?: string;\n error?: boolean;\n glass?: boolean;\n color?: string;\n characterLimit?: number;\n}> = ({ value, onChange, placeholder, error, glass, color, characterLimit }) => {\n const {\n focused,\n setFocused,\n characterCount,\n activeFormats,\n contentRef,\n handleInput,\n handleFormat,\n updateActiveFormats } = useRichEditorState({ value, onChange });\n\n return (\n <Box sx={{ position: 'relative' }}>\n <EditorToolbar glass={glass} activeFormats={activeFormats} onCommand={handleFormat} />\n\n <ContentEditableDiv\n ref={contentRef}\n contentEditable\n data-placeholder={placeholder}\n error={error}\n focused={focused}\n glass={glass}\n customColor={color}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n onInput={handleInput}\n onKeyUp={updateActiveFormats}\n onMouseUp={updateActiveFormats}\n role=\"textbox\"\n aria-multiline=\"true\"\n aria-label={placeholder || 'Rich text editor'}\n />\n\n {characterLimit && (\n <CharacterCount limit={characterLimit} count={characterCount}>\n {characterCount}\n {characterLimit ? `/${characterLimit}` : ''}\n </CharacterCount>\n )}\n </Box>\n );\n};\n"],"mappings":"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","names":["alpha","Box","styled","useState","alpha","alpha","value","jsx","jsxs","styled","alpha","Box","useState"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/form/Textarea/Textarea.tsx","../../src/components/form/Textarea/Textarea.styles.ts","../../src/components/form/Textarea/TextareaRichEditor.tsx"],"sourcesContent":["import {\n alpha,\n Box,\n FormHelperText,\n InputLabel,\n TextareaAutosize } from '@mui/material';\nimport type { Theme } from '@mui/material';\nimport { styled } from '@mui/material';\nimport React, { useState } from 'react';\n\nimport {\n getColorFromTheme,\n textareaEmphasisStyles } from './Textarea.styles';\nimport { TextareaRichEditor } from './TextareaRichEditor';\nimport type { TextareaProps } from './Textarea.types';\n\n// Interface for styled component props\ninterface StyledTextareaProps {\n customVariant?: string;\n customColor?: string;\n customSize?: string;\n glow?: boolean;\n glass?: boolean;\n gradient?: boolean;\n error?: boolean;\n theme?: Theme;\n}\n\n// Glow animation for enhanced visual effects\nconst StyledTextarea = styled(TextareaAutosize, {\n shouldForwardProp: (prop) =>\n !['customVariant', 'customColor', 'customSize', 'glow', 'glass', 'gradient', 'error'].includes(\n prop as string,\n ) })<StyledTextareaProps>(({\n theme,\n customVariant,\n customColor = 'primary',\n customSize = 'md',\n glow,\n glass,\n gradient,\n error }) => {\n if (!theme) return {};\n const colorPalette = getColorFromTheme(theme, customColor);\n const errorColor = theme.palette.error;\n\n const sizeMap = {\n xs: { padding: '6px 8px', fontSize: '0.75rem', minHeight: '60px' },\n sm: { padding: '8px 10px', fontSize: '0.875rem', minHeight: '80px' },\n md: { padding: '10px 12px', fontSize: '1rem', minHeight: '100px' },\n lg: { padding: '12px 14px', fontSize: '1.125rem', minHeight: '120px' },\n xl: { padding: '14px 16px', fontSize: '1.25rem', minHeight: '140px' } };\n\n const baseStyles = {\n width: '100%',\n fontFamily: theme.typography.fontFamily,\n borderRadius: theme.spacing(1),\n border: `2px solid ${error ? errorColor.main : theme.palette.divider}`,\n backgroundColor: theme.palette.background.paper,\n color: theme.palette.text.primary,\n transition: 'all 0.3s ease',\n resize: customVariant === 'resizable' ? 'vertical' : 'none',\n outline: 'none',\n ...sizeMap[customSize as keyof typeof sizeMap],\n\n '&::placeholder': {\n color: theme.palette.text.secondary,\n opacity: 0.7 },\n\n '&:hover': {\n borderColor: error ? errorColor.dark : colorPalette.main,\n backgroundColor: alpha(theme.palette.background.paper, 0.8) },\n\n '&:focus': {\n borderColor: error ? errorColor.main : colorPalette.main,\n backgroundColor: theme.palette.background.paper,\n boxShadow: `0 0 0 3px ${alpha(error ? errorColor.main : colorPalette.main, 0.1)}` } };\n\n // Glass morphism effect\n return {\n ...baseStyles,\n ...textareaEmphasisStyles({ theme, colorPalette, glass, gradient, glow }) };\n});\n\nconst StyledLabel = styled(InputLabel, {\n shouldForwardProp: (prop) => !['glass', 'error'].includes(prop as string) })<{ glass?: boolean; error?: boolean }>(({ theme, glass, error }) => ({\n marginBottom: theme.spacing(1),\n fontWeight: 500,\n color: error ? theme.palette.error.main : theme.palette.text.primary,\n ...(glass && {\n backgroundColor: alpha(theme.palette.background.paper, 0.1),\n backdropFilter: 'blur(10px)',\n padding: '4px 8px',\n borderRadius: '4px',\n border: `1px solid ${alpha(theme.palette.divider, 0.2)}`,\n display: 'inline-block' }) }));\n\n// IconWrapper - replaced with inline Box component for better TypeScript compatibility\n// const IconWrapper = styled(Box)<{ position: 'start' | 'end' }>(({ theme, position }) => {\n// const positionStyles = position === 'start' ? { left: '12px' } : { right: '12px' };\n// return {\n// position: 'absolute' as const,\n// top: '12px',\n// ...positionStyles,\n// color: theme.palette.text.secondary,\n// pointerEvents: 'none' as const,\n// zIndex: 1,\n// };\n// });\n\n// Rich text toolbar styling\n\nconst ICON_GUTTER = '40px';\n\nconst TEXTAREA_DEFAULTS = {\n variant: 'default',\n color: 'primary',\n size: 'md',\n error: false,\n glassLabel: false,\n glow: false,\n glass: false,\n gradient: false,\n iconPosition: 'start',\n minRows: 3 } satisfies Partial<TextareaProps>;\n\n// Strips explicitly-undefined props before the merge, so `prop={undefined}`\n// still falls back to the default as a destructuring default would.\nconst definedProps = (props: TextareaProps): Partial<TextareaProps> =>\n Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<TextareaProps>;\n\n// Label above, helper text below — identical for the plain and rich variants,\n// which previously duplicated both.\nconst TextareaShell: React.FC<{\n testId?: string;\n label?: React.ReactNode;\n glassLabel: boolean;\n error: boolean;\n helperText?: React.ReactNode;\n children: React.ReactNode;\n}> = ({ testId, label, glassLabel, error, helperText, children }) => (\n <Box\n sx={{ position: 'relative', width: '100%' }}\n data-testid={testId ? `${testId}-wrapper` : undefined}\n >\n {label && (\n <StyledLabel glass={glassLabel} error={error}>\n {label}\n </StyledLabel>\n )}\n\n {children}\n\n {helperText && (\n <FormHelperText error={error} sx={{ mt: 1 }}>\n {helperText}\n </FormHelperText>\n )}\n </Box>\n);\n\nconst TextareaIcon: React.FC<{\n icon?: React.ReactNode;\n iconPosition: 'start' | 'end';\n}> = ({ icon, iconPosition }) => (\n <Box\n sx={{\n position: 'absolute',\n top: '12px',\n ...(iconPosition === 'start' ? { left: '12px' } : { right: '12px' }),\n color: 'text.secondary',\n pointerEvents: 'none',\n zIndex: 1 }}\n >\n {icon}\n </Box>\n);\n\nexport const Textarea: React.FC<TextareaProps> = (textareaProps) => {\n const {\n variant,\n color,\n size,\n error,\n helperText,\n label,\n glassLabel,\n glow,\n glass,\n gradient,\n icon,\n iconPosition,\n minRows,\n maxRows,\n style,\n 'data-testid': dataTestId,\n dataTestId: dataTestIdCamelCase,\n ...props\n } = { ...TEXTAREA_DEFAULTS, ...definedProps(textareaProps) };\n\n // Read off the props rather than the merged object: the spread widens every\n // key to optional, which would lose what the variant union already proved.\n const { richEditorCopy } = textareaProps;\n\n const [richTextValue, setRichTextValue] = useState('');\n const hasIcon = Boolean(icon);\n const testId = dataTestId || dataTestIdCamelCase;\n\n const textareaStyle = {\n ...style,\n // Same gap either side; only which side it applies to changes. The previous\n // version had `iconPosition === 'start' ? '40px' : '40px'`, a ternary whose\n // two branches were identical.\n ...(hasIcon && {\n [iconPosition === 'start' ? 'paddingLeft' : 'paddingRight']: ICON_GUTTER }) };\n\n // If rich text variant, use the rich text editor\n if (variant === 'rich' && richEditorCopy) {\n return (\n <TextareaShell testId={testId} label={label} glassLabel={glassLabel} error={error} helperText={helperText}>\n <TextareaRichEditor\n copy={richEditorCopy}\n value={richTextValue}\n onChange={setRichTextValue}\n placeholder={props.placeholder}\n error={error}\n glass={glass}\n color={color}\n characterLimit={props.maxLength}\n />\n </TextareaShell>\n );\n }\n\n return (\n <TextareaShell testId={testId} label={label} glassLabel={glassLabel} error={error} helperText={helperText}>\n <Box sx={{ position: 'relative' }}>\n {hasIcon && <TextareaIcon icon={icon} iconPosition={iconPosition} />}\n\n <StyledTextarea\n customVariant={variant}\n customColor={color}\n customSize={size}\n glow={glow}\n glass={glass}\n gradient={gradient}\n error={error}\n minRows={variant === 'autosize' ? minRows : undefined}\n maxRows={variant === 'autosize' ? maxRows : undefined}\n style={textareaStyle}\n aria-label={label || props['aria-label']}\n data-testid={testId}\n {...props}\n />\n </Box>\n </TextareaShell>\n );\n};\n\nTextarea.displayName = 'Textarea';\n","import { alpha, keyframes } from '@mui/material';\nimport type { CSSObject, Theme } from '@mui/material';\n\nconst glowAnimation = keyframes`\n 0% {\n box-shadow: 0 0 5px currentColor;\n }\n 50% {\n box-shadow: 0 0 20px currentColor, 0 0 30px currentColor;\n }\n 100% {\n box-shadow: 0 0 5px currentColor;\n }\n`;\n\n// Ripple animation for buttons (commented out - not currently used)\n// const rippleAnimation = keyframes`\n// 0% {\n// transform: scale(0);\n// opacity: 1;\n// }\n// 100% {\n// transform: scale(4);\n// opacity: 0;\n// }\n// `;\n\n// Float animation for rich text toolbar\nexport const floatAnimation = keyframes`\n 0% {\n transform: translateY(0px);\n }\n 50% {\n transform: translateY(-3px);\n }\n 100% {\n transform: translateY(0px);\n }\n`;\n\ntype ResolvedPalette = {\n main: string;\n dark: string;\n light: string;\n contrastText: string;\n};\n\ntype PartialPalette = { main: string; dark?: string; light?: string; contrastText?: string };\n\n// grey is indexed by weight rather than main/dark/light, so neutral is built by\n// hand. The literals are the MUI grey values, used if the theme omits a weight.\nconst neutralPalette = (theme: Theme): ResolvedPalette => {\n const grey = theme.palette.grey as unknown as Record<number, string>;\n\n return {\n main: grey?.[700] || '#616161',\n dark: grey?.[800] || '#424242',\n light: grey?.[500] || '#9e9e9e',\n contrastText: '#fff',\n };\n};\n\n// Each slot falls back to the palette's own main, then to primary — a custom\n// theme can define main without dark or light.\nconst pick = (...candidates: Array<string | undefined>): string =>\n candidates.find(Boolean) ?? '';\n\nconst withFallbacks = (theme: Theme, palette: PartialPalette): ResolvedPalette => ({\n main: pick(palette?.main, theme.palette.primary.main),\n dark: pick(palette?.dark, palette?.main, theme.palette.primary.dark),\n light: pick(palette?.light, palette?.main, theme.palette.primary.light),\n contrastText: pick(palette?.contrastText, '#fff'),\n});\n\nexport const getColorFromTheme = (theme: Theme, color: string): ResolvedPalette => {\n if (color === 'neutral') return neutralPalette(theme);\n\n const colorMap: Record<string, PartialPalette> = {\n primary: theme.palette.primary,\n secondary: theme.palette.secondary,\n success: theme.palette.success,\n warning: theme.palette.warning,\n info: theme.palette.info,\n danger: theme.palette.error,\n };\n\n return withFallbacks(theme, colorMap[color] || theme.palette.primary);\n};\n\n// glass, gradient and glow are independent flags that each layer styles onto the\n// base. Spelled out here rather than inline so the styled() callback keeps one\n// branch instead of three.\nexport const textareaEmphasisStyles = ({\n theme,\n colorPalette,\n glass,\n gradient,\n glow,\n}: {\n theme: Theme;\n colorPalette: { main: string; light?: string; dark?: string };\n glass?: boolean;\n gradient?: boolean;\n glow?: boolean;\n}): CSSObject => {\nconst glassStyles = glass\n ? {\n backgroundColor: alpha(theme.palette.background.paper, 0.1),\n backdropFilter: 'blur(20px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.2)}`,\n '&:hover': {\n backgroundColor: alpha(theme.palette.background.paper, 0.15),\n backdropFilter: 'blur(25px)',\n },\n '&:focus': {\n backgroundColor: alpha(theme.palette.background.paper, 0.2),\n backdropFilter: 'blur(30px)',\n },\n }\n : {};\n\n// Gradient border effect\nconst gradientStyles = gradient\n ? {\n background: `linear-gradient(${theme.palette.background.paper}, ${theme.palette.background.paper}) padding-box,\n linear-gradient(135deg, ${colorPalette.main}, ${colorPalette.light}) border-box`,\n border: '2px solid transparent',\n '&:focus': {\n background: `linear-gradient(${theme.palette.background.paper}, ${theme.palette.background.paper}) padding-box,\n linear-gradient(135deg, ${colorPalette.main}, ${colorPalette.dark}) border-box`,\n },\n }\n : {};\n\n// Glow effect\nconst glowStyles = glow\n ? {\n animation: `${glowAnimation} 2s ease-in-out infinite`,\n boxShadow: `0 0 10px ${alpha(colorPalette.main, 0.3)}`,\n }\n : {};\n\n return { ...glassStyles, ...gradientStyles, ...glowStyles };\n};\n","import Code from '@mui/icons-material/Code';\nimport FormatBold from '@mui/icons-material/FormatBold';\nimport FormatColorFill from '@mui/icons-material/FormatColorFill';\nimport FormatColorText from '@mui/icons-material/FormatColorText';\nimport FormatItalic from '@mui/icons-material/FormatItalic';\nimport FormatListBulleted from '@mui/icons-material/FormatListBulleted';\nimport FormatListNumbered from '@mui/icons-material/FormatListNumbered';\nimport FormatQuote from '@mui/icons-material/FormatQuote';\nimport FormatUnderlined from '@mui/icons-material/FormatUnderlined';\nimport Link from '@mui/icons-material/Link';\nimport { alpha, Box, Divider, IconButton, Tooltip } from '@mui/material';\nimport type { Theme } from '@mui/material';\nimport { styled } from '@mui/material';\nimport React, { useEffect, useRef, useState } from 'react';\n\nimport { floatAnimation, getColorFromTheme } from './Textarea.styles';\nimport type { RichEditorToolbarCopy } from '../../../copy';\n\nconst RichToolbar = styled(Box)<{ glass?: boolean }>(({ theme, glass }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n padding: theme.spacing(1),\n borderRadius: `${theme.spacing(1)} ${theme.spacing(1)} 0 0`,\n borderBottom: `1px solid ${theme.palette.divider}`,\n background: glass ? alpha(theme.palette.background.paper, 0.1) : theme.palette.background.paper,\n ...(glass && {\n backdropFilter: 'blur(15px)' }),\n '& .MuiDivider-root': {\n height: 24,\n margin: `0 ${theme.spacing(1)}` } }));\n\nconst ToolbarButton = styled(IconButton, {\n shouldForwardProp: (prop) => prop !== 'active' })<{ active?: boolean }>(({ theme, active }) => ({\n padding: theme.spacing(0.75),\n borderRadius: theme.spacing(0.5),\n color: active ? theme.palette.primary.main : theme.palette.text.secondary,\n backgroundColor: active ? alpha(theme.palette.primary.main, 0.1) : 'transparent',\n transition: 'all 0.2s ease',\n position: 'relative',\n overflow: 'hidden',\n\n '&::before': {\n content: '\"\"',\n position: 'absolute',\n top: '50%',\n left: '50%',\n width: 0,\n height: 0,\n borderRadius: '50%',\n backgroundColor: alpha(theme.palette.primary.main, 0.3),\n transform: 'translate(-50%, -50%)',\n transition: 'width 0.3s, height 0.3s' },\n\n '&:hover': {\n color: theme.palette.primary.main,\n backgroundColor: alpha(theme.palette.primary.main, 0.15),\n transform: 'translateY(-1px)',\n animation: `${floatAnimation} 1.5s ease-in-out infinite`,\n\n '&::before': {\n width: '100%',\n height: '100%' } },\n\n '&:active': {\n transform: 'scale(0.95)' } }));\n\nconst CharacterCount = styled(Box)<{ limit?: number; count: number }>(({ theme, limit, count }) => {\n const isWarning = limit && count > limit * 0.8;\n const isError = limit && count > limit;\n\n return {\n position: 'absolute',\n bottom: theme.spacing(1),\n right: theme.spacing(1),\n fontSize: '0.75rem',\n color: isError\n ? theme.palette.error.main\n : isWarning\n ? theme.palette.warning.main\n : theme.palette.text.secondary,\n padding: '2px 6px',\n borderRadius: theme.spacing(0.5),\n backgroundColor: alpha(theme.palette.background.paper, 0.8),\n backdropFilter: 'blur(10px)',\n transition: 'all 0.3s ease' };\n});\n\nconst ContentEditableDiv = styled('div')<{\n error?: boolean;\n focused?: boolean;\n glass?: boolean;\n customColor?: string;\n theme?: Theme;\n}>(({ theme, error, focused, glass, customColor = 'primary' }) => {\n if (!theme) return {};\n const colorPalette = getColorFromTheme(theme, customColor);\n const errorColor = theme.palette.error;\n\n return {\n minHeight: '120px',\n padding: theme.spacing(1.5),\n borderRadius: `0 0 ${theme.spacing(1)} ${theme.spacing(1)}`,\n border: `2px solid ${error ? errorColor.main : focused ? colorPalette.main : theme.palette.divider}`,\n borderTop: 'none',\n backgroundColor: glass\n ? alpha(theme.palette.background.paper, 0.1)\n : theme.palette.background.paper,\n color: theme.palette.text.primary,\n fontFamily: theme.typography.fontFamily,\n fontSize: '1rem',\n lineHeight: 1.5,\n outline: 'none',\n transition: 'all 0.3s ease',\n cursor: 'text',\n\n ...(glass && {\n backdropFilter: 'blur(20px)' }),\n\n '&:hover': {\n backgroundColor: glass\n ? alpha(theme.palette.background.paper, 0.15)\n : alpha(theme.palette.background.paper, 0.9) },\n\n '&:focus': {\n borderColor: error ? errorColor.main : colorPalette.main,\n boxShadow: `0 0 0 3px ${alpha(error ? errorColor.main : colorPalette.main, 0.1)}` },\n\n '& > *': {\n margin: '0.5em 0' },\n\n '&[contenteditable=\"true\"]:empty::before': {\n content: 'attr(data-placeholder)',\n color: theme.palette.text.secondary,\n opacity: 0.6 } };\n});\n\n// Rich text formatting functions\nconst formatText = (command: string, value?: string) => {\n document.execCommand(command, false, value);\n};\n\n// Editable state: what is typed, how long it is, and which formats apply at the\n// caret. Kept apart from the markup below.\nconst useRichEditorState = ({\n value,\n onChange }: {\n value?: string;\n onChange?: (html: string) => void;\n}) => {\n const [focused, setFocused] = useState(false);\n const [characterCount, setCharacterCount] = useState(0);\n const [activeFormats, setActiveFormats] = useState({\n bold: false,\n italic: false,\n underline: false,\n list: false,\n orderedList: false,\n quote: false,\n code: false });\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (contentRef.current && value !== undefined) {\n if (contentRef.current.innerHTML !== value) {\n contentRef.current.innerHTML = value;\n }\n setCharacterCount(contentRef.current.innerText.length);\n }\n }, [value]);\n\n const handleInput = () => {\n if (contentRef.current) {\n const html = contentRef.current.innerHTML;\n onChange?.(html);\n setCharacterCount(contentRef.current.innerText.length);\n updateActiveFormats();\n }\n };\n\n const updateActiveFormats = () => {\n setActiveFormats({\n bold: document.queryCommandState('bold'),\n italic: document.queryCommandState('italic'),\n underline: document.queryCommandState('underline'),\n list: document.queryCommandState('insertUnorderedList'),\n orderedList: document.queryCommandState('insertOrderedList'),\n quote: false,\n code: false });\n };\n\n const handleFormat = (command: string, value?: string) => {\n formatText(command, value);\n updateActiveFormats();\n contentRef.current?.focus();\n };\n\n return {\n focused,\n setFocused,\n characterCount,\n activeFormats,\n contentRef,\n handleInput,\n handleFormat,\n updateActiveFormats };\n};\n\nconst InlineFormatButtons: React.FC<{\n copy: RichEditorToolbarCopy;\n activeFormats: Record<string, boolean>;\n onCommand: (command: string, value?: string) => void;\n}> = ({ copy, activeFormats, onCommand }) => (\n <>\n <Tooltip title={copy.bold} arrow>\n <ToolbarButton\n size=\"small\"\n active={activeFormats.bold}\n onClick={() => onCommand('bold')}\n >\n <FormatBold fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title={copy.italic} arrow>\n <ToolbarButton\n size=\"small\"\n active={activeFormats.italic}\n onClick={() => onCommand('italic')}\n >\n <FormatItalic fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title={copy.underline} arrow>\n <ToolbarButton\n size=\"small\"\n active={activeFormats.underline}\n onClick={() => onCommand('underline')}\n >\n <FormatUnderlined fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n </>\n);\n\nconst BlockFormatButtons: React.FC<{\n copy: RichEditorToolbarCopy;\n activeFormats: Record<string, boolean>;\n onCommand: (command: string, value?: string) => void;\n}> = ({ copy, activeFormats, onCommand }) => (\n <>\n <Divider orientation=\"vertical\" flexItem />\n\n <Tooltip title={copy.bulletList} arrow>\n <ToolbarButton\n size=\"small\"\n active={activeFormats.list}\n onClick={() => onCommand('insertUnorderedList')}\n >\n <FormatListBulleted fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title={copy.numberedList} arrow>\n <ToolbarButton\n size=\"small\"\n active={activeFormats.orderedList}\n onClick={() => onCommand('insertOrderedList')}\n >\n <FormatListNumbered fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Divider orientation=\"vertical\" flexItem />\n\n <Tooltip title={copy.quote} arrow>\n <ToolbarButton size=\"small\" onClick={() => onCommand('formatBlock', 'blockquote')}>\n <FormatQuote fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title={copy.code} arrow>\n <ToolbarButton size=\"small\" onClick={() => onCommand('formatBlock', 'pre')}>\n <Code fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Divider orientation=\"vertical\" flexItem />\n\n <Tooltip title={copy.insertLink} arrow>\n <ToolbarButton\n size=\"small\"\n onClick={() => {\n const url = window.prompt(copy.linkPrompt);\n if (url) onCommand('createLink', url);\n }}\n >\n <Link fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title={copy.textColor} arrow>\n <ToolbarButton size=\"small\">\n <FormatColorText fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n\n <Tooltip title={copy.backgroundColor} arrow>\n <ToolbarButton size=\"small\">\n <FormatColorFill fontSize=\"small\" />\n </ToolbarButton>\n </Tooltip>\n </>\n);\n\n// The formatting buttons. Split out so the editor body is state, handlers and\n// the editable region.\nconst EditorToolbar: React.FC<{\n copy: RichEditorToolbarCopy;\n glass?: boolean;\n activeFormats: Record<string, boolean>;\n onCommand: (command: string, value?: string) => void;\n}> = ({ copy, glass, activeFormats, onCommand }) => (\n <RichToolbar glass={glass}>\n <InlineFormatButtons copy={copy} activeFormats={activeFormats} onCommand={onCommand} />\n <BlockFormatButtons copy={copy} activeFormats={activeFormats} onCommand={onCommand} />\n </RichToolbar>\n);\n\nexport const TextareaRichEditor: React.FC<{\n /**\n * The ten toolbar buttons' tooltips — which are also their accessible names,\n * since every one of them is a glyph — plus the link prompt. REQUIRED: this\n * package ships no default copy.\n */\n copy: RichEditorToolbarCopy;\n value?: string;\n onChange?: (html: string) => void;\n placeholder?: string;\n error?: boolean;\n glass?: boolean;\n color?: string;\n characterLimit?: number;\n}> = ({ copy, value, onChange, placeholder, error, glass, color, characterLimit }) => {\n const {\n focused,\n setFocused,\n characterCount,\n activeFormats,\n contentRef,\n handleInput,\n handleFormat,\n updateActiveFormats } = useRichEditorState({ value, onChange });\n\n return (\n <Box sx={{ position: 'relative' }}>\n <EditorToolbar copy={copy} glass={glass} activeFormats={activeFormats} onCommand={handleFormat} />\n\n <ContentEditableDiv\n ref={contentRef}\n contentEditable\n data-placeholder={placeholder}\n error={error}\n focused={focused}\n glass={glass}\n customColor={color}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n onInput={handleInput}\n onKeyUp={updateActiveFormats}\n onMouseUp={updateActiveFormats}\n role=\"textbox\"\n aria-multiline=\"true\"\n aria-label={placeholder || 'Rich text editor'}\n />\n\n {characterLimit && (\n <CharacterCount limit={characterLimit} count={characterCount}>\n {characterCount}\n {characterLimit ? `/${characterLimit}` : ''}\n </CharacterCount>\n )}\n </Box>\n );\n};\n"],"mappings":"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","names":["alpha","Box","styled","useState","alpha","alpha","value","jsx","jsxs","styled","alpha","Box","useState"]}
|
|
@@ -205,6 +205,7 @@ import CloudUploadOutlined from "@mui/icons-material/CloudUploadOutlined";
|
|
|
205
205
|
import { Box, Button, LinearProgress, Typography, useTheme } from "@mui/material";
|
|
206
206
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
207
207
|
function UploadDropzone({
|
|
208
|
+
copy,
|
|
208
209
|
label,
|
|
209
210
|
icon,
|
|
210
211
|
disabled,
|
|
@@ -248,17 +249,18 @@ function UploadDropzone({
|
|
|
248
249
|
onOpen();
|
|
249
250
|
},
|
|
250
251
|
"aria-describedby": describedBy,
|
|
251
|
-
"aria-label":
|
|
252
|
+
"aria-label": copy.dropzoneRole(label),
|
|
252
253
|
children: [
|
|
253
254
|
/* @__PURE__ */ jsx(Box, { sx: { mb: 2 }, children: icon || /* @__PURE__ */ jsx(CloudUploadOutlined, { sx: { fontSize: 48, color: "text.secondary" } }) }),
|
|
254
255
|
/* @__PURE__ */ jsx(Typography, { variant: "body1", sx: { mb: 1 }, children: label }),
|
|
255
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children:
|
|
256
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: copy.dropzoneHint })
|
|
256
257
|
]
|
|
257
258
|
}
|
|
258
259
|
);
|
|
259
260
|
}
|
|
260
261
|
var MUI_VARIANT = { outline: "outlined", ghost: "text" };
|
|
261
262
|
function UploadTrigger({
|
|
263
|
+
copy,
|
|
262
264
|
label,
|
|
263
265
|
icon,
|
|
264
266
|
disabled,
|
|
@@ -285,11 +287,12 @@ function UploadTrigger({
|
|
|
285
287
|
"&:hover": { backgroundColor: `${theme.palette.primary.main}08` }
|
|
286
288
|
}
|
|
287
289
|
},
|
|
288
|
-
children: isUploading ?
|
|
290
|
+
children: isUploading ? copy.uploading : label
|
|
289
291
|
}
|
|
290
292
|
);
|
|
291
293
|
}
|
|
292
294
|
function UploadAnnouncer({
|
|
295
|
+
copy,
|
|
293
296
|
announceDragOver,
|
|
294
297
|
isUploading,
|
|
295
298
|
progress,
|
|
@@ -309,14 +312,15 @@ function UploadAnnouncer({
|
|
|
309
312
|
overflow: "hidden"
|
|
310
313
|
},
|
|
311
314
|
children: [
|
|
312
|
-
announceDragOver &&
|
|
313
|
-
isUploading &&
|
|
314
|
-
error &&
|
|
315
|
+
announceDragOver && copy.dropReady,
|
|
316
|
+
isUploading && copy.uploadInProgress(Math.round(progress)),
|
|
317
|
+
error && copy.errorAnnouncement(error)
|
|
315
318
|
]
|
|
316
319
|
}
|
|
317
320
|
);
|
|
318
321
|
}
|
|
319
322
|
function UploadFeedback({
|
|
323
|
+
copy,
|
|
320
324
|
isUploading,
|
|
321
325
|
progress,
|
|
322
326
|
helperText,
|
|
@@ -328,10 +332,7 @@ function UploadFeedback({
|
|
|
328
332
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
329
333
|
isUploading && progress > 0 && /* @__PURE__ */ jsxs(Box, { sx: { mt: 1 }, children: [
|
|
330
334
|
/* @__PURE__ */ jsx(LinearProgress, { variant: "determinate", value: progress, sx: { borderRadius: 1 } }),
|
|
331
|
-
/* @__PURE__ */
|
|
332
|
-
Math.round(progress),
|
|
333
|
-
"% uploaded"
|
|
334
|
-
] })
|
|
335
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", sx: { mt: 0.5, display: "block" }, children: copy.percentUploaded(Math.round(progress)) })
|
|
335
336
|
] }),
|
|
336
337
|
helperText && !error && /* @__PURE__ */ jsx(
|
|
337
338
|
Typography,
|
|
@@ -357,6 +358,7 @@ function UploadFeedback({
|
|
|
357
358
|
/* @__PURE__ */ jsx(
|
|
358
359
|
UploadAnnouncer,
|
|
359
360
|
{
|
|
361
|
+
copy,
|
|
360
362
|
announceDragOver,
|
|
361
363
|
isUploading,
|
|
362
364
|
progress,
|
|
@@ -370,8 +372,9 @@ function UploadFeedback({
|
|
|
370
372
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
371
373
|
var UploadButton = React.forwardRef((props, ref) => {
|
|
372
374
|
const {
|
|
375
|
+
copy,
|
|
373
376
|
variant = "default",
|
|
374
|
-
label =
|
|
377
|
+
label = props.copy.buttonLabel,
|
|
375
378
|
disabled = false,
|
|
376
379
|
multiple = false,
|
|
377
380
|
accept,
|
|
@@ -383,6 +386,7 @@ var UploadButton = React.forwardRef((props, ref) => {
|
|
|
383
386
|
} = props;
|
|
384
387
|
const { inputRef, inputId, state, drag, derived, openPicker, handleInputChange } = useUploadButton(props);
|
|
385
388
|
const trigger = {
|
|
389
|
+
copy,
|
|
386
390
|
label,
|
|
387
391
|
icon,
|
|
388
392
|
disabled,
|
|
@@ -411,6 +415,7 @@ var UploadButton = React.forwardRef((props, ref) => {
|
|
|
411
415
|
/* @__PURE__ */ jsx2(
|
|
412
416
|
UploadFeedback,
|
|
413
417
|
{
|
|
418
|
+
copy,
|
|
414
419
|
isUploading: derived.isUploading,
|
|
415
420
|
progress: derived.progress,
|
|
416
421
|
helperText,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/form/UploadButton/UploadButton.tsx","../../src/components/form/UploadButton/UploadButton.hooks.ts","../../src/components/form/UploadButton/UploadButton.parts.tsx"],"sourcesContent":["import { Box } from '@mui/material';\nimport React from 'react';\n\nimport { useUploadButton } from './UploadButton.hooks';\nimport {\n UploadDropzone,\n UploadFeedback,\n UploadTrigger,\n type TriggerProps,\n} from './UploadButton.parts';\nimport type { UploadButtonProps, UploadButtonState } from './UploadButton.types';\n\n/**\n * A file picker with an optional drag-and-drop surface.\n *\n * The body here is deliberately thin: selection rules live in\n * `UploadButton.hooks`, appearance in `UploadButton.parts`. What remains is the\n * wiring — the hidden input, which trigger to render, and the feedback beneath.\n */\nconst UploadButton = React.forwardRef<HTMLInputElement, UploadButtonProps>((props, ref) => {\n const {\n variant = 'default',\n label = 'Upload File',\n disabled = false,\n multiple = false,\n accept,\n capture,\n helperText,\n icon,\n className,\n 'data-testid': dataTestId,\n } = props;\n const { inputRef, inputId, state, drag, derived, openPicker, handleInputChange } =\n useUploadButton(props);\n\n const trigger: TriggerProps = {\n label,\n icon,\n disabled,\n className,\n dataTestId,\n describedBy: derived.describedBy,\n onOpen: openPicker,\n };\n\n return (\n <Box>\n <input\n ref={ref || inputRef}\n id={inputId}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n capture={capture}\n onChange={handleInputChange}\n style={{ display: 'none' }}\n disabled={disabled}\n aria-hidden=\"true\"\n />\n\n {variant === 'dropzone' ? (\n <UploadDropzone {...trigger} isDragOver={state.isDragOver} drag={drag} />\n ) : (\n <UploadTrigger {...trigger} variant={variant} isUploading={derived.isUploading} />\n )}\n\n <UploadFeedback\n isUploading={derived.isUploading}\n progress={derived.progress}\n helperText={helperText}\n helperId={derived.helperId}\n error={derived.error}\n errorId={derived.errorId}\n announceDragOver={variant === 'dropzone' && state.isDragOver}\n />\n </Box>\n );\n});\n\nUploadButton.displayName = 'UploadButton';\n\nexport { UploadButton };\nexport type { UploadButtonProps, UploadButtonState };\n","import { useCallback, useId, useMemo, useRef, useState } from 'react';\nimport type React from 'react';\n\nimport type { UploadButtonProps, UploadButtonState } from './UploadButton.types';\n\n/** The props {@link useUploadButton} reads — the component's own props. */\ntype UploadButtonHookProps = UploadButtonProps;\n\n/** Percent the simulated progress creeps to while waiting on `onUpload`. */\nconst SIMULATED_PROGRESS_CEILING = 90;\nconst SIMULATED_PROGRESS_STEP = 10;\nconst SIMULATED_PROGRESS_INTERVAL_MS = 100;\nconst PROGRESS_RESET_DELAY_MS = 1000;\nconst BYTES_PER_MB = 1024 * 1024;\n\nconst INITIAL_STATE: UploadButtonState = {\n isDragOver: false,\n isUploading: false,\n uploadProgress: 0,\n error: null,\n};\n\n/** Narrowed `setState` for the pieces below. */\ntype SetState = React.Dispatch<React.SetStateAction<UploadButtonState>>;\n\n/** The size/custom validation applied to every file, in both modes. */\nfunction useFileValidator(\n maxSizeMB: number | undefined,\n validate: ((file: globalThis.File) => string | null) | undefined,\n): (file: globalThis.File) => string | null {\n return useCallback(\n (file: globalThis.File): string | null => {\n if (maxSizeMB && file.size > maxSizeMB * BYTES_PER_MB) {\n return `File size must be less than ${maxSizeMB}MB`;\n }\n return validate ? validate(file) : null;\n },\n [maxSizeMB, validate],\n );\n}\n\n/**\n * The built-in upload path, reachable from BOTH selection modes.\n *\n * Kept apart from selection because it is the only asynchronous part: left\n * inline it was single-file only, which made `onUpload` a silent no-op for a\n * multi-file caller — the worst kind of contract, since nothing fails.\n */\nfunction useUploadRunner(\n onUpload: ((file: globalThis.File) => Promise<void>) | undefined,\n externalUploading: boolean,\n setState: SetState,\n): (file: globalThis.File) => Promise<void> {\n return useCallback(\n async (file: globalThis.File) => {\n if (!onUpload || externalUploading) return;\n try {\n setState((prev) => ({ ...prev, isUploading: true, uploadProgress: 0 }));\n // The real percentage is unknowable through a bare promise, so the bar\n // creeps to a ceiling and only completes when the promise does.\n const timer = globalThis.setInterval(() => {\n setState((prev) => {\n if (prev.uploadProgress >= SIMULATED_PROGRESS_CEILING) {\n globalThis.clearInterval(timer);\n return prev;\n }\n return { ...prev, uploadProgress: prev.uploadProgress + SIMULATED_PROGRESS_STEP };\n });\n }, SIMULATED_PROGRESS_INTERVAL_MS);\n\n await onUpload(file);\n\n globalThis.clearInterval(timer);\n setState((prev) => ({ ...prev, isUploading: false, uploadProgress: 100 }));\n globalThis.setTimeout(() => {\n setState((prev) => ({ ...prev, uploadProgress: 0 }));\n }, PROGRESS_RESET_DELAY_MS);\n } catch (error) {\n setState((prev) => ({\n ...prev,\n isUploading: false,\n uploadProgress: 0,\n error: error instanceof Error ? error.message : 'Upload failed',\n }));\n }\n },\n [onUpload, externalUploading, setState],\n );\n}\n\n/**\n * What {@link useUploadSelection} hands back. Module-private: the published\n * surface is {@link useUploadButton}, not the shape of its internals.\n */\ninterface UploadSelection {\n state: UploadButtonState;\n setDragOver: (isDragOver: boolean) => void;\n /** Route a picked/dropped selection through validation and the callbacks. */\n handleFiles: (files: globalThis.File[]) => void;\n}\n\ninterface UploadSelectionOptions {\n onSelect: (file: globalThis.File) => void;\n multiple: boolean;\n onSelectMany?: (files: globalThis.File[]) => void;\n onUpload?: (file: globalThis.File) => Promise<void>;\n externalUploading: boolean;\n validateFile: (file: globalThis.File) => string | null;\n}\n\n/**\n * Selection, validation and the optional built-in upload.\n *\n * The rendering layer only reads `state` and calls `handleFiles`; every rule\n * about what a selection means lives here.\n */\nfunction useUploadSelection({\n onSelect,\n multiple,\n onSelectMany,\n onUpload,\n externalUploading,\n validateFile,\n}: UploadSelectionOptions): UploadSelection {\n const [state, setState] = useState<UploadButtonState>(INITIAL_STATE);\n const runUpload = useUploadRunner(onUpload, externalUploading, setState);\n\n const selectOne = useCallback(\n (file: globalThis.File) => {\n const error = validateFile(file);\n setState((prev) => ({ ...prev, error }));\n if (error) return;\n onSelect(file);\n void runUpload(file);\n },\n [onSelect, runUpload, validateFile],\n );\n\n /**\n * Multi-file mode is deliberately forgiving: the valid files are handed over\n * and the first rejection is reported alongside them, so dropping a folder\n * that also contains a PDF imports the rest instead of refusing the lot.\n */\n const selectMany = useCallback(\n (files: globalThis.File[], accept: (files: globalThis.File[]) => void) => {\n const accepted: globalThis.File[] = [];\n let rejection: string | null = null;\n for (const file of files) {\n const error = validateFile(file);\n if (error) rejection ??= error;\n else accepted.push(file);\n }\n setState((prev) => ({ ...prev, error: rejection }));\n if (accepted.length === 0) return;\n accept(accepted);\n // `onUpload` applies here too, one file after another, so the prop means\n // the same thing in both modes. Sequential because the progress bar is a\n // single indicator — overlapping uploads would report nonsense.\n void (async () => {\n for (const file of accepted) await runUpload(file);\n })();\n },\n [runUpload, validateFile],\n );\n\n const handleFiles = useCallback(\n (files: globalThis.File[]) => {\n if (files.length === 0) return;\n if (multiple && onSelectMany) selectMany(files, onSelectMany);\n else selectOne(files[0] as globalThis.File);\n },\n [multiple, onSelectMany, selectMany, selectOne],\n );\n\n const setDragOver = useCallback((isDragOver: boolean) => {\n setState((prev) => ({ ...prev, isDragOver }));\n }, []);\n\n return useMemo(() => ({ state, setDragOver, handleFiles }), [state, setDragOver, handleFiles]);\n}\n\n/** Drag-and-drop wiring for the dropzone variant. */\nexport interface DragHandlers {\n onDragEnter: (event: React.DragEvent) => void;\n onDragLeave: (event: React.DragEvent) => void;\n onDragOver: (event: React.DragEvent) => void;\n onDrop: (event: React.DragEvent) => void;\n}\n\nconst swallow = (event: React.DragEvent): void => {\n event.preventDefault();\n event.stopPropagation();\n};\n\nfunction useDragHandlers(\n disabled: boolean,\n setDragOver: (isDragOver: boolean) => void,\n handleFiles: (files: globalThis.File[]) => void,\n): DragHandlers {\n return {\n onDragEnter: (event) => {\n swallow(event);\n if (!disabled) setDragOver(true);\n },\n onDragLeave: (event) => {\n swallow(event);\n setDragOver(false);\n },\n onDragOver: swallow,\n onDrop: (event) => {\n swallow(event);\n setDragOver(false);\n if (!disabled) handleFiles(Array.from(event.dataTransfer.files));\n },\n };\n}\n\n/** Everything the component needs, assembled from its props in one call. */\ninterface UploadButtonKit {\n inputRef: React.RefObject<HTMLInputElement | null>;\n inputId: string;\n state: UploadButtonState;\n drag: DragHandlers;\n derived: DerivedUploadState;\n openPicker: () => void;\n handleInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;\n}\n\n/**\n * The component's whole behaviour in one hook, so the render body stays a thin\n * piece of wiring rather than a place where rules accumulate.\n */\nexport function useUploadButton(props: UploadButtonHookProps): UploadButtonKit {\n const {\n onSelect,\n multiple = false,\n onSelectMany,\n onUpload,\n uploading: externalUploading = false,\n progress: externalProgress = 0,\n maxSizeMB,\n validate,\n helperText,\n errorText,\n disabled = false,\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = `upload-button-${useId()}`;\n const validateFile = useFileValidator(maxSizeMB, validate);\n const { state, setDragOver, handleFiles } = useUploadSelection({\n onSelect,\n multiple,\n onSelectMany,\n onUpload,\n externalUploading,\n validateFile,\n });\n const drag = useDragHandlers(disabled, setDragOver, handleFiles);\n const derived = useDerivedUploadState({\n state,\n inputId,\n externalUploading,\n externalProgress,\n errorText,\n helperText,\n });\n\n const openPicker = useCallback(() => inputRef.current?.click(), []);\n const handleInputChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n handleFiles(Array.from(event.target.files ?? []));\n // Let the same file be picked twice in a row — without this the input\n // holds the old value and re-selecting it fires no change event.\n event.target.value = '';\n },\n [handleFiles],\n );\n\n return { inputRef, inputId, state, drag, derived, openPicker, handleInputChange };\n}\n\n/** The values the render derives from props + internal state. */\ninterface DerivedUploadState {\n isUploading: boolean;\n progress: number;\n error: string | null;\n helperId?: string;\n errorId?: string;\n describedBy?: string;\n}\n\n/**\n * Fold props and internal state into what the render actually shows. External\n * state wins whenever the caller drives it.\n */\nfunction useDerivedUploadState({\n state,\n inputId,\n externalUploading,\n externalProgress,\n errorText,\n helperText,\n}: {\n state: UploadButtonState;\n inputId: string;\n externalUploading: boolean;\n externalProgress: number;\n errorText?: string;\n helperText?: string;\n}): DerivedUploadState {\n const error = errorText || state.error;\n const helperId = helperText ? `${inputId}-helper` : undefined;\n const errorId = error ? `${inputId}-error` : undefined;\n return {\n isUploading: externalUploading || state.isUploading,\n progress: externalUploading ? externalProgress : state.uploadProgress,\n error,\n helperId,\n errorId,\n describedBy: [helperId, errorId].filter(Boolean).join(' ') || undefined,\n };\n}\n","import AttachFileOutlined from '@mui/icons-material/AttachFileOutlined';\nimport CloudUploadOutlined from '@mui/icons-material/CloudUploadOutlined';\nimport { Box, Button, LinearProgress, Typography, useTheme } from '@mui/material';\nimport type React from 'react';\n\nimport type { DragHandlers } from './UploadButton.hooks';\nimport type { UploadButtonProps } from './UploadButton.types';\n\n/** Shared shape for the two trigger variants. */\nexport interface TriggerProps {\n label: string;\n icon?: React.ReactNode;\n disabled: boolean;\n className?: string;\n dataTestId?: string;\n describedBy?: string;\n onOpen: () => void;\n}\n\n/** The drag-and-drop surface. */\nexport function UploadDropzone({\n label,\n icon,\n disabled,\n className,\n dataTestId,\n describedBy,\n onOpen,\n isDragOver,\n drag,\n}: TriggerProps & { isDragOver: boolean; drag: DragHandlers }): React.ReactElement {\n const theme = useTheme();\n return (\n <Box\n component=\"div\"\n {...drag}\n onClick={onOpen}\n sx={{\n border: `2px dashed ${isDragOver ? theme.palette.primary.main : theme.palette.divider}`,\n borderRadius: 2,\n padding: 3,\n textAlign: 'center',\n cursor: disabled ? 'not-allowed' : 'pointer',\n backgroundColor: isDragOver ? `${theme.palette.primary.main}0A` : 'transparent',\n transition: 'all 0.2s ease-in-out',\n ...(!disabled && {\n '&:hover': {\n borderColor: theme.palette.primary.main,\n backgroundColor: `${theme.palette.primary.main}05`,\n },\n }),\n opacity: disabled ? 0.6 : 1,\n }}\n className={className}\n data-testid={dataTestId}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n onKeyDown={(event) => {\n if (event.key !== 'Enter' && event.key !== ' ') return;\n event.preventDefault();\n onOpen();\n }}\n aria-describedby={describedBy}\n aria-label={`Upload file dropzone. ${label}`}\n >\n <Box sx={{ mb: 2 }}>\n {icon || <CloudUploadOutlined sx={{ fontSize: 48, color: 'text.secondary' }} />}\n </Box>\n <Typography variant=\"body1\" sx={{ mb: 1 }}>\n {label}\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n Drop your file here or click to browse\n </Typography>\n </Box>\n );\n}\n\n/** MUI variant for each non-dropzone appearance. */\nconst MUI_VARIANT = { outline: 'outlined', ghost: 'text' } as const;\n\n/** The plain-button trigger. */\nexport function UploadTrigger({\n label,\n icon,\n disabled,\n className,\n dataTestId,\n describedBy,\n onOpen,\n variant,\n isUploading,\n}: TriggerProps & {\n variant: NonNullable<UploadButtonProps['variant']>;\n isUploading: boolean;\n}): React.ReactElement {\n const theme = useTheme();\n return (\n <Button\n variant={MUI_VARIANT[variant as keyof typeof MUI_VARIANT] ?? 'contained'}\n disabled={disabled || isUploading}\n onClick={onOpen}\n startIcon={icon || <AttachFileOutlined />}\n className={className}\n data-testid={dataTestId}\n aria-describedby={describedBy}\n sx={{\n ...(variant === 'ghost' && {\n '&:hover': { backgroundColor: `${theme.palette.primary.main}08` },\n }),\n }}\n >\n {isUploading ? 'Uploading...' : label}\n </Button>\n );\n}\n\n/** The screen-reader live region — drag, progress and error announcements. */\nfunction UploadAnnouncer({\n announceDragOver,\n isUploading,\n progress,\n error,\n}: {\n announceDragOver: boolean;\n isUploading: boolean;\n progress: number;\n error: string | null;\n}): React.ReactElement {\n return (\n <div\n aria-live=\"polite\"\n aria-atomic=\"true\"\n className=\"sr-only\"\n style={{\n position: 'absolute',\n left: '-10000px',\n width: '1px',\n height: '1px',\n overflow: 'hidden',\n }}\n >\n {announceDragOver && 'File ready to drop'}\n {isUploading && `Upload in progress: ${Math.round(progress)}%`}\n {error && `Error: ${error}`}\n </div>\n );\n}\n\n/** Progress bar, helper text, error text and the live region. */\nexport function UploadFeedback({\n isUploading,\n progress,\n helperText,\n helperId,\n error,\n errorId,\n announceDragOver,\n}: {\n isUploading: boolean;\n progress: number;\n helperText?: string;\n helperId?: string;\n error: string | null;\n errorId?: string;\n announceDragOver: boolean;\n}): React.ReactElement {\n return (\n <>\n {isUploading && progress > 0 && (\n <Box sx={{ mt: 1 }}>\n <LinearProgress variant=\"determinate\" value={progress} sx={{ borderRadius: 1 }} />\n <Typography variant=\"caption\" sx={{ mt: 0.5, display: 'block' }}>\n {Math.round(progress)}% uploaded\n </Typography>\n </Box>\n )}\n\n {helperText && !error && (\n <Typography\n id={helperId}\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mt: 0.5 }}\n >\n {helperText}\n </Typography>\n )}\n\n {error && (\n <Typography\n id={errorId}\n variant=\"caption\"\n color=\"error\"\n sx={{ display: 'block', mt: 0.5 }}\n role=\"alert\"\n >\n {error}\n </Typography>\n )}\n\n <UploadAnnouncer\n announceDragOver={announceDragOver}\n isUploading={isUploading}\n progress={progress}\n error={error}\n />\n </>\n );\n}\n"],"mappings":"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","names":["Box","jsx","jsxs","Box"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/form/UploadButton/UploadButton.tsx","../../src/components/form/UploadButton/UploadButton.hooks.ts","../../src/components/form/UploadButton/UploadButton.parts.tsx"],"sourcesContent":["import { Box } from '@mui/material';\nimport React from 'react';\n\nimport { useUploadButton } from './UploadButton.hooks';\nimport {\n UploadDropzone,\n UploadFeedback,\n UploadTrigger,\n type TriggerProps,\n} from './UploadButton.parts';\nimport type { UploadButtonProps, UploadButtonState } from './UploadButton.types';\n\n/**\n * A file picker with an optional drag-and-drop surface.\n *\n * The body here is deliberately thin: selection rules live in\n * `UploadButton.hooks`, appearance in `UploadButton.parts`. What remains is the\n * wiring — the hidden input, which trigger to render, and the feedback beneath.\n */\nconst UploadButton = React.forwardRef<HTMLInputElement, UploadButtonProps>((props, ref) => {\n const {\n copy,\n variant = 'default',\n label = props.copy.buttonLabel,\n disabled = false,\n multiple = false,\n accept,\n capture,\n helperText,\n icon,\n className,\n 'data-testid': dataTestId,\n } = props;\n const { inputRef, inputId, state, drag, derived, openPicker, handleInputChange } =\n useUploadButton(props);\n\n const trigger: TriggerProps = {\n copy,\n label,\n icon,\n disabled,\n className,\n dataTestId,\n describedBy: derived.describedBy,\n onOpen: openPicker,\n };\n\n return (\n <Box>\n <input\n ref={ref || inputRef}\n id={inputId}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n capture={capture}\n onChange={handleInputChange}\n style={{ display: 'none' }}\n disabled={disabled}\n aria-hidden=\"true\"\n />\n\n {variant === 'dropzone' ? (\n <UploadDropzone {...trigger} isDragOver={state.isDragOver} drag={drag} />\n ) : (\n <UploadTrigger {...trigger} variant={variant} isUploading={derived.isUploading} />\n )}\n\n <UploadFeedback\n copy={copy}\n isUploading={derived.isUploading}\n progress={derived.progress}\n helperText={helperText}\n helperId={derived.helperId}\n error={derived.error}\n errorId={derived.errorId}\n announceDragOver={variant === 'dropzone' && state.isDragOver}\n />\n </Box>\n );\n});\n\nUploadButton.displayName = 'UploadButton';\n\nexport { UploadButton };\nexport type { UploadButtonProps, UploadButtonState };\n","import { useCallback, useId, useMemo, useRef, useState } from 'react';\nimport type React from 'react';\n\nimport type { UploadButtonProps, UploadButtonState } from './UploadButton.types';\n\n/** The props {@link useUploadButton} reads — the component's own props. */\ntype UploadButtonHookProps = UploadButtonProps;\n\n/** Percent the simulated progress creeps to while waiting on `onUpload`. */\nconst SIMULATED_PROGRESS_CEILING = 90;\nconst SIMULATED_PROGRESS_STEP = 10;\nconst SIMULATED_PROGRESS_INTERVAL_MS = 100;\nconst PROGRESS_RESET_DELAY_MS = 1000;\nconst BYTES_PER_MB = 1024 * 1024;\n\nconst INITIAL_STATE: UploadButtonState = {\n isDragOver: false,\n isUploading: false,\n uploadProgress: 0,\n error: null,\n};\n\n/** Narrowed `setState` for the pieces below. */\ntype SetState = React.Dispatch<React.SetStateAction<UploadButtonState>>;\n\n/** The size/custom validation applied to every file, in both modes. */\nfunction useFileValidator(\n maxSizeMB: number | undefined,\n validate: ((file: globalThis.File) => string | null) | undefined,\n): (file: globalThis.File) => string | null {\n return useCallback(\n (file: globalThis.File): string | null => {\n if (maxSizeMB && file.size > maxSizeMB * BYTES_PER_MB) {\n return `File size must be less than ${maxSizeMB}MB`;\n }\n return validate ? validate(file) : null;\n },\n [maxSizeMB, validate],\n );\n}\n\n/**\n * The built-in upload path, reachable from BOTH selection modes.\n *\n * Kept apart from selection because it is the only asynchronous part: left\n * inline it was single-file only, which made `onUpload` a silent no-op for a\n * multi-file caller — the worst kind of contract, since nothing fails.\n */\nfunction useUploadRunner(\n onUpload: ((file: globalThis.File) => Promise<void>) | undefined,\n externalUploading: boolean,\n setState: SetState,\n): (file: globalThis.File) => Promise<void> {\n return useCallback(\n async (file: globalThis.File) => {\n if (!onUpload || externalUploading) return;\n try {\n setState((prev) => ({ ...prev, isUploading: true, uploadProgress: 0 }));\n // The real percentage is unknowable through a bare promise, so the bar\n // creeps to a ceiling and only completes when the promise does.\n const timer = globalThis.setInterval(() => {\n setState((prev) => {\n if (prev.uploadProgress >= SIMULATED_PROGRESS_CEILING) {\n globalThis.clearInterval(timer);\n return prev;\n }\n return { ...prev, uploadProgress: prev.uploadProgress + SIMULATED_PROGRESS_STEP };\n });\n }, SIMULATED_PROGRESS_INTERVAL_MS);\n\n await onUpload(file);\n\n globalThis.clearInterval(timer);\n setState((prev) => ({ ...prev, isUploading: false, uploadProgress: 100 }));\n globalThis.setTimeout(() => {\n setState((prev) => ({ ...prev, uploadProgress: 0 }));\n }, PROGRESS_RESET_DELAY_MS);\n } catch (error) {\n setState((prev) => ({\n ...prev,\n isUploading: false,\n uploadProgress: 0,\n error: error instanceof Error ? error.message : 'Upload failed',\n }));\n }\n },\n [onUpload, externalUploading, setState],\n );\n}\n\n/**\n * What {@link useUploadSelection} hands back. Module-private: the published\n * surface is {@link useUploadButton}, not the shape of its internals.\n */\ninterface UploadSelection {\n state: UploadButtonState;\n setDragOver: (isDragOver: boolean) => void;\n /** Route a picked/dropped selection through validation and the callbacks. */\n handleFiles: (files: globalThis.File[]) => void;\n}\n\ninterface UploadSelectionOptions {\n onSelect: (file: globalThis.File) => void;\n multiple: boolean;\n onSelectMany?: (files: globalThis.File[]) => void;\n onUpload?: (file: globalThis.File) => Promise<void>;\n externalUploading: boolean;\n validateFile: (file: globalThis.File) => string | null;\n}\n\n/**\n * Selection, validation and the optional built-in upload.\n *\n * The rendering layer only reads `state` and calls `handleFiles`; every rule\n * about what a selection means lives here.\n */\nfunction useUploadSelection({\n onSelect,\n multiple,\n onSelectMany,\n onUpload,\n externalUploading,\n validateFile,\n}: UploadSelectionOptions): UploadSelection {\n const [state, setState] = useState<UploadButtonState>(INITIAL_STATE);\n const runUpload = useUploadRunner(onUpload, externalUploading, setState);\n\n const selectOne = useCallback(\n (file: globalThis.File) => {\n const error = validateFile(file);\n setState((prev) => ({ ...prev, error }));\n if (error) return;\n onSelect(file);\n void runUpload(file);\n },\n [onSelect, runUpload, validateFile],\n );\n\n /**\n * Multi-file mode is deliberately forgiving: the valid files are handed over\n * and the first rejection is reported alongside them, so dropping a folder\n * that also contains a PDF imports the rest instead of refusing the lot.\n */\n const selectMany = useCallback(\n (files: globalThis.File[], accept: (files: globalThis.File[]) => void) => {\n const accepted: globalThis.File[] = [];\n let rejection: string | null = null;\n for (const file of files) {\n const error = validateFile(file);\n if (error) rejection ??= error;\n else accepted.push(file);\n }\n setState((prev) => ({ ...prev, error: rejection }));\n if (accepted.length === 0) return;\n accept(accepted);\n // `onUpload` applies here too, one file after another, so the prop means\n // the same thing in both modes. Sequential because the progress bar is a\n // single indicator — overlapping uploads would report nonsense.\n void (async () => {\n for (const file of accepted) await runUpload(file);\n })();\n },\n [runUpload, validateFile],\n );\n\n const handleFiles = useCallback(\n (files: globalThis.File[]) => {\n if (files.length === 0) return;\n if (multiple && onSelectMany) selectMany(files, onSelectMany);\n else selectOne(files[0] as globalThis.File);\n },\n [multiple, onSelectMany, selectMany, selectOne],\n );\n\n const setDragOver = useCallback((isDragOver: boolean) => {\n setState((prev) => ({ ...prev, isDragOver }));\n }, []);\n\n return useMemo(() => ({ state, setDragOver, handleFiles }), [state, setDragOver, handleFiles]);\n}\n\n/** Drag-and-drop wiring for the dropzone variant. */\nexport interface DragHandlers {\n onDragEnter: (event: React.DragEvent) => void;\n onDragLeave: (event: React.DragEvent) => void;\n onDragOver: (event: React.DragEvent) => void;\n onDrop: (event: React.DragEvent) => void;\n}\n\nconst swallow = (event: React.DragEvent): void => {\n event.preventDefault();\n event.stopPropagation();\n};\n\nfunction useDragHandlers(\n disabled: boolean,\n setDragOver: (isDragOver: boolean) => void,\n handleFiles: (files: globalThis.File[]) => void,\n): DragHandlers {\n return {\n onDragEnter: (event) => {\n swallow(event);\n if (!disabled) setDragOver(true);\n },\n onDragLeave: (event) => {\n swallow(event);\n setDragOver(false);\n },\n onDragOver: swallow,\n onDrop: (event) => {\n swallow(event);\n setDragOver(false);\n if (!disabled) handleFiles(Array.from(event.dataTransfer.files));\n },\n };\n}\n\n/** Everything the component needs, assembled from its props in one call. */\ninterface UploadButtonKit {\n inputRef: React.RefObject<HTMLInputElement | null>;\n inputId: string;\n state: UploadButtonState;\n drag: DragHandlers;\n derived: DerivedUploadState;\n openPicker: () => void;\n handleInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;\n}\n\n/**\n * The component's whole behaviour in one hook, so the render body stays a thin\n * piece of wiring rather than a place where rules accumulate.\n */\nexport function useUploadButton(props: UploadButtonHookProps): UploadButtonKit {\n const {\n onSelect,\n multiple = false,\n onSelectMany,\n onUpload,\n uploading: externalUploading = false,\n progress: externalProgress = 0,\n maxSizeMB,\n validate,\n helperText,\n errorText,\n disabled = false,\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = `upload-button-${useId()}`;\n const validateFile = useFileValidator(maxSizeMB, validate);\n const { state, setDragOver, handleFiles } = useUploadSelection({\n onSelect,\n multiple,\n onSelectMany,\n onUpload,\n externalUploading,\n validateFile,\n });\n const drag = useDragHandlers(disabled, setDragOver, handleFiles);\n const derived = useDerivedUploadState({\n state,\n inputId,\n externalUploading,\n externalProgress,\n errorText,\n helperText,\n });\n\n const openPicker = useCallback(() => inputRef.current?.click(), []);\n const handleInputChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n handleFiles(Array.from(event.target.files ?? []));\n // Let the same file be picked twice in a row — without this the input\n // holds the old value and re-selecting it fires no change event.\n event.target.value = '';\n },\n [handleFiles],\n );\n\n return { inputRef, inputId, state, drag, derived, openPicker, handleInputChange };\n}\n\n/** The values the render derives from props + internal state. */\ninterface DerivedUploadState {\n isUploading: boolean;\n progress: number;\n error: string | null;\n helperId?: string;\n errorId?: string;\n describedBy?: string;\n}\n\n/**\n * Fold props and internal state into what the render actually shows. External\n * state wins whenever the caller drives it.\n */\nfunction useDerivedUploadState({\n state,\n inputId,\n externalUploading,\n externalProgress,\n errorText,\n helperText,\n}: {\n state: UploadButtonState;\n inputId: string;\n externalUploading: boolean;\n externalProgress: number;\n errorText?: string;\n helperText?: string;\n}): DerivedUploadState {\n const error = errorText || state.error;\n const helperId = helperText ? `${inputId}-helper` : undefined;\n const errorId = error ? `${inputId}-error` : undefined;\n return {\n isUploading: externalUploading || state.isUploading,\n progress: externalUploading ? externalProgress : state.uploadProgress,\n error,\n helperId,\n errorId,\n describedBy: [helperId, errorId].filter(Boolean).join(' ') || undefined,\n };\n}\n","import AttachFileOutlined from '@mui/icons-material/AttachFileOutlined';\nimport CloudUploadOutlined from '@mui/icons-material/CloudUploadOutlined';\nimport { Box, Button, LinearProgress, Typography, useTheme } from '@mui/material';\nimport type React from 'react';\n\nimport type { DragHandlers } from './UploadButton.hooks';\nimport type { UploadButtonCopy } from '../../../copy';\nimport type { UploadButtonProps } from './UploadButton.types';\n\n/** Shared shape for the two trigger variants. */\nexport interface TriggerProps {\n copy: UploadButtonCopy;\n label: string;\n icon?: React.ReactNode;\n disabled: boolean;\n className?: string;\n dataTestId?: string;\n describedBy?: string;\n onOpen: () => void;\n}\n\n/** The drag-and-drop surface. */\nexport function UploadDropzone({\n copy,\n label,\n icon,\n disabled,\n className,\n dataTestId,\n describedBy,\n onOpen,\n isDragOver,\n drag,\n}: TriggerProps & { isDragOver: boolean; drag: DragHandlers }): React.ReactElement {\n const theme = useTheme();\n return (\n <Box\n component=\"div\"\n {...drag}\n onClick={onOpen}\n sx={{\n border: `2px dashed ${isDragOver ? theme.palette.primary.main : theme.palette.divider}`,\n borderRadius: 2,\n padding: 3,\n textAlign: 'center',\n cursor: disabled ? 'not-allowed' : 'pointer',\n backgroundColor: isDragOver ? `${theme.palette.primary.main}0A` : 'transparent',\n transition: 'all 0.2s ease-in-out',\n ...(!disabled && {\n '&:hover': {\n borderColor: theme.palette.primary.main,\n backgroundColor: `${theme.palette.primary.main}05`,\n },\n }),\n opacity: disabled ? 0.6 : 1,\n }}\n className={className}\n data-testid={dataTestId}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n onKeyDown={(event) => {\n if (event.key !== 'Enter' && event.key !== ' ') return;\n event.preventDefault();\n onOpen();\n }}\n aria-describedby={describedBy}\n aria-label={copy.dropzoneRole(label)}\n >\n <Box sx={{ mb: 2 }}>\n {icon || <CloudUploadOutlined sx={{ fontSize: 48, color: 'text.secondary' }} />}\n </Box>\n <Typography variant=\"body1\" sx={{ mb: 1 }}>\n {label}\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {copy.dropzoneHint}\n </Typography>\n </Box>\n );\n}\n\n/** MUI variant for each non-dropzone appearance. */\nconst MUI_VARIANT = { outline: 'outlined', ghost: 'text' } as const;\n\n/** The plain-button trigger. */\nexport function UploadTrigger({\n copy,\n label,\n icon,\n disabled,\n className,\n dataTestId,\n describedBy,\n onOpen,\n variant,\n isUploading,\n}: TriggerProps & {\n variant: NonNullable<UploadButtonProps['variant']>;\n isUploading: boolean;\n}): React.ReactElement {\n const theme = useTheme();\n return (\n <Button\n variant={MUI_VARIANT[variant as keyof typeof MUI_VARIANT] ?? 'contained'}\n disabled={disabled || isUploading}\n onClick={onOpen}\n startIcon={icon || <AttachFileOutlined />}\n className={className}\n data-testid={dataTestId}\n aria-describedby={describedBy}\n sx={{\n ...(variant === 'ghost' && {\n '&:hover': { backgroundColor: `${theme.palette.primary.main}08` },\n }),\n }}\n >\n {isUploading ? copy.uploading : label}\n </Button>\n );\n}\n\n/** The screen-reader live region — drag, progress and error announcements. */\nfunction UploadAnnouncer({\n copy,\n announceDragOver,\n isUploading,\n progress,\n error,\n}: {\n copy: UploadButtonCopy;\n announceDragOver: boolean;\n isUploading: boolean;\n progress: number;\n error: string | null;\n}): React.ReactElement {\n return (\n <div\n aria-live=\"polite\"\n aria-atomic=\"true\"\n className=\"sr-only\"\n style={{\n position: 'absolute',\n left: '-10000px',\n width: '1px',\n height: '1px',\n overflow: 'hidden',\n }}\n >\n {announceDragOver && copy.dropReady}\n {isUploading && copy.uploadInProgress(Math.round(progress))}\n {error && copy.errorAnnouncement(error)}\n </div>\n );\n}\n\n/** Progress bar, helper text, error text and the live region. */\nexport function UploadFeedback({\n copy,\n isUploading,\n progress,\n helperText,\n helperId,\n error,\n errorId,\n announceDragOver,\n}: {\n copy: UploadButtonCopy;\n isUploading: boolean;\n progress: number;\n helperText?: string;\n helperId?: string;\n error: string | null;\n errorId?: string;\n announceDragOver: boolean;\n}): React.ReactElement {\n return (\n <>\n {isUploading && progress > 0 && (\n <Box sx={{ mt: 1 }}>\n <LinearProgress variant=\"determinate\" value={progress} sx={{ borderRadius: 1 }} />\n <Typography variant=\"caption\" sx={{ mt: 0.5, display: 'block' }}>\n {copy.percentUploaded(Math.round(progress))}\n </Typography>\n </Box>\n )}\n\n {helperText && !error && (\n <Typography\n id={helperId}\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mt: 0.5 }}\n >\n {helperText}\n </Typography>\n )}\n\n {error && (\n <Typography\n id={errorId}\n variant=\"caption\"\n color=\"error\"\n sx={{ display: 'block', mt: 0.5 }}\n role=\"alert\"\n >\n {error}\n </Typography>\n )}\n\n <UploadAnnouncer\n copy={copy}\n announceDragOver={announceDragOver}\n isUploading={isUploading}\n progress={progress}\n error={error}\n />\n </>\n );\n}\n"],"mappings":"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","names":["Box","jsx","jsxs","Box"]}
|
package/dist/layout/Dashboard.js
CHANGED
|
@@ -115,6 +115,7 @@ var DashboardFilterToggle = ({ ariaLabel }) => {
|
|
|
115
115
|
DashboardFilterToggle.displayName = "Dashboard.FilterToggle";
|
|
116
116
|
var DashboardSettings = ({
|
|
117
117
|
title = "Settings",
|
|
118
|
+
closeLabel,
|
|
118
119
|
children,
|
|
119
120
|
ariaLabel = "Settings",
|
|
120
121
|
href,
|
|
@@ -153,7 +154,7 @@ var DashboardSettings = ({
|
|
|
153
154
|
/* @__PURE__ */ jsxs(Dialog, { open, onClose: () => setOpen(false), maxWidth: "sm", fullWidth: true, "data-testid": `${testIdPrefix}-settings-dialog`, children: [
|
|
154
155
|
/* @__PURE__ */ jsxs(DialogTitle, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
155
156
|
title,
|
|
156
|
-
/* @__PURE__ */ jsx(IconButton, { "aria-label":
|
|
157
|
+
/* @__PURE__ */ jsx(IconButton, { "aria-label": closeLabel, size: "small", onClick: () => setOpen(false), children: /* @__PURE__ */ jsx(CloseIcon, { fontSize: "small" }) })
|
|
157
158
|
] }),
|
|
158
159
|
/* @__PURE__ */ jsx(DialogContent, { dividers: true, children })
|
|
159
160
|
] })
|