native-spa-route
Version:
provide SPA route's experience with native web component
378 lines (341 loc) • 14.9 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Native SPA Route Demo</title>
<!-- <link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/themes/light.css"
/> -->
<!-- <script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/shoelace.js"></script> -->
</head>
<body class="sl-theme-light">
<script type="module" async>
import { preload } from /*IMPORTSOURCESTART*/'/src/main.ts'/*IMPORTSOURCEEND*/;
preload();
</script>
<style>
:root {
--font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans',
'Helvetica Neue', sans-serif;
--font-family-mono: source-code-pro, Menlo, Monaco, Consolas,
'Courier New', monospace;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 5px;
min-width: 100vw;
min-height: 100vh;
line-height: 1.4;
font-family: var(--font-family-base);
font-size: 16px;
font-weight: 400;
direction: ltr;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
background-color: #61dafb;
}
native-route {
visibility: hidden;
}
native-route:defined {
/* display: block; */
visibility: visible;
}
native-route-container {
visibility: hidden;
}
native-route-container:defined {
visibility: visible;
}
.route-content {
border: 1px solid #d5d5d5;
border-radius: 3px;
box-shadow: 0 0 5px 0px #d5d5d5d9;
margin: 15px;
min-height: 100px;
}
</style>
<main>
<p>
provide SPA route's experience with native web component
<div>
<a href="https://github.com/Yiniau/native-spa-route">Github Repo</a>
</div>
</p>
<p>NOTICE! this demo use `<code>:defined</code>` pseudo-class to avoid undefined element's inner content leak</p>
<p>BTW. you can use `<code>disable-shadow</code>` to disable shadowDOM</p>
<ul>
<li><a href="/common">common</a></li>
<li><a href="/root">nest path: root</a></li>
<li><a href="/root/all">nest path: root/all</a></li>
<div style="height: 16px"></div>
<li>
<a href="/cache-and-drop">cache and drop</a>
</li>
<native-route path="/cache-and-drop">
<ul>
<li>
<a href="/cache-and-drop/cache/input1">cache input 1</a>
</li>
<li>
<a href="/cache-and-drop/cache/input2">cache input 2</a>
</li>
<li>
<a href="/cache-and-drop/drop/input1">drop input 1 (will drop input value after switch route)</a>
</li>
<li>
<a href="/cache-and-drop/drop/input2">drop input 2 (will drop input value after switch route)</a>
</li>
</ul>
</native-route>
<div style="height: 16px"></div>
<li>
<a href="/lazy">lazy demo</a>
<native-route path="/lazy">
<ul>
<li>
<a href="/lazy/sl/button">@shoelace-style/shoelace Button</a>
</li>
<li>
<a href="/lazy/sl/ready_button"
>render shoelace Button after module ready, disable cache to
get clear effect</a
>
</li>
</ul>
</native-route>
</li>
<div style="height: 16px"></div>
<li>
<a href="/custom-render"
>custom render demo, this could be use to render react/vue/other
render lib content<br/>
<strong>If you are in a local environment, you need to additionally run the <code>pnpm run dev:demo</code> command</strong>
</a>
<native-route path="/custom-render">
<ul>
<li>
<a href="/custom-render/react/17/basic">react 17 demo</a>
</li>
<li>
<a href="/custom-render/react/17/custom-render-name">react 17 custom render name</a>
</li>
<li>
<a href="/custom-render/react/17/with-css">react 17 with css</a>
</li>
<li>
<a href="/custom-render/vue/3/basic">vue 3 demo (enable drop)</a>
</li>
</ul>
</native-route>
</li>
<div style="height: 16px"></div>
<li>
<a href="/append-direction/before">append before</a>
</li>
<li>
<a href="/append-direction/after">append after</a>
</li>
<div style="height: 16px"></div>
<li><a href="/loading">loading status</a></li>
</ul>
<h3>common demo area</h3>
<div class="route-content">
<native-route path="/common" element="common"></native-route>
<!-- basic useage -->
<native-route path="/">
<!-- exact case, only active while pathname full match /root -->
<native-route
path="root"
exact
element="exact /root path route here"
></native-route>
<native-route path="root" element="<div>ROOT HERE</div>">
<native-route path="all" element="<div>ALL HERE</div>">
</native-route>
</native-route>
</native-route>
<native-route path="/cache-and-drop">
<native-route path="cache">
<native-route path="input1" element="<input>"></native-route>
<native-route path="input2" element="<input>"></native-route>
</native-route>
<native-route path="drop">
<native-route path="input1" drop element="<input>"></native-route>
<native-route path="input2" drop element="<input>"></native-route>
</native-route>
</native-route>
<!-- lazy useage -->
<native-route path="/lazy/sl">
<native-route
path="button"
url="//cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/components/button/button.js"
css-url='["https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/themes/light.css"]'
element='<sl-button>Button</sl-button><sl-button variant="primary">Primary</sl-button><sl-button variant="neutral" loading>Neutral</sl-button>'
lazy
>
</native-route>
<native-route
path="ready_button"
url="//cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/components/button/button.js"
css-url='["//cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/themes/light.css"]'
element='<sl-button>Render After Ready Button</sl-button><sl-button variant="primary">Primary</sl-button><sl-button variant="neutral" loading>Neutral</sl-button>'
render-after-ready
lazy
>
</native-route>
</native-route>
<!-- custom render useage -->
<native-route path="/custom-render">
<native-route path="react">
<native-route path="17/basic" lazy url="@PUBLICK_PATH/react17.js" custom-render></native-route>
<native-route path="17/custom-render-name" lazy url="@PUBLICK_PATH/react17.js" custom-render="customRenderFunction"></native-route>
<native-route path="17/with-css" lazy url="@PUBLICK_PATH/react17.js" custom-render="withCss" shadowCSSUrl="@PUBLICK_PATH/react17.css"></native-route>
</native-route>
<native-route path="vue">
<native-route drop path="3/basic" lazy url="@PUBLICK_PATH/vue3.js" shadowCSSUrl="@PUBLICK_PATH/vue3.css" custom-render></native-route>
</native-route>
</native-route>
<!-- append direction -->
<native-route path="/append-direction">
<native-route path="before" element="<strong>CENTER</strong>" append-direction="before">
<div slot>child before after</div>
</native-route>
<native-route path="after" element="<strong>CENTER</strong>">
<div slot>child append after</div>
</native-route>
</native-route>
<native-route
path="/loading"
lazy
url="//cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/components/button/button.js"
css-url="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/themes/light.css"
render-after-ready
loadingElement="<span>will show loading... 50000ms</span>"
lockLoadingTime="50000"
></native-route>
</div>
<h3>common route container demo area</h3>
<ul>
<li><a href="/route-container">container (virtualNode, this route's active status will be ignored by container)</a></li>
<li><a href="/route-container/not-match-any-route-asd123t9q3gjh34g1">unvalid route</a></li>
<li><a href="/route-container/not-404">valid route</a></li>
</ul>
<div class="route-content">
<native-route-container root-path="/route-container">
<div slot="404" style="width: 100px; height: 50px; display: flex; align-items: center; justify-content: space-around;">
<strong>404</strong>
</div>
<div>
<native-route
path="/route-container"
lazy
url="//cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/components/button/button.js"
css-url="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/themes/light.css"
render-after-ready
loadingElement="<span>will show loading as last 96ms</span>"
lockLoadingTime="96"
element="<div><code>route container demo</code></div>"
virtualNode
>
<native-route path="not-match-path_1jj41gn5og159" element="not match route, this content should not appear"></native-route>
<native-route path="not-404" element="common content here"></native-route>
</native-route>
</div>
</native-route-container>
</div>
<h3>no shadow dom route container demo area</h3>
<ul>
<li><a href="/light-dom-route-container">container</a></li>
<li><a href="/light-dom-route-container/light-dom-not-match-any-route-asd123t9q3gjh34g1">unvalid route</a></li>
<li><a href="/light-dom-route-container/not-404">valid route</a></li>
</ul>
<div class="route-content">
<native-route-container root-path="/light-dom-route-container" disableShadow>
<native-route
path="/light-dom-route-container"
lazy
url="//cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/components/button/button.js"
css-url="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.83/dist/themes/light.css"
render-after-ready
loadingElement="<span>will show loading as last 96ms</span>"
lockLoadingTime="96"
element="<div><code>no shadow dom route container demo<br/>this line always visiable while location.href starts with `/light-dom-route-container`</code></div>"
virtualNode
>
<native-route path="not-match-path_1jj41gn5og159" element="not match route, this content should not appear"></native-route>
<native-route path="not-404" element="<span>common content here</span>"></native-route>
</native-route>
</native-route-container>
</div>
<h3>dynamic route path</h3>
<ul>
<li><a href="/dynamic-route">dynamic route</a></li>
<li><a href="/dynamic-route/matched_1">matched value 1</a></li>
<li><a href="/dynamic-route/matched_2">matched value 2</a></li>
<li><a href="/dynamic-route/matched_3">matched value 3</a></li>
<li><a href="/dynamic-route/matched_4">matched value 4</a></li>
<li><a href="/dynamic-route/not-matched">not matched</a></li>
</ul>
<div class="route-content">
<native-route-container
disableShadow
root-path="/dynamic-route"
element="<div><code>dynamic route</code></div>"
>
<native-route path="/dynamic-route">
<native-route path=":matched_[0-9]" element="matched"></native-route>
<native-route path=":DEFAULT" element="not match"></native-route>
</native-route>
</native-route-container>
</div>
<h3>group route match mode</h3>
<p>
<section>group match mode will split path to <code style="background-color: #9e9e9e25; border-radius: 4px;">['before self route', 'self route', 'after self route']</code></section>
<section>
common match mode will split path to
<code style="background-color: #9e9e9e25; border-radius: 4px;">
fullpath.split('/')
</code>
</section>
</p>
<ul>
<li><a href="/group-match-route">group-match-route</a></li>
<li><a href="/group-match-route/matched_1">matched value 1</a></li>
<li><a href="/group-match-route/nest/route">nest route</a></li>
<li><a href="/group-match-route/not-matched">not matched</a></li>
</ul>
<div class="route-content">
<native-route-container root-path="/group-match-route" disableShadow>
<native-route path="/group-match-route" element="<div><code>group match mode</code></div>">
<native-route path="matched_1" element="matched value 1" groupMatchMode></native-route>
<native-route path=":(?:^$)|(?:nest)|(?:nest/route)" element="nest route" groupMatchMode></native-route>
<native-route path=":DEFAULT" element="not match" groupMatchMode></native-route>></native-route>
</native-route>
</native-route-container>
</div>
</main>
<script type="module">
document.querySelectorAll('native-route-container').forEach(t => {
console.log(t);
t.set404Content(/* html */`
<div style="width: 100px; height: 50px; display: flex; align-items: center; justify-content: space-around;">
<strong>404</strong>
</div>
`);
})
history.pushState(history.state, '', location.pathname);
</script>
</body>
</html>