@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/form/Autocomplete/Autocomplete.tsx","../../src/components/form/Autocomplete/Autocomplete.helpers.ts","../../src/components/form/Autocomplete/Autocomplete.parts.tsx","../../src/components/form/Autocomplete/useAutocomplete.ts","../../src/components/form/Autocomplete/Autocomplete.keys.ts"],"sourcesContent":["import { Box, ClickAwayListener } from '@mui/material';\nimport React from 'react';\n\nimport {\n defaultGetKey,\n defaultGetLabel,\n defaultGetSuggestionType,\n type MatchMode,\n} from './Autocomplete.helpers';\nimport {\n AutocompleteInput,\n ChipList,\n DefaultSuggestion,\n SuggestionListBox,\n} from './Autocomplete.parts';\nimport type { AutocompleteOption, AutocompleteProps, SuggestionType } from './Autocomplete.types';\nimport { useAutocomplete, type AutocompleteView } from './useAutocomplete';\n\n/** Presentational props resolved from {@link AutocompleteProps} (defaults applied once). */\ninterface RenderConfig<T> {\n getKey: (item: T) => string;\n getLabel: (item: T) => string;\n getSuggestionType: (item: T) => SuggestionType | undefined;\n getDescription?: (item: T) => string | undefined;\n renderSuggestion?: (item: T, state: { active: boolean; query: string }) => React.ReactNode;\n matchMode: MatchMode;\n multiple: boolean;\n selectedItems: T[];\n isLoading: boolean;\n showGhostText: boolean;\n placeholder: string;\n autoFocus: boolean;\n disabled: boolean;\n portal: boolean | { container?: HTMLElement };\n className?: string;\n chipClassName?: string;\n inputAriaLabel?: string;\n inputClassName?: string;\n listClassName?: string;\n itemClassName?: string;\n activeItemClassName?: string;\n}\n\n/** Apply presentational defaults once so the component itself stays branch-light. */\nfunction resolveRenderConfig<T>(p: AutocompleteProps<T>): RenderConfig<T> {\n return {\n getKey: p.getKey ?? defaultGetKey,\n getLabel: p.getLabel ?? defaultGetLabel,\n getSuggestionType: p.getSuggestionType ?? defaultGetSuggestionType,\n getDescription: p.getDescription,\n renderSuggestion: p.renderSuggestion,\n matchMode: p.matchMode ?? 'contains',\n multiple: Boolean(p.multiple),\n selectedItems: p.selectedItems ?? [],\n isLoading: Boolean(p.isLoading),\n showGhostText: p.showGhostText ?? true,\n placeholder: p.placeholder ?? 'Type to search...',\n autoFocus: Boolean(p.autoFocus),\n disabled: Boolean(p.disabled),\n portal: p.portal ?? false,\n className: p.className,\n chipClassName: p.chipClassName,\n inputAriaLabel: p.inputAriaLabel,\n inputClassName: p.inputClassName,\n listClassName: p.listClassName,\n itemClassName: p.itemClassName,\n activeItemClassName: p.activeItemClassName,\n };\n}\n\n/** A single suggestion node: the caller's custom renderer or the default row. */\nfunction renderSuggestionNode<T>(item: T, active: boolean, query: string, cfg: RenderConfig<T>): React.ReactNode {\n if (cfg.renderSuggestion) return cfg.renderSuggestion(item, { active, query });\n return (\n <DefaultSuggestion\n item={item}\n state={{ active, query }}\n getLabel={cfg.getLabel}\n getDescription={cfg.getDescription}\n getSuggestionType={cfg.getSuggestionType}\n matchMode={cfg.matchMode}\n />\n );\n}\n\n/**\n * ARIA combobox with a popup listbox: local/async filtering, inline ghost\n * completion (Tab/→), multi-select chips, custom rendering, and typed\n * `search`/`link` suggestions (a `link` opens its URL instead of filling the\n * input). State/effects/handlers live in {@link useAutocomplete}; presentational\n * pieces live in `Autocomplete.parts`.\n */\nexport const Autocomplete = <T = AutocompleteOption>(props: AutocompleteProps<T>): React.JSX.Element => {\n const cfg = resolveRenderConfig(props);\n const view: AutocompleteView<T> = useAutocomplete<T>(props);\n const s = view.state;\n const showNoResults =\n !cfg.isLoading && view.visibleSuggestions.length === 0 && Boolean(s.inputValue.trim());\n\n return (\n <ClickAwayListener onClickAway={view.onClickAway}>\n <Box className={cfg.className} data-testid=\"autocomplete-container\">\n {cfg.multiple && cfg.selectedItems.length > 0 && (\n <ChipList\n items={cfg.selectedItems}\n getKey={cfg.getKey}\n getLabel={cfg.getLabel}\n onRemove={view.removeSelectedItem}\n chipClassName={cfg.chipClassName}\n />\n )}\n\n <AutocompleteInput\n id={view.id}\n listId={view.listId}\n inputRef={s.inputRef}\n inputValue={s.inputValue}\n ghost={s.ghost}\n showGhost={cfg.showGhostText}\n isInputFocused={s.isInputFocused}\n open={s.open}\n activeDescendant={view.activeDescendant}\n isLoading={cfg.isLoading}\n disabled={cfg.disabled}\n autoFocus={cfg.autoFocus}\n placeholder={cfg.placeholder}\n startAdornment={props.startAdornment}\n inputAriaLabel={cfg.inputAriaLabel}\n inputClassName={cfg.inputClassName}\n onChange={view.onInputChange}\n onKeyDown={view.onKeyDown}\n onFocus={view.onFocus}\n onBlur={view.onBlur}\n onCompositionStart={() => s.setComposition(true)}\n onCompositionEnd={() => s.setComposition(false)}\n />\n\n {s.open && (\n <SuggestionListBox\n open={s.open}\n anchorEl={s.inputRef.current}\n portal={cfg.portal}\n listRef={s.listRef}\n listId={view.listId}\n optionIdPrefix={view.optionIdPrefix}\n items={view.visibleSuggestions}\n activeIndex={s.activeIndex}\n isLoading={cfg.isLoading}\n showNoResults={showNoResults}\n getKey={cfg.getKey}\n onSelect={view.selectItem}\n onHover={s.setActiveIndex}\n renderItem={(item, active) => renderSuggestionNode(item, active, s.inputValue, cfg)}\n listClassName={cfg.listClassName}\n itemClassName={cfg.itemClassName}\n activeItemClassName={cfg.activeItemClassName}\n />\n )}\n </Box>\n </ClickAwayListener>\n );\n};\n\nAutocomplete.displayName = 'Autocomplete';\n\nexport default Autocomplete;\n","import type { SuggestionType } from './Autocomplete.types';\n\n/** Local filtering strategy. */\nexport type MatchMode = 'startsWith' | 'contains' | 'fuzzy';\n\n/** Default key extractor: id/key/value/label, else the item itself stringified. */\nexport const defaultGetKey = <T,>(item: T): string => {\n if (typeof item === 'string') return item;\n if (typeof item === 'object' && item !== null) {\n const obj = item as Record<string, unknown>;\n return String(obj.id ?? obj.key ?? obj.value ?? obj.label ?? obj);\n }\n return String(item);\n};\n\n/** Default label extractor: label/name/text, else the item itself stringified. */\nexport const defaultGetLabel = <T,>(item: T): string => {\n if (typeof item === 'string') return item;\n if (typeof item === 'object' && item !== null) {\n const obj = item as Record<string, unknown>;\n return String(obj.label ?? obj.name ?? obj.text ?? obj);\n }\n return String(item);\n};\n\n/** Default suggestion-type extractor: reads a `type: 'search' | 'link'` field. */\nexport const defaultGetSuggestionType = <T,>(item: T): SuggestionType | undefined => {\n if (typeof item === 'object' && item !== null) {\n const { type } = item as { type?: unknown };\n if (type === 'search' || type === 'link') return type;\n }\n return undefined;\n};\n\n/** Default URL extractor for `link` suggestions: reads a `url: string` field. */\nexport const defaultGetUrl = <T,>(item: T): string | undefined => {\n if (typeof item === 'object' && item !== null) {\n const { url } = item as { url?: unknown };\n if (typeof url === 'string') return url;\n }\n return undefined;\n};\n\n/** Default link opener: a new tab with `noopener,noreferrer`. SSR-guarded. */\nexport const defaultOpenLink = (url: string): void => {\n if (typeof window !== 'undefined') {\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n};\n\n/** Fuzzy match: every char of `query` appears in `label`, in order. */\nfunction fuzzyMatch(label: string, query: string): boolean {\n let labelIndex = 0;\n for (let queryIndex = 0; queryIndex < query.length; queryIndex++) {\n const char = query[queryIndex];\n if (!char) continue;\n labelIndex = label.indexOf(char, labelIndex);\n if (labelIndex === -1) return false;\n labelIndex++;\n }\n return true;\n}\n\n/** True when `label` matches `query` under the given {@link MatchMode} (case-insensitive). */\nfunction matchesQuery(label: string, query: string, matchMode: MatchMode): boolean {\n const haystack = label.toLowerCase();\n const needle = query.toLowerCase();\n if (matchMode === 'startsWith') return haystack.startsWith(needle);\n if (matchMode === 'fuzzy') return fuzzyMatch(haystack, needle);\n return haystack.includes(needle);\n}\n\n/** Filter `suggestions` by `query` under `matchMode`; an empty query returns all. */\nexport function filterSuggestions<T>(\n suggestions: T[],\n query: string,\n matchMode: MatchMode,\n getLabel: (item: T) => string,\n): T[] {\n if (!query) return suggestions;\n return suggestions.filter((item) => matchesQuery(getLabel(item), query, matchMode));\n}\n\n/**\n * The first suggestion eligible for inline ghost completion: a non-`link` item\n * whose label starts with `inputValue` (case-insensitive) but isn't equal to it.\n * Shared by the ghost-text effect and ArrowRight completion.\n */\nexport function firstGhostSuggestion<T>(\n list: T[],\n inputValue: string,\n getLabel: (item: T) => string,\n getSuggestionType: (item: T) => SuggestionType | undefined,\n): T | undefined {\n const needle = inputValue.toLowerCase();\n return list.find((item) => {\n const label = getLabel(item).toLowerCase();\n return getSuggestionType(item) !== 'link' && label.startsWith(needle) && label !== needle;\n });\n}\n\n/** Escape a user query for safe use inside a `RegExp`. */\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Wrap query matches in `<mark>` for the default suggestion renderer. Skipped for\n * fuzzy mode (non-contiguous matches) and empty queries. Returns HTML.\n */\nexport function highlightLabel(label: string, query: string, matchMode: MatchMode): string {\n if (!query || matchMode === 'fuzzy') return label;\n const regex = new RegExp(`(${escapeRegExp(query)})`, 'gi');\n return label.replace(regex, '<mark>$1</mark>');\n}\n","import LinkIcon from '@mui/icons-material/Link';\nimport SearchIcon from '@mui/icons-material/Search';\nimport {\n Box,\n Chip,\n CircularProgress,\n List,\n ListItem,\n ListItemText,\n Paper,\n Popper,\n TextField,\n Typography,\n} from '@mui/material';\nimport { styled } from '@mui/material';\nimport React from 'react';\n\nimport { highlightLabel, type MatchMode } from './Autocomplete.helpers';\nimport type { SuggestionItemState, SuggestionType } from './Autocomplete.types';\n\nconst StyledPopper = styled(Popper)(({ theme }) => ({\n zIndex: theme.zIndex.tooltip,\n width: '100%',\n maxHeight: 300,\n overflow: 'auto',\n // Popper.js writes the computed position (and stamps `data-popper-placement`)\n // in a layout effect that can land AFTER the first paint. Until it does, the\n // element would paint once unpositioned — at the offset-parent origin, far\n // left and full width — then jump under the input, a visible per-keystroke\n // flash as the list re-renders. Hide that unpositioned first frame; it becomes\n // visible the instant popper assigns a placement.\n '&:not([data-popper-placement])': { visibility: 'hidden' },\n}));\n\nconst InlineSuggestionDisplay = styled('div')(() => ({\n position: 'absolute',\n pointerEvents: 'none',\n left: '14px', // Match TextField padding\n top: '50%',\n transform: 'translateY(-50%)',\n fontSize: 'inherit',\n fontFamily: 'inherit',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n zIndex: 1,\n}));\n\nconst UserTextTwin = styled('span')({\n visibility: 'hidden',\n});\n\nconst GhostText = styled('span')(({ theme }) => ({\n color: theme.palette.text.secondary,\n opacity: 0.6,\n}));\n\nconst ChipContainer = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(0.5),\n marginBottom: theme.spacing(1),\n}));\n\n/** Leading icon for a typed suggestion (search vs. link); null for untyped items. */\nexport function suggestionTypeIcon(type: SuggestionType | undefined): React.ReactNode {\n const sx = { color: 'text.secondary', flexShrink: 0 } as const;\n if (type === 'link') return <LinkIcon fontSize=\"small\" sx={sx} />;\n if (type === 'search') return <SearchIcon fontSize=\"small\" sx={sx} />;\n return null;\n}\n\n/** The inline ghost-text overlay: an invisible twin of the typed text + the grey remainder. */\nfunction GhostOverlay({ inputValue, ghost }: { inputValue: string; ghost: string }): React.JSX.Element {\n return (\n <InlineSuggestionDisplay>\n <UserTextTwin>{inputValue}</UserTextTwin>\n <GhostText>{ghost}</GhostText>\n </InlineSuggestionDisplay>\n );\n}\n\nexport interface AutocompleteInputProps {\n id: string;\n listId: string;\n inputRef: React.RefObject<HTMLInputElement | null>;\n inputValue: string;\n ghost: string;\n showGhost: boolean;\n isInputFocused: boolean;\n open: boolean;\n activeDescendant: string | undefined;\n isLoading: boolean;\n disabled: boolean;\n autoFocus: boolean;\n placeholder: string;\n startAdornment?: React.ReactNode;\n inputAriaLabel?: string;\n inputClassName?: string;\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onCompositionStart: () => void;\n onCompositionEnd: () => void;\n}\n\n/** The combobox text field plus its inline ghost-text overlay. */\nexport function AutocompleteInput(props: AutocompleteInputProps): React.JSX.Element {\n const showOverlay = Boolean(props.ghost) && props.showGhost && props.isInputFocused;\n return (\n <Box sx={{ position: 'relative' }}>\n {showOverlay && <GhostOverlay inputValue={props.inputValue} ghost={props.ghost} />}\n <TextField\n ref={props.inputRef}\n fullWidth\n value={props.inputValue}\n onChange={props.onChange}\n onKeyDown={props.onKeyDown}\n onFocus={props.onFocus}\n onBlur={props.onBlur}\n onCompositionStart={props.onCompositionStart}\n onCompositionEnd={props.onCompositionEnd}\n placeholder={props.placeholder}\n disabled={props.disabled}\n autoFocus={props.autoFocus}\n className={props.inputClassName}\n InputProps={{\n startAdornment: props.startAdornment,\n endAdornment: props.isLoading ? <CircularProgress size={20} /> : undefined,\n }}\n inputProps={{\n role: 'combobox',\n 'aria-expanded': props.open,\n 'aria-controls': props.open ? props.listId : undefined,\n 'aria-activedescendant': props.activeDescendant,\n 'aria-autocomplete': 'list',\n 'aria-label': props.inputAriaLabel,\n id: props.id,\n }}\n />\n </Box>\n );\n}\n\n/** Selected-item chips (multiple mode). */\nexport function ChipList<T>({\n items,\n getKey,\n getLabel,\n onRemove,\n chipClassName,\n}: {\n items: T[];\n getKey: (item: T) => string;\n getLabel: (item: T) => string;\n onRemove: (item: T) => void;\n chipClassName?: string;\n}): React.JSX.Element {\n return (\n <ChipContainer data-testid=\"selected-items-container\">\n {items.map((item, index) => (\n <Chip\n key={`${getKey(item)}-${index}`}\n label={getLabel(item)}\n onDelete={() => onRemove(item)}\n size=\"small\"\n className={chipClassName}\n data-testid={`selected-chip-${index}`}\n />\n ))}\n </ChipContainer>\n );\n}\n\n/** Default suggestion row: per-type icon + highlighted label + optional description. */\nexport function DefaultSuggestion<T>({\n item,\n state,\n getLabel,\n getDescription,\n getSuggestionType,\n matchMode,\n}: {\n item: T;\n state: SuggestionItemState;\n getLabel: (item: T) => string;\n getDescription?: (item: T) => string | undefined;\n getSuggestionType: (item: T) => SuggestionType | undefined;\n matchMode: MatchMode;\n}): React.JSX.Element {\n const label = getLabel(item);\n const description = getDescription?.(item);\n const displayLabel = highlightLabel(label, state.query, matchMode);\n return (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: 1,\n width: '100%',\n // Bold the matched prefix (not a yellow <mark> highlight).\n '& mark': { backgroundColor: 'transparent', color: 'inherit', fontWeight: 700 },\n }}\n >\n {suggestionTypeIcon(getSuggestionType(item))}\n <ListItemText\n primary={<span dangerouslySetInnerHTML={{ __html: displayLabel }} />}\n secondary={description}\n />\n </Box>\n );\n}\n\n/** A \"Loading…\" row shown while async suggestions resolve. */\nexport function LoadingRow(): React.JSX.Element {\n return (\n <ListItem>\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <CircularProgress size={16} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n Loading...\n </Typography>\n </Box>\n </ListItem>\n );\n}\n\n/** The empty \"No results found\" row. */\nexport function NoResultsRow(): React.JSX.Element {\n return (\n <ListItem>\n <Typography variant=\"body2\" color=\"text.secondary\">\n No results found\n </Typography>\n </ListItem>\n );\n}\n\n/** Keep the Popper the same width as its anchor input. */\nconst SAME_WIDTH_MODIFIER = {\n name: 'sameWidth',\n enabled: true,\n fn: ({ state }: { state: { elements: { reference?: unknown }; styles: { popper?: Record<string, string> }; rects: { reference: { width: number } } } }) => {\n if (state.elements.reference && state.styles.popper) {\n state.styles.popper.width = `${state.rects.reference.width}px`;\n }\n },\n phase: 'beforeWrite' as const,\n requires: ['computeStyles'],\n};\n\nexport interface SuggestionListBoxProps<T> {\n open: boolean;\n anchorEl: HTMLElement | null;\n portal: boolean | { container?: HTMLElement };\n listRef: React.RefObject<HTMLUListElement | null>;\n listId: string;\n optionIdPrefix: string;\n items: T[];\n activeIndex: number;\n isLoading: boolean;\n showNoResults: boolean;\n getKey: (item: T) => string;\n onSelect: (item: T) => void;\n onHover: (index: number) => void;\n renderItem: (item: T, active: boolean) => React.ReactNode;\n listClassName?: string;\n itemClassName?: string;\n activeItemClassName?: string;\n}\n\n/** The suggestions dropdown: a same-width Popper with the option list + loading/empty rows. */\nexport function SuggestionListBox<T>({\n open,\n anchorEl,\n portal,\n listRef,\n listId,\n optionIdPrefix,\n items,\n activeIndex,\n isLoading,\n showNoResults,\n getKey,\n onSelect,\n onHover,\n renderItem,\n listClassName,\n itemClassName,\n activeItemClassName,\n}: SuggestionListBoxProps<T>): React.JSX.Element {\n return (\n <StyledPopper\n open={open}\n anchorEl={anchorEl}\n placement=\"bottom-start\"\n disablePortal={!portal}\n modifiers={[SAME_WIDTH_MODIFIER]}\n >\n <Paper elevation={8} className={listClassName} data-testid=\"suggestions-dropdown\">\n <List\n ref={listRef}\n role=\"listbox\"\n id={listId}\n dense\n sx={{ maxHeight: 300, overflow: 'auto' }}\n data-testid=\"suggestions-list\"\n >\n {items.map((item, index) => (\n <ListItem\n key={getKey(item)}\n id={`${optionIdPrefix}-${index}`}\n role=\"option\"\n component=\"div\"\n sx={{\n cursor: 'pointer',\n backgroundColor: index === activeIndex ? 'action.hover' : 'transparent',\n '&:hover': { backgroundColor: 'action.hover' },\n }}\n aria-selected={index === activeIndex}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onSelect(item)}\n onMouseEnter={() => onHover(index)}\n className={`${itemClassName} ${index === activeIndex ? activeItemClassName : ''}`}\n data-testid={`suggestion-item-${index}`}\n >\n {renderItem(item, index === activeIndex)}\n </ListItem>\n ))}\n {isLoading && <LoadingRow />}\n {showNoResults && <NoResultsRow />}\n </List>\n </Paper>\n </StyledPopper>\n );\n}\n","import { useEffect, useId, useRef, useState } from 'react';\n\nimport {\n defaultGetKey,\n defaultGetLabel,\n defaultGetSuggestionType,\n defaultGetUrl,\n defaultOpenLink,\n filterSuggestions,\n firstGhostSuggestion,\n type MatchMode,\n} from './Autocomplete.helpers';\nimport { handleAutocompleteKey, type KeyContext } from './Autocomplete.keys';\nimport type { AutocompleteProps } from './Autocomplete.types';\n\ntype Setter<V> = React.Dispatch<React.SetStateAction<V>>;\n\n/** All mutable state + refs for one Autocomplete instance. */\ninterface AutocompleteState<T> {\n open: boolean;\n setOpen: Setter<boolean>;\n activeIndex: number;\n setActiveIndex: Setter<number>;\n ghost: string;\n setGhost: Setter<string>;\n inputValue: string;\n setInputValue: Setter<string>;\n composition: boolean;\n setComposition: Setter<boolean>;\n filteredSuggestions: T[];\n setFilteredSuggestions: Setter<T[]>;\n isInputFocused: boolean;\n setIsInputFocused: Setter<boolean>;\n justCompletedGhost: boolean;\n setJustCompletedGhost: Setter<boolean>;\n userClosedDropdown: boolean;\n setUserClosedDropdown: Setter<boolean>;\n inputRef: React.RefObject<HTMLInputElement | null>;\n listRef: React.RefObject<HTMLUListElement | null>;\n debounceRef: React.RefObject<number | undefined>;\n}\n\nfunction useAutocompleteState<T>(value: string, suggestions: T[]): AutocompleteState<T> {\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const [ghost, setGhost] = useState('');\n const [inputValue, setInputValue] = useState(value);\n const [composition, setComposition] = useState(false);\n const [filteredSuggestions, setFilteredSuggestions] = useState<T[]>(suggestions);\n const [isInputFocused, setIsInputFocused] = useState(false);\n const [justCompletedGhost, setJustCompletedGhost] = useState(false);\n const [userClosedDropdown, setUserClosedDropdown] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLUListElement | null>(null);\n const debounceRef = useRef<number | undefined>(undefined);\n return {\n open, setOpen, activeIndex, setActiveIndex, ghost, setGhost, inputValue, setInputValue,\n composition, setComposition, filteredSuggestions, setFilteredSuggestions, isInputFocused,\n setIsInputFocused, justCompletedGhost, setJustCompletedGhost, userClosedDropdown,\n setUserClosedDropdown, inputRef, listRef, debounceRef,\n };\n}\n\n// ---- effects (one tiny hook each; explicit params keep deps complete) --------\n\nfunction useValueSync(value: string, setInputValue: Setter<string>): void {\n useEffect(() => setInputValue(value), [value, setInputValue]);\n}\n\nfunction useDebounceCleanup(debounceRef: React.RefObject<number | undefined>): void {\n useEffect(\n () => () => {\n if (debounceRef.current) window.clearTimeout(debounceRef.current);\n },\n [debounceRef],\n );\n}\n\nfunction useScrollActiveIntoView(\n activeIndex: number,\n optionIdPrefix: string,\n listRef: React.RefObject<HTMLUListElement | null>,\n): void {\n useEffect(() => {\n if (activeIndex < 0 || !listRef.current) return;\n document\n .getElementById(`${optionIdPrefix}-${activeIndex}`)\n ?.scrollIntoView({ block: 'nearest' });\n }, [activeIndex, optionIdPrefix, listRef]);\n}\n\nfunction useGhostFlagReset(justCompletedGhost: boolean, setJustCompletedGhost: Setter<boolean>): void {\n useEffect(() => {\n if (!justCompletedGhost) return;\n const timer = setTimeout(() => setJustCompletedGhost(false), 50);\n return () => clearTimeout(timer);\n }, [justCompletedGhost, setJustCompletedGhost]);\n}\n\nfunction useLoadingOpen(\n isLoading: boolean,\n inputValue: string,\n disabled: boolean,\n setOpen: Setter<boolean>,\n setActiveIndex: Setter<number>,\n): void {\n useEffect(() => {\n if (isLoading && inputValue.trim().length > 0 && !disabled) setOpen(true);\n if (disabled) {\n setOpen(false);\n setActiveIndex(-1);\n }\n }, [isLoading, inputValue, disabled, setOpen, setActiveIndex]);\n}\n\n/** Inputs to the auto-open check, all primitive/stable so effect deps stay complete. */\ninterface AutoOpenArgs {\n inputValue: string;\n isInputFocused: boolean;\n composition: boolean;\n justCompletedGhost: boolean;\n userClosedDropdown: boolean;\n activeIndex: number;\n setOpen: Setter<boolean>;\n setActiveIndex: Setter<number>;\n}\n\n/** Auto-open the dropdown once local filtering has a fresh result set. */\nfunction maybeAutoOpen(a: AutoOpenArgs, hasResults: boolean): void {\n const canAutoOpen =\n a.inputValue.trim() &&\n a.isInputFocused &&\n !a.composition &&\n !a.justCompletedGhost &&\n !a.userClosedDropdown;\n if (!canAutoOpen) return;\n a.setOpen(true);\n if (hasResults && a.activeIndex === -1) a.setActiveIndex(0);\n}\n\nfunction useLocalFilter<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const propSuggestions = p.suggestions;\n const getLabel = p.getLabel ?? defaultGetLabel;\n const matchMode: MatchMode = p.matchMode ?? 'contains';\n const async = Boolean(p.async);\n const {\n inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdown, activeIndex,\n setFilteredSuggestions, setOpen, setActiveIndex,\n } = s;\n useEffect(() => {\n const suggestions = propSuggestions ?? [];\n if (async || !inputValue) {\n setFilteredSuggestions(suggestions);\n return;\n }\n const filtered = filterSuggestions(suggestions, inputValue, matchMode, getLabel);\n setFilteredSuggestions(filtered);\n maybeAutoOpen(\n { inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdown, activeIndex, setOpen, setActiveIndex },\n filtered.length > 0,\n );\n }, [\n propSuggestions, inputValue, async, getLabel, matchMode, isInputFocused, composition,\n justCompletedGhost, userClosedDropdown, activeIndex, setFilteredSuggestions, setOpen, setActiveIndex,\n ]);\n}\n\nfunction useGhostText<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const getLabel = p.getLabel ?? defaultGetLabel;\n const getType = p.getSuggestionType ?? defaultGetSuggestionType;\n const showGhost = p.showGhostText ?? true;\n const { inputValue, filteredSuggestions, isInputFocused, composition, setGhost } = s;\n useEffect(() => {\n if (!inputValue || !isInputFocused || composition || !showGhost) {\n setGhost('');\n return;\n }\n const first = firstGhostSuggestion(filteredSuggestions, inputValue, getLabel, getType);\n setGhost(first ? getLabel(first).slice(inputValue.length) : '');\n }, [inputValue, filteredSuggestions, isInputFocused, composition, showGhost, getLabel, getType, setGhost]);\n}\n\n// ---- selection (split by mode to keep each function under the complexity bar) -\n\nfunction commitMultiSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const getKey = p.getKey ?? defaultGetKey;\n const current = p.selectedItems ?? [];\n if (!current.some((sel) => getKey(sel) === getKey(item))) p.onSelectedItemsChange?.([...current, item]);\n s.setInputValue('');\n onChange('');\n s.setUserClosedDropdown(false);\n}\n\nfunction commitSingleSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const label = (p.getLabel ?? defaultGetLabel)(item);\n s.setInputValue(label);\n onChange(label);\n}\n\nfunction runSelectItem<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const url = (p.getUrl ?? defaultGetUrl)(item);\n const isLink = (p.getSuggestionType ?? defaultGetSuggestionType)(item) === 'link' && Boolean(url);\n if (isLink) {\n (p.openLink ?? defaultOpenLink)(url as string, item);\n } else if (p.multiple) {\n commitMultiSelect(item, p, s, onChange);\n } else {\n commitSingleSelect(item, p, s, onChange);\n }\n s.setOpen(false);\n s.setActiveIndex(-1);\n p.onSelect?.(item);\n s.inputRef.current?.focus();\n}\n\nfunction buildKeyContext<T>(\n p: AutocompleteProps<T>,\n s: AutocompleteState<T>,\n selectItem: (item: T) => void,\n onChange: (v: string) => void,\n): KeyContext<T> {\n return {\n open: s.open, activeIndex: s.activeIndex, filteredSuggestions: s.filteredSuggestions,\n maxVisibleItems: p.maxVisibleItems ?? 10, allowFreeText: p.allowFreeText ?? true,\n inputValue: s.inputValue, ghost: s.ghost, isInputFocused: s.isInputFocused,\n multiple: Boolean(p.multiple), selectedItems: p.selectedItems ?? [],\n getLabel: p.getLabel ?? defaultGetLabel,\n getSuggestionType: p.getSuggestionType ?? defaultGetSuggestionType,\n setOpen: s.setOpen, setActiveIndex: s.setActiveIndex, setUserClosedDropdown: s.setUserClosedDropdown,\n setInputValue: s.setInputValue, setGhost: s.setGhost, setJustCompletedGhost: s.setJustCompletedGhost,\n debouncedOnChange: onChange, selectItem, onSelectedItemsChange: p.onSelectedItemsChange,\n };\n}\n\n/** The full view-model the presentational component renders. */\nexport interface AutocompleteView<T> {\n id: string;\n listId: string;\n optionIdPrefix: string;\n state: AutocompleteState<T>;\n visibleSuggestions: T[];\n activeDescendant: string | undefined;\n selectItem: (item: T) => void;\n removeSelectedItem: (item: T) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onClickAway: () => void;\n}\n\n/** Wire state, effects, and (plain, per-render) handlers for the Autocomplete component. */\nexport function useAutocomplete<T>(p: AutocompleteProps<T>): AutocompleteView<T> {\n const componentId = useId();\n const id = p.id || componentId;\n const optionIdPrefix = `${id}-option`;\n const s = useAutocompleteState<T>(p.value, p.suggestions ?? []);\n\n const debouncedOnChange = (val: string): void => {\n if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);\n s.debounceRef.current = window.setTimeout(() => p.onChange(val), p.debounceMs ?? 150);\n };\n\n useValueSync(p.value, s.setInputValue);\n useDebounceCleanup(s.debounceRef);\n useScrollActiveIntoView(s.activeIndex, optionIdPrefix, s.listRef);\n useGhostFlagReset(s.justCompletedGhost, s.setJustCompletedGhost);\n useLoadingOpen(Boolean(p.isLoading), s.inputValue, Boolean(p.disabled), s.setOpen, s.setActiveIndex);\n useLocalFilter(p, s);\n useGhostText(p, s);\n\n const selectItem = (item: T): void => runSelectItem(item, p, s, debouncedOnChange);\n\n return {\n id,\n listId: `${id}-listbox`,\n optionIdPrefix,\n state: s,\n visibleSuggestions: s.filteredSuggestions.slice(0, p.maxVisibleItems ?? 10),\n activeDescendant: s.activeIndex >= 0 ? `${optionIdPrefix}-${s.activeIndex}` : undefined,\n selectItem,\n removeSelectedItem: (item: T): void => {\n const getKey = p.getKey ?? defaultGetKey;\n p.onSelectedItemsChange?.((p.selectedItems ?? []).filter((sel) => getKey(sel) !== getKey(item)));\n s.inputRef.current?.focus();\n },\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>): void =>\n handleAutocompleteKey(e, s.composition, buildKeyContext(p, s, selectItem, debouncedOnChange)),\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>): void => {\n s.setInputValue(e.target.value);\n debouncedOnChange(e.target.value);\n if (!s.open || s.filteredSuggestions.length === 0) s.setActiveIndex(-1);\n s.setUserClosedDropdown(false);\n },\n onFocus: (): void => {\n s.setIsInputFocused(true);\n s.setUserClosedDropdown(false);\n if (!s.inputValue.trim()) return;\n s.setOpen(true);\n if (s.filteredSuggestions.length > 0 && s.activeIndex === -1) s.setActiveIndex(0);\n },\n onBlur: (): void => {\n window.setTimeout(() => s.setIsInputFocused(false), 150);\n },\n onClickAway: (): void => {\n s.setOpen(false);\n s.setActiveIndex(-1);\n s.setUserClosedDropdown(true);\n },\n };\n}\n","import type React from 'react';\n\nimport { firstGhostSuggestion } from './Autocomplete.helpers';\nimport type { SuggestionType } from './Autocomplete.types';\n\n/**\n * Everything a key handler needs. Kept as a flat context object so each handler\n * stays a small pure function and the component's `onKeyDown` is a thin dispatch.\n */\nexport interface KeyContext<T> {\n open: boolean;\n activeIndex: number;\n filteredSuggestions: T[];\n maxVisibleItems: number;\n allowFreeText: boolean;\n inputValue: string;\n ghost: string;\n isInputFocused: boolean;\n multiple: boolean;\n selectedItems: T[];\n getLabel: (item: T) => string;\n getSuggestionType: (item: T) => SuggestionType | undefined;\n setOpen: (open: boolean) => void;\n setActiveIndex: React.Dispatch<React.SetStateAction<number>>;\n setUserClosedDropdown: (closed: boolean) => void;\n setInputValue: (value: string) => void;\n setGhost: (ghost: string) => void;\n setJustCompletedGhost: (done: boolean) => void;\n debouncedOnChange: (value: string) => void;\n selectItem: (item: T) => void;\n onSelectedItemsChange?: (items: T[]) => void;\n}\n\ntype KeyHandler<T> = (event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>) => void;\n\n/** True when there's a ghost remainder that can be accepted right now. */\nfunction canAcceptGhost<T>(ctx: KeyContext<T>): boolean {\n return Boolean(ctx.ghost) && ctx.isInputFocused && ctx.filteredSuggestions.length > 0;\n}\n\n/** Commit a completed value: mark the ghost-complete flag, set + propagate, and close. */\nfunction commitCompletion<T>(ctx: KeyContext<T>, newValue: string): void {\n ctx.setJustCompletedGhost(true);\n ctx.setInputValue(newValue);\n ctx.debouncedOnChange(newValue);\n ctx.setGhost('');\n ctx.setOpen(false);\n ctx.setActiveIndex(-1);\n}\n\nconst onArrowDown = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n event.preventDefault();\n if (!ctx.open && ctx.filteredSuggestions.length > 0) {\n ctx.setOpen(true);\n ctx.setUserClosedDropdown(false);\n }\n const max = Math.min(ctx.filteredSuggestions.length - 1, ctx.maxVisibleItems - 1);\n ctx.setActiveIndex((prev) => (prev < max ? prev + 1 : prev));\n};\n\nconst onArrowUp = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n event.preventDefault();\n ctx.setActiveIndex((prev) => (prev > 0 ? prev - 1 : -1));\n};\n\nconst onEnter = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n event.preventDefault();\n const inRange = ctx.open && ctx.activeIndex >= 0 && ctx.activeIndex < ctx.filteredSuggestions.length;\n if (inRange) {\n const selected = ctx.filteredSuggestions[ctx.activeIndex];\n if (selected) ctx.selectItem(selected);\n } else if (ctx.allowFreeText && ctx.inputValue.trim()) {\n ctx.setOpen(false);\n }\n};\n\nconst onTab = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n // Tab completion preserves the user's typed case (input + ghost remainder).\n if (!canAcceptGhost(ctx)) return;\n event.preventDefault();\n commitCompletion(ctx, ctx.inputValue + ctx.ghost);\n};\n\nconst onArrowRight = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n // ArrowRight completion uses the suggestion's original case.\n if (!canAcceptGhost(ctx)) return;\n event.preventDefault();\n const first = firstGhostSuggestion(\n ctx.filteredSuggestions,\n ctx.inputValue,\n ctx.getLabel,\n ctx.getSuggestionType,\n );\n commitCompletion(ctx, first ? ctx.getLabel(first) : ctx.inputValue);\n};\n\nconst onEscape = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n event.preventDefault();\n ctx.setOpen(false);\n ctx.setActiveIndex(-1);\n ctx.setUserClosedDropdown(true);\n if (event.detail === 2) {\n // Double escape clears the value.\n ctx.setInputValue('');\n ctx.debouncedOnChange('');\n }\n};\n\nconst onBackspace = <T,>(_event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n if (ctx.multiple && ctx.inputValue === '' && ctx.selectedItems.length > 0) {\n ctx.onSelectedItemsChange?.(ctx.selectedItems.slice(0, -1));\n }\n};\n\nconst KEY_HANDLERS: Record<string, KeyHandler<unknown>> = {\n ArrowDown: onArrowDown,\n ArrowUp: onArrowUp,\n Enter: onEnter,\n Tab: onTab,\n ArrowRight: onArrowRight,\n Escape: onEscape,\n Backspace: onBackspace,\n};\n\n/** Dispatch a keydown to its handler (no-op during IME composition or unmapped keys). */\nexport function handleAutocompleteKey<T>(\n event: React.KeyboardEvent<HTMLInputElement>,\n composition: boolean,\n ctx: KeyContext<T>,\n): void {\n if (composition) return;\n const handler = KEY_HANDLERS[event.key] as KeyHandler<T> | undefined;\n handler?.(event, ctx);\n}\n"],"mappings":"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","names":["Box","jsx","jsxs","Box"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/form/Autocomplete/Autocomplete.tsx","../../src/components/form/Autocomplete/Autocomplete.helpers.ts","../../src/components/form/Autocomplete/Autocomplete.parts.tsx","../../src/components/form/Autocomplete/useAutocomplete.ts","../../src/components/form/Autocomplete/Autocomplete.keys.ts"],"sourcesContent":["import { Box, ClickAwayListener } from '@mui/material';\nimport React from 'react';\n\nimport {\n defaultGetKey,\n defaultGetLabel,\n defaultGetSuggestionType,\n type MatchMode,\n} from './Autocomplete.helpers';\nimport {\n AutocompleteInput,\n ChipList,\n DefaultSuggestion,\n SuggestionListBox,\n} from './Autocomplete.parts';\nimport type { AutocompleteOption, AutocompleteProps, SuggestionType } from './Autocomplete.types';\nimport { useAutocomplete, type AutocompleteView } from './useAutocomplete';\n\n/** Presentational props resolved from {@link AutocompleteProps} (defaults applied once). */\ninterface RenderConfig<T> {\n getKey: (item: T) => string;\n getLabel: (item: T) => string;\n getSuggestionType: (item: T) => SuggestionType | undefined;\n getDescription?: (item: T) => string | undefined;\n renderSuggestion?: (item: T, state: { active: boolean; query: string }) => React.ReactNode;\n matchMode: MatchMode;\n multiple: boolean;\n selectedItems: T[];\n isLoading: boolean;\n showGhostText: boolean;\n placeholder: string;\n autoFocus: boolean;\n disabled: boolean;\n portal: boolean | { container?: HTMLElement };\n className?: string;\n chipClassName?: string;\n inputAriaLabel?: string;\n inputClassName?: string;\n listClassName?: string;\n itemClassName?: string;\n activeItemClassName?: string;\n}\n\n/** Apply presentational defaults once so the component itself stays branch-light. */\nfunction resolveRenderConfig<T>(p: AutocompleteProps<T>): RenderConfig<T> {\n return {\n getKey: p.getKey ?? defaultGetKey,\n getLabel: p.getLabel ?? defaultGetLabel,\n getSuggestionType: p.getSuggestionType ?? defaultGetSuggestionType,\n getDescription: p.getDescription,\n renderSuggestion: p.renderSuggestion,\n matchMode: p.matchMode ?? 'contains',\n multiple: Boolean(p.multiple),\n selectedItems: p.selectedItems ?? [],\n isLoading: Boolean(p.isLoading),\n showGhostText: p.showGhostText ?? true,\n placeholder: p.placeholder ?? p.copy.placeholder,\n autoFocus: Boolean(p.autoFocus),\n disabled: Boolean(p.disabled),\n portal: p.portal ?? false,\n className: p.className,\n chipClassName: p.chipClassName,\n inputAriaLabel: p.inputAriaLabel,\n inputClassName: p.inputClassName,\n listClassName: p.listClassName,\n itemClassName: p.itemClassName,\n activeItemClassName: p.activeItemClassName,\n };\n}\n\n/** A single suggestion node: the caller's custom renderer or the default row. */\nfunction renderSuggestionNode<T>(item: T, active: boolean, query: string, cfg: RenderConfig<T>): React.ReactNode {\n if (cfg.renderSuggestion) return cfg.renderSuggestion(item, { active, query });\n return (\n <DefaultSuggestion\n item={item}\n state={{ active, query }}\n getLabel={cfg.getLabel}\n getDescription={cfg.getDescription}\n getSuggestionType={cfg.getSuggestionType}\n matchMode={cfg.matchMode}\n />\n );\n}\n\n/**\n * ARIA combobox with a popup listbox: local/async filtering, inline ghost\n * completion (Tab/→), multi-select chips, custom rendering, and typed\n * `search`/`link` suggestions (a `link` opens its URL instead of filling the\n * input). State/effects/handlers live in {@link useAutocomplete}; presentational\n * pieces live in `Autocomplete.parts`.\n */\nexport const Autocomplete = <T = AutocompleteOption>(props: AutocompleteProps<T>): React.JSX.Element => {\n const cfg = resolveRenderConfig(props);\n const view: AutocompleteView<T> = useAutocomplete<T>(props);\n const s = view.state;\n const showNoResults =\n !cfg.isLoading && view.visibleSuggestions.length === 0 && Boolean(s.inputValue.trim());\n\n return (\n <ClickAwayListener onClickAway={view.onClickAway}>\n <Box className={cfg.className} data-testid=\"autocomplete-container\">\n {cfg.multiple && cfg.selectedItems.length > 0 && (\n <ChipList\n items={cfg.selectedItems}\n getKey={cfg.getKey}\n getLabel={cfg.getLabel}\n onRemove={view.removeSelectedItem}\n chipClassName={cfg.chipClassName}\n />\n )}\n\n <AutocompleteInput\n id={view.id}\n listId={view.listId}\n inputRef={s.inputRef}\n inputValue={s.inputValue}\n ghost={s.ghost}\n showGhost={cfg.showGhostText}\n isInputFocused={s.isInputFocused}\n open={s.open}\n activeDescendant={view.activeDescendant}\n isLoading={cfg.isLoading}\n disabled={cfg.disabled}\n autoFocus={cfg.autoFocus}\n placeholder={cfg.placeholder}\n startAdornment={props.startAdornment}\n inputAriaLabel={cfg.inputAriaLabel}\n inputClassName={cfg.inputClassName}\n onChange={view.onInputChange}\n onKeyDown={view.onKeyDown}\n onFocus={view.onFocus}\n onBlur={view.onBlur}\n onCompositionStart={() => s.setComposition(true)}\n onCompositionEnd={() => s.setComposition(false)}\n />\n\n {s.open && (\n <SuggestionListBox\n copy={props.copy}\n open={s.open}\n anchorEl={s.inputRef.current}\n portal={cfg.portal}\n listRef={s.listRef}\n listId={view.listId}\n optionIdPrefix={view.optionIdPrefix}\n items={view.visibleSuggestions}\n activeIndex={s.activeIndex}\n isLoading={cfg.isLoading}\n showNoResults={showNoResults}\n getKey={cfg.getKey}\n onSelect={view.selectItem}\n onHover={s.setActiveIndex}\n renderItem={(item, active) => renderSuggestionNode(item, active, s.inputValue, cfg)}\n listClassName={cfg.listClassName}\n itemClassName={cfg.itemClassName}\n activeItemClassName={cfg.activeItemClassName}\n />\n )}\n </Box>\n </ClickAwayListener>\n );\n};\n\nAutocomplete.displayName = 'Autocomplete';\n\nexport default Autocomplete;\n","import type { SuggestionType } from './Autocomplete.types';\n\n/** Local filtering strategy. */\nexport type MatchMode = 'startsWith' | 'contains' | 'fuzzy';\n\n/** Default key extractor: id/key/value/label, else the item itself stringified. */\nexport const defaultGetKey = <T,>(item: T): string => {\n if (typeof item === 'string') return item;\n if (typeof item === 'object' && item !== null) {\n const obj = item as Record<string, unknown>;\n return String(obj.id ?? obj.key ?? obj.value ?? obj.label ?? obj);\n }\n return String(item);\n};\n\n/** Default label extractor: label/name/text, else the item itself stringified. */\nexport const defaultGetLabel = <T,>(item: T): string => {\n if (typeof item === 'string') return item;\n if (typeof item === 'object' && item !== null) {\n const obj = item as Record<string, unknown>;\n return String(obj.label ?? obj.name ?? obj.text ?? obj);\n }\n return String(item);\n};\n\n/** Default suggestion-type extractor: reads a `type: 'search' | 'link'` field. */\nexport const defaultGetSuggestionType = <T,>(item: T): SuggestionType | undefined => {\n if (typeof item === 'object' && item !== null) {\n const { type } = item as { type?: unknown };\n if (type === 'search' || type === 'link') return type;\n }\n return undefined;\n};\n\n/** Default URL extractor for `link` suggestions: reads a `url: string` field. */\nexport const defaultGetUrl = <T,>(item: T): string | undefined => {\n if (typeof item === 'object' && item !== null) {\n const { url } = item as { url?: unknown };\n if (typeof url === 'string') return url;\n }\n return undefined;\n};\n\n/** Default link opener: a new tab with `noopener,noreferrer`. SSR-guarded. */\nexport const defaultOpenLink = (url: string): void => {\n if (typeof window !== 'undefined') {\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n};\n\n/** Fuzzy match: every char of `query` appears in `label`, in order. */\nfunction fuzzyMatch(label: string, query: string): boolean {\n let labelIndex = 0;\n for (let queryIndex = 0; queryIndex < query.length; queryIndex++) {\n const char = query[queryIndex];\n if (!char) continue;\n labelIndex = label.indexOf(char, labelIndex);\n if (labelIndex === -1) return false;\n labelIndex++;\n }\n return true;\n}\n\n/** True when `label` matches `query` under the given {@link MatchMode} (case-insensitive). */\nfunction matchesQuery(label: string, query: string, matchMode: MatchMode): boolean {\n const haystack = label.toLowerCase();\n const needle = query.toLowerCase();\n if (matchMode === 'startsWith') return haystack.startsWith(needle);\n if (matchMode === 'fuzzy') return fuzzyMatch(haystack, needle);\n return haystack.includes(needle);\n}\n\n/** Filter `suggestions` by `query` under `matchMode`; an empty query returns all. */\nexport function filterSuggestions<T>(\n suggestions: T[],\n query: string,\n matchMode: MatchMode,\n getLabel: (item: T) => string,\n): T[] {\n if (!query) return suggestions;\n return suggestions.filter((item) => matchesQuery(getLabel(item), query, matchMode));\n}\n\n/**\n * The first suggestion eligible for inline ghost completion: a non-`link` item\n * whose label starts with `inputValue` (case-insensitive) but isn't equal to it.\n * Shared by the ghost-text effect and ArrowRight completion.\n */\nexport function firstGhostSuggestion<T>(\n list: T[],\n inputValue: string,\n getLabel: (item: T) => string,\n getSuggestionType: (item: T) => SuggestionType | undefined,\n): T | undefined {\n const needle = inputValue.toLowerCase();\n return list.find((item) => {\n const label = getLabel(item).toLowerCase();\n return getSuggestionType(item) !== 'link' && label.startsWith(needle) && label !== needle;\n });\n}\n\n/** Escape a user query for safe use inside a `RegExp`. */\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Wrap query matches in `<mark>` for the default suggestion renderer. Skipped for\n * fuzzy mode (non-contiguous matches) and empty queries. Returns HTML.\n */\nexport function highlightLabel(label: string, query: string, matchMode: MatchMode): string {\n if (!query || matchMode === 'fuzzy') return label;\n const regex = new RegExp(`(${escapeRegExp(query)})`, 'gi');\n return label.replace(regex, '<mark>$1</mark>');\n}\n","import LinkIcon from '@mui/icons-material/Link';\nimport SearchIcon from '@mui/icons-material/Search';\nimport {\n Box,\n Chip,\n CircularProgress,\n List,\n ListItem,\n ListItemText,\n Paper,\n Popper,\n TextField,\n Typography,\n} from '@mui/material';\nimport { styled } from '@mui/material';\nimport React from 'react';\n\nimport { highlightLabel, type MatchMode } from './Autocomplete.helpers';\nimport type { SuggestionItemState, SuggestionType } from './Autocomplete.types';\nimport type { AutocompleteCopy } from '../../../copy';\n\nconst StyledPopper = styled(Popper)(({ theme }) => ({\n zIndex: theme.zIndex.tooltip,\n width: '100%',\n maxHeight: 300,\n overflow: 'auto',\n // Popper.js writes the computed position (and stamps `data-popper-placement`)\n // in a layout effect that can land AFTER the first paint. Until it does, the\n // element would paint once unpositioned — at the offset-parent origin, far\n // left and full width — then jump under the input, a visible per-keystroke\n // flash as the list re-renders. Hide that unpositioned first frame; it becomes\n // visible the instant popper assigns a placement.\n '&:not([data-popper-placement])': { visibility: 'hidden' },\n}));\n\nconst InlineSuggestionDisplay = styled('div')(() => ({\n position: 'absolute',\n pointerEvents: 'none',\n left: '14px', // Match TextField padding\n top: '50%',\n transform: 'translateY(-50%)',\n fontSize: 'inherit',\n fontFamily: 'inherit',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n zIndex: 1,\n}));\n\nconst UserTextTwin = styled('span')({\n visibility: 'hidden',\n});\n\nconst GhostText = styled('span')(({ theme }) => ({\n color: theme.palette.text.secondary,\n opacity: 0.6,\n}));\n\nconst ChipContainer = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(0.5),\n marginBottom: theme.spacing(1),\n}));\n\n/** Leading icon for a typed suggestion (search vs. link); null for untyped items. */\nexport function suggestionTypeIcon(type: SuggestionType | undefined): React.ReactNode {\n const sx = { color: 'text.secondary', flexShrink: 0 } as const;\n if (type === 'link') return <LinkIcon fontSize=\"small\" sx={sx} />;\n if (type === 'search') return <SearchIcon fontSize=\"small\" sx={sx} />;\n return null;\n}\n\n/** The inline ghost-text overlay: an invisible twin of the typed text + the grey remainder. */\nfunction GhostOverlay({ inputValue, ghost }: { inputValue: string; ghost: string }): React.JSX.Element {\n return (\n <InlineSuggestionDisplay>\n <UserTextTwin>{inputValue}</UserTextTwin>\n <GhostText>{ghost}</GhostText>\n </InlineSuggestionDisplay>\n );\n}\n\nexport interface AutocompleteInputProps {\n id: string;\n listId: string;\n inputRef: React.RefObject<HTMLInputElement | null>;\n inputValue: string;\n ghost: string;\n showGhost: boolean;\n isInputFocused: boolean;\n open: boolean;\n activeDescendant: string | undefined;\n isLoading: boolean;\n disabled: boolean;\n autoFocus: boolean;\n placeholder: string;\n startAdornment?: React.ReactNode;\n inputAriaLabel?: string;\n inputClassName?: string;\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onCompositionStart: () => void;\n onCompositionEnd: () => void;\n}\n\n/** The combobox text field plus its inline ghost-text overlay. */\nexport function AutocompleteInput(props: AutocompleteInputProps): React.JSX.Element {\n const showOverlay = Boolean(props.ghost) && props.showGhost && props.isInputFocused;\n return (\n <Box sx={{ position: 'relative' }}>\n {showOverlay && <GhostOverlay inputValue={props.inputValue} ghost={props.ghost} />}\n <TextField\n ref={props.inputRef}\n fullWidth\n value={props.inputValue}\n onChange={props.onChange}\n onKeyDown={props.onKeyDown}\n onFocus={props.onFocus}\n onBlur={props.onBlur}\n onCompositionStart={props.onCompositionStart}\n onCompositionEnd={props.onCompositionEnd}\n placeholder={props.placeholder}\n disabled={props.disabled}\n autoFocus={props.autoFocus}\n className={props.inputClassName}\n InputProps={{\n startAdornment: props.startAdornment,\n endAdornment: props.isLoading ? <CircularProgress size={20} /> : undefined,\n }}\n inputProps={{\n role: 'combobox',\n 'aria-expanded': props.open,\n 'aria-controls': props.open ? props.listId : undefined,\n 'aria-activedescendant': props.activeDescendant,\n 'aria-autocomplete': 'list',\n 'aria-label': props.inputAriaLabel,\n id: props.id,\n }}\n />\n </Box>\n );\n}\n\n/** Selected-item chips (multiple mode). */\nexport function ChipList<T>({\n items,\n getKey,\n getLabel,\n onRemove,\n chipClassName,\n}: {\n items: T[];\n getKey: (item: T) => string;\n getLabel: (item: T) => string;\n onRemove: (item: T) => void;\n chipClassName?: string;\n}): React.JSX.Element {\n return (\n <ChipContainer data-testid=\"selected-items-container\">\n {items.map((item, index) => (\n <Chip\n key={`${getKey(item)}-${index}`}\n label={getLabel(item)}\n onDelete={() => onRemove(item)}\n size=\"small\"\n className={chipClassName}\n data-testid={`selected-chip-${index}`}\n />\n ))}\n </ChipContainer>\n );\n}\n\n/** Default suggestion row: per-type icon + highlighted label + optional description. */\nexport function DefaultSuggestion<T>({\n item,\n state,\n getLabel,\n getDescription,\n getSuggestionType,\n matchMode,\n}: {\n item: T;\n state: SuggestionItemState;\n getLabel: (item: T) => string;\n getDescription?: (item: T) => string | undefined;\n getSuggestionType: (item: T) => SuggestionType | undefined;\n matchMode: MatchMode;\n}): React.JSX.Element {\n const label = getLabel(item);\n const description = getDescription?.(item);\n const displayLabel = highlightLabel(label, state.query, matchMode);\n return (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: 1,\n width: '100%',\n // Bold the matched prefix (not a yellow <mark> highlight).\n '& mark': { backgroundColor: 'transparent', color: 'inherit', fontWeight: 700 },\n }}\n >\n {suggestionTypeIcon(getSuggestionType(item))}\n <ListItemText\n primary={<span dangerouslySetInnerHTML={{ __html: displayLabel }} />}\n secondary={description}\n />\n </Box>\n );\n}\n\n/** A \"Loading…\" row shown while async suggestions resolve. */\nexport function LoadingRow({ label }: { label: string }): React.JSX.Element {\n return (\n <ListItem>\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <CircularProgress size={16} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {label}\n </Typography>\n </Box>\n </ListItem>\n );\n}\n\n/** The empty \"No results found\" row. */\nexport function NoResultsRow({ label }: { label: string }): React.JSX.Element {\n return (\n <ListItem>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {label}\n </Typography>\n </ListItem>\n );\n}\n\n/** Keep the Popper the same width as its anchor input. */\nconst SAME_WIDTH_MODIFIER = {\n name: 'sameWidth',\n enabled: true,\n fn: ({ state }: { state: { elements: { reference?: unknown }; styles: { popper?: Record<string, string> }; rects: { reference: { width: number } } } }) => {\n if (state.elements.reference && state.styles.popper) {\n state.styles.popper.width = `${state.rects.reference.width}px`;\n }\n },\n phase: 'beforeWrite' as const,\n requires: ['computeStyles'],\n};\n\nexport interface SuggestionListBoxProps<T> {\n copy: AutocompleteCopy;\n open: boolean;\n anchorEl: HTMLElement | null;\n portal: boolean | { container?: HTMLElement };\n listRef: React.RefObject<HTMLUListElement | null>;\n listId: string;\n optionIdPrefix: string;\n items: T[];\n activeIndex: number;\n isLoading: boolean;\n showNoResults: boolean;\n getKey: (item: T) => string;\n onSelect: (item: T) => void;\n onHover: (index: number) => void;\n renderItem: (item: T, active: boolean) => React.ReactNode;\n listClassName?: string;\n itemClassName?: string;\n activeItemClassName?: string;\n}\n\n/** The suggestions dropdown: a same-width Popper with the option list + loading/empty rows. */\nexport function SuggestionListBox<T>({\n copy,\n open,\n anchorEl,\n portal,\n listRef,\n listId,\n optionIdPrefix,\n items,\n activeIndex,\n isLoading,\n showNoResults,\n getKey,\n onSelect,\n onHover,\n renderItem,\n listClassName,\n itemClassName,\n activeItemClassName,\n}: SuggestionListBoxProps<T>): React.JSX.Element {\n return (\n <StyledPopper\n open={open}\n anchorEl={anchorEl}\n placement=\"bottom-start\"\n disablePortal={!portal}\n modifiers={[SAME_WIDTH_MODIFIER]}\n >\n <Paper elevation={8} className={listClassName} data-testid=\"suggestions-dropdown\">\n <List\n ref={listRef}\n role=\"listbox\"\n id={listId}\n dense\n sx={{ maxHeight: 300, overflow: 'auto' }}\n data-testid=\"suggestions-list\"\n >\n {items.map((item, index) => (\n <ListItem\n key={getKey(item)}\n id={`${optionIdPrefix}-${index}`}\n role=\"option\"\n component=\"div\"\n sx={{\n cursor: 'pointer',\n backgroundColor: index === activeIndex ? 'action.hover' : 'transparent',\n '&:hover': { backgroundColor: 'action.hover' },\n }}\n aria-selected={index === activeIndex}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onSelect(item)}\n onMouseEnter={() => onHover(index)}\n className={`${itemClassName} ${index === activeIndex ? activeItemClassName : ''}`}\n data-testid={`suggestion-item-${index}`}\n >\n {renderItem(item, index === activeIndex)}\n </ListItem>\n ))}\n {isLoading && <LoadingRow label={copy.loading} />}\n {showNoResults && <NoResultsRow label={copy.noResults} />}\n </List>\n </Paper>\n </StyledPopper>\n );\n}\n","import { useEffect, useId, useRef, useState } from 'react';\n\nimport {\n defaultGetKey,\n defaultGetLabel,\n defaultGetSuggestionType,\n defaultGetUrl,\n defaultOpenLink,\n filterSuggestions,\n firstGhostSuggestion,\n type MatchMode,\n} from './Autocomplete.helpers';\nimport { handleAutocompleteKey, type KeyContext } from './Autocomplete.keys';\nimport type { AutocompleteProps } from './Autocomplete.types';\n\ntype Setter<V> = React.Dispatch<React.SetStateAction<V>>;\n\n/** All mutable state + refs for one Autocomplete instance. */\ninterface AutocompleteState<T> {\n open: boolean;\n setOpen: Setter<boolean>;\n activeIndex: number;\n setActiveIndex: Setter<number>;\n ghost: string;\n setGhost: Setter<string>;\n inputValue: string;\n setInputValue: Setter<string>;\n composition: boolean;\n setComposition: Setter<boolean>;\n filteredSuggestions: T[];\n setFilteredSuggestions: Setter<T[]>;\n isInputFocused: boolean;\n setIsInputFocused: Setter<boolean>;\n justCompletedGhost: boolean;\n setJustCompletedGhost: Setter<boolean>;\n userClosedDropdown: boolean;\n setUserClosedDropdown: Setter<boolean>;\n inputRef: React.RefObject<HTMLInputElement | null>;\n listRef: React.RefObject<HTMLUListElement | null>;\n debounceRef: React.RefObject<number | undefined>;\n}\n\nfunction useAutocompleteState<T>(value: string, suggestions: T[]): AutocompleteState<T> {\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const [ghost, setGhost] = useState('');\n const [inputValue, setInputValue] = useState(value);\n const [composition, setComposition] = useState(false);\n const [filteredSuggestions, setFilteredSuggestions] = useState<T[]>(suggestions);\n const [isInputFocused, setIsInputFocused] = useState(false);\n const [justCompletedGhost, setJustCompletedGhost] = useState(false);\n const [userClosedDropdown, setUserClosedDropdown] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLUListElement | null>(null);\n const debounceRef = useRef<number | undefined>(undefined);\n return {\n open, setOpen, activeIndex, setActiveIndex, ghost, setGhost, inputValue, setInputValue,\n composition, setComposition, filteredSuggestions, setFilteredSuggestions, isInputFocused,\n setIsInputFocused, justCompletedGhost, setJustCompletedGhost, userClosedDropdown,\n setUserClosedDropdown, inputRef, listRef, debounceRef,\n };\n}\n\n// ---- effects (one tiny hook each; explicit params keep deps complete) --------\n\nfunction useValueSync(value: string, setInputValue: Setter<string>): void {\n useEffect(() => setInputValue(value), [value, setInputValue]);\n}\n\nfunction useDebounceCleanup(debounceRef: React.RefObject<number | undefined>): void {\n useEffect(\n () => () => {\n if (debounceRef.current) window.clearTimeout(debounceRef.current);\n },\n [debounceRef],\n );\n}\n\nfunction useScrollActiveIntoView(\n activeIndex: number,\n optionIdPrefix: string,\n listRef: React.RefObject<HTMLUListElement | null>,\n): void {\n useEffect(() => {\n if (activeIndex < 0 || !listRef.current) return;\n document\n .getElementById(`${optionIdPrefix}-${activeIndex}`)\n ?.scrollIntoView({ block: 'nearest' });\n }, [activeIndex, optionIdPrefix, listRef]);\n}\n\nfunction useGhostFlagReset(justCompletedGhost: boolean, setJustCompletedGhost: Setter<boolean>): void {\n useEffect(() => {\n if (!justCompletedGhost) return;\n const timer = setTimeout(() => setJustCompletedGhost(false), 50);\n return () => clearTimeout(timer);\n }, [justCompletedGhost, setJustCompletedGhost]);\n}\n\nfunction useLoadingOpen(\n isLoading: boolean,\n inputValue: string,\n disabled: boolean,\n setOpen: Setter<boolean>,\n setActiveIndex: Setter<number>,\n): void {\n useEffect(() => {\n if (isLoading && inputValue.trim().length > 0 && !disabled) setOpen(true);\n if (disabled) {\n setOpen(false);\n setActiveIndex(-1);\n }\n }, [isLoading, inputValue, disabled, setOpen, setActiveIndex]);\n}\n\n/** Inputs to the auto-open check, all primitive/stable so effect deps stay complete. */\ninterface AutoOpenArgs {\n inputValue: string;\n isInputFocused: boolean;\n composition: boolean;\n justCompletedGhost: boolean;\n userClosedDropdown: boolean;\n activeIndex: number;\n setOpen: Setter<boolean>;\n setActiveIndex: Setter<number>;\n}\n\n/** Auto-open the dropdown once local filtering has a fresh result set. */\nfunction maybeAutoOpen(a: AutoOpenArgs, hasResults: boolean): void {\n const canAutoOpen =\n a.inputValue.trim() &&\n a.isInputFocused &&\n !a.composition &&\n !a.justCompletedGhost &&\n !a.userClosedDropdown;\n if (!canAutoOpen) return;\n a.setOpen(true);\n if (hasResults && a.activeIndex === -1) a.setActiveIndex(0);\n}\n\nfunction useLocalFilter<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const propSuggestions = p.suggestions;\n const getLabel = p.getLabel ?? defaultGetLabel;\n const matchMode: MatchMode = p.matchMode ?? 'contains';\n const async = Boolean(p.async);\n const {\n inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdown, activeIndex,\n setFilteredSuggestions, setOpen, setActiveIndex,\n } = s;\n useEffect(() => {\n const suggestions = propSuggestions ?? [];\n if (async || !inputValue) {\n setFilteredSuggestions(suggestions);\n return;\n }\n const filtered = filterSuggestions(suggestions, inputValue, matchMode, getLabel);\n setFilteredSuggestions(filtered);\n maybeAutoOpen(\n { inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdown, activeIndex, setOpen, setActiveIndex },\n filtered.length > 0,\n );\n }, [\n propSuggestions, inputValue, async, getLabel, matchMode, isInputFocused, composition,\n justCompletedGhost, userClosedDropdown, activeIndex, setFilteredSuggestions, setOpen, setActiveIndex,\n ]);\n}\n\nfunction useGhostText<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const getLabel = p.getLabel ?? defaultGetLabel;\n const getType = p.getSuggestionType ?? defaultGetSuggestionType;\n const showGhost = p.showGhostText ?? true;\n const { inputValue, filteredSuggestions, isInputFocused, composition, setGhost } = s;\n useEffect(() => {\n if (!inputValue || !isInputFocused || composition || !showGhost) {\n setGhost('');\n return;\n }\n const first = firstGhostSuggestion(filteredSuggestions, inputValue, getLabel, getType);\n setGhost(first ? getLabel(first).slice(inputValue.length) : '');\n }, [inputValue, filteredSuggestions, isInputFocused, composition, showGhost, getLabel, getType, setGhost]);\n}\n\n// ---- selection (split by mode to keep each function under the complexity bar) -\n\nfunction commitMultiSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const getKey = p.getKey ?? defaultGetKey;\n const current = p.selectedItems ?? [];\n if (!current.some((sel) => getKey(sel) === getKey(item))) p.onSelectedItemsChange?.([...current, item]);\n s.setInputValue('');\n onChange('');\n s.setUserClosedDropdown(false);\n}\n\nfunction commitSingleSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const label = (p.getLabel ?? defaultGetLabel)(item);\n s.setInputValue(label);\n onChange(label);\n}\n\nfunction runSelectItem<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const url = (p.getUrl ?? defaultGetUrl)(item);\n const isLink = (p.getSuggestionType ?? defaultGetSuggestionType)(item) === 'link' && Boolean(url);\n if (isLink) {\n (p.openLink ?? defaultOpenLink)(url as string, item);\n } else if (p.multiple) {\n commitMultiSelect(item, p, s, onChange);\n } else {\n commitSingleSelect(item, p, s, onChange);\n }\n s.setOpen(false);\n s.setActiveIndex(-1);\n p.onSelect?.(item);\n s.inputRef.current?.focus();\n}\n\nfunction buildKeyContext<T>(\n p: AutocompleteProps<T>,\n s: AutocompleteState<T>,\n selectItem: (item: T) => void,\n onChange: (v: string) => void,\n): KeyContext<T> {\n return {\n open: s.open, activeIndex: s.activeIndex, filteredSuggestions: s.filteredSuggestions,\n maxVisibleItems: p.maxVisibleItems ?? 10, allowFreeText: p.allowFreeText ?? true,\n inputValue: s.inputValue, ghost: s.ghost, isInputFocused: s.isInputFocused,\n multiple: Boolean(p.multiple), selectedItems: p.selectedItems ?? [],\n getLabel: p.getLabel ?? defaultGetLabel,\n getSuggestionType: p.getSuggestionType ?? defaultGetSuggestionType,\n setOpen: s.setOpen, setActiveIndex: s.setActiveIndex, setUserClosedDropdown: s.setUserClosedDropdown,\n setInputValue: s.setInputValue, setGhost: s.setGhost, setJustCompletedGhost: s.setJustCompletedGhost,\n debouncedOnChange: onChange, selectItem, onSelectedItemsChange: p.onSelectedItemsChange,\n };\n}\n\n/** The full view-model the presentational component renders. */\nexport interface AutocompleteView<T> {\n id: string;\n listId: string;\n optionIdPrefix: string;\n state: AutocompleteState<T>;\n visibleSuggestions: T[];\n activeDescendant: string | undefined;\n selectItem: (item: T) => void;\n removeSelectedItem: (item: T) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onClickAway: () => void;\n}\n\n/** Wire state, effects, and (plain, per-render) handlers for the Autocomplete component. */\nexport function useAutocomplete<T>(p: AutocompleteProps<T>): AutocompleteView<T> {\n const componentId = useId();\n const id = p.id || componentId;\n const optionIdPrefix = `${id}-option`;\n const s = useAutocompleteState<T>(p.value, p.suggestions ?? []);\n\n const debouncedOnChange = (val: string): void => {\n if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);\n s.debounceRef.current = window.setTimeout(() => p.onChange(val), p.debounceMs ?? 150);\n };\n\n useValueSync(p.value, s.setInputValue);\n useDebounceCleanup(s.debounceRef);\n useScrollActiveIntoView(s.activeIndex, optionIdPrefix, s.listRef);\n useGhostFlagReset(s.justCompletedGhost, s.setJustCompletedGhost);\n useLoadingOpen(Boolean(p.isLoading), s.inputValue, Boolean(p.disabled), s.setOpen, s.setActiveIndex);\n useLocalFilter(p, s);\n useGhostText(p, s);\n\n const selectItem = (item: T): void => runSelectItem(item, p, s, debouncedOnChange);\n\n return {\n id,\n listId: `${id}-listbox`,\n optionIdPrefix,\n state: s,\n visibleSuggestions: s.filteredSuggestions.slice(0, p.maxVisibleItems ?? 10),\n activeDescendant: s.activeIndex >= 0 ? `${optionIdPrefix}-${s.activeIndex}` : undefined,\n selectItem,\n removeSelectedItem: (item: T): void => {\n const getKey = p.getKey ?? defaultGetKey;\n p.onSelectedItemsChange?.((p.selectedItems ?? []).filter((sel) => getKey(sel) !== getKey(item)));\n s.inputRef.current?.focus();\n },\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>): void =>\n handleAutocompleteKey(e, s.composition, buildKeyContext(p, s, selectItem, debouncedOnChange)),\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>): void => {\n s.setInputValue(e.target.value);\n debouncedOnChange(e.target.value);\n if (!s.open || s.filteredSuggestions.length === 0) s.setActiveIndex(-1);\n s.setUserClosedDropdown(false);\n },\n onFocus: (): void => {\n s.setIsInputFocused(true);\n s.setUserClosedDropdown(false);\n if (!s.inputValue.trim()) return;\n s.setOpen(true);\n if (s.filteredSuggestions.length > 0 && s.activeIndex === -1) s.setActiveIndex(0);\n },\n onBlur: (): void => {\n window.setTimeout(() => s.setIsInputFocused(false), 150);\n },\n onClickAway: (): void => {\n s.setOpen(false);\n s.setActiveIndex(-1);\n s.setUserClosedDropdown(true);\n },\n };\n}\n","import type React from 'react';\n\nimport { firstGhostSuggestion } from './Autocomplete.helpers';\nimport type { SuggestionType } from './Autocomplete.types';\n\n/**\n * Everything a key handler needs. Kept as a flat context object so each handler\n * stays a small pure function and the component's `onKeyDown` is a thin dispatch.\n */\nexport interface KeyContext<T> {\n open: boolean;\n activeIndex: number;\n filteredSuggestions: T[];\n maxVisibleItems: number;\n allowFreeText: boolean;\n inputValue: string;\n ghost: string;\n isInputFocused: boolean;\n multiple: boolean;\n selectedItems: T[];\n getLabel: (item: T) => string;\n getSuggestionType: (item: T) => SuggestionType | undefined;\n setOpen: (open: boolean) => void;\n setActiveIndex: React.Dispatch<React.SetStateAction<number>>;\n setUserClosedDropdown: (closed: boolean) => void;\n setInputValue: (value: string) => void;\n setGhost: (ghost: string) => void;\n setJustCompletedGhost: (done: boolean) => void;\n debouncedOnChange: (value: string) => void;\n selectItem: (item: T) => void;\n onSelectedItemsChange?: (items: T[]) => void;\n}\n\ntype KeyHandler<T> = (event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>) => void;\n\n/** True when there's a ghost remainder that can be accepted right now. */\nfunction canAcceptGhost<T>(ctx: KeyContext<T>): boolean {\n return Boolean(ctx.ghost) && ctx.isInputFocused && ctx.filteredSuggestions.length > 0;\n}\n\n/** Commit a completed value: mark the ghost-complete flag, set + propagate, and close. */\nfunction commitCompletion<T>(ctx: KeyContext<T>, newValue: string): void {\n ctx.setJustCompletedGhost(true);\n ctx.setInputValue(newValue);\n ctx.debouncedOnChange(newValue);\n ctx.setGhost('');\n ctx.setOpen(false);\n ctx.setActiveIndex(-1);\n}\n\nconst onArrowDown = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n event.preventDefault();\n if (!ctx.open && ctx.filteredSuggestions.length > 0) {\n ctx.setOpen(true);\n ctx.setUserClosedDropdown(false);\n }\n const max = Math.min(ctx.filteredSuggestions.length - 1, ctx.maxVisibleItems - 1);\n ctx.setActiveIndex((prev) => (prev < max ? prev + 1 : prev));\n};\n\nconst onArrowUp = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n event.preventDefault();\n ctx.setActiveIndex((prev) => (prev > 0 ? prev - 1 : -1));\n};\n\nconst onEnter = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n event.preventDefault();\n const inRange = ctx.open && ctx.activeIndex >= 0 && ctx.activeIndex < ctx.filteredSuggestions.length;\n if (inRange) {\n const selected = ctx.filteredSuggestions[ctx.activeIndex];\n if (selected) ctx.selectItem(selected);\n } else if (ctx.allowFreeText && ctx.inputValue.trim()) {\n ctx.setOpen(false);\n }\n};\n\nconst onTab = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n // Tab completion preserves the user's typed case (input + ghost remainder).\n if (!canAcceptGhost(ctx)) return;\n event.preventDefault();\n commitCompletion(ctx, ctx.inputValue + ctx.ghost);\n};\n\nconst onArrowRight = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n // ArrowRight completion uses the suggestion's original case.\n if (!canAcceptGhost(ctx)) return;\n event.preventDefault();\n const first = firstGhostSuggestion(\n ctx.filteredSuggestions,\n ctx.inputValue,\n ctx.getLabel,\n ctx.getSuggestionType,\n );\n commitCompletion(ctx, first ? ctx.getLabel(first) : ctx.inputValue);\n};\n\nconst onEscape = <T,>(event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n event.preventDefault();\n ctx.setOpen(false);\n ctx.setActiveIndex(-1);\n ctx.setUserClosedDropdown(true);\n if (event.detail === 2) {\n // Double escape clears the value.\n ctx.setInputValue('');\n ctx.debouncedOnChange('');\n }\n};\n\nconst onBackspace = <T,>(_event: React.KeyboardEvent<HTMLInputElement>, ctx: KeyContext<T>): void => {\n if (ctx.multiple && ctx.inputValue === '' && ctx.selectedItems.length > 0) {\n ctx.onSelectedItemsChange?.(ctx.selectedItems.slice(0, -1));\n }\n};\n\nconst KEY_HANDLERS: Record<string, KeyHandler<unknown>> = {\n ArrowDown: onArrowDown,\n ArrowUp: onArrowUp,\n Enter: onEnter,\n Tab: onTab,\n ArrowRight: onArrowRight,\n Escape: onEscape,\n Backspace: onBackspace,\n};\n\n/** Dispatch a keydown to its handler (no-op during IME composition or unmapped keys). */\nexport function handleAutocompleteKey<T>(\n event: React.KeyboardEvent<HTMLInputElement>,\n composition: boolean,\n ctx: KeyContext<T>,\n): void {\n if (composition) return;\n const handler = KEY_HANDLERS[event.key] as KeyHandler<T> | undefined;\n handler?.(event, ctx);\n}\n"],"mappings":"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","names":["Box","jsx","jsxs","Box"]}
|
package/dist/form/Calendar.js
CHANGED
package/dist/form/CodeEditor.js
CHANGED
|
@@ -216,6 +216,7 @@ var LanguageBadge = styled(Box)(({ theme }) => ({
|
|
|
216
216
|
letterSpacing: "0.05em"
|
|
217
217
|
}));
|
|
218
218
|
var EditorActions = ({
|
|
219
|
+
copy,
|
|
219
220
|
readOnly,
|
|
220
221
|
isWrapped,
|
|
221
222
|
isCopied,
|
|
@@ -228,7 +229,7 @@ var EditorActions = ({
|
|
|
228
229
|
}) => {
|
|
229
230
|
const testId = makeTestId2(dataTestId);
|
|
230
231
|
return /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, children: [
|
|
231
|
-
!readOnly && /* @__PURE__ */ jsx(Tooltip, { title:
|
|
232
|
+
!readOnly && /* @__PURE__ */ jsx(Tooltip, { title: copy.formatCode, children: /* @__PURE__ */ jsx(
|
|
232
233
|
IconButton,
|
|
233
234
|
{
|
|
234
235
|
size: "small",
|
|
@@ -237,7 +238,7 @@ var EditorActions = ({
|
|
|
237
238
|
children: /* @__PURE__ */ jsx(CodeIcon, { fontSize: "small" })
|
|
238
239
|
}
|
|
239
240
|
) }),
|
|
240
|
-
/* @__PURE__ */ jsx(Tooltip, { title: isWrapped ?
|
|
241
|
+
/* @__PURE__ */ jsx(Tooltip, { title: isWrapped ? copy.disableWrap : copy.enableWrap, children: /* @__PURE__ */ jsx(
|
|
241
242
|
IconButton,
|
|
242
243
|
{
|
|
243
244
|
size: "small",
|
|
@@ -247,7 +248,7 @@ var EditorActions = ({
|
|
|
247
248
|
children: /* @__PURE__ */ jsx(WrapIcon, { fontSize: "small" })
|
|
248
249
|
}
|
|
249
250
|
) }),
|
|
250
|
-
/* @__PURE__ */ jsx(Tooltip, { title: isCopied ?
|
|
251
|
+
/* @__PURE__ */ jsx(Tooltip, { title: isCopied ? copy.copied : copy.copyToClipboard, children: /* @__PURE__ */ jsx(
|
|
251
252
|
IconButton,
|
|
252
253
|
{
|
|
253
254
|
size: "small",
|
|
@@ -257,7 +258,7 @@ var EditorActions = ({
|
|
|
257
258
|
children: /* @__PURE__ */ jsx(CopyIcon, { fontSize: "small" })
|
|
258
259
|
}
|
|
259
260
|
) }),
|
|
260
|
-
/* @__PURE__ */ jsx(Tooltip, { title: isFullscreen ?
|
|
261
|
+
/* @__PURE__ */ jsx(Tooltip, { title: isFullscreen ? copy.exitFullscreen : copy.enterFullscreen, children: /* @__PURE__ */ jsx(
|
|
261
262
|
IconButton,
|
|
262
263
|
{
|
|
263
264
|
size: "small",
|
|
@@ -269,6 +270,7 @@ var EditorActions = ({
|
|
|
269
270
|
] });
|
|
270
271
|
};
|
|
271
272
|
var EditorToolbar = ({
|
|
273
|
+
copy,
|
|
272
274
|
language,
|
|
273
275
|
readOnly,
|
|
274
276
|
isWrapped,
|
|
@@ -287,11 +289,12 @@ var EditorToolbar = ({
|
|
|
287
289
|
/* @__PURE__ */ jsx(CodeIcon, { sx: { fontSize: 14 } }),
|
|
288
290
|
language
|
|
289
291
|
] }),
|
|
290
|
-
readOnly && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children:
|
|
292
|
+
readOnly && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: copy.readOnly })
|
|
291
293
|
] }),
|
|
292
294
|
/* @__PURE__ */ jsx(
|
|
293
295
|
EditorActions,
|
|
294
296
|
{
|
|
297
|
+
copy,
|
|
295
298
|
readOnly,
|
|
296
299
|
isWrapped,
|
|
297
300
|
isCopied,
|
|
@@ -344,7 +347,7 @@ var PlaceholderOverlay = styled2(Box2)(({ theme }) => ({
|
|
|
344
347
|
pointerEvents: "none",
|
|
345
348
|
userSelect: "none"
|
|
346
349
|
}));
|
|
347
|
-
var EditorLoading = () => /* @__PURE__ */ jsx2(
|
|
350
|
+
var EditorLoading = ({ label }) => /* @__PURE__ */ jsx2(
|
|
348
351
|
Box2,
|
|
349
352
|
{
|
|
350
353
|
sx: {
|
|
@@ -354,7 +357,7 @@ var EditorLoading = () => /* @__PURE__ */ jsx2(
|
|
|
354
357
|
height: "100%",
|
|
355
358
|
color: "text.secondary"
|
|
356
359
|
},
|
|
357
|
-
children: /* @__PURE__ */ jsx2(Typography2, { variant: "body2", children:
|
|
360
|
+
children: /* @__PURE__ */ jsx2(Typography2, { variant: "body2", children: label })
|
|
358
361
|
}
|
|
359
362
|
);
|
|
360
363
|
var buildEditorOptions = ({
|
|
@@ -405,7 +408,8 @@ var CodeEditor = (componentProps) => {
|
|
|
405
408
|
autoFormat,
|
|
406
409
|
placeholder,
|
|
407
410
|
onSave,
|
|
408
|
-
dataTestId
|
|
411
|
+
dataTestId,
|
|
412
|
+
copy
|
|
409
413
|
} = resolveCodeEditorProps(componentProps);
|
|
410
414
|
const testId = makeTestId(dataTestId);
|
|
411
415
|
const editor = useCodeEditor({ themeProp, wordWrap, autoFormat, readOnly, onSave });
|
|
@@ -420,6 +424,7 @@ var CodeEditor = (componentProps) => {
|
|
|
420
424
|
showToolbar && /* @__PURE__ */ jsx2(
|
|
421
425
|
EditorToolbar,
|
|
422
426
|
{
|
|
427
|
+
copy,
|
|
423
428
|
language,
|
|
424
429
|
readOnly,
|
|
425
430
|
isWrapped: editor.isWrapped,
|
|
@@ -444,7 +449,7 @@ var CodeEditor = (componentProps) => {
|
|
|
444
449
|
theme: editor.editorTheme,
|
|
445
450
|
options: editorOptions,
|
|
446
451
|
onMount: editor.handleEditorDidMount,
|
|
447
|
-
loading: /* @__PURE__ */ jsx2(EditorLoading, {})
|
|
452
|
+
loading: /* @__PURE__ */ jsx2(EditorLoading, { label: copy.loading })
|
|
448
453
|
}
|
|
449
454
|
)
|
|
450
455
|
] })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/form/CodeEditor/CodeEditor.tsx","../../src/components/form/CodeEditor/CodeEditor.helpers.ts","../../src/components/form/CodeEditor/CodeEditor.hooks.ts","../../src/components/form/CodeEditor/CodeEditor.monaco.ts","../../src/components/form/CodeEditor/CodeEditorToolbar.tsx"],"sourcesContent":["import Editor from '@monaco-editor/react';\nimport {\n alpha,\n Box,\n Paper,\n styled,\n Typography } from '@mui/material';\nimport type { editor } from 'monaco-editor';\nimport type { FC} from 'react';\nimport React, { } from 'react';\n\nimport { makeTestId, resolveCodeEditorProps } from './CodeEditor.helpers';\nimport { useCodeEditor } from './CodeEditor.hooks';\nimport type { CodeEditorProps } from './CodeEditor.types';\nimport { EditorToolbar } from './CodeEditorToolbar';\n\n// Styled components\nconst EditorContainer = styled(Paper)(({ theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.98)} 0%, ${alpha(theme.palette.background.paper, 0.95)} 100%)`,\n backdropFilter: 'blur(10px)',\n WebkitBackdropFilter: 'blur(10px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n borderRadius: theme.shape.borderRadius * 2,\n overflow: 'hidden' }));\n\nconst EditorWrapper = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'fullscreen' })<{ fullscreen: boolean }>(({ theme, fullscreen }) => ({\n position: 'relative',\n flex: 1,\n minHeight: 200,\n ...(fullscreen && {\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: theme.zIndex.modal,\n background: theme.palette.background.paper }) }));\n\nconst PlaceholderOverlay = styled(Box)(({ theme }) => ({\n position: 'absolute',\n top: theme.spacing(2),\n left: theme.spacing(8),\n color: theme.palette.text.disabled,\n fontFamily: 'Monaco, Menlo, \"Ubuntu Mono\", Consolas, source-code-pro, monospace',\n fontSize: '0.875rem',\n pointerEvents: 'none',\n userSelect: 'none' }));\n\n// Monaco editor themes\nconst EditorLoading: FC = () => (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n color: 'text.secondary' }}\n >\n <Typography variant=\"body2\">Loading editor...</Typography>\n </Box>\n);\n\nconst buildEditorOptions = ({\n minimap,\n fontSize,\n isWrapped,\n lineNumbers,\n readOnly }: {\n minimap?: boolean;\n fontSize: number;\n isWrapped: boolean;\n lineNumbers: boolean;\n readOnly: boolean;\n}): editor.IStandaloneEditorConstructionOptions => ({\n readOnly,\n // Explicitly convert minimap to boolean to ensure Monaco receives a definitive value\n // This prevents undefined from being interpreted differently in various environments\n minimap: { enabled: minimap === true },\n fontSize,\n wordWrap: isWrapped ? 'on' : 'off',\n lineNumbers: lineNumbers ? 'on' : 'off',\n scrollBeyondLastLine: false,\n automaticLayout: true,\n tabSize: 2,\n insertSpaces: true,\n folding: true,\n foldingStrategy: 'indentation',\n showFoldingControls: 'mouseover',\n smoothScrolling: true,\n cursorBlinking: 'smooth',\n cursorSmoothCaretAnimation: 'on',\n renderWhitespace: 'selection',\n renderLineHighlight: 'all',\n selectOnLineNumbers: true,\n roundedSelection: true,\n padding: { top: 16, bottom: 16 },\n fontFamily: 'Monaco, Menlo, \"Ubuntu Mono\", Consolas, source-code-pro, monospace',\n fontLigatures: true });\n\nexport const CodeEditor: FC<CodeEditorProps> = (componentProps) => {\n const {\n language,\n height,\n theme: themeProp,\n value,\n onChange,\n readOnly,\n lineNumbers,\n minimap,\n fontSize,\n wordWrap,\n showToolbar,\n autoFormat,\n placeholder,\n onSave,\n dataTestId } = resolveCodeEditorProps(componentProps);\n\n const testId = makeTestId(dataTestId);\n const editor = useCodeEditor({ themeProp, wordWrap, autoFormat, readOnly, onSave });\n\n const editorOptions = buildEditorOptions({\n minimap,\n fontSize,\n isWrapped: editor.isWrapped,\n lineNumbers,\n readOnly });\n\n return (\n <EditorContainer elevation={2} data-testid={dataTestId || 'code-editor'}>\n {showToolbar && (\n <EditorToolbar\n language={language}\n readOnly={readOnly}\n isWrapped={editor.isWrapped}\n isCopied={editor.isCopied}\n isFullscreen={editor.isFullscreen}\n dataTestId={dataTestId}\n onFormat={editor.handleFormat}\n onCopy={editor.handleCopy}\n onWrapToggle={editor.handleWrapToggle}\n onFullscreenToggle={editor.handleFullscreenToggle}\n />\n )}\n\n <EditorWrapper fullscreen={editor.isFullscreen} data-testid={testId('editor-wrapper')}>\n {placeholder && !value && (\n <PlaceholderOverlay data-testid={testId('placeholder')}>{placeholder}</PlaceholderOverlay>\n )}\n\n <Editor\n height={editor.isFullscreen ? '100vh' : height}\n language={language}\n value={value}\n onChange={(newValue) => onChange?.(newValue || '')}\n theme={editor.editorTheme}\n options={editorOptions}\n onMount={editor.handleEditorDidMount}\n loading={<EditorLoading />}\n />\n </EditorWrapper>\n </EditorContainer>\n );\n};\n","import type { CodeEditorProps } from './CodeEditor.types';\n\n// Every element repeated the same conditional test id; this is that ternary once.\nexport const makeTestId =\n (dataTestId?: string) =>\n (suffix: string): string =>\n dataTestId ? `${dataTestId}-${suffix}` : `code-editor-${suffix}`;\n\ntype CodeEditorDefaultedKeys =\n | 'height'\n | 'theme'\n | 'readOnly'\n | 'lineNumbers'\n | 'minimap'\n | 'fontSize'\n | 'wordWrap'\n | 'showToolbar'\n | 'autoFormat';\n\ntype ResolvedCodeEditorProps = CodeEditorProps &\n Required<Pick<CodeEditorProps, CodeEditorDefaultedKeys>>;\n\nconst CODE_EDITOR_DEFAULTS: Pick<CodeEditorProps, CodeEditorDefaultedKeys> = {\n height: '400px',\n theme: 'auto',\n readOnly: false,\n lineNumbers: true,\n minimap: false,\n fontSize: 14,\n wordWrap: false,\n showToolbar: true,\n autoFormat: false,\n};\n\n// Strips explicitly-undefined props before the merge, so `prop={undefined}` still\n// falls back to the default exactly as a destructuring default would. Applied as\n// a merge rather than destructuring defaults, which would otherwise put nine\n// branches into the component's own complexity budget.\nexport const resolveCodeEditorProps = (props: CodeEditorProps): ResolvedCodeEditorProps =>\n ({\n ...CODE_EDITOR_DEFAULTS,\n ...(Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<CodeEditorProps>),\n }) as ResolvedCodeEditorProps;\n","import type { Monaco } from '@monaco-editor/react';\nimport { useTheme } from '@mui/material';\nimport type { editor } from 'monaco-editor';\nimport React, { useEffect, useRef } from 'react';\n\nimport {\n configureTypeScriptDefaults,\n registerEditorThemes,\n registerSaveShortcut,\n resolveEditorTheme,\n scheduleAutoFormat,\n} from './CodeEditor.monaco';\n\nconst COPIED_FEEDBACK_MS = 2000;\n\n// Escape leaves fullscreen, so the flag and its listener belong together.\nconst useFullscreen = () => {\n const [isFullscreen, setIsFullscreen] = React.useState(false);\n\n useEffect(() => {\n if (!isFullscreen) return;\n\n const handleEsc = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') setIsFullscreen(false);\n };\n\n window.addEventListener('keydown', handleEsc);\n return () => window.removeEventListener('keydown', handleEsc);\n }, [isFullscreen]);\n\n return { isFullscreen, toggleFullscreen: () => setIsFullscreen((prev) => !prev) };\n};\n\n// All of the editor's own state: the Monaco handles, the three toggles, and the\n// handlers that drive them.\nexport const useCodeEditor = ({\n themeProp,\n wordWrap,\n autoFormat,\n readOnly,\n onSave,\n}: {\n themeProp: string;\n wordWrap: boolean;\n autoFormat: boolean;\n readOnly: boolean;\n onSave?: (value: string) => void;\n}) => {\n const theme = useTheme();\n const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);\n const monacoRef = useRef<Monaco | null>(null);\n const { isFullscreen, toggleFullscreen } = useFullscreen();\n const [isWrapped, setIsWrapped] = React.useState(wordWrap);\n const [isCopied, setIsCopied] = React.useState(false);\n\n const editorTheme = React.useMemo(\n () => resolveEditorTheme(themeProp, theme.palette.mode),\n [themeProp, theme.palette.mode],\n );\n\n const handleEditorDidMount = (mountedEditor: editor.IStandaloneCodeEditor, monaco: Monaco) => {\n editorRef.current = mountedEditor;\n monacoRef.current = monaco;\n\n registerEditorThemes(monaco);\n configureTypeScriptDefaults(monaco);\n scheduleAutoFormat(mountedEditor, autoFormat && !readOnly);\n registerSaveShortcut(mountedEditor, monaco, onSave);\n };\n\n // No-ops where the clipboard API is unavailable, as in jsdom.\n const handleCopy = async () => {\n if (!editorRef.current || !navigator.clipboard?.writeText) return;\n\n try {\n await navigator.clipboard.writeText(editorRef.current.getValue());\n setIsCopied(true);\n window.setTimeout(() => setIsCopied(false), COPIED_FEEDBACK_MS);\n } catch {\n // Silently handle clipboard errors in test environments\n }\n };\n\n const handleWrapToggle = () => {\n setIsWrapped(!isWrapped);\n editorRef.current?.updateOptions({ wordWrap: !isWrapped ? 'on' : 'off' });\n };\n\n const handleFormat = () => {\n if (!readOnly) editorRef.current?.getAction('editor.action.formatDocument')?.run();\n };\n\n return {\n editorTheme,\n isFullscreen,\n isWrapped,\n isCopied,\n handleEditorDidMount,\n handleCopy,\n handleFullscreenToggle: toggleFullscreen,\n handleWrapToggle,\n handleFormat,\n };\n};\n","import type { Monaco } from '@monaco-editor/react';\nimport type { editor } from 'monaco-editor';\n\nconst customLightTheme = {\n base: 'vs' as const,\n inherit: true,\n rules: [\n { token: 'comment', foreground: '6A737D', fontStyle: 'italic' },\n { token: 'keyword', foreground: 'D73A49' },\n { token: 'string', foreground: '032F62' },\n { token: 'number', foreground: '005CC5' },\n ],\n colors: {\n 'editor.background': '#FFFFFF',\n 'editor.foreground': '#24292E',\n 'editor.lineHighlightBackground': '#F6F8FA',\n 'editorLineNumber.foreground': '#959DA5',\n 'editorIndentGuide.background': '#D1D5DA',\n 'editor.selectionBackground': '#C8E1FF',\n },\n};\n\nconst customDarkTheme = {\n base: 'vs-dark' as const,\n inherit: true,\n rules: [\n { token: 'comment', foreground: '6A737D', fontStyle: 'italic' },\n { token: 'keyword', foreground: 'F97583' },\n { token: 'string', foreground: '9ECBFF' },\n { token: 'number', foreground: '79B8FF' },\n ],\n colors: {\n 'editor.background': '#0D1117',\n 'editor.foreground': '#C9D1D9',\n 'editor.lineHighlightBackground': '#161B22',\n 'editorLineNumber.foreground': '#8B949E',\n 'editorIndentGuide.background': '#21262D',\n 'editor.selectionBackground': '#3392FF44',\n },\n};\n\n// Main component\nconst AUTO_FORMAT_DELAY_MS = 100;\n\nexport const registerEditorThemes = (monaco: Monaco) => {\n monaco.editor.defineTheme('custom-light', customLightTheme);\n monaco.editor.defineTheme('custom-dark', customDarkTheme);\n};\n\n// Best-effort: a Monaco build without the TypeScript worker (as in jsdom) throws\n// here, and the editor is still usable without it.\nexport const configureTypeScriptDefaults = (monaco: Monaco) => {\n try {\n const tsLanguage = monaco.languages\n .getLanguages()\n .find((language) => language.id === 'typescript');\n\n if (!tsLanguage) return;\n\n monaco.languages.typescript.typescriptDefaults.setCompilerOptions({\n target: monaco.languages.typescript.ScriptTarget.ES2020,\n allowNonTsExtensions: true,\n moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,\n module: monaco.languages.typescript.ModuleKind.CommonJS,\n noEmit: true,\n esModuleInterop: true,\n jsx: monaco.languages.typescript.JsxEmit.React,\n reactNamespace: 'React',\n allowJs: true,\n typeRoots: ['node_modules/@types'],\n });\n\n monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({\n noSemanticValidation: false,\n noSyntaxValidation: false,\n noSuggestionDiagnostics: true,\n });\n } catch {\n // Silently handle any TypeScript configuration errors in test environments\n }\n};\n\nexport const scheduleAutoFormat = (mountedEditor: editor.IStandaloneCodeEditor, enabled: boolean) => {\n if (!enabled) return;\n\n window.setTimeout(() => {\n mountedEditor.getAction('editor.action.formatDocument')?.run();\n }, AUTO_FORMAT_DELAY_MS);\n};\n\nexport const registerSaveShortcut = (\n mountedEditor: editor.IStandaloneCodeEditor,\n monaco: Monaco,\n onSave?: (value: string) => void,\n) => {\n mountedEditor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {\n onSave?.(mountedEditor.getValue());\n });\n};\n\n// 'auto' follows the MUI palette; otherwise the caller's choice wins.\nexport const resolveEditorTheme = (themeProp: string, paletteMode: string) => {\n const wantsDark = themeProp === 'auto' ? paletteMode === 'dark' : themeProp === 'dark';\n\n return wantsDark ? 'custom-dark' : 'custom-light';\n};\n\n// Monaco's options object. Only the first five entries vary with our props; the\n// rest are fixed editor preferences.\n","import CodeIcon from '@mui/icons-material/Code';\nimport CopyIcon from '@mui/icons-material/ContentCopy';\nimport ExitFullscreenIcon from '@mui/icons-material/FullscreenExit';\nimport FullscreenIcon from '@mui/icons-material/Fullscreen';\nimport WrapIcon from '@mui/icons-material/WrapText';\nimport { Box, IconButton, Stack, Tooltip, Typography } from '@mui/material';\nimport { alpha, styled } from '@mui/material';\nimport React from 'react';\n\n// Each button repeated the same conditional test id; this is that ternary once.\nconst makeTestId =\n (dataTestId?: string) =>\n (suffix: string): string =>\n dataTestId ? `${dataTestId}-${suffix}` : `code-editor-${suffix}`;\n\nconst Toolbar = styled(Box)(({ theme }) => ({\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: theme.spacing(1, 2),\n borderBottom: `1px solid ${alpha(theme.palette.divider, 0.12)}`,\n background: alpha(theme.palette.background.default, 0.4),\n}));\n\nconst LanguageBadge = styled(Box)(({ theme }) => ({\n display: 'inline-flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n padding: theme.spacing(0.5, 1),\n borderRadius: theme.shape.borderRadius,\n background: alpha(theme.palette.primary.main, 0.1),\n color: theme.palette.primary.main,\n fontSize: '0.75rem',\n fontWeight: 600,\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n}));\n\nconst EditorActions: React.FC<{\n readOnly: boolean;\n isWrapped: boolean;\n isCopied: boolean;\n isFullscreen: boolean;\n dataTestId?: string;\n onFormat: () => void;\n onCopy: () => void;\n onWrapToggle: () => void;\n onFullscreenToggle: () => void;\n}> = ({\n readOnly,\n isWrapped,\n isCopied,\n isFullscreen,\n dataTestId,\n onFormat,\n onCopy,\n onWrapToggle,\n onFullscreenToggle,\n}) => {\n const testId = makeTestId(dataTestId);\n\n return (\n <Stack direction=\"row\" spacing={1}>\n {!readOnly && (\n <Tooltip title=\"Format Code (Ctrl+Shift+F)\">\n <IconButton\n size=\"small\"\n onClick={onFormat}\n data-testid={testId('format-btn')}\n >\n <CodeIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n\n <Tooltip title={isWrapped ? 'Disable Word Wrap' : 'Enable Word Wrap'}>\n <IconButton\n size=\"small\"\n onClick={onWrapToggle}\n color={isWrapped ? 'primary' : 'default'}\n data-testid={testId('wrap-btn')}\n >\n <WrapIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n\n <Tooltip title={isCopied ? 'Copied!' : 'Copy to Clipboard'}>\n <IconButton\n size=\"small\"\n onClick={onCopy}\n color={isCopied ? 'success' : 'default'}\n data-testid={testId('copy-btn')}\n >\n <CopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n\n <Tooltip title={isFullscreen ? 'Exit Fullscreen' : 'Enter Fullscreen'}>\n <IconButton\n size=\"small\"\n onClick={onFullscreenToggle}\n data-testid={testId('fullscreen-btn')}\n >\n {isFullscreen ? (\n <ExitFullscreenIcon fontSize=\"small\" />\n ) : (\n <FullscreenIcon fontSize=\"small\" />\n )}\n </IconButton>\n </Tooltip>\n </Stack>\n );\n};\n\n// Language badge, read-only marker and the four action buttons.\nexport const EditorToolbar: React.FC<{\n language: string;\n readOnly: boolean;\n isWrapped: boolean;\n isCopied: boolean;\n isFullscreen: boolean;\n dataTestId?: string;\n onFormat: () => void;\n onCopy: () => void;\n onWrapToggle: () => void;\n onFullscreenToggle: () => void;\n}> = ({\n language,\n readOnly,\n isWrapped,\n isCopied,\n isFullscreen,\n dataTestId,\n onFormat,\n onCopy,\n onWrapToggle,\n onFullscreenToggle,\n}) => {\n const testId = makeTestId(dataTestId);\n\n return (\n <Toolbar data-testid={testId('toolbar')}>\n <Stack direction=\"row\" spacing={2} alignItems=\"center\">\n <LanguageBadge data-testid={testId('language-badge')}>\n <CodeIcon sx={{ fontSize: 14 }} />\n {language}\n </LanguageBadge>\n {readOnly && (\n <Typography variant=\"caption\" color=\"text.secondary\">\n Read Only\n </Typography>\n )}\n </Stack>\n\n <EditorActions\n readOnly={readOnly}\n isWrapped={isWrapped}\n isCopied={isCopied}\n isFullscreen={isFullscreen}\n dataTestId={dataTestId}\n onFormat={onFormat}\n onCopy={onCopy}\n onWrapToggle={onWrapToggle}\n onFullscreenToggle={onFullscreenToggle}\n />\n </Toolbar>\n );\n};\n"],"mappings":"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","names":["alpha","Box","styled","Typography","makeTestId","jsx","jsxs","styled","alpha","Box","Typography"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/form/CodeEditor/CodeEditor.tsx","../../src/components/form/CodeEditor/CodeEditor.helpers.ts","../../src/components/form/CodeEditor/CodeEditor.hooks.ts","../../src/components/form/CodeEditor/CodeEditor.monaco.ts","../../src/components/form/CodeEditor/CodeEditorToolbar.tsx"],"sourcesContent":["import Editor from '@monaco-editor/react';\nimport {\n alpha,\n Box,\n Paper,\n styled,\n Typography } from '@mui/material';\nimport type { editor } from 'monaco-editor';\nimport type { FC} from 'react';\nimport React, { } from 'react';\n\nimport { makeTestId, resolveCodeEditorProps } from './CodeEditor.helpers';\nimport { useCodeEditor } from './CodeEditor.hooks';\nimport type { CodeEditorProps } from './CodeEditor.types';\nimport { EditorToolbar } from './CodeEditorToolbar';\n\n// Styled components\nconst EditorContainer = styled(Paper)(({ theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.98)} 0%, ${alpha(theme.palette.background.paper, 0.95)} 100%)`,\n backdropFilter: 'blur(10px)',\n WebkitBackdropFilter: 'blur(10px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n borderRadius: theme.shape.borderRadius * 2,\n overflow: 'hidden' }));\n\nconst EditorWrapper = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'fullscreen' })<{ fullscreen: boolean }>(({ theme, fullscreen }) => ({\n position: 'relative',\n flex: 1,\n minHeight: 200,\n ...(fullscreen && {\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: theme.zIndex.modal,\n background: theme.palette.background.paper }) }));\n\nconst PlaceholderOverlay = styled(Box)(({ theme }) => ({\n position: 'absolute',\n top: theme.spacing(2),\n left: theme.spacing(8),\n color: theme.palette.text.disabled,\n fontFamily: 'Monaco, Menlo, \"Ubuntu Mono\", Consolas, source-code-pro, monospace',\n fontSize: '0.875rem',\n pointerEvents: 'none',\n userSelect: 'none' }));\n\n// Monaco editor themes\nconst EditorLoading: FC<{ label: string }> = ({ label }) => (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n color: 'text.secondary' }}\n >\n <Typography variant=\"body2\">{label}</Typography>\n </Box>\n);\n\nconst buildEditorOptions = ({\n minimap,\n fontSize,\n isWrapped,\n lineNumbers,\n readOnly }: {\n minimap?: boolean;\n fontSize: number;\n isWrapped: boolean;\n lineNumbers: boolean;\n readOnly: boolean;\n}): editor.IStandaloneEditorConstructionOptions => ({\n readOnly,\n // Explicitly convert minimap to boolean to ensure Monaco receives a definitive value\n // This prevents undefined from being interpreted differently in various environments\n minimap: { enabled: minimap === true },\n fontSize,\n wordWrap: isWrapped ? 'on' : 'off',\n lineNumbers: lineNumbers ? 'on' : 'off',\n scrollBeyondLastLine: false,\n automaticLayout: true,\n tabSize: 2,\n insertSpaces: true,\n folding: true,\n foldingStrategy: 'indentation',\n showFoldingControls: 'mouseover',\n smoothScrolling: true,\n cursorBlinking: 'smooth',\n cursorSmoothCaretAnimation: 'on',\n renderWhitespace: 'selection',\n renderLineHighlight: 'all',\n selectOnLineNumbers: true,\n roundedSelection: true,\n padding: { top: 16, bottom: 16 },\n fontFamily: 'Monaco, Menlo, \"Ubuntu Mono\", Consolas, source-code-pro, monospace',\n fontLigatures: true });\n\nexport const CodeEditor: FC<CodeEditorProps> = (componentProps) => {\n const {\n language,\n height,\n theme: themeProp,\n value,\n onChange,\n readOnly,\n lineNumbers,\n minimap,\n fontSize,\n wordWrap,\n showToolbar,\n autoFormat,\n placeholder,\n onSave,\n dataTestId,\n copy } = resolveCodeEditorProps(componentProps);\n\n const testId = makeTestId(dataTestId);\n const editor = useCodeEditor({ themeProp, wordWrap, autoFormat, readOnly, onSave });\n\n const editorOptions = buildEditorOptions({\n minimap,\n fontSize,\n isWrapped: editor.isWrapped,\n lineNumbers,\n readOnly });\n\n return (\n <EditorContainer elevation={2} data-testid={dataTestId || 'code-editor'}>\n {showToolbar && (\n <EditorToolbar\n copy={copy}\n language={language}\n readOnly={readOnly}\n isWrapped={editor.isWrapped}\n isCopied={editor.isCopied}\n isFullscreen={editor.isFullscreen}\n dataTestId={dataTestId}\n onFormat={editor.handleFormat}\n onCopy={editor.handleCopy}\n onWrapToggle={editor.handleWrapToggle}\n onFullscreenToggle={editor.handleFullscreenToggle}\n />\n )}\n\n <EditorWrapper fullscreen={editor.isFullscreen} data-testid={testId('editor-wrapper')}>\n {placeholder && !value && (\n <PlaceholderOverlay data-testid={testId('placeholder')}>{placeholder}</PlaceholderOverlay>\n )}\n\n <Editor\n height={editor.isFullscreen ? '100vh' : height}\n language={language}\n value={value}\n onChange={(newValue) => onChange?.(newValue || '')}\n theme={editor.editorTheme}\n options={editorOptions}\n onMount={editor.handleEditorDidMount}\n loading={<EditorLoading label={copy.loading} />}\n />\n </EditorWrapper>\n </EditorContainer>\n );\n};\n","import type { CodeEditorProps } from './CodeEditor.types';\n\n// Every element repeated the same conditional test id; this is that ternary once.\nexport const makeTestId =\n (dataTestId?: string) =>\n (suffix: string): string =>\n dataTestId ? `${dataTestId}-${suffix}` : `code-editor-${suffix}`;\n\ntype CodeEditorDefaultedKeys =\n | 'height'\n | 'theme'\n | 'readOnly'\n | 'lineNumbers'\n | 'minimap'\n | 'fontSize'\n | 'wordWrap'\n | 'showToolbar'\n | 'autoFormat';\n\ntype ResolvedCodeEditorProps = CodeEditorProps &\n Required<Pick<CodeEditorProps, CodeEditorDefaultedKeys>>;\n\nconst CODE_EDITOR_DEFAULTS: Pick<CodeEditorProps, CodeEditorDefaultedKeys> = {\n height: '400px',\n theme: 'auto',\n readOnly: false,\n lineNumbers: true,\n minimap: false,\n fontSize: 14,\n wordWrap: false,\n showToolbar: true,\n autoFormat: false,\n};\n\n// Strips explicitly-undefined props before the merge, so `prop={undefined}` still\n// falls back to the default exactly as a destructuring default would. Applied as\n// a merge rather than destructuring defaults, which would otherwise put nine\n// branches into the component's own complexity budget.\nexport const resolveCodeEditorProps = (props: CodeEditorProps): ResolvedCodeEditorProps =>\n ({\n ...CODE_EDITOR_DEFAULTS,\n ...(Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<CodeEditorProps>),\n }) as ResolvedCodeEditorProps;\n","import type { Monaco } from '@monaco-editor/react';\nimport { useTheme } from '@mui/material';\nimport type { editor } from 'monaco-editor';\nimport React, { useEffect, useRef } from 'react';\n\nimport {\n configureTypeScriptDefaults,\n registerEditorThemes,\n registerSaveShortcut,\n resolveEditorTheme,\n scheduleAutoFormat,\n} from './CodeEditor.monaco';\n\nconst COPIED_FEEDBACK_MS = 2000;\n\n// Escape leaves fullscreen, so the flag and its listener belong together.\nconst useFullscreen = () => {\n const [isFullscreen, setIsFullscreen] = React.useState(false);\n\n useEffect(() => {\n if (!isFullscreen) return;\n\n const handleEsc = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') setIsFullscreen(false);\n };\n\n window.addEventListener('keydown', handleEsc);\n return () => window.removeEventListener('keydown', handleEsc);\n }, [isFullscreen]);\n\n return { isFullscreen, toggleFullscreen: () => setIsFullscreen((prev) => !prev) };\n};\n\n// All of the editor's own state: the Monaco handles, the three toggles, and the\n// handlers that drive them.\nexport const useCodeEditor = ({\n themeProp,\n wordWrap,\n autoFormat,\n readOnly,\n onSave,\n}: {\n themeProp: string;\n wordWrap: boolean;\n autoFormat: boolean;\n readOnly: boolean;\n onSave?: (value: string) => void;\n}) => {\n const theme = useTheme();\n const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);\n const monacoRef = useRef<Monaco | null>(null);\n const { isFullscreen, toggleFullscreen } = useFullscreen();\n const [isWrapped, setIsWrapped] = React.useState(wordWrap);\n const [isCopied, setIsCopied] = React.useState(false);\n\n const editorTheme = React.useMemo(\n () => resolveEditorTheme(themeProp, theme.palette.mode),\n [themeProp, theme.palette.mode],\n );\n\n const handleEditorDidMount = (mountedEditor: editor.IStandaloneCodeEditor, monaco: Monaco) => {\n editorRef.current = mountedEditor;\n monacoRef.current = monaco;\n\n registerEditorThemes(monaco);\n configureTypeScriptDefaults(monaco);\n scheduleAutoFormat(mountedEditor, autoFormat && !readOnly);\n registerSaveShortcut(mountedEditor, monaco, onSave);\n };\n\n // No-ops where the clipboard API is unavailable, as in jsdom.\n const handleCopy = async () => {\n if (!editorRef.current || !navigator.clipboard?.writeText) return;\n\n try {\n await navigator.clipboard.writeText(editorRef.current.getValue());\n setIsCopied(true);\n window.setTimeout(() => setIsCopied(false), COPIED_FEEDBACK_MS);\n } catch {\n // Silently handle clipboard errors in test environments\n }\n };\n\n const handleWrapToggle = () => {\n setIsWrapped(!isWrapped);\n editorRef.current?.updateOptions({ wordWrap: !isWrapped ? 'on' : 'off' });\n };\n\n const handleFormat = () => {\n if (!readOnly) editorRef.current?.getAction('editor.action.formatDocument')?.run();\n };\n\n return {\n editorTheme,\n isFullscreen,\n isWrapped,\n isCopied,\n handleEditorDidMount,\n handleCopy,\n handleFullscreenToggle: toggleFullscreen,\n handleWrapToggle,\n handleFormat,\n };\n};\n","import type { Monaco } from '@monaco-editor/react';\nimport type { editor } from 'monaco-editor';\n\nconst customLightTheme = {\n base: 'vs' as const,\n inherit: true,\n rules: [\n { token: 'comment', foreground: '6A737D', fontStyle: 'italic' },\n { token: 'keyword', foreground: 'D73A49' },\n { token: 'string', foreground: '032F62' },\n { token: 'number', foreground: '005CC5' },\n ],\n colors: {\n 'editor.background': '#FFFFFF',\n 'editor.foreground': '#24292E',\n 'editor.lineHighlightBackground': '#F6F8FA',\n 'editorLineNumber.foreground': '#959DA5',\n 'editorIndentGuide.background': '#D1D5DA',\n 'editor.selectionBackground': '#C8E1FF',\n },\n};\n\nconst customDarkTheme = {\n base: 'vs-dark' as const,\n inherit: true,\n rules: [\n { token: 'comment', foreground: '6A737D', fontStyle: 'italic' },\n { token: 'keyword', foreground: 'F97583' },\n { token: 'string', foreground: '9ECBFF' },\n { token: 'number', foreground: '79B8FF' },\n ],\n colors: {\n 'editor.background': '#0D1117',\n 'editor.foreground': '#C9D1D9',\n 'editor.lineHighlightBackground': '#161B22',\n 'editorLineNumber.foreground': '#8B949E',\n 'editorIndentGuide.background': '#21262D',\n 'editor.selectionBackground': '#3392FF44',\n },\n};\n\n// Main component\nconst AUTO_FORMAT_DELAY_MS = 100;\n\nexport const registerEditorThemes = (monaco: Monaco) => {\n monaco.editor.defineTheme('custom-light', customLightTheme);\n monaco.editor.defineTheme('custom-dark', customDarkTheme);\n};\n\n// Best-effort: a Monaco build without the TypeScript worker (as in jsdom) throws\n// here, and the editor is still usable without it.\nexport const configureTypeScriptDefaults = (monaco: Monaco) => {\n try {\n const tsLanguage = monaco.languages\n .getLanguages()\n .find((language) => language.id === 'typescript');\n\n if (!tsLanguage) return;\n\n monaco.languages.typescript.typescriptDefaults.setCompilerOptions({\n target: monaco.languages.typescript.ScriptTarget.ES2020,\n allowNonTsExtensions: true,\n moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,\n module: monaco.languages.typescript.ModuleKind.CommonJS,\n noEmit: true,\n esModuleInterop: true,\n jsx: monaco.languages.typescript.JsxEmit.React,\n reactNamespace: 'React',\n allowJs: true,\n typeRoots: ['node_modules/@types'],\n });\n\n monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({\n noSemanticValidation: false,\n noSyntaxValidation: false,\n noSuggestionDiagnostics: true,\n });\n } catch {\n // Silently handle any TypeScript configuration errors in test environments\n }\n};\n\nexport const scheduleAutoFormat = (mountedEditor: editor.IStandaloneCodeEditor, enabled: boolean) => {\n if (!enabled) return;\n\n window.setTimeout(() => {\n mountedEditor.getAction('editor.action.formatDocument')?.run();\n }, AUTO_FORMAT_DELAY_MS);\n};\n\nexport const registerSaveShortcut = (\n mountedEditor: editor.IStandaloneCodeEditor,\n monaco: Monaco,\n onSave?: (value: string) => void,\n) => {\n mountedEditor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {\n onSave?.(mountedEditor.getValue());\n });\n};\n\n// 'auto' follows the MUI palette; otherwise the caller's choice wins.\nexport const resolveEditorTheme = (themeProp: string, paletteMode: string) => {\n const wantsDark = themeProp === 'auto' ? paletteMode === 'dark' : themeProp === 'dark';\n\n return wantsDark ? 'custom-dark' : 'custom-light';\n};\n\n// Monaco's options object. Only the first five entries vary with our props; the\n// rest are fixed editor preferences.\n","import CodeIcon from '@mui/icons-material/Code';\nimport CopyIcon from '@mui/icons-material/ContentCopy';\nimport ExitFullscreenIcon from '@mui/icons-material/FullscreenExit';\nimport FullscreenIcon from '@mui/icons-material/Fullscreen';\nimport WrapIcon from '@mui/icons-material/WrapText';\nimport { Box, IconButton, Stack, Tooltip, Typography } from '@mui/material';\nimport { alpha, styled } from '@mui/material';\nimport React from 'react';\n\nimport type { CodeEditorCopy } from '../../../copy';\n\n// Each button repeated the same conditional test id; this is that ternary once.\nconst makeTestId =\n (dataTestId?: string) =>\n (suffix: string): string =>\n dataTestId ? `${dataTestId}-${suffix}` : `code-editor-${suffix}`;\n\nconst Toolbar = styled(Box)(({ theme }) => ({\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: theme.spacing(1, 2),\n borderBottom: `1px solid ${alpha(theme.palette.divider, 0.12)}`,\n background: alpha(theme.palette.background.default, 0.4),\n}));\n\nconst LanguageBadge = styled(Box)(({ theme }) => ({\n display: 'inline-flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n padding: theme.spacing(0.5, 1),\n borderRadius: theme.shape.borderRadius,\n background: alpha(theme.palette.primary.main, 0.1),\n color: theme.palette.primary.main,\n fontSize: '0.75rem',\n fontWeight: 600,\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n}));\n\nconst EditorActions: React.FC<{\n copy: CodeEditorCopy;\n readOnly: boolean;\n isWrapped: boolean;\n isCopied: boolean;\n isFullscreen: boolean;\n dataTestId?: string;\n onFormat: () => void;\n onCopy: () => void;\n onWrapToggle: () => void;\n onFullscreenToggle: () => void;\n}> = ({\n copy,\n readOnly,\n isWrapped,\n isCopied,\n isFullscreen,\n dataTestId,\n onFormat,\n onCopy,\n onWrapToggle,\n onFullscreenToggle,\n}) => {\n const testId = makeTestId(dataTestId);\n\n return (\n <Stack direction=\"row\" spacing={1}>\n {!readOnly && (\n <Tooltip title={copy.formatCode}>\n <IconButton\n size=\"small\"\n onClick={onFormat}\n data-testid={testId('format-btn')}\n >\n <CodeIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n\n <Tooltip title={isWrapped ? copy.disableWrap : copy.enableWrap}>\n <IconButton\n size=\"small\"\n onClick={onWrapToggle}\n color={isWrapped ? 'primary' : 'default'}\n data-testid={testId('wrap-btn')}\n >\n <WrapIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n\n <Tooltip title={isCopied ? copy.copied : copy.copyToClipboard}>\n <IconButton\n size=\"small\"\n onClick={onCopy}\n color={isCopied ? 'success' : 'default'}\n data-testid={testId('copy-btn')}\n >\n <CopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n\n <Tooltip title={isFullscreen ? copy.exitFullscreen : copy.enterFullscreen}>\n <IconButton\n size=\"small\"\n onClick={onFullscreenToggle}\n data-testid={testId('fullscreen-btn')}\n >\n {isFullscreen ? (\n <ExitFullscreenIcon fontSize=\"small\" />\n ) : (\n <FullscreenIcon fontSize=\"small\" />\n )}\n </IconButton>\n </Tooltip>\n </Stack>\n );\n};\n\n// Language badge, read-only marker and the four action buttons.\nexport const EditorToolbar: React.FC<{\n copy: CodeEditorCopy;\n language: string;\n readOnly: boolean;\n isWrapped: boolean;\n isCopied: boolean;\n isFullscreen: boolean;\n dataTestId?: string;\n onFormat: () => void;\n onCopy: () => void;\n onWrapToggle: () => void;\n onFullscreenToggle: () => void;\n}> = ({\n copy,\n language,\n readOnly,\n isWrapped,\n isCopied,\n isFullscreen,\n dataTestId,\n onFormat,\n onCopy,\n onWrapToggle,\n onFullscreenToggle,\n}) => {\n const testId = makeTestId(dataTestId);\n\n return (\n <Toolbar data-testid={testId('toolbar')}>\n <Stack direction=\"row\" spacing={2} alignItems=\"center\">\n <LanguageBadge data-testid={testId('language-badge')}>\n <CodeIcon sx={{ fontSize: 14 }} />\n {language}\n </LanguageBadge>\n {readOnly && (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {copy.readOnly}\n </Typography>\n )}\n </Stack>\n\n <EditorActions\n copy={copy}\n readOnly={readOnly}\n isWrapped={isWrapped}\n isCopied={isCopied}\n isFullscreen={isFullscreen}\n dataTestId={dataTestId}\n onFormat={onFormat}\n onCopy={onCopy}\n onWrapToggle={onWrapToggle}\n onFullscreenToggle={onFullscreenToggle}\n />\n </Toolbar>\n );\n};\n"],"mappings":"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","names":["alpha","Box","styled","Typography","makeTestId","jsx","jsxs","styled","alpha","Box","Typography"]}
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
Calendar,
|
|
3
3
|
addDays,
|
|
4
4
|
startOfWeek
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-KXARS46L.js";
|
|
6
6
|
import {
|
|
7
7
|
DayBoundInput,
|
|
8
8
|
isoToBr
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-TSG5C7MP.js";
|
|
10
10
|
import "../chunk-PZ5AY32C.js";
|
|
11
11
|
|
|
12
12
|
// src/components/form/DateRangePicker/DateRangePicker.tsx
|
|
@@ -111,7 +111,9 @@ function defaultMessages() {
|
|
|
111
111
|
incomplete: "Choose both dates.",
|
|
112
112
|
reversed: "The end date must be on or after the start date.",
|
|
113
113
|
overMax: ({ maxRangeDays }) => `Choose a range of at most ${maxRangeDays} days.`,
|
|
114
|
-
summary: ({ from, to }) => `${isoToBr(from)} \u2013 ${isoToBr(to)}
|
|
114
|
+
summary: ({ from, to }) => `${isoToBr(from)} \u2013 ${isoToBr(to)}`,
|
|
115
|
+
calendarLabel: "Calendar",
|
|
116
|
+
dayMask: "dd/mm/yyyy"
|
|
115
117
|
};
|
|
116
118
|
}
|
|
117
119
|
function statusMessage(status, messages, maxRangeDays) {
|
|
@@ -260,6 +262,7 @@ function DateRangeFields({
|
|
|
260
262
|
/* @__PURE__ */ jsx(
|
|
261
263
|
DayBoundInput,
|
|
262
264
|
{
|
|
265
|
+
mask: messages.dayMask,
|
|
263
266
|
label: messages.from,
|
|
264
267
|
value: value.from ?? void 0,
|
|
265
268
|
onChange: (bound) => onEdit("from", bound ?? null),
|
|
@@ -271,6 +274,7 @@ function DateRangeFields({
|
|
|
271
274
|
/* @__PURE__ */ jsx(
|
|
272
275
|
DayBoundInput,
|
|
273
276
|
{
|
|
277
|
+
mask: messages.dayMask,
|
|
274
278
|
label: messages.to,
|
|
275
279
|
value: value.to ?? void 0,
|
|
276
280
|
onChange: (bound) => onEdit("to", bound ?? null),
|
|
@@ -460,6 +464,7 @@ function useMonthCount(requested) {
|
|
|
460
464
|
return narrow ? 1 : requested;
|
|
461
465
|
}
|
|
462
466
|
function RangeCalendar({
|
|
467
|
+
calendarLabel,
|
|
463
468
|
picker,
|
|
464
469
|
value,
|
|
465
470
|
locale,
|
|
@@ -470,6 +475,7 @@ function RangeCalendar({
|
|
|
470
475
|
return /* @__PURE__ */ jsx3(
|
|
471
476
|
Calendar,
|
|
472
477
|
{
|
|
478
|
+
ariaLabel: calendarLabel,
|
|
473
479
|
className: CALENDAR_CLASS,
|
|
474
480
|
selectionMode: "range",
|
|
475
481
|
locale,
|
|
@@ -531,6 +537,7 @@ function DateRangePicker({
|
|
|
531
537
|
/* @__PURE__ */ jsx3(
|
|
532
538
|
RangeCalendar,
|
|
533
539
|
{
|
|
540
|
+
calendarLabel: picker.copy.calendarLabel,
|
|
534
541
|
picker,
|
|
535
542
|
value,
|
|
536
543
|
locale,
|