diff --git a/README.md b/README.md
index b762532..26105f6 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,8 @@
-
Storybook Github Page
+Storybook Demo Page
+Click on the icon.
@@ -76,7 +77,7 @@
- Dragging and dropping text on the canvas
- Adding custom web font families
- Selecting the modal button and its location
-- Choosing the image type (png, jpg, webp)
+- Choosing the image type (png, jpg, webp, svg)
- Supporting TypeScript and Next
@@ -146,22 +147,24 @@ const App = () => {
// If you do not include this option, the default icon will be used.
iconSize="medium"
- // Please select the size of the default button icon.
- // If no size is specified, the default size (medium) will be applied.
+ // Through this property, you can specify the size of the button icon.
// However, if you are inserting a custom button icon, this option is meaningless.
iconPosition={[0, 20, 20, 0]}
- // Please select the location of the button to open the Thumbnail Model.
- // Sequence: [top, right, bottom, left]
+ // Through this property, you can specify the position of the button icon.
+ // [top, right, bottom, left]
modalPosition='right'
- // Please select the location to open the ThumbnailModal.
+ // Through this property, you can specify the position of the thumbnail generator.
additionalFontFamily={['Noto Sans', ...]}
// You can add the font of your choice to your project, but that font must already applied to your project.
isFullWidth={true}
- // Setting this property to true will make the thumbnail generator modal full width.
+ // Setting this property to true will make the thumbnail generator full-width.
+
+ isDefaultOpen={false}
+ // Setting this property to true will open the thumbnail generator by default.
/>
)
@@ -301,9 +304,15 @@ const App = () => {
- **Optional**
- Default: `false`
- Type: `boolean`
+- isDefaultOpen
+ - **Optional**
+ - Default: `false`
+ - Type: `boolean`
## Reference
- https://github.com/wormwlrm/kwakcheolyong
-- https://github.com/banner-maker/banner-makers
\ No newline at end of file
+- https://github.com/banner-maker/banner-makers
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
index a740f13..32b2793 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-thumbnail-generator",
- "version": "2.8.0",
+ "version": "2.9.0",
"description": "react-thumbnail-generator",
"main": "dist/index.js",
"module": "dist/index.js",
diff --git a/src/components/Canvas/index.tsx b/src/components/Canvas/index.tsx
index 37caec9..8194edf 100644
--- a/src/components/Canvas/index.tsx
+++ b/src/components/Canvas/index.tsx
@@ -122,11 +122,13 @@ const Canvas = React.forwardRef(({ canvasState }: CanvasProps, ref: any) => {
const ctx = canvas.getContext('2d');
if (!ctx) return;
+
if (selectedImage) {
if (isBlur) ctx.filter = 'blur(5px)';
ctx.drawImage(selectedImage, 0, 0);
return;
}
+
ctx.fillStyle = bgColor.hex;
ctx.fillRect(0, 0, canvas.width, canvas.height);
};
diff --git a/src/components/Inputs/RangeInput/index.tsx b/src/components/Inputs/RangeInput/index.tsx
index 8ebf5d0..e841f1a 100644
--- a/src/components/Inputs/RangeInput/index.tsx
+++ b/src/components/Inputs/RangeInput/index.tsx
@@ -36,7 +36,7 @@ const RangeInput = ({
backgroundSize={backgroundSize}
/>
-
+
);
};
diff --git a/src/components/Inputs/TextInput/index.tsx b/src/components/Inputs/TextInput/index.tsx
index e87b9cd..86ac407 100644
--- a/src/components/Inputs/TextInput/index.tsx
+++ b/src/components/Inputs/TextInput/index.tsx
@@ -16,7 +16,7 @@ const TextInput = ({
}: TextInputProps) => {
return (
-
+ {label && }
{
- const LimitWidthSize = window.innerWidth;
-
return (
-
-
- Limit Width: {`${LimitWidthSize}px`}
-
+
+
+
);
};
diff --git a/src/components/Layout/styled.tsx b/src/components/Layout/styled.tsx
index 7820e17..5e948f8 100644
--- a/src/components/Layout/styled.tsx
+++ b/src/components/Layout/styled.tsx
@@ -3,31 +3,12 @@ import styled from 'styled-components';
export const HeaderWrapper = styled.div`
display: flex;
+ justify-content: end;
+ width: 100%;
position: sticky;
top: 0;
- flex-direction: column;
- padding: 10px;
- padding-bottom: 0;
- background-color: #fff;
-
- & > div:first-child {
- justify-content: space-between;
- align-items: center;
- display: flex;
- }
-
- a {
- color: #111111;
- padding: 0;
- margin: 0;
- font-size: 0.875rem;
- font-weight: bold;
- text-decoration: none;
-
- &:hover {
- color: #3264b5;
- }
- }
+ padding: 8px;
+ border-bottom: 1px solid rgb(243, 243, 243);
button {
cursor: pointer;
@@ -38,16 +19,6 @@ export const HeaderWrapper = styled.div`
}
`;
-export const LimitSizeText = styled.div`
- font-size: 0.85rem;
- margin-top: 5px;
- text-align: center;
-
- span {
- font-weight: bold;
- }
-`;
-
export const BodyWrapper = styled.section<{
modalPosition: 'left' | 'right' | 'center';
isFullWidth: boolean;
@@ -62,6 +33,7 @@ export const BodyWrapper = styled.section<{
background-color: #ffffff;
flex-direction: column;
overflow: hidden;
+
font-family: Arial;
* {
diff --git a/src/components/TG.tsx b/src/components/TG.tsx
index 0ce7023..71b6568 100644
--- a/src/components/TG.tsx
+++ b/src/components/TG.tsx
@@ -37,7 +37,6 @@ const TG = ({
isFullWidth,
onToggle,
}: TGProps) => {
- const LIMIT_WIDTH = window.innerWidth;
const [canvasState, setCanvasState] = useState({
value: 'Simple Thumbnail\nGenerator 😁',
fontSize: '30px',
@@ -98,13 +97,6 @@ const TG = ({
const replacedCallback = getReplaceCallback(name);
const replacedValue = value.replace(regex, replacedCallback);
- const validMessage = getValidMessage(
- name === 'canvasWidth' && +replacedValue > LIMIT_WIDTH,
- 'canvasSize'
- );
-
- if (validMessage) return alert(validMessage);
-
setCanvasState({
...canvasState,
[name]: replacedValue,
@@ -143,12 +135,6 @@ const TG = ({
img.src = files[0] && URL.createObjectURL(files[0]);
img.onload = async () => {
- const validMessage = getValidMessage(
- img.width > LIMIT_WIDTH,
- 'imageSize'
- );
- if (validMessage) return alert(validMessage);
-
setCanvasState({
...canvasState,
selectedImage: img,
diff --git a/src/constants/select.ts b/src/constants/select.ts
index 4d8c0e8..82b548f 100644
--- a/src/constants/select.ts
+++ b/src/constants/select.ts
@@ -8,7 +8,7 @@ export const fontFamilies = [
];
export const strokeTypes = ['None', 'Thin', 'Normal', 'Thick'];
-export const imageTypes = ['png', 'jpg', 'webp'];
+export const imageTypes = ['png', 'jpg', 'svg', 'webp'];
export const fontSizes = [
'10px',
diff --git a/src/lib/ThumbnailGenerator.tsx b/src/lib/ThumbnailGenerator.tsx
index 5eafdf7..e6ee9e6 100644
--- a/src/lib/ThumbnailGenerator.tsx
+++ b/src/lib/ThumbnailGenerator.tsx
@@ -8,6 +8,7 @@ import Icon from '@components/Icon';
interface ThumbnailGeneratorProps {
id?: string;
+ isDefaultOpen?: boolean;
buttonIcon?: React.ReactNode;
iconSize?: 'small' | 'medium' | 'large';
position?: Position;
@@ -20,13 +21,14 @@ interface ThumbnailGeneratorProps {
const ThumbnailGenerator = ({
id,
buttonIcon,
+ isDefaultOpen = false,
iconSize = 'medium',
iconPosition = [0, 20, 20, 0],
modalPosition = 'right',
isFullWidth = false,
additionalFontFamily = [],
}: ThumbnailGeneratorProps) => {
- const [isOpen, setIsOpen] = useState(false);
+ const [isOpen, setIsOpen] = useState(isDefaultOpen);
const tgIconSize = getIconSize(iconSize);
const onToggleGenerator = () => {
diff --git a/src/stories/components/ThumbnailGenerator.stories.tsx b/src/stories/components/ThumbnailGenerator.stories.tsx
index d00c180..35a2b8a 100644
--- a/src/stories/components/ThumbnailGenerator.stories.tsx
+++ b/src/stories/components/ThumbnailGenerator.stories.tsx
@@ -43,6 +43,7 @@ const Template: Story = ({
iconPosition={iconPosition}
iconSize={iconSize}
isFullWidth={isFullWidth}
+ isDefaultOpen
/>
);
};
diff --git a/src/types/canvas.ts b/src/types/canvas.ts
index 3e67beb..b7d091a 100644
--- a/src/types/canvas.ts
+++ b/src/types/canvas.ts
@@ -2,7 +2,7 @@ import { Color } from 'react-color-palette';
export type StrokeTypes = 'None' | 'Thin' | 'Normal' | 'Thick';
-export type ImageTypes = 'png' | 'jpg' | 'webp';
+export type ImageTypes = 'png' | 'jpg' | 'webp' | 'svg';
export interface CanvasState {
value: string;
diff --git a/src/utils/common.ts b/src/utils/common.ts
index e59fb9e..e315953 100644
--- a/src/utils/common.ts
+++ b/src/utils/common.ts
@@ -2,23 +2,18 @@ import React from 'react';
import { ImageTypes } from '../types/canvas';
export type ValidType = 'imageSize' | 'canvasSize' | 'angle' | 'lineHeight';
+
export const getValidMessage = (condition: boolean, type: ValidType) => {
const message = {
- imageSize: `Please register a picture smaller than "Limit Width"`,
- canvasSize: `Please set the canvas width smaller than "Limit Width"`,
- angle: 'Please set a value in the range of -360 to 360',
- lineHeight: 'Please set a value in the range of 0 to 360',
+ angle: 'Please set the value to within the range',
+ lineHeight: 'Please set the value to within the range',
} as { [key: string]: string };
if (condition) return message[type];
return '';
};
-export const downloadCanvas = (
- ref: React.RefObject,
- imageType: ImageTypes
-) => {
- const url = ref.current?.toDataURL(`image/${imageType}`);
+const download = (url: string, imageType: string) => {
const link = document.createElement('a');
link.href = url as string;
@@ -27,3 +22,30 @@ export const downloadCanvas = (
link.click();
document.body.removeChild(link);
};
+
+export const downloadCanvas = (
+ ref: React.RefObject,
+ imageType: ImageTypes
+) => {
+ if (ref.current) {
+ if (imageType === 'svg') {
+ const imgWidth = ref.current.width;
+ const imgHeight = ref.current.height;
+ const base64 = ref.current.toDataURL('image/png');
+ const svg = `
+
+ `;
+
+ const svgUrl =
+ 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);
+
+ download(svgUrl, 'svg');
+ return;
+ }
+
+ const url = ref.current.toDataURL(`image/${imageType}`);
+ download(url, imageType);
+ }
+};