diff --git a/.eslintrc.json b/.eslintrc.json index 2060b64..45baed2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,9 +4,6 @@ "plugin:react/recommended", "plugin:prettier/recommended" ], - "ecmaFeatures": { - "experimentalObjectRestSpread": true - }, "env": { "browser": true, "es6": true, diff --git a/README.md b/README.md index cbb9c5f..59c2c61 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ The plugin's name is based on Dutch graphic designer [Wim Crouwel](https://en.wi ## Features - Create an unlimited amount of layout grids with varying dimensions, columns, gutters, and margins -- Build grids and overlay them upon any object: artboards, rectangles, polygons, text, etc. +- Construct grids with columns or rows or both +- Produce grids as rectangle fills or gridlines or both +- Build grids that fit into any object: artboards, rectangles, polygons, text, etc. - Use auto-calculations to make sure your grids hold your desired structure while still being valid - Support for grid construction using decimals -- Produce grids as rectangle fills or gridlines or both diff --git a/package.json b/package.json index aa05b93..f759009 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,12 @@ "watch": "nodemon -w src -e js,jsx,css -w webpack.config.js -x yarn build" }, "devDependencies": { + "@babel/core": "^7.9.6", + "@babel/plugin-transform-react-jsx": "^7.10.1", + "babel-loader": "^8.1.0", "clean-webpack-plugin": "^3.0.0", "copy-webpack-plugin": "^6.0.0", + "css-loader": "^3.5.3", "eslint": "^7.0.0", "eslint-config-prettier": "^6.11.0", "eslint-plugin-jest": "^23.13.1", @@ -24,19 +28,14 @@ "jest": "^26.0.1", "nodemon": "^2.0.4", "prettier": "^2.0.5", + "style-loader": "^1.2.1", "webpack": "^4.43.0", - "webpack-cli": "^3.3.11" + "webpack-cli": "^3.3.11", + "yarn": "^1.22.4" }, "dependencies": { - "@babel/core": "^7.9.6", - "babel-core": "^6.26.3", - "babel-loader": "^8.1.0", - "babel-plugin-transform-react-jsx": "^6.24.1", - "css-loader": "^3.5.3", "prop-types": "^15.7.2", "react": "^16.13.1", - "react-dom": "^16.13.1", - "style-loader": "^1.2.1", - "yarn": "^1.22.4" + "react-dom": "^16.13.1" } } diff --git a/src/components/Panel.jsx b/src/components/Panel.jsx index 5229c53..5093778 100644 --- a/src/components/Panel.jsx +++ b/src/components/Panel.jsx @@ -24,6 +24,8 @@ const Panel = ({ selectionAmount, validSelection }) => { const [boundType, setBoundType] = useState('path') const [canvasWidth, setCanvasWidth] = useState('') const [canvasHeight, setCanvasHeight] = useState('') + + const [createCols, setCreateCols] = useState(true) const [cols, setCols] = useState('') const [gutterWidth, setGutterWidth] = useState(0) const [colWidth, setColWidth] = useState('') @@ -32,6 +34,15 @@ const Panel = ({ selectionAmount, validSelection }) => { const [bottomMargin, setBottomMargin] = useState(0) const [leftMargin, setLeftMargin] = useState(0) + const [createRows, setCreateRows] = useState(true) + const [rows, setRows] = useState('') + const [gutterHeight, setGutterHeight] = useState(0) + const [rowHeight, setRowHeight] = useState('') + const [rowTopMargin, setRowTopMargin] = useState(0) + const [rowRightMargin, setRowRightMargin] = useState(0) + const [rowBottomMargin, setRowBottomMargin] = useState(0) + const [rowLeftMargin, setRowLeftMargin] = useState(0) + const [colWidthsSum, setColWidthsSum] = useState('N/A') const [gridHeight, setGridHeight] = useState('N/A') const [gridWidth, setGridWidth] = useState('N/A') @@ -39,18 +50,25 @@ const Panel = ({ selectionAmount, validSelection }) => { const [topBottomMarginsSum, setTopBottomMarginsSum] = useState(0) const [rightLeftMarginsSum, setRightLeftMarginsSum] = useState(0) + const [rowHeightsSum, setRowHeightsSum] = useState('N/A') + const [rowGridHeight, setRowGridHeight] = useState('N/A') + const [rowGridWidth, setRowGridWidth] = useState('N/A') + const [gutterHeightsSum, setGutterHeightsSum] = useState('N/A') + const [rowTopBottomMarginsSum, setRowTopBottomMarginsSum] = useState(0) + const [rowRightLeftMarginsSum, setRowRightLeftMarginsSum] = useState(0) + const [drawFields, setDrawFields] = useState(true) const [drawGridlines, setDrawGridlines] = useState(true) - const [isCalcReady, setIsCalcReady] = useState(false) + const [isColCalcReady, setIsColCalcReady] = useState(false) + const [isRowCalcReady, setIsRowCalcReady] = useState(false) - const calcState = { + const colCalcState = { + floorVals, canvasHeight, canvasWidth, cols, colWidth, - floorVals, - gridHeight, gutterWidth, topMargin, rightMargin, @@ -58,23 +76,36 @@ const Panel = ({ selectionAmount, validSelection }) => { leftMargin, } + const rowCalcState = { + floorVals, + canvasHeight: canvasWidth, + canvasWidth: canvasHeight, + cols: rows, + colWidth: rowHeight, + gutterWidth: gutterHeight, + topMargin: rowTopMargin, + rightMargin: rowRightMargin, + bottomMargin: rowBottomMargin, + leftMargin: rowLeftMargin, + } + /** - * Reset stats on panel UI. + * Reset column stats on panel UI. */ - const resetStats = () => { + const resetColStats = () => { setColWidthsSum('N/A') setGridHeight('N/A') setGridWidth('N/A') setGutterWidthsSum('N/A') setTopBottomMarginsSum(0) setRightLeftMarginsSum(0) - setIsCalcReady(false) + setIsColCalcReady(false) } /** - * Reset form & stats on panel UI. + * Reset column form & stats on panel UI. */ - const resetForm = () => { + const resetColForm = () => { setFloorVals(true) setCols('') setGutterWidth(0) @@ -83,20 +114,75 @@ const Panel = ({ selectionAmount, validSelection }) => { setRightMargin(0) setBottomMargin(0) setLeftMargin(0) + resetColStats() + } + + /** + * Reset row stats on panel UI. + */ + const resetRowStats = () => { + setRowHeightsSum('N/A') + setRowGridHeight('N/A') + setRowGridWidth('N/A') + setGutterHeightsSum('N/A') + setRowTopBottomMarginsSum(0) + setRowRightLeftMarginsSum(0) + setIsRowCalcReady(false) + } + + /** + * Reset row form & stats on panel UI. + */ + const resetRowForm = () => { + setFloorVals(true) + setRows('') + setGutterHeight(0) + setRowHeight('') + setRowTopMargin(0) + setRowRightMargin(0) + setRowBottomMargin(0) + setRowLeftMargin(0) + resetRowStats() + } + + /** + * Reset form & stats on panel UI. + */ + const resetForm = () => { + setFloorVals(true) setDrawFields(true) setDrawGridlines(true) - resetStats() + + setCols('') + setGutterWidth(0) + setColWidth('') + setTopMargin(0) + setRightMargin(0) + setBottomMargin(0) + setLeftMargin(0) + + setRows('') + setGutterHeight(0) + setRowHeight('') + setRowTopMargin(0) + setRowRightMargin(0) + setRowBottomMargin(0) + setRowLeftMargin(0) + + resetColStats() + resetRowStats() } /** - * Set form to calcState values. + * Set form to column calcState values. + * @param {Object} calcState State for calculations */ const setForm = (calcState) => { + setFloorVals(calcState.floorVals) setCanvasWidth(calcState.canvasWidth) setCanvasHeight(calcState.canvasHeight) setCols(calcState.cols) setColWidth(calcState.colWidth) - setFloorVals(calcState.floorVals) setGutterWidth(calcState.gutterWidth) setTopMargin(calcState.topMargin) setRightMargin(calcState.rightMargin) @@ -105,9 +191,29 @@ const Panel = ({ selectionAmount, validSelection }) => { } /** - * Attempt calculations for column width. + * Set form to rowCalcState values. + * @param {Object} calcState State for calculations */ - const attemptColWidthCalc = () => { + const setRowForm = (calcState) => { + setFloorVals(calcState.floorVals) + setCanvasWidth(calcState.canvasHeight) + setCanvasHeight(calcState.canvasWidth) + setRows(calcState.cols) + setRowHeight(calcState.colWidth) + setGutterHeight(calcState.gutterWidth) + setRowTopMargin(calcState.topMargin) + setRowRightMargin(calcState.rightMargin) + setRowBottomMargin(calcState.bottomMargin) + setRowLeftMargin(calcState.leftMargin) + } + + /** + * Validates calcState for calcColWidth. If validation is successful, calcColWidth is called. + * @param {Object} calcState State for calculations + * @param {boolean} [updateLeftMargin=false] Flag to control update for left margin. By default it is set to false, so the right margin will be updated. + * @returns {Object|null} If a final successful calculation occurred, it will be returned, otherwise it will return null + */ + const validateAndCalcColWidth = (calcState, updateLeftMargin = false) => { let finalResult // Clean inputs to possible values // May not be enough inputs for calculations though @@ -118,7 +224,7 @@ const Panel = ({ selectionAmount, validSelection }) => { if (canCalcColWidth) { // calcColWidth is possible - const results = calcColWidth(calcState, [ + const results = calcColWidth(calcState, updateLeftMargin, [ 'rightLeftMargins', 'cols', 'gutterWidth', @@ -129,39 +235,25 @@ const Panel = ({ selectionAmount, validSelection }) => { if (Array.isArray(results) && results.length > 0) { finalResult = results[results.length - 1] } - } - - if ( - finalResult && - Array.isArray(finalResult.errs) && - finalResult.errs.length === 0 - ) { - // Final result was successful - setColWidthsSum(finalResult.colWidthsSum) - setGridWidth(finalResult.gridWidth) - setGutterWidthsSum(finalResult.gutterWidthsSum) - setRightLeftMarginsSum(finalResult.rightLeftMarginsSum) - // Calculate grid height - const calcGridHeightResult = calcGridHeight(calcState) - setGridHeight(calcState.gridHeight) - setTopBottomMarginsSum(calcGridHeightResult.topBottomMarginsSum) - setIsCalcReady(true) - } + if ( + finalResult && + Array.isArray(finalResult.errs) && + finalResult.errs.length === 0 + ) { + return finalResult + } - if (!canCalcColWidth || !finalResult) { - // Not possible to run calcColWidth or final result failed - resetStats() + return null } - - // Update form UI to reflect input value changes - setForm(calcState) } /** - * Attempt calculations for gutter width. + * Validates calcState for calcGutterWidth. If validation is successful, calcGutterWidth is called. + * @param {Object} calcState State for calculations + * @returns {Object|null} If a final successful calculation occurred, it will be returned, otherwise it will return null */ - const attemptGutterWidthCalc = () => { + const validateAndCalcGutterWidth = (calcState) => { let finalResult // Clean inputs to possible values // May not be enough inputs for calculations though @@ -172,7 +264,7 @@ const Panel = ({ selectionAmount, validSelection }) => { if (canCalcGutterWidth) { // calcGutterWidth is possible - const results = calcGutterWidth(calcState, [ + const results = calcGutterWidth(calcState, false, [ 'rightLeftMargins', 'cols', 'colWidth', @@ -190,22 +282,61 @@ const Panel = ({ selectionAmount, validSelection }) => { Array.isArray(finalResult.errs) && finalResult.errs.length === 0 ) { + return finalResult + } + + return null + } + + /** + * Attempt calculations for column width. + * @param {Object} calcState State for calculations + * @param {boolean} [updateLeftMargin=false] Flag to control update for left margin. By default it is set to false, so the right margin will be updated. + */ + const attemptColWidthCalc = (calcState, updateLeftMargin = false) => { + const result = validateAndCalcColWidth(calcState, updateLeftMargin) + + if (result) { // Final result was successful - setColWidthsSum(finalResult.colWidthsSum) - setGridWidth(finalResult.gridWidth) - setGutterWidthsSum(finalResult.gutterWidthsSum) - setRightLeftMarginsSum(finalResult.rightLeftMarginsSum) + setColWidthsSum(result.colWidthsSum) + setGridWidth(result.gridWidth) + setGutterWidthsSum(result.gutterWidthsSum) + setRightLeftMarginsSum(result.rightLeftMarginsSum) // Calculate grid height const calcGridHeightResult = calcGridHeight(calcState) - setGridHeight(calcState.gridHeight) + setGridHeight(calcGridHeightResult.gridHeight) setTopBottomMarginsSum(calcGridHeightResult.topBottomMarginsSum) - setIsCalcReady(true) + setIsColCalcReady(true) + } else { + resetColStats() } - if (!canCalcGutterWidth || !finalResult) { - // Not possible to run calcColWidth or final result failed - resetStats() + // Update form UI to reflect input value changes + setForm(calcState) + } + + /** + * Attempt calculations for gutter width. + * @param {Object} calcState State for calculations + */ + const attemptGutterWidthCalc = (calcState) => { + const result = validateAndCalcGutterWidth(calcState) + + if (result) { + // Final result was successful + setColWidthsSum(result.colWidthsSum) + setGridWidth(result.gridWidth) + setGutterWidthsSum(result.gutterWidthsSum) + setRightLeftMarginsSum(result.rightLeftMarginsSum) + + // Calculate grid height + const calcGridHeightResult = calcGridHeight(calcState) + setGridHeight(calcGridHeightResult.gridHeight) + setTopBottomMarginsSum(calcGridHeightResult.topBottomMarginsSum) + setIsColCalcReady(true) + } else { + resetColStats() } // Update form UI to reflect input value changes @@ -213,9 +344,10 @@ const Panel = ({ selectionAmount, validSelection }) => { } /** - * Attempt calculations for top bottom margins. + * Attempt calculations for column grid height. + * @param {Object} calcState State for calculations */ - const attemptGridHeightCalc = () => { + const attemptGridHeightCalc = (calcState) => { // Clean inputs to possible values // May not be enough inputs for calculations though validateInputs(calcState) @@ -237,14 +369,103 @@ const Panel = ({ selectionAmount, validSelection }) => { topBottomMarginsSum: result.topBottomMarginsSum, }) ) { - // Previous calculation was valid, so set isCalcReady to true - setIsCalcReady(true) + // Previous calculation was valid, so set isColCalcReady to true + setIsColCalcReady(true) } } setForm(calcState) } + /** + * Attempt calculations for row height. + * @param {Object} calcState State for calculations + * @param {boolean} [updateLeftMargin=true] Flag to control update for left margin. By default it is set to true, so the left margin will be updated. + */ + const attemptRowHeightCalc = (calcState, updateLeftMargin = true) => { + const result = validateAndCalcColWidth(calcState, updateLeftMargin) + + if (result) { + // Final result was successful + setRowHeightsSum(result.colWidthsSum) + setRowGridWidth(result.gridWidth) + setGutterHeightsSum(result.gutterWidthsSum) + setRowRightLeftMarginsSum(result.rightLeftMarginsSum) + + // Calculate grid height + const calcGridHeightResult = calcGridHeight(calcState) + setRowGridHeight(calcGridHeightResult.gridHeight) + setRowTopBottomMarginsSum(calcGridHeightResult.topBottomMarginsSum) + setIsRowCalcReady(true) + } else { + resetRowStats() + } + + // Update form UI to reflect input value changes + setRowForm(calcState) + } + + /** + * Attempt calculations for gutter height. + * @param {Object} calcState State for calculations + */ + const attemptGutterHeightCalc = (calcState) => { + const result = validateAndCalcGutterWidth(calcState) + + if (result) { + // Final result was successful + setRowHeightsSum(result.colWidthsSum) + setRowGridWidth(result.gridWidth) + setGutterHeightsSum(result.gutterWidthsSum) + setRowRightLeftMarginsSum(result.rightLeftMarginsSum) + + // Calculate grid height + const calcGridHeightResult = calcGridHeight(calcState) + setRowGridHeight(calcGridHeightResult.gridHeight) + setRowTopBottomMarginsSum(calcGridHeightResult.topBottomMarginsSum) + setIsRowCalcReady(true) + } else { + resetRowStats() + } + + // Update form UI to reflect input value changes + setRowForm(calcState) + } + + /** + * Attempt calculations for row grid height. + * @param {Object} calcState State for calculations + */ + const attemptRowGridHeightCalc = (calcState) => { + // Clean inputs to possible values + // May not be enough inputs for calculations though + validateInputs(calcState) + + if (validateColWidthCalc(calcState) || validateGutterWidthCalc(calcState)) { + // If calcColWidth or calcGutterWidth is possible, run calcGridHeight + const result = calcGridHeight(calcState) + + setRowGridHeight(result.gridHeight) + setRowTopBottomMarginsSum(result.topBottomMarginsSum) + + if ( + validateStats({ + colWidthsSum: rowHeightsSum, + gutterWidthsSum: gutterHeightsSum, + gridWidth: rowGridWidth, + gridHeight: result.gridHeight, + rightLeftMarginsSum: rowRightLeftMarginsSum, + topBottomMarginsSum: result.topBottomMarginsSum, + }) + ) { + // Previous calculation was valid, so set isRowCalcReady to true + setIsRowCalcReady(true) + } + } + + setRowForm(calcState) + } + /** * Handle bound type change. * @param {*} evt @@ -285,25 +506,31 @@ const Panel = ({ selectionAmount, validSelection }) => { if (canvasType === 'auto' && validSelection && validSelection.guid) { if (boundType === 'draw') { // Bound type is "draw" - calcState.canvasWidth = validSelection.globalDrawBounds.width - calcState.canvasHeight = validSelection.globalDrawBounds.height + colCalcState.canvasWidth = validSelection.globalDrawBounds.width + colCalcState.canvasHeight = validSelection.globalDrawBounds.height + rowCalcState.canvasWidth = validSelection.globalDrawBounds.height + rowCalcState.canvasHeight = validSelection.globalDrawBounds.width } else { // Assume bound type is "path" - calcState.canvasWidth = validSelection.globalBounds.width - calcState.canvasHeight = validSelection.globalBounds.height + colCalcState.canvasWidth = validSelection.globalBounds.width + colCalcState.canvasHeight = validSelection.globalBounds.height + rowCalcState.canvasWidth = validSelection.globalBounds.height + rowCalcState.canvasHeight = validSelection.globalBounds.width } - if (calcState.canvasWidth !== canvasWidth) { - setCanvasWidth(calcState.canvasWidth) + if (colCalcState.canvasWidth !== canvasWidth) { + setCanvasWidth(colCalcState.canvasWidth) } - if (calcState.canvasHeight !== canvasHeight) { - setCanvasHeight(calcState.canvasHeight) + if (colCalcState.canvasHeight !== canvasHeight) { + setCanvasHeight(colCalcState.canvasHeight) } } else { // Use manual canvas values - calcState.canvasWidth = canvasWidth - calcState.canvasHeight = canvasHeight + colCalcState.canvasWidth = canvasWidth + colCalcState.canvasHeight = canvasHeight + rowCalcState.canvasWidth = canvasHeight + rowCalcState.canvasHeight = canvasWidth } let content @@ -317,6 +544,16 @@ const Panel = ({ selectionAmount, validSelection }) => { checked={floorVals} onChange={(evt) => { setFloorVals(evt.target.checked) + colCalcState.floorVals = evt.target.checked + rowCalcState.floorVals = evt.target.checked + + if (createCols) { + attemptColWidthCalc(colCalcState) + } + + if (createRows) { + attemptRowHeightCalc(rowCalcState) + } }} uxp-quiet="true" /> @@ -339,7 +576,6 @@ const Panel = ({ selectionAmount, validSelection }) => { -
+
+ -