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 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", 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/PRD/Masonry_Design_Document.md b/modules/masonry/docs/functional-specification/Masonry_Design_Document.md similarity index 89% rename from modules/masonry/docs/PRD/Masonry_Design_Document.md rename to modules/masonry/docs/functional-specification/Masonry_Design_Document.md index b73c2c2d..12f26331 100644 --- a/modules/masonry/docs/PRD/Masonry_Design_Document.md +++ b/modules/masonry/docs/functional-specification/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/functional-specification/PRD.md similarity index 76% rename from modules/masonry/docs/PRD/PRD.md rename to modules/masonry/docs/functional-specification/PRD.md index 6c555ccd..b3b1154d 100644 --- a/modules/masonry/docs/PRD/PRD.md +++ b/modules/masonry/docs/functional-specification/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/tech-spec/TechSpec.md b/modules/masonry/docs/tech-spec/TechSpec.md deleted file mode 100644 index eb108ea3..00000000 --- a/modules/masonry/docs/tech-spec/TechSpec.md +++ /dev/null @@ -1,385 +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 - -``` -├── 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/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. diff --git a/modules/masonry/docs/tech-spec/Techspec.md b/modules/masonry/docs/technical-specification/Techspec.md similarity index 95% rename from modules/masonry/docs/tech-spec/Techspec.md rename to modules/masonry/docs/technical-specification/Techspec.md index 2bc99422..0250242a 100644 --- a/modules/masonry/docs/tech-spec/Techspec.md +++ b/modules/masonry/docs/technical-specification/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/package.json b/modules/masonry/package.json index a18b7d12..ff6aa6d5 100644 --- a/modules/masonry/package.json +++ b/modules/masonry/package.json @@ -9,6 +9,13 @@ "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" + }, + "dependencies": { + "uuid": "^10.0.0" + }, + "devDependencies": { + "@types/uuid": "^10.0.0" } } 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/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/BrickBlock.tsx b/modules/masonry/playground/pages/workspace/BrickBlock.tsx new file mode 100644 index 00000000..23b35742 --- /dev/null +++ b/modules/masonry/playground/pages/workspace/BrickBlock.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/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/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/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 ( + + + + ); +} 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 }; +}; diff --git a/modules/masonry/playground/pages/workspace/data.ts b/modules/masonry/playground/pages/workspace/data.ts new file mode 100644 index 00000000..4acfd119 --- /dev/null +++ b/modules/masonry/playground/pages/workspace/data.ts @@ -0,0 +1,227 @@ +import { + ModelBrickBlock, + ModelBrickData, + ModelBrickExpression, + ModelBrickStatement, +} from '@/brick'; +import type { TBrickType, TBrickCoords, TBrickArgDataType } from '@/@types/brick'; + +export type InstanceMap = { + data: ModelBrickData; + expression: ModelBrickExpression; + statement: ModelBrickStatement; + block: ModelBrickBlock; +}; + +export type Brick = { + id: string; + type: TBrickType; + instance: InstanceMap[TBrickType]; + surroundingBricks: { above: string; below: string }; + childBricks: string[]; + 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: 'lightpink', + colorFg: 'black', + outline: 'deeppink', + scale: 2, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + nestLengthY: 125, + }), + surroundingBricks: { above: '', below: '' }, + childBricks: ['2', '3', '4', '5', '6'], + 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: '', + }), + surroundingBricks: { above: '1', below: '3' }, + childBricks: [], + 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: '', + }), + surroundingBricks: { above: '2', below: '4' }, + childBricks: [], + 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: 'brown', + colorFg: 'black', + outline: 'grey', + scale: 2, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + nestLengthY: 17, + }), + surroundingBricks: { above: '3', below: '6' }, + childBricks: ['5'], + 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: 'orange', + colorFg: 'black', + outline: 'red', + + scale: 2, + glyph: '', + connectAbove: true, + connectBelow: true, + name: '', + }), + surroundingBricks: { above: '', below: '' }, + childBricks: [], + 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: '', + }), + surroundingBricks: { above: '4', below: '' }, + childBricks: [], + coords: { x: 68, y: 302 }, + }, + ], + }, + ], + }, +]; diff --git a/modules/masonry/playground/pages/workspace/index.tsx b/modules/masonry/playground/pages/workspace/index.tsx new file mode 100644 index 00000000..213afe30 --- /dev/null +++ b/modules/masonry/playground/pages/workspace/index.tsx @@ -0,0 +1,37 @@ +import BrickFactory from './BrickFactory'; +import { WORKSPACES_DATA } from './data'; +import type { Brick } from './data'; + +function RenderBricks({ brickData }: { brickData: Brick }) { + return ( + <> + + {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/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; +} 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"] -} 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'], + }, }); diff --git a/modules/masonry/src/@types/brick.d.ts b/modules/masonry/src/@types/brick.d.ts index 7a9e7e5b..8488cbe8 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,20 @@ 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 */ - 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; - }; + set folded(value: boolean); + + /** 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; + + get connPointsFixed(): Record< + 'insTop' | 'insBottom' | 'insNest', + { extent: TExtent; coords: TCoords } + >; } diff --git a/modules/masonry/src/brick/design0/BrickBlock.ts b/modules/masonry/src/brick/design0/BrickBlock.ts index 969a7c6e..ef3878e7 100644 --- a/modules/masonry/src/brick/design0/BrickBlock.ts +++ b/modules/masonry/src/brick/design0/BrickBlock.ts @@ -1,5 +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'; @@ -12,127 +11,112 @@ 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: { - // intrinsic + uuid: string; name: string; + label: string; - glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - // style - 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; + }[]; }) { 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: 30, + nestLengthY: this._args.length * 20, // Example of generating nest length based on argument count innerLengthX: 100, - argHeights: Array.from({ length: argsKeys.length }, () => 17), + argHeights: Array.from({ length: this._args.length }, () => 17), }); } - 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, + }; } - public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { + 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: 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, + }, + insNest: { + extent: this._pathResults.bBoxNotchInsNestTop!.extent, + coords: this._pathResults.bBoxNotchInsNestTop!.coords, }, }; } - 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, - }, + public get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } } { + const results: { [id: string]: { extent: TExtent; coords: TCoords } } = {}; + + 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; } - public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { + 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, - }, + path: this._pathResults.path, + + label: this._label, + labelArgs: this._args.map(({ label }) => label), + + boundingBoxArgs: this._args.map(({ id }) => this._boundingBoxArgs[id]), + boundingBoxNest: this._boundingBoxNest, + + 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, }; } - 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, - }, - }; + public setBoundingBoxArg(id: string, extent: TExtent): void { + this._boundingBoxArgs[id] = extent; } - 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, - }, - }; + public setBoundingBoxNest(extent: TExtent): void { + this._boundingBoxNest = extent; } - 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, - }, - }; + 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 f15d1911..a219da6e 100644 --- a/modules/masonry/src/brick/design0/BrickData.ts +++ b/modules/masonry/src/brick/design0/BrickData.ts @@ -1,10 +1,7 @@ -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'; -// ------------------------------------------------------------------------------------------------- - /** * @class * Final class that defines a data brick. @@ -13,21 +10,21 @@ 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; - outline: TBrickColor; - scale: number; }) { super(params); + this._pathResults = generatePath({ hasNest: false, hasNotchArg: true, @@ -39,35 +36,47 @@ export default class BrickData extends BrickModelData { }); } - 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, + }; } - public get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords } { - const { extent, coords } = this._pathResults.bBoxBrick; + 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, }, }; } - public get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords } { - const { extent, coords } = this._pathResults.bBoxNotchArg!; + public get renderProps(): TBrickRenderPropsData { return { - extent: { - width: extent.width * this._scale, - height: extent.height * this._scale, - }, - coords: { - x: coords.x * this._scale, - y: coords.y * this._scale, - }, + 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, }; } + + public setDynamic(dynamic: boolean): void { + this._dynamic = dynamic; + } + + 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; + } } diff --git a/modules/masonry/src/brick/design0/BrickExpression.ts b/modules/masonry/src/brick/design0/BrickExpression.ts index e039180a..4b9fd0e4 100644 --- a/modules/masonry/src/brick/design0/BrickExpression.ts +++ b/modules/masonry/src/brick/design0/BrickExpression.ts @@ -1,10 +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. @@ -12,28 +9,22 @@ import { generatePath } from '../utils/path'; export default class BrickExpression extends BrickModelExpression { readonly _pathResults: ReturnType; + private _boundingBoxArgs: Record = {}; + constructor(params: { - // intrinsic + uuid: string; 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; + glyph?: string; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + args: { id: string; label: string }[]; }) { super(params); - const argsKeys = Object.keys(this._args); + this._pathResults = generatePath({ hasNest: false, hasNotchArg: true, @@ -41,57 +32,58 @@ 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), }); } - 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, + }; } - 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, }, }; } - 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, - }, + 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; } - 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, + 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, + outline: this._outline, + scale: this._scale, }; } + + 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 c6e588fd..7dae72d6 100644 --- a/modules/masonry/src/brick/design0/BrickStatement.ts +++ b/modules/masonry/src/brick/design0/BrickStatement.ts @@ -1,10 +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. @@ -12,100 +9,99 @@ import { generatePath } from '../utils/path'; export default class BrickStatement extends BrickModelStatement { readonly _pathResults: ReturnType; + private _boundingBoxArgs: Record = {}; + constructor(params: { - // intrinsic + uuid: string; name: string; label: string; glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - // style - colorBg: TBrickColor; - colorFg: TBrickColor; - outline: TBrickColor; + args: { id: string; label: string }[]; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; 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, + hasNotchInsTop: params.connectAbove, + hasNotchInsBot: params.connectBelow, scale: this._scale, innerLengthX: 100, - argHeights: Array.from({ length: argsKeys.length }, () => 17), + argHeights: Array.from({ length: params.args.length }, () => 17), }); } - 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, + }; } - 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, }, }; } - 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, - }, + 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; } - 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, - }, + 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, + outline: this._outline, + scale: this._scale, }; } - 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, - }, - }; + public setBoundingBoxArg(id: string, extent: TExtent): void { + this._boundingBoxArgs[id] = extent; + } + + public setConnectAbove(connectAbove: boolean): void { + this._connectAbove = connectAbove; + } + + public setConnectBelow(connectBelow: boolean): void { + this._connectBelow = connectBelow; + } + + public setHighlighted(highlighted: boolean): void { + this._highlighted = highlighted; } } 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..9774f996 --- /dev/null +++ b/modules/masonry/src/brick/design0/brickFactory.spec.ts @@ -0,0 +1,138 @@ +import { + createBrickBlock, + createBrickData, + createBrickExpression, + createBrickStatement, + getBrickFromWarehouse, + deleteBrickFromWarehouse, +} from './brickFactory'; +import type { TColor } from '@/@types/brick'; + +// 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: 100, + folded: false, + }); + + expect(brick).toBeDefined(); + expect(getBrickFromWarehouse(brick.uuid)).toBe(brick); + }); + + it('should create a BrickData and add it to the warehouse', () => { + const brick = createBrickData({ + name: 'TestData', + label: 'DataLabel', + glyph: '🔢', + dynamic: true, + value: 42, + input: 'number', + colorBg: mockColor, + colorFg: mockColor, + colorBgHighlight: mockColor, + colorFgHighlight: mockColor, + outline: mockColor, + scale: 1, + }); + + expect(brick).toBeDefined(); + expect(getBrickFromWarehouse(brick.uuid)).toBe(brick); + }); + + 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(brick).toBeDefined(); + expect(getBrickFromWarehouse(brick.uuid)).toBe(brick); + }); + + 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: true, + }); + + expect(brick).toBeDefined(); + expect(getBrickFromWarehouse(brick.uuid)).toBe(brick); + }); + + it('should retrieve a brick from the warehouse by its UUID', () => { + const brick = createBrickBlock({ + 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: true, + nestLengthY: 200, + }); + + const retrievedBrick = getBrickFromWarehouse(brick.uuid); + expect(retrievedBrick).toBe(brick); + }); + + 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: false, + connectBelow: true, + nestLengthY: 50, + }); + + const wasDeleted = deleteBrickFromWarehouse(brick.uuid); + expect(wasDeleted).toBe(true); + expect(getBrickFromWarehouse(brick.uuid)).toBeUndefined(); + }); +}); diff --git a/modules/masonry/src/brick/design0/brickFactory.ts b/modules/masonry/src/brick/design0/brickFactory.ts new file mode 100644 index 00000000..3dff1270 --- /dev/null +++ b/modules/masonry/src/brick/design0/brickFactory.ts @@ -0,0 +1,164 @@ +import { v4 as uuidv4 } from 'uuid'; +import type { TColor } from '@/@types/brick'; +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. + */ +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); +} + +/** + * 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. + * @returns A new instance of BrickBlock. + */ +export function createBrickBlock(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; +}): BrickBlock { + const brick = new BrickBlock({ + uuid: uuidv4(), + ...params, + }); + addBrickToWarehouse(brick); + return brick; +} + +/** + * 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; + dynamic: boolean; + value?: boolean | number | string; + input?: 'boolean' | 'number' | 'string' | 'options'; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + scale: number; +}): BrickData { + const brick = new BrickData({ + uuid: uuidv4(), + ...params, + }); + addBrickToWarehouse(brick); + return brick; +} + +/** + * 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; + 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; +} + +/** + * 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; + colorBg: TColor; + colorFg: TColor; + colorBgHighlight: TColor; + colorFgHighlight: TColor; + outline: TColor; + scale: number; + connectAbove: boolean; + connectBelow: boolean; +}): BrickStatement { + const brick = new BrickStatement({ + uuid: uuidv4(), + ...params, + args: argsRecordToArray(params.args), + }); + addBrickToWarehouse(brick); + return brick; +} + +// Exporting warehouse functions for external use +export { addBrickToWarehouse, getBrickFromWarehouse, deleteBrickFromWarehouse }; diff --git a/modules/masonry/src/brick/design0/components/BrickBlock.tsx b/modules/masonry/src/brick/design0/components/BrickBlock.tsx index 7dd5ed16..7be85bd6 100644 --- a/modules/masonry/src/brick/design0/components/BrickBlock.tsx +++ b/modules/masonry/src/brick/design0/components/BrickBlock.tsx @@ -1,24 +1,52 @@ -import type { JSX } from 'react'; -import type { IBrickBlock } from '@/@types/brick'; - -// ------------------------------------------------------------------------------------------------- - -export default function (props: { instance: IBrickBlock }): JSX.Element { - const { instance } = props; +import React from 'react'; +import type { TBrickRenderPropsBlock } from '@/@types/brick'; +const BrickBlock: React.FC = ({ + path, + label, + labelArgs, + colorBg, + colorFg, + outline, + scale, +}) => { return ( - + + + {label} + + {labelArgs.map((argLabel, index) => ( + + {argLabel} + + ))} + {/* {glyph && ( + + {instance.glyph} + + )} */} ); -} +}; + +export default BrickBlock; diff --git a/modules/masonry/src/brick/design0/components/BrickData.tsx b/modules/masonry/src/brick/design0/components/BrickData.tsx index 0623b736..05da3db0 100644 --- a/modules/masonry/src/brick/design0/components/BrickData.tsx +++ b/modules/masonry/src/brick/design0/components/BrickData.tsx @@ -1,22 +1,43 @@ -import type { JSX } from 'react'; -import type { IBrickData } from '@/@types/brick'; +import React from 'react'; +import type { TBrickRenderPropsData, TCoords } from '@/@types/brick'; -export default function (props: { instance: IBrickData }): JSX.Element { - const { instance } = props; +interface BrickDataProps { + instance: TBrickRenderPropsData; + coords?: TCoords; +} +const BrickData: React.FC = ({ instance, coords = { x: 0, y: 0 } }) => { return ( - + + + {instance.label} + + {instance.glyph && ( + + {instance.glyph} + + )} ); -} +}; + +export default BrickData; diff --git a/modules/masonry/src/brick/design0/components/BrickExpression.tsx b/modules/masonry/src/brick/design0/components/BrickExpression.tsx index 16183bf3..6fd659ae 100644 --- a/modules/masonry/src/brick/design0/components/BrickExpression.tsx +++ b/modules/masonry/src/brick/design0/components/BrickExpression.tsx @@ -1,24 +1,55 @@ -import type { JSX } from 'react'; -import type { IBrickExpression } from '@/@types/brick'; +import React from 'react'; +import type { TBrickRenderPropsExpression, TCoords } from '@/@types/brick'; -// ------------------------------------------------------------------------------------------------- - -export default function (props: { instance: IBrickExpression }): JSX.Element { - const { instance } = props; +interface BrickExpressionProps { + instance: TBrickRenderPropsExpression; + coords?: TCoords; +} +const BrickExpression: React.FC = ({ instance, coords = { x: 0, y: 0 } }) => { return ( - + + + {instance.label} + + {instance.labelArgs.map((argLabel, index) => ( + + {argLabel} + + ))} + {instance.glyph && ( + + {instance.glyph} + + )} ); -} +}; + +export default BrickExpression; diff --git a/modules/masonry/src/brick/design0/components/BrickStatement.tsx b/modules/masonry/src/brick/design0/components/BrickStatement.tsx index b53983b5..f1595297 100644 --- a/modules/masonry/src/brick/design0/components/BrickStatement.tsx +++ b/modules/masonry/src/brick/design0/components/BrickStatement.tsx @@ -1,24 +1,55 @@ -import type { JSX } from 'react'; -import type { IBrickStatement } from '@/@types/brick'; +import React from 'react'; +import type { TBrickRenderPropsStatement, TCoords } from '@/@types/brick'; -// ------------------------------------------------------------------------------------------------- - -export default function (props: { instance: IBrickStatement }): JSX.Element { - const { instance } = props; +interface BrickStatementProps { + instance: TBrickRenderPropsStatement; + coords?: TCoords; +} +const BrickStatement: React.FC = ({ instance, coords = { x: 0, y: 0 } }) => { return ( - + + + {instance.label} + + {instance.labelArgs.map((argLabel, index) => ( + + {argLabel} + + ))} + {instance.glyph && ( + + {instance.glyph} + + )} ); -} +}; + +export default BrickStatement; 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..3a1a0425 --- /dev/null +++ b/modules/masonry/src/brick/design0/components/BrickWrapper.tsx @@ -0,0 +1,105 @@ +import React from 'react'; +import { + createBrickBlock, + createBrickData, + createBrickExpression, + createBrickStatement, +} from '../brickFactory'; +import BrickBlockComponent from './BrickBlock'; +import BrickDataComponent from './BrickData'; +import BrickExpressionComponent from './BrickExpression'; +import BrickStatementComponent from './BrickStatement'; +import type { + TBrickRenderPropsBlock, + TBrickRenderPropsData, + TBrickRenderPropsExpression, + TBrickRenderPropsStatement, + TCoords, +} from '@/@types/brick'; + +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 }; + +const BrickWrapper: React.FC = ({ type, params, coords }) => { + switch (type) { + case 'block': { + 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({ + 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({ + 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({ + 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; + } +}; + +export default BrickWrapper; 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/model.ts b/modules/masonry/src/brick/model.ts index cfadd568..dbbbceb5 100644 --- a/modules/masonry/src/brick/model.ts +++ b/modules/masonry/src/brick/model.ts @@ -6,16 +6,17 @@ import type { IBrickExpression, IBrickInstruction, IBrickStatement, - TBrickArgDataType, - TBrickColor, - TBrickCoords, - TBrickExtent, + TBrickRenderPropsData, + TBrickRenderPropsExpression, + TBrickRenderPropsStatement, + TBrickRenderPropsBlock, TBrickKind, TBrickType, + TColor, + TCoords, + TExtent, } from '@/@types/brick'; -// -- protected classes ------------------------------------------------------------------------------ - /** * @abstract * @class @@ -26,39 +27,54 @@ abstract class BrickModel implements IBrick { protected _name: string; protected _kind: TBrickKind; protected _type: TBrickType; + protected _label: string; protected _glyph: string; + protected _colorBg: TColor; + protected _colorFg: TColor; + protected _colorBgHighlight: TColor; + protected _colorFgHighlight: TColor; + protected _outline: TColor; - protected _colorBg: TBrickColor; - protected _colorFg: TBrickColor; - protected _outline: TBrickColor; - protected _scale: number; - - public highlighted = false; + protected _highlighted = false; + protected _scale = 1; constructor(params: { - // intrinsic + /** 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; - // style - colorBg: TBrickColor; - colorFg: 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 = ''; + 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; } public get uuid(): string { @@ -77,33 +93,17 @@ abstract class BrickModel implements IBrick { 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 set highlighted(value: boolean) { + this._highlighted = value; } - public get scale(): number { - return this._scale; + public set scale(value: number) { + this._scale = value; } - public abstract get bBoxBrick(): { extent: TBrickExtent; coords: TBrickCoords }; + public abstract get boundingBox(): TExtent; - public abstract get SVGpath(): string; + public abstract get connPointsFixed(): Record; } /** @@ -112,31 +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; - constructor(params: { - // intrinsic + uuid: string; name: string; type: TBrickType; + label: string; - glyph: string; - dataType: TBrickArgDataType; - // style - colorBg: TBrickColor; - colorFg: 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 abstract get bBoxNotchArg(): { extent: TBrickExtent; coords: TBrickCoords }; + public abstract get connPointsFixed(): Record< + 'argOutgoing', + { extent: TExtent; coords: TCoords } + >; } /** @@ -145,56 +140,39 @@ 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 _connectAbove: boolean; protected _connectBelow: boolean; + protected _args: { id: string; label: string }[] = []; + constructor(params: { - // intrinsic + uuid: string; 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; + 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 { @@ -205,15 +183,11 @@ abstract class BrickModelInstruction extends BrickModel implements IBrickInstruc return this._connectBelow; } - public abstract get bBoxNotchInsTop(): { extent: TBrickExtent; coords: TBrickCoords }; - - public abstract get bBoxNotchInsBot(): { extent: TBrickExtent; coords: TBrickCoords }; + public abstract get connPointsArg(): { [id: string]: { extent: TExtent; coords: TCoords } }; - public abstract get bBoxArgs(): Record; + public abstract setBoundingBoxArg(id: string, extent: TExtent): void; } -// -- public classes ------------------------------------------------------------------------------- - /** * @abstract * @class @@ -225,19 +199,20 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric protected _input?: 'boolean' | 'number' | 'string' | 'options'; constructor(params: { - // intrinsic + 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'; - // style - colorBg: TBrickColor; - colorFg: TBrickColor; - outline: TBrickColor; - scale: number; }) { super({ ...params, type: 'data' }); @@ -257,6 +232,8 @@ export abstract class BrickModelData extends BrickModelArgument implements IBric public get input(): 'boolean' | 'number' | 'string' | 'options' | undefined { return this._input; } + + public abstract get renderProps(): TBrickRenderPropsData; } /** @@ -265,52 +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< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; + protected _args: { id: string; label: string }[] = []; constructor(params: { - // intrinsic + uuid: string; 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; + 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; } - 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 setBoundingBoxArg(id: string, extent: TExtent): void; - public abstract get bBoxArgs(): Record; + public abstract get renderProps(): TBrickRenderPropsExpression; } /** @@ -320,28 +282,35 @@ export abstract class BrickModelExpression extends BrickModelArgument implements */ export abstract class BrickModelStatement extends BrickModelInstruction implements IBrickStatement { constructor(params: { - // intrinsic + uuid: string; name: string; + label: string; glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - // style - colorBg: TBrickColor; - colorFg: 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' }); } + + public abstract get connPointsFixed(): Record< + 'insTop' | 'insBottom', + { extent: TExtent; coords: TCoords } + >; + + public abstract get renderProps(): TBrickRenderPropsStatement; } /** @@ -350,32 +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 }; - public collapsed = false; + protected _folded = false; constructor(params: { - // intrinsic + uuid: string; name: string; + label: string; - glyph: string; - args: Record< - string, - { - label: string; - dataType: TBrickArgDataType; - meta: unknown; - } - >; - // style - 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; + }[]; }) { super({ ...params, type: 'block' }); } - public abstract get bBoxNotchInsNestTop(): { extent: TBrickExtent; coords: TBrickCoords }; + public set folded(value: boolean) { + this._folded = value; + } + + public abstract get connPointsFixed(): Record< + 'insTop' | 'insBottom' | 'insNest', + { extent: TExtent; coords: TCoords } + >; + + public abstract get renderProps(): TBrickRenderPropsBlock; + + public abstract setBoundingBoxNest(extent: TExtent): void; } 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 && } ); } 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. --- 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",