{"id":13450780,"url":"https://github.com/lloydzhou/x6-html-shape","last_synced_at":"2025-04-11T12:41:56.808Z","repository":{"id":152592145,"uuid":"626529064","full_name":"lloydzhou/x6-html-shape","owner":"lloydzhou","description":"x6 html shape without foreignObject. x6-html-shape, x6-react-shape, x6-vue-shape, x6-svelte-shape all in one!","archived":false,"fork":false,"pushed_at":"2024-08-28T07:15:29.000Z","size":399,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-01T08:36:48.660Z","etag":null,"topics":["antv-x6","html","portal","react","shape","svelte","teleport","vue","x6-html-shape","x6-react-shape","x6-svelte-shape","x6-vue-shape"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/lloydzhou.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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":"2023-04-11T16:42:38.000Z","updated_at":"2024-11-06T06:50:30.000Z","dependencies_parsed_at":"2024-08-28T08:17:41.983Z","dependency_job_id":null,"html_url":"https://github.com/lloydzhou/x6-html-shape","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lloydzhou%2Fx6-html-shape","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lloydzhou%2Fx6-html-shape/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lloydzhou%2Fx6-html-shape/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lloydzhou%2Fx6-html-shape/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lloydzhou","download_url":"https://codeload.github.com/lloydzhou/x6-html-shape/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248402523,"owners_count":21097330,"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":["antv-x6","html","portal","react","shape","svelte","teleport","vue","x6-html-shape","x6-react-shape","x6-svelte-shape","x6-vue-shape"],"created_at":"2024-07-31T07:00:38.387Z","updated_at":"2025-04-11T12:41:56.776Z","avatar_url":"https://github.com/lloydzhou.png","language":"TypeScript","funding_links":[],"categories":["Frameworks"],"sub_categories":["HTML shape"],"readme":"# x6-html-shape\n\nhtml shape for [@antv/x6](https://github.com/antvis/X6)\n\n\u003ca href=\"https://www.npmjs.com/package/x6-html-shape\"\u003e\u003cimg alt=\"NPM Package\" src=\"https://img.shields.io/npm/v/x6-html-shape.svg?style=flat-square\"\u003e\u003c/a\u003e\n![npm bundle size](https://img.shields.io/bundlephobia/minzip/x6-html-shape?style=flat-square)\n![npm](https://img.shields.io/npm/dm/x6-html-shape?style=flat-square)\n\u003ca href=\"/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/lloydzhou/x6-html-shape?style=flat-square\" alt=\"MIT License\"\u003e\u003c/a\u003e\n\n![image](https://github.com/lloydzhou/x6-html-shape/assets/1826685/1ea8cbc4-49f1-478b-a0b7-228eea993f88)\n\n## online demo\n\n[svelte codesandbox demo](https://codesandbox.io/s/x6-html-shape-svelte-5t1r9r)\n\n[vue codesandbox demo](https://codesandbox.io/s/x6-html-shape-vue-xvvlsh)\n\n[react codesandbox demo](https://codesandbox.io/s/html-shape-for-x6-0y71sv)\n\n![image](https://user-images.githubusercontent.com/1826685/231785511-1363f084-235f-44cd-b88a-0b88e3be09d2.png)\n\n## example\n\n```\nimport { register } from \"x6-html-shape\";\n\nregister({\n  shape: \"html-shape-for-react\",\n  render: (node, graph, container) =\u003e {\n    const root = createRoot(container);\n    root.render(\u003cCustomComponent node={node} /\u003e);\n    return () =\u003e root.unmount();\n  },\n  width: 100,\n  height: 40\n});\n\n\nconst graph = new Graph({\n  container: this.container,\n  background: {\n    color: \"#F2F7FA\"\n  }\n});\n\ngraph.addNode({\n  shape: \"html-shape-for-react\",\n  x: 100,\n  y: 200,\n  label: 'rect', \n})\n\n```\n\n## 事件穿透\n1. 由于DOM层级关系，html-shape实现的节点总是在svg上层\n2. 通过给`x6-html-shape-container`设置`pointer-events: none`屏蔽这一层的交互，使得鼠标事件能穿透到svg内部节点。但是`x6-html-shape-node`内部有一些元素是需要交互的，所以给节点打开\n3. 至于事件穿透使用`forwardEvent`将节点内部的鼠标事件转发到对应的`x6-node`内部\n\n```\nexport function forwardEvent(eventType, fromElement, toElement) {\n  fromElement.addEventListener(eventType, function (event) {\n    toElement.dispatchEvent(new event.constructor(event.type, event));\n    event.preventDefault();\n    event.stopPropagation();\n  });\n}\n```\n\n\n# react\n\n## react18\n```\nimport createRender from 'x6-html-shape/dist/react'\n\nconst render = createRender(Component)\n\nregister({\n  shape: 'react18-node',\n  render,\n  width: 100,\n  height: 40,\n})\n```\n\n## react17\n```\nimport createRender from 'x6-html-shape/dist/react17'\n\nconst render = createRender(Component)\n\nregister({\n  shape: 'react17-node',\n  render,\n  width: 100,\n  height: 40,\n})\n```\n\n## react-portal\n```\nimport { register } from 'x6-html-shape'\nimport createRender from 'x6-html-shape/dist/portal'\n// 1. createRender using Component\n const [render, Provider] = createRender(Component)\n2. register node\nregister({\n  shape: 'react-portal-node',\n  render,\n  width: 100,\n  height: 40,\n})\n\n// 3.render Provider in react app before call graph.addNode\n \u003cProvider /\u003e\n// 4. add Node\ngraph.addNode({\n  shape: 'react-portal-node',\n  id: 'node1',\n  label: 'node1',\n  x: 100,\n  y: 100,\n})\n```\n\n# vue\n\n## vue3\n```\nimport createRender from 'x6-html-shape/dist/vue'\n\nconst render = createRender(Component)\n\nregister({\n  shape: 'vue3-node',\n  render,\n  width: 100,\n  height: 40,\n})\n```\n\n## vue2\n```\nimport createRender from 'x6-html-shape/dist/vue2'\n\nconst render = createRender(Component)\n\nregister({\n  shape: 'vue2-node',\n  render,\n  width: 100,\n  height: 40,\n})\n```\n\n## vue3-teleport\n```\nimport { register } from 'x6-html-shape'\nimport createRender from 'x6-html-shape/dist/teleport'\n// 1. createRender using Component\n const [render, Provider] = createRender(Component)\n2. register node\nregister({\n  shape: 'vue3-teleport-node',\n  render,\n  width: 100,\n  height: 40,\n})\n\n// 3.render Provider in react app before call graph.addNode\n \u003cProvider /\u003e\n// 4. add Node\ngraph.addNode({\n  shape: 'vue3-teleport-node',\n  id: 'vue3-teleport-node',\n  label: 'vue3 teleport node',\n  x: 100,\n  y: 100,\n})\n```\n\n# svelte\n```\nimport { register } from 'x6-html-shape'\nimport createRender from 'x6-html-shape/dist/svelte'\n// 1. createRender using Component\n const render = createRender(Component)\n2. register node\nregister({\n  shape: 'svelte-node',\n  render,\n  width: 100,\n  height: 40,\n})\n\n// 3. add Node\ngraph.addNode({\n  shape: 'svelte-node',\n  label: 'svelte node',\n  x: 100,\n  y: 100,\n})\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flloydzhou%2Fx6-html-shape","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flloydzhou%2Fx6-html-shape","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flloydzhou%2Fx6-html-shape/lists"}