├── .babelrc ├── .browserslistrc ├── .editorconfig ├── .eslintrc ├── .gitignore ├── .prettierrc.js ├── LICENSE ├── README.md ├── example ├── .gitignore ├── README.md ├── babel.config.js ├── blog │ ├── 2019-05-28-first-blog-post.md │ ├── 2019-05-29-long-blog-post.md │ ├── 2021-08-01-mdx-blog-post.mdx │ ├── 2021-08-26-welcome │ │ ├── docusaurus-plushie-banner.jpeg │ │ └── index.md │ └── authors.yml ├── docs │ ├── algorithms │ │ ├── _category_.json │ │ └── resize-algorithm.mdx │ ├── components │ │ ├── BoundingBox.mdx │ │ ├── CircleStencil.mdx │ │ ├── Cropper.mdx │ │ ├── CropperBackgroundImage.mdx │ │ ├── CropperBackgroundWrapper.mdx │ │ ├── CropperCanvas.mdx │ │ ├── CropperPreview.mdx │ │ ├── CropperWrapper.mdx │ │ ├── DraggableArea.mdx │ │ ├── DraggableElement.mdx │ │ ├── RectangleStencil.mdx │ │ ├── SimpleHandler.mdx │ │ ├── SimpleLine.mdx │ │ ├── StencilOverlay.mdx │ │ ├── StencilWrapper.mdx │ │ ├── StretchableBoundary.mdx │ │ ├── TransformableImage.mdx │ │ └── _category_.json │ ├── concept │ │ ├── _category_.json │ │ ├── defaults.md │ │ ├── introduction.md │ │ ├── modifiers.md │ │ ├── settings.md │ │ ├── state.md │ │ └── utils.md │ ├── faq.mdx │ ├── guides │ │ ├── _category_.json │ │ ├── advanced-recipes.mdx │ │ ├── components-and-hooks.mdx │ │ ├── cropper-types.mdx │ │ ├── cross-origin.mdx │ │ ├── customize-appearance.mdx │ │ ├── recipes.mdx │ │ └── themes.mdx │ ├── hooks │ │ ├── _category_.json │ │ ├── useAbstractCropperState.mdx │ │ ├── useCropperImage.mdx │ │ ├── useCropperState.mdx │ │ ├── useMoveImageOptions.mdx │ │ ├── useScaleImageOptions.mdx │ │ └── useWindowResize.mdx │ ├── intro.mdx │ ├── showcase.mdx │ └── tutorials │ │ ├── _category_.json │ │ ├── absolute-zoom.mdx │ │ ├── custom-stencil.mdx │ │ └── image-editor.mdx ├── docusaurus.config.js ├── package.json ├── sidebars.js ├── src │ ├── components │ │ ├── CroppersWizard.scss │ │ ├── CroppersWizard.tsx │ │ ├── CroppersWizardInfo.scss │ │ ├── CroppersWizardInfo.tsx │ │ ├── CroppersWizardSettings.scss │ │ ├── CroppersWizardSettings.tsx │ │ ├── HomepageFeatures.module.css │ │ ├── HomepageFeatures.tsx │ │ ├── InstallationBlock.scss │ │ ├── InstallationBlock.tsx │ │ ├── SettingsCheckbox.scss │ │ ├── SettingsCheckbox.tsx │ │ ├── SettingsInput.scss │ │ ├── SettingsInput.tsx │ │ ├── algorithms │ │ │ ├── ResizeAlgorithm │ │ │ │ ├── index.scss │ │ │ │ └── index.tsx │ │ │ └── utils.ts │ │ ├── croppers │ │ │ ├── DefaultCropper │ │ │ │ ├── DefaultCropper.scss │ │ │ │ ├── DefaultCropper.tsx │ │ │ │ └── components │ │ │ │ │ ├── Navigation.scss │ │ │ │ │ └── Navigation.tsx │ │ │ └── FixedCropper │ │ │ │ ├── FixedCropper.scss │ │ │ │ ├── FixedCropper.tsx │ │ │ │ ├── README.md │ │ │ │ ├── components │ │ │ │ ├── Navigation.scss │ │ │ │ ├── Navigation.tsx │ │ │ │ ├── Slider.scss │ │ │ │ ├── Slider.tsx │ │ │ │ ├── Wrapper.scss │ │ │ │ └── Wrapper.tsx │ │ │ │ └── icons │ │ │ │ ├── ZoomInIcon.tsx │ │ │ │ └── ZoomOutIcon.tsx │ │ ├── examples │ │ │ ├── AdjustStencilExample.scss │ │ │ ├── AdjustStencilExample.tsx │ │ │ ├── ChangingStencilExample.scss │ │ │ ├── ChangingStencilExample.tsx │ │ │ ├── CropperScrollExample.scss │ │ │ ├── CropperScrollExample.tsx │ │ │ ├── CropperTypesExample.scss │ │ │ ├── CropperTypesExample.tsx │ │ │ ├── CustomPreviewExample.scss │ │ │ ├── CustomPreviewExample.tsx │ │ │ ├── CustomRestrictionsExample.scss │ │ │ ├── CustomRestrictionsExample.tsx │ │ │ ├── DefaultCoordinatesExample.scss │ │ │ ├── DefaultCoordinatesExample.tsx │ │ │ ├── DefaultTransformsExample.scss │ │ │ ├── DefaultTransformsExample.tsx │ │ │ ├── DefaultVisibleArea.scss │ │ │ ├── DefaultVisibleArea.tsx │ │ │ ├── FillingCropperExample.scss │ │ │ ├── FillingCropperExample.tsx │ │ │ ├── FixedCroperTypeExample.scss │ │ │ ├── FixedCropperTypeExample.tsx │ │ │ ├── FixedSizeExample.scss │ │ │ ├── FixedSizeExample.tsx │ │ │ ├── GettingResultExample.scss │ │ │ ├── GettingResultExample.tsx │ │ │ ├── GettingResultManualExample.scss │ │ │ ├── GettingResultManualExample.tsx │ │ │ ├── GettingStartedExample.scss │ │ │ ├── GettingStartedExample.tsx │ │ │ ├── ImageRestrictionExample.scss │ │ │ ├── ImageRestrictionExample.tsx │ │ │ ├── LoadImageExample.scss │ │ │ ├── LoadImageExample.tsx │ │ │ ├── OverlayColorExample.scss │ │ │ ├── OverlayColorExample.tsx │ │ │ ├── PreviewResultExample.scss │ │ │ ├── PreviewResultExample.tsx │ │ │ ├── RefreshExample.scss │ │ │ ├── RefreshExample.tsx │ │ │ ├── ResizeResultExample.scss │ │ │ ├── ResizeResultExample.tsx │ │ │ ├── RotateImageExample.scss │ │ │ ├── RotateImageExample.tsx │ │ │ ├── SetCoordinatesExample.scss │ │ │ ├── SetCoordinatesExample.tsx │ │ │ ├── StencilGridExample.tsx │ │ │ ├── ThemeExample.scss │ │ │ ├── ThemeExample.tsx │ │ │ ├── TransformImageExample.scss │ │ │ ├── TransformImageExample.tsx │ │ │ ├── UploadExample.scss │ │ │ ├── UploadExample.tsx │ │ │ └── components │ │ │ │ ├── BackgroundWrapperWithNotifications.scss │ │ │ │ ├── BackgroundWrapperWithNotifications.tsx │ │ │ │ ├── PreviewResults.scss │ │ │ │ ├── PreviewResults.tsx │ │ │ │ ├── SquareButton.scss │ │ │ │ ├── SquareButton.tsx │ │ │ │ ├── VerticalButtons.scss │ │ │ │ └── VerticalButtons.tsx │ │ ├── icons │ │ │ ├── ArrowBottomIcon.tsx │ │ │ ├── ArrowLeftIcon.tsx │ │ │ ├── ArrowRightIcon.tsx │ │ │ ├── ArrowTopIcon.tsx │ │ │ ├── CenterIcon.tsx │ │ │ ├── CheckboxIcon.tsx │ │ │ ├── CircleStencilIcon.tsx │ │ │ ├── ClearIcon.tsx │ │ │ ├── CloseIcon.tsx │ │ │ ├── DefaultCropperIcon.tsx │ │ │ ├── DownloadIcon.tsx │ │ │ ├── FixedCropperIcon.tsx │ │ │ ├── FlipHorizontalIcon.tsx │ │ │ ├── FlipVerticalIcon.tsx │ │ │ ├── GridStencilIcon.tsx │ │ │ ├── InfoIcon.tsx │ │ │ ├── Logo.tsx │ │ │ ├── MobileCropperIcon.tsx │ │ │ ├── RectangleStencilIcon.tsx │ │ │ ├── ResetIcon.tsx │ │ │ ├── ResizeHorizontalIcon.tsx │ │ │ ├── ResizeIcon.tsx │ │ │ ├── ResizeMaximizeIcon.tsx │ │ │ ├── ResizeReduceIcon.tsx │ │ │ ├── ResizeVerticalIcon.tsx │ │ │ ├── RotateLeftIcon.tsx │ │ │ ├── RotateRightIcon.tsx │ │ │ ├── SaveIcon.tsx │ │ │ ├── Separator.tsx │ │ │ ├── SettingsIcon.tsx │ │ │ ├── UploadIcon.tsx │ │ │ ├── ZoomInIcon.tsx │ │ │ ├── ZoomOutIcon.tsx │ │ │ └── settings │ │ │ │ ├── CircleIcon.tsx │ │ │ │ ├── FillAreaIcon.tsx │ │ │ │ ├── FitAreaIcon.tsx │ │ │ │ ├── FreeAspectRatioIcon.tsx │ │ │ │ ├── HorizontalAspectRatioIcon.tsx │ │ │ │ ├── NoneIcon.tsx │ │ │ │ ├── PortraitAspectRatioIcon.tsx │ │ │ │ ├── RangeAspectRatioIcon.tsx │ │ │ │ ├── RectangleIcon.tsx │ │ │ │ ├── SquareAspectRatioIcon.tsx │ │ │ │ ├── StencilIcon.tsx │ │ │ │ └── VerticalAspectRatioIcon.tsx │ │ ├── images │ │ │ └── concept │ │ │ │ └── introduction │ │ │ │ ├── State.scss │ │ │ │ └── State.tsx │ │ ├── layout │ │ │ └── Layout.tsx │ │ ├── schemes │ │ │ ├── Appearance │ │ │ │ ├── BackgroundImage.tsx │ │ │ │ ├── CropperStructure.scss │ │ │ │ ├── CropperStructure.tsx │ │ │ │ ├── StencilStructure.scss │ │ │ │ ├── StencilStructure.tsx │ │ │ │ └── WrapperBackground.tsx │ │ │ ├── ComponentsHierarchy.tsx │ │ │ ├── HierarchyElement.scss │ │ │ ├── HierarchyElement.tsx │ │ │ ├── SchemeLabel.scss │ │ │ ├── SchemeLabel.tsx │ │ │ └── StencilHierarchy.tsx │ │ ├── showcase │ │ │ ├── Something │ │ │ │ ├── SomethingShowcase.scss │ │ │ │ ├── SomethingShowcase.tsx │ │ │ │ ├── components │ │ │ │ │ ├── SomethingCropper.scss │ │ │ │ │ └── SomethingCropper.tsx │ │ │ │ ├── icons │ │ │ │ │ ├── CropIcon.tsx │ │ │ │ │ ├── RotateLeftIcon.tsx │ │ │ │ │ └── RotateRightIcon.tsx │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ ├── Telegram │ │ │ │ ├── TelegramShowcase.scss │ │ │ │ ├── TelegramShowcase.tsx │ │ │ │ ├── components │ │ │ │ │ ├── CropperWrapper.scss │ │ │ │ │ ├── CropperWrapper.tsx │ │ │ │ │ ├── Navigation.scss │ │ │ │ │ ├── Navigation.tsx │ │ │ │ │ ├── RotateComponent.scss │ │ │ │ │ ├── RotateComponent.tsx │ │ │ │ │ ├── TelegramCropper.scss │ │ │ │ │ └── TelegramCropper.tsx │ │ │ │ └── icons │ │ │ │ │ ├── FlipHorizontalIcon.tsx │ │ │ │ │ ├── FlipVerticalIcon.tsx │ │ │ │ │ ├── RotateLeftIcon.tsx │ │ │ │ │ ├── RotateRightIcon.tsx │ │ │ │ │ └── Spinner.tsx │ │ │ └── Twitter │ │ │ │ ├── TwitterShowcase.scss │ │ │ │ ├── TwitterShowcase.tsx │ │ │ │ ├── components │ │ │ │ ├── Navigation.scss │ │ │ │ ├── Navigation.tsx │ │ │ │ ├── Slider.scss │ │ │ │ ├── Slider.tsx │ │ │ │ ├── TwitterCropper.scss │ │ │ │ ├── TwitterCropper.tsx │ │ │ │ ├── Wrapper.scss │ │ │ │ └── Wrapper.tsx │ │ │ │ └── icons │ │ │ │ ├── ZoomInIcon.tsx │ │ │ │ └── ZoomOutIcon.tsx │ │ └── tutorials │ │ │ ├── AbsoluteZoom │ │ │ ├── AbsoluteZoom.scss │ │ │ ├── AbsoluteZoom.tsx │ │ │ ├── components │ │ │ │ ├── CustomCropper.tsx │ │ │ │ ├── CustomWrapper.scss │ │ │ │ ├── CustomWrapper.tsx │ │ │ │ └── Navigation │ │ │ │ │ ├── Navigation.scss │ │ │ │ │ ├── Navigation.tsx │ │ │ │ │ ├── Slider.scss │ │ │ │ │ └── Slider.tsx │ │ │ └── icons │ │ │ │ ├── ZoomInIcon.tsx │ │ │ │ └── ZoomOutIcon.tsx │ │ │ ├── CustomStencil │ │ │ ├── CustomStencil.scss │ │ │ ├── CustomStencil.tsx │ │ │ └── components │ │ │ │ ├── CircleStencil.scss │ │ │ │ ├── CircleStencil.tsx │ │ │ │ └── handler.svg │ │ │ └── ImageEditor │ │ │ ├── ImageEditor.scss │ │ │ ├── ImageEditor.tsx │ │ │ ├── components │ │ │ ├── AdjustableCropperBackground.tsx │ │ │ ├── AdjustableImage.scss │ │ │ ├── AdjustableImage.tsx │ │ │ ├── AdjustablePreviewBackground.tsx │ │ │ ├── Button.scss │ │ │ ├── Button.tsx │ │ │ ├── Navigation.scss │ │ │ ├── Navigation.tsx │ │ │ ├── Slider.scss │ │ │ └── Slider.tsx │ │ │ └── icons │ │ │ ├── BrightnessIcon.tsx │ │ │ ├── ContrastIcon.tsx │ │ │ ├── CropIcon.tsx │ │ │ ├── DownloadIcon.tsx │ │ │ ├── HueIcon.tsx │ │ │ ├── ResetIcon.tsx │ │ │ ├── SaturationIcon.tsx │ │ │ └── UploadIcon.tsx │ ├── css │ │ ├── constants.scss │ │ ├── custom.css │ │ └── mixins.scss │ ├── pages │ │ ├── index.scss │ │ └── index.tsx │ └── service │ │ ├── react.ts │ │ ├── useHashState.ts │ │ ├── useQueryState.ts │ │ ├── useToggle.ts │ │ ├── useWindowResize.ts │ │ └── utils.ts ├── static │ ├── .nojekyll │ └── img │ │ ├── concept │ │ └── introduction │ │ │ ├── settings.svg │ │ │ └── state.svg │ │ ├── cross-origin │ │ └── problem.svg │ │ ├── custom-stencil │ │ ├── idea-resize.svg │ │ ├── idea.svg │ │ └── resize-directions.svg │ │ ├── customize-appearance │ │ ├── cropper-structure.svg │ │ └── stencil-structure.svg │ │ ├── docusaurus.png │ │ ├── drag-event │ │ ├── bad-result.svg │ │ ├── good-result.svg │ │ ├── overview.svg │ │ ├── problem.svg │ │ └── shift-method.svg │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── fixed-cropper.png │ │ ├── github-logo.svg │ │ ├── images │ │ ├── adam-flockemann-9j4xyaSQhUQ-unsplash.jpg │ │ ├── anna1991anna-0WDLQzK7u0E-unsplash.jpg │ │ ├── anna1991anna-1mwSwmPrHM4-unsplash.jpg │ │ ├── farzin-yarahmadi-yR3GrvkWnLA-unsplash.jpg │ │ ├── kamyar-ghalamchi-HO4cDQGPlq0-unsplash.jpg │ │ ├── karina-tess-GIgMRVBD-1s-unsplash.jpg │ │ ├── karina-tess-GIgMRVBD-1s-unsplash__preview.jpg │ │ ├── pexels-isabella-mariana-1988684.jpg │ │ ├── pexels-jeandaniel-francoeur-8832900.jpg │ │ ├── pexels-photo-10426274.jpeg │ │ ├── pexels-photo-12381305.jpeg │ │ ├── pexels-photo-1451124.jpeg │ │ ├── pexels-photo-1642574.jpeg │ │ ├── pexels-photo-1758144.jpeg │ │ ├── pexels-photo-2890387.jpeg │ │ ├── pexels-photo-3761018.jpeg │ │ ├── pexels-photo-4218687.jpeg │ │ ├── pexels-photo-4383577.jpeg │ │ ├── pexels-photo-5006465.jpeg │ │ ├── pexels-photo-573238.jpeg │ │ ├── pexels-photo-6524107.jpeg │ │ ├── pexels-photo-876344.jpeg │ │ ├── pexels-photo-876344__preview.jpeg │ │ ├── pexels-sampiccs-7244804.jpg │ │ ├── photo-1485178575877-1a13bf489dfe.jpg │ │ ├── photo-1494205577727-d32e58564756.jpg │ │ ├── photo-1507692812060-98338d07aca3.jpeg │ │ ├── photo-1520927640400-f9e83b1bc43e.jpg │ │ ├── photo-1527137342181-19aab11a8ee8.jpg │ │ ├── photo-1527199372136-dff50c10ea34.jpg │ │ ├── photo-1532182657011-d3d31357b5d8.jpg │ │ ├── photo-1538888649860-8fb12eb67541.jpg │ │ ├── photo-1542571255-84471dc5581c.jpg │ │ ├── photo-1553301208-a3718cc0150e.jpg │ │ ├── photo-1571040895662-2daba5bb466f.jpg │ │ ├── photo-1583149577728-9ab503747013.jpg │ │ ├── photo-1583172332547-c768b4e2f5ff.jpg │ │ ├── photo-1583511655857-d19b40a7a54e.jpg │ │ ├── photo-1583853287541-6e82b3d5ea12.jpg │ │ ├── photo-1586083718719-019f9dc6ca94.jpg │ │ ├── photo-1586598901893-8ac605430b78.jpg │ │ ├── photo-1587767959235-abd2d4b4cbe8.jpg │ │ ├── photo-1587977966839-4bd2a74441cc.jpg │ │ ├── photo-1595435934249-5df7ed86e1c0.jpg │ │ ├── photo-1596473322597-91d5b6938b8a.jpg │ │ ├── photo-1599032909756-5deb82fea3b0.jpg │ │ ├── photo-1599032909756-5deb82fea3b0__preview.jpg │ │ ├── photo-1599140849279-1014532882fe.jpg │ │ ├── photo-1600353068867-5b4de71e3afb.jpg │ │ ├── photo-1602718571797-49d5e9d54563.jpg │ │ ├── photo-1604335079441-274c03ad99a1.jpg │ │ ├── photo-1623432532623-f8f1347d954c.jpg │ │ ├── photo-1633158617942-204b1469bc05.jpg │ │ ├── photo-1639141700803-e5836ba39b4b.jpg │ │ ├── photo-1639141700803-e5836ba39b4b__preview.jpg │ │ ├── showcase-background.png │ │ └── sule-makaroglu-wvEaVy5DGf4-unsplash.jpg │ │ ├── logo-dark.svg │ │ ├── logo.svg │ │ ├── move-event │ │ └── example.svg │ │ ├── og-image.jpg │ │ ├── resize-event │ │ └── example.svg │ │ └── tutorial │ │ ├── docsVersionDropdown.png │ │ └── localeDropdown.png └── tsconfig.json ├── jest.config.js ├── package.json ├── rollup.config.js ├── scripts ├── clean.js └── themes.js ├── src ├── components │ ├── AbstractCropper.tsx │ ├── croppers │ │ ├── Cropper.tsx │ │ └── FixedCropper.tsx │ ├── handlers │ │ └── SimpleHandler.tsx │ ├── helpers │ │ ├── CropperPreview.tsx │ │ ├── CropperPreviewBackground.tsx │ │ └── CropperPreviewWrapper.tsx │ ├── lines │ │ └── SimpleLine.tsx │ ├── service │ │ ├── ArtificialTransition.tsx │ │ ├── BoundingBox.tsx │ │ ├── CropperBackgroundImage.tsx │ │ ├── CropperBackgroundWrapper.tsx │ │ ├── CropperCanvas.tsx │ │ ├── CropperFade.tsx │ │ ├── CropperSource.tsx │ │ ├── CropperWrapper.tsx │ │ ├── DraggableArea.tsx │ │ ├── DraggableElement.tsx │ │ ├── HandlerWrapper.tsx │ │ ├── LineWrapper.tsx │ │ ├── StencilGrid.tsx │ │ ├── StencilOverlay.tsx │ │ ├── StencilWrapper.tsx │ │ ├── StretchableBoundary.tsx │ │ └── TransformableImage.tsx │ └── stencils │ │ ├── CircleStencil.tsx │ │ └── RectangleStencil.tsx ├── deprecated │ └── hybridAutoZoom.ts ├── hooks │ ├── useAbstractCropper.ts │ ├── useAbstractCropperProps.ts │ ├── useCropperAutoReconcile.ts │ ├── useCropperImage.ts │ ├── useCropperInstance.ts │ ├── useDeprecationWarning.ts │ ├── useFirstMountState.ts │ ├── useForceRerender.ts │ ├── useMoveImageOptions.ts │ ├── usePersistentFunction.ts │ ├── useRotateImageOptions.ts │ ├── useScaleImageOptions.ts │ ├── useStateWithCallback.ts │ ├── useTransition.ts │ ├── useUpdateEffect.ts │ └── useWindowResize.ts ├── index.ts ├── instance │ └── CropperInstance.ts ├── react-app-env.d.ts ├── service │ ├── constants.ts │ ├── cropper.ts │ ├── events.ts │ ├── react.ts │ └── utils.ts └── types.ts ├── tests └── components │ └── croppers │ └── Cropper.test.tsx ├── tsconfig.json └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false 5 | }], 6 | "stage-0", 7 | "react" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | Firefox ESR 4 | ie >= 11 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = tab 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "eslint:recommended", 4 | "plugin:react/recommended", 5 | "plugin:@typescript-eslint/recommended", 6 | "prettier/@typescript-eslint", 7 | "plugin:prettier/recommended", 8 | "plugin:react-hooks/recommended" 9 | ], 10 | "plugins": [ 11 | "react", 12 | "@typescript-eslint", 13 | "prettier", 14 | "eslint-plugin-import" 15 | ], 16 | "env": { 17 | "browser": true, 18 | "jasmine": true, 19 | "jest": true, 20 | "es6": true, 21 | "node": true 22 | }, 23 | "rules": { 24 | "prettier/prettier": [ 25 | "error", 26 | { 27 | "singleQuote": true 28 | } 29 | ], 30 | "@typescript-eslint/explicit-function-return-type": "off", 31 | "@typescript-eslint/explicit-member-accessibility": "off", 32 | "@typescript-eslint/no-object-literal-type-assertion": "off", 33 | "@typescript-eslint/no-use-before-define": "off", 34 | "import/order": "warn" 35 | }, 36 | "settings": { 37 | "react": { 38 | "pragma": "React", 39 | "version": "detect" 40 | } 41 | }, 42 | "parser": "@typescript-eslint/parser" 43 | } 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # See https://help.github.com/ignore-files/ for more about ignoring files. 3 | 4 | # dependencies 5 | node_modules 6 | 7 | # builds 8 | dist 9 | .rpt2_cache 10 | 11 | # misc 12 | .DS_Store 13 | .env 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | .vscode 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | example/package-lock.json 24 | example/yarn.lock 25 | 26 | stats.html 27 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trailingComma: 'all', 3 | endOfLine: 'auto', 4 | semi: true, 5 | singleQuote: true, 6 | printWidth: 120, 7 | useTabs: true, 8 | tabWidth: 4, 9 | }; 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The source code of this library is licensed under MIT, the documentation content belongs to Norserium, except the photos that belong to their respective owners. 2 | 3 | The MIT License 4 | 5 | Copyright (c) Norserium, https://github.com/Norserium 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | ``` 30 | $ GIT_USER= USE_SSH=true yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /example/blog/2019-05-28-first-blog-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: first-blog-post 3 | title: First Blog Post 4 | authors: 5 | name: Gao Wei 6 | title: Docusaurus Core Team 7 | url: https://github.com/wgao19 8 | image_url: https://github.com/wgao19.png 9 | tags: [hola, docusaurus] 10 | --- 11 | 12 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 13 | -------------------------------------------------------------------------------- /example/blog/2021-08-01-mdx-blog-post.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | slug: mdx-blog-post 3 | title: MDX Blog Post 4 | authors: [slorber] 5 | tags: [docusaurus] 6 | --- 7 | 8 | Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/). 9 | 10 | :::tip 11 | 12 | Use the power of React to create interactive blog posts. 13 | 14 | ```js 15 | 16 | ``` 17 | 18 | 19 | 20 | ::: 21 | -------------------------------------------------------------------------------- /example/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/advanced-cropper/react-advanced-cropper/4dd28225bb0e209d447b9a8f2307e89e2fe15ece/example/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg -------------------------------------------------------------------------------- /example/blog/2021-08-26-welcome/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: welcome 3 | title: Welcome 4 | authors: [slorber, yangshun] 5 | tags: [facebook, hello, docusaurus] 6 | --- 7 | 8 | [Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog). 9 | 10 | Simply add Markdown files (or folders) to the `blog` directory. 11 | 12 | Regular blog authors can be added to `authors.yml`. 13 | 14 | The blog post date can be extracted from filenames, such as: 15 | 16 | - `2019-05-30-welcome.md` 17 | - `2019-05-30-welcome/index.md` 18 | 19 | A blog post folder can be convenient to co-locate blog post images: 20 | 21 | ![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg) 22 | 23 | The blog supports tags as well! 24 | 25 | **And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config. 26 | -------------------------------------------------------------------------------- /example/blog/authors.yml: -------------------------------------------------------------------------------- 1 | endi: 2 | name: Endilie Yacop Sucipto 3 | title: Maintainer of Docusaurus 4 | url: https://github.com/endiliey 5 | image_url: https://github.com/endiliey.png 6 | 7 | yangshun: 8 | name: Yangshun Tay 9 | title: Front End Engineer @ Facebook 10 | url: https://github.com/yangshun 11 | image_url: https://github.com/yangshun.png 12 | 13 | slorber: 14 | name: Sébastien Lorber 15 | title: Docusaurus maintainer 16 | url: https://sebastienlorber.com 17 | image_url: https://github.com/slorber.png 18 | -------------------------------------------------------------------------------- /example/docs/algorithms/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Algorithms", 3 | "position": 7 4 | } 5 | -------------------------------------------------------------------------------- /example/docs/algorithms/resize-algorithm.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Resize Algorithm 3 | sidebar_position: 7 4 | --- 5 | import { ResizeAlgorithm } from '../../src/components/algorithms/ResizeAlgorithm'; 6 | 7 | # Advanced Recipes 8 | 9 | ## Resize Algorithm 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/docs/components/BoundingBox.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: BoundingBox 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/CropperBackgroundImage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: CropperBackgroundImage 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/CropperBackgroundWrapper.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: CropperBackgroundImage 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/CropperCanvas.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: CropperCanvas 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/CropperPreview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: CropperPreview 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/CropperWrapper.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: CropperWrapper 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/DraggableArea.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: DraggableArea 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/DraggableElement.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: DraggableElement 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/SimpleHandler.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: SimpleHandler 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/SimpleLine.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: SimpleLine 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/StencilOverlay.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: StencilOverlay 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/StencilWrapper.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: StencilWrapper 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/StretchableBoundary.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: StretchableBoundary 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/TransformableImage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: CropperBackgroundImage 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/components/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Components", 3 | "position": 4 4 | } 5 | -------------------------------------------------------------------------------- /example/docs/concept/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Concept", 3 | "position": 6 4 | } 5 | -------------------------------------------------------------------------------- /example/docs/guides/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Guides", 3 | "position": 2 4 | } 5 | -------------------------------------------------------------------------------- /example/docs/hooks/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Hooks", 3 | "position": 5 4 | } 5 | -------------------------------------------------------------------------------- /example/docs/hooks/useAbstractCropperState.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: useAbstractCropperState 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/hooks/useCropperImage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: useCropperImage 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/hooks/useCropperState.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: useCropperState 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/hooks/useMoveImageOptions.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: useMoveImageOptions 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/hooks/useScaleImageOptions.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: useScaleImageOptions 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/hooks/useWindowResize.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: useWindowResize 3 | --- 4 | 5 | :::note 6 | This section has not been documented yet. Stay up to date. 7 | ::: 8 | -------------------------------------------------------------------------------- /example/docs/showcase.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | title: Showcase 4 | --- 5 | 6 | import { TelegramShowcase } from '../src/components/showcase/Telegram/TelegramShowcase'; 7 | import { TwitterShowcase } from '../src/components/showcase/Twitter/TwitterShowcase'; 8 | import { SomethingShowcase } from '../src/components/showcase/Something/SomethingShowcase'; 9 | 10 | :::tip Hey! 11 | If you've encountered the cropper on the Web that can't be implemented with this library, feel free to [write me](mailto:norserium@gmail.com) about it. 12 | ::: 13 | 14 | At this page you can find the examples of reimplementing existing croppers from the existing sites to demonstrate the library possibilities. 15 | 16 | ## Telegram 17 | 18 | This is the attempt of recreating the behavior of the cropper that used in the mobile version of the popular messenger [Telegram](https://telegram.org). 19 | 20 | 21 |
22 | 23 | :::info How to use it? 24 | This example is available as the standalone library [`react-mobile-cropper`](https://github.com/advanced-cropper/react-mobile-cropper). Feel free to use this library 25 | in your projects instead of this library. It's based on this one and has almost identical API. 26 | ::: 27 | 28 | ## Twitter 29 | 30 | This is the attempt of recreating the appearance and behavior of the cropper that you can find in the [Twitter](https://twitter.com). 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/docs/tutorials/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Tutorials", 3 | "position": 3 4 | } 5 | -------------------------------------------------------------------------------- /example/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | module.exports = { 13 | // By default, Docusaurus generates a sidebar from the docs folder structure 14 | tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }], 15 | 16 | // But you can create a sidebar manually 17 | /* 18 | tutorialSidebar: [ 19 | { 20 | type: 'category', 21 | label: 'Tutorial', 22 | items: ['hello'], 23 | }, 24 | ], 25 | */ 26 | }; 27 | -------------------------------------------------------------------------------- /example/src/components/CroppersWizardInfo.scss: -------------------------------------------------------------------------------- 1 | @import "../css/constants"; 2 | @import "../css/mixins"; 3 | 4 | .croppers-wizard-info { 5 | color: white; 6 | padding: 50px 80px; 7 | &__name { 8 | margin-bottom: 24px; 9 | font-size: 24px; 10 | } 11 | &__property-title { 12 | font-size: 16px; 13 | opacity: 0.8; 14 | margin-bottom: 6px; 15 | } 16 | &__property { 17 | margin-bottom: 24px; 18 | } 19 | &__features { 20 | display: flex; 21 | flex-wrap: wrap; 22 | padding-top: 5px; 23 | padding-bottom: 5px; 24 | } 25 | &__feature { 26 | padding: 2px 8px; 27 | background: #424242; 28 | font-size: 12px; 29 | color: white; 30 | display: inline-block; 31 | border-radius: 5px; 32 | margin-right: 16px; 33 | margin-bottom: 16px; 34 | } 35 | @include small-mobile() { 36 | padding-left: 40px; 37 | padding-right: 40px; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /example/src/components/CroppersWizardInfo.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, useLayoutEffect, useMemo, useRef, useState } from 'react'; 2 | import { CropperDescription } from './CroppersWizard'; 3 | import './CroppersWizardInfo.scss'; 4 | 5 | interface Props { 6 | data: CropperDescription; 7 | } 8 | 9 | export const CroppersWizardInfo: FC = (props) => { 10 | const { data } = props; 11 | 12 | return ( 13 |
14 |
{data.info.name}
15 | 16 |
17 |
Description
18 |
{data.info.description}
19 |
20 | {data.link && ( 21 |
22 |
Link
23 | 29 | {data.link} 30 | 31 |
32 | )} 33 |
34 |
Features
35 |
36 | {data.features.map((feature, index) => ( 37 |
38 | {feature} 39 |
40 | ))} 41 |
42 |
43 |
44 | ); 45 | }; 46 | -------------------------------------------------------------------------------- /example/src/components/CroppersWizardSettings.scss: -------------------------------------------------------------------------------- 1 | @import "../css/constants"; 2 | @import "../css/mixins"; 3 | 4 | .croppers-wizard-settings { 5 | color: white; 6 | padding: 20px 40px; 7 | position: relative; 8 | &__name { 9 | margin-bottom: 24px; 10 | font-size: 24px; 11 | } 12 | &__inline-property { 13 | margin-right: 16px; 14 | } 15 | &__property-title { 16 | font-size: 16px; 17 | opacity: 0.8; 18 | margin-bottom: 6px; 19 | } 20 | &__property-values { 21 | margin-bottom: 20px; 22 | display: flex; 23 | align-items: center; 24 | margin-left: -40px; 25 | margin-right: -40px; 26 | padding-left: 40px; 27 | } 28 | &__icon { 29 | cursor: pointer; 30 | display: flex; 31 | align-items: center; 32 | padding: 5px 15px; 33 | height: 100%; 34 | fill: white; 35 | stroke: white; 36 | transition: fill 0.5s, stroke 0.5s; 37 | &--active { 38 | fill: $theme-color; 39 | stroke: $theme-color; 40 | } 41 | } 42 | &__inputs { 43 | display: flex; 44 | margin-left: -40px; 45 | margin-right: -40px; 46 | padding-left: 40px; 47 | margin-bottom: 24px; 48 | } 49 | &__input { 50 | max-width: 125px; 51 | padding-right: 40px; 52 | } 53 | 54 | &__close-button { 55 | @include reset-browsers-button-styles(); 56 | @include center-content(); 57 | @include circle(); 58 | transition: 0.5s; 59 | opacity: 0.5; 60 | cursor: pointer; 61 | position: absolute; 62 | width: 32px; 63 | height: 32px; 64 | top: 5px; 65 | right: 10px; 66 | padding: 5px; 67 | &:hover, &:focus { 68 | opacity: 1; 69 | } 70 | } 71 | 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /example/src/components/HomepageFeatures.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /example/src/components/InstallationBlock.scss: -------------------------------------------------------------------------------- 1 | @import '../css/constants'; 2 | @import '../css/mixins'; 3 | 4 | .installation-block { 5 | background: #212121; 6 | border-radius: 10px; 7 | padding: 20px 30px; 8 | color: white; 9 | position: relative; 10 | &__prefix { 11 | user-select: none; 12 | color: $theme-color; 13 | margin-right: 8px; 14 | } 15 | &__buttons { 16 | position: absolute; 17 | top: 50%; 18 | transform: translateY(-50%); 19 | right: 20px; 20 | opacity: 0.6; 21 | } 22 | &__button { 23 | @include reset-browsers-button-styles(); 24 | cursor: pointer; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /example/src/components/InstallationBlock.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, useState } from 'react'; 2 | import './InstallationBlock.scss'; 3 | 4 | export const InstallationBlock: FC = () => { 5 | const [manager, setManager] = useState('yarn'); 6 | 7 | return ( 8 |
9 |
10 | /{' '} 11 | 12 |
13 |
14 | $ 15 | {manager === 'yarn' ? 'yarn add react-advanced-cropper' : 'npm install -S react-advanced-cropper'} 16 |
17 |
18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /example/src/components/SettingsCheckbox.scss: -------------------------------------------------------------------------------- 1 | @import '../css/mixins'; 2 | 3 | .settings-checkbox { 4 | display: flex; 5 | cursor: pointer; 6 | align-items: center; 7 | flex-shrink: 0; 8 | &__label { 9 | font-size: 16px; 10 | opacity: 0.8; 11 | } 12 | &__icon { 13 | width: 8px; 14 | height: 8px; 15 | transition: opacity 0.5s; 16 | &--hidden { 17 | opacity: 0; 18 | } 19 | } 20 | &__icon-wrapper { 21 | width: 16px; 22 | height: 16px; 23 | display: flex; 24 | align-items: center; 25 | justify-content: center; 26 | border: solid 1px white; 27 | border-radius: 2px; 28 | margin-right: 12px; 29 | fill: transparent; 30 | transition: 0.5s; 31 | &--checked { 32 | fill: #61DAFB; 33 | } 34 | } 35 | &__input { 36 | display: none; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /example/src/components/SettingsCheckbox.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import cn from 'classnames'; 3 | import './SettingsCheckbox.scss'; 4 | import { CheckboxIcon } from '@site/src/components/icons/CheckboxIcon'; 5 | 6 | interface Props { 7 | value?: boolean; 8 | placeholder?: string; 9 | className?: string; 10 | label: string; 11 | onChange?: (value?: boolean) => void; 12 | } 13 | 14 | export const SettingsCheckbox: FC = (props) => { 15 | const { value, className, label, placeholder, onChange } = props; 16 | const onChangeInternal = (event: React.ChangeEvent) => { 17 | if (onChange) { 18 | onChange(event.target.checked); 19 | } 20 | }; 21 | return ( 22 | 35 | ); 36 | }; 37 | -------------------------------------------------------------------------------- /example/src/components/SettingsInput.scss: -------------------------------------------------------------------------------- 1 | @import '../css/mixins'; 2 | 3 | .settings-input { 4 | &__label { 5 | font-size: 16px; 6 | opacity: 0.8; 7 | margin-bottom: 6px; 8 | text-align: center; 9 | white-space: nowrap; 10 | } 11 | &__input { 12 | @include reset-browsers-input-styles; 13 | text-align: center; 14 | font-size: 24px; 15 | color: white; 16 | width: 100%; 17 | border-bottom: solid 1px white; 18 | padding-bottom: 8px; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/src/components/SettingsInput.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import './SettingsInput.scss'; 3 | 4 | interface Props { 5 | value?: number; 6 | placeholder?: string; 7 | label: string; 8 | onChange?: (value?: number) => void; 9 | } 10 | 11 | export const SettingsInput: FC = (props) => { 12 | const { value, label, placeholder, onChange } = props; 13 | const onChangeInternal = (event: React.ChangeEvent) => { 14 | if (onChange) { 15 | if (event.target.value) { 16 | onChange(Number(event.target.value)); 17 | } else { 18 | onChange(undefined); 19 | } 20 | } 21 | }; 22 | return ( 23 |
24 |
{label}
25 | 32 |
33 | ); 34 | }; 35 | -------------------------------------------------------------------------------- /example/src/components/algorithms/ResizeAlgorithm/index.scss: -------------------------------------------------------------------------------- 1 | .resize-algorithm { 2 | width: 100%; 3 | height: 400px; 4 | &__boundary { 5 | position: relative; 6 | } 7 | &__stencil { 8 | position: absolute; 9 | color: var(--ifm-color-primary); 10 | &-line { 11 | border-color: var(--ifm-color-primary); 12 | } 13 | } 14 | &__reference { 15 | position: absolute; 16 | border: solid 1px var(--ifm-color-primary-dark) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /example/src/components/algorithms/utils.ts: -------------------------------------------------------------------------------- 1 | import { Coordinates } from 'advanced-cropper'; 2 | 3 | export function coordinatesToStyle(coordinates: Coordinates | null) { 4 | return coordinates 5 | ? { 6 | width: `${coordinates.width}px`, 7 | height: `${coordinates.height}px`, 8 | left: `${coordinates.left}px`, 9 | top: `${coordinates.top}px`, 10 | } 11 | : {}; 12 | } 13 | -------------------------------------------------------------------------------- /example/src/components/croppers/DefaultCropper/DefaultCropper.scss: -------------------------------------------------------------------------------- 1 | .default-cropper { 2 | display: flex; 3 | flex-direction: column; 4 | height: 100%; 5 | background: black; 6 | &__cropper { 7 | height: 100%; 8 | min-height: 0; 9 | } 10 | &__navigation { 11 | background: #080808; 12 | border-top: solid 1px #171616; 13 | height: 64px; 14 | flex-shrink: 0; 15 | margin-top: auto; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /example/src/components/croppers/DefaultCropper/components/Navigation.scss: -------------------------------------------------------------------------------- 1 | .default-cropper-navigation { 2 | background: #080808; 3 | border-top: solid 1px #171616; 4 | height: 64px; 5 | display: flex; 6 | justify-content: center; 7 | 8 | &__delimiter { 9 | width: 80px; 10 | display: flex; 11 | align-items: center; 12 | justify-content: center; 13 | position: relative; 14 | } 15 | 16 | &__dot { 17 | width: 6px; 18 | height: 6px; 19 | background: #393939; 20 | border-radius: 50%; 21 | transform: scale(1); 22 | transition: transform 0.5s; 23 | 24 | &--hidden { 25 | transform: scale(0); 26 | } 27 | } 28 | 29 | &__button, &__reset-button { 30 | cursor: pointer; 31 | width: 80px; 32 | height: 100%; 33 | display: flex; 34 | align-items: center; 35 | justify-content: center; 36 | background: none; 37 | border: none; 38 | outline: none; 39 | transition: transform 0.5s; 40 | padding: 0; 41 | fill: white; 42 | 43 | &:hover, &:focus { 44 | transform: scale(1.1); 45 | } 46 | } 47 | 48 | &__reset-button { 49 | position: absolute; 50 | top: 50%; 51 | left: 50%; 52 | transition: transform 0.5s; 53 | 54 | &, &:hover, &:focus { 55 | transform: translate(-50%, -50%) scale(1); 56 | } 57 | transition-delay: 0.25s; 58 | 59 | &--hidden { 60 | transition-delay: 0s; 61 | &, &:hover, &:focus { 62 | transform: translate(-50%, -50%) scale(0); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /example/src/components/croppers/FixedCropper/FixedCropper.scss: -------------------------------------------------------------------------------- 1 | .fixed-cropper { 2 | display: flex; 3 | flex-direction: column; 4 | height: 100%; 5 | background: black; 6 | } 7 | 8 | .fixed-cropper-stencil { 9 | &__overlay, &__preview { 10 | border-radius: 10px; 11 | &--circle { 12 | border-radius: 50%; 13 | } 14 | } 15 | &__preview { 16 | border: solid 2px rgba(white, 0.5); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /example/src/components/croppers/FixedCropper/components/Navigation.scss: -------------------------------------------------------------------------------- 1 | .fixed-cropper-navigation { 2 | height: 80px; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | 7 | &__delimiter { 8 | width: 80px; 9 | display: flex; 10 | align-items: center; 11 | justify-content: center; 12 | position: relative; 13 | } 14 | 15 | &__dot { 16 | width: 6px; 17 | height: 6px; 18 | background: #393939; 19 | border-radius: 50%; 20 | transform: scale(1); 21 | transition: transform 0.5s; 22 | 23 | &--hidden { 24 | transform: scale(0); 25 | } 26 | } 27 | 28 | &__button { 29 | will-change: transform; 30 | cursor: pointer; 31 | width: 80px; 32 | height: 100%; 33 | display: flex; 34 | align-items: center; 35 | justify-content: center; 36 | background: none; 37 | border: none; 38 | outline: none; 39 | transition: transform 0.5s; 40 | padding: 0; 41 | 42 | &:hover, &:focus { 43 | transform: scale(1.1); 44 | } 45 | } 46 | 47 | &__reset-button { 48 | position: absolute; 49 | top: 50%; 50 | left: 50%; 51 | transition: transform 0.5s; 52 | 53 | &, &:hover, &:focus { 54 | transform: translate(-50%, -50%) scale(1); 55 | } 56 | transition-delay: 0.25s; 57 | 58 | &--hidden { 59 | transition-delay: 0s; 60 | &, &:hover, &:focus { 61 | transform: translate(-50%, -50%) scale(0); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /example/src/components/croppers/FixedCropper/components/Navigation.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import { isNumber } from 'advanced-cropper'; 3 | import cn from 'classnames'; 4 | import { ZoomInIcon } from '../icons/ZoomInIcon'; 5 | import { ZoomOutIcon } from '../icons/ZoomOutIcon'; 6 | import { Slider } from './Slider'; 7 | import './Navigation.scss'; 8 | 9 | interface Props { 10 | zoom?: number; 11 | onZoom?: (value: number, transitions?: boolean) => void; 12 | className?: string; 13 | disabled?: unknown; 14 | } 15 | 16 | export const Navigation: FC = ({ className, onZoom, zoom }) => { 17 | const onZoomIn = () => { 18 | if (onZoom && isNumber(zoom)) { 19 | onZoom(Math.min(1, zoom + 0.25), true); 20 | } 21 | }; 22 | 23 | const onZoomOut = () => { 24 | if (onZoom && isNumber(zoom)) { 25 | onZoom(Math.max(0, zoom - 0.25), true); 26 | } 27 | }; 28 | 29 | return ( 30 |
31 | 34 | 35 | 38 |
39 | ); 40 | }; 41 | -------------------------------------------------------------------------------- /example/src/components/croppers/FixedCropper/components/Wrapper.scss: -------------------------------------------------------------------------------- 1 | .fixed-cropper-wrapper { 2 | &__content { 3 | display: flex; 4 | height: 100%; 5 | min-height: 0; 6 | overflow: visible; 7 | margin-bottom: -40px; 8 | } 9 | &__navigation { 10 | height: 80px; 11 | flex-shrink: 0; 12 | overflow: hidden; 13 | margin: 0 auto; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/src/components/croppers/FixedCropper/components/Wrapper.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties, FC } from 'react'; 2 | import { CropperRef, CropperFade } from 'react-advanced-cropper'; 3 | import { getAbsoluteZoom, getZoomFactor } from 'advanced-cropper/extensions/absolute-zoom'; 4 | import cn from 'classnames'; 5 | import { Navigation } from './Navigation'; 6 | import './Wrapper.scss'; 7 | 8 | interface Props { 9 | cropper: CropperRef; 10 | className?: string; 11 | style?: CSSProperties; 12 | } 13 | 14 | export const Wrapper: FC = ({ cropper, children, className }) => { 15 | const state = cropper.getState(); 16 | 17 | const settings = cropper.getSettings(); 18 | 19 | const absoluteZoom = getAbsoluteZoom(state, settings); 20 | 21 | const navigationWidth = state ? Math.min(state.boundary.height, state.boundary.width) - 40 : 0; 22 | 23 | const onZoom = (value: number, transitions?: boolean) => { 24 | if (cropper) { 25 | cropper.zoomImage(getZoomFactor(state, settings, value), { 26 | transitions: !!transitions, 27 | }); 28 | } 29 | }; 30 | 31 | return ( 32 | 33 |
{children}
34 |
35 | 36 |
37 |
38 | ); 39 | }; 40 | -------------------------------------------------------------------------------- /example/src/components/croppers/FixedCropper/icons/ZoomInIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ZoomInIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 18 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /example/src/components/croppers/FixedCropper/icons/ZoomOutIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ZoomOutIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 18 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /example/src/components/examples/AdjustStencilExample.scss: -------------------------------------------------------------------------------- 1 | .adjust-stencil-example { 2 | position: relative; 3 | &__cropper { 4 | max-height: 500px; 5 | background: #354146; 6 | } 7 | &__adjust { 8 | background: rgba(black, 0.7); 9 | padding: 10px 20px; 10 | position: absolute; 11 | left: 20px; 12 | top: 20px; 13 | color: white; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/src/components/examples/ChangingStencilExample.scss: -------------------------------------------------------------------------------- 1 | .changing-stencil-example { 2 | background: #354146; 3 | } 4 | -------------------------------------------------------------------------------- /example/src/components/examples/ChangingStencilExample.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { CircleStencil, CropperRef, Cropper } from 'react-advanced-cropper'; 3 | import './ChangingStencilExample.scss'; 4 | 5 | export const ChangingStencilExample = () => { 6 | const [image] = useState( 7 | '/react-advanced-cropper/img/images/photo-1485178575877-1a13bf489dfe.jpg', 8 | ); 9 | 10 | const onChange = (cropper: CropperRef) => { 11 | console.log(cropper.getCoordinates(), cropper.getCanvas()); 12 | }; 13 | 14 | return ( 15 | 21 | ); 22 | }; 23 | -------------------------------------------------------------------------------- /example/src/components/examples/CropperScrollExample.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/advanced-cropper/react-advanced-cropper/4dd28225bb0e209d447b9a8f2307e89e2fe15ece/example/src/components/examples/CropperScrollExample.scss -------------------------------------------------------------------------------- /example/src/components/examples/CropperScrollExample.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Cropper, ImageRestriction } from 'react-advanced-cropper'; 3 | import { BackgroundWrapperWithNotifications } from '@site/src/components/examples/components/BackgroundWrapperWithNotifications'; 4 | import './CropperScrollExample.scss'; 5 | 6 | export const CropperScrollExample = () => { 7 | const [image] = useState( 8 | '/react-advanced-cropper/img/images/photo-1633158617942-204b1469bc05.jpg', 9 | ); 10 | 11 | return ( 12 | 27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /example/src/components/examples/CropperTypesExample.scss: -------------------------------------------------------------------------------- 1 | .cropper-types-example { 2 | &--medium { 3 | max-height: 500px; 4 | } 5 | &--small { 6 | max-height: 400px; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/src/components/examples/CropperTypesExample.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cn from 'classnames'; 3 | import { CropperProps, Cropper } from 'react-advanced-cropper'; 4 | import './CropperTypesExample.scss'; 5 | 6 | interface Props extends CropperProps { 7 | size?: 'small' | 'medium'; 8 | } 9 | 10 | export const CropperTypesExample = ({ size, ...props }: Props) => { 11 | return ( 12 |
13 | 21 |
22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /example/src/components/examples/CustomPreviewExample.scss: -------------------------------------------------------------------------------- 1 | .custom-preview-example { 2 | &__stencil-preview { 3 | border: dashed 2px rgba(255,255,255, 0.45); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /example/src/components/examples/CustomPreviewExample.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { CircleStencil, Cropper } from 'react-advanced-cropper'; 3 | import './CustomPreviewExample.scss'; 4 | 5 | export const CustomPreviewExample = () => { 6 | const [image] = useState('/react-advanced-cropper/img/images/pexels-photo-1642574.jpeg'); 7 | 8 | return ( 9 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /example/src/components/examples/DefaultCoordinatesExample.scss: -------------------------------------------------------------------------------- 1 | .default-position-example { 2 | max-height: 450px; 3 | background: #354146; 4 | } 5 | -------------------------------------------------------------------------------- /example/src/components/examples/DefaultCoordinatesExample.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Cropper } from 'react-advanced-cropper'; 3 | import './GettingStartedExample.scss'; 4 | 5 | export const DefaultCoordinatesExample = () => { 6 | return ( 7 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /example/src/components/examples/DefaultTransformsExample.scss: -------------------------------------------------------------------------------- 1 | @import "../../css/constants"; 2 | 3 | .default-transforms-example { 4 | 5 | &__cropper { 6 | background: #354146; 7 | width: 100%; 8 | max-height: 500px; 9 | } 10 | 11 | &__panel { 12 | color: white; 13 | display: flex; 14 | background: $black-button-color; 15 | } 16 | 17 | &__panel-left { 18 | width: 100%; 19 | padding: 20px; 20 | padding-right: 30px; 21 | border-right: solid 1px $black-button-color-hover; 22 | } 23 | 24 | &__input { 25 | border: solid 1px $black-button-color; 26 | } 27 | 28 | &__input-control { 29 | padding: 8px; 30 | width: 100%; 31 | border: none; 32 | color: black; 33 | font: inherit; 34 | font-size: 15px; 35 | } 36 | 37 | &__input-label { 38 | display: block; 39 | font-size: 11px; 40 | margin-bottom: 5px; 41 | } 42 | 43 | &__button { 44 | width: 150px; 45 | display: flex; 46 | align-items: center; 47 | justify-content: center; 48 | color: white; 49 | font-size: 16px; 50 | padding: 10px 20px; 51 | text-align: center; 52 | background: #1f8255; 53 | cursor: pointer; 54 | transition: background 0.5s; 55 | font-weight: normal; 56 | height: 100%; 57 | background: $black-button-color; 58 | 59 | &:hover { 60 | background: $black-button-color-hover; 61 | text-decoration: none !important; 62 | } 63 | 64 | input { 65 | display: none; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/src/components/examples/DefaultVisibleArea.scss: -------------------------------------------------------------------------------- 1 | .default-visible-area-example { 2 | max-height: 450px; 3 | background: #354146; 4 | } 5 | -------------------------------------------------------------------------------- /example/src/components/examples/DefaultVisibleArea.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Cropper, Priority } from 'react-advanced-cropper'; 3 | import './DefaultVisibleArea.scss'; 4 | 5 | export const DefaultVisibleArea = () => { 6 | const defaultVisibleArea = { 7 | width: 800, 8 | height: 775, 9 | left: 63, 10 | top: 668, 11 | }; 12 | return ( 13 | 21 | ); 22 | }; 23 | -------------------------------------------------------------------------------- /example/src/components/examples/FillingCropperExample.scss: -------------------------------------------------------------------------------- 1 | .filling-cropper-example { 2 | max-height: 450px; 3 | background: #354146; 4 | } 5 | -------------------------------------------------------------------------------- /example/src/components/examples/FillingCropperExample.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Cropper } from 'react-advanced-cropper'; 3 | import './FillingCropperExample.scss'; 4 | 5 | export const FillingCropperExample = () => { 6 | const defaultSize = ({ imageSize, visibleArea }) => { 7 | return { 8 | width: (visibleArea || imageSize).width, 9 | height: (visibleArea || imageSize).height, 10 | }; 11 | }; 12 | return ( 13 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /example/src/components/examples/FixedCroperTypeExample.scss: -------------------------------------------------------------------------------- 1 | .fixed-cropper-type-example { 2 | &--medium { 3 | max-height: 500px; 4 | } 5 | &--small { 6 | max-height: 400px; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/src/components/examples/FixedCropperTypeExample.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cn from 'classnames'; 3 | import { FixedCropper, FixedCropperProps } from 'react-advanced-cropper'; 4 | import './FixedCroperTypeExample.scss'; 5 | 6 | interface Props extends FixedCropperProps { 7 | size?: 'small' | 'medium'; 8 | } 9 | 10 | export const FixedCropperTypeExample = ({ size, ...props }: Props) => { 11 | return ( 12 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /example/src/components/examples/FixedSizeExample.scss: -------------------------------------------------------------------------------- 1 | .fixed-size-example { 2 | max-height: 450px; 3 | background: #354146; 4 | } 5 | -------------------------------------------------------------------------------- /example/src/components/examples/FixedSizeExample.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FixedCropper, ImageRestriction } from 'react-advanced-cropper'; 3 | import './FixedSizeExample.scss'; 4 | 5 | export const FixedSizeExample = () => { 6 | return ( 7 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /example/src/components/examples/GettingResultExample.scss: -------------------------------------------------------------------------------- 1 | .getting-result-example { 2 | position: relative; 3 | &__cropper { 4 | max-height: 450px; 5 | background: #354146; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /example/src/components/examples/GettingResultExample.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { CropperRef, Cropper, Coordinates } from 'react-advanced-cropper'; 3 | import { useDebouncedCallback } from 'use-debounce'; 4 | import { PreviewResults } from '@site/src/components/examples/components/PreviewResults'; 5 | import './GettingResultExample.scss'; 6 | 7 | export const GettingResultExample = () => { 8 | const [coordinates, setCoordinates] = useState(null); 9 | 10 | const [preview, setPreview] = useState(); 11 | 12 | const [image] = useState( 13 | '/react-advanced-cropper/img/images/photo-1583511655857-d19b40a7a54e.jpg', 14 | ); 15 | 16 | const onChange = useDebouncedCallback((cropper: CropperRef) => { 17 | setCoordinates(cropper.getCoordinates()); 18 | setPreview(cropper.getCanvas()?.toDataURL()); 19 | }, 500); 20 | 21 | return ( 22 |
23 | 29 | {coordinates && preview && } 30 |
31 | ); 32 | }; 33 | -------------------------------------------------------------------------------- /example/src/components/examples/GettingResultManualExample.scss: -------------------------------------------------------------------------------- 1 | .getting-result-manual-example { 2 | position: relative; 3 | 4 | &__cropper { 5 | max-height: 720px; 6 | background: #354146; 7 | } 8 | 9 | &__crop-button { 10 | display: flex; 11 | justify-content: center; 12 | margin-top: 10px; 13 | position: absolute; 14 | left: 50%; 15 | top: -10px; 16 | transform: translateX(-50%); 17 | background: rgba(black, 0.8); 18 | padding: 5px 20px; 19 | transition: background 0.5s; 20 | color: white; 21 | font-size: 16px; 22 | cursor: pointer; 23 | 24 | &:hover { 25 | background: rgba(#1AA7F9, 0.9); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/src/components/examples/GettingResultManualExample.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useRef } from 'react'; 2 | import { CropperRef, Cropper, Coordinates } from 'react-advanced-cropper'; 3 | import { PreviewResults } from '../../components/examples/components/PreviewResults'; 4 | import './GettingResultManualExample.scss'; 5 | 6 | export const GettingResultManualExample = () => { 7 | const cropperRef = useRef(null); 8 | 9 | const [coordinates, setCoordinates] = useState(null); 10 | 11 | const [preview, setPreview] = useState(); 12 | 13 | const [image] = useState( 14 | '/react-advanced-cropper/img/images/photo-1586083718719-019f9dc6ca94.jpg', 15 | ); 16 | 17 | const onCrop = () => { 18 | if (cropperRef.current) { 19 | setCoordinates(cropperRef.current.getCoordinates()); 20 | setPreview(cropperRef.current.getCanvas()?.toDataURL()); 21 | } 22 | }; 23 | 24 | return ( 25 |
26 | 32 |
33 | Crop Image 34 |
35 | {coordinates && preview && } 36 |
37 | ); 38 | }; 39 | -------------------------------------------------------------------------------- /example/src/components/examples/GettingStartedExample.scss: -------------------------------------------------------------------------------- 1 | .getting-started-example { 2 | height: 600px; 3 | } 4 | -------------------------------------------------------------------------------- /example/src/components/examples/GettingStartedExample.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { CropperRef, Cropper } from 'react-advanced-cropper'; 3 | import './GettingStartedExample.scss'; 4 | 5 | export const GettingStartedExample = () => { 6 | const [image] = useState( 7 | '/react-advanced-cropper/img/images/photo-1599140849279-1014532882fe.jpg', 8 | ); 9 | 10 | const onChange = (cropper: CropperRef) => { 11 | console.log(cropper.getCoordinates(), cropper.getCanvas()); 12 | }; 13 | 14 | return ; 15 | }; 16 | -------------------------------------------------------------------------------- /example/src/components/examples/ImageRestrictionExample.scss: -------------------------------------------------------------------------------- 1 | @import "../../css/constants"; 2 | 3 | .image-restriction-example { 4 | 5 | &__cropper { 6 | background: #354146; 7 | width: 100%; 8 | max-height: 500px; 9 | } 10 | 11 | &__panel { 12 | color: white; 13 | display: flex; 14 | background: $black-button-color; 15 | } 16 | 17 | &__panel-left { 18 | width: 100%; 19 | padding: 20px; 20 | padding-right: 30px; 21 | border-right: solid 1px $black-button-color-hover; 22 | } 23 | 24 | &__input { 25 | border: solid 1px $black-button-color; 26 | } 27 | 28 | &__input-control { 29 | padding: 8px; 30 | width: 100%; 31 | border: none; 32 | color: black; 33 | font: inherit; 34 | font-size: 15px; 35 | } 36 | 37 | &__input-label { 38 | display: block; 39 | font-size: 11px; 40 | margin-bottom: 5px; 41 | } 42 | 43 | &__button { 44 | width: 150px; 45 | display: flex; 46 | align-items: center; 47 | justify-content: center; 48 | color: white; 49 | font-size: 16px; 50 | padding: 10px 20px; 51 | text-align: center; 52 | background: #1f8255; 53 | cursor: pointer; 54 | transition: background 0.5s; 55 | font-weight: normal; 56 | height: 100%; 57 | background: $black-button-color; 58 | 59 | &:hover { 60 | background: $black-button-color-hover; 61 | text-decoration: none !important; 62 | } 63 | 64 | input { 65 | display: none; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/src/components/examples/LoadImageExample.scss: -------------------------------------------------------------------------------- 1 | @import '../../css/constants'; 2 | 3 | .load-image-example { 4 | margin-top: 20px; 5 | margin-bottom: 20px; 6 | user-select: none; 7 | 8 | &__cropper { 9 | border: solid 1px $black-button-color; 10 | min-height: 400px; 11 | max-height: 500px; 12 | width: 100%; 13 | background: white; 14 | } 15 | 16 | &__cropper-background { 17 | background: black; 18 | } 19 | 20 | &__cropper-wrapper { 21 | position: relative; 22 | } 23 | 24 | &__reset-button { 25 | position: absolute; 26 | right: 20px; 27 | bottom: 20px; 28 | cursor: pointer; 29 | display: flex; 30 | align-items: center; 31 | justify-content: center; 32 | height: 42px; 33 | width: 42px; 34 | background: $black-button-color; 35 | transition: background 0.5s; 36 | &:hover { 37 | background: $black-button-color-hover; 38 | } 39 | } 40 | 41 | &__buttons-wrapper { 42 | display: flex; 43 | justify-content: center; 44 | } 45 | 46 | &__button { 47 | border: none; 48 | outline: solid transparent; 49 | color: white; 50 | font-size: 16px; 51 | padding: 10px 20px; 52 | background: $black-button-color; 53 | cursor: pointer; 54 | transition: background 0.5s; 55 | width: 100%; 56 | &:hover, 57 | &:focus { 58 | background: $black-button-color-hover; 59 | } 60 | input { 61 | display: none; 62 | } 63 | } 64 | 65 | &__file-type { 66 | position: absolute; 67 | top: 20px; 68 | left: 20px; 69 | background: #0d0d0d; 70 | border-radius: 5px; 71 | padding: 0 10px; 72 | padding-bottom: 2px; 73 | font-size: 12px; 74 | color: white; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /example/src/components/examples/OverlayColorExample.scss: -------------------------------------------------------------------------------- 1 | .overlay-color-example { 2 | height: 500px; 3 | &__overlay { 4 | color: #601f55eb; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/src/components/examples/OverlayColorExample.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { CircleStencil, Cropper } from 'react-advanced-cropper'; 3 | import './OverlayColorExample.scss'; 4 | 5 | export const OverlayColorExample = () => { 6 | const [image] = useState( 7 | 'https://images.unsplash.com/photo-1653443664854-47e17177f78b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=430&q=80', 8 | ); 9 | 10 | return ( 11 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /example/src/components/examples/PreviewResultExample.scss: -------------------------------------------------------------------------------- 1 | .preview-result-example { 2 | display: flex; 3 | position: relative; 4 | &__cropper { 5 | width: 300px; 6 | } 7 | &__previews { 8 | margin-left: 32px; 9 | } 10 | &__preview { 11 | border-radius: 50%; 12 | overflow: hidden; 13 | margin-top: 24px; 14 | margin-bottom: 24px; 15 | width: 100px; 16 | height: 100px; 17 | &--small { 18 | width: 60px; 19 | height: 60px; 20 | } 21 | } 22 | &__preview-image { 23 | width: 100%; 24 | } 25 | &__buttons { 26 | position: absolute; 27 | display: flex; 28 | left: 16px; 29 | bottom: 0; 30 | } 31 | &__button { 32 | fill: white; 33 | &:not(:last-child) { 34 | margin-right: 16px; 35 | } 36 | } 37 | &__download-input{ 38 | display: none; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /example/src/components/examples/RefreshExample.scss: -------------------------------------------------------------------------------- 1 | @import '../../css/constants'; 2 | 3 | .refresh-example { 4 | position: relative; 5 | height: 400px; 6 | width: 100%; 7 | border: solid 1px #EEE; 8 | 9 | &__wrapper { 10 | position: absolute; 11 | } 12 | 13 | &__cropper { 14 | width: 100%; 15 | height: 100%; 16 | } 17 | &__line { 18 | border-color: rgba($theme-color, 0.5); 19 | } 20 | &__handler { 21 | background: $theme-color; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/src/components/examples/ResizeResultExample.scss: -------------------------------------------------------------------------------- 1 | @import '../../css/constants'; 2 | 3 | .resize-result-example { 4 | &__cropper { 5 | width: 100%; 6 | max-height: 450px; 7 | border: solid 1px #eee; 8 | background: #354146; 9 | } 10 | } 11 | 12 | .resize-result-example-panel { 13 | border: solid 1px #ddd; 14 | color: black; 15 | display: flex; 16 | padding: 20px; 17 | background: rgb(250, 250, 250); 18 | &__left { 19 | width: 100%; 20 | padding-right: 30px; 21 | } 22 | &__right { 23 | display: flex; 24 | align-items: stretch; 25 | flex-direction: column; 26 | } 27 | &__button { 28 | width: 120px; 29 | margin-top: 15px; 30 | color: white; 31 | font-size: 16px; 32 | padding: 17px 20px; 33 | text-align: center; 34 | background: $black-button-color; 35 | cursor: pointer; 36 | transition: background 0.5s; 37 | font-weight: normal; 38 | height: 100%; 39 | display: flex; 40 | align-items: center; 41 | justify-content: center; 42 | &:hover { 43 | background: $black-button-color-hover; 44 | text-decoration: none !important; 45 | } 46 | input { 47 | display: none; 48 | } 49 | } 50 | &__input { 51 | margin-bottom: 8px; 52 | } 53 | &__input-control { 54 | padding: 4px; 55 | width: 100%; 56 | color: black; 57 | font: inherit; 58 | font-size: 15px; 59 | border: solid 1px #aaa; 60 | } 61 | &__input-label { 62 | display: block; 63 | font-size: 11px; 64 | margin-bottom: 3px; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /example/src/components/examples/RotateImageExample.scss: -------------------------------------------------------------------------------- 1 | .rotate-image-example { 2 | position: relative; 3 | 4 | &__cropper { 5 | max-height: 450px; 6 | background: #354146; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/src/components/examples/SetCoordinatesExample.scss: -------------------------------------------------------------------------------- 1 | .set-coordinates-example { 2 | position: relative; 3 | 4 | &__cropper { 5 | max-height: 500px; 6 | background: #354146; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/src/components/examples/StencilGridExample.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Cropper } from 'react-advanced-cropper'; 3 | 4 | export const StencilGridExample = () => { 5 | const [image] = useState('/react-advanced-cropper/img/images/anna1991anna-0WDLQzK7u0E-unsplash.jpg'); 6 | 7 | return ( 8 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/examples/ThemeExample.scss: -------------------------------------------------------------------------------- 1 | 2 | 3 | .theme-example { 4 | margin-top: 20px; 5 | margin-bottom: 20px; 6 | position: relative; 7 | user-select: none; 8 | min-height: 200px; 9 | border: solid 1px #eee; 10 | 11 | &--compact { 12 | @import '~react-advanced-cropper/dist/themes/compact.scss'; 13 | } 14 | 15 | &--classic { 16 | @import '~react-advanced-cropper/dist/themes/classic.scss'; 17 | } 18 | 19 | &--bubble { 20 | @import '~react-advanced-cropper/dist/themes/bubble.scss'; 21 | } 22 | 23 | &--corners { 24 | @import '~react-advanced-cropper/dist/themes/corners.scss'; 25 | } 26 | 27 | &__theme { 28 | color: white; 29 | position: absolute; 30 | font-size: 10px; 31 | right: 10px; 32 | bottom: 10px; 33 | opacity: 0.5; 34 | } 35 | 36 | &__button { 37 | fill: white; 38 | transition: fill 0.5s; 39 | &--inactive { 40 | fill: #888; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/src/components/examples/TransformImageExample.scss: -------------------------------------------------------------------------------- 1 | .transform-image-example { 2 | position: relative; 3 | 4 | &__cropper { 5 | max-height: 450px; 6 | background: #354146; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/src/components/examples/UploadExample.scss: -------------------------------------------------------------------------------- 1 | @import '../../css/constants'; 2 | 3 | .upload-example { 4 | margin-bottom: 20px; 5 | &__cropper { 6 | border: solid 1px $black-button-color; 7 | max-height: 450px; 8 | width: 100%; 9 | background: white; 10 | } 11 | 12 | &__cropper-background { 13 | background: black; 14 | } 15 | 16 | &__cropper-wrapper { 17 | position: relative; 18 | } 19 | 20 | &__button-wrapper { 21 | display: flex; 22 | justify-content: center; 23 | } 24 | 25 | &__button { 26 | color: white; 27 | font-size: 16px; 28 | padding: 10px 20px; 29 | background: $black-button-color; 30 | cursor: pointer; 31 | transition: background 0.5s; 32 | width: 100%; 33 | text-align: center; 34 | &:hover { 35 | background: $black-button-color-hover; 36 | } 37 | input { 38 | display: none; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /example/src/components/examples/UploadExample.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useRef } from 'react'; 2 | import { CropperRef, Cropper } from 'react-advanced-cropper'; 3 | import './UploadExample.scss'; 4 | 5 | export const UploadExample = () => { 6 | const cropperRef = useRef(null); 7 | 8 | const [image] = useState('/react-advanced-cropper/img/images/photo-1604335079441-274c03ad99a1.jpg'); 9 | 10 | const onUpload = () => { 11 | const canvas = cropperRef.current?.getCanvas(); 12 | if (canvas) { 13 | const form = new FormData(); 14 | canvas.toBlob((blob) => { 15 | if (blob) { 16 | form.append('file', blob); 17 | fetch('http://example.com/upload/', { 18 | method: 'POST', 19 | body: form, 20 | }); 21 | } 22 | }, 'image/jpeg'); 23 | } 24 | }; 25 | 26 | return ( 27 |
28 |
29 | 35 |
36 |
37 |
38 | Crop Image 39 |
40 |
41 |
42 | ); 43 | }; 44 | -------------------------------------------------------------------------------- /example/src/components/examples/components/BackgroundWrapperWithNotifications.scss: -------------------------------------------------------------------------------- 1 | .cropper-event-notification { 2 | background: rgba(0,0,0,0.6); 3 | color: white; 4 | position: absolute; 5 | left: 0; 6 | top: 0; 7 | bottom: 0; 8 | right:0; 9 | display: flex; 10 | justify-content: center; 11 | align-items: center; 12 | text-align: center; 13 | font-size: 20px; 14 | transition: opacity 1s; 15 | opacity: 0; 16 | pointer-events: none; 17 | padding-left: 50px; 18 | padding-right: 50px; 19 | &--visible { 20 | transition: opacity 0.25s; 21 | pointer-events: all; 22 | opacity: 1; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/src/components/examples/components/PreviewResults.scss: -------------------------------------------------------------------------------- 1 | @import '../../../css/mixins'; 2 | 3 | .preview-results { 4 | &__wrapper { 5 | display: flex; 6 | position: absolute; 7 | right: 15px; 8 | bottom: 15px; 9 | border: dashed 1px rgba(white, 0.5); 10 | } 11 | &__coordinates { 12 | background: rgba(black, 0.8); 13 | padding: 5px; 14 | font-size: 10px; 15 | color: white; 16 | pointer-events: none; 17 | @include mobile() { 18 | display: none; 19 | } 20 | } 21 | &__coordinates-title { 22 | font-weight: bold; 23 | } 24 | &__coordinates-title, 25 | &__coordinates-value { 26 | margin-top: 2px; 27 | margin-bottom: 2px; 28 | } 29 | &__preview { 30 | width: 107px; 31 | height: 107px; 32 | opacity: 0.8; 33 | pointer-events: none; 34 | img { 35 | width: 100%; 36 | height: 100%; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /example/src/components/examples/components/PreviewResults.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import { Coordinates } from 'react-advanced-cropper'; 3 | import './PreviewResults.scss'; 4 | 5 | interface Props { 6 | coordinates: Coordinates; 7 | preview: string | null; 8 | } 9 | 10 | export const PreviewResults: FC = ({ coordinates, preview }) => { 11 | return ( 12 |
13 | {preview && ( 14 |
15 |
16 |

Results:

17 |

Width: {coordinates.width}

18 |

Height: {coordinates.height}

19 |

Left: {coordinates.left}

20 |

Top: {coordinates.top}

21 |
22 |
23 | 24 |
25 |
26 | )} 27 |
28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /example/src/components/examples/components/SquareButton.scss: -------------------------------------------------------------------------------- 1 | @import '../../../css/mixins'; 2 | 3 | .square-button { 4 | @include reset-browsers-button-styles(); 5 | background: rgba(black, 0.4); 6 | display: flex; 7 | align-items: center; 8 | justify-content: center; 9 | height: 42px; 10 | width: 42px; 11 | margin-bottom: 10px; 12 | cursor: pointer; 13 | transition: background 0.5s; 14 | &:hover { 15 | background: black; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /example/src/components/examples/components/SquareButton.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, ButtonHTMLAttributes } from 'react'; 2 | import cn from 'classnames'; 3 | import './SquareButton.scss'; 4 | 5 | export const SquareButton: FC> = ({ children, className, ...props }) => { 6 | return ( 7 | 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /example/src/components/examples/components/VerticalButtons.scss: -------------------------------------------------------------------------------- 1 | .vertical-buttons { 2 | position: absolute; 3 | left: 10px; 4 | top: 50%; 5 | transform: translateY(-50%); 6 | } 7 | -------------------------------------------------------------------------------- /example/src/components/examples/components/VerticalButtons.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import cn from 'classnames'; 3 | import './VerticalButtons.scss'; 4 | 5 | interface Props { 6 | className?: string; 7 | } 8 | 9 | export const VerticalButtons: FC = ({ children, className, ...props }) => { 10 | return
{children}
; 11 | }; 12 | -------------------------------------------------------------------------------- /example/src/components/icons/ArrowBottomIcon.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/no-unknown-property */ 2 | import React, { FC } from 'react'; 3 | 4 | interface Props { 5 | className?: string; 6 | } 7 | 8 | export const ArrowBottomIcon: FC = ({ className }) => { 9 | return ( 10 | 11 | 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /example/src/components/icons/ArrowLeftIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ArrowLeftIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/ArrowRightIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ArrowRightIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/ArrowTopIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ArrowTopIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/CenterIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const CenterIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /example/src/components/icons/CheckboxIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const CheckboxIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /example/src/components/icons/CircleStencilIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const CircleStencilIcon: FC = ({ className }) => { 8 | return ( 9 | 16 | 27 | 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /example/src/components/icons/ClearIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ClearIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/CloseIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const CloseIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/DefaultCropperIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const DefaultCropperIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/DownloadIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const DownloadIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /example/src/components/icons/FixedCropperIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const FixedCropperIcon: FC = ({ className }) => { 8 | return ( 9 | 17 | 18 | 19 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /example/src/components/icons/FlipHorizontalIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const FlipHorizontalIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/FlipVerticalIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const FlipVerticalIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | 16 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /example/src/components/icons/GridStencilIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const GridStencilIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /example/src/components/icons/InfoIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const InfoIcon: FC = ({ className }) => { 8 | return ( 9 | 17 | 18 | 19 | 20 | 24 | 25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /example/src/components/icons/Logo.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const Logo: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /example/src/components/icons/MobileCropperIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const MobileCropperIcon: FC = ({ className }) => { 8 | return ( 9 | 17 | 20 | 21 | ); 22 | }; 23 | -------------------------------------------------------------------------------- /example/src/components/icons/RectangleStencilIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const RectangleStencilIcon: FC = ({ className }) => { 8 | return ( 9 | 16 | 26 | 27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /example/src/components/icons/ResetIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ResetIcon: FC = ({ className }) => { 8 | return ( 9 | 17 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /example/src/components/icons/ResizeHorizontalIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ResizeHorizontalIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/ResizeIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ResizeIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/ResizeMaximizeIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ResizeMaximizeIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/ResizeReduceIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ResizeReduceIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/ResizeVerticalIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ResizeVerticalIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/RotateLeftIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const RotateLeftIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/RotateRightIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const RotateRightIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/SaveIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const SaveIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /example/src/components/icons/Separator.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const Separator: FC = ({ className }) => { 8 | return ( 9 | 10 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /example/src/components/icons/SettingsIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const SettingsIcon: FC = ({ className }) => { 8 | return ( 9 | 17 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /example/src/components/icons/UploadIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const UploadIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /example/src/components/icons/ZoomInIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ZoomInIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 18 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /example/src/components/icons/ZoomOutIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const ZoomOutIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 18 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /example/src/components/icons/settings/CircleIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const CircleIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 14 | 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /example/src/components/icons/settings/FreeAspectRatioIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const FreeAspectRatioIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /example/src/components/icons/settings/HorizontalAspectRatioIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const HorizontalAspectRatioIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /example/src/components/icons/settings/PortraitAspectRatioIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const PortraitAspectRatioIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /example/src/components/icons/settings/SquareAspectRatioIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const SquareAspectRatioIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /example/src/components/icons/settings/VerticalAspectRatioIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const VerticalAspectRatioIcon: FC = ({ className }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /example/src/components/images/concept/introduction/State.scss: -------------------------------------------------------------------------------- 1 | @import '../../../../css/mixins'; 2 | 3 | .introduction-state { 4 | float: right; 5 | margin-left: 16px; 6 | display: block; 7 | @include mobile() { 8 | float: none; 9 | margin: 0 auto; 10 | margin-bottom: 16px; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /example/src/components/layout/Layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import SkipToContent from '@theme/SkipToContent'; 4 | import AnnouncementBar from '@theme/AnnouncementBar'; 5 | import Footer from '@theme/Footer'; 6 | import LayoutProviders from '@theme/LayoutProviders'; 7 | import LayoutHead from '@theme/LayoutHead'; 8 | import type { Props } from '@theme/Layout'; 9 | import useKeyboardNavigation from '@theme/hooks/useKeyboardNavigation'; 10 | import { ThemeClassNames } from '@docusaurus/theme-common'; 11 | 12 | function Layout(props: Props): JSX.Element { 13 | const { children, noFooter, wrapperClassName, pageClassName } = props; 14 | 15 | useKeyboardNavigation(); 16 | 17 | return ( 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
{children}
26 | 27 | {!noFooter &&