From 0c1c8e8c784ac1172f637a803957beef9048c639 Mon Sep 17 00:00:00 2001 From: Vinoth Pandian Date: Fri, 18 Jun 2021 18:05:24 +0200 Subject: [PATCH 1/8] refactor code directory structure --- libs/react-sketch-canvas/src/index.ts | 2 +- .../src/lib/{Canvas.tsx => Canvas/index.tsx} | 4 +- .../src/lib/Paths/index.tsx | 48 +++++++++++++++ .../ReactSketchCanvas.spec.tsx | 0 .../index.tsx} | 30 +++++----- .../{typings.ts => types/canvasPath.type.ts} | 7 +-- .../src/lib/types/export.type.ts | 1 + .../src/lib/types/index.ts | 3 + .../src/lib/types/point.type.ts | 4 ++ .../src/lib/{Paths.tsx => utils/commands.ts} | 60 +++---------------- .../src/lib/utils/index.ts | 1 + 11 files changed, 83 insertions(+), 77 deletions(-) rename libs/react-sketch-canvas/src/lib/{Canvas.tsx => Canvas/index.tsx} (98%) create mode 100644 libs/react-sketch-canvas/src/lib/Paths/index.tsx rename libs/react-sketch-canvas/src/lib/{ => ReactSketchCanvas}/ReactSketchCanvas.spec.tsx (100%) rename libs/react-sketch-canvas/src/lib/{ReactSketchCanvas.tsx => ReactSketchCanvas/index.tsx} (94%) rename libs/react-sketch-canvas/src/lib/{typings.ts => types/canvasPath.type.ts} (65%) create mode 100644 libs/react-sketch-canvas/src/lib/types/export.type.ts create mode 100644 libs/react-sketch-canvas/src/lib/types/index.ts create mode 100644 libs/react-sketch-canvas/src/lib/types/point.type.ts rename libs/react-sketch-canvas/src/lib/{Paths.tsx => utils/commands.ts} (58%) create mode 100644 libs/react-sketch-canvas/src/lib/utils/index.ts diff --git a/libs/react-sketch-canvas/src/index.ts b/libs/react-sketch-canvas/src/index.ts index d5a538c..ab1daf8 100644 --- a/libs/react-sketch-canvas/src/index.ts +++ b/libs/react-sketch-canvas/src/index.ts @@ -1,3 +1,3 @@ export * from './lib/Canvas'; export * from './lib/ReactSketchCanvas'; -export * from './lib/typings'; +export * from './lib/types'; diff --git a/libs/react-sketch-canvas/src/lib/Canvas.tsx b/libs/react-sketch-canvas/src/lib/Canvas/index.tsx similarity index 98% rename from libs/react-sketch-canvas/src/lib/Canvas.tsx rename to libs/react-sketch-canvas/src/lib/Canvas/index.tsx index dcccbe7..94bc658 100644 --- a/libs/react-sketch-canvas/src/lib/Canvas.tsx +++ b/libs/react-sketch-canvas/src/lib/Canvas/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import Paths from './Paths'; -import { CanvasPath, ExportImageType, Point } from './typings'; +import Paths from '../Paths'; +import { CanvasPath, ExportImageType, Point } from '../types'; /* Default settings */ diff --git a/libs/react-sketch-canvas/src/lib/Paths/index.tsx b/libs/react-sketch-canvas/src/lib/Paths/index.tsx new file mode 100644 index 0000000..32b8a87 --- /dev/null +++ b/libs/react-sketch-canvas/src/lib/Paths/index.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { CanvasPath, Point } from '../types'; +import { bezierCommand } from '../utils'; + +const svgPath = ( + paths: Point[], + id: string, + strokeWidth: number, + strokeColor: string, + command: (point: Point, i: number, a: Point[]) => string +): JSX.Element => { + const d = paths.reduce( + (acc, point, i, a) => + i === 0 ? `M ${point.x},${point.y}` : `${acc} ${command(point, i, a)}`, + '' + ); + + return ( + + ); +}; + +type PathProps = { + paths: CanvasPath[]; +}; + +const Paths = ({ paths }: PathProps): JSX.Element => ( + + {paths.map((path: CanvasPath, id: number) => + svgPath( + path.paths, + id.toString(), + path.strokeWidth, + path.strokeColor, + bezierCommand + ) + )} + +); + +export default Paths; diff --git a/libs/react-sketch-canvas/src/lib/ReactSketchCanvas.spec.tsx b/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/ReactSketchCanvas.spec.tsx similarity index 100% rename from libs/react-sketch-canvas/src/lib/ReactSketchCanvas.spec.tsx rename to libs/react-sketch-canvas/src/lib/ReactSketchCanvas/ReactSketchCanvas.spec.tsx diff --git a/libs/react-sketch-canvas/src/lib/ReactSketchCanvas.tsx b/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/index.tsx similarity index 94% rename from libs/react-sketch-canvas/src/lib/ReactSketchCanvas.tsx rename to libs/react-sketch-canvas/src/lib/ReactSketchCanvas/index.tsx index 8488ec6..5b66229 100644 --- a/libs/react-sketch-canvas/src/lib/ReactSketchCanvas.tsx +++ b/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/index.tsx @@ -1,23 +1,23 @@ -import { produce } from "immer"; -import React from "react"; -import { Canvas } from "./Canvas"; -import { CanvasPath, ExportImageType, Point } from "./typings"; +import { produce } from 'immer'; +import React from 'react'; +import { Canvas } from '../Canvas'; +import { CanvasPath, ExportImageType, Point } from '../types'; /* Default settings */ const defaultProps = { - width: "100%", - height: "100%", - className: "", - canvasColor: "white", - strokeColor: "red", - background: "", + width: '100%', + height: '100%', + className: '', + canvasColor: 'white', + strokeColor: 'red', + background: '', strokeWidth: 4, eraserWidth: 8, - allowOnlyPointerType: "all", + allowOnlyPointerType: 'all', style: { - border: "0.0625rem solid #9c9c9c", - borderRadius: "0.25rem", + border: '0.0625rem solid #9c9c9c', + borderRadius: '0.25rem', }, // eslint-disable-next-line @typescript-eslint/no-empty-function onUpdate: (_: CanvasPath[]): void => {}, @@ -294,7 +294,7 @@ export class ReactSketchCanvas extends React.Component< const exportImage = this.svgCanvas.current?.exportImage; if (!exportImage) { - throw Error("Export function called before canvas loaded"); + throw Error('Export function called before canvas loaded'); } else { return exportImage(imageType); } @@ -305,7 +305,7 @@ export class ReactSketchCanvas extends React.Component< const exportSvg = this.svgCanvas.current?.exportSvg; if (!exportSvg) { - reject(Error("Export function called before canvas loaded")); + reject(Error('Export function called before canvas loaded')); } else { exportSvg() .then((data) => { diff --git a/libs/react-sketch-canvas/src/lib/typings.ts b/libs/react-sketch-canvas/src/lib/types/canvasPath.type.ts similarity index 65% rename from libs/react-sketch-canvas/src/lib/typings.ts rename to libs/react-sketch-canvas/src/lib/types/canvasPath.type.ts index 828fc5c..7f55b80 100644 --- a/libs/react-sketch-canvas/src/lib/typings.ts +++ b/libs/react-sketch-canvas/src/lib/types/canvasPath.type.ts @@ -1,9 +1,4 @@ -export type ExportImageType = "jpeg" | "png"; - -export interface Point { - readonly x: number; - readonly y: number; -} +import { Point } from '.'; export interface CanvasPath { readonly paths: Point[]; diff --git a/libs/react-sketch-canvas/src/lib/types/export.type.ts b/libs/react-sketch-canvas/src/lib/types/export.type.ts new file mode 100644 index 0000000..9b52725 --- /dev/null +++ b/libs/react-sketch-canvas/src/lib/types/export.type.ts @@ -0,0 +1 @@ +export type ExportImageType = 'jpeg' | 'png'; diff --git a/libs/react-sketch-canvas/src/lib/types/index.ts b/libs/react-sketch-canvas/src/lib/types/index.ts new file mode 100644 index 0000000..f053b0d --- /dev/null +++ b/libs/react-sketch-canvas/src/lib/types/index.ts @@ -0,0 +1,3 @@ +export * from './canvasPath.type'; +export * from './export.type'; +export * from './point.type'; diff --git a/libs/react-sketch-canvas/src/lib/types/point.type.ts b/libs/react-sketch-canvas/src/lib/types/point.type.ts new file mode 100644 index 0000000..ea60820 --- /dev/null +++ b/libs/react-sketch-canvas/src/lib/types/point.type.ts @@ -0,0 +1,4 @@ +export interface Point { + readonly x: number; + readonly y: number; +} diff --git a/libs/react-sketch-canvas/src/lib/Paths.tsx b/libs/react-sketch-canvas/src/lib/utils/commands.ts similarity index 58% rename from libs/react-sketch-canvas/src/lib/Paths.tsx rename to libs/react-sketch-canvas/src/lib/utils/commands.ts index 219d7ac..18cabe4 100644 --- a/libs/react-sketch-canvas/src/lib/Paths.tsx +++ b/libs/react-sketch-canvas/src/lib/utils/commands.ts @@ -1,29 +1,10 @@ -import React from "react"; -import { Point, CanvasPath } from "./typings"; +import { Point } from '../types'; -const svgPath = ( - paths: Point[], - id: string, - strokeWidth: number, - strokeColor: string, - command: (point: Point, i: number, a: Point[]) => string -): JSX.Element => { - const d = paths.reduce( - (acc, point, i, a) => - i === 0 ? `M ${point.x},${point.y}` : `${acc} ${command(point, i, a)}`, - "" - ); - - return ( - - ); +export type ControlPoints = { + current: Point; + previous?: Point; + next?: Point; + reverse?: boolean; }; const line = (pointA: Point, pointB: Point) => { @@ -36,13 +17,6 @@ const line = (pointA: Point, pointB: Point) => { }; }; -type ControlPoints = { - current: Point; - previous?: Point; - next?: Point; - reverse?: boolean; -}; - const controlPoint = (controlPoints: ControlPoints): [number, number] => { const { current, next, previous, reverse } = controlPoints; @@ -62,7 +36,7 @@ const controlPoint = (controlPoints: ControlPoints): [number, number] => { return [x, y]; }; -const bezierCommand = (point: Point, i: number, a: Point[]): string => { +export const bezierCommand = (point: Point, i: number, a: Point[]): string => { let cpsX = null; let cpsY = null; @@ -96,23 +70,3 @@ const bezierCommand = (point: Point, i: number, a: Point[]): string => { return `C ${cpsX},${cpsY} ${cpeX},${cpeY} ${point.x}, ${point.y}`; }; - -type PathProps = { - paths: CanvasPath[]; -}; - -const Paths = ({ paths }: PathProps): JSX.Element => ( - - {paths.map((path: CanvasPath, id: number) => - svgPath( - path.paths, - id.toString(), - path.strokeWidth, - path.strokeColor, - bezierCommand - ) - )} - -); - -export default Paths; diff --git a/libs/react-sketch-canvas/src/lib/utils/index.ts b/libs/react-sketch-canvas/src/lib/utils/index.ts new file mode 100644 index 0000000..30272ff --- /dev/null +++ b/libs/react-sketch-canvas/src/lib/utils/index.ts @@ -0,0 +1 @@ +export * from './commands'; From a7c917cfd1e29658487136603ca166333d6aa806 Mon Sep 17 00:00:00 2001 From: Vinoth Pandian Date: Tue, 24 Aug 2021 08:30:01 +0200 Subject: [PATCH 2/8] add vscode tasks --- .vscode/launch.json | 23 +++++++++++++++++++++++ .vscode/tasks.json | 13 +++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..63270a5 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "pwa-chrome", + "request": "launch", + "name": "Debug storybook", + "url": "http://localhost:4400", + "webRoot": "${workspaceFolder}", + "preLaunchTask": "Storybook", + "sourceMaps": true, + "sourceMapPathOverrides": { + "webpack:///*": "${webRoot}/*", + "webpack:///./*": "${webRoot}/*", + "webpack:///src/*": "${webRoot}/*", + "webpack:///./~/*": "${webRoot}/node_modules/*" + } + } + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..5aac4f7 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,13 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Storybook", + "type": "shell", + "command": "nx run react-sketch-canvas:storybook", + "isBackground": true + } + ] +} From 2522238a07901b8bd81df4bc1797197125c12531 Mon Sep 17 00:00:00 2001 From: Vinoth Pandian Date: Tue, 24 Aug 2021 16:32:58 +0200 Subject: [PATCH 3/8] upgrade dependencies & update folder structure --- .storybook/main.js | 9 +- .storybook/webpack.config.js | 12 - apps/react-sketch-canvas-e2e/.eslintrc.json | 17 - apps/react-sketch-canvas-e2e/cypress.json | 13 - .../src/fixtures/example.json | 4 - .../src/plugins/index.js | 22 - .../src/support/commands.ts | 33 - .../src/support/index.ts | 17 - .../react-sketch-canvas-e2e/tsconfig.e2e.json | 10 - apps/react-sketch-canvas-e2e/tsconfig.json | 10 - jest.config.js | 4 +- libs/react-sketch-canvas/.babelrc | 6 +- libs/react-sketch-canvas/.storybook/main.js | 26 +- .../react-sketch-canvas/.storybook/preview.js | 16 +- .../.storybook/tsconfig.json | 4 + .../.storybook/webpack.config.js | 84 - .../src/lib/Canvas/index.tsx | 11 +- .../src/lib/Paths/index.tsx | 72 +- ...as.spec.tsx => ReactSketchCanvas.test.tsx} | 2 +- .../src/lib/ReactSketchCanvas/index.tsx | 7 +- .../types/{canvasPath.type.ts => canvas.ts} | 7 +- .../src/lib/types/export.type.ts | 1 - .../src/lib/types/index.ts | 4 +- .../src/lib/types/point.type.ts | 4 - .../src/lib/utils/commands.ts | 72 - .../src/lib/utils/index.ts | 1 - .../src/stories/0.demo.stories.mdx | 4 +- .../src/stories/1.demo.stories.tsx | 320 +- .../src/stories/2.demo.stories.tsx | 41 + .../src/stories/demo.stories.css | 2 +- nx.json | 12 +- package.json | 59 +- workspace.json | 38 - yarn.lock | 5229 +++++++---------- 34 files changed, 2423 insertions(+), 3750 deletions(-) delete mode 100644 .storybook/webpack.config.js delete mode 100644 apps/react-sketch-canvas-e2e/.eslintrc.json delete mode 100644 apps/react-sketch-canvas-e2e/cypress.json delete mode 100644 apps/react-sketch-canvas-e2e/src/fixtures/example.json delete mode 100644 apps/react-sketch-canvas-e2e/src/plugins/index.js delete mode 100644 apps/react-sketch-canvas-e2e/src/support/commands.ts delete mode 100644 apps/react-sketch-canvas-e2e/src/support/index.ts delete mode 100644 apps/react-sketch-canvas-e2e/tsconfig.e2e.json delete mode 100644 apps/react-sketch-canvas-e2e/tsconfig.json delete mode 100644 libs/react-sketch-canvas/.storybook/webpack.config.js rename libs/react-sketch-canvas/src/lib/ReactSketchCanvas/{ReactSketchCanvas.spec.tsx => ReactSketchCanvas.test.tsx} (80%) rename libs/react-sketch-canvas/src/lib/types/{canvasPath.type.ts => canvas.ts} (65%) delete mode 100644 libs/react-sketch-canvas/src/lib/types/export.type.ts delete mode 100644 libs/react-sketch-canvas/src/lib/types/point.type.ts delete mode 100644 libs/react-sketch-canvas/src/lib/utils/commands.ts delete mode 100644 libs/react-sketch-canvas/src/lib/utils/index.ts create mode 100644 libs/react-sketch-canvas/src/stories/2.demo.stories.tsx diff --git a/.storybook/main.js b/.storybook/main.js index 84be9fa..1492ac6 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,4 +1,11 @@ module.exports = { stories: [], - addons: ['@storybook/addon-knobs/register'], + addons: ['@storybook/addon-essentials'], + // uncomment the property below if you want to apply some webpack config globally + // webpackFinal: async (config, { configType }) => { + // // Make whatever fine-grained changes you need that should apply to all storybook configs + + // // Return the altered config + // return config; + // }, }; diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js deleted file mode 100644 index 69fcea7..0000000 --- a/.storybook/webpack.config.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Export a function. Accept the base config as the only param. - * @param {Object} options - * @param {Required} options.config - * @param {'DEVELOPMENT' | 'PRODUCTION'} options.mode - change the build configuration. 'PRODUCTION' is used when building the static version of storybook. - */ -module.exports = async ({ config, mode }) => { - // Make whatever fine-grained changes you need - - // Return the altered config - return config; -}; diff --git a/apps/react-sketch-canvas-e2e/.eslintrc.json b/apps/react-sketch-canvas-e2e/.eslintrc.json deleted file mode 100644 index 4c5989b..0000000 --- a/apps/react-sketch-canvas-e2e/.eslintrc.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} - }, - { - "files": ["src/plugins/index.js"], - "rules": { - "@typescript-eslint/no-var-requires": "off", - "no-undef": "off" - } - } - ] -} diff --git a/apps/react-sketch-canvas-e2e/cypress.json b/apps/react-sketch-canvas-e2e/cypress.json deleted file mode 100644 index 73aba0a..0000000 --- a/apps/react-sketch-canvas-e2e/cypress.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "fileServerFolder": ".", - "fixturesFolder": "./src/fixtures", - "integrationFolder": "./src/integration", - "modifyObstructiveCode": false, - "pluginsFile": "./src/plugins/index", - "supportFile": "./src/support/index.ts", - "video": true, - "videosFolder": "../../dist/cypress/apps/react-sketch-canvas-e2e/videos", - "screenshotsFolder": "../../dist/cypress/apps/react-sketch-canvas-e2e/screenshots", - "chromeWebSecurity": false, - "baseUrl": "http://localhost:4400" -} diff --git a/apps/react-sketch-canvas-e2e/src/fixtures/example.json b/apps/react-sketch-canvas-e2e/src/fixtures/example.json deleted file mode 100644 index 294cbed..0000000 --- a/apps/react-sketch-canvas-e2e/src/fixtures/example.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io" -} diff --git a/apps/react-sketch-canvas-e2e/src/plugins/index.js b/apps/react-sketch-canvas-e2e/src/plugins/index.js deleted file mode 100644 index 9067e75..0000000 --- a/apps/react-sketch-canvas-e2e/src/plugins/index.js +++ /dev/null @@ -1,22 +0,0 @@ -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor'); - -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config - - // Preprocess Typescript file using Nx helper - on('file:preprocessor', preprocessTypescript(config)); -}; diff --git a/apps/react-sketch-canvas-e2e/src/support/commands.ts b/apps/react-sketch-canvas-e2e/src/support/commands.ts deleted file mode 100644 index 310f1fa..0000000 --- a/apps/react-sketch-canvas-e2e/src/support/commands.ts +++ /dev/null @@ -1,33 +0,0 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** - -// eslint-disable-next-line @typescript-eslint/no-namespace -declare namespace Cypress { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface Chainable { - login(email: string, password: string): void; - } -} -// -// -- This is a parent command -- -Cypress.Commands.add('login', (email, password) => { - console.log('Custom command example: Login', email, password); -}); -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/apps/react-sketch-canvas-e2e/src/support/index.ts b/apps/react-sketch-canvas-e2e/src/support/index.ts deleted file mode 100644 index 3d469a6..0000000 --- a/apps/react-sketch-canvas-e2e/src/support/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example support/index.js is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands'; diff --git a/apps/react-sketch-canvas-e2e/tsconfig.e2e.json b/apps/react-sketch-canvas-e2e/tsconfig.e2e.json deleted file mode 100644 index 9dc3660..0000000 --- a/apps/react-sketch-canvas-e2e/tsconfig.e2e.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "sourceMap": false, - "outDir": "../../dist/out-tsc", - "allowJs": true, - "types": ["cypress", "node"] - }, - "include": ["src/**/*.ts", "src/**/*.js"] -} diff --git a/apps/react-sketch-canvas-e2e/tsconfig.json b/apps/react-sketch-canvas-e2e/tsconfig.json deleted file mode 100644 index 08841a7..0000000 --- a/apps/react-sketch-canvas-e2e/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.e2e.json" - } - ] -} diff --git a/jest.config.js b/jest.config.js index 086ee35..42c86fd 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,3 +1,5 @@ +const { getJestProjects } = require('@nrwl/jest'); + module.exports = { - projects: [, '/libs/react-sketch-canvas'], + projects: getJestProjects(), }; diff --git a/libs/react-sketch-canvas/.babelrc b/libs/react-sketch-canvas/.babelrc index ccae900..0c705df 100644 --- a/libs/react-sketch-canvas/.babelrc +++ b/libs/react-sketch-canvas/.babelrc @@ -8,5 +8,9 @@ } ] ], - "plugins": [] + "plugins": [ + ["@babel/plugin-proposal-class-properties", { "loose": false }], + ["@babel/plugin-proposal-private-methods", { "loose": false }], + ["@babel/plugin-proposal-private-property-in-object", { "loose": false }] + ] } diff --git a/libs/react-sketch-canvas/.storybook/main.js b/libs/react-sketch-canvas/.storybook/main.js index 87e71d3..60d494d 100644 --- a/libs/react-sketch-canvas/.storybook/main.js +++ b/libs/react-sketch-canvas/.storybook/main.js @@ -1,12 +1,22 @@ const rootMain = require('../../../.storybook/main'); -rootMain.addons.push(...['@storybook/addon-docs', '@storybook/preset-scss']); +module.exports = { + ...rootMain, -rootMain.stories.push( - ...[ - '../src/stories/**/*.stories.mdx', - '../src/stories/**/*.stories.@(js|jsx|ts|tsx)', - ] -); + stories: [ + ...rootMain.stories, + '../src/stories/*.stories.mdx', + '../src/stories/*.stories.@(js|jsx|ts|tsx)', + ], + addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'], + webpackFinal: async (config, { configType }) => { + // apply any global webpack configs that might have been specified in .storybook/main.js + if (rootMain.webpackFinal) { + config = await rootMain.webpackFinal(config, { configType }); + } -module.exports = rootMain; + // add your own webpack tweaks if needed + + return config; + }, +}; diff --git a/libs/react-sketch-canvas/.storybook/preview.js b/libs/react-sketch-canvas/.storybook/preview.js index b6146b1..4b3718a 100644 --- a/libs/react-sketch-canvas/.storybook/preview.js +++ b/libs/react-sketch-canvas/.storybook/preview.js @@ -1,9 +1,17 @@ -import { withKnobs } from '@storybook/addon-knobs'; -import { addDecorator, addParameters } from '@storybook/react'; - -addDecorator(withKnobs); +import { addParameters } from '@storybook/react'; addParameters({ layout: 'centered', viewMode: 'docs', + controls: { + matchers: { + color: /(color)$/i, + date: /Date$/, + }, + }, + docs: { + source: { + type: 'code', + }, + }, }); diff --git a/libs/react-sketch-canvas/.storybook/tsconfig.json b/libs/react-sketch-canvas/.storybook/tsconfig.json index 9c7c2c5..56bdf56 100644 --- a/libs/react-sketch-canvas/.storybook/tsconfig.json +++ b/libs/react-sketch-canvas/.storybook/tsconfig.json @@ -4,6 +4,10 @@ "emitDecoratorMetadata": true, "outDir": "" }, + "files": [ + "../../../node_modules/@nrwl/react/typings/cssmodule.d.ts", + "../../../node_modules/@nrwl/react/typings/image.d.ts" + ], "exclude": [ "../**/*.spec.ts", "../**/*.spec.js", diff --git a/libs/react-sketch-canvas/.storybook/webpack.config.js b/libs/react-sketch-canvas/.storybook/webpack.config.js deleted file mode 100644 index 37c9551..0000000 --- a/libs/react-sketch-canvas/.storybook/webpack.config.js +++ /dev/null @@ -1,84 +0,0 @@ -const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); -const rootWebpackConfig = require('../../../.storybook/webpack.config'); -/** - * Export a function. Accept the base config as the only param. - * - * @param {Parameters[0]} options - */ -module.exports = async ({ config, mode }) => { - config = await rootWebpackConfig({ config, mode }); - - const tsPaths = new TsconfigPathsPlugin({ - configFile: './tsconfig.base.json', - }); - - config.resolve.plugins - ? config.resolve.plugins.push(tsPaths) - : (config.resolve.plugins = [tsPaths]); - - // Found this here: https://github.com/nrwl/nx/issues/2859 - // And copied the part of the solution that made it work - - const svgRuleIndex = config.module.rules.findIndex((rule) => { - const { test } = rule; - - return test.toString().startsWith('/\\.(svg|ico'); - }); - config.module.rules[ - svgRuleIndex - ].test = /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/; - - config.module.rules.push( - { - test: /\.(png|jpe?g|gif|webp)$/, - loader: require.resolve('url-loader'), - options: { - limit: 10000, // 10kB - name: '[name].[hash:7].[ext]', - }, - }, - { - test: /\.svg$/, - oneOf: [ - // If coming from JS/TS file, then transform into React component using SVGR. - { - issuer: { - test: /\.[jt]sx?$/, - }, - use: [ - { - loader: require.resolve('@svgr/webpack'), - options: { - svgo: false, - titleProp: true, - ref: true, - }, - }, - { - loader: require.resolve('url-loader'), - options: { - limit: 10000, // 10kB - name: '[name].[hash:7].[ext]', - esModule: false, - }, - }, - ], - }, - // Fallback to plain URL loader. - { - use: [ - { - loader: require.resolve('url-loader'), - options: { - limit: 10000, // 10kB - name: '[name].[hash:7].[ext]', - }, - }, - ], - }, - ], - } - ); - - return config; -}; diff --git a/libs/react-sketch-canvas/src/lib/Canvas/index.tsx b/libs/react-sketch-canvas/src/lib/Canvas/index.tsx index 94bc658..fb24063 100644 --- a/libs/react-sketch-canvas/src/lib/Canvas/index.tsx +++ b/libs/react-sketch-canvas/src/lib/Canvas/index.tsx @@ -207,15 +207,8 @@ export class Canvas extends React.Component { /* Finally!!! Render method */ render(): JSX.Element { - const { - width, - height, - className, - canvasColor, - background, - style, - paths, - } = this.props; + const { width, height, className, canvasColor, background, style, paths } = + this.props; return (
{ + const lengthX = pointB.x - pointA.x; + const lengthY = pointB.y - pointA.y; + + return { + length: Math.sqrt(lengthX ** 2 + lengthY ** 2), + angle: Math.atan2(lengthY, lengthX), + }; +}; + +type ControlPoints = { + current: Point; + previous?: Point; + next?: Point; + reverse?: boolean; +}; + +const controlPoint = (controlPoints: ControlPoints): [number, number] => { + const { current, next, previous, reverse } = controlPoints; + + const p = previous || current; + const n = next || current; + + const smoothing = 0.2; + + const o = line(p, n); + + const angle = o.angle + (reverse ? Math.PI : 0); + const length = o.length * smoothing; + + const x = current.x + Math.cos(angle) * length; + const y = current.y + Math.sin(angle) * length; + + return [x, y]; +}; + +const bezierCommand = (point: Point, i: number, a: Point[]): string => { + let cpsX = null; + let cpsY = null; + + switch (i) { + case 0: + [cpsX, cpsY] = controlPoint({ + current: point, + }); + break; + case 1: + [cpsX, cpsY] = controlPoint({ + current: a[i - 1], + next: point, + }); + break; + default: + [cpsX, cpsY] = controlPoint({ + current: a[i - 1], + previous: a[i - 2], + next: point, + }); + break; + } + + const [cpeX, cpeY] = controlPoint({ + current: point, + previous: a[i - 1], + next: a[i + 1], + reverse: true, + }); + + return `C ${cpsX},${cpsY} ${cpeX},${cpeY} ${point.x}, ${point.y}`; +}; + type PathProps = { paths: CanvasPath[]; }; diff --git a/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/ReactSketchCanvas.spec.tsx b/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/ReactSketchCanvas.test.tsx similarity index 80% rename from libs/react-sketch-canvas/src/lib/ReactSketchCanvas/ReactSketchCanvas.spec.tsx rename to libs/react-sketch-canvas/src/lib/ReactSketchCanvas/ReactSketchCanvas.test.tsx index 5c747cd..672680f 100644 --- a/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/ReactSketchCanvas.spec.tsx +++ b/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/ReactSketchCanvas.test.tsx @@ -1,5 +1,5 @@ import { render } from '@testing-library/react'; -import { ReactSketchCanvas } from './ReactSketchCanvas'; +import { ReactSketchCanvas } from '.'; describe('ReactSketchCanvas', () => { it('should render successfully', () => { diff --git a/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/index.tsx b/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/index.tsx index 5b66229..f564215 100644 --- a/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/index.tsx +++ b/libs/react-sketch-canvas/src/lib/ReactSketchCanvas/index.tsx @@ -246,12 +246,7 @@ export class ReactSketchCanvas extends React.Component< draft.currentPaths = draft.resetStack; draft.resetStack = []; }), - () => { - const { currentPaths } = this.state; - const { onUpdate } = this.props; - - onUpdate(currentPaths); - } + this.liftPathsUp ); return; diff --git a/libs/react-sketch-canvas/src/lib/types/canvasPath.type.ts b/libs/react-sketch-canvas/src/lib/types/canvas.ts similarity index 65% rename from libs/react-sketch-canvas/src/lib/types/canvasPath.type.ts rename to libs/react-sketch-canvas/src/lib/types/canvas.ts index 7f55b80..828fc5c 100644 --- a/libs/react-sketch-canvas/src/lib/types/canvasPath.type.ts +++ b/libs/react-sketch-canvas/src/lib/types/canvas.ts @@ -1,4 +1,9 @@ -import { Point } from '.'; +export type ExportImageType = "jpeg" | "png"; + +export interface Point { + readonly x: number; + readonly y: number; +} export interface CanvasPath { readonly paths: Point[]; diff --git a/libs/react-sketch-canvas/src/lib/types/export.type.ts b/libs/react-sketch-canvas/src/lib/types/export.type.ts deleted file mode 100644 index 9b52725..0000000 --- a/libs/react-sketch-canvas/src/lib/types/export.type.ts +++ /dev/null @@ -1 +0,0 @@ -export type ExportImageType = 'jpeg' | 'png'; diff --git a/libs/react-sketch-canvas/src/lib/types/index.ts b/libs/react-sketch-canvas/src/lib/types/index.ts index f053b0d..baba675 100644 --- a/libs/react-sketch-canvas/src/lib/types/index.ts +++ b/libs/react-sketch-canvas/src/lib/types/index.ts @@ -1,3 +1 @@ -export * from './canvasPath.type'; -export * from './export.type'; -export * from './point.type'; +export * from './canvas'; diff --git a/libs/react-sketch-canvas/src/lib/types/point.type.ts b/libs/react-sketch-canvas/src/lib/types/point.type.ts deleted file mode 100644 index ea60820..0000000 --- a/libs/react-sketch-canvas/src/lib/types/point.type.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface Point { - readonly x: number; - readonly y: number; -} diff --git a/libs/react-sketch-canvas/src/lib/utils/commands.ts b/libs/react-sketch-canvas/src/lib/utils/commands.ts deleted file mode 100644 index 18cabe4..0000000 --- a/libs/react-sketch-canvas/src/lib/utils/commands.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Point } from '../types'; - -export type ControlPoints = { - current: Point; - previous?: Point; - next?: Point; - reverse?: boolean; -}; - -const line = (pointA: Point, pointB: Point) => { - const lengthX = pointB.x - pointA.x; - const lengthY = pointB.y - pointA.y; - - return { - length: Math.sqrt(lengthX ** 2 + lengthY ** 2), - angle: Math.atan2(lengthY, lengthX), - }; -}; - -const controlPoint = (controlPoints: ControlPoints): [number, number] => { - const { current, next, previous, reverse } = controlPoints; - - const p = previous || current; - const n = next || current; - - const smoothing = 0.2; - - const o = line(p, n); - - const angle = o.angle + (reverse ? Math.PI : 0); - const length = o.length * smoothing; - - const x = current.x + Math.cos(angle) * length; - const y = current.y + Math.sin(angle) * length; - - return [x, y]; -}; - -export const bezierCommand = (point: Point, i: number, a: Point[]): string => { - let cpsX = null; - let cpsY = null; - - switch (i) { - case 0: - [cpsX, cpsY] = controlPoint({ - current: point, - }); - break; - case 1: - [cpsX, cpsY] = controlPoint({ - current: a[i - 1], - next: point, - }); - break; - default: - [cpsX, cpsY] = controlPoint({ - current: a[i - 1], - previous: a[i - 2], - next: point, - }); - break; - } - - const [cpeX, cpeY] = controlPoint({ - current: point, - previous: a[i - 1], - next: a[i + 1], - reverse: true, - }); - - return `C ${cpsX},${cpsY} ${cpeX},${cpeY} ${point.x}, ${point.y}`; -}; diff --git a/libs/react-sketch-canvas/src/lib/utils/index.ts b/libs/react-sketch-canvas/src/lib/utils/index.ts deleted file mode 100644 index 30272ff..0000000 --- a/libs/react-sketch-canvas/src/lib/utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './commands'; diff --git a/libs/react-sketch-canvas/src/stories/0.demo.stories.mdx b/libs/react-sketch-canvas/src/stories/0.demo.stories.mdx index 94f0290..e4feba8 100644 --- a/libs/react-sketch-canvas/src/stories/0.demo.stories.mdx +++ b/libs/react-sketch-canvas/src/stories/0.demo.stories.mdx @@ -1,5 +1,5 @@ -import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks'; -import { ReactSketchCanvas } from 'react-sketch-canvas'; +import { Meta, Story, Canvas } from '@storybook/addon-docs'; +import { ReactSketchCanvas } from '..'; diff --git a/libs/react-sketch-canvas/src/stories/1.demo.stories.tsx b/libs/react-sketch-canvas/src/stories/1.demo.stories.tsx index fc742dd..31d71e8 100644 --- a/libs/react-sketch-canvas/src/stories/1.demo.stories.tsx +++ b/libs/react-sketch-canvas/src/stories/1.demo.stories.tsx @@ -1,27 +1,29 @@ /* eslint-disable react/no-danger */ /* eslint-disable jsx-a11y/label-has-associated-control */ -import { - boolean, - button, - color, - files, - number, - optionsKnob as options, - text, -} from '@storybook/addon-knobs'; -import * as React from 'react'; + +import { Meta, Story } from '@storybook/react'; +import React from 'react'; import { CanvasPath, ExportImageType, ReactSketchCanvas, -} from 'react-sketch-canvas'; + ReactSketchCanvasProps, +} from '..'; import './demo.stories.css'; export default { - title: 'Demo/React Sketch Canvas', + title: 'Demo/With Reference', component: ReactSketchCanvas, - parameters: { docs: { disable: true, page: null }, viewMode: 'story' }, -}; + argTypes: { + allowOnlyPointerType: { + options: ['mouse', 'touch', 'pen', 'all'], + control: { type: 'radio' }, + }, + strokeColor: { + control: { type: 'color' }, + }, + }, +} as Meta; const pointerModes = { mouse: 'mouse', @@ -38,7 +40,19 @@ const imageTypes: { [key: string]: ExportImageType } = { type CanvasRef = React.RefObject; type Handlers = [string, () => void, string][]; -export const SketchCanvas = () => { +const Template: Story = ({ + className, + width, + height, + background, + strokeWidth, + strokeColor, + canvasColor, + eraserWidth, + allowOnlyPointerType, + style, + withTimestamp, +}) => { const canvasRef: CanvasRef = React.useRef(null); const [dataURI, setDataURI] = React.useState(''); @@ -46,70 +60,11 @@ export const SketchCanvas = () => { const [paths, setPaths] = React.useState([]); const [sketchingTime, setSketchingTime] = React.useState(0); - const width = text('Canvas width in em/rem/px (width)', '100%'); - const height = text('Canvas height in em/rem/px (height)', '500px'); - const className = text('Class name (className)', 'react-sketch-canvas'); - const canvasColor = color('Canvas background color (canvasColor)', '#FFFFFF'); - const background = text( - 'SVG background using CSS (background)', - 'url(https://upload.wikimedia.org/wikipedia/commons/7/70/Graph_paper_scan_1600x1000_%286509259561%29.jpg)' - ); - const strokeColor = color('Stroke color (strokeColor)', '#000000'); - const strokeWidth = number('Stroke thickness (strokeWidth)', 4); - const eraserWidth = number('Eraser thickness (eraserWidth)', 5); - const pointerType = options( - 'Allowed pointer type (allowOnlyPointerType)', - pointerModes, - 'all', - { - display: 'radio', - } - ); - - const imageType = options('Image type to export ', imageTypes, 'png', { - display: 'radio', - }); - - const withTimestamp = boolean('Add timestamp to strokes', true); - - const pathsToLoad = files('Load Paths from JSON file', '.json', []); - - const loadPathHandler = () => { - if (pathsToLoad.length === 0) { - alert( - "Add a file to 'Load path from uploaded file' to load it on canvas" - ); - return; - } - - if (pathsToLoad.length > 1) { - alert( - "Please choose only one file on 'Load path from uploaded file' to load it on canvas" - ); - return; - } - - try { - const dataURI = pathsToLoad[0]; - const data = atob(dataURI.substring(29)); - const newPaths: CanvasPath[] = JSON.parse(data); - - canvasRef.current?.loadPaths(newPaths); - } catch (error) { - alert( - error.message + - 'Invalid Path format. It must be a list of CanvasPath type. More information on required fields in CanvasPath can be found here -> https://github.com/vinothpandian/react-sketch-canvas/#types' - ); - } - }; - - button('Load path from a uploaded file', loadPathHandler); - const imageExportHandler = async () => { const exportImage = canvasRef.current?.exportImage; if (exportImage) { - const exportedDataURI = await exportImage(imageType); + const exportedDataURI = await exportImage('png'); setDataURI(exportedDataURI); } }; @@ -186,6 +141,7 @@ export const SketchCanvas = () => { themeColor: string ) => (