From cf0d834675a8d530d09e60c3094f41d1f47c8e62 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 15 Jul 2024 13:59:56 +0530 Subject: [PATCH 01/12] feat(masonry): Add and verify utils/path.ts for SVG Path Generation of Bricks - Implemented functions to generate SVG paths for different types of bricks - Added functionality for handling various brick features including notches, nests, and arguments. - Defined constants and private helper functions for path generation. - Included public function for creating SVG paths and bounding box calculations. --- modules/masonry/src/brick/utils/path.ts | 605 ++++++++++++++++++++++++ 1 file changed, 605 insertions(+) create mode 100644 modules/masonry/src/brick/utils/path.ts diff --git a/modules/masonry/src/brick/utils/path.ts b/modules/masonry/src/brick/utils/path.ts new file mode 100644 index 00000000..56bdc06e --- /dev/null +++ b/modules/masonry/src/brick/utils/path.ts @@ -0,0 +1,605 @@ +// == constants ==================================================================================== + +const cornerRadius = 4; +const strokeWidth = 0.5; + +const notchInsOffsetX = 4; +const notchInsLengthX = 10; +const notchInsLengthY = 2; + +const notchArgLengthX = 8; +const notchArgLengthY = 12; +const notchArgBaseLengthX = 4; +const notchArgBaseLengthY = 10; +const notchArgStemLengthY = 4; + +const nestLengthYMin = cornerRadius * 2 + notchArgLengthY; +const innerLengthXMin = cornerRadius * 2 + notchInsOffsetX * 2 + notchInsLengthX; + +// == private variables ============================================================================ + +let _hasNest = false; +let _hasNotchArg = false; +let _hasNotchInsTop = false; +let _hasNotchInsBot = false; + +let _scale = 1; +let _nestLengthY = nestLengthYMin; +let _innerLengthX = innerLengthXMin; +let _argsLengthY: number[] = []; + +// == private functions ============================================================================ + +/** + * Sets internal variables that control the shape of the path + * @param options options to control the shape of the path + * + * @private + */ +function _setOptions(options: { + hasNest: boolean; + hasNotchArg: boolean; + hasNotchInsTop: boolean; + hasNotchInsBot: boolean; + scale: number; + nestLengthY?: number; + innerLengthX: number; + argHeights: number[]; +}): void { + _hasNest = options.hasNest; + + _hasNotchArg = options.hasNotchArg; + _hasNotchInsTop = options.hasNotchInsTop; + _hasNotchInsBot = options.hasNotchInsBot; + + _scale = options.scale; + if (options.nestLengthY) _nestLengthY = Math.max(nestLengthYMin, options.nestLengthY); + _innerLengthX = Math.max(innerLengthXMin, options.innerLengthX); + _argsLengthY = options.argHeights; +} + +/** + * Generates top section of the path (left arc to right arc) + * + * @remarks + * left to right + * + * @private + */ +function _getPathTop(): string[] { + const lineLengthX = _innerLengthX - cornerRadius * 2 - (notchInsOffsetX + notchInsLengthX); + + return [ + `a ${cornerRadius} ${cornerRadius} 90 0 1 ${cornerRadius} -${cornerRadius}`, + `h ${notchInsOffsetX}`, + ...(_hasNotchInsTop + ? [ + // + `v ${notchInsLengthY}`, + `h ${notchInsLengthX}`, + `v -${notchInsLengthY}`, + ] + : [ + // + `h ${notchInsLengthX}`, + ]), + `h ${lineLengthX}`, + `a ${cornerRadius} ${cornerRadius} 90 0 1 ${cornerRadius} ${cornerRadius}`, + ]; +} + +/** + * Generates bottom section of the path (right arc to left arc; includes nest) + * + * @remarks + * right to left + * + * @private + */ +function _getPathBottom(): string[] { + if (!_hasNest) { + const lineLengthX = _innerLengthX - cornerRadius * 2 - (notchInsOffsetX + notchInsLengthX); + + return [ + `a ${cornerRadius} ${cornerRadius} 90 0 1 -${cornerRadius} ${cornerRadius}`, + `h -${lineLengthX}`, + ...(_hasNotchInsBot + ? [ + 'h -1', + `v ${notchInsLengthY}`, + `h -${notchInsLengthX - 2}`, + `v -${notchInsLengthY}`, + 'h -1', + ] + : [ + // + `h -${notchInsLengthX}`, + ]), + `h -${notchInsOffsetX}`, + `a ${cornerRadius} ${cornerRadius} 90 0 1 -${cornerRadius} -${cornerRadius}`, + ]; + } + + const lineLengthX = + _innerLengthX - + cornerRadius * 2 - + (notchInsOffsetX + notchInsLengthX) - + (cornerRadius + notchInsOffsetX + 1); + + return [ + `a ${cornerRadius} ${cornerRadius} 90 0 1 -${cornerRadius} ${cornerRadius}`, + `h -${lineLengthX}`, + 'h -1', + `v ${notchInsLengthY}`, + `h -${notchInsLengthX - 2}`, + `v -${notchInsLengthY}`, + 'h -1', + `h -${notchInsOffsetX}`, + `a ${cornerRadius + 1} ${cornerRadius + 1} 90 0 0 -${cornerRadius + 1} ${cornerRadius + 1}`, + `v ${_nestLengthY - cornerRadius * 2}`, + `a ${cornerRadius + 1} ${cornerRadius + 1} 90 0 0 ${cornerRadius + 1} ${cornerRadius + 1}`, + `h ${notchInsOffsetX}`, + `v ${notchInsLengthY}`, + `h ${notchInsLengthX}`, + `v -${notchInsLengthY}`, + `h ${notchInsOffsetX}`, + `a ${cornerRadius} ${cornerRadius} 90 0 1 ${cornerRadius} ${cornerRadius}`, + `v ${notchArgLengthY}`, + `a ${cornerRadius} ${cornerRadius} 90 0 1 -${cornerRadius} ${cornerRadius}`, + 'h -1', + `h -${cornerRadius + notchInsOffsetX * 2}`, + ...(_hasNotchInsBot + ? [ + 'h -1', + `v ${notchInsLengthY}`, + `h -${notchInsLengthX - 2}`, + `v -${notchInsLengthY}`, + 'h -1', + ] + : [ + // + `h -${notchInsLengthX}`, + ]), + `h -${notchInsOffsetX}`, + `a ${cornerRadius} ${cornerRadius} 90 0 1 -${cornerRadius} -${cornerRadius}`, + `v -${cornerRadius * 2 + notchArgLengthY}`, + 'v -1', + `v -${_nestLengthY - cornerRadius * 2}`, + 'v -1', + `v -${cornerRadius * 2}`, + ]; +} + +/** + * Generates the argument connector (concave) positioned on the right + * + * @remarks + * top to bottom + * + * @private + */ +function _getNotchArgInner(): string[] { + const endLineLengthY = (notchArgLengthY - notchArgStemLengthY) / 2; + const stemLengthX = notchArgLengthX - notchArgBaseLengthX; + const baseRiseLengthY = (notchArgBaseLengthY - notchArgStemLengthY) / 2; + + return [ + `v ${endLineLengthY}`, + `h -${stemLengthX}`, + `v -${baseRiseLengthY}`, + `h -${notchArgBaseLengthX}`, + `v ${notchArgBaseLengthY}`, + `h ${notchArgBaseLengthX}`, + `v -${baseRiseLengthY}`, + `h ${stemLengthX}`, + `v ${endLineLengthY}`, + ]; +} + +/** + * Generates the argument connector (convex) positioned on the left + * + * @remarks + * bottom to top + * + * @private + */ +function _getNotchArgOuter(): string[] { + const endLineLengthY = (notchArgLengthY - notchArgStemLengthY) / 2 + 1; + const stemLengthX = notchArgLengthX - notchArgBaseLengthX + 2; + const baseRiseLengthY = (notchArgBaseLengthY - notchArgStemLengthY) / 2; + + return [ + `v -${endLineLengthY}`, + `h -${stemLengthX}`, + `v ${baseRiseLengthY}`, + `h -${notchArgBaseLengthX - 2}`, + `v -${notchArgBaseLengthY - 2}`, + `h ${notchArgBaseLengthX - 2}`, + `v ${baseRiseLengthY}`, + `h ${stemLengthX}`, + `v -${endLineLengthY}`, + ]; +} + +/** + * Generates portion for one argument connector (concave) positioned on the right + * @param options determines shape + * + * @remarks + * top to bottom + * + * @private + */ +function _generateArgSection(options: { + /** whether protrude vertical top line */ + hasOffsetTop: boolean; + /** whether protrude vertical bottom line */ + hasOffsetBot: boolean; + /** total vertical length of the portion */ + sectionLengthY: number; +}): string[] { + const { hasOffsetTop, hasOffsetBot, sectionLengthY } = options; + + const sectionOffsetTopY = hasOffsetTop ? cornerRadius : 0; + const sectionOffsetBotY = sectionLengthY - cornerRadius - notchArgLengthY - cornerRadius; + + return [ + // + `v ${sectionOffsetTopY}`, + ..._getNotchArgInner(), + `v ${hasOffsetBot ? cornerRadius : 0}`, + `v ${sectionOffsetBotY}`, + ]; +} + +/** + * Generates right section of the path (includes argument connectors) + * + * @remarks + * top to bottom + * + * @private + */ +function _getPathRight() { + const sectionLengthYMin = cornerRadius * 2 + notchArgLengthY; + + return _argsLengthY.length === 0 + ? [ + // + `v ${notchArgLengthY}`, + ] + : _argsLengthY + .map((sectionLengthY, i) => + _generateArgSection({ + hasOffsetTop: i !== 0, + hasOffsetBot: i < _argsLengthY.length - 1, + sectionLengthY: Math.max(sectionLengthYMin, sectionLengthY), + }), + ) + .reduce((a, b) => [...a, ...b], []); +} + +/** + * Generates left section of the path (includes argument notch) + * + * @remarks + * bottom to top + * + * @private + */ +function _getPathLeft() { + const lineLengthY = Math.max( + 0, + _argsLengthY.reduce((a, b) => a + b, 0) - cornerRadius * 2 - notchArgLengthY, + ); + + return [ + // + `v -${lineLengthY}`, + ...(_hasNotchArg + ? _getNotchArgOuter() + : [ + // + `v -${notchArgLengthY}`, + ]), + ]; +} + +// -- private helper functions --------------------------------------------------------------------- + +/** + * Generates brick SVG path + * + * @private + */ +function _getPath(): string { + const offsetX = 0.5 + (_hasNotchArg ? notchArgLengthX : 0); + const offsetY = 0.5 + cornerRadius; + + return [ + `m ${offsetX} ${offsetY}`, + ...[_getPathTop(), _getPathRight(), _getPathBottom(), _getPathLeft()].map((sections) => + sections.join(' '), + ), + 'z', + ].join(' '); +} + +/** + * Generates bounding box of the brick (excludes notches) + * + * @private + */ +function _getBBoxBrick(): { + extent: { width: number; height: number }; + coords: { x: number; y: number }; +} { + const argSectionLengthYMin = cornerRadius * 2 + notchArgLengthY; + const argsLength = _argsLengthY + .map((sectionLengthY) => Math.max(argSectionLengthYMin, sectionLengthY)) + .reduce((a, b) => a + b, 0); + + let height = + strokeWidth + + (argsLength !== 0 ? argsLength : 2 * cornerRadius + notchArgLengthY) + + strokeWidth; + + if (_hasNest) { + height += _nestLengthY + strokeWidth * 4 + 2 * cornerRadius + notchArgLengthY; + } + + return { + extent: { + width: strokeWidth + _innerLengthX + strokeWidth, + height: height, + }, + coords: { + x: _hasNotchArg ? notchArgLengthX : 0, + y: 0, + }, + }; +} + +/** + * Generates bounding box of the argument notch positioned on the left + * + * @private + */ +function _getBBoxNotchArg(): { + extent: { width: number; height: number }; + coords: { x: number; y: number }; +} { + return { + extent: { + width: _hasNotchArg ? notchArgLengthX : 0, + height: _hasNotchArg ? strokeWidth + 8 + strokeWidth : 0, + }, + coords: { + x: 0, + y: _hasNotchArg ? 6 : 0, + }, + }; +} + +/** + * Generates bounding box of the top instruction notch + * + * @private + */ +function _getBBoxNotchInsTop(): { + extent: { width: number; height: number }; + coords: { x: number; y: number }; +} { + return { + extent: { + width: notchInsLengthX - 2 * strokeWidth, + height: notchInsLengthY, + }, + coords: { + x: + strokeWidth + + (_hasNotchArg ? notchArgLengthX : 0) + + cornerRadius + + notchInsOffsetX + + strokeWidth, + y: 0, + }, + }; +} + +/** + * Generates bounding box of the bottom instruction notch + * + * @private + */ +function _getBBoxNotchInsBot(): { + extent: { width: number; height: number }; + coords: { x: number; y: number }; +} { + return { + extent: { + width: notchInsLengthX - 2 * strokeWidth, + height: strokeWidth + notchInsLengthY - strokeWidth, + }, + coords: { + x: + strokeWidth + + (_hasNotchArg ? notchArgLengthX : 0) + + cornerRadius + + notchInsOffsetX + + strokeWidth, + y: _getBBoxBrick().extent.height, + }, + }; +} + +/** + * Generates bounding box of the top instruction notch inside a nesting + * + * @private + */ +function _getBBoxNotchInsNestTop(): { + extent: { width: number; height: number }; + coords: { x: number; y: number }; +} { + const argSectionLengthYMin = cornerRadius * 2 + notchArgLengthY; + const argsLength = _argsLengthY + .map((sectionLengthY) => Math.max(argSectionLengthYMin, sectionLengthY)) + .reduce((a, b) => a + b, 0); + + const offsetY = + strokeWidth + + (argsLength !== 0 ? argsLength : 2 * cornerRadius + notchArgLengthY) + + strokeWidth; + + return { + extent: { + width: notchInsLengthX - 2 * strokeWidth, + height: notchInsLengthY, + }, + coords: { + x: + strokeWidth + + (_hasNotchArg ? notchArgLengthX : 0) + + cornerRadius + + notchInsOffsetX + + notchInsLengthX - + strokeWidth, + y: offsetY, + }, + }; +} + +/** + * Generates list of bounding boxes for each argument connector positioned on the right + * + * @private + */ +function _getBBoxArgs(): { + extent: { width: number; height: number }; + coords: { x: number; y: number }[]; +} { + const offsetX = + strokeWidth + + (_hasNotchArg ? notchArgLengthX : 0) + + _innerLengthX - + notchArgLengthX + + strokeWidth; + const firstOffsetY = strokeWidth + cornerRadius + 1 + strokeWidth; + const argSectionLengthYMin = cornerRadius * 2 + notchArgLengthY; + const argsLength = _argsLengthY.map((sectionLengthY) => + Math.max(argSectionLengthYMin, sectionLengthY), + ); + + return { + extent: { + width: notchArgLengthX, + height: 10 - 2 * strokeWidth, + }, + coords: _argsLengthY.map((_, index) => { + return { + x: offsetX, + y: + firstOffsetY + + (index === 0 ? 0 : argsLength.slice(0, index).reduce((a, b) => a + b, 0)), + }; + }), + }; +} + +// == public functions ============================================================================= + +/** + * Generates SVG path along with information about the bounding boxes of notches and arguments. + * + * @remarks + * Use https://yqnn.github.io/svg-path-editor/ to visualize the path + * + * @param options determines how the path looks + * @param print whether to print results in the console (only to be used during development) + */ +export function generatePath( + options: + | { + hasNest: true; + hasNotchArg: boolean; + hasNotchInsTop: boolean; + hasNotchInsBot: boolean; + scale: number; + nestLengthY: number; + innerLengthX: number; + argHeights: number[]; + } + | { + hasNest: false; + hasNotchArg: boolean; + hasNotchInsTop: boolean; + hasNotchInsBot: boolean; + scale: number; + innerLengthX: number; + argHeights: number[]; + }, + print?: boolean, +): { + /** path definition commands string */ + path: string; + /** bounding box of the brick (actual area of the brick excluding notches) */ + bBoxBrick: { + /** width and height of the brick */ + extent: { width: number; height: number }; + /** x and y co-ordinates of the brick relative to the origin of the SVG */ + coords: { x: number; y: number }; + }; + /** bounding box of the argument notch (on the left) */ + bBoxNotchArg: { + /** width and height of the argument notch */ + extent: { width: number; height: number }; + /** x and y co-ordinates of the argument notch relative to the origin of the SVG */ + coords: { x: number; y: number }; + } | null; + /** bounding box of the top instruction notch */ + bBoxNotchInsTop: { + /** width and height of the top instruction notch */ + extent: { width: number; height: number }; + /** x and y co-ordinates of the top instruction notch relative to the origin of the SVG */ + coords: { x: number; y: number }; + } | null; + /** bounding box of the bottom instruction notch */ + bBoxNotchInsBot: { + /** width and height of the bottom instruction notch */ + extent: { width: number; height: number }; + /** x and y co-ordinates of the bottom instruction notch relative to the origin of the SVG */ + coords: { x: number; y: number }; + } | null; + /** bounding box of the top instruction notch inside a nest (only for bricks with nesting) */ + bBoxNotchInsNestTop: { + /** width and height of the top instruction notch inside a nest */ + extent: { width: number; height: number }; + /** x and y co-ordinates of the top instruction notch inside a nest relative to the origin of the SVG */ + coords: { x: number; y: number }; + } | null; + /** list of bounding boxes for the argument connections */ + bBoxArgs: { + /** width and height of each argument connection */ + extent: { width: number; height: number }; + /** list of x and y co-ordinates of each argument connection relative to the origin of the SVG */ + coords: { x: number; y: number }[]; + }; +} { + _setOptions(options); + + const results = { + path: _getPath(), + bBoxBrick: _getBBoxBrick(), + bBoxNotchArg: _getBBoxNotchArg(), + bBoxNotchInsTop: _getBBoxNotchInsTop(), + bBoxNotchInsBot: _getBBoxNotchInsBot(), + bBoxNotchInsNestTop: _getBBoxNotchInsNestTop(), + bBoxArgs: _getBBoxArgs(), + }; + + if (print) console.log(results); + + return results; +} From bb83f893fd8905e0f01de72cfd9b7c42996d8722 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 15 Jul 2024 14:01:08 +0530 Subject: [PATCH 02/12] feat(masonry): Add tests in path.spec.ts for Comprehensive Testing of path.ts --- .../masonry/src/brick/utils/spec/path.spec.ts | 529 ++++++++++++++++++ 1 file changed, 529 insertions(+) create mode 100644 modules/masonry/src/brick/utils/spec/path.spec.ts diff --git a/modules/masonry/src/brick/utils/spec/path.spec.ts b/modules/masonry/src/brick/utils/spec/path.spec.ts new file mode 100644 index 00000000..92dd5d07 --- /dev/null +++ b/modules/masonry/src/brick/utils/spec/path.spec.ts @@ -0,0 +1,529 @@ +import { generatePath } from '../path'; + +describe('Masonry: Brick > Design 0 > Utility: Path', () => { + describe('Path Generation', () => { + it('generates path with arguments of different extents', () => { + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -78 h -10 h -4 a 4 4 90 0 1 -4 -4 v -0 v -12 z', + ); + } + + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [20, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -78 h -10 h -4 a 4 4 90 0 1 -4 -4 v -20 v -12 z', + ); + } + + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [20, 20, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -78 h -10 h -4 a 4 4 90 0 1 -4 -4 v -40 v -12 z', + ); + } + + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [40, 20, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 20 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -78 h -10 h -4 a 4 4 90 0 1 -4 -4 v -60 v -12 z', + ); + } + + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [20, 40, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 20 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -78 h -10 h -4 a 4 4 90 0 1 -4 -4 v -60 v -12 z', + ); + } + + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [20, 20, 40], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 20 a 4 4 90 0 1 -4 4 h -78 h -10 h -4 a 4 4 90 0 1 -4 -4 v -60 v -12 z', + ); + } + }); + + it('generates path with argument notch and no arguments', () => { + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: true, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [], + }); + expect(path).toBe( + 'm 8.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -78 h -10 h -4 a 4 4 90 0 1 -4 -4 v -0 v -5 h -6 v 3 h -2 v -8 h 2 v 3 h 6 v -5 z', + ); + } + }); + + it('generates path with argument notch and arguments', () => { + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: true, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [20, 20], + }); + expect(path).toBe( + 'm 8.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -78 h -10 h -4 a 4 4 90 0 1 -4 -4 v -20 v -5 h -6 v 3 h -2 v -8 h 2 v 3 h 6 v -5 z', + ); + } + }); + + it('generates path with both instruction notches and no arguments', () => { + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + argHeights: [], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 v 2 h 10 v -2 h 78 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -78 h -1 v 2 h -8 v -2 h -1 h -4 a 4 4 90 0 1 -4 -4 v -0 v -12 z', + ); + } + }); + + it('generates path with both instruction notches and arguments', () => { + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + argHeights: [20, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 v 2 h 10 v -2 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -78 h -1 v 2 h -8 v -2 h -1 h -4 a 4 4 90 0 1 -4 -4 v -20 v -12 z', + ); + } + }); + + it('generates path with top instruction notch and no arguments', () => { + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 v 2 h 10 v -2 h 78 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -78 h -10 h -4 a 4 4 90 0 1 -4 -4 v -0 v -12 z', + ); + } + }); + + it('generates path with top instruction notch and arguments', () => { + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [20, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 v 2 h 10 v -2 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -78 h -10 h -4 a 4 4 90 0 1 -4 -4 v -20 v -12 z', + ); + } + }); + + it('generates path with bottom instruction notch and no arguments', () => { + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + argHeights: [], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -78 h -1 v 2 h -8 v -2 h -1 h -4 a 4 4 90 0 1 -4 -4 v -0 v -12 z', + ); + } + }); + + it('generates path with bottom instruction notch and arguments', () => { + { + const { path } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + argHeights: [20, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -78 h -1 v 2 h -8 v -2 h -1 h -4 a 4 4 90 0 1 -4 -4 v -20 v -12 z', + ); + } + }); + + it('generates path with nesting, both instruction notches, and no arguments', () => { + { + const { path } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + nestLengthY: 40, + argHeights: [], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 v 2 h 10 v -2 h 78 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -69 h -1 v 2 h -8 v -2 h -1 h -4 a 5 5 90 0 0 -5 5 v 32 a 5 5 90 0 0 5 5 h 4 v 2 h 10 v -2 h 4 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -1 h -12 h -1 v 2 h -8 v -2 h -1 h -4 a 4 4 90 0 1 -4 -4 v -20 v -1 v -32 v -1 v -8 v -0 v -12 z', + ); + } + }); + + it('generates path with nesting, both instruction notches, and arguments', () => { + { + const { path } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + nestLengthY: 40, + argHeights: [20, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 v 2 h 10 v -2 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -69 h -1 v 2 h -8 v -2 h -1 h -4 a 5 5 90 0 0 -5 5 v 32 a 5 5 90 0 0 5 5 h 4 v 2 h 10 v -2 h 4 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -1 h -12 h -1 v 2 h -8 v -2 h -1 h -4 a 4 4 90 0 1 -4 -4 v -20 v -1 v -32 v -1 v -8 v -20 v -12 z', + ); + } + }); + + it('generates path with nesting, top instruction notch, and no arguments', () => { + { + const { path } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + nestLengthY: 40, + argHeights: [], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 v 2 h 10 v -2 h 78 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -69 h -1 v 2 h -8 v -2 h -1 h -4 a 5 5 90 0 0 -5 5 v 32 a 5 5 90 0 0 5 5 h 4 v 2 h 10 v -2 h 4 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -1 h -12 h -10 h -4 a 4 4 90 0 1 -4 -4 v -20 v -1 v -32 v -1 v -8 v -0 v -12 z', + ); + } + }); + + it('generates path with nesting, top instruction notch, and arguments', () => { + { + const { path } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + nestLengthY: 40, + argHeights: [20, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 v 2 h 10 v -2 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -69 h -1 v 2 h -8 v -2 h -1 h -4 a 5 5 90 0 0 -5 5 v 32 a 5 5 90 0 0 5 5 h 4 v 2 h 10 v -2 h 4 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -1 h -12 h -10 h -4 a 4 4 90 0 1 -4 -4 v -20 v -1 v -32 v -1 v -8 v -20 v -12 z', + ); + } + }); + + it('generates path with nesting, bottom instruction notch, and no arguments', () => { + { + const { path } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + nestLengthY: 40, + argHeights: [], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -69 h -1 v 2 h -8 v -2 h -1 h -4 a 5 5 90 0 0 -5 5 v 32 a 5 5 90 0 0 5 5 h 4 v 2 h 10 v -2 h 4 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -1 h -12 h -1 v 2 h -8 v -2 h -1 h -4 a 4 4 90 0 1 -4 -4 v -20 v -1 v -32 v -1 v -8 v -0 v -12 z', + ); + } + }); + + it('generates path with nesting, bottom instruction notch, and arguments', () => { + { + const { path } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + nestLengthY: 40, + argHeights: [20, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -69 h -1 v 2 h -8 v -2 h -1 h -4 a 5 5 90 0 0 -5 5 v 32 a 5 5 90 0 0 5 5 h 4 v 2 h 10 v -2 h 4 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -1 h -12 h -1 v 2 h -8 v -2 h -1 h -4 a 4 4 90 0 1 -4 -4 v -20 v -1 v -32 v -1 v -8 v -20 v -12 z', + ); + } + }); + + it('generates path with nesting, no instruction notch, and no arguments', () => { + { + const { path } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + nestLengthY: 40, + argHeights: [], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -69 h -1 v 2 h -8 v -2 h -1 h -4 a 5 5 90 0 0 -5 5 v 32 a 5 5 90 0 0 5 5 h 4 v 2 h 10 v -2 h 4 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -1 h -12 h -10 h -4 a 4 4 90 0 1 -4 -4 v -20 v -1 v -32 v -1 v -8 v -0 v -12 z', + ); + } + }); + + it('generates path with nesting, no instruction notch, and arguments', () => { + { + const { path } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + nestLengthY: 40, + argHeights: [20, 20], + }); + expect(path).toBe( + 'm 0.5 4.5 a 4 4 90 0 1 4 -4 h 4 h 10 h 78 a 4 4 90 0 1 4 4 v 0 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 4 v 0 v 4 v 4 h -4 v -3 h -4 v 10 h 4 v -3 h 4 v 4 v 0 v 0 a 4 4 90 0 1 -4 4 h -69 h -1 v 2 h -8 v -2 h -1 h -4 a 5 5 90 0 0 -5 5 v 32 a 5 5 90 0 0 5 5 h 4 v 2 h 10 v -2 h 4 a 4 4 90 0 1 4 4 v 12 a 4 4 90 0 1 -4 4 h -1 h -12 h -10 h -4 a 4 4 90 0 1 -4 -4 v -20 v -1 v -32 v -1 v -8 v -20 v -12 z', + ); + } + }); + }); + + describe('Bounding Box Calculation', () => { + it('evaluates brick bounding box for brick with no argument notch', () => { + const { bBoxBrick } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + argHeights: [], + }); + expect(bBoxBrick.extent.height).toBe(21); + expect(bBoxBrick.extent.width).toBe(101); + expect(bBoxBrick.coords.x).toBe(0); + expect(bBoxBrick.coords.y).toBe(0); + }); + + it('evaluates brick bounding box for brick with argument notch', () => { + const { bBoxBrick } = generatePath({ + hasNest: false, + hasNotchArg: true, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [], + }); + expect(bBoxBrick.extent.height).toBe(21); + expect(bBoxBrick.extent.width).toBe(101); + expect(bBoxBrick.coords.x).toBe(8); + expect(bBoxBrick.coords.y).toBe(0); + }); + + it('evaluates argument notch bounding box for brick', () => { + const { bBoxNotchArg } = generatePath({ + hasNest: false, + hasNotchArg: true, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: 1, + innerLengthX: 100, + argHeights: [], + }); + expect(bBoxNotchArg?.extent.height).toBe(9); + expect(bBoxNotchArg?.extent.width).toBe(8); + expect(bBoxNotchArg?.coords.x).toBe(0); + expect(bBoxNotchArg?.coords.y).toBe(6); + }); + + it('evaluates top instruction notch bounding box', () => { + const { bBoxNotchInsTop } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + argHeights: [], + }); + expect(bBoxNotchInsTop?.extent.height).toBe(2); + expect(bBoxNotchInsTop?.extent.width).toBe(9); + expect(bBoxNotchInsTop?.coords.x).toBe(9); + expect(bBoxNotchInsTop?.coords.y).toBe(0); + }); + + it('evaluates bottom instruction notch bounding box for non-nesting brick', () => { + const { bBoxNotchInsBot } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + argHeights: [], + }); + expect(bBoxNotchInsBot?.extent.height).toBe(2); + expect(bBoxNotchInsBot?.extent.width).toBe(9); + expect(bBoxNotchInsBot?.coords.x).toBe(9); + expect(bBoxNotchInsBot?.coords.y).toBe(21); + }); + + it('evaluates bottom instruction notch bounding box for nesting brick', () => { + const { bBoxNotchInsBot } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + nestLengthY: 30, + innerLengthX: 100, + argHeights: [], + }); + expect(bBoxNotchInsBot?.extent.height).toBe(2); + expect(bBoxNotchInsBot?.extent.width).toBe(9); + expect(bBoxNotchInsBot?.coords.x).toBe(9); + expect(bBoxNotchInsBot?.coords.y).toBe(73); + }); + + it('evaluates inner top instruction notch bounding box for nesting brick', () => { + const { bBoxNotchInsNestTop } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + nestLengthY: 30, + innerLengthX: 100, + argHeights: [], + }); + expect(bBoxNotchInsNestTop?.extent.height).toBe(2); + expect(bBoxNotchInsNestTop?.extent.width).toBe(9); + expect(bBoxNotchInsNestTop?.coords.x).toBe(18); + expect(bBoxNotchInsNestTop?.coords.y).toBe(21); + }); + + it('evaluates inner top instruction notch bounding box for nesting brick', () => { + const { bBoxNotchInsNestTop } = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + nestLengthY: 30, + innerLengthX: 100, + argHeights: [], + }); + expect(bBoxNotchInsNestTop?.extent.height).toBe(2); + expect(bBoxNotchInsNestTop?.extent.width).toBe(9); + expect(bBoxNotchInsNestTop?.coords.x).toBe(18); + expect(bBoxNotchInsNestTop?.coords.y).toBe(21); + }); + + it('evaluates bounding boxes for arguments', () => { + const { bBoxArgs } = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: 1, + innerLengthX: 100, + argHeights: [17, 30, 40], + }); + expect(bBoxArgs.extent.height).toBe(9); + expect(bBoxArgs.extent.width).toBe(8); + expect(bBoxArgs.coords).toStrictEqual([ + { x: 93, y: 6 }, + { x: 93, y: 26 }, + { x: 93, y: 56 }, + ]); + }); + }); +}); From 9f128e034c20ac0edc38a2dc6e072d8f20296037 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Wed, 24 Jul 2024 10:12:32 +0530 Subject: [PATCH 03/12] docs(masonry): fix image path in PRD --- modules/masonry/docs/PRD/PRD.md | 36 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/modules/masonry/docs/PRD/PRD.md b/modules/masonry/docs/PRD/PRD.md index 04443c79..6c555ccd 100644 --- a/modules/masonry/docs/PRD/PRD.md +++ b/modules/masonry/docs/PRD/PRD.md @@ -9,22 +9,22 @@ - Hardcoded Data Brick: Fixed values that cannot be changed by the user. Examples include predefined note values, counts, etc. - ![alt text](./images/image.png) + ![alt text](../images/image.png) - Editable Data Brick: Values that can be modified by the user. When clicked, these bricks open a text editor or a dropdown menu for user input, allowing customization of note names, pitches, etc. - ![editable bricks](./images/image-1.png) + ![editable bricks](../images/image-1.png) #### 2. Expression Bricks: Takes values as input, returns a value as output - ![alt text](./images/image-2.png) + ![alt text](../images/image-2.png) #### 3. Statement Bricks: These define actions to be taken - ![example](./images/image-3.png) + ![example](../images/image-3.png) #### 4. Block Bricks: Contain nesting, also execute something like the statement bricks. Takes 0 or more arguments - ![alt text](./images/image-14.png) + ![alt text](../images/image-14.png) ### b. Brick Appearance @@ -50,19 +50,19 @@ - **Inline Text Editing**: Users can click on text fields within bricks to edit labels and values directly. - Some bricks only open an inline text editor when clicked. - ![inline text editing](./images/image-4.png) + ![inline text editing](../images/image-4.png) - Other bricks open both an inline text editor and a context menu for additional options. - ![inline text editor with context menu](./images/image-15.png) + ![inline text editor with context menu](../images/image-15.png) - **Context Menus**: For more complex properties, a separate interface allows detailed configuration. - ![dedicated editors](./images/image-5.png) + ![dedicated editors](../images/image-5.png) - **Connection Types**: 1. **Argument Connections**: Bricks can be connected to input arguments of other bricks. This allows for passing data or parameters into the brick’s function. 2. **Brick-to-Brick or Stack Connections**: Bricks can be connected directly to other bricks or to a stack of bricks. This enables building complex sequences and structures by chaining bricks together. - ![alt text](./images/image-8.png) + ![alt text](../images/image-8.png) ## 2. Stack of Bricks @@ -70,12 +70,10 @@ - **Visual Feedback**: Indicators show whether brick combinations are valid. - ![alt text](./images/image-6.png) - - **Error Indicators**: Explanations for incompatible connections help users troubleshoot. - Add a reddish boundary for users to easily tell whether the bricks are mergeable or not. - ![alt text](./images/image-7.png) + ![alt text](../images/image-7.png) - **Disable Validation**: Temporarily turn off validation for complex or experimental setups. @@ -90,7 +88,7 @@ - **Collapsible Groups**: Groups can be collapsed or expanded to manage complexity. - ![alt text](./images/image-9.png) + ![alt text](../images/image-9.png) ## 3. Palette @@ -100,13 +98,13 @@ - Visual separators or dividers between categories - Customizable order and arrangement of categories - ![alt text](./images/image-10.png) + ![alt text](../images/image-10.png) ### b. **Brick Previews** - Tooltips or pop-ups displaying Brick names and brief descriptions - ![alt text](./images/image-16.png) + ![alt text](../images/image-16.png) - Color-coding or visual cues for distinguishing different Brick types @@ -117,11 +115,11 @@ - Live search results or suggestions as the user types - Searchbar in Musicblocks as of now: - ![alt text](./images//image-11.png) + ![alt text](../images//image-11.png) - Searchbar design to be implemented: - ![alt text](./images/image-17.png) + ![alt text](../images/image-17.png) The idea here is to have a fixed searchbar on the left side of the workspace through which users can search for bricks, group them etc. Note - It is just a one big list and categories on the left are positions on the list. @@ -130,13 +128,13 @@ - Ability to drag and drop Bricks from the palette onto the workspace. - Visual indicators (e.g., ghost preview, outline) for valid drop locations. - ![drag and drop](./images/image-12.png) + ![drag and drop](../images/image-12.png) - While dragging a brick from the palette, the brick should temporarily disappear from the palette until it is placed in the workspace. ## 4. Workspace -![alt text](./images/image-13.png) +![alt text](../images/image-13.png) - **Cloning/Duplication**: Users can easily create copies of bricks for repeated use. - **Scaling and Rotation**: Bricks can be resized and rotated to fit the workspace better. From 4585a7ad9e942f1639f4759a40c92ef75071f96f Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Wed, 24 Jul 2024 15:51:08 +0530 Subject: [PATCH 04/12] docs(masonry): initialize storybook --- .gitignore | 2 ++ modules/masonry/.storybook/main.ts | 37 +++++++++++++++++++++++++++ modules/masonry/.storybook/preview.ts | 13 ++++++++++ modules/masonry/package.json | 21 +++++++++++++-- 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 modules/masonry/.storybook/main.ts create mode 100644 modules/masonry/.storybook/preview.ts diff --git a/.gitignore b/.gitignore index 3da87c9a..191b596f 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* + +*storybook.log \ No newline at end of file diff --git a/modules/masonry/.storybook/main.ts b/modules/masonry/.storybook/main.ts new file mode 100644 index 00000000..cd4e8a1d --- /dev/null +++ b/modules/masonry/.storybook/main.ts @@ -0,0 +1,37 @@ +import type { UserConfigExport } from 'vite'; + +import path from 'path'; +import { mergeConfig } from 'vite'; + +// ------------------------------------------------------------------------------------------------- + +function resolve(rootPath: string) { + return path.resolve(__dirname, '..', rootPath); +} + +export default { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(tsx|ts|jsx|js)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], + framework: { + name: '@storybook/react-vite', + options: {}, + }, + docs: { + autodocs: 'tag', + }, + async viteFinal(config: UserConfigExport) { + return mergeConfig(config, { + resolve: { + alias: { + '@': resolve('src'), + '@res': resolve('../../res'), + }, + extensions: ['.tsx', '.ts', '.js', '.scss', '.sass', '.json'], + }, + }); + }, +}; diff --git a/modules/masonry/.storybook/preview.ts b/modules/masonry/.storybook/preview.ts new file mode 100644 index 00000000..ae3ab20a --- /dev/null +++ b/modules/masonry/.storybook/preview.ts @@ -0,0 +1,13 @@ +import '@res/scss/base.scss'; + +export const parameters = { + actions: { + argTypesRegex: '^on[A-Z].*', + }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, +}; diff --git a/modules/masonry/package.json b/modules/masonry/package.json index 59ef5a8b..22c99c5a 100644 --- a/modules/masonry/package.json +++ b/modules/masonry/package.json @@ -7,11 +7,28 @@ "scripts": { "test": "vitest", "coverage": "vitest run --coverage", - "lint": "eslint src" + "lint": "eslint src", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", + "@storybook/addon-essentials": "^8.2.5", + "@storybook/addon-interactions": "^8.2.5", + "@storybook/addon-links": "^8.2.5", + "@storybook/addon-onboarding": "^8.2.5", + "@storybook/blocks": "^8.2.5", + "@storybook/react": "^8.2.5", + "@storybook/react-vite": "^8.2.5", + "@storybook/test": "^8.2.5", + "@storybook/testing-library": "^0.0.14-next.2", "@types/jest": "^29.5.12", "jest": "^29.7.0", - "ts-jest": "^29.1.5" + "prop-types": "^15.8.1", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "storybook": "^8.2.5", + "ts-jest": "^29.1.5", + "typescript": "^5.5.4" } } From 4c73a2e22664950772bc8e9d38ee34327b444351 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Wed, 24 Jul 2024 17:37:38 +0530 Subject: [PATCH 05/12] Add brick components making sure that model and view are seperate --- .../src/brick/components/BrickBlock.tsx | 122 ++++++++++++++++++ .../src/brick/components/BrickData.tsx | 72 +++++++++++ .../src/brick/components/BrickExpression.tsx | 100 ++++++++++++++ .../src/brick/components/BrickStatement.tsx | 112 ++++++++++++++++ .../src/brick/components/BrickWrapper.tsx | 11 ++ 5 files changed, 417 insertions(+) create mode 100644 modules/masonry/src/brick/components/BrickBlock.tsx create mode 100644 modules/masonry/src/brick/components/BrickData.tsx create mode 100644 modules/masonry/src/brick/components/BrickExpression.tsx create mode 100644 modules/masonry/src/brick/components/BrickStatement.tsx create mode 100644 modules/masonry/src/brick/components/BrickWrapper.tsx diff --git a/modules/masonry/src/brick/components/BrickBlock.tsx b/modules/masonry/src/brick/components/BrickBlock.tsx new file mode 100644 index 00000000..516bb38e --- /dev/null +++ b/modules/masonry/src/brick/components/BrickBlock.tsx @@ -0,0 +1,122 @@ +import BrickWrapper from './BrickWrapper'; +import type { JSX } from 'react'; +import type { IBrickBlock, TBrickArgDataType, TBrickColor } from '@/@types/brick'; + +// ------------------------------------------------------------------------------------------------- + +export default function (props: { + Component: (props: { instance: IBrickBlock; visualIndicators?: JSX.Element }) => JSX.Element; + prototype: new (params: { + name: string; + label: string; + glyph: string; + args: Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + } + >; + colorBg: TBrickColor; + colorFg: TBrickColor; + outline: TBrickColor; + scale: number; + connectAbove: boolean; + connectBelow: boolean; + }) => IBrickBlock; + label: string; + args: string[]; + colorBg: string; + colorFg: string; + outline: string; + scale: number; +}): JSX.Element { + const { Component, prototype, label, args, colorBg, colorFg, outline, scale } = props; + + const instance = new prototype({ + label, + args: Object.fromEntries( + args.map<[string, { label: string; dataType: TBrickArgDataType; meta: unknown }]>((name) => [ + name, + { label: name, dataType: 'any', meta: undefined }, + ]), + ), + colorBg, + colorFg, + outline, + scale, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + }); + + const VisualIndicators = () => ( + <> + {/* Overall Bounding Box of the Brick */} + + + {/* Right args bounding box */} + {Object.keys(instance.bBoxArgs).map((name, i) => { + const arg = instance.bBoxArgs[name]; + + return ( + + ); + })} + + {/* Top instruction notch bounding box */} + + + {/* Bottom instruction notch bounding box */} + + + {/* Top instruction notch inside nesting bounding box */} + + + ); + + return ( + + + + + ); +} diff --git a/modules/masonry/src/brick/components/BrickData.tsx b/modules/masonry/src/brick/components/BrickData.tsx new file mode 100644 index 00000000..217aa774 --- /dev/null +++ b/modules/masonry/src/brick/components/BrickData.tsx @@ -0,0 +1,72 @@ +import BrickWrapper from './BrickWrapper'; +import type { JSX } from 'react'; +import type { IBrickData, TBrickArgDataType, TBrickColor } from '@/@types/brick'; + +// ------------------------------------------------------------------------------------------------- + +export default function (props: { + Component: (props: { instance: IBrickData; visualIndicators?: JSX.Element }) => JSX.Element; + prototype: new (params: { + name: string; + label: string; + glyph: string; + dataType: TBrickArgDataType; + dynamic: boolean; + value?: boolean | number | string; + input?: 'boolean' | 'number' | 'string' | 'options'; + colorBg: TBrickColor; + colorFg: TBrickColor; + outline: TBrickColor; + scale: number; + }) => IBrickData; + label: string; + colorBg: string; + colorFg: string; + outline: string; + scale: number; +}): JSX.Element { + const { Component, prototype, label, colorBg, colorFg, outline, scale } = props; + + const instance = new prototype({ + label, + colorBg, + colorFg, + outline, + scale, + glyph: '', + dynamic: false, + dataType: 'any', + name: '', + }); + + const VisualIndicators = () => ( + <> + {/* Overall Bounding Box of the Brick */} + + + {/* Left notch bounding box */} + + + ); + + return ( + + + + + ); +} diff --git a/modules/masonry/src/brick/components/BrickExpression.tsx b/modules/masonry/src/brick/components/BrickExpression.tsx new file mode 100644 index 00000000..8d1a1b69 --- /dev/null +++ b/modules/masonry/src/brick/components/BrickExpression.tsx @@ -0,0 +1,100 @@ +import BrickWrapper from './BrickWrapper'; +import type { JSX } from 'react'; +import type { IBrickExpression, TBrickArgDataType, TBrickColor } from '@/@types/brick'; + +// ------------------------------------------------------------------------------------------------- + +export default function (props: { + Component: (props: { instance: IBrickExpression; visualIndicators?: JSX.Element }) => JSX.Element; + prototype: new (params: { + name: string; + label: string; + glyph: string; + dataType: TBrickArgDataType; + args: Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + } + >; + colorBg: TBrickColor; + colorFg: TBrickColor; + outline: TBrickColor; + scale: number; + }) => IBrickExpression; + label: string; + args: string[]; + colorBg: string; + colorFg: string; + outline: string; + scale: number; +}): JSX.Element { + const { Component, prototype, label, args, colorBg, colorFg, outline, scale } = props; + + const instance = new prototype({ + label, + args: Object.fromEntries( + args.map<[string, { label: string; dataType: TBrickArgDataType; meta: unknown }]>((name) => [ + name, + { label: name, dataType: 'any', meta: undefined }, + ]), + ), + colorBg, + colorFg, + outline, + scale, + glyph: '', + dataType: 'any', + name: '', + }); + + const VisualIndicators = () => ( + <> + {/* Overall Bounding Box of the Brick */} + + + {/* Right args bounding box */} + {Object.keys(instance.bBoxArgs).map((name, i) => { + const arg = instance.bBoxArgs[name]; + + return ( + + ); + })} + + {/* Left notch bounding box */} + + + ); + + return ( + + + + + ); +} diff --git a/modules/masonry/src/brick/components/BrickStatement.tsx b/modules/masonry/src/brick/components/BrickStatement.tsx new file mode 100644 index 00000000..b68c3969 --- /dev/null +++ b/modules/masonry/src/brick/components/BrickStatement.tsx @@ -0,0 +1,112 @@ +import BrickWrapper from './BrickWrapper'; +import type { JSX } from 'react'; +import type { IBrickStatement, TBrickArgDataType, TBrickColor } from '@/@types/brick'; + +// ------------------------------------------------------------------------------------------------- + +export default function (props: { + Component: (props: { instance: IBrickStatement; visualIndicators?: JSX.Element }) => JSX.Element; + prototype: new (params: { + name: string; + label: string; + glyph: string; + args: Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + } + >; + colorBg: TBrickColor; + colorFg: TBrickColor; + outline: TBrickColor; + scale: number; + connectAbove: boolean; + connectBelow: boolean; + }) => IBrickStatement; + label: string; + args: string[]; + colorBg: string; + colorFg: string; + outline: string; + scale: number; +}): JSX.Element { + const { Component, prototype, label, args, colorBg, colorFg, outline, scale } = props; + + const instance = new prototype({ + label, + args: Object.fromEntries( + args.map<[string, { label: string; dataType: TBrickArgDataType; meta: unknown }]>((name) => [ + name, + { label: name, dataType: 'any', meta: undefined }, + ]), + ), + colorBg, + colorFg, + outline, + scale, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + }); + + const VisualIndicators = () => ( + <> + {/* Overall Bounding Box of the Brick */} + + + {/* Right args bounding box */} + {Object.keys(instance.bBoxArgs).map((name, i) => { + const arg = instance.bBoxArgs[name]; + + return ( + + ); + })} + + {/* Top instruction notch bounding box */} + + + {/* Bottom instruction notch bounding box */} + + + ); + + return ( + + + + + ); +} diff --git a/modules/masonry/src/brick/components/BrickWrapper.tsx b/modules/masonry/src/brick/components/BrickWrapper.tsx new file mode 100644 index 00000000..74fa20ec --- /dev/null +++ b/modules/masonry/src/brick/components/BrickWrapper.tsx @@ -0,0 +1,11 @@ +import type { PropsWithChildren } from 'react'; + +// ------------------------------------------------------------------------------------------------- + +export default function (props: PropsWithChildren): JSX.Element { + return ( + + {props.children} + + ); +} From 3d2099ec821cf5fdd4bd787db92dd65c9a9cb72a Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Sat, 27 Jul 2024 16:20:26 +0530 Subject: [PATCH 06/12] chore(masonry): modify package.json --- modules/masonry/jest.config.js | 4 ---- modules/masonry/package.json | 20 -------------------- 2 files changed, 24 deletions(-) delete mode 100644 modules/masonry/jest.config.js diff --git a/modules/masonry/jest.config.js b/modules/masonry/jest.config.js deleted file mode 100644 index 6d6062b3..00000000 --- a/modules/masonry/jest.config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', -}; diff --git a/modules/masonry/package.json b/modules/masonry/package.json index 22c99c5a..a18b7d12 100644 --- a/modules/masonry/package.json +++ b/modules/masonry/package.json @@ -10,25 +10,5 @@ "lint": "eslint src", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build" - }, - "devDependencies": { - "@chromatic-com/storybook": "^1.6.1", - "@storybook/addon-essentials": "^8.2.5", - "@storybook/addon-interactions": "^8.2.5", - "@storybook/addon-links": "^8.2.5", - "@storybook/addon-onboarding": "^8.2.5", - "@storybook/blocks": "^8.2.5", - "@storybook/react": "^8.2.5", - "@storybook/react-vite": "^8.2.5", - "@storybook/test": "^8.2.5", - "@storybook/testing-library": "^0.0.14-next.2", - "@types/jest": "^29.5.12", - "jest": "^29.7.0", - "prop-types": "^15.8.1", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "storybook": "^8.2.5", - "ts-jest": "^29.1.5", - "typescript": "^5.5.4" } } From 2078edf47bd2e577512ada988da1b3fcf65dcf52 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Sat, 27 Jul 2024 18:27:45 +0530 Subject: [PATCH 07/12] feat(masonry): restructure brick code, add stories and create components --- .../masonry/src/brick/design0/BrickBlock.ts | 90 +++++++++++++++++++ .../masonry/src/brick/design0/BrickData.ts | 53 +++++++++++ .../src/brick/design0/BrickExpression.ts | 75 ++++++++++++++++ .../src/brick/design0/BrickStatement.ts | 80 +++++++++++++++++ .../brick/design0/components/BrickBlock.tsx | 36 ++++++++ .../brick/design0/components/BrickData.tsx | 34 +++++++ .../design0/components/BrickExpression.tsx | 34 +++++++ .../design0/components/BrickStatement.tsx | 34 +++++++ .../design0/stories/BrickBlock.stories.ts | 36 ++++++++ .../design0/stories/BrickData.stories.ts | 22 +++++ .../stories/BrickExpression.stories.ts | 23 +++++ .../design0/stories/BrickStatement.stories.ts | 36 ++++++++ modules/masonry/src/brick/design0/utils.ts | 25 ++++++ modules/masonry/src/brick/index.ts | 9 ++ .../masonry/src/brick/stories/brickBlock.ts | 14 +++ .../masonry/src/brick/stories/brickData.ts | 14 +++ .../src/brick/stories/brickExpression.ts | 14 +++ .../src/brick/stories/brickStatement.ts | 14 +++ .../{ => stories}/components/BrickBlock.tsx | 0 .../{ => stories}/components/BrickData.tsx | 0 .../components/BrickExpression.tsx | 0 .../components/BrickStatement.tsx | 0 .../{ => stories}/components/BrickWrapper.tsx | 0 23 files changed, 643 insertions(+) create mode 100644 modules/masonry/src/brick/design0/BrickBlock.ts create mode 100644 modules/masonry/src/brick/design0/BrickData.ts create mode 100644 modules/masonry/src/brick/design0/BrickExpression.ts create mode 100644 modules/masonry/src/brick/design0/BrickStatement.ts create mode 100644 modules/masonry/src/brick/design0/components/BrickBlock.tsx create mode 100644 modules/masonry/src/brick/design0/components/BrickData.tsx create mode 100644 modules/masonry/src/brick/design0/components/BrickExpression.tsx create mode 100644 modules/masonry/src/brick/design0/components/BrickStatement.tsx create mode 100644 modules/masonry/src/brick/design0/stories/BrickBlock.stories.ts create mode 100644 modules/masonry/src/brick/design0/stories/BrickData.stories.ts create mode 100644 modules/masonry/src/brick/design0/stories/BrickExpression.stories.ts create mode 100644 modules/masonry/src/brick/design0/stories/BrickStatement.stories.ts create mode 100644 modules/masonry/src/brick/design0/utils.ts create mode 100644 modules/masonry/src/brick/stories/brickBlock.ts create mode 100644 modules/masonry/src/brick/stories/brickData.ts create mode 100644 modules/masonry/src/brick/stories/brickExpression.ts create mode 100644 modules/masonry/src/brick/stories/brickStatement.ts rename modules/masonry/src/brick/{ => stories}/components/BrickBlock.tsx (100%) rename modules/masonry/src/brick/{ => stories}/components/BrickData.tsx (100%) rename modules/masonry/src/brick/{ => stories}/components/BrickExpression.tsx (100%) rename modules/masonry/src/brick/{ => stories}/components/BrickStatement.tsx (100%) rename modules/masonry/src/brick/{ => stories}/components/BrickWrapper.tsx (100%) diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts new file mode 100644 index 00000000..3cedecf1 --- /dev/null +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -0,0 +1,90 @@ +import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; + +import { BrickModelBlock } from '../model'; +import { generatePath } from '../utils/path'; + +// ------------------------------------------------------------------------------------------------- + +/** + * @class + * Final class that defines a block brick. + */ +export default class BrickBlock extends BrickModelBlock { + readonly _pathResults: ReturnType; + + constructor(params: { + // intrinsic + name: string; + label: string; + glyph: string; + args: Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + } + >; + // style + colorBg: TBrickColor; + colorFg: TBrickColor; + outline: TBrickColor; + scale: number; + connectAbove: boolean; + connectBelow: boolean; + nestLengthY?: number; + }) { + super(params); + const argsKeys = Object.keys(this._args); + this._pathResults = generatePath({ + hasNest: true, + hasNotchArg: false, + hasNotchInsTop: this._connectAbove, + hasNotchInsBot: this._connectBelow, + scale: this._scale, + nestLengthY: params.nestLengthY ?? 17, + innerLengthX: 100, + argHeights: Array.from({ length: argsKeys.length }, () => 17), + }); + } + + public get SVGpath(): string { + return this._pathResults.path; + } + + public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxBrick; + } + + public get bBoxArgs(): Record { + const argsKeys = Object.keys(this._args); + const result: Record = {}; + + argsKeys.forEach((key, index) => { + result[key] = { extent: { width: 0, height: 0 }, coords: { x: 0, y: 0 } }; + const argX = this._pathResults.bBoxArgs.coords[index].x; + const argY = this._pathResults.bBoxArgs.coords[index].y; + + result[key].extent = this._pathResults.bBoxArgs.extent; + result[key].coords = { x: argX, y: argY }; + }); + + return result; + } + + public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxNotchArg!; + } + + public get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxNotchInsTop!; + } + + public get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxNotchInsBot!; + } + + public get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxNotchInsNestTop!; + } +} diff --git a/modules/masonry/src/brick/design0/BrickData.ts b/modules/masonry/src/brick/design0/BrickData.ts new file mode 100644 index 00000000..9e3c0678 --- /dev/null +++ b/modules/masonry/src/brick/design0/BrickData.ts @@ -0,0 +1,53 @@ +import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; + +import { BrickModelData } from '../model'; +import { generatePath } from '../utils/path'; + +// ------------------------------------------------------------------------------------------------- + +/** + * @class + * Final class that defines a data brick. + */ +export default class BrickData extends BrickModelData { + readonly _pathResults: ReturnType; + + constructor(params: { + // intrinsic + name: string; + label: string; + glyph: string; + dataType: TBrickArgDataType; + dynamic: boolean; + value?: boolean | number | string; + input?: 'boolean' | 'number' | 'string' | 'options'; + // style + colorBg: TBrickColor; + colorFg: TBrickColor; + outline: TBrickColor; + scale: number; + }) { + super(params); + this._pathResults = generatePath({ + hasNest: false, + hasNotchArg: true, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: this._scale, + innerLengthX: 100, + argHeights: [], + }); + } + + public get SVGpath(): string { + return this._pathResults.path; + } + + public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxBrick; + } + + public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxNotchArg!; + } +} diff --git a/modules/masonry/src/brick/design0/BrickExpression.ts b/modules/masonry/src/brick/design0/BrickExpression.ts new file mode 100644 index 00000000..8b910f3a --- /dev/null +++ b/modules/masonry/src/brick/design0/BrickExpression.ts @@ -0,0 +1,75 @@ +import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; + +import { BrickModelExpression } from '../model'; +import { generatePath } from '../utils/path'; + +// ------------------------------------------------------------------------------------------------- + +/** + * @class + * Final class that defines a expression brick. + */ +export default class BrickExpression extends BrickModelExpression { + readonly _pathResults: ReturnType; + + constructor(params: { + // intrinsic + name: string; + label: string; + glyph: string; + dataType: TBrickArgDataType; + args: Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + } + >; + // style + colorBg: TBrickColor; + colorFg: TBrickColor; + outline: TBrickColor; + scale: number; + }) { + super(params); + const argsKeys = Object.keys(this._args); + this._pathResults = generatePath({ + hasNest: false, + hasNotchArg: true, + hasNotchInsTop: false, + hasNotchInsBot: false, + scale: this._scale, + innerLengthX: 100, + argHeights: Array.from({ length: argsKeys.length }, () => 17), + }); + } + + public get SVGpath(): string { + return this._pathResults.path; + } + + public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxBrick; + } + + public get bBoxArgs(): Record { + const argsKeys = Object.keys(this._args); + const result: Record = {}; + + argsKeys.forEach((key, index) => { + result[key] = { extent: { width: 0, height: 0 }, coords: { x: 0, y: 0 } }; + const argX = this._pathResults.bBoxArgs.coords[index].x; + const argY = this._pathResults.bBoxArgs.coords[index].y; + + result[key].extent = this._pathResults.bBoxArgs.extent; + result[key].coords = { x: argX, y: argY }; + }); + + return result; + } + + public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxNotchArg!; + } +} diff --git a/modules/masonry/src/brick/design0/BrickStatement.ts b/modules/masonry/src/brick/design0/BrickStatement.ts new file mode 100644 index 00000000..aa710959 --- /dev/null +++ b/modules/masonry/src/brick/design0/BrickStatement.ts @@ -0,0 +1,80 @@ +import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; + +import { BrickModelStatement } from '../model'; +import { generatePath } from '../utils/path'; + +// ------------------------------------------------------------------------------------------------- + +/** + * @class + * Final class that defines a statement brick. + */ +export default class BrickStatement extends BrickModelStatement { + readonly _pathResults: ReturnType; + + constructor(params: { + // intrinsic + name: string; + label: string; + glyph: string; + args: Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + } + >; + // style + colorBg: TBrickColor; + colorFg: TBrickColor; + outline: TBrickColor; + scale: number; + connectAbove: boolean; + connectBelow: boolean; + }) { + super(params); + const argsKeys = Object.keys(this._args); + this._pathResults = generatePath({ + hasNest: false, + hasNotchArg: false, + hasNotchInsTop: true, + hasNotchInsBot: true, + scale: this._scale, + innerLengthX: 100, + argHeights: Array.from({ length: argsKeys.length }, () => 17), + }); + } + + public get SVGpath(): string { + return this._pathResults.path; + } + + public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxBrick; + } + + public get bBoxArgs(): Record { + const argsKeys = Object.keys(this._args); + const result: Record = {}; + + argsKeys.forEach((key, index) => { + result[key] = { extent: { width: 0, height: 0 }, coords: { x: 0, y: 0 } }; + const argX = this._pathResults.bBoxArgs.coords[index].x; + const argY = this._pathResults.bBoxArgs.coords[index].y; + + result[key].extent = this._pathResults.bBoxArgs.extent; + result[key].coords = { x: argX, y: argY }; + }); + + return result; + } + + public get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxNotchInsTop!; + } + + public get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords } { + return this._pathResults.bBoxNotchInsBot!; + } +} diff --git a/modules/masonry/src/brick/design0/components/BrickBlock.tsx b/modules/masonry/src/brick/design0/components/BrickBlock.tsx new file mode 100644 index 00000000..2a9d15b2 --- /dev/null +++ b/modules/masonry/src/brick/design0/components/BrickBlock.tsx @@ -0,0 +1,36 @@ +import type { DOMAttributes, JSX } from 'react'; +import type { Brick } from 'playground/pages/WorkSpace/data'; + +// ------------------------------------------------------------------------------------------------- + +export default function ({ + brickData, + moveProps, + coords, + color, +}: { + brickData: Brick; + moveProps: DOMAttributes; + coords: { x: number; y: number }; + color: string; +}): JSX.Element { + return ( + + + + ); +} diff --git a/modules/masonry/src/brick/design0/components/BrickData.tsx b/modules/masonry/src/brick/design0/components/BrickData.tsx new file mode 100644 index 00000000..d12f9813 --- /dev/null +++ b/modules/masonry/src/brick/design0/components/BrickData.tsx @@ -0,0 +1,34 @@ +import type { DOMAttributes, JSX } from 'react'; +import type { Brick } from 'playground/pages/WorkSpace/data'; + +export default function ({ + brickData, + moveProps, + coords, + color, +}: { + brickData: Brick; + moveProps: DOMAttributes; + coords: { x: number; y: number }; + color: string; +}): JSX.Element { + return ( + + + + ); +} diff --git a/modules/masonry/src/brick/design0/components/BrickExpression.tsx b/modules/masonry/src/brick/design0/components/BrickExpression.tsx new file mode 100644 index 00000000..d12f9813 --- /dev/null +++ b/modules/masonry/src/brick/design0/components/BrickExpression.tsx @@ -0,0 +1,34 @@ +import type { DOMAttributes, JSX } from 'react'; +import type { Brick } from 'playground/pages/WorkSpace/data'; + +export default function ({ + brickData, + moveProps, + coords, + color, +}: { + brickData: Brick; + moveProps: DOMAttributes; + coords: { x: number; y: number }; + color: string; +}): JSX.Element { + return ( + + + + ); +} diff --git a/modules/masonry/src/brick/design0/components/BrickStatement.tsx b/modules/masonry/src/brick/design0/components/BrickStatement.tsx new file mode 100644 index 00000000..d12f9813 --- /dev/null +++ b/modules/masonry/src/brick/design0/components/BrickStatement.tsx @@ -0,0 +1,34 @@ +import type { DOMAttributes, JSX } from 'react'; +import type { Brick } from 'playground/pages/WorkSpace/data'; + +export default function ({ + brickData, + moveProps, + coords, + color, +}: { + brickData: Brick; + moveProps: DOMAttributes; + coords: { x: number; y: number }; + color: string; +}): JSX.Element { + return ( + + + + ); +} diff --git a/modules/masonry/src/brick/design0/stories/BrickBlock.stories.ts b/modules/masonry/src/brick/design0/stories/BrickBlock.stories.ts new file mode 100644 index 00000000..4fcb241c --- /dev/null +++ b/modules/masonry/src/brick/design0/stories/BrickBlock.stories.ts @@ -0,0 +1,36 @@ +import { MetaData, Story } from '../../stories/brickBlock'; +import MBrickBlock from '../BrickBlock'; +import CBrickBlock from '../components/BrickBlock'; + +export default { + title: 'Design 0/Block Brick', + ...MetaData, +}; + +// ------------------------------------------------------------------------------------------------- + +export const NoArgs: Story = { + args: { + Component: CBrickBlock, + prototype: MBrickBlock, + label: 'Block', + args: [], + colorBg: 'yellow', + colorFg: 'black', + outline: 'red', + scale: 1, + }, +}; + +export const WithArgs: Story = { + args: { + Component: CBrickBlock, + prototype: MBrickBlock, + label: 'Block', + args: ['Label 1'], + colorBg: 'yellow', + colorFg: 'black', + outline: 'red', + scale: 1, + }, +}; diff --git a/modules/masonry/src/brick/design0/stories/BrickData.stories.ts b/modules/masonry/src/brick/design0/stories/BrickData.stories.ts new file mode 100644 index 00000000..962108c8 --- /dev/null +++ b/modules/masonry/src/brick/design0/stories/BrickData.stories.ts @@ -0,0 +1,22 @@ +import { MetaData, Story } from '../../stories/brickData'; +import MBrickData from '../BrickData'; +import CBrickData from '../components/BrickData'; + +export default { + title: 'Design 0/Data Brick', + ...MetaData, +}; + +// ------------------------------------------------------------------------------------------------- + +export const Static: Story = { + args: { + Component: CBrickData, + prototype: MBrickData, + label: 'Data', + colorBg: 'yellow', + colorFg: 'black', + outline: 'red', + scale: 1, + }, +}; diff --git a/modules/masonry/src/brick/design0/stories/BrickExpression.stories.ts b/modules/masonry/src/brick/design0/stories/BrickExpression.stories.ts new file mode 100644 index 00000000..b47a3faa --- /dev/null +++ b/modules/masonry/src/brick/design0/stories/BrickExpression.stories.ts @@ -0,0 +1,23 @@ +import { MetaData, Story } from '../../stories/brickExpression'; +import MBrickExpression from '../BrickExpression'; +import CBrickExpression from '../components/BrickExpression'; + +export default { + title: 'Design 0/Expression Brick', + ...MetaData, +}; + +// ------------------------------------------------------------------------------------------------- + +export const WithArgs: Story = { + args: { + Component: CBrickExpression, + prototype: MBrickExpression, + label: 'Expression', + args: ['Label 1'], + colorBg: 'yellow', + colorFg: 'black', + outline: 'red', + scale: 1, + }, +}; diff --git a/modules/masonry/src/brick/design0/stories/BrickStatement.stories.ts b/modules/masonry/src/brick/design0/stories/BrickStatement.stories.ts new file mode 100644 index 00000000..404f2763 --- /dev/null +++ b/modules/masonry/src/brick/design0/stories/BrickStatement.stories.ts @@ -0,0 +1,36 @@ +import { MetaData, Story } from '../../stories/brickStatement'; +import MBrickStatement from '../BrickStatement'; +import CBrickStatement from '../components/BrickStatement'; + +export default { + title: 'Design 0/Statement Brick', + ...MetaData, +}; + +// ------------------------------------------------------------------------------------------------- + +export const NoArgs: Story = { + args: { + Component: CBrickStatement, + prototype: MBrickStatement, + label: 'Statement', + args: [], + colorBg: 'yellow', + colorFg: 'black', + outline: 'red', + scale: 1, + }, +}; + +export const WithArgs: Story = { + args: { + Component: CBrickStatement, + prototype: MBrickStatement, + label: 'Statement', + args: ['Label 1'], + colorBg: 'yellow', + colorFg: 'black', + outline: 'red', + scale: 1, + }, +}; diff --git a/modules/masonry/src/brick/design0/utils.ts b/modules/masonry/src/brick/design0/utils.ts new file mode 100644 index 00000000..6b049b67 --- /dev/null +++ b/modules/masonry/src/brick/design0/utils.ts @@ -0,0 +1,25 @@ +import type { + TBrickType, + TBrickCoords, + IBrickData, + IBrickExpression, + IBrickStatement, + IBrickBlock, +} from '@/@types/brick'; + +type InstanceMap = { + data: IBrickData; + expression: IBrickExpression; + statement: IBrickStatement; + block: IBrickBlock; +}; + +export type Brick = { + id: string; + type: TBrickType; + instance: InstanceMap[TBrickType]; + surroundingBricks: { above: string; below: string }; + childBricks: string[]; + coords: TBrickCoords; + children?: Brick[]; +}; diff --git a/modules/masonry/src/brick/index.ts b/modules/masonry/src/brick/index.ts index e69de29b..6718a5cd 100644 --- a/modules/masonry/src/brick/index.ts +++ b/modules/masonry/src/brick/index.ts @@ -0,0 +1,9 @@ +export { default as ModelBrickData } from './design0/BrickData'; +export { default as ModelBrickExpression } from './design0/BrickExpression'; +export { default as ModelBrickStatement } from './design0/BrickStatement'; +export { default as ModelBrickBlock } from './design0/BrickBlock'; + +export { default as BrickData } from './design0/components/BrickData'; +export { default as BrickExpression } from './design0/components/BrickExpression'; +export { default as BrickStatement } from './design0/components/BrickStatement'; +export { default as BrickBlock } from './design0/components/BrickBlock'; diff --git a/modules/masonry/src/brick/stories/brickBlock.ts b/modules/masonry/src/brick/stories/brickBlock.ts new file mode 100644 index 00000000..154b50e7 --- /dev/null +++ b/modules/masonry/src/brick/stories/brickBlock.ts @@ -0,0 +1,14 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import CBrickBlock from './components/BrickBlock'; + +// ------------------------------------------------------------------------------------------------- + +export const MetaData: Meta = { + component: CBrickBlock, + parameters: { + layout: 'centered', + }, +}; + +export type Story = StoryObj; diff --git a/modules/masonry/src/brick/stories/brickData.ts b/modules/masonry/src/brick/stories/brickData.ts new file mode 100644 index 00000000..3c9268d5 --- /dev/null +++ b/modules/masonry/src/brick/stories/brickData.ts @@ -0,0 +1,14 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import CBrickData from './components/BrickData'; + +// ------------------------------------------------------------------------------------------------- + +export const MetaData: Meta = { + component: CBrickData, + parameters: { + layout: 'centered', + }, +}; + +export type Story = StoryObj; diff --git a/modules/masonry/src/brick/stories/brickExpression.ts b/modules/masonry/src/brick/stories/brickExpression.ts new file mode 100644 index 00000000..02b89299 --- /dev/null +++ b/modules/masonry/src/brick/stories/brickExpression.ts @@ -0,0 +1,14 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import CBrickExpression from './components/BrickExpression'; + +// ------------------------------------------------------------------------------------------------- + +export const MetaData: Meta = { + component: CBrickExpression, + parameters: { + layout: 'centered', + }, +}; + +export type Story = StoryObj; diff --git a/modules/masonry/src/brick/stories/brickStatement.ts b/modules/masonry/src/brick/stories/brickStatement.ts new file mode 100644 index 00000000..0dd82a9f --- /dev/null +++ b/modules/masonry/src/brick/stories/brickStatement.ts @@ -0,0 +1,14 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import CBrickStatement from './components/BrickStatement'; + +// ------------------------------------------------------------------------------------------------- + +export const MetaData: Meta = { + component: CBrickStatement, + parameters: { + layout: 'centered', + }, +}; + +export type Story = StoryObj; diff --git a/modules/masonry/src/brick/components/BrickBlock.tsx b/modules/masonry/src/brick/stories/components/BrickBlock.tsx similarity index 100% rename from modules/masonry/src/brick/components/BrickBlock.tsx rename to modules/masonry/src/brick/stories/components/BrickBlock.tsx diff --git a/modules/masonry/src/brick/components/BrickData.tsx b/modules/masonry/src/brick/stories/components/BrickData.tsx similarity index 100% rename from modules/masonry/src/brick/components/BrickData.tsx rename to modules/masonry/src/brick/stories/components/BrickData.tsx diff --git a/modules/masonry/src/brick/components/BrickExpression.tsx b/modules/masonry/src/brick/stories/components/BrickExpression.tsx similarity index 100% rename from modules/masonry/src/brick/components/BrickExpression.tsx rename to modules/masonry/src/brick/stories/components/BrickExpression.tsx diff --git a/modules/masonry/src/brick/components/BrickStatement.tsx b/modules/masonry/src/brick/stories/components/BrickStatement.tsx similarity index 100% rename from modules/masonry/src/brick/components/BrickStatement.tsx rename to modules/masonry/src/brick/stories/components/BrickStatement.tsx diff --git a/modules/masonry/src/brick/components/BrickWrapper.tsx b/modules/masonry/src/brick/stories/components/BrickWrapper.tsx similarity index 100% rename from modules/masonry/src/brick/components/BrickWrapper.tsx rename to modules/masonry/src/brick/stories/components/BrickWrapper.tsx From 09e0b0935ddc1ee9489017fa46a71c04d75624e9 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 29 Jul 2024 15:54:34 +0530 Subject: [PATCH 08/12] fix(masonry): fix brick imports --- .../brick/design0/components/BrickBlock.tsx | 2 +- .../brick/design0/components/BrickData.tsx | 2 +- .../design0/components/BrickExpression.tsx | 2 +- .../design0/components/BrickStatement.tsx | 2 +- .../src/brick/design0/components/utils.ts | 25 +++++++++++++++++++ 5 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 modules/masonry/src/brick/design0/components/utils.ts diff --git a/modules/masonry/src/brick/design0/components/BrickBlock.tsx b/modules/masonry/src/brick/design0/components/BrickBlock.tsx index 2a9d15b2..0b1ff553 100644 --- a/modules/masonry/src/brick/design0/components/BrickBlock.tsx +++ b/modules/masonry/src/brick/design0/components/BrickBlock.tsx @@ -1,5 +1,5 @@ import type { DOMAttributes, JSX } from 'react'; -import type { Brick } from 'playground/pages/WorkSpace/data'; +import type { Brick } from './utils'; // ------------------------------------------------------------------------------------------------- diff --git a/modules/masonry/src/brick/design0/components/BrickData.tsx b/modules/masonry/src/brick/design0/components/BrickData.tsx index d12f9813..4b018bac 100644 --- a/modules/masonry/src/brick/design0/components/BrickData.tsx +++ b/modules/masonry/src/brick/design0/components/BrickData.tsx @@ -1,5 +1,5 @@ import type { DOMAttributes, JSX } from 'react'; -import type { Brick } from 'playground/pages/WorkSpace/data'; +import type { Brick } from './utils'; export default function ({ brickData, diff --git a/modules/masonry/src/brick/design0/components/BrickExpression.tsx b/modules/masonry/src/brick/design0/components/BrickExpression.tsx index d12f9813..4b018bac 100644 --- a/modules/masonry/src/brick/design0/components/BrickExpression.tsx +++ b/modules/masonry/src/brick/design0/components/BrickExpression.tsx @@ -1,5 +1,5 @@ import type { DOMAttributes, JSX } from 'react'; -import type { Brick } from 'playground/pages/WorkSpace/data'; +import type { Brick } from './utils'; export default function ({ brickData, diff --git a/modules/masonry/src/brick/design0/components/BrickStatement.tsx b/modules/masonry/src/brick/design0/components/BrickStatement.tsx index d12f9813..4b018bac 100644 --- a/modules/masonry/src/brick/design0/components/BrickStatement.tsx +++ b/modules/masonry/src/brick/design0/components/BrickStatement.tsx @@ -1,5 +1,5 @@ import type { DOMAttributes, JSX } from 'react'; -import type { Brick } from 'playground/pages/WorkSpace/data'; +import type { Brick } from './utils'; export default function ({ brickData, diff --git a/modules/masonry/src/brick/design0/components/utils.ts b/modules/masonry/src/brick/design0/components/utils.ts new file mode 100644 index 00000000..6b049b67 --- /dev/null +++ b/modules/masonry/src/brick/design0/components/utils.ts @@ -0,0 +1,25 @@ +import type { + TBrickType, + TBrickCoords, + IBrickData, + IBrickExpression, + IBrickStatement, + IBrickBlock, +} from '@/@types/brick'; + +type InstanceMap = { + data: IBrickData; + expression: IBrickExpression; + statement: IBrickStatement; + block: IBrickBlock; +}; + +export type Brick = { + id: string; + type: TBrickType; + instance: InstanceMap[TBrickType]; + surroundingBricks: { above: string; below: string }; + childBricks: string[]; + coords: TBrickCoords; + children?: Brick[]; +}; From 11c2250adaa815ff701eaa5d1eb58ebe6c55e8d8 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Tue, 20 Aug 2024 18:37:03 +0530 Subject: [PATCH 09/12] fix(masonry): fix errors in path.ts and BrickBlock.ts --- modules/masonry/src/brick/design0/BrickBlock.ts | 3 +-- modules/masonry/src/brick/utils/path.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index 3cedecf1..03902b61 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -32,7 +32,6 @@ export default class BrickBlock extends BrickModelBlock { scale: number; connectAbove: boolean; connectBelow: boolean; - nestLengthY?: number; }) { super(params); const argsKeys = Object.keys(this._args); @@ -42,7 +41,7 @@ export default class BrickBlock extends BrickModelBlock { hasNotchInsTop: this._connectAbove, hasNotchInsBot: this._connectBelow, scale: this._scale, - nestLengthY: params.nestLengthY ?? 17, + nestLengthY: 30, innerLengthX: 100, argHeights: Array.from({ length: argsKeys.length }, () => 17), }); diff --git a/modules/masonry/src/brick/utils/path.ts b/modules/masonry/src/brick/utils/path.ts index 56bdc06e..f8b3b276 100644 --- a/modules/masonry/src/brick/utils/path.ts +++ b/modules/masonry/src/brick/utils/path.ts @@ -599,7 +599,7 @@ export function generatePath( bBoxArgs: _getBBoxArgs(), }; - if (print) console.log(results); + if (print || import.meta.env.DEV) console.log(results); return results; } From 022f0c20a471da8059da0eb0d495a42f492d9034 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Tue, 20 Aug 2024 18:37:48 +0530 Subject: [PATCH 10/12] fix(masonry): rewrite components and render them in storybook --- .../brick/design0/components/BrickBlock.tsx | 30 ++++++----------- .../brick/design0/components/BrickData.tsx | 30 ++++++----------- .../design0/components/BrickExpression.tsx | 32 +++++++------------ .../design0/components/BrickStatement.tsx | 32 +++++++------------ .../src/brick/design0/components/utils.ts | 25 --------------- 5 files changed, 40 insertions(+), 109 deletions(-) delete mode 100644 modules/masonry/src/brick/design0/components/utils.ts diff --git a/modules/masonry/src/brick/design0/components/BrickBlock.tsx b/modules/masonry/src/brick/design0/components/BrickBlock.tsx index 0b1ff553..7dd5ed16 100644 --- a/modules/masonry/src/brick/design0/components/BrickBlock.tsx +++ b/modules/masonry/src/brick/design0/components/BrickBlock.tsx @@ -1,31 +1,19 @@ -import type { DOMAttributes, JSX } from 'react'; -import type { Brick } from './utils'; +import type { JSX } from 'react'; +import type { IBrickBlock } from '@/@types/brick'; // ------------------------------------------------------------------------------------------------- -export default function ({ - brickData, - moveProps, - coords, - color, -}: { - brickData: Brick; - moveProps: DOMAttributes; - coords: { x: number; y: number }; - color: string; -}): JSX.Element { +export default function (props: { instance: IBrickBlock }): JSX.Element { + const { instance } = props; + return ( - + ; - coords: { x: number; y: number }; - color: string; -}): JSX.Element { return ( - + ; - coords: { x: number; y: number }; - color: string; -}): JSX.Element { return ( - + ; - coords: { x: number; y: number }; - color: string; -}): JSX.Element { return ( - + Date: Wed, 21 Aug 2024 16:41:45 +0530 Subject: [PATCH 11/12] fix(masonry): Fix bounding box scale error for BrickData.ts --- .../masonry/src/brick/design0/BrickData.ts | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/modules/masonry/src/brick/design0/BrickData.ts b/modules/masonry/src/brick/design0/BrickData.ts index 9e3c0678..f15d1911 100644 --- a/modules/masonry/src/brick/design0/BrickData.ts +++ b/modules/masonry/src/brick/design0/BrickData.ts @@ -44,10 +44,30 @@ export default class BrickData extends BrickModelData { } public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxBrick; + const { extent, coords } = this._pathResults.bBoxBrick; + return { + extent: { + width: extent.width * this._scale, + height: extent.height * this._scale, + }, + coords: { + x: coords.x * this._scale, + y: coords.y * this._scale, + }, + }; } public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxNotchArg!; + const { extent, coords } = this._pathResults.bBoxNotchArg!; + return { + extent: { + width: extent.width * this._scale, + height: extent.height * this._scale, + }, + coords: { + x: coords.x * this._scale, + y: coords.y * this._scale, + }, + }; } } From 47539cf6a34fa16529a2e4b82243e0fcb7e8c5cc Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Wed, 21 Aug 2024 17:05:47 +0530 Subject: [PATCH 12/12] fix(masonry): Fix bounding box scale error for all bricks --- .../masonry/src/brick/design0/BrickBlock.ts | 71 ++++++++++++++++--- .../src/brick/design0/BrickExpression.ts | 40 ++++++++--- .../src/brick/design0/BrickStatement.ts | 49 ++++++++++--- modules/masonry/src/brick/design0/utils.ts | 25 ------- 4 files changed, 131 insertions(+), 54 deletions(-) delete mode 100644 modules/masonry/src/brick/design0/utils.ts diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index 03902b61..969a7c6e 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -52,7 +52,16 @@ export default class BrickBlock extends BrickModelBlock { } public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxBrick; + return { + extent: { + width: this._pathResults.bBoxBrick.extent.width * this._scale, + height: this._pathResults.bBoxBrick.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxBrick.coords.x * this._scale, + y: this._pathResults.bBoxBrick.coords.y * this._scale, + }, + }; } public get bBoxArgs(): Record { @@ -60,30 +69,70 @@ export default class BrickBlock extends BrickModelBlock { const result: Record = {}; argsKeys.forEach((key, index) => { - result[key] = { extent: { width: 0, height: 0 }, coords: { x: 0, y: 0 } }; - const argX = this._pathResults.bBoxArgs.coords[index].x; - const argY = this._pathResults.bBoxArgs.coords[index].y; - - result[key].extent = this._pathResults.bBoxArgs.extent; - result[key].coords = { x: argX, y: argY }; + result[key] = { + extent: { + width: this._pathResults.bBoxArgs.extent.width * this._scale, + height: this._pathResults.bBoxArgs.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxArgs.coords[index].x * this._scale, + y: this._pathResults.bBoxArgs.coords[index].y * this._scale, + }, + }; }); return result; } public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxNotchArg!; + return { + extent: { + width: this._pathResults.bBoxNotchArg!.extent.width * this._scale, + height: this._pathResults.bBoxNotchArg!.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxNotchArg!.coords.x * this._scale, + y: this._pathResults.bBoxNotchArg!.coords.y * this._scale, + }, + }; } public get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxNotchInsTop!; + return { + extent: { + width: this._pathResults.bBoxNotchInsTop!.extent.width * this._scale, + height: this._pathResults.bBoxNotchInsTop!.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxNotchInsTop!.coords.x * this._scale, + y: this._pathResults.bBoxNotchInsTop!.coords.y * this._scale, + }, + }; } public get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxNotchInsBot!; + return { + extent: { + width: this._pathResults.bBoxNotchInsBot!.extent.width * this._scale, + height: this._pathResults.bBoxNotchInsBot!.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxNotchInsBot!.coords.x * this._scale, + y: this._pathResults.bBoxNotchInsBot!.coords.y * this._scale, + }, + }; } public get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxNotchInsNestTop!; + return { + extent: { + width: this._pathResults.bBoxNotchInsNestTop!.extent.width * this._scale, + height: this._pathResults.bBoxNotchInsNestTop!.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxNotchInsNestTop!.coords.x * this._scale, + y: this._pathResults.bBoxNotchInsNestTop!.coords.y * this._scale, + }, + }; } } diff --git a/modules/masonry/src/brick/design0/BrickExpression.ts b/modules/masonry/src/brick/design0/BrickExpression.ts index 8b910f3a..e039180a 100644 --- a/modules/masonry/src/brick/design0/BrickExpression.ts +++ b/modules/masonry/src/brick/design0/BrickExpression.ts @@ -7,7 +7,7 @@ import { generatePath } from '../utils/path'; /** * @class - * Final class that defines a expression brick. + * Final class that defines an expression brick. */ export default class BrickExpression extends BrickModelExpression { readonly _pathResults: ReturnType; @@ -50,7 +50,16 @@ export default class BrickExpression extends BrickModelExpression { } public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxBrick; + return { + extent: { + width: this._pathResults.bBoxBrick.extent.width * this._scale, + height: this._pathResults.bBoxBrick.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxBrick.coords.x * this._scale, + y: this._pathResults.bBoxBrick.coords.y * this._scale, + }, + }; } public get bBoxArgs(): Record { @@ -58,18 +67,31 @@ export default class BrickExpression extends BrickModelExpression { const result: Record = {}; argsKeys.forEach((key, index) => { - result[key] = { extent: { width: 0, height: 0 }, coords: { x: 0, y: 0 } }; - const argX = this._pathResults.bBoxArgs.coords[index].x; - const argY = this._pathResults.bBoxArgs.coords[index].y; - - result[key].extent = this._pathResults.bBoxArgs.extent; - result[key].coords = { x: argX, y: argY }; + result[key] = { + extent: { + width: this._pathResults.bBoxArgs.extent.width * this._scale, + height: this._pathResults.bBoxArgs.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxArgs.coords[index].x * this._scale, + y: this._pathResults.bBoxArgs.coords[index].y * this._scale, + }, + }; }); return result; } public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxNotchArg!; + return { + extent: { + width: this._pathResults.bBoxNotchArg!.extent.width * this._scale, + height: this._pathResults.bBoxNotchArg!.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxNotchArg!.coords.x * this._scale, + y: this._pathResults.bBoxNotchArg!.coords.y * this._scale, + }, + }; } } diff --git a/modules/masonry/src/brick/design0/BrickStatement.ts b/modules/masonry/src/brick/design0/BrickStatement.ts index aa710959..c6e588fd 100644 --- a/modules/masonry/src/brick/design0/BrickStatement.ts +++ b/modules/masonry/src/brick/design0/BrickStatement.ts @@ -51,7 +51,16 @@ export default class BrickStatement extends BrickModelStatement { } public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxBrick; + return { + extent: { + width: this._pathResults.bBoxBrick.extent.width * this._scale, + height: this._pathResults.bBoxBrick.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxBrick.coords.x * this._scale, + y: this._pathResults.bBoxBrick.coords.y * this._scale, + }, + }; } public get bBoxArgs(): Record { @@ -59,22 +68,44 @@ export default class BrickStatement extends BrickModelStatement { const result: Record = {}; argsKeys.forEach((key, index) => { - result[key] = { extent: { width: 0, height: 0 }, coords: { x: 0, y: 0 } }; - const argX = this._pathResults.bBoxArgs.coords[index].x; - const argY = this._pathResults.bBoxArgs.coords[index].y; - - result[key].extent = this._pathResults.bBoxArgs.extent; - result[key].coords = { x: argX, y: argY }; + result[key] = { + extent: { + width: this._pathResults.bBoxArgs.extent.width * this._scale, + height: this._pathResults.bBoxArgs.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxArgs.coords[index].x * this._scale, + y: this._pathResults.bBoxArgs.coords[index].y * this._scale, + }, + }; }); return result; } public get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxNotchInsTop!; + return { + extent: { + width: this._pathResults.bBoxNotchInsTop!.extent.width * this._scale, + height: this._pathResults.bBoxNotchInsTop!.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxNotchInsTop!.coords.x * this._scale, + y: this._pathResults.bBoxNotchInsTop!.coords.y * this._scale, + }, + }; } public get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords } { - return this._pathResults.bBoxNotchInsBot!; + return { + extent: { + width: this._pathResults.bBoxNotchInsBot!.extent.width * this._scale, + height: this._pathResults.bBoxNotchInsBot!.extent.height * this._scale, + }, + coords: { + x: this._pathResults.bBoxNotchInsBot!.coords.x * this._scale, + y: this._pathResults.bBoxNotchInsBot!.coords.y * this._scale, + }, + }; } } diff --git a/modules/masonry/src/brick/design0/utils.ts b/modules/masonry/src/brick/design0/utils.ts deleted file mode 100644 index 6b049b67..00000000 --- a/modules/masonry/src/brick/design0/utils.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { - TBrickType, - TBrickCoords, - IBrickData, - IBrickExpression, - IBrickStatement, - IBrickBlock, -} from '@/@types/brick'; - -type InstanceMap = { - data: IBrickData; - expression: IBrickExpression; - statement: IBrickStatement; - block: IBrickBlock; -}; - -export type Brick = { - id: string; - type: TBrickType; - instance: InstanceMap[TBrickType]; - surroundingBricks: { above: string; below: string }; - childBricks: string[]; - coords: TBrickCoords; - children?: Brick[]; -};