@12-apps/ui 6.7.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-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/DataGrid.js +1 -1
- package/dist/data-display/DataViews.js +88 -65
- 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/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 +159 -8
- package/dist/pt-BR.js.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 +27 -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-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/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 +12 -165
- package/dist/types/copy.d.ts.map +1 -1
- package/dist/types/pt-BR.d.ts +15 -22
- 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/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 +27 -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-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/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 +12 -173
- 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 -307
- package/src/pt-BR.utility.ts +21 -0
- package/src/user-avatar/user-avatar.tsx +8 -2
- 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/data-display/TimingDiagram/TimingDiagram.tsx","../../src/components/data-display/TimingDiagram/TimingDiagram.views.tsx"],"sourcesContent":["import { alpha, Box, Paper, styled, Typography } from '@mui/material';\nimport type { FC } from 'react';\nimport React, { useMemo } from 'react';\n\nimport type { TimingData, TimingDiagramProps } from './TimingDiagram.types';\nimport type { Phase, PhaseKey, TimingViewProps } from './TimingDiagram.views';\nimport {\n HorizontalView,\n phaseColors,\n StackedView,\n WaterfallView,\n} from './TimingDiagram.views';\n\n// Styled components\nconst DiagramContainer = styled(Paper)(({ theme }) => ({\n padding: theme.spacing(3),\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.9)} 0%, ${alpha(theme.palette.background.paper, 0.8)} 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}));\n\nconst Legend = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(2),\n marginTop: theme.spacing(2),\n paddingTop: theme.spacing(2),\n borderTop: `1px solid ${alpha(theme.palette.divider, 0.2)}`,\n}));\n\nconst LegendItem = styled(Box)(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n '& .color': {\n width: 12,\n height: 12,\n borderRadius: 2,\n },\n '& .label': {\n fontSize: '0.8rem',\n color: theme.palette.text.secondary,\n },\n}));\n\n// Helper functions\nconst calculatePercentages = (data: TimingData): Record<string, number> => {\n const total = data.total || 1;\n return {\n dns: ((data.dns || 0) / total) * 100,\n connect: ((data.connect || 0) / total) * 100,\n ssl: ((data.ssl || 0) / total) * 100,\n request: ((data.request || 0) / total) * 100,\n response: ((data.response || 0) / total) * 100,\n };\n};\n\n// A phase with no recorded time never happened — an HTTP request has no SSL\n// handshake, for instance — so it gets no bar and no legend entry.\nconst phasesOf = (data: TimingData): Phase[] =>\n [\n { key: 'dns', label: 'DNS Lookup', value: data.dns },\n { key: 'connect', label: 'Connection', value: data.connect },\n { key: 'ssl', label: 'SSL/TLS', value: data.ssl },\n { key: 'request', label: 'Request', value: data.request },\n { key: 'response', label: 'Response', value: data.response },\n ].filter((phase) => phase.value !== undefined && phase.value > 0);\n\nconst VIEWS: Record<string, FC<TimingViewProps>> = {\n waterfall: WaterfallView,\n stacked: StackedView,\n horizontal: HorizontalView,\n};\n\n// Main component\nexport const TimingDiagram: FC<TimingDiagramProps> = ({\n data,\n showLabels = true,\n height = 40,\n animated = true,\n showTooltips = true,\n variant = 'waterfall',\n}) => {\n const percentages = useMemo(() => calculatePercentages(data), [data]);\n const phases = phasesOf(data);\n const View = VIEWS[variant];\n\n return (\n <DiagramContainer elevation={2} role=\"region\" aria-label=\"Timing diagram\" tabIndex={0}>\n <Typography variant=\"h6\" fontWeight=\"bold\" gutterBottom>\n Request Timing\n </Typography>\n\n {View && (\n <View\n phases={phases}\n percentages={percentages}\n data={data}\n animated={animated}\n showLabels={showLabels}\n showTooltips={showTooltips}\n height={height}\n />\n )}\n\n {showLabels && (\n <Legend>\n {phases.map((phase) => (\n <LegendItem key={phase.key}>\n <Box\n className=\"color\"\n sx={{ backgroundColor: phaseColors[phase.key as PhaseKey] }}\n />\n <Typography className=\"label\">{phase.label}</Typography>\n </LegendItem>\n ))}\n </Legend>\n )}\n </DiagramContainer>\n );\n};\n\n// Export default\nexport default TimingDiagram;\n","import { alpha, Box, styled, Tooltip, Typography, useTheme } from '@mui/material';\nimport type { FC, ReactElement } from 'react';\nimport React from 'react';\n\nimport type { TimingData } from './TimingDiagram.types';\n\n// Color configurations\nexport const phaseColors = {\n dns: '#9C27B0', // Purple\n connect: '#2196F3', // Blue\n ssl: '#00BCD4', // Cyan\n request: '#4CAF50', // Green\n response: '#FF9800', // Orange\n};\n\nexport type PhaseKey = keyof typeof phaseColors;\n\nexport interface Phase {\n key: string;\n label: string;\n value?: number;\n}\n\nexport interface TimingViewProps {\n phases: Phase[];\n percentages: Record<string, number>;\n data: TimingData;\n animated: boolean;\n showLabels: boolean;\n showTooltips: boolean;\n height: number;\n}\n\nexport const formatTime = (ms: number): string => {\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n};\n\nconst colorOf = (phase: Phase): string => phaseColors[phase.key as PhaseKey];\nconst widthOf = (percentages: Record<string, number>, phase: Phase): number =>\n percentages[phase.key] ?? 0;\n\n// Waterfall and stacked both offer the same hover explanation of a segment; only\n// whether tooltips are on at all varies.\nconst withTooltip = (\n phase: Phase,\n enabled: boolean,\n element: ReactElement,\n): ReactElement =>\n enabled ? (\n <Tooltip\n key={phase.key}\n title={`${phase.label}: ${formatTime(phase.value!)}`}\n placement=\"top\"\n role=\"tooltip\"\n aria-describedby={`tooltip-${phase.key}`}\n >\n {element}\n </Tooltip>\n ) : (\n element\n );\n\nconst WaterfallContainer = styled(Box)(({ theme }) => ({\n position: 'relative',\n width: '100%',\n marginTop: theme.spacing(2),\n}));\n\nconst WaterfallBar = styled(Box, {\n shouldForwardProp: (prop) =>\n !['phaseColor', 'offset', 'width', 'animated'].includes(prop as string),\n})<{\n phaseColor: string;\n offset: number;\n width: number;\n animated: boolean;\n}>(({ theme, phaseColor, offset, width, animated }) => ({\n position: 'absolute',\n height: 32,\n left: `${offset}%`,\n width: `${width}%`,\n background: `linear-gradient(90deg, ${phaseColor} 0%, ${alpha(phaseColor, 0.8)} 100%)`,\n borderRadius: theme.shape.borderRadius,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: theme.palette.getContrastText(phaseColor),\n fontSize: '0.75rem',\n fontWeight: 500,\n boxShadow: `0 2px 8px ${alpha(phaseColor, 0.3)}`,\n transition: animated ? 'all 0.5s ease' : 'none',\n animation: animated ? 'slideIn 0.5s ease' : 'none',\n '@keyframes slideIn': {\n from: {\n transform: 'translateX(-20px)',\n opacity: 0,\n },\n to: {\n transform: 'translateX(0)',\n opacity: 1,\n },\n },\n '&:hover': {\n transform: 'translateY(-2px)',\n boxShadow: `0 4px 12px ${alpha(phaseColor, 0.5)}`,\n zIndex: 10,\n },\n}));\n\nconst TimelineAxis = styled(Box)(({ theme }) => ({\n display: 'flex',\n justifyContent: 'space-between',\n marginTop: theme.spacing(1),\n paddingTop: theme.spacing(1),\n borderTop: `1px solid ${alpha(theme.palette.divider, 0.2)}`,\n}));\n\nconst TimeLabel = styled(Typography)(({ theme }) => ({\n fontSize: '0.7rem',\n color: theme.palette.text.secondary,\n fontWeight: 500,\n}));\n\nexport const WaterfallView: FC<TimingViewProps> = ({\n phases,\n percentages,\n data,\n animated,\n showLabels,\n showTooltips,\n height,\n}) => {\n // Each bar starts where the previous one ended, so the row reads as a timeline.\n let offset = 0;\n\n return (\n <WaterfallContainer style={{ height: height + 40 }} data-variant=\"waterfall\">\n {phases.map((phase, index) => {\n const width = widthOf(percentages, phase);\n const currentOffset = offset;\n offset += width;\n\n return withTooltip(\n phase,\n showTooltips,\n <WaterfallBar\n key={phase.key}\n data-testid={`timing-segment-${phase.key}`}\n phaseColor={colorOf(phase)}\n offset={currentOffset}\n width={width}\n animated={animated}\n data-animated={animated.toString()}\n style={{\n top: index * 8,\n width: `${width}%`,\n left: `${currentOffset}%`,\n }}\n >\n {showLabels && width > 10 && (\n <span data-testid=\"timing-label\">{formatTime(phase.value!)}</span>\n )}\n </WaterfallBar>,\n );\n })}\n <TimelineAxis style={{ marginTop: height }}>\n <TimeLabel>0ms</TimeLabel>\n <TimeLabel>{formatTime(data.total / 2)}</TimeLabel>\n <TimeLabel>{formatTime(data.total)}</TimeLabel>\n </TimelineAxis>\n </WaterfallContainer>\n );\n};\n\nconst StackedBar = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'animated',\n})<{ animated: boolean }>(({ theme, animated }) => ({\n display: 'flex',\n width: '100%',\n height: 40,\n borderRadius: theme.shape.borderRadius,\n overflow: 'hidden',\n boxShadow: theme.shadows[2],\n ...(animated && {\n '& > div': {\n animation: 'expandWidth 0.8s ease',\n },\n '@keyframes expandWidth': {\n from: { width: 0 },\n to: { width: '100%' },\n },\n }),\n}));\n\nconst StackedSegment = styled(Box, {\n shouldForwardProp: (prop) => !['phaseColor', 'width'].includes(prop as string),\n})<{ phaseColor: string; width: number }>(({ phaseColor, width }) => ({\n width: `${width}%`,\n background: `linear-gradient(135deg, ${phaseColor} 0%, ${alpha(phaseColor, 0.85)} 100%)`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#fff',\n fontSize: '0.7rem',\n fontWeight: 600,\n position: 'relative',\n transition: 'all 0.3s ease',\n '&:hover': {\n filter: 'brightness(1.1)',\n zIndex: 1,\n },\n}));\n\nexport const StackedView: FC<TimingViewProps> = ({\n phases,\n percentages,\n data,\n animated,\n showLabels,\n showTooltips,\n}) => (\n <Box data-variant=\"stacked\">\n <StackedBar animated={animated} data-animated={animated.toString()}>\n {phases.map((phase) => {\n const width = widthOf(percentages, phase);\n\n return withTooltip(\n phase,\n showTooltips,\n <StackedSegment\n key={phase.key}\n data-testid={`timing-segment-${phase.key}`}\n phaseColor={colorOf(phase)}\n width={width}\n style={{ width: `${width}%` }}\n >\n {showLabels && width > 10 && (\n <span data-testid=\"timing-label\">{formatTime(phase.value!)}</span>\n )}\n </StackedSegment>,\n );\n })}\n </StackedBar>\n <Box sx={{ display: 'flex', justifyContent: 'space-between', mt: 1 }}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n 0ms\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" fontWeight=\"bold\">\n Total: {formatTime(data.total)}\n </Typography>\n </Box>\n </Box>\n);\n\nconst HorizontalBar = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(1),\n marginTop: theme.spacing(2),\n}));\n\nconst HorizontalSegment = styled(Box, {\n shouldForwardProp: (prop) => !['phaseColor', 'width', 'animated'].includes(prop as string),\n})<{\n phaseColor: string;\n width: number;\n animated: boolean;\n}>(({ theme, phaseColor, animated }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n '& .label': {\n minWidth: 80,\n fontSize: '0.85rem',\n fontWeight: 500,\n color: theme.palette.text.secondary,\n },\n '& .bar': {\n flex: 1,\n height: 24,\n borderRadius: theme.shape.borderRadius,\n background: `linear-gradient(90deg, ${phaseColor} 0%, ${alpha(phaseColor, 0.7)} 100%)`,\n position: 'relative',\n overflow: 'hidden',\n boxShadow: `0 2px 6px ${alpha(phaseColor, 0.25)}`,\n ...(animated && {\n '&::after': {\n content: '\"\"',\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: `linear-gradient(90deg, transparent 0%, ${alpha('#fff', 0.3)} 50%, transparent 100%)`,\n animation: 'shimmer 2s infinite',\n },\n '@keyframes shimmer': {\n from: { transform: 'translateX(-100%)' },\n to: { transform: 'translateX(100%)' },\n },\n }),\n },\n '& .value': {\n minWidth: 60,\n textAlign: 'right',\n fontSize: '0.85rem',\n fontWeight: 600,\n color: phaseColor,\n },\n}));\n\nexport const HorizontalView: FC<TimingViewProps> = ({\n phases,\n percentages,\n data,\n animated,\n}) => {\n const theme = useTheme();\n\n return (\n <HorizontalBar data-variant=\"horizontal\">\n {phases.map((phase) => (\n <HorizontalSegment\n key={phase.key}\n data-testid={`timing-segment-${phase.key}`}\n phaseColor={colorOf(phase)}\n width={widthOf(percentages, phase)}\n animated={animated}\n data-animated={animated.toString()}\n >\n <Typography className=\"label\">{phase.label}</Typography>\n <Box className=\"bar\" style={{ width: `${percentages[phase.key]}%` }} />\n <Typography className=\"value\" data-testid=\"timing-label\">\n {formatTime(phase.value!)}\n </Typography>\n </HorizontalSegment>\n ))}\n <Box sx={{ mt: 2, pt: 2, borderTop: `1px solid ${alpha(theme.palette.divider, 0.2)}` }}>\n <Typography variant=\"body2\" fontWeight=\"bold\" color=\"primary\">\n Total Time: {formatTime(data.total)}\n </Typography>\n </Box>\n </HorizontalBar>\n );\n};\n"],"mappings":"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","names":["alpha","Box","styled","Typography","jsx","jsxs","styled","alpha","Box","Typography"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/data-display/TimingDiagram/TimingDiagram.tsx","../../src/components/data-display/TimingDiagram/TimingDiagram.views.tsx"],"sourcesContent":["import { alpha, Box, Paper, styled, Typography } from '@mui/material';\nimport type { FC } from 'react';\nimport React, { useMemo } from 'react';\n\nimport type { TimingData, TimingDiagramProps } from './TimingDiagram.types';\nimport type { Phase, PhaseKey, TimingViewProps } from './TimingDiagram.views';\nimport {\n HorizontalView,\n phaseColors,\n StackedView,\n WaterfallView,\n} from './TimingDiagram.views';\n\n// Styled components\nconst DiagramContainer = styled(Paper)(({ theme }) => ({\n padding: theme.spacing(3),\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.9)} 0%, ${alpha(theme.palette.background.paper, 0.8)} 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}));\n\nconst Legend = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(2),\n marginTop: theme.spacing(2),\n paddingTop: theme.spacing(2),\n borderTop: `1px solid ${alpha(theme.palette.divider, 0.2)}`,\n}));\n\nconst LegendItem = styled(Box)(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n '& .color': {\n width: 12,\n height: 12,\n borderRadius: 2,\n },\n '& .label': {\n fontSize: '0.8rem',\n color: theme.palette.text.secondary,\n },\n}));\n\n// Helper functions\nconst calculatePercentages = (data: TimingData): Record<string, number> => {\n const total = data.total || 1;\n return {\n dns: ((data.dns || 0) / total) * 100,\n connect: ((data.connect || 0) / total) * 100,\n ssl: ((data.ssl || 0) / total) * 100,\n request: ((data.request || 0) / total) * 100,\n response: ((data.response || 0) / total) * 100,\n };\n};\n\n// A phase with no recorded time never happened — an HTTP request has no SSL\n// handshake, for instance — so it gets no bar and no legend entry.\nconst phasesOf = (data: TimingData): Phase[] =>\n [\n { key: 'dns', label: 'DNS Lookup', value: data.dns },\n { key: 'connect', label: 'Connection', value: data.connect },\n { key: 'ssl', label: 'SSL/TLS', value: data.ssl },\n { key: 'request', label: 'Request', value: data.request },\n { key: 'response', label: 'Response', value: data.response },\n ].filter((phase) => phase.value !== undefined && phase.value > 0);\n\nconst VIEWS: Record<string, FC<TimingViewProps>> = {\n waterfall: WaterfallView,\n stacked: StackedView,\n horizontal: HorizontalView,\n};\n\n// Main component\nexport const TimingDiagram: FC<TimingDiagramProps> = ({\n copy,\n data,\n showLabels = true,\n height = 40,\n animated = true,\n showTooltips = true,\n variant = 'waterfall',\n}) => {\n const percentages = useMemo(() => calculatePercentages(data), [data]);\n const phases = phasesOf(data);\n const View = VIEWS[variant];\n\n return (\n <DiagramContainer elevation={2} role=\"region\" aria-label={copy.regionLabel} tabIndex={0}>\n <Typography variant=\"h6\" fontWeight=\"bold\" gutterBottom>\n {copy.heading}\n </Typography>\n\n {View && (\n <View\n phases={phases}\n percentages={percentages}\n data={data}\n animated={animated}\n showLabels={showLabels}\n showTooltips={showTooltips}\n height={height}\n />\n )}\n\n {showLabels && (\n <Legend>\n {phases.map((phase) => (\n <LegendItem key={phase.key}>\n <Box\n className=\"color\"\n sx={{ backgroundColor: phaseColors[phase.key as PhaseKey] }}\n />\n <Typography className=\"label\">{phase.label}</Typography>\n </LegendItem>\n ))}\n </Legend>\n )}\n </DiagramContainer>\n );\n};\n\n// Export default\nexport default TimingDiagram;\n","import { alpha, Box, styled, Tooltip, Typography, useTheme } from '@mui/material';\nimport type { FC, ReactElement } from 'react';\nimport React from 'react';\n\nimport type { TimingData } from './TimingDiagram.types';\n\n// Color configurations\nexport const phaseColors = {\n dns: '#9C27B0', // Purple\n connect: '#2196F3', // Blue\n ssl: '#00BCD4', // Cyan\n request: '#4CAF50', // Green\n response: '#FF9800', // Orange\n};\n\nexport type PhaseKey = keyof typeof phaseColors;\n\nexport interface Phase {\n key: string;\n label: string;\n value?: number;\n}\n\nexport interface TimingViewProps {\n phases: Phase[];\n percentages: Record<string, number>;\n data: TimingData;\n animated: boolean;\n showLabels: boolean;\n showTooltips: boolean;\n height: number;\n}\n\nexport const formatTime = (ms: number): string => {\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n};\n\nconst colorOf = (phase: Phase): string => phaseColors[phase.key as PhaseKey];\nconst widthOf = (percentages: Record<string, number>, phase: Phase): number =>\n percentages[phase.key] ?? 0;\n\n// Waterfall and stacked both offer the same hover explanation of a segment; only\n// whether tooltips are on at all varies.\nconst withTooltip = (\n phase: Phase,\n enabled: boolean,\n element: ReactElement,\n): ReactElement =>\n enabled ? (\n <Tooltip\n key={phase.key}\n title={`${phase.label}: ${formatTime(phase.value!)}`}\n placement=\"top\"\n role=\"tooltip\"\n aria-describedby={`tooltip-${phase.key}`}\n >\n {element}\n </Tooltip>\n ) : (\n element\n );\n\nconst WaterfallContainer = styled(Box)(({ theme }) => ({\n position: 'relative',\n width: '100%',\n marginTop: theme.spacing(2),\n}));\n\nconst WaterfallBar = styled(Box, {\n shouldForwardProp: (prop) =>\n !['phaseColor', 'offset', 'width', 'animated'].includes(prop as string),\n})<{\n phaseColor: string;\n offset: number;\n width: number;\n animated: boolean;\n}>(({ theme, phaseColor, offset, width, animated }) => ({\n position: 'absolute',\n height: 32,\n left: `${offset}%`,\n width: `${width}%`,\n background: `linear-gradient(90deg, ${phaseColor} 0%, ${alpha(phaseColor, 0.8)} 100%)`,\n borderRadius: theme.shape.borderRadius,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: theme.palette.getContrastText(phaseColor),\n fontSize: '0.75rem',\n fontWeight: 500,\n boxShadow: `0 2px 8px ${alpha(phaseColor, 0.3)}`,\n transition: animated ? 'all 0.5s ease' : 'none',\n animation: animated ? 'slideIn 0.5s ease' : 'none',\n '@keyframes slideIn': {\n from: {\n transform: 'translateX(-20px)',\n opacity: 0,\n },\n to: {\n transform: 'translateX(0)',\n opacity: 1,\n },\n },\n '&:hover': {\n transform: 'translateY(-2px)',\n boxShadow: `0 4px 12px ${alpha(phaseColor, 0.5)}`,\n zIndex: 10,\n },\n}));\n\nconst TimelineAxis = styled(Box)(({ theme }) => ({\n display: 'flex',\n justifyContent: 'space-between',\n marginTop: theme.spacing(1),\n paddingTop: theme.spacing(1),\n borderTop: `1px solid ${alpha(theme.palette.divider, 0.2)}`,\n}));\n\nconst TimeLabel = styled(Typography)(({ theme }) => ({\n fontSize: '0.7rem',\n color: theme.palette.text.secondary,\n fontWeight: 500,\n}));\n\nexport const WaterfallView: FC<TimingViewProps> = ({\n phases,\n percentages,\n data,\n animated,\n showLabels,\n showTooltips,\n height,\n}) => {\n // Each bar starts where the previous one ended, so the row reads as a timeline.\n let offset = 0;\n\n return (\n <WaterfallContainer style={{ height: height + 40 }} data-variant=\"waterfall\">\n {phases.map((phase, index) => {\n const width = widthOf(percentages, phase);\n const currentOffset = offset;\n offset += width;\n\n return withTooltip(\n phase,\n showTooltips,\n <WaterfallBar\n key={phase.key}\n data-testid={`timing-segment-${phase.key}`}\n phaseColor={colorOf(phase)}\n offset={currentOffset}\n width={width}\n animated={animated}\n data-animated={animated.toString()}\n style={{\n top: index * 8,\n width: `${width}%`,\n left: `${currentOffset}%`,\n }}\n >\n {showLabels && width > 10 && (\n <span data-testid=\"timing-label\">{formatTime(phase.value!)}</span>\n )}\n </WaterfallBar>,\n );\n })}\n <TimelineAxis style={{ marginTop: height }}>\n <TimeLabel>0ms</TimeLabel>\n <TimeLabel>{formatTime(data.total / 2)}</TimeLabel>\n <TimeLabel>{formatTime(data.total)}</TimeLabel>\n </TimelineAxis>\n </WaterfallContainer>\n );\n};\n\nconst StackedBar = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'animated',\n})<{ animated: boolean }>(({ theme, animated }) => ({\n display: 'flex',\n width: '100%',\n height: 40,\n borderRadius: theme.shape.borderRadius,\n overflow: 'hidden',\n boxShadow: theme.shadows[2],\n ...(animated && {\n '& > div': {\n animation: 'expandWidth 0.8s ease',\n },\n '@keyframes expandWidth': {\n from: { width: 0 },\n to: { width: '100%' },\n },\n }),\n}));\n\nconst StackedSegment = styled(Box, {\n shouldForwardProp: (prop) => !['phaseColor', 'width'].includes(prop as string),\n})<{ phaseColor: string; width: number }>(({ phaseColor, width }) => ({\n width: `${width}%`,\n background: `linear-gradient(135deg, ${phaseColor} 0%, ${alpha(phaseColor, 0.85)} 100%)`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#fff',\n fontSize: '0.7rem',\n fontWeight: 600,\n position: 'relative',\n transition: 'all 0.3s ease',\n '&:hover': {\n filter: 'brightness(1.1)',\n zIndex: 1,\n },\n}));\n\nexport const StackedView: FC<TimingViewProps> = ({\n phases,\n percentages,\n data,\n animated,\n showLabels,\n showTooltips,\n}) => (\n <Box data-variant=\"stacked\">\n <StackedBar animated={animated} data-animated={animated.toString()}>\n {phases.map((phase) => {\n const width = widthOf(percentages, phase);\n\n return withTooltip(\n phase,\n showTooltips,\n <StackedSegment\n key={phase.key}\n data-testid={`timing-segment-${phase.key}`}\n phaseColor={colorOf(phase)}\n width={width}\n style={{ width: `${width}%` }}\n >\n {showLabels && width > 10 && (\n <span data-testid=\"timing-label\">{formatTime(phase.value!)}</span>\n )}\n </StackedSegment>,\n );\n })}\n </StackedBar>\n <Box sx={{ display: 'flex', justifyContent: 'space-between', mt: 1 }}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n 0ms\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" fontWeight=\"bold\">\n Total: {formatTime(data.total)}\n </Typography>\n </Box>\n </Box>\n);\n\nconst HorizontalBar = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(1),\n marginTop: theme.spacing(2),\n}));\n\nconst HorizontalSegment = styled(Box, {\n shouldForwardProp: (prop) => !['phaseColor', 'width', 'animated'].includes(prop as string),\n})<{\n phaseColor: string;\n width: number;\n animated: boolean;\n}>(({ theme, phaseColor, animated }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n '& .label': {\n minWidth: 80,\n fontSize: '0.85rem',\n fontWeight: 500,\n color: theme.palette.text.secondary,\n },\n '& .bar': {\n flex: 1,\n height: 24,\n borderRadius: theme.shape.borderRadius,\n background: `linear-gradient(90deg, ${phaseColor} 0%, ${alpha(phaseColor, 0.7)} 100%)`,\n position: 'relative',\n overflow: 'hidden',\n boxShadow: `0 2px 6px ${alpha(phaseColor, 0.25)}`,\n ...(animated && {\n '&::after': {\n content: '\"\"',\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: `linear-gradient(90deg, transparent 0%, ${alpha('#fff', 0.3)} 50%, transparent 100%)`,\n animation: 'shimmer 2s infinite',\n },\n '@keyframes shimmer': {\n from: { transform: 'translateX(-100%)' },\n to: { transform: 'translateX(100%)' },\n },\n }),\n },\n '& .value': {\n minWidth: 60,\n textAlign: 'right',\n fontSize: '0.85rem',\n fontWeight: 600,\n color: phaseColor,\n },\n}));\n\nexport const HorizontalView: FC<TimingViewProps> = ({\n phases,\n percentages,\n data,\n animated,\n}) => {\n const theme = useTheme();\n\n return (\n <HorizontalBar data-variant=\"horizontal\">\n {phases.map((phase) => (\n <HorizontalSegment\n key={phase.key}\n data-testid={`timing-segment-${phase.key}`}\n phaseColor={colorOf(phase)}\n width={widthOf(percentages, phase)}\n animated={animated}\n data-animated={animated.toString()}\n >\n <Typography className=\"label\">{phase.label}</Typography>\n <Box className=\"bar\" style={{ width: `${percentages[phase.key]}%` }} />\n <Typography className=\"value\" data-testid=\"timing-label\">\n {formatTime(phase.value!)}\n </Typography>\n </HorizontalSegment>\n ))}\n <Box sx={{ mt: 2, pt: 2, borderTop: `1px solid ${alpha(theme.palette.divider, 0.2)}` }}>\n <Typography variant=\"body2\" fontWeight=\"bold\" color=\"primary\">\n Total Time: {formatTime(data.total)}\n </Typography>\n </Box>\n </HorizontalBar>\n );\n};\n"],"mappings":"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","names":["alpha","Box","styled","Typography","jsx","jsxs","styled","alpha","Box","Typography"]}
|
package/dist/feedback/Sonner.js
CHANGED
|
@@ -118,6 +118,7 @@ var SonnerToast = ({
|
|
|
118
118
|
type = "default",
|
|
119
119
|
variant = "default",
|
|
120
120
|
closable = true,
|
|
121
|
+
dismissLabel,
|
|
121
122
|
action,
|
|
122
123
|
cancel,
|
|
123
124
|
icon,
|
|
@@ -163,7 +164,7 @@ var SonnerToast = ({
|
|
|
163
164
|
{
|
|
164
165
|
size: "small",
|
|
165
166
|
onClick: handleDismiss,
|
|
166
|
-
"aria-label":
|
|
167
|
+
"aria-label": dismissLabel,
|
|
167
168
|
sx: {
|
|
168
169
|
ml: "auto",
|
|
169
170
|
color: "text.secondary",
|
|
@@ -209,7 +210,7 @@ var trackPromiseWithToasts = async (promiseToResolve, options, toasts) => {
|
|
|
209
210
|
throw err;
|
|
210
211
|
}
|
|
211
212
|
};
|
|
212
|
-
var SonnerProvider = ({ children }) => {
|
|
213
|
+
var SonnerProvider = ({ children, dismissLabel }) => {
|
|
213
214
|
const [toasts, setToasts] = useState([]);
|
|
214
215
|
const toastCounter = useRef(0);
|
|
215
216
|
const dismiss = useCallback((id) => {
|
|
@@ -231,7 +232,7 @@ var SonnerProvider = ({ children }) => {
|
|
|
231
232
|
[dismiss]
|
|
232
233
|
);
|
|
233
234
|
const makeShortcut = useCallback(
|
|
234
|
-
(type, extra) => (message, options) => addToast({ ...options, ...extra, title: message }, type),
|
|
235
|
+
(type, extra) => (message, options) => addToast({ dismissLabel, ...options, ...extra, title: message }, type),
|
|
235
236
|
[addToast]
|
|
236
237
|
);
|
|
237
238
|
const toast2 = useMemo(() => makeShortcut("default"), [makeShortcut]);
|
|
@@ -389,7 +390,7 @@ var createToastInstance = () => {
|
|
|
389
390
|
return methods;
|
|
390
391
|
};
|
|
391
392
|
var toast = createToastInstance();
|
|
392
|
-
var Toaster = ({ children }) => /* @__PURE__ */ jsx2(SonnerProvider, { children });
|
|
393
|
+
var Toaster = ({ children, dismissLabel }) => /* @__PURE__ */ jsx2(SonnerProvider, { dismissLabel, children });
|
|
393
394
|
export {
|
|
394
395
|
SonnerProvider,
|
|
395
396
|
Toaster,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/feedback/Sonner/Sonner.tsx","../../src/components/feedback/Sonner/SonnerToast.tsx"],"sourcesContent":["import {\n Box,\n Portal } from '@mui/material';\nimport React, { createContext, useCallback, useContext, useRef,useState, useMemo } from 'react';\n\nimport type { SonnerContextType, SonnerItem,SonnerProps } from './Sonner.types';\n\nconst SonnerContext = createContext<SonnerContextType | null>(null);\n\nconst DEFAULT_DURATION_MS = 4000;\n\nconst buildToastItem = (\n toast: Omit<SonnerProps, 'id'>,\n id: string,\n type?: SonnerProps['type'],\n): SonnerItem => ({\n ...toast,\n id,\n type: type || toast.type || 'default',\n createdAt: Date.now(),\n visible: true });\n\n// Persistent toasts and `duration: 0` stay until dismissed explicitly.\nconst scheduleAutoDismiss = (\n toast: Omit<SonnerProps, 'id'>,\n id: string,\n dismiss: (id?: string) => void,\n) => {\n if (toast.persistent || toast.duration === 0) return;\n\n window.setTimeout(() => dismiss(id), toast.duration ?? DEFAULT_DURATION_MS);\n};\n\nconst EXIT_TRANSITION_MS = 300;\n\ntype SonnerPromiseOptions<T> = {\n loading: React.ReactNode;\n success: React.ReactNode | ((data: T) => React.ReactNode);\n error: React.ReactNode | ((error: Error) => React.ReactNode);\n};\n\nconst resolveMessage = <T,>(\n message: React.ReactNode | ((value: T) => React.ReactNode),\n value: T,\n): React.ReactNode => (typeof message === 'function' ? message(value) : message);\n\n// Shows a pinned loading toast for the life of a promise, then swaps it for a\n// success or error one. Takes the shortcuts it needs rather than reaching for\n// context, so it is testable on its own.\nconst trackPromiseWithToasts = async <T,>(\n promiseToResolve: Promise<T>,\n options: SonnerPromiseOptions<T>,\n toasts: {\n loading: (message: React.ReactNode) => string;\n success: (message: React.ReactNode) => string;\n error: (message: React.ReactNode) => string;\n dismiss: (id?: string) => void;\n },\n): Promise<T> => {\n const toastId = toasts.loading(options.loading);\n\n try {\n const data = await promiseToResolve;\n toasts.dismiss(toastId);\n toasts.success(resolveMessage(options.success, data));\n return data;\n } catch (err) {\n toasts.dismiss(toastId);\n toasts.error(resolveMessage(options.error, err instanceof Error ? err : new Error(String(err))));\n throw err;\n }\n};\n\nexport const SonnerProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const [toasts, setToasts] = useState<SonnerItem[]>([]);\n const toastCounter = useRef(0);\n\n // Hide first, then drop after the exit transition. Passing no id targets every\n // toast; the two branches only differ in which toasts they match, so that is\n // the only thing that varies here.\n const dismiss = useCallback((id?: string) => {\n const matches = (toast: SonnerItem) => id === undefined || toast.id === id;\n\n setToasts((prev) =>\n prev.map((toast) => (matches(toast) ? { ...toast, visible: false } : toast)),\n );\n\n window.setTimeout(() => {\n setToasts((prev) => prev.filter((toast) => !matches(toast)));\n }, EXIT_TRANSITION_MS);\n }, []);\n\n const addToast = useCallback(\n (toast: Omit<SonnerProps, 'id'>, type?: SonnerProps['type']): string => {\n const id = `sonner-${++toastCounter.current}`;\n setToasts((prev) => [...prev, buildToastItem(toast, id, type)]);\n scheduleAutoDismiss(toast, id, dismiss);\n return id;\n },\n [dismiss],\n );\n\n // The six shortcuts differ only by the type they tag and, for loading, by\n // pinning persistent. Built from one factory rather than six near-identical\n // useCallback blocks.\n const makeShortcut = useCallback(\n (type: SonnerProps['type'], extra?: Partial<SonnerProps>) =>\n (message: React.ReactNode, options?: Partial<SonnerProps>) =>\n addToast({ ...options, ...extra, title: message }, type),\n [addToast],\n );\n\n const toast = useMemo(() => makeShortcut('default'), [makeShortcut]);\n const success = useMemo(() => makeShortcut('success'), [makeShortcut]);\n const error = useMemo(() => makeShortcut('error'), [makeShortcut]);\n const warning = useMemo(() => makeShortcut('warning'), [makeShortcut]);\n const info = useMemo(() => makeShortcut('info'), [makeShortcut]);\n const loading = useMemo(\n () => makeShortcut('loading', { persistent: true }),\n [makeShortcut],\n );\n\n const promise = useCallback(\n <T,>(promiseToResolve: Promise<T>, options: SonnerPromiseOptions<T>): Promise<T> =>\n trackPromiseWithToasts(promiseToResolve, options, { loading, success, error, dismiss }),\n [loading, success, error, dismiss],\n );\n\n const contextValue: SonnerContextType = {\n toast,\n success,\n error,\n warning,\n info,\n loading,\n dismiss,\n promise };\n\n // Register this context globally for imperative API\n useRegisterGlobalToast(contextValue);\n\n return (\n <SonnerContext.Provider value={contextValue}>\n {children}\n <SonnerToaster toasts={toasts} onDismiss={dismiss} />\n </SonnerContext.Provider>\n );\n};\n\nexport const useSonner = (): SonnerContextType => {\n const context = useContext(SonnerContext);\n if (!context) {\n throw new Error('useSonner must be used within a SonnerProvider');\n }\n return context;\n};\n\n// A caller-supplied icon always wins; otherwise the type picks one.\nimport { SonnerToast } from './SonnerToast';\n\nconst SonnerToaster: React.FC<{\n toasts: SonnerItem[];\n onDismiss: (id: string) => void;\n}> = ({ toasts, onDismiss }) => {\n // Limit visible toasts to prevent overflow\n const MAX_VISIBLE_TOASTS = 5;\n const visibleToasts = toasts.slice(-MAX_VISIBLE_TOASTS);\n const hiddenCount = Math.max(0, toasts.length - MAX_VISIBLE_TOASTS);\n\n return (\n <Portal>\n <Box\n sx={{\n position: 'fixed',\n top: 16,\n right: 16,\n zIndex: 9999,\n display: 'flex',\n flexDirection: 'column',\n pointerEvents: 'none',\n maxHeight: 'calc(100vh - 32px)',\n overflowY: 'auto',\n overflowX: 'hidden' }}\n >\n {hiddenCount > 0 && (\n <Box\n sx={{\n p: 1,\n mb: 0.5,\n textAlign: 'center',\n fontSize: '0.75rem',\n color: 'text.secondary',\n pointerEvents: 'none' }}\n >\n +{hiddenCount} more\n </Box>\n )}\n {visibleToasts.map((toast) => (\n <Box key={toast.id} sx={{ pointerEvents: 'auto' }}>\n <SonnerToast {...toast} onDismiss={onDismiss} />\n </Box>\n ))}\n </Box>\n </Portal>\n );\n};\n\n// Global toast instance for imperative API\nlet globalToastContext: SonnerContextType | null = null;\n\n// Hook to register the global context (used internally by SonnerProvider)\nexport const useRegisterGlobalToast = (context: SonnerContextType) => {\n React.useEffect(() => {\n globalToastContext = context;\n return () => {\n globalToastContext = null;\n };\n }, [context]);\n};\n\n// Create a production-ready toast instance for imperative usage\nconst createToastInstance = (): SonnerContextType => {\n const warnNoProvider = () => {\n // Use a more React-appropriate warning mechanism\n if (typeof window !== 'undefined' && window.console && window.console.warn) {\n window.console.warn('Sonner: No SonnerProvider found. Please wrap your app with SonnerProvider.');\n }\n };\n\n const methods: SonnerContextType = {\n toast: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.toast(message, options);\n },\n success: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.success(message, options);\n },\n error: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.error(message, options);\n },\n warning: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.warning(message, options);\n },\n info: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.info(message, options);\n },\n loading: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.loading(message, options);\n },\n dismiss: (id?: string) => {\n if (!globalToastContext) {\n warnNoProvider();\n return;\n }\n globalToastContext.dismiss(id);\n },\n promise: async <T,>(\n promiseToResolve: Promise<T>,\n options: {\n loading: React.ReactNode;\n success: React.ReactNode | ((data: T) => React.ReactNode);\n error: React.ReactNode | ((error: Error) => React.ReactNode);\n },\n ): Promise<T> => {\n if (!globalToastContext) {\n warnNoProvider();\n throw new Error('No SonnerProvider found');\n }\n return globalToastContext.promise(promiseToResolve, options);\n } };\n\n return methods;\n};\n\n// Export toast instance for imperative API usage\nexport const toast = createToastInstance();\n\n// Export Toaster as alias for SonnerProvider for stories compatibility\nexport const Toaster: React.FC<{\n children?: React.ReactNode;\n position?: string;\n theme?: string;\n expand?: boolean;\n richColors?: boolean;\n closeButton?: boolean;\n}> = ({ children }) => <SonnerProvider>{children}</SonnerProvider>;\n","import SuccessIcon from '@mui/icons-material/CheckCircle';\nimport CloseIcon from '@mui/icons-material/Close';\nimport ErrorIcon from '@mui/icons-material/Error';\nimport InfoIcon from '@mui/icons-material/Info';\nimport WarningIcon from '@mui/icons-material/Warning';\nimport {\n alpha,\n Box,\n Button,\n CircularProgress,\n Collapse,\n IconButton,\n Typography,\n useTheme,\n} from '@mui/material';\nimport type { CSSObject, Theme } from '@mui/material';\nimport React from 'react';\n\nimport type { SonnerItem } from './Sonner.types';\nimport type { SonnerProps } from './Sonner.types';\n\nconst renderToastIcon = (icon: SonnerProps['icon'], type: SonnerProps['type']) => {\n if (icon) return icon;\n\n switch (type) {\n case 'success':\n return <SuccessIcon sx={{ fontSize: 20, color: 'success.main' }} />;\n case 'error':\n return <ErrorIcon sx={{ fontSize: 20, color: 'error.main' }} />;\n case 'warning':\n return <WarningIcon sx={{ fontSize: 20, color: 'warning.main' }} />;\n case 'info':\n return <InfoIcon sx={{ fontSize: 20, color: 'info.main' }} />;\n case 'loading':\n return <CircularProgress size={16} />;\n default:\n return null;\n }\n};\n\n// Errors and toasts flagged important interrupt the screen reader; the rest wait\n// for the next pause. Computed once instead of duplicating the same condition\n// across the role and aria-live attributes.\nconst resolveToastAnnouncement = (important: boolean, type: SonnerProps['type']) => {\n const interrupts = important || type === 'error';\n\n return {\n role: interrupts ? 'alert' : 'status',\n live: (interrupts ? 'assertive' : 'polite') as 'assertive' | 'polite',\n };\n};\n\nconst buildToastStyles = (\n theme: Theme,\n variant: SonnerProps['variant'],\n visible: boolean,\n): CSSObject => {\n const baseStyles: CSSObject = {\n borderRadius: theme.spacing(1.5),\n border: `1px solid ${theme.palette.divider}`,\n backgroundColor: theme.palette.background.paper,\n boxShadow: theme.shadows[4],\n transition: theme.transitions.create(['all', 'transform', 'opacity'], {\n duration: theme.transitions.duration.short,\n }),\n transform: visible ? 'scale(1)' : 'scale(0.95)',\n opacity: visible ? 1 : 0,\n };\n\n switch (variant) {\n case 'glass':\n return {\n ...baseStyles,\n backgroundColor: alpha(theme.palette.background.paper, 0.1),\n backdropFilter: 'blur(20px)',\n border: `1px solid ${alpha(theme.palette.primary.main, 0.2)}`,\n boxShadow: `0 8px 32px ${alpha(theme.palette.common.black, 0.1)}`,\n };\n\n case 'minimal':\n return {\n ...baseStyles,\n backgroundColor: theme.palette.background.default,\n border: 'none',\n boxShadow: 'none',\n borderLeft: `4px solid ${theme.palette.primary.main}`,\n borderRadius: 0,\n };\n\n default:\n return baseStyles;\n }\n};\n\n// Title, description and the optional action row. Split out so the toast shell\n// keeps only its own concerns — announcement, styling and dismissal.\nconst ToastContent: React.FC<{\n title?: SonnerProps['title'];\n description?: SonnerProps['description'];\n important: boolean;\n action?: SonnerProps['action'];\n cancel?: SonnerProps['cancel'];\n}> = ({ title, description, important, action, cancel }) => (\n <Box sx={{ flex: 1, minWidth: 0 }}>\n {title && (\n <Typography\n variant=\"body2\"\n sx={{\n fontWeight: important ? 600 : 500,\n color: 'text.primary',\n mb: description ? 0.5 : 0,\n }}\n >\n {title}\n </Typography>\n )}\n\n {description && (\n <Typography variant=\"body2\" sx={{ color: 'text.secondary', fontSize: '0.875rem' }}>\n {description}\n </Typography>\n )}\n\n {(action || cancel) && (\n <Box sx={{ display: 'flex', gap: 1, mt: 1.5 }}>\n {action && (\n <ToastActionButton action={action} buttonVariant=\"contained\" />\n )}\n {cancel && <ToastActionButton action={cancel} buttonVariant=\"outlined\" />}\n </Box>\n )}\n </Box>\n);\n\nconst ToastActionButton: React.FC<{\n action: NonNullable<SonnerProps['action']>;\n buttonVariant: 'contained' | 'outlined';\n}> = ({ action, buttonVariant }) => (\n <Button\n size=\"small\"\n onClick={action.onClick}\n variant={buttonVariant}\n sx={{ fontSize: '0.75rem', py: 0.5, px: 1.5 }}\n >\n {action.label}\n </Button>\n);\n\nexport const SonnerToast: React.FC<SonnerItem & { onDismiss: (id: string) => void }> = ({\n id,\n title,\n description,\n type = 'default',\n variant = 'default',\n closable = true,\n action,\n cancel,\n icon,\n important = false,\n visible,\n onDismiss,\n}) => {\n const theme = useTheme();\n const announcement = resolveToastAnnouncement(important, type);\n\n const handleDismiss = () => {\n onDismiss(id);\n };\n\n return (\n <Collapse in={visible} timeout={200}>\n <Box\n role={announcement.role}\n aria-live={announcement.live}\n aria-atomic=\"true\"\n sx={{\n ...buildToastStyles(theme, variant, visible),\n p: 2,\n mb: 1,\n minWidth: 356,\n maxWidth: 400,\n display: 'flex',\n alignItems: 'flex-start',\n gap: 1.5,\n }}\n >\n {renderToastIcon(icon, type)}\n\n <ToastContent\n title={title}\n description={description}\n important={important}\n action={action}\n cancel={cancel}\n />\n\n {closable && (\n <IconButton\n size=\"small\"\n onClick={handleDismiss}\n aria-label=\"Dismiss notification\"\n sx={{\n ml: 'auto',\n color: 'text.secondary',\n '&:hover': {\n backgroundColor: 'action.hover',\n },\n }}\n >\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Box>\n </Collapse>\n );\n};\n"],"mappings":"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","names":["Box","jsx","jsxs","toast","Box"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/feedback/Sonner/Sonner.tsx","../../src/components/feedback/Sonner/SonnerToast.tsx"],"sourcesContent":["import {\n Box,\n Portal } from '@mui/material';\nimport React, { createContext, useCallback, useContext, useRef,useState, useMemo } from 'react';\n\nimport type { SonnerContextType, SonnerItem,SonnerProps } from './Sonner.types';\n\nconst SonnerContext = createContext<SonnerContextType | null>(null);\n\nconst DEFAULT_DURATION_MS = 4000;\n\nconst buildToastItem = (\n toast: Omit<SonnerProps, 'id'>,\n id: string,\n type?: SonnerProps['type'],\n): SonnerItem => ({\n ...toast,\n id,\n type: type || toast.type || 'default',\n createdAt: Date.now(),\n visible: true });\n\n// Persistent toasts and `duration: 0` stay until dismissed explicitly.\nconst scheduleAutoDismiss = (\n toast: Omit<SonnerProps, 'id'>,\n id: string,\n dismiss: (id?: string) => void,\n) => {\n if (toast.persistent || toast.duration === 0) return;\n\n window.setTimeout(() => dismiss(id), toast.duration ?? DEFAULT_DURATION_MS);\n};\n\nconst EXIT_TRANSITION_MS = 300;\n\ntype SonnerPromiseOptions<T> = {\n loading: React.ReactNode;\n success: React.ReactNode | ((data: T) => React.ReactNode);\n error: React.ReactNode | ((error: Error) => React.ReactNode);\n};\n\nconst resolveMessage = <T,>(\n message: React.ReactNode | ((value: T) => React.ReactNode),\n value: T,\n): React.ReactNode => (typeof message === 'function' ? message(value) : message);\n\n// Shows a pinned loading toast for the life of a promise, then swaps it for a\n// success or error one. Takes the shortcuts it needs rather than reaching for\n// context, so it is testable on its own.\nconst trackPromiseWithToasts = async <T,>(\n promiseToResolve: Promise<T>,\n options: SonnerPromiseOptions<T>,\n toasts: {\n loading: (message: React.ReactNode) => string;\n success: (message: React.ReactNode) => string;\n error: (message: React.ReactNode) => string;\n dismiss: (id?: string) => void;\n },\n): Promise<T> => {\n const toastId = toasts.loading(options.loading);\n\n try {\n const data = await promiseToResolve;\n toasts.dismiss(toastId);\n toasts.success(resolveMessage(options.success, data));\n return data;\n } catch (err) {\n toasts.dismiss(toastId);\n toasts.error(resolveMessage(options.error, err instanceof Error ? err : new Error(String(err))));\n throw err;\n }\n};\n\nexport const SonnerProvider: React.FC<{\n children: React.ReactNode;\n /**\n * The dismiss button's accessible name, for every toast this provider\n * raises. REQUIRED and mounted ONCE — the shortcut helpers\n * (`sonner.success(…)`) take a message and nothing else by design, so the\n * word cannot be a per-call argument without changing what they are for.\n */\n dismissLabel: string;\n}> = ({ children, dismissLabel }) => {\n const [toasts, setToasts] = useState<SonnerItem[]>([]);\n const toastCounter = useRef(0);\n\n // Hide first, then drop after the exit transition. Passing no id targets every\n // toast; the two branches only differ in which toasts they match, so that is\n // the only thing that varies here.\n const dismiss = useCallback((id?: string) => {\n const matches = (toast: SonnerItem) => id === undefined || toast.id === id;\n\n setToasts((prev) =>\n prev.map((toast) => (matches(toast) ? { ...toast, visible: false } : toast)),\n );\n\n window.setTimeout(() => {\n setToasts((prev) => prev.filter((toast) => !matches(toast)));\n }, EXIT_TRANSITION_MS);\n }, []);\n\n const addToast = useCallback(\n (toast: Omit<SonnerProps, 'id'>, type?: SonnerProps['type']): string => {\n const id = `sonner-${++toastCounter.current}`;\n setToasts((prev) => [...prev, buildToastItem(toast, id, type)]);\n scheduleAutoDismiss(toast, id, dismiss);\n return id;\n },\n [dismiss],\n );\n\n // The six shortcuts differ only by the type they tag and, for loading, by\n // pinning persistent. Built from one factory rather than six near-identical\n // useCallback blocks.\n const makeShortcut = useCallback(\n (type: SonnerProps['type'], extra?: Partial<SonnerProps>) =>\n (message: React.ReactNode, options?: Partial<SonnerProps>) =>\n addToast({ dismissLabel, ...options, ...extra, title: message }, type),\n [addToast],\n );\n\n const toast = useMemo(() => makeShortcut('default'), [makeShortcut]);\n const success = useMemo(() => makeShortcut('success'), [makeShortcut]);\n const error = useMemo(() => makeShortcut('error'), [makeShortcut]);\n const warning = useMemo(() => makeShortcut('warning'), [makeShortcut]);\n const info = useMemo(() => makeShortcut('info'), [makeShortcut]);\n const loading = useMemo(\n () => makeShortcut('loading', { persistent: true }),\n [makeShortcut],\n );\n\n const promise = useCallback(\n <T,>(promiseToResolve: Promise<T>, options: SonnerPromiseOptions<T>): Promise<T> =>\n trackPromiseWithToasts(promiseToResolve, options, { loading, success, error, dismiss }),\n [loading, success, error, dismiss],\n );\n\n const contextValue: SonnerContextType = {\n toast,\n success,\n error,\n warning,\n info,\n loading,\n dismiss,\n promise };\n\n // Register this context globally for imperative API\n useRegisterGlobalToast(contextValue);\n\n return (\n <SonnerContext.Provider value={contextValue}>\n {children}\n <SonnerToaster toasts={toasts} onDismiss={dismiss} />\n </SonnerContext.Provider>\n );\n};\n\nexport const useSonner = (): SonnerContextType => {\n const context = useContext(SonnerContext);\n if (!context) {\n throw new Error('useSonner must be used within a SonnerProvider');\n }\n return context;\n};\n\n// A caller-supplied icon always wins; otherwise the type picks one.\nimport { SonnerToast } from './SonnerToast';\n\nconst SonnerToaster: React.FC<{\n toasts: SonnerItem[];\n onDismiss: (id: string) => void;\n}> = ({ toasts, onDismiss }) => {\n // Limit visible toasts to prevent overflow\n const MAX_VISIBLE_TOASTS = 5;\n const visibleToasts = toasts.slice(-MAX_VISIBLE_TOASTS);\n const hiddenCount = Math.max(0, toasts.length - MAX_VISIBLE_TOASTS);\n\n return (\n <Portal>\n <Box\n sx={{\n position: 'fixed',\n top: 16,\n right: 16,\n zIndex: 9999,\n display: 'flex',\n flexDirection: 'column',\n pointerEvents: 'none',\n maxHeight: 'calc(100vh - 32px)',\n overflowY: 'auto',\n overflowX: 'hidden' }}\n >\n {hiddenCount > 0 && (\n <Box\n sx={{\n p: 1,\n mb: 0.5,\n textAlign: 'center',\n fontSize: '0.75rem',\n color: 'text.secondary',\n pointerEvents: 'none' }}\n >\n +{hiddenCount} more\n </Box>\n )}\n {visibleToasts.map((toast) => (\n <Box key={toast.id} sx={{ pointerEvents: 'auto' }}>\n <SonnerToast {...toast} onDismiss={onDismiss} />\n </Box>\n ))}\n </Box>\n </Portal>\n );\n};\n\n// Global toast instance for imperative API\nlet globalToastContext: SonnerContextType | null = null;\n\n// Hook to register the global context (used internally by SonnerProvider)\nexport const useRegisterGlobalToast = (context: SonnerContextType) => {\n React.useEffect(() => {\n globalToastContext = context;\n return () => {\n globalToastContext = null;\n };\n }, [context]);\n};\n\n// Create a production-ready toast instance for imperative usage\nconst createToastInstance = (): SonnerContextType => {\n const warnNoProvider = () => {\n // Use a more React-appropriate warning mechanism\n if (typeof window !== 'undefined' && window.console && window.console.warn) {\n window.console.warn('Sonner: No SonnerProvider found. Please wrap your app with SonnerProvider.');\n }\n };\n\n const methods: SonnerContextType = {\n toast: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.toast(message, options);\n },\n success: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.success(message, options);\n },\n error: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.error(message, options);\n },\n warning: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.warning(message, options);\n },\n info: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.info(message, options);\n },\n loading: (message: React.ReactNode, options?: Partial<SonnerProps>) => {\n if (!globalToastContext) {\n warnNoProvider();\n return 'no-provider';\n }\n return globalToastContext.loading(message, options);\n },\n dismiss: (id?: string) => {\n if (!globalToastContext) {\n warnNoProvider();\n return;\n }\n globalToastContext.dismiss(id);\n },\n promise: async <T,>(\n promiseToResolve: Promise<T>,\n options: {\n loading: React.ReactNode;\n success: React.ReactNode | ((data: T) => React.ReactNode);\n error: React.ReactNode | ((error: Error) => React.ReactNode);\n },\n ): Promise<T> => {\n if (!globalToastContext) {\n warnNoProvider();\n throw new Error('No SonnerProvider found');\n }\n return globalToastContext.promise(promiseToResolve, options);\n } };\n\n return methods;\n};\n\n// Export toast instance for imperative API usage\nexport const toast = createToastInstance();\n\n// Export Toaster as alias for SonnerProvider for stories compatibility\nexport const Toaster: React.FC<{\n children?: React.ReactNode;\n position?: string;\n theme?: string;\n expand?: boolean;\n richColors?: boolean;\n closeButton?: boolean;\n dismissLabel: string;\n}> = ({ children, dismissLabel }) => (\n <SonnerProvider dismissLabel={dismissLabel}>{children}</SonnerProvider>\n);\n","import SuccessIcon from '@mui/icons-material/CheckCircle';\nimport CloseIcon from '@mui/icons-material/Close';\nimport ErrorIcon from '@mui/icons-material/Error';\nimport InfoIcon from '@mui/icons-material/Info';\nimport WarningIcon from '@mui/icons-material/Warning';\nimport {\n alpha,\n Box,\n Button,\n CircularProgress,\n Collapse,\n IconButton,\n Typography,\n useTheme,\n} from '@mui/material';\nimport type { CSSObject, Theme } from '@mui/material';\nimport React from 'react';\n\nimport type { SonnerItem } from './Sonner.types';\nimport type { SonnerProps } from './Sonner.types';\n\nconst renderToastIcon = (icon: SonnerProps['icon'], type: SonnerProps['type']) => {\n if (icon) return icon;\n\n switch (type) {\n case 'success':\n return <SuccessIcon sx={{ fontSize: 20, color: 'success.main' }} />;\n case 'error':\n return <ErrorIcon sx={{ fontSize: 20, color: 'error.main' }} />;\n case 'warning':\n return <WarningIcon sx={{ fontSize: 20, color: 'warning.main' }} />;\n case 'info':\n return <InfoIcon sx={{ fontSize: 20, color: 'info.main' }} />;\n case 'loading':\n return <CircularProgress size={16} />;\n default:\n return null;\n }\n};\n\n// Errors and toasts flagged important interrupt the screen reader; the rest wait\n// for the next pause. Computed once instead of duplicating the same condition\n// across the role and aria-live attributes.\nconst resolveToastAnnouncement = (important: boolean, type: SonnerProps['type']) => {\n const interrupts = important || type === 'error';\n\n return {\n role: interrupts ? 'alert' : 'status',\n live: (interrupts ? 'assertive' : 'polite') as 'assertive' | 'polite',\n };\n};\n\nconst buildToastStyles = (\n theme: Theme,\n variant: SonnerProps['variant'],\n visible: boolean,\n): CSSObject => {\n const baseStyles: CSSObject = {\n borderRadius: theme.spacing(1.5),\n border: `1px solid ${theme.palette.divider}`,\n backgroundColor: theme.palette.background.paper,\n boxShadow: theme.shadows[4],\n transition: theme.transitions.create(['all', 'transform', 'opacity'], {\n duration: theme.transitions.duration.short,\n }),\n transform: visible ? 'scale(1)' : 'scale(0.95)',\n opacity: visible ? 1 : 0,\n };\n\n switch (variant) {\n case 'glass':\n return {\n ...baseStyles,\n backgroundColor: alpha(theme.palette.background.paper, 0.1),\n backdropFilter: 'blur(20px)',\n border: `1px solid ${alpha(theme.palette.primary.main, 0.2)}`,\n boxShadow: `0 8px 32px ${alpha(theme.palette.common.black, 0.1)}`,\n };\n\n case 'minimal':\n return {\n ...baseStyles,\n backgroundColor: theme.palette.background.default,\n border: 'none',\n boxShadow: 'none',\n borderLeft: `4px solid ${theme.palette.primary.main}`,\n borderRadius: 0,\n };\n\n default:\n return baseStyles;\n }\n};\n\n// Title, description and the optional action row. Split out so the toast shell\n// keeps only its own concerns — announcement, styling and dismissal.\nconst ToastContent: React.FC<{\n title?: SonnerProps['title'];\n description?: SonnerProps['description'];\n important: boolean;\n action?: SonnerProps['action'];\n cancel?: SonnerProps['cancel'];\n}> = ({ title, description, important, action, cancel }) => (\n <Box sx={{ flex: 1, minWidth: 0 }}>\n {title && (\n <Typography\n variant=\"body2\"\n sx={{\n fontWeight: important ? 600 : 500,\n color: 'text.primary',\n mb: description ? 0.5 : 0,\n }}\n >\n {title}\n </Typography>\n )}\n\n {description && (\n <Typography variant=\"body2\" sx={{ color: 'text.secondary', fontSize: '0.875rem' }}>\n {description}\n </Typography>\n )}\n\n {(action || cancel) && (\n <Box sx={{ display: 'flex', gap: 1, mt: 1.5 }}>\n {action && (\n <ToastActionButton action={action} buttonVariant=\"contained\" />\n )}\n {cancel && <ToastActionButton action={cancel} buttonVariant=\"outlined\" />}\n </Box>\n )}\n </Box>\n);\n\nconst ToastActionButton: React.FC<{\n action: NonNullable<SonnerProps['action']>;\n buttonVariant: 'contained' | 'outlined';\n}> = ({ action, buttonVariant }) => (\n <Button\n size=\"small\"\n onClick={action.onClick}\n variant={buttonVariant}\n sx={{ fontSize: '0.75rem', py: 0.5, px: 1.5 }}\n >\n {action.label}\n </Button>\n);\n\nexport const SonnerToast: React.FC<SonnerItem & { onDismiss: (id: string) => void }> = ({\n id,\n title,\n description,\n type = 'default',\n variant = 'default',\n closable = true,\n dismissLabel,\n action,\n cancel,\n icon,\n important = false,\n visible,\n onDismiss,\n}) => {\n const theme = useTheme();\n const announcement = resolveToastAnnouncement(important, type);\n\n const handleDismiss = () => {\n onDismiss(id);\n };\n\n return (\n <Collapse in={visible} timeout={200}>\n <Box\n role={announcement.role}\n aria-live={announcement.live}\n aria-atomic=\"true\"\n sx={{\n ...buildToastStyles(theme, variant, visible),\n p: 2,\n mb: 1,\n minWidth: 356,\n maxWidth: 400,\n display: 'flex',\n alignItems: 'flex-start',\n gap: 1.5,\n }}\n >\n {renderToastIcon(icon, type)}\n\n <ToastContent\n title={title}\n description={description}\n important={important}\n action={action}\n cancel={cancel}\n />\n\n {closable && (\n <IconButton\n size=\"small\"\n onClick={handleDismiss}\n aria-label={dismissLabel}\n sx={{\n ml: 'auto',\n color: 'text.secondary',\n '&:hover': {\n backgroundColor: 'action.hover',\n },\n }}\n >\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Box>\n </Collapse>\n );\n};\n"],"mappings":"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","names":["Box","jsx","jsxs","toast","Box"]}
|
|
@@ -222,6 +222,7 @@ var StepDot = styled(Box, {
|
|
|
222
222
|
}
|
|
223
223
|
}));
|
|
224
224
|
var TutorialStepNav = ({
|
|
225
|
+
copy,
|
|
225
226
|
currentStep,
|
|
226
227
|
stepCount,
|
|
227
228
|
isLastStep,
|
|
@@ -240,14 +241,14 @@ var TutorialStepNav = ({
|
|
|
240
241
|
"data-testid": "tutorial-navigation",
|
|
241
242
|
children: [
|
|
242
243
|
/* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, children: [
|
|
243
|
-
allowSkip && /* @__PURE__ */ jsx(Button, { size: "small", onClick: onSkip, variant: "text", children:
|
|
244
|
+
allowSkip && /* @__PURE__ */ jsx(Button, { size: "small", onClick: onSkip, variant: "text", children: copy.skip }),
|
|
244
245
|
stepCount > 1 && /* @__PURE__ */ jsx(
|
|
245
246
|
IconButton,
|
|
246
247
|
{
|
|
247
248
|
size: "small",
|
|
248
249
|
onClick: onRestart,
|
|
249
250
|
disabled: currentStep === 0,
|
|
250
|
-
title:
|
|
251
|
+
title: copy.restart,
|
|
251
252
|
children: /* @__PURE__ */ jsx(RestartIcon, { fontSize: "small" })
|
|
252
253
|
}
|
|
253
254
|
)
|
|
@@ -261,7 +262,7 @@ var TutorialStepNav = ({
|
|
|
261
262
|
onClick: onPrev,
|
|
262
263
|
disabled: currentStep === 0,
|
|
263
264
|
"data-testid": "tutorial-prev-button",
|
|
264
|
-
children:
|
|
265
|
+
children: copy.previous
|
|
265
266
|
}
|
|
266
267
|
),
|
|
267
268
|
!isLastStep ? /* @__PURE__ */ jsx(
|
|
@@ -274,7 +275,7 @@ var TutorialStepNav = ({
|
|
|
274
275
|
disabled: requiresActionBeforeNext,
|
|
275
276
|
title: requiresActionBeforeNext ? "Complete the required action first" : "",
|
|
276
277
|
"data-testid": "tutorial-next-button",
|
|
277
|
-
children:
|
|
278
|
+
children: copy.next
|
|
278
279
|
}
|
|
279
280
|
) : /* @__PURE__ */ jsx(
|
|
280
281
|
Button,
|
|
@@ -336,6 +337,7 @@ var TutorialStepHeader = ({ title, currentStep, allowSkip, onSkip }) => /* @__PU
|
|
|
336
337
|
}
|
|
337
338
|
);
|
|
338
339
|
var TutorialStepBody = ({
|
|
340
|
+
copy,
|
|
339
341
|
step,
|
|
340
342
|
currentStep,
|
|
341
343
|
stepCount,
|
|
@@ -390,6 +392,7 @@ var TutorialStepBody = ({
|
|
|
390
392
|
/* @__PURE__ */ jsx(
|
|
391
393
|
TutorialStepNav,
|
|
392
394
|
{
|
|
395
|
+
copy,
|
|
393
396
|
currentStep,
|
|
394
397
|
stepCount,
|
|
395
398
|
isLastStep,
|
|
@@ -560,7 +563,15 @@ var TutorialLayers = ({ variant, targetBounds, isVisible, spotlightPadding }) =>
|
|
|
560
563
|
)
|
|
561
564
|
] });
|
|
562
565
|
};
|
|
563
|
-
var TutorialTooltip = ({
|
|
566
|
+
var TutorialTooltip = ({
|
|
567
|
+
tutorial,
|
|
568
|
+
steps,
|
|
569
|
+
allowSkip,
|
|
570
|
+
showProgress,
|
|
571
|
+
animated,
|
|
572
|
+
requiresActionBeforeNext,
|
|
573
|
+
copy
|
|
574
|
+
}) => /* @__PURE__ */ jsx2(Fade, { in: tutorial.isVisible, timeout: 300, children: /* @__PURE__ */ jsx2(
|
|
564
575
|
TooltipContainer,
|
|
565
576
|
{
|
|
566
577
|
ref: tutorial.tooltipRef,
|
|
@@ -578,6 +589,7 @@ var TutorialTooltip = ({ tutorial, steps, allowSkip, showProgress, animated, req
|
|
|
578
589
|
children: /* @__PURE__ */ jsx2(
|
|
579
590
|
TutorialStepBody,
|
|
580
591
|
{
|
|
592
|
+
copy,
|
|
581
593
|
step: tutorial.currentStepData,
|
|
582
594
|
currentStep: tutorial.currentStep,
|
|
583
595
|
stepCount: steps.length,
|
|
@@ -596,6 +608,7 @@ var TutorialTooltip = ({ tutorial, steps, allowSkip, showProgress, animated, req
|
|
|
596
608
|
) });
|
|
597
609
|
var TutorialOverlay = (componentProps) => {
|
|
598
610
|
const {
|
|
611
|
+
copy,
|
|
599
612
|
steps,
|
|
600
613
|
onComplete,
|
|
601
614
|
onSkip,
|
|
@@ -636,6 +649,7 @@ var TutorialOverlay = (componentProps) => {
|
|
|
636
649
|
/* @__PURE__ */ jsx2(
|
|
637
650
|
TutorialTooltip,
|
|
638
651
|
{
|
|
652
|
+
copy,
|
|
639
653
|
tutorial: { ...tutorial, currentStepData },
|
|
640
654
|
steps,
|
|
641
655
|
allowSkip,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/feedback/TutorialOverlay/TutorialOverlay.tsx","../../src/components/feedback/TutorialOverlay/TutorialOverlay.hooks.ts","../../src/components/feedback/TutorialOverlay/TutorialOverlay.geometry.ts","../../src/components/feedback/TutorialOverlay/TutorialStepBody.tsx"],"sourcesContent":["import {\n alpha,\n Box,\n Fade,\n keyframes,\n LinearProgress,\n Paper,\n Portal,\n styled } from '@mui/material';\nimport type { FC} from 'react';\nimport React, { } from 'react';\n\nimport { useTutorialOverlay } from './TutorialOverlay.hooks';\nimport { TutorialStepBody } from './TutorialStepBody';\nimport type { TutorialOverlayProps } from './TutorialOverlay.types';\n\n// Animation keyframes\nconst pulseAnimation = keyframes`\n 0% {\n box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);\n }\n 70% {\n box-shadow: 0 0 0 20px rgba(255, 255, 255, 0);\n }\n 100% {\n box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);\n }\n`;\n\nconst floatAnimation = keyframes`\n 0%, 100% {\n transform: translateY(0);\n }\n 50% {\n transform: translateY(-10px);\n }\n`;\n\n// Styled components\nconst Overlay = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'allowClickThrough' })<{ allowClickThrough?: boolean }>(({ theme, allowClickThrough }) => ({\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: theme.zIndex.modal + 100,\n pointerEvents: allowClickThrough ? 'none' : 'auto',\n transition: 'opacity 0.3s ease' }));\n\nconst Backdrop = styled(Box)(() => ({\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: alpha('#000', 0.7),\n backdropFilter: 'blur(2px)' }));\n\nconst Spotlight = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'bounds' && prop !== 'padding' })<{ bounds: globalThis.DOMRect; padding: number }>(({ bounds, padding }) => ({\n position: 'absolute',\n top: bounds.top - padding,\n left: bounds.left - padding,\n width: bounds.width + padding * 2,\n height: bounds.height + padding * 2,\n borderRadius: 8,\n border: '2px solid rgba(255, 255, 255, 0.5)',\n animation: `${pulseAnimation} 2s infinite`,\n pointerEvents: 'none',\n '&::before': {\n content: '\"\"',\n position: 'absolute',\n inset: -2,\n borderRadius: 8,\n background: 'transparent',\n boxShadow: '0 0 0 9999px rgba(0, 0, 0, 0.7)' } }));\n\nconst TooltipContainer = styled(Paper, {\n shouldForwardProp: (prop) => prop !== 'placement' })<{ placement: string }>(({ theme, placement }) => ({\n position: 'absolute',\n maxWidth: 360,\n padding: theme.spacing(3),\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.98)} 0%, ${alpha(theme.palette.background.paper, 0.95)} 100%)`,\n backdropFilter: 'blur(20px)',\n WebkitBackdropFilter: 'blur(20px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n boxShadow: theme.shadows[12],\n animation: `${floatAnimation} 3s ease-in-out infinite`,\n pointerEvents: 'auto',\n zIndex: theme.zIndex.modal + 101,\n '&::before': {\n content: '\"\"',\n position: 'absolute',\n width: 12,\n height: 12,\n background: 'inherit',\n transform: 'rotate(45deg)',\n border: 'inherit',\n ...(placement === 'top' && {\n bottom: -7,\n left: '50%',\n marginLeft: -6,\n borderTop: 'none',\n borderLeft: 'none' }),\n ...(placement === 'bottom' && {\n top: -7,\n left: '50%',\n marginLeft: -6,\n borderBottom: 'none',\n borderRight: 'none' }),\n ...(placement === 'left' && {\n right: -7,\n top: '50%',\n marginTop: -6,\n borderLeft: 'none',\n borderBottom: 'none' }),\n ...(placement === 'right' && {\n left: -7,\n top: '50%',\n marginTop: -6,\n borderRight: 'none',\n borderTop: 'none' }) } }));\n\nconst ProgressBar = styled(LinearProgress)(({ theme }) => ({\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n height: 4,\n zIndex: theme.zIndex.modal + 102,\n '& .MuiLinearProgress-bar': {\n background: `linear-gradient(90deg, ${theme.palette.primary.main} 0%, ${theme.palette.primary.light} 100%)` } }));\n\ntype TutorialDefaultedKeys =\n | 'initialStep'\n | 'active'\n | 'showProgress'\n | 'allowKeyboardNavigation'\n | 'allowClickThrough'\n | 'variant'\n | 'allowSkip'\n | 'animated';\n\ntype ResolvedTutorialProps = TutorialOverlayProps &\n Required<Pick<TutorialOverlayProps, TutorialDefaultedKeys>>;\n\nconst TUTORIAL_DEFAULTS: Pick<TutorialOverlayProps, TutorialDefaultedKeys> = {\n initialStep: 0,\n active: true,\n showProgress: true,\n allowKeyboardNavigation: true,\n allowClickThrough: false,\n variant: 'tooltip',\n allowSkip: false,\n animated: true };\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 eight\n// branches into the component's own complexity budget.\nconst resolveProps = (props: TutorialOverlayProps): ResolvedTutorialProps =>\n ({\n ...TUTORIAL_DEFAULTS,\n ...(Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<TutorialOverlayProps>) }) as ResolvedTutorialProps;\n\n// The dimming layer and the cut-out over the highlighted element. Local because\n// Backdrop and Spotlight cannot cross a module boundary (TS2742).\nconst TutorialLayers: React.FC<{\n variant: string;\n targetBounds: globalThis.DOMRect | null;\n isVisible: boolean;\n spotlightPadding?: number;\n}> = ({ variant, targetBounds, isVisible, spotlightPadding }) => {\n const isSpotlight = variant === 'spotlight' || variant === 'highlight';\n const dimmed = variant === 'modal' || isSpotlight;\n\n return (\n <>\n {dimmed && <Backdrop />}\n {targetBounds && isVisible && isSpotlight && (\n <Spotlight\n bounds={targetBounds}\n padding={spotlightPadding || 8}\n data-testid=\"tutorial-highlight\"\n />\n )}\n </>\n );\n};\n\n// The positioned card. Local because TooltipContainer cannot cross a module\n// boundary (TS2742).\nconst TutorialTooltip: React.FC<{\n tutorial: ReturnType<typeof useTutorialOverlay> & {\n currentStepData: TutorialOverlayProps['steps'][number];\n };\n steps: TutorialOverlayProps['steps'];\n allowSkip: boolean;\n showProgress: boolean;\n animated: boolean;\n requiresActionBeforeNext: boolean;\n}> = ({ tutorial, steps, allowSkip, showProgress, animated, requiresActionBeforeNext }) => (\n <Fade in={tutorial.isVisible} timeout={300}>\n <TooltipContainer\n ref={tutorial.tooltipRef}\n placement={tutorial.actualPlacement}\n elevation={12}\n style={{\n top: tutorial.tooltipPosition.top,\n left: tutorial.tooltipPosition.left,\n animation: animated ? undefined : 'none' }}\n role=\"dialog\"\n aria-labelledby={`tutorial-title-${tutorial.currentStep}`}\n aria-describedby={`tutorial-content-${tutorial.currentStep}`}\n data-testid={`tutorial-step-${tutorial.currentStep}`}\n >\n <TutorialStepBody\n step={tutorial.currentStepData}\n currentStep={tutorial.currentStep}\n stepCount={steps.length}\n progress={tutorial.progress}\n isLastStep={tutorial.isLastStep}\n allowSkip={allowSkip}\n showProgress={showProgress}\n requiresActionBeforeNext={requiresActionBeforeNext}\n onNext={tutorial.handleNext}\n onPrev={tutorial.handlePrev}\n onSkip={tutorial.handleSkip}\n onRestart={tutorial.handleRestart}\n />\n </TooltipContainer>\n </Fade>\n);\n\nexport const TutorialOverlay: FC<TutorialOverlayProps> = (componentProps) => {\n const {\n steps,\n onComplete,\n onSkip,\n onStepComplete,\n initialStep,\n active,\n showProgress,\n allowKeyboardNavigation,\n allowClickThrough,\n variant,\n allowSkip,\n animated } = resolveProps(componentProps);\n\n const tutorial = useTutorialOverlay({\n steps,\n initialStep,\n active,\n allowKeyboardNavigation,\n onComplete,\n onSkip,\n onStepComplete });\n const { currentStepData, isLastStep, isVisible, targetBounds, progress } = tutorial;\n\n const requiresActionBeforeNext = Boolean(currentStepData?.requiresAction) && !isLastStep;\n\n if (!active || !currentStepData) return null;\n\n // Handle empty steps array\n if (steps.length === 0) return null;\n\n return (\n <Portal>\n <Overlay allowClickThrough={allowClickThrough} data-testid=\"tutorial-overlay\">\n {showProgress && <ProgressBar variant=\"determinate\" value={progress} />}\n\n <TutorialLayers\n variant={variant}\n targetBounds={targetBounds}\n isVisible={isVisible}\n spotlightPadding={currentStepData.spotlightPadding}\n />\n\n <TutorialTooltip\n tutorial={{ ...tutorial, currentStepData }}\n steps={steps}\n allowSkip={allowSkip}\n showProgress={showProgress}\n animated={animated}\n requiresActionBeforeNext={requiresActionBeforeNext}\n />\n </Overlay>\n </Portal>\n );\n};\n\n// Export default\nexport default TutorialOverlay;\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { calculateTooltipPosition, getElementBounds } from './TutorialOverlay.geometry';\nimport type { TutorialOverlayProps } from './TutorialOverlay.types';\n\n// Tracks the highlighted element's box, re-measuring on resize and scroll. Scroll\n// is captured (third argument true) so it fires for any scrolling ancestor, not\n// just the window.\nconst useTargetBounds = ({\n active,\n target,\n}: {\n active: boolean;\n target?: string;\n}) => {\n const [targetBounds, setTargetBounds] = useState<globalThis.DOMRect | null>(null);\n const [isVisible, setIsVisible] = useState(false);\n\n useEffect(() => {\n if (!active || !target) return;\n\n const updateBounds = () => {\n const bounds = getElementBounds(target);\n setTargetBounds(bounds);\n setIsVisible(Boolean(bounds));\n };\n\n updateBounds();\n\n window.addEventListener('resize', updateBounds);\n window.addEventListener('scroll', updateBounds, true);\n\n return () => {\n window.removeEventListener('resize', updateBounds);\n window.removeEventListener('scroll', updateBounds, true);\n };\n }, [active, target]);\n\n return { targetBounds, isVisible };\n};\n\n// Places the tooltip against the measured target once both boxes are known.\nconst useTooltipPlacement = ({\n targetBounds,\n isVisible,\n preferredPosition,\n}: {\n targetBounds: globalThis.DOMRect | null;\n isVisible: boolean;\n preferredPosition?: string;\n}) => {\n const tooltipRef = useRef<HTMLDivElement>(null);\n const [tooltipPosition, setTooltipPosition] = useState({ top: 0, left: 0 });\n const [actualPlacement, setActualPlacement] = useState<string>('bottom');\n\n useEffect(() => {\n if (!targetBounds || !tooltipRef.current || !isVisible) return;\n\n const { position, placement } = calculateTooltipPosition(\n targetBounds,\n tooltipRef.current.getBoundingClientRect(),\n preferredPosition || 'auto',\n );\n\n setTooltipPosition(position);\n setActualPlacement(placement);\n }, [targetBounds, isVisible, preferredPosition]);\n\n return { tooltipRef, tooltipPosition, actualPlacement };\n};\n\n// Arrow keys step through the tour, Escape skips it.\nconst useTutorialKeyboard = ({\n enabled,\n onNext,\n onPrev,\n onSkip,\n}: {\n enabled: boolean;\n onNext: () => void;\n onPrev: () => void;\n onSkip: () => void;\n}) => {\n useEffect(() => {\n if (!enabled) return;\n\n const handleKeyPress = (e: globalThis.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowLeft':\n onPrev();\n break;\n case 'ArrowRight':\n onNext();\n break;\n case 'Escape':\n onSkip();\n break;\n }\n };\n\n window.addEventListener('keydown', handleKeyPress);\n return () => window.removeEventListener('keydown', handleKeyPress);\n }, [enabled, onNext, onPrev, onSkip]);\n};\n\nexport const useTutorialOverlay = ({\n steps,\n initialStep,\n active,\n allowKeyboardNavigation,\n onComplete,\n onSkip,\n onStepComplete,\n}: {\n steps: TutorialOverlayProps['steps'];\n initialStep: number;\n active: boolean;\n allowKeyboardNavigation: boolean;\n onComplete?: () => void;\n onSkip?: () => void;\n onStepComplete?: (stepId: string) => void;\n}) => {\n const [currentStep, setCurrentStep] = useState(initialStep);\n\n const currentStepData = steps[currentStep];\n const isLastStep = currentStep === steps.length - 1;\n\n const { targetBounds, isVisible } = useTargetBounds({\n active,\n target: currentStepData?.target,\n });\n\n const { tooltipRef, tooltipPosition, actualPlacement } = useTooltipPlacement({\n targetBounds,\n isVisible,\n preferredPosition: currentStepData?.position,\n });\n\n const handleNext = useCallback(() => {\n const currentStepId = steps[currentStep]?.id;\n if (currentStepId) onStepComplete?.(currentStepId);\n\n if (currentStep < steps.length - 1) {\n setCurrentStep(currentStep + 1);\n return;\n }\n\n onComplete?.();\n }, [currentStep, steps, onComplete, onStepComplete]);\n\n const handlePrev = useCallback(() => {\n setCurrentStep((step) => Math.max(step - 1, 0));\n }, []);\n\n const handleSkip = useCallback(() => {\n onSkip?.();\n }, [onSkip]);\n\n const handleRestart = useCallback(() => {\n setCurrentStep(0);\n }, []);\n\n useTutorialKeyboard({\n enabled: allowKeyboardNavigation && active,\n onNext: handleNext,\n onPrev: handlePrev,\n onSkip: handleSkip,\n });\n\n return {\n currentStep,\n currentStepData,\n isLastStep,\n isVisible,\n targetBounds,\n tooltipRef,\n tooltipPosition,\n actualPlacement,\n progress: ((currentStep + 1) / steps.length) * 100,\n handleNext,\n handlePrev,\n handleSkip,\n handleRestart,\n };\n};\n","const DEFAULT_PADDING = 16;\n\nexport const getElementBounds = (selector: string): globalThis.DOMRect | null =>\n document.querySelector(selector)?.getBoundingClientRect() ?? null;\n\n// With placement 'auto', the side with the most free space around the target\n// wins.\nconst pickPlacement = (targetBounds: globalThis.DOMRect): string => {\n const spaces = {\n top: targetBounds.top,\n bottom: window.innerHeight - targetBounds.bottom,\n left: targetBounds.left,\n right: window.innerWidth - targetBounds.right,\n };\n\n return Object.entries(spaces).reduce((a, b) => (b[1] > a[1] ? b : a))[0];\n};\n\nconst offsetFor = (\n placement: string,\n targetBounds: globalThis.DOMRect,\n tooltipBounds: globalThis.DOMRect,\n padding: number,\n): { top: number; left: number } => {\n const centredLeft = targetBounds.left + targetBounds.width / 2 - tooltipBounds.width / 2;\n const centredTop = targetBounds.top + targetBounds.height / 2 - tooltipBounds.height / 2;\n\n switch (placement) {\n case 'top':\n return { top: targetBounds.top - tooltipBounds.height - padding, left: centredLeft };\n case 'bottom':\n return { top: targetBounds.bottom + padding, left: centredLeft };\n case 'left':\n return { top: centredTop, left: targetBounds.left - tooltipBounds.width - padding };\n case 'right':\n return { top: centredTop, left: targetBounds.right + padding };\n default:\n return { top: 0, left: 0 };\n }\n};\n\n// Keeps the tooltip fully on screen, whatever the chosen side works out to.\nconst clampToViewport = (\n position: { top: number; left: number },\n tooltipBounds: globalThis.DOMRect,\n padding: number,\n) => ({\n top: Math.max(padding, Math.min(position.top, window.innerHeight - tooltipBounds.height - padding)),\n left: Math.max(padding, Math.min(position.left, window.innerWidth - tooltipBounds.width - padding)),\n});\n\nexport const calculateTooltipPosition = (\n targetBounds: globalThis.DOMRect,\n tooltipBounds: globalThis.DOMRect,\n placement: string,\n padding = DEFAULT_PADDING,\n) => {\n const finalPlacement = placement === 'auto' ? pickPlacement(targetBounds) : placement;\n const offset = offsetFor(finalPlacement, targetBounds, tooltipBounds, padding);\n\n return {\n position: clampToViewport(offset, tooltipBounds, padding),\n placement: finalPlacement,\n };\n};\n","import CompleteIcon from '@mui/icons-material/CheckCircle';\nimport CloseIcon from '@mui/icons-material/Close';\nimport PrevIcon from '@mui/icons-material/NavigateBefore';\nimport NextIcon from '@mui/icons-material/NavigateNext';\nimport RestartIcon from '@mui/icons-material/Refresh';\nimport {\n alpha,\n Box,\n Button,\n IconButton,\n Stack,\n styled,\n Typography } from '@mui/material';\nimport React, { } from 'react';\n\nimport type { TutorialOverlayProps } from './TutorialOverlay.types';\n\n// Animation keyframes\n\nconst StepIndicator = styled(Box)(({ theme }) => ({\n display: 'flex',\n gap: theme.spacing(1),\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(2) }));\n\n\nconst StepDot = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'active' && prop !== 'completed' })<{ active?: boolean; completed?: boolean }>(({ theme, active, completed }) => ({\n width: 8,\n height: 8,\n borderRadius: '50%',\n background: completed\n ? theme.palette.success.main\n : active\n ? theme.palette.primary.main\n : alpha(theme.palette.text.primary, 0.3),\n transition: 'all 0.3s ease',\n ...(active && {\n transform: 'scale(1.5)' }) }));\n\n// Title, body copy, the step dots and the navigation row.\n\n// The step's controls: skip/restart on the left, previous/next on the right.\nconst TutorialStepNav: React.FC<{\n currentStep: number;\n stepCount: number;\n isLastStep: boolean;\n allowSkip: boolean;\n requiresActionBeforeNext?: boolean;\n onNext: () => void;\n onPrev: () => void;\n onSkip: () => void;\n onRestart: () => void;\n}> = ({\n currentStep,\n stepCount,\n isLastStep,\n allowSkip,\n requiresActionBeforeNext,\n onNext,\n onPrev,\n onSkip,\n onRestart }) => (\n <Stack\n direction=\"row\"\n spacing={1}\n justifyContent=\"space-between\"\n data-testid=\"tutorial-navigation\"\n >\n <Stack direction=\"row\" spacing={1}>\n {allowSkip && (\n <Button size=\"small\" onClick={onSkip} variant=\"text\">\n Skip\n </Button>\n )}\n {stepCount > 1 && (\n <IconButton\n size=\"small\"\n onClick={onRestart}\n disabled={currentStep === 0}\n title=\"Restart\"\n >\n <RestartIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Stack>\n\n <Stack direction=\"row\" spacing={1}>\n {stepCount > 1 && currentStep > 0 && (\n <Button\n size=\"small\"\n startIcon={<PrevIcon />}\n onClick={onPrev}\n disabled={currentStep === 0}\n data-testid=\"tutorial-prev-button\"\n >\n Previous\n </Button>\n )}\n\n {!isLastStep ? (\n <Button\n variant=\"contained\"\n size=\"small\"\n endIcon={<NextIcon />}\n onClick={onNext}\n disabled={requiresActionBeforeNext}\n title={requiresActionBeforeNext ? 'Complete the required action first' : ''}\n data-testid=\"tutorial-next-button\"\n >\n Next\n </Button>\n ) : (\n <Button\n variant=\"contained\"\n size=\"small\"\n endIcon={<CompleteIcon />}\n onClick={onNext}\n sx={{\n background: 'linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%)' }}\n data-testid=\"tutorial-finish-button\"\n >\n {stepCount === 1 ? 'Complete' : 'Finish'}\n </Button>\n )}\n </Stack>\n </Stack>\n);\n\nconst StepDots: React.FC<{ currentStep: number; stepCount: number }> = ({\n currentStep,\n stepCount }) => (\n <StepIndicator data-testid=\"tutorial-step-indicators\">\n {Array.from({ length: stepCount }).map((_, index) => (\n <StepDot\n key={index}\n active={index === currentStep}\n completed={index < currentStep}\n data-testid={`tutorial-indicator-${index}`}\n />\n ))}\n </StepIndicator>\n);\n\n// Title, and the close button when skipping is allowed.\nconst TutorialStepHeader: React.FC<{\n title: React.ReactNode;\n currentStep: number;\n allowSkip: boolean;\n onSkip: () => void;\n}> = ({ title, currentStep, allowSkip, onSkip }) => (\n <Box\n sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}\n >\n <Typography\n id={`tutorial-title-${currentStep}`}\n variant=\"h6\"\n fontWeight=\"bold\"\n sx={{ flex: 1 }}\n data-testid=\"tutorial-step-title\"\n >\n {title}\n </Typography>\n {allowSkip && (\n <IconButton\n size=\"small\"\n onClick={onSkip}\n sx={{ ml: 1, mt: -1, mr: -1 }}\n data-testid=\"tutorial-close-button\"\n >\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Box>\n);\n\nexport const TutorialStepBody: React.FC<{\n step: TutorialOverlayProps['steps'][number];\n currentStep: number;\n stepCount: number;\n progress: number;\n isLastStep: boolean;\n allowSkip: boolean;\n showProgress: boolean;\n requiresActionBeforeNext?: boolean;\n onNext: () => void;\n onPrev: () => void;\n onSkip: () => void;\n onRestart: () => void;\n}> = ({\n step,\n currentStep,\n stepCount,\n progress: _progress,\n isLastStep,\n allowSkip,\n showProgress,\n requiresActionBeforeNext,\n onNext,\n onPrev,\n onSkip,\n onRestart }) => (\n <Stack spacing={2}>\n <TutorialStepHeader\n title={step.title}\n currentStep={currentStep}\n allowSkip={allowSkip}\n onSkip={onSkip}\n />\n\n <Typography\n id={`tutorial-content-${currentStep}`}\n variant=\"body2\"\n color=\"text.secondary\"\n data-testid=\"tutorial-step-content\"\n >\n {step.content}\n </Typography>\n\n {showProgress && (\n <Typography variant=\"caption\" color=\"text.secondary\" align=\"center\">\n {currentStep + 1} of {stepCount}\n </Typography>\n )}\n\n {step.action && (\n <Button\n variant=\"contained\"\n size=\"small\"\n onClick={step.action.onClick}\n sx={{\n background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',\n color: 'white' }}\n >\n {step.action.label}\n </Button>\n )}\n\n <StepDots currentStep={currentStep} stepCount={stepCount} />\n\n <TutorialStepNav\n currentStep={currentStep}\n stepCount={stepCount}\n isLastStep={isLastStep}\n allowSkip={allowSkip}\n requiresActionBeforeNext={requiresActionBeforeNext}\n onNext={onNext}\n onPrev={onPrev}\n onSkip={onSkip}\n onRestart={onRestart}\n />\n </Stack>\n);\n\n// Main component\n"],"mappings":";;;AAAA;AAAA,EACE,SAAAA;AAAA,EACA,OAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAAC;AAAA,OAAc;;;ACRhB,SAAS,aAAa,WAAW,QAAQ,gBAAgB;;;ACAzD,IAAM,kBAAkB;AAEjB,IAAM,mBAAmB,CAAC,aAC/B,SAAS,cAAc,QAAQ,GAAG,sBAAsB,KAAK;AAI/D,IAAM,gBAAgB,CAAC,iBAA6C;AAClE,QAAM,SAAS;AAAA,IACb,KAAK,aAAa;AAAA,IAClB,QAAQ,OAAO,cAAc,aAAa;AAAA,IAC1C,MAAM,aAAa;AAAA,IACnB,OAAO,OAAO,aAAa,aAAa;AAAA,EAC1C;AAEA,SAAO,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,GAAG,MAAO,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAE,EAAE,CAAC;AACzE;AAEA,IAAM,YAAY,CAChB,WACA,cACA,eACA,YACkC;AAClC,QAAM,cAAc,aAAa,OAAO,aAAa,QAAQ,IAAI,cAAc,QAAQ;AACvF,QAAM,aAAa,aAAa,MAAM,aAAa,SAAS,IAAI,cAAc,SAAS;AAEvF,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,EAAE,KAAK,aAAa,MAAM,cAAc,SAAS,SAAS,MAAM,YAAY;AAAA,IACrF,KAAK;AACH,aAAO,EAAE,KAAK,aAAa,SAAS,SAAS,MAAM,YAAY;AAAA,IACjE,KAAK;AACH,aAAO,EAAE,KAAK,YAAY,MAAM,aAAa,OAAO,cAAc,QAAQ,QAAQ;AAAA,IACpF,KAAK;AACH,aAAO,EAAE,KAAK,YAAY,MAAM,aAAa,QAAQ,QAAQ;AAAA,IAC/D;AACE,aAAO,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,EAC7B;AACF;AAGA,IAAM,kBAAkB,CACtB,UACA,eACA,aACI;AAAA,EACJ,KAAK,KAAK,IAAI,SAAS,KAAK,IAAI,SAAS,KAAK,OAAO,cAAc,cAAc,SAAS,OAAO,CAAC;AAAA,EAClG,MAAM,KAAK,IAAI,SAAS,KAAK,IAAI,SAAS,MAAM,OAAO,aAAa,cAAc,QAAQ,OAAO,CAAC;AACpG;AAEO,IAAM,2BAA2B,CACtC,cACA,eACA,WACA,UAAU,oBACP;AACH,QAAM,iBAAiB,cAAc,SAAS,cAAc,YAAY,IAAI;AAC5E,QAAM,SAAS,UAAU,gBAAgB,cAAc,eAAe,OAAO;AAE7E,SAAO;AAAA,IACL,UAAU,gBAAgB,QAAQ,eAAe,OAAO;AAAA,IACxD,WAAW;AAAA,EACb;AACF;;;ADxDA,IAAM,kBAAkB,CAAC;AAAA,EACvB;AAAA,EACA;AACF,MAGM;AACJ,QAAM,CAAC,cAAc,eAAe,IAAI,SAAoC,IAAI;AAChF,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,OAAQ;AAExB,UAAM,eAAe,MAAM;AACzB,YAAM,SAAS,iBAAiB,MAAM;AACtC,sBAAgB,MAAM;AACtB,mBAAa,QAAQ,MAAM,CAAC;AAAA,IAC9B;AAEA,iBAAa;AAEb,WAAO,iBAAiB,UAAU,YAAY;AAC9C,WAAO,iBAAiB,UAAU,cAAc,IAAI;AAEpD,WAAO,MAAM;AACX,aAAO,oBAAoB,UAAU,YAAY;AACjD,aAAO,oBAAoB,UAAU,cAAc,IAAI;AAAA,IACzD;AAAA,EACF,GAAG,CAAC,QAAQ,MAAM,CAAC;AAEnB,SAAO,EAAE,cAAc,UAAU;AACnC;AAGA,IAAM,sBAAsB,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,MAIM;AACJ,QAAM,aAAa,OAAuB,IAAI;AAC9C,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,EAAE,KAAK,GAAG,MAAM,EAAE,CAAC;AAC1E,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAiB,QAAQ;AAEvE,YAAU,MAAM;AACd,QAAI,CAAC,gBAAgB,CAAC,WAAW,WAAW,CAAC,UAAW;AAExD,UAAM,EAAE,UAAU,UAAU,IAAI;AAAA,MAC9B;AAAA,MACA,WAAW,QAAQ,sBAAsB;AAAA,MACzC,qBAAqB;AAAA,IACvB;AAEA,uBAAmB,QAAQ;AAC3B,uBAAmB,SAAS;AAAA,EAC9B,GAAG,CAAC,cAAc,WAAW,iBAAiB,CAAC;AAE/C,SAAO,EAAE,YAAY,iBAAiB,gBAAgB;AACxD;AAGA,IAAM,sBAAsB,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAKM;AACJ,YAAU,MAAM;AACd,QAAI,CAAC,QAAS;AAEd,UAAM,iBAAiB,CAAC,MAAgC;AACtD,cAAQ,EAAE,KAAK;AAAA,QACb,KAAK;AACH,iBAAO;AACP;AAAA,QACF,KAAK;AACH,iBAAO;AACP;AAAA,QACF,KAAK;AACH,iBAAO;AACP;AAAA,MACJ;AAAA,IACF;AAEA,WAAO,iBAAiB,WAAW,cAAc;AACjD,WAAO,MAAM,OAAO,oBAAoB,WAAW,cAAc;AAAA,EACnE,GAAG,CAAC,SAAS,QAAQ,QAAQ,MAAM,CAAC;AACtC;AAEO,IAAM,qBAAqB,CAAC;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAQM;AACJ,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,WAAW;AAE1D,QAAM,kBAAkB,MAAM,WAAW;AACzC,QAAM,aAAa,gBAAgB,MAAM,SAAS;AAElD,QAAM,EAAE,cAAc,UAAU,IAAI,gBAAgB;AAAA,IAClD;AAAA,IACA,QAAQ,iBAAiB;AAAA,EAC3B,CAAC;AAED,QAAM,EAAE,YAAY,iBAAiB,gBAAgB,IAAI,oBAAoB;AAAA,IAC3E;AAAA,IACA;AAAA,IACA,mBAAmB,iBAAiB;AAAA,EACtC,CAAC;AAED,QAAM,aAAa,YAAY,MAAM;AACnC,UAAM,gBAAgB,MAAM,WAAW,GAAG;AAC1C,QAAI,cAAe,kBAAiB,aAAa;AAEjD,QAAI,cAAc,MAAM,SAAS,GAAG;AAClC,qBAAe,cAAc,CAAC;AAC9B;AAAA,IACF;AAEA,iBAAa;AAAA,EACf,GAAG,CAAC,aAAa,OAAO,YAAY,cAAc,CAAC;AAEnD,QAAM,aAAa,YAAY,MAAM;AACnC,mBAAe,CAAC,SAAS,KAAK,IAAI,OAAO,GAAG,CAAC,CAAC;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,aAAa,YAAY,MAAM;AACnC,aAAS;AAAA,EACX,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,gBAAgB,YAAY,MAAM;AACtC,mBAAe,CAAC;AAAA,EAClB,GAAG,CAAC,CAAC;AAEL,sBAAoB;AAAA,IAClB,SAAS,2BAA2B;AAAA,IACpC,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAY,cAAc,KAAK,MAAM,SAAU;AAAA,IAC/C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AExLA,OAAO,kBAAkB;AACzB,OAAO,eAAe;AACtB,OAAO,cAAc;AACrB,OAAO,cAAc;AACrB,OAAO,iBAAiB;AACxB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAAkB;AAyDV,SAEI,KAFJ;AAlDV,IAAM,gBAAgB,OAAO,GAAG,EAAE,CAAC,EAAE,MAAM,OAAO;AAAA,EAChD,SAAS;AAAA,EACT,KAAK,MAAM,QAAQ,CAAC;AAAA,EACpB,WAAW,MAAM,QAAQ,CAAC;AAAA,EAC1B,cAAc,MAAM,QAAQ,CAAC;AAAE,EAAE;AAGnC,IAAM,UAAU,OAAO,KAAK;AAAA,EAC1B,mBAAmB,CAAC,SAAS,SAAS,YAAY,SAAS;AAAY,CAAC,EAA6C,CAAC,EAAE,OAAO,QAAQ,UAAU,OAAO;AAAA,EACxJ,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,YAAY,YACR,MAAM,QAAQ,QAAQ,OACtB,SACE,MAAM,QAAQ,QAAQ,OACtB,MAAM,MAAM,QAAQ,KAAK,SAAS,GAAG;AAAA,EAC3C,YAAY;AAAA,EACZ,GAAI,UAAU;AAAA,IACZ,WAAW;AAAA,EAAa;AAAG,EAAE;AAKjC,IAAM,kBAUD,CAAC;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAU,MACJ;AAAA,EAAC;AAAA;AAAA,IACC,WAAU;AAAA,IACV,SAAS;AAAA,IACT,gBAAe;AAAA,IACf,eAAY;AAAA,IAEZ;AAAA,2BAAC,SAAM,WAAU,OAAM,SAAS,GAC7B;AAAA,qBACC,oBAAC,UAAO,MAAK,SAAQ,SAAS,QAAQ,SAAQ,QAAO,kBAErD;AAAA,QAED,YAAY,KACX;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS;AAAA,YACT,UAAU,gBAAgB;AAAA,YAC1B,OAAM;AAAA,YAEN,8BAAC,eAAY,UAAS,SAAQ;AAAA;AAAA,QAChC;AAAA,SAEJ;AAAA,MAEA,qBAAC,SAAM,WAAU,OAAM,SAAS,GAC7B;AAAA,oBAAY,KAAK,cAAc,KAC9B;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAW,oBAAC,YAAS;AAAA,YACrB,SAAS;AAAA,YACT,UAAU,gBAAgB;AAAA,YAC1B,eAAY;AAAA,YACb;AAAA;AAAA,QAED;AAAA,QAGD,CAAC,aACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,SAAS,oBAAC,YAAS;AAAA,YACnB,SAAS;AAAA,YACT,UAAU;AAAA,YACV,OAAO,2BAA2B,uCAAuC;AAAA,YACzE,eAAY;AAAA,YACb;AAAA;AAAA,QAED,IAEA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,SAAS,oBAAC,gBAAa;AAAA,YACvB,SAAS;AAAA,YACT,IAAI;AAAA,cACF,YAAY;AAAA,YAAoD;AAAA,YAClE,eAAY;AAAA,YAEX,wBAAc,IAAI,aAAa;AAAA;AAAA,QAClC;AAAA,SAEJ;AAAA;AAAA;AACF;AAGR,IAAM,WAAiE,CAAC;AAAA,EACtE;AAAA,EACA;AAAU,MACV,oBAAC,iBAAc,eAAY,4BACxB,gBAAM,KAAK,EAAE,QAAQ,UAAU,CAAC,EAAE,IAAI,CAAC,GAAG,UACzC;AAAA,EAAC;AAAA;AAAA,IAEC,QAAQ,UAAU;AAAA,IAClB,WAAW,QAAQ;AAAA,IACnB,eAAa,sBAAsB,KAAK;AAAA;AAAA,EAHnC;AAIP,CACD,GACH;AAIF,IAAM,qBAKD,CAAC,EAAE,OAAO,aAAa,WAAW,OAAO,MACtC;AAAA,EAAC;AAAA;AAAA,IACC,IAAI,EAAE,SAAS,QAAQ,gBAAgB,iBAAiB,YAAY,aAAa;AAAA,IAEjF;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,IAAI,kBAAkB,WAAW;AAAA,UACjC,SAAQ;AAAA,UACR,YAAW;AAAA,UACX,IAAI,EAAE,MAAM,EAAE;AAAA,UACd,eAAY;AAAA,UAEX;AAAA;AAAA,MACH;AAAA,MACC,aACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG;AAAA,UAC5B,eAAY;AAAA,UAEZ,8BAAC,aAAU,UAAS,SAAQ;AAAA;AAAA,MAC9B;AAAA;AAAA;AAEJ;AAGD,IAAM,mBAaR,CAAC;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAU,MACN,qBAAC,SAAM,SAAS,GACd;AAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,KAAK;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF;AAAA,EAEA;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,oBAAoB,WAAW;AAAA,MACnC,SAAQ;AAAA,MACR,OAAM;AAAA,MACN,eAAY;AAAA,MAEX,eAAK;AAAA;AAAA,EACR;AAAA,EAEC,gBACC,qBAAC,cAAW,SAAQ,WAAU,OAAM,kBAAiB,OAAM,UACxD;AAAA,kBAAc;AAAA,IAAE;AAAA,IAAK;AAAA,KACxB;AAAA,EAGD,KAAK,UACJ;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,SAAS,KAAK,OAAO;AAAA,MACrB,IAAI;AAAA,QACF,YAAY;AAAA,QACZ,OAAO;AAAA,MAAQ;AAAA,MAEhB,eAAK,OAAO;AAAA;AAAA,EACf;AAAA,EAGF,oBAAC,YAAS,aAA0B,WAAsB;AAAA,EAE1D;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF;AAAA,GACF;;;AHvEF,mBACa,OAAAC,MADb,QAAAC,aAAA;AAnKJ,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYvB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUvB,IAAM,UAAUC,QAAOC,MAAK;AAAA,EAC1B,mBAAmB,CAAC,SAAS,SAAS;AAAoB,CAAC,EAAmC,CAAC,EAAE,OAAO,kBAAkB,OAAO;AAAA,EACjI,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ,MAAM,OAAO,QAAQ;AAAA,EAC7B,eAAe,oBAAoB,SAAS;AAAA,EAC5C,YAAY;AAAoB,EAAE;AAEpC,IAAM,WAAWD,QAAOC,IAAG,EAAE,OAAO;AAAA,EAClC,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,YAAYC,OAAM,QAAQ,GAAG;AAAA,EAC7B,gBAAgB;AAAY,EAAE;AAEhC,IAAM,YAAYF,QAAOC,MAAK;AAAA,EAC5B,mBAAmB,CAAC,SAAS,SAAS,YAAY,SAAS;AAAU,CAAC,EAAmD,CAAC,EAAE,QAAQ,QAAQ,OAAO;AAAA,EACnJ,UAAU;AAAA,EACV,KAAK,OAAO,MAAM;AAAA,EAClB,MAAM,OAAO,OAAO;AAAA,EACpB,OAAO,OAAO,QAAQ,UAAU;AAAA,EAChC,QAAQ,OAAO,SAAS,UAAU;AAAA,EAClC,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,WAAW,GAAG,cAAc;AAAA,EAC5B,eAAe;AAAA,EACf,aAAa;AAAA,IACX,SAAS;AAAA,IACT,UAAU;AAAA,IACV,OAAO;AAAA,IACP,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,WAAW;AAAA,EAAkC;AAAE,EAAE;AAErD,IAAM,mBAAmBD,QAAO,OAAO;AAAA,EACrC,mBAAmB,CAAC,SAAS,SAAS;AAAY,CAAC,EAAyB,CAAC,EAAE,OAAO,UAAU,OAAO;AAAA,EACvG,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS,MAAM,QAAQ,CAAC;AAAA,EACxB,YAAY,2BAA2BE,OAAM,MAAM,QAAQ,WAAW,OAAO,IAAI,CAAC,QAAQA,OAAM,MAAM,QAAQ,WAAW,OAAO,IAAI,CAAC;AAAA,EACrI,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,QAAQ,aAAaA,OAAM,MAAM,QAAQ,SAAS,IAAI,CAAC;AAAA,EACvD,WAAW,MAAM,QAAQ,EAAE;AAAA,EAC3B,WAAW,GAAG,cAAc;AAAA,EAC5B,eAAe;AAAA,EACf,QAAQ,MAAM,OAAO,QAAQ;AAAA,EAC7B,aAAa;AAAA,IACX,SAAS;AAAA,IACT,UAAU;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,GAAI,cAAc,SAAS;AAAA,MACzB,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,YAAY;AAAA,IAAO;AAAA,IACrB,GAAI,cAAc,YAAY;AAAA,MAC5B,KAAK;AAAA,MACL,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,aAAa;AAAA,IAAO;AAAA,IACtB,GAAI,cAAc,UAAU;AAAA,MAC1B,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,cAAc;AAAA,IAAO;AAAA,IACvB,GAAI,cAAc,WAAW;AAAA,MAC3B,MAAM;AAAA,MACN,KAAK;AAAA,MACL,WAAW;AAAA,MACX,aAAa;AAAA,MACb,WAAW;AAAA,IAAO;AAAA,EAAG;AAAE,EAAE;AAE/B,IAAM,cAAcF,QAAO,cAAc,EAAE,CAAC,EAAE,MAAM,OAAO;AAAA,EACzD,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ,MAAM,OAAO,QAAQ;AAAA,EAC7B,4BAA4B;AAAA,IAC1B,YAAY,0BAA0B,MAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,QAAQ,QAAQ,KAAK;AAAA,EAAS;AAAE,EAAE;AAepH,IAAM,oBAAuE;AAAA,EAC3E,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,yBAAyB;AAAA,EACzB,mBAAmB;AAAA,EACnB,SAAS;AAAA,EACT,WAAW;AAAA,EACX,UAAU;AAAK;AAMjB,IAAM,eAAe,CAAC,WACnB;AAAA,EACC,GAAG;AAAA,EACH,GAAI,OAAO;AAAA,IACT,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS;AAAA,EACjE;AAAoC;AAIxC,IAAM,iBAKD,CAAC,EAAE,SAAS,cAAc,WAAW,iBAAiB,MAAM;AAC/D,QAAM,cAAc,YAAY,eAAe,YAAY;AAC3D,QAAM,SAAS,YAAY,WAAW;AAEtC,SACE,gBAAAD,MAAA,YACG;AAAA,cAAU,gBAAAD,KAAC,YAAS;AAAA,IACpB,gBAAgB,aAAa,eAC5B,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ;AAAA,QACR,SAAS,oBAAoB;AAAA,QAC7B,eAAY;AAAA;AAAA,IACd;AAAA,KAEJ;AAEJ;AAIA,IAAM,kBASD,CAAC,EAAE,UAAU,OAAO,WAAW,cAAc,UAAU,yBAAyB,MAC7E,gBAAAA,KAAC,QAAK,IAAI,SAAS,WAAW,SAAS,KACrC,0BAAAA;AAAA,EAAC;AAAA;AAAA,IACC,KAAK,SAAS;AAAA,IACd,WAAW,SAAS;AAAA,IACpB,WAAW;AAAA,IACX,OAAO;AAAA,MACL,KAAK,SAAS,gBAAgB;AAAA,MAC9B,MAAM,SAAS,gBAAgB;AAAA,MAC/B,WAAW,WAAW,SAAY;AAAA,IAAO;AAAA,IAC3C,MAAK;AAAA,IACL,mBAAiB,kBAAkB,SAAS,WAAW;AAAA,IACvD,oBAAkB,oBAAoB,SAAS,WAAW;AAAA,IAC1D,eAAa,iBAAiB,SAAS,WAAW;AAAA,IAElD,0BAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,SAAS;AAAA,QACf,aAAa,SAAS;AAAA,QACtB,WAAW,MAAM;AAAA,QACjB,UAAU,SAAS;AAAA,QACnB,YAAY,SAAS;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ,SAAS;AAAA,QACjB,QAAQ,SAAS;AAAA,QACjB,QAAQ,SAAS;AAAA,QACjB,WAAW,SAAS;AAAA;AAAA,IACtB;AAAA;AACF,GACF;AAGD,IAAM,kBAA4C,CAAC,mBAAmB;AAC3E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAS,IAAI,aAAa,cAAc;AAE1C,QAAM,WAAW,mBAAmB;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAe,CAAC;AAClB,QAAM,EAAE,iBAAiB,YAAY,WAAW,cAAc,SAAS,IAAI;AAE3E,QAAM,2BAA2B,QAAQ,iBAAiB,cAAc,KAAK,CAAC;AAE9E,MAAI,CAAC,UAAU,CAAC,gBAAiB,QAAO;AAGxC,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,SACE,gBAAAA,KAAC,UACC,0BAAAC,MAAC,WAAQ,mBAAsC,eAAY,oBACxD;AAAA,oBAAgB,gBAAAD,KAAC,eAAY,SAAQ,eAAc,OAAO,UAAU;AAAA,IAErE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA,kBAAkB,gBAAgB;AAAA;AAAA,IACpC;AAAA,IAEA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,EAAE,GAAG,UAAU,gBAAgB;AAAA,QACzC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,KACF,GACF;AAEJ;","names":["alpha","Box","styled","jsx","jsxs","styled","Box","alpha"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/feedback/TutorialOverlay/TutorialOverlay.tsx","../../src/components/feedback/TutorialOverlay/TutorialOverlay.hooks.ts","../../src/components/feedback/TutorialOverlay/TutorialOverlay.geometry.ts","../../src/components/feedback/TutorialOverlay/TutorialStepBody.tsx"],"sourcesContent":["import {\n alpha,\n Box,\n Fade,\n keyframes,\n LinearProgress,\n Paper,\n Portal,\n styled } from '@mui/material';\nimport type { FC} from 'react';\nimport React, { } from 'react';\n\nimport { useTutorialOverlay } from './TutorialOverlay.hooks';\nimport { TutorialStepBody } from './TutorialStepBody';\nimport type { TutorialOverlayProps } from './TutorialOverlay.types';\n\n// Animation keyframes\nconst pulseAnimation = keyframes`\n 0% {\n box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);\n }\n 70% {\n box-shadow: 0 0 0 20px rgba(255, 255, 255, 0);\n }\n 100% {\n box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);\n }\n`;\n\nconst floatAnimation = keyframes`\n 0%, 100% {\n transform: translateY(0);\n }\n 50% {\n transform: translateY(-10px);\n }\n`;\n\n// Styled components\nconst Overlay = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'allowClickThrough' })<{ allowClickThrough?: boolean }>(({ theme, allowClickThrough }) => ({\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: theme.zIndex.modal + 100,\n pointerEvents: allowClickThrough ? 'none' : 'auto',\n transition: 'opacity 0.3s ease' }));\n\nconst Backdrop = styled(Box)(() => ({\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: alpha('#000', 0.7),\n backdropFilter: 'blur(2px)' }));\n\nconst Spotlight = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'bounds' && prop !== 'padding' })<{ bounds: globalThis.DOMRect; padding: number }>(({ bounds, padding }) => ({\n position: 'absolute',\n top: bounds.top - padding,\n left: bounds.left - padding,\n width: bounds.width + padding * 2,\n height: bounds.height + padding * 2,\n borderRadius: 8,\n border: '2px solid rgba(255, 255, 255, 0.5)',\n animation: `${pulseAnimation} 2s infinite`,\n pointerEvents: 'none',\n '&::before': {\n content: '\"\"',\n position: 'absolute',\n inset: -2,\n borderRadius: 8,\n background: 'transparent',\n boxShadow: '0 0 0 9999px rgba(0, 0, 0, 0.7)' } }));\n\nconst TooltipContainer = styled(Paper, {\n shouldForwardProp: (prop) => prop !== 'placement' })<{ placement: string }>(({ theme, placement }) => ({\n position: 'absolute',\n maxWidth: 360,\n padding: theme.spacing(3),\n background: `linear-gradient(135deg, ${alpha(theme.palette.background.paper, 0.98)} 0%, ${alpha(theme.palette.background.paper, 0.95)} 100%)`,\n backdropFilter: 'blur(20px)',\n WebkitBackdropFilter: 'blur(20px)',\n border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,\n boxShadow: theme.shadows[12],\n animation: `${floatAnimation} 3s ease-in-out infinite`,\n pointerEvents: 'auto',\n zIndex: theme.zIndex.modal + 101,\n '&::before': {\n content: '\"\"',\n position: 'absolute',\n width: 12,\n height: 12,\n background: 'inherit',\n transform: 'rotate(45deg)',\n border: 'inherit',\n ...(placement === 'top' && {\n bottom: -7,\n left: '50%',\n marginLeft: -6,\n borderTop: 'none',\n borderLeft: 'none' }),\n ...(placement === 'bottom' && {\n top: -7,\n left: '50%',\n marginLeft: -6,\n borderBottom: 'none',\n borderRight: 'none' }),\n ...(placement === 'left' && {\n right: -7,\n top: '50%',\n marginTop: -6,\n borderLeft: 'none',\n borderBottom: 'none' }),\n ...(placement === 'right' && {\n left: -7,\n top: '50%',\n marginTop: -6,\n borderRight: 'none',\n borderTop: 'none' }) } }));\n\nconst ProgressBar = styled(LinearProgress)(({ theme }) => ({\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n height: 4,\n zIndex: theme.zIndex.modal + 102,\n '& .MuiLinearProgress-bar': {\n background: `linear-gradient(90deg, ${theme.palette.primary.main} 0%, ${theme.palette.primary.light} 100%)` } }));\n\ntype TutorialDefaultedKeys =\n | 'initialStep'\n | 'active'\n | 'showProgress'\n | 'allowKeyboardNavigation'\n | 'allowClickThrough'\n | 'variant'\n | 'allowSkip'\n | 'animated';\n\ntype ResolvedTutorialProps = TutorialOverlayProps &\n Required<Pick<TutorialOverlayProps, TutorialDefaultedKeys>>;\n\nconst TUTORIAL_DEFAULTS: Pick<TutorialOverlayProps, TutorialDefaultedKeys> = {\n initialStep: 0,\n active: true,\n showProgress: true,\n allowKeyboardNavigation: true,\n allowClickThrough: false,\n variant: 'tooltip',\n allowSkip: false,\n animated: true };\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 eight\n// branches into the component's own complexity budget.\nconst resolveProps = (props: TutorialOverlayProps): ResolvedTutorialProps =>\n ({\n ...TUTORIAL_DEFAULTS,\n ...(Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<TutorialOverlayProps>) }) as ResolvedTutorialProps;\n\n// The dimming layer and the cut-out over the highlighted element. Local because\n// Backdrop and Spotlight cannot cross a module boundary (TS2742).\nconst TutorialLayers: React.FC<{\n variant: string;\n targetBounds: globalThis.DOMRect | null;\n isVisible: boolean;\n spotlightPadding?: number;\n}> = ({ variant, targetBounds, isVisible, spotlightPadding }) => {\n const isSpotlight = variant === 'spotlight' || variant === 'highlight';\n const dimmed = variant === 'modal' || isSpotlight;\n\n return (\n <>\n {dimmed && <Backdrop />}\n {targetBounds && isVisible && isSpotlight && (\n <Spotlight\n bounds={targetBounds}\n padding={spotlightPadding || 8}\n data-testid=\"tutorial-highlight\"\n />\n )}\n </>\n );\n};\n\n// The positioned card. Local because TooltipContainer cannot cross a module\n// boundary (TS2742).\nconst TutorialTooltip: React.FC<{\n tutorial: ReturnType<typeof useTutorialOverlay> & {\n currentStepData: TutorialOverlayProps['steps'][number];\n };\n steps: TutorialOverlayProps['steps'];\n allowSkip: boolean;\n showProgress: boolean;\n animated: boolean;\n requiresActionBeforeNext: boolean;\n copy: TutorialOverlayProps['copy'];\n}> = ({\n tutorial,\n steps,\n allowSkip,\n showProgress,\n animated,\n requiresActionBeforeNext,\n copy,\n}) => (\n <Fade in={tutorial.isVisible} timeout={300}>\n <TooltipContainer\n ref={tutorial.tooltipRef}\n placement={tutorial.actualPlacement}\n elevation={12}\n style={{\n top: tutorial.tooltipPosition.top,\n left: tutorial.tooltipPosition.left,\n animation: animated ? undefined : 'none' }}\n role=\"dialog\"\n aria-labelledby={`tutorial-title-${tutorial.currentStep}`}\n aria-describedby={`tutorial-content-${tutorial.currentStep}`}\n data-testid={`tutorial-step-${tutorial.currentStep}`}\n >\n <TutorialStepBody\n copy={copy}\n step={tutorial.currentStepData}\n currentStep={tutorial.currentStep}\n stepCount={steps.length}\n progress={tutorial.progress}\n isLastStep={tutorial.isLastStep}\n allowSkip={allowSkip}\n showProgress={showProgress}\n requiresActionBeforeNext={requiresActionBeforeNext}\n onNext={tutorial.handleNext}\n onPrev={tutorial.handlePrev}\n onSkip={tutorial.handleSkip}\n onRestart={tutorial.handleRestart}\n />\n </TooltipContainer>\n </Fade>\n);\n\nexport const TutorialOverlay: FC<TutorialOverlayProps> = (componentProps) => {\n const {\n copy,\n steps,\n onComplete,\n onSkip,\n onStepComplete,\n initialStep,\n active,\n showProgress,\n allowKeyboardNavigation,\n allowClickThrough,\n variant,\n allowSkip,\n animated } = resolveProps(componentProps);\n\n const tutorial = useTutorialOverlay({\n steps,\n initialStep,\n active,\n allowKeyboardNavigation,\n onComplete,\n onSkip,\n onStepComplete });\n const { currentStepData, isLastStep, isVisible, targetBounds, progress } = tutorial;\n\n const requiresActionBeforeNext = Boolean(currentStepData?.requiresAction) && !isLastStep;\n\n if (!active || !currentStepData) return null;\n\n // Handle empty steps array\n if (steps.length === 0) return null;\n\n return (\n <Portal>\n <Overlay allowClickThrough={allowClickThrough} data-testid=\"tutorial-overlay\">\n {showProgress && <ProgressBar variant=\"determinate\" value={progress} />}\n\n <TutorialLayers\n variant={variant}\n targetBounds={targetBounds}\n isVisible={isVisible}\n spotlightPadding={currentStepData.spotlightPadding}\n />\n\n <TutorialTooltip\n copy={copy}\n tutorial={{ ...tutorial, currentStepData }}\n steps={steps}\n allowSkip={allowSkip}\n showProgress={showProgress}\n animated={animated}\n requiresActionBeforeNext={requiresActionBeforeNext}\n />\n </Overlay>\n </Portal>\n );\n};\n\n// Export default\nexport default TutorialOverlay;\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { calculateTooltipPosition, getElementBounds } from './TutorialOverlay.geometry';\nimport type { TutorialOverlayProps } from './TutorialOverlay.types';\n\n// Tracks the highlighted element's box, re-measuring on resize and scroll. Scroll\n// is captured (third argument true) so it fires for any scrolling ancestor, not\n// just the window.\nconst useTargetBounds = ({\n active,\n target,\n}: {\n active: boolean;\n target?: string;\n}) => {\n const [targetBounds, setTargetBounds] = useState<globalThis.DOMRect | null>(null);\n const [isVisible, setIsVisible] = useState(false);\n\n useEffect(() => {\n if (!active || !target) return;\n\n const updateBounds = () => {\n const bounds = getElementBounds(target);\n setTargetBounds(bounds);\n setIsVisible(Boolean(bounds));\n };\n\n updateBounds();\n\n window.addEventListener('resize', updateBounds);\n window.addEventListener('scroll', updateBounds, true);\n\n return () => {\n window.removeEventListener('resize', updateBounds);\n window.removeEventListener('scroll', updateBounds, true);\n };\n }, [active, target]);\n\n return { targetBounds, isVisible };\n};\n\n// Places the tooltip against the measured target once both boxes are known.\nconst useTooltipPlacement = ({\n targetBounds,\n isVisible,\n preferredPosition,\n}: {\n targetBounds: globalThis.DOMRect | null;\n isVisible: boolean;\n preferredPosition?: string;\n}) => {\n const tooltipRef = useRef<HTMLDivElement>(null);\n const [tooltipPosition, setTooltipPosition] = useState({ top: 0, left: 0 });\n const [actualPlacement, setActualPlacement] = useState<string>('bottom');\n\n useEffect(() => {\n if (!targetBounds || !tooltipRef.current || !isVisible) return;\n\n const { position, placement } = calculateTooltipPosition(\n targetBounds,\n tooltipRef.current.getBoundingClientRect(),\n preferredPosition || 'auto',\n );\n\n setTooltipPosition(position);\n setActualPlacement(placement);\n }, [targetBounds, isVisible, preferredPosition]);\n\n return { tooltipRef, tooltipPosition, actualPlacement };\n};\n\n// Arrow keys step through the tour, Escape skips it.\nconst useTutorialKeyboard = ({\n enabled,\n onNext,\n onPrev,\n onSkip,\n}: {\n enabled: boolean;\n onNext: () => void;\n onPrev: () => void;\n onSkip: () => void;\n}) => {\n useEffect(() => {\n if (!enabled) return;\n\n const handleKeyPress = (e: globalThis.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowLeft':\n onPrev();\n break;\n case 'ArrowRight':\n onNext();\n break;\n case 'Escape':\n onSkip();\n break;\n }\n };\n\n window.addEventListener('keydown', handleKeyPress);\n return () => window.removeEventListener('keydown', handleKeyPress);\n }, [enabled, onNext, onPrev, onSkip]);\n};\n\nexport const useTutorialOverlay = ({\n steps,\n initialStep,\n active,\n allowKeyboardNavigation,\n onComplete,\n onSkip,\n onStepComplete,\n}: {\n steps: TutorialOverlayProps['steps'];\n initialStep: number;\n active: boolean;\n allowKeyboardNavigation: boolean;\n onComplete?: () => void;\n onSkip?: () => void;\n onStepComplete?: (stepId: string) => void;\n}) => {\n const [currentStep, setCurrentStep] = useState(initialStep);\n\n const currentStepData = steps[currentStep];\n const isLastStep = currentStep === steps.length - 1;\n\n const { targetBounds, isVisible } = useTargetBounds({\n active,\n target: currentStepData?.target,\n });\n\n const { tooltipRef, tooltipPosition, actualPlacement } = useTooltipPlacement({\n targetBounds,\n isVisible,\n preferredPosition: currentStepData?.position,\n });\n\n const handleNext = useCallback(() => {\n const currentStepId = steps[currentStep]?.id;\n if (currentStepId) onStepComplete?.(currentStepId);\n\n if (currentStep < steps.length - 1) {\n setCurrentStep(currentStep + 1);\n return;\n }\n\n onComplete?.();\n }, [currentStep, steps, onComplete, onStepComplete]);\n\n const handlePrev = useCallback(() => {\n setCurrentStep((step) => Math.max(step - 1, 0));\n }, []);\n\n const handleSkip = useCallback(() => {\n onSkip?.();\n }, [onSkip]);\n\n const handleRestart = useCallback(() => {\n setCurrentStep(0);\n }, []);\n\n useTutorialKeyboard({\n enabled: allowKeyboardNavigation && active,\n onNext: handleNext,\n onPrev: handlePrev,\n onSkip: handleSkip,\n });\n\n return {\n currentStep,\n currentStepData,\n isLastStep,\n isVisible,\n targetBounds,\n tooltipRef,\n tooltipPosition,\n actualPlacement,\n progress: ((currentStep + 1) / steps.length) * 100,\n handleNext,\n handlePrev,\n handleSkip,\n handleRestart,\n };\n};\n","const DEFAULT_PADDING = 16;\n\nexport const getElementBounds = (selector: string): globalThis.DOMRect | null =>\n document.querySelector(selector)?.getBoundingClientRect() ?? null;\n\n// With placement 'auto', the side with the most free space around the target\n// wins.\nconst pickPlacement = (targetBounds: globalThis.DOMRect): string => {\n const spaces = {\n top: targetBounds.top,\n bottom: window.innerHeight - targetBounds.bottom,\n left: targetBounds.left,\n right: window.innerWidth - targetBounds.right,\n };\n\n return Object.entries(spaces).reduce((a, b) => (b[1] > a[1] ? b : a))[0];\n};\n\nconst offsetFor = (\n placement: string,\n targetBounds: globalThis.DOMRect,\n tooltipBounds: globalThis.DOMRect,\n padding: number,\n): { top: number; left: number } => {\n const centredLeft = targetBounds.left + targetBounds.width / 2 - tooltipBounds.width / 2;\n const centredTop = targetBounds.top + targetBounds.height / 2 - tooltipBounds.height / 2;\n\n switch (placement) {\n case 'top':\n return { top: targetBounds.top - tooltipBounds.height - padding, left: centredLeft };\n case 'bottom':\n return { top: targetBounds.bottom + padding, left: centredLeft };\n case 'left':\n return { top: centredTop, left: targetBounds.left - tooltipBounds.width - padding };\n case 'right':\n return { top: centredTop, left: targetBounds.right + padding };\n default:\n return { top: 0, left: 0 };\n }\n};\n\n// Keeps the tooltip fully on screen, whatever the chosen side works out to.\nconst clampToViewport = (\n position: { top: number; left: number },\n tooltipBounds: globalThis.DOMRect,\n padding: number,\n) => ({\n top: Math.max(padding, Math.min(position.top, window.innerHeight - tooltipBounds.height - padding)),\n left: Math.max(padding, Math.min(position.left, window.innerWidth - tooltipBounds.width - padding)),\n});\n\nexport const calculateTooltipPosition = (\n targetBounds: globalThis.DOMRect,\n tooltipBounds: globalThis.DOMRect,\n placement: string,\n padding = DEFAULT_PADDING,\n) => {\n const finalPlacement = placement === 'auto' ? pickPlacement(targetBounds) : placement;\n const offset = offsetFor(finalPlacement, targetBounds, tooltipBounds, padding);\n\n return {\n position: clampToViewport(offset, tooltipBounds, padding),\n placement: finalPlacement,\n };\n};\n","import CompleteIcon from '@mui/icons-material/CheckCircle';\nimport CloseIcon from '@mui/icons-material/Close';\nimport PrevIcon from '@mui/icons-material/NavigateBefore';\nimport NextIcon from '@mui/icons-material/NavigateNext';\nimport RestartIcon from '@mui/icons-material/Refresh';\nimport {\n alpha,\n Box,\n Button,\n IconButton,\n Stack,\n styled,\n Typography } from '@mui/material';\nimport React, { } from 'react';\n\nimport type { TutorialOverlayProps } from './TutorialOverlay.types';\nimport type { TutorialCopy } from '../../../copy';\n\n// Animation keyframes\n\nconst StepIndicator = styled(Box)(({ theme }) => ({\n display: 'flex',\n gap: theme.spacing(1),\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(2) }));\n\n\nconst StepDot = styled(Box, {\n shouldForwardProp: (prop) => prop !== 'active' && prop !== 'completed' })<{ active?: boolean; completed?: boolean }>(({ theme, active, completed }) => ({\n width: 8,\n height: 8,\n borderRadius: '50%',\n background: completed\n ? theme.palette.success.main\n : active\n ? theme.palette.primary.main\n : alpha(theme.palette.text.primary, 0.3),\n transition: 'all 0.3s ease',\n ...(active && {\n transform: 'scale(1.5)' }) }));\n\n// Title, body copy, the step dots and the navigation row.\n\n// The step's controls: skip/restart on the left, previous/next on the right.\nconst TutorialStepNav: React.FC<{\n copy: TutorialCopy;\n currentStep: number;\n stepCount: number;\n isLastStep: boolean;\n allowSkip: boolean;\n requiresActionBeforeNext?: boolean;\n onNext: () => void;\n onPrev: () => void;\n onSkip: () => void;\n onRestart: () => void;\n}> = ({\n copy,\n currentStep,\n stepCount,\n isLastStep,\n allowSkip,\n requiresActionBeforeNext,\n onNext,\n onPrev,\n onSkip,\n onRestart }) => (\n <Stack\n direction=\"row\"\n spacing={1}\n justifyContent=\"space-between\"\n data-testid=\"tutorial-navigation\"\n >\n <Stack direction=\"row\" spacing={1}>\n {allowSkip && (\n <Button size=\"small\" onClick={onSkip} variant=\"text\">\n {copy.skip}\n </Button>\n )}\n {stepCount > 1 && (\n <IconButton\n size=\"small\"\n onClick={onRestart}\n disabled={currentStep === 0}\n title={copy.restart}\n >\n <RestartIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Stack>\n\n <Stack direction=\"row\" spacing={1}>\n {stepCount > 1 && currentStep > 0 && (\n <Button\n size=\"small\"\n startIcon={<PrevIcon />}\n onClick={onPrev}\n disabled={currentStep === 0}\n data-testid=\"tutorial-prev-button\"\n >\n {copy.previous}\n </Button>\n )}\n\n {!isLastStep ? (\n <Button\n variant=\"contained\"\n size=\"small\"\n endIcon={<NextIcon />}\n onClick={onNext}\n disabled={requiresActionBeforeNext}\n title={requiresActionBeforeNext ? 'Complete the required action first' : ''}\n data-testid=\"tutorial-next-button\"\n >\n {copy.next}\n </Button>\n ) : (\n <Button\n variant=\"contained\"\n size=\"small\"\n endIcon={<CompleteIcon />}\n onClick={onNext}\n sx={{\n background: 'linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%)' }}\n data-testid=\"tutorial-finish-button\"\n >\n {stepCount === 1 ? 'Complete' : 'Finish'}\n </Button>\n )}\n </Stack>\n </Stack>\n);\n\nconst StepDots: React.FC<{ currentStep: number; stepCount: number }> = ({\n currentStep,\n stepCount }) => (\n <StepIndicator data-testid=\"tutorial-step-indicators\">\n {Array.from({ length: stepCount }).map((_, index) => (\n <StepDot\n key={index}\n active={index === currentStep}\n completed={index < currentStep}\n data-testid={`tutorial-indicator-${index}`}\n />\n ))}\n </StepIndicator>\n);\n\n// Title, and the close button when skipping is allowed.\nconst TutorialStepHeader: React.FC<{\n title: React.ReactNode;\n currentStep: number;\n allowSkip: boolean;\n onSkip: () => void;\n}> = ({ title, currentStep, allowSkip, onSkip }) => (\n <Box\n sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}\n >\n <Typography\n id={`tutorial-title-${currentStep}`}\n variant=\"h6\"\n fontWeight=\"bold\"\n sx={{ flex: 1 }}\n data-testid=\"tutorial-step-title\"\n >\n {title}\n </Typography>\n {allowSkip && (\n <IconButton\n size=\"small\"\n onClick={onSkip}\n sx={{ ml: 1, mt: -1, mr: -1 }}\n data-testid=\"tutorial-close-button\"\n >\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Box>\n);\n\nexport const TutorialStepBody: React.FC<{\n copy: TutorialCopy;\n step: TutorialOverlayProps['steps'][number];\n currentStep: number;\n stepCount: number;\n progress: number;\n isLastStep: boolean;\n allowSkip: boolean;\n showProgress: boolean;\n requiresActionBeforeNext?: boolean;\n onNext: () => void;\n onPrev: () => void;\n onSkip: () => void;\n onRestart: () => void;\n}> = ({\n copy,\n step,\n currentStep,\n stepCount,\n progress: _progress,\n isLastStep,\n allowSkip,\n showProgress,\n requiresActionBeforeNext,\n onNext,\n onPrev,\n onSkip,\n onRestart }) => (\n <Stack spacing={2}>\n <TutorialStepHeader\n title={step.title}\n currentStep={currentStep}\n allowSkip={allowSkip}\n onSkip={onSkip}\n />\n\n <Typography\n id={`tutorial-content-${currentStep}`}\n variant=\"body2\"\n color=\"text.secondary\"\n data-testid=\"tutorial-step-content\"\n >\n {step.content}\n </Typography>\n\n {showProgress && (\n <Typography variant=\"caption\" color=\"text.secondary\" align=\"center\">\n {currentStep + 1} of {stepCount}\n </Typography>\n )}\n\n {step.action && (\n <Button\n variant=\"contained\"\n size=\"small\"\n onClick={step.action.onClick}\n sx={{\n background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',\n color: 'white' }}\n >\n {step.action.label}\n </Button>\n )}\n\n <StepDots currentStep={currentStep} stepCount={stepCount} />\n\n <TutorialStepNav\n copy={copy}\n currentStep={currentStep}\n stepCount={stepCount}\n isLastStep={isLastStep}\n allowSkip={allowSkip}\n requiresActionBeforeNext={requiresActionBeforeNext}\n onNext={onNext}\n onPrev={onPrev}\n onSkip={onSkip}\n onRestart={onRestart}\n />\n </Stack>\n);\n\n// Main component\n"],"mappings":"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","names":["alpha","Box","styled","jsx","jsxs","styled","Box","alpha"]}
|