@12-apps/ui 1.0.0 → 1.3.1
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/components-catalog.md +14 -0
- package/package.json +42 -27
- package/src/__tests__/data-grid.test.tsx +125 -0
- package/src/__tests__/package-wiring.test.ts +12 -8
- package/src/__tests__/social-login-button.test.tsx +5 -5
- package/src/__tests__/viewport.test.ts +50 -0
- package/src/charts/index.ts +8 -0
- package/src/components/data-display/Alert/Alert.md +1 -1
- package/src/components/data-display/Alert/Alert.stories.tsx +5 -7
- package/src/components/data-display/Alert/Alert.styles.tsx +255 -0
- package/src/components/data-display/Alert/Alert.test.stories.tsx +11 -13
- package/src/components/data-display/Alert/Alert.tsx +135 -328
- package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +3 -1
- package/src/components/data-display/AlertDialog/AlertDialog.tsx +191 -78
- package/src/components/data-display/AlertDialog/AlertDialog.types.ts +8 -1
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +5 -5
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.tsx +44 -35
- package/src/components/data-display/Avatar/Avatar.stories.tsx +4 -1
- package/src/components/data-display/Avatar/Avatar.test.stories.tsx +5 -3
- package/src/components/data-display/Avatar/Avatar.tsx +154 -450
- package/src/components/data-display/Avatar/Avatar.view.tsx +396 -0
- package/src/components/data-display/Badge/Badge.animations.ts +67 -0
- package/src/components/data-display/Badge/Badge.helpers.ts +74 -0
- package/src/components/data-display/Badge/Badge.stories.tsx +14 -16
- package/src/components/data-display/Badge/Badge.styles.ts +261 -0
- package/src/components/data-display/Badge/Badge.test.stories.tsx +32 -31
- package/src/components/data-display/Badge/Badge.tsx +151 -557
- package/src/components/data-display/Badge/Badge.variants.ts +106 -0
- package/src/components/data-display/Badge/BadgeContent.tsx +107 -0
- package/src/components/data-display/Banner/Banner.stories.tsx +5 -1
- package/src/components/data-display/Banner/Banner.styles.ts +120 -0
- package/src/components/data-display/Banner/Banner.tsx +179 -224
- package/src/components/data-display/Chart/Chart.md +48 -1
- package/src/components/data-display/Chart/Chart.tsx +82 -500
- package/src/components/data-display/Chart/Chart.types.ts +2 -0
- package/src/components/data-display/Chart/ChartComposables.tsx +121 -0
- package/src/components/data-display/Chart/ChartSpec.types.ts +70 -0
- package/src/components/data-display/Chart/SpecChart.stories.tsx +150 -0
- package/src/components/data-display/Chart/SpecChart.test.stories.tsx +56 -0
- package/src/components/data-display/Chart/SpecChart.tsx +53 -0
- package/src/components/data-display/Chart/__tests__/SpecChart.test.tsx +60 -0
- package/src/components/data-display/Chart/__tests__/chart-format.test.ts +43 -0
- package/src/components/data-display/Chart/__tests__/chart-spec.test.ts +119 -0
- package/src/components/data-display/Chart/chart-format.ts +26 -0
- package/src/components/data-display/Chart/chart-internals.ts +148 -0
- package/src/components/data-display/Chart/chart-renderers.tsx +338 -0
- package/src/components/data-display/Chart/chart-spec-registry.ts +74 -0
- package/src/components/data-display/Chart/chart-spec.ts +171 -0
- package/src/components/data-display/Chart/index.ts +30 -0
- package/src/components/data-display/Chip/Chip.helpers.tsx +131 -0
- package/src/components/data-display/Chip/Chip.stories.tsx +2 -1
- package/src/components/data-display/Chip/Chip.test.stories.tsx +11 -8
- package/src/components/data-display/Chip/Chip.tsx +31 -94
- package/src/components/data-display/DataGrid/DataGrid.body.tsx +141 -0
- package/src/components/data-display/DataGrid/DataGrid.cells.tsx +238 -0
- package/src/components/data-display/DataGrid/DataGrid.model.ts +315 -0
- package/src/components/data-display/DataGrid/DataGrid.rows.ts +112 -0
- package/src/components/data-display/DataGrid/DataGrid.states.tsx +102 -0
- package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +6 -12
- package/src/components/data-display/DataGrid/DataGrid.tsx +129 -725
- package/src/components/data-display/DataViews/DataViewsGrid.tsx +187 -0
- package/src/components/data-display/DataViews/DataViewsTableBase.tsx +400 -0
- package/src/components/data-display/DataViews/ManageViewsDialog.tsx +140 -0
- package/src/components/data-display/DataViews/SaveViewModal.tsx +289 -0
- package/src/components/data-display/DataViews/__tests__/DataViewsGrid.test.tsx +271 -0
- package/src/components/data-display/DataViews/__tests__/DataViewsTableBase.test.tsx +134 -0
- package/src/components/data-display/DataViews/__tests__/SaveViewModal.test.tsx +83 -0
- package/src/components/data-display/DataViews/__tests__/data-views-filter.test.ts +115 -0
- package/src/components/data-display/DataViews/__tests__/data-views-preview.test.ts +53 -0
- package/src/components/data-display/DataViews/__tests__/range-pill.test.tsx +114 -0
- package/src/components/data-display/DataViews/base-card.stories.tsx +136 -0
- package/src/components/data-display/DataViews/base-card.tsx +278 -0
- package/src/components/data-display/DataViews/data-views-filter-panel.tsx +184 -0
- package/src/components/data-display/DataViews/data-views-filter.ts +138 -0
- package/src/components/data-display/DataViews/data-views-grid-helpers.tsx +248 -0
- package/src/components/data-display/DataViews/data-views-grid-parts.tsx +400 -0
- package/src/components/data-display/DataViews/data-views-inline-bar.tsx +257 -0
- package/src/components/data-display/DataViews/data-views-layout-context.tsx +176 -0
- package/src/components/data-display/DataViews/data-views-pagination.tsx +31 -0
- package/src/components/data-display/DataViews/data-views-preview.ts +53 -0
- package/src/components/data-display/DataViews/data-views-range-pill.tsx +277 -0
- package/src/components/data-display/DataViews/data-views-table-parts.tsx +150 -0
- package/src/components/data-display/DataViews/data-views-toolbar.tsx +149 -0
- package/src/components/data-display/DataViews/data-views-types.ts +312 -0
- package/src/components/data-display/DataViews/data-views-view-mutations.ts +68 -0
- package/src/components/data-display/DataViews/index.ts +33 -0
- package/src/components/data-display/DataViews/use-data-views-state.ts +349 -0
- package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.hooks.ts +104 -0
- package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.tsx +68 -118
- package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +1 -1
- package/src/components/data-display/DescriptionItem/DescriptionItem.tsx +52 -34
- package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +6 -6
- package/src/components/data-display/EmptyState/EmptyState.tsx +218 -135
- package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +2 -2
- package/src/components/data-display/ErrorState/ErrorState.tsx +83 -55
- package/src/components/data-display/HoverCard/HoverCard.stories.tsx +3 -1
- package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +5 -5
- package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.hooks.ts +99 -0
- package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.styles.ts +87 -0
- package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.tsx +28 -155
- package/src/components/data-display/LazyImage/LazyImage.hooks.ts +203 -0
- package/src/components/data-display/LazyImage/LazyImage.md +1 -1
- package/src/components/data-display/LazyImage/LazyImage.stories.tsx +3 -3
- package/src/components/data-display/LazyImage/LazyImage.tsx +144 -243
- package/src/components/data-display/Lightbox/Lightbox.constants.ts +53 -0
- package/src/components/data-display/Lightbox/Lightbox.helpers.ts +39 -0
- package/src/components/data-display/Lightbox/Lightbox.hooks.ts +259 -0
- package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +28 -35
- package/src/components/data-display/Lightbox/Lightbox.tsx +98 -658
- package/src/components/data-display/Lightbox/LightboxControls.tsx +152 -0
- package/src/components/data-display/Lightbox/LightboxCurrentMedia.tsx +50 -0
- package/src/components/data-display/Lightbox/LightboxMedia.tsx +76 -0
- package/src/components/data-display/Lightbox/LightboxOverlay.tsx +83 -0
- package/src/components/data-display/Lightbox/LightboxStage.tsx +97 -0
- package/src/components/data-display/Lightbox/LightboxThumbnails.tsx +83 -0
- package/src/components/data-display/Lightbox/useLightbox.ts +80 -0
- package/src/components/data-display/LoadingState/LoadingState.helpers.ts +52 -0
- package/src/components/data-display/LoadingState/LoadingState.tsx +117 -87
- package/src/components/data-display/MapPreview/MapControlBar.tsx +116 -0
- package/src/components/data-display/MapPreview/MapDecorations.tsx +155 -0
- package/src/components/data-display/MapPreview/MapLayers.tsx +70 -0
- package/src/components/data-display/MapPreview/MapMarkers.tsx +84 -0
- package/src/components/data-display/MapPreview/MapOverlays.tsx +68 -0
- package/src/components/data-display/MapPreview/MapPreview.constants.ts +19 -0
- package/src/components/data-display/MapPreview/MapPreview.helpers.ts +63 -0
- package/src/components/data-display/MapPreview/MapPreview.hooks.ts +265 -0
- package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +14 -10
- package/src/components/data-display/MapPreview/MapPreview.tsx +52 -882
- package/src/components/data-display/MapPreview/MapPreview.types.ts +8 -1
- package/src/components/data-display/MapPreview/MapSearchBar.tsx +64 -0
- package/src/components/data-display/MapPreview/MapTiles.tsx +70 -0
- package/src/components/data-display/MapPreview/StaticMapView.tsx +63 -0
- package/src/components/data-display/MapPreview/mapProjection.ts +52 -0
- package/src/components/data-display/MapPreview/mapSurface.ts +37 -0
- package/src/components/data-display/MapPreview/useMapPreview.ts +62 -0
- package/src/components/data-display/Popover/Popover.test.stories.tsx +13 -19
- package/src/components/data-display/Progress/Progress.helpers.ts +37 -0
- package/src/components/data-display/Progress/Progress.styles.ts +101 -0
- package/src/components/data-display/Progress/Progress.tsx +185 -213
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +1 -1
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.tsx +1 -1
- package/src/components/data-display/StatCard/StatCard.md +117 -0
- package/src/components/data-display/StatCard/StatCard.stories.tsx +167 -0
- package/src/components/data-display/StatCard/StatCard.test.stories.tsx +240 -0
- package/src/components/data-display/StatCard/StatCard.tsx +236 -0
- package/src/components/data-display/StatCard/StatCard.types.ts +62 -0
- package/src/components/data-display/StatCard/index.ts +7 -0
- package/src/components/data-display/Stepper/Stepper.test.stories.tsx +12 -19
- package/src/components/data-display/Stepper/Stepper.tsx +1 -1
- package/src/components/data-display/Table/Table.helpers.ts +31 -0
- package/src/components/data-display/Table/Table.hooks.ts +161 -0
- package/src/components/data-display/Table/Table.stories.tsx +3 -1
- package/src/components/data-display/Table/Table.styles.ts +223 -0
- package/src/components/data-display/Table/Table.test.stories.tsx +4 -4
- package/src/components/data-display/Table/Table.tsx +291 -748
- package/src/components/data-display/Table/TableParts.hooks.tsx +112 -0
- package/src/components/data-display/Table/TableParts.tsx +298 -0
- package/src/components/data-display/Table/TableStates.tsx +21 -0
- package/src/components/data-display/Timeline/Timeline.stories.tsx +10 -12
- package/src/components/data-display/Timeline/Timeline.test.stories.tsx +30 -44
- package/src/components/data-display/Timeline/Timeline.tsx +23 -284
- package/src/components/data-display/Timeline/TimelineRow.tsx +346 -0
- package/src/components/data-display/TimingDiagram/TimingDiagram.tsx +38 -311
- package/src/components/data-display/TimingDiagram/TimingDiagram.views.tsx +346 -0
- package/src/components/data-display/Tooltip/Tooltip.stories.tsx +4 -1
- package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +44 -58
- package/src/components/data-display/Tooltip/Tooltip.tsx +67 -62
- package/src/components/data-display/index.ts +1 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.hooks.ts +96 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.md +140 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.parts.tsx +154 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.stories.tsx +146 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.test.stories.tsx +114 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.tsx +46 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.types.ts +111 -0
- package/src/components/feedback/ConfirmAction/ConfirmButton.tsx +18 -0
- package/src/components/feedback/ConfirmAction/__tests__/confirm-action.test.tsx +288 -0
- package/src/components/feedback/ConfirmAction/index.ts +16 -0
- package/src/components/feedback/ConfirmAction/with-confirmation.tsx +112 -0
- package/src/components/feedback/Dialog/Dialog.styles.ts +4 -2
- package/src/components/feedback/Dialog/Dialog.tsx +26 -1
- package/src/components/feedback/Dialog/__tests__/dialog-content-spacing.test.tsx +66 -0
- package/src/components/feedback/Modal/Modal.md +1 -1
- package/src/components/feedback/Modal/Modal.stories.tsx +2 -2
- package/src/components/feedback/Sonner/Sonner.tsx +104 -288
- package/src/components/feedback/Sonner/Sonner.types.ts +7 -0
- package/src/components/feedback/Sonner/SonnerToast.tsx +216 -0
- package/src/components/feedback/StackedModal/StackedModal.hooks.ts +226 -0
- package/src/components/feedback/StackedModal/StackedModal.parts.tsx +311 -0
- package/src/components/feedback/StackedModal/StackedModal.stories.tsx +13 -15
- package/src/components/feedback/StackedModal/StackedModal.styles.ts +193 -0
- package/src/components/feedback/StackedModal/StackedModal.tsx +100 -619
- package/src/components/feedback/StackedModal/StackedModal.types.ts +17 -3
- package/src/components/feedback/StackedModal/__tests__/stacked-modal-viewport.test.tsx +104 -0
- package/src/components/feedback/StackedModal/modal-stack.tsx +119 -0
- package/src/components/feedback/Toast/Toast.tsx +92 -81
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.geometry.ts +65 -0
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.hooks.ts +185 -0
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +2 -2
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.tsx +156 -414
- package/src/components/feedback/TutorialOverlay/TutorialStepBody.tsx +255 -0
- package/src/components/feedback/index.ts +1 -0
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.helpers.ts +58 -0
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.hooks.ts +93 -0
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.mapper.ts +57 -0
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +4 -2
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +20 -16
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.tsx +26 -829
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.types.ts +11 -0
- package/src/components/form/AddressAutocomplete/AddressAutocompleteField.tsx +86 -0
- package/src/components/form/AddressAutocomplete/AddressFallbackField.tsx +64 -0
- package/src/components/form/AddressAutocomplete/AddressInputField.tsx +80 -0
- package/src/components/form/AddressAutocomplete/AddressOption.tsx +83 -0
- package/src/components/form/AddressAutocomplete/AddressSuggestionsPaper.tsx +24 -0
- package/src/components/form/AddressAutocomplete/AddressTextField.tsx +43 -0
- package/src/components/form/AddressAutocomplete/mockPlaces.ts +208 -0
- package/src/components/form/AddressAutocomplete/useAddressPredictions.ts +136 -0
- package/src/components/form/AddressAutocomplete/useAddressSelection.ts +113 -0
- package/src/components/form/AddressAutocomplete/useCurrentLocation.ts +116 -0
- package/src/components/form/AddressAutocomplete/useGoogleMapsAPI.ts +75 -0
- package/src/components/form/Button/Button.helpers.ts +36 -0
- package/src/components/form/Button/Button.stories.tsx +4 -1
- package/src/components/form/Button/Button.styles.ts +225 -0
- package/src/components/form/Button/Button.test.stories.tsx +25 -21
- package/src/components/form/Button/Button.tsx +45 -252
- package/src/components/form/Calendar/Calendar.dates.ts +100 -0
- package/src/components/form/Calendar/Calendar.helpers.ts +32 -0
- package/src/components/form/Calendar/Calendar.hooks.ts +278 -0
- package/src/components/form/Calendar/Calendar.keyboard.ts +32 -0
- package/src/components/form/Calendar/Calendar.selection.ts +156 -0
- package/src/components/form/Calendar/Calendar.test.stories.tsx +33 -34
- package/src/components/form/Calendar/Calendar.tsx +63 -551
- package/src/components/form/Calendar/Calendar.types.ts +16 -0
- package/src/components/form/Calendar/CalendarDay.tsx +127 -0
- package/src/components/form/Calendar/CalendarDayCell.tsx +52 -0
- package/src/components/form/Calendar/CalendarMonth.tsx +128 -0
- package/src/components/form/CepField/CepField.md +138 -0
- package/src/components/form/CepField/CepField.stories.tsx +138 -0
- package/src/components/form/CepField/CepField.test.stories.tsx +281 -0
- package/src/components/form/CepField/CepField.tsx +211 -0
- package/src/components/form/CepField/CepField.types.ts +73 -0
- package/src/components/form/CepField/index.ts +2 -0
- package/src/components/form/Checkbox/Checkbox.helpers.ts +28 -0
- package/src/components/form/Checkbox/Checkbox.tsx +19 -16
- package/src/components/form/CodeEditor/CodeEditor.helpers.ts +45 -0
- package/src/components/form/CodeEditor/CodeEditor.hooks.ts +104 -0
- package/src/components/form/CodeEditor/CodeEditor.monaco.ts +109 -0
- package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +17 -18
- package/src/components/form/CodeEditor/CodeEditor.tsx +81 -330
- package/src/components/form/CodeEditor/CodeEditorToolbar.tsx +168 -0
- package/src/components/form/Command/Command.hooks.ts +207 -0
- package/src/components/form/Command/Command.parts.tsx +58 -0
- package/src/components/form/Command/Command.styles.ts +83 -0
- package/src/components/form/Command/Command.tsx +61 -270
- package/src/components/form/CreatableSelect/CreatableSelect.md +1 -1
- package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +1 -1
- package/src/components/form/CreatableSelect/CreatableSelect.tsx +152 -71
- package/src/components/form/CreatableSelect/CreatableSelect.types.ts +13 -0
- package/src/components/form/HeaderButton/HeaderButton.tsx +80 -0
- package/src/components/form/HeaderButton/index.ts +2 -0
- package/src/components/form/Input/Input.stories.tsx +5 -1
- package/src/components/form/Input/Input.styles.ts +176 -0
- package/src/components/form/Input/Input.test.stories.tsx +30 -23
- package/src/components/form/Input/Input.tsx +71 -211
- package/src/components/form/Input/Input.types.ts +11 -0
- package/src/components/form/InputOTP/InputOTP.test.stories.tsx +9 -17
- package/src/components/form/Menubar/Menubar.test.stories.tsx +4 -8
- package/src/components/form/PasswordStrength/PasswordStrength.helpers.tsx +117 -0
- package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +3 -3
- package/src/components/form/PasswordStrength/PasswordStrength.tsx +202 -255
- package/src/components/form/PhoneInput/PhoneInput.hooks.ts +134 -0
- package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +4 -4
- package/src/components/form/PhoneInput/PhoneInput.tsx +279 -292
- package/src/components/form/PhoneInput/countries.ts +54 -0
- package/src/components/form/PhoneInput/phone.ts +47 -0
- package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +9 -9
- package/src/components/form/RichTextEditor/RichTextEditor.dom.ts +124 -0
- package/src/components/form/RichTextEditor/RichTextEditor.format.ts +61 -0
- package/src/components/form/RichTextEditor/RichTextEditor.hooks.ts +142 -0
- package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +5 -12
- package/src/components/form/RichTextEditor/RichTextEditor.tsx +98 -410
- package/src/components/form/RichTextEditor/RichTextEditorToolbar.tsx +187 -0
- package/src/components/form/SearchPalette/SearchPalette.parts.tsx +22 -0
- package/src/components/form/SearchPalette/SearchPalette.tsx +13 -9
- package/src/components/form/Select/Select.test.stories.tsx +35 -27
- package/src/components/form/Slider/Slider.test.stories.tsx +9 -11
- package/src/components/form/Switch/Switch.md +2 -1
- package/src/components/form/Switch/Switch.test.stories.tsx +6 -6
- package/src/components/form/Textarea/Textarea.styles.ts +143 -0
- package/src/components/form/Textarea/Textarea.test.stories.tsx +20 -26
- package/src/components/form/Textarea/Textarea.tsx +114 -535
- package/src/components/form/Textarea/TextareaRichEditor.tsx +377 -0
- package/src/components/form/Toggle/Toggle.styles.ts +211 -0
- package/src/components/form/Toggle/Toggle.test.stories.tsx +19 -27
- package/src/components/form/Toggle/Toggle.tsx +10 -185
- package/src/components/form/UploadButton/UploadButton.hooks.ts +323 -0
- package/src/components/form/UploadButton/UploadButton.parts.tsx +210 -0
- package/src/components/form/UploadButton/UploadButton.stories.tsx +2 -1
- package/src/components/form/UploadButton/UploadButton.test.stories.tsx +123 -4
- package/src/components/form/UploadButton/UploadButton.tsx +76 -305
- package/src/components/form/UploadButton/UploadButton.types.ts +16 -0
- package/src/components/form/index.ts +1 -0
- package/src/components/form/total-form/Fields/CepField.tsx +143 -0
- package/src/components/form/total-form/Fields/ToggleField.tsx +61 -0
- package/src/components/form/total-form/Fields/index.ts +4 -0
- package/src/components/form/total-form/FormContainer.tsx +3 -3
- package/src/components/form/total-form/SubmitButton.tsx +25 -2
- package/src/components/form/total-form/total-form.test.tsx +118 -1
- package/src/components/layout/Accordion/Accordion.md +1 -1
- package/src/components/layout/Accordion/Accordion.stories.tsx +5 -1
- package/src/components/layout/Accordion/Accordion.styles.ts +80 -0
- package/src/components/layout/Accordion/Accordion.test.stories.tsx +32 -50
- package/src/components/layout/Accordion/Accordion.tsx +2 -75
- package/src/components/layout/Card/Card.helpers.ts +30 -0
- package/src/components/layout/Card/Card.stories.tsx +9 -11
- package/src/components/layout/Card/Card.styles.ts +182 -0
- package/src/components/layout/Card/Card.test.stories.tsx +46 -46
- package/src/components/layout/Card/Card.tsx +24 -241
- package/src/components/layout/CardGrid/CardGrid.md +96 -0
- package/src/components/layout/CardGrid/CardGrid.tsx +140 -0
- package/src/components/layout/CardGrid/__tests__/CardGrid.test.tsx +92 -0
- package/src/components/layout/CardGrid/index.ts +2 -0
- package/src/components/layout/Collapsible/Collapsible.helpers.ts +83 -0
- package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +7 -3
- package/src/components/layout/Collapsible/Collapsible.tsx +111 -107
- package/src/components/layout/Container/Container.test.stories.tsx +11 -16
- package/src/components/layout/ContentToolbar/ColumnsMenu.tsx +1 -1
- package/src/components/layout/ContentToolbar/ContentToolbar.tsx +120 -44
- package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +9 -0
- package/src/components/layout/ContentToolbar/FilterTrigger.tsx +1 -1
- package/src/components/layout/ContentToolbar/MultiSelectDropdown.tsx +58 -43
- package/src/components/layout/ContentToolbar/MultiSelectTriggers.tsx +139 -0
- package/src/components/layout/ContentToolbar/SavedViewsMenu.tsx +10 -3
- package/src/components/layout/ContentToolbar/SortByDropdown.tsx +35 -11
- package/src/components/layout/ContentToolbar/ViewSelector.tsx +5 -6
- package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +21 -0
- package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +27 -1
- package/src/components/layout/Dashboard/Dashboard.tsx +27 -8
- package/src/components/layout/Dashboard/DashboardParts.tsx +12 -19
- package/src/components/layout/Dashboard/index.ts +2 -1
- package/src/components/layout/Drawer/Drawer.stories.tsx +8 -10
- package/src/components/layout/Drawer/Drawer.test.stories.tsx +18 -14
- package/src/components/layout/Drawer/Drawer.tsx +67 -53
- package/src/components/layout/Resizable/Resizable.helpers.ts +133 -0
- package/src/components/layout/Resizable/Resizable.hooks.ts +68 -0
- package/src/components/layout/Resizable/Resizable.tsx +38 -153
- package/src/components/layout/ScrollArea/ScrollArea.helpers.ts +51 -0
- package/src/components/layout/ScrollArea/ScrollArea.styles.ts +248 -0
- package/src/components/layout/ScrollArea/ScrollArea.tsx +183 -374
- package/src/components/layout/ScrollArea/ScrollAreaContent.tsx +70 -0
- package/src/components/layout/ScrollArea/ScrollViewport.tsx +90 -0
- package/src/components/layout/Separator/Separator.styles.ts +128 -0
- package/src/components/layout/Separator/Separator.test.stories.tsx +3 -12
- package/src/components/layout/Separator/Separator.tsx +6 -132
- package/src/components/layout/SettingsLayout/SettingsLayout.parts.tsx +2 -1
- package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +6 -8
- package/src/components/layout/Sidebar/Sidebar.stories.tsx +10 -12
- package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +35 -37
- package/src/components/layout/Skeleton/Skeleton.helpers.ts +33 -0
- package/src/components/layout/Skeleton/Skeleton.styles.ts +114 -0
- package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +3 -3
- package/src/components/layout/Skeleton/Skeleton.tsx +67 -155
- package/src/components/layout/TableFilter/TableFilter.tsx +2 -1
- package/src/components/navigation/Breadcrumbs/BreadcrumbEntry.tsx +305 -0
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.md +2 -1
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +12 -14
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.styles.tsx +212 -0
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +62 -61
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +116 -429
- package/src/components/navigation/CommandPalette/CommandPalette.helpers.ts +82 -0
- package/src/components/navigation/CommandPalette/CommandPalette.hooks.ts +202 -0
- package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +3 -1
- package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +3 -5
- package/src/components/navigation/CommandPalette/CommandPalette.tsx +108 -341
- package/src/components/navigation/CommandPalette/CommandPaletteResults.tsx +182 -0
- package/src/components/navigation/CommandPalette/ShortcutChip.tsx +18 -0
- package/src/components/navigation/ContextMenu/ContextMenu.md +3 -1
- package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +4 -1
- package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +19 -24
- package/src/components/navigation/ContextMenu/ContextMenu.tsx +70 -54
- package/src/components/navigation/DropdownMenu/DropdownMenu.md +3 -1
- package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +17 -19
- package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +26 -26
- package/src/components/navigation/DropdownMenu/DropdownMenu.tsx +189 -111
- package/src/components/navigation/NavigationMenu/NavigationMegaSection.tsx +66 -0
- package/src/components/navigation/NavigationMenu/NavigationMenu.md +7 -2
- package/src/components/navigation/NavigationMenu/NavigationMenu.shell.tsx +218 -0
- package/src/components/navigation/NavigationMenu/NavigationMenu.styles.ts +223 -0
- package/src/components/navigation/NavigationMenu/NavigationMenu.tsx +119 -808
- package/src/components/navigation/NavigationMenu/NavigationMenuItem.hooks.ts +126 -0
- package/src/components/navigation/NavigationMenu/NavigationMenuItem.tsx +352 -0
- package/src/components/navigation/NavigationMenu/NavigationStandardBody.tsx +148 -0
- package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +15 -17
- package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +27 -23
- package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +11 -13
- package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +9 -11
- package/src/components/navigation/Pagination/Pagination.helpers.tsx +85 -0
- package/src/components/navigation/Pagination/Pagination.md +2 -1
- package/src/components/navigation/Pagination/Pagination.stories.tsx +4 -6
- package/src/components/navigation/Pagination/Pagination.styles.ts +135 -0
- package/src/components/navigation/Pagination/Pagination.tsx +178 -313
- package/src/components/navigation/Pagination/PaginationParts.tsx +81 -0
- package/src/components/navigation/Tabs/Tabs.md +3 -1
- package/src/components/navigation/Tabs/Tabs.stories.tsx +21 -23
- package/src/components/navigation/Tabs/Tabs.styles.ts +163 -0
- package/src/components/navigation/Tabs/Tabs.test.stories.tsx +37 -37
- package/src/components/navigation/Tabs/Tabs.tsx +192 -361
- package/src/components/navigation/Tabs/TabsPanel.tsx +100 -0
- package/src/components/typography/Blockquote/Blockquote.tsx +1 -1
- package/src/components/typography/Code/Code.test.stories.tsx +5 -5
- package/src/components/typography/Code/Code.tsx +74 -49
- package/src/components/typography/Heading/Heading.test.stories.tsx +8 -8
- package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +5 -12
- package/src/components/typography/Text/Text.tsx +84 -77
- package/src/components/utility/AnimatedIcon/AnimatedIcon.md +4 -4
- package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +19 -21
- package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +19 -12
- package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +9 -9
- package/src/components/utility/InfiniteScroll/InfiniteScroll.hooks.ts +118 -0
- package/src/components/utility/InfiniteScroll/InfiniteScroll.parts.tsx +54 -0
- package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +12 -9
- package/src/components/utility/InfiniteScroll/InfiniteScroll.tsx +29 -148
- package/src/components/utility/InstallPrompt/InstallPrompt.helpers.ts +124 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.md +113 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.stories.tsx +118 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.styles.ts +50 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.test.stories.tsx +83 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.tsx +192 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.types.ts +78 -0
- package/src/components/utility/InstallPrompt/__tests__/InstallPrompt.ios.test.tsx +65 -0
- package/src/components/utility/InstallPrompt/__tests__/usePwaInstall.test.tsx +271 -0
- package/src/components/utility/InstallPrompt/index.ts +10 -0
- package/src/components/utility/InstallPrompt/usePwaInstall.ts +171 -0
- package/src/components/utility/Transition/Transition.helpers.ts +40 -0
- package/src/components/utility/Transition/Transition.tsx +17 -68
- package/src/components/utility/VirtualList/VirtualList.hooks.ts +319 -0
- package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +49 -38
- package/src/components/utility/VirtualList/VirtualList.tsx +110 -315
- package/src/components/utility/WorkflowStep/WorkflowStep.helpers.ts +151 -0
- package/src/components/utility/WorkflowStep/WorkflowStep.parts.tsx +371 -0
- package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +9 -11
- package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +7 -7
- package/src/components/utility/WorkflowStep/WorkflowStep.tsx +51 -449
- package/src/components/utility/WorkflowStep/WorkflowStepRow.tsx +96 -0
- package/src/components/utility/index.ts +1 -0
- package/src/mui/Link.ts +2 -0
- package/src/utils/index.ts +2 -1
- package/src/utils/viewport.ts +65 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Box, CircularProgress, Fade } from '@mui/material';
|
|
2
|
+
import { styled } from '@mui/material/styles';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import type { TabPanelProps } from './Tabs.types';
|
|
6
|
+
|
|
7
|
+
const TabPanel = styled(Box, {
|
|
8
|
+
shouldForwardProp: (prop) => !['animate', 'persist'].includes(prop as string),
|
|
9
|
+
})<{ animate?: boolean; persist?: boolean }>(({ animate, persist }) => ({
|
|
10
|
+
width: '100%',
|
|
11
|
+
|
|
12
|
+
...(animate && {
|
|
13
|
+
transition: 'all 0.3s ease-in-out',
|
|
14
|
+
}),
|
|
15
|
+
|
|
16
|
+
...(persist && {
|
|
17
|
+
'&[hidden]': {
|
|
18
|
+
display: 'none !important',
|
|
19
|
+
},
|
|
20
|
+
}),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
const LoadingContainer = styled(Box)(({ theme }) => ({
|
|
24
|
+
display: 'flex',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
justifyContent: 'center',
|
|
27
|
+
minHeight: 200,
|
|
28
|
+
color: theme.palette.text.secondary,
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
// A loading panel shows the caller's placeholder, or a spinner if there isn't one.
|
|
32
|
+
const panelContent = (
|
|
33
|
+
loading: boolean,
|
|
34
|
+
loadingComponent: React.ReactNode,
|
|
35
|
+
children: React.ReactNode,
|
|
36
|
+
): React.ReactNode => {
|
|
37
|
+
if (!loading) return children;
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
loadingComponent || (
|
|
41
|
+
<LoadingContainer>
|
|
42
|
+
<CircularProgress size={32} />
|
|
43
|
+
</LoadingContainer>
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const panelTestId = (dataTestId: string | undefined, index: number): string =>
|
|
49
|
+
dataTestId ? `${dataTestId}-panel-${index}` : `tabs-panel-${index}`;
|
|
50
|
+
|
|
51
|
+
export const CustomTabPanel: React.FC<TabPanelProps & { dataTestId?: string; index: number }> = ({
|
|
52
|
+
children,
|
|
53
|
+
id,
|
|
54
|
+
value,
|
|
55
|
+
animate = false,
|
|
56
|
+
animationDuration = 300,
|
|
57
|
+
persist = false,
|
|
58
|
+
loading = false,
|
|
59
|
+
loadingComponent,
|
|
60
|
+
className,
|
|
61
|
+
dataTestId,
|
|
62
|
+
index,
|
|
63
|
+
...props
|
|
64
|
+
}) => {
|
|
65
|
+
const isActive = value === id;
|
|
66
|
+
const shouldRender = isActive || persist;
|
|
67
|
+
|
|
68
|
+
if (!shouldRender) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const content = panelContent(loading, loadingComponent, children);
|
|
73
|
+
const testId = panelTestId(dataTestId, index);
|
|
74
|
+
|
|
75
|
+
const panel = (
|
|
76
|
+
<TabPanel
|
|
77
|
+
role="tabpanel"
|
|
78
|
+
hidden={!isActive}
|
|
79
|
+
id={`tabpanel-${id}`}
|
|
80
|
+
aria-labelledby={`tab-${id}`}
|
|
81
|
+
animate={animate}
|
|
82
|
+
persist={persist}
|
|
83
|
+
className={className}
|
|
84
|
+
data-testid={testId}
|
|
85
|
+
{...props}
|
|
86
|
+
>
|
|
87
|
+
{content}
|
|
88
|
+
</TabPanel>
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// The animated and plain panels are the same element; only the Fade wrapper
|
|
92
|
+
// differs.
|
|
93
|
+
if (!animate) return panel;
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<Fade in={isActive} timeout={animationDuration}>
|
|
97
|
+
{panel}
|
|
98
|
+
</Fade>
|
|
99
|
+
);
|
|
100
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Box, createTheme,ThemeProvider, Typography } from '@mui/material';
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import { expect, fn,userEvent, waitFor, within } from 'storybook/test';
|
|
4
|
+
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
5
5
|
|
|
6
6
|
import { Code } from './Code';
|
|
7
7
|
|
|
@@ -189,8 +189,8 @@ export const KeyboardNavigation: Story = {
|
|
|
189
189
|
const copyButton = canvas.getByRole('button', { name: /copy code/i });
|
|
190
190
|
|
|
191
191
|
// Focus the copy button
|
|
192
|
-
|
|
193
|
-
expect(copyButton).toHaveFocus();
|
|
192
|
+
await userEvent.click(copyButton);
|
|
193
|
+
await waitFor(() => expect(copyButton).toHaveFocus());
|
|
194
194
|
|
|
195
195
|
// Test Enter key
|
|
196
196
|
await userEvent.keyboard('{Enter}');
|
|
@@ -213,8 +213,8 @@ export const KeyboardNavigation: Story = {
|
|
|
213
213
|
|
|
214
214
|
// Focus the first button (which should be the copy button)
|
|
215
215
|
const copyButton = buttons[0];
|
|
216
|
-
|
|
217
|
-
expect(copyButton).toHaveFocus();
|
|
216
|
+
await userEvent.click(copyButton);
|
|
217
|
+
await waitFor(() => expect(copyButton).toHaveFocus());
|
|
218
218
|
|
|
219
219
|
// Verify that keyboard navigation works by checking the button is focusable
|
|
220
220
|
expect(copyButton).toHaveAttribute('tabindex');
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Check from '@mui/icons-material/Check';
|
|
2
|
+
import ContentCopy from '@mui/icons-material/ContentCopy';
|
|
2
3
|
import { alpha,Box, IconButton, Tooltip } from '@mui/material';
|
|
3
4
|
import { styled } from '@mui/material/styles';
|
|
4
5
|
import React, { useState } from 'react';
|
|
@@ -139,6 +140,73 @@ const LanguageLabel = styled(Box)(({ theme }) => ({
|
|
|
139
140
|
boxShadow: theme.palette.mode === 'light' ? theme.shadows[1] : 'none',
|
|
140
141
|
}));
|
|
141
142
|
|
|
143
|
+
// Renders each source line beside a gutter number. Keys combine the line number
|
|
144
|
+
// with a slice of the content and its length, so editing one line in place does
|
|
145
|
+
// not reshuffle the keys of the lines around it.
|
|
146
|
+
const renderNumberedLines = (source: string) =>
|
|
147
|
+
source.split('\n').map((line, index) => {
|
|
148
|
+
const stableKey = `line-${index + 1}-${line.slice(0, 10).replace(/\s+/g, '')}-${line.length}`;
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<div key={stableKey} style={{ display: 'flex' }}>
|
|
152
|
+
<span
|
|
153
|
+
style={{
|
|
154
|
+
display: 'inline-block',
|
|
155
|
+
minWidth: '3em',
|
|
156
|
+
opacity: 0.5,
|
|
157
|
+
userSelect: 'none',
|
|
158
|
+
marginRight: '1em',
|
|
159
|
+
textAlign: 'right',
|
|
160
|
+
}}
|
|
161
|
+
>
|
|
162
|
+
{index + 1}
|
|
163
|
+
</span>
|
|
164
|
+
<span>{line}</span>
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Only block-ish variants get a language label or a copy affordance.
|
|
170
|
+
const resolveCodeFlags = (
|
|
171
|
+
variant: CodeProps['variant'],
|
|
172
|
+
copyable: boolean,
|
|
173
|
+
language: CodeProps['language'],
|
|
174
|
+
) => {
|
|
175
|
+
const isBlock = variant === 'block' || variant === 'highlight';
|
|
176
|
+
return {
|
|
177
|
+
isBlock,
|
|
178
|
+
showCopy: copyable && isBlock,
|
|
179
|
+
showLanguage: Boolean(language) && isBlock,
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Owns its own "just copied" flash. Keeping it here rather than inline in Code
|
|
184
|
+
// means the copied/not-copied branches do not count against the main render, and
|
|
185
|
+
// the flash re-renders only the button. Non-string children are still a no-op on
|
|
186
|
+
// click, exactly as before.
|
|
187
|
+
const CodeCopyButton: React.FC<{ source: React.ReactNode }> = ({ source }) => {
|
|
188
|
+
const [copied, setCopied] = useState(false);
|
|
189
|
+
|
|
190
|
+
const handleCopy = async () => {
|
|
191
|
+
if (typeof source !== 'string') return;
|
|
192
|
+
try {
|
|
193
|
+
await navigator.clipboard.writeText(source);
|
|
194
|
+
setCopied(true);
|
|
195
|
+
window.setTimeout(() => setCopied(false), 2000);
|
|
196
|
+
} catch {
|
|
197
|
+
// Silently fail if clipboard access is denied
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
<Tooltip title={copied ? 'Copied!' : 'Copy code'}>
|
|
203
|
+
<CopyButton onClick={handleCopy} size="small" color={copied ? 'success' : 'default'}>
|
|
204
|
+
{copied ? <Check /> : <ContentCopy />}
|
|
205
|
+
</CopyButton>
|
|
206
|
+
</Tooltip>
|
|
207
|
+
);
|
|
208
|
+
};
|
|
209
|
+
|
|
142
210
|
export const Code = React.forwardRef<HTMLElement, CodeProps>(
|
|
143
211
|
(
|
|
144
212
|
{
|
|
@@ -152,23 +220,7 @@ export const Code = React.forwardRef<HTMLElement, CodeProps>(
|
|
|
152
220
|
},
|
|
153
221
|
ref,
|
|
154
222
|
) => {
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
const handleCopy = async () => {
|
|
158
|
-
if (typeof children === 'string') {
|
|
159
|
-
try {
|
|
160
|
-
await navigator.clipboard.writeText(children);
|
|
161
|
-
setCopied(true);
|
|
162
|
-
window.setTimeout(() => setCopied(false), 2000);
|
|
163
|
-
} catch {
|
|
164
|
-
// Silently fail if clipboard access is denied
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
const isBlock = variant === 'block' || variant === 'highlight';
|
|
170
|
-
const shouldShowCopy = copyable && isBlock;
|
|
171
|
-
const shouldShowLanguage = language && isBlock;
|
|
223
|
+
const { isBlock, showCopy, showLanguage } = resolveCodeFlags(variant, copyable, language);
|
|
172
224
|
|
|
173
225
|
// Process children for line numbers if needed
|
|
174
226
|
const processedChildren = React.useMemo(() => {
|
|
@@ -176,28 +228,7 @@ export const Code = React.forwardRef<HTMLElement, CodeProps>(
|
|
|
176
228
|
return children;
|
|
177
229
|
}
|
|
178
230
|
|
|
179
|
-
return children
|
|
180
|
-
// Use line content hash + line number for more stable keys
|
|
181
|
-
const stableKey = `line-${index + 1}-${line.slice(0, 10).replace(/\s+/g, '')}-${line.length}`;
|
|
182
|
-
|
|
183
|
-
return (
|
|
184
|
-
<div key={stableKey} style={{ display: 'flex' }}>
|
|
185
|
-
<span
|
|
186
|
-
style={{
|
|
187
|
-
display: 'inline-block',
|
|
188
|
-
minWidth: '3em',
|
|
189
|
-
opacity: 0.5,
|
|
190
|
-
userSelect: 'none',
|
|
191
|
-
marginRight: '1em',
|
|
192
|
-
textAlign: 'right',
|
|
193
|
-
}}
|
|
194
|
-
>
|
|
195
|
-
{index + 1}
|
|
196
|
-
</span>
|
|
197
|
-
<span>{line}</span>
|
|
198
|
-
</div>
|
|
199
|
-
);
|
|
200
|
-
});
|
|
231
|
+
return renderNumberedLines(children);
|
|
201
232
|
}, [children, lineNumbers, isBlock]);
|
|
202
233
|
|
|
203
234
|
return (
|
|
@@ -206,20 +237,14 @@ export const Code = React.forwardRef<HTMLElement, CodeProps>(
|
|
|
206
237
|
component={variant === 'inline' ? 'span' : 'div'}
|
|
207
238
|
customVariant={variant}
|
|
208
239
|
customSize={size}
|
|
209
|
-
copyable={
|
|
240
|
+
copyable={showCopy}
|
|
210
241
|
{...props}
|
|
211
242
|
>
|
|
212
|
-
{
|
|
243
|
+
{showLanguage && <LanguageLabel>{language}</LanguageLabel>}
|
|
213
244
|
|
|
214
245
|
<StyledCode>{processedChildren}</StyledCode>
|
|
215
246
|
|
|
216
|
-
{
|
|
217
|
-
<Tooltip title={copied ? 'Copied!' : 'Copy code'}>
|
|
218
|
-
<CopyButton onClick={handleCopy} size="small" color={copied ? 'success' : 'default'}>
|
|
219
|
-
{copied ? <Check /> : <ContentCopy />}
|
|
220
|
-
</CopyButton>
|
|
221
|
-
</Tooltip>
|
|
222
|
-
)}
|
|
247
|
+
{showCopy && <CodeCopyButton source={children} />}
|
|
223
248
|
</StyledCodeContainer>
|
|
224
249
|
);
|
|
225
250
|
},
|
|
@@ -89,10 +89,10 @@ const FocusManagementComponent = () => {
|
|
|
89
89
|
h3: React.useRef<globalThis.HTMLHeadingElement>(null),
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
-
const focusHeading = (level: string) => {
|
|
92
|
+
const focusHeading = async (level: string) => {
|
|
93
93
|
const ref = headingRefs[level as keyof typeof headingRefs];
|
|
94
94
|
if (ref.current) {
|
|
95
|
-
ref.current
|
|
95
|
+
await userEvent.click(ref.current);
|
|
96
96
|
setActiveHeading(level);
|
|
97
97
|
}
|
|
98
98
|
};
|
|
@@ -342,21 +342,21 @@ export const KeyboardNavigation: Story = {
|
|
|
342
342
|
|
|
343
343
|
// Tab to first heading
|
|
344
344
|
await userEvent.tab();
|
|
345
|
-
expect(h1).toHaveFocus();
|
|
345
|
+
await waitFor(() => expect(h1).toHaveFocus());
|
|
346
346
|
await waitFor(() => {
|
|
347
347
|
expect(focusDisplay).toHaveTextContent('Focused: h1');
|
|
348
348
|
});
|
|
349
349
|
|
|
350
350
|
// Tab to second heading
|
|
351
351
|
await userEvent.tab();
|
|
352
|
-
expect(h2).toHaveFocus();
|
|
352
|
+
await waitFor(() => expect(h2).toHaveFocus());
|
|
353
353
|
await waitFor(() => {
|
|
354
354
|
expect(focusDisplay).toHaveTextContent('Focused: h2');
|
|
355
355
|
});
|
|
356
356
|
|
|
357
357
|
// Tab to third heading
|
|
358
358
|
await userEvent.tab();
|
|
359
|
-
expect(h3).toHaveFocus();
|
|
359
|
+
await waitFor(() => expect(h3).toHaveFocus());
|
|
360
360
|
await waitFor(() => {
|
|
361
361
|
expect(focusDisplay).toHaveTextContent('Focused: h3');
|
|
362
362
|
});
|
|
@@ -433,21 +433,21 @@ export const FocusManagement: Story = {
|
|
|
433
433
|
|
|
434
434
|
// Focus H1
|
|
435
435
|
await userEvent.click(focusH1Btn);
|
|
436
|
-
expect(h1).toHaveFocus();
|
|
436
|
+
await waitFor(() => expect(h1).toHaveFocus());
|
|
437
437
|
await waitFor(() => {
|
|
438
438
|
expect(activeDisplay).toHaveTextContent('Active: h1');
|
|
439
439
|
});
|
|
440
440
|
|
|
441
441
|
// Focus H2
|
|
442
442
|
await userEvent.click(focusH2Btn);
|
|
443
|
-
expect(h2).toHaveFocus();
|
|
443
|
+
await waitFor(() => expect(h2).toHaveFocus());
|
|
444
444
|
await waitFor(() => {
|
|
445
445
|
expect(activeDisplay).toHaveTextContent('Active: h2');
|
|
446
446
|
});
|
|
447
447
|
|
|
448
448
|
// Focus H3
|
|
449
449
|
await userEvent.click(focusH3Btn);
|
|
450
|
-
expect(h3).toHaveFocus();
|
|
450
|
+
await waitFor(() => expect(h3).toHaveFocus());
|
|
451
451
|
await waitFor(() => {
|
|
452
452
|
expect(activeDisplay).toHaveTextContent('Active: h3');
|
|
453
453
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { expect,within } from 'storybook/test';
|
|
2
|
+
import { expect, userEvent, waitFor, within } from 'storybook/test';
|
|
3
3
|
|
|
4
4
|
import { Paragraph } from './Paragraph';
|
|
5
5
|
|
|
@@ -37,8 +37,8 @@ export const KeyboardNavigation: Story = {
|
|
|
37
37
|
const paragraph = canvas.getByText(sampleText);
|
|
38
38
|
|
|
39
39
|
// Paragraph should not be focusable by default
|
|
40
|
-
|
|
41
|
-
expect(paragraph).not.toHaveFocus();
|
|
40
|
+
await userEvent.click(paragraph);
|
|
41
|
+
await waitFor(() => expect(paragraph).not.toHaveFocus());
|
|
42
42
|
},
|
|
43
43
|
};
|
|
44
44
|
|
|
@@ -67,8 +67,8 @@ export const FocusManagement: Story = {
|
|
|
67
67
|
const paragraph = canvas.getByText(sampleText);
|
|
68
68
|
|
|
69
69
|
// When tabIndex is set, paragraph should be focusable
|
|
70
|
-
|
|
71
|
-
expect(paragraph).toHaveFocus();
|
|
70
|
+
await userEvent.click(paragraph);
|
|
71
|
+
await waitFor(() => expect(paragraph).toHaveFocus());
|
|
72
72
|
},
|
|
73
73
|
};
|
|
74
74
|
|
|
@@ -152,16 +152,9 @@ export const Performance: Story = {
|
|
|
152
152
|
play: async ({ canvasElement }) => {
|
|
153
153
|
const canvas = within(canvasElement);
|
|
154
154
|
|
|
155
|
-
const startTime = Date.now();
|
|
156
|
-
|
|
157
155
|
const paragraph = canvas.getByText(sampleText);
|
|
158
156
|
expect(paragraph).toBeInTheDocument();
|
|
159
157
|
|
|
160
|
-
const endTime = Date.now();
|
|
161
|
-
const renderTime = endTime - startTime;
|
|
162
|
-
|
|
163
|
-
// Paragraph should render quickly (under 100ms)
|
|
164
|
-
expect(renderTime).toBeLessThan(100);
|
|
165
158
|
},
|
|
166
159
|
};
|
|
167
160
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import type { Theme} from '@mui/material';
|
|
3
|
+
import type { CSSObject, Theme } from '@mui/material';
|
|
4
4
|
import { alpha,Typography } from '@mui/material';
|
|
5
5
|
import { styled } from '@mui/material/styles';
|
|
6
6
|
import React from 'react';
|
|
@@ -26,6 +26,86 @@ const getColorFromTheme = (theme: Theme, color: string) => {
|
|
|
26
26
|
return colorMap[color] || theme.palette.text.primary;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
const SIZE_MAP: Record<string, { fontSize: string; lineHeight: number }> = {
|
|
30
|
+
xs: { fontSize: '0.75rem', lineHeight: 1.2 },
|
|
31
|
+
sm: { fontSize: '0.875rem', lineHeight: 1.3 },
|
|
32
|
+
md: { fontSize: '1rem', lineHeight: 1.5 },
|
|
33
|
+
lg: { fontSize: '1.125rem', lineHeight: 1.4 },
|
|
34
|
+
xl: { fontSize: '1.25rem', lineHeight: 1.3 },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const WEIGHT_MAP: Record<string, number> = {
|
|
38
|
+
light: 300,
|
|
39
|
+
normal: 400,
|
|
40
|
+
medium: 500,
|
|
41
|
+
semibold: 600,
|
|
42
|
+
bold: 700,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
interface TextStyleArgs {
|
|
46
|
+
theme: Theme;
|
|
47
|
+
customVariant?: string;
|
|
48
|
+
customColor?: string;
|
|
49
|
+
customSize?: string;
|
|
50
|
+
customWeight?: string;
|
|
51
|
+
italic?: boolean;
|
|
52
|
+
underline?: boolean;
|
|
53
|
+
strikethrough?: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// underline and strikethrough combine into one declaration rather than one
|
|
57
|
+
// winning over the other.
|
|
58
|
+
const decorationFor = (underline?: boolean, strikethrough?: boolean): string =>
|
|
59
|
+
[underline && 'underline', strikethrough && 'line-through'].filter(Boolean).join(' ') || 'none';
|
|
60
|
+
|
|
61
|
+
const baseTextStyles = (theme: Theme, a: TextStyleArgs): CSSObject => ({
|
|
62
|
+
color: getColorFromTheme(theme, a.customColor ?? 'neutral'),
|
|
63
|
+
fontSize: SIZE_MAP[a.customSize ?? 'md']?.fontSize,
|
|
64
|
+
lineHeight: SIZE_MAP[a.customSize ?? 'md']?.lineHeight,
|
|
65
|
+
fontWeight: WEIGHT_MAP[a.customWeight ?? 'normal'],
|
|
66
|
+
fontStyle: a.italic ? 'italic' : 'normal',
|
|
67
|
+
textDecoration: decorationFor(a.underline, a.strikethrough),
|
|
68
|
+
transition: 'all 0.2s ease',
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Captions and code shrink relative to the body scale, but only at the default
|
|
72
|
+
// size — an explicit size wins.
|
|
73
|
+
const sizeOverride = (customSize: string | undefined, atDefault: string): string | undefined =>
|
|
74
|
+
(customSize ?? 'md') === 'md' ? atDefault : SIZE_MAP[customSize ?? 'md']?.fontSize;
|
|
75
|
+
|
|
76
|
+
const textVariantStyles = (theme: Theme, a: TextStyleArgs, base: CSSObject): CSSObject => {
|
|
77
|
+
const weight = a.customWeight ?? 'normal';
|
|
78
|
+
|
|
79
|
+
switch (a.customVariant) {
|
|
80
|
+
case 'heading':
|
|
81
|
+
return {
|
|
82
|
+
...base,
|
|
83
|
+
fontFamily: theme.typography.h4.fontFamily,
|
|
84
|
+
fontWeight: weight === 'normal' ? 600 : WEIGHT_MAP[weight],
|
|
85
|
+
letterSpacing: '-0.01em',
|
|
86
|
+
};
|
|
87
|
+
case 'caption':
|
|
88
|
+
return {
|
|
89
|
+
...base,
|
|
90
|
+
fontSize: sizeOverride(a.customSize, '0.75rem'),
|
|
91
|
+
opacity: 0.8,
|
|
92
|
+
letterSpacing: '0.02em',
|
|
93
|
+
};
|
|
94
|
+
case 'code':
|
|
95
|
+
return {
|
|
96
|
+
...base,
|
|
97
|
+
fontFamily: 'Monaco, Menlo, "Ubuntu Mono", "Courier New", monospace',
|
|
98
|
+
fontSize: sizeOverride(a.customSize, '0.875rem'),
|
|
99
|
+
backgroundColor: alpha(theme.palette.primary.main, 0.08),
|
|
100
|
+
padding: '2px 6px',
|
|
101
|
+
borderRadius: theme.shape.borderRadius / 2,
|
|
102
|
+
border: `1px solid ${alpha(theme.palette.primary.main, 0.12)}`,
|
|
103
|
+
};
|
|
104
|
+
default:
|
|
105
|
+
return { ...base, fontFamily: theme.typography.body1.fontFamily };
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
29
109
|
const StyledText = styled(Typography, {
|
|
30
110
|
shouldForwardProp: (prop) =>
|
|
31
111
|
![
|
|
@@ -45,82 +125,9 @@ const StyledText = styled(Typography, {
|
|
|
45
125
|
italic?: boolean;
|
|
46
126
|
underline?: boolean;
|
|
47
127
|
strikethrough?: boolean;
|
|
48
|
-
}>(({
|
|
49
|
-
theme
|
|
50
|
-
|
|
51
|
-
customColor = 'neutral',
|
|
52
|
-
customSize = 'md',
|
|
53
|
-
customWeight = 'normal',
|
|
54
|
-
italic,
|
|
55
|
-
underline,
|
|
56
|
-
strikethrough,
|
|
57
|
-
}) => {
|
|
58
|
-
const textColor = getColorFromTheme(theme, customColor);
|
|
59
|
-
|
|
60
|
-
// Size mapping
|
|
61
|
-
const sizeMap = {
|
|
62
|
-
xs: { fontSize: '0.75rem', lineHeight: 1.2 },
|
|
63
|
-
sm: { fontSize: '0.875rem', lineHeight: 1.3 },
|
|
64
|
-
md: { fontSize: '1rem', lineHeight: 1.5 },
|
|
65
|
-
lg: { fontSize: '1.125rem', lineHeight: 1.4 },
|
|
66
|
-
xl: { fontSize: '1.25rem', lineHeight: 1.3 },
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// Weight mapping
|
|
70
|
-
const weightMap = {
|
|
71
|
-
light: 300,
|
|
72
|
-
normal: 400,
|
|
73
|
-
medium: 500,
|
|
74
|
-
semibold: 600,
|
|
75
|
-
bold: 700,
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
// Base styles
|
|
79
|
-
const baseStyles = {
|
|
80
|
-
color: textColor,
|
|
81
|
-
fontSize: sizeMap[customSize as keyof typeof sizeMap]?.fontSize,
|
|
82
|
-
lineHeight: sizeMap[customSize as keyof typeof sizeMap]?.lineHeight,
|
|
83
|
-
fontWeight: weightMap[customWeight as keyof typeof weightMap],
|
|
84
|
-
fontStyle: italic ? 'italic' : 'normal',
|
|
85
|
-
textDecoration:
|
|
86
|
-
[underline && 'underline', strikethrough && 'line-through'].filter(Boolean).join(' ') ||
|
|
87
|
-
'none',
|
|
88
|
-
transition: 'all 0.2s ease',
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// Variant-specific styles
|
|
92
|
-
const variantStyles = {
|
|
93
|
-
body: {
|
|
94
|
-
...baseStyles,
|
|
95
|
-
fontFamily: theme.typography.body1.fontFamily,
|
|
96
|
-
},
|
|
97
|
-
heading: {
|
|
98
|
-
...baseStyles,
|
|
99
|
-
fontFamily: theme.typography.h4.fontFamily,
|
|
100
|
-
fontWeight:
|
|
101
|
-
customWeight === 'normal' ? 600 : weightMap[customWeight as keyof typeof weightMap],
|
|
102
|
-
letterSpacing: '-0.01em',
|
|
103
|
-
},
|
|
104
|
-
caption: {
|
|
105
|
-
...baseStyles,
|
|
106
|
-
fontSize:
|
|
107
|
-
customSize === 'md' ? '0.75rem' : sizeMap[customSize as keyof typeof sizeMap]?.fontSize,
|
|
108
|
-
opacity: 0.8,
|
|
109
|
-
letterSpacing: '0.02em',
|
|
110
|
-
},
|
|
111
|
-
code: {
|
|
112
|
-
...baseStyles,
|
|
113
|
-
fontFamily: 'Monaco, Menlo, "Ubuntu Mono", "Courier New", monospace',
|
|
114
|
-
fontSize:
|
|
115
|
-
customSize === 'md' ? '0.875rem' : sizeMap[customSize as keyof typeof sizeMap]?.fontSize,
|
|
116
|
-
backgroundColor: alpha(theme.palette.primary.main, 0.08),
|
|
117
|
-
padding: '2px 6px',
|
|
118
|
-
borderRadius: theme.shape.borderRadius / 2,
|
|
119
|
-
border: `1px solid ${alpha(theme.palette.primary.main, 0.12)}`,
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
return variantStyles[customVariant as keyof typeof variantStyles] || variantStyles.body;
|
|
128
|
+
}>((args) => {
|
|
129
|
+
const { theme } = args;
|
|
130
|
+
return textVariantStyles(theme, args, baseTextStyles(theme, args));
|
|
124
131
|
});
|
|
125
132
|
|
|
126
133
|
export const Text = React.forwardRef<HTMLElement, TextProps>(
|
|
@@ -17,7 +17,7 @@ An animated icon wrapper component that can animate any icon or SVG with various
|
|
|
17
17
|
|
|
18
18
|
```tsx
|
|
19
19
|
import { AnimatedIcon } from '@/components/enhanced/AnimatedIcon';
|
|
20
|
-
import
|
|
20
|
+
import Settings from '@mui/icons-material/Settings';
|
|
21
21
|
|
|
22
22
|
// Simple rotating animation
|
|
23
23
|
<AnimatedIcon variant="rotate">
|
|
@@ -199,7 +199,7 @@ The AnimatedIcon component includes comprehensive test support through the `data
|
|
|
199
199
|
```tsx
|
|
200
200
|
import { render, screen } from '@testing-library/react';
|
|
201
201
|
import { AnimatedIcon } from '@/components/enhanced/AnimatedIcon';
|
|
202
|
-
import
|
|
202
|
+
import Settings from '@mui/icons-material/Settings';
|
|
203
203
|
|
|
204
204
|
// In your tests
|
|
205
205
|
test('should render with test ID', () => {
|
|
@@ -220,7 +220,7 @@ test('should render with test ID', () => {
|
|
|
220
220
|
import { render, screen } from '@testing-library/react';
|
|
221
221
|
import userEvent from '@testing-library/user-event';
|
|
222
222
|
import { AnimatedIcon } from '@/components/enhanced/AnimatedIcon';
|
|
223
|
-
import
|
|
223
|
+
import Favorite from '@mui/icons-material/Favorite';
|
|
224
224
|
|
|
225
225
|
test('should handle click events', async () => {
|
|
226
226
|
const handleClick = jest.fn();
|
|
@@ -247,7 +247,7 @@ test('should handle click events', async () => {
|
|
|
247
247
|
```tsx
|
|
248
248
|
import { render, screen } from '@testing-library/react';
|
|
249
249
|
import { AnimatedIcon } from '@/components/enhanced/AnimatedIcon';
|
|
250
|
-
import
|
|
250
|
+
import Refresh from '@mui/icons-material/Refresh';
|
|
251
251
|
|
|
252
252
|
test('should have proper accessibility attributes', () => {
|
|
253
253
|
render(
|
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Waves,
|
|
21
|
-
} from '@mui/icons-material';
|
|
1
|
+
import AccountCircle from '@mui/icons-material/AccountCircle';
|
|
2
|
+
import AutoAwesome from '@mui/icons-material/AutoAwesome';
|
|
3
|
+
import Bolt from '@mui/icons-material/Bolt';
|
|
4
|
+
import Diamond from '@mui/icons-material/Diamond';
|
|
5
|
+
import Download from '@mui/icons-material/Download';
|
|
6
|
+
import Favorite from '@mui/icons-material/Favorite';
|
|
7
|
+
import FlashOn from '@mui/icons-material/FlashOn';
|
|
8
|
+
import Home from '@mui/icons-material/Home';
|
|
9
|
+
import Lens from '@mui/icons-material/Lens';
|
|
10
|
+
import Lightbulb from '@mui/icons-material/Lightbulb';
|
|
11
|
+
import Notifications from '@mui/icons-material/Notifications';
|
|
12
|
+
import Psychology from '@mui/icons-material/Psychology';
|
|
13
|
+
import Refresh from '@mui/icons-material/Refresh';
|
|
14
|
+
import Rocket from '@mui/icons-material/Rocket';
|
|
15
|
+
import Search from '@mui/icons-material/Search';
|
|
16
|
+
import Settings from '@mui/icons-material/Settings';
|
|
17
|
+
import Star from '@mui/icons-material/Star';
|
|
18
|
+
import Upload from '@mui/icons-material/Upload';
|
|
19
|
+
import Waves from '@mui/icons-material/Waves';
|
|
22
20
|
import { Box, Chip,Grid, Paper, Stack, Typography } from '@mui/material';
|
|
23
21
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
24
22
|
import React from 'react';
|