@madojs/mado 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +291 -0
- package/CHANGELOG.md +23 -0
- package/LICENSE +21 -0
- package/README.md +371 -0
- package/ROADMAP.md +52 -0
- package/dist/src/component.d.ts +48 -0
- package/dist/src/component.js +140 -0
- package/dist/src/component.js.map +1 -0
- package/dist/src/context.d.ts +40 -0
- package/dist/src/context.js +67 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/css.d.ts +54 -0
- package/dist/src/css.js +137 -0
- package/dist/src/css.js.map +1 -0
- package/dist/src/devtools.d.ts +22 -0
- package/dist/src/devtools.js +63 -0
- package/dist/src/devtools.js.map +1 -0
- package/dist/src/diagnostics.d.ts +11 -0
- package/dist/src/diagnostics.js +28 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/each.d.ts +39 -0
- package/dist/src/each.js +35 -0
- package/dist/src/each.js.map +1 -0
- package/dist/src/forms.d.ts +71 -0
- package/dist/src/forms.js +161 -0
- package/dist/src/forms.js.map +1 -0
- package/dist/src/head.d.ts +19 -0
- package/dist/src/head.js +97 -0
- package/dist/src/head.js.map +1 -0
- package/dist/src/html/bindings.d.ts +78 -0
- package/dist/src/html/bindings.js +304 -0
- package/dist/src/html/bindings.js.map +1 -0
- package/dist/src/html/parser.d.ts +64 -0
- package/dist/src/html/parser.js +521 -0
- package/dist/src/html/parser.js.map +1 -0
- package/dist/src/html/template-types.d.ts +27 -0
- package/dist/src/html/template-types.js +8 -0
- package/dist/src/html/template-types.js.map +1 -0
- package/dist/src/html/template.d.ts +45 -0
- package/dist/src/html/template.js +119 -0
- package/dist/src/html/template.js.map +1 -0
- package/dist/src/html.d.ts +16 -0
- package/dist/src/html.js +16 -0
- package/dist/src/html.js.map +1 -0
- package/dist/src/index.d.ts +35 -0
- package/dist/src/index.js +39 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lazy.d.ts +38 -0
- package/dist/src/lazy.js +73 -0
- package/dist/src/lazy.js.map +1 -0
- package/dist/src/lifecycle.d.ts +45 -0
- package/dist/src/lifecycle.js +66 -0
- package/dist/src/lifecycle.js.map +1 -0
- package/dist/src/page.d.ts +161 -0
- package/dist/src/page.js +38 -0
- package/dist/src/page.js.map +1 -0
- package/dist/src/persisted.d.ts +47 -0
- package/dist/src/persisted.js +119 -0
- package/dist/src/persisted.js.map +1 -0
- package/dist/src/resource.d.ts +120 -0
- package/dist/src/resource.js +275 -0
- package/dist/src/resource.js.map +1 -0
- package/dist/src/router/manifest.d.ts +56 -0
- package/dist/src/router/manifest.js +302 -0
- package/dist/src/router/manifest.js.map +1 -0
- package/dist/src/router/match.d.ts +62 -0
- package/dist/src/router/match.js +117 -0
- package/dist/src/router/match.js.map +1 -0
- package/dist/src/router/navigation.d.ts +89 -0
- package/dist/src/router/navigation.js +263 -0
- package/dist/src/router/navigation.js.map +1 -0
- package/dist/src/router.d.ts +13 -0
- package/dist/src/router.js +13 -0
- package/dist/src/router.js.map +1 -0
- package/dist/src/signal.d.ts +67 -0
- package/dist/src/signal.js +238 -0
- package/dist/src/signal.js.map +1 -0
- package/docs/README.md +12 -0
- package/docs/en/00-the-mado-way.md +106 -0
- package/docs/en/01-routing.md +204 -0
- package/docs/en/02-project-layout.md +58 -0
- package/docs/en/03-static-bake.md +251 -0
- package/docs/en/04-ide-setup.md +162 -0
- package/docs/en/05-why-mado.md +193 -0
- package/docs/en/06-for-backenders.md +422 -0
- package/docs/en/07-llm-pitfalls.md +486 -0
- package/docs/en/08-llm-zero-history-test.md +56 -0
- package/docs/en/09-shadow-vs-light-dom.md +122 -0
- package/docs/en/README.md +16 -0
- package/docs/fr/00-the-mado-way.md +108 -0
- package/docs/fr/01-routing.md +202 -0
- package/docs/fr/02-project-layout.md +58 -0
- package/docs/fr/03-static-bake.md +290 -0
- package/docs/fr/04-ide-setup.md +162 -0
- package/docs/fr/05-why-mado.md +193 -0
- package/docs/fr/06-for-backenders.md +432 -0
- package/docs/fr/07-llm-pitfalls.md +487 -0
- package/docs/fr/08-llm-zero-history-test.md +60 -0
- package/docs/fr/09-shadow-vs-light-dom.md +121 -0
- package/docs/fr/README.md +16 -0
- package/docs/ru/00-the-mado-way.md +93 -0
- package/docs/ru/01-routing.md +194 -0
- package/docs/ru/02-project-layout.md +57 -0
- package/docs/ru/03-static-bake.md +251 -0
- package/docs/ru/04-ide-setup.md +144 -0
- package/docs/ru/05-why-mado.md +193 -0
- package/docs/ru/06-for-backenders.md +422 -0
- package/docs/ru/07-llm-pitfalls.md +485 -0
- package/docs/ru/08-llm-zero-history-test.md +56 -0
- package/docs/ru/09-shadow-vs-light-dom.md +122 -0
- package/docs/ru/README.md +14 -0
- package/docs/uk/00-the-mado-way.md +54 -0
- package/docs/uk/01-routing.md +82 -0
- package/docs/uk/02-project-layout.md +46 -0
- package/docs/uk/03-static-bake.md +49 -0
- package/docs/uk/04-ide-setup.md +26 -0
- package/docs/uk/05-why-mado.md +34 -0
- package/docs/uk/06-for-backenders.md +50 -0
- package/docs/uk/07-llm-pitfalls.md +82 -0
- package/docs/uk/08-llm-zero-history-test.md +31 -0
- package/docs/uk/09-shadow-vs-light-dom.md +40 -0
- package/docs/uk/README.md +16 -0
- package/llms.txt +155 -0
- package/package.json +81 -0
- package/scripts/bake.mjs +406 -0
- package/scripts/bundle.mjs +146 -0
- package/scripts/cli.mjs +382 -0
- package/scripts/new.mjs +80 -0
- package/scripts/preview.mjs +176 -0
- package/scripts/release-notes.mjs +66 -0
- package/scripts/showcase-regression.mjs +392 -0
- package/server/serve.mjs +292 -0
- package/starters/crud/README.md +21 -0
- package/starters/crud/index.html +20 -0
- package/starters/crud/package.json +17 -0
- package/starters/crud/src/components/app-shell.ts +51 -0
- package/starters/crud/src/components/ticket-detail.ts +33 -0
- package/starters/crud/src/components/ticket-form.ts +69 -0
- package/starters/crud/src/components/ticket-list.ts +66 -0
- package/starters/crud/src/lib/api.ts +76 -0
- package/starters/crud/src/main.ts +12 -0
- package/starters/crud/src/pages/home.ts +18 -0
- package/starters/crud/src/pages/not-found.ts +12 -0
- package/starters/crud/src/pages/ticket-detail.ts +6 -0
- package/starters/crud/src/pages/ticket-new.ts +6 -0
- package/starters/crud/src/pages/tickets.ts +6 -0
- package/starters/crud/src/routes.ts +9 -0
- package/starters/crud/src/styles/global.ts +155 -0
- package/starters/crud/tsconfig.json +15 -0
- package/starters/minimal/README.md +19 -0
- package/starters/minimal/index.html +20 -0
- package/starters/minimal/package.json +17 -0
- package/starters/minimal/src/components/app-counter.ts +31 -0
- package/starters/minimal/src/main.ts +9 -0
- package/starters/minimal/src/pages/home.ts +18 -0
- package/starters/minimal/src/pages/not-found.ts +14 -0
- package/starters/minimal/src/routes.ts +6 -0
- package/starters/minimal/src/styles/global.ts +60 -0
- package/starters/minimal/tsconfig.json +15 -0
- package/templates/page-detail.ts +63 -0
- package/templates/page-form.ts +94 -0
- package/templates/page-list.ts +79 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { html, render } from "@madojs/mado";
|
|
2
|
+
import "./styles/global.js";
|
|
3
|
+
import router from "./routes.js";
|
|
4
|
+
import "./components/app-counter.js";
|
|
5
|
+
|
|
6
|
+
const app = document.getElementById("app");
|
|
7
|
+
if (!app) throw new Error("#app not found");
|
|
8
|
+
|
|
9
|
+
render(html`${router.view}`, app);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { html, page } from "@madojs/mado";
|
|
2
|
+
|
|
3
|
+
export default page({
|
|
4
|
+
title: "__APP_NAME__",
|
|
5
|
+
view: () => html`
|
|
6
|
+
<main class="shell">
|
|
7
|
+
<section class="panel">
|
|
8
|
+
<p class="eyebrow">Mado starter</p>
|
|
9
|
+
<h1>__APP_NAME__</h1>
|
|
10
|
+
<p>
|
|
11
|
+
A tiny native-web app with browser ESM, Web Components, signals and
|
|
12
|
+
tagged-template HTML.
|
|
13
|
+
</p>
|
|
14
|
+
<x-app-counter></x-app-counter>
|
|
15
|
+
</section>
|
|
16
|
+
</main>
|
|
17
|
+
`,
|
|
18
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { html, page } from "@madojs/mado";
|
|
2
|
+
|
|
3
|
+
export default page({
|
|
4
|
+
title: "Not found",
|
|
5
|
+
view: () => html`
|
|
6
|
+
<main class="shell">
|
|
7
|
+
<section class="panel">
|
|
8
|
+
<h1>Not found</h1>
|
|
9
|
+
<p>The page does not exist.</p>
|
|
10
|
+
<a href="/" data-link>Back home</a>
|
|
11
|
+
</section>
|
|
12
|
+
</main>
|
|
13
|
+
`,
|
|
14
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { css } from "@madojs/mado";
|
|
2
|
+
|
|
3
|
+
const sheet = css`
|
|
4
|
+
:root {
|
|
5
|
+
color-scheme: light;
|
|
6
|
+
font-family:
|
|
7
|
+
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
|
8
|
+
"Segoe UI", sans-serif;
|
|
9
|
+
color: #172033;
|
|
10
|
+
background: #f6f7f9;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
body {
|
|
14
|
+
margin: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
a {
|
|
18
|
+
color: #2563eb;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.shell {
|
|
22
|
+
min-height: 100vh;
|
|
23
|
+
display: grid;
|
|
24
|
+
place-items: center;
|
|
25
|
+
padding: 2rem;
|
|
26
|
+
box-sizing: border-box;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.panel {
|
|
30
|
+
width: min(100%, 44rem);
|
|
31
|
+
border: 1px solid #d9dee8;
|
|
32
|
+
border-radius: 8px;
|
|
33
|
+
background: white;
|
|
34
|
+
padding: 2rem;
|
|
35
|
+
box-shadow: 0 16px 40px rgb(17 24 39 / 0.08);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.eyebrow {
|
|
39
|
+
margin: 0 0 0.5rem;
|
|
40
|
+
color: #64748b;
|
|
41
|
+
font-size: 0.8rem;
|
|
42
|
+
font-weight: 700;
|
|
43
|
+
letter-spacing: 0.08em;
|
|
44
|
+
text-transform: uppercase;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
h1 {
|
|
48
|
+
margin: 0 0 0.75rem;
|
|
49
|
+
font-size: clamp(2rem, 6vw, 4rem);
|
|
50
|
+
line-height: 1;
|
|
51
|
+
letter-spacing: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
p {
|
|
55
|
+
max-width: 34rem;
|
|
56
|
+
line-height: 1.6;
|
|
57
|
+
}
|
|
58
|
+
`;
|
|
59
|
+
|
|
60
|
+
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"lib": ["ES2022", "DOM"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"outDir": "dist",
|
|
10
|
+
"rootDir": "src",
|
|
11
|
+
"declaration": false,
|
|
12
|
+
"sourceMap": true
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*.ts"]
|
|
15
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template: detail page by :id (loads one entity).
|
|
3
|
+
*
|
|
4
|
+
* Add to routes.ts:
|
|
5
|
+
* '/__name__/:id': () => import('./pages/__name__-detail.js'),
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
page,
|
|
10
|
+
component,
|
|
11
|
+
html,
|
|
12
|
+
css,
|
|
13
|
+
resource,
|
|
14
|
+
jsonFetcher,
|
|
15
|
+
} from "@madojs/mado";
|
|
16
|
+
|
|
17
|
+
interface Entity {
|
|
18
|
+
id: number;
|
|
19
|
+
name: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
component(
|
|
23
|
+
"x-__name__-detail",
|
|
24
|
+
({ host }) => {
|
|
25
|
+
// id comes from data-id; page() sets it from params.
|
|
26
|
+
const idAttr = () => host.dataset.id ?? "";
|
|
27
|
+
|
|
28
|
+
const item = resource<Entity>(
|
|
29
|
+
() => `/api/__name__/${idAttr()}`,
|
|
30
|
+
jsonFetcher(),
|
|
31
|
+
{ staleTime: 60_000 },
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return () => html`
|
|
35
|
+
<section>
|
|
36
|
+
${() =>
|
|
37
|
+
item.loading()
|
|
38
|
+
? html`<p><i>loading…</i></p>`
|
|
39
|
+
: item.error()
|
|
40
|
+
? html`<p class="err">${item.error()!.message}</p>`
|
|
41
|
+
: item.data()
|
|
42
|
+
? html`
|
|
43
|
+
<h1>${item.data()!.name}</h1>
|
|
44
|
+
<p>id: ${item.data()!.id}</p>
|
|
45
|
+
`
|
|
46
|
+
: null}
|
|
47
|
+
<a href="/__name__" data-link>← back to list</a>
|
|
48
|
+
</section>
|
|
49
|
+
`;
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
styles: css`
|
|
53
|
+
:host { display: block; }
|
|
54
|
+
.err { color: #c00; }
|
|
55
|
+
`,
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
export default page<{ id: string }>({
|
|
60
|
+
title: ({ id }) => `__Name__ #${id}`,
|
|
61
|
+
view: ({ params }) =>
|
|
62
|
+
html`<x-__name__-detail data-id=${params.id}></x-__name__-detail>`,
|
|
63
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template: create/edit form page.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
page,
|
|
7
|
+
component,
|
|
8
|
+
html,
|
|
9
|
+
css,
|
|
10
|
+
signal,
|
|
11
|
+
useForm,
|
|
12
|
+
mutation,
|
|
13
|
+
} from "@madojs/mado";
|
|
14
|
+
|
|
15
|
+
interface Values {
|
|
16
|
+
name: string;
|
|
17
|
+
email: string;
|
|
18
|
+
[k: string]: string | number | boolean | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
component(
|
|
22
|
+
"x-__name__-page",
|
|
23
|
+
() => {
|
|
24
|
+
const f = useForm<Values>({
|
|
25
|
+
name: { required: true, minLength: 2, default: "" },
|
|
26
|
+
email: { required: true, type: "email", default: "" },
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const save = mutation<Values, Values>(async (v) => {
|
|
30
|
+
const r = await fetch("/api/__name__", {
|
|
31
|
+
method: "POST",
|
|
32
|
+
headers: { "content-type": "application/json" },
|
|
33
|
+
body: JSON.stringify(v),
|
|
34
|
+
});
|
|
35
|
+
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
|
36
|
+
return (await r.json()) as Values;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const done = signal(false);
|
|
40
|
+
|
|
41
|
+
const submit = f.onSubmit(async (v) => {
|
|
42
|
+
await save.run(v);
|
|
43
|
+
done.set(true);
|
|
44
|
+
f.reset();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const err = (name: keyof Values) => () =>
|
|
48
|
+
f.touched()[name as string] && f.errors()[name as string]
|
|
49
|
+
? html`<small class="err">${f.errors()[name as string]}</small>`
|
|
50
|
+
: null;
|
|
51
|
+
|
|
52
|
+
return () => html`
|
|
53
|
+
<section>
|
|
54
|
+
<h1>__Name__</h1>
|
|
55
|
+
<form @submit=${submit} novalidate>
|
|
56
|
+
<label>
|
|
57
|
+
Name
|
|
58
|
+
<input name="name" .value=${() => f.values().name ?? ""}
|
|
59
|
+
@input=${f.onInput} @blur=${f.onBlur} />
|
|
60
|
+
${err("name")}
|
|
61
|
+
</label>
|
|
62
|
+
<label>
|
|
63
|
+
Email
|
|
64
|
+
<input name="email" type="email" .value=${() => f.values().email ?? ""}
|
|
65
|
+
@input=${f.onInput} @blur=${f.onBlur} />
|
|
66
|
+
${err("email")}
|
|
67
|
+
</label>
|
|
68
|
+
<button type="submit"
|
|
69
|
+
?disabled=${() => !f.isValid() || f.submitting() || save.loading()}>
|
|
70
|
+
${() => (save.loading() || f.submitting() ? "saving…" : "save")}
|
|
71
|
+
</button>
|
|
72
|
+
${() => (save.error() ? html`<p class="err">${save.error()!.message}</p>` : null)}
|
|
73
|
+
${() => (done() ? html`<p class="ok">saved</p>` : null)}
|
|
74
|
+
</form>
|
|
75
|
+
</section>
|
|
76
|
+
`;
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
styles: css`
|
|
80
|
+
:host { display: block; }
|
|
81
|
+
label { display: block; margin: .5rem 0; }
|
|
82
|
+
input { display: block; margin-top: .25rem; padding: .25rem .5rem;
|
|
83
|
+
border: 1px solid #999; border-radius: 4px; min-width: 14rem; }
|
|
84
|
+
.err { color: #c00; }
|
|
85
|
+
.ok { color: #060; }
|
|
86
|
+
button:disabled { opacity: .5; }
|
|
87
|
+
`,
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
export default page({
|
|
92
|
+
title: "__Name__",
|
|
93
|
+
view: () => html`<x-__name__-page></x-__name__-page>`,
|
|
94
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template: list page with URL filter and pagination.
|
|
3
|
+
* Copy into src/pages/ and rename.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
page,
|
|
8
|
+
component,
|
|
9
|
+
html,
|
|
10
|
+
css,
|
|
11
|
+
each,
|
|
12
|
+
resource,
|
|
13
|
+
queryParam,
|
|
14
|
+
jsonFetcher,
|
|
15
|
+
} from "@madojs/mado";
|
|
16
|
+
|
|
17
|
+
interface Item {
|
|
18
|
+
id: number;
|
|
19
|
+
name: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
component(
|
|
23
|
+
"x-__name__-page",
|
|
24
|
+
() => {
|
|
25
|
+
const search = queryParam("q", "");
|
|
26
|
+
const pageQ = queryParam("page", "1");
|
|
27
|
+
const limit = 20;
|
|
28
|
+
|
|
29
|
+
const items = resource<Item[]>(
|
|
30
|
+
() =>
|
|
31
|
+
`/api/__name__?q=${encodeURIComponent(search())}&page=${pageQ()}&limit=${limit}`,
|
|
32
|
+
jsonFetcher(),
|
|
33
|
+
{ staleTime: 30_000 },
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
return () => html`
|
|
37
|
+
<section>
|
|
38
|
+
<h1>__Name__</h1>
|
|
39
|
+
<input
|
|
40
|
+
placeholder="search..."
|
|
41
|
+
.value=${search}
|
|
42
|
+
@input=${(e: Event) =>
|
|
43
|
+
search.set((e.target as HTMLInputElement).value)}
|
|
44
|
+
/>
|
|
45
|
+
${() => (items.loading() ? html`<p><i>loading…</i></p>` : null)}
|
|
46
|
+
${() =>
|
|
47
|
+
items.error()
|
|
48
|
+
? html`<p class="err">${items.error()!.message}</p>`
|
|
49
|
+
: null}
|
|
50
|
+
<ul>
|
|
51
|
+
${() =>
|
|
52
|
+
each(
|
|
53
|
+
items.data() ?? [],
|
|
54
|
+
(it) => it.id,
|
|
55
|
+
(it) => html`<li>${it.name}</li>`,
|
|
56
|
+
)}
|
|
57
|
+
</ul>
|
|
58
|
+
<nav>
|
|
59
|
+
<button @click=${() =>
|
|
60
|
+
pageQ.set(String(Math.max(1, +pageQ() - 1)))}>‹</button>
|
|
61
|
+
<span>${pageQ}</span>
|
|
62
|
+
<button @click=${() => pageQ.set(String(+pageQ() + 1))}>›</button>
|
|
63
|
+
</nav>
|
|
64
|
+
</section>
|
|
65
|
+
`;
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
styles: css`
|
|
69
|
+
:host { display: block; }
|
|
70
|
+
.err { color: #c00; }
|
|
71
|
+
ul { padding-left: 1.2rem; }
|
|
72
|
+
`,
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
export default page({
|
|
77
|
+
title: "__Name__",
|
|
78
|
+
view: () => html`<x-__name__-page></x-__name__-page>`,
|
|
79
|
+
});
|