{"id":16945122,"url":"https://github.com/yiniau/native-spa-route","last_synced_at":"2025-04-13T21:52:17.585Z","repository":{"id":45287984,"uuid":"498719593","full_name":"Yiniau/native-spa-route","owner":"Yiniau","description":"Provide SPA route's experience with native web component","archived":false,"fork":false,"pushed_at":"2024-02-07T08:20:42.000Z","size":410,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-27T12:12:42.790Z","etag":null,"topics":["router","spa","webcomponent"],"latest_commit_sha":null,"homepage":"https://native-spa-route.vercel.app","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/Yiniau.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":"2022-06-01T12:05:05.000Z","updated_at":"2024-06-26T01:48:53.000Z","dependencies_parsed_at":"2024-10-13T21:21:10.299Z","dependency_job_id":null,"html_url":"https://github.com/Yiniau/native-spa-route","commit_stats":{"total_commits":97,"total_committers":3,"mean_commits":"32.333333333333336","dds":0.09278350515463918,"last_synced_commit":"18045b6c65a64ae5d9c3d04d8c8d29ce5aed44a1"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yiniau%2Fnative-spa-route","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yiniau%2Fnative-spa-route/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yiniau%2Fnative-spa-route/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yiniau%2Fnative-spa-route/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Yiniau","download_url":"https://codeload.github.com/Yiniau/native-spa-route/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248788867,"owners_count":21161726,"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":["router","spa","webcomponent"],"created_at":"2024-10-13T21:21:06.024Z","updated_at":"2025-04-13T21:52:17.564Z","avatar_url":"https://github.com/Yiniau.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# native-spa-route\n\n[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/owner/native-spa-route)\n\nprovide SPA route's experience with native web component\n\n[Online Demo](https://native-spa-route.vercel.app/)\n\n## Installation\n\n`pnpm install native-spa-route`\n\n## Usage\n\nthe fully example are ready in the index.html.\n\nhere are just some brief descriptions.\n\n### 1. Init module\n\nrun this in the top of your application\n\n```typescript\nimport { preload } from 'native-spa-route';\npreload();\n```\n\n**At current time (2022/6/6-17:04), this `preload` only supportted fully history API hook and fully `a` tag hook**,\nThis means that there is a high possibility of conflict with the routing scheme of some existing libraries.\n\nin this version, the hook of history api implament by add function to origin `history`'s prototype.\n\n```typescript\nexport function hook_history_change(\n  cb?: (...)\n) {\n  const prototype = Reflect.getPrototypeOf(history) as History;\n  const originPushState = prototype.pushState;\n  History.prototype.pushState = function pushState(...) {...};\n  // ... other function\n}\n```\n\nto direct use hook functions or write your own hook is toally supported.\n\nEVEN! You can use the `history:replaceState` event and `history:pushState` event to use this module in any enviroment\n\n```typescript\nfunction hook_route_change(callback: (e: HistoryChangeEvent) =\u003e void) {\n  window.addEventListener('history:pushState', callback as EventListener);\n  window.addEventListener('history:replaceState', callback as EventListener);\n  window.addEventListener('history:back', callback as EventListener);\n  window.addEventListener('history:forward', callback as EventListener);\n  window.addEventListener('history:go', callback as EventListener);\n  window.addEventListener('popstate', callback as EventListener, false);\n}\n```\n\n### 2. use Route\n\n```html\n\u003cnative-route path=\"/\"\u003e\n  \u003c!-- exact case, only active while pathname full match /root --\u003e\n  \u003cnative-route\n    path=\"root\"\n    exact\n    element=\"exact /root path route here\"\n  \u003e\u003c/native-route\u003e\n  \u003cnative-route path=\"root\" element=\"\u003cdiv\u003eROOT HERE\u003c/div\u003e\"\u003e\n    \u003cnative-route path=\"all\" element=\"\u003cdiv\u003eALL HERE\u003c/div\u003e\"\u003e\n    \u003c/native-route\u003e\n  \u003c/native-route\u003e\n\u003c/native-route\u003e\n```\n\nIf this module could write content as child, like `\u003cnative-route\u003e content here \u003c/native-route\u003e`\n\nOf course it works. But you need to do extra work to make them perform better.\n\nBecouse the Broswer will take unregisted component as `HTMLUnknowElement`, the content of them will visibale.\nSo you need to hidden them by css:\n\n```css\nnative-route {\n  display: none;\n}\nnative-route:defined {\n  display: block;\n}\n```\n\n\u003e The `visibility` property on my pc(MacBook Pro 12.3.1 M1) causes height changes, components to flicker.\n\nexample code:\n\n```html\n\u003cnative-route path=\"/lazy\"\u003e\n  \u003cul\u003e\n    \u003cli\u003e\u003ca href=\"/lazy/sl/button\"\u003e@shoelace-style/shoelace Button\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\n      \u003ca href=\"/lazy/sl/ready_button\"\u003e\n        render shoelace Button after module ready, disable cache to\n        get clear effect\n      \u003c/a\u003e\n    \u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/native-route\u003e\n```\n\nThose `a` tags only show while `/^\\/lazy/.test(location.pathname) === true`.\n\n## Lazy support\n\n\u003e see the demo to get detail\n\n```html\n\u003c!-- lazy useage --\u003e\n\u003cnative-route path=\"/lazy/sl\"\u003e\n  \u003cnative-route\n    path=\"button\"\n    url=\"https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.74/dist/components/button/button.js\"\n    element='\u003csl-button\u003eButton\u003c/sl-button\u003e\u003csl-button variant=\"primary\"\u003ePrimary\u003c/sl-button\u003e\u003csl-button variant=\"neutral\" loading\u003eNeutral\u003c/sl-button\u003e'\n    lazy\n  \u003e\n  \u003c/native-route\u003e\n  \u003cnative-route\n    path=\"ready_button\"\n    url=\"https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.74/dist/components/button/button.js\"\n    element='\u003csl-button\u003eRender After Ready Button\u003c/sl-button\u003e\u003csl-button variant=\"primary\"\u003ePrimary\u003c/sl-button\u003e\u003csl-button variant=\"neutral\" loading\u003eNeutral\u003c/sl-button\u003e'\n    render-after-ready\n    lazy\n  \u003e\n  \u003c/native-route\u003e\n\u003c/native-route\u003e\n```\n\n## Custom Render\n\n\u003e see the demo to get detail\n\nthis could be use to render react/vue/other render lib content.\n\n```html\n\u003cnative-route path=\"/custom-render\"\u003e\n  \u003cnative-route path=\"react\"\u003e\n    \u003cnative-route path=\"17/basic\" lazy url=\"@PUBLICK_PATH/react17.js\" custom-render\u003e\u003c/native-route\u003e\n    \u003cnative-route path=\"17/custom-render-name\" lazy url=\"@PUBLICK_PATH/react17.js\" custom-render=\"customRenderFunction\"\u003e\u003c/native-route\u003e\n    \u003cnative-route path=\"17/with-css\" lazy url=\"@PUBLICK_PATH/react17.js\" custom-render=\"withCss\" shadowCSSUrl=\"@PUBLICK_PATH/react17.css\"\u003e\u003c/native-route\u003e\n  \u003c/native-route\u003e\n  \u003cnative-route path=\"vue\"\u003e\n    \u003cnative-route path=\"3/basic\" lazy url=\"@PUBLICK_PATH/vue3.js\" shadowCSSUrl=\"@PUBLICK_PATH/vue3.css\" custom-render\u003e\u003c/native-route\u003e\n  \u003c/native-route\u003e\n\u003c/native-route\u003e\n```\n\n**this function require the JS source export an render function, the name can custom by `custom-render=\"\u003crender function name\u003e\"`**\n\n## Content Style CSS\n\nuse `\u003cstyle\u003e\u003call CSS content\u003e\u003c/style\u003e` to inject css into Shadow DOM content.\n\nuse by `css-url=\"\u003ccss url here\u003e\"`\n\nsupport multi css `css-url=\"['url1', 'url2']\"`\n\n```html\n\u003cnative-route path=\"17/with-css\" lazy url=\"@PUBLICK_PATH/react17.js\" custom-render=\"withCss\" shadowCSSUrl=\"@PUBLICK_PATH/react17.css\"\u003e\u003c/native-route\u003e\n\u003cnative-route path=\"3/basic\" lazy url=\"@PUBLICK_PATH/vue3.js\" shadowCSSUrl=\"@PUBLICK_PATH/vue3.css\" custom-render\u003e\u003c/native-route\u003e\n```\n\n## Disable Shadow DOM wrapper\n\nthe Shadow DOM wrapper is default provide by `lit`.\n\nIn some cases, it may cause strange problems, such as Antd's pop-up window mounting problem.\nuse `disable-shadow` could disable it. But! it may cause more content leak.\n\nexample:\n\n```html\n\u003cnative-route disable-shadow\u003e\u003c/native-route\u003e\n```\n\n## Disable render cache\n\ncache is enabled by default.\n\nuse `drop` attribute to disable this.\n\n```html\n\u003cnative-route\n  // ...\n  drop\n  // ...\n\u003e\u003c/native-route\u003e\n```\n\n## Redirect\n\n```typescript\nimport { redirect } from 'native-spa-route';\n// ...\nredirect('/', '/other/path');\n// ...\n```\n\n## Online Demo\n\n![Online Demo]([https://](https://native-spa-route.vercel.app/))\n\n## next step plan\n\n1. [x] ~~implament `\u003cnative-redirect from=\"/\" to=\"/home\"\u003e\u003c/native-redirect\u003e` component~~ implament redirect api\n2. [x] regexp based dynamic route\n3. [ ] support scoped route to avoid global history api change.\n\n```html\n\u003cnative-router\u003e\n  \u003cnative-route xxxx\u003e\n    \u003cnaitve-link\u003elink to other route\u003c/native-link\u003e\n  \u003c/native-route\u003e\n\u003c/native-router\u003e\n```\n\n## Contributing\n\n1. Fork it!\n2. Create your feature branch: `git checkout -b feature/my-new-feature`\n3. Commit your changes: `git commit -am 'feat: Add some feature'`\n4. Push to the branch: `git push origin feature/my-new-feature`\n5. Submit a pull request :D\n\n## License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyiniau%2Fnative-spa-route","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyiniau%2Fnative-spa-route","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyiniau%2Fnative-spa-route/lists"}