{"id":14973748,"url":"https://github.com/graphieros/grid-plan","last_synced_at":"2025-10-27T02:31:19.443Z","repository":{"id":245480781,"uuid":"818606849","full_name":"graphieros/grid-plan","owner":"graphieros","description":"A lightweight Vue3 component to create dynamic blueprints for rooms, datacenters, racks, etc. Ships with TS types","archived":false,"fork":false,"pushed_at":"2025-02-08T09:51:51.000Z","size":236,"stargazers_count":28,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-08T09:52:39.089Z","etag":null,"topics":["blueprint","datacenter","plan","rack","room","vue3","vuejs"],"latest_commit_sha":null,"homepage":"https://grid-plan.graphieros.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/graphieros.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-22T10:11:52.000Z","updated_at":"2025-02-08T09:51:55.000Z","dependencies_parsed_at":"2024-06-22T10:24:12.047Z","dependency_job_id":"d50e51ec-caef-424b-a140-71c56d5b8321","html_url":"https://github.com/graphieros/grid-plan","commit_stats":{"total_commits":27,"total_committers":1,"mean_commits":27.0,"dds":0.0,"last_synced_commit":"d5cf1b76b74a8ef7473d38dd99d397b39ce3aa8e"},"previous_names":["graphieros/grid-plan"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphieros%2Fgrid-plan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphieros%2Fgrid-plan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphieros%2Fgrid-plan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphieros%2Fgrid-plan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/graphieros","download_url":"https://codeload.github.com/graphieros/grid-plan/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238422914,"owners_count":19469653,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blueprint","datacenter","plan","rack","room","vue3","vuejs"],"created_at":"2024-09-24T13:49:20.944Z","updated_at":"2025-10-27T02:31:19.431Z","avatar_url":"https://github.com/graphieros.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://grid-plan.graphieros.com/\"\u003e\u003cimg width=\"500\" src=\"https://github.com/user-attachments/assets/fcfe7151-419e-4a3f-98f6-92491d917db0\"\u003e\u003c/a\u003e\n    \u003cbr\u003e\n    \u003ca href=\"https://grid-plan.graphieros.com/\"\u003e\u003cimg width=\"500\" src=\"https://github.com/user-attachments/assets/acf2ec8f-a520-445d-a8eb-3ae5f09ffd8a\"\u003e\u003c/a\u003e\n    \u003cbr\u003e\n    \u003ca href=\"https://grid-plan.graphieros.com/\"\u003e\u003cimg width=\"200\" src=\"https://github.com/user-attachments/assets/75eb428f-984d-4b5b-ad13-bbeba7fcab04\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# grid-plan\n\n![npm](https://img.shields.io/npm/v/grid-plan)\n![npm](https://img.shields.io/npm/dt/grid-plan)\n![GitHub issues](https://img.shields.io/github/issues/graphieros/grid-plan)\n\ngrid-plan is a Vue3 component to create blueprints for rooms, datacenters, racks, etc.\n\nCreate available component types, and place, resize or delete them from the blueprint.\n\ngrid-plan ships with:\n\n- config options to customize the looks of your blueprint\n- slots to customize icons related to component types\n- slots to create your available components menu and your inventory\n\n## Installation\n\n```\nnpm i grid-plan\n```\n\nGrid Plan requires Three.js as peer dependency.\n\n```bash\nnpm install grid-plan three\n# or\nyarn add grid-plan three\n# or\npnpm add grid-plan three\n```\n\nYou can declare the component globally in your main.js:\n\n```js\nimport { createApp } from \"vue\";\nimport App from \"./App.vue\";\n\nimport { GridPlan } from \"grid-plan\";\n\nconst app = createApp(App);\n\napp.component(\"GridPlan\", GridPlan);\napp.mount(\"#app\");\n```\n\nOr you can import it directly in your Vue file:\n\n```html\n\u003cscript setup\u003e\n  import { GridPlan } from \"grid-plan\";\n\u003c/script\u003e\n```\n\n## Props\n\n| Prop name      | TS type            | Required                            | Description                                                 |\n| -------------- | ------------------ | ----------------------------------- | ----------------------------------------------------------- |\n| availableTypes | GridPlanItemType[] | YES                                 | The types of components that can be placed on the blueprint |\n| placedItems    | GridPlanItem[]     | YES (can be empty)                  | Components already placed on the blueprint                  |\n| readonly       | boolean            | NO (default: false)                 | Blueprint will be readonly if true                          |\n| config         | GridPlanConfig     | NO (default config will be applied) | Configuration object to customize looks                     |\n\n## Example\n\n- Script:\n\n```js\nimport { ref } from \"vue\";\nimport { GridPlan } from \"grid-plan\";\n\nconst availableTypes = ref([\n  {\n    typeId: 1,\n    color: \"#3366DD\",\n    description: \"server\",\n    icon: \"server\",\n    iconColor: \"#FFFFFF\",\n    depth: 2, // optional item height (defaults to 1 (grid cell size) if not provided)\n  },\n  {\n    typeId: 2,\n    color: \"#DD6633\",\n    description: \"power\",\n    icon: \"bolt\",\n    iconColor: \"#FFFFFF\",\n  },\n  {\n    typeId: 3,\n    color: \"#71a4a8\",\n    description: \"monitor\",\n    icon: \"deviceLaptop\",\n    iconColor: \"#1A1A1A\",\n  },\n]);\n\nconst placedItems = ref([\n  { x: 0, y: 0, h: 1, w: 12, typeId: 1 }, // it's a server component\n  { x: 0, y: 1, h: 4, w: 12, typeId: 3 }, // it's a monitor component\n]);\n\n// Config is optional\n// You can provide a partial config, as missing attributes will use defaults\nconst config = ref({\n  abscissaType: \"alphabetic\",\n  accordionMenuTitle: \"Menu\",\n  coordinatesBackground: \"#2A2A2A\",\n  coordinatesColor: \"#8A8A8A\",\n  crosshairBackground: \"#4A4A4A\",\n  fontFamily: \"Arial\",\n  grid3dPosition: \"top\",\n  gridFill: \"#3A3A3A\",\n  gridHeight: 42,\n  gridHighlightColor: \"#00FF00\",\n  gridStroke: \"#1A1A1A\",\n  gridStrokeWidth: 0.02,\n  gridWidth: 12,\n  handleFill: \"#FFFFFF\",\n  handleSize: 0.3,\n  iconColor: \"#1A1A1A\",\n  nonSelectedOpacity: 0.3,\n  ordinatesType: \"numeric\",\n  showCrosshair: true,\n  showGrid3d: true,\n  tooltipColor: \"#FFFFFF\",\n  useAccordionMenu: true,\n  useGradient: true,\n  useShadow: true,\n  showBox: true,\n  boxThickness: 0.3,\n  boxHeight: 1,\n  boxColor: \"#5A5A5A\",\n});\n\n// Events\n\nfunction selectType(menuItem) {\n  // Triggered when a menu item is selected\n  console.log(\"SELECT TYPE\", menuItem);\n}\n\nfunction change(item) {\n  // Triggered whenever an item is changed\n  console.log(\"CHANGED\", item);\n}\n\nfunction deleteItem(item) {\n  // Triggered whenever an item is deleted\n  console.log(\"DELETED\", item);\n}\n\nfunction selectItem(item) {\n  // Triggered whenever an item is selected\n  console.log(\"SELECTED\", item);\n}\n\nfunction createdItem(item) {\n  // Triggered whenever an item is created\n  console.log(\"CREATED\", item);\n}\n\nfunction unselected() {\n  // Triggered when an item is unselected\n  // Pressing ESC will trigger unselect\n  // Selecting an already selected item will trigger unselect\n  console.log(\"BLUEPRINT IS NOW UNSELECTED\");\n}\n```\n\n- Template:\n\n```html\n\u003ctemplate\u003e\n  \u003cGridPlan\n    ref=\"plan\"\n    :availableTypes\n    :config\n    :placedItems\n    @change=\"change\"\n    @delete=\"deleteItem\"\n    @select=\"selectItem\"\n    @created=\"createdItem\"\n    @unselect=\"unselected\"\n    @selectType=\"selectType\"\n  \u003e\n    \u003c!-- A slot to do whatever you need before the component --\u003e\n    \u003ctemplate\n      #before=\"{ items, deleteItem, focusItem, getFocusState, activeEntity }\"\n    \u003e\n      \u003cdiv\u003eACTIVE ENTITY: {{ activeEntity }}\u003c/div\u003e\n      \u003cdiv v-for=\"item in items\"\u003e\n        {{ item.description }}\n        \u003cbutton @click=\"deleteItem(item)\"\u003eDELETE\u003c/button\u003e\n        \u003cbutton @click=\"focusItem(item)\"\u003eDELETE\u003c/button\u003e\n        FOCUS STATE: {{ getFocusState(item) }}\n      \u003c/div\u003e\n    \u003c/template\u003e\n\n    \u003c!-- Create your available types menu --\u003e\n    \u003ctemplate #availableType=\"{ availableType }\"\u003e\n      \u003c!-- The click event is managed by the component, that will select the type to be used when adding a component to the blueprint --\u003e\n      \u003cbutton\u003e{{ availableType.description }}\u003c/button\u003e\n    \u003c/template\u003e\n\n    \u003c!-- Create your inventory, which will be displayed inside a details element (target the .grid-plan-inventory css class to style) --\u003e\n    \u003ctemplate #inventory=\"{ item, deleteItem, focusItem, isFocused }\"\u003e\n      \u003cdiv\n        :style=\"`display: flex; flex-direction:row; flex-wrap: wrap; border: 1px solid ${item.color};width: fit-content; padding: 6px 12px; gap:6px; ${isFocused ? 'background: #FFFFFF20' : ''}`\"\n      \u003e\n        \u003cspan\u003e{{ item.description }}\u003c/span\u003e\n        \u003cspan\u003ex:{{ item.x }}\u003c/span\u003e\n        \u003cspan\u003ey:{{ item.y }}\u003c/span\u003e\n        \u003cspan\u003eh:{{ item.h }}\u003c/span\u003e\n        \u003cspan\u003ew:{{ item.w }}\u003c/span\u003e\n        \u003cbutton @click=\"deleteItem\"\u003eDELETE\u003c/button\u003e\n        \u003cbutton @click=\"focusItem\"\u003e\n          {{ isFocused ? 'UNFOCUS' : 'FOCUS' }}\n        \u003c/button\u003e\n      \u003c/div\u003e\n    \u003c/template\u003e\n\n    \u003c!-- Use your own svg icons for component types (not necessary if the icon provided is part of the available icons) --\u003e\n    \u003ctemplate #componentIcon=\"{ placedItem, maxSize }\"\u003e\n      \u003csvg\n        v-if=\"placedItem.description === 'server'\"\n        viewBox=\"0 0 24 24\"\n        stroke-width=\"1.5\"\n        stroke=\"#FFFFFF\"\n        fill=\"none\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n        :style=\"`width:${maxSize}px; position: absolute; transform: scale(0.8, 0.8)`\"\n      \u003e\n        \u003cpath stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" /\u003e\n        \u003cpath\n          d=\"M3 4m0 3a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3z\"\n        /\u003e\n        \u003cpath\n          d=\"M3 12m0 3a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3z\"\n        /\u003e\n        \u003cpath d=\"M7 8l0 .01\" /\u003e\n        \u003cpath d=\"M7 16l0 .01\" /\u003e\n        \u003cpath d=\"M11 8h6\" /\u003e\n        \u003cpath d=\"M11 16h6\" /\u003e\n      \u003c/svg\u003e\n    \u003c/template\u003e\n\n    \u003c!-- Or use this slot to display a single letter or an icon font --\u003e\n    \u003ctemplate #componentText=\"{ placedItem }\"\u003e {{ placedItem.icon }} \u003c/template\u003e\n\n    \u003c!-- A slot to do whatever you need after the component --\u003e\n    \u003ctemplate\n      #after=\"{ items, deleteItem, focusItem, getFocusState, activeEntity }\"\n    \u003e\n      \u003cdiv\u003eACTIVE ENTITY: {{ activeEntity }}\u003c/div\u003e\n      \u003cdiv v-for=\"item in items\"\u003e\n        {{ item.description }}\n        \u003cbutton @click=\"deleteItem(item)\"\u003eDELETE\u003c/button\u003e\n        \u003cbutton @click=\"focusItem(item)\"\u003eDELETE\u003c/button\u003e\n        FOCUS STATE: {{ getFocusState(item) }}\n      \u003c/div\u003e\n    \u003c/template\u003e\n  \u003c/GridPlan\u003e\n\u003c/template\u003e\n```\n\n## Config details\n\n| Attribute             | TS type                   | Default      | Description                                                         |\n| --------------------- | ------------------------- | ------------ | ------------------------------------------------------------------- |\n| abscissaType          | \"alphabetic\" OR \"numeric\" | \"alphabetic\" | Display abscissa coordinates as letters or numbers                  |\n| accordionMenuTitle    | string                    | \"Menu\"       | Text content of detail summary                                      |\n| coordinatesBackground | string                    | \"#2A2A2A\"    | Background color of the coordinates cells                           |\n| coordinatesColor      | string                    | \"#8A8A8A\"    | Text color of the coordinates cells                                 |\n| crosshairBackground   | string                    | \"#4A4A4A\"    | Background color of the crosshair                                   |\n| fontFamily            | string                    | \"Arial\"      | Font used for all elements in the component                         |\n| grid3dPosition        | \"top\" OR \"bottom\"         | \"top\"        | Display 3d blueprint on top or below                                |\n| gridFill              | string                    | \"#3A3A3A\"    | Background color of unused blueprint cells                          |\n| gridHeight            | number                    | 20           | The height of the blueprint in cell units                           |\n| gridHighlightColor    | string                    | \"#FFFFFF\"    | The contour of available cells on hover                             |\n| gridStroke            | string                    | \"#1A1A1A\"    | The color of grid lines                                             |\n| gridWidth             | number                    | 20           | The width of the blueprint in cell units                            |\n| handleFill            | string                    | \"#FFFFFF\"    | The color of resize handles                                         |\n| handleSize            | number                    | 0.3          | The handle size                                                     |\n| iconColor             | string                    | \"#1A1A1A\"    | The text color when using the #componentText slot                   |\n| inventoryTitle        | string                    | \"Inventory\"  | The text content of the inventory details summary element           |\n| nonSelectedOpacity    | number                    | 0.3          | The opacity of non selected components when a component is selected |\n| ordinatesType         | \"alphabetic\" OR \"numeric\" | \"numeric\"    | Display ordinate coordinates as letters or numbers                  |\n| showCrosshair         | boolean                   | true         | Show crosshair when hovering available cells                        |\n| showGrid3d            | boolean                   | true         | Show the 3d blueprint                                               |\n| showInventory         | boolean                   | true         | Show inventory of placed components inside a details HTML element   |\n| tooltipColor          | string                    | \"#FFFFFF\"    | The tooltip text color                                              |\n| useAccordionMenu      | boolean                   | true         | Display the menu inside a details HTML element                      |\n| useGradient           | boolean                   | true         | Shows components with a subtle gradient                             |\n| useShadow             | boolean                   | true         | Show selected item with a drop shadow                               |\n| showBox               | boolean                   | true         | Show a 'wall' around the grid                                       |\n| boxThickness          | number                    | 0.3          | Box thickness, defaults to 1/3 of a grid cell                       |\n| boxHeight             | number                    | 1            | Box height, defaults to the same size as a grid cell                |\n| boxColor              | string                    | \"#5A5A5A\"    | Box color                                                           |\n\n## CSS classes\n\nGrid Plan does not ship css.\nTo customize the styling of the menu and inventory, target the following css classes:\n\n```css\n.grid-plan-main {\n}\n.grid-plan-menu {\n}\n.grid-plan-menu__summary {\n} /* If useAccordionMenu is true */\n.grid-plan-menu__body {\n} /* If useAccordionMenu is true */\n.grid-plan-inventory {\n}\n.grid-plan-inventory__summary {\n}\n.grid-plan-inventory__body {\n}\n.grid-plan-grid {\n}\n.grid-plan-grid-3d {\n}\n.grid-plan-grid-3d-label {\n}\n```\n\n## Icons\n\nA set of icons is provided by grid-plan. These icons are adapted from the great [Tabler icons](https://tablericons.com/) open source icon library.\n\nIcons are used in availableTypes:\n\n```js\nconst availableTypes = ref([\n  {\n    color: '#6376DD',\n    description: 'router',\n    icon: 'router',\n    typeId: 1,\n    iconColor: '#FFFFFF'\n  },\n  {...}\n])\n```\n\n| Icon name           |\n| ------------------- |\n| airConditioning     |\n| alertTriangle       |\n| analyze             |\n| archive             |\n| armchair            |\n| award               |\n| bath                |\n| battery             |\n| bed                 |\n| bell                |\n| bellSchool          |\n| bolt                |\n| boltOff             |\n| books               |\n| bulb                |\n| bulfOff             |\n| burger              |\n| calculator          |\n| camera              |\n| cctv                |\n| chefHat             |\n| circleKey           |\n| circuitCapacitor    |\n| circuitCell         |\n| circuitGround       |\n| circuitSwitchClosed |\n| circuitSwitchOpen   |\n| clock               |\n| cloud               |\n| cloudComputing      |\n| coffee              |\n| cpu                 |\n| cricuitLoop         |\n| database            |\n| deviceDesktop       |\n| deviceDesktopOff    |\n| deviceDualScreen    |\n| deviceImac          |\n| deviceImacOff       |\n| deviceLaptop        |\n| deviceLaptopOff     |\n| deviceTablet        |\n| deviceTabletOff     |\n| deviceTv            |\n| deviceTvOff         |\n| deviceUsb           |\n| devicesPc           |\n| devicesPcOff        |\n| disabled            |\n| door                |\n| doorEnter           |\n| doorExit            |\n| elevator            |\n| elevatorOff         |\n| escalator           |\n| escalatorDown       |\n| escalatorUp         |\n| fingerprint         |\n| firstAidKit         |\n| folder              |\n| folders             |\n| headphones          |\n| headset             |\n| hexagon             |\n| home                |\n| key                 |\n| keyboard            |\n| leaf                |\n| lock                |\n| lockAccess          |\n| man                 |\n| microphone          |\n| microscope          |\n| network             |\n| networkOff          |\n| package             |\n| packages            |\n| paperclip           |\n| phone               |\n| plant               |\n| plugConnected       |\n| power               |\n| printer             |\n| printerOff          |\n| prism               |\n| propeller           |\n| propellerOff        |\n| reportAnalytics     |\n| robot               |\n| router              |\n| salad               |\n| server              |\n| serverBolt          |\n| serverCog           |\n| serverOff           |\n| shredder            |\n| sofa                |\n| solarPanel          |\n| soup                |\n| squareKey           |\n| stack               |\n| toilet              |\n| toiletPaper         |\n| toolsKitchen        |\n| trafficCone         |\n| trash               |\n| trolley             |\n| volume              |\n| wall                |\n| washMachine         |\n| wave                |\n| wifi                |\n| windMill            |\n| windmillOff         |\n| window              |\n| world               |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraphieros%2Fgrid-plan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgraphieros%2Fgrid-plan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraphieros%2Fgrid-plan/lists"}