From 9dc66d5068d411855a4ffe3b4e9e4609dd0202a4 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Wed, 26 Jun 2024 12:29:26 +0530 Subject: [PATCH 01/58] build(masonry): create initial folder structure --- modules/masonry/package.json | 12 ++++++++++++ modules/masonry/tsconfig.json | 18 ++++++++++++++++++ package-lock.json | 8 ++++++++ package.json | 1 + 4 files changed, 39 insertions(+) create mode 100644 modules/masonry/package.json create mode 100644 modules/masonry/tsconfig.json diff --git a/modules/masonry/package.json b/modules/masonry/package.json new file mode 100644 index 00000000..09bfbe5d --- /dev/null +++ b/modules/masonry/package.json @@ -0,0 +1,12 @@ +{ + "name": "@sugarlabs/mb4-module-masonry", + "version": "4.2.0", + "description": "Graphical project builder using drag & drop code bricks", + "private": "true", + "main": "src/index.ts", + "scripts": { + "test": "vitest", + "coverage": "vitest run --coverage", + "lint": "eslint src" + } +} diff --git a/modules/masonry/tsconfig.json b/modules/masonry/tsconfig.json new file mode 100644 index 00000000..737827ed --- /dev/null +++ b/modules/masonry/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.json", + "include": [ + "./**/*.ts", + "./**/*.tsx" + ], + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": [ + "./src/*" + ], + "#/@types/*": [ + "../../@types/*" + ] + } + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8e2766f7..501bc56a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "modules/menu", "modules/painter", "modules/singer", + "modules/masonry", "app" ], "dependencies": { @@ -167,6 +168,9 @@ "react-dom": "~18.x" } }, + "modules/masonry": { + "version": "4.2.0" + }, "modules/menu": { "name": "@sugarlabs/mb4-module-menu", "version": "4.2.0", @@ -9231,6 +9235,10 @@ "resolved": "modules/editor", "link": true }, + "node_modules/@sugarlabs/mb4-module-masonry": { + "resolved": "modules/masonry", + "link": true + }, "node_modules/@sugarlabs/mb4-module-menu": { "resolved": "modules/menu", "link": true diff --git a/package.json b/package.json index 9c609287..cd0bb8ee 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "modules/menu", "modules/painter", "modules/singer", + "modules/masonry", "app" ], "dependencies": { From b36b9f5bd0914f3bf9398f9f37824b3a3fe37e24 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Wed, 26 Jun 2024 12:40:39 +0530 Subject: [PATCH 02/58] docs(masonry): create docs folder and add PRD --- .../masonry/docs/Masonry_Design_Document.md | 359 ++++++++++++++++++ modules/masonry/docs/PRD.md | 147 +++++++ modules/masonry/docs/images/image-1.png | Bin 0 -> 7399 bytes modules/masonry/docs/images/image-10.png | Bin 0 -> 43593 bytes modules/masonry/docs/images/image-11.png | Bin 0 -> 42991 bytes modules/masonry/docs/images/image-12.png | Bin 0 -> 39534 bytes modules/masonry/docs/images/image-13.png | Bin 0 -> 123408 bytes modules/masonry/docs/images/image-14.png | Bin 0 -> 37197 bytes modules/masonry/docs/images/image-15.png | Bin 0 -> 32910 bytes modules/masonry/docs/images/image-16.png | Bin 0 -> 74509 bytes modules/masonry/docs/images/image-17.png | Bin 0 -> 131387 bytes modules/masonry/docs/images/image-18.png | Bin 0 -> 13374 bytes modules/masonry/docs/images/image-19.png | Bin 0 -> 13707 bytes modules/masonry/docs/images/image-2.png | Bin 0 -> 12583 bytes modules/masonry/docs/images/image-3.png | Bin 0 -> 13594 bytes modules/masonry/docs/images/image-4.png | Bin 0 -> 3649 bytes modules/masonry/docs/images/image-5.png | Bin 0 -> 72792 bytes modules/masonry/docs/images/image-6.png | Bin 0 -> 9704 bytes modules/masonry/docs/images/image-7.png | Bin 0 -> 9622 bytes modules/masonry/docs/images/image-8.png | Bin 0 -> 33252 bytes modules/masonry/docs/images/image-9.png | Bin 0 -> 4914 bytes modules/masonry/docs/images/image.png | Bin 0 -> 4441 bytes 22 files changed, 506 insertions(+) create mode 100644 modules/masonry/docs/Masonry_Design_Document.md create mode 100644 modules/masonry/docs/PRD.md create mode 100644 modules/masonry/docs/images/image-1.png create mode 100644 modules/masonry/docs/images/image-10.png create mode 100644 modules/masonry/docs/images/image-11.png create mode 100644 modules/masonry/docs/images/image-12.png create mode 100644 modules/masonry/docs/images/image-13.png create mode 100644 modules/masonry/docs/images/image-14.png create mode 100644 modules/masonry/docs/images/image-15.png create mode 100644 modules/masonry/docs/images/image-16.png create mode 100644 modules/masonry/docs/images/image-17.png create mode 100644 modules/masonry/docs/images/image-18.png create mode 100644 modules/masonry/docs/images/image-19.png create mode 100644 modules/masonry/docs/images/image-2.png create mode 100644 modules/masonry/docs/images/image-3.png create mode 100644 modules/masonry/docs/images/image-4.png create mode 100644 modules/masonry/docs/images/image-5.png create mode 100644 modules/masonry/docs/images/image-6.png create mode 100644 modules/masonry/docs/images/image-7.png create mode 100644 modules/masonry/docs/images/image-8.png create mode 100644 modules/masonry/docs/images/image-9.png create mode 100644 modules/masonry/docs/images/image.png diff --git a/modules/masonry/docs/Masonry_Design_Document.md b/modules/masonry/docs/Masonry_Design_Document.md new file mode 100644 index 00000000..78cc85e1 --- /dev/null +++ b/modules/masonry/docs/Masonry_Design_Document.md @@ -0,0 +1,359 @@ + +--- + +# Music Blocks v4 : Masonry Design Document + +## Overview +1. **Short Description of the Product** + - The Masonry (previously called Project Builder) in Music Blocks v4 facilitates graphical brick-based music composition, offering various Brick types such as Start, Rhythm, Note, Pitch, and Instrument Bricks. Each brick represents a specific functionality, enabling users, especially children, to visually create music programs. The Masonry module simplifies the process of selecting and arranging bricks to generate music sequences. + +2. **Key Features** + - Enhance the brick library with comprehensive functionalities and render the stack of bricks. + - Implement collision detection and enhance the user interface for a seamless user experience. + - Add text to bricks (SVGs) for customization and personalization. + - Introduce a palette feature, allowing for effortless music composition through intuitive drag-and-drop functionality. + - Integrate Music Blocks v4 with Masonry to streamline music program creation. + - Address bugs and make overall improvements to enhance the tool's performance and usability. + +3. **Main User Activities** + - Interacting with the bricks using the palette. + - Composing music using visual programming bricks/stack of bricks. + - Editing music sequences dynamically. + +4. **Subsystems** + - Palette Subsystem: Manages the palette interface within Music Blocks, providing a selection of bricks for users to drag and drop into the workspace. + - Workspace Subsystem: Controls the workspace area where users can arrange bricks and create music compositions. + - Brick Stack Subsystem: Handles the creation and management of stacks of bricks within the workspace, allowing users to combine bricks to form musical sequences. + - Collision Detection Subsystem: Implements collision detection functionality within the workspace, ensuring that bricks interact appropriately to prevent overlapping or conflicting arrangements. + +5. **Additional Functionality and Design** + - Implementation of a MusicBlocks guide button at the top of the interface for user convenience. + - Integration of a collision detection UI inspired by the Brickly game by Google, enhancing user experience and interaction feedback. + - Optimization of the palette by combining similar types of bricks, reducing clutter and improving usability. + - Enhancement of the search functionality to facilitate easier navigation and selection of bricks within the palette. + +6. **Purpose** + - The purpose of this document is to outline the design and architecture of Masonry framework for Music Blocks v4 + +7. **Scope** + - This document covers the technical details and design considerations of Music Blocks v4, including its features and subsystems. + +8. **Audience** + - The intended audience includes developers, contributors, and members involved in the development and maintenance of Music Blocks v4. + +9. **Definitions and Abbreviations** + - **Masonry:** The term used to describe the replication and enhancement of the functionality related to bricks from the palette, stack of bricks, and other related components of the project, aimed at improving their functionality and effectiveness. + +[Screencast from 13-05-24 12:15:30 PM IST.webm](https://github.com/Karan-Palan/musicblocks-v4/assets/143683619/ae9df412-8b3a-4930-8635-ad89da828ba9) + +10. **References** + - [Link to Music Blocks v3 project](https://github.com/sugarlabs/musicblocks) + - [Link to Masonry Framework](https://github.com/sugarlabs/musicblocks-v4/tree/develop/modules/code-builder) + +## Requirements, Wiki Storages and Docs +1. **Requirements** + - Functional requirements: Dynamic editing, text addition, UI enhancements, palette feature, integration with Music Blocks v4 project. + - Non-functional requirements: Performance, scalability, maintainability. + +2. **Wiki Storages** + - [Link to project documentation](https://github.com/sugarlabs/musicblocks/blob/master/guide/README.md) + +4. **Docs and Responsible Entities** + - Documentation maintained by project contributors. + - Responsible entities: Project maintainers, contributors. + +5. **Roles, Responsibilities, and Assumptions** + - Roles: Developers, contributors, project maintainers. + - Responsibilities: Implementing features, reviewing code, documenting changes. + - Assumptions: Basic understanding of React, JavaScript/TypeScript, and information about Music Blocks software. + +## Architecture and Requirements Diagram +To be added + +## Design Specification + +#### 1. Workspace: + - Canvas Area: + - Large central area for creating and manipulating musical compositions + - Resizable canvas to accommodate compositions of varying sizes + - Optional background grid or ruled lines for precise Brick placement + + - Grid System: + - Configurable grid spacing and subdivisions + - Snap-to-grid functionality for aligning Bricks to grid lines + - Visual indicators (e.g., dotted lines, highlights) for grid lines and snap points + + - Staff Rendering: + - Multiple staff lines for representing different instruments or voices + - Customizable staff parameters (number of lines, clef, key signature, time signature) + - Dynamic staff layout and spacing based on the composition's content + + - Brick Connections: + - Visual representation of connections between Bricks (e.g., lines, curves, bezier paths) + - Color-coding or highlighting for different connection types or data flows + - Animated transitions or visual cues when establishing or breaking connections + + - Visual Feedback: + - Error indicators (e.g., red outlines, warning icons) for invalid Brick placements or connections + - Compatibility indicators (e.g., green highlights) for valid Brick combinations + - Tooltips or popups for providing additional information or guidance + + - Navigation and Viewing: + - Panning and scrolling functionality for navigating large compositions + - Zoom controls for adjusting the workspace scale and level of detail + - Minimap or overview panel for a bird's-eye view of the entire composition + + - Workspace Customization: + - Options to hide or show grid lines, staff lines, or other visual aids + - Configurable workspace background color or theme + - Ability to save and load workspace layouts or configurati + +#### 2. Palette: + - Layout and Organization: + - Collapsible/expandable categories or sections for different Brick types + - Customizable order and arrangement of categories + - Visual separators or dividers between categories + + - Brick Previews: + - Thumbnail or icon previews for each Brick within a category + - Tooltips or pop-ups displaying Brick names and brief descriptions + - Color-coding or visual cues for distinguishing different Brick types + + - Search and Filtering: + - Search bar or input field for locating specific Bricks by name or keyword + - Filter options for narrowing down Bricks based on category, type, or properties + - Live search results or suggestions as the user types + + - Drag and Drop: + - Ability to drag and drop Bricks from the palette onto the workspace + - Visual indicators (e.g., ghost preview, outline) for valid drop locations + - Snap-to-grid or precise positioning when dropping Bricks + + - Brick Creation: + - Options for creating new Bricks or Brick instances directly from the palette + - Context menus or shortcuts for duplicating or cloning existing Bricks + - Visual feedback or animations when creating or instantiating new Bricks + + - Customization: + - User-defined categories or custom groupings for organizing Bricks + - Ability to rename, reorder, or hide/show specific categories + - Import/export functionality for sharing or backing up custom palette configurations + + - Palette Behavior: + - Dockable or floating palette panel for flexible positioning + - Resizable palette window or panel for adjusting its size + - Auto-hide or collapse functionality for maximizing workspace area + +#### 3. Bricks: + - Shape and Appearance: + - Distinct geometric shapes (rectangles, circles, hexagons) for different Brick categories + - Color schemes and palettes for visually differentiating Brick types + - Textured or patterned backgrounds for certain Brick categories (e.g., control structures) + + - Brick Labels and Icons: + - Clear and concise text labels describing the Brick's function + - Intuitive icons or symbols representing the Brick's purpose + - Customizable font styles, sizes, and colors for labels and icons + + - Input/Output Ports: + - Shaped ports or connectors for linking Bricks together + - Color-coding or visual cues for indicating compatible port types + - Tooltips or labels explaining the purpose and data type of each port + + - Brick Parameters: + - Editable fields within Bricks for adjusting parameters (e.g., note values, durations) + - Drop-down menus or selectors for choosing from predefined parameter options + - Visual indicators like sliders, knobs, or dials for continuous parameter adjustments + + - Resizing and Scaling: + - Resize handles (corners, edges) for adjusting Brick dimensions + - Proportional scaling or aspect ratio locking options + - Dynamic scaling of Brick contents (text, icons) during resizing + + - Rotation and Flipping: + - Rotation handles or controls for changing Brick orientation + - Flip or mirror functionality for reversing Brick placement + - Snap-to-angle or constrained rotation options (e.g., 90-degree increments) + + - Cloning and Duplication: + - Duplicate or clone functionality for creating copies of existing Bricks + - Visual previews or ghosted outlines for cloned Brick instances + - Options for shallow cloning (duplicating the Brick) or deep cloning (including nested Bricks) + + - Advanced Editing: + - Context menus or dedicated editors for advanced Brick customization + - Visual indicators or badges for displaying Brick metadata (e.g., unique IDs) + - Color-coding or visual cues for distinguishing different Brick states or modes + +#### 4. Brick Connections: + - Connection Styles: + - Various visual styles for rendering connections (straight lines, curves, bezier paths) + - Customizable line thickness, colors, and patterns for different connection types + - Animated transitions or visual effects when establishing or breaking connections + + - Connection Routing: + - Automatic routing algorithms for avoiding overlaps and minimizing crossed connections + - Manual routing options for overriding automatic layouts + - Visual guides or markers for assisting with precise connection routing + + - Connection Labels: + - Ability to add labels or annotations along connections + - Customizable label styles (font, color, background) for different connection types + - Positioning options for labels (centered, aligned to start/end) + + - Data Flow Visualization: + - Visual indicators or animations for showing data flow direction along connections + - Color-coding or highlighting for different data types or flows + - Tooltips or pop-ups for displaying data values or previews + + - Connection Validation: + - Visual feedback for valid and invalid connections (e.g., green/red highlights) + - Error messages or tooltips explaining incompatible connections + - Ability to temporarily disable validation for advanced use cases + + - Connection Editing: + - Options for rerouting, splitting, or merging connections + - Context menus or shortcuts for quickly editing connection properties + - Undo/redo functionality for connection editing operations + + - Connection Grouping: + - Ability to group multiple connections together for better organization + - Visual boundaries or outlines for defining connection groups + - Collapsible or expandable groups for managing complexity + +#### 5. Collision Detection and Snapping: + - Brick Bounding Boxes: + - Visual representations of Brick bounding boxes or hit areas + - Configurable padding or margins around Brick boundaries + - Color-coding or highlighting of bounding boxes for debugging or visualization + + - Proximity Detection: + - Visual indicators or highlights when Bricks are within a specified proximity + - Adjustable proximity thresholds or ranges for different snapping behaviors + - Tooltips or pop-ups displaying the current proximity distance + + - Snap-to-Grid: + - Visual guides or markers for grid lines and snap points + - Configurable grid spacing and subdivision settings + - Adjustable snapping strength or magnetic attraction to the grid + + - Snap-to-Brick: + - Alignment guides or visual cues for snapping Bricks to other Brick edges or centers + - Customizable snapping priorities (e.g., snap to centers first, then edges) + - Temporary visual previews of snapped positions before releasing the Brick + + - Snap-to-Connection: + - Visual indicators or highlights for compatible connection points between Bricks + - Automatic connection establishment when Bricks are snapped together + - Animations or visual effects during the snapping and connection process + + - Overlap Prevention: + - Visual feedback or error indicators for overlapping or invalid Brick placements + - Automatic repositioning or nudging of Bricks to avoid overlaps + - User-defined rules or constraints for allowing or preventing Brick overlaps + + - Snapping Customization: + - Options to enable or disable specific snapping behaviors (grid, Brick, connection) + - User-defined snapping preferences or profiles + - Import/export functionality for sharing custom snapping configurations + +#### 6. Brick Editing and Customization: + - Inline Editing: + - Editable text fields within Bricks for modifying labels, values, or parameters + - Visual indicators or highlights for active inline editing mode + - Validation and error feedback for invalid inputs or out-of-range values + + - Drop-down Menus: + - Drop-down lists or selectors within Bricks for choosing from predefined options + - Customizable visual styles (fonts, colors, icons) for drop-down menu items + - Tooltips or previews for displaying additional information about each option + + - Context Menus: + - Right-click or long-press context menus for accessing Brick-specific actions + - Hierarchical or nested menus for organizing related actions and options + - Keyboard shortcuts or mnemonics for quick access to frequently used actions + + - Dedicated Editors: + - Modal dialogs or dedicated panels for advanced Brick customization + - Visual editing interfaces (e.g., piano roll, rhythm editors) for specialized parameters + - Undo/redo functionality within dedicated editors for tracking changes + + - Undo/Redo Indicators: + - Visual indicators or badges for displaying the current undo/redo state + - Animations or visual effects when undoing or redoing Brick editing actions + - Tooltips or pop-ups showing a preview of the undo/redo operation + +#### 7. Musical Notation Rendering: + - Notation Styles: + - Traditional staff notation with notes, rests, and other musical symbols + - Alternative representations like piano roll, guitar tablature, or custom notations + - Customizable notation styles (fonts, colors, line spacing) for different instruments + + - Real-time Updates: + - Synchronized updates to the notation as Bricks are added, removed, or modified + - Smooth transitions or animations when updating the notation + - Visual indicators or highlights for recently changed or updated notation elements + + - Notation Switching: + - Options or controls for switching between different notation styles or views + - Visual previews or thumbnails of each notation style for easy identification + - Customizable keyboard shortcuts or hotkeys for quickly switching notations + + - Notation Overlays: + - Ability to overlay multiple notation styles or representations simultaneously + - Visual separators or dividers between different notation layers + - Customizable transparency or opacity settings for each notation layer + + - Playback Integration: + - Synchronized highlighting or animations within the notation during audio playback + - Visual indicators or markers for the current playback position + - Customizable playback cursors or beat markers for different notation styles + +#### 8. Audio Playback and Visualization: + - Playback Controls: + - Intuitive play, pause, stop, and seek buttons or controls + - Visual feedback for playback state (playing, paused, stopped) + - Seek bar or timeline for navigating through the composition + + - Audio Visualizations: + - Synchronized visualizations like piano roll, waveform, or custom graphical representations + - Configurable visualization styles (colors, themes, rendering modes) + - Visual indicators or animations synchronized with the audio playback + + - Instrument Selection: + - Visual representations (icons, thumbnails) for different instrument sounds + - Categorization or grouping of instruments (e.g., by family, genre) + - Tooltips or previews for auditioning instrument sounds + + - Playback Overlays: + - Ability to overlay multiple visualizations or instrument views simultaneously + - Visual separators or dividers between different overlay layers + - Customizable transparency or opacity settings for each overlay layer + +#### 9. User Interface and Interactions: + - Responsive Layout: + - Adaptive and responsive design for different screen sizes and resolutions + - Automatic layout adjustments and reflow for optimal viewing experience + - Optional full-screen or immersive mode for maximizing workspace area + + - Keyboard Shortcuts: + - Visual indicators or tooltips for available keyboard shortcuts and hotkeys + - Customizable keyboard shortcut mappings and assignments + - Conflict resolution or priority handling for overlapping shortcut combinations + + - Toolbars and Menus: + - Configurable toolbars and menus for quick access to frequently used features + - Customizable toolbar and menu layouts (docking, floating, auto-hide) + - Visual indicators or badges for displaying tool states or modes + + - Themes and Customization: + - Predefined color themes and visual styles for different preferences + - Customizable color schemes, font styles, and icon sets + - Import/export functionality for sharing custom theme configurations + + - Accessibility: + - High-contrast mode or themes for improved visibility + - Screen reader support and appropriate labeling for accessibility + - Adjustable font sizes and zoom levels for better readability + +--- diff --git a/modules/masonry/docs/PRD.md b/modules/masonry/docs/PRD.md new file mode 100644 index 00000000..d35c7609 --- /dev/null +++ b/modules/masonry/docs/PRD.md @@ -0,0 +1,147 @@ + +# Product Requirements Document (PRD): Masonry Framework + +## 1. Bricks + +### a. Brick Types + +#### 1. Data Bricks: These serve as inputs for other bricks and come in two types: hardcoded and editable. + - Hardcoded Data Brick: Fixed values that cannot be changed by the user. Examples include predefined note values, counts, etc. + + ![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) + + + +#### 2. Expression Bricks: Takes values as input, returns a value as output. + + ![alt text](./images/image-2.png) + +#### 3. Statement Bricks: These define actions to be taken. + + ![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) + +### b. Brick Appearance + - **Distinct Shapes**: Each brick type has a unique shape to differentiate its function visually. + - **Colors**: + 1. **Original Color**: Each brick has a unique color that represents its type. + 2. **Hover Color**: When a user hovers over a brick, it changes to a distinct color to indicate it is selectable. + 3. **Disconnected Color**: If a brick is not connected to the stack, it turns gray to indicate it is inactive. + 4. **Execution Color**: When a brick is executed, it changes to a darker shade of its original color to show that it has been activated. + - **Sprites**: Visual symbols that indicate specific functions or properties of the brick. Some bricks may have sprites (like the start brick), while others may not. + - **Labels**: + 1. **Functionality Labels**: Text labels that indicate the function of the brick. + 2. **Argument Labels**: Text labels that indicate the arguments or parameters that need to be provided for the brick's function. + - **Input/Output Ports**: Connectors that visually represent where bricks can attach to each other. + - **Editable Text Labels/Fields**: Users can input data directly into the bricks, such as note names, durations, and numerical values. + + **Side Note:** If we want to implement a design similar to Scratch in the future, we can consider the following approach for connecting blocks: + - In Scratch, blocks are connected horizontally in a row for sequential execution. Each block has a tab at the bottom and a notch at the top, allowing them to snap together in a linear sequence. This design makes it clear which blocks will execute in order. + +### c. Brick Interactions + - **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) + + + - 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) + - **Context Menus**: For more complex properties, a separate interface allows detailed configuration. + + ![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) + + + + +## 2. Stack of Bricks + +### a. Stack Validation: + - **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) + + + - **Disable Validation**: Temporarily turn off validation for complex or experimental setups. + + + **Note** - this is up for further discussion + +### b. Stack Editing: + - **Connection Editing**: Options for re-positioning, disconnecting, or connecting. + - **Quick Edit Shortcuts**: Context menus or keyboard shortcuts speed up editing. + +### c. Stack Grouping: + - **Collapsible Groups**: Groups can be collapsed or expanded to manage complexity. + + ![alt text](./images/image-9.png) + + +## 3. Palette: +### a. **Layout and Organization**: + - Collapsible/expandable categories or sections for different Brick types + - Visual separators or dividers between categories + - Customizable order and arrangement of categories + + + ![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) + + - Color-coding or visual cues for distinguishing different Brick types + +### c. **Search and Filtering**: + - Search bar or input field for locating specific Bricks by name or keyword + - Filter options for narrowing down Bricks based on category, type, or properties + - Live search results or suggestions as the user types + - Searchbar in Musicblocks as of now: + + ![alt text](./images//image-11.png) + + - Searchbar design to be implemented: + + ![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. + +### d. **Drag and Drop**: + - 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) + + - 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) + + + - **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. + - **Undo/Redo**: Users can revert or reapply changes to their stacks. + - **Removal/Deletion of Bricks** : Users can remove/delete bricks \ No newline at end of file diff --git a/modules/masonry/docs/images/image-1.png b/modules/masonry/docs/images/image-1.png new file mode 100644 index 0000000000000000000000000000000000000000..e732c6fa12402e5dca0f6076f2d6405a6b693b3e GIT binary patch literal 7399 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 literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-10.png b/modules/masonry/docs/images/image-10.png new file mode 100644 index 0000000000000000000000000000000000000000..adde8621ecebaf855c01b67d25123e185e99616f GIT binary patch literal 43593 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 literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-11.png b/modules/masonry/docs/images/image-11.png new file mode 100644 index 0000000000000000000000000000000000000000..ad96d427f55880172ff95c298e98f16f14626ae1 GIT binary patch literal 42991 zcma&O1z6Qv*FB07B7%aXNLnD>-3SOuH%Ll%cPJnrAP7h|h;&Iwr&7`&-QC@F=YGHM zyZ8R@bL%|E;{kqq?-g^+Ip!E+@mWqr0t~6)0^#dN4q|E!iq=LB&U$u+NXAyymWK59@9hi?t?W d?i#1mGbC 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�n84rzx)Qj!*VzrW&w}GehGv} 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 literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-14.png b/modules/masonry/docs/images/image-14.png new file mode 100644 index 0000000000000000000000000000000000000000..e1943ab43ab6c0c503f22d2c381913097d1eb722 GIT binary patch literal 37197 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 AhyVZp literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-17.png b/modules/masonry/docs/images/image-17.png new file mode 100644 index 0000000000000000000000000000000000000000..c2cf47dd8bc7c32a944648b1d4bf7c4200f9e18e GIT binary patch literal 131387 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

6G_uO)7MbTng@&Yv%xlVj{HaK2Im|)?C2& zb(-z|C(>!Vp+a(9jJ8VfdognD{t(};oBft4+r9>~6Ks$*1%_7ny=Lgg5bT5u%s!np zgAxBV6f2g~`qbB=eH@%lufLh#8;qQyPq>!A?>1zi4$e+E!bs&75q0HVMfH*Yss(rh zBuaaYr`z-|&SG;CSquYE(zvPeizm)L`?YSv=JzRJ>bK z`Fe*qF%r1IpLF*#@qy=f3gE3OJI>^1yy&Gso?23ca>qoY_NRLy&@Dq`eGVAS1>~zQ zhXQ-HY@d1Tpjli?wL@EqqMX!S3gT{8)KIyWlsU|y&b-~VwA5LBiczY67tcNft}|=s z%XrURrOoBXHc@lf32Oile;G44AiwM__8?<#23 z_klgb$SDBc*5yb}>|N1%$a~6DDiUn8MU?n3xmk{Q!zh0}eb$zEnYq}G`rdw-+Qlbq znQM%Gv5SZ82x0_LT`g5gaQNfvYw>mA1{HB}@$^(8OH}ry!vx~s2pzFfsV}@(5MZaH zj=KZLMlK;TSnCao`@|0e7kc$!`hp4zPy3nR<2(XMvLjxy6j9@voC`HieepQ#8nHCm zg{{tlD=aszKSVjjHXZ3gY&7;bDIK=#*AnwYF>E>8rG+ikXzOej0iz_5GY<5|`80cM zpT;4T%;kLR3~|#C^h5`bheA%v3*ROs+z}hJ{{*A=Q#D&;jcmjjNJsXtp{f`}>4_B7 zdfBt;1BY5xbs>i3udkMignJf?@c3gJ1{q67FxrohJP1ZA3Xr9I^<6lkmb+?t;tGh)w1AN(6~jdQ_UVx*mOZ7r7Vl9Oc>kn3`7m={YBl7+6`1 zRrg)mg)WOaQszRY=>uP@{Baf~Oj6SK{N9n<_r_E!Tq6|)+BlG{lp}$=B>w!M6uGpJ zM}b z=~6IL+CJmKEak37>!aMWb=#SNFpon8Smzn$!Lo}8xU9b}{39z}^_*~4Lzp%J=)Hhh zNP==uLl*+ju{k0S4QC!gRuxWfB8QN}aoGEEO}@3*Z3U~GsqL2=yREnVvNMEA#}ZW9 zS>$~8(o$+pIuG1ph{Nv8PSK<|Cciklk%TNPOY(G=yV$kxg}9F{=Xenh!ZB+D1=x0; zVmYDMyCC$oq`c7Upq*#9w8tsjKPZ0cz>?k57FTjXw22AsS>(0ekQd=N75lQhJTnx; z3Hf^Yr1X4fSBE_Mg$f5i852QWUC?|BSbL6vK54|zd%c5=mx^v;wbX~I*v|HBDI7-H zuH}0K156^WeyK3li-0v;$+uu@db(VaJK!5NT7^5VhY5YOG2Bxz`}mGWkrzurQ~7l}l5vRB77ZLR;;mFeEd%pmST%=FFyWOI6>!ueJ+6)3y~X1A`m_cGX2* zHYx0`NX(NcHrA*WY*1@@hW4M$D`s1>7jNv&o`N0Xhh&|>HtA@(lY)5U%TLT+rqQl$ zDsB6K+5YISlkM-)-srKv{!Zm=%Gn3f4fb#apWSYfpw3V=X)(;XK>JXYDT=)O`pVAU z-dg;~U@+wTur0Brv72hd@ZGWIb8W3ybajwwa_zgLg^Ap!kU=vG&#Na#i>$31ez%(i z$#Rf4Zd}Km)>~rQDqS~!X2w1nTwOvU^9l+I98&&XZWv~K-SPAWPSipn6g7-cg=}>O zl~c#|PAp86$qKU|z%U&qe3?iJn>I;0w)XnE$?F3>m?R)G z)h}L){|IVVan{q2SkVEvH5sZZ1TEKSXacb7NN^f=J=5mPO_7AHuWQ{>Gs$P;5N!@8#?P6!gDph=2 zZ>Yi;qq?6_=<*9^DbG0Q&OmbhFI5y9C4+#Sw!9=jRKOZPM?Atn((t1Q|0%4BqHrRZo{D%wHiB_c4&}%gr;53bcpSQ>?d}_5My(- zde{Veh6hz7U=n_g3TSc-=-p<;>}J*MW<2x*%h2fNLFQQ!kWu(GhM)DgQobzU<)qN{ z=CmdnOLWj01Tx9LPG2d}Nka!d&^stq36O~mwQ3vmT#R?b4KJNN=V9YhAANJOphfPt zGN}Js4BrrRPkhtur+ou%zOr^pqNq>kHq!h{q)CIa30l_jGxTM}Ny?Gw?4~#1u zT3SmWhZu(Ok+y*L?At6XD$$EO*+S?6!qd%Og;*olm)GIgk)x1S+=#wt?)YO2c)P0AjZ*@&BYTtc1U%8uq7uyJA{OBkWmDB~}C zZkCp!$irVh_I`p1KQVV(Gt=C7+w~trUXgP|DJ?g6UhJjJHm_>oS9+t!15kyyGg71R zCKX4u3x{5etXHV{g387)1Cjll%wq2CRsw7^0Zix&PuDcg3Z)en^lQ}dSe*^rcOhKt(-93M9scx`mK;t+p*1ynDBfCi&^{J3aFM;Mu z%A#&vk z;o=A@5g%DcT!+#v0t|sR}5*|cH9_0td^M&*^6&GhxH1~c;`C#_6{|b zv3wXFO={;{HF6zE2AX_IB8XpVFaOgO|(Mf5huD5Go|^qfo2 zngVMA@)zgN^4d;>jN=wele~rwaH>OTM`eZ?6L}YBW9k98Y$K0%v-gtpDcrViR@zqf z+269Avy-YfHf{(>`swKdxCl@EW9U$2=5lmES#oV{Eme+?r94+F*})BS`3GzC*7XVp ztlSU^5q_iVF9qjX?T<=&r<`>pS9BBbqm7Mev@>@0SIc{is=`orL~ zl@F*od-KmC{(v>@;JmzPUxn-tV&2XO1r!1PqR5piPt*mMKtF@v%m3gQ#+2rJmq7m-f3DaNj+n7HtdF!ae0ezz^R`>{8B>IRWeEV!!KEk0Ye& zl;xCmrGRDOT^>7n&X_Kg+T45iR}23}g@3gr zUl@Q$-Y&G@&OQS}B?bCIoDF}R7Iy=MUl}2&5m#lI@y^*wGhxq8_ZZv>{i~=k*^1+3 z6@{~f#q;Htss9&i`gcvD>FE#Mv_b(93oazHBjZfzQ%BpEh^j9>$X$?z9Xk4lXl!gT zzY#3a)KIZfIQY^`TiP0_D^7j`Um9wK{h+A-?MG1Pa)<+qO(nEv?(Z3cHH`4b6Cr{1 zUW)yi^2>em`hT2?k@TBEMl?f9>QJ`77sktV7d{)PltHO#DrdlLIKk$bBbHO&6G6IJ z)R7{VUcQ#KLk9(xnSGCvop>d5qkvN9|JN!>y7bO!z3JjlMRABWi!w#I^=+ovmJWF75P0C=JI9E9!jQ;*TLMU9Wf}S)Pp;Mb5p<1|#CGYu;Vqfb zYdL?5#wB09g4IAB`zJ;91+ZuD^IjLJSGrq|zr62C-mK~F5=SkGYydK|0vaF` zLOaMmNkz!0!Omz(hd634KoE86P|WSRPRbLPy&zfUEItX#)}ca#{quZZ@y`Rry80Lg z$Ps>_YPQtXn|1&+6lbd7d@Dm9dM~zT;z%{834_r>DJ5Aexg9H-6{r{2cx~i3m%d+W zZQwbD4S}01JYpnp#)ft|#qT>rkzC#~Z)!QcY8?C!$;a& zO^p5_-AoH7=j;&CrX=|xe@foJ8cqi)n;V@XC2+xpjst(8?w7BC3I5M`?MLwwZnbv>-<`K;mFInBCor- z#He_9#OZ~1k(9BIN>Z6l3Y#3Ebb@bVz%!nDhPek#oJ+Y!P8=yLhN^4YOngTaNcw2> zR!Vjg??uLvI7}+5RYo!h8$o%{i#g?JJ-wbY)-1ULUci?!jQDKPaDRrR*>5IN#ea8^ zy$Bp^0m^HBjlNeUCHI_Kt07v=KnJ|e!um!BfRU`n?UrwA$@M3WgMHU4wV1^Z-C6SP z;t~eu?L=A(u~XZaNggBRzHKZ=T59~*=EOxC>>1@aoqn8tGDbB{wD=3>KCoO$tN&by z+|td8B=)xhpik{VLXISK#D5(x6H9Q7xoJy0s0dNk@*~kB9UZS{YuGq0#Em}@KrSuv++bFh zio*^^K}Rn1aD_q&v32rOf(lE4FMRh;)MFF|JQPIzpyiShUN6LG$59)Eta7B=_a|HZ zX!q`E$;WTTe;&o}HI?w&BRqe=I}$mQ(YM?0?t)6;o;ldIXMd&W-n>C0A_%TC>($pS zkCU!ea1qmQ`SFU_Yj_)`xt}J*cQZL+#5`M=v~fQmK;XJgEN|?mNT?`3aRW)Gtw4gP zL8!3r$X*<0phpfzf*!PPJwxMa)j1jQ0Ej5TK)byjR ze`NB~F-`9reWD45fq`Q3?J9eJ6EUF9dXYmM=|+b<tXT^C?uth(Dl> zdE~H@-BuwQTiMmD7jz!2?xiZ9Ud_<%6pif*L`MW8MFr)CV92PffBALT7pU1UGy_r9 zb+?yIS5V1!Yb{E2sL+WW?v_c|KF&OEFxS}=r4%e2LQM(f#Qc!V{*mP}Z06C2_8Jm) zN(Twt#hfQEb`mX4o$kc29r>6GbNsyLkXm&xAhAq0(Z1ssN9*BZHPJt8cs zhXeg(Qm``m(5g&#^9HZL@+bfLomwqGf^0-!@h)|1+;L?rTi$+7uia5mEl)|0Yb^Dk zxSeBczp#_2Rbl)0n)RytTCKC>lhGN<8+>xegE=GSE?J?&@)onGHm{LZzQ4*-CU?8; zx?HBjz_8C)NtqB*$&BZGtp|r|+v1+wy{uGW7W6`kew|L^0H&G-I1~bTy?HFB*#Vs? zDI9dTQVFd=XwMpO1+3z*so_T>r$5)&FNKg}@>|OOupqokmA&$qybbN4|YF&FQ{#i7Atp_`?#_>*b>4DZxy)Ug+>t`2mK`KY< zksj!Y&PyeHj$YeZCtMp`-|4gS%9->R4A*FGHm4?KOI%62NSU>&UQb{MNIAz#UdSxJ z)MV|x(S)z_%EYF#9RZq=Gt)&ZO}<^_xT{>L{7PV(R3yF8*6BenOvQj1-_MHn;ttx) z#qO4iF$J8hV+of4p>epN+M;=%ZIjf7tHVxx)fR=lj=)M*(_LI_E_it-LU291m>Mh} zi#t-a>Du+O=)9++hSF0e(yF%*WrXaem8Lg5$i28awnv`5oT$~fH*ZMxChtwODwKmU zS1LXYYcY$7y?RfBEluvte9p$e4WFg`?9;U0u4!jyx~-PI*4GHo*TvLGO-8;568_Z) z?5}-{T^MS~agRhCuKk2<0k^5;dEqQHN|&D@pwi!VrzvwTlwRoQcU4P?3?b(StgNs} zKaTpuo#_j)`<H~cBfOY-Z1f`a2+|J zIDhHCFF|=Q(^8%3C&39rep@=6^pKMzUM)Kmi0sY$ZG!vwrN@&3C)MW=dX<={LMg=| z$OsY_XmDg+I;A4K8$vx*=P>hZBwIY#F#cy3nLf;Ly}cW_Oa{Nif9|tkbqyb22{fCs zolaSDcG_7&cLX$zH&7(Druog!U#}mFMj$7?gAJ0n=as!a(sVjzb(mbUCw206WT=*$ z>!$Y;2#$%e>YOqBvDAIR)tL2wqnd*5_h+znZyz~E%P`NY8O|&8sjd_jMuhz??U|&U zzh033Ykz)w0C=PAR{ovoMjN(DL-P!*zpg12aD2^RVzk5L5gA!dr{4yLw;Rf+Qwic; zr`N|*X%?~P#+@I>WGyOTV7vBBqx5R|K~yx%p;pGE>Nh9Ltw@8Vj9(3N{@On_R@EX5 zcCLMi-5pKbvaWc&>1Gn15y2N5o!3oP&Cg;%wICs4SxX;z=4bU{ZTpeCJLs%mAzMfTJ%rvy1#&31N~4k-Em}HSXrgN1VhjUezLo0CN@ET zxNcfYPDT>7C)&hDHK$)s^~MDkUqi0+M^abNkCpu3}DX^s%>F zwyDjDZ{EEbOcva)D61n%L}5O7p8H?glEqo61!3-6J-Yw$X(SzAikuJJs2> z9m=yaVrlss!kO}}Ez`g^BIG7=QkO`%B<{8T6O3!)j`y4W`emKZgtu4|iesg`J`7=tUBilSaD09-aCBd{bQYF-A1}^?$ z)xV8XLL^21aGQF#U(SeKp3Ymp2+dkLvf{bSIWu&;%o~zQd^Kar=CRqM-<;aa#St27 z$^zR{o~7_-Qc}Db`c~Qj|0m49z?bBUD*#lFp&vS5dR;&LR85x1#kB3b3N~iaV{})l z_SQ?v-Gyd`o%5zUVm&sv*tU?$VDo8gPqjaI$EpnD-0AoAHhthwpHlq+DkG>x#z_0R zq%)`+?Kt8i6oZ;~Qm#8&3$O}mV{o=0h>0rwB>JHdGUfcO(dBt4`3_!?;IJwk5yss4 zIkCA5B;Y}0Q&wG^$(<{m8ci=hh`26NKR#sh*d+RqE1HTobCILMnv*7)t6u7~@;&+8 zyHZChO&Y4ISDyGAh>^vST^)>k=g`Psm-N5M3rscUkP~>oVBg2hAP152d)#k>vShaB zWy`O&QoS@|P^SKpQpRW`uf_ds>rKZz{)}R)HQD-{c~#uK8tO)Phbml zzDaHs*qSk(FtxuP>3!~c0l{J&EDwWq8-nNW-E3HW=UoQQKlCG?pm#me-o>)bP1|oO z|2e7fA}tGxQSJMYU@qL|rgOzAv1iXWHE;>xhiAZngxAukAV=i<_p+s@d$#xp{x`g3l7(!WR%64ybryo2R$o4Pf4=`V zCbs*B`|@;pI0~BZgUspUA3n5Q1l>2j{rTPM7AY^XUSD{`a4wqrjA%$~dHNeSij?li zbuN@{;t!`AcEA7kr{ViBy8NdIqfLYas%yeBdZiuZ`_2U(y`CGp6qgHp>g2 zHr#PK(J-mc`=33nUt0-<5{HB*SNSjUO^W(+nK+{)0%t7?G}dIBj?e>#&VkUr>)Cl8 zC4HC|?a!I5sx$IB30oRw>OJ`nxaecR++=H{h~vgPE#xQut?O5|SIOyKj^J5e8YyzzH=8bdVlh8k2vsf+^SY!zO4y117V3OLG31m7xb z>9r@dGJE@WErdQ|h)3jis~B|OJJQ4b6(=6p_U~fZP5M*06nEpo%(!W2hi?R%=~c-8 zR|}DWC+{Z*)%S~Hp+=>DY;_xMz4_yI0fq8niw{2t1bUk07rP*L{#w4sI$`6F>enkG zp=5N6$Z~`4)0LKk6uyU>GqaYzj2W#*n_(Jn12hIbKo#UKpLVq)i5{S8OA-)WfBMl+DH8}W?y|? zvrh0`7Jw272m3Gt0dKxP+6d)*Fz+u^&88U-E{NZ1ChS|tUYfOxkiA<3`mYawe39w$ zOn7Xhp8vdu2wB$BHlanVlIqQNBzZ=vwP5@L_Xitj*C<{jwcqGm2{F#hG?ZWPUn!HN zG1*v383`)+(;S*GaWn(M`A~uI;q}MG%UGJio#nF|oXw^8_4C$t4#>m@`ivF_z8pu`nDJ+$Wm@+~Qr^(lM-iNU)<^YZIOyj)ctZn$WT)MgX1K_?Dy9wX8F z*=Y3+N&9I+*Zp5Ydl6lsV5_Ts!#BPl}SonWs8Fk-Xx%7adMhMa7&2C1$revzIiX5sakrx`^%;09R~e0wW$F;^sEf1!x$_le*g4p>QAPQ{DPNUo)k@~5>vzHk&lWO z3aF1-z0vozKEv3;U6#Lo6u85X-kgKk`)K>_x7hSfu3m+Z872Qis;$IhzQt2dCERU}kI#I&u>I%3 zn@Vqmx@reI#>uy{Yhd@Xm&3Esc7##1mgD!%qdV0pV>ur}zr241y4JaIUz@N6dt#(m z;5y8p)2l5bIe%(&6>+40DLS2BUJxfG!PEsYxf2A{8lgUy~(kk3=z(;O0KWde{uI z@5!y=J$4~(#|5r`z3EbmPdmBa19z2zSC9_eb&`6Yk7p1k%k2m`236@3L(`alSdO`+9yW?h`|5IV@;Lg;lmHhjya^I)J}4B z&q;a7Zd$b-i;&KHC`4IB$&SH6w10A&3o|(H?HttI$&-?Ymz4qbye{=&$?vd%_;;gU zM2Jo6tEqz#iJrL=U(5dF{PeClnY;>6vfZeOkg%}I`p<8sXhXp)CFJZ*RHaz-zam9; z_2Xnak8btG;&vlfDt~U~?ugh(-F!}eCfJZ8OgiS89pO~5ZC1zo3R(HL&`&q+Z&3ZX z`7AvhDQ5Ihr!n?vmiRj{-gkHJtVBfdnF~%BM)%&1;iHsXP1-$qK(K_Gf%Db&+DtMq z{Hx&Oo>cX`s19gH)D9MDrw?^k&B@=-IRL@eE@UU8(xz`>?YF9)L+QC@CpeA|MK*nM zRE=6v>&@0y~BZLFzU!9dsqnhMN zHpQFGRODw;QerIKT+T4Q6aS&NtU~nx=Ju=B`Fe48{W!lXb(F_ipICeSDp-AW1Z&^- zV>AkQ$`?<~m_le3%RC!Fprz1&LBytBiuBao zu?bp|Yq3DFYTv?Vc@?`ugMhnCsY&!5trv^^J@GM`KAcyJ{_}$u&q*A+GZUPdYP}X@ zAa(crz=}RRktL{`X8Bzm8y#wTp_4~Oxal=pkin$` zGH3~&FLu7(oZDev5N!sxaeV4ML;i7d3A1AU^|pHv|&d3)wo#G>Q#Z?x6!PCDKg0BIa)?bm!UOH&2{#!oN!7?Kn4Ff%Y(RQaGfl z;2o)GWpR`MandMT<`>aRBP+pLrn`Myr3~3*g^NbeCpXqhz_> z%-$Q;2O8m-69**x$=%Syu6Tw^%1^IU+3UNEP1u?(GOD&cx&b* z#vbGM1;V6fKYS1fz1`LtQ}srGc4^|mIu=7{dBgtU@nO?P%E_=sc7^-1Z0WWsEN-Ul zcJ$3Gnc5EyO@R1a7z6bl76oPNzhK=tOw2a$O24h4YZUCJ1xe6Yphe!M0VCX+_k$Upmn&QOmR%(G^Ba(dMw^m=I z;=~R-c#^lNK1%b{grPovQD$-c6uXWVxQkYlhhK81e-cQ@ZSl6h$L zd*0O~Xf&R~vpIj}gz1j(Q+q-Tz^!KC1(G?_9YQkteBXs-?I>GL43k)~o9m(i=gDff zh(x$?Z%_5TF7|R72g5wSy&l~vdic5AOBpfRaUX(xrOAl#;3lOt@9F7p zH^q^Q<>bBXN%}TS9@8M=m_dIBk;S(x4?ag&O_IYtrEe*8mA`R^oP;dbi4b_?#|g%_3|xjxHf}nRekT_Yo3y}2AA}={f73r=PSJ8+FdXKO z^4winR3&hYK3t?eaI!NbNw^t!`T5Y(Fnwkn-)F_Smh`3 z{o!Ht|IqaoU{Q5l`#6e%bcoU*4bt79($XN^Ez%+#gVNF=9g2iVcMmaA5+mIVLkyim z*Zhv(_kSOKzU%$ZHC~)?&ILQxS?gZ+y7%5idht@@YhKiIX9CXacN`pXk+(OX=`fRL zh~=lYCVS>TR#29gCJp9wLanZH1oVHVoW@gAeIICI z?!~Jji9@6R;1pW~EEz3HPIGyWrsY9(Ls#D-&y_>t>nA@#o;!+^E?_|eOuc%7oCWn{ zeBbAuHetmnOZe|bqIT(@4h~la>N00dghEZHjU2S6H@_p!olk`A2Yx=~rNH~qO?@Hf z1G{~3c_Im3v;#SrYq3i2lzp#bo3G$kkwC}AIKR~sH}#4MHPZSbL$Xs1;U6#uu`zac zCKC}_e(-3aGjfm*OaDsmVq| zYhojn4dpwF0gX4+)d&iO4Jzz+0*}-~W>rXvei&ze z`y;)oghKf^Ri&3t+z~e_O-Ly|`NzCZI+YPM+`Ko7;@3Y(5|$qPByK%gZj)6I0Of2v zfEhb=Ze>^Uk=~x*tv;HR7LppBs=X(|Mr3Ford>$Aj8i zB9ydg;EUwY_|*2IMW0!P%md#yx5)`J54^I_p`bfSi-&EXzT_J7PKw4o)pMA9+9|Np zQ}iqEHTJY)t`Jn=wG8dt^T>m6>&6qwMkg-Z?K>dF?^l;=!500@W_WY>=Td*42;-!B z`D0GBMu7={;2yF4i>p_*epdCKYP5d51oJ-p3^^Z9{MhY{&NQl1L1P<-n^xS+lN9QR zWx~QNZ8?Op%Z4KmSLs>VLrb!qU)<$!kC+jj8bJ)?2437WFKE20w97O?8~IWvZ6y$X zG}&-)d8Asmcy;m;E;B{3eBxUrFI2V&8~ zFnNvjwY+NS9prKWd?pRsa+o(%`Bj4+Ek-mf-P!Q*{QQ*AIc&JVf;B5L6I`)rW-pYpzfm+|G*Zt z9k(zsCAI1LQ#dRmaEfyk;cRsrg|e7qI1Qr}>6FZ-NVWRw570)oV*(P$KVKo7O?r`oO4zCK-n?Qus4(Q zi{q@0szq^BW?ht^W4YO|8iB9y(fJ+%F0kLrqp31_SCLJy=JYS8k&R+FI$Pb48r5bW}U zrA|08v*F=fP+&~Cw(Q;Ck;-AzXS$(vcBinijRer>;izcdsq{|T$20e%o7Wm3fX|Df zQehQyyME%U{Y=RxNzD%*+2)mw4wY3nc2g(F1~?Q)EsU(LrnpZ= zo`CrF()i#JXIIC2ru*bw?Wb0Ot^kg&OT?UXR!0hv+YIVG@*9HIlo^QI!-{$ zGB3+>c<0xLd)GtL1bSDCfhG0ZB}eef28u(=Kb9kFsDDbz&RRW3S@-fh{`~@k!V!BN zv1{IA1+@fNn112QjOJoUc!E*ow-M3b7DW6#o#)UK0lv_Rxw6BTOt&$+1Rv&#?T~ad zJQXdP#@?~fcu`kj;NK}4GfeW^hE7KgS=wLte2N_XSP0cLytAgmysRF`1vdOi*gnV{UDbXn~dLqvZYNajRSrnzIKKk&=vH=THBCf6x5>- z)BT*0J+HCn^N^34cmn9GTM6OX(ulp zH_ZVYs)6iXme;Cq06Eg}1)@ps9-(G(J)c`&qm>a$^$|aULWgOtU!_M2H;bpZmY6~P zI5jzDUoV>tWQ-J4bho--r{8>{v`Pa>Ycl?UB5zCk7jmE>kzRZtc#(oJ^w#oz?C8@` z$J?^_YWZh95q!3TSvu=!{lcc`&m2|8E9yOCZRezlawmd0`(+R|1=jO!++TYaf)+H5 zw;OlX*bPoS@QYW>LdGw$gm*DdolMn=Jn4)DPAdk}E^s|tAp8C;3z{odEc7v?wS_#- zM!!wyTVhty#mPG{nHb)oJnA4856ai9qk7D)s%ukQz0^x+dcnaH16S9bxj1W}`5Arq zuX5b#*&qdF@YJ@=wW`->K*xhZl`C;khe>`HxFy$74ZtV$^u76rea34sYErid^*^Rb z2|N}PH5-&}1s0*r;!QV)3yOHDJPWBt61BtA{v%b#NH>AnQ!ENJSVXi<5U-v>p@o7wze=Rtf zX*&>6!7#_)=y#8oCRmWFksrW|%PQ$;g3#(Y2%Nz)YeT{5wJ!vvSOEPaKojWG$S|=|MWqj^a zm~@V_4&P4#dtVbgR1oRUc^fnc6+h}=P*0RPfP>G()An z80ADb5U2ylhn7qRIqVJ@Pn7<;nK-!w%}CG^yQ5vEGl0Hy;*BFkrf)zuiP< z!;}T|D#YZ%uh{eQw1l84Eh1twq;B1Zs>0Uwmk);~i64WHuM!d6qDj^-&JfQ8d0!7c zD*=i((ZUpX*R2f{3Zbd{4LTan1tt*pqAluB!T+2e2aJeEjiHqitrynj3KyN1pVWer z9r9GzR%*`N_A*o_nsyoX-NGm_d}p28>esmfFBz^1*v&s1ScL3sewznPyP0=)eR*%k z4C_9uN1Rvu zF1em(KseJ`>wvb1aJq>^t_+yycpFc62Ob9%A=K%~am{%`tpqZvLOkz&XkBmo6XyDO z>6t`{cn_Sq&jef!YR_0a9FEChsx2ATm`sZ`a}M^|t|W z(@&eLh!g#I55Fg5c@7suOSrSztUX!&v z^l-w%!d!i3ecpR-qB%~RzIZXEM#ajytj+*6KZ;pVqV~krb#Uz9ll`F(1#ElmC}1vR z@33m6^E%?biv#IjEOGC>mapd#XJte@H_(aF=8EX1l0jTwp4PqaD>c!1LaA$iN8GXf z=1`{+X{+l`UzOB$KPD$WMfL`_hm@b2gDMIH^&Q^E2r`9B0CkveFg? zz%Wh`O8rP#rCYz{s}`O(yxHnw+;Df0L^8*_Y5OL8AeJ544~(}8Y{{G1?WA~m&L`9;l#5KCi=?j9aXyEtjABewagvY8&i}Q6q%~en|VC) zcVorhnL4Y1BgYpNXjUC!f@+_a&(cc3W6e|Lw<@&_4mbU#sk>JZyN;txoiQGZzf1w! z`&?M5NO<2)DSxW7D6YM0FN&|RFcr%MJ|%H!O_ZumE8nf)?qjDzq_aopo8`y5Y3FI( zd&PYe=;rq`a8a&lOfjyuM6n?dI`46xWcM~L=OOf~!!Ty+B+VASAU~ zt(KN|v$WKA_;Vm1J$-Ndownw9qe?v2sm9c{e#JK~&;(MMIhoP!KpUWE<}<0Vw}@X! zN=h#ewhaKrr2h833H7zn2odvJq$h@;%&Pv>bz!9)K~#=+qD{ChUzq#WIi-l7hCpuF zOiYWO@XJZZ{Bciw>M8#&t1C?RtK-`rx=t%G=}7(gb+JqDff?P&Bn8^$tTgJ}w!dyQoS;|XV-Xxs6zW57k0upgwBszlo64wX?*0=il+Y5G*$e%JZ z?9!{Ou3mYn4J}&J`z57MyTXJ<*>*vKN~3at>$723Ic_AW03Hnoh@?cJH;e%AWFq7) z>91bABvf$2QU>?0eYq-sJz*#txPP}g;P^t@!I^e9W?Oj`Cv$qY{%CBA4%)B zX5-gnROSiwQnzMnYI%#qai?tD^MFcuK=(9eswH2hg1 zx>BcgM#c})r{2Nqg*^|o<@BNp3x(gRPT+IZ>A20?Q-26_ifoAo9sJ6hV+ zVNvN~Wz0lKyx&r)l=2%FVRaMJP|kjB_e5_LWmD|3)^DuArnJy!dW(mA%!SCS5{9#K zF*%JZ{syaw<1xwk&WtRcCw_u%+6Goueg1S&9+}9d8*qB5X~Ur_H5$75PB4(ro?e@P zoAI3+IO%V33>_wZfoX#|_7jpEY?KXXxm0;HZLkV@b9;C_B3zi=$+IPR^7Cu1c!f1?&RaQ3aY=nGGuko;>dxKK@4w0QFSh6?G8)J?8){KP$-r9KYy= zH$PSp>QlS12OG+ydS0(r4>mz29ykbOzXt^E2+{(w*`W0*iYv%B&kDTdi zbU;-l7`7kaBJF@*3n8Xh+*p@*bl;e-Z)lqCUt$cZsM1OO!ufZ22DI&?jfIuGwMwFO z*)y49JFm3Dv$5yjo@Z3_x7=y@8j@8@c*JD!;)bW+GXL`RQ@bDiGx?1vI5|4Q}BhQK$193N@RmU>C~C$;;E<%`Es z>M)d`P7cqd$-Db9d3dXnVpZ?Yhb>Bd-MJ+BhgSv{VTVUI>K0hML^JEg&MHEam#-Xr z&Z|!cjWs&Xn*1W8BRbZ~eV$y?*(OC+R}(Yi#;twm{CD>TMk~OHo=Rn!k`}`K)3_# zbF0+8S{0M!U*((@Tho)1lY@qUN&^o?46v*GOZJ5w5smv{&3e3<(Z9aBdk4r+e0t>g zQ)_Z0tL}dV6Pr`~p`oE6p`kzogHO4ue)+H5{Df}Jzr+;or2%FJjMIF3zG*(Rt#ZQw zo~0)@kECvNHav68+>1C-~TuV@yH+wNJ+@u;DU}uH|a1tBA9!xDu-E3t_{jZ zddVa5+Vo#~3@3-CUCp0>s7quT9)rz4!b0~!YN2b}e|x3?*f0TRdp{E>6qMS8hJ{%Q zVY>YPNxWd%DG~Q{5rck_yYVW%y031~skg6l#DT{iaqY+Dso?goq{Ik;Jy=nW$KaJydShtC$V=@gD~ZTpDWco%&zFTK^Vl#3)h+Qq<%Igp5E#lTJProIV%5&Be>Q*pMWd zp^gT>(W+@k$dN*lGpl6uvOJ zVq58}2M=w-Cl<*(9YbQE=YmB*@(i@f9PrCzZtw{JCoFlHH2H}C{$Sm9LZ>Y4n+*gQ zq05;(Ja;9jwYSYQC`{n6>(B{`Z7*7{+I1P3l2Amm( zgWAVv&UGhP&-(N;E0yo&JCMVFjm6viXKsNx&KE4emyWTC0=xu!1?03cba3FK((dl* z!aKdrBR5yXmAPcqi2Lm28Pj^y#qaK_U%|7>?+L zF$F082IrxIcU>PtmfbB5tX$_O0*5lCPAx}!O;wy1@d18a#(7aKC9vvl5D>(0C8`L3 zbSTGn)wz8b4}Q`Pl!*I{VaJp50&#zD0ZnpmQtXjf!j9=liZ3 zK9a|c_%BL3xxarW^jpN1GD{h%wM(sBdG^Tu>#*%aHOQRu7x(!E{pf2zD)T1^i>TE^ zO5G+$i|^ZAmA}AXZuZ&2W~rBjHFXU%WcaulJTNc|jVHvM!Yk=X5sBjWlZ>o`cKl?dx4#^_lYhK7$LkeQx979reI2&Am0CC+=6fV*qKbH76TYtNDNa94`=mYpaAS zcea6SR%__k=)0mlXf1@D}{*!yTLnXY`xq+i-2I$BDDO!A`%} z^0U%jIyQ6?F5Z8!(n)OM0xoJ!P7I&~G+xljGU>ycONm8;V@c_KR`X~3_vG_qpKKT4 z0ue4xzOqmAnX1J<$ps*yW==ahEV7omk{}z32D_3Zxx6HpZrv1CwJ~qN)?Lth4}hQj zbNhACrYi^!@LB$)AHhDz#iC#SVXl(^vXemmrKu5mspxWgQljL$jp<0w-Q|d=sIMKG z!)KY)A|I7mx!4M-t3RfF({N-twu~PNo0v_~%cTu31DOfFmy3Pz?@>8t+a4lFI~m<> zy*+2la&9~wUe~Yl6*Si5~YPW_vEmp#mfr|sDchS|Mt>Ki;TLIpVTL)tq*J85yyY?f6t`?`SsOC}t zMF>IBSOcuB+mfEXkfCY;O3!r?nZlv)A5RVZ{Nd6xhfH@xE+k)HlWXo0qv>D3v^N80 zU-RYWs`mWA3WVA>h$~8>v|0-;O2HM4J-Q<&O1ad-=%l)WBIV`G$e_)H`9PS8F2^m} zZvvX&al+TIDyA3MHAP1&rOqOg?Q*3S1Z`qIRRv_gdvl^+8TcG~;&KRlOJb|;6q)!} zYh*L57rVOW{gB<^fP#q*Ugh7uL0&k|pOhuIeUrfrqF=GmD$Pll1sgmpHK3+0o6mQmioXBinCo zFw3w;R&+N_4Z}^Fsaat*Sk1=}UgZxa8Gk)A5ikU28nh%%wbV_rd=Bec+?^P(9j5gG zbqc{$K%#bYNvTMw@lw|pQW8KQt%uJ*L(sb|$m3#pe=pZ(+m!3 zVd*2hzX8^J9rw68z=d4tkmd+G8h2+Z8xX9Fzp+XXV*SP*>eU+Xc(@Dic*~OUX(^xt zvG`RIMPvuZ@N5mx?Vg2?ZD)I_`I6hCf7~|V1!QitbN0o9 znO8z%Q1NFYrNs46j<2tEvC!vkWM@B3SvH7M+!)H{+uSQ-GftEI1dQb7VijU*DeT?; z>(BluUni!&LCO~)gtKl3s=gbZVx(tVUp+C zi8ZL|g8{cS@8wozy43eHpQNYTj`DH!ItewNGQkxJvWB`qIWu%dJF?Q7qR!@>NnY2J zuH}(8e>*UH?ZoCE7SbAC+GIxmOFYLUHk$d6 z&|r8zqX+tvvuBWW_CUVFCAo?GS{HNkqcyx7YTR=Q2%8>{Lsh}Be1+g$TNBftrwZ7v zgHN3+$+MH}tW~A*V<=`^!4b8r?mWz#+=~h?SWr;n+p-NF^p>+doM&>kCEt!JZPb|_ zO$dTsu+Wbyz6|F9#IARsoUCpME$zgqbCd^7OpSx`8-x#EXodfpg~IWRo~vwAB;zkJQXoqHOwag^Gpi!>Pl*>(Df{N#Inta3nrcl*_QQB@h^Y^b^>(k zS^<=HiP5IDiIf4lrzzJ=t)RY^;%8TD@)!8$hi=m+w62fQf6=5# zc6Nni?qj?W3S%*Lf3zuF>R8E^C0dxVGi1wb9m?xvX|sS1^3Zjap~*%{(%Ev)P^#t= zIGHPN`A!eeog6B*CM=`@MR?U51=$ZQtg7&@26A=bEsL}2RiZ@7B>G!qdiN!+W}Igg z$jRf!uQ8Sely^BUL_hF26xl+V%8KrJ`ySHd$rw*JE7W<4{=uTe_W*_;fFjK74){s? zzJp#P2DrJg67#sXb;oqz-EQcl_Z(c zWGbS$S1i!+mDO}k!-pc+Z7gWGF&m3O0{@jjG4Hjqj7X?WZfhKXgwLqxiT$68YEN78 z!W}OOlBp2yE)Z{&GQD)PmYt20rU++3LDvl#>Qm#_clYDck!OdwoFl-2nZgb<_LNT} z0YTht?#3S*Pxv~QtOR0Osq&dd>Yj6zg7PMTD%z$@Rw)>&2CwI?#A^>C=g$TBdaz4* zrpuF+g$FxpCw7Ik;hUgx+n+68JmQ9$+BHw&+76{?8m)*M7JMatXB1cl@ZTadO(;#G zADUKfgrW z&#SBXHvjf^$uvmjaciw4MsPwNAM6yym5LKrWK(}vPZ#;<@nbF1#ST>Se_1*7TNTAb z9|Wkue>cg_I8fNsj(2)W@Lc7$9v#H~WIKai%75Lac~0IEP>1hcw1|}ZVLz;Ss+l&hegagdgItui3vdtzvklo*k|Z*xg<*3F06>|h z`N-6?&m$NDC}N+_NQu>78T>{7#{6DTk7OCg_L{re$!6CMuT#@!YgX6!IGDvjB2rm^ z0MNJBueH)f@4i7UX~Me74=cx+iC@J2VZrSbG4cRQ+h&C>XD~!cLGf{Bp08z#{l99z zsCNzM?~WBM{2b*5uU03$aJBP$pWq|<7=Z}Ud}U!ftgQZ95grq`KtJmH5A6`7ehok# z#$Lb3H_L7<1)nP0Iy$hDyfEr{%#nzp{QUfJUzfEMVw$U5N|{C!don}?hqI7LCAQN80AJ7`Xs32=V<|GfG%*XQb*sHVQ&?vtZh zJ@`A%!PR{ueZcB~c@!=NlP>?hJmzFXA@ozzbXRoT3w^P=yGB|I;;e;|>ki<-%vT1e zkSdmETbSXLkVjWjW9x%hgN^I>qrE0t>sCM(P}(46z4syR!hbD+{WIqA?r^fw)bDzZ zE@o8i2kv&*{8IZ^@YTCwH_q46e3LdyWS(UKNv0+l^)e^r^aLgtu{f?eF%z{qk)L|> zJzJ~}?}qtizzZ2@jM!cG`lIPBr%AfXbcvuRMWAT#tv$Mr;)?^&%FP$_W`Yw1s zEn(&6&M)m#@pe?``npVU<{!WP2S+8;cfN_SxtfJGz1}fXN>7nFb+VZz&h%t7?NMYA zy^xoeATqVH5@CV%RSz-KG*&jlv8bhAoHDt-WG-Op&T@5@55|MbRIphs-{WIedp){M zm{8BcYKM*fqd@ApYfg-jK8U8HuM>j zK?(Yio~7NMGp!U$=eO>tI4+#up(=D9y?uT_63tGECU(r`wQJNS1Yanu*F=&gm@OKh zFEd}IMo=w$m;{gkS6-sQ;pdUe2k?zK3}9WK}sW-G1`E5a5PqI_&fH~9X~9= zD~eB}M=u8D2VYsiknRqte_TGjlLo*Y8363VBG)?4MyH}yZnRBcY~=i1)MGEvrz#>( zaV5^(9xN2e@o#jxVn~vyo!O75kS(u5(X)YaRrO(vogJ?`b2705$8VMKj;F#y)9eVU zp%3)|$8=a$DH;IW+%17IcP-Ni-OYpG>fjS4(Sj@F zgPPZJt`7VZF==gTJAQ#ZvlorO7a{%gnoS#r7bS>Y3)s$Qsso%>;|V0LZ_bIOsqH;c z+xJQ)pV(S6LC{%X_wBdYZDj%s(TLbU%W9N0{yxa>eTzqw zZi#N$*UOUK29Me|yHjFD+uvGXhM&YL-z|uMvAgvoiAl?H@{GkgsUK0MV0ODM(sRLq`{W)XWtCe-v8n`%x%wl8&v)A zWfz|4`S^}?wCD#5>|mqFZc9pZICxK1sEQmzSKyhu6M6BCA?^5I;9X1P9nTr; z#AvU5yCFHb+-A5px8`*}pXu!u|6aCHcSiMPnY@vRBLTftvXI(I&nL{n_}ru zO{hyYQ65k4^6YxHf6e47IQO3T4jcb{#NsrtfK!~msHHYOtJd@;Jxtf}#{+?>6MKR`4XH*N z)}D(a0$YO;N9*Q{b8mWD23xPi!c-+b0$bJegbUXm%<6!-?ssLb8?JWn?D}hEb&X5= z6}xPnr>l0l$_vooZbw@rESSLx-}uEx-Y1Od%;2()NHE7?))Y%xm>WF5ZpnN$y&Ptz zd}q47Pg%fL)9}$Uf^<@Ij%sskamO=BLm7Q>a9(Ox<{x90_2hC#1oRB%!W1`~e-2HZ zl1nCAK;#eL3ba<;^jXbuxfL$>F79C0)HfUryht{J6#ghXnzroXaOxk)51|%YZA^nr z;PNr{FmC^sz#5j*dy+VzGCKa307C(8#5Q9MV+T>$8M{hgu6erE6;E`G#!V&&`f#9& zS9#7H1@udvjU$s_G~G+4#@iD4w8p}CSwiRaxR(VT)GobxXl9a+M&~sq?hy>X|Bm2< z?rNhYVOyw3B@1?aRuMUSR+(98jV{4QK<{*&PK$NPYmX}Wpn^`*5Jh zGyiVu8HSxWuj=`gpN{{z69cJAKOOtTaN2X4dHi4lq=Qd@g`}vxXQ0Q{v$tcrrK~th zo@8j=3(W0VInaYUTpx&{!WX|UWhOr6N=uZnD32oYai;PNwnMyf8$ZW=%TLvMq2?J`A zHdL)%Pglacr!`0ssbk2--R_fD!g7rp5w|MTNn!T~Z}VdH9*^@{yvDYpnvaVnp-g8J zdi<%@6}G+R1dgjxe85i8QC%NUfd}cREi#{;y%plcMK5I?QPek5{F4VfAcPTLCc6jr z3@WM4`&wN)E+tX~>$RJz1q@)TNsU<|=-_)$Gb`5xq_e4s^?HigZL&i}v!i>O_*u-l z5C-JkQ!)&1M4mT~v4{n>yD2C(@?p=r7Ga_ppOYsf_|?bVARcjlf%fYg@3+)MPuHQ# z>gxVKOtE#8;>;_k-MB{?FIxmFU{eGua6<0_?NZ}G`54yXwiG)LQx#{CfpQQ7HK{BeouGy zm-qK|j=G=HDnu*W^=CW|yn)u?LfsEbv@wq04KZlZPhFA7cG9E-%k`>(@Wab4-@w3m zG%%Yz93}M~Q8{8y#mhw8O{=Z>fnCs&H^ZK@_Z2-PRp&3 z8gj`#h+atmntxq$=*2+hg})9z)2GfMBrP!Km?S8C9A#f3hg$6+bH~fvy43 zGt{#-?k{wb!b%a!S2#Sa|8V<*3TM$)iRcD!*eaR zSd*@xvq$?Qp)-%CXeMr+kbMT@Yb`nFajNGDJaZ9cwOspmeOUg8%ny zH^=ZdZC<-HxN4Awnl@GD@zFeRp^)~Go%_P0iyKTG-u2!!np?M<3Ruq7lVf*WaB~#5wa`nmMo785BkI(p$(cX%08iL2di6P19D@XmS%dz8fp3G zp4S|(3-)DXvhIBYm8rtA2lwf{ z7v=)R&+ihw5e9=j$qA!&!>&C4JfVsW9ER1=+F@RBj(#<7TX3+EDbifD`uw2oDoyM{ zL7WD)abxUFu5yE%8*KVgJl1(oRuMYw^|M&wWJ)~UXKyp|jhU?H-38MyO7^*q%dAdZ zq~oL6^qcAZv`Ac!Fat3^p#k~qZt4cJ-hH)N@0(mREvGvpeBY1M)`q2xd-n_P`?v(& zmx&Y0P-7KO~*f+zEy|V_EvjdV|pmN4&2lb3?TCCZ|o1`F4kMOoO%T7 zYXhe&A3Of!|61kUfopE=h|I|2b#UKk@wg@5{J~^O_{W?t=@%x&nr)Fg;{C!#WZowZO z#~S(yR=sjxJzG-?@Nzg@d=*M7q}=)Z$mLw^%Y|!vbhv7c&vBqyI&XIIS$@rHr}gE} zMs^|ITX|@tCMT56E!*6Z_P_x1Ex#m~=$yqOJ~SNig^j~#-^J@zI$Jm`OF*1EK)2VyY`jX{VjF@#xSPTV z(w^;F9kHJtJfEDz-2c?OKNB6kJR1u!g;ZLki9;W+|G_(> z4cOr%8uM9myX$t`)oxodG+_(LKlSjenoywqe2WEQ=bIDmW{IgW0u(ntR6HCQe11Eh zxfXk87X+OJ7(CP42D+f+=WZ__5R|iCAKzt)wKbKxuqn}>;fq9XqYQ4|FwD7HU~lA> ze#Bul@LeC$5h3@W7Yz~ysamNVb!~EWx!Ea%WiZP#z96&nn%hgbk_vJt?ADtO)Waw) zKR@w(h=``epNuQKQ^rL{V}Z=x>lVNtO&0P}U%qwEZV`e&6>l?}Qp(QU zHxq6Q+I61Y^q&ny)2zY|**{hWr9K|7{w~oM@}&%Yje3Rz*X(G@1}zPryC*iqAALk0 zcWkd`{N-QF@61N>!#G>SBUGrn7)nJcrgKNmbI%VdV-l6Et(NxUa7?&PjK5L*H%3>X zlFqQ#y9q1e!sbE7$3lg2L_~V#DKi=mHoellrz0g?r-pvJsLL>Bv@J@CJAH!@+-R91 zfh1Sal%L`Q?B^x^bJ#X)#3TUvZ`Nl9pE)>+u9#5}mZ(`rv8D z4Kr8nP^PStxFtRWJG#6WpszRCdu@$pwZFkWXvUw;kMm^}xnCup^RjScSZkg!laJWh z2c6>j&^=f<8^>4+M;KhaVh1y#LEYCd#Gys~a+7RxoKmlgJ!3T(H@&G?`xBb zS+h1Q`jQuAd6T54Q`1&VKgt}&1aEwY{gB>sf;z>bp0Wu9fN2yeUIBsKw`&zIJCA^BD2NWAAMk@ zYXL-JXCf6!CnO%Mp5A$;F4c<~jI!{?aO(=iOmq;alT1yQ4;(hMmE_BP&);B3>Ok2S zNvg7RXh*wT81bGTg%&90{-j1I~a{Vnk zI(!KMlf1DHy2`ntJd-^3LbM)AJY~i z412q2FC~2DQd>S_T}}DSk#dB$@fP)_Na1>Q5~6H>K?hP zvXx2lFZjLS=Dy)UJ3js6!%QXEhl@=R_=g~{assCAvYNpl-jLW-Vk@<|Ji%noae0pC z#KxIup37l80*8%V#r$;faGH8aex|WGb6?h#Fsl2q`4gA@(SFW*S01YFPm}FKfSUB5 z*S)3maMYj^%B||PQ?KSA+e3yOex5!~uf?Qeux*Z?m^;k>eI_btc(6zuly9jg5#Sd8 z#lRvbuspa%ST28xm1I%Q8lOsOy87Wv_XqfbDi0MT$smZO%*?FekBg=kuPROg{SZve zh60`X=CbL1jc!+WuoHzU0E6i^+f=i7!kS#b9qce~ku{g%?5&Ctwd{>`NE0nnpe51f z65JIorcACf+LnjxYCHL!}{T332`v(WjPm$`C zPzx3}*wy1H>diU$x%Qd8Ex<^)??Sn^>TVIYUXQiaB!K9Xa&R1qr$Pk?N0oDP_ARy! zF&VA7h&DxmPCf}A2!;rz=?lDIBzZy+WA20<#`Ii8C6hXHAri8-xo!KWi`Jw%0Q=z% zJ15mvJI6|Aa~eBX_@jgz4c1m1ekaeYoK>p3f3X?#kyV?xFgBK)Az=qRXUXF9!DOdii34!(C`B-k zl#jDWN+CCH23wa=yeBzRO-{{mNi6cLgL~(!1DB7_ZL?z%DU$TSp1fBM!Q{PawtLzQ z@#*O!IN4E(c7VymM!p}a{UX>fYLa4MKE*Zm$5N_40cjr(uwvH@{z&*}i*}%Cn6#Ov0TX1b{-E2jSCz;m=sNQ?Ro#Z@!Wj7@hQ5yn{*$U%;tNM-DY zKvFJoi7pg4+I-owMM+6%)4TFbams&tPtuqw%QibNhw%C%`za-EpsC)MO{q<1!A#bL zKIuX>eCqA4f}t{)XC6^mZ%0Rd{~MnYu6*5J?X))`ETCC!OZ~9dWoEhARk2fTq#yNAefsz07s%Z2t6l0x95o={b&F`R5Ck#J!f&sX-C7>RzA1f@NvSAQ51D8e7*OWVZsE`wT!V9 z0M|X!p7%7&qsee;!YZT0uaDpV4sq^z?Tp3r&RGd85Eq>HT&P^c7Y*M?;>S+RL|NuH zU8ql+>4X;Ne}4mos)U8u7jREwS8pLws>M@Dz)LFW#ABk2R6<3gWlJqo>cYuk?J3#> zDt6vE;&=Ez{#ELZhzL5B-@}L-vwrtJJUr0wnN-Q05(T7a-Vjy1Q77J*`=ftt>=mK- zf{kSF&R9@57mX}UxBdcd*lq%IEXSMWtrg;yM|J=D%@0^f)FOZzf0(juM~1X`;=AS- zWFQHmT{jbEl(zo8ch>2o7twoF!tNiWlx8+9thrVlks z-H<}!la7DHM;);6pR&sTHt<3GDt{>V_1TM$4gt|*$y2sZS|uxbyCa_akW5`R9>8#t zX8xr(iRh!Dv;XpYe5&)R6TbM|v|R7}YP|*8u)62Np7bmIU;XaOVE}F}m2>EW4sV?z zFJ=q|4QrX-Q~xE12JYYSNhAh#J9S}lPW`HFB;U}x?FRQ0tu_2BUIG2h#{}+zvX?VM zGDlZ@_*&Tp*~`_QDg1FFzpwn5{rH$UU0#3rX8tU0{m^&5)D#vU6x&>0%{%z>B=7@K z$%JIZoV9Cg)O&;BkSWeGY%N1-#!-0_C93eDCjfERNGFMc-~Ut30BkzjK{Y_HEzvqk{JrkT(9%1D;ejf zoc=X?jH*D#0mJvd{XLc!=&Lrzd+8OO5pth#)-NdbRBX9D4pSSxx9IGXLLEN~h!D0g z9Iii9?&bJAOuGFC_xz95CNi@PxUv9Gko3UMK9%j6pHmoSIAaRyEWm!>8?!#(6#n42 zDN#4D8N|ZRhjs9TFtWZ~Yqr|l#vn*R`t|1?-H0LQ<61aZWOv>nvmq~!lcY3`n1N-& zgW3z--T8n&bO+Fbklo;u@Rf_lQmuh zsc-_qk(uO;G)cX<6X_?%c^)|yp|L}zsxGQ{Kzy6gYz5?yLf6Y%d zQfc;mo1Gd}*MRaQucd}*Lk@RI@ycMN4Dq~?(m-OW-EXS z!~~-$?}hL0+Rp#N9hDSvw7vSoz#Damc%b|;V9?04H`PHkZ|}B^*wlqMCPb;`d%93p zPd=Qh2XB~h$Ot!i-Wjo76kf~ym*}ana6q{Qze<_ z+v3}-QL7d;ETEGzNrauFr=)atMt`5bdQq^ z8!7+Yh`t;Lg>3`BopkQv-qzLX~XP z9n6o@O!Aq=p9x@$IIVz=(aM(8~7oMFuS*e;knLF=)! zjKSYN)SBSaxCYsB=YjnSW>tB0*yz#ItxW$A2BR0vu8c1OlH!2>nADkcojre!9pd+d z0!w>|b-g|p_vJ<_!622&`v9lWyOWBn9gTx8ouz7?Sh$NhVgO&rw!dc6?XvyXcDXZk zjFKc_=enc0W&w0y8&g8?t%G>}bla0gYoRTCOC=%5-;-LzmbQ{uX-{bt5t_IhWF0 zLZ9%U(B3kmA9aB^>0jo^KFSW#S1;N1}a+3V*1*t ztrRyVF)GyJpS7(hGySi3t4LYdD=atS-y6Ga#vL}AP)m6YN|F25=B3CJlVaOVQ=|z6 zx)$|#HtcU+*&P`uq0{*alL!IeM^SCM%rFvI22nZZw;m_=-_eIwnMqs9?_eV4YjgGb zedPW4+=SMPuW+9G z1c$*1?ry=|gIgd-a0~A4On{(+4el-jGr*m^|9`$izV+UF_u7kLWbNL&y1T0Dsi&$N zp&A>QgIi+_+b(-ehE29AWVu0E%%oU|bAl`3v!?sMAxBrjmLJjdGdgC01j~9oQ%iNp zv-^F!2aDHn|7}qSUn$OH!`Fop60T%RD8bCIzVjPU*7a%W%F+O4#|KW%m204P3bMq9tW!x+ z_hng&zR`GAF?c{UxWLr@4o9Z~;723$KHYrN%cwiac;8j1=WntkM6d@^l>1>;1 zuLK=GSqSf=dbch9`7g_^r^hP>ma@zcKF9(`A=e#w$B10hs0(6Lz0x|{V{AQfA?x~) zh%=DcKg!@Sm)zQ0?nK#QhKZm1row?9UU${Y7{DLeA$-lvZHVr)`datCHgE`V_SUUT zC`iyu?R<4(vIo6p zr6xx~@cxMwLxxF?j4}EJDA%AXYV~lnJCdwEN zK$m>|yC#r4D@zArqeY-O!$UDpHqLr^)oi1wUN-FlK#8z2kQa#>4aU|u(Dk{NvuUyW zO8`q+v)|RWWnzTQM6j1{JG=!vxu8*?NFVy6J_rWxipIm{P03y3>CCCg^T?Zy7X8gO zW%zbaOeHg^nI8Lf2kV++iM)QJYl)#Ryv`XNf$bqA*J!mno4i`e#MFMJD)E;|`AZj0 z_i99@_dR~5<0TAu&mTtQ?!|8oDf$hdSNOhnDKj7<`oOV8y4cv{SGtxv197_#<(TnfYcg4g<~h2bNcy~o(Ar;Wv>cKHBx&uz4)D;4O*3k&)- zf_C_%+IZL@$L^);O&C*Bft5}f!Ph^Jxu*@~bu0%E{sqkbOjYV7K6r&}eR{oN1hLq^zSopM-+kk;8Y9bDpK)Vsp}wV9@4@S6{IAwwm80_WUR=hlNOPP!Ipox& zE*y=6ecjvUr|<;2b)f@^7^b;;GEVd7P)vsaFbzFOmWI@H>5K#Euz`0s#NX{gv)|Lp z+}Pq@EZ*?+p+4wa9x4{m%Ln+@Ld>P%4d$;-KXrR;_5;z7QaPR_TYnb5%A@EiU3uq0 zP0CB>J7yS&p(N-8BK^wk>^psM4~+(|D|H~PuHOJ^AKHxt@2n}U4Hp*fJpvGEPm_Sm zuYXt`HQHs2DSlGjR*E~4T^W0iK6S9DKK<9Sxh0aN5-%pnug@v+)?v#bIBL=DCH1v% z*mr565zKRSr;qiKI0IQDtk@0+FHoO{2^^e|@sY+Hjw9A9bFHJBLZ(YG)_V|vJ4f`0ONTA3EE2LV7#X!r+bn-8L6&AxG!lIhZi?0skXO#Y zg&}#ACVD|1w+ZH;+29XDwYD345-for?+1=-*c4&Z{qzm#;*3PK<#O{erjaOr4z42U zd*uzoZ0(h2O@bx19L~K@?oY=)q+gQ+SFZ^s^XSO$>_zSrGEjq)dB1g0i1NBmHFeU~ z*{?GS`d+ndo&uf})SaASAI9p{JoOb8yodHb(LDn~jtRf^`qj}J ziWwF!Mj{1C8`>mkeP0<{9I~*xfpRHvMYP&B7h-OCFcP=IQj$otiTJD5+iF@s*K6Fq z-s;*ZIscN);HqJM+C>;oF{5)dja%sQ0MImUx5lP0DMdQGX^t1SHoOYkeAw#B*v5@& zB6d1c;-eY+Hl`3gW{o8v6p8%cNI}s=I>*^>e?_ZB#OS7(H7Z`{v{yoS1K)D!SLJ6) z#5>`}mRqXkU8rN@Q5a+fXo_i5iE<=oC`}OC+7J`Uy32=mR3W`m+HFr*=fNsUcF#tp z4|&^e)L82+h2-Z`6o72zdiG?K1ue)3w$dtKk56an`Z= zR`U36$W=rhhxqBdalINv^zM=i$rbFpfzPP^QB!kns|}Gc12QGZj-m9>%e6RC_6|W* zn5MrN*_77%sAzlU?97NhnVK8yB-mZ2>l2h^VLXK^a{c}I)A?BgdFIiKp$8wHiIFRQ zhp1Di+;3CDpN^X!q+&?t|8=Ae9NRTj#3sVX9x_h%J~7TE-Rr@ZpeAmoL*4jf_rh%} zKVa&!&8;epl}$)kosi?mMfL$K9Asl9(Lfl>^X?YGo~*7&bgOD3?#!$22SH;{pvR|H zXd5+yKij*xiCF0^HQdM z`eGfvzk1b=^$UtiAp;*vMdss5`(K|;>AtmG)y+A&yW7$xPjo7;b9!=VaG9OXd2x?w zWd&^h*6Mz&HEOmOHpL8gNpsT1RMGc5&i7R+gm^NP5y@3_>lH;;Heze+>tZ`P01Al{ z6eAOYU6#M%NA4(opPvP&u!stTwjq1k^9yv~wJsBaN2W!xZ>y5cYDL+-9MyULo`Y}k z(2n~tH0U;~o$pUP$;eCQ{WQ^b$=@6tQxeoJc$+CG1f5AmZjwCv8K*eNjsb_t+Kwj; z-tqz~28=&BtcKxD>aj7+zNcAeKK_9ysuomyspZ}AT0)hJtcSBq!|PFnA^7muV!&G- zODmM^O;f;~Z*39yf*<)J8V(27aT8^Ld#mOh_>iCcYH>JGFP}S*u;J%Q>=7)5^%~)n zX=0Q{x5KG2Ty3d5$gV}DK+nG~ObowpAfN70yKSxxDT@-I;c>AQs+y5Km|?jWN{fX- zgUkJa-u$IU<}J^^So0rbEoHLmFyHGie@+~Z;at3Ae3eTnw}SLnk3c7{CP2h#+gm%z zukTMyF^|4FV|hMyca}ixD_}&tR zD&Vv}1`iI}@z5I9FJy@`MT+mB`&QzMcemOfo*`7vlL=Rt$8y=jh(zg+a}*w;vVo84 zIKuDdnSg2|2``PB zu25uS^o3O+%ZS$;9VQ}4(MdsKub*Tp(l_lkk?Oj$%_=pw^MYi5fPkamidjodO%;D$ z+F%*3g(JK@&C^si;C^gwIyqQ(3eevCCswq=C=ne<~HehR@D4V=pOCPN9)4|f6Z!~U4J;zbS}4*m=F)gBvm+6QUM&I zPyaW(nRYOg`m?4w0p8!9Lb0Iz!n_))r(`Zmd&88BypU7Gyz-+0Piu@ZhZ?u{z`*13 zJ|<0-J!2o6xOameb{46882U^(_y+psy29_WAKzts3@t4lRW_3lL>{K;Bs&Td~|w=T&fefk1^rXje#C%X+mFAdki%yjxJ6}x}Gmge{& z&|^+D)A@nMEIv!4E~$Si=WAk;5nD;;)a>D33V}Vrv9M}tm*!>6g?qLPU%=F^{5$Ea zhFl(bQ#mi?llp^YQhojOZgD$}>mOSMvE{~kCNEsQj@#Aam+LErdO{Wq01c0d3sKcb z%YJy1nUO8mNw{+=1fM~R7mLrGe|vyGM}6d)**#5O8j-f*Y=qVgv&^Ce8SBE6tSqg2 z*rM{i-@O(OLh{j!krf(l&N}JypIkrLT#k#wElT8?3A82U zSplB}AtO4|q?#K>pZy4{$>ecrnbfUM&b!S;O2))6dUn)P*uQ)Z`pop9l$Z&jhl|ao zUYN%|MvI^~uh)pZ`IbMaUh9iRYATOcLx*k4_18zuhdFD&2i!ir9uTesP$AD6+m-}h z^RA-5zzS*doxDUnV&NC#^JvJY0F>L&k=ia0Nz{+oHsEk(LTq}P@#7G^F-`cr^IP&# zu_D0;x)2!1cJ|P5;Y}sBDv0!TK;YI7!jZI)v3e*4^`Tt}^@bhgE35$g$k3EzF|b4x zPkRah5>E?mC_R1yFM7t(#BBLvgkDB4A^AnN5ZL68YCs6ZKA1VL+pNnJ0&hHbo7P&= z8QHOKw&=wqBgI@?!u=H3F6BtZ4YU40XN-LP{qwu+XV>siv{G&Z-el#eYF>_Hrfta} zJ6ME`x%~W{WXNeWXUzkryfWv=l`AP^LcEA05yQCZKCWm+GuBZQYk6dOYM(wfEi%U+ zwBLB&viGI5%#AjM-;+yx{uFBTey) zBa4(>BoRA>=d3r>s<;7j@9L^U@Oxppiv&V+V-}s1W6W^!A>6yPNay=fRT~o|zV!f1aN4NT_hn{)KIF{4+0K;--_M?`ztdkFC{7Le;9o$%qU5=?GtE<$uhY%Z^zj?77!K~KP7rMY_ zyD}Oy#!opllmjGr*Khj*gLgI==bU%-CkRdj5YD!E#TSKwxmgNr{u`M5P7P zgt=P&i)a>x$1Xey&Sq+|4^2b^Zzs0!nA4D&m{h#iPp*{%3g7mYu|$jd=BSC?7qSQ^ zelAjYE=^e5BlG49KBnQTA?)Bbmc*h8rVpN373o|YNdQG4g2CAiSICvy+JETxCn84} z@_9ktm;Wnr_U$8I?)@D;(;LN6U9;YS>UC8CVPBUaf&0_S2e#|=V7-!BfHE3_5VM{Q zYi#0*xlPFSFC3$zksro)($7Wxn{89T1V6iVAuIei;g`bX=fNgsewQJ{P`zLy*#)B&o>c$oNnGlQ>`d zB`*5~c&5xw$}_jtw$1xu+}xi8TNOdL1KkYJcXBA|YTbpfvoEht@%vnHlasqvL;_^W zT*|qm!&=KO6t8FI=H%h{nyc6Bg1h_6AOkzc+{y1T4REFpcwKA?=Q+c>*Q$ zsAh6M8FNgoxa71A3$;=j?cu^8D6?D^I{tO9=*v%?gAp4Y5yIx@TOKtWf^x0P7qnN1 zVvOu@f@s`&p~Xy3@ilnB!tr5$lZj=C$KCI?gi2lG`8?x_f)m^DQtb#NS7`1CCLN`; zy@61B(k$Puxw$^!#z-tm6U<;d39+}JMn29OZhTGtmZW>pdyA3J4)$|K)`++z*hALGJ=#}r#~9_^-qgR?74R+)>D zd)@l&ETfHCTyqD*ilG1HzjCvP5gw)RPk6En>Ico>S{eNIAZ(ti;!~=zcD{)c-+>m zcc-93_nR2ettyt#ZmbOdF|P1F?T*-~t7m?1?mf*}L&5{sW-A4s>FZ#mz;Ksu$bEgR zVYkuJU5V%5$?Z;x7`uX{Wzvk+GX&Q~f)Qh8Xi2A0b=T9JKM%Ox*KI{;fe$6Y{jhOIxm`O!eAVMEvP_?uOK z-r**QU1SlRik8)cWf*`8)oX@vIzQU*G>jU&h z`Yy6bO`CIUbdu@Qajz5P`x|9U-YgFL&~t#x;uBjh2VqgK{M1ZmLH=DG-|Y3$X=XTa zdo+wAA~RN>``$yrqAW9yR6Ih-ko zWpG46Uw6yB9fKg_RF4(O3uot5h1KD_d924}j`s`-swAhno4k|#NZrV}gVYc@WxKkH z>>YLyU{3n@fnzBi?k;p?fLPWolevi^r=fTRhnty`t=dXXJMp+5)G5W=nf<8LnPr}* z%FC`%ogIz-;uRuz50RB8%ONNeRbAh{k8eaESf*YoGVBLda#+nF$}8y&;yyq!>)zXA z3WP2s6(?G=@w-lE4x*CqI zEUCEc6TSb8FHipTL2J^pY&yI)s6%JFsF2|vN%YE=7Cz~3PG8@pa?oWZnfi~di@RI zWcVzVRfsosP>F4>uDcSDo``5I_hNFM4aqh%2tIUAi`WWq=Xi{y|Ish$Fm^O(i!0>z znn50XKRfbNQx7M9p5i+tsHti8GX^|HFOg^S0Fh)fsxBEF2=j)M{@@&CuG{aaf)Ei- z4204|9q+#ez?t(4v;j?k?)&>4u~sjw z=7dVUJ-*eVyloG~pYNUV8Kj`d>iMA)>z^81uz!0RxFLZLP z1W*>Zlo%H>dtGW3yFSY9(h3W$-1WOp($#y;_;B||sZ}@=6cZvdWC<$*^xH}GLU#NK zhlHW8Y!?|v^HNq!Bu%4UBZdph%$V8EKYO*N!`SdpQ9br{C;7!{umKT4WvFOd%c&k$ z*ZjD7rx~Zk=kNrOXS{`&q%na4GmiE63}aNJ)#`%ZKtrpDF@Vp~&fOmCHx%6PFweoV zM1~#Nu)H;IiX2;e$WNX+<;n`$ZdFFNJ~ZhlwCIWGj=3VVL$$ToiE%l7Hc^oPSAlfuIW zHwXwJULFwh9>|#JtSetfSN%Es1~Yuezf~8k>O!yKxsVrPSR@&3H@5?FR*-c$ z+SHgC!_yfibnAM>!;gbZq z_H^;krcQfhE(^Swy*daJTdlPHyLgfwd-neoM3A?q#8^dtAC29=(I=YCRd!b`$J;CZ zOHD&aUc_4hcDrXultv<&I7{g}bM#&ul>MDyEibnq%d{6&ZI-la*V3zRcOJQu{X6(> z^8`ZAmivUsK!I7FoScHwhPBaN1=becYw){&=_~6kjy%cy6{!vT|Dpe{gJcloiE%_V z8kt>FkV~VPD?yx8z%lA$wW`LS!PS96bFNh*SGNl<;0*KB_oq@Z*)K#v^Mp~#`V?l9 zVZR|(6dCOv+zxK=b+*WHtW=@Oaiq%f3tK1O*r|=Q(nw8JvbA08Qmy)N;LiJO^>Z7) z{xjYJW_c3AO6AmjswpdD8-*X!PJ(LklmC$IBB`leSIA2#sdi-iX_7rl-Fen635^>Q&dyYkW30Q;<`yJhoH2)#?`<3shfxkakVKv}q(stxNwP zbOiiBMz%uN(uzZV!{>XK8@swdy|(?D7Xq$uTbn)hC9L2R@+GjBWfo$m;1IF_R@cGf ztk4Tc#9HWf7a8YT?v2~#$<|~&)U{dF!nR^}2i?8aZ?t^NKQi=XbYFvw2(*ec0_k@h zKhLW`&_i4He&M!1Vh)QP)r%P9Uv6zR{`-o<>yzIdi*3=It`BMyU8~Ad5u0|g$UBUP z;#2#wSS#(^eEr_^`*m2ZhBJmJPmvnl+&*zi=Hc*_8Q!}2zljCKKR_>U|67Jah26Hb zQ=#MR$UbDfBa&SnnaA8R6evNhoM}N8yB{S(6JU{^YPRM#XY5s1SJ${?tD>SJKwkC- z)cP-HUFhr|x}lyla$5TP+oy^AJLM_v2R%%_JmpVVU-Nk1Q)EM$zfAch2HwbitwZm~ z-AMgTOu)SLQ0ta6;qYm8WuU|DHp;WkRHuH!cBIXKjYw49sd^z z?{=P}bajgFFk`hDM|cgi4c3>LxmesTZudQ5Nhpu!qSm@Pu1zMG$?^g&b8ZiF)SBm< zZyE^(RvdJN*}T8M+$4y}T+SFwziv9;q^Y=D>Jp5yQE9Ia8f8dvfW4Q6@OXEsuUw4- z!z_$U@Hl8-0sulKa1mma;T78G`zcvo*EhYAZ{4pcIKwkF2ZH)5fb` zGtH5H!k%8E+t0kKdgXePr;SG3J%kq_+UM)0m-bT`W3iPLUjXf|KtzI`JGF;?_l`Cf zrQEJX$YogaoK;hyFMX>Fd~nfcc<&&08BQf0PUBZpC#5SA53o}62tT3vIswS~wOmA- z?$ypM1%=mb;s?rR-s3tY8*2i)0f&1|D^RSTzQ)#eAwjYyk3u5y3WJrax7+%I`AmIQ zKVoW2eSDMEcV4g;x|N5Wp>yooIYm_a7tD5)hSoV)AOWXH>EbT5_DE;yAX86^%m$i+ zGPTzWmbIDUZZWRb)XrR&uouXhv(BpBs54?n{%@zcTkIbIbV+*uLBRfU`v8zVn!(yO zMn>^_9X+rJD5KbRFGE-O>Z@UaxjJU$GW1E30#X}R&Ny+~L1T% zomC_u8|n80UsZ5>B6jc12JWH&ee~$^4PJiP#+cH`jcJZ`fL;42dT@&4@XdF3$NnA| zi^=L>Mkg)dRrjm;+&9)kTVKRE-B-JykVT7uWS-1g*0C_J6t>O?l}2#b&RM^X6__H2 zhH?<=!(DOf$tV02()h%<)9s34bFDPY3@dCBn&ZAj27ZWT{edgMZ1+{}$LAUJWEsLD zBhqeCp(of030JL5_5V!_|B($G-;r@M@#c3c@Hl~V9kwp!A7uHReZ6C{O;1ja6SJl& z)2@pM2nZmcfV#Q}U$;_p+0z%k0I9qBG5GOQNBes)mmM!Y&8-?TjU`kyyg2;HGAi+- zbTJ6Wy3=x3ANZPcUh0$h+I7?sT6jYyN6-E#_iH{;aQTOs zcp7WP`ZDBzV0dhKshJWZEwFXEK6c{)2y$ZDQ7ia)Yz#<67^d$9S z=n$@fI-|Ntf0AOohkT#~lw0ncXzq`A>zt?KqR@R$v!_4r=CoDVSUT3C-pPtR_BbGwlt*hjPNSA=Mx+JY2Z>AH&Gia z@K>zkN(?Ghy5mb_0yJ?kM&s>JmP=6X8uX?o=rQ=1oh9SGy_rbHgU%=?&UGtR#)|!s z!g1nrKG@##YQExVSk2@_s5yd$$R9zh%(o=cPS8#7Teno;R}YJ;O@=Nf-Q2g7R3>V+&K9t7zW zlf|Yo9^|3jrnqdmH>>n7QT;89c)Wb_eK0U0{rfC?ES-LEKBn~MlYCTeB&nUx(#z`B zAKS8j<{AB0%MS$5!ky!k&k0P0*NI#Erasa31Bp5mseEKd~2mI z2YB$V`3ofmOq@-$?5y;RDbY*0A53w;X4Ejgdn_$hX;x_-(v+;QE%Rf0xD&BwavCk=^PR@Ojc83)ySyU_j`#CnH* z8CG+Ogo1!a+hW33NWDpKF@`)TVHM-A8!_>lF7`s3ZFA*TSZNEaY!3R!_Clfa zs55B-9ayz4BYYV@E>B-EE=Yq<^~t-cEFr8U8J`Fs*!*%@< z`3G!E7S`u9*yO92rz)4KPkdFO`2O+elXxz3lHCoz0F7GnR~R`zGeMBsrmMikptun->HSJJwft!o2$z+j=xwIIP-oqWp8vZ zr&Udgit3=Z2Nzr=?VfLAh##Zwa4MtUOBK8duS3gB9yxhAspA;XZl^`<51q%82+oT~ zfd9(&_J}ND=?E(}@xXQJVoA_pQ0A|vF?leN>;2Zg_p-)`Q$Q#NbZDUCAxp|(*%G`@ zl3Kg0q>wm&P)$>m#D144PksN%*_AohnR}D13j8s``V2Hqpeu`0E~(W`V!( zSA5*;MdL2Ds6?``G`KHM(mkvO%r$-egb|=5n55Yb!*It z5-g_4M8L$HNm6S6oW(CM=%pQ+t27#slyr80OiLPFYs>I}TLHJOtGj39cJF$2>?ia7 zl9H0{O-Jx)?==ENM1kgiJ)uTS@UGt#fy?7)Jc1E6n!1UoMDDeW!=I)!J8j_6kdQ-> z6+YolRUt|QZZ;n-uD|R{Oow!*$m|Pw|Ex)v@Oi~&@X@hWnwdZ@^ysF3XH-+M2sfkL z>0VonsZZssa5?8gWd=L2tX+|F?HhZRx^wM`GJJpq^X{eAD9VQoQy(OWo|H0X zDMe=eZqpiiPypI!2m#o-@s(@~y0pSP15NEFUpUsZ*MuV=ar>2VHoLY^sl)dx`v0=s zgCg{=rwKHqSX-B4SfK}(NcN@|5#mzS=pj@=-QZLpueI&g*KPYLzYic%E2n~-(rlKZ zF0HvOD@g(IM1YshW0b-fzRL^V6^39;$h=Zw!okrmK1_X9S>#OoqOz9*W^Ofk?Yten zxnIABfOb<3DXoug(h>LDMs-PhkB>k{jo^umiFW?{)my&5q*}&KMSIaaj=lTpHpBp*kcnBh5WG$Mzy85kG5!&FcD3P z%d_7rj{OLqBJOuj7ss!d9}X^&PeQ3SvTkKEYvnK^r-w^!b=7?)-lb1rZyl9((-D*) z$npsn+r;38OLPL{(#!ob)zEis2R}HhVje6mSvP1~oFEqez^*M95i{-$TuF#n0$V$c z`lMA>CtFJk3r{i82rAU59zX)dT8sk?6VpRpn7Ys@;Lu~nsBv=f7qba*71n>%qeur^dB9hw?5XG`BpUfZ!qHcZ(hFb@JN8G zlEdcqn!@DKp_G39Qq8)`qDiybK<2=HqH&k{^`uycp$LbZr!#z0Ew{;ko^O@t1ijQkE|NwxHZMz!^a2v0(uQbTFkYXC3z zhg%n+Gju$+=T!>}vp6dR;|BcOimq%vMh`pyt6HKc26;1iLyppV_ol;X%-@<&qiSv3 zxZ=kkz=6U`ZT!(DU#$9U>Nz!a|5=L9m)@14orN`M*22| zJ=1*ITHcUrp_2UZiDsZzi^qMl7!ti5?Mtk_*MfgU_0KV%LEHL?Yx|ZzpUj=X^plHq z`H#HzF1a_YKF3oZ`Q&{9Q_Ar_ef=~Y@48y>7Uj5;m}$FPTqx===Vb%C9u~Tv0AuXN zudT-Dd9u{@SL39F;ETYTHG!iX;Gwv`7bDod@iGzAMKIUjhpfYI=q;r?&~_Xkk}u7Z zi=X#+&|TSN)%gBr2Ayb#$|CDZd}odx+ng?AU@=s1K+PB_wfI>O@7yVg2b->>{qFYS zgvWm8Nn&6~ZzUxx&?F^kBvxkN)f~Zf^|ciEW8BkS%uK#q8@aTBJq`MexR(sE(8k;^ zvFsiqF|VdiSx%E-NBO#${xv~SkIHnxld(dB4jC2`;N$0Y9VddTlW-=tuDzyycfY8S z#M@&gCPOWS7o}s_ReW9uO8MzI6l5z{U^2{|T{D#j&t<@R-;wix%_5f^CLu*US;MI- zH+;C@LTAqB=_q(w7!4gB8@T*^=MP0E?MK;(x#n+monOe4{f3>&BHCYmt&b+gaAz2- zPuQxi-)$bq@oZAqrr?}Z=$!pkXtj3uo87<;G-aJALnGh(J^X!}5#vk+s48t`$y;>x zVT-jDGTg#Gkj6t5Zt}gN&4LFP3vo~ZEg@$!Y8Q63 z4hCJG5|6w*b6niXPXz)R3^{@ACpFB+nRw!M(^?4ny!au|A z&+Gh1pE@27ypC3d==txnUswZskey1m^SQit`zf>DJxgvrQWp7}13mlq19s$E^7bj~ zUBRrU8QU{2V;F{d_cKthvyiZJo@yxgi;~u!uTKqh=6CPpD7^`wANTjm#KOI`6*U(F zxI^UKVb+aDY*mM5Nbr2x8WkhJWK%_j|3Mjsb$$IOjat>i)YpEIv9$cF8q!iZ$655< z-xhaH^)2kLhfX${?4hV}=RQj{l(_evmKPomX0I9#TPW6%r=+DTAJ(fUj_I#g?r&k< zmgloYc637SQWx&cB;@>@uZ&fm!tQ=1=NR+heX~=yW-LfalD^g?|0POMI^CU%9J>u_ zk~3n#b#E|Tb34R_cTx7d(?lUiBkSR9NH8J7Y5RWeS? zHv?ooG8vKGJdyrOmKN2N?hu0$q&(pDSRY%V(gg%lx>F|-9$*9C;oDDL_niWi0{wh2 zQ|?4hkiN@V9NR`ww6>$XeYG0n_FZz>3M*Ljp0L9GsY<53?!@>up+*<)KDcOo^(@e^ zzu_0r7sL$s54C+`h>zGTWUKLmOG~VVhUFhlp=D*xC00g&mjX-1eb(SQn5Qu5FKi6T zDFiLqsuEKDRCLzE!X}Vu^d0%m=jEHUdV=%E)Tj6(*7^^`Nc`*4ahE9tWoVfBgJzSB z*8CZvG3Je?j1(eQuPBm(P>?Zi<)I836lo(NDdgM2(08qoR%zZ^0JA&Lz)goB-t45C z`^EI9-;!cMLOp!jd+WrAsdc69;NzUy*6v8-RWLlK0`+3(Y1t6#*b%R>CTHE=sk3`8LO2HYJ z6UP2*&(j6&GsnWh4G-Lr( zaWjH1^PM#w(@||O?U+MMD}CR%Swb)3d6MqFPaBJlw0`3@CNsvd=Lco}u(#{b)p(BO zEcV#U^NOvrc7nGeKFMDCdP9e*vuB>0n)mhtG%EGpJsoCtxfZ`)B)t5HU$1R2P;QiX z^^211scYE)H{utX6J*0vg2wH@9fu4=(w4NRElW~ayz;=PWQy37kG(WRF$NA?$1-{y zm=%7s%^R1y#^2>AMNb%hyMrH=mwok17`2(O4y%M3r;u!=M~q?XQ^`*3u4xTbs51mx zleW>>8Q}0kes!<%-#q>5KEOelf|BN|f#cGW{lQV0Xyz9mr||l#el9LS`(E)i`u${s z6}jn9j1a~wBUHl&YetD!%h>-U#+hjFv}73!_S(uxM8?3E4L@m!II8E3SA1Qit66uf z^Vto>1mw2xaWBe^@B7Ea9)8h%ij@3Gi?W$#xTi}Nw(VXO4T@@RivAuI(HLUeT7~!3*+DY1mjQDUu zW@nRr+prV})MDQacdSmBi>^&Yc>8*)7@>8)INVvBLFw_5>Uc0bUQK3V3@3P>m^EQ^ zmW%LxVD^(#i-cE!WC~8Z;|FJ1aPn_NGPRk$;%H~=VXFWGr+UcTJnrg_;mO1YcSnM# zJxsa@+RP%1uxuxYL8F1nMIEZ7!Or#J5+NB%D7K|XRI+B&=aiGx#T|~xC#uNZ2?<-< z`p%TC)hHkKSLeVJ#;%O{O*-TtOD7dwd>sewN^`6(gD?f1VK^PNvR!X5s9LfdfD%Ma zw|PlNpfe&GwPG9QD#DAHCufG>PC8MU%oTEAT^w;pz9X}Ixy*)Rt*M6hkK%|YYFZ-S zgJ%V1!E?|DeG4ikVnJlavl}c%M|enqqYl(VHzO*^gos+R9bxEtbeHG)TQLvwsRHF; zIH5}4oX3(WfNo6(L=x!XPbBKk`rBBmJa@X}$#@bh{G;K8Ct-o0vQ6-|cQm=~V3pO4p|A|U`$as`{4na>jq zw0+YjXU`y@;)ynwZ36MVYdJ~L3u4$kk^Q`(B(ZmW^Cr7|X{Z~)Cw7m|+D6%<*U2`P z`DH`Vf=xHZ6y-rHr1*MtEkCiyp&XttFc5r8odj?%POUJH2pX$1Nc4l40{B-hr zc0$ZX&iLSKk9y;I?`P@L?|{x6#fW9}5jn8mh$~!Wu?_-*q}#&?v>tr5FFFF9z@w)p zBN`d8c5Y2K&htFu8437PR*qx%=BJQERvav8B2LdY)DcMi&Pxf=(e6EpQA@wo+umye zi1i4d$lLN^t`eemF6ZZD6*MBc+QYKAoVe-N@HP6YZkCS<{{tr&eN9OJ;2?{rWpSgI z1+UF8==;4fKj32Yz*P?vlE+50+rv)@<864!k2+*0W!;k7*X#U#qlFHZ-*Cu^@Xu0hzOqTz77mnVjO_0ul0bRP;ETse5%{~R z1=2>{7A=7We4A1PVuq-kxUpK+<}`ggW|hkgfbM6F>01V|&J?l5jV@!uv(>LWj+KyeNu@5-GaS95<8) z-&=OyJ6#mH*i&6+4~j(|zLP19oAn2uFC$yuR>F%^zIG1J{2hj1A$V6T8cm#Ivrag0 zEi(wAU@bScNy07t?qe0}M$Zj)Cim@#LT0f9$oW{!B;P_@eTYJ9H&4%1z%jVszMF{{ zu;#QBhx=`!&7!ANC7)??Z666qnufK3(@%Zpf7Aocyt1M#c73un(nmx1n56ONNtsn{ zFOO-}_gN4QIo(`L+Ui&!^RP8naG7C=Q0($Wm?A7;)L^tpy7f zaq`Pqhy8Rh-BUGG%&T?>GB-Pd(@#$KPwC7RV{G`h>Ko6(qpi`ljH`P)6qex5)TU|~ zDKC$3#d>&5@_kzwcC1^zrSS*RD>+NnmVtZ_(Ua3F!?R{Xg0OtSg$9P-w@dV5Z z3L>aiKmMj^koeQvtKrw&L*YwiKYjn~;c=kMW}-5?Q`DIMtaR+XqV0h~{(8t3w_qW@ z@wKC`7Z%V*FJ{D$&F~#M$wR&PchS)?)+80X!=C#KAZH|FU_;8ZQB^c2-9Y89n~ZH9 z)q~^U>Eu+G5%Cx%GjAOQKHV`TI+I?TMZox+SRHN7^YVI@f4mTAc;+HG#9P1q>ugOw zNaD?0NWs}3luDAPg{%Q2?rG-Qk`lFS(aN_$gIZ4;H=<`}x4B2%BTtexlUq$-XT70h zr#AT+I3V**V}H4VC$qm4y#b8=$?2+Vcdq=9HL{ZV(%~3nxPC)LP{o2W$xF2CHAqVlsD{p=id z5r)-9b<%<6bKf_P}~;7*lu_sfke;?j~5w3LzHfpz8ohJyYF z8vWyen*UIoi`FW4t#WlCfFecqh4f9{`I0j6kR-D}*y}Z!h_ZgdoXz_k{}ZS^_k8}ZQNCIBMLI+h-^;@5* z74sZfMG%vPRXR?bA*`s5<+Sy7@q#D%% zy^C(}aG2pTbkPbczb8FVbX#0|)&9Y=agSJihwg=nvSxG0fT5vUdsbj*q07JVp-BaZ zj{?{4>9tF495ke60W!Ei(dQ1Z7Fn=|iY@r`vazB!&pnDOOMCWhsPGm=)nRq>hmA|* zDk`cDO#=F{YRc}sQkQZ@Y8^|*9XMziu+4G~0*!0Ru-cweN3uGYiF^=l|K-uiAKCuj zBg<6hM%}wz%5%d+H8m%2#IUC%8eLN2$_k7EdG@-*^3@wg)~?MDRE)fpdd8o=rr@0L zPVlluj$V*jLx)(?KJtluQb6d_k#pb^-q^U>`Q;8BC{2ck0=kZiu1zfOd7=z_Li-&< zhxzN*T1u~{kYLF$3fe|lL+tXe3 zjxmxQ@8T7)Uj2ktnEYdRapK#?>d(sOYbx-UgV$HnjcfSfkMdC!Ki>XLp_SNs(d2%G zMK7thxJb^{WG??UHNJ7p4L;|d?64!p%0TO;g2#oiGTuM5dqBLS;k{g*eSGeL3dvA= zvE22|R~QA7adOiN$Az7)@!IW>yz8EPc-wUxOYS6)tHC2rj?SC8QoP$c#ju`;8fpo# z-z7M3B@yv+Z`f`oQzsoq(NK{4?iNz-@;`<&{-_|gBAJ|je(wbVPJC(;8IrJLO>uc? z-|m7_kBN^Sna_ER07LE3cRPK8f=@1ux<@e!@ye;!VeXogmOXmQT;Ac!EbFZdsnIc*M%tN0SJD1)D@Yo*`K65Ohg|@# zNWi8QI2`mcTRSh`vrI250B$h;&mq$t6z~+Dgcb0Hippl)aSjC$p*))q4XIjd+MtOs zV_NJDk@aj{xDPjL3*wBOf9{<>mF{ z3NQ7-Yaz;x!&$7sSbeXRD0lNeJduBo8i1^>G9(H6n;Y;7u+n1gjPXA`{hxm<8hY`9 zk29Xynp?xebczx50wK-+ZZ`TK?Y+RvE(xwAc;{(3Fd(ZG9rJesREG(vdG@lj`Hg}i ziV=bWe+rpAI(|knzy5xEw`%X~O&Uu5_*)smFbOIyF0R!}&r|5#^T7A;+C>^gv|pwz z`)nK5odq0PmT2hdjjL%232gx>gHYXbJkfOe-7xt5K7xyz**jL06cjMw#4Gr(*H7JL zOG|5F zY6=(H^7O6@vSzuu=f%!@xVSTT?Fuz2^&6LtDip0Mt9X~T(~Fj-glHA>n?o$8#)1q3 zi9~vPPDB`Ju2;lr>Vjq|pqb2I$^z{6{;G}~vGJ73lR1)=>ZYL&dzn*wJ|>m{%}yYC_NGO95%;@~ zE5GmA_cHQ~7wvsvXa8vK)NIR0bh+>NY^UWD2LC#S?^;DZAI1x_y9fP^rsx}8&;83qw%qu%*oTz) zXfqAbr7W6?cRshuRRurqX6+cFV;(U*65g4bn*I@ULc-*9u}o$`etuk1lBAZFmPXO! z=G7K_=>N=u-)U5SuC6mEdeL+Gl$4()?RFDz(kmQ$QYoqL`u`C29#BnnTh}l}LArF1 zrqYY_5+HyIN(U9C3nERV_Z~V(jes->AfjNQcL=?Aq?gb_fJi6w(DEI>`(B^>jsLyl zXOIy%43g}9*4}%qIp;2>06NVKV(B z{2$51>fd5wNMSl?vx!7rObW1!fcgFWITQwi73&medPD)A@{8{V`BglbuXA*7k6p6t zc5p9j&15LA8IqdvQy^Mv7LsiQ4_4g?h=?cTaUbuXeqNM$J=lWjRhbIhsfa;{=+(3f zh}@KRcqLIVw$!_mHuk~mv~tL@G~X75;ACg@2aiC#!@0JF5qo&_6FwELQP~N|A8uO% z_Tz`Z$B%NQTaEvPc%FpN*_$t&oPRGW;+B_(|I|yo);~0qUtL{oBI1uQn_pMljq!c! zue= z8*bHSb94zTgDwV~FCO5L`Cj^?1YQoDS4@fFf)>l~UR$y;e9CcGkYR7NOPt{fjW1k( z#l7Y^zdioBW7qkj!_lQLv9ye97Qdm0fgofXN=z_fX)p6=Sa!9?>BUW=QbVB;T_Qff z-PEs1SoM%Ao1v)*4*hTAYy!slL{CrI#)e1#XVsr^Ru~sq+1NbO(;J)k?oq$vk>h;~ zeni#=tqACpOD!?%-u6~nu#T`8)I*mtu=k1x-%{O=@x}skaIiEWzMr6!8B3|r^--^< z$Lx;H<$*TC32XaEUY5}1umre~u3Uk-+JUcC`q)rdaeT0id3gV|5sgA29)lmdbk;%S z3(WpJ6=v@DK0e&s(;bt?Uz77TV z7#rVC2#}JJ%5kT@^N9Z+tzEIszdN&hL1X~QSeL{*SOpY?eKYElYr7nOUI%cL6dF}T z;u8{i#NLhb0J6|+wr8uzSwS~rxiJdv{$V>lIo^}t%O^J%3{A_&Fpxlh*8^>X_bclS zF$-7Hy5_^Ugiw6{E4Ff{K>@iU2(v_TeoBRpYjqB_D#yT5jCb93(}dP(dkLr@2z{9) zZolwDKS&qK@^Na*5Dl@~iae;&{YS>sbH!)aI#trp`E$|XOPeicg5O?ADznmSGw{8!N z+U~4n9}yp*GpTst4)hf=a(o}3-?tGIdDw&IcJM}Ru^)YIOqzJhEi0P=ydrS(;c{6z zBgN+pFYu)UkBOkoWiWAjVOm|qtl0dOE=LZaf_s7NLF%R9P3ghkV(r24o!kQ%HF53v zT55({FYU7H$q2m{3C;%mq71I2S(+s>k?8DB{)l;$GS57x=D$x%K)}+aRUL>Sf(AbC ze?Jz~r9E{SjtS^Kz+I$IAeo{{t=vz)rn$~nW*fdMU28WuMayquGPe7BHjkDuKC>R$ zU#u9Q!-gtvwtDA$P_i(^(nOJ~OTTsNZ~xW;knTFhcYs18+AN3BRE!DSh}WaFTeMf$ z0hvPQRjC`P!zkn;F5b2|_NX&y9^(V{X^b{uuPy8Cw>2M{N6~bY!DvOc>xNA%^@mp1 z(faTGwtO!xp0F$`$|RR;%wof8S)#LfgQHQgpu_i=i;a3R(YQAcPUF^9-GARfWq_La za?1eK>4qY?H%CJKsrU}IUwba7+u9VOqL@82gJ02JSr`6~^TU;{zFlqnaL6<=fwkqA z2ic{B=}M8PnzVAj!LLEEp=_u!8%w(0#;c|A$EKk^ef#BfU?+_N z97S^f9XiT;tF3~N?)VZXi*qzo>sGUGYODyBxWv)!a!eOVvFnPWufZHF&b1#kUr8u6 zWANEeYp*HYG(Dwh_I0}Fh;`7j>Q}wMgkUABk+=TC%rzMNplpwte~Gi#VRRs#Qxaf> zpOLW7_=jgriqtce^!*mLZWBoU!fY(huEV<~9P8{Jn|%e3+w`j`Xr3=mRx7t<(R5@^ zj|j93gBdHSxP9=(sqx@hLiHdTQ(&t%qoHgn%GBZHjClBC@`^M4!&poA$zrEe&;{>F za|0~jEQ~pct>`%Y>YjtPLg=P2Yed;^g=|~{Dedis>94GWfiXC{x^dEqq5; z-gWNXeD-;}B}=Sk?d49lQcI+%*HrS zaJ%+p`Kp85SDEYjcuJa#A71Ik1co`s9469GcvQHf-f0i_7kKsEIg4Q|!y!T|aN4FU{BV}?Uj;Jt#HE2OHK`p-2 z142fac~ofjLcO#wRdvVo8WQh85U0Hc1tshI1Oyp zj_YkU&5&8k7gzp(atC@ARe!ATG*s^~Z%w^({hGR*^3O*W?K3%L%=Q`0M{1;JhAlOz z*p%yW>o4%HrJrN@sl)(5DgM4p)Pkd|Bd`empICbsVgA#mD0878P zDA36mGSE9#x5ImV+pOK+(J0s-XP{aql5xKlODm?G%%07Yz_f*G;Lq458x74g7qIk= zAZ$(y&;97~uy&hzv}wMp5xtU>SO}f`tBmkSxWRqU^h!rri89CU8ZD)KXvO5f%9Qt@ zb?4fRJbY1z5RB zW+gL}=FGzF+vVrZ+Dv(}sBY#jXQpA%Nv)>7+aR~WU7xL&r@f9cF2SCh&co9!YcBX< zh%zBRJMG}01_RZI8J2dEp?R2rra*~EQQi$OAlkSa#wC_h!Uq+z)2X@Quu z-SGA9<2iJZE0xffmWyx^Mbm__n&7Hxf_%EJlg8t4&mphS-!!9(`>iqzkvIpYb+PgA zKbz(2^uVwc>UMRbCfKOjdwQ~dX36Rk=!DhD-rcieY{Eo{n~jKvsNKWI6}qpD&e?`I zcA65Kao8HL$M7&y{T{cOXY>gtK`U}x50UP zOipmjD>sT8&KK!X+2#?}J-7Yj@iZw3-C})LqicLOO_VH$KaLiMirxpx1Qh9CX56Eb)*eW;eVMYK-?Z4(EucV18C%oDhk}6 zED7$^tu6+D-St))3X|yXk-u^fmgAevbpRdo z6bIy-XB*!jh7CN5k`8JPkPrKC6~?q=+$o_e+@jzqho<4mLL@L9o7fAM_n8PfPLdK~nTp>`5>84{EU|21zS+fu9F|V8JJokDnE= zwy&aftko{T**Ir_?d#8ar(hlrBLv|J2<=W!AF<vm0#IM3pkAo-6(Yl|Cs-9RpcZzr5s;zZ)<>}n} zx&oHImTbk~uo!Z)X+vnn`K3j27KD#H_5t5bE*gB`AJXr9+#mpHiJG?8?xi*Q?sDwz zb*_+sgd{TaoN5z3rwAIBp0cp}_)GI%UYSxxuc8>?HzGN&wIxocF_rNitP{Be84o^+ zvaaM$6=6b74W~V`<8KiiFPqJ{z)yak`ui_vyAG~);K_2OP9B;*3VB1A$nD98zT5{F z&msqB%F-74DwF~&w>z1G>SH;CcYUX?g9E0isE(JCa4hZIj%wZO9?J(fYH>VKM5W%b_^L6^xV;JxNT3!;I$@*Cyl{ zlOikyYLuj;j=|P70g4PG|qO%k;BOz2a4W1Ca_#UpY0>1nNL=JK2MVq$TZTG6ztA2{- zZtUnB|JMWV6@n65ysTxfI7E|N{R=Z30TglQrV00`+UvtN#0TbCooA4CW~)UEkC&L6 zDUZ8ZmS$i0XMLr>N8e&5HZQHvPK$_E*-!7|Qeq7k-aP!4ub5LM_@CzP8zr)LK9k>BP>V}8m%!`LIL zEKI~D47f2%@RWdxAK66{_|?z1uk6R9l{oHwN7e^9Tf2WNA#H)>pMHuWaj7R*T&mUZ`Hz%nHD|Libu!C!x34v3|m~# zOdvL#wtOI#>b}gqaN=vLeh9|@6EY4r!TJ~3eTc^5cD64@H+K(a(%ds7oQ>pFDa3HS z{-+01ItdrOOy#e)?vI1jZQr>jT8CARw7YP>Ue#Jm^3Ff3-ai{f5{zL$@VO@M^);x4GNyEP_HlWPOg!zx>O-IgP#Y7bJq#qO=M z2JB=URt}s&o|82euyv;+7T1DO7{xt%OtWjTid&R|>dMfyK1kO2l8gH|GzgBr=3 zilqW&a%S1R(qdf=(ZFV*|%Y$kl`9iv|TRzuk;@Oxj|XdnEOFOy!&GFYZj{ zLoe;v!4Q`yB8;$aN~RJ=%RK|=9oeS-MBa}7udYA`&BLwIFtJj%3G#Ql^$5%EX9Id& z@1$G@{hHa(Ao?>>PP}yl=nT0dh+0cFCEv}{E#3P0U&R8o=#w~^!pnrPE{e@BaWn;m zh2%iAU}IxrP;fWv(~lo9uSC_L>}y4cod0 zhesE?d`zY2#XFmmg`e||`U58leSaEXDkwO;F{`j-b9gTG{cJ;N?&9ISD0cJld!%jU z-Wrrn$h5ISu&=dJ0&5Dp`vay=x2HOFyKF^K=!xG(Z32<2T(^P{;xR zL4Z!!1wn-%@o)^%c=_dDNLJ7p1k6gHjw%725w8AjPG9U%1n zR#-T7U0L-0uEb+)Sy|cBOUT=|Z-Kle_4gk?-nxJ&$;zJZRwvFQ z6{o;<*<5AM=~9JhG5YQcR#ey-434Wek#j74TIONP6w^uBUz+4f$={ou!{Fs^(1oW> zuTX|nQtvF6c707{<$XK;^ZelQzPoMLe+1un7iw0r`Dhir`ojl!etz@$wWs(-*Ag2a zhCJ+_Och>F&38Q3;_0pR?4>zun-NV9nL zhm@3&g#{gNZ|`c8MDop@o&3hez>eVtR!UA^*rw;KdPy=sOtvM_=UYG9*ja0|1~-){@M0-ZwN`m!^+CaCr_W|T01eLZ(bb@e|moPMYwWPq|ES zze3FOnxh{*Sq`g_-aW^#zFSa}vE|sE-;@o4tmFtmF4Mt} ze$4H`{fb!E1lhAa{9W@8=vT%W@l!0XL2h%ziOXwhY}&I^1k5zVN!b3ZU~n{BMi;g?oh5)of}S&l-p zVW<<%+wbnvCjax7tkRY=`F8s?yk<+pxLpQ6T9T#%^Jc4|!tb^7gt(h>f%?ME4$*j| z|8Qzny8xCmF)>kDU0rTB#zPQ-2Wd7(?(rpReEq$(#l=Lv4B+U+#Y0}2oX@Je>&yx+ z^QK4u3QT%SN;PbV~^QYS%!uyYX3`HVI+0JYQ`|ac6GRzes6g zK5-IwgNf%cFVE#{83LAXygSTqx9TT|qHt0Y0g9gXVQ=cTVrY>CA`k4?O#@BOU{tq| z#Rj+S+SHSg<$0~^!H=r;#x-gk*nQkz1q#C4eaUF#kKTU*nW$h9cs zq7p%n8Ik73Qp1ePJjvdrt#{+@2nsn%oGU@91i$u{U@xvR;b#vk6SB|UFYggz9 zk9Prm;~s{H0y(@ib_(+gdpWwRk%&@Auu+%l^ELwxP2z?{dB&z=P-O(NqPzVC*=R*d zi6W(wFG!*Pv>>gedGagA)SWfy!D+1YsL-7eg7NQ_nW*GeVwGod^ zU)$!b3*r~nkN8U(F~YW4t^^}*;;1GaKIPYkE-YMo6cWmYre~!8H8LXg+w;PVI5Oqd z1<7AulA1ZVfAw==VO&xY4M5+Hy!lXEEKC!9?fZwTH4x48wii&%Ryd6e;B_O1BOcJaiR)emd4KNZ3%W2=oB)7GxQd2)v_! z01c;5>YQ+A&-rf0J3iS$939V~mbU$V$9!!LvZVb0w1dj3*%++|;Y|x3qcjI|2hO2G z4QXuR!zQ%lZSO4ZyZB|St9SaF*?Vy}REq^RT8Rk#)E#zOm{Z(C&1G4KjMbfRa23En z&?A-&>`4jkT|!BP_xNOXV+zL@c6aKMXa2=hhJWpm7{0l2Q}-TJ@T>)CNGyiMs7Uv8}lTxEZ<~rO*DHI z`~>t-EhvHa6}I}&!B$P=P8LdS_)7cuC(8Z7>-REgOn8@X^R-Hyg9gqIK#tNZy=ogc!~w`0DI#a0YC`HnF1Z_@a233F18iY%?We)D#LT@Sk_(?*dAs} z$~NlmUdc^ooN!3C6s+Yd&%Ghg$xg~HlTVL#6s?j}fY+7LI)V5b4-YnYP6x`~XC`N7 zT{OCn`QK8OJKb@%CNvG81D6rFZLQzO5)X%X@7)VMvGN|H)_G=@F0nM|c|rz&$&R**3};jeF3xVX#+!hF|MeC+HTT2!BW?l)q5@{d^J?%li> zLJWCLP3$F8ny#*5krrF&hHuCvP2B0qtA`&}36b@e15DHS)Rf-KmsyFg41s})-s8ix zW~JrZPF$UK9%6DDZpdU2dSK*k zgQSAQSug#1DR$5Ge9_wy8vB){4JIQZy0lGeF97uLBd7^DqP(~QJ7F*AL0Oap5fDY! z9lN>XMQ@-1iNPhp*9RPiQ}*$Fk)ED19I`Tz@j;8HY{sFze5dIxTf-~ScfiiHdGzCd z?H~B(A|R~3K}}AC@oQXJTU&MkdG%6s8S^=O7%FHyo1!5ux1QV{mrVRK3@Px=9 z6+Xi#&j+U)mj3L!@(f$*yHyA@ugLbrS*q%B!y?>dlmm}!chUC(D@Ay6bl7*;y;B^- zcZm)83TF>;77Rd^_-EsmXAf0_jvmzR=&qNT|Csl^pmNSvIy0F8oucMmCLp@)s~ll6 z&U@~~^%thVV@@F<$8SGCN5S`M$$L&XQPQYPDtauX5r>CxsJ1w__+m^v3}j=wkPrX& zc0410I^tN>0*-o2Y^*DY6~s!p<#jGx5z!sfWYqTkxgXR3Fc1?HlgGtHI5su?X*Qk7 zN?D`w>R8JHs=>(LLB_0B_FOqaHf`39yy+?E!~9gDDzR2EDrJ!g8FM z!GEsGNOM5HDWmLD7}0il6jYcY9-z0^6`Y_}Eze{^{%QW(ianKs<#{H%_-hk?mP@>+jwL{1A5yK1|838RC+Y8xUu#Xk0#IQ$g*ey*#O!2?~I9KI%S|EqsfUAxPlW znv_<-qJFX!lGUrP#@TLNGX2fnP1L&Kt!g(nslhj$RmFbMIaD}tj19O(fIsKtJ?VFo zIuTj$#PD%kX(P;_M#a}(lULD%Ho5<$j~gqiKJs?9sJHBtP0dq8dW+;eeTQh;J89vK zbpARzsr7%0EF>lh&#_q_#l+JwriuDKJFd>L-~3@YTWM$XosBf&TS-YleZ6t(9t21m zaRF&b-r{D50y&myU!To5k>SDT0r^nJpLBkoJ#4_VgYj)It}&k^hi803oH1jocS52* zS&xh|b&G48O{a&>AG1o66OzkFXA(yBUk_FwyZk%RJ-v)sG!XmjshAu?VbRNs4|3VmwBGvzkLP}YyS7|B!K+s!2|r_ z?I4-7#0Mz##{>~=;&+)NLnKsppZ%@ekT^hc9bO@)?DGZCo`3rKl^fw0XINBJDPsk`k2&iu5-td={XuMvb$vn)|`IMvVs?*VeXn{W5b+*}vT zKI~-@B^1xgZ1(}O!}H#@;MaWSwzSnd`V}s|UT+)tzh&w`h{cTmd4$iT#)(@=DW|-= z{3-py_K;JJp1%HL2t@JE^;_{a@UO}VUCD7O#)^J2$$j7ex2E0_Mk(4Fv?Y`O+FImb zh&yN+-${h|2ly-QyM!5kYKQX#un9 z1@_U+-KSsKH;}_Q-CI9%Qh%PF zY5gJ~qkysMDi)NdU!9e;sE^|0ebfBJVZVaO5d<-eZKgq#`~D74%JJfA0=2eLv>~6G1gvJ@!7QY6{}N${?R{P z6E*W&;C|Mc3Iq49e7^5JKOf(1cIepbtOn2&wi>}aCYf!;rFV9E2kXujfZKN+xc9b8 zi*@d7Jz>F1IE!s{pEj26Kf7;`hXEF7Ys=f&**W86-9yjFI5sn*{^#BaTBZWi?V)j- zYP3c~0GVEXo2!ju<7&r>Ws04OabS4Z#rB^Q)$N-aPcm2XZ0g>9pc4TQOL)N*5Jlv& z0CaHs=50DsYj}#7CSbL45pB$SgSsDFkcCVg@KPcB<{iuYB+zF>?REg8?GUs7X5XK> z5AHr~YX8;({A=flqsOGH&-byXDlE2^qvgMu%qW9xDE&Elt&)IQo-8pRK0DeZAqtak zTjJJCePUoBv!xKPpKmuhGZVeI3yh|{Yxe{gTC^P{ZklZqm?gu#RljeK&N{HP4HX$SqmWnmM}prK;vF@w(VfY5*oC~g?d za%Ple6RK7c(!Jf%^4Yfi=iI@$fg!b<#Ck2%^|FAnV48G)Er(;RRpyp@iWUkM!HB`A zJH?ULysklDumQj^w|}5IyYZEO;c|O>uC7nDh44Gqinejf3xli{x{}_$uz<^=J%&_= z{nA%ncYcb4Q(rN4)ABg(UWF}!52aa9*a6UyX)&(j`MzGeMC2LE3`(8o^Ak{5F<7=G zg_rovZ?zUP8*+J8X^n%U@xS#udU83dR_S+qtAaP1j`(?24OJ!;J5L}dx5k=e1rbFQ zeC!g~^OuM>_FJ6>OG_QPbb6A)S;jRoT}Br^EP@Q)qqTSXd~-@z%U{(xGq`|QySBX~ z+}E@K{MW1`t-fAvvd~D`&W@j!N9%Tm*0M|7ab{OklPf`|4K1#AH^+fBh}yiaG@2N4 zB*UI9oAUFuuKVyZo$Z1T{q+)X2M32wa-NeygsZaX7eG8Y^2Q@P(nofnai78I<0hV9 z+eg(MRIw7H`}u?f$N@UF*dggSeS9EWE@$s+<4SU1!${>)^kBy_q%7zAMrj;x%Z6EN z*h$l)zy>X`HKHf zD3aJf`_*O6RTOUh6y&`inR(2+yX>7USbG%L7B>)wP`G)uV$iiqbGCM!H7;`tiR5t3 zEh9x{DLuwZM$Z8OSW!>!Zeql(f^r70= z?}!}L%pjt)fY}Ef8Ly9&y$^;$SwQlq-hfF^&?XNRnef&A-VCsGB7@?PMhoj|@7;7) zXs2NPq05cU3>cpPwX`$s;tTo3(<7Sd2-@j_;p;6M(=9)2WGY0IVlpI5GGul<&5RH& zXFWX269w*Pu-+AJ9?Y*2nP)5t8Lo91Ip}pS`1;01->Ij>(4IJIPA}s$%NzU2TOhl6 zZcv`gX=OiK^%NQNFs8=A@}i*RmDA;7-EQaO&m?>bn1EvWid){@0_+XDk0u|tJO!sk z80cE|>+Oy_*<8Mw>dRzWBsXZOnH7*)Z zma1= zM?jnIpH|wRmh74if5mG0?gw)4X8Ci`kLlPTNgg4>%FI%guE+zQ6^+g_hr% zpGsw`wXVB z)So|5R`f^Qt)8JUbwZaW!mfmPOAaM54U4t=84Jb86VhaY= z5_c5_GUJm=k+-|+PMF$7TRy*IPHwx{Jd&#yq(VEKJkIv9C(K%<&49Hwd!cI`54*f5 zLeGMnDSp{Fdn~q>&oNxsrQdHtlfS5HW9p0UKzd8do_=F%S)XY=e@&u-0Zy%hvB5 zxc+s(v^1D=2gk45Fg55aKcw;O1lsN6KI%IsH-BB9GJ8&A=yWRumTDWEayL5|mOG55 zOusj!DNJ3@$z%Am-oHhrSG9QXIt8_#kjtUUyIW@afy(f$-EY4TUDYmky6Fys+PjZ$ z(v{ZDe_-<@kTF-pmw&Hu_}Z8Pd>BW8I4&5DIr)`%_@uPN7zkJ^t8v%dmgc&L^R`^Y zwnJG?JDI7M6NIzRubfXmeYD+0WG&aa$23&73B$c(q8P1f{v?d7WlzHMwT$M1 z18;=-??EMZgt>HC$r~_>1Z#ZDHJc9|hM2x*3xNj|3l96DfqvKZ3Z|B(_Z5dlOa?1T zoNgOQMB8Ps{<ih9uN~4KoMcTX!!zqz0t(?FzV#snE{EO z;71?Z7j&`Ls-W}TyNgigoLt8;R1wSLV15+B=-7;rfv0G<@a}Vo?3Sp3r%{gJPQ|5S zlcsK}tGbAL{bs16HM|O21_^7X?k7QcHeixZ8Eyag;Ns+9RakqK39ic-w^_i&<|SmJ zsA}eSr+f8ie+3VX=u24rLCd~+vWVm6XMG-c_)v$E2?R^#PpA}geMp%w_crG4kydtU zTG?ed{#q9ECky2d$B|}c{-5K4-Q&5Im-}ka4!J2xEO{#X4dJJ6ccXl5iNvQL%#MH8 zvvYO^a%3uO25$)n2&7BcQsVJu``mq>&D;Qpyzu}}O|L*_(1)YFlP|r0BIoVu0vs}= z1k_h%{UB2N-riPr=7RD*tR@GN(xpaEgQ}je>rmU+%-K>b;K=rdkBKZNwZB}+usz7Ag6{p^#cACY%@Qm&x<7MM zd!41Y(OC&*ws1Ly!^C&r&ZykemJKl}PEVL(@?mIt>cWNdnzY%eLotHiOMW};;Wm8& zi$x{r8C}8`_p^9~9Du`VyVJ}e5wFvP0fXpVg8|L?Ah>f$xCmkI$!UEtrPZRo z8MP5G-IZ+1lV;}0)qJsOj&*fbtQcy32c4Sk{mI%SHon-yu3Ii|i7Bs|BvIAv_u^>( zQC;oTZAKR6>#UdlHFG)quD>wV`^|E9tN2({fv?1DnqBMIu2;o(sR!Uh?AOOu4(>A) zZ#5iDMN32xMR7MaCyQ7naQOcY4|`L;3T~uJTJHu)02QJ>qSn}@wb-nOMyHfs?SHvE z&wL8D*B&G~5+y>$sGM!+yx-*pOc70UN@ zioFMdA5Ul6#95DXS(G!F4miv70Uho(P^=5c)XY@5E~O-Mow!7+QZJxV?(`J!-Vvjv!IVyl&7y|x)_01 zABR&flO$*2em#uJyXD+e?VB356nd7Pe9lmHPzR->GGfjgly(5hwG9~u?utIU_rLeN zlcRfERatq{fr{YC^XDq+cD+xkr3LB$KM&NL4y@-lb2q;_n)p#6mo*qsJpPeF{reVsQA-EdH*ep{eK}Uq{`w4vFZ=rYE9U#s^Dta_ zArQT-{Clu3oI6$=(V}=>-uST_FFh1Sx{4T6A>aJU!h4UJ9l5qXrjICyto*We2hB{& zRrW)vx(nwW#`^{bU;MWLaJ>cWYix418g-tU%AnOho>U&@Qs=0Zp3)y~)P7=20QCK3 z3vpRI3ArD9|MtN-Bgb376d=txLqkK#YuK%=t&ZIjs?9}HD*9Wx;+t_w6N18S-d#N){NTfpR5MSTop%@+ArfT8d!-E{bJMp573IaRW6k6+*8X+NDzQv zn8=glg0)^%YJ7cmEv!}9$rpwE0w6qDHl((}?dz|#y}8W;zeP*f$bIJ@x?{b4skrMD zvwygM%~khkPcno1yA?sdxR@Tl=rQI?4`rl9yUn!NmX|}dvgLP@f8$Baii8miQ4inW z8O`ZmZ3DoJ$w}!o+uoY0D&)zzYn>?o-wccb*p*JMOXT#H*IT&e_duz*MS5cUJ-qR@ z$Ewc4!p>KsUZ4P>el7+|YG`db#~ z?3nd5G&BIbl$VY)e#Quz`{W&f8F?N}XMd5Vc?0fM%YWi?pTo)9JgS`};i2C#%5;h; za4m11O+_x#g^7nUlOnTdx32O&tr=Bt9m-vRnfDesZJ8|Q`VW_S@OeYcn$=&Z;N2Dg z|A|*S&Bp*9p@_4C_R#wO)e`_Zj~@;-ZasgXNezEe%`T4`NA87*@NT;$kLmO4ZEm7l z(k!x+EIOR(y8a3nHG^uC|M>V40MQMEr+}K^CTT?ZyiOMYQ5hQ>fBW|Bmw0o#8nE;P z0DS`Wd@Ip_52GyQ^;YFh8>W@%dw1CozvCk-=Ks`W`qx)aI)Dd%`|;y55a+C|tvzk* z_7X_>TvwL?aF@VG-19kZJo{qx2RBn8jadB@A%9CO?+%QTq5!$%#&qc6z+L?69~hO( z@?Qizzy(S>&Z>wqvA(b{6G*wsME-}52W%FA3O|lyJOZqAG;RdY2G(*dQ`0E0)xt=_ zqx2F6@6I*R8%)GG)ckb;#NX0g+yA{qiX0Z{@e(wmCyfBG>lr7@4gr4tI{>u$gs&r# zf(5wd(`Yv5Bm-2Ah0kYiGlY1&NmJu`*9kO~pa!T|V5wkG-GU7)4*-~o-}lXHtL>xFFPXmK(nHi9cpj>6U;t2s)Pt*TPXP#5 zU7ZB!lKw_g!@z(Mh{iewjw=z{pe!9=^olvq{e3qFY3-$3(SLx;Cw$=W|B-ealLx@N zNo?7PbcGh1QOer@Q$1_rz*JF#*(#`NeQ5{Nv?|4mPMx>*_7%?%=!2&(U&bT0hcqrn zx@;;Eb8>Vc5D1`U5xb9CUouRMur`u!iag}1FS9!7o<8y9;iF@Jh`ZFi@rbB-el>Wk zV4L}h(hHotC9Rf0>>a;gNagh`Zo-02)9|AEGV{c5==3wIjlS=(Al*=h`$Ep3XfR!` ziU_5x&YJMw;vV9W*nO~8R<2R`A8Hc!X}r8pjFx=&s#e_5A>UVd#USm$OL;B+kZiM4 zY=7x@wjX53*n)@IEXHsoW9%m>@+hT}LudsUsU!P=C<-o{v z9)Hc0LVUj1D|?Jrtk@W?XS-&BuPd~@ zR3;-2g49DT^G{D_#hDPV5)B2P>~!;86|Su74_+XxZyKm^kC$sPVlZ0d@~Tr zPBo=?BWuJ%)Py#8Q797UJyaYby5)B#|MwYm@>-mOGk5`N=ju z?1lDvu%EVssWes78IwonlG1P}=g+00!F5DX^RO0(#dW6WhTh$BeX8r&8XsDmyB@Xl1K@$QA2&E zp3N#|Ui0Vag@UL5T#!yxl*j@+`D}ZbWwB||eO#tl?RZdvmkI`1l_^5|DUYV8LO`>!?5|I+ZvC!&lk8k9A z4>$oygK1WH&BhYaTd{+-YX01l8nDv&r^!QVF*TC~GKR&@o1N%t*OhA`C51b8GeWKU zR*F0=Yz+ME*0soe8dozpO}!pcPo1RhKX#M}@~dJiXn*Aw5kV%?JRY_*XnNb@GJMNXl}c0ErQ}k#qR$w@w=88!)Q*L==YhKWWjbH zr>jeBaD!>`TT-O8`{y3w!vA$oBA;PIO&${)#Wyv2o3p3tj zagKPaQw!V#+0dTblVvWV;wB(ksEUBU#8>H#Y@WK`)uYSPpWx*N!Z=5Ht+jjf-)PWEjROcj*$C8Pfb2;H* z&^mIRA$bJzw2Hw6mM11;bD1|bL%Ok$61IL|DVhv@5obh%Hi9c_1JjIqKST`v-n5uf zbR=we_cF27c7;c8@{JAV=uxxz?u^VzCKy?&=ZdoTq^Z}Qn%UT)?vq(#ZIL3 z>8a4^FmJ9T)kA8Z)A_@ssWDB92|R@&hhV*eHo?tNe_DzpJ<&84THSz6Y|q(jBJPAsL(3tv1#9}O|} zv1Q$o>Vwu)KBfA%;MD7$_grk*Gxp2p_EQd{!)t}bFePen0YpOPb2xZ=GjntdifC7d;3Cuw8Q?{a7$7CFbbPw)fXZP$MN8tG?)N{!NMV=4+VPcdz` zM3=(OZs-bAQ25~HC#sJ3XP_U-tM61VDv*B>VY=GN`iWmE>wbbAVi+rLS?fs5TmAZ1 zW((+D9NgjafY87-Ox5MNIVtA3G4AlUE4KLEz|#FNeCV)T0E4E%xR_nv0?x*?#zLxlP{D!En3g(G zY$x7ZU&3O4At=hh)Vx18)qJO9YN2=@y}Mo~(Y5WmwUqDMcV~E0gj@F1t4>@+i0m2Y z_{RU!g+|4z08pmR?f=oj_`-y#bae3>1MQ8WuS{nB>n=wk9cmJ(F<&A|d;+Tfc5wf* zdJ~`C2ZUa~-&w)K5_=h$qS{dfG8qG2g8tSYf6+5zkw;A(etM@d0==%j74v@u9)BW( zI0DiLZq9&5FQ!c)G{%~KJ?Z(6z$A4c0&ZaJjFakro<)yIRI6FumvJ`xfJa=26BBs0 zq-moDTWrS8DJk^@tdqp=mBRPv4VFE8%jc8+C+v841As_ooc?tGI8J_O(aQ%dx#{hM zU*=mN26lhh;pqEEiml)10Y_6iQ=md>doL5vHbSwTr6e8ail`lPlRW8Ybs zoclF?=VPG*VlO~+!YdNYD{@~TrA1s@OCmZXaeMMHHDTs_h(!goXJ)e3iUxopgc>Pq zi~dJy#&&l3@r7p9^Z)Jpv44^BQ|Iw7)_Na&xEkZlTufl~C+!~6CzL)w%H~~$R*waV ze`^5}MvWP-x0t84hjRv86L=Z^(J$JIn?LLKooxvoCI3x)+sv;GLnUPG{9I^im+{tU4%;jOw8L3p%5U``BDln|6^jDpRH_K)E`{L?u zbJGI;d5#%#sfA|W(veyZ-bFNz(lmhF3L%ZL;i%(V;r5VLMJ$OKf! zx|8?BM~2&%lGIe8(hg_B{Po#)u4K)_;)nk}a+qal#FAZ9liqkIsf=@_R8k5&XLD+G zbfs}keq#`$y$kG-A5*XIg6D_k+(%no`t$i-NYHP@zU%q*e@J`Fu(r0X4U`(}O=-J} z7p*{XX>qUO?k>d|+$~s3fnvekB{-zGOR*G(AOV7V2=2~Z`<%Ay?|kQeKki)*tf!$X zV~(k7jCZ_qOnLhH#GQ6lVf%>AE8!t=n9u`k?aEO<4!97F)P!b?#M6g3-95(@#=&KH zJ<6X08fA-xE0|GJzsBX)u&?pA$>+cLWI9`R*s#BTY84TzHEc}(*XGugSGoNpEflNV zIz&ksT67F#%iJRbP`hddszz{QC*q#Ln?a#gjqcBmy%J;#v_S5-;1RA5mQgizd=?r0 z(^+o}_}KYm$q54S`UGkPQANLt92iMRD-!0;H@UsVI&O|2ki?mgAD=JUAuyvVX( zqs@1t-9z(~ocDViN87Q@Ba`*be6x=Nj;Q8v9O;1lB^@s&JQbM;soIhfw3mnR8kNOf z8t-J%C2CA7h<^6*T2Teb(ydT|?D{6Vd>XG)V~KM+avtJO68AfiG`3WffF7 zr>;=%m0(Gw-rGID)r*y6Yy4eHMu?&l|kH9k)ri*YoZbT;0@gibi8Q4+xZCvbi%j2gnKWNbK z3#@)4VjsV?Q;V!wVe3Y-EA1~!FYJWz0%90#%P4++|W zlcf!71O|e?#$`L4)N-KK*KybvIeDQ?Ai?3gl52m`Qp06rB{SckMDHGEC74ONH_oj) z8P;M$?UIX;a|2Uh2D^tRmq`_)afVi-mT~$%Tu*-12BMH};=# z0*T;&FA*+xDfYiaEE3(TcgO=W^1aWGH{Gg_$r7cjfjJFSnOf@%e}YvW+JX`VS~}PP`VrWN=f})y1GwF9cVj z=+temu6A-9o{-f_)tub*C%9a(b~V|hJK2nXPlFWd-3V>$4@a)(W6PL$ob4rPP^?VN zOaUjK#&Dc0SxW1<2$86LaXC8p>)~C&)_tnS0L{u~NTXf3k#gDD`gTdpZprx3Mfr0A zTRS(c<5Z@gT;}2K-)T>uX6k)=(g>$&DIoFx2rRI(WA=e@j@rV|5mr1yqy8_JV}C(2 zX0M31CJJD2p`vF2@d578%~JddKI;E*PazsH!e(v)hsq>7!lBim>q8z>N*dIgXtdePh{&$mUs zt0sp{RYUt!zbhY;zG+`gtWE1N&+%mgTghgD{iE1D>{pN8bF-r`8Z!nj({p1FFmIwLVm=&5@?Mr9*+&Lj2%H5wBTfkT zIM@ZPBNU&;zb0X$pPj#R$Kk!=*kNgAc`x>K(#4tFb)v!_AOG4MknQ)%kvJG9?A0(OKdpPPgaCBMAe}X6%h^bTE&|07Q-UU=1%H1 zKg1I-b9_?aOf_dKZX>qcKGU1($GIV5Y{h0y(jd0oF;rvIK65-s3DZ~Cg*5Kt*H^%9 z>BD$ae8nbPw^EW@V}<$R!CNO>-IKbKxVYO}yO^Gi>LHPiq_fK|uLeVJg*Gu5|7Ul@ zd)%q*`Tm;=y_@vQ)sZ!utN3mt4Q%=~~YRbg8drge9Iy%!&b z8xUx@?s>383(g zgO058R@B=jF&jH64n@j}07v7;4US#D1x%G~$E&L3nlMz~Jjej->Eojpr*223NGD+r7S z23bF_t+5;0`84&yy*nWA>yN)|q!;r0P3r=582&-Y4fo+5i)p;IflRDPAZAs&pUu>4 z41KV-8_6`zy8-avy>L-v34b~|MdCGvPMN?}c%$1;Rd%Co{AP*w)-WRaA7n-#RA()7 zjh^<}+!>vOcc6UlYBPNf2fQRcRw4Un_44Oq^>iOJ%ZMa@KEtXc?_uh@(Hx#B4*>Bm z0p9y>yW(pwzXyl+hLeEb)U9TCzFJx19E$m}m4?xdEYGHV-szR#pAC-KWd%bwtXv!0 zGe)H1y(Yz+;#DllHYRNclg*z^L;`2I`}^JV@o%|kfA&1|+yVm;ilROlS1mqQy~hf( zJlg=zq*i|uY~U%uV0{L%zJ_0<3;mNeFQg+@B8igKbBA#reLEmWT-g zS+ZlbdWt9bGOHTkvmX}}bX_+MB03i#4ZdfeO}r=1_mlE7B#(44NZ981&cUwQTP*FJ zBD3OS)dN=ekp!124`>U;m@g7$6lg|l_jON|@L zsYGKt7Zp`CFS(* z-J1~GTlVm8KeONb@(jVX8Cs1q}Xvd#vF zrhFgVgDeFzZOzuwEw5L@da)r!VIMggg7?NvQ(8c#dYw2yn@{iq*8lL6;b<6kNE5{I zM(kKIJ_lp3(-BMT3{Tx_d$#Od_0|nGm$Pa0nEOXc3*a!^W*m|dJL|T)e=Y$`@^PG^ z*Z)WcnJIZCe|%wl^}(}`1B(#4p9NBWyCBfyOgz9?kzz#l;wKV&gi%1B0W?hfqX4(0OY)sR{ zNjg=KLGv(>(Sk5)C2V0(oAu$tPQeSO>lG(lA^j?1uwb+>vreFARE6yY)WK9yU~oq` zk-PB5tklf8_2@{|po#RDE7+4~(Al%O6e{I%{=F_vQKjokz|i>dcc$Aulv#=lzy`+{ z;}XywahKU-wY_Ea-g=UQfPI2Dd2?}@7xrQ=0v*Zw zjoo``WKSnsv6#V^RbRS7GkL-@SjJw<%HAi)FUU<=Pq$L}(o#wx+gSZY?P`>NHhAuq z0TuzIt5q+-XUagH-*$E>4}eBqzW%ii{J1jRYFxlD-@Od=+Oj?D)U{0DoT_^zMIxWR zPWyoT(S3@q^t*qoJqx{jr|d$py5REe)eRh6+`z}5*L76yLdyqYVmNii!6}PL_A^Z) z_bKCL5+buCM7EGjZ2i@n7%*)JC(IqJ!-IuI>X!9Z@%xomV5%=_he<9LYD#C82?)6sFVc6QFG^Jzb6$2M7^Ux$X&E&GaZ2t^p zHM(Q!DY<9bFR!cn!Soy3N3;3Dv`TAf!qyyj_oUGVL>l73#Ql#Od3?GdiDY3L97f}Q z9Wr-qEI6_B#doUku>O7N59j3;s>)b4XeNbaFY#$sVOsT^*-mO`&}|D41j5(9lU-Ux zS(S+@6yrzUn4{7!lBM(KpTB~*b1QR-6n^G=Judu~DmCvs{`E=gsD2X#mUsHRsItx!qiGiM zh4?xl_D{uv$@~n&BQ&*8gw7O}xt+t4%5TL8`6K95BopgQ*E?9WDmEKrN|}|SN4O;K z`4i#ZQPxn&3`wlYuc^_XqX0*}Nl&BcTqvo?%Tf&ARdEAPoptp{BN^zJXE;(tK7zUo zo~T#^<<^$Jt?~6-B0e2aCQ<4w{+jRPnA=$T*0R@DLh-Q$gAlSH=}+AvkCN9B1@b2I z$lY`YtvTrj0$*;-J|-DIt@phASbTZbeV2#~-Hvw?YJ=bQ;YED*_=a9|_yNo^>_U+=F%TegZ|@I=o4o^n!xQC@tlb0$BHiNm7g;wYf%NNnvWy9^QBC(&ALKF z*77oOMR{eXEoCQH`EJEXplBwz17(%i5z01Dl9Nh@bTmc@UEvDBe!$8pLe0AQmGy{J zB>jq_g1{wYc>#cRJnBA_Cl#@eoT(*mC4VMzIMHp-Bp1AM22)@M2 zgwM#G_{8kyU~`(=2I6Mli3-OkJT~eqz4yq^h%~~O9QO;e@uJ(Ic5K2z`d`@IgU#FK zmo=$FM=(Co6T?{%l;Kv6&qH-;)u-+fR$fJ+ z>o&>fwwzjFmV2B@-00y`KED-^nMIrIHJW#dY7GU(^LsQp&+OwzMUS_c5Y75m1iO1Q z5+&KmZoBDquXHMp+_x~1i)zT!j)IKHrkQJwE{#O(?D~+hrfT|W$8#V%10xTe5>=?! zJ!-)s=NYhEQOZpgkuyzKK`Mlp&uvag9vebjZjWGZ>p;dGl3d~(EHx_StT6kRGrVlPIchSxj%90_KSx7o?Ds@ z>owr%nF{p#5kapq))eih5`hlldv;n5gY%*l&dRxkCXs7Sq;7UTa_GI{flgBo={tM3 z@(c3^4`pDT$$|=idCte0@P-tNomc_)*3XjeYt{wLfjCw=ccGv;gR+C^Q?3MI`xM|1 z7PSTYt0JZ6YEltq2~bmR^;#PRZ9jt_O^bC26pRCl&R1$&z2rvalSTKejTy{a@G6Q= z8zFdB1BT8*nL)6INT8sBXXf*rwI>PTy6v+HxJMb)r8?+JYB>ZT>VomMQtE{F1TEAO+hIXBCZvA_6*P ziHHfNdSG&TzX(;V2F~9Ra9DU7k{_DAfBe=PQ`_}tIjFtdNvHAYGf>S;HB37(|2z=& zuC-aS5->f4WhYo_pnDvty04{J=9F=;8{Y%f>~fbVUR@sIz6IY%~P(@ zQVH)CRtKl#9BUUwz@a-cB+!NK$JU02cBJCL4?ocg$Klm{rBdu<@P?4_#6%36T%cIW z>wfM^!NwBRvJS3~?e*o??PXv>>L)!k98S%rB{z8`!vCULiAsv!xeMiH+RAm>UCS&) zwYQeJC%`G7=QgjSv)o39GF9y4Fwi1 zeMu@~b}ap#Ov25Ka_;<&T)nl-zouJb^Gz$s>{1H{NpKYK^c<10Djy@5QG&C49WUX# z=DiT?qBtG|)6db(uI&_CUMDptPoI0o)cx&)^WM?n5V$)olRChxu$(L6`8Y=(Ur?rUd&ffo1V_;=a=7Db=OyWP9S}JErW8Y+j&Ba#$U3o zoY(8zR^~7x0|PXz?2AWd(GmDDpoCRnZ>EB9ur&n1U)YXxCI*%*_ z!p@35m?S`O-P2C|)tDCLf@c)WKN@e~--%7i!^!7CuLp}TwX^B)o~Q`z|KQQ1~f$#*|nBwx1^xdQ}9)BapzP_zx`*6i6%}#zZsBDR9-&vut128 zk4^(Qd&nmyZNE&OD;s?wuo}*3I)Ns0 zCA#l_WVD`$gVn75h9T)4mE0>!T=CIMIK*iX^0l;=F}aa9x0TM1tBO7A@;qsHk{EeP z$>L^f=%YKM3H!<;_gqB(=a?D`or2noE*dK99#|6@)dmV6nks=TX~ErGrqhbXrlwt` z_)Te!I%;%Y>uy4O-s#2%O~_*hH9BI;AtsoIPQk(*yNP_FG7jSv)?pBd=X)S$K@Bl5 zp!^g`Zy~4Cl(H)@rG~pvv73|w&^d3YF^6J>g=qe$we?^>HL4h)-pGvNco%f%-;Kkb z;3)LQ?fanV+Q=D|((7eOjcm?NwZi43&aTeR2ul=rlW4uRm;yd1L81dANr}rC=Motn zE+nQDYJ8{InQ}72=B2_WvNmLUWqXif4!jx6MbFUfq$ZU^*+fcDYd3o)Z;-U;^d^!b zlJ)2jJyE#r3qmtNq(6IxW}_y@MpHANI29a8HO;92VKR10R8iVZut3EaYfK3XQiZA} z9lnTOoJl({e$7=*W@g4QOc9=+fJcP96P>~#k=+UFzJX;(BH%k{ZBnQ~Cv7zUak>>6ufEpB=aH$94Ku5%`= zD@LJp+r*Mx8b^y65Rr*$otBd{L$NG+W+@%XrQ-gSB_I2Fv9LOxN*e43E%0`6n(Z$Q z1^F3WTBoMwT%AhQOw^yeeJS#DRty5bkJr6c`ME_6#^du)TH3DpDKQaeAuG3;&^uzR zgAebLbURK78M@W}?7xfofDtqYoiX0{d8FNiCV%^Aq?YF5fxjO!&c8)AuMStNJL)+1 zTg`gtZRL$k>6~s(gC-rPJ+^42U*KVp2Jsd+hb@Q177G|;sSQ>IJVJz+-nY7+I+VLq zrg$i@38|x6-LJ1U$|-J|TRH9Wx={DJKrMLaf;%1>_y%XcE+Y6@&{&1Ft$9K=bN9rS z?93EwiwZg9;m_~|XlzO-`(eQ|M1H2}ZR7Zct5?d}rAkMWM_+YaPI_fwGoC9Kwe!1s z2Se2EGFz6+qa89@;ABIm*YfD;uSr=&6hGyw4>^k2=m~rQ*Jfkjja#>XiErz^k0sp| zRjm62dIIf@MqD+7xd?GR*6|8dj$^gV4f8yh!{{ArbbYw^e#T13}}PE)BWy{8_Rx(sAn?v{e1 z=^6_S9-fwDFy|#)VvrS!h1L8dG`Z#0_CaJ;onCZtwVGLwBwR+W-c!BN;YNtPMke)^Y)o0bF@9mFWUXr>}M|o_N?Pi@J#nqf2o>Fpf?OaAk zAl59W?ixtgC08rnR6XK3v~4peb2w$_7Km=CaJ<*mB|Wnz$i$@Mco5>zM{tO;OQs_J zW&UAd&3en@9x1uKlH8Hnil$AOInCJL?`T^%Fjn-?nzxk*iJFh>B7@E}Jx}IUI$cy` zSdSDOo!)UQidfjB^cuU3KEUscE-%w%l(i@wId=#3@uKTYCDo|u#!cp_zMq)|i$AE3 zuD0GTVxw8!$S;3VQl}A-G9ESNT5n>S!F)K52t)@YcL?ohLIe++LuG9#tGdIPijz`^ zs~&_}b~&C={W2f1u+px0g=#^H%d}Ei?g&qwXw6J`oY(IJEM!t^&Tj|psRgUqf~9L0j6q^L^R8ob6;2LK!t0SAb~fw2I-{ygLIl7fqwC^?Ehiv^ z-);&lq_%QR>w{3!xPNf4^2jLHx~r}hGPfsqSQrMf2a^WG4CyS4Rb^mB+!Ojb*9n~Q{Iozm%QecQr0 zCwjT8RxdI3X)>qOX~$bcbT`2f`=;5O1Wqo2o#VE6ga9-E&gS*lW0@Y^&e8zuMH5g}KL;q23sC?~h1N&rc3>H$ld>8SWds=2}q83WOzz6bUthWpRWif0qAD_&F6C zB9%qn7q;mJ95Xq9ECl}Xo-t2mQMc6>rMj^br|%*xN^(U0~6j5dR3o)c80=a!Gy>5Du5X~ z&zM(Va&&U9RapisPwre{Hu^pXf3Yc`Do+l!wx zS<);^$y5q16N@+xu;b-!OMDiZ95beJzL0Y$!fj%@I!f2I@0A+QOJkk~3S3Jy*Ic|y ze82PjjBG9Whf&CMA#iHT|H2D^o*8}Jsm!Yq$SGh)%RoF*=f$Gdz+{}Fk;ReIZoK4b zBw$Mr9+M!}2k$ykaiQZCG8zzhy*-au7BI-nx+X^owr)K2C7c^~Li?fYMUp^~x zTk4avEOd%4<&`r{PR_7Jv#c$6zsJH7C6b);c}Mg7V*X^V*WFfX<_Lc}))=fj8J7>A z&PP7FI~3U%qjz4XSs}|h6ZUfk)Y@lGY`+U)Jv~?Uu+l24EVLY4=1DBC=ulaH^Oocu6hBEP?9z!zy^j_|{6mkz}pGC%N7OeE6b2SB0S9P@HxjePE_hWC82vdW_vfdhZ! z2V7xfyd>T*1)HCyV#19d$F@$c1*GoJKv7sV9p@+2yg#7?e>S{AY@ zdqT=}AWn@V8LDc#4#_?Hx%z%$8so0~&LuRVYM<8Q5Yi0z)Su+;V|hOjWeC0jQuN!@ zQK5ww4V`qq#O6}7v{x1ZmrG*I5kwsR$D+UB3sJUinC}W$Ww%OHrPx}2=@h%6!S!?T zvADdowbHye`aw;xQCtAdAVhcBp3<@W-Ttz*GsrTMrZo)y?ESxthvDt1LIOk4w!Xow znQso`Y*lN%&g3d63i5#iRKdgnGMeiYvDH#sm!-S1>z)>O ze>S+olEcRX9WMTzNZ-@-JBpLx{FO+|por*V63vL%P5y(XAwpc<2~V&1O3|#(Da*Eo z`Q~?lEF8WE%_2+{3-%|c`?lFVF~ma7;2`YEi#vcT?xRSG)5DJU=o20n!&_Li^N$et zlEuan{P|EA$j?}_k{R`kddBr<@z{@5C(`IV#|AbIq-)IF%ief-7k$^p2sc+p~3@e52#`18Ud<@q@x*hjpGqn(SS|0o4XuFSh=xO_vgRm@qT$EI`7%o z%DT+RExC2ag7jI#O|0hh&t$N>-Ry+hn$H^W)>|F#oit2dlKuQfoJM83x`Q=SQpARW zlB2^9dvofUVt;=@T0X^6ff@P!QV;+IwfbZi1@#b0#eaf?>tY|ywM}r*`dj~WS!eZ^ z|8%&d)a|3W`lD!ZcI3buabS*()hut2V?&~}d$ZOdFH=uMEiX6uY3u4`Y^g!QOO{Z- zwHcds{s}Il$k3N1AN`k&c~+C!U7s}&{%jbJKeEQm%qPJR`^_xxKsBC_*}(h4HIX-y zQ*acIiG;B9UAB2-AIK(=D~_QGqZ2VBlf;-qPfpfoZnAvaU8C_7DidCID>0v!J^Z~4 z+j-Ci@Mik+)iTZ}tq5AU{2xD!2Anz@zoH494KN^;Swf;BhUsc$yA#M7k)8ujc59Kj7c}&&-*mt*j84(XELcoPtq$j;26Z<1TbPWrho`%ke7OdK*U<8=o!D_ZK$k~4Eu~Ddfu^2Ad0GNt!s^bUT-(4zLMJ9&- zv{&-ecl_DZ?Cye|O5+3<`4hzGeK$Z$J30VYM`Y(md`-yDd{*8v7Y>Y#KAI-r@3oYV zSR{aF*YUBj@R%g$XpSc|YEJjM@44ADFd+$I1`kqO4w?hti|E{8XIAl%a=|V3Lj0cv z`RSTL#CGCP=*t$xd8*d;d#zIt1>s>M*=+_cI0vE|3yb0dy>H}V=@Q5;SyQO7SkjMD znUfgfSO~9-ng=15a-d4TdXCioWe3=J+%LaMY>_Iz3V*YO9be$f-)qpbPl~(&!k!k{ zfB#BiGS)D3lz^j{*cJQJPH!HIPFPTQ+^%Q|s!K2j&%Cpz|HE{mtLMnp2ndt34M^Yr zbdGlkCHbkf%X#*0_U)+nt=t;c?8@x83`@xT3+JBA$J}@TVC{M{`zAwW%Omc;v8c9d zFw-vzZp~;|ul8u6CK)LA*(a}*YwHlpkQDl}FaIti*x)y=3w&btyOsiY5~L=f`#0~a zT3cI=qEIN6sYNF++cP83>u|BVIbR|Z(A9{7#Dx9P%G`-eS;ZA9Mm~mYVz~oz+1EB% zu{VEK0WghmqFRL1Pdp1ePaOO;rwAXJ9Q6)E7FKscEcsnULxjCP#C#};lOBp1Zymb? zAPW`eSTiyEK*4FkPIl})20U`4?LN$z>|kn-xi@}RVAeHahl?ht@H;>yj-J_4W9Qw! z`tj*MA{~E!G%q*3@vk+pI%q>>qxKB?^~0s@?%|6*1@)_G<(&Lw&5I)q^h<1o`ARWL zkIg>23Ku%YIQ~=FeJ8@veySO0BAc|DRsM?iGP{huyx!Z=AClPrw~53Iw4mGe&}$Nv z5CxSgHzWT;k5xIJ0lE3s>~p$ z{o`o?PrAIwWvJYLGiv|~n$%cyrgHcRvAuQ${M1WC4~0RVo>F*R^e^4&o6wjlF7Q-? zitF!s!-U4#bi{UCj?UPw9TZZHbwb&jsD+`J(LYa5J(l=gA!6^xbvIztI#og$UNDS& zr0M)Nv!bFPaWtll$a#LsT4S9oz|c)bDP{`!ef)QKVu=y}bMFO<)E3W@S$B7@ddpOU614JWsp{rO!M-Z zJYacYIXRLI)@4)ynXA8$TmB37Yv~3Ct$aEmm5;VW-rz>&oh;1w&us_tj7ajfbSY#RiH8_Q*Mr9sE=WCuw zs8e1)J7)yhzZs^T4oN;8gt|&Fd~r_XXHB!d6!UviQkvEK^L+?BukRv{8~Vg5OO{&X zc~-rHHDV zxmaNqQ7vzc>|)BZR-223w*Kfeytkh4F-wCwo@n*xctuaM$h^rmsJQNuxM64c)Kh1n zM5dQ%pK)ST@LT(JS)?xjDOrzo_$^vK>40|&KgG5%I3+^jAFUzBYEMOlj<<(u(S8L7 z8yMKI(2;P4cvgcRvN(=1V&)_H*!;CN!KC0U67~cN9vOba6vACe>&-CFBeVH~yCmW{ zJu&z*V4^3QwpYuh{-Nj_Z39mmv*36j*-Qz@k}h zv*`)zl|1;7>2?5n^DB@GOhN>`FV5^cEukZ$9Ch(CYRRcJ-P=aaKgI!LOn{9~O9wN7)Xrh0iz zJx0qSbR)NtE%eUW5nMwJnOoSiFVtUFhEP#Mj={`_POdGivS4hX#{bnryPm|QUs9UUVSm{lDT*Msn z0YZogQ?-s=4&JIEr1}HyXhhnPvQnJra_@IHG>^Sy5X2I3)lA@!)s&~dIKPSR5Q84( z?r#eOWG2&gTGItiLnGZ%=>TxSmVsr!IpvAOSyYFuSZQzyoWFE5B+YOJyKs{O9n;k=BexeO7;&v#=9B{1D?RMgRO zDj_AF9;|mEanP#i>9j*gZbE`q1^NQNHTZAWbBVv-K5;vI%G5Nek(^eJAB3iDrAyow_O3&6U1N`kp+++5}p)fXg{@sB|K zE17UiN1_)C((xcbs$cQ(KvTw%?>&~lY6I6ZuAgQs&=<|(nS@l{O-;$it83pY0zy43 zVF2`2bv9-#RC=_Ns&lRpdR5js~`ok6Ka_VZ9H24}-@izyk7D zYic@J&r(H0M+~ttU0xs)+C(197MHMJb3OaP=dgV!t%5c7{)vyV?ucXSg-Sy-fIPBr2P37usDBTZ~YWq z@Pf`t4_=!q^9YURDuZKp74I3}mVx>TnuYQucVO37nvtVMhBx!;zpHp~(zNP59vW(T z`slZW=I;Q;2IuWQ{DEtd*Dj!tm@o{A@)fQ~DGGQ99(syfE1Q@b8m1%&`j&o< zf7v_7^u@3wjsiY@^{Vs-*&ATzid0L6_9T89aDaZ-+M9KZVe-8}rJP!! z&3;f0p%s?GuOkh8p1ON}Wac+S-s%=N&GRZq;f(Jn#^-b>|P^NTP9lyjCrNR`Ew5&>PH zhzG^N9IV&X8BJ6^-PqBEW7o%=-w@N|eW4R+@6lQg&Be=5jFBJ{s65$=<*#*HYGJ-xF<$jJG6czH@RYm%Kib@lcv0L2dP-reu{tg zRVFdi=0S=svJj;k%w%TTwQj&svB2-<3Vz4dq*t_+lA0XV^RZ`y%d1e?6;7$jBDznY@zcjIUtgWTb@KtoO46}43N-$bMJuMg>e?=3 z*Z#N?(Z zCkV2Oj%rnO#1N=xsw^{F-HEINvf=)^B53ThNW2GW*GJb%jVt@~B3`W4Al_CsI!?P# z>I^()nojsKav;Y{9J#P>ThF86Z=q^wS){4uzXA^bzdSM0i)GQZ{XFCBK8>XKVb?3n z`VRlos@EkDamAI55KzKPJRj!LS|E*V>Bb!2tN+WXOT9n9wxg~*gh+6l_}ua&{;E62 z7;`ZbTOje4iD2|fxa767*Fu|j1mmjdEnrt3q&fBGu!qaOHH1IO_v)x!Z00vmRt(z ze>mG=(orpAu#eyZ*|Lvq)Qy+E zq2gl1lDblEo7eXp_z>e|n;?f7t!d@#0gGP zj$#Ori$>fEh&Zr6lBDYqCoEIUpue1pM37uP?d_2Y*5g!2htsQ00G+%=$tgpz?v z6o2o0l>xBD35<6ebs1tH2@x*!A8Pm4vp3CCqv@uaL~D12^Xe69ElTzg#OS!ZfTLLH z2vuv0?jKSS@L(pEF=qz%|08@ENw(W%>!yBp~!XVsCMDA)|V$2DI!OZ zxIsgWdXeIVF7{v#J%BFcp-T|bQKx;q!05B{W>)?$#&-Klmj&3fjgve1) zU;Lzit&Tlau5Aok8Tg+0)lI_(=T(2!UtrDMQ~LF(|t;K{^;d}yIfhPS7w+I&Ls zVbO<$zUfdd0eoK@&xG>y`j!4Eb{4LRd-X(pKg3lmby`zaDjY+)dc=VU;j*~2-}q6n z(eK{Jx`4~hdFF#8qFTy?1xHVYy0aE?j)XnUAo~-l=zx0xl;2N40rOQn7)b&#UMWQb z(GT@BMN`HX3ci2cX|vDRfqbZwKfr=^F+%G1Lbpd}mU^Z=)I>-frpd#9;v7k_C-2Sx+=dWm*b z-0-i9^g3L>L~=X3Z?$h8@}mnL9G*{?Q{+`kGFq>LFP)fVn0UC*)qEb*SMEoaGnjq% zuB@9=`^juaLMQ%IIzt)6&@L2g@V5?Fr#_0uj};W3CG!iEpm=&y>HUuy{B8A$c|{Y# zQQ$wP5)E@C0LFml`S2xNbOUedV)F1JrUl2${QbKE$@$&W&%a48fJ~d*3_@Y?cOMXJ zDI(v@z3O(Gi@`qwZ=eLTuS=`3SH%NdIV+Uv`qYhA`Zbyx0c2xy!`Ipz!YR;q^!LA_ zo(NTOsZ^bp3FhtTp7|%|+u$0-xeHtysGS|M26*BF*&0$5E- zh(bL<-ON&e?UZQ!{hM2^b(szcvx;(v|9vMba3+P)HO^wv~P6DhP(T}v>5x?u=I;hgsMaz&J~RXZCB zVoL|Mk7C3|9yVzU=u{%%CriJ}ZvHEiup{mGra=W$A)^FjE;pa^dCe5OCYzy~+n6-F zaP}M9wP(j`q=5Sj1mLYbx0>MBDtIq0>`$`_#-tBp>Baa26{LlVTz_Zw)j+x9iznR$ z4svJWY`4zX7cBYf!(=wDHTaYU!aQZ`Ex`0kBCpO+tXyra0NMKN@lXVOAreG;)lCxm zo+wC^rpljukID>BsgmDe^E?ic8Y_$_xVE1~X(i{Vq&q7PeC{e$)D+6}hPzZ9VYKcw z)D@^|C2}mfwMcXyyk}C0!yg>vIJZmQtnnvHwPd90&3v!)Hvs?h^1k(+VKOL#A~n#? z-2-xh&Qx*BoK)@E2HcUw;WdtK%c3{|s{#Ap&to-PO)9zk)#zpd=}Q`}Ia2lp}ROfWMh9N<3tZAyF zL|q!PKp{W+3J6N4$Eav&6^xFm{ughNx%6+Z0HFTePE}9Iz7qWYtSnQsz(NxA@2VuF=MQ|F5*auANkyZ~rv6yHT^>S6`B$v?(A^>9GuWR5A)P^Ln z`>C7RTWP1HzXbZvG83OU^|l*zBcec%G| z`2=!PK??Fi>aQF7J}uyjwNZ+N=MHV{_<{0U;tF9GdD`KSOFcRXxkAffO12K=qCaox zEWf7PzyD($U#x8T~g z$%AgPWEbg@k9A2d(snu$$;cHlKk3#egNf3H#t-?EvyqPVAem7BZH%b%yOBC3k4aLU2{zcbT|yEUbx2#gUjpK`&X)pm3xXs zPw2q%Cx#XeaQxjvu4Vh(2e!UE@_Q1>MjvXu7^DohC4{K07M{fPsfR&77k(ldK;=Jm z+djZ<&_(1DgD3wg`V|KRW`sO|)%j4+729^mPMrtrki~8arSS#Yo!1^_dRoE)SILiv z3pzO@{5n~3e>ac!pkIu2Z~#0bfsB4cM~#Tm=1Dy)fX{R4C{>AbuSP$iHVy%&exUAMj zSkE=Cr~eU%AUrHlS1z;9)Z~BW_~T`tdR%%yo~2#VSeWs3f#R$H?(mXNN>kB6ADQC( zWw8X?NroAbVLar1L3MR5Rp7Y6V>RfAoXOys)}GnI5X&7hl7T4yC!P<8Pz+N`Y1*kw_Ib+rp5rhIxYX95C+@eEt%7p6L1ah!;vwq9K9)9h4Mw|JD3X z(hdNAJ9%DBwnCG>?Qaa>_lq>X``e+Y41$&|A2o6hfz-?fHjyhOCL5wGf*&g1qu zaKB;(nKl44F+`6b5SvI|ae=Dyn+5J~ITQHqlqLQv2!LQHgKmkW@Orwv{^W3=M+;-Q z*nI=?$SbeN-s6JMG{NP^W|}tI9RXAJUpz(ufXC<a@nBRj&+Wezof&p6Q zH*wx&vh}O;=>9w6HQ5^;#Zmvo=}l{ zSv(^)t=7(A;W?lNfwhPxx)n)abz?{m; zEB=Qb?u+-n6*AO5k4uBsdU4cW(27x0dgMMPrX;$ExK$Te*15`yhC79dG|EerS;`q} z!j|szi}+ui?#SgqfcGD3iS3YTpU6=#NT;r$NwOp*esnBey^uCj<1Q0ZY&WnCzvpE) zbJ>610KI|&n_hCuEGbkk#oBuF&1#q+SaDD;i>4TOXXDrhcG z$Yv$Gb;ZqwT-#~6?atOh-JBfk)6A)vvY^*)?dsPREo$GKGkBB97m5dh8uPB0#2j~) zjc!fXR&&^_5A`Wwh^S9h;}TivIGU*8$dVbq17!lv{6-@I=<)YY7D1b$3%1p%?Y?bR zBF{T&{|Vtgnl7O`D}2_plNF%z6)fSCDbuFQ6`YLFysXk*_mv&b>D^ua-uOHwR5x40 zSK#;KTEK(BI_oI0l)Ol3Q&WfJYw0HoJA?M?NIh(lRDRDI_xeLWO81NJ4P_!bH?G|J zbx*}ma%1N|RRO+bk}BZ4GPbfQU~8X~xI0;z-m?a|(6-g>F6_JT@~V#YuY^mOB$znr z{!*Vtf-XkDmn2@YG$_%Nw@030^-JrD<4PxQKLlY_R|=UnE@M%J6i0H zl}A={>Hg#BaI&HrLa5orw~`v^&keq~Xyw3*ObI^>pW^sZ)-q`09|HWL+xTHtT^y1r z!fD|a->MYph=VA(P2?VZ$b0N2=xco4m*wK>xNI*<)Pr3nMVzjyo%hEw_y%2~!_&v9 z{||F-0T$KQ#*2c0bayKtNOun)N=hl+NOyOGl(c|=w35!32}c9L$@Ro$Xp7sS>g z)ye0EJuj2;yR2EO4_mQrFCi}rqk_`c@;^8;a$H}GZ~qjs;1V}-G144vS{3BQ@`Nre z`xrhW7dB%>OaUz$_NQZ5x}ViY7wF?pnwBqG_TbNj@{?i0O5TVUVW^6K(jRb-UXf(|FxiXLngy8gKk!-km| zGbnh-FLB596eNr5%Nzfqu?D^twoi;!W{W&h(J*BI6BYADjdp7z$|ERCxq@YIqewER-nRj%? zr`x$O42oxb(SdzEJS^LzSP2Yl&AB>eT4{Xbm9_G5mW zPyT*_?SGyc2?~x9gM#d8l|&fX1iTE`RKO=Ft!ilHlfB=fY)S)m34MX zJ}pT6pB?CLf11c({k)1O8$}WiFS;A>WMwGX$;w6Y3gUMAD^f& zaC%2s^VE^e=_W}dD*591@JfyIkWt2x##;S=jYXB}n#8rO#4y%G@1Oxo;(pL4{h0ce zve-|Vfzr1#&R;fO7Kn3{5E&?H*RtdrQRW)5*!+m^vUh@U>ae*Mzwlj{H7&31?%vg7 zTCs5ff(^E+o-)Ped;BJNyA}K2CJ?VTNk!Sh|LuA&W<5d&Tg|U`-s6AqNXmSnNEL*2 zGoG<@>ae|%H(4oEF>rmA*RmIVMKrec<&23yK7UG20T$`F3%v;(J2*FtyLZ z<_>+)$8%Zft_WFcK1SgKArhtpJNo3l!TCG4i^RY#pVC$H5be&W()qbz`0X_qsDFt4 zhcZqis+EqTf#u^)1#J5)uyJryS(5)V&i^a+1M`lKD)^X^c@GT$bQWpuZ`?$b=(q)o zHZ%Scvi!8gqn~!+bT$?Yoba|862@g~Y`)?m{0|KA^V$sZqq)n<|6wzhi>8h*PmtQJ zPOr7Pu(bxRD6TIRpeseg3x4f4HbSMgC#(PF_gw(f4#xE-41fAssVl7?y6ic48ufSH z)-DTbUUvg-#$lG89ePH{)WT=6sbI@pVZQ;+Rx}P_Y6|SLo@E$qe3z?M*H#WHJGs?h zSDq-;vEB0sKG}v~ctu54+*zL;R4H+1A7SCx#cRQa?BQc)WPuZz<-iq_hBNhb+PI#p z`PPr-FW}yct{ddA?Ec*9%bp16kkV@f>G-S}^1;K#%f%6c5#^QGR;S_B^%>3>x{awPW_p(AO9fKUN8PeCnSzj24ZdY~~LC{4{2mNAibuKXuh&tS7bNu02=}f6Y=jc}9p`Lu9Ci|z1@{*&#a!@oRSyVUn)yHkR1#jeO8A|5G#s#b^-IHc zVtI}7ZY7X!YRU|X9x}o{6~nH>v!Q?9=e_%MN&q2#C%m=5YHkAYOHq7-heqw#NuVLI zKO{Z!=|tU*(_|8!z`J%diH*qY_80u1kHi#GVVh$}NyEH4(2Mz^T<;Ssu!;wGnl;zE z$Aj0AJP68CW|ILwhP0z>8Xt++8Xrv^DhEqk4XHvc4ZZDO>4Ya{6PGH?NXY7-_+|@3ZZj+lA-5oC6j<;3L0? z&w0|MbhD$QKT-B>#9Bq>#SD`VG`lF*cc1a)`pm+exqUUEazb%`v2E5)u?$=@``|;( zt|ADPIjE6|#jYMJMq)U660FA&O4;V)=HblHle#B5P_f9 z8`t7M0`4r_U^M&~C*(a!0Jn?7>MYv> zCfj2rfUP`ViQ^nk?SehA0=I|uD_gyv965i`MazNjj+hSXAP#Sb1vb#8kHJzMW1h}L zu6n;vt}M_&74I)KL5T{h~InR{F6 z{TFWeU9L^bQ|Nz@QZENL1XF0b%t~qhaapqn@3T&Cu2k9lVX9Jb) zE<+`K@x|imc*vhks+M&s0JO;;{J#|oJK4})25Er=6+mP_ighuiW&MmLURkKEk-2+Q z!#Ut8N?9b`Lem4KbME-eBCYOwwM%2>{}q-U0RoGy%9?;0F6HNt#_8#Ye@!ZB z|7@MG185}u;|NCky8b_gnpL0wS_(-i7Zx)~^c#f-T{0muWUA$wh;l_^pI-*uBcY%D zF2#{bk2cp!|1*g$_+v4H)h1PP@1MO>hjMc>-t50}P9?Lr25 zUAkMWZJnadLL43*j>8&~;VSHM4gz-7(q@xkOcECQG-AcY!_(#T{!x{7zAA?rb1Ji0 z4e)ezYAROwL^sgiOOOCxp!Sdm0eAvot*6`T;WZ`@flnE1(4waH(&{?ApnW*6j>5peV8IcP7Bz2R)Nh=aZ%Pz?zg0{OxcewgclBFtI!8j_rY!AnwYP3+l$&gQPom+;*&BXaImcMQac8&L*C>_-3$U?H7dm@r zZ;Uwt5e5oN@>leJK*6Gu{tD^aw{Lg|_Wdb?n+YR?eP%qsx>2RD%O~;~M4lT4{Z>YH zhHjIDr;Um{Y5A?K{xg&I^PiIJMLovGL=hgHM&V498+2dPl@_}D`}&GL@jX=q1Vj=I z$k) zgIX=$Y+4DGy4o7ATg4q7)bM6D@`yqd68<%rQK2p_K!=b3nMq%3 z5;W`)L@d=CohJwY=xYwP0|}p=`G{KXDaD72E>VNG>du^;V!mZFI?) z85DOZkbGY1s8O8ABrt@lVLY{{N7=96WX{=soNoTz21q1?Drh@4@3$J9cqA&CRock! zgi|vPAgn$<7mdfCnzidah$mY&SgO;Go|_H{U#bHecz35dHf8BKHb?JP#L0VNp-Mh- z<>+;)lB?1NmAuXFKYa#hA5}`1>{MIPSJGY9F(5HZcQcD?&Y__@vyj;Hb{DN$e&}49 zcYp6{P5gv$BGGb)TanP3ab>(QmUxC2#LB(tJC;?4*7bQw*6~4q#?r-J~ON$;y4zp+Mv%ut${JT z;tM!O5}ZI0p|0$!yzTP*7fU%KI8l}}4ZgnVSM^7S5fYQ`ir&d1uRX7?9Ky$nmKI*b zl9w>9&uV2jGlR59Y$x;=B6|Nx0O-EeF{W>t*Jt5BPf0AF^%$KM>~MDkHQ`KUV!r`ryH!dp2x?>Qa5|hnNFM90-Bm0B^qWaNtd=7*<~Z{WQtoUBG}h7M0Cu2 z(L!s_>^e)Ir(R>bW|6@3{_e9i~^X4Fn!kk1gf= zde0zY1L_E|6F}n+zL-*O>`)^tVj49i*9_?gPQ^ii4^eY+zG$CJ=>h{SG+_oQy!6Uc z3gZx%=T)?A!dRx7=P8uzSV*ASC`=L7hxQd9ZbNE9yiBZ9a;xqE8THd9W)+cH5TyUN znV~!Va9Da;_cU*RTY_5oK;;$ScWS<>dg=FictWJ;&?C)>ins+@Lm}rfd7W)yqE-%j zj0tby3#`%euxGTfAC(y=MQ&}D4|s5+jEu|&b(W-E62q$8kXRK5vF)m8&ZeNBKY`av zz$t=% zNksXsBnU@}l9sV1V21@Ed#YjO!`hIz?Nvkf-qci;EfY_Q*e4QzT`FdSUX`SC8fzEf zQ_VVTcQca26HeIPGL=edPK$Eu2?_Ys)7zoT6P0>{Q58754TqOydi7CujQ+63Cwuon zg&MI0K*jAIg1nTZx_+_Cmf)_1v=-{tWO=q5_BfJgSjgL(9!5X_y;*-KH9n>3LPmtB zu&y_zMuEq~SlByjtb!2bM%64Q{YKRl+UpI*uPYdp?H5tZYwX0)5#<1Yvj#BHZy>>^ z)ToaW1T{(E!UAq1oS*O8s%U!&sQrH9Fyu4v?2~wk!_PhJ@WG@%Jyw0lR z*Ra5^p-2U=U)r#=KXQ9DNxav67R7J+fpDU$r^iHn131UR=F$*7hvw+O_Kge#x5{;H{KNPSlYlJ(`o)qtW!wL;YD%wyy z4nWK&giUWT(H=r4V{UvG&*0@&y0vs$2aT27tkmNmeL8!odW;?kM0o}3&VBfhqE$et$! z5G)D5Cq~Y_qT0@B*2PYH!gzEOJb|9TU5&L4!N5Ct$NM=dOp9M@7E@#a=HO%T-q|E5 zd!r@p{1?lSB`5 z>Q0s$)u$hCX{v~P)`$s4w@&ZgHMbD&7f zA?Dl!9G%s125Cv4%GkilnHGnXV5^w#nNd`Bf}3;vJmQR+&`R9BHi}_do?XoSi=><{ zrSOuQa~e@AglSU*!8bnG@Xm7B*BaHPVO~r4eQ&J zY1RombopZWLIqLWS#X;?&Z9%T4mCRvgO381<_j$nOKNY+2yi>w^6I4Ua$=o3byI&D zxaxBjOPSLuo)qM1fU#B{dS!l=ikeqPT}cmt0A$Tx1G0zk=f<=)KsU7B8{PW&)4Bh@FrK zOFkR=@3IQtgqG?bn<7fmDZB< zsTOkyaXE460anDw7G}9fo!a5sh6V65qLr_n_5mCRRK#mfE0;Ua1slYRd~@Pd3qJYw z*lXZW6O7t+chK7Fv;dZ26x>M%?<|G3XQ3L+;w8TeB$zh|?H`Wn*{kfh@zhY?4mdG9 z%PWP_w$mopnJ%10J-kHK%X2vgidD4Y&pa4kT4iyHVJ|p!jugNWDmlp|;O z9DiQk58c~~==B6&R)GBc1jvcMq-N5zsswtV0{bsYAZ0;#IyonC!d!Jl>BUj_j$0_ zxGS(%U&kZvnddVpVK?3yMVNZE`$>LM#cs%~KF}!L~1XR{8<5;&g@qFdq$60xcIg+o+SXIkk}juMT0I zv+qPG<|j`n<7G{GBG<(`ISnQDK`SHcuG_ELJ}v~E;m7kAK{+94kN`Rs^VxL9Y(bLf zxNw>=E2`}09|qvZ)Sue$0&3}5Lbd8-L}NpqtX59sQV)oph&P{%e)*B6mbQMSr1&hR zeO2G9dwOK@W~<{Wq<3MDdw&sj%A5+2H1ElG?P#!d&*nMzmT&YYA9GN*-UsFcxjG2= zDoHu<+ucWN0b5s!HG8TRt9$tzS}5z(SWI{vXtE@SggLP!=a$-rH$MPeBaTxMjL$p? z@SAyg(d}n=pb<*y(iUT;md#A7Q#%pFpFEf7v$?x!wZVY63@YuX*Dw2rUhT4i7+*aI!zT>IZa6aJve4CX7)pP*%Pqqit*^c>(5y z&8*27RoaB%8t}Gm_bHxS(=fm46bvMwuDc4Z1mMGU!;)Mr=EdCZ`Xx}UZLL#0S!=X! z2>Us`?A=mow$OU)dOXqU^VDCCJ(mC(ah_F+W{$hXe^%h)@-p6b(upkm==8M4fA&*| zXlS!m1<1HpO(8MAdpN6WOr0i7Gyo%~1qYx+&5YDvYub)DgL4`LL^#eTWb;e}fZgs| z$+Bl$kGT6yPf~JC(twiUU7E1(7?zgrPvq!YYVTFHek`iodr_R}XubahuuZo) zlT-1Qs{LxxY<|erTeS=Udy}h+<7M&FjwBRuA6YrJWX00-AAE?Wm0 zkgJnwv%ijOK2MH@+ETtSB42<%1}ODG%GChsW1rZ^HyksXWn$a=X6}Nteg=eVWkW+( zxg?QHIev+}!ys3HBD(P{$G{|qhYYyXgLC-5=r(ra>zTAweLT!p<6xi$F8}^{C1G^$nlJfp&;_K> zKuMB+4Jfr8JH64hH)~7f*<xvpD89>z7Ydrcy8-j3)aw>WxvCfDzk60D9VlD9IrYO318ZwymQ8imu2^ z*9bw~=|9;w#-#Vf#eM(Gr2tM2@cmZW7`BEFRMXB4yK?c75v!)=?3xYBbT-`5rA!>I zYkpRG|FcP^?%U5AQWsPORaUOYlwldM?%eQIO064@BuKo5&W*!kl;fmK-(ffIK;WM_ z@PO{R4iKH8Z<{}v2Wu}R=Cg~5K>EKCOeRtoOGmfY{8BtXM)}K@TW+EJS=Iq7EB6EU zbDGJ4TMgz+ZIKd-2hfE_KaHS~QhaKxB>lA4w9z-J6A%l=0q zahXW3nA4WRq_g^q#zSkg_&hR)l4BRJ26=WnhiEkG?|KDa>Mu8h0BmDFBPs&;AVL~+ zG0iiJ8XX`zKnK5m{JtZ*O`K(gM{I@X+%G$BXh_%>8<>o9HIcaTo{t7otmxea+x{wI z@brkGgO~XqFDI}24&Z6_9wlIYTNsh_^}USQ!=*w-EH5ty4CgK?DmfL|yJru%bW2CZ z$5*a^YV#=fVbLocn1tbcr|l36zGgVuR-Lth8fAH6+4fSnR$&9|Xu6rR>bK=K68=AB z>UN2;A2_y~koUVh@!J~7Vn{+~8NUcMttl2NcKdSUr9oNbQLyHe{M#HY)QpU1$8C}o z8Ntl969bzL3&3vxb{gUp^>|jSzP`1U*WBzou?k2^0qC(|^I49b@dAFPj7kWRtI&H< z5cvw`@&Ov|=Xlx8kgl#!J<*0e?t?7sc8dfZ3spIIzd`oIe$G2a2O|f8U1|T^@Z}%3 z^g*@w*+U{_E8uW8)5}lxfLgf>4w~_#5vDK!2@Gw0>C<219L2)M#zy@1$!hB7nY(2^Y?l4!260}R4)v{~JS=8)%;ERGP*>O<8;p6M` z5C>NeDA43v-?m}oTVsGwp+@cxtsU~!@&ZhfMX+HYd5`t{Dn#@fW} zuF3q2hW=?`=@*Mp*;wJVZ8e>G2V$eP4G)Lb9ge1E5yp9LKqUtosleTI-6qbu-9Rdq z*e(O4@Bb3Sm^w!?!WX5ym{xPU2pDo0?5!Q+pu1yJ)Wig+K45v5dCgwL$?oV6;qs?M zHAW;rfsn6SEZ_T+WnE}PtnlepU;;Q?GhXYTziw>o{A8q(;*>0T{+aB@av|R%iB=ME z_{}eQ@tB(SR%G20J4?6i1lH*#<17eiNX_m{qqCwNQ5A7unoEEJ^Zrp48zJT~k+#)% zmWzoK(4Jcwvak>=zedwfqxX|fQNN{gH;{!~1f2_Xy9sjuMfCglr%@)~`e}h`OiT=* z>5TL2Ehf^alsR)gQ>LUwZk@)>FMG!T%5B=RJjYG3KvlTmC%Li#%l=DP0DR0N(C{BmeF%8qA>;n*TWp?e}1d2u?33cBLGMNb&`if zR`&K;Zg4>RGj=O*92$2xuCEFm?|f^`B@D`52td$ubBBG}s)VBAN_-8M%|Tc^u59(2 zJI6rvcqquvkB=<7cb@i}E53H)!tA+({*1=DUOLNH9_9ax>gE#(fQco$qya^iABX46 zH&;KW?b&vv`^jOpZ(^r;{U_^K#yeRRuu~FpiWdO3&CAOZ1YIDPmkVQCGDk~-k zpcS%kvud4wBS2L2e`&BM|62+F>aM=#Z}Zh<;7P+e_oE52^w_?K1tv@({zuOHR}Z<@ z*S7&ShK9{vMT*<+Ka$B_*_=~$=JNiYHDpswS>0t!AN$k1d zd`)%abJZ$}w0B>s?YE*q5zAI0ER-WGU+d)3Xp2XqI z%+8{}G!^{-+;jniS=@yuLP>+8`o`*{jUd<@{6d)Y^< z_^kMpb9agqzF)h1*@H|esMIBE`=CUkcu=_FsXS^4^RI=SN=)_7t87D6Dh!n8j0}Gv zlTqN_u4(y-#9=xC9u8Hld0#a>CP@InoIpwL~ezVcs zV9w3x(>p3jzj_2m2@?9u)^~Rcwb@juXbRO?xc#J{qG^SNj6eVe3SxvUs(?kmVE_V< z7f~dRAP6+DzP?`Tq1tQ0o!G}PI5^1r^+N=#BG4c%EZz+SZI`Js_6 zKcw^*y`H$L4wPI|`|-o?1L4`FSZc}&Z(<8@xd^YH7N9LTztoPgQzHZ#Ab-{Z@(Jni z!`(eG;!P(j4EXr@6O@aJG%$dYP@S%MZya@|%U9;lCS#>uH``mSBRJ4y1DO0nv_v~r z&;9!PJ?Oj^d(Pg<@BRW;4zxRfiJ$ugw50;RFy*5Zyg)13vDj2+_2sj8!TrS(W5a_ZE(zC}0f@?PQv(#Fm+84@5zLq+ z8KX*j`z?lXkez@6kaeiDjC}vj2WE{)ca{Q!R4cy1W?%LahIYx5a4 zjn|c-PxvT$12aAHM&2HXfA$oAUP$7WAXJebmiMgR<)-KUzqN>3$35t3>XjX?^Dhu- zy)}MhRQ5S%lq?4q1b39HG-A5Uz^|e zz{1qB%)(;NDR#*UEAgeYg33Ef|o zln88dM9v(h9_3!rEkd9CdPYu8+m=i73I!24k}OjF5ewn#q3*sPOZn+9&kfGxKd6?d zv3xJalHFUe;?LK#{U-FWUVtP*icW@yx-~UzRY>VvD6Q}e&f%9%0BFf@qkjR#anFzL z^%;+|4pwM=JI0{(8Ek72$tYy$OO2`cmBo|@f+br#&CQv?M{|S;ju1!-)dBgGT9C>d zwr@DJns?DM2eXj~?u6=hed)CO6d;S8hSgw8$0Mh}$ESwGJ48bTi(;vr#aUdcA;a^e z#C?-SX!bfnmMHm2uw!i4V21ubb}Vs3tSkI1yG_{uv$xQ5t{H}z?**| z$NU0%tS3?3bStWnA4lHdhpPicywMH5s(bfdb$=1y|4BI9@dR1|dIUk*rbZAs^~X~dWna&zl(?kD zhDCaY&Es!bU9M%qluVTBfOz?)vS|-K-wPwPh4THrWF>W{?0ov^?^o?XAhq-r!rCTYT_UP_zB1(`^;*99r*F%*%pQ9YpN>x*D!OZaU36Z97!@_ND^{3?t`z0> z)n$XEn*ni3DhMcp1VmOE%&1JbwFTtkXRJV%jWmz(d{3&XdQGd=x7yDHGH0v|Ay(kf{l!#n)KzJ8yiWl_%Zn}E3e4kt?*|0k)mwe=>%(AWs_IZJiQ>f`dh z|MrafyV`af<4iI{u8H1IKD7HE#=a9+j_Y_&WKKTi(xjoz<>(&OkQbTcXuG-D znASCZar#+LfYLZ*kTQJgKq`2tO(fQbYuA@NI^u`!a;A@R_E^rO44cqJE8A|R8eBdy zE}6M$GKXrp6I%8E2>sJBl1W$kxK_~4Q1w0>B^HUelu9^29*Zl`%w$}q(VA+x6n`_W*uj6H5 zwOT2R^(1}l+l<=*Tqg9FZ{y4OKjH-PlfZJ!`Hr?}HrDXiEHDy3O=ENX*S4wP!C>?| z1gIXD)SHj0rsbYZqpC=#TO5X%^OR$AG_*vo#^w2D0Lrf(zU5Xv4BQWQmT|>WAkv&& z@{A)660y5QyV5Co@o<-V){2}-CNt0X5NXdGt)LZlcB%mK2#lQL@fs;@w%P$*d|3~k zr+;%YspBpK?DqrT?NGLBJ0}u==x0ny4@8{afZ^svNr;veiu)l3=7}5I4W>XX!gdC# zb}DsxaW$2ZJM4?g>Z;>(vvKpeNVWd*nupd@$~_3lF=jF<@glD;kpljxi#AEwF~X^Dj8{8NytfZM0@IrNfvuN zvGB?O<3a!GUaNjXU=))a8wtG!Ti_;d=5q3yg_oBlIaxbVfEy{ilYM0Jk`)GN_d0qj zgCy>|Hxlni9piyayHQ9hOB-=95_dDXFppaAoa1@t#)OnJ+Mwk%g52v`xurL%;`eZ9!g^03X`ToB)GR<9o;>DL%$Sw%gii{gE*I@?OW5Pd5X&LgSDbkT)IhNd$poB-4QJPJhFpI;IfTv$~~b=ByIdpas2BYmgtHtK-BK+Xq>t++}z@E+H7~bq1rX{ zjS04LQc`tW0{=sgm#e=#Y(Hp)$(G3>mU-c#{FG;DJ5*av#-V_c_uUw$;)NFW27CcbF< zB`jCv`V;9BdrY|pf|6nNkDDku-(Mq(yL~91F2?(_!|V9>uC6->@5)KZ8QmD7o18c^N7GgD4BalmwB>u9RC&1s-wQJ59SmfSB|O7q?OLuZR$@lu z^x5&M%{LW#Z^7+aQDxhg3lm`@!6cGq-cm?0*DjwZS%R-bh*b6CKW5aKdEBOBeuU;g zBe$rsuww7Q^2dOs_zOx{j->98M56%XH+B}I86G9G)|eOBdq9A1Fho$rM%U@qS#`d_ z04x?CbDnuoob1yRvN+^1xz7|57Y$T43?bj#N*1TK)d`s5`ES7LO!4e*wz;X&l_l*L z4F}mU>R)jNPQ^cIeV(6-NH#qIk1wX0R>aWZf8~k2ahBxCze{RD_xn$-Ol0>#mL5%I zJ#^O2T|ZO(L(ejHw1Sk>F`>AT_Cv)7)!0B283GQ~{tKAMS_wqdn=eK^_oIVGrfca# zjwZ%ByC8~U9X2za@u$@PHc91{~pfi59t18H4s z;|%_wn{yiU)7F~SY3o1Y!5_~wCi_N+ju14~ctN>-TuY`l#z)qjp+bN^Qb>Sn`K}i; zI@Hq8X8X(fwJ~}9!cH&sse7fjva_-eDB7#RnYv=-Rru($yf9ng3;jbGnaTnoCjNA3 zzBh);+cP|Z3>e8f;qyEWQ|!xYMe6XQI+Pd`i-a$)~ zUn`PRt*1I|jT4;g!30J5Z&#{GhiZ2F*_&_=bWWf;j3X_nukpUbMh#<3N=ltF;RW== zvfRDMjVdYd60OjZq-72=!fP}92*}ox7j%(TgkjQ)8&$|np3~5i*%Vjo!bMoEavC>C ztsw=v!O$a1IqBE9%!1O{_al7yU9T+v(M|$%!_crFrij5&S+Kxd{cx^iK|FtP=Lv=? zIg;xLmWdBZNw)L^UPcxLLI>O1#gC$kwbAP~r8g4lw=WxWyHBm(v{0y2q+-~|KcJy^>T zEnb?LO~p)$K39laoh+}_{*Xu2-ih~xxW8YY`z8X;NNNY;T++l4vxKpPz?9`NJd7jHFMf!A3DT^ zHK(W6;{yYFN6B_vj*W^Jt11tvQc) zT7O?N_^e>j8Ev_r=cr`5R)>SN z<4H&HbU8Uk)@f%~|Fr+{&z|yc9+ssDsz;@)o_Rwb9b?_K2D(pbcZ2l0n(se2Bvgv*wU1H>l zHK7E&C#>4k25Q%dW^FJiQ1`H`8)K4#!qC_5(1t`-sGWzP*ovAY3qE~^uErV|;8GVk zHJ~*1z@uEh>TAWlo-j$Ze%|01KetVEEA3Yp+U1%++rWC$Lal?b!DOn-eY)I1CLML6 zxS;}$4WC3dU<5wj1j}A*caz;c6-|wbm1mDuV={rA$_qJtc9nM~aW&8(QZCVX2d*CC z-BgGttyp>duDb5%bS*H2bD%&_$kpD`NNs=JNco;n0$cMvtRFv5m{`{7Fmk7$v}w$R ziRJ8YK17p%Wf{lB+ia6D{xOu?Lc-5}s45P5jjvfjN9B9>@vzE$l~W-Rm*O5;I+J=a zt#2{$@$EU7Tb)$S6xcC1n^r$kPEvWKQqi^yHGZ8Qj~pua##^i3%i5MI!x|?+TQ;bx z`8ZM9Zq_`4Wbkq98%QyTR`GpcW%W_Rg6*`6G;~~_N-01GqkHsitOcHeS%RE-Lb1ck zM}s=-jB+H1%FVB`JyKGo)trnBz`Cl?yrkL6Eha58r@a;{~ z)Q$I5vMTLH2ZTrYMsTPq9+b8em=rP~x;#B3EkRHf**ZH=BKC2s<~&a{hIgd&C16L#ULd) zFe8I;C+O3q)Le^J54*4JsWsv45^9>Jnp>sc;bl-NYs0?R%h?NyAC|%kBYoM8GGc-<5QP57 z)#IU#(Z$ka|Dk*fyat)({M_4bn~@X;yGrOU#E;K?h&DKQzoLW-3+d%OKE5_%vR6iI z7_3p%ozqfM-=ku3!@v1>zM4>VuIN4;wQ9`u@oAOi0>Vybx#ybTHMJ-{xZU5hY18&! zD_*CWn)^{{=!VV>80nnHaE~ZmrKYgaHd&iK18)Zs1bfL%D*PetJ8wM~tzNq-L=wtX zY|^%)B(8vi3_S5m8qUu>*UGnpQ`dTV?@{&adnSTc8sFIUS*x_M5bpK6fH6k_bx38E zCvn~qyM8H_@zZQ~QQ3q}LZ%rlG}}@rY5j%2t^}#T!9;gtaHV`%PmofF8PI}$fGc0J zh@YOZUBf*^(z6KuK!WE=!dc4ek;oPyl0sQS;l!5M;0`-3G=yhVap9jC=yGQWL%VSF zqLn_B=uJVibk&~P+|3T;iHRJ6tD^%h#1^M{M90kmLPMU&_IQ%TR;6wVBXE`f@=%_! z>LYl91wHjUyWip~RKQVYir|A;>G2VQW-U7na%S!Z25$IVUOs5q!Ew~6DpQ3nrLkm) z8*r0^O(w`OyjCts=(h)fXU%vzO{zK^>b0oWaIddHch)1UiVsWYAH9_BjC_ZFvy)>9 zYY(U|o!DRCl<$?h^VXXWKZz7pW>w0oJLTOl@WKsQ>G zOw4n2H9GoZA=!;RI-xg3RO=@u!0vw_4TbaDkASC1e~mnf$=Uz3>vxF=syZMLMi7ekop zzFtE$eFEqQhK3$%XuMTiX+>a6LN6&Xv9Ku26*BUodzGe0D&@RI6iTXN$75&&Tgs3? z=NBcuHLY|TTU#WA&?ooTn+#9Ankwk2Fo-`h0^YOFj-73oc_;bQ>1ioZXt1Bw);#VJ z7{V!;C_Q&vY)|GFT~h+mQu}H0e7eqS)%|J)65EdRqne}Wepfp*bC-?OTO^@c2OfH? zQ98dIgMmm`yVngf!ns&jW&3=M8$65&?6nDfB=&ehor^3q_o0=eW93<6f*dk0FYo&1 zOoOP08DBWz+76ywvL~q{Nw`iYZ_%=l&|<(;$=;@CA|nVHaLA3WF1(C;weDh>jJ&?TlGe+SLp)|08C8K#rc!a<3INiONnvj8 z5))Wc9cGsgu~G(ykukK!3)v-4=K-RPn>YKcXgRUFgdQh}Nk2QhqSvn2j(tXyvN^?_ zn)d2DI9Ta9vZ3|9n*TUaC}PKs#}f?=z**@SwxeB~_R@XP_I%eEdwfh9f(i*(y>q?k z@D~tRZNV=5% zj-RFg-l<`uru1bFCyfhtzQV^f46s0yAM5}uASS+KomSK7*!Xm`F`<#~&T_I!)5D?h zLOxG|iXV8viwC-&&RO*oz*AnB(=OKgiqdPOYb?T>z&w}%+j@V0$_#Os7JGR^HYK_X zHO|XvYyP^r;=Qeo-^O*7Pkw!cBBN_xPHhqcdfLDRC%mRo7Qe49RV>?wmvE3ovD>_b zrvkbeKob53g;{N_Z*PAFwta9j=uI0dsw%Iqx5#Q~s^BCJE!Sif5f!y{F`%Qf;VAy_ zn#H$-^==$UAX;>HOUGxfUbd&dm+tI3wa97ESkSKeRS^wN$GkD~+igq)&UmSkUkb&S zzReb6v~ji`sYc=BF=3Ir7dDnmJRR-I-j=Fcs_@*)*>np@76b(Nn$GFcQt1p2ek^d1 zvHlEAZ==2g*cN{2=w_zWcJaxk{O zK)SbCVGQQN!-+^e!Asfp0B+!$um|zun!Nf+)UzC_{&mmr%n}Qe8+-sO%A2{Ujv`M4PB|Lol$hJj5Xxo?@J+2 zG2_M`>a?@JUZB0a45IWvFcP~Na_ceK$2-Ig^7_Rt8|AB%fxG zClH&)H{abRCJjSejDR!*g*Ecw%E*tFMfb!FJY3$WW9n4w#R55wJdaYF+MHot?o&y8>6V4 zFt^}Hk))$XNREG1*{H>VVA=_XoEjjSVZSh;IjfW?v!_bx3w?_tRm(P`N&etXM z$4|s}zG%nPr8o%zw>%2W;b#6f4hJB1Z21jyaHGJ%VPPmhq`Je)3lMW1Kw#K9>~yFH zoAI#6rcSt11F5gPK}2E6tJ2NUI)-Lypi_W2KG)#~1z?`XR5S{b&!?dL;4#xDXOF9w zY-0f}PUyAZ{+YuBpkIN*B#`bbivX`4<re8pYTAw~gYr;^{J(L3 zY&|pSKzH3^pmjlABa9;c$rztidieJ+%#Ydv0bs2Z^M^R7MAF490rZovU%e_}5|)y~ z!T0fNlxz0SQPp_vH8K@R2CN{LYBX}R9YpKQ)tdW8^PZ^mLk|3(9y;Pgw4Vb*aOPWp zWv6NPg9(2L<9Eu^P|k%wj7I?~P`y3FY>n%#Bx3;ey`#A=m@GvhXU49*w{q33v-o5Z z2{#sDhi6d(1IU0D6N7kNJ4my?#s^$4>jkO!;hr6d2Jf|@!4IgM*2X*bXz$SY5j5=W zbkJV&;>jcAcw1hlM+f-Rc!%>CZIy=6d~|Z@p{kl$@$t*?FuceL`3?;*(JD zn64VLz9A-&R>?a(ue0)s6jlt}_HhlEwsWLAIrYx5k3wAC1gl4y)65`V)xJbmg5Y6Z zR^|3x@j$m@SC_^WiJH6j-loK}(->v8Tu!PWX?Y;Fk7L63nuFTU0x8#Q?gSA}_EQ9T z?fY>1FRxWH{NQn#(KCI6@CW7s|30truJ{P;DqcxX80Rp7;NvQPk{erTqo>i1wh_%{ zwX@Bf*QcJfdlp#Jk|LnMl*zEtYFU)qjs$AUmd?xEg-KEUgRmVDV z*gV{B!Ha%xZ3r>K6H)hnGTZM4Kt22r$>TN5UVaX}BQRF?UK(=G3LFe|}Kwr7KE+ywo~S03VZH7Bq>2P2-NKaEN4Ymp=Y{bI6eMS(|5p#{d<@TTA)}e$$9!A5!+zJ zfJk4pCc9g!{MwB{#Xb&)Nj=65<|o~LSa`xzq0>F_l0`c&$AYFT7;{Pz#Hn$WLqT2I zfR7sX{?u2^d(bV%wUycBEyh9D@eOzQCa)*g8wC4cE)APZK2$0g04Hu470k3eLBUAG zmdM|>S608&u17t#oa~gMM2FQ~Tz$thR9Aas9JZG>X-coJ#4+HbhU!oS3Jn|=Pings z$cPm8Fv>}7^%`25C92?zxl?O_uHjR$Z`1f~_OJD+Fnn;VFQdqY14{{893BUZQ1AV$ z-wv+(bi#Ky(DQ9c-SXrMQ%M2zdj6r8bkxFpZ67@?S+E|pxTgGgD3P>Dq#Zy(X7Snr zVbG36g~0Wi&?$3d3<=?_6L&DWS|2SB0%ah(S&=M;#g{zkC=4$cOuS;}ZIFq#khhnp z140y=&bp6<>3R4lyg~cYC}HY?9}fxdN979|DdEX)e}7zPK4%DQGhN^?Gj4YQSDfy@grNZ zYu~%WfnJR>$1DPcu73d%jEv!f=>@s*2s5cc-&t9wtCs%)9l%$f4`8e7HEFP>72UQB zew&1JJB#t$40yY{$cQ9`Q2p(~KO(|H^W4e6`Pmc|v9iia@)8e7>6w_XBlmkNOLqI= z)6Z+%^9>b+&G~i-a~mG!yu;sJFqgl9b|Ivx6*!S&qTCoPVxxCO?LRpH#;LG(MWYos z3tPtm99z|?h>~UCXFGf$_?*b+cu&cZNW&O+Bsnj{Sb=8;-OF&u>1`ad(D~SpXtm!4 zM4PdMKVBI|4i0Zg7~3Hbq5vyY6$D)FFco&zs6hD~>67UTrcP^X>p=E{sL3qvKTI+L z=o)vL-1y4tf4Hr=%8mRdkMlR%#Ea?KA!zxMIUV&);EcYLmM_)9OmFDfPu+z!%sa~i zIPv|@HQC%WziWR+$6zMgoswDJ9-U`X<1)DD3u51fM_*iE`F2gnd%V^R!s`4uJG`>M zQu{cOqYu#trj+2?i~;1Ui(>DClG#w~8rBv&p(8=AtFAtgWer}8kOOed`uWQWc`r;; z-S@`f@w>l-;`(?)#%04LcU?k|i#6Ht?a^@uCF|L9$G?+OI5VX8tJt#;`Zom=67o=X zg8Z{Kc6yZNFXe{fj_q<}ZQIqG(h*XV9PYE*+AnEf)8^18g`>guo3IT4xDB0|D0HR> z&u&DpxJ~d70D09ndCJ+OExiw)Hy4c&^>2wMGI-0`nNLtIt^kJr2B24#BV&7PX70wV z%v|7B^6Ak-HB=Q3xsHa2@BLiwFYh3@v$K6EdS5htgIMT)uHtF2f*K6}{!XzlhU)Tq zIyKKu549ej!N^73))3i-|C&b09I2JTIauQ8Dzd{c+z|B9MPs4JQn6b0$x^xm(3omg zw+O0Z?4V?FXz&Cv=|HLb1VgjTgrH`G)8@6a0+Lzty)*J&ndyeN#A@`E9aZH&})OGW&$ zO>`TL)Tj4Crbx0SS|!VgABmuhtNy>fzPY)%`C*w!=|^v%T=ANC0)aq70x?71yAo2% zPT}&@H=~;7_JKH_!8i%b@ky1#epvpT4Chss2$k|mk+e0|h)SWbbD4GO6M>5!6_D{B zaD(t+Y_UUjZHsjThGH31HOeAA66eqp31^%-PIouw<803=>LD?Dp7!&3&3H%q3@u`J z0J0Mi`V;4E0hy`wWxZub_8$DLEan4R`|+GxTLM^un6XpB$r!w37yPOG~zBqBu~2NaqU|`36Udko*2> z?EI_oN{+v*RIRKeq0ru~xx@`Ce%*;56E68PlA<|{zt{0TjYa;+$NY(y z;fN8OVn*zN^q`Z+b*l(%QrQ!&g8t)Pxe1uJRd^C!uwH} u^Tt_8OiW5oiMIo-F!7msXr3HXAo`n)MNz!|z@?*moUhtkw|-`IC*>ctc!7K4ywWJ$3MbrC$=$C1m zGW^Hp1#cYsk;ZoxQ+NJlXX@-~;AjG6W@~3-!sKM+XkudPWNznt4$~#@k%{rYOd^gZ z2F@0Cwq(i{HYQMVcDBX_?qsYiWODy=Vr3^|Vdv%G=H*}``zfa?9N7;AMFu4$Dx~a| zewyLxg*7`Ll9jS5cmCBPAKfD^%Gp8*HlDsi9g2`FROeIM79uB_54|dE0WGvYwDd2= zn>86)DZiWAMeDY6(zHNWXbVD4(EVmz7S*paezvyjRi|a1Ff?H@uq0)Hs7w7P3{bu! zg_tM+9RHOL@R5*}ME`hXA{-Vf3ZTPO5~akDN{Imgz>>p(jVo3x1H!|qlIzHc&dZ*P zZjFA$DH~XtS5K9UK@0DHsPcC9r75F&^LS=n`zKZ75einQ(=?{Y?=Y7|bO_i<(0I|I zLvYXCj2P2B3)}!yU}Y@mC-5FWlCqjTifb~y?znWx1QRLx5HCtmVZgV_6BFz~2Jl)) zek}&;pM*oy>Z|5O18StwGLxS=IwccLzE0G~+(cP!eK0m09{NKF-LZ$RBhwsbQU~o5 zI?FMggi#T+D-125dvZp3V?A5t#IhL4Vd5e`%;Ihcd(V0jBTC)&IGS9_cvDrV`jj0S zTG=Fww=C}HA>@4h-(z|olOtQ$K=LnJIPGK@IxXwWuYNql81pM+s)aMOH~YL4jN>L9 z1fYEFNsj>)5E%J6>~9dyXOg2Sfq#YZv{O?O8#oQS;#E7;-Xy(SfdYkyh4IBoctEhE zboi@iKOQ2;>iVsofPZ)g9X^~brO0#bAOWlQ^h$vJ)2D;pzDZcP+ym+L;P`kn@@h(I z!>H&%=d<*@3c7CuO|XFwe5=NyJUKet6BXKoDJOJ?>u5$wLzK^dk%~&)|S%yV{x)9tzc+3jQ;z z4}~AR+nCGElhfLkSD}hL@d-v!ual@u_uRbB79?{apWfS}?fG3bM_+0^Wp|3 z=|aiGTv#-pbky-mi)bocSHl?=A?z>%Zv|918;dhcBgo(IouN@YEXo5iIM$ycr*|s zKX=E*KrQs=1MX!kRxlJ-pzZJB_XBjqfrVO+`bl8<@LQq+)IITIGD~XB{p>W9^WTxR z=gkuHv`oNV7Ksk+!Vaw)l|jtOhviB!JS3DxQRs!#Se{}ZA9bMK?`#e(iDRFy+Q;@R zof}wz;fJblZ}2vyR(Q%yxP-2n&B?YMn=b@w1zAEK48kkeX=X7oH^PV)QJ zw*#n}TV&;`KUI`nU5U8Fj_1r*;<_8CXp}PkoDkl`)YcZPe1AcmZT>Nv&4)F zw@~SV(fwG^O1f^1&h?+0J};)%V5*iSP+84YJC70Ek@8Dhio=nA`gC))l2U@o_d{7d zIZrNr#k4jkE>EtRNtsT8Ql)DDl*4Ml`|iZ1g6r%^g*O_nr*A@VVyMpSa54u5GZ>{n zakbT})9|zF&0*ga0xMBUY~sN2^?u!T_a})orAo$ydJw7Wsbev+sbXjJe2dX@%5Mb` zfs}7G+Q)QZ^t+(^qucg6Q{*=ilKNuB?Z%lDaLN!rs=(hCnI!d#qp}EMZZwsSyWJKv z+`$W)EaSG6``kE8hadtnW$G%;?HmT$6sV7C&_TkCN5e)B?FoDYUU&Ef;e z1i*P+Z%1>*FFyBtvEaAYUt34^xHWu1WUhYxNA3|p7-Dz5C;I!Szpl>Ah&APEyu|Z< z6-w578(EuxUB5doI`NQ1nf>j2KkG7sT8QUDu-FW*#!3`FAJk z90fk1KC?`N;dwo$Z*)VIzv0VlEPo^?z3zL?*iC|KnA->A&V55lm(0YiH0+CM3~My; zFV;NMTO5N7Y?d*$w)+zEBvPu)(JeGI_-0zzpajpBAP*A)d8Ybgs4i!+rMeT$&-c^M ztF9V6CI~iG^QPKG@-rwXdv#1&@b~v-UP-{2V$}-m)AbrN)TeUB;Jd?Lx!1sc$fV5- zEs%zqwORtzQe3?D{6KN-;lapfwJ{P|&pW6rTn2Q?g`JTaQ8}UD@TO290m-tm8btGW5>Yvq;X{`+lwaj6`YF9jw<!seCBAjZio3|^EbpK#?7HGBpZ`p3PdIeyvR@hP7@sv zNLzr`dR3_6%wCb3_vn0WnkpvFO1JO%nZUfP$3mxQ8+tb;kMjFR(Ezq*BOeGjxyjkt#SG&DCf~PHNI{#^uC43Iy zH1lt7x1Y0oJiRagQc~~PWKGr4R5;F+moGO(V|8Q}J>T>g*TfjGeC*k?=57a-ZQKNe zBa;j25<1XOVM<;}w_etagl`W4C8z@GKYl=+9j|2w@q1qFq6+E*A-oyI)zy5TKK)cl zSj+exmk1VmnJuHDXL!Cas6{1iJuG9bqdWmSXS zhcDXejYm$;?a!W~qO;XZ=;p_|z(<4Xt|9uzxH@x zI?O#h=6JZpF9=A)ny@>5$mrlE8?A%4JC`FU`-d&DRB`d8g7K4)$crnlpid3B4t7k) zh50u22QcM_76(SH8yM|~%yQJT{KIA$qo=)_d2HUP9NQNsi{*=TA#x!o-|YI}*7UkE zA5ra{>z0R z51uX5eX&ze5Qc#Pjac|o=I3K^4_G!hZjItYJGD1l{c!j#PDo^p8SAAi&J5cAA4nZd950UK+9jWD!)Q(082mA5?5A$K5aevfz$1;Mco`L=I!?c!SW zp^!>E_^InsI_1)~c8`Wf7*u0Y>>j2K8?Fxav!=ICo4)PVPv~S=Pe(8p6|OZ}xm{ik zmi)?tqbQQw4##Gw*4-!X?;l{@s2M!??!(uHLP7~(k3ahu6W2)q3W=cZ#zGdCo$2G# zZ3I3GREE5Sx;;xJ5LmumThQ%rjmu0eKvO9$HAH;dq8)MFU|?Xs%3RkN8?o2S!{e~q ziWX+X>#TnbreIvH$?LvzQmeX}JDO!jK`nAuj$gGw$JwXP@b1pZ{F~8WiT)wilYEGt)_rM4%=;($0*cOBinObGrdKmu!g0PiUm25Rd<$s8VazrvQ+4z7 zaAc(pu6Tb5STr;k$d{_OUcvKwtTUZ7*^%T$CLQ0er=M>OG|$)E2XE~b zW6A97_R6&ela`w(0<(o~kG$^tF>l&!kM8y{sab3;4RLH1dpm;IafbtrgoLcMTI2u2 zYR0#gK8uZ!^`o->Fwl4o=N){v|3qfS?-6m)35K&q5-;a^gUXj{gG`R+&~b=HoiJ%w zUpGS#Wo120hOv+q7hf)pt4;)eM{tg%)@+V2r@Ri)5Har(5? zUbUcVWRtioHY^&*M+9bb(FL@S&;eoris>0uL7;fa%Dzp+iw~Q1S3FG8p=O(s5|k0s zQ^x?SBpTKoTPLdRu#wLxCBRPb7c^p6bA9z17MO$a**^)O1e=&1^v80X01IR^`S1iy zHo7Mr7v03(Zvr2Sd>4sj$6|D!&PFDdFBu^b1(n^}nj0Sa!^I^*j_^zNhXDQx|04~P zg1RkiF!Zy!`)DVHA;XEbE^tbM8TvYb0q^%|Z-I%-2VkE`2gzUz8c0cYS9><)jnTS} z7b5JPa!wT$CK3n~ymv&8puKnvD+6`mCDG|{f;&8GC~3BrYA7r}BlTZr3Be zR%Lsir)5^iE&r&Pd@cg193NkdlotFV5kp+|pV=QDPP3)yEus7OWlDeSj_la5O$nm^ zpB2n=pb7rD>kz); zKQ4&w^iZdsVREJ=1rg3egbV-5_~>tH0mEYDRiiG1h2LJ|_0Ix}-K2P_GBfmOG9sML zY=}L&a@6*u&!Rpgd)sQO@K~_iPQ0KXDs1h*HC~vp>$sP|itWO92zx55 zxw-Df)at}`d8MsXtQNceTrJ)a3AvU>p(NT=pStWte2d=7ZN=Cl3a%PQ^)vp3fm_FH zSZ&I)Q2UPK;(Z*GV!3q{REnK6-~+(0>>AxkDU{{RTo>l=YGns`5YN7^^HotkmooKd zAI1N%TFByA8&spjpL)1H31)Q{QbFgM&EN&Plxv5ickW{IH{XmT~@qN+vw)jQ>fn4ne zG=C}j#y06PK62(D|u zy1|{wU?O)?JMCL)GX4muS^m8uo^9!O7oB7D14U#(J-cju`Ggf4sKFbFf|wP!t8mFP z3G)7iO#0=J@YCu4Rx^ z8rnu9QG-Q1s^0@5$3ouGaIo&5ap=feu&^+Ca^hi(lM7sr^PV>V${h+j@nE>;Ml4m1^oJQZ$ zYWCbHd+Dtai+^}feB>UF3to%-dWS;a=(nTvQ<9+W{79EoHbJms`;>B&4Jn|f8&cP3 zZuRxDq}h{4k$)*<&7eb)tH5ZKGd4X2yzgCH8dhrgub2Q9TIDl`9hLNDDkt_IR!=|+ zbJ=XzqV<4vtv+W;O|lIMNJahnN%HTpSHc1&vzc8gEIU;{O>;kVtc(!3#c<_9M!v~< zr*nP+v9F$BrLKIBelzF&fc{^=r8K>dP^H@wufx+7Hqs&|v#5$PI{`95Bu<%lxT?7j zVi-c0;qyx+hXXxl0S5SmxUdDB87h0<7&=_l21z9wlHD28$0<7b$&as43tldFsqh# zFc_>75+=m(9~eP|43(_( zxhJ;p#LeTzG5|~weJr8Cn>h#0tlCm0qADtYUST2|@q|HRR!k>yoVvw8@dggNK$QSB z4l{sNTb^b`;QSpK#cXd&-aMahq{?R=ku6^gjUg|l(Eus=H>^;%U6PeB%Qp08hU?I z$RfleXyjMwts&z*eTe;8EuViUF)b!BgX2j)B^xngyK9T}+5!L}&{VNg4mLI^KS}}x z`yAoL03|=;eY3m7H{ZY9I2pC^dc?8x zAR#;PU!kG2^775~=707#dYT(8er-8&y!6elGwvptDUfj8SF z7^0Aw|D61dQLl@ncw;PuL9Oy)fY9z=xdz)nB%xYuoZR!{x>Z@p+lj|sRAfIVGEMql zu6>MUD;B+%E2LF%*d-Hi1KK>7Nu6XnRyc(Adny$b1vxPM!rYGi?JXu9$qz`6&~$fN zLr*Uyr3y{J-tBfpnb^Nov>5@4gnVFmOCKMI!2UYS7q{2#X#CYKK}0=IWVvzU#w1eT z^tWif-aO_m*}+66hDw^)jEu2^$vi0q1+$rAMJj=HFE{?K{syB3KkZLLLd&5viLc}7 zo?btpevR_#k}k)6C!E=iy7NxCSmOk0K}D2%mVXlIjG$=hT6wt6n<0GRNh*(N@PI}p z%^c*4ZYr`>#&Su$HJsWq!ecCYa2_@C@;!vjifT{OSe7&C#EpH&(XbF-;dSXP`EA4Z zbO))hQd448Mmd+FIMas1iNn@0HU^C_(c2#1GHNy=eQ*&tJzw)hVj9z zSJQ7B2sSu{%`7%0WhjKyCppQvgwl90ogCPVGil3p=5&ilwJ`W~G$cjPfuQRP|8SDl zyTSI00qqEh$5l7D}Vp}oML5dPK{SSaYD)Ble!K@ zc5rRGBrjE~qn>?v;db5WRh5Y-@N#wTgo-m!xKMUPd1cy{sYl5uS&dH zuEBB;_l%&<8_k!>_2Y_&u}=o1@YSNPY0?O{x$dKYg==*=4Jb|acXHTKPNg?bYS<%! z3A-Yey1OwF<~u~bKy|)9?i*%N&@Oo@VijzGLWhjE9{01%P8Mp|EvE8kcAEnw(9nFt z*iz;NXK>_wuDSbk7ey_5RbpQN@U9~riu8ZL2HZ5dC_W7nUcF#z89Bb^Mz*Q zOXo18ge=#X$Y`=#_NS5hjy`HJ21j-{2EhzkKV}fjR*q%%g$%K-;OU(9FV<OTKczdJ_&v2d%t@`*@8;c?By?h^~(P-Mit!(|gP4W}D zYX?z#l<=}4)_xOX(dW~{?n;VPo&Dz_kkmYf6TJkP4hU9%)2hmVg`mZA6z^@N<2m@% z_jFaJX)>?HwHKE4)`J9(FS$Mfsj%}hm?=paCB=hZq5TTsgD62dUT!js7>^*}2zz*N zQ?1e+dwINeKgbEWpg#^I+@IsS6Lx))BOJsUx#sh7#VmEoT*qne_ir9=7pVON{PVBr zNngP2*z8Eq6W0fK?&7IP!d$=sC8tz4BKmt#qupk2r~$0bVz;N>OZa4$+T{_h#(`bL zA_JH^V!-9Nb}vo=@0$z#s(5svMgSbU)dHHBBDeDk_xs6ubW+F{nKe&TS1zt4cAMc3 z6Y}cAs5}vH4)xJ#i?v~|-AdAH#v`35vg?#G*Vl(!h?1Fi7OF5Hu1A?qgfH(LMC5P%>l8yosni-| zP!Is+(lY8bMM26`!HM9W@M!*l8f3zQwNCG~%Q|X>z2z3COM9p7ysECfYix$%54yKX z&u1vq=N0OwD4puqF5J%{_*Uryx2a3|wMpX-b`J4S-mnA8>KK5)N^YK(?CHaQmi5J@ z)XbAAKDmUC8?gz_A_Q`?BZ&Lo&#KcZAjs0n2AN?}an#?u9_(MFS@8E7b6f`NdROQ` z`G$%HB*tQb~qdh{X_dx)5|)Ee|TymbCs+TN3@w1G@hy`BJnG1H0QA`1IpD;KQq1A`G90-j~U*j){rBxY$%6zeocBD}M`| zl)RhFYpM`9{I7Oahh;u+uVak#M?=v!|6h;qiF$%0J^9jxzSlssYdyZ-M=$cH93K5M zZz%Kf#{P=@=TjQ`E6Wj^qUj(idiOt-DY}UDJI1;$bMJ};D`9om4L$O)q_`%tT z$zqI23vTo%PO(@CHydVc9UTWJr@q-)Y#JJxdQBz*xm`4H*wtxgWHD_R9I66Wnrm!z z#yjEcpH?AVw-C;P_fZ#Zb{M?J(@EOauJ#y-)Ta+|Bcz}AHo6A346oCV+)cuNwa{Ee z#O2cKO+((PU;@E+dl-G`BghA+Kkx)BsNT0uc!M*J5G z5Yn()ld$iUiU}9xD;OytM{#j`Q#7Z8`CzQD6j?*WI)C}|mX_rGbt$)WCZX?Z`90%% zazwhOKtkp%jDxGgV3#x( zTUyc&B`MT-_k3sMx;4{g7Q{Lh>-4aP&$=R8KMUX7VV*$0>63(eUEfR(RHJTWR+nFB z-_AEn-)(DCxIP+LcN{`kBs9DHH($xuvdIWaimrZn!`kC}#;0-26tr3q|E-)hQWL>` zHvzx%tjO=a?2h9*I9PM)z_i}^#PelL|G|nnfciZ5akaXBO%B(TL z@$7Td+Na5*N7mbvMK&|QIpyj^n30+k_ccS@3J%+8hcC;gPzJ_lbHda2rjX>kvJ{*P zOrz(n@yg>?sW5NkSb8aJTyzSp!a2zN;1^O-(ieZLNsFbfdbeAZGeo6o-4`%(Q`1h% zJxR7nDDxjzr0tA-UMH{FiS!yMT395n;6q}6`ze(?k#&@ZBFb36k7ZLhEmyDJ2oHluChM!A?zo_fc!p zo6?{zJ<5zMj|_**L<**Xj?oSmFMIk8e5>N;e)```8M0;iuFjfVUf$_aa?<0Mfcp9r z-Vli;^=+C4wks8w+NW^qZtHQ zh;)Wk5G}B|WiKQ2=;TkxukrO#%VRzCL+$36AESB!p>M#hOwUOU2E;!ye_lFmiO-9o zA01RreL{lwlj=HpBu(e1{HQWu*7^FCWW^gv z%9z6+M)>xo%kE_f^WMIIhU_P~f3g-w+u&_mKHmT%@`UI9GPrK;`1{M4gtufMy`(m8 zLd}SX#?>>r2i!54CzBDy+Nf);bdGo19{(uGJ-}?x&g6av&W#pFe)Q}|(aKLO;fWTu zOLdUwXVEA8aZ0#JZqcBTf_6BmguE~=GXx=rUX3Ji>C_*;js=2eR{P5om`&ajWTz%< z^auPt7A1AgU*@hwWAW{ypfq{?_7|?K(bqptPmHy;Jdax*+Raw#f*3fmX5;7klCw0` z=iy(SyUs;Wa5SS3PvP##Jr|XA-^-Zt&PIq^ISuAows%V*sn~sX=RSX{=roM+!w%xm zsAZ{wJ{8f%a*^(K6K`Kjm*U%crj}m7 zU+!@`1|L(sT&VK?*S0Y1F z^tp7x|0x(+{d=0{-=QyK%3SwdxW_N;gUjCM8*Wa})1Msn_Hzo>V8KE7(y|!wna>lJfJq4f|2!qSRX0!Wza|_fS&|X?q5Zq-S(vfh8?t-R;U3n+4<67w7 zAeap`7YIK0BHdi{tYm3>pI%|buCC-z=;TVg;nKn&QVuz*i<-VpkqFfk1V7_KDA*hD zIq3sU?&m4;O-c9ikxUkci_Cv+?5#Wzh`tc$lJEyX2FLtT_z_7AZ!{NBc9)I zYv(hlm978ny9f_bUu3dp3x@3xK+LyFJyn)=D?m+ zpBd|O&q%Y+wo#e#q9VRZ>*r4Dbbj2;Mpz3a)Z0pPzy{_qtO#@EDf zovvJtcJSiwp09hwafg@NsAGoQu8_RXCJAd-HAV3j9R*f8-^=CwJ#2T^68D;(#qKC^ z)%Dt)qSwMA1lXXiWWL{5|%(6B~T7;BpeoIc4k(wfJuf**s3$9(0RXaBve ztONgyb&>XsRybbjhCBj}%}{b(>IE}9!7Dsl?+d?YrSDn?E#6;#Px<=9Kiva2%2i@I z?|)JMwi7LG!WBaHU_E`_*3Rlt)qV>GcdYMj6xiXZ`ZA6v!IJ&ud-!UU8nm^0sE|Rz ze06N%F!E&g<5zg1O{={bCe7%xul{VoI3G8lRsY6Ahb{B@6fGR?DF|b3Tq^xmLhc$$!^Doebp;7DQH>xKCS&#cNEI z0^#wRRPh*b`*C0WMKi$R{o@Oi4({(t-*Ujw=C5<)1{jNmr_E#z`^$qt8p#mw;;HD5 zxDJVP7cvMAvziMP-%zxjXMP zCg-X$-HuRSk*QNrJE%291?YW7#vA4}-0IV*=dva+3U@NLX7AQ=AFV>dir@E|$h;4K zY%0FH*GxNyKO3(w=-Qky5k%<$?gnWSCLt< zNGYvAA$W4pT6NC)RC89REEZ};oYz-^PzhgNs#rE9vC)CU+!i&vnu9PE_-Xk|FBo6+ zIh)jnL$}($jRgG)dC;Oo_Y+^kSwK3>>{x&J-xXd6lYp$1XSj%8lyMshU+E%xX&VJK zL=LnGLPK!QF&)$&ZE#D zJa&#FwzoCb7;^62%FqDv>Kp7%6~Ssj}-rR5hd#^$j? zhCp314@=~%;91^5B`WS&CU1c5CeYkF)p0^+GoOmuh)L-65q&PVt|b|@a^u;_^?K^W zU80wa^ajig$M{Pc+Y3;q#8A(oCvoC}!@0hUP#FTL zucsec1NXa(-sHYv;T_i4KfZ{uqF5JL&4fHQT3rytYt%E8KVhn_o-SpTYPLVY*v1~v z)2C)H7^O?%*58czMg-*{O0Yfdz;~XKCZt(&vZ}H%HVC#k!p{%KV4?HMofZl3kzMe9GF;~$P`;5M(;|+ z_I;Xm*W^!svCRnQ61b4oM!cD)&5+d^LQ-Yh6j=@>oCVUQeYhtO-w!xv-Hq!4 z$xTq&4ibsG;E&AjBXrI7W=rVJ*gJhYV#Z2B;k#BPmG5$6HrjjZ7o=fEcfCTz;TK4C zWxm@troDI-g|}AO zSiHAMUOIb7PxAg0^Ovz-)M~iOP})du6P;U@v7=R@eI>szxppksDrMn%ia2*JZaJvt zW5y$e(lu{u@uqmCA6gFrB>@#(HEaT{|BI zWSg)yoW-FmnWzAJR=f(Mq-B})J}f$f3pc0pE!U$%erwa60kZOz)0?-aT%*$Ui*KFf zy<>R2#u7cr$4A_`44cdg#wyhGRS#pNGn4-8;tI1vke{MaKtroO^CHZxStszq`5IfX zLL!vMml{4C?K7`x5QoZ%=0(hbwxFn6%QJ}JbRf+Aof6U0)k!rdN~LXoOKw7TaBNIs zZ>z#GnN^abb>mbQQiQW=S}F|GZS$q5FMWwsk#Z(+J0`LT%m-YN5^p6)Qr`Xl#o_-i zG&`XOV0+U_14@dO_sk?b{wH>SK~9vuE>@Zn`_J$b(ol*41}N`a`sdltSZdY0e>A>m zGMOuDH8&#wfgeuXm6Dc5zrVFXl;C*S+Z!w_+|LjVAqQ2VGC#PV*jfi^VHM;icH=v( z`Yq5(8ak|?ennc#DBT@?85GXqz<4RqD@4i4P;>TO^awRTNvpZ?PnCinBL%EqK{|Y3 z?aP1W?B)%cSYkcK^o&b2qJSZYF>4+zf@Y+@_!xTJiw;?WsO0brO)LXh3m|vaa`Mo* z`Fk6N6M3SND1MCO8yjtyf06^6xJ^`yIhL{t-M{)0Bw-~>^p;L$N;T0yG`zaHf3!HG zAI`M!&*ZRkhOo$q%22XH_FfTr6~*apE`HhH^reCr)`bSnte#hnL~g8S`tEag+=vMx z{T0hL@;f;3;*LS_TE3-bG8fjLd3}GLU@qq<19EAlGn2r2qRzZJYn+kd0T9C;%Lc;+ zO++`UDUp)mV)u>xP2M&?fRc`Bl|rbtTGZWt3PRMVc}!bKUK6a z#mf}`Sqc>?{wr?8Ym=@F(>Ei(JciM&IMo2?hwRCowUw5-zmm7;N>$>v4E;gi+)cpLpu7F91j$hJKAdHv>O-YGWP`INtI5d{kodh6SDgQAp&+ zK8#sr(-=$-HBJi&=#<}8Oa8_SGOioyDdL%^>i6MMehi{~e=qP;7G|XWd7B-VDG72w zguV_UJlC0;Z&U*=SL+dV=1bv+5IOlV&L9u6^>)`LVe>*A-Nd!H*>=?Yd4s;T)4@cu!LQ5`MW;#@g9@TGb4TiT)~o z*y1zQz-JMe*?~JLj#0ba(DeMP z2xvl1s)^-z8upDpT?Hi(8`BByF16X^m$KT$Ap*x5R265o_I#*)#pj&p9}hQI4S8s9 aq(;y#)c?*)1V8@mfszuF7p)Z5_y0eS_g4G> literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-19.png b/modules/masonry/docs/images/image-19.png new file mode 100644 index 0000000000000000000000000000000000000000..4b7f10cc00fa54325bb0132d1b6f683b4ad2f9f0 GIT binary patch literal 13707 zcmZ{LWmFtZv@L-Iw*(9B?hb<`xVvj`8GLX}kU-ENg9Huk?j8tk!QI{6?KaF%8F8G$OOnRFfeE`(&DNxFtGH%_e?~1;D3MhBP~$8g^0?i zBLaUuh-RU{F}{n0wu_pBg^RnfvpI~Vy@Q=OGsM){+}s{w<=}Dx*DefHVtTD4=4@{4 zV(nm0rfzL#4x`{;Z)WUC#=%CW@L$2fMaISj;^qf&a*`=4_`5>>!N8Eg$cTSd_eecj za`#X-pYK>(nT(eaMb3GH^i~w9Ri>Q6poxNlj!yfHxw)$bW_Q4GK3D?xoldSc40QQ3 z2>CPUcOoXD44Iv3UfN0YC$c=+xFIURdM%bX$nr(HWvAJ8a(xlDgbJo8B6*M_hm8~h zSrG6&22V!ywOos*l6n7nN-dU30w^#QWn!^`LX?mC|64&XomXwhqGIk-E<;7CY&q*v zWQitrajlChq6)e?0b0K%n)2C<`eaduf!66t9i}L@R5C4nSbvagd9U*mC?V-%$xOK= zHRGMKx5w)AZ@2>Wf*NYXQHw5@XTiLJ0#$Kl@wmxDt>$}}`gsXW#<1b7Mq$9ZlfnsyUc)bt`*XaQhWk1ySoA4W-4>LtOP~@br`)0*mwT>+q@+VlsJ?w|dd|sw@ZRN~>XICyRKYE! zN)Tq&;jEC1iaZTRGzqh7fOE>Q6_x80gFXd?qumUP)J^o=Jok9LT~|VaMWQznFv^{t zK>ft=+%JZB)Fyv)v$YwL{A+ykP;c$v>E>bH}N3_9;-& zG0v4$io*zaOE)Y=^c8BI$YscvDC|T;L(ffTs3a=2*@y)!Mj6t+_bd<^w0h-ckTA=3 zJMVqiM&@GEHOfbCvR_icR!){ra<}hwS?f%LEh~FxxYAyhfIbz@=g}f>EnQE?6kX*g zxV*jlB?$8dv6%;f&VrLCdn{c8^bQ)1au1J2_1Ot_{wF5aR1rTYBI{rlI)^ZHsUJJC zxWTYU>H#zJSxmXP8SaY;xH0yZ`@!F*+EnV#{p)!e>_stAWEeUq5{N3ohre633z^`-;_37^k~~)u(3|BP`i;$l)UQTImK-!=Rfyr)CoK z4=I?UvvRqzsB3RBvy+_np=Eun>PAHlr)N)(On@(NXS`Q`HHvdg`Ic1R@M~XizWj~Ce9p2J}*M80`7SV6M0eS`9nUn)>z+`mr<>k=8f6u!q6&S zZXH5uz+RIjAA-@yFP5TXr$jL%t@#1wHE&lD8RFGo2{Hz@7Ss$K} zFF_l{QYmgA$VW*aei(bp7_%7V@(lsTV{ggbDKhj+U-f9hzWb`} zv%{5*4~_h)vnVVh1?5>X+cyF%T8oT&?NXmMW4NOgpSV>#!^|;}m;TL@Hp=@RwC3Kd zdNbv&!DnXrH{4xT%Z*B98+j3zL?XQgjbAnMducO4n&H9mDQ9lcz*aI4`=qC;F5$0I zH*br2H|o#l{sfAyaZvhM&%2 zz$LWp<(YSoMk&wNgHOq2Pt@ZJ*^2Fgq=JY@kNb(@5r?6$ue%wQ_1<2@?n=A%j6s_h z^nuhnVm9dQ_v?L$w13LaAg2I#%TbG`>m%FSl@~`wGo{3qR6g&7WhKGSFUL#CkGC7P z^Q|dLcuXBjQ&3)7h4sP^(mX%yj}Tl|8ZN#hOUX!z5{qGzmEL4myID-Uw5UC~MA*~o z)3sfPqg1;}UC-N#(K)Y2z9mYEkF!NM?7R+DkE0?w-n*ELMt;fnpFg{WcN5@AEy279 zj-nNpXInC(wWn59thMA$-hd#RO6#U9`DWO8wxYH(~8gJb}#BMnbN_So1Ek#H)W*A?vQ*7MVy%ahly??Es+8}fNf z`qB@ljtPptf(A>2r}EH9Wk!Y?+ z?T>byowr^Gnt(@hoK0UKuMR4t%mU+=5k)ebG~(W4)iRrp;Vb<3({g9ja`2#hff@JW z?t%+EkIjmQ)1R!vX-iR5bmxwtweL~6;kkaLRGFk;t8r-=f45Hwb zCJgsRIq{Q|KiqCEw_0N*Os%wSm$ysH%bD7|JSUZEs&aBj5BGg49y>LgDN7Cgu_i7b zAw()!i9^fZjE&XxJx##Vda;2B3ArOPT?l`=nHMF2wbz9HIsZVH+s2HR4#uYTSKCrk zOzN+J+J**`DX8b+$7HGK?T6fWGGQsb3SR*O0J|taDJZnks@xZGnD8z2`eAjEBM7ShxB}lzMVk^+C541Y^l+ zI0SXv-1(c#Nf#!%!((?YxYDRVm{6uCby*AUj>hZd0sm;_ZWLrLc=VlqSoSCY(DLZd>J#$^_BLJarO_n9qRp(DPctitno?AxbR#K zQHd#p6A3Kc9y6Ev#lt<-7dsQ+X{Moi!`-DzFBp@!*nuPVmgmQd$zp>P6}7z6qw(C? z=jl!-cAD?xqe8u3&o<`#HxbGI{JA`wjfvhF-jG&TkE$xJx8K^S1>y=RO^K3C+aCL5K(^3bFK}NiF-2 zm-wTMLc=$na2Tyrt7(|QQw+Uya@&iQ(!y!ybkE$KNuUQU{l!HH)aj-~RQf5eB=zQf zW#S1{jT1Yb&coBrq}_Ca&7bRo=?|izRjdDw)9YLhK5QNhC-Fl(3heX<;1MAA^W3;c z%fnrE3t1C3XVW%!E|*q4qbX7$_?#cdo48p(#0Ti4+o!p5kKUWoF7qWJD#L@}|B5t{ zo6S-7Xt3HyNFK9|+Btkt)8XO3+ry@Rb7TYsd_gDvS2$@4HNV61Y4cePH*b6&Dzr=G zGx%bFMH=RGD+1qzlsk-tQi`KRiL_Hxl+Wj!s@-m0yc!-YiQW3cPwrFK$I$ma*X=K3 zkV~tkdWX^eYRkDAZ(e2!iu1#B`iS-n(psCz)xlsCnZdq}nS~Us3_s9lRlS}X;0zYs z8ykW16V*ZOh38X6ZgvTWb6t=Xzi`RY?TcPgOOtX#TOq&H9bBf>#HR;qEZm-{zv2nc zX9%Fugz}y!SC?6d^F6ufpUL)AHGXQEJ{KoMJC|klf?Q7UFdKQkBYN4*XZK=u))Npm z&Env`(&7r8(ukDjU^ogq(a?1#tJw9TiOT)0M9-W06>axhHXt&SLNhWlJYLD5cRzw~ zHn@Uei`3V$xxv~MrU+qKm@2Ixk(N`~)|a}Phesr=q$)@9i#j{gFU6W$=X^y7Z!3KJ zKj4<@_pjqHYS;S;^h;8H(bcmLyNXUKTC&hD|s0*xCM z&hu(7-}A08-+7=gA8_O;Dy8mwC40%Nx>>G`Y#U3+gcUH7Qc|v(oz8 zlUQohR&bcTVGXy~{w52*No`ca`mP@+_El-HI3Fi^nQ#&&}Fq8)8Urj?Jai zv4!E`FzRgk8R6hDoxv4#)toddZ@;X3H*Xwi^w#WGRJECmTs@)|xI2s6d#pUeo3!CZ z({o>2>vvG&Y*F$2&J=`6ouzunhoMrbD`QXz3r1?DNQHtArWG4$q&?Zw_yd8|Q;u@S z({%9hfYr9JFbX|;auFWGeB_;y@RGxTQ;Qo8juQ8b09{dM>$A5-ndwe?sfQ^v2y2Vq&V~hcnpP7f5%rTBKtskaL}#K5wnB@3H|X!=fos+n>x=Y(m@+$fi2+=R8&T zfh{SNN`@Y`+sXyV;vBH!3Qt9Gw7++I-b~31IWErvKtMPZy~G##?QNed+d2E?l1rI^ zDfMpaxNjRs)GL)bh~!~nvGEiYJ-w!KKYbNbznSoug1o24jN`*|RYvM3E~nIknej@Z z(8Um)qJL85hH@ySb~vA9$#=Vw>50N7BVc5inel<*ot=codhihBQfaG`;fJln(^ zamRlRR767uB=X4c0`JbvhZ0${c|IyzZ)s^6VoUVvHk7_yfKhkRQp0JxV=M+2*VUT} ztC?wIm*vTtPz2HWpDXIY^59D|60Q2IwA zcc^QXmc%kL&_aX=1u23%@Q|WC+&$0YjXJS5G5=G(Md?M_k zkb;?!{;7n$?k_u{3ND2YVQjihcM{daY;b|J58Tqfz1)pI?+=BWcYMx0O(JLHGs5mPV&E1kP zaem}S8^&TII1SMENmj?8;qi=h)C()>Wt{Sz5McnGSm zRWIfHZ!Aa@lXDi`&Ly!E)w1@~Tj7MGqy9Q`AcIvuz%bMj_+}$w^YU5?y%!Bd9uR~4 z{e7cUKh;y@!N&z3Ba*MEN>;34{uCU^by})aeXlT9%sscWK7o~UC5}kWP{Fpuh~E0b zKf$C5%|nm;yg9lT7r&sm92z_Qf&6Pl&$5U5m;eY>MK;78YJZrHc@uyfmxH)=DB3D& zjW>&~EX_`P;e8p^UVC21mU38K)4Da!t*TX4BWIBH=ow9V0svP9n6GnNaUP+L@>rGt z-x}8kZqbv?7KXj&W1Z9q%%@0XweM4ZRFKzNmK!f&dnfke_k<`GN6#hu@XWn1j75NS z+8E)t;cu9^iSW1&9A^btv^j>D7&G3XW)Kb==&wntILa>U&O&0P;;!XQTwq@Fy-&Vn z4k8ZHMCylr&7n!=d$tsGN*s6M_IA8;sS3=(5)BQL(NztqfK!U3-78EG9PRGTd5;(8 z9Z5=lj040phWo8%bjCTlDSRLzm2c9qs{QJ&#bJrzv@AeI6QW8F1bcbhaXCX~_GXKH z^{FW%X{a1Pz$S(x1WNn$_clUs6tB)82nh8e6Y&^Yg~1!|Ramf7(5Quon?8v zA~hrb$c2Qb0Fy2ABxzq1P|S$bmZq8RP<13-xV+QF)b&Tk5EIY_hzL+Fm!)z7f=Gp>d76P;~gW(lWmO++~fx-(l#cvHVgdr7F4G(#lm)_(=blI;C1;QWDaGr(0b@ z37O$8l&00|V^5pwe;03;nfO42jsmz*brTF@L#R@NB4i4w0#HB4X2!FNXo(ax-EDa< z8*;iAg*5%F^cRs?@sD;o(iJpd=CaQq`vhE%hE54KKZ05B5x++gu zf<{J``n?sRqYL6q&?m7k$}!GI}EF4ChZl zWoS$bx8m#t>bpf+tkcx+tOmgf%J!Td`&I2X>PI8bemXu5@I(*4uv0(<)K9VOO@RkzVKnYULZ_0?@wHCvl?*-E{xCi2b zeFVekEseY+&8UD}D63clWpJu^R#ny6pqS(1C*}-+)E@(1=rr%bIN)>1=9}G6+|*X~ zNFqlNHyhYfpQU!#Ssdx(iv7d$w-p%&hvZl{iw4_6O_h;VC!Lr&`DJ2Nk*qY%N3{*r z>z@b1h3cGdE~m0{c9sOolH`*V(*{I%B7Ij@?L}mBJ5;mCx}SLq-?kq%zkn`_1ms>$ zO-x!@N1BP4BMfuvf5sbx zU!9NNnh>`WU3Iu{*WltAat^pF+25}zzfVWs77d)L=puF~_)d?Jhsu76#g54bYn6RC z)=PY6er7gm zI<9`)?WuP-P~BiDXh6Og1J6TAZES`R0>*fbgVFNiCKk4Yv37>Aps)+wvY}zi*;#Lm z$LZ&&G+~20cI>IJ;gmb8WkIPBU`Hdvk5iR>;62${tqT;q-3*LE?9f`I@E9sVknVFwyeA{<0GC{G$_W8Cs_+f~N3R17OGV*=Af6xV6qD{qNPSiz$r(3zas@JcTZaeA5m0mG>WrQV)E9 zTkxGOIJ{La)up+?yTL7{2uBVZhj_S;#tXA@?9`U?d9G492y;ZTE0Au?@VCSKG#>iW zFBP7=2%%7_`Peo1ly|zYXjG|tTyoe5*+Q3;h@iSwWh!nr=$?G@@_L8$5rpVOV60zl*sLF!??S>I8yeM zDhnrZV!r-@(3rzpSAoJG^buhnUyo7+evMY`p<~`jQLVMP>a>}8Mr|-AmXR&ivyir5 zs6=h_MibEj2kpj5&7;5hVOc+EFVZD zF}xyhe-B%$<#S_6Dz47{HqG@3f=2UCe4ig2Jia=fZO?d;iaMQ#jBX`oE+%LNoC7G* z;>)b5I(XvyJ~4>xHraCaVaAAmAj0QNV*h5S_3vF79D*Z&N_KA#!!Q{(ewYbG9MNy- z8)9wCRJ=KU1wdzFD60=ze1~t^pJhc&D9YZyZ;%vsT-_ZTe?&gUM?yMd(tD=tRpOgD zDgG{JdwpX#uTC?g-BBc|O0qFgdpuc$e3J1h~AiWs@s&c$rpCS2)N zKeyYJVkHi_6&Cf z@%3A$N+-eVNz+Th@r(_rs0-=#_lGOZ?by*3=lyKD|2(|5L1p6yPIgnsqibDG;F+@7 zEBpCItgr8%9`FvD+}j>w-^bB7aq=fylKRH?!eeaD?oC`0aemL3!F}RCbsts87y&>- zPuqWFl4t~f*9z$1MJ`a0e*Bm$QVG1tR~%+}c%Ce55piYUHsf9roU`RYe|G(fA>x&| z{M0;NVa=TG=f{-DYUJ!2G9^SS#zynvqswb4e8!h=*y+2iI|GbC66VxI)g3 zyt9qHB&33%$l}0YjqXs5t^#(Hcn=3d4T0ivlvR8Qa^F@&E9sQA(An%T)EX^dVEQs?l4m# z1^4#$-tkCw8fD-&T!?m+7t-*88FLNS@g41+uMun8iv_ta{1r3T_xMfhJf&pGgX_}d zmkXau79Gwnc`fY0A>JZ?FX<<=s|9XS44SBk<7!uHrBJEJa3#DFDDD7j0GZaT5ij8 z)#K8nTt8l*`fcN}WF|JZ-8S{ntSv^zm|tlj;75mqzHB z58$r`&nEJ9s_kB>tP}?!SzX<-DbE*0bGFQJjWV2Mhehcx2PY|WHJ(Cx^>!4(J2TLrckBeKQZjL$guX>yy4VNg9|=lDaWlXTDG{Qzd+*H%;4>6!SFY`30|~*sI!o zDV=C5M3|RJ;PV@0@TB1L{l@Mk$n7~{D)#h&wLN>xW>>`RQxphJ4Ay!s8^?RbVyaNJ z(BroIeGo5-lnS>Xb1L6nkU&Qc(vF=*Nj^nJ|E@|CK=mM$%a32@naj9H{8of9x3fy{VoH zV4n&FKAOc_V@}z8zUNzDJXRPO?73Gh09U@!cDh2Wy$tQXg?gLOPV7jQTU37eQZ8+Z zyIF>c_9%(IixPMf|wQLsKY)+QU39zkhd^X=x07ZoKfjM^Xy>rnKxq33UCG z?c=RU531_K_^t6&kxB2H({nW?a{!LUaM=$EHykaz*a_E&W@e5Y%9gr#;z$FT-#|Tx zyUjSxPNG+`N59&0S$!DDNlf3?J=93|^`c0bIa&W3gEExX`Zb19awjDdMtg{7y*zK{ z!S%w+qB4W=uF=|??BRicrLyq@cAPWqpQ~{K>mApBEH^mN5H%mvQXST}R|eiuW_gye zj@;=%#b<(ZG$%?bGpt6VXOO39G-oKg`dOye62afp=r?5d@?4tX(0qZ2QQia>Q;Q?}iMGvT3ikuYqQ^A4_KRnv`9mM$RTS6{Op%(FFUhlb|8pDa=f zM>hafxIW=ZMw1SwA9=H-47;49amrZF<`|cOgan29hUh#_ckJr1ezFHj?dWZv2g?QV z_VK6uoteVpwL{%YXsOr1I7gH;KnI8MbtZ4nPlDHj!Ohnn)$H`|4ruZs1TuU$IiMyl zYv17!;!=OfE=Cec*eme6-E%P$a(AvCryuACf?Nx>4+h6z6ZTl8#h04+{WOcGJiI-P z-y|Ee-UQ;w5**Q`d;S$c7u^Rz3EWcs zAW(+?4(RH98K<^Mip}x^q<(gHQulEwY^7T{CKVK`zv@}q?q9ioFjt60I+QjTU95G{ zx%-IK(@c-Oe6Kp|2^KzRvpSk>`i+A0$K~9tY=fb-P4x)*=;)|x2GTZoyuLTSAuK9p zGgd2y(d62iF+$wDzM)q0c5*^%G!on>0%OHxgPQ)Xd`nFqk9h(~8CO-KIY1q38c~<` zcL9FzkW__AF(&6REj$Iq@3WtkE5UyKz>=s5yUxFT$ag;mj(agqA`?!hd9 z)$jrEGw9p%-QY=kqVLPpJEZGNuE&P8D8=0a#TSNM`M;Fhl6BwL&bBwMQ!^}iyY2+? zimcwQnWjd9#G>^|sezv?@8hix7n|aU_1rf1_bWp{YdT=+T?2iq$<~Yrgb1Z7dpmHVkDu= zXkW)L_fANF+RiAJ`vyFkLv5%B0V)+0&34fVK+AN8Ra2dV6~^EZ#Hjc7zm;G>#Ng2^ z`!d()!a9Fw+(pZIG@duIUzLoG*}oB_+3EI>72F# zIVHP^CK>KP!eYzIWp}%Ej8#+f1X%LQr6~#%dAW_?`sL20;YcZXGqjK8gaooSx&-Y2 z&u?%nX+n{~q^-Q}v7~Px!$Sa=fUc&5g=z-@8>$$>L-*o@kCP^wo8?)Z(DFFmu3c{f zzXFQ_}4a?X<%icKO`OmxGOzH3;g#vDq#D(lF&{4|v1~E}at#ae?hp&d0m__dp=y z#k~JUXGzLe^2U709n25eMI8olQ!XWq98Wd($q(k(Wt0@ArI8%|{Vs8k%zw|^gnAsN zn{9E@)Y{P0yct%lIMHN#Z%p}evludoit+oP!oE@0g@`%Fjm~v{YAxE};Ul|+cofY& ziSO~w1%_}}*F+!>@%-%5vPMhs>2m%FyLl(}z5Aim%AY5DwArPhv#wsxi!S_KWGkFo zZ?Nponyh&3xce&|es`AWw#yH|@GFFeBIpw?F48EPzfbBysplf9&V4u_HBH$4wbF8?E_ZS2^%|M5Wr@)Pl)TFIgO%A;cWHlA~y+T-hPKa+tl0GJ5wH+{xwzr#C{Ws=32V&b_E(p zr(mCwpZtx^H(vZcsbKF*P42YIZQ~YRTJ4WxWTtJXC{6N4KW!r zC4bC#ur#Y_%0+I7Mn$eawk^B!h^7LJP~^eXM)*nl&c#WaSnf!VVtT zO#j8kflh^~{^-eCOh``dSCYfSYxJ3634XEjyl-%%O`6EAAt(o?nCEV>JNQI38xwAA3#`Ik&Ft(-1IG9-nmgd(`hU{B69GxA-#OE zrP8E6Nq+whpF}t!g`LKPHPPOE765b`@>a-P%|{}cUy*b!JKdtD6SwBp;WAcCb0$iT z55Uf(DHn#NJU-qR8ZqR$=>6z{elqX`(qWz@Zq-|6{sg3)lMecqn)7!?tR|~p1F!_X z9wbIKc<-N{)+xni!Dfx-VK@4y&G^l&hbotgoslKQ6IY z7&#ydCv0)qA<5IpnMZzZE?k&Ia33A0omP}ss{xc~i_CwkX-K@1(a4bVFi^zOdc#_w z-!hCe*30Mp^UoOkSa#24B7z*bWK_k2mAi9od6uxC;rC@_3@ThK$LBm`sfnm@A6~(8 zwW3pcmwW_)iM>A~ubcZcB|4#fRp)+LZo2*dzA>;jMWzdGU?a15|B*lay z<~{xoX7V@GYUv13nMuRiEc#@e(Fz#h6nBy|XYAHyIXV@(43am|-DZ?qc|RH$t!EEs zm*Ci}bU-U4JP^+8-76XkIwpSmyc>+`j4I{6M)SMq^H43rd8wv zxB}$lJxz`Y$cd^?`L9OCxa8(@#U}9Rh%Vpp@w)}_EpouR{}DW|IypcEN-q;j@xKg^ z>8mK0FSwca84DKR46;PW;o;YX{93ZRFhxT-r~!fqNB(e&OVwU|v6c%U)CyiJ1+dd3 zv(W%;FoZzzbkJM<0if&OLwLY{t#%r#+9?nd2RNF<=ETQ-w(RJgA|%zyfE`Se6O10S zWjgbPMSZ?)en`CaTJx}h%I5*pz$;An7WkQ~bp9==7Ab(?TBP7h^!xW))XFM|t-uq7 z35ZTc7MLu_m5)s{*iaJOPWPHYX`aL6OI3eEG&WQuPIi@pFuOCS3y6q2h2(OvFOPL$ zQ&{cDr#+Sc4Jj1&dDwb)CR2Q79-9zp59u&!PA^9j3KJ-D6ga<@<@z~$JbpL5^9SA6 zmT4q%@faC7+4pZK>8k zKOdz7?oA;h``)!=`3**^RADa;aK$78H}hl4`+bc#1Fh>#D-9&J+X?apAum_W#IICz zfIW^iVso%Rqm2^0Z9>RYontjtE}pz?x*HcMVWrQDKimjL>%e)fh67X+1v*aNkY<1t zzc5*#Qalx#^lC`YpZqbwr%qQaac}?AQooC%%Ek06^W&(Nd^IcB{z428M)notjC5sn=I4dv{0olSS6*Z87arU-E@=u6A_z|C$Z4a**gm{7{ zQ*PgF>BkDM*}yso@dR!LQ5_#lC4Bt{!;;$2aXvSA3x4>#e7oXuSr%LH+9l|>uDEzl z&bB``m8aLyoP{d&G%#JX!hZwY+sr3oBZIgQhgEo(=lUY39n^}AOAj~v?eF81XkS8d zGhT+W)uf;|Vz0dw$9LRKil3FMObv@L>4?Ly05VxXINNK89~n|_d0ly%1gzGA;xA5c z&Qx?Tc3ySA?M~`!_1bWXyLAoMP=E)?LgnX@`N2;L_bG514U#so=Q?SvO8c<0%Q;3T zJM95&;j)^*G>wf30wcLaj+t@K)d~YwiDE0f`?UlCXNy3KI#i29NAR?KntbC({yP;Z z78k!d{|5$uVUrJ1yUo@X$ExQOA4wQ^;8X-a<8$I7YTLEPS`1Z}v!@coeaGRYGzPk1Cc9BAEO zIEAt~+HuR4>zVtpQrE7f-3Rw4x5ss9|f(2|vM z+eh9l7WU`I#6DI?0>n{|svoKU7XE(hw?6`jj|~}%J+va>wFbo zPNk43L_`I_wStAdhWAK(z?x8Z}=&c-0fsD}M9F9N<8^Kv4z3NZYl)B1kBR4t!(o0o?d|PGNYmX}EeNVE-XQ+oJhC)q z4BRi6Tt=3@o1k24fSs@NIY21z)o(&gD!}g1OkOnNZ*sJh0SQ5OnM_!>#h;bom2?ec z705bsmDJLOulZCyme_6gpQ(R9=S=JYCQThvGnePLAvslwYD2nPS_(cdyUy@C zLvNu{m+?To{9}D=M@hueRus87MXOJDmaTC*(zWePQp1)b6#Ffd)xyO zugLVgDFU_8d=i@CLasGrV|NDiSDzJUkJpP;B|=7KP$vo(8TsANCDBCFv8oiZir!## zsq??ge8Im|4w=T`yjeEf@uJu%ukj!+;k7NIv{!o!#H!KKyAKv?Py<)>?i2qj&V8la zg9>aJ&&VNY0(g04b2I_T2Cw0qI_LRKzd!a7C?g&7 z`lJLeYQ4pSE}?{K_YhlJK&2`v4LXgWd-%QYq2t&3u2oQh;4eEk->=!(nC9Z+N-?}C zNb+NjZZ>CF-&0an%gc0r$U@O2q}6S|5|sI&X$do0{{=e6fDZ&+_I0Sz&sd5|be_c1 zW_(YV2Bi!H%3GC^p(brpUgyyRGhTpkv((LGBl-f-Mp|t%itOu)s80H2rAz4D+h9z# zJ7fG}GlAjglh9QaR}8}+X^oxwV8RMCcE#1e`?ho^Z6jH$stquEs30Jmajv2=ul0)$ z9$400UqC2QdLsw>cj$W#vHM8l^uT?4Ho~x19sDRy=EY$1gF?t3F`iC_Au-Kf(}1>+N(AKZv5QE|5Nwy!Fkb zqRYB;@l(!4c^d_>CE^gNRgFu)b_y{m@;Qi$Pu$0oVnz+9@C46vqf;b+lTKFV#?6sf^mM_BuUX+57kx&#b6a5nKKLJAe AG5`Po literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-2.png b/modules/masonry/docs/images/image-2.png new file mode 100644 index 0000000000000000000000000000000000000000..f9d37d75a010231627ea955a562df5790d3eddca GIT binary patch literal 12583 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 literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-3.png b/modules/masonry/docs/images/image-3.png new file mode 100644 index 0000000000000000000000000000000000000000..3924e09e035ee7a62102c70550ab3e8e0e79e5d6 GIT binary patch literal 13594 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 SXo2UJK=RVcQWX-WpZ^<~TZ+^G literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-4.png b/modules/masonry/docs/images/image-4.png new file mode 100644 index 0000000000000000000000000000000000000000..7af5aa5ccfdbe39395f31cf758199fcef78c6a18 GIT binary patch literal 3649 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 literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-5.png b/modules/masonry/docs/images/image-5.png new file mode 100644 index 0000000000000000000000000000000000000000..bbe377f17fdb7875319efa83788ac257634a7410 GIT binary patch literal 72792 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μ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 literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-7.png b/modules/masonry/docs/images/image-7.png new file mode 100644 index 0000000000000000000000000000000000000000..00d3a06e0867106a0cf808a96a483b998fc087b1 GIT binary patch literal 9622 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 literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image-9.png b/modules/masonry/docs/images/image-9.png new file mode 100644 index 0000000000000000000000000000000000000000..eb75758c35277f6f13937ada4d12d7c22fe92915 GIT binary patch literal 4914 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 NtZDGHR^2}4e*kjakC^}f literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/images/image.png b/modules/masonry/docs/images/image.png new file mode 100644 index 0000000000000000000000000000000000000000..9242044d2063491379674217e37bc29feba4deb6 GIT binary patch literal 4441 zcmb7|cT^Kk)b~RZq<85}K#)$T5~}nnAiYa(p$gJOYJdPLy#x?Y5Q7MWPNXDA@6x3C zql;82p@%1W-oM_zo@dY5y}Nh6GjsON?0oJ_@)JWX3Q`tQ002Otqpfa&v%9#{p5zYh z$~AHBg)@XfYC2Cza7QGGOA_vxIatFo*woK0IMgZ772po`^K}&oat?HL1qXTf1s@P} zD&a)Je?^Z2U7dnG{lHvLJ$+pP27X`{r!X!_aV~>@MpBAPT>g=?%p-AWE>#1AiS%p$ zfEuBruKM%^Y_BLZ*v725PuXZG!$-bpgLXkKgydUH{u{OM4~cd;;soeoC(7Y?L_F

^83FMek%63EH0;EwxL(}AX?|5=F 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 Date: Wed, 26 Jun 2024 12:41:58 +0530 Subject: [PATCH 03/58] docs(masonry): add DFD for level 1 and level 2 --- .../docs/Architecture/MasonryDFD.drawio | 238 ++++++++++++++++++ .../docs/Architecture/MasonryDFD.drawio.png | Bin 0 -> 364693 bytes .../masonry/docs/Architecture/Processes.md | 196 +++++++++++++++ 3 files changed, 434 insertions(+) create mode 100644 modules/masonry/docs/Architecture/MasonryDFD.drawio create mode 100644 modules/masonry/docs/Architecture/MasonryDFD.drawio.png create mode 100644 modules/masonry/docs/Architecture/Processes.md diff --git a/modules/masonry/docs/Architecture/MasonryDFD.drawio b/modules/masonry/docs/Architecture/MasonryDFD.drawio new file mode 100644 index 00000000..80205179 --- /dev/null +++ b/modules/masonry/docs/Architecture/MasonryDFD.drawio @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/masonry/docs/Architecture/MasonryDFD.drawio.png b/modules/masonry/docs/Architecture/MasonryDFD.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..114eb4aaadd8f032c00821b6a2e7de18b46fc9c5 GIT binary patch literal 364693 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 literal 0 HcmV?d00001 diff --git a/modules/masonry/docs/Architecture/Processes.md b/modules/masonry/docs/Architecture/Processes.md new file mode 100644 index 00000000..9ba07c40 --- /dev/null +++ b/modules/masonry/docs/Architecture/Processes.md @@ -0,0 +1,196 @@ +# Processes for Data Flow Diagram + +## Level 0: Masonry Framework Communication with MusicBlocks +1. **Load Configuration**: + - Input: Configuration File + - Output: Initialized System + +2. **Save Configuration**: + - Input: Current State + - Output: Updated Configuration File + +3. **Generate Syntax Tree**: + - Input: Brick Stack Data + - Output: Syntax Tree + +4. **Parse Syntax Tree**: + - Input: Syntax Tree + - Output: Executable Actions + +## Level 1: Interaction between Brick, Palette, Workspace, and Stack of Bricks + +### Bricks: +1. **Initialize Brick**: + - Input: Brick Properties + - Output: Initialized Brick + +2. **Provide Brick Properties**: + - Input: Brick ID from Workspace + - Output: Brick Properties to Workspace + +### Palette: +1. **Load Brick List**: + - Input: Configuration Settings + - Output: List of Bricks + +2. **Select Brick**: + - Input: Brick Selection + - Output: Selected Brick Properties to Workspace + (How this works is, The palette will have a loaded list of SVGs. When you drag one from palette onto the workspace, the brick will be created on the workspace whos id matches to the one in brick) + +### Workspace: +1. **Add Brick to Workspace**: + - Input: Brick Properties from Palette + - Output: Updated Workspace + +2. **Update Brick Position**: + - Input: Brick ID and Position Data + - Output: Updated Brick Position in Workspace + +3. **Connect Bricks**: + - Input: Brick IDs and Connection Data + - Output: Updated Brick Stack in Workspace + +4. **Disconnect Bricks**: + - Input: Brick IDs + - Output: Updated Brick Stack in Workspace + +5. **Save Workspace State**: + - Input: Current Workspace Data + - Output: Saved Workspace State + +### Stack of Bricks: +1. **Initialize Stack**: + - Input: Brick Stack Data + - Output: Initialized Stack + +2. **Provide Stack Properties**: + - Input: Stack ID from Workspace + - Output: Stack Properties to Workspace + +## Level 2: Detailed Interaction within MVC Architecture + + +### Model: +1. BrickModel: + - Properties: + - brickType + - originalColor + - hoverColor + - disconnectedColor + - executionColor + - highlightState + - shape + - sprites + - labels + - inputPorts + - outputPorts + - editableTextLabels + - Methods: + - setHighlightState(state) + - updateProperties(properties) + - updateLabels(labels) + - updatePorts(inputPorts, outputPorts) +2. StackModel: + - Properties: + - connectedBricks + - startPosition + - validationRules + - collapsibleState + - Methods: + - addBrick(brick) + - removeBrick(brick) + - updateProperties(properties) + - validateStack() + - setCollapsibleState(state) +3. PaletteModel: + - Properties: + - availableBricks + - categories + - searchQuery + - filters + - Methods: + - loadBricks(bricks) + - updateBrickAvailability(brick, available) + - categorizeItems(categories) + - filterItems(filters) + - searchItems(query) +4. WorkspaceModel: + - Properties: + - connectedStacks + - brickPositions + - zoomLevel + - undoRedoStack + - Methods: + - addStack(stack) + - removeStack(stack) + - updateBrickPosition(brick, position) + - connectBricks(brick1, brick2) + - disconnectBricks(brick1, brick2) + - deleteBrick(brick) + - zoomIn() + - zoomOut() + - undo() + - redo() + +### View: +1. BrickView: + - Methods: + - renderBrick(brick) + - updateBrickAppearance(brick) + - renderInlineTextEditing(brick) + - renderContextMenu(brick) +2. StackView: + - Methods: + - renderStack(stack) + - updateStackAppearance(stack) + - renderValidationFeedback(stack) + - renderCollapsibleState(stack) +3. PaletteView: + - Methods: + - renderPalette(palette) + - updatePaletteAppearance(palette) + - renderCategories(categories) + - renderSearchBar(searchQuery) + - renderFilters(filters) +4. WorkspaceView: + - Methods: + - renderWorkspace(workspace) + - updateWorkspaceAppearance(workspace) + - handleUserInteractions(interaction) + - renderZoomControls(zoomLevel) + - renderUndoRedoButtons(undoRedoStack) + +### Controller: +1. BrickController: + - Methods: + - handleBrickPropertyChange(brick, properties) + - handleBrickHighlightStateChange(brick, state) + - handleInlineTextEditing(brick, text) + - handleContextMenuAction(brick, action) +2. StackController: + - Methods: + - handleAddBrick(stack, brick) + - handleRemoveBrick(stack, brick) + - handleStackPropertyChange(stack, properties) + - handleStackValidation(stack) + - handleCollapsibleStateChange(stack, state) +3. PaletteController: + - Methods: + - handleBrickLoad(palette, bricks) + - handleBrickAvailabilityChange(palette, brick, available) + - handleCategorization(palette, categories) + - handleFiltering(palette, filters) + - handleSearching(palette, query) +4. WorkspaceController: + - Methods: + - handleAddStack(workspace, stack) + - handleRemoveStack(workspace, stack) + - handleBrickPositionChange(workspace, brick, position) + - handleBrickConnection(workspace, brick1, brick2) + - handleBrickDisconnection(workspace, brick1, brick2) + - handleBrickDeletion(workspace, brick) + - handleZoomIn(workspace) + - handleZoomOut(workspace) + - handleUndo(workspace) + - handleRedo(workspace) From 78b0d6ea46c2ff176fd79c5c58a8d65214626e19 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Wed, 26 Jun 2024 12:49:31 +0530 Subject: [PATCH 04/58] docs(masonry) : add tech-spec --- .../docs/{ => PRD}/Masonry_Design_Document.md | 0 modules/masonry/docs/{ => PRD}/PRD.md | 0 .../MasonryDFD.drawio | 0 .../MasonryDFD.drawio.png | Bin .../Processes.md | 0 modules/masonry/docs/tech-spec/TechSpec.md | 385 ++++++++++++++++++ modules/masonry/docs/tech-spec/Techspec.md | 150 +++++++ 7 files changed, 535 insertions(+) rename modules/masonry/docs/{ => PRD}/Masonry_Design_Document.md (100%) rename modules/masonry/docs/{ => PRD}/PRD.md (100%) rename modules/masonry/docs/{Architecture => architecture}/MasonryDFD.drawio (100%) rename modules/masonry/docs/{Architecture => architecture}/MasonryDFD.drawio.png (100%) rename modules/masonry/docs/{Architecture => architecture}/Processes.md (100%) create mode 100644 modules/masonry/docs/tech-spec/TechSpec.md create mode 100644 modules/masonry/docs/tech-spec/Techspec.md diff --git a/modules/masonry/docs/Masonry_Design_Document.md b/modules/masonry/docs/PRD/Masonry_Design_Document.md similarity index 100% rename from modules/masonry/docs/Masonry_Design_Document.md rename to modules/masonry/docs/PRD/Masonry_Design_Document.md diff --git a/modules/masonry/docs/PRD.md b/modules/masonry/docs/PRD/PRD.md similarity index 100% rename from modules/masonry/docs/PRD.md rename to modules/masonry/docs/PRD/PRD.md diff --git a/modules/masonry/docs/Architecture/MasonryDFD.drawio b/modules/masonry/docs/architecture/MasonryDFD.drawio similarity index 100% rename from modules/masonry/docs/Architecture/MasonryDFD.drawio rename to modules/masonry/docs/architecture/MasonryDFD.drawio diff --git a/modules/masonry/docs/Architecture/MasonryDFD.drawio.png b/modules/masonry/docs/architecture/MasonryDFD.drawio.png similarity index 100% rename from modules/masonry/docs/Architecture/MasonryDFD.drawio.png rename to modules/masonry/docs/architecture/MasonryDFD.drawio.png diff --git a/modules/masonry/docs/Architecture/Processes.md b/modules/masonry/docs/architecture/Processes.md similarity index 100% rename from modules/masonry/docs/Architecture/Processes.md rename to modules/masonry/docs/architecture/Processes.md diff --git a/modules/masonry/docs/tech-spec/TechSpec.md b/modules/masonry/docs/tech-spec/TechSpec.md new file mode 100644 index 00000000..3a389b35 --- /dev/null +++ b/modules/masonry/docs/tech-spec/TechSpec.md @@ -0,0 +1,385 @@ +# Masonry Framework Tech Spec + +This tech spec outlines the implementation details for the Masonry Framework, a core component of the MusicBlocks V4 project built with React and TypeScript. + +## Project Structure: + +``` +├── src +│ ├── utils +│ │ ├── dragAndDropUtils.ts +│ │ ├── validationUtils.ts +│ │ ├── dataUtils.ts +│ │ ├── quadtreeUtils.ts +│ │ └──... +│ ├── components +│ │ ├── brick +│ │ │ ├── Brick.tsx +│ │ │ ├── BrickInput.tsx +│ │ │ ├── BrickOutput.tsx +│ │ │ ├── DataBrick.tsx +│ │ │ ├── ExpressionBrick.tsx +│ │ │ ├── StatementBrick.tsx +│ │ │ ├── BlockBrick.tsx +│ │ │ └──... +│ │ ├── palette +│ │ │ ├── Palette.tsx +│ │ │ ├── PaletteCategory.tsx +│ │ │ └── PaletteSearch.tsx +│ │ ├── workspace +│ │ │ ├── Workspace.tsx +│ │ │ ├── WorkspaceGrid.tsx +│ │ │ ├── WorkspaceToolbar.tsx +│ │ │ └──... +│ ├── hooks +│ │ ├── useBrick.ts +│ │ ├── useStack.ts +│ │ ├── useWorkspace.ts +│ │ └──... +│ ├── models +│ │ ├── Brick.ts +│ │ ├── Stack.ts +│ │ ├── Workspace.ts +│ │ └──... +│ ├── services +│ │ ├── BrickService.ts +│ │ ├── StackService.ts +│ │ ├── WorkspaceService.ts +│ │ ├── QuadtreeService.ts +│ │ ├── ErrorHandlingService.ts +│ │ └──... +│ ├── App.tsx +│ └── index.tsx +├──... +``` + +## Dependencies: + +- React +- TypeScript +- React-aria (for drag-and-drop functionality) +- ... (other relevant libraries) + +## Description: + +### Components: + +#### a) Brick: + +- **Brick.tsx:** + - Properties: + - `brick`: The brick model instance. + - `onDragStart`: Callback for drag start event. + - `onDragOver`: Callback for drag-over event. + - `onDrop`: Callback for drop event. + - `onDragEnd`: Callback for drag end event. + - `onClick`: Callback for click event. + - `onDoubleClick`: Callback for double-click event. + - `onContextMenu`: Callback for context menu event. + - `onInputChange`: Callback for input change event. + - `onOutputChange`: Callback for output change event. + - Functions: + - `render()`: Renders the brick component with its visual appearance and input/output ports. + - `handleDragStart()`: Handles the drag start event for the brick. + - `handleDragOver()`: Handles the drag-over event for the brick. + - `handleDrop()`: Handles the drop event for the brick. + - `handleDragEnd()`: Handles the drag end event for the brick. + - `handleClick()`: Handles the click event for the brick. + - `handleDoubleClick()`: Handles the double-click event for the brick. + - `handleContextMenu()`: Handles the context menu event for the brick. + - `handleInputChange()`: Handles the input change event for the brick. + - `handleOutputChange()`: Handles the output change event for the brick. +- **BrickInput.tsx:** + - Properties: + - `brick`: The brick model instance. + - `onConnect`: Callback for connect event. + - `onDisconnect`: Callback for disconnect event. + - Functions: + - `render()`: Renders the input port of the brick. + - `handleConnect()`: Handles the connect event for the input port. + - `handleDisconnect()`: Handles the disconnect event for the input port. +- **BrickOutput.tsx:** + - Properties: + - `brick`: The brick model instance. + - `onConnect`: Callback for connect event. + - `onDisconnect`: Callback for disconnect event. + - Functions: + - `render()`: Renders the output port of the brick. + - `handleConnect()`: Handles the connect event for the output port. + - `handleDisconnect()`: Handles the disconnect event for the output port. +- **DataBrick.tsx:** + - Properties: + - `brick`: The brick model instance. + - `onInputChange`: Callback for input change event. + - `onOutputChange`: Callback for output change event. + - Functions: + - `render()`: Renders the data brick component with its visual appearance and input/output ports. + - `handleInputChange()`: Handles the input change event for the data brick. + - `handleOutputChange()`: Handles the output change event for the data brick. +- **ExpressionBrick.tsx:** + - Properties: + - `brick`: The brick model instance. + - `onInputChange`: Callback for input change event. + - `onOutputChange`: Callback for output change event. + - Functions: + - `render()`: Renders the expression brick component with its visual appearance and input/output ports. + - `handleInputChange()`: Handles the input change event for the expression brick. + - `handleOutputChange()`: Handles the output change event for the expression brick. +- **StatementBrick.tsx:** + - Properties: + - `brick`: The brick model instance. + - `onInputChange`: Callback for input change event. + - `onOutputChange`: Callback for output change event. + - Functions: + - `render()`: Renders the statement brick component with its visual appearance and input/output ports. + - `handleInputChange()`: Handles the input change event for the statement brick. + - `handleOutputChange()`: Handles the output change event for the statement brick. +- **BlockBrick.tsx:** + - Properties: + - `brick`: The brick model instance. + - `onInputChange`: Callback for input change event. + - `onOutputChange`: Callback for output change event. + - `children`: An array of nested brick instances. + - Functions: + - `render()`: Renders the block brick component with its visual appearance and input/output ports. + - `handleInputChange()`: Handles the input change event for the block brick. + - `handleOutputChange()`: Handles the output change event for the block brick. + - `handleNesting()`: Handles the nesting logic for nested bricks. + - `handleArguments()`: Manages the arguments for block bricks. + +#### b) Palette: + +- **Palette.tsx:** + - Properties: + - `bricks`: An array of brick model instances. + - `onDragStart`: Callback for drag start event. + - `onDragOver`: Callback for drag-over event. + - `onDrop`: Callback for drop event. + - `onSearch`: Callback for search event. + - `searchQuery`: The current search query. + - Functions: + - `render()`: Renders the palette component with its visual appearance and categories. + - `handleDragStart()`: Handles the drag start event for the palette. + - `handleDragOver()`: Handles the drag-over event for the palette. + - `handleDrop()`: Handles the drop event for the palette. + - `handleSearch()`: Handles the search event for the palette. +- **PaletteCategory.tsx:** + - Properties: + - `category`: The category model instance. + - `bricks`: An array of brick model instances. + - Functions: + - `render()`: Renders the category component with its visual appearance and bricks. +- **PaletteSearch.tsx:** + - Properties: + - `searchQuery`: The current search query. + - `onSearch`: Callback for search event. + - Functions: + - `render()`: Renders the search component with its visual appearance and input field. + - `handleSearch()`: Handles the search event for the search component. + +#### c) Workspace: + +- **Workspace.tsx:** + - Properties: + - `workspace`: The workspace model instance. + - `onBrickAdd`: Callback for brick add event. + - `onBrickRemove`: Callback for brick remove event. + - `onBrickConnect`: Callback for brick connect event. + - `onBrickDisconnect`: Callback for brick disconnect event. + - `onBrickMove`: Callback for brick move event. + - `onBrickResize`: Callback for brick resize event. + - `onBrickRotate`: Callback for brick rotate event. + - `onUndo`: Callback for undo event. + - `onRedo`: Callback for redo event. + - Functions: + - `render()`: Renders the workspace component with its visual appearance and bricks. + - `handleBrickAdd()`: Handles the brick add event for the workspace. + - `handleBrickRemove()`: Handles the brick remove event for the workspace. + - `handleBrickConnect()`: Handles the brick connect event for the workspace. + - `handleBrickDisconnect()`: Handles the brick disconnect event for the workspace. + - `handleBrickMove()`: Handles the brick move event for the workspace. + - `handleBrickResize()`: Handles the brick resize event for the workspace. + - `handleBrickRotate()`: Handles the brick rotate event for the workspace. + - `handleUndo()`: Handles the undo event for the workspace. + - `handleRedo()`: Handles the redo event for the workspace. +- **WorkspaceGrid.tsx:** + - Properties: + - `gridSize`: The size of the grid. + - `onGridClick`: Callback for grid click event. + - Functions: + - `render()`: Renders the grid component with its visual appearance and grid lines. + - `handleGridClick()`: Handles the grid click event for the grid component. +- **WorkspaceToolbar.tsx:** + - Properties: + - `onUndo`: Callback for undo event. + - `onRedo`: Callback for redo event. + - Functions: + - `render()`: Renders the toolbar component with its visual appearance and buttons. + - `handleUndo()`: Handles the undo event for the toolbar. + - `handleRedo()`: Handles the redo event for the toolbar. + +### Utilities: + +- **dragAndDropUtils.ts:** + - Functions: + - `handleDragStart()`: Handles the drag start event for draggable elements. + - `handleDragOver()`: Handles the drag-over event for draggable elements. + - `handleDrop()`: Handles the drop event for draggable elements. + - `handleDragEnd()`: Handles the drag end event for draggable elements. +- **validationUtils.ts:** + - Functions: + - `validateBrickConnection()`: Validates the connection between two bricks. + - `validateBrickPosition()`: Validates the position of a brick in the workspace. + - `validateBrickData()`: Validates the data within a brick. +- **dataUtils.ts:** + - Functions: + - `saveWorkspace()`: Saves the workspace state to local storage or server. + - `loadWorkspace()`: Loads the workspace state from local storage or server. + - `exportWorkspace()`: Exports the workspace state to a file. + - `importWorkspace()`: Imports the workspace state from a file. +- **quadtreeUtils.ts:** + - Functions: + - `insertBrick()`: Inserts a brick into the quadtree for spatial indexing. + - `removeBrick()`: Removes a brick from the quadtree. + - `updateBrick()`: Updates the position of a brick in the quadtree. + - `findNearbyBricks()`: Finds nearby bricks within a certain radius using the quadtree. + +### Hooks: + +**a) useBrick:** + +- A hook for managing a single brick. +- Provides an instance of the `Brick` model. +- Handles updating the brick's properties and arguments. +- Properties: + - `brick`: The brick model instance. + - `setBrick()`: A function to update the brick instance. +- Functions: + - `useEffect()`: A React hook for handling side effects. + - `fetchBrick()`: A function to fetch the brick data from the server. + - `useCallback()`: A React hook for memoizing functions. + - `handleInputChange()`: A function to handle input changes for the brick. + - `handleOutputChange()`: A function to handle output changes for the brick. + +**b) useStack:** + +- A hook for managing a stack of bricks. +- Provides an instance of the `Stack` model. +- Handles updating the stack's bricks and connections. +- Properties: + - `stack`: The stack model instance. + - `setStack()`: A function to update the stack instance. +- Functions: + - `useEffect()`: A React hook for handling side effects. + - `fetchStack()`: A function to fetch the stack data from the server. + - `useCallback()`: A React hook for memoizing functions. + - `handleBrickAdd()`: A function to handle adding a brick to the stack. + - `handleBrickRemove()`: A function to handle removing a brick from the stack. + - `handleBrickConnect()`: A function to handle connecting bricks in the stack. + - `handleBrickDisconnect()`: A function to handle disconnecting bricks in the stack. + +**c) useWorkspace:** + +- A hook for managing the workspace state. +- Provides an instance of the `Workspace` model. +- Handles updating the workspace's bricks, connections, and layout. +- Properties: + - `workspace`: The workspace model instance. + - `setWorkspace()`: A function to update the workspace instance. +- Functions: + - `useEffect()`: A React hook for handling side effects. + - `fetchWorkspace()`: A function to fetch the workspace data from the server. + - `useCallback()`: A React hook for memoizing functions. + - `handleBrickAdd()`: A function to handle adding a brick to the workspace. + - `handleBrickRemove()`: A function to handle removing a brick from the workspace. + - `handleBrickConnect()`: A function to handle connecting bricks in the workspace. + - `handleBrickDisconnect()`: A function to handle disconnecting bricks in the workspace. + - `handleBrickMove()`: A function to handle moving a brick in the workspace. + - `handleBrickResize()`: A function to handle resizing a brick in the workspace. + - `handleBrickRotate()`: A function to handle rotating a brick in the workspace. + +### Models: + +Certainly! Below, I'll expand on the properties and functionalities of the `Brick` model to include bounding boxes (b-boxes) and related methods: + +### Models: + +- **Brick.ts:** + - Properties: + - `id`: Unique identifier for the brick. + - `type`: Type of the brick (data, expression, statement, block). + - `position`: Position of the brick in the workspace. + - `inputs`: Array of input ports for the brick. + - `outputs`: Array of output ports for the brick. + - `data`: Data associated with the brick. + - `boundingBox`: Bounding box coordinates of the brick for collision detection and spatial indexing. + - Functions: + - `connect()`: Connects the brick to another brick. + - `disconnect()`: Disconnects the brick from another brick. + - `move()`: Moves the brick to a new position. + - `resize()`: Resizes the brick. + - `rotate()`: Rotates the brick. + - `calculateBoundingBox()`: Calculates the bounding box of the brick based on its size and position. + - `checkCollision()`: Checks for collision with other bricks or boundaries. + - `handleCollision()`: Handles collision events by adjusting the position or behavior of the brick. + - `updatePosition()`: Updates the position of the brick based on collision resolution or user interaction. + +- **Stack.ts:** + - Properties: + - `id`: Unique identifier for the stack. + - `bricks`: Array of bricks in the stack. + - Functions: + - `addBrick()`: Adds a brick to the stack. + - `removeBrick()`: Removes a brick from the stack. + - `connectBricks()`: Connects two bricks in the stack. + - `disconnectBricks()`: Disconnects two bricks in the stack. +- **Workspace.ts:** + - Properties: + - `id`: Unique identifier for the workspace. + - `stacks`: Array of stacks in the workspace. + - `gridSize`: Size of the grid in the workspace. + - `zoomLevel`: Zoom level of the workspace. + - Functions: + - `addStack()`: Adds a stack to the workspace. + - `removeStack()`: Removes a stack from the workspace. + - `findBrickById()`: Finds a brick in the workspace by its ID. + - `validateWorkspace()`: Validates the workspace state. + - `exportWorkspace()`: Exports the workspace state to a file. + - `importWorkspace()`: Imports the workspace state from a file. + +### Services: + +- **BrickService.ts:** + - Functions: + - `createBrick()`: Creates a new brick instance. + - `deleteBrick()`: Deletes a brick instance. + - `updateBrick()`: Updates a brick instance. + - `findBrickById()`: Finds a brick instance by its ID. +- **StackService.ts:** + - Functions: + - `createStack()`: Creates a new stack instance. + - `deleteStack()`: Deletes a stack instance. + - `updateStack()`: Updates a stack instance. + - `findStackById()`: Finds a stack instance by its ID. +- **WorkspaceService.ts:** + - Functions: + - `createWorkspace()`: Creates a new workspace instance. + - `deleteWorkspace()`: Deletes a workspace instance. + - `updateWorkspace()`: Updates a workspace instance. + - `findWorkspaceById()`: Finds a workspace instance by its ID. +- **QuadtreeService.ts:** + - Functions: + - `insertBrick()`: Inserts a brick into the quadtree for spatial indexing. + - `removeBrick()`: Removes a brick from the quadtree. + - `updateBrick()`: Updates the position of a brick in the quadtree. + - `findNearbyBricks()`: Finds nearby bricks within a certain radius using the quadtree. +- **ErrorHandlingService.ts:** + - Functions: + - `handleError()`: Handles errors and exceptions in the application. + - `logError()`: Logs errors to a server or local storage. + +## Testing: + +- Write unit tests for components, utilities, and hooks using Jest and React Testing Library. +- Write integration tests for drag-and-drop functionality and state management. +- Write end-to-end tests for the overall workflow using Cypress or Selenium. diff --git a/modules/masonry/docs/tech-spec/Techspec.md b/modules/masonry/docs/tech-spec/Techspec.md new file mode 100644 index 00000000..491027ac --- /dev/null +++ b/modules/masonry/docs/tech-spec/Techspec.md @@ -0,0 +1,150 @@ +# Masonry Framework + +## Palette + +#### Config (Inputs) +- **Categories**: + - **Attributes**: names, icons + - **Sections**: + - **Attributes**: name, icon, color + - **Bricks**: + - **Attributes**: id, name, description, thumbnail, BBox + +#### Search +- **Search text**: + - Substring match on name + - Substring match on description + - Minimum 3 characters + +#### Drag & Drop +- **For a brick**: + 1. Start drag operation + 2. Transfer brick's logo to workspace + 3. Replace thumbnail with silhouette (silhouette is a grayed-out thumbnail at 50% opacity) + +- **Drag Ended**: + - Replace silhouette with the original thumbnail + +- **Workspace (WS)**: + - Handles drag operations + - Stops drag within the palette + - Stops drag outside the palette + +## Brick + +#### Brick Types +- **Data Bricks** + - Returns values + - Connects only as arguments + - Example: input +- **Expression Bricks** + - Returns values + - Can take 0 or more arguments + - Connects only as arguments +- **Statement Bricks** + - Execute actions + - Connects with other statement/block types + - Can take 0 or more arguments +- **Block Bricks** + - Can nest other bricks + - Connects with other statement/block types + - Can take 0 or more arguments + +#### Brick Appearance +- **Attributes**: + - Color + - Shape + - Primary label + - Any labels (copied) + - Any connectors + +#### Brick Interactions +- **Inline Edit**: + - Only applicable to Data bricks + - Example: input text + +#### Brick Structure Overview +- **Brick**: + - Color + - Argument connectors + - Connectors for expression +- **Argument**: + - Can connect to data bricks +- **Data**: + - Inputs, labels, nodes +- **Expression**: + - Contains data bricks +- **Statement**: + - Instructions, connected to block +- **Block**: + - Can nest other bricks + + +## Stack + +### Stack Validation +- **Visual Feedback**: + - Indicators show whether brick combinations are valid. + - Example: A green outline appears for a valid connection, while a red outline indicates an invalid connection. +- **Error Indicators**: + - Provide explanations for incompatible connections to help users troubleshoot. + - Example: A reddish boundary and error message explain why the connection is invalid. + +### Stack Editing +- **Connection Editing**: + - Options for repositioning, disconnecting, or connecting bricks. + - Visual indicators show possible connections. + - Example: Highlight potential connection points when a brick is moved. + +### Stack Grouping +- **Collapsible Groups**: + - Groups can be collapsed or expanded to manage complexity. + - Example: Users can organize bricks into groups that can be collapsed to reduce visual clutter. + - Collapsed groups can be moved as a single unit. + +## Workspace + +### Layout and Interaction +- **Cloning**: + - Users can easily create copies of bricks for repeated use. + - Example: Right-click on a brick and select "Duplicate". +- **Scaling and Rotation**: + - Bricks can be resized and rotated to fit the workspace better. + - Example: Click and drag corner handles to resize, or use rotation handles to rotate. +- **Undo/Redo**: + - Users can revert or reapply changes to their stacks. + - Example: Undo the last action with Ctrl+Z, redo with Ctrl+Y. +- **Deletion of Bricks**: + - Users can remove or delete bricks. + - Example: Drag a brick to the trash icon or press the delete key. + +### Data Flow and Interaction + +#### Adding Bricks +- **From Palette to Workspace**: + 1. User drags a brick from the palette. + 2. Workspace detects the drag operation and shows a drop area. + 3. User drops the brick in the workspace. + 4. Workspace creates a new brick instance at the drop location. + +#### Connecting Bricks +- **Within Workspace**: + 1. User selects a connection point on a brick. + 2. User drags to another brick's connection point. + 3. Workspace validates the connection. + 4. If valid, a connection is established and visual feedback is provided. + 5. If invalid, an error message is shown. + +#### Editing Connections +- **Repositioning and Disconnecting**: + 1. User clicks on a connection line. + 2. User can drag the connection to a new point or disconnect it. + 3. Workspace updates the connections and provides visual feedback. + +#### Grouping Bricks +- **Creating and Managing Groups**: + 1. User selects multiple bricks. + 2. User groups them into a collapsible unit. + 3. Workspace treats the group as a single entity for movement and scaling. + 4. User can collapse or expand the group to manage workspace complexity. + From 9384a72c91628014c20093ba39264a0794a2d7b6 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Wed, 26 Jun 2024 13:00:41 +0530 Subject: [PATCH 05/58] feat(masonry/playground): add demo workspace and render stack of bricks --- modules/masonry/playground/index.html | 13 + modules/masonry/playground/package-lock.json | 3255 +++++++++++++++++ modules/masonry/playground/package.json | 28 + modules/masonry/playground/public/vite.svg | 1 + modules/masonry/playground/src/App.css | 0 modules/masonry/playground/src/App.tsx | 134 + .../masonry/playground/src/assets/react.svg | 1 + modules/masonry/playground/src/index.css | 0 modules/masonry/playground/src/main.tsx | 10 + modules/masonry/playground/src/test/Test.tsx | 137 + modules/masonry/playground/src/vite-env.d.ts | 1 + modules/masonry/playground/tsconfig.app.json | 27 + modules/masonry/playground/tsconfig.json | 11 + modules/masonry/playground/tsconfig.node.json | 13 + modules/masonry/playground/vite.config.ts | 7 + 15 files changed, 3638 insertions(+) create mode 100644 modules/masonry/playground/index.html create mode 100644 modules/masonry/playground/package-lock.json create mode 100644 modules/masonry/playground/package.json create mode 100644 modules/masonry/playground/public/vite.svg create mode 100644 modules/masonry/playground/src/App.css create mode 100644 modules/masonry/playground/src/App.tsx create mode 100644 modules/masonry/playground/src/assets/react.svg create mode 100644 modules/masonry/playground/src/index.css create mode 100644 modules/masonry/playground/src/main.tsx create mode 100644 modules/masonry/playground/src/test/Test.tsx create mode 100644 modules/masonry/playground/src/vite-env.d.ts create mode 100644 modules/masonry/playground/tsconfig.app.json create mode 100644 modules/masonry/playground/tsconfig.json create mode 100644 modules/masonry/playground/tsconfig.node.json create mode 100644 modules/masonry/playground/vite.config.ts diff --git a/modules/masonry/playground/index.html b/modules/masonry/playground/index.html new file mode 100644 index 00000000..47565672 --- /dev/null +++ b/modules/masonry/playground/index.html @@ -0,0 +1,13 @@ + + + + + + + Masonry-Test + + +

+ + + diff --git a/modules/masonry/playground/package-lock.json b/modules/masonry/playground/package-lock.json new file mode 100644 index 00000000..9aafa49f --- /dev/null +++ b/modules/masonry/playground/package-lock.json @@ -0,0 +1,3255 @@ +{ + "name": "masonry-test", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "masonry-test", + "version": "0.0.0", + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", + "@vitejs/plugin-react": "^4.3.1", + "eslint": "^8.57.0", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react-refresh": "^0.4.7", + "typescript": "^5.2.2", + "vite": "^5.3.1" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", + "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", + "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", + "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/type-utils": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", + "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", + "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", + "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", + "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", + "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", + "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", + "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.1", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", + "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.5", + "@babel/plugin-transform-react-jsx-self": "^7.24.5", + "@babel/plugin-transform-react-jsx-source": "^7.24.1", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/acorn": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.16" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001636", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", + "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.810", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.810.tgz", + "integrity": "sha512-Kaxhu4T7SJGpRQx99tq216gCq2nMxJo+uuT6uzz9l8TVN2stL7M06MIIXAtr9jsrLs2Glflgf2vMQRepxawOdQ==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.7.tgz", + "integrity": "sha512-yrj+KInFmwuQS2UQcg1SF83ha1tuHC1jMQbRNyuWtlEzzKRDgAl7L4Yp4NlDUZTZNlWvHEzOtJhMi40R7JxcSw==", + "dev": true, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", + "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz", + "integrity": "sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/modules/masonry/playground/package.json b/modules/masonry/playground/package.json new file mode 100644 index 00000000..8a458ece --- /dev/null +++ b/modules/masonry/playground/package.json @@ -0,0 +1,28 @@ +{ + "name": "masonry-test", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", + "@vitejs/plugin-react": "^4.3.1", + "eslint": "^8.57.0", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react-refresh": "^0.4.7", + "typescript": "^5.2.2", + "vite": "^5.3.1" + } +} diff --git a/modules/masonry/playground/public/vite.svg b/modules/masonry/playground/public/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/modules/masonry/playground/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/masonry/playground/src/App.css b/modules/masonry/playground/src/App.css new file mode 100644 index 00000000..e69de29b diff --git a/modules/masonry/playground/src/App.tsx b/modules/masonry/playground/src/App.tsx new file mode 100644 index 00000000..ee6258eb --- /dev/null +++ b/modules/masonry/playground/src/App.tsx @@ -0,0 +1,134 @@ +import React, { useState, useRef, useEffect } from 'react'; + +interface Brick { + id: number; + type: string; + x: number; + y: number; + color: string; +} + +const App: React.FC = () => { + const [bricks, setBricks] = useState([ + { id: 1, type: 'top', x: 50, y: 50, color: '#ff6b6b' }, + { id: 2, type: 'middle', x: 50, y: 110, color: '#4ecdc4' }, + { id: 3, type: 'middle', x: 50, y: 170, color: '#45b7d1' }, + { id: 4, type: 'middle', x: 50, y: 230, color: '#f9d56e' }, + { id: 5, type: 'middle', x: 50, y: 290, color: '#ff9ff3' }, + { id: 6, type: 'bottom', x: 50, y: 350, color: '#54a0ff' }, + ]); + const [isDragging, setIsDragging] = useState(false); + const [draggedBrickId, setDraggedBrickId] = useState(null); + const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); + const svgRef = useRef(null); + + const isConnected = (brick1: Brick, brick2: Brick) => + Math.abs(brick1.y + 60 - brick2.y) < 5 && Math.abs(brick1.x - brick2.x) < 5; + + const findConnectedBricks = (startId: number): number[] => { + const result: number[] = [startId]; + let currentId = startId; + + // Find bricks below + while (true) { + const currentBrick = bricks.find(b => b.id === currentId); + const nextBrick = bricks.find(b => b.id !== currentId && isConnected(currentBrick!, b)); + if (nextBrick && nextBrick.y > currentBrick!.y) { + result.push(nextBrick.id); + currentId = nextBrick.id; + } else { + break; + } + } + + return result; + }; + + const handleMouseDown = (e: React.MouseEvent, id: number) => { + const brick = bricks.find(b => b.id === id); + if (brick) { + const svgRect = svgRef.current?.getBoundingClientRect(); + if (svgRect) { + setIsDragging(true); + setDraggedBrickId(id); + setDragOffset({ + x: e.clientX - svgRect.left - brick.x, + y: e.clientY - svgRect.top - brick.y + }); + } + } + }; + + const handleMouseMove = (e: MouseEvent) => { + if (isDragging && draggedBrickId !== null) { + const svgRect = svgRef.current?.getBoundingClientRect(); + if (svgRect) { + const newX = e.clientX - svgRect.left - dragOffset.x; + const newY = e.clientY - svgRect.top - dragOffset.y; + + const connectedBricks = findConnectedBricks(draggedBrickId); + + setBricks(prevBricks => { + return prevBricks.map(brick => { + if (connectedBricks.includes(brick.id)) { + const index = connectedBricks.indexOf(brick.id); + return { + ...brick, + x: newX, + y: newY + index * 60 + }; + } + return brick; + }); + }); + } + } + }; + + const handleMouseUp = () => { + setIsDragging(false); + setDraggedBrickId(null); + }; + + useEffect(() => { + window.addEventListener('mousemove', handleMouseMove); + window.addEventListener('mouseup', handleMouseUp); + return () => { + window.removeEventListener('mousemove', handleMouseMove); + window.removeEventListener('mouseup', handleMouseUp); + }; + }, [isDragging, draggedBrickId]); + + const renderBrickPath = (type: string) => { + switch (type) { + case 'top': + return "M0,0 h100 v50 h-80 l-20,10 v-60 z"; + case 'middle': + return "M0,0 h80 l20,-10 v60 h-80 l-20,10 v-60 z"; + case 'bottom': + return "M0,0 h80 l20,-10 v60 h-100 v-50 z"; + default: + return ""; + } + }; + + return ( + + {bricks.map(brick => ( + handleMouseDown(e, brick.id)} + > + + + ))} + + ); +}; + +export default App; \ No newline at end of file diff --git a/modules/masonry/playground/src/assets/react.svg b/modules/masonry/playground/src/assets/react.svg new file mode 100644 index 00000000..6c87de9b --- /dev/null +++ b/modules/masonry/playground/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/masonry/playground/src/index.css b/modules/masonry/playground/src/index.css new file mode 100644 index 00000000..e69de29b diff --git a/modules/masonry/playground/src/main.tsx b/modules/masonry/playground/src/main.tsx new file mode 100644 index 00000000..3d7150da --- /dev/null +++ b/modules/masonry/playground/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/modules/masonry/playground/src/test/Test.tsx b/modules/masonry/playground/src/test/Test.tsx new file mode 100644 index 00000000..a59eaec0 --- /dev/null +++ b/modules/masonry/playground/src/test/Test.tsx @@ -0,0 +1,137 @@ +import React, { useState, useRef, useEffect } from 'react'; + +interface Brick { + id: number; + type: string; + x: number; + y: number; + color: string; +} + +const Test: React.FC = () => { + const [bricks, setBricks] = useState([ + { id: 1, type: 'set', x: 50, y: 50, color: '#ff9ff3' }, + { id: 2, type: 'repeat', x: 50, y: 110, color: '#54a0ff' }, + { id: 3, type: 'do', x: 200, y: 200, color: '#5f27cd' }, + ]); + const [isDragging, setIsDragging] = useState(false); + const [draggedBrickId, setDraggedBrickId] = useState(null); + const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); + const svgRef = useRef(null); + + const CONNECT_THRESHOLD = 20; // Pixels within which bricks can connect + const NOT_CONNECTABLE_THRESHOLD = 40; // Pixels within which bricks show they can't connect + + const isConnectable = (brick1: Brick, brick2: Brick) => + Math.abs(brick1.y + 60 - brick2.y) < CONNECT_THRESHOLD && Math.abs(brick1.x - brick2.x) < CONNECT_THRESHOLD; + + const isCloseButNotConnectable = (brick1: Brick, brick2: Brick) => + Math.abs(brick1.y + 60 - brick2.y) < NOT_CONNECTABLE_THRESHOLD && Math.abs(brick1.x - brick2.x) < NOT_CONNECTABLE_THRESHOLD; + + const handleMouseDown = (e: React.MouseEvent, id: number) => { + const brick = bricks.find(b => b.id === id); + if (brick) { + const svgRect = svgRef.current?.getBoundingClientRect(); + if (svgRect) { + setIsDragging(true); + setDraggedBrickId(id); + setDragOffset({ + x: e.clientX - svgRect.left - brick.x, + y: e.clientY - svgRect.top - brick.y + }); + } + } + }; + + const handleMouseMove = (e: MouseEvent) => { + if (isDragging && draggedBrickId !== null) { + const svgRect = svgRef.current?.getBoundingClientRect(); + if (svgRect) { + const newX = e.clientX - svgRect.left - dragOffset.x; + const newY = e.clientY - svgRect.top - dragOffset.y; + + setBricks(prevBricks => { + return prevBricks.map(brick => { + if (brick.id === draggedBrickId) { + return { ...brick, x: newX, y: newY }; + } + return brick; + }); + }); + } + } + }; + + const handleMouseUp = () => { + if (isDragging && draggedBrickId !== null) { + setBricks(prevBricks => { + const draggedBrick = prevBricks.find(b => b.id === draggedBrickId)!; + const connectableBrick = prevBricks.find(b => b.id !== draggedBrickId && isConnectable(draggedBrick, b)); + + if (connectableBrick) { + return prevBricks.map(brick => + brick.id === draggedBrickId ? { ...brick, x: connectableBrick.x, y: connectableBrick.y + 60 } : brick + ); + } + return prevBricks; + }); + } + setIsDragging(false); + setDraggedBrickId(null); + }; + + useEffect(() => { + window.addEventListener('mousemove', handleMouseMove); + window.addEventListener('mouseup', handleMouseUp); + return () => { + window.removeEventListener('mousemove', handleMouseMove); + window.removeEventListener('mouseup', handleMouseUp); + }; + }, [isDragging, draggedBrickId]); + + const renderBrickPath = (type: string) => { + switch (type) { + case 'set': + return "M0,0 h120 v60 h-100 l-20,10 v-70 z"; + case 'repeat': + return "M0,0 h140 v60 h-120 l-20,10 v-70 z"; + case 'do': + return "M0,0 h80 v60 h-60 l-20,10 v-70 z"; + default: + return ""; + } + }; + + return ( + + + + + + + {bricks.map(brick => { + const isConnectableToAny = bricks.some(b => b.id !== brick.id && isConnectable(brick, b)); + const isCloseButNotConnectableToAny = bricks.some(b => b.id !== brick.id && isCloseButNotConnectable(brick, b) && !isConnectable(brick, b)); + + return ( + handleMouseDown(e, brick.id)} + > + + {brick.type} + + ); + })} + + ); +}; + +export default Test; \ No newline at end of file diff --git a/modules/masonry/playground/src/vite-env.d.ts b/modules/masonry/playground/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/modules/masonry/playground/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/modules/masonry/playground/tsconfig.app.json b/modules/masonry/playground/tsconfig.app.json new file mode 100644 index 00000000..d739292a --- /dev/null +++ b/modules/masonry/playground/tsconfig.app.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/modules/masonry/playground/tsconfig.json b/modules/masonry/playground/tsconfig.json new file mode 100644 index 00000000..ea9d0cd8 --- /dev/null +++ b/modules/masonry/playground/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/modules/masonry/playground/tsconfig.node.json b/modules/masonry/playground/tsconfig.node.json new file mode 100644 index 00000000..3afdd6e3 --- /dev/null +++ b/modules/masonry/playground/tsconfig.node.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true, + "noEmit": true + }, + "include": ["vite.config.ts"] +} diff --git a/modules/masonry/playground/vite.config.ts b/modules/masonry/playground/vite.config.ts new file mode 100644 index 00000000..5a33944a --- /dev/null +++ b/modules/masonry/playground/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}) From 7efa22f05ae04a09cce7b4c5bdb58a94aa083f98 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Wed, 26 Jun 2024 13:26:45 +0530 Subject: [PATCH 06/58] fix(masonry) : fix lint errors and create src/index.ts --- .../docs/PRD/Masonry_Design_Document.md | 589 +++++++++--------- modules/masonry/docs/PRD/PRD.md | 127 ++-- .../masonry/docs/architecture/Processes.md | 21 +- modules/masonry/docs/tech-spec/TechSpec.md | 506 +++++++-------- modules/masonry/docs/tech-spec/Techspec.md | 23 +- modules/masonry/src/index.ts | 0 6 files changed, 648 insertions(+), 618 deletions(-) create mode 100644 modules/masonry/src/index.ts diff --git a/modules/masonry/docs/PRD/Masonry_Design_Document.md b/modules/masonry/docs/PRD/Masonry_Design_Document.md index 78cc85e1..b73c2c2d 100644 --- a/modules/masonry/docs/PRD/Masonry_Design_Document.md +++ b/modules/masonry/docs/PRD/Masonry_Design_Document.md @@ -4,6 +4,7 @@ # Music Blocks v4 : Masonry Design Document ## Overview + 1. **Short Description of the Product** - The Masonry (previously called Project Builder) in Music Blocks v4 facilitates graphical brick-based music composition, offering various Brick types such as Start, Rhythm, Note, Pitch, and Instrument Bricks. Each brick represents a specific functionality, enabling users, especially children, to visually create music programs. The Masonry module simplifies the process of selecting and arranging bricks to generate music sequences. @@ -22,7 +23,7 @@ 4. **Subsystems** - Palette Subsystem: Manages the palette interface within Music Blocks, providing a selection of bricks for users to drag and drop into the workspace. - - Workspace Subsystem: Controls the workspace area where users can arrange bricks and create music compositions. + - Workspace Subsystem: Controls the workspace area where users can arrange bricks and create music compositions. - Brick Stack Subsystem: Handles the creation and management of stacks of bricks within the workspace, allowing users to combine bricks to form musical sequences. - Collision Detection Subsystem: Implements collision detection functionality within the workspace, ensuring that bricks interact appropriately to prevent overlapping or conflicting arrangements. @@ -31,7 +32,7 @@ - Integration of a collision detection UI inspired by the Brickly game by Google, enhancing user experience and interaction feedback. - Optimization of the palette by combining similar types of bricks, reducing clutter and improving usability. - Enhancement of the search functionality to facilitate easier navigation and selection of bricks within the palette. - + 6. **Purpose** - The purpose of this document is to outline the design and architecture of Masonry framework for Music Blocks v4 @@ -43,14 +44,16 @@ 9. **Definitions and Abbreviations** - **Masonry:** The term used to describe the replication and enhancement of the functionality related to bricks from the palette, stack of bricks, and other related components of the project, aimed at improving their functionality and effectiveness. - + [Screencast from 13-05-24 12:15:30 PM IST.webm](https://github.com/Karan-Palan/musicblocks-v4/assets/143683619/ae9df412-8b3a-4930-8635-ad89da828ba9) 10. **References** - - [Link to Music Blocks v3 project](https://github.com/sugarlabs/musicblocks) - - [Link to Masonry Framework](https://github.com/sugarlabs/musicblocks-v4/tree/develop/modules/code-builder) + +- [Link to Music Blocks v3 project](https://github.com/sugarlabs/musicblocks) +- [Link to Masonry Framework](https://github.com/sugarlabs/musicblocks-v4/tree/develop/modules/code-builder) ## Requirements, Wiki Storages and Docs + 1. **Requirements** - Functional requirements: Dynamic editing, text addition, UI enhancements, palette feature, integration with Music Blocks v4 project. - Non-functional requirements: Performance, scalability, maintainability. @@ -68,292 +71,302 @@ - Assumptions: Basic understanding of React, JavaScript/TypeScript, and information about Music Blocks software. ## Architecture and Requirements Diagram + To be added ## Design Specification -#### 1. Workspace: - - Canvas Area: - - Large central area for creating and manipulating musical compositions - - Resizable canvas to accommodate compositions of varying sizes - - Optional background grid or ruled lines for precise Brick placement - - - Grid System: - - Configurable grid spacing and subdivisions - - Snap-to-grid functionality for aligning Bricks to grid lines - - Visual indicators (e.g., dotted lines, highlights) for grid lines and snap points - - - Staff Rendering: - - Multiple staff lines for representing different instruments or voices - - Customizable staff parameters (number of lines, clef, key signature, time signature) - - Dynamic staff layout and spacing based on the composition's content - - - Brick Connections: - - Visual representation of connections between Bricks (e.g., lines, curves, bezier paths) - - Color-coding or highlighting for different connection types or data flows - - Animated transitions or visual cues when establishing or breaking connections - - - Visual Feedback: - - Error indicators (e.g., red outlines, warning icons) for invalid Brick placements or connections - - Compatibility indicators (e.g., green highlights) for valid Brick combinations - - Tooltips or popups for providing additional information or guidance - - - Navigation and Viewing: - - Panning and scrolling functionality for navigating large compositions - - Zoom controls for adjusting the workspace scale and level of detail - - Minimap or overview panel for a bird's-eye view of the entire composition - - - Workspace Customization: - - Options to hide or show grid lines, staff lines, or other visual aids - - Configurable workspace background color or theme - - Ability to save and load workspace layouts or configurati - -#### 2. Palette: - - Layout and Organization: - - Collapsible/expandable categories or sections for different Brick types - - Customizable order and arrangement of categories - - Visual separators or dividers between categories - - - Brick Previews: - - Thumbnail or icon previews for each Brick within a category - - Tooltips or pop-ups displaying Brick names and brief descriptions - - Color-coding or visual cues for distinguishing different Brick types - - - Search and Filtering: - - Search bar or input field for locating specific Bricks by name or keyword - - Filter options for narrowing down Bricks based on category, type, or properties - - Live search results or suggestions as the user types - - - Drag and Drop: - - Ability to drag and drop Bricks from the palette onto the workspace - - Visual indicators (e.g., ghost preview, outline) for valid drop locations - - Snap-to-grid or precise positioning when dropping Bricks - - - Brick Creation: - - Options for creating new Bricks or Brick instances directly from the palette - - Context menus or shortcuts for duplicating or cloning existing Bricks - - Visual feedback or animations when creating or instantiating new Bricks - - - Customization: - - User-defined categories or custom groupings for organizing Bricks - - Ability to rename, reorder, or hide/show specific categories - - Import/export functionality for sharing or backing up custom palette configurations - - - Palette Behavior: - - Dockable or floating palette panel for flexible positioning - - Resizable palette window or panel for adjusting its size - - Auto-hide or collapse functionality for maximizing workspace area - -#### 3. Bricks: - - Shape and Appearance: - - Distinct geometric shapes (rectangles, circles, hexagons) for different Brick categories - - Color schemes and palettes for visually differentiating Brick types - - Textured or patterned backgrounds for certain Brick categories (e.g., control structures) - - - Brick Labels and Icons: - - Clear and concise text labels describing the Brick's function - - Intuitive icons or symbols representing the Brick's purpose - - Customizable font styles, sizes, and colors for labels and icons - - - Input/Output Ports: - - Shaped ports or connectors for linking Bricks together - - Color-coding or visual cues for indicating compatible port types - - Tooltips or labels explaining the purpose and data type of each port - - - Brick Parameters: - - Editable fields within Bricks for adjusting parameters (e.g., note values, durations) - - Drop-down menus or selectors for choosing from predefined parameter options - - Visual indicators like sliders, knobs, or dials for continuous parameter adjustments - - - Resizing and Scaling: - - Resize handles (corners, edges) for adjusting Brick dimensions - - Proportional scaling or aspect ratio locking options - - Dynamic scaling of Brick contents (text, icons) during resizing - - - Rotation and Flipping: - - Rotation handles or controls for changing Brick orientation - - Flip or mirror functionality for reversing Brick placement - - Snap-to-angle or constrained rotation options (e.g., 90-degree increments) - - - Cloning and Duplication: - - Duplicate or clone functionality for creating copies of existing Bricks - - Visual previews or ghosted outlines for cloned Brick instances - - Options for shallow cloning (duplicating the Brick) or deep cloning (including nested Bricks) - - - Advanced Editing: - - Context menus or dedicated editors for advanced Brick customization - - Visual indicators or badges for displaying Brick metadata (e.g., unique IDs) - - Color-coding or visual cues for distinguishing different Brick states or modes - -#### 4. Brick Connections: - - Connection Styles: - - Various visual styles for rendering connections (straight lines, curves, bezier paths) - - Customizable line thickness, colors, and patterns for different connection types - - Animated transitions or visual effects when establishing or breaking connections - - - Connection Routing: - - Automatic routing algorithms for avoiding overlaps and minimizing crossed connections - - Manual routing options for overriding automatic layouts - - Visual guides or markers for assisting with precise connection routing - - - Connection Labels: - - Ability to add labels or annotations along connections - - Customizable label styles (font, color, background) for different connection types - - Positioning options for labels (centered, aligned to start/end) - - - Data Flow Visualization: - - Visual indicators or animations for showing data flow direction along connections - - Color-coding or highlighting for different data types or flows - - Tooltips or pop-ups for displaying data values or previews - - - Connection Validation: - - Visual feedback for valid and invalid connections (e.g., green/red highlights) - - Error messages or tooltips explaining incompatible connections - - Ability to temporarily disable validation for advanced use cases - - - Connection Editing: - - Options for rerouting, splitting, or merging connections - - Context menus or shortcuts for quickly editing connection properties - - Undo/redo functionality for connection editing operations - - - Connection Grouping: - - Ability to group multiple connections together for better organization - - Visual boundaries or outlines for defining connection groups - - Collapsible or expandable groups for managing complexity - -#### 5. Collision Detection and Snapping: - - Brick Bounding Boxes: - - Visual representations of Brick bounding boxes or hit areas - - Configurable padding or margins around Brick boundaries - - Color-coding or highlighting of bounding boxes for debugging or visualization - - - Proximity Detection: - - Visual indicators or highlights when Bricks are within a specified proximity - - Adjustable proximity thresholds or ranges for different snapping behaviors - - Tooltips or pop-ups displaying the current proximity distance - - - Snap-to-Grid: - - Visual guides or markers for grid lines and snap points - - Configurable grid spacing and subdivision settings - - Adjustable snapping strength or magnetic attraction to the grid - - - Snap-to-Brick: - - Alignment guides or visual cues for snapping Bricks to other Brick edges or centers - - Customizable snapping priorities (e.g., snap to centers first, then edges) - - Temporary visual previews of snapped positions before releasing the Brick - - - Snap-to-Connection: - - Visual indicators or highlights for compatible connection points between Bricks - - Automatic connection establishment when Bricks are snapped together - - Animations or visual effects during the snapping and connection process - - - Overlap Prevention: - - Visual feedback or error indicators for overlapping or invalid Brick placements - - Automatic repositioning or nudging of Bricks to avoid overlaps - - User-defined rules or constraints for allowing or preventing Brick overlaps - - - Snapping Customization: - - Options to enable or disable specific snapping behaviors (grid, Brick, connection) - - User-defined snapping preferences or profiles - - Import/export functionality for sharing custom snapping configurations - -#### 6. Brick Editing and Customization: - - Inline Editing: - - Editable text fields within Bricks for modifying labels, values, or parameters - - Visual indicators or highlights for active inline editing mode - - Validation and error feedback for invalid inputs or out-of-range values - - - Drop-down Menus: - - Drop-down lists or selectors within Bricks for choosing from predefined options - - Customizable visual styles (fonts, colors, icons) for drop-down menu items - - Tooltips or previews for displaying additional information about each option - - - Context Menus: - - Right-click or long-press context menus for accessing Brick-specific actions - - Hierarchical or nested menus for organizing related actions and options - - Keyboard shortcuts or mnemonics for quick access to frequently used actions - - - Dedicated Editors: - - Modal dialogs or dedicated panels for advanced Brick customization - - Visual editing interfaces (e.g., piano roll, rhythm editors) for specialized parameters - - Undo/redo functionality within dedicated editors for tracking changes - - - Undo/Redo Indicators: - - Visual indicators or badges for displaying the current undo/redo state - - Animations or visual effects when undoing or redoing Brick editing actions - - Tooltips or pop-ups showing a preview of the undo/redo operation - -#### 7. Musical Notation Rendering: - - Notation Styles: - - Traditional staff notation with notes, rests, and other musical symbols - - Alternative representations like piano roll, guitar tablature, or custom notations - - Customizable notation styles (fonts, colors, line spacing) for different instruments - - - Real-time Updates: - - Synchronized updates to the notation as Bricks are added, removed, or modified - - Smooth transitions or animations when updating the notation - - Visual indicators or highlights for recently changed or updated notation elements - - - Notation Switching: - - Options or controls for switching between different notation styles or views - - Visual previews or thumbnails of each notation style for easy identification - - Customizable keyboard shortcuts or hotkeys for quickly switching notations - - - Notation Overlays: - - Ability to overlay multiple notation styles or representations simultaneously - - Visual separators or dividers between different notation layers - - Customizable transparency or opacity settings for each notation layer - - - Playback Integration: - - Synchronized highlighting or animations within the notation during audio playback - - Visual indicators or markers for the current playback position - - Customizable playback cursors or beat markers for different notation styles - -#### 8. Audio Playback and Visualization: - - Playback Controls: - - Intuitive play, pause, stop, and seek buttons or controls - - Visual feedback for playback state (playing, paused, stopped) - - Seek bar or timeline for navigating through the composition - - - Audio Visualizations: - - Synchronized visualizations like piano roll, waveform, or custom graphical representations - - Configurable visualization styles (colors, themes, rendering modes) - - Visual indicators or animations synchronized with the audio playback - - - Instrument Selection: - - Visual representations (icons, thumbnails) for different instrument sounds - - Categorization or grouping of instruments (e.g., by family, genre) - - Tooltips or previews for auditioning instrument sounds - - - Playback Overlays: - - Ability to overlay multiple visualizations or instrument views simultaneously - - Visual separators or dividers between different overlay layers - - Customizable transparency or opacity settings for each overlay layer - -#### 9. User Interface and Interactions: - - Responsive Layout: - - Adaptive and responsive design for different screen sizes and resolutions - - Automatic layout adjustments and reflow for optimal viewing experience - - Optional full-screen or immersive mode for maximizing workspace area - - - Keyboard Shortcuts: - - Visual indicators or tooltips for available keyboard shortcuts and hotkeys - - Customizable keyboard shortcut mappings and assignments - - Conflict resolution or priority handling for overlapping shortcut combinations - - - Toolbars and Menus: - - Configurable toolbars and menus for quick access to frequently used features - - Customizable toolbar and menu layouts (docking, floating, auto-hide) - - Visual indicators or badges for displaying tool states or modes - - - Themes and Customization: - - Predefined color themes and visual styles for different preferences - - Customizable color schemes, font styles, and icon sets - - Import/export functionality for sharing custom theme configurations - - - Accessibility: - - High-contrast mode or themes for improved visibility - - Screen reader support and appropriate labeling for accessibility - - Adjustable font sizes and zoom levels for better readability +#### 1. Workspace + +- Canvas Area: + - Large central area for creating and manipulating musical compositions + - Resizable canvas to accommodate compositions of varying sizes + - Optional background grid or ruled lines for precise Brick placement + +- Grid System: + - Configurable grid spacing and subdivisions + - Snap-to-grid functionality for aligning Bricks to grid lines + - Visual indicators (e.g., dotted lines, highlights) for grid lines and snap points + +- Staff Rendering: + - Multiple staff lines for representing different instruments or voices + - Customizable staff parameters (number of lines, clef, key signature, time signature) + - Dynamic staff layout and spacing based on the composition's content + +- Brick Connections: + - Visual representation of connections between Bricks (e.g., lines, curves, bezier paths) + - Color-coding or highlighting for different connection types or data flows + - Animated transitions or visual cues when establishing or breaking connections + +- Visual Feedback: + - Error indicators (e.g., red outlines, warning icons) for invalid Brick placements or connections + - Compatibility indicators (e.g., green highlights) for valid Brick combinations + - Tooltips or popups for providing additional information or guidance + +- Navigation and Viewing: + - Panning and scrolling functionality for navigating large compositions + - Zoom controls for adjusting the workspace scale and level of detail + - Minimap or overview panel for a bird's-eye view of the entire composition + +- Workspace Customization: + - Options to hide or show grid lines, staff lines, or other visual aids + - Configurable workspace background color or theme + - Ability to save and load workspace layouts or configurati + +#### 2. Palette + +- Layout and Organization: + - Collapsible/expandable categories or sections for different Brick types + - Customizable order and arrangement of categories + - Visual separators or dividers between categories + +- Brick Previews: + - Thumbnail or icon previews for each Brick within a category + - Tooltips or pop-ups displaying Brick names and brief descriptions + - Color-coding or visual cues for distinguishing different Brick types + +- Search and Filtering: + - Search bar or input field for locating specific Bricks by name or keyword + - Filter options for narrowing down Bricks based on category, type, or properties + - Live search results or suggestions as the user types + +- Drag and Drop: + - Ability to drag and drop Bricks from the palette onto the workspace + - Visual indicators (e.g., ghost preview, outline) for valid drop locations + - Snap-to-grid or precise positioning when dropping Bricks + +- Brick Creation: + - Options for creating new Bricks or Brick instances directly from the palette + - Context menus or shortcuts for duplicating or cloning existing Bricks + - Visual feedback or animations when creating or instantiating new Bricks + +- Customization: + - User-defined categories or custom groupings for organizing Bricks + - Ability to rename, reorder, or hide/show specific categories + - Import/export functionality for sharing or backing up custom palette configurations + +- Palette Behavior: + - Dockable or floating palette panel for flexible positioning + - Resizable palette window or panel for adjusting its size + - Auto-hide or collapse functionality for maximizing workspace area + +#### 3. Bricks + +- Shape and Appearance: + - Distinct geometric shapes (rectangles, circles, hexagons) for different Brick categories + - Color schemes and palettes for visually differentiating Brick types + - Textured or patterned backgrounds for certain Brick categories (e.g., control structures) + +- Brick Labels and Icons: + - Clear and concise text labels describing the Brick's function + - Intuitive icons or symbols representing the Brick's purpose + - Customizable font styles, sizes, and colors for labels and icons + +- Input/Output Ports: + - Shaped ports or connectors for linking Bricks together + - Color-coding or visual cues for indicating compatible port types + - Tooltips or labels explaining the purpose and data type of each port + +- Brick Parameters: + - Editable fields within Bricks for adjusting parameters (e.g., note values, durations) + - Drop-down menus or selectors for choosing from predefined parameter options + - Visual indicators like sliders, knobs, or dials for continuous parameter adjustments + +- Resizing and Scaling: + - Resize handles (corners, edges) for adjusting Brick dimensions + - Proportional scaling or aspect ratio locking options + - Dynamic scaling of Brick contents (text, icons) during resizing + +- Rotation and Flipping: + - Rotation handles or controls for changing Brick orientation + - Flip or mirror functionality for reversing Brick placement + - Snap-to-angle or constrained rotation options (e.g., 90-degree increments) + +- Cloning and Duplication: + - Duplicate or clone functionality for creating copies of existing Bricks + - Visual previews or ghosted outlines for cloned Brick instances + - Options for shallow cloning (duplicating the Brick) or deep cloning (including nested Bricks) + +- Advanced Editing: + - Context menus or dedicated editors for advanced Brick customization + - Visual indicators or badges for displaying Brick metadata (e.g., unique IDs) + - Color-coding or visual cues for distinguishing different Brick states or modes + +#### 4. Brick Connections + +- Connection Styles: + - Various visual styles for rendering connections (straight lines, curves, bezier paths) + - Customizable line thickness, colors, and patterns for different connection types + - Animated transitions or visual effects when establishing or breaking connections + +- Connection Routing: + - Automatic routing algorithms for avoiding overlaps and minimizing crossed connections + - Manual routing options for overriding automatic layouts + - Visual guides or markers for assisting with precise connection routing + +- Connection Labels: + - Ability to add labels or annotations along connections + - Customizable label styles (font, color, background) for different connection types + - Positioning options for labels (centered, aligned to start/end) + +- Data Flow Visualization: + - Visual indicators or animations for showing data flow direction along connections + - Color-coding or highlighting for different data types or flows + - Tooltips or pop-ups for displaying data values or previews + +- Connection Validation: + - Visual feedback for valid and invalid connections (e.g., green/red highlights) + - Error messages or tooltips explaining incompatible connections + - Ability to temporarily disable validation for advanced use cases + +- Connection Editing: + - Options for rerouting, splitting, or merging connections + - Context menus or shortcuts for quickly editing connection properties + - Undo/redo functionality for connection editing operations + +- Connection Grouping: + - Ability to group multiple connections together for better organization + - Visual boundaries or outlines for defining connection groups + - Collapsible or expandable groups for managing complexity + +#### 5. Collision Detection and Snapping + +- Brick Bounding Boxes: + - Visual representations of Brick bounding boxes or hit areas + - Configurable padding or margins around Brick boundaries + - Color-coding or highlighting of bounding boxes for debugging or visualization + +- Proximity Detection: + - Visual indicators or highlights when Bricks are within a specified proximity + - Adjustable proximity thresholds or ranges for different snapping behaviors + - Tooltips or pop-ups displaying the current proximity distance + +- Snap-to-Grid: + - Visual guides or markers for grid lines and snap points + - Configurable grid spacing and subdivision settings + - Adjustable snapping strength or magnetic attraction to the grid + +- Snap-to-Brick: + - Alignment guides or visual cues for snapping Bricks to other Brick edges or centers + - Customizable snapping priorities (e.g., snap to centers first, then edges) + - Temporary visual previews of snapped positions before releasing the Brick + +- Snap-to-Connection: + - Visual indicators or highlights for compatible connection points between Bricks + - Automatic connection establishment when Bricks are snapped together + - Animations or visual effects during the snapping and connection process + +- Overlap Prevention: + - Visual feedback or error indicators for overlapping or invalid Brick placements + - Automatic repositioning or nudging of Bricks to avoid overlaps + - User-defined rules or constraints for allowing or preventing Brick overlaps + +- Snapping Customization: + - Options to enable or disable specific snapping behaviors (grid, Brick, connection) + - User-defined snapping preferences or profiles + - Import/export functionality for sharing custom snapping configurations + +#### 6. Brick Editing and Customization + +- Inline Editing: + - Editable text fields within Bricks for modifying labels, values, or parameters + - Visual indicators or highlights for active inline editing mode + - Validation and error feedback for invalid inputs or out-of-range values + +- Drop-down Menus: + - Drop-down lists or selectors within Bricks for choosing from predefined options + - Customizable visual styles (fonts, colors, icons) for drop-down menu items + - Tooltips or previews for displaying additional information about each option + +- Context Menus: + - Right-click or long-press context menus for accessing Brick-specific actions + - Hierarchical or nested menus for organizing related actions and options + - Keyboard shortcuts or mnemonics for quick access to frequently used actions + +- Dedicated Editors: + - Modal dialogs or dedicated panels for advanced Brick customization + - Visual editing interfaces (e.g., piano roll, rhythm editors) for specialized parameters + - Undo/redo functionality within dedicated editors for tracking changes + +- Undo/Redo Indicators: + - Visual indicators or badges for displaying the current undo/redo state + - Animations or visual effects when undoing or redoing Brick editing actions + - Tooltips or pop-ups showing a preview of the undo/redo operation + +#### 7. Musical Notation Rendering + +- Notation Styles: + - Traditional staff notation with notes, rests, and other musical symbols + - Alternative representations like piano roll, guitar tablature, or custom notations + - Customizable notation styles (fonts, colors, line spacing) for different instruments + +- Real-time Updates: + - Synchronized updates to the notation as Bricks are added, removed, or modified + - Smooth transitions or animations when updating the notation + - Visual indicators or highlights for recently changed or updated notation elements + +- Notation Switching: + - Options or controls for switching between different notation styles or views + - Visual previews or thumbnails of each notation style for easy identification + - Customizable keyboard shortcuts or hotkeys for quickly switching notations + +- Notation Overlays: + - Ability to overlay multiple notation styles or representations simultaneously + - Visual separators or dividers between different notation layers + - Customizable transparency or opacity settings for each notation layer + +- Playback Integration: + - Synchronized highlighting or animations within the notation during audio playback + - Visual indicators or markers for the current playback position + - Customizable playback cursors or beat markers for different notation styles + +#### 8. Audio Playback and Visualization + +- Playback Controls: + - Intuitive play, pause, stop, and seek buttons or controls + - Visual feedback for playback state (playing, paused, stopped) + - Seek bar or timeline for navigating through the composition + +- Audio Visualizations: + - Synchronized visualizations like piano roll, waveform, or custom graphical representations + - Configurable visualization styles (colors, themes, rendering modes) + - Visual indicators or animations synchronized with the audio playback + +- Instrument Selection: + - Visual representations (icons, thumbnails) for different instrument sounds + - Categorization or grouping of instruments (e.g., by family, genre) + - Tooltips or previews for auditioning instrument sounds + +- Playback Overlays: + - Ability to overlay multiple visualizations or instrument views simultaneously + - Visual separators or dividers between different overlay layers + - Customizable transparency or opacity settings for each overlay layer + +#### 9. User Interface and Interactions + +- Responsive Layout: + - Adaptive and responsive design for different screen sizes and resolutions + - Automatic layout adjustments and reflow for optimal viewing experience + - Optional full-screen or immersive mode for maximizing workspace area + +- Keyboard Shortcuts: + - Visual indicators or tooltips for available keyboard shortcuts and hotkeys + - Customizable keyboard shortcut mappings and assignments + - Conflict resolution or priority handling for overlapping shortcut combinations + +- Toolbars and Menus: + - Configurable toolbars and menus for quick access to frequently used features + - Customizable toolbar and menu layouts (docking, floating, auto-hide) + - Visual indicators or badges for displaying tool states or modes + +- Themes and Customization: + - Predefined color themes and visual styles for different preferences + - Customizable color schemes, font styles, and icon sets + - Import/export functionality for sharing custom theme configurations + +- Accessibility: + - High-contrast mode or themes for improved visibility + - Screen reader support and appropriate labeling for accessibility + - Adjustable font sizes and zoom levels for better readability --- diff --git a/modules/masonry/docs/PRD/PRD.md b/modules/masonry/docs/PRD/PRD.md index d35c7609..04443c79 100644 --- a/modules/masonry/docs/PRD/PRD.md +++ b/modules/masonry/docs/PRD/PRD.md @@ -5,143 +5,140 @@ ### a. Brick Types -#### 1. Data Bricks: These serve as inputs for other bricks and come in two types: hardcoded and editable. - - Hardcoded Data Brick: Fixed values that cannot be changed by the user. Examples include predefined note values, counts, etc. +#### 1. Data Bricks: These serve as inputs for other bricks and come in two types: hardcoded and editable + +- Hardcoded Data Brick: Fixed values that cannot be changed by the user. Examples include predefined note values, counts, etc. ![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 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) - - -#### 2. Expression Bricks: Takes values as input, returns a value as output. +#### 2. Expression Bricks: Takes values as input, returns a value as output ![alt text](./images/image-2.png) -#### 3. Statement Bricks: These define actions to be taken. +#### 3. Statement Bricks: These define actions to be taken ![example](./images/image-3.png) -#### 4. Block Bricks: Contain nesting, also execute something like the statement bricks. Takes 0 or more arguments. - +#### 4. Block Bricks: Contain nesting, also execute something like the statement bricks. Takes 0 or more arguments + ![alt text](./images/image-14.png) ### b. Brick Appearance - - **Distinct Shapes**: Each brick type has a unique shape to differentiate its function visually. - - **Colors**: + +- **Distinct Shapes**: Each brick type has a unique shape to differentiate its function visually. +- **Colors**: 1. **Original Color**: Each brick has a unique color that represents its type. 2. **Hover Color**: When a user hovers over a brick, it changes to a distinct color to indicate it is selectable. 3. **Disconnected Color**: If a brick is not connected to the stack, it turns gray to indicate it is inactive. 4. **Execution Color**: When a brick is executed, it changes to a darker shade of its original color to show that it has been activated. - - **Sprites**: Visual symbols that indicate specific functions or properties of the brick. Some bricks may have sprites (like the start brick), while others may not. - - **Labels**: +- **Sprites**: Visual symbols that indicate specific functions or properties of the brick. Some bricks may have sprites (like the start brick), while others may not. +- **Labels**: 1. **Functionality Labels**: Text labels that indicate the function of the brick. 2. **Argument Labels**: Text labels that indicate the arguments or parameters that need to be provided for the brick's function. - - **Input/Output Ports**: Connectors that visually represent where bricks can attach to each other. - - **Editable Text Labels/Fields**: Users can input data directly into the bricks, such as note names, durations, and numerical values. +- **Input/Output Ports**: Connectors that visually represent where bricks can attach to each other. +- **Editable Text Labels/Fields**: Users can input data directly into the bricks, such as note names, durations, and numerical values. **Side Note:** If we want to implement a design similar to Scratch in the future, we can consider the following approach for connecting blocks: - - In Scratch, blocks are connected horizontally in a row for sequential execution. Each block has a tab at the bottom and a notch at the top, allowing them to snap together in a linear sequence. This design makes it clear which blocks will execute in order. + +- In Scratch, blocks are connected horizontally in a row for sequential execution. Each block has a tab at the bottom and a notch at the top, allowing them to snap together in a linear sequence. This design makes it clear which blocks will execute in order. ### c. Brick Interactions - - **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**: 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) + - Other bricks open both an inline text editor and a context menu for additional options. - - 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) - - **Context Menus**: For more complex properties, a separate interface allows detailed configuration. +- **Context Menus**: For more complex properties, a separate interface allows detailed configuration. ![dedicated editors](./images/image-5.png) - - **Connection Types**: +- **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) - - - ## 2. Stack of Bricks -### a. Stack Validation: - - **Visual Feedback**: Indicators show whether brick combinations are valid. +### a. Stack Validation - ![alt text](./images/image-6.png) +- **Visual Feedback**: Indicators show whether brick combinations are valid. - - **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-6.png) - ![alt text](./images/image-7.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) - - **Disable Validation**: Temporarily turn off validation for complex or experimental setups. +- **Disable Validation**: Temporarily turn off validation for complex or experimental setups. - **Note** - this is up for further discussion -### b. Stack Editing: - - **Connection Editing**: Options for re-positioning, disconnecting, or connecting. - - **Quick Edit Shortcuts**: Context menus or keyboard shortcuts speed up editing. +### b. Stack Editing + +- **Connection Editing**: Options for re-positioning, disconnecting, or connecting. +- **Quick Edit Shortcuts**: Context menus or keyboard shortcuts speed up editing. + +### c. Stack Grouping -### c. Stack Grouping: - - **Collapsible Groups**: Groups can be collapsed or expanded to manage complexity. +- **Collapsible Groups**: Groups can be collapsed or expanded to manage complexity. ![alt text](./images/image-9.png) +## 3. Palette -## 3. Palette: -### a. **Layout and Organization**: - - Collapsible/expandable categories or sections for different Brick types - - Visual separators or dividers between categories - - Customizable order and arrangement of categories - +### a. **Layout and Organization** + +- Collapsible/expandable categories or sections for different Brick types +- Visual separators or dividers between categories +- Customizable order and arrangement of categories ![alt text](./images/image-10.png) -### b. **Brick Previews**: - - Tooltips or pop-ups displaying Brick names and brief descriptions +### b. **Brick Previews** + +- Tooltips or pop-ups displaying Brick names and brief descriptions ![alt text](./images/image-16.png) - - Color-coding or visual cues for distinguishing different Brick types +- Color-coding or visual cues for distinguishing different Brick types -### c. **Search and Filtering**: - - Search bar or input field for locating specific Bricks by name or keyword - - Filter options for narrowing down Bricks based on category, type, or properties - - Live search results or suggestions as the user types - - Searchbar in Musicblocks as of now: +### c. **Search and Filtering** + +- Search bar or input field for locating specific Bricks by name or keyword +- Filter options for narrowing down Bricks based on category, type, or properties +- Live search results or suggestions as the user types + - Searchbar in Musicblocks as of now: ![alt text](./images//image-11.png) - - Searchbar design to be implemented: + - Searchbar design to be implemented: ![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. -### d. **Drag and Drop**: - - Ability to drag and drop Bricks from the palette onto the workspace. - - Visual indicators (e.g., ghost preview, outline) for valid drop locations. +### d. **Drag and Drop** +- 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) - - While dragging a brick from the palette, the brick should temporarily disappear from the palette until it is placed in the workspace. - - -## 4. Workspace: + - 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) - - - **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. - - **Undo/Redo**: Users can revert or reapply changes to their stacks. - - **Removal/Deletion of Bricks** : Users can remove/delete bricks \ No newline at end of file +- **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. +- **Undo/Redo**: Users can revert or reapply changes to their stacks. +- **Removal/Deletion of Bricks** : Users can remove/delete bricks diff --git a/modules/masonry/docs/architecture/Processes.md b/modules/masonry/docs/architecture/Processes.md index 9ba07c40..89471f88 100644 --- a/modules/masonry/docs/architecture/Processes.md +++ b/modules/masonry/docs/architecture/Processes.md @@ -1,6 +1,7 @@ # Processes for Data Flow Diagram ## Level 0: Masonry Framework Communication with MusicBlocks + 1. **Load Configuration**: - Input: Configuration File - Output: Initialized System @@ -19,7 +20,8 @@ ## Level 1: Interaction between Brick, Palette, Workspace, and Stack of Bricks -### Bricks: +### Bricks + 1. **Initialize Brick**: - Input: Brick Properties - Output: Initialized Brick @@ -28,7 +30,8 @@ - Input: Brick ID from Workspace - Output: Brick Properties to Workspace -### Palette: +### Palette + 1. **Load Brick List**: - Input: Configuration Settings - Output: List of Bricks @@ -38,7 +41,8 @@ - Output: Selected Brick Properties to Workspace (How this works is, The palette will have a loaded list of SVGs. When you drag one from palette onto the workspace, the brick will be created on the workspace whos id matches to the one in brick) -### Workspace: +### Workspace + 1. **Add Brick to Workspace**: - Input: Brick Properties from Palette - Output: Updated Workspace @@ -59,7 +63,8 @@ - Input: Current Workspace Data - Output: Saved Workspace State -### Stack of Bricks: +### Stack of Bricks + 1. **Initialize Stack**: - Input: Brick Stack Data - Output: Initialized Stack @@ -70,8 +75,8 @@ ## Level 2: Detailed Interaction within MVC Architecture +### Model -### Model: 1. BrickModel: - Properties: - brickType @@ -133,7 +138,8 @@ - undo() - redo() -### View: +### View + 1. BrickView: - Methods: - renderBrick(brick) @@ -161,7 +167,8 @@ - renderZoomControls(zoomLevel) - renderUndoRedoButtons(undoRedoStack) -### Controller: +### Controller + 1. BrickController: - Methods: - handleBrickPropertyChange(brick, properties) diff --git a/modules/masonry/docs/tech-spec/TechSpec.md b/modules/masonry/docs/tech-spec/TechSpec.md index 3a389b35..eb108ea3 100644 --- a/modules/masonry/docs/tech-spec/TechSpec.md +++ b/modules/masonry/docs/tech-spec/TechSpec.md @@ -2,7 +2,7 @@ This tech spec outlines the implementation details for the Masonry Framework, a core component of the MusicBlocks V4 project built with React and TypeScript. -## Project Structure: +## Project Structure ``` ├── src @@ -53,198 +53,198 @@ This tech spec outlines the implementation details for the Masonry Framework, a ├──... ``` -## Dependencies: +## Dependencies - React - TypeScript - React-aria (for drag-and-drop functionality) - ... (other relevant libraries) -## Description: +## Description -### Components: +### Components -#### a) Brick: +#### a) Brick - **Brick.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onDragStart`: Callback for drag start event. - - `onDragOver`: Callback for drag-over event. - - `onDrop`: Callback for drop event. - - `onDragEnd`: Callback for drag end event. - - `onClick`: Callback for click event. - - `onDoubleClick`: Callback for double-click event. - - `onContextMenu`: Callback for context menu event. - - `onInputChange`: Callback for input change event. - - `onOutputChange`: Callback for output change event. - - Functions: - - `render()`: Renders the brick component with its visual appearance and input/output ports. - - `handleDragStart()`: Handles the drag start event for the brick. - - `handleDragOver()`: Handles the drag-over event for the brick. - - `handleDrop()`: Handles the drop event for the brick. - - `handleDragEnd()`: Handles the drag end event for the brick. - - `handleClick()`: Handles the click event for the brick. - - `handleDoubleClick()`: Handles the double-click event for the brick. - - `handleContextMenu()`: Handles the context menu event for the brick. - - `handleInputChange()`: Handles the input change event for the brick. - - `handleOutputChange()`: Handles the output change event for the brick. + - Properties: + - `brick`: The brick model instance. + - `onDragStart`: Callback for drag start event. + - `onDragOver`: Callback for drag-over event. + - `onDrop`: Callback for drop event. + - `onDragEnd`: Callback for drag end event. + - `onClick`: Callback for click event. + - `onDoubleClick`: Callback for double-click event. + - `onContextMenu`: Callback for context menu event. + - `onInputChange`: Callback for input change event. + - `onOutputChange`: Callback for output change event. + - Functions: + - `render()`: Renders the brick component with its visual appearance and input/output ports. + - `handleDragStart()`: Handles the drag start event for the brick. + - `handleDragOver()`: Handles the drag-over event for the brick. + - `handleDrop()`: Handles the drop event for the brick. + - `handleDragEnd()`: Handles the drag end event for the brick. + - `handleClick()`: Handles the click event for the brick. + - `handleDoubleClick()`: Handles the double-click event for the brick. + - `handleContextMenu()`: Handles the context menu event for the brick. + - `handleInputChange()`: Handles the input change event for the brick. + - `handleOutputChange()`: Handles the output change event for the brick. - **BrickInput.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onConnect`: Callback for connect event. - - `onDisconnect`: Callback for disconnect event. - - Functions: - - `render()`: Renders the input port of the brick. - - `handleConnect()`: Handles the connect event for the input port. - - `handleDisconnect()`: Handles the disconnect event for the input port. + - Properties: + - `brick`: The brick model instance. + - `onConnect`: Callback for connect event. + - `onDisconnect`: Callback for disconnect event. + - Functions: + - `render()`: Renders the input port of the brick. + - `handleConnect()`: Handles the connect event for the input port. + - `handleDisconnect()`: Handles the disconnect event for the input port. - **BrickOutput.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onConnect`: Callback for connect event. - - `onDisconnect`: Callback for disconnect event. - - Functions: - - `render()`: Renders the output port of the brick. - - `handleConnect()`: Handles the connect event for the output port. - - `handleDisconnect()`: Handles the disconnect event for the output port. + - Properties: + - `brick`: The brick model instance. + - `onConnect`: Callback for connect event. + - `onDisconnect`: Callback for disconnect event. + - Functions: + - `render()`: Renders the output port of the brick. + - `handleConnect()`: Handles the connect event for the output port. + - `handleDisconnect()`: Handles the disconnect event for the output port. - **DataBrick.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onInputChange`: Callback for input change event. - - `onOutputChange`: Callback for output change event. - - Functions: - - `render()`: Renders the data brick component with its visual appearance and input/output ports. - - `handleInputChange()`: Handles the input change event for the data brick. - - `handleOutputChange()`: Handles the output change event for the data brick. + - Properties: + - `brick`: The brick model instance. + - `onInputChange`: Callback for input change event. + - `onOutputChange`: Callback for output change event. + - Functions: + - `render()`: Renders the data brick component with its visual appearance and input/output ports. + - `handleInputChange()`: Handles the input change event for the data brick. + - `handleOutputChange()`: Handles the output change event for the data brick. - **ExpressionBrick.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onInputChange`: Callback for input change event. - - `onOutputChange`: Callback for output change event. - - Functions: - - `render()`: Renders the expression brick component with its visual appearance and input/output ports. - - `handleInputChange()`: Handles the input change event for the expression brick. - - `handleOutputChange()`: Handles the output change event for the expression brick. + - Properties: + - `brick`: The brick model instance. + - `onInputChange`: Callback for input change event. + - `onOutputChange`: Callback for output change event. + - Functions: + - `render()`: Renders the expression brick component with its visual appearance and input/output ports. + - `handleInputChange()`: Handles the input change event for the expression brick. + - `handleOutputChange()`: Handles the output change event for the expression brick. - **StatementBrick.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onInputChange`: Callback for input change event. - - `onOutputChange`: Callback for output change event. - - Functions: - - `render()`: Renders the statement brick component with its visual appearance and input/output ports. - - `handleInputChange()`: Handles the input change event for the statement brick. - - `handleOutputChange()`: Handles the output change event for the statement brick. + - Properties: + - `brick`: The brick model instance. + - `onInputChange`: Callback for input change event. + - `onOutputChange`: Callback for output change event. + - Functions: + - `render()`: Renders the statement brick component with its visual appearance and input/output ports. + - `handleInputChange()`: Handles the input change event for the statement brick. + - `handleOutputChange()`: Handles the output change event for the statement brick. - **BlockBrick.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onInputChange`: Callback for input change event. - - `onOutputChange`: Callback for output change event. - - `children`: An array of nested brick instances. - - Functions: - - `render()`: Renders the block brick component with its visual appearance and input/output ports. - - `handleInputChange()`: Handles the input change event for the block brick. - - `handleOutputChange()`: Handles the output change event for the block brick. - - `handleNesting()`: Handles the nesting logic for nested bricks. - - `handleArguments()`: Manages the arguments for block bricks. + - Properties: + - `brick`: The brick model instance. + - `onInputChange`: Callback for input change event. + - `onOutputChange`: Callback for output change event. + - `children`: An array of nested brick instances. + - Functions: + - `render()`: Renders the block brick component with its visual appearance and input/output ports. + - `handleInputChange()`: Handles the input change event for the block brick. + - `handleOutputChange()`: Handles the output change event for the block brick. + - `handleNesting()`: Handles the nesting logic for nested bricks. + - `handleArguments()`: Manages the arguments for block bricks. -#### b) Palette: +#### b) Palette - **Palette.tsx:** - - Properties: - - `bricks`: An array of brick model instances. - - `onDragStart`: Callback for drag start event. - - `onDragOver`: Callback for drag-over event. - - `onDrop`: Callback for drop event. - - `onSearch`: Callback for search event. - - `searchQuery`: The current search query. - - Functions: - - `render()`: Renders the palette component with its visual appearance and categories. - - `handleDragStart()`: Handles the drag start event for the palette. - - `handleDragOver()`: Handles the drag-over event for the palette. - - `handleDrop()`: Handles the drop event for the palette. - - `handleSearch()`: Handles the search event for the palette. + - Properties: + - `bricks`: An array of brick model instances. + - `onDragStart`: Callback for drag start event. + - `onDragOver`: Callback for drag-over event. + - `onDrop`: Callback for drop event. + - `onSearch`: Callback for search event. + - `searchQuery`: The current search query. + - Functions: + - `render()`: Renders the palette component with its visual appearance and categories. + - `handleDragStart()`: Handles the drag start event for the palette. + - `handleDragOver()`: Handles the drag-over event for the palette. + - `handleDrop()`: Handles the drop event for the palette. + - `handleSearch()`: Handles the search event for the palette. - **PaletteCategory.tsx:** - - Properties: - - `category`: The category model instance. - - `bricks`: An array of brick model instances. - - Functions: - - `render()`: Renders the category component with its visual appearance and bricks. + - Properties: + - `category`: The category model instance. + - `bricks`: An array of brick model instances. + - Functions: + - `render()`: Renders the category component with its visual appearance and bricks. - **PaletteSearch.tsx:** - - Properties: - - `searchQuery`: The current search query. - - `onSearch`: Callback for search event. - - Functions: - - `render()`: Renders the search component with its visual appearance and input field. - - `handleSearch()`: Handles the search event for the search component. + - Properties: + - `searchQuery`: The current search query. + - `onSearch`: Callback for search event. + - Functions: + - `render()`: Renders the search component with its visual appearance and input field. + - `handleSearch()`: Handles the search event for the search component. -#### c) Workspace: +#### c) Workspace - **Workspace.tsx:** - - Properties: - - `workspace`: The workspace model instance. - - `onBrickAdd`: Callback for brick add event. - - `onBrickRemove`: Callback for brick remove event. - - `onBrickConnect`: Callback for brick connect event. - - `onBrickDisconnect`: Callback for brick disconnect event. - - `onBrickMove`: Callback for brick move event. - - `onBrickResize`: Callback for brick resize event. - - `onBrickRotate`: Callback for brick rotate event. - - `onUndo`: Callback for undo event. - - `onRedo`: Callback for redo event. - - Functions: - - `render()`: Renders the workspace component with its visual appearance and bricks. - - `handleBrickAdd()`: Handles the brick add event for the workspace. - - `handleBrickRemove()`: Handles the brick remove event for the workspace. - - `handleBrickConnect()`: Handles the brick connect event for the workspace. - - `handleBrickDisconnect()`: Handles the brick disconnect event for the workspace. - - `handleBrickMove()`: Handles the brick move event for the workspace. - - `handleBrickResize()`: Handles the brick resize event for the workspace. - - `handleBrickRotate()`: Handles the brick rotate event for the workspace. - - `handleUndo()`: Handles the undo event for the workspace. - - `handleRedo()`: Handles the redo event for the workspace. + - Properties: + - `workspace`: The workspace model instance. + - `onBrickAdd`: Callback for brick add event. + - `onBrickRemove`: Callback for brick remove event. + - `onBrickConnect`: Callback for brick connect event. + - `onBrickDisconnect`: Callback for brick disconnect event. + - `onBrickMove`: Callback for brick move event. + - `onBrickResize`: Callback for brick resize event. + - `onBrickRotate`: Callback for brick rotate event. + - `onUndo`: Callback for undo event. + - `onRedo`: Callback for redo event. + - Functions: + - `render()`: Renders the workspace component with its visual appearance and bricks. + - `handleBrickAdd()`: Handles the brick add event for the workspace. + - `handleBrickRemove()`: Handles the brick remove event for the workspace. + - `handleBrickConnect()`: Handles the brick connect event for the workspace. + - `handleBrickDisconnect()`: Handles the brick disconnect event for the workspace. + - `handleBrickMove()`: Handles the brick move event for the workspace. + - `handleBrickResize()`: Handles the brick resize event for the workspace. + - `handleBrickRotate()`: Handles the brick rotate event for the workspace. + - `handleUndo()`: Handles the undo event for the workspace. + - `handleRedo()`: Handles the redo event for the workspace. - **WorkspaceGrid.tsx:** - - Properties: - - `gridSize`: The size of the grid. - - `onGridClick`: Callback for grid click event. - - Functions: - - `render()`: Renders the grid component with its visual appearance and grid lines. - - `handleGridClick()`: Handles the grid click event for the grid component. + - Properties: + - `gridSize`: The size of the grid. + - `onGridClick`: Callback for grid click event. + - Functions: + - `render()`: Renders the grid component with its visual appearance and grid lines. + - `handleGridClick()`: Handles the grid click event for the grid component. - **WorkspaceToolbar.tsx:** - - Properties: - - `onUndo`: Callback for undo event. - - `onRedo`: Callback for redo event. - - Functions: - - `render()`: Renders the toolbar component with its visual appearance and buttons. - - `handleUndo()`: Handles the undo event for the toolbar. - - `handleRedo()`: Handles the redo event for the toolbar. + - Properties: + - `onUndo`: Callback for undo event. + - `onRedo`: Callback for redo event. + - Functions: + - `render()`: Renders the toolbar component with its visual appearance and buttons. + - `handleUndo()`: Handles the undo event for the toolbar. + - `handleRedo()`: Handles the redo event for the toolbar. -### Utilities: +### Utilities - **dragAndDropUtils.ts:** - - Functions: - - `handleDragStart()`: Handles the drag start event for draggable elements. - - `handleDragOver()`: Handles the drag-over event for draggable elements. - - `handleDrop()`: Handles the drop event for draggable elements. - - `handleDragEnd()`: Handles the drag end event for draggable elements. + - Functions: + - `handleDragStart()`: Handles the drag start event for draggable elements. + - `handleDragOver()`: Handles the drag-over event for draggable elements. + - `handleDrop()`: Handles the drop event for draggable elements. + - `handleDragEnd()`: Handles the drag end event for draggable elements. - **validationUtils.ts:** - - Functions: - - `validateBrickConnection()`: Validates the connection between two bricks. - - `validateBrickPosition()`: Validates the position of a brick in the workspace. - - `validateBrickData()`: Validates the data within a brick. + - Functions: + - `validateBrickConnection()`: Validates the connection between two bricks. + - `validateBrickPosition()`: Validates the position of a brick in the workspace. + - `validateBrickData()`: Validates the data within a brick. - **dataUtils.ts:** - - Functions: - - `saveWorkspace()`: Saves the workspace state to local storage or server. - - `loadWorkspace()`: Loads the workspace state from local storage or server. - - `exportWorkspace()`: Exports the workspace state to a file. - - `importWorkspace()`: Imports the workspace state from a file. + - Functions: + - `saveWorkspace()`: Saves the workspace state to local storage or server. + - `loadWorkspace()`: Loads the workspace state from local storage or server. + - `exportWorkspace()`: Exports the workspace state to a file. + - `importWorkspace()`: Imports the workspace state from a file. - **quadtreeUtils.ts:** - - Functions: - - `insertBrick()`: Inserts a brick into the quadtree for spatial indexing. - - `removeBrick()`: Removes a brick from the quadtree. - - `updateBrick()`: Updates the position of a brick in the quadtree. - - `findNearbyBricks()`: Finds nearby bricks within a certain radius using the quadtree. + - Functions: + - `insertBrick()`: Inserts a brick into the quadtree for spatial indexing. + - `removeBrick()`: Removes a brick from the quadtree. + - `updateBrick()`: Updates the position of a brick in the quadtree. + - `findNearbyBricks()`: Finds nearby bricks within a certain radius using the quadtree. -### Hooks: +### Hooks **a) useBrick:** @@ -252,14 +252,14 @@ This tech spec outlines the implementation details for the Masonry Framework, a - Provides an instance of the `Brick` model. - Handles updating the brick's properties and arguments. - Properties: - - `brick`: The brick model instance. - - `setBrick()`: A function to update the brick instance. + - `brick`: The brick model instance. + - `setBrick()`: A function to update the brick instance. - Functions: - - `useEffect()`: A React hook for handling side effects. - - `fetchBrick()`: A function to fetch the brick data from the server. - - `useCallback()`: A React hook for memoizing functions. - - `handleInputChange()`: A function to handle input changes for the brick. - - `handleOutputChange()`: A function to handle output changes for the brick. + - `useEffect()`: A React hook for handling side effects. + - `fetchBrick()`: A function to fetch the brick data from the server. + - `useCallback()`: A React hook for memoizing functions. + - `handleInputChange()`: A function to handle input changes for the brick. + - `handleOutputChange()`: A function to handle output changes for the brick. **b) useStack:** @@ -267,16 +267,16 @@ This tech spec outlines the implementation details for the Masonry Framework, a - Provides an instance of the `Stack` model. - Handles updating the stack's bricks and connections. - Properties: - - `stack`: The stack model instance. - - `setStack()`: A function to update the stack instance. + - `stack`: The stack model instance. + - `setStack()`: A function to update the stack instance. - Functions: - - `useEffect()`: A React hook for handling side effects. - - `fetchStack()`: A function to fetch the stack data from the server. - - `useCallback()`: A React hook for memoizing functions. - - `handleBrickAdd()`: A function to handle adding a brick to the stack. - - `handleBrickRemove()`: A function to handle removing a brick from the stack. - - `handleBrickConnect()`: A function to handle connecting bricks in the stack. - - `handleBrickDisconnect()`: A function to handle disconnecting bricks in the stack. + - `useEffect()`: A React hook for handling side effects. + - `fetchStack()`: A function to fetch the stack data from the server. + - `useCallback()`: A React hook for memoizing functions. + - `handleBrickAdd()`: A function to handle adding a brick to the stack. + - `handleBrickRemove()`: A function to handle removing a brick from the stack. + - `handleBrickConnect()`: A function to handle connecting bricks in the stack. + - `handleBrickDisconnect()`: A function to handle disconnecting bricks in the stack. **c) useWorkspace:** @@ -284,101 +284,101 @@ This tech spec outlines the implementation details for the Masonry Framework, a - Provides an instance of the `Workspace` model. - Handles updating the workspace's bricks, connections, and layout. - Properties: - - `workspace`: The workspace model instance. - - `setWorkspace()`: A function to update the workspace instance. + - `workspace`: The workspace model instance. + - `setWorkspace()`: A function to update the workspace instance. - Functions: - - `useEffect()`: A React hook for handling side effects. - - `fetchWorkspace()`: A function to fetch the workspace data from the server. - - `useCallback()`: A React hook for memoizing functions. - - `handleBrickAdd()`: A function to handle adding a brick to the workspace. - - `handleBrickRemove()`: A function to handle removing a brick from the workspace. - - `handleBrickConnect()`: A function to handle connecting bricks in the workspace. - - `handleBrickDisconnect()`: A function to handle disconnecting bricks in the workspace. - - `handleBrickMove()`: A function to handle moving a brick in the workspace. - - `handleBrickResize()`: A function to handle resizing a brick in the workspace. - - `handleBrickRotate()`: A function to handle rotating a brick in the workspace. + - `useEffect()`: A React hook for handling side effects. + - `fetchWorkspace()`: A function to fetch the workspace data from the server. + - `useCallback()`: A React hook for memoizing functions. + - `handleBrickAdd()`: A function to handle adding a brick to the workspace. + - `handleBrickRemove()`: A function to handle removing a brick from the workspace. + - `handleBrickConnect()`: A function to handle connecting bricks in the workspace. + - `handleBrickDisconnect()`: A function to handle disconnecting bricks in the workspace. + - `handleBrickMove()`: A function to handle moving a brick in the workspace. + - `handleBrickResize()`: A function to handle resizing a brick in the workspace. + - `handleBrickRotate()`: A function to handle rotating a brick in the workspace. -### Models: +### Models Certainly! Below, I'll expand on the properties and functionalities of the `Brick` model to include bounding boxes (b-boxes) and related methods: -### Models: +### Models - **Brick.ts:** - - Properties: - - `id`: Unique identifier for the brick. - - `type`: Type of the brick (data, expression, statement, block). - - `position`: Position of the brick in the workspace. - - `inputs`: Array of input ports for the brick. - - `outputs`: Array of output ports for the brick. - - `data`: Data associated with the brick. - - `boundingBox`: Bounding box coordinates of the brick for collision detection and spatial indexing. - - Functions: - - `connect()`: Connects the brick to another brick. - - `disconnect()`: Disconnects the brick from another brick. - - `move()`: Moves the brick to a new position. - - `resize()`: Resizes the brick. - - `rotate()`: Rotates the brick. - - `calculateBoundingBox()`: Calculates the bounding box of the brick based on its size and position. - - `checkCollision()`: Checks for collision with other bricks or boundaries. - - `handleCollision()`: Handles collision events by adjusting the position or behavior of the brick. - - `updatePosition()`: Updates the position of the brick based on collision resolution or user interaction. + - Properties: + - `id`: Unique identifier for the brick. + - `type`: Type of the brick (data, expression, statement, block). + - `position`: Position of the brick in the workspace. + - `inputs`: Array of input ports for the brick. + - `outputs`: Array of output ports for the brick. + - `data`: Data associated with the brick. + - `boundingBox`: Bounding box coordinates of the brick for collision detection and spatial indexing. + - Functions: + - `connect()`: Connects the brick to another brick. + - `disconnect()`: Disconnects the brick from another brick. + - `move()`: Moves the brick to a new position. + - `resize()`: Resizes the brick. + - `rotate()`: Rotates the brick. + - `calculateBoundingBox()`: Calculates the bounding box of the brick based on its size and position. + - `checkCollision()`: Checks for collision with other bricks or boundaries. + - `handleCollision()`: Handles collision events by adjusting the position or behavior of the brick. + - `updatePosition()`: Updates the position of the brick based on collision resolution or user interaction. - **Stack.ts:** - - Properties: - - `id`: Unique identifier for the stack. - - `bricks`: Array of bricks in the stack. - - Functions: - - `addBrick()`: Adds a brick to the stack. - - `removeBrick()`: Removes a brick from the stack. - - `connectBricks()`: Connects two bricks in the stack. - - `disconnectBricks()`: Disconnects two bricks in the stack. + - Properties: + - `id`: Unique identifier for the stack. + - `bricks`: Array of bricks in the stack. + - Functions: + - `addBrick()`: Adds a brick to the stack. + - `removeBrick()`: Removes a brick from the stack. + - `connectBricks()`: Connects two bricks in the stack. + - `disconnectBricks()`: Disconnects two bricks in the stack. - **Workspace.ts:** - - Properties: - - `id`: Unique identifier for the workspace. - - `stacks`: Array of stacks in the workspace. - - `gridSize`: Size of the grid in the workspace. - - `zoomLevel`: Zoom level of the workspace. - - Functions: - - `addStack()`: Adds a stack to the workspace. - - `removeStack()`: Removes a stack from the workspace. - - `findBrickById()`: Finds a brick in the workspace by its ID. - - `validateWorkspace()`: Validates the workspace state. - - `exportWorkspace()`: Exports the workspace state to a file. - - `importWorkspace()`: Imports the workspace state from a file. + - Properties: + - `id`: Unique identifier for the workspace. + - `stacks`: Array of stacks in the workspace. + - `gridSize`: Size of the grid in the workspace. + - `zoomLevel`: Zoom level of the workspace. + - Functions: + - `addStack()`: Adds a stack to the workspace. + - `removeStack()`: Removes a stack from the workspace. + - `findBrickById()`: Finds a brick in the workspace by its ID. + - `validateWorkspace()`: Validates the workspace state. + - `exportWorkspace()`: Exports the workspace state to a file. + - `importWorkspace()`: Imports the workspace state from a file. -### Services: +### Services - **BrickService.ts:** - - Functions: - - `createBrick()`: Creates a new brick instance. - - `deleteBrick()`: Deletes a brick instance. - - `updateBrick()`: Updates a brick instance. - - `findBrickById()`: Finds a brick instance by its ID. + - Functions: + - `createBrick()`: Creates a new brick instance. + - `deleteBrick()`: Deletes a brick instance. + - `updateBrick()`: Updates a brick instance. + - `findBrickById()`: Finds a brick instance by its ID. - **StackService.ts:** - - Functions: - - `createStack()`: Creates a new stack instance. - - `deleteStack()`: Deletes a stack instance. - - `updateStack()`: Updates a stack instance. - - `findStackById()`: Finds a stack instance by its ID. + - Functions: + - `createStack()`: Creates a new stack instance. + - `deleteStack()`: Deletes a stack instance. + - `updateStack()`: Updates a stack instance. + - `findStackById()`: Finds a stack instance by its ID. - **WorkspaceService.ts:** - - Functions: - - `createWorkspace()`: Creates a new workspace instance. - - `deleteWorkspace()`: Deletes a workspace instance. - - `updateWorkspace()`: Updates a workspace instance. - - `findWorkspaceById()`: Finds a workspace instance by its ID. + - Functions: + - `createWorkspace()`: Creates a new workspace instance. + - `deleteWorkspace()`: Deletes a workspace instance. + - `updateWorkspace()`: Updates a workspace instance. + - `findWorkspaceById()`: Finds a workspace instance by its ID. - **QuadtreeService.ts:** - - Functions: - - `insertBrick()`: Inserts a brick into the quadtree for spatial indexing. - - `removeBrick()`: Removes a brick from the quadtree. - - `updateBrick()`: Updates the position of a brick in the quadtree. - - `findNearbyBricks()`: Finds nearby bricks within a certain radius using the quadtree. + - Functions: + - `insertBrick()`: Inserts a brick into the quadtree for spatial indexing. + - `removeBrick()`: Removes a brick from the quadtree. + - `updateBrick()`: Updates the position of a brick in the quadtree. + - `findNearbyBricks()`: Finds nearby bricks within a certain radius using the quadtree. - **ErrorHandlingService.ts:** - - Functions: - - `handleError()`: Handles errors and exceptions in the application. - - `logError()`: Logs errors to a server or local storage. + - Functions: + - `handleError()`: Handles errors and exceptions in the application. + - `logError()`: Logs errors to a server or local storage. -## Testing: +## Testing - Write unit tests for components, utilities, and hooks using Jest and React Testing Library. - Write integration tests for drag-and-drop functionality and state management. diff --git a/modules/masonry/docs/tech-spec/Techspec.md b/modules/masonry/docs/tech-spec/Techspec.md index 491027ac..2bc99422 100644 --- a/modules/masonry/docs/tech-spec/Techspec.md +++ b/modules/masonry/docs/tech-spec/Techspec.md @@ -1,8 +1,9 @@ -# Masonry Framework +# Masonry Framework ## Palette #### Config (Inputs) + - **Categories**: - **Attributes**: names, icons - **Sections**: @@ -11,12 +12,14 @@ - **Attributes**: id, name, description, thumbnail, BBox #### Search + - **Search text**: - Substring match on name - Substring match on description - Minimum 3 characters -#### Drag & Drop +#### Drag & Drop + - **For a brick**: 1. Start drag operation 2. Transfer brick's logo to workspace @@ -30,9 +33,10 @@ - Stops drag within the palette - Stops drag outside the palette -## Brick +## Brick #### Brick Types + - **Data Bricks** - Returns values - Connects only as arguments @@ -51,6 +55,7 @@ - Can take 0 or more arguments #### Brick Appearance + - **Attributes**: - Color - Shape @@ -59,11 +64,13 @@ - Any connectors #### Brick Interactions + - **Inline Edit**: - Only applicable to Data bricks - Example: input text #### Brick Structure Overview + - **Brick**: - Color - Argument connectors @@ -79,10 +86,10 @@ - **Block**: - Can nest other bricks - ## Stack ### Stack Validation + - **Visual Feedback**: - Indicators show whether brick combinations are valid. - Example: A green outline appears for a valid connection, while a red outline indicates an invalid connection. @@ -91,12 +98,14 @@ - Example: A reddish boundary and error message explain why the connection is invalid. ### Stack Editing + - **Connection Editing**: - Options for repositioning, disconnecting, or connecting bricks. - Visual indicators show possible connections. - Example: Highlight potential connection points when a brick is moved. ### Stack Grouping + - **Collapsible Groups**: - Groups can be collapsed or expanded to manage complexity. - Example: Users can organize bricks into groups that can be collapsed to reduce visual clutter. @@ -105,6 +114,7 @@ ## Workspace ### Layout and Interaction + - **Cloning**: - Users can easily create copies of bricks for repeated use. - Example: Right-click on a brick and select "Duplicate". @@ -121,6 +131,7 @@ ### Data Flow and Interaction #### Adding Bricks + - **From Palette to Workspace**: 1. User drags a brick from the palette. 2. Workspace detects the drag operation and shows a drop area. @@ -128,6 +139,7 @@ 4. Workspace creates a new brick instance at the drop location. #### Connecting Bricks + - **Within Workspace**: 1. User selects a connection point on a brick. 2. User drags to another brick's connection point. @@ -136,15 +148,16 @@ 5. If invalid, an error message is shown. #### Editing Connections + - **Repositioning and Disconnecting**: 1. User clicks on a connection line. 2. User can drag the connection to a new point or disconnect it. 3. Workspace updates the connections and provides visual feedback. #### Grouping Bricks + - **Creating and Managing Groups**: 1. User selects multiple bricks. 2. User groups them into a collapsible unit. 3. Workspace treats the group as a single entity for movement and scaling. 4. User can collapse or expand the group to manage workspace complexity. - diff --git a/modules/masonry/src/index.ts b/modules/masonry/src/index.ts new file mode 100644 index 00000000..e69de29b From d8ec0edb6b04df99d49317d42c63d22407063dfd Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 8 Jul 2024 17:28:48 +0530 Subject: [PATCH 07/58] feat(masonry/playground): add stack made wit divs, SVGs and SVGs with foreign objects --- modules/masonry/playground/index.html | 2 +- modules/masonry/playground/public/vite.svg | 1 - modules/masonry/playground/src/App.tsx | 141 ++-------------- .../masonry/playground/src/assets/react.svg | 1 - .../playground/src/components/DivStack.tsx | 135 ++++++++++++++++ .../playground/src/components/NormalSVG.tsx | 139 ++++++++++++++++ .../src/components/SVGWithValues.tsx | 150 ++++++++++++++++++ modules/masonry/playground/src/index.css | 0 modules/masonry/playground/src/main.tsx | 9 +- modules/masonry/playground/src/test/Test.tsx | 137 ---------------- modules/masonry/playground/vite.config.ts | 7 +- 11 files changed, 446 insertions(+), 276 deletions(-) delete mode 100644 modules/masonry/playground/public/vite.svg delete mode 100644 modules/masonry/playground/src/assets/react.svg create mode 100644 modules/masonry/playground/src/components/DivStack.tsx create mode 100644 modules/masonry/playground/src/components/NormalSVG.tsx create mode 100644 modules/masonry/playground/src/components/SVGWithValues.tsx delete mode 100644 modules/masonry/playground/src/index.css delete mode 100644 modules/masonry/playground/src/test/Test.tsx diff --git a/modules/masonry/playground/index.html b/modules/masonry/playground/index.html index 47565672..23c0a4d0 100644 --- a/modules/masonry/playground/index.html +++ b/modules/masonry/playground/index.html @@ -2,7 +2,7 @@ - + Masonry-Test diff --git a/modules/masonry/playground/public/vite.svg b/modules/masonry/playground/public/vite.svg deleted file mode 100644 index e7b8dfb1..00000000 --- a/modules/masonry/playground/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/modules/masonry/playground/src/App.tsx b/modules/masonry/playground/src/App.tsx index ee6258eb..bc4dab65 100644 --- a/modules/masonry/playground/src/App.tsx +++ b/modules/masonry/playground/src/App.tsx @@ -1,134 +1,19 @@ -import React, { useState, useRef, useEffect } from 'react'; - -interface Brick { - id: number; - type: string; - x: number; - y: number; - color: string; -} +import React from 'react'; +import DivStack from './components/DivStack'; +import NormalSVG from './components/NormalSVG'; +import SVGWithValues from './components/SVGWithValues'; const App: React.FC = () => { - const [bricks, setBricks] = useState([ - { id: 1, type: 'top', x: 50, y: 50, color: '#ff6b6b' }, - { id: 2, type: 'middle', x: 50, y: 110, color: '#4ecdc4' }, - { id: 3, type: 'middle', x: 50, y: 170, color: '#45b7d1' }, - { id: 4, type: 'middle', x: 50, y: 230, color: '#f9d56e' }, - { id: 5, type: 'middle', x: 50, y: 290, color: '#ff9ff3' }, - { id: 6, type: 'bottom', x: 50, y: 350, color: '#54a0ff' }, - ]); - const [isDragging, setIsDragging] = useState(false); - const [draggedBrickId, setDraggedBrickId] = useState(null); - const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); - const svgRef = useRef(null); - - const isConnected = (brick1: Brick, brick2: Brick) => - Math.abs(brick1.y + 60 - brick2.y) < 5 && Math.abs(brick1.x - brick2.x) < 5; - - const findConnectedBricks = (startId: number): number[] => { - const result: number[] = [startId]; - let currentId = startId; - - // Find bricks below - while (true) { - const currentBrick = bricks.find(b => b.id === currentId); - const nextBrick = bricks.find(b => b.id !== currentId && isConnected(currentBrick!, b)); - if (nextBrick && nextBrick.y > currentBrick!.y) { - result.push(nextBrick.id); - currentId = nextBrick.id; - } else { - break; - } - } - - return result; - }; - - const handleMouseDown = (e: React.MouseEvent, id: number) => { - const brick = bricks.find(b => b.id === id); - if (brick) { - const svgRect = svgRef.current?.getBoundingClientRect(); - if (svgRect) { - setIsDragging(true); - setDraggedBrickId(id); - setDragOffset({ - x: e.clientX - svgRect.left - brick.x, - y: e.clientY - svgRect.top - brick.y - }); - } - } - }; - - const handleMouseMove = (e: MouseEvent) => { - if (isDragging && draggedBrickId !== null) { - const svgRect = svgRef.current?.getBoundingClientRect(); - if (svgRect) { - const newX = e.clientX - svgRect.left - dragOffset.x; - const newY = e.clientY - svgRect.top - dragOffset.y; - - const connectedBricks = findConnectedBricks(draggedBrickId); - - setBricks(prevBricks => { - return prevBricks.map(brick => { - if (connectedBricks.includes(brick.id)) { - const index = connectedBricks.indexOf(brick.id); - return { - ...brick, - x: newX, - y: newY + index * 60 - }; - } - return brick; - }); - }); - } - } - }; - - const handleMouseUp = () => { - setIsDragging(false); - setDraggedBrickId(null); - }; - - useEffect(() => { - window.addEventListener('mousemove', handleMouseMove); - window.addEventListener('mouseup', handleMouseUp); - return () => { - window.removeEventListener('mousemove', handleMouseMove); - window.removeEventListener('mouseup', handleMouseUp); - }; - }, [isDragging, draggedBrickId]); - - const renderBrickPath = (type: string) => { - switch (type) { - case 'top': - return "M0,0 h100 v50 h-80 l-20,10 v-60 z"; - case 'middle': - return "M0,0 h80 l20,-10 v60 h-80 l-20,10 v-60 z"; - case 'bottom': - return "M0,0 h80 l20,-10 v60 h-100 v-50 z"; - default: - return ""; - } - }; - return ( - - {bricks.map(brick => ( - handleMouseDown(e, brick.id)} - > - - - ))} - +
+

Div Stack

+ +

Normal SVG

+ +

SVG With Values

+ +
); }; -export default App; \ No newline at end of file +export default App; diff --git a/modules/masonry/playground/src/assets/react.svg b/modules/masonry/playground/src/assets/react.svg deleted file mode 100644 index 6c87de9b..00000000 --- a/modules/masonry/playground/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/modules/masonry/playground/src/components/DivStack.tsx b/modules/masonry/playground/src/components/DivStack.tsx new file mode 100644 index 00000000..d0ca0895 --- /dev/null +++ b/modules/masonry/playground/src/components/DivStack.tsx @@ -0,0 +1,135 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +/* eslint-disable no-constant-condition */ +import React, { useState, useEffect } from 'react'; + +interface Brick { + id: number; + type: string; + x: number; + y: number; + color: string; +} + +const DivStack: React.FC = () => { + const [bricks, setBricks] = useState([ + { id: 1, type: 'top', x: 50, y: 50, color: '#ff6b6b' }, + { id: 2, type: 'middle', x: 50, y: 110, color: '#4ecdc4' }, + { id: 3, type: 'middle', x: 50, y: 170, color: '#45b7d1' }, + { id: 4, type: 'middle', x: 50, y: 230, color: '#f9d56e' }, + { id: 5, type: 'middle', x: 50, y: 290, color: '#ff9ff3' }, + { id: 6, type: 'bottom', x: 50, y: 350, color: '#54a0ff' }, + ]); + + const [isDragging, setIsDragging] = useState(false); + const [draggedBrickId, setDraggedBrickId] = useState(null); + const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); + + const isConnected = (brick1: Brick, brick2: Brick) => + Math.abs(brick1.y + 60 - brick2.y) < 5 && Math.abs(brick1.x - brick2.x) < 5; + + const findConnectedBricks = (startId: number): number[] => { + const result: number[] = [startId]; + let currentId = startId; + + while (true) { + const currentBrick = bricks.find((b) => b.id === currentId); + const nextBrick = bricks.find((b) => b.id !== currentId && isConnected(currentBrick!, b)); + if (nextBrick && nextBrick.y > currentBrick!.y) { + result.push(nextBrick.id); + currentId = nextBrick.id; + } else { + break; + } + } + return result; + }; + + const handleMouseDown = (e: React.MouseEvent, id: number) => { + const brick = bricks.find((b) => b.id === id); + if (brick) { + setIsDragging(true); + setDraggedBrickId(id); + setDragOffset({ + x: e.clientX - brick.x, + y: e.clientY - brick.y, + }); + } + }; + + const handleMouseMove = (e: MouseEvent) => { + if (isDragging && draggedBrickId !== null) { + const newX = e.clientX - dragOffset.x; + const newY = e.clientY - dragOffset.y; + const connectedBricks = findConnectedBricks(draggedBrickId); + setBricks((prevBricks) => { + return prevBricks.map((brick) => { + if (connectedBricks.includes(brick.id)) { + const index = connectedBricks.indexOf(brick.id); + return { + ...brick, + x: newX, + y: newY + index * 60, + }; + } + return brick; + }); + }); + } + }; + + const handleMouseUp = () => { + setIsDragging(false); + setDraggedBrickId(null); + }; + + useEffect(() => { + window.addEventListener('mousemove', handleMouseMove); + window.addEventListener('mouseup', handleMouseUp); + return () => { + window.removeEventListener('mousemove', handleMouseMove); + window.removeEventListener('mouseup', handleMouseUp); + }; + }, [isDragging, draggedBrickId]); + + return ( +
+
+ {bricks.map((brick) => ( +
handleMouseDown(e, brick.id)} + > + {brick.type === 'top' && } + {brick.type === 'middle' && } + {brick.type === 'bottom' && } +
+ ))} +
+
+ ); +}; + +export default DivStack; diff --git a/modules/masonry/playground/src/components/NormalSVG.tsx b/modules/masonry/playground/src/components/NormalSVG.tsx new file mode 100644 index 00000000..1b01eb58 --- /dev/null +++ b/modules/masonry/playground/src/components/NormalSVG.tsx @@ -0,0 +1,139 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +/* eslint-disable no-constant-condition */ +/* eslint-disable prettier/prettier */ +import React, { useState, useRef, useEffect } from 'react'; + +interface Brick { + id: number; + type: string; + x: number; + y: number; + color: string; +} + +const NormalSVG: React.FC = () => { + const [bricks, setBricks] = useState([ + { id: 1, type: 'top', x: 50, y: 50, color: '#ff6b6b' }, + { id: 2, type: 'middle', x: 50, y: 110, color: '#4ecdc4' }, + { id: 3, type: 'middle', x: 50, y: 170, color: '#45b7d1' }, + { id: 4, type: 'middle', x: 50, y: 230, color: '#f9d56e' }, + { id: 5, type: 'middle', x: 50, y: 290, color: '#ff9ff3' }, + { id: 6, type: 'bottom', x: 50, y: 350, color: '#54a0ff' }, + ]); + const [isDragging, setIsDragging] = useState(false); + const [draggedBrickId, setDraggedBrickId] = useState(null); + const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); + const svgRef = useRef(null); + + const isConnected = (brick1: Brick, brick2: Brick) => + Math.abs(brick1.y + 60 - brick2.y) < 5 && Math.abs(brick1.x - brick2.x) < 5; + + const findConnectedBricks = (startId: number): number[] => { + const result: number[] = [startId]; + let currentId = startId; + + while (true) { + const currentBrick = bricks.find((b) => b.id === currentId); + const nextBrick = bricks.find( + (b) => b.id !== currentId && isConnected(currentBrick!, b), + ); + if (nextBrick && nextBrick.y > currentBrick!.y) { + result.push(nextBrick.id); + currentId = nextBrick.id; + } else { + break; + } + } + + return result; + }; + + const handleMouseDown = (e: React.MouseEvent, id: number) => { + const brick = bricks.find((b) => b.id === id); + if (brick) { + const svgRect = svgRef.current?.getBoundingClientRect(); + if (svgRect) { + setIsDragging(true); + setDraggedBrickId(id); + setDragOffset({ + x: e.clientX - svgRect.left - brick.x, + y: e.clientY - svgRect.top - brick.y, + }); + } + } + }; + + const handleMouseMove = (e: MouseEvent) => { + if (isDragging && draggedBrickId !== null) { + const svgRect = svgRef.current?.getBoundingClientRect(); + if (svgRect) { + const newX = e.clientX - svgRect.left - dragOffset.x; + const newY = e.clientY - svgRect.top - dragOffset.y; + + const connectedBricks = findConnectedBricks(draggedBrickId); + + setBricks((prevBricks) => { + return prevBricks.map((brick) => { + if (connectedBricks.includes(brick.id)) { + const index = connectedBricks.indexOf(brick.id); + return { + ...brick, + x: newX, + y: newY + index * 60, + }; + } + return brick; + }); + }); + } + } + }; + + const handleMouseUp = () => { + setIsDragging(false); + setDraggedBrickId(null); + }; + + useEffect(() => { + window.addEventListener('mousemove', handleMouseMove); + window.addEventListener('mouseup', handleMouseUp); + return () => { + window.removeEventListener('mousemove', handleMouseMove); + window.removeEventListener('mouseup', handleMouseUp); + }; + }, [isDragging, draggedBrickId]); + + const renderBrickPath = (type: string) => { + switch (type) { + case 'top': + return 'M0,0 h100 v50 h-80 l-20,10 v-60 z'; + case 'middle': + return 'M0,0 h80 l20,-10 v60 h-80 l-20,10 v-60 z'; + case 'bottom': + return 'M0,0 h80 l20,-10 v60 h-100 v-50 z'; + default: + return ''; + } + }; + + return ( + + {bricks.map((brick) => ( + handleMouseDown(e, brick.id)} + > + + + ))} + + ); +}; + +export default NormalSVG; diff --git a/modules/masonry/playground/src/components/SVGWithValues.tsx b/modules/masonry/playground/src/components/SVGWithValues.tsx new file mode 100644 index 00000000..5b2c0baf --- /dev/null +++ b/modules/masonry/playground/src/components/SVGWithValues.tsx @@ -0,0 +1,150 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +/* eslint-disable no-constant-condition */ +/* eslint-disable prettier/prettier */ +import React, { useState, useRef, useEffect } from 'react'; + +interface Brick { + id: number; + type: string; + x: number; + y: number; + color: string; +} + +const SVGWithValues: React.FC = () => { + const [bricks, setBricks] = useState([ + { id: 1, type: 'top', x: 50, y: 50, color: '#ff6b6b' }, + { id: 2, type: 'middle', x: 50, y: 110, color: '#4ecdc4' }, + { id: 3, type: 'middle', x: 50, y: 170, color: '#45b7d1' }, + { id: 4, type: 'middle', x: 50, y: 230, color: '#f9d56e' }, + { id: 5, type: 'middle', x: 50, y: 290, color: '#ff9ff3' }, + { id: 6, type: 'bottom', x: 50, y: 350, color: '#54a0ff' }, + ]); + + const [isDragging, setIsDragging] = useState(false); + const [draggedBrickId, setDraggedBrickId] = useState(null); + const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); + const svgRef = useRef(null); + + const isConnected = (brick1: Brick, brick2: Brick) => + Math.abs(brick1.y + 60 - brick2.y) < 5 && Math.abs(brick1.x - brick2.x) < 5; + + const findConnectedBricks = (startId: number): number[] => { + const result: number[] = [startId]; + let currentId = startId; + + // Find bricks below + while (true) { + const currentBrick = bricks.find((b) => b.id === currentId); + const nextBrick = bricks.find( + (b) => b.id !== currentId && isConnected(currentBrick!, b), + ); + if (nextBrick && nextBrick.y > currentBrick!.y) { + result.push(nextBrick.id); + currentId = nextBrick.id; + } else { + break; + } + } + return result; + }; + + const handleMouseDown = (e: React.MouseEvent, id: number) => { + const brick = bricks.find((b) => b.id === id); + if (brick) { + const svgRect = svgRef.current?.getBoundingClientRect(); + if (svgRect) { + setIsDragging(true); + setDraggedBrickId(id); + setDragOffset({ + x: e.clientX - svgRect.left - brick.x, + y: e.clientY - svgRect.top - brick.y, + }); + } + } + }; + + const handleMouseMove = (e: MouseEvent) => { + if (isDragging && draggedBrickId !== null) { + const svgRect = svgRef.current?.getBoundingClientRect(); + if (svgRect) { + const newX = e.clientX - svgRect.left - dragOffset.x; + const newY = e.clientY - svgRect.top - dragOffset.y; + const connectedBricks = findConnectedBricks(draggedBrickId); + setBricks((prevBricks) => { + return prevBricks.map((brick) => { + if (connectedBricks.includes(brick.id)) { + const index = connectedBricks.indexOf(brick.id); + return { + ...brick, + x: newX, + y: newY + index * 60, + }; + } + return brick; + }); + }); + } + } + }; + + const handleMouseUp = () => { + setIsDragging(false); + setDraggedBrickId(null); + }; + + useEffect(() => { + window.addEventListener('mousemove', handleMouseMove); + window.addEventListener('mouseup', handleMouseUp); + return () => { + window.removeEventListener('mousemove', handleMouseMove); + window.removeEventListener('mouseup', handleMouseUp); + }; + }, [isDragging, draggedBrickId]); + + const renderBrickPath = (type: string) => { + switch (type) { + case 'top': + return 'M0,0 h100 v50 h-80 l-20,10 v-60 z'; + case 'middle': + return 'M0,0 h80 l20,-10 v60 h-80 l-20,10 v-60 z'; + case 'bottom': + return 'M0,0 h80 l20,-10 v60 h-100 v-50 z'; + default: + return ''; + } + }; + + return ( +
+ + {bricks.map((brick) => ( + handleMouseDown(e, brick.id)} + > + + + {brick.type === 'top' && } + {brick.type === 'middle' && ( + + )} + {brick.type === 'bottom' && } + + + ))} + +
+ ); +}; + +export default SVGWithValues; diff --git a/modules/masonry/playground/src/index.css b/modules/masonry/playground/src/index.css deleted file mode 100644 index e69de29b..00000000 diff --git a/modules/masonry/playground/src/main.tsx b/modules/masonry/playground/src/main.tsx index 3d7150da..c018515c 100644 --- a/modules/masonry/playground/src/main.tsx +++ b/modules/masonry/playground/src/main.tsx @@ -1,10 +1,9 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App.tsx' -import './index.css' +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; ReactDOM.createRoot(document.getElementById('root')!).render( , -) +); diff --git a/modules/masonry/playground/src/test/Test.tsx b/modules/masonry/playground/src/test/Test.tsx deleted file mode 100644 index a59eaec0..00000000 --- a/modules/masonry/playground/src/test/Test.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import React, { useState, useRef, useEffect } from 'react'; - -interface Brick { - id: number; - type: string; - x: number; - y: number; - color: string; -} - -const Test: React.FC = () => { - const [bricks, setBricks] = useState([ - { id: 1, type: 'set', x: 50, y: 50, color: '#ff9ff3' }, - { id: 2, type: 'repeat', x: 50, y: 110, color: '#54a0ff' }, - { id: 3, type: 'do', x: 200, y: 200, color: '#5f27cd' }, - ]); - const [isDragging, setIsDragging] = useState(false); - const [draggedBrickId, setDraggedBrickId] = useState(null); - const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); - const svgRef = useRef(null); - - const CONNECT_THRESHOLD = 20; // Pixels within which bricks can connect - const NOT_CONNECTABLE_THRESHOLD = 40; // Pixels within which bricks show they can't connect - - const isConnectable = (brick1: Brick, brick2: Brick) => - Math.abs(brick1.y + 60 - brick2.y) < CONNECT_THRESHOLD && Math.abs(brick1.x - brick2.x) < CONNECT_THRESHOLD; - - const isCloseButNotConnectable = (brick1: Brick, brick2: Brick) => - Math.abs(brick1.y + 60 - brick2.y) < NOT_CONNECTABLE_THRESHOLD && Math.abs(brick1.x - brick2.x) < NOT_CONNECTABLE_THRESHOLD; - - const handleMouseDown = (e: React.MouseEvent, id: number) => { - const brick = bricks.find(b => b.id === id); - if (brick) { - const svgRect = svgRef.current?.getBoundingClientRect(); - if (svgRect) { - setIsDragging(true); - setDraggedBrickId(id); - setDragOffset({ - x: e.clientX - svgRect.left - brick.x, - y: e.clientY - svgRect.top - brick.y - }); - } - } - }; - - const handleMouseMove = (e: MouseEvent) => { - if (isDragging && draggedBrickId !== null) { - const svgRect = svgRef.current?.getBoundingClientRect(); - if (svgRect) { - const newX = e.clientX - svgRect.left - dragOffset.x; - const newY = e.clientY - svgRect.top - dragOffset.y; - - setBricks(prevBricks => { - return prevBricks.map(brick => { - if (brick.id === draggedBrickId) { - return { ...brick, x: newX, y: newY }; - } - return brick; - }); - }); - } - } - }; - - const handleMouseUp = () => { - if (isDragging && draggedBrickId !== null) { - setBricks(prevBricks => { - const draggedBrick = prevBricks.find(b => b.id === draggedBrickId)!; - const connectableBrick = prevBricks.find(b => b.id !== draggedBrickId && isConnectable(draggedBrick, b)); - - if (connectableBrick) { - return prevBricks.map(brick => - brick.id === draggedBrickId ? { ...brick, x: connectableBrick.x, y: connectableBrick.y + 60 } : brick - ); - } - return prevBricks; - }); - } - setIsDragging(false); - setDraggedBrickId(null); - }; - - useEffect(() => { - window.addEventListener('mousemove', handleMouseMove); - window.addEventListener('mouseup', handleMouseUp); - return () => { - window.removeEventListener('mousemove', handleMouseMove); - window.removeEventListener('mouseup', handleMouseUp); - }; - }, [isDragging, draggedBrickId]); - - const renderBrickPath = (type: string) => { - switch (type) { - case 'set': - return "M0,0 h120 v60 h-100 l-20,10 v-70 z"; - case 'repeat': - return "M0,0 h140 v60 h-120 l-20,10 v-70 z"; - case 'do': - return "M0,0 h80 v60 h-60 l-20,10 v-70 z"; - default: - return ""; - } - }; - - return ( - - - - - - - {bricks.map(brick => { - const isConnectableToAny = bricks.some(b => b.id !== brick.id && isConnectable(brick, b)); - const isCloseButNotConnectableToAny = bricks.some(b => b.id !== brick.id && isCloseButNotConnectable(brick, b) && !isConnectable(brick, b)); - - return ( - handleMouseDown(e, brick.id)} - > - - {brick.type} - - ); - })} - - ); -}; - -export default Test; \ No newline at end of file diff --git a/modules/masonry/playground/vite.config.ts b/modules/masonry/playground/vite.config.ts index 5a33944a..1d2d1a4b 100644 --- a/modules/masonry/playground/vite.config.ts +++ b/modules/masonry/playground/vite.config.ts @@ -1,7 +1,8 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +/* eslint-disable prettier/prettier */ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], -}) +}); From 12493e781e482936e1cd7b38c630d8fbb42cdc50 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 8 Jul 2024 18:00:33 +0530 Subject: [PATCH 08/58] feat(masonry): add brick/model, brick types and create tree for stack of bricks --- modules/masonry/jest.config.js | 4 + modules/masonry/package.json | 5 + modules/masonry/src/@types/brick.d.ts | 220 +++++++++++++++ modules/masonry/src/brick/README.md | 121 ++++++++ modules/masonry/src/brick/index.ts | 0 modules/masonry/src/brick/model.ts | 381 ++++++++++++++++++++++++++ modules/masonry/src/stack/README.md | 59 ++++ modules/masonry/src/stack/data.ts | 318 +++++++++++++++++++++ modules/masonry/src/stack/index.ts | 0 9 files changed, 1108 insertions(+) create mode 100644 modules/masonry/jest.config.js create mode 100644 modules/masonry/src/@types/brick.d.ts create mode 100644 modules/masonry/src/brick/README.md create mode 100644 modules/masonry/src/brick/index.ts create mode 100644 modules/masonry/src/brick/model.ts create mode 100644 modules/masonry/src/stack/README.md create mode 100644 modules/masonry/src/stack/data.ts create mode 100644 modules/masonry/src/stack/index.ts diff --git a/modules/masonry/jest.config.js b/modules/masonry/jest.config.js new file mode 100644 index 00000000..6d6062b3 --- /dev/null +++ b/modules/masonry/jest.config.js @@ -0,0 +1,4 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', +}; diff --git a/modules/masonry/package.json b/modules/masonry/package.json index 09bfbe5d..59ef5a8b 100644 --- a/modules/masonry/package.json +++ b/modules/masonry/package.json @@ -8,5 +8,10 @@ "test": "vitest", "coverage": "vitest run --coverage", "lint": "eslint src" + }, + "devDependencies": { + "@types/jest": "^29.5.12", + "jest": "^29.7.0", + "ts-jest": "^29.1.5" } } diff --git a/modules/masonry/src/@types/brick.d.ts b/modules/masonry/src/@types/brick.d.ts new file mode 100644 index 00000000..7a9e7e5b --- /dev/null +++ b/modules/masonry/src/@types/brick.d.ts @@ -0,0 +1,220 @@ +/** + * @type + * Kind (instruction or argument) of a brick. + */ +export type TBrickKind = 'instruction' | 'argument'; + +/** + * @type + * Type (data, expression, statement, block) of a brick. + */ +export type TBrickType = 'data' | 'expression' | 'statement' | 'block'; + +/** + * @type + * Data type (boolean, number, string, any) returned by an argument brick. + */ +export type TBrickArgDataType = 'boolean' | 'number' | 'string' | 'any'; + +/** + * @type + * Bounding box dimensions of a brick. + */ +export type TBrickExtent = { + width: number; + height: number; +}; + +/** + * @type + * Position co-ordinates of a brick. + */ +export type TBrickCoords = { + /** relative x co-ordinate */ + x: number; + /** relative y co-ordinate */ + y: number; +}; + +/** + * @type + * Defines color property of a brick. Supported types are RGC, HSL, and hexadecimal. + */ +export type TBrickColor = ['rgb' | 'hsl', number, number, number] | string; + +// ------------------------------------------------------------------------------------------------- + +/** + * @interface + * Style properties of a generic brick. + */ +export interface IBrickStyle { + /** background color */ + get colorBg(): TBrickColor; + /** foreground color */ + get colorFg(): TBrickColor; + /** outline/stroke color */ + get outline(): TBrickColor; + /** scale factor of the brick SVG */ + get scale(): number; +} + +/** + * @interface + * Arguments for a brick. + */ +export interface IBrickArgs { + /** map of argument ID to data associated with the argument */ + get args(): Record< + string, + { + /** argument label */ + label: string; + /** data type returned by the argument brick */ + dataType: TBrickArgDataType; + /** metadata — reserved for future-proofing */ + meta: unknown; + } + >; +} + +/** + * @interface + * State properties associated with bricks that can take arguments. + */ +export interface IBrickArgsState { + /** Map of argument ID to corresponding extent and coords */ + get bBoxArgs(): Record< + string, + { + /** Bounding box dimensions */ + extent: TBrickExtent; + /** Co-ordinates of the argument connections relative to the brick */ + coords: TBrickCoords; + } + >; +} + +/** + * @interface + * Type definition of a generic brick (any type). + */ +export interface IBrick extends IBrickStyle { + /** unique ID of the brick */ + get uuid(): string; + /** name of the brick — to be used for internal bookkeeping */ + get name(): string; + /** kind of the brick */ + get kind(): TBrickKind; + /** type of the brick */ + get type(): TBrickType; + /** label for the brick */ + get label(): string; + /** glyph icon associated with the brick */ + get glyph(): string; + + // states + /** whether brick is highlighted */ + highlighted: boolean; + /** Bounding box dimensions and coords of the brick */ + get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords }; + + /** SVG string for the brick based on defining properties and current state */ + get SVGpath(): string; +} + +/** + * @interface + * Type definition of a generic argument brick (data or expression type). + */ +export interface IBrickArgument extends IBrick { + /** data type returned by an argument brick */ + get dataType(): TBrickArgDataType; + + /** Bounding box dimensions and coords of the left notch */ + get bBoxNotchArg(): { + /** Bounding box dimensions of the left notch */ + extent: TBrickExtent; + /** Co-ordinates of the left notch relative to the brick */ + coords: TBrickCoords; + }; +} + +/** + * @interface + * Type definition of a generic instruction brick (statement or block type). + */ +export interface IBrickInstruction extends IBrick, IBrickArgs, IBrickArgsState { + // style + /** is connection allowed above the brick */ + get connectAbove(): boolean; + /** is connection allowed below the brick */ + get connectBelow(): boolean; + + /** Bounding box dimensions and coords of the top instruction notch */ + get bBoxNotchInsTop(): { + /** Bounding box dimensions of the top instruction notch */ + extent: TBrickExtent; + /** Co-ordinates of the top instruction notch relative to the brick */ + coords: TBrickCoords; + }; + + /** Bounding box dimensions and coords of the bottom instruction notch */ + get bBoxNotchInsBot(): { + /** Bounding box dimensions of the bottom instruction notch */ + extent: TBrickExtent; + /** Co-ordinates of the bottom instruction notch relative to the brick */ + coords: TBrickCoords; + }; +} + +/** + * @interface + * Type definition of a data brick. + */ +export interface IBrickData extends IBrickArgument { + /** whether brick has a static label or value can be updated */ + get dynamic(): boolean; + /** (if dynamic) current value of the brick */ + get value(): undefined | boolean | number | string; + /** (if dynamic) input mode for the brick (checkbox, number box, text box, dropdown, etc.) */ + get input(): undefined | 'boolean' | 'number' | 'string' | 'options'; +} + +/** + * @interface + * Type definition of an argument brick. + */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface IBrickExpression extends IBrickArgument, IBrickArgs, IBrickArgsState { + // reserving spot for future-proofing +} + +/** + * @interface + * Type definition of a statement brick. + */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface IBrickStatement extends IBrickInstruction { + // reserving spot for future-proofing +} + +/** + * @interface + * Type definition of a block brick. + */ +export interface IBrickBlock extends IBrickInstruction, IBrickNotchInsNestTopState { + // state + /** combined bounding box of the instructions nested within the brick */ + get nestExtent(): TBrickExtent; + /** whether brick nesting is hidden */ + collapsed: boolean; + + /** Bounding box dimensions and coords of the top instruction notch of the nesting */ + get bBoxNotchInsNestTop(): { + /** Bounding box dimensions of the top instruction notch of the nesting */ + extent: TBrickExtent; + /** Co-ordinates of the top instruction notch of the nesting relative to the brick */ + coords: TBrickCoords; + }; +} diff --git a/modules/masonry/src/brick/README.md b/modules/masonry/src/brick/README.md new file mode 100644 index 00000000..d5830cef --- /dev/null +++ b/modules/masonry/src/brick/README.md @@ -0,0 +1,121 @@ +# Data Model for Bricks + +## Data Bricks + +### Intrinsic + +- `uuid`: unique ID for the brick instance +- `name`: name for internal bookkeeping +- `kind`: argument or instruction +- `type`: data, expression, statement, block +- `label`: display name +- `glyph`: glyph icon +- `dataType`: the type (boolean, number, string, any) of value returned +- `dynamic`: whether label is fixed or is a modifiable value +- `value`: modifiable value +- `input`: modification input (checkbox, number, text box, list of options) + +### Style + +- `colorBg`: background fill color +- `colorFg`: text color +- `outline`: outline/stroke color +- `scale`: sizing scale factor + +### State + +- `highlighted`: whether brick is highlighted +- `extent`(G): bounding box dimensions + +## Expression Bricks + +### Intrinsic + +- `uuid`: unique ID for the brick instance +- `name`: name for internal bookkeeping +- `kind`: argument or instruction +- `type`: data, expression, statement, block +- `label`: display name +- `glyph`: glyph icon +- `dataType`: type (boolean, number, string, any) of value returned +- `args`: map of argument keys and labels, type, and metadata + +### Style + +- `colorBg`: background fill color +- `colorFg`: text color +- `outline`: outline/stroke color +- `scale`: sizing scale factor + +### State + +- `highlighted`: whether brick is highlighted +- `extent`(G): bounding box dimensions +- `argsExtent`: bounding box dimensions for each argument +- `argsCoords`(G): relative coordinates of each argument connection point + +## Statement Bricks + +### Intrinsic + +- `uuid`: unique ID for the brick instance +- `name`: name for internal bookkeeping +- `kind`: argument or instruction +- `type`: data, expression, statement, block +- `label`: display name +- `glyph`: glyph icon +- `args`: map of argument keys and labels, type, and metadata + +### Style + +- `colorBg`: background fill color +- `colorFg`: text color +- `outline`: outline/stroke color +- `scale`: sizing scale factor +- `connectAbove`: whether connection above brick is allowed +- `connectAbove`: whether connection below brick is allowed + +### State + +- `highlighted`: whether brick is highlighted +- `extent`(G): bounding box dimensions +- `argsExtent`: bounding box dimensions for each argument +- `argsCoords`(G): relative coordinates of each argument connection point + +## Block Bricks + +### Intrinsic + +- `uuid`: unique ID for the brick instance +- `name`: name for internal bookkeeping +- `kind`: argument or instruction +- `type`: data, expression, statement, block +- `label`: display name +- `glyph`: glyph icon +- `args`: map of argument keys and labels, type, and metadata + +### Style + +- `colorBg`: background fill color +- `colorFg`: text color +- `outline`: outline/stroke color +- `scale`: sizing scale factor +- `connectAbove`: whether connections above brick is allowed +- `connectAbove`: whether connections below brick is allowed + +### State + +- `highlighted`: whether brick is highlighted +- `extent`(G): bounding box dimensions +- `argsExtent`: bounding box dimensions for each argument +- `argsCoords`(G): relative coordinates of each argument connection point +- `nestExtent`: bounding box dimensions of child nesting +- `collapsed`: whether or not inner nesting is visible + +--- + +**Note:** Intrinsic and Style properties are set in the constructor and cannot be modified once +instantiated. They are accesible using getters. + +**Note:** States marked '(G)' represent getters — values for those will be generated within the +instance and cannot be set from outside. diff --git a/modules/masonry/src/brick/index.ts b/modules/masonry/src/brick/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/modules/masonry/src/brick/model.ts b/modules/masonry/src/brick/model.ts new file mode 100644 index 00000000..cfadd568 --- /dev/null +++ b/modules/masonry/src/brick/model.ts @@ -0,0 +1,381 @@ +import type { + IBrick, + IBrickArgument, + IBrickBlock, + IBrickData, + IBrickExpression, + IBrickInstruction, + IBrickStatement, + TBrickArgDataType, + TBrickColor, + TBrickCoords, + TBrickExtent, + TBrickKind, + TBrickType, +} from '@/@types/brick'; + +// -- protected classes ------------------------------------------------------------------------------ + +/** + * @abstract + * @class + * Defines the data model of a generic brick. + */ +abstract class BrickModel implements IBrick { + protected _uuid: string; + protected _name: string; + protected _kind: TBrickKind; + protected _type: TBrickType; + protected _label: string; + protected _glyph: string; + + protected _colorBg: TBrickColor; + protected _colorFg: TBrickColor; + protected _outline: TBrickColor; + protected _scale: number; + + public highlighted = false; + + constructor(params: { + // intrinsic + name: string; + kind: TBrickKind; + type: TBrickType; + label: string; + glyph: string; + // style + colorBg: TBrickColor; + colorFg: TBrickColor; + outline: TBrickColor; + scale: number; + }) { + this._uuid = ''; + this._name = params.name; + this._kind = params.kind; + this._type = params.type; + this._label = params.label; + this._glyph = params.glyph; + this._colorBg = params.colorBg; + this._colorFg = params.colorFg; + this._outline = params.outline; + this._scale = params.scale; + } + + public get uuid(): string { + return this._uuid; + } + + public get name(): string { + return this._name; + } + + public get kind(): TBrickKind { + return this._kind; + } + + public get type(): TBrickType { + return this._type; + } + + public get label(): string { + return this._label; + } + + public get glyph(): string { + return this._glyph; + } + + public get colorBg(): TBrickColor { + return this._colorBg; + } + + public get colorFg(): TBrickColor { + return this._colorFg; + } + + public get outline(): TBrickColor { + return this._outline; + } + + public get scale(): number { + return this._scale; + } + + public abstract get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords }; + + public abstract get SVGpath(): string; +} + +/** + * @abstract + * @class + * Defines the data model of a generic argument brick. + */ +abstract class BrickModelArgument extends BrickModel implements IBrickArgument { + protected _dataType: TBrickArgDataType; + + constructor(params: { + // intrinsic + name: string; + type: TBrickType; + label: string; + glyph: string; + dataType: TBrickArgDataType; + // style + colorBg: TBrickColor; + colorFg: TBrickColor; + outline: TBrickColor; + scale: number; + }) { + super({ ...params, kind: 'argument' }); + + this._dataType = params.dataType; + } + + public get dataType(): TBrickArgDataType { + return this._dataType; + } + + public abstract get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords }; +} + +/** + * @abstract + * @class + * Defines the data model of a generic instruction brick. + */ +abstract class BrickModelInstruction extends BrickModel implements IBrickInstruction { + protected _args: Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + } + >; + + protected _connectAbove: boolean; + protected _connectBelow: boolean; + + constructor(params: { + // intrinsic + name: string; + type: TBrickType; + 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, kind: 'instruction' }); + + this._args = params.args; + this._connectAbove = params.connectAbove; + this._connectBelow = params.connectBelow; + } + + public get args(): Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + } + > { + return this._args; + } + + public get connectAbove(): boolean { + return this._connectAbove; + } + + public get connectBelow(): boolean { + return this._connectBelow; + } + + public abstract get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords }; + + public abstract get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords }; + + public abstract get bBoxArgs(): Record; +} + +// -- public classes ------------------------------------------------------------------------------- + +/** + * @abstract + * @class + * Defines the data model of a data brick. + */ +export abstract class BrickModelData extends BrickModelArgument implements IBrickData { + protected _dynamic: boolean; + protected _value?: boolean | number | string; + protected _input?: 'boolean' | 'number' | 'string' | 'options'; + + 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, type: 'data' }); + + this._dynamic = params.dynamic; + this._value = params.value; + this._input = params.input; + } + + public get dynamic(): boolean { + return this._dynamic; + } + + public get value(): boolean | number | string | undefined { + return this._value; + } + + public get input(): 'boolean' | 'number' | 'string' | 'options' | undefined { + return this._input; + } +} + +/** + * @abstract + * @class + * Defines the data model of an expression brick. + */ +export abstract class BrickModelExpression extends BrickModelArgument implements IBrickExpression { + protected _args: Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + } + >; + + 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, type: 'expression' }); + + this._args = params.args; + } + + public get args(): Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + } + > { + return this._args; + } + + public abstract get bBoxArgs(): Record; +} + +/** + * @abstract + * @class + * Defines the data model of a statement brick. + */ +export abstract class BrickModelStatement extends BrickModelInstruction implements IBrickStatement { + 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, type: 'statement' }); + } +} + +/** + * @abstract + * @class + * Defines the data model of a block brick. + */ +export abstract class BrickModelBlock extends BrickModelInstruction implements IBrickBlock { + public nestExtent: TBrickExtent = { width: 0, height: 0 }; + public collapsed = false; + + 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, type: 'block' }); + } + + public abstract get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords }; +} diff --git a/modules/masonry/src/stack/README.md b/modules/masonry/src/stack/README.md new file mode 100644 index 00000000..83140316 --- /dev/null +++ b/modules/masonry/src/stack/README.md @@ -0,0 +1,59 @@ +# Data Model for Stack Tree + +## Stack Node + +### Intrinsic + +- `brick`: reference to the BrickModel (Data, Expression, Statement, Block) instance +- `children`: array of child StackNode instances + +### Methods + +- `constructor(brick: BrickModelData | BrickModelExpression | BrickModelStatement |BrickModelBlock)`: Initializes a StackNode with the given brick and an empty children array. + +## Stack + +### Intrinsic + +- `id`: unique ID for the stack instance +- `rootNodes`: array of root StackNode instances +- `_validationDisabled`: private flag to disable validation checks + +### Methods + +- `constructor(id: string)`: Initializes a Stack with the given ID and an empty rootNodes array. +- `validate(): boolean`: Validates the stack, returning `true` if there are no validation errors or +if validation is disabled. +- `addNode(node: IStackNode, parentId?: string): void`: Adds a node to the stack. If `parentId` is +provided, the node is added as a child of the specified parent node. +- `removeNode(id: string): void`: Removes a node from the stack by its ID. +- `moveNode(id: string, newParentId: string, newIndex: number): void`: Moves a node to a new parent + node at the specified index. +- `collapse(id: string): void`: Collapses a block node, hiding its children. +- `expand(id: string): void`: Expands a block node, showing its children. +- `getValidationErrors(): string[]`: Returns an array of validation error messages. +- `disableValidation(): void`: Disables validation checks. +- `enableValidation(): void`: Enables validation checks. + +### Private Methods + +- `findNode(id: string): IStackNode | null`: Finds a node by its ID. +- `updateNestExtent(node: IStackNode): void`: Updates the nesting extent of a block node based on + its children. +- `isValidConnection(node: IStackNode, position: 'above' | 'below'): boolean`: Checks if a connection +at the specified position is valid for the given node. + +## Factory Function + +### Methods + +- `createStackNode(brick: BrickModelData | BrickModelExpression | BrickModelStatement | +BrickModelBlock): IStackNode`: Creates a StackNode based on the given brick type. + +--- + +**Note:** Intrinsic properties are set in the constructor and cannot be modified once instantiated. They are accessible using getters. + +**Note:** Private methods are for internal use within the Stack class and should not be accessed directly from outside. + +--- diff --git a/modules/masonry/src/stack/data.ts b/modules/masonry/src/stack/data.ts new file mode 100644 index 00000000..1d1e2217 --- /dev/null +++ b/modules/masonry/src/stack/data.ts @@ -0,0 +1,318 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { + BrickModelData, + BrickModelExpression, + BrickModelStatement, + BrickModelBlock, +} from '../brick/model'; + +/** + * @interface IStackNode + * Represents a node in the stack structure. + */ +export interface IStackNode { + /** The brick model associated with this node */ + brick: BrickModelData | BrickModelExpression | BrickModelStatement | BrickModelBlock; + /** Child nodes of this node */ + children: IStackNode[]; +} + +/** + * @interface IStack + * Represents the stack structure for managing bricks. + */ +export interface IStack { + /** Unique identifier for the stack */ + id: string; + /** Root nodes of the stack */ + rootNodes: IStackNode[]; + + /** + * Validates the entire stack structure. + * @returns {boolean} True if the stack is valid, false otherwise. + */ + validate(): boolean; + + /** + * Adds a new node to the stack. + * @param {IStackNode} node - The node to add. + * @param {string} [parentId] - The ID of the parent node (optional). + */ + addNode(node: IStackNode, parentId?: string): void; + + /** + * Removes a node from the stack. + * @param {string} id - The ID of the node to remove. + */ + removeNode(id: string): void; + + /** + * Moves a node to a new position in the stack. + * @param {string} id - The ID of the node to move. + * @param {string} newParentId - The ID of the new parent node. + * @param {number} newIndex - The new index position under the parent. + */ + moveNode(id: string, newParentId: string, newIndex: number): void; + + /** + * Collapses a block node. + * @param {string} id - The ID of the node to collapse. + */ + collapse(id: string): void; + + /** + * Expands a block node. + * @param {string} id - The ID of the node to expand. + */ + expand(id: string): void; + + /** + * Gets all validation errors in the stack. + * @returns {string[]} An array of error messages. + */ + getValidationErrors(): string[]; +} + +/** + * @class StackNode + * Implements the IStackNode interface. + */ +class StackNode implements IStackNode { + brick: BrickModelData | BrickModelExpression | BrickModelStatement | BrickModelBlock; + children: IStackNode[]; + + /** + * Creates a new StackNode. + * @param {BrickModelData | BrickModelExpression | BrickModelStatement | BrickModelBlock} brick - The brick model for this node. + */ + constructor( + brick: BrickModelData | BrickModelExpression | BrickModelStatement | BrickModelBlock, + ) { + this.brick = brick; + this.children = []; + } +} + +/** + * @class Stack + * Implements the IStack interface. + */ +class Stack implements IStack { + id: string; + rootNodes: IStackNode[]; + private _validationDisabled = false; + + /** + * Creates a new Stack. + * @param {string} id - The unique identifier for this stack. + */ + constructor(id: string) { + this.id = id; + this.rootNodes = []; + } + + validate(): boolean { + if (this._validationDisabled) return true; + return this.getValidationErrors().length === 0; + } + + addNode(node: IStackNode, parentId?: string): void { + if (!parentId) { + this.rootNodes.push(node); + } else { + const parent = this.findNode(parentId); + if ( + parent && + (parent.brick instanceof BrickModelBlock || + parent.brick instanceof BrickModelExpression) + ) { + parent.children.push(node); + this.updateNestExtent(parent); + } else { + throw new Error('Parent node not found or cannot have children'); + } + } + } + + removeNode(id: string): void { + const remove = (nodes: IStackNode[]): boolean => { + for (let i = 0; i < nodes.length; i++) { + if (nodes[i].brick.uuid === id) { + nodes.splice(i, 1); + return true; + } + if (nodes[i].children.length > 0 && remove(nodes[i].children)) { + this.updateNestExtent(nodes[i]); + return true; + } + } + return false; + }; + remove(this.rootNodes); + } + + moveNode(id: string, newParentId: string, newIndex: number): void { + const node = this.findNode(id); + if (!node) throw new Error('Node not found'); + + this.removeNode(id); + const newParent = this.findNode(newParentId); + if (!newParent) throw new Error('New parent node not found'); + + if ( + !(newParent.brick instanceof BrickModelBlock) && + !(newParent.brick instanceof BrickModelExpression) + ) { + throw new Error('New parent cannot have children'); + } + + newParent.children.splice(newIndex, 0, node); + this.updateNestExtent(newParent); + } + + collapse(id: string): void { + const node = this.findNode(id); + if (node && node.brick instanceof BrickModelBlock) { + node.brick.collapsed = true; + this.updateNestExtent(node); + } + } + + expand(id: string): void { + const node = this.findNode(id); + if (node && node.brick instanceof BrickModelBlock) { + node.brick.collapsed = false; + this.updateNestExtent(node); + } + } + + getValidationErrors(): string[] { + const errors: string[] = []; + const validateNode = (node: IStackNode) => { + // Check connection compatibility + if ( + node.brick instanceof BrickModelStatement || + node.brick instanceof BrickModelBlock + ) { + if (node.brick.connectAbove && !this.isValidConnection(node, 'above')) { + errors.push(`Invalid connection above for node ${node.brick.uuid}`); + } + if (node.brick.connectBelow && !this.isValidConnection(node, 'below')) { + errors.push(`Invalid connection below for node ${node.brick.uuid}`); + } + } + + // Check argument data type compatibility + if ( + node.brick instanceof BrickModelExpression || + node.brick instanceof BrickModelStatement || + node.brick instanceof BrickModelBlock + ) { + for (const [argId, arg] of Object.entries(node.brick.args)) { + const childNode = node.children.find((child) => child.brick.uuid === argId); + if (childNode && 'dataType' in childNode.brick) { + if (childNode.brick.dataType !== arg.dataType && arg.dataType !== 'any') { + errors.push( + `Data type mismatch for argument ${argId} in node ${node.brick.uuid}`, + ); + } + } + } + } + + // Recursively validate children + node.children.forEach(validateNode); + }; + + this.rootNodes.forEach(validateNode); + return errors; + } + + /** + * Disables validation for this stack. + */ + disableValidation(): void { + this._validationDisabled = true; + } + + /** + * Enables validation for this stack. + */ + enableValidation(): void { + this._validationDisabled = false; + } + + /** + * Finds a node in the stack by its ID. + * @param {string} id - The ID of the node to find. + * @returns {IStackNode | null} The found node or null if not found. + */ + private findNode(id: string): IStackNode | null { + const find = (nodes: IStackNode[]): IStackNode | null => { + for (const node of nodes) { + if (node.brick.uuid === id) return node; + if (node.children.length > 0) { + const found = find(node.children); + if (found) return found; + } + } + return null; + }; + return find(this.rootNodes); + } + + /** + * Updates the nest extent of a block node. + * @param {IStackNode} node - The node to update. + */ + private updateNestExtent(node: IStackNode): void { + if (node.brick instanceof BrickModelBlock) { + const childrenExtent = node.children.reduce( + (acc, child) => { + const childExtent = child.brick.bBoxBrick.extent; + return { + width: Math.max(acc.width, childExtent.width), + height: acc.height + childExtent.height, + }; + }, + { width: 0, height: 0 }, + ); + + node.brick.nestExtent = childrenExtent; + } + } + + /** + * Checks if a connection is valid for a given node and position. + * @param {IStackNode} node - The node to check. + * @param {'above' | 'below'} position - The position to check. + * @returns {boolean} True if the connection is valid, false otherwise. + */ + private isValidConnection(node: IStackNode, position: 'above' | 'below'): boolean { + if (!(node.brick instanceof BrickModelStatement || node.brick instanceof BrickModelBlock)) { + return false; + } + + if (position === 'above') { + return node.brick.connectAbove; + } else if (position === 'below') { + return node.brick.connectBelow; + } + + return false; + } +} + +/** + * Creates a StackNode based on the provided brick model. + * @param {BrickModelData | BrickModelExpression | BrickModelStatement | BrickModelBlock} brick - The brick model for the node. + * @returns {IStackNode} A new StackNode instance. + */ +function createStackNode( + brick: BrickModelData | BrickModelExpression | BrickModelStatement | BrickModelBlock, +): IStackNode { + return new StackNode(brick); +} + +// Export the Stack class and createStackNode function +export { Stack, createStackNode }; diff --git a/modules/masonry/src/stack/index.ts b/modules/masonry/src/stack/index.ts new file mode 100644 index 00000000..e69de29b From cf0d834675a8d530d09e60c3094f41d1f47c8e62 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 15 Jul 2024 13:59:56 +0530 Subject: [PATCH 09/58] 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 10/58] 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 11/58] 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 12/58] 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 13/58] 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 14/58] 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 15/58] 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 16/58] 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 17/58] 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 18/58] 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 19/58] 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 20/58] 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[]; -}; From aa5ce477f31fef1ae75f1d2fc9af728d92d113cb Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Sun, 25 Aug 2024 15:22:29 +0530 Subject: [PATCH 21/58] chore(masonry): modify package.json --- modules/masonry/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/masonry/package.json b/modules/masonry/package.json index a18b7d12..a0548e9f 100644 --- a/modules/masonry/package.json +++ b/modules/masonry/package.json @@ -9,6 +9,7 @@ "coverage": "vitest run --coverage", "lint": "eslint src", "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build" + "build-storybook": "storybook build", + "playground": "vite playground --host --port 5601" } } From 43a177cb180a6de460b78f8f4d8a9d8654f86774 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Sun, 25 Aug 2024 15:25:55 +0530 Subject: [PATCH 22/58] feat(masonry): add coords in brick components --- .../src/brick/design0/components/BrickBlock.tsx | 14 +++++++++----- .../src/brick/design0/components/BrickData.tsx | 14 +++++++++----- .../brick/design0/components/BrickExpression.tsx | 14 +++++++++----- .../brick/design0/components/BrickStatement.tsx | 14 +++++++++----- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/modules/masonry/src/brick/design0/components/BrickBlock.tsx b/modules/masonry/src/brick/design0/components/BrickBlock.tsx index 7dd5ed16..92c3293f 100644 --- a/modules/masonry/src/brick/design0/components/BrickBlock.tsx +++ b/modules/masonry/src/brick/design0/components/BrickBlock.tsx @@ -1,13 +1,17 @@ import type { JSX } from 'react'; -import type { IBrickBlock } from '@/@types/brick'; +import type { IBrickBlock, TBrickCoords } from '@/@types/brick'; // ------------------------------------------------------------------------------------------------- -export default function (props: { instance: IBrickBlock }): JSX.Element { - const { instance } = props; - +export default function ({ + instance, + coords = { x: 0, y: 0 }, +}: { + instance: IBrickBlock; + coords?: TBrickCoords; +}): JSX.Element { return ( - + + + + Date: Sun, 25 Aug 2024 15:28:03 +0530 Subject: [PATCH 23/58] build(masonry/playground): setup playground --- modules/masonry/playground/index.html | 36 ++++++++++++++++++----- modules/masonry/playground/index.tsx | 18 ++++++++++++ modules/masonry/playground/vite.config.ts | 16 ++++++++-- 3 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 modules/masonry/playground/index.tsx diff --git a/modules/masonry/playground/index.html b/modules/masonry/playground/index.html index 23c0a4d0..85dbc925 100644 --- a/modules/masonry/playground/index.html +++ b/modules/masonry/playground/index.html @@ -1,13 +1,33 @@ - + - - - - Masonry-Test + + + + Masonry - Playground + + + -
- + +
+ - + \ No newline at end of file diff --git a/modules/masonry/playground/index.tsx b/modules/masonry/playground/index.tsx new file mode 100644 index 00000000..184a0b11 --- /dev/null +++ b/modules/masonry/playground/index.tsx @@ -0,0 +1,18 @@ +import { createRoot } from 'react-dom/client'; +import { createBrowserRouter, Navigate, RouterProvider } from 'react-router-dom'; + +import WorkSpace from './pages/workspace'; + +const router = createBrowserRouter([ + { + path: '/workspace', + element: , + }, + { + path: '/', + element: , + }, +]); + +const root = createRoot(document.getElementById('playground-root') as HTMLElement); +root.render(); diff --git a/modules/masonry/playground/vite.config.ts b/modules/masonry/playground/vite.config.ts index 1d2d1a4b..abd1d975 100644 --- a/modules/masonry/playground/vite.config.ts +++ b/modules/masonry/playground/vite.config.ts @@ -1,8 +1,18 @@ -/* eslint-disable prettier/prettier */ +import path from 'path'; + import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -// https://vitejs.dev/config/ export default defineConfig({ - plugins: [react()], + plugins: [ + // + react(), + ], + + resolve: { + alias: { + '@': path.resolve(__dirname, '..', 'src'), + }, + extensions: ['.tsx', '.ts', '.js', '.scss', '.sass', '.json'], + }, }); From 3698be5fa57dafe82c2325f7f673c63658e6cabb Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Sun, 25 Aug 2024 15:45:21 +0530 Subject: [PATCH 24/58] feat(masonry/playground): render a dummy brick stack --- modules/masonry/playground/package-lock.json | 3255 ----------------- modules/masonry/playground/package.json | 28 - .../playground/pages/workspace/data.ts | 213 ++ .../playground/pages/workspace/index.tsx | 65 + modules/masonry/playground/src/App.css | 0 modules/masonry/playground/src/App.tsx | 19 - .../playground/src/components/DivStack.tsx | 135 - .../playground/src/components/NormalSVG.tsx | 139 - .../src/components/SVGWithValues.tsx | 150 - modules/masonry/playground/src/main.tsx | 9 - modules/masonry/playground/src/vite-env.d.ts | 1 - modules/masonry/playground/tsconfig.app.json | 27 - modules/masonry/playground/tsconfig.json | 11 - modules/masonry/playground/tsconfig.node.json | 13 - 14 files changed, 278 insertions(+), 3787 deletions(-) delete mode 100644 modules/masonry/playground/package-lock.json delete mode 100644 modules/masonry/playground/package.json create mode 100644 modules/masonry/playground/pages/workspace/data.ts create mode 100644 modules/masonry/playground/pages/workspace/index.tsx delete mode 100644 modules/masonry/playground/src/App.css delete mode 100644 modules/masonry/playground/src/App.tsx delete mode 100644 modules/masonry/playground/src/components/DivStack.tsx delete mode 100644 modules/masonry/playground/src/components/NormalSVG.tsx delete mode 100644 modules/masonry/playground/src/components/SVGWithValues.tsx delete mode 100644 modules/masonry/playground/src/main.tsx delete mode 100644 modules/masonry/playground/src/vite-env.d.ts delete mode 100644 modules/masonry/playground/tsconfig.app.json delete mode 100644 modules/masonry/playground/tsconfig.json delete mode 100644 modules/masonry/playground/tsconfig.node.json diff --git a/modules/masonry/playground/package-lock.json b/modules/masonry/playground/package-lock.json deleted file mode 100644 index 9aafa49f..00000000 --- a/modules/masonry/playground/package-lock.json +++ /dev/null @@ -1,3255 +0,0 @@ -{ - "name": "masonry-test", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "masonry-test", - "version": "0.0.0", - "dependencies": { - "react": "^18.3.1", - "react-dom": "^18.3.1" - }, - "devDependencies": { - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", - "@vitejs/plugin-react": "^4.3.1", - "eslint": "^8.57.0", - "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.7", - "typescript": "^5.2.2", - "vite": "^5.3.1" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", - "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", - "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helpers": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", - "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", - "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dev": true, - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", - "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", - "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", - "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", - "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", - "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", - "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", - "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", - "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", - "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", - "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", - "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", - "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", - "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", - "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", - "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", - "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", - "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", - "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", - "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", - "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", - "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", - "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", - "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", - "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", - "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", - "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", - "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/type-utils": "7.13.1", - "@typescript-eslint/utils": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", - "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/typescript-estree": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", - "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", - "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.13.1", - "@typescript-eslint/utils": "7.13.1", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", - "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", - "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", - "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/typescript-estree": "7.13.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", - "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.13.1", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", - "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.5", - "@babel/plugin-transform-react-jsx-self": "^7.24.5", - "@babel/plugin-transform-react-jsx-source": "^7.24.1", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0" - } - }, - "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", - "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001629", - "electron-to-chromium": "^1.4.796", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.16" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001636", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", - "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.810", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.810.tgz", - "integrity": "sha512-Kaxhu4T7SJGpRQx99tq216gCq2nMxJo+uuT6uzz9l8TVN2stL7M06MIIXAtr9jsrLs2Glflgf2vMQRepxawOdQ==", - "dev": true - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.7.tgz", - "integrity": "sha512-yrj+KInFmwuQS2UQcg1SF83ha1tuHC1jMQbRNyuWtlEzzKRDgAl7L4Yp4NlDUZTZNlWvHEzOtJhMi40R7JxcSw==", - "dev": true, - "peerDependencies": { - "eslint": ">=7" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", - "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.0", - "@rollup/rollup-android-arm64": "4.18.0", - "@rollup/rollup-darwin-arm64": "4.18.0", - "@rollup/rollup-darwin-x64": "4.18.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", - "@rollup/rollup-linux-arm-musleabihf": "4.18.0", - "@rollup/rollup-linux-arm64-gnu": "4.18.0", - "@rollup/rollup-linux-arm64-musl": "4.18.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", - "@rollup/rollup-linux-riscv64-gnu": "4.18.0", - "@rollup/rollup-linux-s390x-gnu": "4.18.0", - "@rollup/rollup-linux-x64-gnu": "4.18.0", - "@rollup/rollup-linux-x64-musl": "4.18.0", - "@rollup/rollup-win32-arm64-msvc": "4.18.0", - "@rollup/rollup-win32-ia32-msvc": "4.18.0", - "@rollup/rollup-win32-x64-msvc": "4.18.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", - "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/vite": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz", - "integrity": "sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==", - "dev": true, - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.38", - "rollup": "^4.13.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/modules/masonry/playground/package.json b/modules/masonry/playground/package.json deleted file mode 100644 index 8a458ece..00000000 --- a/modules/masonry/playground/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "masonry-test", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", - "preview": "vite preview" - }, - "dependencies": { - "react": "^18.3.1", - "react-dom": "^18.3.1" - }, - "devDependencies": { - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", - "@vitejs/plugin-react": "^4.3.1", - "eslint": "^8.57.0", - "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.7", - "typescript": "^5.2.2", - "vite": "^5.3.1" - } -} diff --git a/modules/masonry/playground/pages/workspace/data.ts b/modules/masonry/playground/pages/workspace/data.ts new file mode 100644 index 00000000..f29c39f6 --- /dev/null +++ b/modules/masonry/playground/pages/workspace/data.ts @@ -0,0 +1,213 @@ +import { + ModelBrickBlock, + ModelBrickData, + ModelBrickExpression, + ModelBrickStatement, +} from '@/brick'; +import type { TBrickType, TBrickCoords, TBrickArgDataType } from '@/@types/brick'; + +type InstanceMap = { + data: ModelBrickData; + expression: ModelBrickExpression; + statement: ModelBrickStatement; + block: ModelBrickBlock; +}; + +export type Brick = { + id: string; + type: TBrickType; + instance: InstanceMap[TBrickType]; + coords: TBrickCoords; + children?: Brick[]; +}; + +export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ + { + id: 'workspace1', + data: [ + { + id: '1', + type: 'block', + instance: new ModelBrickBlock({ + label: 'Block', + args: Object.fromEntries( + [].map< + [string, { label: string; dataType: TBrickArgDataType; meta: unknown }] + >((name) => [name, { label: name, dataType: 'any', meta: undefined }]), + ), + colorBg: 'yellow', + colorFg: 'black', + outline: 'red', + scale: 2, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + nestLengthY: 125, + }), + coords: { x: 50, y: 50 }, + children: [ + { + id: '2', + type: 'statement', + instance: new ModelBrickStatement({ + label: 'Statement', + args: Object.fromEntries( + [].map< + [ + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + }, + ] + >((name) => [ + name, + { label: name, dataType: 'any', meta: undefined }, + ]), + ), + colorBg: 'lightblue', + colorFg: 'black', + outline: 'blue', + scale: 2, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + }), + coords: { x: 68, y: 92 }, + }, + { + id: '3', + type: 'statement', + instance: new ModelBrickStatement({ + label: 'Statement', + args: Object.fromEntries( + [].map< + [ + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + }, + ] + >((name) => [ + name, + { label: name, dataType: 'any', meta: undefined }, + ]), + ), + colorBg: 'lightgreen', + colorFg: 'black', + outline: 'green', + scale: 2, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + }), + coords: { x: 68, y: 134 }, + }, + { + id: '4', + type: 'block', + instance: new ModelBrickBlock({ + label: 'Block', + args: Object.fromEntries( + [].map< + [ + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + }, + ] + >((name) => [ + name, + { label: name, dataType: 'any', meta: undefined }, + ]), + ), + colorBg: 'orange', + colorFg: 'black', + outline: 'grey', + scale: 2, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + nestLengthY: 17, + }), + coords: { x: 68, y: 176 }, + children: [ + { + id: '5', + type: 'statement', + instance: new ModelBrickStatement({ + label: 'Statement', + args: Object.fromEntries( + [].map< + [ + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + }, + ] + >((name) => [ + name, + { label: name, dataType: 'any', meta: undefined }, + ]), + ), + colorBg: 'lightpink', + colorFg: 'black', + outline: 'deeppink', + + scale: 2, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + }), + coords: { x: 86, y: 218 }, + }, + ], + }, + { + id: '6', + type: 'statement', + instance: new ModelBrickStatement({ + label: 'Statement', + args: Object.fromEntries( + [].map< + [ + string, + { + label: string; + dataType: TBrickArgDataType; + meta: unknown; + }, + ] + >((name) => [ + name, + { label: name, dataType: 'any', meta: undefined }, + ]), + ), + colorBg: 'lightgreen', + colorFg: 'black', + outline: 'green', + scale: 2, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + }), + coords: { x: 68, y: 302 }, + }, + ], + }, + ], + }, +]; \ No newline at end of file diff --git a/modules/masonry/playground/pages/workspace/index.tsx b/modules/masonry/playground/pages/workspace/index.tsx new file mode 100644 index 00000000..eca5b957 --- /dev/null +++ b/modules/masonry/playground/pages/workspace/index.tsx @@ -0,0 +1,65 @@ +import { + BrickBlock, + BrickData, + BrickExpression, + BrickStatement, + ModelBrickBlock, + ModelBrickData, + ModelBrickExpression, + ModelBrickStatement, +} from '@/brick'; +import { WORKSPACES_DATA } from './data'; +import type { TBrickCoords, TBrickType } from '@/@types/brick'; +import type { Brick } from './data'; + +function getBrick( + type: TBrickType, + instance: ModelBrickBlock | ModelBrickData | ModelBrickExpression | ModelBrickStatement, + coords: TBrickCoords, +) { + switch (type) { + case 'data': + return ; + case 'expression': + return ; + case 'statement': + return ; + case 'block': + return ; + default: + return <>; + } +} + +function RenderBricks({ brickData }: { brickData: Brick }) { + return ( + <> + {getBrick(brickData.type, brickData.instance, brickData.coords)} + {brickData.children && + brickData.children?.length > 0 && + brickData.children.map((child) => )} + + ); +} + +function WorkSpace() { + return ( +
+ {WORKSPACES_DATA.map((workspace) => ( + + {workspace.data.map((brick) => { + return ; + })} + + ))} +
+ ); +} + +export default WorkSpace; diff --git a/modules/masonry/playground/src/App.css b/modules/masonry/playground/src/App.css deleted file mode 100644 index e69de29b..00000000 diff --git a/modules/masonry/playground/src/App.tsx b/modules/masonry/playground/src/App.tsx deleted file mode 100644 index bc4dab65..00000000 --- a/modules/masonry/playground/src/App.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import DivStack from './components/DivStack'; -import NormalSVG from './components/NormalSVG'; -import SVGWithValues from './components/SVGWithValues'; - -const App: React.FC = () => { - return ( -
-

Div Stack

- -

Normal SVG

- -

SVG With Values

- -
- ); -}; - -export default App; diff --git a/modules/masonry/playground/src/components/DivStack.tsx b/modules/masonry/playground/src/components/DivStack.tsx deleted file mode 100644 index d0ca0895..00000000 --- a/modules/masonry/playground/src/components/DivStack.tsx +++ /dev/null @@ -1,135 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -/* eslint-disable no-constant-condition */ -import React, { useState, useEffect } from 'react'; - -interface Brick { - id: number; - type: string; - x: number; - y: number; - color: string; -} - -const DivStack: React.FC = () => { - const [bricks, setBricks] = useState([ - { id: 1, type: 'top', x: 50, y: 50, color: '#ff6b6b' }, - { id: 2, type: 'middle', x: 50, y: 110, color: '#4ecdc4' }, - { id: 3, type: 'middle', x: 50, y: 170, color: '#45b7d1' }, - { id: 4, type: 'middle', x: 50, y: 230, color: '#f9d56e' }, - { id: 5, type: 'middle', x: 50, y: 290, color: '#ff9ff3' }, - { id: 6, type: 'bottom', x: 50, y: 350, color: '#54a0ff' }, - ]); - - const [isDragging, setIsDragging] = useState(false); - const [draggedBrickId, setDraggedBrickId] = useState(null); - const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); - - const isConnected = (brick1: Brick, brick2: Brick) => - Math.abs(brick1.y + 60 - brick2.y) < 5 && Math.abs(brick1.x - brick2.x) < 5; - - const findConnectedBricks = (startId: number): number[] => { - const result: number[] = [startId]; - let currentId = startId; - - while (true) { - const currentBrick = bricks.find((b) => b.id === currentId); - const nextBrick = bricks.find((b) => b.id !== currentId && isConnected(currentBrick!, b)); - if (nextBrick && nextBrick.y > currentBrick!.y) { - result.push(nextBrick.id); - currentId = nextBrick.id; - } else { - break; - } - } - return result; - }; - - const handleMouseDown = (e: React.MouseEvent, id: number) => { - const brick = bricks.find((b) => b.id === id); - if (brick) { - setIsDragging(true); - setDraggedBrickId(id); - setDragOffset({ - x: e.clientX - brick.x, - y: e.clientY - brick.y, - }); - } - }; - - const handleMouseMove = (e: MouseEvent) => { - if (isDragging && draggedBrickId !== null) { - const newX = e.clientX - dragOffset.x; - const newY = e.clientY - dragOffset.y; - const connectedBricks = findConnectedBricks(draggedBrickId); - setBricks((prevBricks) => { - return prevBricks.map((brick) => { - if (connectedBricks.includes(brick.id)) { - const index = connectedBricks.indexOf(brick.id); - return { - ...brick, - x: newX, - y: newY + index * 60, - }; - } - return brick; - }); - }); - } - }; - - const handleMouseUp = () => { - setIsDragging(false); - setDraggedBrickId(null); - }; - - useEffect(() => { - window.addEventListener('mousemove', handleMouseMove); - window.addEventListener('mouseup', handleMouseUp); - return () => { - window.removeEventListener('mousemove', handleMouseMove); - window.removeEventListener('mouseup', handleMouseUp); - }; - }, [isDragging, draggedBrickId]); - - return ( -
-
- {bricks.map((brick) => ( -
handleMouseDown(e, brick.id)} - > - {brick.type === 'top' && } - {brick.type === 'middle' && } - {brick.type === 'bottom' && } -
- ))} -
-
- ); -}; - -export default DivStack; diff --git a/modules/masonry/playground/src/components/NormalSVG.tsx b/modules/masonry/playground/src/components/NormalSVG.tsx deleted file mode 100644 index 1b01eb58..00000000 --- a/modules/masonry/playground/src/components/NormalSVG.tsx +++ /dev/null @@ -1,139 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -/* eslint-disable no-constant-condition */ -/* eslint-disable prettier/prettier */ -import React, { useState, useRef, useEffect } from 'react'; - -interface Brick { - id: number; - type: string; - x: number; - y: number; - color: string; -} - -const NormalSVG: React.FC = () => { - const [bricks, setBricks] = useState([ - { id: 1, type: 'top', x: 50, y: 50, color: '#ff6b6b' }, - { id: 2, type: 'middle', x: 50, y: 110, color: '#4ecdc4' }, - { id: 3, type: 'middle', x: 50, y: 170, color: '#45b7d1' }, - { id: 4, type: 'middle', x: 50, y: 230, color: '#f9d56e' }, - { id: 5, type: 'middle', x: 50, y: 290, color: '#ff9ff3' }, - { id: 6, type: 'bottom', x: 50, y: 350, color: '#54a0ff' }, - ]); - const [isDragging, setIsDragging] = useState(false); - const [draggedBrickId, setDraggedBrickId] = useState(null); - const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); - const svgRef = useRef(null); - - const isConnected = (brick1: Brick, brick2: Brick) => - Math.abs(brick1.y + 60 - brick2.y) < 5 && Math.abs(brick1.x - brick2.x) < 5; - - const findConnectedBricks = (startId: number): number[] => { - const result: number[] = [startId]; - let currentId = startId; - - while (true) { - const currentBrick = bricks.find((b) => b.id === currentId); - const nextBrick = bricks.find( - (b) => b.id !== currentId && isConnected(currentBrick!, b), - ); - if (nextBrick && nextBrick.y > currentBrick!.y) { - result.push(nextBrick.id); - currentId = nextBrick.id; - } else { - break; - } - } - - return result; - }; - - const handleMouseDown = (e: React.MouseEvent, id: number) => { - const brick = bricks.find((b) => b.id === id); - if (brick) { - const svgRect = svgRef.current?.getBoundingClientRect(); - if (svgRect) { - setIsDragging(true); - setDraggedBrickId(id); - setDragOffset({ - x: e.clientX - svgRect.left - brick.x, - y: e.clientY - svgRect.top - brick.y, - }); - } - } - }; - - const handleMouseMove = (e: MouseEvent) => { - if (isDragging && draggedBrickId !== null) { - const svgRect = svgRef.current?.getBoundingClientRect(); - if (svgRect) { - const newX = e.clientX - svgRect.left - dragOffset.x; - const newY = e.clientY - svgRect.top - dragOffset.y; - - const connectedBricks = findConnectedBricks(draggedBrickId); - - setBricks((prevBricks) => { - return prevBricks.map((brick) => { - if (connectedBricks.includes(brick.id)) { - const index = connectedBricks.indexOf(brick.id); - return { - ...brick, - x: newX, - y: newY + index * 60, - }; - } - return brick; - }); - }); - } - } - }; - - const handleMouseUp = () => { - setIsDragging(false); - setDraggedBrickId(null); - }; - - useEffect(() => { - window.addEventListener('mousemove', handleMouseMove); - window.addEventListener('mouseup', handleMouseUp); - return () => { - window.removeEventListener('mousemove', handleMouseMove); - window.removeEventListener('mouseup', handleMouseUp); - }; - }, [isDragging, draggedBrickId]); - - const renderBrickPath = (type: string) => { - switch (type) { - case 'top': - return 'M0,0 h100 v50 h-80 l-20,10 v-60 z'; - case 'middle': - return 'M0,0 h80 l20,-10 v60 h-80 l-20,10 v-60 z'; - case 'bottom': - return 'M0,0 h80 l20,-10 v60 h-100 v-50 z'; - default: - return ''; - } - }; - - return ( - - {bricks.map((brick) => ( - handleMouseDown(e, brick.id)} - > - - - ))} - - ); -}; - -export default NormalSVG; diff --git a/modules/masonry/playground/src/components/SVGWithValues.tsx b/modules/masonry/playground/src/components/SVGWithValues.tsx deleted file mode 100644 index 5b2c0baf..00000000 --- a/modules/masonry/playground/src/components/SVGWithValues.tsx +++ /dev/null @@ -1,150 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -/* eslint-disable no-constant-condition */ -/* eslint-disable prettier/prettier */ -import React, { useState, useRef, useEffect } from 'react'; - -interface Brick { - id: number; - type: string; - x: number; - y: number; - color: string; -} - -const SVGWithValues: React.FC = () => { - const [bricks, setBricks] = useState([ - { id: 1, type: 'top', x: 50, y: 50, color: '#ff6b6b' }, - { id: 2, type: 'middle', x: 50, y: 110, color: '#4ecdc4' }, - { id: 3, type: 'middle', x: 50, y: 170, color: '#45b7d1' }, - { id: 4, type: 'middle', x: 50, y: 230, color: '#f9d56e' }, - { id: 5, type: 'middle', x: 50, y: 290, color: '#ff9ff3' }, - { id: 6, type: 'bottom', x: 50, y: 350, color: '#54a0ff' }, - ]); - - const [isDragging, setIsDragging] = useState(false); - const [draggedBrickId, setDraggedBrickId] = useState(null); - const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); - const svgRef = useRef(null); - - const isConnected = (brick1: Brick, brick2: Brick) => - Math.abs(brick1.y + 60 - brick2.y) < 5 && Math.abs(brick1.x - brick2.x) < 5; - - const findConnectedBricks = (startId: number): number[] => { - const result: number[] = [startId]; - let currentId = startId; - - // Find bricks below - while (true) { - const currentBrick = bricks.find((b) => b.id === currentId); - const nextBrick = bricks.find( - (b) => b.id !== currentId && isConnected(currentBrick!, b), - ); - if (nextBrick && nextBrick.y > currentBrick!.y) { - result.push(nextBrick.id); - currentId = nextBrick.id; - } else { - break; - } - } - return result; - }; - - const handleMouseDown = (e: React.MouseEvent, id: number) => { - const brick = bricks.find((b) => b.id === id); - if (brick) { - const svgRect = svgRef.current?.getBoundingClientRect(); - if (svgRect) { - setIsDragging(true); - setDraggedBrickId(id); - setDragOffset({ - x: e.clientX - svgRect.left - brick.x, - y: e.clientY - svgRect.top - brick.y, - }); - } - } - }; - - const handleMouseMove = (e: MouseEvent) => { - if (isDragging && draggedBrickId !== null) { - const svgRect = svgRef.current?.getBoundingClientRect(); - if (svgRect) { - const newX = e.clientX - svgRect.left - dragOffset.x; - const newY = e.clientY - svgRect.top - dragOffset.y; - const connectedBricks = findConnectedBricks(draggedBrickId); - setBricks((prevBricks) => { - return prevBricks.map((brick) => { - if (connectedBricks.includes(brick.id)) { - const index = connectedBricks.indexOf(brick.id); - return { - ...brick, - x: newX, - y: newY + index * 60, - }; - } - return brick; - }); - }); - } - } - }; - - const handleMouseUp = () => { - setIsDragging(false); - setDraggedBrickId(null); - }; - - useEffect(() => { - window.addEventListener('mousemove', handleMouseMove); - window.addEventListener('mouseup', handleMouseUp); - return () => { - window.removeEventListener('mousemove', handleMouseMove); - window.removeEventListener('mouseup', handleMouseUp); - }; - }, [isDragging, draggedBrickId]); - - const renderBrickPath = (type: string) => { - switch (type) { - case 'top': - return 'M0,0 h100 v50 h-80 l-20,10 v-60 z'; - case 'middle': - return 'M0,0 h80 l20,-10 v60 h-80 l-20,10 v-60 z'; - case 'bottom': - return 'M0,0 h80 l20,-10 v60 h-100 v-50 z'; - default: - return ''; - } - }; - - return ( -
- - {bricks.map((brick) => ( - handleMouseDown(e, brick.id)} - > - - - {brick.type === 'top' && } - {brick.type === 'middle' && ( - - )} - {brick.type === 'bottom' && } - - - ))} - -
- ); -}; - -export default SVGWithValues; diff --git a/modules/masonry/playground/src/main.tsx b/modules/masonry/playground/src/main.tsx deleted file mode 100644 index c018515c..00000000 --- a/modules/masonry/playground/src/main.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import App from './App'; - -ReactDOM.createRoot(document.getElementById('root')!).render( - - - , -); diff --git a/modules/masonry/playground/src/vite-env.d.ts b/modules/masonry/playground/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2..00000000 --- a/modules/masonry/playground/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/modules/masonry/playground/tsconfig.app.json b/modules/masonry/playground/tsconfig.app.json deleted file mode 100644 index d739292a..00000000 --- a/modules/masonry/playground/tsconfig.app.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"] -} diff --git a/modules/masonry/playground/tsconfig.json b/modules/masonry/playground/tsconfig.json deleted file mode 100644 index ea9d0cd8..00000000 --- a/modules/masonry/playground/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "files": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.node.json" - } - ] -} diff --git a/modules/masonry/playground/tsconfig.node.json b/modules/masonry/playground/tsconfig.node.json deleted file mode 100644 index 3afdd6e3..00000000 --- a/modules/masonry/playground/tsconfig.node.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true, - "strict": true, - "noEmit": true - }, - "include": ["vite.config.ts"] -} From d5122c8202ce0aafbead9c6764f2d7401bc00deb Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Sun, 25 Aug 2024 16:37:42 +0530 Subject: [PATCH 25/58] fix(masonry): Add nestLengthY in the constructor --- modules/masonry/playground/pages/workspace/data.ts | 2 +- modules/masonry/src/brick/design0/BrickBlock.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/masonry/playground/pages/workspace/data.ts b/modules/masonry/playground/pages/workspace/data.ts index f29c39f6..9f2bab01 100644 --- a/modules/masonry/playground/pages/workspace/data.ts +++ b/modules/masonry/playground/pages/workspace/data.ts @@ -210,4 +210,4 @@ export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ }, ], }, -]; \ No newline at end of file +]; diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index 969a7c6e..476b3ff0 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -32,6 +32,7 @@ export default class BrickBlock extends BrickModelBlock { scale: number; connectAbove: boolean; connectBelow: boolean; + nestLengthY: number; }) { super(params); const argsKeys = Object.keys(this._args); @@ -41,7 +42,7 @@ export default class BrickBlock extends BrickModelBlock { hasNotchInsTop: this._connectAbove, hasNotchInsBot: this._connectBelow, scale: this._scale, - nestLengthY: 30, + nestLengthY: params.nestLengthY, innerLengthX: 100, argHeights: Array.from({ length: argsKeys.length }, () => 17), }); From 9b58c14b51bc72ae754d0350f78c5574079dbaa1 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Tue, 27 Aug 2024 16:39:09 +0530 Subject: [PATCH 26/58] docs(masonry): fix lint errors --- .../docs/PRD/Masonry_Design_Document.md | 60 ++++++++++++------- modules/masonry/docs/PRD/PRD.md | 52 +++++++++++----- .../masonry/docs/architecture/Processes.md | 3 +- modules/masonry/docs/tech-spec/TechSpec.md | 18 +++--- modules/masonry/docs/tech-spec/Techspec.md | 17 +++--- modules/masonry/src/stack/README.md | 15 +++-- 6 files changed, 102 insertions(+), 63 deletions(-) diff --git a/modules/masonry/docs/PRD/Masonry_Design_Document.md b/modules/masonry/docs/PRD/Masonry_Design_Document.md index b73c2c2d..12f26331 100644 --- a/modules/masonry/docs/PRD/Masonry_Design_Document.md +++ b/modules/masonry/docs/PRD/Masonry_Design_Document.md @@ -1,18 +1,20 @@ - ---- - # Music Blocks v4 : Masonry Design Document ## Overview 1. **Short Description of the Product** - - The Masonry (previously called Project Builder) in Music Blocks v4 facilitates graphical brick-based music composition, offering various Brick types such as Start, Rhythm, Note, Pitch, and Instrument Bricks. Each brick represents a specific functionality, enabling users, especially children, to visually create music programs. The Masonry module simplifies the process of selecting and arranging bricks to generate music sequences. + - The Masonry (previously called Project Builder) in Music Blocks v4 facilitates graphical brick + -based music composition, offering various Brick types such as Start, Rhythm, Note, Pitch, and + Instrument Bricks. Each brick represents a specific functionality, enabling users, especially + children, to visually create music programs. The Masonry module simplifies the process of + selecting and arranging bricks to generate music sequences. 2. **Key Features** - Enhance the brick library with comprehensive functionalities and render the stack of bricks. - Implement collision detection and enhance the user interface for a seamless user experience. - Add text to bricks (SVGs) for customization and personalization. - - Introduce a palette feature, allowing for effortless music composition through intuitive drag-and-drop functionality. + - Introduce a palette feature, allowing for effortless music composition through intuitive + drag-and-drop functionality. - Integrate Music Blocks v4 with Masonry to streamline music program creation. - Address bugs and make overall improvements to enhance the tool's performance and usability. @@ -22,30 +24,42 @@ - Editing music sequences dynamically. 4. **Subsystems** - - Palette Subsystem: Manages the palette interface within Music Blocks, providing a selection of bricks for users to drag and drop into the workspace. - - Workspace Subsystem: Controls the workspace area where users can arrange bricks and create music compositions. - - Brick Stack Subsystem: Handles the creation and management of stacks of bricks within the workspace, allowing users to combine bricks to form musical sequences. - - Collision Detection Subsystem: Implements collision detection functionality within the workspace, ensuring that bricks interact appropriately to prevent overlapping or conflicting arrangements. + - Palette Subsystem: Manages the palette interface within Music Blocks, providing a selection of + bricks for users to drag and drop into the workspace. + - Workspace Subsystem: Controls the workspace area where users can arrange bricks and create + music compositions. + - Brick Stack Subsystem: Handles the creation and management of stacks of bricks within the + workspace, allowing users to combine bricks to form musical sequences. + - Collision Detection Subsystem: Implements collision detection functionality within the + workspace, ensuring that bricks interact appropriately to prevent overlapping or conflicting arrangements. 5. **Additional Functionality and Design** - Implementation of a MusicBlocks guide button at the top of the interface for user convenience. - - Integration of a collision detection UI inspired by the Brickly game by Google, enhancing user experience and interaction feedback. - - Optimization of the palette by combining similar types of bricks, reducing clutter and improving usability. - - Enhancement of the search functionality to facilitate easier navigation and selection of bricks within the palette. + - Integration of a collision detection UI inspired by the Brickly game by Google, enhancing user + experience and interaction feedback. + - Optimization of the palette by combining similar types of bricks, reducing clutter and + improving usability. + - Enhancement of the search functionality to facilitate easier navigation and selection of bricks + within the palette. 6. **Purpose** - - The purpose of this document is to outline the design and architecture of Masonry framework for Music Blocks v4 + - The purpose of this document is to outline the design and architecture of Masonry framework for + Music Blocks v4 7. **Scope** - - This document covers the technical details and design considerations of Music Blocks v4, including its features and subsystems. + - This document covers the technical details and design considerations of Music Blocks v4, + including its features and subsystems. 8. **Audience** - - The intended audience includes developers, contributors, and members involved in the development and maintenance of Music Blocks v4. + - The intended audience includes developers, contributors, and members involved in the development + and maintenance of Music Blocks v4. 9. **Definitions and Abbreviations** - - **Masonry:** The term used to describe the replication and enhancement of the functionality related to bricks from the palette, stack of bricks, and other related components of the project, aimed at improving their functionality and effectiveness. + - **Masonry:** The term used to describe the replication and enhancement of the functionality + related to bricks from the palette, stack of bricks, and other related components of the + project, aimed at improving their functionality and effectiveness. -[Screencast from 13-05-24 12:15:30 PM IST.webm](https://github.com/Karan-Palan/musicblocks-v4/assets/143683619/ae9df412-8b3a-4930-8635-ad89da828ba9) + [Screencast from 13-05-24 12:15:30 PM IST.webm](https://github.com/Karan-Palan/musicblocks-v4/assets/143683619/ae9df412-8b3a-4930-8635-ad89da828ba9) 10. **References** @@ -55,26 +69,28 @@ ## Requirements, Wiki Storages and Docs 1. **Requirements** - - Functional requirements: Dynamic editing, text addition, UI enhancements, palette feature, integration with Music Blocks v4 project. + - Functional requirements: Dynamic editing, text addition, UI enhancements, palette feature, + integration with Music Blocks v4 project. - Non-functional requirements: Performance, scalability, maintainability. 2. **Wiki Storages** - [Link to project documentation](https://github.com/sugarlabs/musicblocks/blob/master/guide/README.md) -4. **Docs and Responsible Entities** +3. **Docs and Responsible Entities** - Documentation maintained by project contributors. - Responsible entities: Project maintainers, contributors. -5. **Roles, Responsibilities, and Assumptions** +4. **Roles, Responsibilities, and Assumptions** - Roles: Developers, contributors, project maintainers. - Responsibilities: Implementing features, reviewing code, documenting changes. - - Assumptions: Basic understanding of React, JavaScript/TypeScript, and information about Music Blocks software. + - Assumptions: Basic understanding of React, JavaScript/TypeScript, and information about Music + Blocks software. ## Architecture and Requirements Diagram To be added -## Design Specification +### Design Specification #### 1. Workspace diff --git a/modules/masonry/docs/PRD/PRD.md b/modules/masonry/docs/PRD/PRD.md index 6c555ccd..b3b1154d 100644 --- a/modules/masonry/docs/PRD/PRD.md +++ b/modules/masonry/docs/PRD/PRD.md @@ -5,12 +5,16 @@ ### a. Brick Types -#### 1. Data Bricks: These serve as inputs for other bricks and come in two types: hardcoded and editable +#### 1.Data Bricks: These serve as inputs for other bricks and come in two types -- Hardcoded Data Brick: Fixed values that cannot be changed by the user. Examples include predefined note values, counts, etc. +#### hardcoded and editable + +- Hardcoded Data Brick: Fixed values that cannot be changed by the user. Examples include predefined + note values, counts, etc. ![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 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) @@ -22,7 +26,9 @@ ![example](../images/image-3.png) -#### 4. Block Bricks: Contain nesting, also execute something like the statement bricks. Takes 0 or more arguments +#### 4. Block Bricks: Contain nesting, also execute something like the statement + +#### bricks. Takes 0 or more arguments ![alt text](../images/image-14.png) @@ -31,19 +37,28 @@ - **Distinct Shapes**: Each brick type has a unique shape to differentiate its function visually. - **Colors**: 1. **Original Color**: Each brick has a unique color that represents its type. - 2. **Hover Color**: When a user hovers over a brick, it changes to a distinct color to indicate it is selectable. - 3. **Disconnected Color**: If a brick is not connected to the stack, it turns gray to indicate it is inactive. - 4. **Execution Color**: When a brick is executed, it changes to a darker shade of its original color to show that it has been activated. -- **Sprites**: Visual symbols that indicate specific functions or properties of the brick. Some bricks may have sprites (like the start brick), while others may not. + 2. **Hover Color**: When a user hovers over a brick, it changes to a distinct color to indicate + it is selectable. + 3. **Disconnected Color**: If a brick is not connected to the stack, it turns gray to indicate + it is inactive. + 4. **Execution Color**: When a brick is executed, it changes to a darker shade of its original + color to show that it has been activated. +- **Sprites**: Visual symbols that indicate specific functions or properties of the brick. Some +bricks may have sprites (like the start brick), while others may not. - **Labels**: 1. **Functionality Labels**: Text labels that indicate the function of the brick. - 2. **Argument Labels**: Text labels that indicate the arguments or parameters that need to be provided for the brick's function. + 2. **Argument Labels**: Text labels that indicate the arguments or parameters that need to be + provided for the brick's function. - **Input/Output Ports**: Connectors that visually represent where bricks can attach to each other. -- **Editable Text Labels/Fields**: Users can input data directly into the bricks, such as note names, durations, and numerical values. +- **Editable Text Labels/Fields**: Users can input data directly into the bricks, such as note names, + durations, and numerical values. - **Side Note:** If we want to implement a design similar to Scratch in the future, we can consider the following approach for connecting blocks: + **Side Note:** If we want to implement a design similar to Scratch in the future, we can consider +the following approach for connecting blocks: -- In Scratch, blocks are connected horizontally in a row for sequential execution. Each block has a tab at the bottom and a notch at the top, allowing them to snap together in a linear sequence. This design makes it clear which blocks will execute in order. +- In Scratch, blocks are connected horizontally in a row for sequential execution. Each block has a +tab at the bottom and a notch at the top, allowing them to snap together in a linear sequence. This +design makes it clear which blocks will execute in order. ### c. Brick Interactions @@ -59,8 +74,11 @@ ![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. + 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 chainingbricks + together. ![alt text](../images/image-8.png) @@ -120,7 +138,8 @@ - Searchbar design to be implemented: ![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. + 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. ### d. **Drag and Drop** @@ -130,7 +149,8 @@ ![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. + - While dragging a brick from the palette, the brick should temporarily disappear from the palette + until it is placed in the workspace. ## 4. Workspace diff --git a/modules/masonry/docs/architecture/Processes.md b/modules/masonry/docs/architecture/Processes.md index 89471f88..ffff0d69 100644 --- a/modules/masonry/docs/architecture/Processes.md +++ b/modules/masonry/docs/architecture/Processes.md @@ -39,7 +39,8 @@ 2. **Select Brick**: - Input: Brick Selection - Output: Selected Brick Properties to Workspace - (How this works is, The palette will have a loaded list of SVGs. When you drag one from palette onto the workspace, the brick will be created on the workspace whos id matches to the one in brick) + (How this works is, The palette will have a loaded list of SVGs. When you drag one from palette on + to the workspace, the brick will be created on the workspace whos id matches to the one in brick) ### Workspace diff --git a/modules/masonry/docs/tech-spec/TechSpec.md b/modules/masonry/docs/tech-spec/TechSpec.md index eb108ea3..45b4fcb6 100644 --- a/modules/masonry/docs/tech-spec/TechSpec.md +++ b/modules/masonry/docs/tech-spec/TechSpec.md @@ -1,10 +1,11 @@ # Masonry Framework Tech Spec -This tech spec outlines the implementation details for the Masonry Framework, a core component of the MusicBlocks V4 project built with React and TypeScript. +This tech spec outlines the implementation details for the Masonry Framework, a core component of +the MusicBlocks V4 project built with React and TypeScript. ## Project Structure -``` +```md ├── src │ ├── utils │ │ ├── dragAndDropUtils.ts @@ -64,7 +65,7 @@ This tech spec outlines the implementation details for the Masonry Framework, a ### Components -#### a) Brick +#### a Brick - **Brick.tsx:** - Properties: @@ -122,7 +123,8 @@ This tech spec outlines the implementation details for the Masonry Framework, a - `onInputChange`: Callback for input change event. - `onOutputChange`: Callback for output change event. - Functions: - - `render()`: Renders the expression brick component with its visual appearance and input/output ports. + - `render()`: Renders the expression brick component with its visual appearance and input/output + ports. - `handleInputChange()`: Handles the input change event for the expression brick. - `handleOutputChange()`: Handles the output change event for the expression brick. - **StatementBrick.tsx:** @@ -147,7 +149,7 @@ This tech spec outlines the implementation details for the Masonry Framework, a - `handleNesting()`: Handles the nesting logic for nested bricks. - `handleArguments()`: Manages the arguments for block bricks. -#### b) Palette +#### b Palette - **Palette.tsx:** - Properties: @@ -177,7 +179,7 @@ This tech spec outlines the implementation details for the Masonry Framework, a - `render()`: Renders the search component with its visual appearance and input field. - `handleSearch()`: Handles the search event for the search component. -#### c) Workspace +#### c Workspace - **Workspace.tsx:** - Properties: @@ -300,10 +302,6 @@ This tech spec outlines the implementation details for the Masonry Framework, a ### Models -Certainly! Below, I'll expand on the properties and functionalities of the `Brick` model to include bounding boxes (b-boxes) and related methods: - -### Models - - **Brick.ts:** - Properties: - `id`: Unique identifier for the brick. diff --git a/modules/masonry/docs/tech-spec/Techspec.md b/modules/masonry/docs/tech-spec/Techspec.md index 2bc99422..0250242a 100644 --- a/modules/masonry/docs/tech-spec/Techspec.md +++ b/modules/masonry/docs/tech-spec/Techspec.md @@ -2,7 +2,7 @@ ## Palette -#### Config (Inputs) +### Config (Inputs) - **Categories**: - **Attributes**: names, icons @@ -11,14 +11,14 @@ - **Bricks**: - **Attributes**: id, name, description, thumbnail, BBox -#### Search +### Search - **Search text**: - Substring match on name - Substring match on description - Minimum 3 characters -#### Drag & Drop +### Drag & Drop - **For a brick**: 1. Start drag operation @@ -35,7 +35,7 @@ ## Brick -#### Brick Types +### Brick Types - **Data Bricks** - Returns values @@ -54,7 +54,7 @@ - Connects with other statement/block types - Can take 0 or more arguments -#### Brick Appearance +### Brick Appearance - **Attributes**: - Color @@ -63,13 +63,13 @@ - Any labels (copied) - Any connectors -#### Brick Interactions +### Brick Interactions - **Inline Edit**: - Only applicable to Data bricks - Example: input text -#### Brick Structure Overview +### Brick Structure Overview - **Brick**: - Color @@ -92,7 +92,8 @@ - **Visual Feedback**: - Indicators show whether brick combinations are valid. - - Example: A green outline appears for a valid connection, while a red outline indicates an invalid connection. + - Example: A green outline appears for a valid connection, while a red outline indicates an + invalid connection. - **Error Indicators**: - Provide explanations for incompatible connections to help users troubleshoot. - Example: A reddish boundary and error message explain why the connection is invalid. diff --git a/modules/masonry/src/stack/README.md b/modules/masonry/src/stack/README.md index 83140316..3c208712 100644 --- a/modules/masonry/src/stack/README.md +++ b/modules/masonry/src/stack/README.md @@ -9,17 +9,18 @@ ### Methods -- `constructor(brick: BrickModelData | BrickModelExpression | BrickModelStatement |BrickModelBlock)`: Initializes a StackNode with the given brick and an empty children array. +- `constructor(brick: BrickModelData | BrickModelExpression | BrickModelStatement |BrickModelBlock)` +: Initializes a StackNode with the given brick and an empty children array. ## Stack -### Intrinsic +### - Intrinsic - `id`: unique ID for the stack instance - `rootNodes`: array of root StackNode instances - `_validationDisabled`: private flag to disable validation checks -### Methods +### - Methods - `constructor(id: string)`: Initializes a Stack with the given ID and an empty rootNodes array. - `validate(): boolean`: Validates the stack, returning `true` if there are no validation errors or @@ -45,15 +46,17 @@ at the specified position is valid for the given node. ## Factory Function -### Methods +### -Methods - `createStackNode(brick: BrickModelData | BrickModelExpression | BrickModelStatement | BrickModelBlock): IStackNode`: Creates a StackNode based on the given brick type. --- -**Note:** Intrinsic properties are set in the constructor and cannot be modified once instantiated. They are accessible using getters. +**Note:** Intrinsic properties are set in the constructor and cannot be modified once instantiated. +They are accessible using getters. -**Note:** Private methods are for internal use within the Stack class and should not be accessed directly from outside. +**Note:** Private methods are for internal use within the Stack class and should not be accessed +directly from outside. --- From 80c3a94a4dbcedd2f28e45de172faa185eed4db5 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Tue, 27 Aug 2024 19:17:17 +0530 Subject: [PATCH 27/58] style(masonry): add seperation line in BrickData.tsx --- modules/masonry/src/brick/design0/components/BrickData.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/masonry/src/brick/design0/components/BrickData.tsx b/modules/masonry/src/brick/design0/components/BrickData.tsx index 2cbfb716..206a6050 100644 --- a/modules/masonry/src/brick/design0/components/BrickData.tsx +++ b/modules/masonry/src/brick/design0/components/BrickData.tsx @@ -1,6 +1,8 @@ import type { JSX } from 'react'; import type { IBrickData, TBrickCoords } from '@/@types/brick'; +// ------------------------------------------------------------------------------------------------- + export default function ({ instance, coords = { x: 0, y: 0 }, From 6a4a44ff0d51c2d13b1006fd7f4cbf3fb736345a Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 2 Sep 2024 16:00:50 +0530 Subject: [PATCH 28/58] feat(masonry/playground): Create Brick components with movement props --- .../playground/pages/workspace/BrickBlock.tsx | 36 +++++++++++++++++++ .../playground/pages/workspace/BrickData.tsx | 36 +++++++++++++++++++ .../pages/workspace/BrickExpression.tsx | 34 ++++++++++++++++++ .../pages/workspace/BrickStatement.tsx | 34 ++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 modules/masonry/playground/pages/workspace/BrickBlock.tsx create mode 100644 modules/masonry/playground/pages/workspace/BrickData.tsx create mode 100644 modules/masonry/playground/pages/workspace/BrickExpression.tsx create mode 100644 modules/masonry/playground/pages/workspace/BrickStatement.tsx diff --git a/modules/masonry/playground/pages/workspace/BrickBlock.tsx b/modules/masonry/playground/pages/workspace/BrickBlock.tsx new file mode 100644 index 00000000..346ff48c --- /dev/null +++ b/modules/masonry/playground/pages/workspace/BrickBlock.tsx @@ -0,0 +1,36 @@ +import type { DOMAttributes, JSX } from 'react'; +import type { Brick } from '../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/playground/pages/workspace/BrickData.tsx b/modules/masonry/playground/pages/workspace/BrickData.tsx new file mode 100644 index 00000000..23b35742 --- /dev/null +++ b/modules/masonry/playground/pages/workspace/BrickData.tsx @@ -0,0 +1,36 @@ +import type { DOMAttributes, JSX } from 'react'; +import type { Brick } from './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/playground/pages/workspace/BrickExpression.tsx b/modules/masonry/playground/pages/workspace/BrickExpression.tsx new file mode 100644 index 00000000..50be6868 --- /dev/null +++ b/modules/masonry/playground/pages/workspace/BrickExpression.tsx @@ -0,0 +1,34 @@ +import type { DOMAttributes, JSX } from 'react'; +import type { Brick } from './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/playground/pages/workspace/BrickStatement.tsx b/modules/masonry/playground/pages/workspace/BrickStatement.tsx new file mode 100644 index 00000000..50be6868 --- /dev/null +++ b/modules/masonry/playground/pages/workspace/BrickStatement.tsx @@ -0,0 +1,34 @@ +import type { DOMAttributes, JSX } from 'react'; +import type { Brick } from './data'; + +export default function ({ + brickData, + moveProps, + coords, + color, +}: { + brickData: Brick; + moveProps: DOMAttributes; + coords: { x: number; y: number }; + color: string; +}): JSX.Element { + return ( + + + + ); +} From c4b54fec1007f4ad7962cf9e6bc770efd8643d42 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 2 Sep 2024 16:01:31 +0530 Subject: [PATCH 29/58] feat(masonry/playground): Add dummy stack data --- .../playground/pages/workspace/data.ts | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/modules/masonry/playground/pages/workspace/data.ts b/modules/masonry/playground/pages/workspace/data.ts index 9f2bab01..4acfd119 100644 --- a/modules/masonry/playground/pages/workspace/data.ts +++ b/modules/masonry/playground/pages/workspace/data.ts @@ -6,7 +6,7 @@ import { } from '@/brick'; import type { TBrickType, TBrickCoords, TBrickArgDataType } from '@/@types/brick'; -type InstanceMap = { +export type InstanceMap = { data: ModelBrickData; expression: ModelBrickExpression; statement: ModelBrickStatement; @@ -17,6 +17,8 @@ export type Brick = { id: string; type: TBrickType; instance: InstanceMap[TBrickType]; + surroundingBricks: { above: string; below: string }; + childBricks: string[]; coords: TBrickCoords; children?: Brick[]; }; @@ -35,9 +37,9 @@ export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ [string, { label: string; dataType: TBrickArgDataType; meta: unknown }] >((name) => [name, { label: name, dataType: 'any', meta: undefined }]), ), - colorBg: 'yellow', + colorBg: 'lightpink', colorFg: 'black', - outline: 'red', + outline: 'deeppink', scale: 2, glyph: '', connectAbove: true, @@ -45,6 +47,8 @@ export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ name: '', nestLengthY: 125, }), + surroundingBricks: { above: '', below: '' }, + childBricks: ['2', '3', '4', '5', '6'], coords: { x: 50, y: 50 }, children: [ { @@ -76,6 +80,8 @@ export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ connectBelow: true, name: '', }), + surroundingBricks: { above: '1', below: '3' }, + childBricks: [], coords: { x: 68, y: 92 }, }, { @@ -107,6 +113,8 @@ export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ connectBelow: true, name: '', }), + surroundingBricks: { above: '2', below: '4' }, + childBricks: [], coords: { x: 68, y: 134 }, }, { @@ -129,7 +137,7 @@ export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ { label: name, dataType: 'any', meta: undefined }, ]), ), - colorBg: 'orange', + colorBg: 'brown', colorFg: 'black', outline: 'grey', scale: 2, @@ -139,6 +147,8 @@ export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ name: '', nestLengthY: 17, }), + surroundingBricks: { above: '3', below: '6' }, + childBricks: ['5'], coords: { x: 68, y: 176 }, children: [ { @@ -161,9 +171,9 @@ export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ { label: name, dataType: 'any', meta: undefined }, ]), ), - colorBg: 'lightpink', + colorBg: 'orange', colorFg: 'black', - outline: 'deeppink', + outline: 'red', scale: 2, glyph: '', @@ -171,6 +181,8 @@ export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ connectBelow: true, name: '', }), + surroundingBricks: { above: '', below: '' }, + childBricks: [], coords: { x: 86, y: 218 }, }, ], @@ -204,6 +216,8 @@ export const WORKSPACES_DATA: { id: string; data: Brick[] }[] = [ connectBelow: true, name: '', }), + surroundingBricks: { above: '4', below: '' }, + childBricks: [], coords: { x: 68, y: 302 }, }, ], From d4d6a5c560638a6ed18b1e416747ca5148cc85d3 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 2 Sep 2024 16:04:19 +0530 Subject: [PATCH 30/58] feat(masonry/playground): Add Zustand State initialization --- .../pages/workspace/BricksCoordsStore.ts | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 modules/masonry/playground/pages/workspace/BricksCoordsStore.ts diff --git a/modules/masonry/playground/pages/workspace/BricksCoordsStore.ts b/modules/masonry/playground/pages/workspace/BricksCoordsStore.ts new file mode 100644 index 00000000..94d3b73e --- /dev/null +++ b/modules/masonry/playground/pages/workspace/BricksCoordsStore.ts @@ -0,0 +1,50 @@ +import { create } from 'zustand'; + +type CoordsState = { + allCoords: { + brickId: string; + coords: { + x: number; + y: number; + }; + }[]; + setCoords: (brickId: string, coords: { x: number; y: number }) => void; + getCoords: (brickId: string) => { x: number; y: number } | undefined; +}; + +const useBricksCoordsStore = create((set, get) => ({ + allCoords: [ + { brickId: '1', coords: { x: 50, y: 50 } }, + { brickId: '2', coords: { x: 68, y: 92 } }, + { brickId: '3', coords: { x: 68, y: 134 } }, + { brickId: '4', coords: { x: 68, y: 176 } }, + { brickId: '5', coords: { x: 86, y: 218 } }, + { brickId: '6', coords: { x: 68, y: 302 } }, + ], + setCoords: (brickId: string, coords: { x: number; y: number }) => + set( + (state: { + allCoords: { + brickId: string; + coords: { + x: number; + y: number; + }; + }[]; + }) => ({ + allCoords: state.allCoords.map((item) => + item.brickId === brickId ? { brickId, coords } : item, + ), + }), + ), + getCoords: (brickId: string) => + get().allCoords.find((item) => item.brickId === brickId)?.coords, +})); + +export const useBricksCoords = () => { + const allCoords = useBricksCoordsStore((state) => state.allCoords); + const setCoords = useBricksCoordsStore((state) => state.setCoords); + const getCoords = useBricksCoordsStore((state) => state.getCoords); + + return { allCoords, setCoords, getCoords }; +}; From e22225907df9340dcd8eeb5451d58c87ab0a0a47 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 2 Sep 2024 16:06:44 +0530 Subject: [PATCH 31/58] feat(masonry): Enable drag and drop for bricks and stack --- .../pages/workspace/BrickFactory.tsx | 87 +++++++++++++++++++ .../playground/pages/workspace/index.tsx | 40 ++------- 2 files changed, 93 insertions(+), 34 deletions(-) create mode 100644 modules/masonry/playground/pages/workspace/BrickFactory.tsx diff --git a/modules/masonry/playground/pages/workspace/BrickFactory.tsx b/modules/masonry/playground/pages/workspace/BrickFactory.tsx new file mode 100644 index 00000000..cc541a14 --- /dev/null +++ b/modules/masonry/playground/pages/workspace/BrickFactory.tsx @@ -0,0 +1,87 @@ +import { useState } from 'react'; +import { useMove } from 'react-aria'; +import BrickBlock from './BrickBlock'; +import BrickExpression from './BrickExpression'; +import BrickStatement from './BrickStatement'; +import BrickData from './BrickData'; +import { useBricksCoords } from './BricksCoordsStore'; +import { WORKSPACES_DATA } from './data'; +import type { Brick } from './data'; +import { getBelowBricksIds } from './utils'; + +const BrickFactory = ({ + brickData, + isPalette = false, + onDragEnd, +}: { + brickData: Brick; + isPalette?: boolean; + onDragEnd?: (brick: Brick) => void; +}) => { + const CONTAINER_SIZE_X = 2000; + const CONTAINER_SIZE_Y = 800; + const BRICK_HEIGHT = brickData.instance.bBoxBrick.extent.height; + const BRICK_WIDTH = brickData.instance.bBoxBrick.extent.width; + const { getCoords, setCoords } = useBricksCoords(); + const brickCoords = getCoords(brickData.id) || { x: 0, y: 0 }; + const [color, setColor] = useState(brickData.instance.colorBg as string); + + const clampX = (pos: number) => Math.min(Math.max(pos, 0), CONTAINER_SIZE_X - BRICK_WIDTH * 2); + const clampY = (pos: number) => Math.min(Math.max(pos, 0), CONTAINER_SIZE_Y - BRICK_HEIGHT * 2); + + const { moveProps } = useMove({ + onMoveStart(e) { + console.log(`move start with pointerType = ${e.pointerType}`); + setColor('white'); + }, + onMove(e) { + if (!isPalette) { + const newX = brickCoords.x + e.deltaX; + const newY = brickCoords.y + e.deltaY; + setCoords(brickData.id, { x: clampX(newX), y: clampY(newY) }); + + brickData.childBricks.forEach((childBrick) => { + const childBrickCoords = getCoords(childBrick)!; + setCoords(childBrick, { + x: childBrickCoords.x + e.deltaX, + y: childBrickCoords.y + e.deltaY, + }); + }); + + const belowBrickIds = getBelowBricksIds(WORKSPACES_DATA[0].data, brickData.id); + belowBrickIds.forEach((belowBrickId) => { + const belowBrickCoords = getCoords(belowBrickId)!; + setCoords(belowBrickId, { + x: belowBrickCoords.x + e.deltaX, + y: belowBrickCoords.y + e.deltaY, + }); + }); + } + }, + onMoveEnd(e) { + console.log(`move end with pointerType = ${e.pointerType}`); + setColor(brickData.instance.colorBg as string); + if (isPalette && onDragEnd) { + onDragEnd(brickData); + } + }, + }); + + const BrickComponent = { + data: BrickData, + expression: BrickExpression, + statement: BrickStatement, + block: BrickBlock, + }[brickData.type]; + + return ( + + ); +}; + +export default BrickFactory; diff --git a/modules/masonry/playground/pages/workspace/index.tsx b/modules/masonry/playground/pages/workspace/index.tsx index eca5b957..213afe30 100644 --- a/modules/masonry/playground/pages/workspace/index.tsx +++ b/modules/masonry/playground/pages/workspace/index.tsx @@ -1,40 +1,11 @@ -import { - BrickBlock, - BrickData, - BrickExpression, - BrickStatement, - ModelBrickBlock, - ModelBrickData, - ModelBrickExpression, - ModelBrickStatement, -} from '@/brick'; +import BrickFactory from './BrickFactory'; import { WORKSPACES_DATA } from './data'; -import type { TBrickCoords, TBrickType } from '@/@types/brick'; import type { Brick } from './data'; -function getBrick( - type: TBrickType, - instance: ModelBrickBlock | ModelBrickData | ModelBrickExpression | ModelBrickStatement, - coords: TBrickCoords, -) { - switch (type) { - case 'data': - return ; - case 'expression': - return ; - case 'statement': - return ; - case 'block': - return ; - default: - return <>; - } -} - function RenderBricks({ brickData }: { brickData: Brick }) { return ( <> - {getBrick(brickData.type, brickData.instance, brickData.coords)} + {brickData.children && brickData.children?.length > 0 && brickData.children.map((child) => )} @@ -44,14 +15,15 @@ function RenderBricks({ brickData }: { brickData: Brick }) { function WorkSpace() { return ( -
+
{WORKSPACES_DATA.map((workspace) => ( {workspace.data.map((brick) => { return ; From 2ee22f97c48282806c6a24ac4ed46518c3629d71 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 2 Sep 2024 16:08:34 +0530 Subject: [PATCH 32/58] feat(masonry): Create functionality to attach bricks below the top brick --- .../playground/pages/workspace/utils.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 modules/masonry/playground/pages/workspace/utils.ts diff --git a/modules/masonry/playground/pages/workspace/utils.ts b/modules/masonry/playground/pages/workspace/utils.ts new file mode 100644 index 00000000..8adb28d5 --- /dev/null +++ b/modules/masonry/playground/pages/workspace/utils.ts @@ -0,0 +1,23 @@ +import type { Brick } from './data'; + +export function getBelowBricksIds(arr: Brick[], item: string): string[] { + let result: string[] = []; + + function recursiveSearch(arr: Brick[], item: string) { + arr.forEach((element, index) => { + if (element.id === item) { + arr.slice(index + 1, arr.length).map((el) => { + result = result.concat(el.childBricks); + result = result.concat(el.id); + }); + return; + } + if (Array.isArray(element.children)) { + recursiveSearch(element.children, item); + } + }); + } + + recursiveSearch(arr, item); + return result; +} From 22e94e9218ada67d02fdd09f33e2730de189ccce Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 2 Sep 2024 16:51:48 +0530 Subject: [PATCH 33/58] fix(masonry): Fix import in BrickBlock --- modules/masonry/playground/pages/workspace/BrickBlock.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/masonry/playground/pages/workspace/BrickBlock.tsx b/modules/masonry/playground/pages/workspace/BrickBlock.tsx index 346ff48c..23b35742 100644 --- a/modules/masonry/playground/pages/workspace/BrickBlock.tsx +++ b/modules/masonry/playground/pages/workspace/BrickBlock.tsx @@ -1,5 +1,5 @@ import type { DOMAttributes, JSX } from 'react'; -import type { Brick } from '../pages/workspace/data'; +import type { Brick } from './data'; // ------------------------------------------------------------------------------------------------- From 4ca73f9ee6e93ea8d4044a2cc70e185618a4847b Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 2 Sep 2024 18:50:11 +0530 Subject: [PATCH 34/58] feat(masonry): Add id property in the final classes and use uuid to generate uuids in model.ts --- modules/masonry/src/brick/design0/BrickBlock.ts | 4 +++- modules/masonry/src/brick/design0/BrickData.ts | 4 +++- modules/masonry/src/brick/design0/BrickExpression.ts | 4 +++- modules/masonry/src/brick/design0/BrickStatement.ts | 4 +++- modules/masonry/src/brick/model.ts | 3 ++- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index 476b3ff0..52ac6b99 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -11,9 +11,11 @@ import { generatePath } from '../utils/path'; */ export default class BrickBlock extends BrickModelBlock { readonly _pathResults: ReturnType; + readonly id: string; constructor(params: { // intrinsic + id: string; name: string; label: string; glyph: string; @@ -25,7 +27,6 @@ export default class BrickBlock extends BrickModelBlock { meta: unknown; } >; - // style colorBg: TBrickColor; colorFg: TBrickColor; outline: TBrickColor; @@ -35,6 +36,7 @@ export default class BrickBlock extends BrickModelBlock { nestLengthY: number; }) { super(params); + this.id = params.id; const argsKeys = Object.keys(this._args); this._pathResults = generatePath({ hasNest: true, diff --git a/modules/masonry/src/brick/design0/BrickData.ts b/modules/masonry/src/brick/design0/BrickData.ts index f15d1911..4e745d50 100644 --- a/modules/masonry/src/brick/design0/BrickData.ts +++ b/modules/masonry/src/brick/design0/BrickData.ts @@ -11,9 +11,11 @@ import { generatePath } from '../utils/path'; */ export default class BrickData extends BrickModelData { readonly _pathResults: ReturnType; + readonly id: string; constructor(params: { // intrinsic + id: string; name: string; label: string; glyph: string; @@ -21,13 +23,13 @@ export default class BrickData extends BrickModelData { dynamic: boolean; value?: boolean | number | string; input?: 'boolean' | 'number' | 'string' | 'options'; - // style colorBg: TBrickColor; colorFg: TBrickColor; outline: TBrickColor; scale: number; }) { super(params); + this.id = params.id; this._pathResults = generatePath({ hasNest: false, hasNotchArg: true, diff --git a/modules/masonry/src/brick/design0/BrickExpression.ts b/modules/masonry/src/brick/design0/BrickExpression.ts index e039180a..9808124a 100644 --- a/modules/masonry/src/brick/design0/BrickExpression.ts +++ b/modules/masonry/src/brick/design0/BrickExpression.ts @@ -1,5 +1,4 @@ import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; - import { BrickModelExpression } from '../model'; import { generatePath } from '../utils/path'; @@ -11,9 +10,11 @@ import { generatePath } from '../utils/path'; */ export default class BrickExpression extends BrickModelExpression { readonly _pathResults: ReturnType; + readonly id: string; constructor(params: { // intrinsic + id: string; name: string; label: string; glyph: string; @@ -33,6 +34,7 @@ export default class BrickExpression extends BrickModelExpression { scale: number; }) { super(params); + this.id = params.id; const argsKeys = Object.keys(this._args); this._pathResults = generatePath({ hasNest: false, diff --git a/modules/masonry/src/brick/design0/BrickStatement.ts b/modules/masonry/src/brick/design0/BrickStatement.ts index c6e588fd..2f1ad577 100644 --- a/modules/masonry/src/brick/design0/BrickStatement.ts +++ b/modules/masonry/src/brick/design0/BrickStatement.ts @@ -1,5 +1,4 @@ import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; - import { BrickModelStatement } from '../model'; import { generatePath } from '../utils/path'; @@ -11,9 +10,11 @@ import { generatePath } from '../utils/path'; */ export default class BrickStatement extends BrickModelStatement { readonly _pathResults: ReturnType; + readonly id: string; constructor(params: { // intrinsic + id: string; name: string; label: string; glyph: string; @@ -34,6 +35,7 @@ export default class BrickStatement extends BrickModelStatement { connectBelow: boolean; }) { super(params); + this.id = params.id; const argsKeys = Object.keys(this._args); this._pathResults = generatePath({ hasNest: false, diff --git a/modules/masonry/src/brick/model.ts b/modules/masonry/src/brick/model.ts index cfadd568..bb85f655 100644 --- a/modules/masonry/src/brick/model.ts +++ b/modules/masonry/src/brick/model.ts @@ -1,3 +1,4 @@ +import { v4 as uuidv4 } from 'uuid'; import type { IBrick, IBrickArgument, @@ -49,7 +50,7 @@ abstract class BrickModel implements IBrick { outline: TBrickColor; scale: number; }) { - this._uuid = ''; + this._uuid = uuidv4(); this._name = params.name; this._kind = params.kind; this._type = params.type; From 67bb2e6c360930973e28257df2ae612236e15408 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 2 Sep 2024 18:50:40 +0530 Subject: [PATCH 35/58] feat(masonry): Create brick factory --- .../masonry/src/brick/design0/BrickFactory.ts | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 modules/masonry/src/brick/design0/BrickFactory.ts diff --git a/modules/masonry/src/brick/design0/BrickFactory.ts b/modules/masonry/src/brick/design0/BrickFactory.ts new file mode 100644 index 00000000..8ae36f81 --- /dev/null +++ b/modules/masonry/src/brick/design0/BrickFactory.ts @@ -0,0 +1,120 @@ +import { v4 as uuidv4 } from 'uuid'; +import type { TBrickArgDataType, TBrickColor } from '@/@types/brick'; +import BrickStatement from './BrickStatement'; +import BrickExpression from './BrickExpression'; +import BrickData from './BrickData'; +import BrickBlock from './BrickBlock'; + +/** + * Factory function to create a new BrickBlock instance. + * @param params - Parameters to initialize the BrickBlock. + * @returns A new instance of BrickBlock. + */ +export function createBrickBlock(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; + nestLengthY: number; +}): BrickBlock { + return new BrickBlock({ + id: uuidv4(), + ...params, + }); +} + +/** + * Factory function to create a new BrickData instance. + * @param params - Parameters to initialize the BrickData. + * @returns A new instance of BrickData. + */ +export function createBrickData(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; +}): BrickData { + return new BrickData({ + id: uuidv4(), + ...params, + }); +} + +/** + * Factory function to create a new BrickExpression instance. + * @param params - Parameters to initialize the BrickExpression. + * @returns A new instance of BrickExpression. + */ +export function createBrickExpression(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; +}): BrickExpression { + return new BrickExpression({ + id: uuidv4(), + ...params, + }); +} + +/** + * Factory function to create a new BrickStatement instance. + * @param params - Parameters to initialize the BrickStatement. + * @returns A new instance of BrickStatement. + */ +export function createBrickStatement(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; +}): BrickStatement { + return new BrickStatement({ + id: uuidv4(), + ...params, + }); +} From 1a72c64961d7df5df9ee69fd177f4810b983f947 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 2 Sep 2024 18:51:01 +0530 Subject: [PATCH 36/58] feat(masonry): Add tests for brick factory --- .../src/brick/design0/BrickFactory.spec.ts | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 modules/masonry/src/brick/design0/BrickFactory.spec.ts diff --git a/modules/masonry/src/brick/design0/BrickFactory.spec.ts b/modules/masonry/src/brick/design0/BrickFactory.spec.ts new file mode 100644 index 00000000..54406e05 --- /dev/null +++ b/modules/masonry/src/brick/design0/BrickFactory.spec.ts @@ -0,0 +1,89 @@ +import { + createBrickBlock, + createBrickData, + createBrickExpression, + createBrickStatement, +} from './BrickFactory'; +import BrickBlock from './BrickBlock'; +import BrickData from './BrickData'; +import BrickExpression from './BrickExpression'; +import BrickStatement from './BrickStatement'; + +describe('Factory Functions', () => { + test('createBrickBlock creates a BrickBlock instance', () => { + const block = createBrickBlock({ + name: 'Block', + label: 'Label', + glyph: 'Glyph', + args: {}, + colorBg: 'red', + colorFg: 'blue', + outline: 'black', + scale: 1, + connectAbove: true, + connectBelow: false, + nestLengthY: 20, + }); + + expect(block).toBeInstanceOf(BrickBlock); + expect(block.id).toBeDefined(); + expect(block.SVGpath).toBeDefined(); + }); + + test('createBrickData creates a BrickData instance', () => { + const data = createBrickData({ + name: 'Data', + label: 'Label', + glyph: 'Glyph', + dataType: 'string', + dynamic: true, + value: 'Test', + input: 'string', + colorBg: 'green', + colorFg: 'white', + outline: 'black', + scale: 1, + }); + + expect(data).toBeInstanceOf(BrickData); + expect(data.id).toBeDefined(); + expect(data.SVGpath).toBeDefined(); + }); + + test('createBrickExpression creates a BrickExpression instance', () => { + const expression = createBrickExpression({ + name: 'Expression', + label: 'Label', + glyph: 'Glyph', + dataType: 'number', + args: {}, + colorBg: 'blue', + colorFg: 'yellow', + outline: 'black', + scale: 1, + }); + + expect(expression).toBeInstanceOf(BrickExpression); + expect(expression.id).toBeDefined(); + expect(expression.SVGpath).toBeDefined(); + }); + + test('createBrickStatement creates a BrickStatement instance', () => { + const statement = createBrickStatement({ + name: 'Statement', + label: 'Label', + glyph: 'Glyph', + args: {}, + colorBg: 'orange', + colorFg: 'purple', + outline: 'black', + scale: 1, + connectAbove: true, + connectBelow: false, + }); + + expect(statement).toBeInstanceOf(BrickStatement); + expect(statement.id).toBeDefined(); + expect(statement.SVGpath).toBeDefined(); + }); +}); From 4fba69dd672fa2c7b5f1df1fece6a4f7f88c004b Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Mon, 2 Sep 2024 20:26:47 +0530 Subject: [PATCH 37/58] feat(masonry): Create Brick Warehouse module with functions to add, retrieve and delete instances --- modules/masonry/package.json | 6 +++ ...ckFactory.spec.ts => brickFactory.spec.ts} | 2 +- .../{BrickFactory.ts => brickFactory.ts} | 17 +++++++-- .../src/brick/design0/brickWarehouse.ts | 38 +++++++++++++++++++ 4 files changed, 58 insertions(+), 5 deletions(-) rename modules/masonry/src/brick/design0/{BrickFactory.spec.ts => brickFactory.spec.ts} (99%) rename modules/masonry/src/brick/design0/{BrickFactory.ts => brickFactory.ts} (87%) create mode 100644 modules/masonry/src/brick/design0/brickWarehouse.ts diff --git a/modules/masonry/package.json b/modules/masonry/package.json index a0548e9f..ff6aa6d5 100644 --- a/modules/masonry/package.json +++ b/modules/masonry/package.json @@ -11,5 +11,11 @@ "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", "playground": "vite playground --host --port 5601" + }, + "dependencies": { + "uuid": "^10.0.0" + }, + "devDependencies": { + "@types/uuid": "^10.0.0" } } diff --git a/modules/masonry/src/brick/design0/BrickFactory.spec.ts b/modules/masonry/src/brick/design0/brickFactory.spec.ts similarity index 99% rename from modules/masonry/src/brick/design0/BrickFactory.spec.ts rename to modules/masonry/src/brick/design0/brickFactory.spec.ts index 54406e05..e6fa6ae2 100644 --- a/modules/masonry/src/brick/design0/BrickFactory.spec.ts +++ b/modules/masonry/src/brick/design0/brickFactory.spec.ts @@ -3,7 +3,7 @@ import { createBrickData, createBrickExpression, createBrickStatement, -} from './BrickFactory'; +} from './brickFactory'; import BrickBlock from './BrickBlock'; import BrickData from './BrickData'; import BrickExpression from './BrickExpression'; diff --git a/modules/masonry/src/brick/design0/BrickFactory.ts b/modules/masonry/src/brick/design0/brickFactory.ts similarity index 87% rename from modules/masonry/src/brick/design0/BrickFactory.ts rename to modules/masonry/src/brick/design0/brickFactory.ts index 8ae36f81..814db3a7 100644 --- a/modules/masonry/src/brick/design0/BrickFactory.ts +++ b/modules/masonry/src/brick/design0/brickFactory.ts @@ -4,6 +4,7 @@ import BrickStatement from './BrickStatement'; import BrickExpression from './BrickExpression'; import BrickData from './BrickData'; import BrickBlock from './BrickBlock'; +import { addBrickToWarehouse } from './brickWarehouse'; /** * Factory function to create a new BrickBlock instance. @@ -30,10 +31,12 @@ export function createBrickBlock(params: { connectBelow: boolean; nestLengthY: number; }): BrickBlock { - return new BrickBlock({ + const brick = new BrickBlock({ id: uuidv4(), ...params, }); + addBrickToWarehouse(brick); + return brick; } /** @@ -54,10 +57,12 @@ export function createBrickData(params: { outline: TBrickColor; scale: number; }): BrickData { - return new BrickData({ + const brick = new BrickData({ id: uuidv4(), ...params, }); + addBrickToWarehouse(brick); + return brick; } /** @@ -83,10 +88,12 @@ export function createBrickExpression(params: { outline: TBrickColor; scale: number; }): BrickExpression { - return new BrickExpression({ + const brick = new BrickExpression({ id: uuidv4(), ...params, }); + addBrickToWarehouse(brick); + return brick; } /** @@ -113,8 +120,10 @@ export function createBrickStatement(params: { connectAbove: boolean; connectBelow: boolean; }): BrickStatement { - return new BrickStatement({ + const brick = new BrickStatement({ id: uuidv4(), ...params, }); + addBrickToWarehouse(brick); + return brick; } diff --git a/modules/masonry/src/brick/design0/brickWarehouse.ts b/modules/masonry/src/brick/design0/brickWarehouse.ts new file mode 100644 index 00000000..4ad3d132 --- /dev/null +++ b/modules/masonry/src/brick/design0/brickWarehouse.ts @@ -0,0 +1,38 @@ +import BrickStatement from './BrickStatement'; +import BrickExpression from './BrickExpression'; +import BrickData from './BrickData'; +import BrickBlock from './BrickBlock'; + +// Warehouse to manage brick instances +const brickWarehouse: Map = + new Map(); + +/** + * Adds a brick instance to the warehouse. + * @param brick - The brick instance to add. + */ +export function addBrickToWarehouse( + brick: BrickStatement | BrickExpression | BrickData | BrickBlock, +): void { + brickWarehouse.set(brick.id, brick); +} + +/** + * Retrieves a brick instance from the warehouse by its ID. + * @param id - The ID of the brick to retrieve. + * @returns The brick instance if found, otherwise undefined. + */ +export function getBrickFromWarehouse( + id: string, +): BrickStatement | BrickExpression | BrickData | BrickBlock | undefined { + return brickWarehouse.get(id); +} + +/** + * Deletes a brick instance from the warehouse by its ID. + * @param id - The ID of the brick to delete. + * @returns True if the brick was deleted, false if it was not found. + */ +export function deleteBrickFromWarehouse(id: string): boolean { + return brickWarehouse.delete(id); +} From dc630724d2faf1e1d8852b82b48bc0b41a2650d0 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Tue, 3 Sep 2024 15:00:58 +0530 Subject: [PATCH 38/58] feat(masonry): Add missing methods to BrickBlock.ts --- .../masonry/src/brick/design0/BrickBlock.ts | 138 +++++++++++++++--- 1 file changed, 119 insertions(+), 19 deletions(-) diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index 52ac6b99..bbc2c091 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -1,20 +1,20 @@ 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. + * Defines a block brick, extending `BrickModelBlock`. */ export default class BrickBlock extends BrickModelBlock { readonly _pathResults: ReturnType; readonly id: string; + readonly colorBgHighlight: TBrickColor; + readonly colorFgHighlight: TBrickColor; + public highlighted: boolean; + private _argExtents: Record = {}; + private _folded: boolean; constructor(params: { - // intrinsic id: string; name: string; label: string; @@ -22,31 +22,60 @@ export default class BrickBlock extends BrickModelBlock { args: Record< string, { - label: string; - dataType: TBrickArgDataType; - meta: unknown; + argId: string; + argLabel: string; + argTypeIncoming: TBrickArgDataType; } >; colorBg: TBrickColor; colorFg: TBrickColor; outline: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; scale: number; connectAbove: boolean; connectBelow: boolean; nestLengthY: number; + folded?: boolean; + highlighted?: boolean; }) { - super(params); + super({ + name: params.name, + label: params.label, + glyph: params.glyph, + args: Object.fromEntries( + Object.entries(params.args).map(([key, value]) => [ + key, + { + label: value.argLabel, + dataType: value.argTypeIncoming, + meta: {}, + }, + ]), + ), + colorBg: params.colorBg, + colorFg: params.colorFg, + outline: params.outline, + scale: params.scale, + connectAbove: params.connectAbove, + connectBelow: params.connectBelow, + }); + this.id = params.id; - const argsKeys = Object.keys(this._args); + this.colorBgHighlight = params.colorBgHighlight; + this.colorFgHighlight = params.colorFgHighlight; + this.highlighted = params.highlighted ?? false; + this._folded = params.folded ?? false; + this._pathResults = generatePath({ hasNest: true, hasNotchArg: false, - hasNotchInsTop: this._connectAbove, - hasNotchInsBot: this._connectBelow, - scale: this._scale, + hasNotchInsTop: params.connectAbove, + hasNotchInsBot: params.connectBelow, + scale: params.scale, nestLengthY: params.nestLengthY, innerLengthX: 100, - argHeights: Array.from({ length: argsKeys.length }, () => 17), + argHeights: Array(Object.keys(params.args).length).fill(17), }); } @@ -68,10 +97,8 @@ export default class BrickBlock extends BrickModelBlock { } public get bBoxArgs(): Record { - const argsKeys = Object.keys(this._args); const result: Record = {}; - - argsKeys.forEach((key, index) => { + Object.keys(this._args).forEach((key, index) => { result[key] = { extent: { width: this._pathResults.bBoxArgs.extent.width * this._scale, @@ -83,7 +110,6 @@ export default class BrickBlock extends BrickModelBlock { }, }; }); - return result; } @@ -138,4 +164,78 @@ export default class BrickBlock extends BrickModelBlock { }, }; } + + public get instantiationProperties(): { + id: string; + name: string; + label: string; + glyph: string; + args: Record< + string, + { + argId: string; + argLabel: string; + argTypeIncoming: TBrickArgDataType; + } + >; + colorBg: TBrickColor; + colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; + outline: TBrickColor; + scale: number; + connectAbove: boolean; + connectBelow: boolean; + highlighted: boolean; + argExtents: Record; + folded: boolean; + } { + return { + id: this.id, + name: this.name, + label: this.label, + glyph: this.glyph, + args: Object.fromEntries( + Object.entries(this._args).map(([key, value]) => [ + key, + { + argId: value.label, + argLabel: value.label, + argTypeIncoming: value.dataType, + }, + ]), + ), + colorBg: this.colorBg, + colorFg: this.colorFg, + colorBgHighlight: this.colorBgHighlight, + colorFgHighlight: this.colorFgHighlight, + outline: this.outline, + scale: this._scale, + connectAbove: this.connectAbove, + connectBelow: this.connectBelow, + highlighted: this.highlighted, + argExtents: this._argExtents, + folded: this._folded, + }; + } + + public get renderProperties(): { + boundingBox: { extent: TBrickExtent; coords: TBrickCoords }; + connectionPoints: { + Top: { extent: TBrickExtent; coords: TBrickCoords } | null; + Bottom: { extent: TBrickExtent; coords: TBrickCoords } | null; + TopInner: { extent: TBrickExtent; coords: TBrickCoords } | null; + ArgsIncoming: { extent: TBrickExtent; coords: TBrickCoords } | null; + }; + } { + return { + boundingBox: this.bBoxBrick, + connectionPoints: { + Top: this.bBoxNotchInsTop, + Bottom: this.bBoxNotchInsBot, + TopInner: this.bBoxNotchInsNestTop, + ArgsIncoming: this.bBoxNotchArg, + }, + }; + } } From 554b7a0c3039f788adf09f76280fcdcbe165d2fb Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Tue, 3 Sep 2024 15:46:50 +0530 Subject: [PATCH 39/58] feat(masonry): Add currentState function for react props in BrickBlock.ts --- .../masonry/src/brick/design0/BrickBlock.ts | 118 ++++++++++-------- 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index bbc2c091..44703f8c 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -19,14 +19,11 @@ export default class BrickBlock extends BrickModelBlock { name: string; label: string; glyph: string; - args: Record< - string, - { - argId: string; - argLabel: string; - argTypeIncoming: TBrickArgDataType; - } - >; + args: Array<{ + argId: string; + argLabel: string; + argTypeIncoming: TBrickArgDataType; + }>; colorBg: TBrickColor; colorFg: TBrickColor; outline: TBrickColor; @@ -43,15 +40,24 @@ export default class BrickBlock extends BrickModelBlock { name: params.name, label: params.label, glyph: params.glyph, - args: Object.fromEntries( - Object.entries(params.args).map(([key, value]) => [ - key, - { - label: value.argLabel, - dataType: value.argTypeIncoming, + // Convert array to object for super call + args: params.args.reduce( + (acc, arg) => { + acc[arg.argId] = { + label: arg.argLabel, + dataType: arg.argTypeIncoming, meta: {}, - }, - ]), + }; + return acc; + }, + {} as Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: Record; + } + >, ), colorBg: params.colorBg, colorFg: params.colorFg, @@ -75,7 +81,7 @@ export default class BrickBlock extends BrickModelBlock { scale: params.scale, nestLengthY: params.nestLengthY, innerLengthX: 100, - argHeights: Array(Object.keys(params.args).length).fill(17), + argHeights: Array(params.args.length).fill(17), }); } @@ -165,19 +171,36 @@ export default class BrickBlock extends BrickModelBlock { }; } - public get instantiationProperties(): { + public get calculatedProperties(): { + boundingBox: { extent: TBrickExtent; coords: TBrickCoords }; + connectionPoints: { + Top: { extent: TBrickExtent; coords: TBrickCoords } | null; + Bottom: { extent: TBrickExtent; coords: TBrickCoords } | null; + TopInner: { extent: TBrickExtent; coords: TBrickCoords } | null; + ArgsIncoming: { extent: TBrickExtent; coords: TBrickCoords } | null; + }; + } { + return { + boundingBox: this.bBoxBrick, + connectionPoints: { + Top: this.bBoxNotchInsTop, + Bottom: this.bBoxNotchInsBot, + TopInner: this.bBoxNotchInsNestTop, + ArgsIncoming: this.bBoxNotchArg, + }, + }; + } + + public get currentState(): { id: string; name: string; label: string; glyph: string; - args: Record< - string, - { - argId: string; - argLabel: string; - argTypeIncoming: TBrickArgDataType; - } - >; + args: Array<{ + argId: string; + argLabel: string; + argTypeIncoming: TBrickArgDataType; + }>; colorBg: TBrickColor; colorFg: TBrickColor; colorBgHighlight: TBrickColor; @@ -195,16 +218,11 @@ export default class BrickBlock extends BrickModelBlock { name: this.name, label: this.label, glyph: this.glyph, - args: Object.fromEntries( - Object.entries(this._args).map(([key, value]) => [ - key, - { - argId: value.label, - argLabel: value.label, - argTypeIncoming: value.dataType, - }, - ]), - ), + args: Object.entries(this._args).map(([key, value]) => ({ + argId: key, + argLabel: value.label, + argTypeIncoming: value.dataType, + })), colorBg: this.colorBg, colorFg: this.colorFg, colorBgHighlight: this.colorBgHighlight, @@ -219,23 +237,15 @@ export default class BrickBlock extends BrickModelBlock { }; } - public get renderProperties(): { - boundingBox: { extent: TBrickExtent; coords: TBrickCoords }; - connectionPoints: { - Top: { extent: TBrickExtent; coords: TBrickCoords } | null; - Bottom: { extent: TBrickExtent; coords: TBrickCoords } | null; - TopInner: { extent: TBrickExtent; coords: TBrickCoords } | null; - ArgsIncoming: { extent: TBrickExtent; coords: TBrickCoords } | null; - }; - } { - return { - boundingBox: this.bBoxBrick, - connectionPoints: { - Top: this.bBoxNotchInsTop, - Bottom: this.bBoxNotchInsBot, - TopInner: this.bBoxNotchInsNestTop, - ArgsIncoming: this.bBoxNotchArg, - }, - }; + public setHighlighted(value: boolean): void { + this.highlighted = value; + } + + public setFolded(value: boolean): void { + this._folded = value; + } + + public setArgExtent(argId: string, extent: { argLengthX?: number; argLengthY: number }): void { + this._argExtents[argId] = extent; } } From bf625057b13b0e15299a945466b976ae268140c4 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Tue, 3 Sep 2024 18:11:40 +0530 Subject: [PATCH 40/58] feat(masonry): Update Abstract classes with remaining properties --- modules/masonry/src/brick/model.ts | 143 ++++++++++++----------------- 1 file changed, 57 insertions(+), 86 deletions(-) diff --git a/modules/masonry/src/brick/model.ts b/modules/masonry/src/brick/model.ts index bb85f655..5a84dc29 100644 --- a/modules/masonry/src/brick/model.ts +++ b/modules/masonry/src/brick/model.ts @@ -1,4 +1,3 @@ -import { v4 as uuidv4 } from 'uuid'; import type { IBrick, IBrickArgument, @@ -23,34 +22,37 @@ import type { * Defines the data model of a generic brick. */ abstract class BrickModel implements IBrick { + // intrinsic protected _uuid: string; protected _name: string; protected _kind: TBrickKind; protected _type: TBrickType; protected _label: string; protected _glyph: string; - + // style protected _colorBg: TBrickColor; protected _colorFg: TBrickColor; + protected _colorBgHighlight: TBrickColor; + protected _colorFgHighlight: TBrickColor; protected _outline: TBrickColor; - protected _scale: number; public highlighted = false; + protected _scale: number; constructor(params: { - // intrinsic name: string; kind: TBrickKind; type: TBrickType; label: string; glyph: string; - // style colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; }) { - this._uuid = uuidv4(); + this._uuid = ''; this._name = params.name; this._kind = params.kind; this._type = params.type; @@ -58,52 +60,51 @@ abstract class BrickModel implements IBrick { this._glyph = params.glyph; this._colorBg = params.colorBg; this._colorFg = params.colorFg; + this._colorBgHighlight = params.colorBgHighlight; + this._colorFgHighlight = params.colorFgHighlight; this._outline = params.outline; this._scale = params.scale; } + // Getters public get uuid(): string { return this._uuid; } - public get name(): string { return this._name; } - public get kind(): TBrickKind { return this._kind; } - public get type(): TBrickType { return this._type; } - public get label(): string { return this._label; } - public get glyph(): string { return this._glyph; } - public get colorBg(): TBrickColor { return this._colorBg; } - public get colorFg(): TBrickColor { return this._colorFg; } - + public get colorBgHighlight(): TBrickColor { + return this._colorBgHighlight; + } + public get colorFgHighlight(): TBrickColor { + return this._colorFgHighlight; + } public get outline(): TBrickColor { return this._outline; } - public get scale(): number { return this._scale; } public abstract get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords }; - public abstract get SVGpath(): string; } @@ -114,6 +115,7 @@ abstract class BrickModel implements IBrick { */ abstract class BrickModelArgument extends BrickModel implements IBrickArgument { protected _dataType: TBrickArgDataType; + protected _argExtents: Map = new Map(); constructor(params: { // intrinsic @@ -125,17 +127,21 @@ abstract class BrickModelArgument extends BrickModel implements IBrickArgument { // style colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; }) { super({ ...params, kind: 'argument' }); - this._dataType = params.dataType; } public get dataType(): TBrickArgDataType { return this._dataType; } + public get argExtents(): Map { + return this._argExtents; + } public abstract get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords }; } @@ -146,17 +152,10 @@ abstract class BrickModelArgument extends BrickModel implements IBrickArgument { * Defines the data model of a generic instruction brick. */ abstract class BrickModelInstruction extends BrickModel implements IBrickInstruction { - protected _args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - + protected _args: Record; protected _connectAbove: boolean; protected _connectBelow: boolean; + protected _argExtents: Map = new Map(); constructor(params: { // intrinsic @@ -164,24 +163,18 @@ abstract class BrickModelInstruction extends BrickModel implements IBrickInstruc type: TBrickType; label: string; glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; + args: Record; // style colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; connectAbove: boolean; connectBelow: boolean; }) { super({ ...params, kind: 'instruction' }); - this._args = params.args; this._connectAbove = params.connectAbove; this._connectBelow = params.connectBelow; @@ -189,27 +182,22 @@ abstract class BrickModelInstruction extends BrickModel implements IBrickInstruc public get args(): Record< string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } + { label: string; dataType: TBrickArgDataType; meta: unknown } > { return this._args; } - public get connectAbove(): boolean { return this._connectAbove; } - public get connectBelow(): boolean { return this._connectBelow; } + public get argExtents(): Map { + return this._argExtents; + } public abstract get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords }; - public abstract get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords }; - public abstract get bBoxArgs(): Record; } @@ -226,7 +214,6 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric protected _input?: 'boolean' | 'number' | 'string' | 'options'; constructor(params: { - // intrinsic name: string; label: string; glyph: string; @@ -234,14 +221,14 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric dynamic: boolean; value?: boolean | number | string; input?: 'boolean' | 'number' | 'string' | 'options'; - // style colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; }) { super({ ...params, type: 'data' }); - this._dynamic = params.dynamic; this._value = params.value; this._input = params.input; @@ -250,11 +237,9 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric public get dynamic(): boolean { return this._dynamic; } - public get value(): boolean | number | string | undefined { return this._value; } - public get input(): 'boolean' | 'number' | 'string' | 'options' | undefined { return this._input; } @@ -266,47 +251,28 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric * Defines the data model of an expression brick. */ export abstract class BrickModelExpression extends BrickModelArgument implements IBrickExpression { - protected _args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; + protected _args: Record; constructor(params: { - // intrinsic name: string; label: string; glyph: string; dataType: TBrickArgDataType; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - // style + args: Record; colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; }) { super({ ...params, type: 'expression' }); - this._args = params.args; } public get args(): Record< string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } + { label: string; dataType: TBrickArgDataType; meta: unknown } > { return this._args; } @@ -321,21 +287,14 @@ export abstract class BrickModelExpression extends BrickModelArgument implements */ export abstract class BrickModelStatement extends BrickModelInstruction implements IBrickStatement { constructor(params: { - // intrinsic name: string; label: string; glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - // style + args: Record; colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; connectAbove: boolean; @@ -353,9 +312,9 @@ export abstract class BrickModelStatement extends BrickModelInstruction implemen export abstract class BrickModelBlock extends BrickModelInstruction implements IBrickBlock { public nestExtent: TBrickExtent = { width: 0, height: 0 }; public collapsed = false; + protected _folded = false; constructor(params: { - // intrinsic name: string; label: string; glyph: string; @@ -364,12 +323,17 @@ export abstract class BrickModelBlock extends BrickModelInstruction implements I { label: string; dataType: TBrickArgDataType; - meta: unknown; + meta: { + argId: string; + argLabel: string; + argTypeIncoming: string; + }; } >; - // style colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; connectAbove: boolean; @@ -378,5 +342,12 @@ export abstract class BrickModelBlock extends BrickModelInstruction implements I super({ ...params, type: 'block' }); } + public get folded(): boolean { + return this._folded; + } + public set folded(value: boolean) { + this._folded = value; + } + public abstract get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords }; } From ee77d01e9ec61552b77006a5f41abd2180bfd4b8 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Tue, 3 Sep 2024 19:07:40 +0530 Subject: [PATCH 41/58] build: update dependencies --- package-lock.json | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 501bc56a..daa6c170 100644 --- a/package-lock.json +++ b/package-lock.json @@ -169,7 +169,26 @@ } }, "modules/masonry": { - "version": "4.2.0" + "name": "@sugarlabs/mb4-module-masonry", + "version": "4.2.0", + "dependencies": { + "uuid": "^10.0.0" + }, + "devDependencies": { + "@types/uuid": "^10.0.0" + } + }, + "modules/masonry/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } }, "modules/menu": { "name": "@sugarlabs/mb4-module-menu", @@ -10215,6 +10234,12 @@ "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", "dev": true }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true + }, "node_modules/@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", From c12fc153e9793f7fd02d53e44df1deaa3d0234ea Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Tue, 3 Sep 2024 19:33:08 +0530 Subject: [PATCH 42/58] feat(masonry): Update abstract classes to support connection points --- modules/masonry/src/brick/model.ts | 55 ++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/modules/masonry/src/brick/model.ts b/modules/masonry/src/brick/model.ts index 5a84dc29..9b529f06 100644 --- a/modules/masonry/src/brick/model.ts +++ b/modules/masonry/src/brick/model.ts @@ -14,8 +14,6 @@ import type { TBrickType, } from '@/@types/brick'; -// -- protected classes ------------------------------------------------------------------------------ - /** * @abstract * @class @@ -39,6 +37,12 @@ abstract class BrickModel implements IBrick { public highlighted = false; protected _scale: number; + // Common connection points + protected _connectionPoints: { + ArgsIncoming?: TBrickCoords[]; + ArgsOutgoing?: TBrickCoords[]; + }; + constructor(params: { name: string; kind: TBrickKind; @@ -64,6 +68,7 @@ abstract class BrickModel implements IBrick { this._colorFgHighlight = params.colorFgHighlight; this._outline = params.outline; this._scale = params.scale; + this._connectionPoints = {}; } // Getters @@ -103,9 +108,17 @@ abstract class BrickModel implements IBrick { public get scale(): number { return this._scale; } + public get connectionPoints(): { + ArgsIncoming?: TBrickCoords[]; + ArgsOutgoing?: TBrickCoords[]; + } { + return this._connectionPoints; + } public abstract get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords }; public abstract get SVGpath(): string; + + protected abstract updateConnectionPoints(): void; } /** @@ -201,8 +214,6 @@ abstract class BrickModelInstruction extends BrickModel implements IBrickInstruc public abstract get bBoxArgs(): Record; } -// -- public classes ------------------------------------------------------------------------------- - /** * @abstract * @class @@ -232,6 +243,8 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric this._dynamic = params.dynamic; this._value = params.value; this._input = params.input; + this._connectionPoints.ArgsOutgoing = []; + this.updateConnectionPoints(); } public get dynamic(): boolean { @@ -243,6 +256,8 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric public get input(): 'boolean' | 'number' | 'string' | 'options' | undefined { return this._input; } + + protected abstract updateConnectionPoints(): void; } /** @@ -268,6 +283,9 @@ export abstract class BrickModelExpression extends BrickModelArgument implements }) { super({ ...params, type: 'expression' }); this._args = params.args; + this._connectionPoints.ArgsIncoming = []; + this._connectionPoints.ArgsOutgoing = []; + this.updateConnectionPoints(); } public get args(): Record< @@ -278,6 +296,8 @@ export abstract class BrickModelExpression extends BrickModelArgument implements } public abstract get bBoxArgs(): Record; + + protected abstract updateConnectionPoints(): void; } /** @@ -301,7 +321,11 @@ export abstract class BrickModelStatement extends BrickModelInstruction implemen connectBelow: boolean; }) { super({ ...params, type: 'statement' }); + this._connectionPoints.ArgsOutgoing = []; + this.updateConnectionPoints(); } + + protected abstract updateConnectionPoints(): void; } /** @@ -314,6 +338,12 @@ export abstract class BrickModelBlock extends BrickModelInstruction implements I public collapsed = false; protected _folded = false; + protected _connectionPointsBlock: { + Top: TBrickCoords[]; + Bottom: TBrickCoords[]; + TopInner: TBrickCoords[]; + }; + constructor(params: { name: string; label: string; @@ -340,14 +370,27 @@ export abstract class BrickModelBlock extends BrickModelInstruction implements I connectBelow: boolean; }) { super({ ...params, type: 'block' }); + this._connectionPointsBlock = { + Top: [], + Bottom: [], + TopInner: [], + }; + this._connectionPoints.ArgsIncoming = []; + this.updateConnectionPoints(); } public get folded(): boolean { return this._folded; } - public set folded(value: boolean) { - this._folded = value; + public get connectionPointsBlock(): { + Top: TBrickCoords[]; + Bottom: TBrickCoords[]; + TopInner: TBrickCoords[]; + } { + return this._connectionPointsBlock; } public abstract get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords }; + + protected abstract updateConnectionPoints(): void; } From efa2b886ca8db896f4aaaba710172b0d7256e4af Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Wed, 4 Sep 2024 19:38:36 +0530 Subject: [PATCH 43/58] fix(masonry): rename collapsed property to folded --- modules/masonry/src/@types/brick.d.ts | 2 +- modules/masonry/src/brick/model.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/masonry/src/@types/brick.d.ts b/modules/masonry/src/@types/brick.d.ts index 7a9e7e5b..ab410a51 100644 --- a/modules/masonry/src/@types/brick.d.ts +++ b/modules/masonry/src/@types/brick.d.ts @@ -208,7 +208,7 @@ export interface IBrickBlock extends IBrickInstruction, IBrickNotchInsNestTopSta /** combined bounding box of the instructions nested within the brick */ get nestExtent(): TBrickExtent; /** whether brick nesting is hidden */ - collapsed: boolean; + folded: boolean; /** Bounding box dimensions and coords of the top instruction notch of the nesting */ get bBoxNotchInsNestTop(): { diff --git a/modules/masonry/src/brick/model.ts b/modules/masonry/src/brick/model.ts index 9b529f06..ee0b4150 100644 --- a/modules/masonry/src/brick/model.ts +++ b/modules/masonry/src/brick/model.ts @@ -335,7 +335,6 @@ export abstract class BrickModelStatement extends BrickModelInstruction implemen */ export abstract class BrickModelBlock extends BrickModelInstruction implements IBrickBlock { public nestExtent: TBrickExtent = { width: 0, height: 0 }; - public collapsed = false; protected _folded = false; protected _connectionPointsBlock: { @@ -382,6 +381,7 @@ export abstract class BrickModelBlock extends BrickModelInstruction implements I public get folded(): boolean { return this._folded; } + public get connectionPointsBlock(): { Top: TBrickCoords[]; Bottom: TBrickCoords[]; From a385c3a6c31f50f70da7fd971bd5eb7ab1e3c4ad Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Thu, 5 Sep 2024 02:53:16 +0530 Subject: [PATCH 44/58] feat(masonry): Implement all the abstract classes and Final classes for BrickBlock and BrickData --- .../masonry/src/brick/design0/BrickBlock.ts | 194 +++++++----------- .../masonry/src/brick/design0/BrickData.ts | 58 +++++- modules/masonry/src/brick/model.ts | 17 +- 3 files changed, 142 insertions(+), 127 deletions(-) diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index 44703f8c..9b4fbab2 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -2,93 +2,66 @@ import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from import { BrickModelBlock } from '../model'; import { generatePath } from '../utils/path'; +// ------------------------------------------------------------------------------------------------- + /** - * Defines a block brick, extending `BrickModelBlock`. + * @class + * Final class that defines a block brick. */ export default class BrickBlock extends BrickModelBlock { readonly _pathResults: ReturnType; - readonly id: string; - readonly colorBgHighlight: TBrickColor; - readonly colorFgHighlight: TBrickColor; - public highlighted: boolean; - private _argExtents: Record = {}; - private _folded: boolean; constructor(params: { - id: string; + uuid: string; name: string; label: string; glyph: string; - args: Array<{ - argId: string; - argLabel: string; - argTypeIncoming: TBrickArgDataType; - }>; + args: Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: { + argId: string; + argLabel: string; + argTypeIncoming: string; + }; + } + >; colorBg: TBrickColor; colorFg: TBrickColor; - outline: TBrickColor; colorBgHighlight: TBrickColor; colorFgHighlight: TBrickColor; + outline: TBrickColor; scale: number; connectAbove: boolean; connectBelow: boolean; nestLengthY: number; - folded?: boolean; - highlighted?: boolean; + folded?: boolean; // Made folded optional }) { - super({ - name: params.name, - label: params.label, - glyph: params.glyph, - // Convert array to object for super call - args: params.args.reduce( - (acc, arg) => { - acc[arg.argId] = { - label: arg.argLabel, - dataType: arg.argTypeIncoming, - meta: {}, - }; - return acc; - }, - {} as Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: Record; - } - >, - ), - colorBg: params.colorBg, - colorFg: params.colorFg, - outline: params.outline, - scale: params.scale, - connectAbove: params.connectAbove, - connectBelow: params.connectBelow, - }); - - this.id = params.id; - this.colorBgHighlight = params.colorBgHighlight; - this.colorFgHighlight = params.colorFgHighlight; - this.highlighted = params.highlighted ?? false; - this._folded = params.folded ?? false; - + super(params); + const argsKeys = Object.keys(this._args); this._pathResults = generatePath({ hasNest: true, hasNotchArg: false, - hasNotchInsTop: params.connectAbove, - hasNotchInsBot: params.connectBelow, - scale: params.scale, + hasNotchInsTop: this._connectAbove, + hasNotchInsBot: this._connectBelow, + scale: this._scale, nestLengthY: params.nestLengthY, innerLengthX: 100, - argHeights: Array(params.args.length).fill(17), + argHeights: Array.from({ length: argsKeys.length }, () => 17), }); + + // Set folded to its initial state or default to false + this._folded = params.folded ?? false; } + // Getter for SVG path public get SVGpath(): string { return this._pathResults.path; } + // Getter for bounding box of the brick public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { return { extent: { @@ -102,9 +75,12 @@ export default class BrickBlock extends BrickModelBlock { }; } + // Getter for bounding boxes of the arguments public get bBoxArgs(): Record { + const argsKeys = Object.keys(this._args); const result: Record = {}; - Object.keys(this._args).forEach((key, index) => { + + argsKeys.forEach((key, index) => { result[key] = { extent: { width: this._pathResults.bBoxArgs.extent.width * this._scale, @@ -116,9 +92,11 @@ export default class BrickBlock extends BrickModelBlock { }, }; }); + return result; } + // Getter for bounding box of the argument notch public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { return { extent: { @@ -132,6 +110,7 @@ export default class BrickBlock extends BrickModelBlock { }; } + // Getter for bounding box of the top insertion notch public get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords } { return { extent: { @@ -145,6 +124,7 @@ export default class BrickBlock extends BrickModelBlock { }; } + // Getter for bounding box of the bottom insertion notch public get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords } { return { extent: { @@ -158,6 +138,7 @@ export default class BrickBlock extends BrickModelBlock { }; } + // Getter for bounding box of the nest insertion notch public get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords } { return { extent: { @@ -171,81 +152,64 @@ export default class BrickBlock extends BrickModelBlock { }; } - public get calculatedProperties(): { - boundingBox: { extent: TBrickExtent; coords: TBrickCoords }; - connectionPoints: { - Top: { extent: TBrickExtent; coords: TBrickCoords } | null; - Bottom: { extent: TBrickExtent; coords: TBrickCoords } | null; - TopInner: { extent: TBrickExtent; coords: TBrickCoords } | null; - ArgsIncoming: { extent: TBrickExtent; coords: TBrickCoords } | null; - }; - } { + // Method to return React props for the BrickBlock component + public getReactProps(): Record { return { - boundingBox: this.bBoxBrick, - connectionPoints: { - Top: this.bBoxNotchInsTop, - Bottom: this.bBoxNotchInsBot, - TopInner: this.bBoxNotchInsNestTop, - ArgsIncoming: this.bBoxNotchArg, - }, - }; - } - - public get currentState(): { - id: string; - name: string; - label: string; - glyph: string; - args: Array<{ - argId: string; - argLabel: string; - argTypeIncoming: TBrickArgDataType; - }>; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; - connectAbove: boolean; - connectBelow: boolean; - highlighted: boolean; - argExtents: Record; - folded: boolean; - } { - return { - id: this.id, + uuid: this.uuid, name: this.name, label: this.label, glyph: this.glyph, - args: Object.entries(this._args).map(([key, value]) => ({ - argId: key, - argLabel: value.label, - argTypeIncoming: value.dataType, - })), + args: this.args, colorBg: this.colorBg, colorFg: this.colorFg, colorBgHighlight: this.colorBgHighlight, colorFgHighlight: this.colorFgHighlight, outline: this.outline, - scale: this._scale, + scale: this.scale, connectAbove: this.connectAbove, connectBelow: this.connectBelow, + folded: this.folded, highlighted: this.highlighted, - argExtents: this._argExtents, - folded: this._folded, }; } - public setHighlighted(value: boolean): void { - this.highlighted = value; + // Setters for properties that can change at runtime + public setArgs( + args: Record< + string, + { + label: string; + dataType: TBrickArgDataType; + meta: { argId: string; argLabel: string; argTypeIncoming: string }; + } + >, + ): void { + this._args = args; + this.updateConnectionPoints(); + } + + public setConnectAbove(connectAbove: boolean): void { + this._connectAbove = connectAbove; + } + + public setConnectBelow(connectBelow: boolean): void { + this._connectBelow = connectBelow; + } + + public setFolded(folded?: boolean): void { + // Set folded as optional + this._folded = folded ?? false; // Default to false if not provided } - public setFolded(value: boolean): void { - this._folded = value; + public setHighlighted(highlighted: boolean): void { + this.highlighted = highlighted; } - public setArgExtent(argId: string, extent: { argLengthX?: number; argLengthY: number }): void { - this._argExtents[argId] = extent; + // Method to update connection points based on current state + protected updateConnectionPoints(): void { + // Update the connection points for the top, bottom, and nest of the block + this._connectionPointsBlock.Top = this.connectAbove ? [{ x: 0, y: 0 }] : []; + this._connectionPointsBlock.Bottom = this.connectBelow ? [{ x: 0, y: 0 }] : []; + this._connectionPointsBlock.TopInner = this.folded ? [] : [{ x: 0, y: 0 }]; } } diff --git a/modules/masonry/src/brick/design0/BrickData.ts b/modules/masonry/src/brick/design0/BrickData.ts index 4e745d50..e9ab6178 100644 --- a/modules/masonry/src/brick/design0/BrickData.ts +++ b/modules/masonry/src/brick/design0/BrickData.ts @@ -1,5 +1,4 @@ import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; - import { BrickModelData } from '../model'; import { generatePath } from '../utils/path'; @@ -11,11 +10,10 @@ import { generatePath } from '../utils/path'; */ export default class BrickData extends BrickModelData { readonly _pathResults: ReturnType; - readonly id: string; constructor(params: { - // intrinsic - id: string; + //intrinsic + uuid: string; name: string; label: string; glyph: string; @@ -23,13 +21,15 @@ export default class BrickData extends BrickModelData { dynamic: boolean; value?: boolean | number | string; input?: 'boolean' | 'number' | 'string' | 'options'; + //style colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; }) { super(params); - this.id = params.id; this._pathResults = generatePath({ hasNest: false, hasNotchArg: true, @@ -41,10 +41,12 @@ export default class BrickData extends BrickModelData { }); } + // Getter for SVG path public get SVGpath(): string { return this._pathResults.path; } + // Getter for bounding box of the brick public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { const { extent, coords } = this._pathResults.bBoxBrick; return { @@ -59,6 +61,7 @@ export default class BrickData extends BrickModelData { }; } + // Getter for bounding box of the argument notch public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { const { extent, coords } = this._pathResults.bBoxNotchArg!; return { @@ -72,4 +75,49 @@ export default class BrickData extends BrickModelData { }, }; } + + // Method to return React props for the BrickData component + public renderProps(): Record { + return { + uuid: this.uuid, + name: this.name, + label: this.label, + glyph: this.glyph, + dataType: this.dataType, + dynamic: this.dynamic, + value: this.value, + input: this.input, + colorBg: this.colorBg, + colorFg: this.colorFg, + colorBgHighlight: this.colorBgHighlight, + colorFgHighlight: this.colorFgHighlight, + outline: this.outline, + scale: this.scale, + highlighted: this.highlighted, + }; + } + + // Setters for properties that can change at runtime + public setDynamic(dynamic: boolean): void { + this._dynamic = dynamic; + this.updateConnectionPoints(); + } + + public setValue(value: boolean | number | string): void { + this._value = value; + } + + public setInput(input: 'boolean' | 'number' | 'string' | 'options'): void { + this._input = input; + } + + public setHighlighted(highlighted: boolean): void { + this.highlighted = highlighted; + } + + // Method to update connection points based on current state + protected updateConnectionPoints(): void { + // Update connection points logic if needed + this._connectionPoints.ArgsOutgoing = this._dynamic ? [{ x: 0, y: 0 }] : []; + } } diff --git a/modules/masonry/src/brick/model.ts b/modules/masonry/src/brick/model.ts index ee0b4150..636ec414 100644 --- a/modules/masonry/src/brick/model.ts +++ b/modules/masonry/src/brick/model.ts @@ -44,6 +44,7 @@ abstract class BrickModel implements IBrick { }; constructor(params: { + uuid: string; name: string; kind: TBrickKind; type: TBrickType; @@ -56,7 +57,7 @@ abstract class BrickModel implements IBrick { outline: TBrickColor; scale: number; }) { - this._uuid = ''; + this._uuid = params.uuid; this._name = params.name; this._kind = params.kind; this._type = params.type; @@ -131,13 +132,12 @@ abstract class BrickModelArgument extends BrickModel implements IBrickArgument { protected _argExtents: Map = new Map(); constructor(params: { - // intrinsic - name: string; + uuid: string; // Added uuid + name: string; // Added name type: TBrickType; label: string; glyph: string; dataType: TBrickArgDataType; - // style colorBg: TBrickColor; colorFg: TBrickColor; colorBgHighlight: TBrickColor; @@ -171,13 +171,12 @@ abstract class BrickModelInstruction extends BrickModel implements IBrickInstruc protected _argExtents: Map = new Map(); constructor(params: { - // intrinsic - name: string; + uuid: string; // Added uuid + name: string; // Added name type: TBrickType; label: string; glyph: string; args: Record; - // style colorBg: TBrickColor; colorFg: TBrickColor; colorBgHighlight: TBrickColor; @@ -225,6 +224,7 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric protected _input?: 'boolean' | 'number' | 'string' | 'options'; constructor(params: { + uuid: string; // Added uuid name: string; label: string; glyph: string; @@ -269,6 +269,7 @@ export abstract class BrickModelExpression extends BrickModelArgument implements protected _args: Record; constructor(params: { + uuid: string; // Added uuid name: string; label: string; glyph: string; @@ -307,6 +308,7 @@ export abstract class BrickModelExpression extends BrickModelArgument implements */ export abstract class BrickModelStatement extends BrickModelInstruction implements IBrickStatement { constructor(params: { + uuid: string; // Added uuid name: string; label: string; glyph: string; @@ -344,6 +346,7 @@ export abstract class BrickModelBlock extends BrickModelInstruction implements I }; constructor(params: { + uuid: string; // Added uuid name: string; label: string; glyph: string; From f52f067a4f5ff1c00a64ad5e56c1afee7b8d43a7 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Thu, 5 Sep 2024 02:54:23 +0530 Subject: [PATCH 45/58] feat(masonry): Implement final classes for BrickExpression and BrickStatement --- .../src/brick/design0/BrickExpression.ts | 55 +++++++++++++++-- .../src/brick/design0/BrickStatement.ts | 60 +++++++++++++++++-- 2 files changed, 105 insertions(+), 10 deletions(-) diff --git a/modules/masonry/src/brick/design0/BrickExpression.ts b/modules/masonry/src/brick/design0/BrickExpression.ts index 9808124a..e6a58dc7 100644 --- a/modules/masonry/src/brick/design0/BrickExpression.ts +++ b/modules/masonry/src/brick/design0/BrickExpression.ts @@ -10,11 +10,9 @@ import { generatePath } from '../utils/path'; */ export default class BrickExpression extends BrickModelExpression { readonly _pathResults: ReturnType; - readonly id: string; constructor(params: { - // intrinsic - id: string; + uuid: string; name: string; label: string; glyph: string; @@ -27,14 +25,14 @@ export default class BrickExpression extends BrickModelExpression { meta: unknown; } >; - // style colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; }) { super(params); - this.id = params.id; const argsKeys = Object.keys(this._args); this._pathResults = generatePath({ hasNest: false, @@ -47,10 +45,12 @@ export default class BrickExpression extends BrickModelExpression { }); } + // Getter for SVG path public get SVGpath(): string { return this._pathResults.path; } + // Getter for bounding box of the brick public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { return { extent: { @@ -64,6 +64,7 @@ export default class BrickExpression extends BrickModelExpression { }; } + // Getter for bounding boxes of the arguments public get bBoxArgs(): Record { const argsKeys = Object.keys(this._args); const result: Record = {}; @@ -84,6 +85,7 @@ export default class BrickExpression extends BrickModelExpression { return result; } + // Getter for bounding box of the argument notch public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { return { extent: { @@ -96,4 +98,47 @@ export default class BrickExpression extends BrickModelExpression { }, }; } + + // Method to return React props for the BrickExpression component + public getReactProps(): Record { + return { + uuid: this.uuid, + name: this.name, + label: this.label, + glyph: this.glyph, + dataType: this.dataType, + args: this.args, + colorBg: this.colorBg, + colorFg: this.colorFg, + colorBgHighlight: this.colorBgHighlight, + colorFgHighlight: this.colorFgHighlight, + outline: this.outline, + scale: this.scale, + highlighted: this.highlighted, + }; + } + + // Setters for properties that can change at runtime + public setArgs( + args: Record, + ): void { + this._args = args; + this.updateConnectionPoints(); + } + + public setHighlighted(highlighted: boolean): void { + this.highlighted = highlighted; + } + + // Method to update connection points based on current state + protected updateConnectionPoints(): void { + this._connectionPoints.ArgsIncoming = Object.keys(this._args).map((_, index) => ({ + x: 0, + y: index * 20, + })); + this._connectionPoints.ArgsOutgoing = Object.keys(this._args).map((_, index) => ({ + x: 0, + y: index * 20, + })); + } } diff --git a/modules/masonry/src/brick/design0/BrickStatement.ts b/modules/masonry/src/brick/design0/BrickStatement.ts index 2f1ad577..bf815ec7 100644 --- a/modules/masonry/src/brick/design0/BrickStatement.ts +++ b/modules/masonry/src/brick/design0/BrickStatement.ts @@ -10,11 +10,9 @@ import { generatePath } from '../utils/path'; */ export default class BrickStatement extends BrickModelStatement { readonly _pathResults: ReturnType; - readonly id: string; constructor(params: { - // intrinsic - id: string; + uuid: string; name: string; label: string; glyph: string; @@ -26,16 +24,16 @@ export default class BrickStatement extends BrickModelStatement { meta: unknown; } >; - // style colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; connectAbove: boolean; connectBelow: boolean; }) { super(params); - this.id = params.id; const argsKeys = Object.keys(this._args); this._pathResults = generatePath({ hasNest: false, @@ -48,10 +46,12 @@ export default class BrickStatement extends BrickModelStatement { }); } + // Getter for SVG path public get SVGpath(): string { return this._pathResults.path; } + // Getter for bounding box of the brick public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { return { extent: { @@ -65,6 +65,7 @@ export default class BrickStatement extends BrickModelStatement { }; } + // Getter for bounding boxes of the arguments public get bBoxArgs(): Record { const argsKeys = Object.keys(this._args); const result: Record = {}; @@ -85,6 +86,7 @@ export default class BrickStatement extends BrickModelStatement { return result; } + // Getter for bounding box of the top insertion notch public get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords } { return { extent: { @@ -98,6 +100,7 @@ export default class BrickStatement extends BrickModelStatement { }; } + // Getter for bounding box of the bottom insertion notch public get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords } { return { extent: { @@ -110,4 +113,51 @@ export default class BrickStatement extends BrickModelStatement { }, }; } + + // Method to return React props for the BrickStatement component + public getReactProps(): Record { + return { + uuid: this.uuid, + name: this.name, + label: this.label, + glyph: this.glyph, + args: this.args, + colorBg: this.colorBg, + colorFg: this.colorFg, + colorBgHighlight: this.colorBgHighlight, + colorFgHighlight: this.colorFgHighlight, + outline: this.outline, + scale: this.scale, + connectAbove: this.connectAbove, + connectBelow: this.connectBelow, + highlighted: this.highlighted, + }; + } + + // Setters for properties that can change at runtime + public setArgs( + args: Record, + ): void { + this._args = args; + this.updateConnectionPoints(); + } + + public setConnectAbove(connectAbove: boolean): void { + this._connectAbove = connectAbove; + } + + public setConnectBelow(connectBelow: boolean): void { + this._connectBelow = connectBelow; + } + + public setHighlighted(highlighted: boolean): void { + this.highlighted = highlighted; + } + + // Method to update connection points based on current state + protected updateConnectionPoints(): void { + // Update the connection points for the top and bottom of the brick + this._connectionPoints.ArgsIncoming = this.connectAbove ? [{ x: 0, y: 0 }] : []; + this._connectionPoints.ArgsOutgoing = this.connectBelow ? [{ x: 0, y: 0 }] : []; + } } From e7d681d075b3b49f0feb09c587027abf5f305f59 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Thu, 5 Sep 2024 03:13:24 +0530 Subject: [PATCH 46/58] feat(masonry): Update brickFactory and its tests according to the updated classes --- .../src/brick/design0/brickFactory.spec.ts | 94 +++++++++++++++++-- .../masonry/src/brick/design0/brickFactory.ts | 61 ++++++++++-- 2 files changed, 142 insertions(+), 13 deletions(-) diff --git a/modules/masonry/src/brick/design0/brickFactory.spec.ts b/modules/masonry/src/brick/design0/brickFactory.spec.ts index e6fa6ae2..9bfd40a7 100644 --- a/modules/masonry/src/brick/design0/brickFactory.spec.ts +++ b/modules/masonry/src/brick/design0/brickFactory.spec.ts @@ -3,6 +3,9 @@ import { createBrickData, createBrickExpression, createBrickStatement, + addBrickToWarehouse, + getBrickFromWarehouse, + deleteBrickFromWarehouse, } from './brickFactory'; import BrickBlock from './BrickBlock'; import BrickData from './BrickData'; @@ -15,9 +18,17 @@ describe('Factory Functions', () => { name: 'Block', label: 'Label', glyph: 'Glyph', - args: {}, + args: { + arg1: { + label: 'Arg1', + dataType: 'string', + meta: { argId: '1', argLabel: 'Arg1', argTypeIncoming: 'string' }, + }, + }, colorBg: 'red', colorFg: 'blue', + colorBgHighlight: 'pink', + colorFgHighlight: 'cyan', outline: 'black', scale: 1, connectAbove: true, @@ -26,8 +37,9 @@ describe('Factory Functions', () => { }); expect(block).toBeInstanceOf(BrickBlock); - expect(block.id).toBeDefined(); + expect(block.uuid).toBeDefined(); expect(block.SVGpath).toBeDefined(); + expect(block.args).toHaveProperty('arg1'); }); test('createBrickData creates a BrickData instance', () => { @@ -41,13 +53,16 @@ describe('Factory Functions', () => { input: 'string', colorBg: 'green', colorFg: 'white', + colorBgHighlight: 'lightgreen', + colorFgHighlight: 'lightgrey', outline: 'black', scale: 1, }); expect(data).toBeInstanceOf(BrickData); - expect(data.id).toBeDefined(); + expect(data.uuid).toBeDefined(); expect(data.SVGpath).toBeDefined(); + expect(data.value).toBe('Test'); }); test('createBrickExpression creates a BrickExpression instance', () => { @@ -56,16 +71,21 @@ describe('Factory Functions', () => { label: 'Label', glyph: 'Glyph', dataType: 'number', - args: {}, + args: { + arg1: { label: 'Arg1', dataType: 'number', meta: {} }, + }, colorBg: 'blue', colorFg: 'yellow', + colorBgHighlight: 'lightblue', + colorFgHighlight: 'lightyellow', outline: 'black', scale: 1, }); expect(expression).toBeInstanceOf(BrickExpression); - expect(expression.id).toBeDefined(); + expect(expression.uuid).toBeDefined(); expect(expression.SVGpath).toBeDefined(); + expect(expression.args).toHaveProperty('arg1'); }); test('createBrickStatement creates a BrickStatement instance', () => { @@ -73,9 +93,13 @@ describe('Factory Functions', () => { name: 'Statement', label: 'Label', glyph: 'Glyph', - args: {}, + args: { + arg1: { label: 'Arg1', dataType: 'boolean', meta: {} }, + }, colorBg: 'orange', colorFg: 'purple', + colorBgHighlight: 'lightorange', + colorFgHighlight: 'lightpurple', outline: 'black', scale: 1, connectAbove: true, @@ -83,7 +107,63 @@ describe('Factory Functions', () => { }); expect(statement).toBeInstanceOf(BrickStatement); - expect(statement.id).toBeDefined(); + expect(statement.uuid).toBeDefined(); expect(statement.SVGpath).toBeDefined(); + expect(statement.args).toHaveProperty('arg1'); + }); +}); + +describe('Warehouse Module', () => { + test('addBrickToWarehouse adds a Brick instance to the warehouse', () => { + const brick = createBrickBlock({ + name: 'Block', + label: 'Label', + glyph: 'Glyph', + args: { + arg1: { + label: 'Arg1', + dataType: 'string', + meta: { argId: '1', argLabel: 'Arg1', argTypeIncoming: 'string' }, + }, + }, + colorBg: 'red', + colorFg: 'blue', + colorBgHighlight: 'pink', + colorFgHighlight: 'cyan', + outline: 'black', + scale: 1, + connectAbove: true, + connectBelow: false, + nestLengthY: 20, + }); + + addBrickToWarehouse(brick); + const storedBrick = getBrickFromWarehouse(brick.uuid); + expect(storedBrick).toBe(brick); + }); + + test('deleteBrickFromWarehouse removes a Brick instance from the warehouse', () => { + const brick = createBrickStatement({ + name: 'Statement', + label: 'Label', + glyph: 'Glyph', + args: { + arg1: { label: 'Arg1', dataType: 'boolean', meta: {} }, + }, + colorBg: 'orange', + colorFg: 'purple', + colorBgHighlight: 'lightorange', + colorFgHighlight: 'lightpurple', + outline: 'black', + scale: 1, + connectAbove: true, + connectBelow: false, + }); + + addBrickToWarehouse(brick); + const isDeleted = deleteBrickFromWarehouse(brick.uuid); + const storedBrick = getBrickFromWarehouse(brick.uuid); + expect(isDeleted).toBe(true); + expect(storedBrick).toBeUndefined(); }); }); diff --git a/modules/masonry/src/brick/design0/brickFactory.ts b/modules/masonry/src/brick/design0/brickFactory.ts index 814db3a7..73a22cff 100644 --- a/modules/masonry/src/brick/design0/brickFactory.ts +++ b/modules/masonry/src/brick/design0/brickFactory.ts @@ -4,7 +4,40 @@ import BrickStatement from './BrickStatement'; import BrickExpression from './BrickExpression'; import BrickData from './BrickData'; import BrickBlock from './BrickBlock'; -import { addBrickToWarehouse } from './brickWarehouse'; + +// Warehouse to manage brick instances +const brickWarehouse: Map = + new Map(); + +/** + * Adds a brick instance to the warehouse. + * @param brick - The brick instance to add. + */ +function addBrickToWarehouse( + brick: BrickStatement | BrickExpression | BrickData | BrickBlock, +): void { + brickWarehouse.set(brick.uuid, brick); +} + +/** + * Retrieves a brick instance from the warehouse by its ID. + * @param id - The ID of the brick to retrieve. + * @returns The brick instance if found, otherwise undefined. + */ +function getBrickFromWarehouse( + id: string, +): BrickStatement | BrickExpression | BrickData | BrickBlock | undefined { + return brickWarehouse.get(id); +} + +/** + * Deletes a brick instance from the warehouse by its ID. + * @param id - The ID of the brick to delete. + * @returns True if the brick was deleted, false if it was not found. + */ +function deleteBrickFromWarehouse(id: string): boolean { + return brickWarehouse.delete(id); +} /** * Factory function to create a new BrickBlock instance. @@ -20,19 +53,26 @@ export function createBrickBlock(params: { { label: string; dataType: TBrickArgDataType; - meta: unknown; + meta: { + argId: string; + argLabel: string; + argTypeIncoming: string; + }; } >; colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; connectAbove: boolean; connectBelow: boolean; nestLengthY: number; + folded?: boolean; }): BrickBlock { const brick = new BrickBlock({ - id: uuidv4(), + uuid: uuidv4(), ...params, }); addBrickToWarehouse(brick); @@ -54,11 +94,13 @@ export function createBrickData(params: { input?: 'boolean' | 'number' | 'string' | 'options'; colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; }): BrickData { const brick = new BrickData({ - id: uuidv4(), + uuid: uuidv4(), ...params, }); addBrickToWarehouse(brick); @@ -85,11 +127,13 @@ export function createBrickExpression(params: { >; colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; }): BrickExpression { const brick = new BrickExpression({ - id: uuidv4(), + uuid: uuidv4(), ...params, }); addBrickToWarehouse(brick); @@ -115,15 +159,20 @@ export function createBrickStatement(params: { >; colorBg: TBrickColor; colorFg: TBrickColor; + colorBgHighlight: TBrickColor; + colorFgHighlight: TBrickColor; outline: TBrickColor; scale: number; connectAbove: boolean; connectBelow: boolean; }): BrickStatement { const brick = new BrickStatement({ - id: uuidv4(), + uuid: uuidv4(), ...params, }); addBrickToWarehouse(brick); return brick; } + +// Exporting warehouse functions for external use +export { addBrickToWarehouse, getBrickFromWarehouse, deleteBrickFromWarehouse }; From b559510b902cbd2f89917353fc249a1dafdf00b2 Mon Sep 17 00:00:00 2001 From: Anindya Kundu Date: Thu, 5 Sep 2024 12:17:00 +0530 Subject: [PATCH 47/58] docs(masonry): rename specification folders --- .../Masonry_Design_Document.md | 0 .../{PRD => functional-specification}/PRD.md | 0 modules/masonry/docs/tech-spec/TechSpec.md | 383 ------------------ .../Techspec.md | 0 4 files changed, 383 deletions(-) rename modules/masonry/docs/{PRD => functional-specification}/Masonry_Design_Document.md (100%) rename modules/masonry/docs/{PRD => functional-specification}/PRD.md (100%) delete mode 100644 modules/masonry/docs/tech-spec/TechSpec.md rename modules/masonry/docs/{tech-spec => technical-specification}/Techspec.md (100%) diff --git a/modules/masonry/docs/PRD/Masonry_Design_Document.md b/modules/masonry/docs/functional-specification/Masonry_Design_Document.md similarity index 100% rename from modules/masonry/docs/PRD/Masonry_Design_Document.md rename to modules/masonry/docs/functional-specification/Masonry_Design_Document.md diff --git a/modules/masonry/docs/PRD/PRD.md b/modules/masonry/docs/functional-specification/PRD.md similarity index 100% rename from modules/masonry/docs/PRD/PRD.md rename to modules/masonry/docs/functional-specification/PRD.md diff --git a/modules/masonry/docs/tech-spec/TechSpec.md b/modules/masonry/docs/tech-spec/TechSpec.md deleted file mode 100644 index 45b4fcb6..00000000 --- a/modules/masonry/docs/tech-spec/TechSpec.md +++ /dev/null @@ -1,383 +0,0 @@ -# Masonry Framework Tech Spec - -This tech spec outlines the implementation details for the Masonry Framework, a core component of -the MusicBlocks V4 project built with React and TypeScript. - -## Project Structure - -```md -├── src -│ ├── utils -│ │ ├── dragAndDropUtils.ts -│ │ ├── validationUtils.ts -│ │ ├── dataUtils.ts -│ │ ├── quadtreeUtils.ts -│ │ └──... -│ ├── components -│ │ ├── brick -│ │ │ ├── Brick.tsx -│ │ │ ├── BrickInput.tsx -│ │ │ ├── BrickOutput.tsx -│ │ │ ├── DataBrick.tsx -│ │ │ ├── ExpressionBrick.tsx -│ │ │ ├── StatementBrick.tsx -│ │ │ ├── BlockBrick.tsx -│ │ │ └──... -│ │ ├── palette -│ │ │ ├── Palette.tsx -│ │ │ ├── PaletteCategory.tsx -│ │ │ └── PaletteSearch.tsx -│ │ ├── workspace -│ │ │ ├── Workspace.tsx -│ │ │ ├── WorkspaceGrid.tsx -│ │ │ ├── WorkspaceToolbar.tsx -│ │ │ └──... -│ ├── hooks -│ │ ├── useBrick.ts -│ │ ├── useStack.ts -│ │ ├── useWorkspace.ts -│ │ └──... -│ ├── models -│ │ ├── Brick.ts -│ │ ├── Stack.ts -│ │ ├── Workspace.ts -│ │ └──... -│ ├── services -│ │ ├── BrickService.ts -│ │ ├── StackService.ts -│ │ ├── WorkspaceService.ts -│ │ ├── QuadtreeService.ts -│ │ ├── ErrorHandlingService.ts -│ │ └──... -│ ├── App.tsx -│ └── index.tsx -├──... -``` - -## Dependencies - -- React -- TypeScript -- React-aria (for drag-and-drop functionality) -- ... (other relevant libraries) - -## Description - -### Components - -#### a Brick - -- **Brick.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onDragStart`: Callback for drag start event. - - `onDragOver`: Callback for drag-over event. - - `onDrop`: Callback for drop event. - - `onDragEnd`: Callback for drag end event. - - `onClick`: Callback for click event. - - `onDoubleClick`: Callback for double-click event. - - `onContextMenu`: Callback for context menu event. - - `onInputChange`: Callback for input change event. - - `onOutputChange`: Callback for output change event. - - Functions: - - `render()`: Renders the brick component with its visual appearance and input/output ports. - - `handleDragStart()`: Handles the drag start event for the brick. - - `handleDragOver()`: Handles the drag-over event for the brick. - - `handleDrop()`: Handles the drop event for the brick. - - `handleDragEnd()`: Handles the drag end event for the brick. - - `handleClick()`: Handles the click event for the brick. - - `handleDoubleClick()`: Handles the double-click event for the brick. - - `handleContextMenu()`: Handles the context menu event for the brick. - - `handleInputChange()`: Handles the input change event for the brick. - - `handleOutputChange()`: Handles the output change event for the brick. -- **BrickInput.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onConnect`: Callback for connect event. - - `onDisconnect`: Callback for disconnect event. - - Functions: - - `render()`: Renders the input port of the brick. - - `handleConnect()`: Handles the connect event for the input port. - - `handleDisconnect()`: Handles the disconnect event for the input port. -- **BrickOutput.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onConnect`: Callback for connect event. - - `onDisconnect`: Callback for disconnect event. - - Functions: - - `render()`: Renders the output port of the brick. - - `handleConnect()`: Handles the connect event for the output port. - - `handleDisconnect()`: Handles the disconnect event for the output port. -- **DataBrick.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onInputChange`: Callback for input change event. - - `onOutputChange`: Callback for output change event. - - Functions: - - `render()`: Renders the data brick component with its visual appearance and input/output ports. - - `handleInputChange()`: Handles the input change event for the data brick. - - `handleOutputChange()`: Handles the output change event for the data brick. -- **ExpressionBrick.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onInputChange`: Callback for input change event. - - `onOutputChange`: Callback for output change event. - - Functions: - - `render()`: Renders the expression brick component with its visual appearance and input/output - ports. - - `handleInputChange()`: Handles the input change event for the expression brick. - - `handleOutputChange()`: Handles the output change event for the expression brick. -- **StatementBrick.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onInputChange`: Callback for input change event. - - `onOutputChange`: Callback for output change event. - - Functions: - - `render()`: Renders the statement brick component with its visual appearance and input/output ports. - - `handleInputChange()`: Handles the input change event for the statement brick. - - `handleOutputChange()`: Handles the output change event for the statement brick. -- **BlockBrick.tsx:** - - Properties: - - `brick`: The brick model instance. - - `onInputChange`: Callback for input change event. - - `onOutputChange`: Callback for output change event. - - `children`: An array of nested brick instances. - - Functions: - - `render()`: Renders the block brick component with its visual appearance and input/output ports. - - `handleInputChange()`: Handles the input change event for the block brick. - - `handleOutputChange()`: Handles the output change event for the block brick. - - `handleNesting()`: Handles the nesting logic for nested bricks. - - `handleArguments()`: Manages the arguments for block bricks. - -#### b Palette - -- **Palette.tsx:** - - Properties: - - `bricks`: An array of brick model instances. - - `onDragStart`: Callback for drag start event. - - `onDragOver`: Callback for drag-over event. - - `onDrop`: Callback for drop event. - - `onSearch`: Callback for search event. - - `searchQuery`: The current search query. - - Functions: - - `render()`: Renders the palette component with its visual appearance and categories. - - `handleDragStart()`: Handles the drag start event for the palette. - - `handleDragOver()`: Handles the drag-over event for the palette. - - `handleDrop()`: Handles the drop event for the palette. - - `handleSearch()`: Handles the search event for the palette. -- **PaletteCategory.tsx:** - - Properties: - - `category`: The category model instance. - - `bricks`: An array of brick model instances. - - Functions: - - `render()`: Renders the category component with its visual appearance and bricks. -- **PaletteSearch.tsx:** - - Properties: - - `searchQuery`: The current search query. - - `onSearch`: Callback for search event. - - Functions: - - `render()`: Renders the search component with its visual appearance and input field. - - `handleSearch()`: Handles the search event for the search component. - -#### c Workspace - -- **Workspace.tsx:** - - Properties: - - `workspace`: The workspace model instance. - - `onBrickAdd`: Callback for brick add event. - - `onBrickRemove`: Callback for brick remove event. - - `onBrickConnect`: Callback for brick connect event. - - `onBrickDisconnect`: Callback for brick disconnect event. - - `onBrickMove`: Callback for brick move event. - - `onBrickResize`: Callback for brick resize event. - - `onBrickRotate`: Callback for brick rotate event. - - `onUndo`: Callback for undo event. - - `onRedo`: Callback for redo event. - - Functions: - - `render()`: Renders the workspace component with its visual appearance and bricks. - - `handleBrickAdd()`: Handles the brick add event for the workspace. - - `handleBrickRemove()`: Handles the brick remove event for the workspace. - - `handleBrickConnect()`: Handles the brick connect event for the workspace. - - `handleBrickDisconnect()`: Handles the brick disconnect event for the workspace. - - `handleBrickMove()`: Handles the brick move event for the workspace. - - `handleBrickResize()`: Handles the brick resize event for the workspace. - - `handleBrickRotate()`: Handles the brick rotate event for the workspace. - - `handleUndo()`: Handles the undo event for the workspace. - - `handleRedo()`: Handles the redo event for the workspace. -- **WorkspaceGrid.tsx:** - - Properties: - - `gridSize`: The size of the grid. - - `onGridClick`: Callback for grid click event. - - Functions: - - `render()`: Renders the grid component with its visual appearance and grid lines. - - `handleGridClick()`: Handles the grid click event for the grid component. -- **WorkspaceToolbar.tsx:** - - Properties: - - `onUndo`: Callback for undo event. - - `onRedo`: Callback for redo event. - - Functions: - - `render()`: Renders the toolbar component with its visual appearance and buttons. - - `handleUndo()`: Handles the undo event for the toolbar. - - `handleRedo()`: Handles the redo event for the toolbar. - -### Utilities - -- **dragAndDropUtils.ts:** - - Functions: - - `handleDragStart()`: Handles the drag start event for draggable elements. - - `handleDragOver()`: Handles the drag-over event for draggable elements. - - `handleDrop()`: Handles the drop event for draggable elements. - - `handleDragEnd()`: Handles the drag end event for draggable elements. -- **validationUtils.ts:** - - Functions: - - `validateBrickConnection()`: Validates the connection between two bricks. - - `validateBrickPosition()`: Validates the position of a brick in the workspace. - - `validateBrickData()`: Validates the data within a brick. -- **dataUtils.ts:** - - Functions: - - `saveWorkspace()`: Saves the workspace state to local storage or server. - - `loadWorkspace()`: Loads the workspace state from local storage or server. - - `exportWorkspace()`: Exports the workspace state to a file. - - `importWorkspace()`: Imports the workspace state from a file. -- **quadtreeUtils.ts:** - - Functions: - - `insertBrick()`: Inserts a brick into the quadtree for spatial indexing. - - `removeBrick()`: Removes a brick from the quadtree. - - `updateBrick()`: Updates the position of a brick in the quadtree. - - `findNearbyBricks()`: Finds nearby bricks within a certain radius using the quadtree. - -### Hooks - -**a) useBrick:** - -- A hook for managing a single brick. -- Provides an instance of the `Brick` model. -- Handles updating the brick's properties and arguments. -- Properties: - - `brick`: The brick model instance. - - `setBrick()`: A function to update the brick instance. -- Functions: - - `useEffect()`: A React hook for handling side effects. - - `fetchBrick()`: A function to fetch the brick data from the server. - - `useCallback()`: A React hook for memoizing functions. - - `handleInputChange()`: A function to handle input changes for the brick. - - `handleOutputChange()`: A function to handle output changes for the brick. - -**b) useStack:** - -- A hook for managing a stack of bricks. -- Provides an instance of the `Stack` model. -- Handles updating the stack's bricks and connections. -- Properties: - - `stack`: The stack model instance. - - `setStack()`: A function to update the stack instance. -- Functions: - - `useEffect()`: A React hook for handling side effects. - - `fetchStack()`: A function to fetch the stack data from the server. - - `useCallback()`: A React hook for memoizing functions. - - `handleBrickAdd()`: A function to handle adding a brick to the stack. - - `handleBrickRemove()`: A function to handle removing a brick from the stack. - - `handleBrickConnect()`: A function to handle connecting bricks in the stack. - - `handleBrickDisconnect()`: A function to handle disconnecting bricks in the stack. - -**c) useWorkspace:** - -- A hook for managing the workspace state. -- Provides an instance of the `Workspace` model. -- Handles updating the workspace's bricks, connections, and layout. -- Properties: - - `workspace`: The workspace model instance. - - `setWorkspace()`: A function to update the workspace instance. -- Functions: - - `useEffect()`: A React hook for handling side effects. - - `fetchWorkspace()`: A function to fetch the workspace data from the server. - - `useCallback()`: A React hook for memoizing functions. - - `handleBrickAdd()`: A function to handle adding a brick to the workspace. - - `handleBrickRemove()`: A function to handle removing a brick from the workspace. - - `handleBrickConnect()`: A function to handle connecting bricks in the workspace. - - `handleBrickDisconnect()`: A function to handle disconnecting bricks in the workspace. - - `handleBrickMove()`: A function to handle moving a brick in the workspace. - - `handleBrickResize()`: A function to handle resizing a brick in the workspace. - - `handleBrickRotate()`: A function to handle rotating a brick in the workspace. - -### Models - -- **Brick.ts:** - - Properties: - - `id`: Unique identifier for the brick. - - `type`: Type of the brick (data, expression, statement, block). - - `position`: Position of the brick in the workspace. - - `inputs`: Array of input ports for the brick. - - `outputs`: Array of output ports for the brick. - - `data`: Data associated with the brick. - - `boundingBox`: Bounding box coordinates of the brick for collision detection and spatial indexing. - - Functions: - - `connect()`: Connects the brick to another brick. - - `disconnect()`: Disconnects the brick from another brick. - - `move()`: Moves the brick to a new position. - - `resize()`: Resizes the brick. - - `rotate()`: Rotates the brick. - - `calculateBoundingBox()`: Calculates the bounding box of the brick based on its size and position. - - `checkCollision()`: Checks for collision with other bricks or boundaries. - - `handleCollision()`: Handles collision events by adjusting the position or behavior of the brick. - - `updatePosition()`: Updates the position of the brick based on collision resolution or user interaction. - -- **Stack.ts:** - - Properties: - - `id`: Unique identifier for the stack. - - `bricks`: Array of bricks in the stack. - - Functions: - - `addBrick()`: Adds a brick to the stack. - - `removeBrick()`: Removes a brick from the stack. - - `connectBricks()`: Connects two bricks in the stack. - - `disconnectBricks()`: Disconnects two bricks in the stack. -- **Workspace.ts:** - - Properties: - - `id`: Unique identifier for the workspace. - - `stacks`: Array of stacks in the workspace. - - `gridSize`: Size of the grid in the workspace. - - `zoomLevel`: Zoom level of the workspace. - - Functions: - - `addStack()`: Adds a stack to the workspace. - - `removeStack()`: Removes a stack from the workspace. - - `findBrickById()`: Finds a brick in the workspace by its ID. - - `validateWorkspace()`: Validates the workspace state. - - `exportWorkspace()`: Exports the workspace state to a file. - - `importWorkspace()`: Imports the workspace state from a file. - -### Services - -- **BrickService.ts:** - - Functions: - - `createBrick()`: Creates a new brick instance. - - `deleteBrick()`: Deletes a brick instance. - - `updateBrick()`: Updates a brick instance. - - `findBrickById()`: Finds a brick instance by its ID. -- **StackService.ts:** - - Functions: - - `createStack()`: Creates a new stack instance. - - `deleteStack()`: Deletes a stack instance. - - `updateStack()`: Updates a stack instance. - - `findStackById()`: Finds a stack instance by its ID. -- **WorkspaceService.ts:** - - Functions: - - `createWorkspace()`: Creates a new workspace instance. - - `deleteWorkspace()`: Deletes a workspace instance. - - `updateWorkspace()`: Updates a workspace instance. - - `findWorkspaceById()`: Finds a workspace instance by its ID. -- **QuadtreeService.ts:** - - Functions: - - `insertBrick()`: Inserts a brick into the quadtree for spatial indexing. - - `removeBrick()`: Removes a brick from the quadtree. - - `updateBrick()`: Updates the position of a brick in the quadtree. - - `findNearbyBricks()`: Finds nearby bricks within a certain radius using the quadtree. -- **ErrorHandlingService.ts:** - - Functions: - - `handleError()`: Handles errors and exceptions in the application. - - `logError()`: Logs errors to a server or local storage. - -## Testing - -- Write unit tests for components, utilities, and hooks using Jest and React Testing Library. -- Write integration tests for drag-and-drop functionality and state management. -- Write end-to-end tests for the overall workflow using Cypress or Selenium. diff --git a/modules/masonry/docs/tech-spec/Techspec.md b/modules/masonry/docs/technical-specification/Techspec.md similarity index 100% rename from modules/masonry/docs/tech-spec/Techspec.md rename to modules/masonry/docs/technical-specification/Techspec.md From 33e63ec68f7636f84b16716da1b633780be4e795 Mon Sep 17 00:00:00 2001 From: Anindya Kundu Date: Thu, 5 Sep 2024 12:18:10 +0530 Subject: [PATCH 48/58] config(dev): [vscode] update config --- .vscode/settings.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 2ba7ff8c..fd7a62d3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,7 @@ { - "editor.rulers": [100], + "editor.rulers": [ + 100 + ], "editor.renderWhitespace": "boundary", "editor.defaultFormatter": "esbenp.prettier-vscode", "javascript.updateImportsOnFileMove.enabled": "always", @@ -25,7 +27,7 @@ "editor.suggest.snippetsPreventQuickSuggestions": false, "editor.suggestSelection": "first", "editor.tabCompletion": "onlySnippets", - "editor.wordBasedSuggestions": false + "editor.wordBasedSuggestions": "off" }, "[markdown]": { "editor.wordWrap": "on", From bca5df11ef0770cf9125abce93dc976bcd42b72b Mon Sep 17 00:00:00 2001 From: Anindya Kundu Date: Thu, 5 Sep 2024 12:22:04 +0530 Subject: [PATCH 49/58] config(dev): [markdownlint] update old properties --- .markdownlint.jsonc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc index 25310649..c2481488 100644 --- a/.markdownlint.jsonc +++ b/.markdownlint.jsonc @@ -81,8 +81,6 @@ "tables": true, // Include headings "headings": true, - // Include headings - "headers": true, // Strict length checking "strict": false, // Stern length checking @@ -118,9 +116,7 @@ // MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content "MD024": { // Only check sibling headings - "allow_different_nesting": true, - // Only check sibling headings - "siblings_only": false + "siblings_only": true }, // MD025/single-title/single-h1 - Multiple top-level headings in the same document From 81bf7d83d390445b5c12a6c8aa529a8feb6ea4f3 Mon Sep 17 00:00:00 2001 From: Anindya Kundu Date: Thu, 5 Sep 2024 17:06:08 +0530 Subject: [PATCH 50/58] feat(masonry): [brick] update models --- modules/masonry/src/@types/brick.d.ts | 194 +++++++------- modules/masonry/src/brick/model.ts | 359 ++++++++++++-------------- 2 files changed, 247 insertions(+), 306 deletions(-) diff --git a/modules/masonry/src/@types/brick.d.ts b/modules/masonry/src/@types/brick.d.ts index ab410a51..d50bac6b 100644 --- a/modules/masonry/src/@types/brick.d.ts +++ b/modules/masonry/src/@types/brick.d.ts @@ -10,17 +10,11 @@ export type TBrickKind = 'instruction' | 'argument'; */ export type TBrickType = 'data' | 'expression' | 'statement' | 'block'; -/** - * @type - * Data type (boolean, number, string, any) returned by an argument brick. - */ -export type TBrickArgDataType = 'boolean' | 'number' | 'string' | 'any'; - /** * @type * Bounding box dimensions of a brick. */ -export type TBrickExtent = { +export type TExtent = { width: number; height: number; }; @@ -29,7 +23,7 @@ export type TBrickExtent = { * @type * Position co-ordinates of a brick. */ -export type TBrickCoords = { +export type TCoords = { /** relative x co-ordinate */ x: number; /** relative y co-ordinate */ @@ -38,68 +32,73 @@ export type TBrickCoords = { /** * @type - * Defines color property of a brick. Supported types are RGC, HSL, and hexadecimal. + * Defines color property of a brick. Supported types are RGB, HSL, and hexadecimal. */ -export type TBrickColor = ['rgb' | 'hsl', number, number, number] | string; +export type TColor = ['rgb' | 'hsl', number, number, number] | string; // ------------------------------------------------------------------------------------------------- -/** - * @interface - * Style properties of a generic brick. - */ -export interface IBrickStyle { - /** background color */ - get colorBg(): TBrickColor; - /** foreground color */ - get colorFg(): TBrickColor; - /** outline/stroke color */ - get outline(): TBrickColor; - /** scale factor of the brick SVG */ - get scale(): number; -} +type TBrickRenderProps = { + path: string; + label: string; + glyph: string; + colorBg: TColor; + colorFg: TColor; + outline: TColor; + scale: number; +}; + +export type TBrickRenderPropsData = TBrickRenderProps & { + // reserving spot for future-proofing +}; + +export type TBrickRenderPropsExpression = TBrickRenderProps & { + labelArgs: string[]; + boundingBoxArgs: TExtent[]; +}; + +export type TBrickRenderPropsStatement = TBrickRenderProps & { + labelArgs: string[]; + boundingBoxArgs: TExtent[]; +}; + +export type TBrickRenderPropsBlock = TBrickRenderProps & { + labelArgs: string[]; + boundingBoxArgs: TExtent[]; + boundingBoxNest: TExtent; + folded: boolean; +}; + +// ------------------------------------------------------------------------------------------------- /** * @interface * Arguments for a brick. */ export interface IBrickArgs { - /** map of argument ID to data associated with the argument */ - get args(): Record< - string, - { - /** argument label */ - label: string; - /** data type returned by the argument brick */ - dataType: TBrickArgDataType; - /** metadata — reserved for future-proofing */ - meta: unknown; - } - >; -} + /** list of argument connection points of the brick */ + get connPointsArg(): { + [id: string]: { + /** bounding box dimensions of the connection point */ + extent: TExtent; + /** co-ordinates of the connection point */ + coords: TCoords; + }; + }; -/** - * @interface - * State properties associated with bricks that can take arguments. - */ -export interface IBrickArgsState { - /** Map of argument ID to corresponding extent and coords */ - get bBoxArgs(): Record< - string, - { - /** Bounding box dimensions */ - extent: TBrickExtent; - /** Co-ordinates of the argument connections relative to the brick */ - coords: TBrickCoords; - } - >; + /** + * Sets the bounding box extents for an arg + * @param id arg identifier + * @param extent width and height values of the arg + */ + setBoundingBoxArg(id: string, extent: TExtent): void; } /** * @interface * Type definition of a generic brick (any type). */ -export interface IBrick extends IBrickStyle { +export interface IBrick { /** unique ID of the brick */ get uuid(): string; /** name of the brick — to be used for internal bookkeeping */ @@ -108,64 +107,44 @@ export interface IBrick extends IBrickStyle { get kind(): TBrickKind; /** type of the brick */ get type(): TBrickType; - /** label for the brick */ - get label(): string; - /** glyph icon associated with the brick */ - get glyph(): string; - // states /** whether brick is highlighted */ - highlighted: boolean; - /** Bounding box dimensions and coords of the brick */ - get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords }; - - /** SVG string for the brick based on defining properties and current state */ - get SVGpath(): string; + set highlighted(value: boolean); + /** current vector scale factor */ + set scale(value: number); + + /** bounding box dimensions of the brick */ + get boundingBox(): TExtent; + /** list of fixed connection points of the brick */ + get connPointsFixed(): Record< + string, + { + /** bounding box dimensions of the connection point */ + extent: TExtent; + /** co-ordinates of the connection point */ + coords: TCoords; + } + >; } /** * @interface * Type definition of a generic argument brick (data or expression type). */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface export interface IBrickArgument extends IBrick { - /** data type returned by an argument brick */ - get dataType(): TBrickArgDataType; - - /** Bounding box dimensions and coords of the left notch */ - get bBoxNotchArg(): { - /** Bounding box dimensions of the left notch */ - extent: TBrickExtent; - /** Co-ordinates of the left notch relative to the brick */ - coords: TBrickCoords; - }; + // reserving spot for future-proofing } /** * @interface * Type definition of a generic instruction brick (statement or block type). */ -export interface IBrickInstruction extends IBrick, IBrickArgs, IBrickArgsState { - // style +export interface IBrickInstruction extends IBrick, IBrickArgs { /** is connection allowed above the brick */ get connectAbove(): boolean; /** is connection allowed below the brick */ get connectBelow(): boolean; - - /** Bounding box dimensions and coords of the top instruction notch */ - get bBoxNotchInsTop(): { - /** Bounding box dimensions of the top instruction notch */ - extent: TBrickExtent; - /** Co-ordinates of the top instruction notch relative to the brick */ - coords: TBrickCoords; - }; - - /** Bounding box dimensions and coords of the bottom instruction notch */ - get bBoxNotchInsBot(): { - /** Bounding box dimensions of the bottom instruction notch */ - extent: TBrickExtent; - /** Co-ordinates of the bottom instruction notch relative to the brick */ - coords: TBrickCoords; - }; } /** @@ -179,24 +158,27 @@ export interface IBrickData extends IBrickArgument { get value(): undefined | boolean | number | string; /** (if dynamic) input mode for the brick (checkbox, number box, text box, dropdown, etc.) */ get input(): undefined | 'boolean' | 'number' | 'string' | 'options'; + + /** list of properties required to render the data brick graphic */ + get renderProps(): IBrickRenderPropsData; } /** * @interface * Type definition of an argument brick. */ -// eslint-disable-next-line @typescript-eslint/no-empty-interface export interface IBrickExpression extends IBrickArgument, IBrickArgs, IBrickArgsState { - // reserving spot for future-proofing + /** list of properties required to render the expression brick graphic */ + get renderProps(): IBrickRenderPropsExpression; } /** * @interface * Type definition of a statement brick. */ -// eslint-disable-next-line @typescript-eslint/no-empty-interface export interface IBrickStatement extends IBrickInstruction { - // reserving spot for future-proofing + /** list of properties required to render the statement brick graphic */ + get renderProps(): IBrickRenderPropsStatement; } /** @@ -204,17 +186,15 @@ export interface IBrickStatement extends IBrickInstruction { * Type definition of a block brick. */ export interface IBrickBlock extends IBrickInstruction, IBrickNotchInsNestTopState { - // state - /** combined bounding box of the instructions nested within the brick */ - get nestExtent(): TBrickExtent; /** whether brick nesting is hidden */ - folded: boolean; + set folded(value: boolean); - /** Bounding box dimensions and coords of the top instruction notch of the nesting */ - get bBoxNotchInsNestTop(): { - /** Bounding box dimensions of the top instruction notch of the nesting */ - extent: TBrickExtent; - /** Co-ordinates of the top instruction notch of the nesting relative to the brick */ - coords: TBrickCoords; - }; + /** list of properties required to render the block brick graphic */ + get renderProps(): IBrickRenderPropsBlock; + + /** + * Sets the bounding box extents for the nested area + * @param extent width and height values of the nest area + */ + setBoundingBoxNest(extent: TExtent): void; } diff --git a/modules/masonry/src/brick/model.ts b/modules/masonry/src/brick/model.ts index 636ec414..dbbbceb5 100644 --- a/modules/masonry/src/brick/model.ts +++ b/modules/masonry/src/brick/model.ts @@ -6,12 +6,15 @@ import type { IBrickExpression, IBrickInstruction, IBrickStatement, - TBrickArgDataType, - TBrickColor, - TBrickCoords, - TBrickExtent, + TBrickRenderPropsData, + TBrickRenderPropsExpression, + TBrickRenderPropsStatement, + TBrickRenderPropsBlock, TBrickKind, TBrickType, + TColor, + TCoords, + TExtent, } from '@/@types/brick'; /** @@ -20,106 +23,87 @@ import type { * Defines the data model of a generic brick. */ abstract class BrickModel implements IBrick { - // intrinsic protected _uuid: string; protected _name: string; protected _kind: TBrickKind; protected _type: TBrickType; + protected _label: string; protected _glyph: string; - // style - protected _colorBg: TBrickColor; - protected _colorFg: TBrickColor; - protected _colorBgHighlight: TBrickColor; - protected _colorFgHighlight: TBrickColor; - protected _outline: TBrickColor; - - public highlighted = false; - protected _scale: number; - - // Common connection points - protected _connectionPoints: { - ArgsIncoming?: TBrickCoords[]; - ArgsOutgoing?: TBrickCoords[]; - }; + protected _colorBg: TColor; + protected _colorFg: TColor; + protected _colorBgHighlight: TColor; + protected _colorFgHighlight: TColor; + protected _outline: TColor; + + protected _highlighted = false; + protected _scale = 1; constructor(params: { + /** unique ID */ uuid: string; + /** name — to be used for internal bookkeeping */ name: string; + /** kind — instruction or argument */ kind: TBrickKind; + /** type — data, expression, statement, or block */ type: TBrickType; + /** primary label */ label: string; - glyph: string; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; + /** glyph icon associated with the brick */ + glyph?: string; + /** primary background color */ + colorBg: TColor; + /** primary foreground color */ + colorFg: TColor; + /** highlighted state background color */ + colorBgHighlight: TColor; + /** highlighted state foreground color */ + colorFgHighlight: TColor; + /** outline/stroke color */ + outline: TColor; }) { this._uuid = params.uuid; this._name = params.name; this._kind = params.kind; this._type = params.type; + this._label = params.label; - this._glyph = params.glyph; + this._glyph = params.glyph ?? ''; this._colorBg = params.colorBg; this._colorFg = params.colorFg; this._colorBgHighlight = params.colorBgHighlight; this._colorFgHighlight = params.colorFgHighlight; this._outline = params.outline; - this._scale = params.scale; - this._connectionPoints = {}; } - // Getters public get uuid(): string { return this._uuid; } + public get name(): string { return this._name; } + public get kind(): TBrickKind { return this._kind; } + public get type(): TBrickType { return this._type; } - public get label(): string { - return this._label; - } - public get glyph(): string { - return this._glyph; - } - public get colorBg(): TBrickColor { - return this._colorBg; - } - public get colorFg(): TBrickColor { - return this._colorFg; - } - public get colorBgHighlight(): TBrickColor { - return this._colorBgHighlight; - } - public get colorFgHighlight(): TBrickColor { - return this._colorFgHighlight; - } - public get outline(): TBrickColor { - return this._outline; - } - public get scale(): number { - return this._scale; + + public set highlighted(value: boolean) { + this._highlighted = value; } - public get connectionPoints(): { - ArgsIncoming?: TBrickCoords[]; - ArgsOutgoing?: TBrickCoords[]; - } { - return this._connectionPoints; + + public set scale(value: number) { + this._scale = value; } - public abstract get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords }; - public abstract get SVGpath(): string; + public abstract get boundingBox(): TExtent; - protected abstract updateConnectionPoints(): void; + public abstract get connPointsFixed(): Record; } /** @@ -128,35 +112,26 @@ abstract class BrickModel implements IBrick { * Defines the data model of a generic argument brick. */ abstract class BrickModelArgument extends BrickModel implements IBrickArgument { - protected _dataType: TBrickArgDataType; - protected _argExtents: Map = new Map(); - constructor(params: { - uuid: string; // Added uuid - name: string; // Added name + uuid: string; + name: string; type: TBrickType; + label: string; - glyph: string; - dataType: TBrickArgDataType; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; + glyph?: string; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; }) { super({ ...params, kind: 'argument' }); - this._dataType = params.dataType; } - public get dataType(): TBrickArgDataType { - return this._dataType; - } - public get argExtents(): Map { - return this._argExtents; - } - - public abstract get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords }; + public abstract get connPointsFixed(): Record< + 'argOutgoing', + { extent: TExtent; coords: TCoords } + >; } /** @@ -165,52 +140,52 @@ abstract class BrickModelArgument extends BrickModel implements IBrickArgument { * Defines the data model of a generic instruction brick. */ abstract class BrickModelInstruction extends BrickModel implements IBrickInstruction { - protected _args: Record; protected _connectAbove: boolean; protected _connectBelow: boolean; - protected _argExtents: Map = new Map(); + + protected _args: { id: string; label: string }[] = []; constructor(params: { - uuid: string; // Added uuid - name: string; // Added name + uuid: string; + name: string; type: TBrickType; + label: string; - glyph: string; - args: Record; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; + glyph?: string; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; connectAbove: boolean; connectBelow: boolean; + + args: { + /** unique identifier of the argument */ + id: string; + /** label for the argument */ + label: string; + }[]; }) { super({ ...params, kind: 'instruction' }); - this._args = params.args; + this._connectAbove = params.connectAbove; this._connectBelow = params.connectBelow; - } - public get args(): Record< - string, - { label: string; dataType: TBrickArgDataType; meta: unknown } - > { - return this._args; + this._args = params.args; } + public get connectAbove(): boolean { return this._connectAbove; } + public get connectBelow(): boolean { return this._connectBelow; } - public get argExtents(): Map { - return this._argExtents; - } - public abstract get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords }; - public abstract get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords }; - public abstract get bBoxArgs(): Record; + public abstract get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } }; + + public abstract setBoundingBoxArg(id: string, extent: TExtent): void; } /** @@ -224,40 +199,41 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric protected _input?: 'boolean' | 'number' | 'string' | 'options'; constructor(params: { - uuid: string; // Added uuid + uuid: string; name: string; + label: string; - glyph: string; - dataType: TBrickArgDataType; + glyph?: string; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + dynamic: boolean; value?: boolean | number | string; input?: 'boolean' | 'number' | 'string' | 'options'; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; }) { super({ ...params, type: 'data' }); + this._dynamic = params.dynamic; this._value = params.value; this._input = params.input; - this._connectionPoints.ArgsOutgoing = []; - this.updateConnectionPoints(); } public get dynamic(): boolean { return this._dynamic; } + public get value(): boolean | number | string | undefined { return this._value; } + public get input(): 'boolean' | 'number' | 'string' | 'options' | undefined { return this._input; } - protected abstract updateConnectionPoints(): void; + public abstract get renderProps(): TBrickRenderPropsData; } /** @@ -266,39 +242,37 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric * Defines the data model of an expression brick. */ export abstract class BrickModelExpression extends BrickModelArgument implements IBrickExpression { - protected _args: Record; + protected _args: { id: string; label: string }[] = []; constructor(params: { - uuid: string; // Added uuid + uuid: string; name: string; + label: string; - glyph: string; - dataType: TBrickArgDataType; - args: Record; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; + glyph?: string; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + + args: { + /** unique identifier of the argument */ + id: string; + /** label for the argument */ + label: string; + }[]; }) { super({ ...params, type: 'expression' }); + this._args = params.args; - this._connectionPoints.ArgsIncoming = []; - this._connectionPoints.ArgsOutgoing = []; - this.updateConnectionPoints(); } - public get args(): Record< - string, - { label: string; dataType: TBrickArgDataType; meta: unknown } - > { - return this._args; - } + public abstract get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } }; - public abstract get bBoxArgs(): Record; + public abstract setBoundingBoxArg(id: string, extent: TExtent): void; - protected abstract updateConnectionPoints(): void; + public abstract get renderProps(): TBrickRenderPropsExpression; } /** @@ -308,26 +282,35 @@ export abstract class BrickModelExpression extends BrickModelArgument implements */ export abstract class BrickModelStatement extends BrickModelInstruction implements IBrickStatement { constructor(params: { - uuid: string; // Added uuid + uuid: string; name: string; + label: string; glyph: string; - args: Record; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; connectAbove: boolean; connectBelow: boolean; + + args: { + /** unique identifier of the argument */ + id: string; + /** label for the argument */ + label: string; + }[]; }) { super({ ...params, type: 'statement' }); - this._connectionPoints.ArgsOutgoing = []; - this.updateConnectionPoints(); } - protected abstract updateConnectionPoints(): void; + public abstract get connPointsFixed(): Record< + 'insTop' | 'insBottom', + { extent: TExtent; coords: TCoords } + >; + + public abstract get renderProps(): TBrickRenderPropsStatement; } /** @@ -336,64 +319,42 @@ export abstract class BrickModelStatement extends BrickModelInstruction implemen * Defines the data model of a block brick. */ export abstract class BrickModelBlock extends BrickModelInstruction implements IBrickBlock { - public nestExtent: TBrickExtent = { width: 0, height: 0 }; protected _folded = false; - protected _connectionPointsBlock: { - Top: TBrickCoords[]; - Bottom: TBrickCoords[]; - TopInner: TBrickCoords[]; - }; - constructor(params: { - uuid: string; // Added uuid + uuid: string; name: string; + label: string; - glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: { - argId: string; - argLabel: string; - argTypeIncoming: string; - }; - } - >; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; + glyph?: string; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; connectAbove: boolean; connectBelow: boolean; + + args: { + /** unique identifier of the argument */ + id: string; + /** label for the argument */ + label: string; + }[]; }) { super({ ...params, type: 'block' }); - this._connectionPointsBlock = { - Top: [], - Bottom: [], - TopInner: [], - }; - this._connectionPoints.ArgsIncoming = []; - this.updateConnectionPoints(); } - public get folded(): boolean { - return this._folded; + public set folded(value: boolean) { + this._folded = value; } - public get connectionPointsBlock(): { - Top: TBrickCoords[]; - Bottom: TBrickCoords[]; - TopInner: TBrickCoords[]; - } { - return this._connectionPointsBlock; - } + public abstract get connPointsFixed(): Record< + 'insTop' | 'insBottom' | 'insNest', + { extent: TExtent; coords: TCoords } + >; - public abstract get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords }; + public abstract get renderProps(): TBrickRenderPropsBlock; - protected abstract updateConnectionPoints(): void; + public abstract setBoundingBoxNest(extent: TExtent): void; } From 94e1e28e265f493fecfbd62504013f0ace452af1 Mon Sep 17 00:00:00 2001 From: Anindya Kundu Date: Thu, 5 Sep 2024 17:06:48 +0530 Subject: [PATCH 51/58] feat(masonry): [design0/block] update concrete model --- .../masonry/src/brick/design0/BrickBlock.ts | 340 ++++++++++-------- 1 file changed, 181 insertions(+), 159 deletions(-) diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index 9b4fbab2..c0feb5aa 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -1,4 +1,4 @@ -import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; +import type { TBrickRenderPropsBlock, TColor, TCoords, TExtent } from '@/@types/brick'; import { BrickModelBlock } from '../model'; import { generatePath } from '../utils/path'; @@ -11,205 +11,227 @@ import { generatePath } from '../utils/path'; export default class BrickBlock extends BrickModelBlock { readonly _pathResults: ReturnType; + private _boundingBoxArgs: Record = {}; + private _boundingBoxNest: TExtent = { width: 0, height: 0 }; + constructor(params: { uuid: string; name: string; + label: string; - glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: { - argId: string; - argLabel: string; - argTypeIncoming: string; - }; - } - >; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; + glyph?: string; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; connectAbove: boolean; connectBelow: boolean; - nestLengthY: number; - folded?: boolean; // Made folded optional + + args: { + /** unique identifier of the argument */ + id: string; + /** label for the argument */ + label: string; + }[]; }) { 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, + nestLengthY: 0, // generate from length of label/s innerLengthX: 100, - argHeights: Array.from({ length: argsKeys.length }, () => 17), + argHeights: Array.from({ length: this._args.length }, () => 17), }); - - // Set folded to its initial state or default to false - this._folded = params.folded ?? false; } - // Getter for SVG path - public get SVGpath(): string { - return this._pathResults.path; + /** @todo implement correctly */ + public get boundingBox(): TExtent { + return { + width: this._pathResults.bBoxBrick.extent.width * this._scale, + height: this._pathResults.bBoxBrick.extent.height * this._scale, + }; } - // Getter for bounding box of the brick - public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { + /** @todo implement correctly */ + public get connPointsFixed(): Record< + 'insTop' | 'insBottom' | 'insNest', + { extent: TExtent; coords: TCoords } + > { return { - extent: { - width: this._pathResults.bBoxBrick.extent.width * this._scale, - height: this._pathResults.bBoxBrick.extent.height * this._scale, + insTop: { + extent: { width: 0, height: 0 }, + coords: { x: 0, y: 0 }, + }, + insBottom: { + extent: { width: 0, height: 0 }, + coords: { x: 0, y: 0 }, }, - coords: { - x: this._pathResults.bBoxBrick.coords.x * this._scale, - y: this._pathResults.bBoxBrick.coords.y * this._scale, + insNest: { + extent: { width: 0, height: 0 }, + coords: { x: 0, y: 0 }, }, }; } - // Getter for bounding boxes of the arguments - public get bBoxArgs(): Record { - const argsKeys = Object.keys(this._args); - const result: Record = {}; - - argsKeys.forEach((key, index) => { - 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, - }, + /** @todo implement correctly */ + get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } } { + const results: { [id: string]: { extent: TExtent; coords: TCoords } } = {}; + + this._args.forEach(({ id }) => { + results[id] = { + extent: { width: 0, height: 0 }, + coords: { x: 0, y: 0 }, }; }); - return result; + return results; } - // Getter for bounding box of the argument notch - public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { + /** @todo implement correctly */ + public get renderProps(): TBrickRenderPropsBlock { 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, - }, - }; - } - - // Getter for bounding box of the top insertion notch - public get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords } { - 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, - }, - }; - } + path: this._pathResults.path, - // Getter for bounding box of the bottom insertion notch - public get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords } { - 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, - }, - }; - } + label: this._label, + labelArgs: this._args.map(({ label }) => label), - // Getter for bounding box of the nest insertion notch - public get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords } { - 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, - }, - }; - } + boundingBoxArgs: this._args.map(({ id }) => this._boundingBoxArgs[id]), + boundingBoxNest: this._boundingBoxNest, - // Method to return React props for the BrickBlock component - public getReactProps(): Record { - return { - uuid: this.uuid, - name: this.name, - label: this.label, - glyph: this.glyph, - args: this.args, - colorBg: this.colorBg, - colorFg: this.colorFg, - colorBgHighlight: this.colorBgHighlight, - colorFgHighlight: this.colorFgHighlight, - outline: this.outline, - scale: this.scale, - connectAbove: this.connectAbove, - connectBelow: this.connectBelow, + glyph: this._glyph, + colorBg: !this._highlighted ? this._colorBg : this._colorBgHighlight, + colorFg: !this._highlighted ? this._colorFg : this._colorFgHighlight, + outline: this._outline, + scale: this._scale, folded: this.folded, - highlighted: this.highlighted, }; } - // Setters for properties that can change at runtime - public setArgs( - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: { argId: string; argLabel: string; argTypeIncoming: string }; - } - >, - ): void { - this._args = args; - this.updateConnectionPoints(); + /** @todo implement correctly */ + public setBoundingBoxArg(id: string, extent: TExtent): void { + this._boundingBoxArgs[id] = extent; } - public setConnectAbove(connectAbove: boolean): void { - this._connectAbove = connectAbove; + public setBoundingBoxNest(extent: TExtent): void { + this._boundingBoxNest = extent; } - public setConnectBelow(connectBelow: boolean): void { - this._connectBelow = connectBelow; - } - - public setFolded(folded?: boolean): void { - // Set folded as optional - this._folded = folded ?? false; // Default to false if not provided - } - - public setHighlighted(highlighted: boolean): void { - this.highlighted = highlighted; - } - - // Method to update connection points based on current state - protected updateConnectionPoints(): void { - // Update the connection points for the top, bottom, and nest of the block - this._connectionPointsBlock.Top = this.connectAbove ? [{ x: 0, y: 0 }] : []; - this._connectionPointsBlock.Bottom = this.connectBelow ? [{ x: 0, y: 0 }] : []; - this._connectionPointsBlock.TopInner = this.folded ? [] : [{ x: 0, y: 0 }]; - } + // // Getter for bounding box of the brick + // public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { + // 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, + // }, + // }; + // } + + // // Getter for bounding boxes of the arguments + // public get bBoxArgs(): Record { + // const argsKeys = Object.keys(this._args); + // const result: Record = {}; + + // argsKeys.forEach((key, index) => { + // 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; + // } + + // // Getter for bounding box of the argument notch + // public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { + // 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, + // }, + // }; + // } + + // // Getter for bounding box of the top insertion notch + // public get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords } { + // 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, + // }, + // }; + // } + + // // Getter for bounding box of the bottom insertion notch + // public get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords } { + // 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, + // }, + // }; + // } + + // // Getter for bounding box of the nest insertion notch + // public get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords } { + // 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, + // }, + // }; + // } + + // // Setters for properties that can change at runtime + // public setArgs( + // args: Record< + // string, + // { + // label: string; + // dataType: TBrickArgDataType; + // meta: { argId: string; argLabel: string; argTypeIncoming: string }; + // } + // >, + // ): void { + // this._args = args; + // this.updateConnectionPoints(); + // } + + // // Method to update connection points based on current state + // protected updateConnectionPoints(): void { + // // Update the connection points for the top, bottom, and nest of the block + // this._connectionPointsBlock.Top = this.connectAbove ? [{ x: 0, y: 0 }] : []; + // this._connectionPointsBlock.Bottom = this.connectBelow ? [{ x: 0, y: 0 }] : []; + // this._connectionPointsBlock.TopInner = this.folded ? [] : [{ x: 0, y: 0 }]; + // } } From ab5866494ce0d475a19702584867a8e357dc7b78 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Fri, 6 Sep 2024 12:13:22 +0530 Subject: [PATCH 52/58] fix(masonry): Fix issues in the concrete classes and add exports to the components --- .../masonry/src/brick/design0/BrickBlock.ts | 145 ++--------------- .../masonry/src/brick/design0/BrickData.ts | 94 ++++------- .../src/brick/design0/BrickExpression.ts | 147 ++++++----------- .../src/brick/design0/BrickStatement.ts | 154 +++++++----------- .../masonry/src/brick/design0/brickFactory.ts | 88 +++++----- .../src/brick/design0/brickWarehouse.ts | 38 ----- .../brick/design0/components/BrickBlock.tsx | 4 +- .../brick/design0/components/BrickData.tsx | 2 +- .../design0/components/BrickExpression.tsx | 4 +- .../design0/components/BrickStatement.tsx | 4 +- .../brick/design0/components/BrickWrapper.tsx | 0 11 files changed, 191 insertions(+), 489 deletions(-) delete mode 100644 modules/masonry/src/brick/design0/brickWarehouse.ts create mode 100644 modules/masonry/src/brick/design0/components/BrickWrapper.tsx diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index c0feb5aa..9271201a 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -43,56 +43,52 @@ export default class BrickBlock extends BrickModelBlock { hasNotchInsTop: this._connectAbove, hasNotchInsBot: this._connectBelow, scale: this._scale, - nestLengthY: 0, // generate from length of label/s + nestLengthY: this._args.length * 20, // Example of generating nest length based on argument count innerLengthX: 100, argHeights: Array.from({ length: this._args.length }, () => 17), }); } - /** @todo implement correctly */ public get boundingBox(): TExtent { return { - width: this._pathResults.bBoxBrick.extent.width * this._scale, - height: this._pathResults.bBoxBrick.extent.height * this._scale, + width: this._pathResults.bBoxBrick.extent.width, + height: this._pathResults.bBoxBrick.extent.height, }; } - /** @todo implement correctly */ public get connPointsFixed(): Record< 'insTop' | 'insBottom' | 'insNest', { extent: TExtent; coords: TCoords } > { return { insTop: { - extent: { width: 0, height: 0 }, - coords: { x: 0, y: 0 }, + extent: this._pathResults.bBoxNotchInsTop!.extent, + coords: this._pathResults.bBoxNotchInsTop!.coords, }, insBottom: { - extent: { width: 0, height: 0 }, - coords: { x: 0, y: 0 }, + extent: this._pathResults.bBoxNotchInsBot!.extent, + coords: this._pathResults.bBoxNotchInsBot!.coords, }, insNest: { - extent: { width: 0, height: 0 }, - coords: { x: 0, y: 0 }, + extent: this._pathResults.bBoxNotchInsNestTop!.extent, + coords: this._pathResults.bBoxNotchInsNestTop!.coords, }, }; } - /** @todo implement correctly */ - get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } } { + public get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } } { const results: { [id: string]: { extent: TExtent; coords: TCoords } } = {}; - this._args.forEach(({ id }) => { + this._args.forEach(({ id }, index) => { results[id] = { - extent: { width: 0, height: 0 }, - coords: { x: 0, y: 0 }, + extent: { width: 10, height: 10 }, // Example extent + coords: { x: 0, y: index * 20 }, // Example coordinates calculation }; }); return results; } - /** @todo implement correctly */ public get renderProps(): TBrickRenderPropsBlock { return { path: this._pathResults.path, @@ -112,7 +108,6 @@ export default class BrickBlock extends BrickModelBlock { }; } - /** @todo implement correctly */ public setBoundingBoxArg(id: string, extent: TExtent): void { this._boundingBoxArgs[id] = extent; } @@ -120,118 +115,4 @@ export default class BrickBlock extends BrickModelBlock { public setBoundingBoxNest(extent: TExtent): void { this._boundingBoxNest = extent; } - - // // Getter for bounding box of the brick - // public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { - // 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, - // }, - // }; - // } - - // // Getter for bounding boxes of the arguments - // public get bBoxArgs(): Record { - // const argsKeys = Object.keys(this._args); - // const result: Record = {}; - - // argsKeys.forEach((key, index) => { - // 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; - // } - - // // Getter for bounding box of the argument notch - // public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { - // 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, - // }, - // }; - // } - - // // Getter for bounding box of the top insertion notch - // public get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords } { - // 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, - // }, - // }; - // } - - // // Getter for bounding box of the bottom insertion notch - // public get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords } { - // 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, - // }, - // }; - // } - - // // Getter for bounding box of the nest insertion notch - // public get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords } { - // 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, - // }, - // }; - // } - - // // Setters for properties that can change at runtime - // public setArgs( - // args: Record< - // string, - // { - // label: string; - // dataType: TBrickArgDataType; - // meta: { argId: string; argLabel: string; argTypeIncoming: string }; - // } - // >, - // ): void { - // this._args = args; - // this.updateConnectionPoints(); - // } - - // // Method to update connection points based on current state - // protected updateConnectionPoints(): void { - // // Update the connection points for the top, bottom, and nest of the block - // this._connectionPointsBlock.Top = this.connectAbove ? [{ x: 0, y: 0 }] : []; - // this._connectionPointsBlock.Bottom = this.connectBelow ? [{ x: 0, y: 0 }] : []; - // this._connectionPointsBlock.TopInner = this.folded ? [] : [{ x: 0, y: 0 }]; - // } } diff --git a/modules/masonry/src/brick/design0/BrickData.ts b/modules/masonry/src/brick/design0/BrickData.ts index e9ab6178..b8b3b5f3 100644 --- a/modules/masonry/src/brick/design0/BrickData.ts +++ b/modules/masonry/src/brick/design0/BrickData.ts @@ -1,4 +1,4 @@ -import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; +import type { TBrickRenderPropsData, TColor, TCoords, TExtent } from '@/@types/brick'; import { BrickModelData } from '../model'; import { generatePath } from '../utils/path'; @@ -12,112 +12,80 @@ export default class BrickData extends BrickModelData { readonly _pathResults: ReturnType; constructor(params: { - //intrinsic uuid: string; name: string; label: string; glyph: string; - dataType: TBrickArgDataType; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; dynamic: boolean; value?: boolean | number | string; input?: 'boolean' | 'number' | 'string' | 'options'; - //style - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; }) { super(params); + this._pathResults = generatePath({ hasNest: false, hasNotchArg: true, hasNotchInsTop: false, hasNotchInsBot: false, scale: this._scale, - innerLengthX: 100, + innerLengthX: 100, // This could be dynamic based on text size or other criteria argHeights: [], }); } - // Getter for SVG path - public get SVGpath(): string { - return this._pathResults.path; - } - - // Getter for bounding box of the brick - public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { - const { extent, coords } = this._pathResults.bBoxBrick; + // Getter for bounding box dimensions of the brick + public get boundingBox(): TExtent { return { - extent: { - width: extent.width * this._scale, - height: extent.height * this._scale, - }, - coords: { - x: coords.x * this._scale, - y: coords.y * this._scale, - }, + width: this._pathResults.bBoxBrick.extent.width, + height: this._pathResults.bBoxBrick.extent.height, }; } - // Getter for bounding box of the argument notch - public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { - const { extent, coords } = this._pathResults.bBoxNotchArg!; + // Getter for fixed connection points of the brick + public get connPointsFixed(): Record<'argOutgoing', { extent: TExtent; coords: TCoords }> { return { - extent: { - width: extent.width * this._scale, - height: extent.height * this._scale, - }, - coords: { - x: coords.x * this._scale, - y: coords.y * this._scale, + argOutgoing: { + extent: this._pathResults.bBoxNotchArg!.extent, + coords: this._pathResults.bBoxNotchArg!.coords, }, }; } - // Method to return React props for the BrickData component - public renderProps(): Record { + // Getter for properties required to render the data brick graphic + public get renderProps(): TBrickRenderPropsData { return { - uuid: this.uuid, - name: this.name, - label: this.label, - glyph: this.glyph, - dataType: this.dataType, - dynamic: this.dynamic, - value: this.value, - input: this.input, - colorBg: this.colorBg, - colorFg: this.colorFg, - colorBgHighlight: this.colorBgHighlight, - colorFgHighlight: this.colorFgHighlight, - outline: this.outline, - scale: this.scale, - highlighted: this.highlighted, + path: this._pathResults.path, + label: this._label, + glyph: this._glyph, + colorBg: !this._highlighted ? this._colorBg : this._colorBgHighlight, + colorFg: !this._highlighted ? this._colorFg : this._colorFgHighlight, + outline: this._outline, + scale: this._scale, }; } - // Setters for properties that can change at runtime + // Setter for dynamic property public setDynamic(dynamic: boolean): void { this._dynamic = dynamic; - this.updateConnectionPoints(); } + // Setter for value property public setValue(value: boolean | number | string): void { this._value = value; } + // Setter for input type property public setInput(input: 'boolean' | 'number' | 'string' | 'options'): void { this._input = input; } + // Setter for highlighted property public setHighlighted(highlighted: boolean): void { - this.highlighted = highlighted; - } - - // Method to update connection points based on current state - protected updateConnectionPoints(): void { - // Update connection points logic if needed - this._connectionPoints.ArgsOutgoing = this._dynamic ? [{ x: 0, y: 0 }] : []; + this._highlighted = highlighted; } } diff --git a/modules/masonry/src/brick/design0/BrickExpression.ts b/modules/masonry/src/brick/design0/BrickExpression.ts index e6a58dc7..7fb2b974 100644 --- a/modules/masonry/src/brick/design0/BrickExpression.ts +++ b/modules/masonry/src/brick/design0/BrickExpression.ts @@ -1,9 +1,7 @@ -import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; +import type { TBrickRenderPropsExpression, TColor, TCoords, TExtent } from '@/@types/brick'; import { BrickModelExpression } from '../model'; import { generatePath } from '../utils/path'; -// ------------------------------------------------------------------------------------------------- - /** * @class * Final class that defines an expression brick. @@ -11,29 +9,29 @@ import { generatePath } from '../utils/path'; export default class BrickExpression extends BrickModelExpression { readonly _pathResults: ReturnType; + private _boundingBoxArgs: Record = {}; + constructor(params: { uuid: string; name: string; + label: string; - glyph: string; - dataType: TBrickArgDataType; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; - scale: number; + glyph?: string; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + + args: { + /** unique identifier of the argument */ + id: string; + /** label for the argument */ + label: string; + }[]; }) { super(params); - const argsKeys = Object.keys(this._args); + this._pathResults = generatePath({ hasNest: false, hasNotchArg: true, @@ -41,104 +39,57 @@ export default class BrickExpression extends BrickModelExpression { hasNotchInsBot: false, scale: this._scale, innerLengthX: 100, - argHeights: Array.from({ length: argsKeys.length }, () => 17), + argHeights: Array.from({ length: this._args.length }, () => 17), }); } - // Getter for SVG path - public get SVGpath(): string { - return this._pathResults.path; + public get boundingBox(): TExtent { + return { + width: this._pathResults.bBoxBrick.extent.width, + height: this._pathResults.bBoxBrick.extent.height, + }; } - // Getter for bounding box of the brick - public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { + public get connPointsFixed(): Record<'argOutgoing', { extent: TExtent; coords: TCoords }> { 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, + argOutgoing: { + extent: this._pathResults.bBoxNotchArg!.extent, + coords: this._pathResults.bBoxNotchArg!.coords, }, }; } - // Getter for bounding boxes of the arguments - public get bBoxArgs(): Record { - const argsKeys = Object.keys(this._args); - const result: Record = {}; + // Implementation of argument connection points getter + public get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } } { + const results: { [id: string]: { extent: TExtent; coords: TCoords } } = {}; - argsKeys.forEach((key, index) => { - 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, - }, + this._args.forEach(({ id }, index) => { + results[id] = { + extent: { width: 10, height: 10 }, // Example extent + coords: { x: 0, y: index * 20 }, // Example coordinates calculation }; }); - return result; + return results; } - // Getter for bounding box of the argument notch - public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { + public get renderProps(): TBrickRenderPropsExpression { 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, - }, - }; - } + path: this._pathResults.path, - // Method to return React props for the BrickExpression component - public getReactProps(): Record { - return { - uuid: this.uuid, - name: this.name, - label: this.label, - glyph: this.glyph, - dataType: this.dataType, - args: this.args, - colorBg: this.colorBg, - colorFg: this.colorFg, - colorBgHighlight: this.colorBgHighlight, - colorFgHighlight: this.colorFgHighlight, - outline: this.outline, - scale: this.scale, - highlighted: this.highlighted, - }; - } + label: this._label, + labelArgs: this._args.map(({ label }) => label), + boundingBoxArgs: this._args.map(({ id }) => this._boundingBoxArgs[id]), - // Setters for properties that can change at runtime - public setArgs( - args: Record, - ): void { - this._args = args; - this.updateConnectionPoints(); - } - - public setHighlighted(highlighted: boolean): void { - this.highlighted = highlighted; + glyph: this._glyph, + colorBg: !this._highlighted ? this._colorBg : this._colorBgHighlight, + colorFg: !this._highlighted ? this._colorFg : this._colorFgHighlight, + outline: this._outline, + scale: this._scale, + }; } - // Method to update connection points based on current state - protected updateConnectionPoints(): void { - this._connectionPoints.ArgsIncoming = Object.keys(this._args).map((_, index) => ({ - x: 0, - y: index * 20, - })); - this._connectionPoints.ArgsOutgoing = Object.keys(this._args).map((_, index) => ({ - x: 0, - y: index * 20, - })); + public setBoundingBoxArg(id: string, extent: TExtent): void { + this._boundingBoxArgs[id] = extent; } } diff --git a/modules/masonry/src/brick/design0/BrickStatement.ts b/modules/masonry/src/brick/design0/BrickStatement.ts index bf815ec7..f4c09291 100644 --- a/modules/masonry/src/brick/design0/BrickStatement.ts +++ b/modules/masonry/src/brick/design0/BrickStatement.ts @@ -1,9 +1,7 @@ -import type { TBrickArgDataType, TBrickColor, TBrickCoords, TBrickExtent } from '@/@types/brick'; +import type { TBrickRenderPropsStatement, TColor, TCoords, TExtent } from '@/@types/brick'; import { BrickModelStatement } from '../model'; import { generatePath } from '../utils/path'; -// ------------------------------------------------------------------------------------------------- - /** * @class * Final class that defines a statement brick. @@ -11,6 +9,8 @@ import { generatePath } from '../utils/path'; export default class BrickStatement extends BrickModelStatement { readonly _pathResults: ReturnType; + private _boundingBoxArgs: Record = {}; + constructor(params: { uuid: string; name: string; @@ -20,126 +20,93 @@ export default class BrickStatement extends BrickModelStatement { string, { label: string; - dataType: TBrickArgDataType; + dataType: string; // Change from TBrickArgDataType to string for compatibility meta: unknown; } >; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; scale: number; connectAbove: boolean; connectBelow: boolean; }) { - super(params); - const argsKeys = Object.keys(this._args); + // Convert `args` to an array + const formattedArgs = Object.keys(params.args).map((id) => ({ + id, + label: params.args[id].label, + })); + + super({ + ...params, + args: formattedArgs, + }); + this._pathResults = generatePath({ hasNest: false, hasNotchArg: false, - hasNotchInsTop: true, - hasNotchInsBot: true, + hasNotchInsTop: this._connectAbove, + hasNotchInsBot: this._connectBelow, scale: this._scale, innerLengthX: 100, - argHeights: Array.from({ length: argsKeys.length }, () => 17), + argHeights: Array.from({ length: formattedArgs.length }, () => 17), }); } - // Getter for SVG path - public get SVGpath(): string { - return this._pathResults.path; + public get boundingBox(): TExtent { + return { + width: this._pathResults.bBoxBrick.extent.width, + height: this._pathResults.bBoxBrick.extent.height, + }; } - // Getter for bounding box of the brick - public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { + public get connPointsFixed(): Record< + 'insTop' | 'insBottom', + { extent: TExtent; coords: TCoords } + > { return { - extent: { - width: this._pathResults.bBoxBrick.extent.width * this._scale, - height: this._pathResults.bBoxBrick.extent.height * this._scale, + insTop: { + extent: this._pathResults.bBoxNotchInsTop!.extent, + coords: this._pathResults.bBoxNotchInsTop!.coords, }, - coords: { - x: this._pathResults.bBoxBrick.coords.x * this._scale, - y: this._pathResults.bBoxBrick.coords.y * this._scale, + insBottom: { + extent: this._pathResults.bBoxNotchInsBot!.extent, + coords: this._pathResults.bBoxNotchInsBot!.coords, }, }; } - // Getter for bounding boxes of the arguments - public get bBoxArgs(): Record { - const argsKeys = Object.keys(this._args); - const result: Record = {}; + public get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } } { + const results: { [id: string]: { extent: TExtent; coords: TCoords } } = {}; - argsKeys.forEach((key, index) => { - 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, - }, + Object.keys(this._args).forEach((id) => { + results[id] = { + extent: { width: 10, height: 10 }, // Example extent + coords: { x: 0, y: 0 }, // Example coordinates calculation }; }); - return result; + return results; } - // Getter for bounding box of the top insertion notch - public get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords } { + public get renderProps(): TBrickRenderPropsStatement { 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, - }, - }; - } - - // Getter for bounding box of the bottom insertion notch - public get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords } { - 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, - }, - }; - } - - // Method to return React props for the BrickStatement component - public getReactProps(): Record { - return { - uuid: this.uuid, - name: this.name, - label: this.label, - glyph: this.glyph, - args: this.args, - colorBg: this.colorBg, - colorFg: this.colorFg, - colorBgHighlight: this.colorBgHighlight, - colorFgHighlight: this.colorFgHighlight, - outline: this.outline, - scale: this.scale, - connectAbove: this.connectAbove, - connectBelow: this.connectBelow, - highlighted: this.highlighted, + path: this._pathResults.path, + label: this._label, + labelArgs: Object.values(this._args).map(({ label }) => label), + boundingBoxArgs: Object.keys(this._args).map((id) => this._boundingBoxArgs[id]), + glyph: this._glyph, + colorBg: !this._highlighted ? this._colorBg : this._colorBgHighlight, + colorFg: !this._highlighted ? this._colorFg : this._colorFgHighlight, + outline: this._outline, + scale: this._scale, }; } - // Setters for properties that can change at runtime - public setArgs( - args: Record, - ): void { - this._args = args; - this.updateConnectionPoints(); + public setBoundingBoxArg(id: string, extent: TExtent): void { + this._boundingBoxArgs[id] = extent; } public setConnectAbove(connectAbove: boolean): void { @@ -153,11 +120,4 @@ export default class BrickStatement extends BrickModelStatement { public setHighlighted(highlighted: boolean): void { this.highlighted = highlighted; } - - // Method to update connection points based on current state - protected updateConnectionPoints(): void { - // Update the connection points for the top and bottom of the brick - this._connectionPoints.ArgsIncoming = this.connectAbove ? [{ x: 0, y: 0 }] : []; - this._connectionPoints.ArgsOutgoing = this.connectBelow ? [{ x: 0, y: 0 }] : []; - } } diff --git a/modules/masonry/src/brick/design0/brickFactory.ts b/modules/masonry/src/brick/design0/brickFactory.ts index 73a22cff..30111620 100644 --- a/modules/masonry/src/brick/design0/brickFactory.ts +++ b/modules/masonry/src/brick/design0/brickFactory.ts @@ -1,5 +1,5 @@ import { v4 as uuidv4 } from 'uuid'; -import type { TBrickArgDataType, TBrickColor } from '@/@types/brick'; +import type { TColor } from '@/@types/brick'; import BrickStatement from './BrickStatement'; import BrickExpression from './BrickExpression'; import BrickData from './BrickData'; @@ -39,6 +39,17 @@ function deleteBrickFromWarehouse(id: string): boolean { return brickWarehouse.delete(id); } +/** + * Converts a Record type args to an array. + * @param argsRecord - Record of args objects. + * @returns Converted args as an array. + */ +function argsRecordToArray( + argsRecord: Record, +): { id: string; label: string }[] { + return Object.entries(argsRecord).map(([id, { label }]) => ({ id, label })); +} + /** * Factory function to create a new BrickBlock instance. * @param params - Parameters to initialize the BrickBlock. @@ -48,23 +59,12 @@ export function createBrickBlock(params: { name: string; label: string; glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: { - argId: string; - argLabel: string; - argTypeIncoming: string; - }; - } - >; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; + args: { id: string; label: string }[]; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; scale: number; connectAbove: boolean; connectBelow: boolean; @@ -88,15 +88,14 @@ export function createBrickData(params: { name: string; label: string; glyph: string; - dataType: TBrickArgDataType; dynamic: boolean; value?: boolean | number | string; input?: 'boolean' | 'number' | 'string' | 'options'; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; scale: number; }): BrickData { const brick = new BrickData({ @@ -116,25 +115,18 @@ export function createBrickExpression(params: { name: string; label: string; glyph: string; - dataType: TBrickArgDataType; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; + args: Record; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; scale: number; }): BrickExpression { const brick = new BrickExpression({ uuid: uuidv4(), ...params, + args: argsRecordToArray(params.args), // Convert Record to array }); addBrickToWarehouse(brick); return brick; @@ -149,19 +141,12 @@ export function createBrickStatement(params: { name: string; label: string; glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - colorBg: TBrickColor; - colorFg: TBrickColor; - colorBgHighlight: TBrickColor; - colorFgHighlight: TBrickColor; - outline: TBrickColor; + args: Record; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; scale: number; connectAbove: boolean; connectBelow: boolean; @@ -169,6 +154,7 @@ export function createBrickStatement(params: { const brick = new BrickStatement({ uuid: uuidv4(), ...params, + args: argsRecordToArray(params.args), }); addBrickToWarehouse(brick); return brick; diff --git a/modules/masonry/src/brick/design0/brickWarehouse.ts b/modules/masonry/src/brick/design0/brickWarehouse.ts deleted file mode 100644 index 4ad3d132..00000000 --- a/modules/masonry/src/brick/design0/brickWarehouse.ts +++ /dev/null @@ -1,38 +0,0 @@ -import BrickStatement from './BrickStatement'; -import BrickExpression from './BrickExpression'; -import BrickData from './BrickData'; -import BrickBlock from './BrickBlock'; - -// Warehouse to manage brick instances -const brickWarehouse: Map = - new Map(); - -/** - * Adds a brick instance to the warehouse. - * @param brick - The brick instance to add. - */ -export function addBrickToWarehouse( - brick: BrickStatement | BrickExpression | BrickData | BrickBlock, -): void { - brickWarehouse.set(brick.id, brick); -} - -/** - * Retrieves a brick instance from the warehouse by its ID. - * @param id - The ID of the brick to retrieve. - * @returns The brick instance if found, otherwise undefined. - */ -export function getBrickFromWarehouse( - id: string, -): BrickStatement | BrickExpression | BrickData | BrickBlock | undefined { - return brickWarehouse.get(id); -} - -/** - * Deletes a brick instance from the warehouse by its ID. - * @param id - The ID of the brick to delete. - * @returns True if the brick was deleted, false if it was not found. - */ -export function deleteBrickFromWarehouse(id: string): boolean { - return brickWarehouse.delete(id); -} diff --git a/modules/masonry/src/brick/design0/components/BrickBlock.tsx b/modules/masonry/src/brick/design0/components/BrickBlock.tsx index 92c3293f..646ba5fc 100644 --- a/modules/masonry/src/brick/design0/components/BrickBlock.tsx +++ b/modules/masonry/src/brick/design0/components/BrickBlock.tsx @@ -1,9 +1,7 @@ import type { JSX } from 'react'; import type { IBrickBlock, TBrickCoords } from '@/@types/brick'; -// ------------------------------------------------------------------------------------------------- - -export default function ({ +export default function BrickBlock({ instance, coords = { x: 0, y: 0 }, }: { diff --git a/modules/masonry/src/brick/design0/components/BrickData.tsx b/modules/masonry/src/brick/design0/components/BrickData.tsx index 206a6050..476ffd46 100644 --- a/modules/masonry/src/brick/design0/components/BrickData.tsx +++ b/modules/masonry/src/brick/design0/components/BrickData.tsx @@ -3,7 +3,7 @@ import type { IBrickData, TBrickCoords } from '@/@types/brick'; // ------------------------------------------------------------------------------------------------- -export default function ({ +export default function BrickData({ instance, coords = { x: 0, y: 0 }, }: { diff --git a/modules/masonry/src/brick/design0/components/BrickExpression.tsx b/modules/masonry/src/brick/design0/components/BrickExpression.tsx index 71d36a94..68b56ddc 100644 --- a/modules/masonry/src/brick/design0/components/BrickExpression.tsx +++ b/modules/masonry/src/brick/design0/components/BrickExpression.tsx @@ -1,9 +1,7 @@ import type { JSX } from 'react'; import type { IBrickExpression, TBrickCoords } from '@/@types/brick'; -// ------------------------------------------------------------------------------------------------- - -export default function ({ +export default function BrickExpression({ instance, coords = { x: 0, y: 0 }, }: { diff --git a/modules/masonry/src/brick/design0/components/BrickStatement.tsx b/modules/masonry/src/brick/design0/components/BrickStatement.tsx index c0bd6db8..748055b9 100644 --- a/modules/masonry/src/brick/design0/components/BrickStatement.tsx +++ b/modules/masonry/src/brick/design0/components/BrickStatement.tsx @@ -1,9 +1,7 @@ import type { JSX } from 'react'; import type { IBrickStatement, TBrickCoords } from '@/@types/brick'; -// ------------------------------------------------------------------------------------------------- - -export default function ({ +export default function BrickStatement({ instance, coords = { x: 0, y: 0 }, }: { diff --git a/modules/masonry/src/brick/design0/components/BrickWrapper.tsx b/modules/masonry/src/brick/design0/components/BrickWrapper.tsx new file mode 100644 index 00000000..e69de29b From bd52b37bd1f96fd121e32daff156a4056ac86dc4 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Fri, 6 Sep 2024 13:05:31 +0530 Subject: [PATCH 53/58] feat(masonry): Update factory and create components --- .../masonry/src/brick/design0/BrickBlock.ts | 4 + .../masonry/src/brick/design0/BrickData.ts | 11 +- .../src/brick/design0/BrickExpression.ts | 16 +- .../src/brick/design0/BrickStatement.ts | 36 +-- .../src/brick/design0/brickFactory.spec.ts | 217 ++++++++---------- .../brick/design0/components/BrickBlock.tsx | 48 ++-- .../brick/design0/components/BrickData.tsx | 50 ++-- .../design0/components/BrickExpression.tsx | 48 ++-- .../design0/components/BrickStatement.tsx | 48 ++-- .../brick/design0/components/BrickWrapper.tsx | 109 +++++++++ 10 files changed, 358 insertions(+), 229 deletions(-) diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index 9271201a..ef3878e7 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -115,4 +115,8 @@ export default class BrickBlock extends BrickModelBlock { public setBoundingBoxNest(extent: TExtent): void { this._boundingBoxNest = extent; } + + public setHighlighted(highlighted: boolean): void { + this._highlighted = highlighted; + } } diff --git a/modules/masonry/src/brick/design0/BrickData.ts b/modules/masonry/src/brick/design0/BrickData.ts index b8b3b5f3..a219da6e 100644 --- a/modules/masonry/src/brick/design0/BrickData.ts +++ b/modules/masonry/src/brick/design0/BrickData.ts @@ -2,8 +2,6 @@ import type { TBrickRenderPropsData, TColor, TCoords, TExtent } from '@/@types/b import { BrickModelData } from '../model'; import { generatePath } from '../utils/path'; -// ------------------------------------------------------------------------------------------------- - /** * @class * Final class that defines a data brick. @@ -33,12 +31,11 @@ export default class BrickData extends BrickModelData { hasNotchInsTop: false, hasNotchInsBot: false, scale: this._scale, - innerLengthX: 100, // This could be dynamic based on text size or other criteria + innerLengthX: 100, argHeights: [], }); } - // Getter for bounding box dimensions of the brick public get boundingBox(): TExtent { return { width: this._pathResults.bBoxBrick.extent.width, @@ -46,7 +43,6 @@ export default class BrickData extends BrickModelData { }; } - // Getter for fixed connection points of the brick public get connPointsFixed(): Record<'argOutgoing', { extent: TExtent; coords: TCoords }> { return { argOutgoing: { @@ -56,7 +52,6 @@ export default class BrickData extends BrickModelData { }; } - // Getter for properties required to render the data brick graphic public get renderProps(): TBrickRenderPropsData { return { path: this._pathResults.path, @@ -69,22 +64,18 @@ export default class BrickData extends BrickModelData { }; } - // Setter for dynamic property public setDynamic(dynamic: boolean): void { this._dynamic = dynamic; } - // Setter for value property public setValue(value: boolean | number | string): void { this._value = value; } - // Setter for input type property public setInput(input: 'boolean' | 'number' | 'string' | 'options'): void { this._input = input; } - // Setter for highlighted property public setHighlighted(highlighted: boolean): void { this._highlighted = highlighted; } diff --git a/modules/masonry/src/brick/design0/BrickExpression.ts b/modules/masonry/src/brick/design0/BrickExpression.ts index 7fb2b974..4b9fd0e4 100644 --- a/modules/masonry/src/brick/design0/BrickExpression.ts +++ b/modules/masonry/src/brick/design0/BrickExpression.ts @@ -14,7 +14,6 @@ export default class BrickExpression extends BrickModelExpression { constructor(params: { uuid: string; name: string; - label: string; glyph?: string; colorBg: TColor; @@ -22,13 +21,7 @@ export default class BrickExpression extends BrickModelExpression { colorBgHighlight: TColor; colorFgHighlight: TColor; outline: TColor; - - args: { - /** unique identifier of the argument */ - id: string; - /** label for the argument */ - label: string; - }[]; + args: { id: string; label: string }[]; }) { super(params); @@ -59,7 +52,6 @@ export default class BrickExpression extends BrickModelExpression { }; } - // Implementation of argument connection points getter public get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } } { const results: { [id: string]: { extent: TExtent; coords: TCoords } } = {}; @@ -76,11 +68,9 @@ export default class BrickExpression extends BrickModelExpression { public get renderProps(): TBrickRenderPropsExpression { return { path: this._pathResults.path, - label: this._label, labelArgs: this._args.map(({ label }) => label), boundingBoxArgs: this._args.map(({ id }) => this._boundingBoxArgs[id]), - glyph: this._glyph, colorBg: !this._highlighted ? this._colorBg : this._colorBgHighlight, colorFg: !this._highlighted ? this._colorFg : this._colorFgHighlight, @@ -92,4 +82,8 @@ export default class BrickExpression extends BrickModelExpression { public setBoundingBoxArg(id: string, extent: TExtent): void { this._boundingBoxArgs[id] = extent; } + + public setHighlighted(highlighted: boolean): void { + this._highlighted = highlighted; + } } diff --git a/modules/masonry/src/brick/design0/BrickStatement.ts b/modules/masonry/src/brick/design0/BrickStatement.ts index f4c09291..7dae72d6 100644 --- a/modules/masonry/src/brick/design0/BrickStatement.ts +++ b/modules/masonry/src/brick/design0/BrickStatement.ts @@ -16,14 +16,7 @@ export default class BrickStatement extends BrickModelStatement { name: string; label: string; glyph: string; - args: Record< - string, - { - label: string; - dataType: string; // Change from TBrickArgDataType to string for compatibility - meta: unknown; - } - >; + args: { id: string; label: string }[]; colorBg: TColor; colorFg: TColor; colorBgHighlight: TColor; @@ -33,25 +26,16 @@ export default class BrickStatement extends BrickModelStatement { connectAbove: boolean; connectBelow: boolean; }) { - // Convert `args` to an array - const formattedArgs = Object.keys(params.args).map((id) => ({ - id, - label: params.args[id].label, - })); - - super({ - ...params, - args: formattedArgs, - }); + super(params); this._pathResults = generatePath({ hasNest: false, hasNotchArg: false, - hasNotchInsTop: this._connectAbove, - hasNotchInsBot: this._connectBelow, + hasNotchInsTop: params.connectAbove, + hasNotchInsBot: params.connectBelow, scale: this._scale, innerLengthX: 100, - argHeights: Array.from({ length: formattedArgs.length }, () => 17), + argHeights: Array.from({ length: params.args.length }, () => 17), }); } @@ -81,10 +65,10 @@ export default class BrickStatement extends BrickModelStatement { public get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } } { const results: { [id: string]: { extent: TExtent; coords: TCoords } } = {}; - Object.keys(this._args).forEach((id) => { + this._args.forEach(({ id }, index) => { results[id] = { extent: { width: 10, height: 10 }, // Example extent - coords: { x: 0, y: 0 }, // Example coordinates calculation + coords: { x: 0, y: index * 20 }, // Example coordinates calculation }; }); @@ -95,8 +79,8 @@ export default class BrickStatement extends BrickModelStatement { return { path: this._pathResults.path, label: this._label, - labelArgs: Object.values(this._args).map(({ label }) => label), - boundingBoxArgs: Object.keys(this._args).map((id) => this._boundingBoxArgs[id]), + labelArgs: this._args.map(({ label }) => label), + boundingBoxArgs: this._args.map(({ id }) => this._boundingBoxArgs[id]), glyph: this._glyph, colorBg: !this._highlighted ? this._colorBg : this._colorBgHighlight, colorFg: !this._highlighted ? this._colorFg : this._colorFgHighlight, @@ -118,6 +102,6 @@ export default class BrickStatement extends BrickModelStatement { } public setHighlighted(highlighted: boolean): void { - this.highlighted = highlighted; + this._highlighted = highlighted; } } diff --git a/modules/masonry/src/brick/design0/brickFactory.spec.ts b/modules/masonry/src/brick/design0/brickFactory.spec.ts index 9bfd40a7..9774f996 100644 --- a/modules/masonry/src/brick/design0/brickFactory.spec.ts +++ b/modules/masonry/src/brick/design0/brickFactory.spec.ts @@ -3,167 +3,136 @@ import { createBrickData, createBrickExpression, createBrickStatement, - addBrickToWarehouse, getBrickFromWarehouse, deleteBrickFromWarehouse, } from './brickFactory'; -import BrickBlock from './BrickBlock'; -import BrickData from './BrickData'; -import BrickExpression from './BrickExpression'; -import BrickStatement from './BrickStatement'; +import type { TColor } from '@/@types/brick'; -describe('Factory Functions', () => { - test('createBrickBlock creates a BrickBlock instance', () => { - const block = createBrickBlock({ - name: 'Block', - label: 'Label', - glyph: 'Glyph', - args: { - arg1: { - label: 'Arg1', - dataType: 'string', - meta: { argId: '1', argLabel: 'Arg1', argTypeIncoming: 'string' }, - }, - }, - colorBg: 'red', - colorFg: 'blue', - colorBgHighlight: 'pink', - colorFgHighlight: 'cyan', - outline: 'black', +// Mock color data for testing +const mockColor: TColor = '#FFFFFF'; + +// Test suite for BrickFactory +describe('BrickFactory', () => { + it('should create a BrickBlock and add it to the warehouse', () => { + const brick = createBrickBlock({ + name: 'TestBlock', + label: 'BlockLabel', + glyph: '🔲', + args: [{ id: 'arg1', label: 'Arg 1' }], + colorBg: mockColor, + colorFg: mockColor, + colorBgHighlight: mockColor, + colorFgHighlight: mockColor, + outline: mockColor, scale: 1, connectAbove: true, connectBelow: false, - nestLengthY: 20, + nestLengthY: 100, + folded: false, }); - expect(block).toBeInstanceOf(BrickBlock); - expect(block.uuid).toBeDefined(); - expect(block.SVGpath).toBeDefined(); - expect(block.args).toHaveProperty('arg1'); + expect(brick).toBeDefined(); + expect(getBrickFromWarehouse(brick.uuid)).toBe(brick); }); - test('createBrickData creates a BrickData instance', () => { - const data = createBrickData({ - name: 'Data', - label: 'Label', - glyph: 'Glyph', - dataType: 'string', + it('should create a BrickData and add it to the warehouse', () => { + const brick = createBrickData({ + name: 'TestData', + label: 'DataLabel', + glyph: '🔢', dynamic: true, - value: 'Test', - input: 'string', - colorBg: 'green', - colorFg: 'white', - colorBgHighlight: 'lightgreen', - colorFgHighlight: 'lightgrey', - outline: 'black', + value: 42, + input: 'number', + colorBg: mockColor, + colorFg: mockColor, + colorBgHighlight: mockColor, + colorFgHighlight: mockColor, + outline: mockColor, scale: 1, }); - expect(data).toBeInstanceOf(BrickData); - expect(data.uuid).toBeDefined(); - expect(data.SVGpath).toBeDefined(); - expect(data.value).toBe('Test'); + expect(brick).toBeDefined(); + expect(getBrickFromWarehouse(brick.uuid)).toBe(brick); }); - test('createBrickExpression creates a BrickExpression instance', () => { - const expression = createBrickExpression({ - name: 'Expression', - label: 'Label', - glyph: 'Glyph', - dataType: 'number', - args: { - arg1: { label: 'Arg1', dataType: 'number', meta: {} }, - }, - colorBg: 'blue', - colorFg: 'yellow', - colorBgHighlight: 'lightblue', - colorFgHighlight: 'lightyellow', - outline: 'black', + it('should create a BrickExpression and add it to the warehouse', () => { + const brick = createBrickExpression({ + name: 'TestExpression', + label: 'ExpressionLabel', + glyph: '📐', + args: { arg1: { label: 'Arg 1', dataType: 'number', meta: {} } }, + colorBg: mockColor, + colorFg: mockColor, + colorBgHighlight: mockColor, + colorFgHighlight: mockColor, + outline: mockColor, scale: 1, }); - expect(expression).toBeInstanceOf(BrickExpression); - expect(expression.uuid).toBeDefined(); - expect(expression.SVGpath).toBeDefined(); - expect(expression.args).toHaveProperty('arg1'); + expect(brick).toBeDefined(); + expect(getBrickFromWarehouse(brick.uuid)).toBe(brick); }); - test('createBrickStatement creates a BrickStatement instance', () => { - const statement = createBrickStatement({ - name: 'Statement', - label: 'Label', - glyph: 'Glyph', - args: { - arg1: { label: 'Arg1', dataType: 'boolean', meta: {} }, - }, - colorBg: 'orange', - colorFg: 'purple', - colorBgHighlight: 'lightorange', - colorFgHighlight: 'lightpurple', - outline: 'black', + it('should create a BrickStatement and add it to the warehouse', () => { + const brick = createBrickStatement({ + name: 'TestStatement', + label: 'StatementLabel', + glyph: '📄', + args: { arg1: { label: 'Arg 1', dataType: 'string', meta: {} } }, + colorBg: mockColor, + colorFg: mockColor, + colorBgHighlight: mockColor, + colorFgHighlight: mockColor, + outline: mockColor, scale: 1, connectAbove: true, - connectBelow: false, + connectBelow: true, }); - expect(statement).toBeInstanceOf(BrickStatement); - expect(statement.uuid).toBeDefined(); - expect(statement.SVGpath).toBeDefined(); - expect(statement.args).toHaveProperty('arg1'); + expect(brick).toBeDefined(); + expect(getBrickFromWarehouse(brick.uuid)).toBe(brick); }); -}); -describe('Warehouse Module', () => { - test('addBrickToWarehouse adds a Brick instance to the warehouse', () => { + it('should retrieve a brick from the warehouse by its UUID', () => { const brick = createBrickBlock({ - name: 'Block', - label: 'Label', - glyph: 'Glyph', - args: { - arg1: { - label: 'Arg1', - dataType: 'string', - meta: { argId: '1', argLabel: 'Arg1', argTypeIncoming: 'string' }, - }, - }, - colorBg: 'red', - colorFg: 'blue', - colorBgHighlight: 'pink', - colorFgHighlight: 'cyan', - outline: 'black', + name: 'RetrieveBlock', + label: 'RetrieveLabel', + glyph: '🔲', + args: [{ id: 'arg2', label: 'Arg 2' }], + colorBg: mockColor, + colorFg: mockColor, + colorBgHighlight: mockColor, + colorFgHighlight: mockColor, + outline: mockColor, scale: 1, connectAbove: true, - connectBelow: false, - nestLengthY: 20, + connectBelow: true, + nestLengthY: 200, }); - addBrickToWarehouse(brick); - const storedBrick = getBrickFromWarehouse(brick.uuid); - expect(storedBrick).toBe(brick); + const retrievedBrick = getBrickFromWarehouse(brick.uuid); + expect(retrievedBrick).toBe(brick); }); - test('deleteBrickFromWarehouse removes a Brick instance from the warehouse', () => { - const brick = createBrickStatement({ - name: 'Statement', - label: 'Label', - glyph: 'Glyph', - args: { - arg1: { label: 'Arg1', dataType: 'boolean', meta: {} }, - }, - colorBg: 'orange', - colorFg: 'purple', - colorBgHighlight: 'lightorange', - colorFgHighlight: 'lightpurple', - outline: 'black', + it('should delete a brick from the warehouse by its UUID', () => { + const brick = createBrickBlock({ + name: 'DeleteBlock', + label: 'DeleteLabel', + glyph: '🔲', + args: [{ id: 'arg3', label: 'Arg 3' }], + colorBg: mockColor, + colorFg: mockColor, + colorBgHighlight: mockColor, + colorFgHighlight: mockColor, + outline: mockColor, scale: 1, - connectAbove: true, - connectBelow: false, + connectAbove: false, + connectBelow: true, + nestLengthY: 50, }); - addBrickToWarehouse(brick); - const isDeleted = deleteBrickFromWarehouse(brick.uuid); - const storedBrick = getBrickFromWarehouse(brick.uuid); - expect(isDeleted).toBe(true); - expect(storedBrick).toBeUndefined(); + const wasDeleted = deleteBrickFromWarehouse(brick.uuid); + expect(wasDeleted).toBe(true); + expect(getBrickFromWarehouse(brick.uuid)).toBeUndefined(); }); }); diff --git a/modules/masonry/src/brick/design0/components/BrickBlock.tsx b/modules/masonry/src/brick/design0/components/BrickBlock.tsx index 646ba5fc..4fa2f1e4 100644 --- a/modules/masonry/src/brick/design0/components/BrickBlock.tsx +++ b/modules/masonry/src/brick/design0/components/BrickBlock.tsx @@ -1,26 +1,46 @@ -import type { JSX } from 'react'; -import type { IBrickBlock, TBrickCoords } from '@/@types/brick'; +import React from 'react'; +import type { IBrickBlock } from '@/@types/brick'; -export default function BrickBlock({ - instance, - coords = { x: 0, y: 0 }, -}: { +/** + * Props for BrickBlock component. + */ +interface BrickBlockProps { instance: IBrickBlock; - coords?: TBrickCoords; -}): JSX.Element { +} + +/** + * Component to render a BrickBlock. + * @param props - The props for BrickBlock. + * @returns JSX.Element representing the BrickBlock as an SVG. + */ +const BrickBlockComponent: React.FC = ({ instance }) => { + const renderProps = instance.renderProps(); + const { path: SVGpath, label, glyph, colorBg, colorFg, outline, scale } = renderProps; + return ( - + + {glyph && ( + + {glyph} + + )} + {label && ( + + {label} + + )} ); -} +}; + +export default BrickBlockComponent; diff --git a/modules/masonry/src/brick/design0/components/BrickData.tsx b/modules/masonry/src/brick/design0/components/BrickData.tsx index 476ffd46..d9d362a6 100644 --- a/modules/masonry/src/brick/design0/components/BrickData.tsx +++ b/modules/masonry/src/brick/design0/components/BrickData.tsx @@ -1,28 +1,46 @@ -import type { JSX } from 'react'; -import type { IBrickData, TBrickCoords } from '@/@types/brick'; +import React from 'react'; +import type { IBrickData } from '@/@types/brick'; -// ------------------------------------------------------------------------------------------------- +/** + * Props for BrickData component. + */ +interface BrickDataProps { + instance: IBrickData; // The instance of BrickData +} + +/** + * Component to render a BrickData. + * @param props - The props for BrickData. + * @returns JSX.Element representing the BrickData as an SVG. + */ +const BrickDataComponent: React.FC = ({ instance }) => { + const renderProps = instance.renderProps(); + const { path: SVGpath, label, glyph, colorBg, colorFg, outline, scale } = renderProps; -export default function BrickData({ - instance, - coords = { x: 0, y: 0 }, -}: { - instance: IBrickData; - coords?: TBrickCoords; -}): JSX.Element { return ( - + + {glyph && ( + + {glyph} + + )} + {label && ( + + {label} + + )} ); -} +}; + +export default BrickDataComponent; diff --git a/modules/masonry/src/brick/design0/components/BrickExpression.tsx b/modules/masonry/src/brick/design0/components/BrickExpression.tsx index 68b56ddc..948bca67 100644 --- a/modules/masonry/src/brick/design0/components/BrickExpression.tsx +++ b/modules/masonry/src/brick/design0/components/BrickExpression.tsx @@ -1,26 +1,46 @@ -import type { JSX } from 'react'; -import type { IBrickExpression, TBrickCoords } from '@/@types/brick'; +import React from 'react'; +import type { IBrickExpression } from '@/@types/brick'; -export default function BrickExpression({ - instance, - coords = { x: 0, y: 0 }, -}: { +/** + * Props for BrickExpression component. + */ +interface BrickExpressionProps { instance: IBrickExpression; - coords?: TBrickCoords; -}): JSX.Element { +} + +/** + * Component to render a BrickExpression. + * @param props - The props for BrickExpression. + * @returns JSX.Element representing the BrickExpression as an SVG. + */ +const BrickExpressionComponent: React.FC = ({ instance }) => { + const renderProps = instance.renderProps(); + const { path: SVGpath, label, glyph, colorBg, colorFg, outline, scale } = renderProps; + return ( - + + {glyph && ( + + {glyph} + + )} + {label && ( + + {label} + + )} ); -} +}; + +export default BrickExpressionComponent; diff --git a/modules/masonry/src/brick/design0/components/BrickStatement.tsx b/modules/masonry/src/brick/design0/components/BrickStatement.tsx index 748055b9..49127520 100644 --- a/modules/masonry/src/brick/design0/components/BrickStatement.tsx +++ b/modules/masonry/src/brick/design0/components/BrickStatement.tsx @@ -1,26 +1,46 @@ -import type { JSX } from 'react'; -import type { IBrickStatement, TBrickCoords } from '@/@types/brick'; +import React from 'react'; +import type { IBrickStatement } from '@/@types/brick'; -export default function BrickStatement({ - instance, - coords = { x: 0, y: 0 }, -}: { +/** + * Props for BrickStatement component. + */ +interface BrickStatementProps { instance: IBrickStatement; - coords?: TBrickCoords; -}): JSX.Element { +} + +/** + * Component to render a BrickStatement. + * @param props - The props for BrickStatement. + * @returns JSX.Element representing the BrickStatement as an SVG. + */ +const BrickStatementComponent: React.FC = ({ instance }) => { + const renderProps = instance.renderProps(); + const { path: SVGpath, label, glyph, colorBg, colorFg, outline, scale } = renderProps; + return ( - + + {glyph && ( + + {glyph} + + )} + {label && ( + + {label} + + )} ); -} +}; + +export default BrickStatementComponent; diff --git a/modules/masonry/src/brick/design0/components/BrickWrapper.tsx b/modules/masonry/src/brick/design0/components/BrickWrapper.tsx index e69de29b..27583031 100644 --- a/modules/masonry/src/brick/design0/components/BrickWrapper.tsx +++ b/modules/masonry/src/brick/design0/components/BrickWrapper.tsx @@ -0,0 +1,109 @@ +import React from 'react'; +import { + createBrickBlock, + createBrickData, + createBrickExpression, + createBrickStatement, +} from '../brickFactory'; +import BrickDataComponent from './BrickData'; +import BrickBlockComponent from './BrickBlock'; +import BrickExpressionComponent from './BrickExpression'; +import BrickStatementComponent from './BrickStatement'; +import type { TColor } from '@/@types/brick'; + +type BrickType = 'block' | 'data' | 'expression' | 'statement'; + +interface BrickWrapperProps { + type: BrickType; + params: + | { + name: string; + label: string; + glyph: string; + args: { id: string; label: string }[]; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + scale: number; + connectAbove: boolean; + connectBelow: boolean; + nestLengthY: number; + folded?: boolean; + } + | { + name: string; + label: string; + glyph: string; + dynamic: boolean; + value?: boolean | number | string; + input?: 'boolean' | 'number' | 'string' | 'options'; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + scale: number; + } + | { + name: string; + label: string; + glyph: string; + args: Record; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + scale: number; + } + | { + name: string; + label: string; + glyph: string; + args: Record; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + scale: number; + connectAbove: boolean; + connectBelow: boolean; + }; +} + +/** + * Higher-order component to wrap different brick components. + * @param props - The props for BrickWrapper. + * @returns JSX.Element representing the specific brick component. + */ +const BrickWrapper: React.FC = ({ type, params }) => { + switch (type) { + case 'block': { + const instance = createBrickBlock(params as any); + return ; + } + + case 'data': { + const instance = createBrickData(params as any); + return ; + } + + case 'expression': { + const instance = createBrickExpression(params as any); + return ; + } + + case 'statement': { + const instance = createBrickStatement(params as any); + return ; + } + + default: + return null; + } +}; + +export default BrickWrapper; From f2d9c12500fa91ef2516dc72edf8d77bc0c9c536 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Fri, 6 Sep 2024 13:18:40 +0530 Subject: [PATCH 54/58] fix(masonry): remove any type in BrickWrapper --- .../brick/design0/components/BrickWrapper.tsx | 68 +++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/modules/masonry/src/brick/design0/components/BrickWrapper.tsx b/modules/masonry/src/brick/design0/components/BrickWrapper.tsx index 27583031..7ba02052 100644 --- a/modules/masonry/src/brick/design0/components/BrickWrapper.tsx +++ b/modules/masonry/src/brick/design0/components/BrickWrapper.tsx @@ -82,22 +82,82 @@ interface BrickWrapperProps { const BrickWrapper: React.FC = ({ type, params }) => { switch (type) { case 'block': { - const instance = createBrickBlock(params as any); + const instance = createBrickBlock( + params as { + name: string; + label: string; + glyph: string; + args: { id: string; label: string }[]; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + scale: number; + connectAbove: boolean; + connectBelow: boolean; + nestLengthY: number; + folded?: boolean; + }, + ); return ; } case 'data': { - const instance = createBrickData(params as any); + const instance = createBrickData( + params as { + name: string; + label: string; + glyph: string; + dynamic: boolean; + value?: boolean | number | string; + input?: 'boolean' | 'number' | 'string' | 'options'; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + scale: number; + }, + ); return ; } case 'expression': { - const instance = createBrickExpression(params as any); + const instance = createBrickExpression( + params as { + name: string; + label: string; + glyph: string; + args: Record; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + scale: number; + }, + ); return ; } case 'statement': { - const instance = createBrickStatement(params as any); + const instance = createBrickStatement( + params as { + name: string; + label: string; + glyph: string; + args: Record; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + scale: number; + connectAbove: boolean; + connectBelow: boolean; + }, + ); return ; } From dfd550161ad2b34928cb8b3d9295242afb5a5d97 Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Sat, 7 Sep 2024 19:48:36 +0530 Subject: [PATCH 55/58] fix(masonry): Fix errors in Wrapper component and update individual components with all props --- .../brick/design0/components/BrickBlock.tsx | 71 +++--- .../brick/design0/components/BrickData.tsx | 61 +++-- .../design0/components/BrickExpression.tsx | 71 +++--- .../design0/components/BrickStatement.tsx | 71 +++--- .../brick/design0/components/BrickWrapper.tsx | 220 +++++++----------- 5 files changed, 227 insertions(+), 267 deletions(-) diff --git a/modules/masonry/src/brick/design0/components/BrickBlock.tsx b/modules/masonry/src/brick/design0/components/BrickBlock.tsx index 4fa2f1e4..7f81d1d7 100644 --- a/modules/masonry/src/brick/design0/components/BrickBlock.tsx +++ b/modules/masonry/src/brick/design0/components/BrickBlock.tsx @@ -1,46 +1,55 @@ import React from 'react'; -import type { IBrickBlock } from '@/@types/brick'; +import type { TBrickRenderPropsBlock, TCoords } from '@/@types/brick'; -/** - * Props for BrickBlock component. - */ interface BrickBlockProps { - instance: IBrickBlock; + instance: TBrickRenderPropsBlock; + coords?: TCoords; } -/** - * Component to render a BrickBlock. - * @param props - The props for BrickBlock. - * @returns JSX.Element representing the BrickBlock as an SVG. - */ -const BrickBlockComponent: React.FC = ({ instance }) => { - const renderProps = instance.renderProps(); - const { path: SVGpath, label, glyph, colorBg, colorFg, outline, scale } = renderProps; - +const BrickBlock: React.FC = ({ instance, coords = { x: 0, y: 0 } }) => { return ( - + - {glyph && ( - - {glyph} + + {instance.label} + + {instance.labelArgs.map((argLabel, index) => ( + + {argLabel} - )} - {label && ( - - {label} + ))} + {instance.glyph && ( + + {instance.glyph} )} ); }; -export default BrickBlockComponent; +export default BrickBlock; diff --git a/modules/masonry/src/brick/design0/components/BrickData.tsx b/modules/masonry/src/brick/design0/components/BrickData.tsx index d9d362a6..05da3db0 100644 --- a/modules/masonry/src/brick/design0/components/BrickData.tsx +++ b/modules/masonry/src/brick/design0/components/BrickData.tsx @@ -1,46 +1,43 @@ import React from 'react'; -import type { IBrickData } from '@/@types/brick'; +import type { TBrickRenderPropsData, TCoords } from '@/@types/brick'; -/** - * Props for BrickData component. - */ interface BrickDataProps { - instance: IBrickData; // The instance of BrickData + instance: TBrickRenderPropsData; + coords?: TCoords; } -/** - * Component to render a BrickData. - * @param props - The props for BrickData. - * @returns JSX.Element representing the BrickData as an SVG. - */ -const BrickDataComponent: React.FC = ({ instance }) => { - const renderProps = instance.renderProps(); - const { path: SVGpath, label, glyph, colorBg, colorFg, outline, scale } = renderProps; - +const BrickData: React.FC = ({ instance, coords = { x: 0, y: 0 } }) => { return ( - + - {glyph && ( - - {glyph} - - )} - {label && ( - - {label} + + {instance.label} + + {instance.glyph && ( + + {instance.glyph} )} ); }; -export default BrickDataComponent; +export default BrickData; diff --git a/modules/masonry/src/brick/design0/components/BrickExpression.tsx b/modules/masonry/src/brick/design0/components/BrickExpression.tsx index 948bca67..6fd659ae 100644 --- a/modules/masonry/src/brick/design0/components/BrickExpression.tsx +++ b/modules/masonry/src/brick/design0/components/BrickExpression.tsx @@ -1,46 +1,55 @@ import React from 'react'; -import type { IBrickExpression } from '@/@types/brick'; +import type { TBrickRenderPropsExpression, TCoords } from '@/@types/brick'; -/** - * Props for BrickExpression component. - */ interface BrickExpressionProps { - instance: IBrickExpression; + instance: TBrickRenderPropsExpression; + coords?: TCoords; } -/** - * Component to render a BrickExpression. - * @param props - The props for BrickExpression. - * @returns JSX.Element representing the BrickExpression as an SVG. - */ -const BrickExpressionComponent: React.FC = ({ instance }) => { - const renderProps = instance.renderProps(); - const { path: SVGpath, label, glyph, colorBg, colorFg, outline, scale } = renderProps; - +const BrickExpression: React.FC = ({ instance, coords = { x: 0, y: 0 } }) => { return ( - + - {glyph && ( - - {glyph} + + {instance.label} + + {instance.labelArgs.map((argLabel, index) => ( + + {argLabel} - )} - {label && ( - - {label} + ))} + {instance.glyph && ( + + {instance.glyph} )} ); }; -export default BrickExpressionComponent; +export default BrickExpression; diff --git a/modules/masonry/src/brick/design0/components/BrickStatement.tsx b/modules/masonry/src/brick/design0/components/BrickStatement.tsx index 49127520..f1595297 100644 --- a/modules/masonry/src/brick/design0/components/BrickStatement.tsx +++ b/modules/masonry/src/brick/design0/components/BrickStatement.tsx @@ -1,46 +1,55 @@ import React from 'react'; -import type { IBrickStatement } from '@/@types/brick'; +import type { TBrickRenderPropsStatement, TCoords } from '@/@types/brick'; -/** - * Props for BrickStatement component. - */ interface BrickStatementProps { - instance: IBrickStatement; + instance: TBrickRenderPropsStatement; + coords?: TCoords; } -/** - * Component to render a BrickStatement. - * @param props - The props for BrickStatement. - * @returns JSX.Element representing the BrickStatement as an SVG. - */ -const BrickStatementComponent: React.FC = ({ instance }) => { - const renderProps = instance.renderProps(); - const { path: SVGpath, label, glyph, colorBg, colorFg, outline, scale } = renderProps; - +const BrickStatement: React.FC = ({ instance, coords = { x: 0, y: 0 } }) => { return ( - + - {glyph && ( - - {glyph} + + {instance.label} + + {instance.labelArgs.map((argLabel, index) => ( + + {argLabel} - )} - {label && ( - - {label} + ))} + {instance.glyph && ( + + {instance.glyph} )} ); }; -export default BrickStatementComponent; +export default BrickStatement; diff --git a/modules/masonry/src/brick/design0/components/BrickWrapper.tsx b/modules/masonry/src/brick/design0/components/BrickWrapper.tsx index 7ba02052..3a1a0425 100644 --- a/modules/masonry/src/brick/design0/components/BrickWrapper.tsx +++ b/modules/masonry/src/brick/design0/components/BrickWrapper.tsx @@ -5,162 +5,98 @@ import { createBrickExpression, createBrickStatement, } from '../brickFactory'; -import BrickDataComponent from './BrickData'; import BrickBlockComponent from './BrickBlock'; +import BrickDataComponent from './BrickData'; import BrickExpressionComponent from './BrickExpression'; import BrickStatementComponent from './BrickStatement'; -import type { TColor } from '@/@types/brick'; +import type { + TBrickRenderPropsBlock, + TBrickRenderPropsData, + TBrickRenderPropsExpression, + TBrickRenderPropsStatement, + TCoords, +} from '@/@types/brick'; -type BrickType = 'block' | 'data' | 'expression' | 'statement'; +type TBrickWrapperProps = + | { type: 'block'; params: TBrickRenderPropsBlock; coords?: TCoords } + | { type: 'data'; params: TBrickRenderPropsData; coords?: TCoords } + | { type: 'expression'; params: TBrickRenderPropsExpression; coords?: TCoords } + | { type: 'statement'; params: TBrickRenderPropsStatement; coords?: TCoords }; -interface BrickWrapperProps { - type: BrickType; - params: - | { - name: string; - label: string; - glyph: string; - args: { id: string; label: string }[]; - colorBg: TColor; - colorFg: TColor; - colorBgHighlight: TColor; - colorFgHighlight: TColor; - outline: TColor; - scale: number; - connectAbove: boolean; - connectBelow: boolean; - nestLengthY: number; - folded?: boolean; - } - | { - name: string; - label: string; - glyph: string; - dynamic: boolean; - value?: boolean | number | string; - input?: 'boolean' | 'number' | 'string' | 'options'; - colorBg: TColor; - colorFg: TColor; - colorBgHighlight: TColor; - colorFgHighlight: TColor; - outline: TColor; - scale: number; - } - | { - name: string; - label: string; - glyph: string; - args: Record; - colorBg: TColor; - colorFg: TColor; - colorBgHighlight: TColor; - colorFgHighlight: TColor; - outline: TColor; - scale: number; - } - | { - name: string; - label: string; - glyph: string; - args: Record; - colorBg: TColor; - colorFg: TColor; - colorBgHighlight: TColor; - colorFgHighlight: TColor; - outline: TColor; - scale: number; - connectAbove: boolean; - connectBelow: boolean; - }; -} - -/** - * Higher-order component to wrap different brick components. - * @param props - The props for BrickWrapper. - * @returns JSX.Element representing the specific brick component. - */ -const BrickWrapper: React.FC = ({ type, params }) => { +const BrickWrapper: React.FC = ({ type, params, coords }) => { switch (type) { case 'block': { - const instance = createBrickBlock( - params as { - name: string; - label: string; - glyph: string; - args: { id: string; label: string }[]; - colorBg: TColor; - colorFg: TColor; - colorBgHighlight: TColor; - colorFgHighlight: TColor; - outline: TColor; - scale: number; - connectAbove: boolean; - connectBelow: boolean; - nestLengthY: number; - folded?: boolean; - }, - ); - return ; + const instance = createBrickBlock({ + name: params.label, + label: params.label, + glyph: params.glyph || '', + args: params.labelArgs.map((label, index) => ({ id: `arg${index}`, label })), + colorBg: params.colorBg, + colorFg: params.colorFg, + colorBgHighlight: params.colorBg, + colorFgHighlight: params.colorFg, + outline: params.outline, + scale: params.scale, + connectAbove: true, + connectBelow: true, + nestLengthY: 0, + folded: params.folded, + }); + return ; } - case 'data': { - const instance = createBrickData( - params as { - name: string; - label: string; - glyph: string; - dynamic: boolean; - value?: boolean | number | string; - input?: 'boolean' | 'number' | 'string' | 'options'; - colorBg: TColor; - colorFg: TColor; - colorBgHighlight: TColor; - colorFgHighlight: TColor; - outline: TColor; - scale: number; - }, - ); - return ; + const instance = createBrickData({ + name: params.label, + label: params.label, + glyph: params.glyph || '', + dynamic: true, + colorBg: params.colorBg, + colorFg: params.colorFg, + colorBgHighlight: params.colorBg, + colorFgHighlight: params.colorFg, + outline: params.outline, + scale: params.scale, + }); + return ; } - case 'expression': { - const instance = createBrickExpression( - params as { - name: string; - label: string; - glyph: string; - args: Record; - colorBg: TColor; - colorFg: TColor; - colorBgHighlight: TColor; - colorFgHighlight: TColor; - outline: TColor; - scale: number; - }, - ); - return ; + const instance = createBrickExpression({ + name: params.label, + label: params.label, + glyph: params.glyph || '', + args: params.labelArgs.reduce((acc, label, index) => { + acc[`arg${index}`] = { label, dataType: 'unknown', meta: {} }; + return acc; + }, {} as Record), + colorBg: params.colorBg, + colorFg: params.colorFg, + colorBgHighlight: params.colorBg, + colorFgHighlight: params.colorFg, + outline: params.outline, + scale: params.scale, + }); + return ; } - case 'statement': { - const instance = createBrickStatement( - params as { - name: string; - label: string; - glyph: string; - args: Record; - colorBg: TColor; - colorFg: TColor; - colorBgHighlight: TColor; - colorFgHighlight: TColor; - outline: TColor; - scale: number; - connectAbove: boolean; - connectBelow: boolean; - }, - ); - return ; + const instance = createBrickStatement({ + name: params.label, + label: params.label, + glyph: params.glyph || '', + args: params.labelArgs.reduce((acc, label, index) => { + acc[`arg${index}`] = { label, dataType: 'unknown', meta: {} }; + return acc; + }, {} as Record), + colorBg: params.colorBg, + colorFg: params.colorFg, + colorBgHighlight: params.colorBg, + colorFgHighlight: params.colorFg, + outline: params.outline, + scale: params.scale, + connectAbove: true, + connectBelow: true, + }); + return ; } - default: return null; } From 54a25988b55ef3cb41033080c2b16c8dd0b5bfd5 Mon Sep 17 00:00:00 2001 From: Anindya Kundu Date: Sat, 7 Sep 2024 23:15:24 +0530 Subject: [PATCH 56/58] feat(masonry): [block] modify React component and Storybook stories --- modules/masonry/src/@types/brick.d.ts | 5 + .../masonry/src/brick/design0/brickFactory.ts | 2 +- .../brick/design0/components/BrickBlock.tsx | 43 +++--- .../design0/stories/BrickBlock.stories.ts | 14 +- .../brick/stories/components/BrickBlock.tsx | 138 +++++++++--------- 5 files changed, 104 insertions(+), 98 deletions(-) diff --git a/modules/masonry/src/@types/brick.d.ts b/modules/masonry/src/@types/brick.d.ts index d50bac6b..8488cbe8 100644 --- a/modules/masonry/src/@types/brick.d.ts +++ b/modules/masonry/src/@types/brick.d.ts @@ -197,4 +197,9 @@ export interface IBrickBlock extends IBrickInstruction, IBrickNotchInsNestTopSta * @param extent width and height values of the nest area */ setBoundingBoxNest(extent: TExtent): void; + + get connPointsFixed(): Record< + 'insTop' | 'insBottom' | 'insNest', + { extent: TExtent; coords: TCoords } + >; } diff --git a/modules/masonry/src/brick/design0/brickFactory.ts b/modules/masonry/src/brick/design0/brickFactory.ts index 30111620..3dff1270 100644 --- a/modules/masonry/src/brick/design0/brickFactory.ts +++ b/modules/masonry/src/brick/design0/brickFactory.ts @@ -58,7 +58,7 @@ function argsRecordToArray( export function createBrickBlock(params: { name: string; label: string; - glyph: string; + glyph?: string; args: { id: string; label: string }[]; colorBg: TColor; colorFg: TColor; diff --git a/modules/masonry/src/brick/design0/components/BrickBlock.tsx b/modules/masonry/src/brick/design0/components/BrickBlock.tsx index 7f81d1d7..7be85bd6 100644 --- a/modules/masonry/src/brick/design0/components/BrickBlock.tsx +++ b/modules/masonry/src/brick/design0/components/BrickBlock.tsx @@ -1,43 +1,40 @@ import React from 'react'; -import type { TBrickRenderPropsBlock, TCoords } from '@/@types/brick'; +import type { TBrickRenderPropsBlock } from '@/@types/brick'; -interface BrickBlockProps { - instance: TBrickRenderPropsBlock; - coords?: TCoords; -} - -const BrickBlock: React.FC = ({ instance, coords = { x: 0, y: 0 } }) => { +const BrickBlock: React.FC = ({ + path, + label, + labelArgs, + colorBg, + colorFg, + outline, + scale, +}) => { return ( - + - - {instance.label} + + {label} - {instance.labelArgs.map((argLabel, index) => ( + {labelArgs.map((argLabel, index) => ( {argLabel} ))} - {instance.glyph && ( + {/* {glyph && ( = ({ instance, coords = { x: 0, y: 0 > {instance.glyph} - )} + )} */} ); }; diff --git a/modules/masonry/src/brick/design0/stories/BrickBlock.stories.ts b/modules/masonry/src/brick/design0/stories/BrickBlock.stories.ts index 4fcb241c..ef30eb05 100644 --- a/modules/masonry/src/brick/design0/stories/BrickBlock.stories.ts +++ b/modules/masonry/src/brick/design0/stories/BrickBlock.stories.ts @@ -11,8 +11,10 @@ export default { export const NoArgs: Story = { args: { - Component: CBrickBlock, - prototype: MBrickBlock, + View: CBrickBlock, + Model: MBrickBlock, + showIndicators: true, + label: 'Block', args: [], colorBg: 'yellow', @@ -24,10 +26,12 @@ export const NoArgs: Story = { export const WithArgs: Story = { args: { - Component: CBrickBlock, - prototype: MBrickBlock, + View: CBrickBlock, + Model: MBrickBlock, + showIndicators: true, + label: 'Block', - args: ['Label 1'], + args: ['Label 1', 'Label 2'], colorBg: 'yellow', colorFg: 'black', outline: 'red', diff --git a/modules/masonry/src/brick/stories/components/BrickBlock.tsx b/modules/masonry/src/brick/stories/components/BrickBlock.tsx index 516bb38e..c65748b1 100644 --- a/modules/masonry/src/brick/stories/components/BrickBlock.tsx +++ b/modules/masonry/src/brick/stories/components/BrickBlock.tsx @@ -1,30 +1,35 @@ -import BrickWrapper from './BrickWrapper'; import type { JSX } from 'react'; -import type { IBrickBlock, TBrickArgDataType, TBrickColor } from '@/@types/brick'; +import type { IBrickBlock, TBrickRenderPropsBlock, TColor } from '@/@types/brick'; + +import BrickWrapper from './BrickWrapper'; // ------------------------------------------------------------------------------------------------- export default function (props: { - Component: (props: { instance: IBrickBlock; visualIndicators?: JSX.Element }) => JSX.Element; - prototype: new (params: { + View: React.FC; + Model: new (params: { + uuid: string; name: string; + label: string; - glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - colorBg: TBrickColor; - colorFg: TBrickColor; - outline: TBrickColor; - scale: number; + glyph?: string; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; connectAbove: boolean; connectBelow: boolean; + + args: { + /** unique identifier of the argument */ + id: string; + /** label for the argument */ + label: string; + }[]; }) => IBrickBlock; + showIndicators: boolean; + label: string; args: string[]; colorBg: string; @@ -32,91 +37,86 @@ export default function (props: { outline: string; scale: number; }): JSX.Element { - const { Component, prototype, label, args, colorBg, colorFg, outline, scale } = props; + const { View, Model, showIndicators, label, args, colorBg, colorFg, outline, scale } = props; + + const instance = new Model({ + uuid: '', + name: '', - 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, + colorBgHighlight: '', + colorFgHighlight: '', outline, - scale, - glyph: '', connectAbove: true, connectBelow: true, - name: '', + + args: args.map((label, i) => ({ id: `label_${i}`, label })), }); + instance.scale = scale; + 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 */} + {/* Connection point of Top */} - {/* Bottom instruction notch bounding box */} + {/* Connection point of Bottom */} - {/* Top instruction notch inside nesting bounding box */} + {/* Connection point of Nesting */} + + {/* Connection points of Args */} + {Object.values(instance.connPointsArg).map(({ extent, coords }) => ( + + ))} ); return ( - - + + {showIndicators && } ); } From 55c9e860b883a29c3e2b8c5a69b39b4e7589163c Mon Sep 17 00:00:00 2001 From: Karan Palan Date: Sun, 8 Sep 2024 14:02:03 +0530 Subject: [PATCH 57/58] docs(masonry): Add technical specs for brick and stack --- .../docs/technical-specification/Brick.md | 103 +++++++++++++ .../docs/technical-specification/Stack.md | 137 ++++++++++++++++++ 2 files changed, 240 insertions(+) create mode 100644 modules/masonry/docs/technical-specification/Brick.md create mode 100644 modules/masonry/docs/technical-specification/Stack.md diff --git a/modules/masonry/docs/technical-specification/Brick.md b/modules/masonry/docs/technical-specification/Brick.md new file mode 100644 index 00000000..99eef6e3 --- /dev/null +++ b/modules/masonry/docs/technical-specification/Brick.md @@ -0,0 +1,103 @@ +### 1. **`model.ts`**: Abstract Classes + +This file contains the abstract classes that define the blueprint for different types of bricks. These classes are not instantiated directly; instead, they are extended by concrete classes to provide specific implementations. + +#### Abstract Classes + +- **`BrickModel`**: The base class for all brick types. + - **Properties:** + - `uuid: string` - Unique identifier. + - `name: string` - Name for internal bookkeeping. + - `kind: TBrickKind` - Represents the kind (e.g., "instruction" or "argument"). + - `type: TBrickType` - Represents the type (e.g., "data", "expression", "statement", "block"). + - `label: string` - Primary label for display. + - `glyph: string` - Optional glyph icon. + - `colorBg`, `colorFg`, `colorBgHighlight`, `colorFgHighlight`, `outline` - Colors for display. + - `highlighted: boolean` - State indicating whether the brick is highlighted. + - `scale: number` - Scale factor for rendering. + - **Abstract Methods:** + - `get boundingBox(): TExtent` - Returns the bounding box dimensions of the brick. + - `get connPointsFixed(): Record` - Returns fixed connection points. + +- **`BrickModelArgument`**: Extends `BrickModel` for bricks that act as arguments. + - **Abstract Methods:** + - `get connPointsFixed(): Record<'argOutgoing', { extent: TExtent; coords: TCoords }>` - Returns the outgoing connection point for arguments. + +- **`BrickModelInstruction`**: Extends `BrickModel` for instruction bricks. + - **Properties:** + - `connectAbove: boolean` - Indicates if the brick can connect above. + - `connectBelow: boolean` - Indicates if the brick can connect below. + - `args: { id: string; label: string }[]` - List of arguments. + - **Abstract Methods:** + - `get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } }` - Returns connection points for arguments. + - `setBoundingBoxArg(id: string, extent: TExtent): void` - Sets the bounding box for an argument. + +- **`BrickModelData`**: Extends `BrickModelArgument` for data bricks. + - **Properties:** + - `dynamic: boolean` - Indicates if the data brick is dynamic. + - `value?: boolean | number | string` - Value of the data brick. + - `input?: 'boolean' | 'number' | 'string' | 'options'` - Type of input for the data brick. + - **Abstract Methods:** + - `get renderProps(): TBrickRenderPropsData` - Returns properties required to render the data brick. + +- **`BrickModelExpression`**: Extends `BrickModelArgument` for expression bricks. + - **Properties:** + - `args: { id: string; label: string }[]` - List of arguments. + - **Abstract Methods:** + - `get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } }` - Returns connection points for arguments. + - `setBoundingBoxArg(id: string, extent: TExtent): void` - Sets the bounding box for an argument. + - `get renderProps(): TBrickRenderPropsExpression` - Returns properties required to render the expression brick. + +- **`BrickModelStatement`**: Extends `BrickModelInstruction` for statement bricks. + - **Abstract Methods:** + - `get connPointsFixed(): Record<'insTop' | 'insBottom', { extent: TExtent; coords: TCoords }>` - Returns fixed connection points for insertion points. + - `get renderProps(): TBrickRenderPropsStatement` - Returns properties required to render the statement brick. + +- **`BrickModelBlock`**: Extends `BrickModelInstruction` for block bricks. + - **Properties:** + - `folded: boolean` - Indicates if the block brick is folded. + - **Abstract Methods:** + - `get connPointsFixed(): Record<'insTop' | 'insBottom' | 'insNest', { extent: TExtent; coords: TCoords }>` - Returns fixed connection points for block insertion. + - `get renderProps(): TBrickRenderPropsBlock` - Returns properties required to render the block brick. + - `setBoundingBoxNest(extent: TExtent): void` - Sets the bounding box for the nested elements. + +### 2. **Concrete Classes** + +The concrete classes provide specific implementations of the abstract classes. These classes are used to create actual brick instances. + +- **`BrickBlock.ts`**: Concrete implementation of `BrickModelBlock`. + - Provides methods to calculate and return bounding boxes (`boundingBox`, `connPointsFixed`), render properties (`renderProps`), and set bounding boxes (`setBoundingBoxArg`, `setBoundingBoxNest`). + +- **`BrickData.ts`**: Concrete implementation of `BrickModelData`. + - Implements properties for dynamic data (`dynamic`, `value`, `input`), and methods to get connection points (`connPointsFixed`), render properties (`renderProps`), and set various properties (`setDynamic`, `setValue`, `setInput`). + +- **`BrickExpression.ts`**: Concrete implementation of `BrickModelExpression`. + - Manages expressions with arguments, implementing methods to calculate argument connection points (`connPointsArg`), set bounding boxes (`setBoundingBoxArg`), and provide rendering properties (`renderProps`). + +- **`BrickStatement.ts`**: Concrete implementation of `BrickModelStatement`. + - Converts argument objects to arrays, provides methods for fixed and argument connection points (`connPointsFixed`, `connPointsArg`), and rendering properties (`renderProps`). + +### 3. **`BrickFactory.ts`: Factory Functions and Warehouse** + +This file manages the creation of brick instances and their storage in a warehouse for easy retrieval, addition, and deletion. + +- **Warehouse**: A `Map` to store brick instances keyed by their `uuid`. + - Functions: + - `addBrickToWarehouse(brick)`: Adds a brick instance to the warehouse. + - `getBrickFromWarehouse(id)`: Retrieves a brick by its ID. + - `deleteBrickFromWarehouse(id)`: Deletes a brick by its ID. + +- **Factory Functions**: + - `createBrickBlock`, `createBrickData`, `createBrickExpression`, `createBrickStatement`: Functions that create instances of respective brick types and add them to the warehouse. + +### 4. **Components** + +Each brick type has a corresponding React component to handle its visual representation. The components use the `renderProps()` method from the concrete classes to render the brick according to its properties. + +- **`BrickWrapper.tsx`**: A Higher-Order Component (HOC) that wraps individual brick components. + - Retrieves brick instances from the warehouse using factory functions. + - Passes the `renderProps()` from each brick instance to the specific brick component (`BrickBlock`, `BrickData`, `BrickExpression`, `BrickStatement`) for rendering. + +### 5. **Stories** + +- **Storybook Files**: Used to create stories for each brick type. These files demonstrate different states and variations of the bricks, using the factory functions to create instances for visualization. \ No newline at end of file diff --git a/modules/masonry/docs/technical-specification/Stack.md b/modules/masonry/docs/technical-specification/Stack.md new file mode 100644 index 00000000..b89e0eb8 --- /dev/null +++ b/modules/masonry/docs/technical-specification/Stack.md @@ -0,0 +1,137 @@ +### 1. **Config for Brick Stack** + +#### (A) Define the Tree Structure Representing a Brick Stack +- **Tree Structure**: A hierarchical representation where each node is a brick. + - **Nodes**: Represent bricks with unique identifiers (`id`) that link back to their corresponding brick model instances. + - **Chaining of Arguments**: Some bricks will have arguments that connect in a chain-like manner. + - **Nesting of Instructions**: Instructions can be nested within other instructions. + - **Shadow Instructions and Arguments**: Handle bricks that act as shadows or placeholders. + +#### (B) Define the Properties Required to Render the Brick Stack +- **Positioning Information**: Store the relative positions of each brick in the stack to determine how they are rendered visually. +- **Stack Dimensions**: Overall dimensions based on the size of all bricks combined. + +#### (C) Define How Connection Points Will Be Mapped +- **Mapping Connection Points**: For any given connection point, identify: + - Which brick it belongs to. + - Which part of the brick it represents (e.g., if it's an argument connector, specify which argument). +- **Coordinate Storage**: Store coordinates relative to the origin of the brick stack. + +### 2. **Code for Brick Stack** + +#### **Brick Stack Class (Model)** +This class will encapsulate the functionalities required to manage and render the brick stack. It will have the following: + +- **Methods to Set and Get the Current Tree**: + - Manage the current state of the tree structure representing the stack. + +- **Methods to Query the Map of Connection Points**: + - Provide a way to retrieve all connection points and their corresponding bricks. + +- **Method to Return Props for the React Component (View)**: + - Gather all properties needed to render the brick stack in the React component based on the current state. + +#### **Brick Stack Positioning Calculations** +The class will also handle: + +- **Preorder Traversal for Argument Chains**: + - Query brick classes (model) to get their bounding boxes. + - Calculate relative positions of bricks along the argument chains. + - Determine sizes for argument bricks at different levels of the stack. + +- **Preorder Traversal for Instruction Tree**: + - Query brick models to get their bounding boxes. + - Calculate relative positions of bricks within the instruction tree. + - Determine sizes for instruction bricks at different levels of nesting. + +- **Mapping of Connection Point Coordinates**: + - Translate the connection points' coordinates from the brick models to their positions in the stack. + +#### **React Component for Brick Stack (View)** +- **Props will be (B)**: + - The component will receive props that include the positioning data and information necessary to render the stack correctly. + +- **Use the Brick React Components Developed Earlier**: + - It will utilize the individual brick components (`BrickBlock`, `BrickData`, etc.) that were developed earlier. + +#### **Warehouse Module for Brick Stacks** +- **Map of Brick Stack ID to Instance**: + - Manage instances of brick stacks using a map structure to keep track of them. + +- **Functions to Add, Retrieve, and Delete Instances**: + - Add a new brick stack, retrieve an existing one, or delete a stack from the warehouse. + +### 3. **Storybook Files for Brick Stack Configurations and States** + +#### **Configurations to Cover:** +- No nesting +- Some nesting +- Deep nesting +- No arguments +- Chain of arguments +- Some missing arguments +- Shadow arguments +- Shadow instructions + +### Additional Details and Notes + +- **Inline and In-File Documentation**: + - Ensure that all classes, methods, and complex logic are well-documented to help future contributors understand the codebase. + +- **Export the Brick Stack Class, React Component, and Warehouse Module**: + - Make sure these are accessible to the workspace submodule, which will utilize them. + +--- + +What is required of brick + +### 1. **Brick Model Classes and Instances** + +- **Access to Concrete Classes (`BrickBlock`, `BrickData`, `BrickExpression`, `BrickStatement`)**: + - Instantiate these classes based on their constructor arguments. + - Call methods from these classes to get properties like bounding boxes, connection points, and render props. + +- **Methods to Retrieve Brick States**: + - Functions like `getBoundingBox()`, `getConnPointsFixed()`, and `getConnPointsArg()` from each concrete class to calculate the position and alignment of each brick in the stack. + +- **Methods to Set and Update Brick States**: + - Methods like `setScale()`, `setHighlighted()`, and other setters that allow changing the state of bricks dynamically as the stack is manipulated. + +### 2. **Brick Factory and Warehouse Functions** + +- **Factory Functions** (`createBrickBlock`, `createBrickData`, etc.): + - These will be used to create new brick instances with the correct properties. The factory functions will handle generating UUIDs and initializing instances with the correct configuration. + +- **Warehouse Functions** (`addBrickToWarehouse`, `getBrickFromWarehouse`, `deleteBrickFromWarehouse`): + - To store, retrieve, and manage instances of bricks efficiently. The brick stack needs to interact with the warehouse to maintain a map of all brick instances it contains. + +### 3. **Type Definitions and Interfaces** + +- **Types for Brick Properties and States** (`TBrickRenderProps`, `TColor`, `TExtent`, `TCoords`, etc.): + - Use these types to ensure consistent typing for the properties and states across both the brick stack and brick submodules. + +- **Interfaces for Brick Contracts** (`IBrick`, `IBrickBlock`, `IBrickData`, etc.): + - These will define the contract that each brick type must fulfill. The stack will rely on these contracts to interact with different brick instances. + +### 4. **Render Properties and Methods** + +- **Render Prop Methods** (`renderProps()`): + - Use the methods from the concrete brick classes to gather all necessary data for rendering each brick in the stack. This data will be passed to the React component representing the stack. + +### 5. **Bounding Box and Connection Point Calculations** + +- **Bounding Box Methods** (`getBoundingBox()`, etc.): + - Need these to determine the dimensions of each brick and calculate their positions within the stack. + +- **Connection Point Methods** (`getConnPointsFixed()`, `getConnPointsArg()`, etc.): + - These will help manage how bricks connect to each other, especially when considering nested or chained configurations. + +### 6. **Hooks for State Changes** + +- **State Management Hooks**: + - Hooks or methods that listen to or trigger changes in brick states (e.g., highlight state, scale state) so that the stack can re-render or adjust positioning when necessary. + +### 7. **Storybook and Test Utilities** + +- **Storybook Stories and Test Configurations**: + - Use the existing stories and test configurations to verify that the stack integrates correctly with different brick types and configurations. From d9ab1ee3413846c98af80873139db21948212676 Mon Sep 17 00:00:00 2001 From: Anindya Kundu Date: Thu, 12 Jun 2025 02:50:38 +0530 Subject: [PATCH 58/58] lint(masonry): [docs] fix linting errors --- .../docs/technical-specification/Brick.md | 74 +++++++---- .../docs/technical-specification/Stack.md | 118 +++++++++++------- 2 files changed, 122 insertions(+), 70 deletions(-) diff --git a/modules/masonry/docs/technical-specification/Brick.md b/modules/masonry/docs/technical-specification/Brick.md index 99eef6e3..5d08a1ca 100644 --- a/modules/masonry/docs/technical-specification/Brick.md +++ b/modules/masonry/docs/technical-specification/Brick.md @@ -1,8 +1,12 @@ -### 1. **`model.ts`**: Abstract Classes +# Brick -This file contains the abstract classes that define the blueprint for different types of bricks. These classes are not instantiated directly; instead, they are extended by concrete classes to provide specific implementations. +## 1. **`model.ts`**: Abstract Classes -#### Abstract Classes +This file contains the abstract classes that define the blueprint for different types of bricks. +These classes are not instantiated directly; instead, they are extended by concrete classes to provide +specific implementations. + +### Abstract Classes - **`BrickModel`**: The base class for all brick types. - **Properties:** @@ -17,11 +21,13 @@ This file contains the abstract classes that define the blueprint for different - `scale: number` - Scale factor for rendering. - **Abstract Methods:** - `get boundingBox(): TExtent` - Returns the bounding box dimensions of the brick. - - `get connPointsFixed(): Record` - Returns fixed connection points. + - `get connPointsFixed(): Record` - Returns fixed + connection points. - **`BrickModelArgument`**: Extends `BrickModel` for bricks that act as arguments. - **Abstract Methods:** - - `get connPointsFixed(): Record<'argOutgoing', { extent: TExtent; coords: TCoords }>` - Returns the outgoing connection point for arguments. + - `get connPointsFixed(): Record<'argOutgoing', { extent: TExtent; coords: TCoords }>` - Returns + the outgoing connection point for arguments. - **`BrickModelInstruction`**: Extends `BrickModel` for instruction bricks. - **Properties:** @@ -29,7 +35,8 @@ This file contains the abstract classes that define the blueprint for different - `connectBelow: boolean` - Indicates if the brick can connect below. - `args: { id: string; label: string }[]` - List of arguments. - **Abstract Methods:** - - `get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } }` - Returns connection points for arguments. + - `get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } }` - Returns connection + points for arguments. - `setBoundingBoxArg(id: string, extent: TExtent): void` - Sets the bounding box for an argument. - **`BrickModelData`**: Extends `BrickModelArgument` for data bricks. @@ -44,42 +51,55 @@ This file contains the abstract classes that define the blueprint for different - **Properties:** - `args: { id: string; label: string }[]` - List of arguments. - **Abstract Methods:** - - `get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } }` - Returns connection points for arguments. + - `get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } }` - Returns connection + points for arguments. - `setBoundingBoxArg(id: string, extent: TExtent): void` - Sets the bounding box for an argument. - - `get renderProps(): TBrickRenderPropsExpression` - Returns properties required to render the expression brick. + - `get renderProps(): TBrickRenderPropsExpression` - Returns properties required to render the + expression brick. - **`BrickModelStatement`**: Extends `BrickModelInstruction` for statement bricks. - **Abstract Methods:** - - `get connPointsFixed(): Record<'insTop' | 'insBottom', { extent: TExtent; coords: TCoords }>` - Returns fixed connection points for insertion points. - - `get renderProps(): TBrickRenderPropsStatement` - Returns properties required to render the statement brick. + - `get connPointsFixed(): Record<'insTop' | 'insBottom', { extent: TExtent; coords: TCoords }>` - + Returns fixed connection points for insertion points. + - `get renderProps(): TBrickRenderPropsStatement` - Returns properties required to render the + statement brick. - **`BrickModelBlock`**: Extends `BrickModelInstruction` for block bricks. - **Properties:** - `folded: boolean` - Indicates if the block brick is folded. - **Abstract Methods:** - - `get connPointsFixed(): Record<'insTop' | 'insBottom' | 'insNest', { extent: TExtent; coords: TCoords }>` - Returns fixed connection points for block insertion. + - `get connPointsFixed(): + Record<'insTop' | 'insBottom' | 'insNest', { extent: TExtent; coords: TCoords }>` - Returns fixed + connection points for block insertion. - `get renderProps(): TBrickRenderPropsBlock` - Returns properties required to render the block brick. - `setBoundingBoxNest(extent: TExtent): void` - Sets the bounding box for the nested elements. -### 2. **Concrete Classes** +## 2. **Concrete Classes** -The concrete classes provide specific implementations of the abstract classes. These classes are used to create actual brick instances. +The concrete classes provide specific implementations of the abstract classes. These classes are used +to create actual brick instances. - **`BrickBlock.ts`**: Concrete implementation of `BrickModelBlock`. - - Provides methods to calculate and return bounding boxes (`boundingBox`, `connPointsFixed`), render properties (`renderProps`), and set bounding boxes (`setBoundingBoxArg`, `setBoundingBoxNest`). + - Provides methods to calculate and return bounding boxes (`boundingBox`, `connPointsFixed`), render + properties (`renderProps`), and set bounding boxes (`setBoundingBoxArg`, `setBoundingBoxNest`). - **`BrickData.ts`**: Concrete implementation of `BrickModelData`. - - Implements properties for dynamic data (`dynamic`, `value`, `input`), and methods to get connection points (`connPointsFixed`), render properties (`renderProps`), and set various properties (`setDynamic`, `setValue`, `setInput`). + - Implements properties for dynamic data (`dynamic`, `value`, `input`), and methods to get connection + points (`connPointsFixed`), render properties (`renderProps`), and set various properties (`setDynamic`, + `setValue`, `setInput`). - **`BrickExpression.ts`**: Concrete implementation of `BrickModelExpression`. - - Manages expressions with arguments, implementing methods to calculate argument connection points (`connPointsArg`), set bounding boxes (`setBoundingBoxArg`), and provide rendering properties (`renderProps`). + - Manages expressions with arguments, implementing methods to calculate argument connection points + (`connPointsArg`), set bounding boxes (`setBoundingBoxArg`), and provide rendering properties (`renderProps`). - **`BrickStatement.ts`**: Concrete implementation of `BrickModelStatement`. - - Converts argument objects to arrays, provides methods for fixed and argument connection points (`connPointsFixed`, `connPointsArg`), and rendering properties (`renderProps`). + - Converts argument objects to arrays, provides methods for fixed and argument connection points + (`connPointsFixed`, `connPointsArg`), and rendering properties (`renderProps`). -### 3. **`BrickFactory.ts`: Factory Functions and Warehouse** +## 3. **`BrickFactory.ts`: Factory Functions and Warehouse** -This file manages the creation of brick instances and their storage in a warehouse for easy retrieval, addition, and deletion. +This file manages the creation of brick instances and their storage in a warehouse for easy retrieval, +addition, and deletion. - **Warehouse**: A `Map` to store brick instances keyed by their `uuid`. - Functions: @@ -88,16 +108,20 @@ This file manages the creation of brick instances and their storage in a warehou - `deleteBrickFromWarehouse(id)`: Deletes a brick by its ID. - **Factory Functions**: - - `createBrickBlock`, `createBrickData`, `createBrickExpression`, `createBrickStatement`: Functions that create instances of respective brick types and add them to the warehouse. + - `createBrickBlock`, `createBrickData`, `createBrickExpression`, `createBrickStatement`: Functions + that create instances of respective brick types and add them to the warehouse. -### 4. **Components** +## 4. **Components** -Each brick type has a corresponding React component to handle its visual representation. The components use the `renderProps()` method from the concrete classes to render the brick according to its properties. +Each brick type has a corresponding React component to handle its visual representation. The components +use the `renderProps()` method from the concrete classes to render the brick according to its properties. - **`BrickWrapper.tsx`**: A Higher-Order Component (HOC) that wraps individual brick components. - Retrieves brick instances from the warehouse using factory functions. - - Passes the `renderProps()` from each brick instance to the specific brick component (`BrickBlock`, `BrickData`, `BrickExpression`, `BrickStatement`) for rendering. + - Passes the `renderProps()` from each brick instance to the specific brick component (`BrickBlock`, + `BrickData`, `BrickExpression`, `BrickStatement`) for rendering. -### 5. **Stories** +## 5. **Stories** -- **Storybook Files**: Used to create stories for each brick type. These files demonstrate different states and variations of the bricks, using the factory functions to create instances for visualization. \ No newline at end of file +- **Storybook Files**: Used to create stories for each brick type. These files demonstrate different +states and variations of the bricks, using the factory functions to create instances for visualization. diff --git a/modules/masonry/docs/technical-specification/Stack.md b/modules/masonry/docs/technical-specification/Stack.md index b89e0eb8..093125a2 100644 --- a/modules/masonry/docs/technical-specification/Stack.md +++ b/modules/masonry/docs/technical-specification/Stack.md @@ -1,39 +1,50 @@ -### 1. **Config for Brick Stack** +# Brick Stack + +## 1. **Config for Brick Stack** + +### (A) Define the Tree Structure Representing a Brick Stack -#### (A) Define the Tree Structure Representing a Brick Stack - **Tree Structure**: A hierarchical representation where each node is a brick. - - **Nodes**: Represent bricks with unique identifiers (`id`) that link back to their corresponding brick model instances. + - **Nodes**: Represent bricks with unique identifiers (`id`) that link back to their corresponding + brick model instances. - **Chaining of Arguments**: Some bricks will have arguments that connect in a chain-like manner. - **Nesting of Instructions**: Instructions can be nested within other instructions. - **Shadow Instructions and Arguments**: Handle bricks that act as shadows or placeholders. -#### (B) Define the Properties Required to Render the Brick Stack -- **Positioning Information**: Store the relative positions of each brick in the stack to determine how they are rendered visually. +### (B) Define the Properties Required to Render the Brick Stack + +- **Positioning Information**: Store the relative positions of each brick in the stack to determine +how they are rendered visually. - **Stack Dimensions**: Overall dimensions based on the size of all bricks combined. -#### (C) Define How Connection Points Will Be Mapped +### (C) Define How Connection Points Will Be Mapped + - **Mapping Connection Points**: For any given connection point, identify: - Which brick it belongs to. - Which part of the brick it represents (e.g., if it's an argument connector, specify which argument). - **Coordinate Storage**: Store coordinates relative to the origin of the brick stack. -### 2. **Code for Brick Stack** +## 2. **Code for Brick Stack** -#### **Brick Stack Class (Model)** -This class will encapsulate the functionalities required to manage and render the brick stack. It will have the following: +### **Brick Stack Class (Model)** -- **Methods to Set and Get the Current Tree**: +This class will encapsulate the functionalities required to manage and render the brick stack. It will +have the following: + +- **Methods to Set and Get the Current Tree**: - Manage the current state of the tree structure representing the stack. - -- **Methods to Query the Map of Connection Points**: + +- **Methods to Query the Map of Connection Points**: - Provide a way to retrieve all connection points and their corresponding bricks. - **Method to Return Props for the React Component (View)**: - - Gather all properties needed to render the brick stack in the React component based on the current state. + - Gather all properties needed to render the brick stack in the React component based on the current + state. + +### **Brick Stack Positioning Calculations** -#### **Brick Stack Positioning Calculations** The class will also handle: - + - **Preorder Traversal for Argument Chains**: - Query brick classes (model) to get their bounding boxes. - Calculate relative positions of bricks along the argument chains. @@ -47,23 +58,28 @@ The class will also handle: - **Mapping of Connection Point Coordinates**: - Translate the connection points' coordinates from the brick models to their positions in the stack. -#### **React Component for Brick Stack (View)** +### **React Component for Brick Stack (View)** + - **Props will be (B)**: - - The component will receive props that include the positioning data and information necessary to render the stack correctly. + - The component will receive props that include the positioning data and information necessary to + render the stack correctly. - **Use the Brick React Components Developed Earlier**: - - It will utilize the individual brick components (`BrickBlock`, `BrickData`, etc.) that were developed earlier. + - It will utilize the individual brick components (`BrickBlock`, `BrickData`, etc.) that were + developed earlier. + +### **Warehouse Module for Brick Stacks** -#### **Warehouse Module for Brick Stacks** - **Map of Brick Stack ID to Instance**: - Manage instances of brick stacks using a map structure to keep track of them. - + - **Functions to Add, Retrieve, and Delete Instances**: - Add a new brick stack, retrieve an existing one, or delete a stack from the warehouse. -### 3. **Storybook Files for Brick Stack Configurations and States** +## 3. **Storybook Files for Brick Stack Configurations and States** + +### **Configurations to Cover:** -#### **Configurations to Cover:** - No nesting - Some nesting - Deep nesting @@ -73,10 +89,11 @@ The class will also handle: - Shadow arguments - Shadow instructions -### Additional Details and Notes +## Additional Details and Notes -- **Inline and In-File Documentation**: - - Ensure that all classes, methods, and complex logic are well-documented to help future contributors understand the codebase. +- **Inline and In-File Documentation**: + - Ensure that all classes, methods, and complex logic are well-documented to help future contributors + understand the codebase. - **Export the Brick Stack Class, React Component, and Warehouse Module**: - Make sure these are accessible to the workspace submodule, which will utilize them. @@ -85,53 +102,64 @@ The class will also handle: What is required of brick -### 1. **Brick Model Classes and Instances** +## 1. **Brick Model Classes and Instances** - **Access to Concrete Classes (`BrickBlock`, `BrickData`, `BrickExpression`, `BrickStatement`)**: - - Instantiate these classes based on their constructor arguments. - - Call methods from these classes to get properties like bounding boxes, connection points, and render props. + - Instantiate these classes based on their constructor arguments. + - Call methods from these classes to get properties like bounding boxes, connection points, and + render props. - **Methods to Retrieve Brick States**: - - Functions like `getBoundingBox()`, `getConnPointsFixed()`, and `getConnPointsArg()` from each concrete class to calculate the position and alignment of each brick in the stack. + - Functions like `getBoundingBox()`, `getConnPointsFixed()`, and `getConnPointsArg()` from each + concrete class to calculate the position and alignment of each brick in the stack. - **Methods to Set and Update Brick States**: - - Methods like `setScale()`, `setHighlighted()`, and other setters that allow changing the state of bricks dynamically as the stack is manipulated. + - Methods like `setScale()`, `setHighlighted()`, and other setters that allow changing the state of + bricks dynamically as the stack is manipulated. -### 2. **Brick Factory and Warehouse Functions** +## 2. **Brick Factory and Warehouse Functions** - **Factory Functions** (`createBrickBlock`, `createBrickData`, etc.): - - These will be used to create new brick instances with the correct properties. The factory functions will handle generating UUIDs and initializing instances with the correct configuration. + - These will be used to create new brick instances with the correct properties. The factory functions + will handle generating UUIDs and initializing instances with the correct configuration. - **Warehouse Functions** (`addBrickToWarehouse`, `getBrickFromWarehouse`, `deleteBrickFromWarehouse`): - - To store, retrieve, and manage instances of bricks efficiently. The brick stack needs to interact with the warehouse to maintain a map of all brick instances it contains. + - To store, retrieve, and manage instances of bricks efficiently. The brick stack needs to interact + with the warehouse to maintain a map of all brick instances it contains. -### 3. **Type Definitions and Interfaces** +## 3. **Type Definitions and Interfaces** - **Types for Brick Properties and States** (`TBrickRenderProps`, `TColor`, `TExtent`, `TCoords`, etc.): - - Use these types to ensure consistent typing for the properties and states across both the brick stack and brick submodules. - + - Use these types to ensure consistent typing for the properties and states across both the brick + stack and brick submodules. + - **Interfaces for Brick Contracts** (`IBrick`, `IBrickBlock`, `IBrickData`, etc.): - - These will define the contract that each brick type must fulfill. The stack will rely on these contracts to interact with different brick instances. + - These will define the contract that each brick type must fulfill. The stack will rely on these + contracts to interact with different brick instances. -### 4. **Render Properties and Methods** +## 4. **Render Properties and Methods** - **Render Prop Methods** (`renderProps()`): - - Use the methods from the concrete brick classes to gather all necessary data for rendering each brick in the stack. This data will be passed to the React component representing the stack. + - Use the methods from the concrete brick classes to gather all necessary data for rendering each + brick in the stack. This data will be passed to the React component representing the stack. -### 5. **Bounding Box and Connection Point Calculations** +## 5. **Bounding Box and Connection Point Calculations** - **Bounding Box Methods** (`getBoundingBox()`, etc.): - Need these to determine the dimensions of each brick and calculate their positions within the stack. - **Connection Point Methods** (`getConnPointsFixed()`, `getConnPointsArg()`, etc.): - - These will help manage how bricks connect to each other, especially when considering nested or chained configurations. + - These will help manage how bricks connect to each other, especially when considering nested or + chained configurations. -### 6. **Hooks for State Changes** +## 6. **Hooks for State Changes** - **State Management Hooks**: - - Hooks or methods that listen to or trigger changes in brick states (e.g., highlight state, scale state) so that the stack can re-render or adjust positioning when necessary. + - Hooks or methods that listen to or trigger changes in brick states (e.g., highlight state, scale + state) so that the stack can re-render or adjust positioning when necessary. -### 7. **Storybook and Test Utilities** +## 7. **Storybook and Test Utilities** - **Storybook Stories and Test Configurations**: - - Use the existing stories and test configurations to verify that the stack integrates correctly with different brick types and configurations. + - Use the existing stories and test configurations to verify that the stack integrates correctly + with different brick types and configurations.

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