@techninja/clearstack 0.3.6 → 0.3.8
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/docs/CONVENTIONS.md +46 -2
- package/docs/SERVER_AND_DEPS.md +10 -1
- package/lib/check.js +35 -17
- package/lib/package-gen.js +12 -0
- package/lib/spec-utils.js +32 -0
- package/package.json +10 -1
- package/templates/fullstack/src/router/index.js +1 -1
- package/templates/shared/.configs/jsconfig.json +8 -1
- package/templates/shared/docs/clearstack/CONVENTIONS.md +46 -2
- package/templates/shared/docs/clearstack/SERVER_AND_DEPS.md +10 -1
- package/templates/shared/src/components/atoms/theme-toggle/theme-toggle.js +2 -2
- package/templates/shared/src/index.html +8 -1
- package/templates/static/src/pages/home/home-view.js +3 -3
- package/templates/static/src/router/index.js +1 -1
package/docs/CONVENTIONS.md
CHANGED
|
@@ -109,6 +109,50 @@ render: ({ items }) => html`
|
|
|
109
109
|
|
|
110
110
|
---
|
|
111
111
|
|
|
112
|
+
## Import Map Aliases
|
|
113
|
+
|
|
114
|
+
All cross-directory imports in browser-facing code use `#prefix/` aliases
|
|
115
|
+
defined in the import map (`src/index.html`). This eliminates fragile
|
|
116
|
+
relative paths like `../../../utils/foo.js`.
|
|
117
|
+
|
|
118
|
+
### Available Prefixes
|
|
119
|
+
|
|
120
|
+
| Prefix | Resolves to |
|
|
121
|
+
| --------------- | ------------------------------ |
|
|
122
|
+
| `#store/` | `/store/` |
|
|
123
|
+
| `#utils/` | `/utils/` |
|
|
124
|
+
| `#atoms/` | `/components/atoms/` |
|
|
125
|
+
| `#molecules/` | `/components/molecules/` |
|
|
126
|
+
| `#organisms/` | `/components/organisms/` |
|
|
127
|
+
| `#templates/` | `/components/templates/` |
|
|
128
|
+
| `#pages/` | `/pages/` |
|
|
129
|
+
|
|
130
|
+
### Rules
|
|
131
|
+
|
|
132
|
+
- **No `../` imports.** The spec check (`npm run spec`) flags any `../`
|
|
133
|
+
in browser-facing JS. Use a `#prefix/` alias instead.
|
|
134
|
+
- **Same-directory `./` is fine.** `index.js` re-exports and co-located
|
|
135
|
+
files use `./` naturally.
|
|
136
|
+
- **Server/API files are exempt.** `src/api/` and `src/server.js` run in
|
|
137
|
+
Node, not the browser — they use `./` relative imports.
|
|
138
|
+
- **Test files are exempt.** `*.test.js` files may use relative paths.
|
|
139
|
+
- **jsconfig.json mirrors the import map.** The `paths` entries in
|
|
140
|
+
`.configs/jsconfig.json` let `tsc --checkJs` resolve `#prefix/` imports.
|
|
141
|
+
|
|
142
|
+
### Examples
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
// ✅ Good — clear, refactor-safe
|
|
146
|
+
import AppState from '#store/AppState.js';
|
|
147
|
+
import { formatDate } from '#utils/formatDate.js';
|
|
148
|
+
import '#atoms/app-badge/app-badge.js';
|
|
149
|
+
|
|
150
|
+
// ❌ Bad — fragile, hard to read
|
|
151
|
+
import AppState from '../../../store/AppState.js';
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
112
156
|
## Error Handling
|
|
113
157
|
|
|
114
158
|
Errors are handled **at the boundary where they are actionable.** Each layer
|
|
@@ -193,8 +237,8 @@ state: store(AppState),
|
|
|
193
237
|
// In src/utils/filterActive.js
|
|
194
238
|
export const filterActive = (items) => items.filter(i => i.active);
|
|
195
239
|
|
|
196
|
-
// In component
|
|
197
|
-
import { filterActive } from '
|
|
240
|
+
// In component — use import map alias, never ../
|
|
241
|
+
import { filterActive } from '#utils/filterActive.js';
|
|
198
242
|
render: ({ items }) => html`<ul>${filterActive(items).map(...)}</ul>`,
|
|
199
243
|
```
|
|
200
244
|
|
package/docs/SERVER_AND_DEPS.md
CHANGED
|
@@ -121,7 +121,14 @@ declared in `src/index.html`.
|
|
|
121
121
|
<script type="importmap">
|
|
122
122
|
{
|
|
123
123
|
"imports": {
|
|
124
|
-
"hybrids": "/vendor/hybrids/index.js"
|
|
124
|
+
"hybrids": "/vendor/hybrids/index.js",
|
|
125
|
+
"#store/": "/store/",
|
|
126
|
+
"#utils/": "/utils/",
|
|
127
|
+
"#atoms/": "/components/atoms/",
|
|
128
|
+
"#molecules/": "/components/molecules/",
|
|
129
|
+
"#organisms/": "/components/organisms/",
|
|
130
|
+
"#templates/": "/components/templates/",
|
|
131
|
+
"#pages/": "/pages/"
|
|
125
132
|
}
|
|
126
133
|
}
|
|
127
134
|
</script>
|
|
@@ -139,6 +146,8 @@ declared in `src/index.html`.
|
|
|
139
146
|
2. Import map resolves `'hybrids'` → `/vendor/hybrids/index.js`.
|
|
140
147
|
3. Server serves the file from `src/vendor/hybrids/index.js`.
|
|
141
148
|
4. Hybrids' internal imports use relative paths — they resolve naturally.
|
|
149
|
+
5. `#prefix/` entries resolve cross-directory app imports without `../`.
|
|
150
|
+
For example, `import '#utils/formatDate.js'` resolves to `/utils/formatDate.js`.
|
|
142
151
|
|
|
143
152
|
### Rules
|
|
144
153
|
|
package/lib/check.js
CHANGED
|
@@ -6,9 +6,16 @@
|
|
|
6
6
|
|
|
7
7
|
import { readFileSync, existsSync } from 'node:fs';
|
|
8
8
|
import { resolve } from 'node:path';
|
|
9
|
-
import { checkFileLines, runCmd, countFiles } from './spec-utils.js';
|
|
9
|
+
import { checkFileLines, runCmd, countFiles, checkImports } from './spec-utils.js';
|
|
10
10
|
|
|
11
|
-
export { checkFileLines, runCmd, countFiles, findFiles, elapsed } from './spec-utils.js';
|
|
11
|
+
export { checkFileLines, runCmd, countFiles, findFiles, elapsed, checkImports } from './spec-utils.js';
|
|
12
|
+
|
|
13
|
+
/** Detect the project's package manager runner (npx, pnpm exec, yarn). */
|
|
14
|
+
function detectRunner(projectDir) {
|
|
15
|
+
if (existsSync(resolve(projectDir, 'pnpm-lock.yaml'))) return 'pnpm exec';
|
|
16
|
+
if (existsSync(resolve(projectDir, 'yarn.lock'))) return 'yarn';
|
|
17
|
+
return 'npx';
|
|
18
|
+
}
|
|
12
19
|
|
|
13
20
|
/** @param {string} src */
|
|
14
21
|
function parseEnv(src) {
|
|
@@ -36,15 +43,24 @@ export function loadConfig(projectDir) {
|
|
|
36
43
|
};
|
|
37
44
|
}
|
|
38
45
|
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
46
|
+
/**
|
|
47
|
+
* Build check commands for the detected package manager.
|
|
48
|
+
* @param {string} runner
|
|
49
|
+
*/
|
|
50
|
+
function buildCmds(runner) {
|
|
51
|
+
const audit = runner === 'pnpm exec' ? 'pnpm audit --prod' : 'npm audit --omit=dev';
|
|
52
|
+
return {
|
|
53
|
+
lint: `${runner} eslint --config .configs/eslint.config.js . --fix`,
|
|
54
|
+
stylelint: `${runner} stylelint --config .configs/.stylelintrc.json "src/**/*.css" --fix`,
|
|
55
|
+
prettier: `${runner} prettier --config .configs/.prettierrc --write src scripts`,
|
|
56
|
+
mdlint: `${runner} markdownlint-cli2 --config .configs/.markdownlint.jsonc --fix "docs/**/*.md" "*.md"`,
|
|
57
|
+
types: `${runner} tsc --project .configs/jsconfig.json`,
|
|
58
|
+
audit,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** @deprecated Use buildCmds() instead — kept for backward compat. */
|
|
63
|
+
export const CMDS = buildCmds('npx');
|
|
48
64
|
|
|
49
65
|
/**
|
|
50
66
|
* Run the full spec compliance check (used by clearstack CLI).
|
|
@@ -53,6 +69,7 @@ export const CMDS = {
|
|
|
53
69
|
*/
|
|
54
70
|
export async function check(projectDir, scope) {
|
|
55
71
|
const cfg = loadConfig(projectDir);
|
|
72
|
+
const cmds = buildCmds(detectRunner(projectDir));
|
|
56
73
|
|
|
57
74
|
if (scope === 'code') {
|
|
58
75
|
if (!checkFileLines(projectDir, cfg.codeExt, cfg.codeMax, cfg.ignore, `Code (max ${cfg.codeMax} lines)`))
|
|
@@ -73,12 +90,13 @@ export async function check(projectDir, scope) {
|
|
|
73
90
|
const results = [
|
|
74
91
|
checkFileLines(projectDir, cfg.codeExt, cfg.codeMax, cfg.ignore, `Code (max ${cfg.codeMax} lines)`),
|
|
75
92
|
checkFileLines(projectDir, cfg.docsExt, cfg.docsMax, cfg.ignore, `Docs (max ${cfg.docsMax} lines)`),
|
|
76
|
-
|
|
77
|
-
runCmd('
|
|
78
|
-
runCmd('
|
|
79
|
-
runCmd('
|
|
80
|
-
runCmd('
|
|
81
|
-
runCmd('
|
|
93
|
+
checkImports(projectDir, cfg.ignore, 'Import map aliases (no ../ imports)'),
|
|
94
|
+
runCmd('ESLint', cmds.lint, projectDir, `${jsFiles} files`),
|
|
95
|
+
runCmd('Stylelint', cmds.stylelint, projectDir, `${cssFiles} files`),
|
|
96
|
+
runCmd('Prettier', cmds.prettier, projectDir, `${jsFiles} files`),
|
|
97
|
+
runCmd('Markdown', cmds.mdlint, projectDir, `${mdFiles} files`),
|
|
98
|
+
runCmd('JSDoc types', cmds.types, projectDir, `${jsFiles} files`),
|
|
99
|
+
runCmd('Security audit', cmds.audit, projectDir),
|
|
82
100
|
];
|
|
83
101
|
|
|
84
102
|
const passed = results.filter(Boolean).length;
|
package/lib/package-gen.js
CHANGED
|
@@ -49,6 +49,16 @@ export async function writePackageJson(dest, vars, existing) {
|
|
|
49
49
|
typescript: '^6.0.2',
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
+
const subpathImports = {
|
|
53
|
+
'#store/*': './src/store/*',
|
|
54
|
+
'#utils/*': './src/utils/*',
|
|
55
|
+
'#atoms/*': './src/components/atoms/*',
|
|
56
|
+
'#molecules/*': './src/components/molecules/*',
|
|
57
|
+
'#organisms/*': './src/components/organisms/*',
|
|
58
|
+
'#templates/*': './src/components/templates/*',
|
|
59
|
+
'#pages/*': './src/pages/*',
|
|
60
|
+
};
|
|
61
|
+
|
|
52
62
|
const pkg = existing
|
|
53
63
|
? {
|
|
54
64
|
...existing,
|
|
@@ -56,6 +66,7 @@ export async function writePackageJson(dest, vars, existing) {
|
|
|
56
66
|
description: vars.description,
|
|
57
67
|
type: 'module',
|
|
58
68
|
main: 'src/server.js',
|
|
69
|
+
imports: { ...existing.imports, ...subpathImports },
|
|
59
70
|
scripts: { ...existing.scripts, ...specScripts },
|
|
60
71
|
dependencies: { ...existing.dependencies, ...specDeps },
|
|
61
72
|
devDependencies: { ...existing.devDependencies, ...specDevDeps },
|
|
@@ -66,6 +77,7 @@ export async function writePackageJson(dest, vars, existing) {
|
|
|
66
77
|
type: 'module',
|
|
67
78
|
description: vars.description,
|
|
68
79
|
main: 'src/server.js',
|
|
80
|
+
imports: subpathImports,
|
|
69
81
|
scripts: specScripts,
|
|
70
82
|
keywords: ['hybrids', 'web-components', 'no-build'],
|
|
71
83
|
license: 'MIT',
|
package/lib/spec-utils.js
CHANGED
|
@@ -79,6 +79,38 @@ export function checkFileLines(root, extensions, max, ignoreDirs, label) {
|
|
|
79
79
|
return false;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Check for relative parent imports (`../`) in browser-facing JS files.
|
|
84
|
+
* Same-directory (`./`) and server/test files are allowed.
|
|
85
|
+
* @param {string} root
|
|
86
|
+
* @param {string[]} ignoreDirs
|
|
87
|
+
* @param {string} label
|
|
88
|
+
* @returns {boolean}
|
|
89
|
+
*/
|
|
90
|
+
export function checkImports(root, ignoreDirs, label) {
|
|
91
|
+
const start = performance.now();
|
|
92
|
+
const files = findFiles(root, ['.js'], ignoreDirs, root)
|
|
93
|
+
.filter((f) => f.startsWith('src/') && !f.includes('vendor/') && !f.includes('api/') && !f.endsWith('.test.js') && !f.endsWith('server.js'));
|
|
94
|
+
const violations = [];
|
|
95
|
+
const importRe = /(?:^|\n)\s*import\s.*?from\s+['"](\.\.[^'"]*)['"]|(?:^|\n)\s*import\s+['"](\.\.[^'"]*)['"]|(?:^|\n)\s*export\s.*?from\s+['"](\.\.[^'"]*)['"/]/g;
|
|
96
|
+
for (const file of files) {
|
|
97
|
+
const src = readFileSync(resolve(root, file), 'utf-8');
|
|
98
|
+
let m;
|
|
99
|
+
while ((m = importRe.exec(src)) !== null) {
|
|
100
|
+
const spec = m[1] || m[2] || m[3];
|
|
101
|
+
violations.push({ file, spec });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const time = elapsed(start);
|
|
105
|
+
if (violations.length === 0) {
|
|
106
|
+
console.log(` ✅ ${label} (${files.length} files, ${time})`);
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
console.log(` ❌ ${label} — ${violations.length} violation(s):`);
|
|
110
|
+
for (const v of violations) console.log(` ${v.file}: import '${v.spec}' → use #prefix/ alias`);
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
82
114
|
/**
|
|
83
115
|
* Run a shell command, report pass/fail with timing.
|
|
84
116
|
* @param {string} label
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techninja/clearstack",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A no-build web component framework specification — scaffold, validate, and evolve spec-compliant projects",
|
|
6
6
|
"bin": {
|
|
@@ -31,6 +31,15 @@
|
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
|
+
"imports": {
|
|
35
|
+
"#store/*": "./src/store/*",
|
|
36
|
+
"#utils/*": "./src/utils/*",
|
|
37
|
+
"#atoms/*": "./src/components/atoms/*",
|
|
38
|
+
"#molecules/*": "./src/components/molecules/*",
|
|
39
|
+
"#organisms/*": "./src/components/organisms/*",
|
|
40
|
+
"#templates/*": "./src/components/templates/*",
|
|
41
|
+
"#pages/*": "./src/pages/*"
|
|
42
|
+
},
|
|
34
43
|
"keywords": [
|
|
35
44
|
"web-components",
|
|
36
45
|
"no-build",
|
|
@@ -10,7 +10,14 @@
|
|
|
10
10
|
"skipLibCheck": true,
|
|
11
11
|
"types": ["node"],
|
|
12
12
|
"paths": {
|
|
13
|
-
"hybrids": ["../node_modules/hybrids/types/index.d.ts"]
|
|
13
|
+
"hybrids": ["../node_modules/hybrids/types/index.d.ts"],
|
|
14
|
+
"#store/*": ["../src/store/*"],
|
|
15
|
+
"#utils/*": ["../src/utils/*"],
|
|
16
|
+
"#atoms/*": ["../src/components/atoms/*"],
|
|
17
|
+
"#molecules/*": ["../src/components/molecules/*"],
|
|
18
|
+
"#organisms/*": ["../src/components/organisms/*"],
|
|
19
|
+
"#templates/*": ["../src/components/templates/*"],
|
|
20
|
+
"#pages/*": ["../src/pages/*"]
|
|
14
21
|
}
|
|
15
22
|
},
|
|
16
23
|
"include": ["../src/**/*.js", "../scripts/**/*.js"],
|
|
@@ -109,6 +109,50 @@ render: ({ items }) => html`
|
|
|
109
109
|
|
|
110
110
|
---
|
|
111
111
|
|
|
112
|
+
## Import Map Aliases
|
|
113
|
+
|
|
114
|
+
All cross-directory imports in browser-facing code use `#prefix/` aliases
|
|
115
|
+
defined in the import map (`src/index.html`). This eliminates fragile
|
|
116
|
+
relative paths like `../../../utils/foo.js`.
|
|
117
|
+
|
|
118
|
+
### Available Prefixes
|
|
119
|
+
|
|
120
|
+
| Prefix | Resolves to |
|
|
121
|
+
| --------------- | ------------------------------ |
|
|
122
|
+
| `#store/` | `/store/` |
|
|
123
|
+
| `#utils/` | `/utils/` |
|
|
124
|
+
| `#atoms/` | `/components/atoms/` |
|
|
125
|
+
| `#molecules/` | `/components/molecules/` |
|
|
126
|
+
| `#organisms/` | `/components/organisms/` |
|
|
127
|
+
| `#templates/` | `/components/templates/` |
|
|
128
|
+
| `#pages/` | `/pages/` |
|
|
129
|
+
|
|
130
|
+
### Rules
|
|
131
|
+
|
|
132
|
+
- **No `../` imports.** The spec check (`npm run spec`) flags any `../`
|
|
133
|
+
in browser-facing JS. Use a `#prefix/` alias instead.
|
|
134
|
+
- **Same-directory `./` is fine.** `index.js` re-exports and co-located
|
|
135
|
+
files use `./` naturally.
|
|
136
|
+
- **Server/API files are exempt.** `src/api/` and `src/server.js` run in
|
|
137
|
+
Node, not the browser — they use `./` relative imports.
|
|
138
|
+
- **Test files are exempt.** `*.test.js` files may use relative paths.
|
|
139
|
+
- **jsconfig.json mirrors the import map.** The `paths` entries in
|
|
140
|
+
`.configs/jsconfig.json` let `tsc --checkJs` resolve `#prefix/` imports.
|
|
141
|
+
|
|
142
|
+
### Examples
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
// ✅ Good — clear, refactor-safe
|
|
146
|
+
import AppState from '#store/AppState.js';
|
|
147
|
+
import { formatDate } from '#utils/formatDate.js';
|
|
148
|
+
import '#atoms/app-badge/app-badge.js';
|
|
149
|
+
|
|
150
|
+
// ❌ Bad — fragile, hard to read
|
|
151
|
+
import AppState from '../../../store/AppState.js';
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
112
156
|
## Error Handling
|
|
113
157
|
|
|
114
158
|
Errors are handled **at the boundary where they are actionable.** Each layer
|
|
@@ -193,8 +237,8 @@ state: store(AppState),
|
|
|
193
237
|
// In src/utils/filterActive.js
|
|
194
238
|
export const filterActive = (items) => items.filter(i => i.active);
|
|
195
239
|
|
|
196
|
-
// In component
|
|
197
|
-
import { filterActive } from '
|
|
240
|
+
// In component — use import map alias, never ../
|
|
241
|
+
import { filterActive } from '#utils/filterActive.js';
|
|
198
242
|
render: ({ items }) => html`<ul>${filterActive(items).map(...)}</ul>`,
|
|
199
243
|
```
|
|
200
244
|
|
|
@@ -121,7 +121,14 @@ declared in `src/index.html`.
|
|
|
121
121
|
<script type="importmap">
|
|
122
122
|
{
|
|
123
123
|
"imports": {
|
|
124
|
-
"hybrids": "/vendor/hybrids/index.js"
|
|
124
|
+
"hybrids": "/vendor/hybrids/index.js",
|
|
125
|
+
"#store/": "/store/",
|
|
126
|
+
"#utils/": "/utils/",
|
|
127
|
+
"#atoms/": "/components/atoms/",
|
|
128
|
+
"#molecules/": "/components/molecules/",
|
|
129
|
+
"#organisms/": "/components/organisms/",
|
|
130
|
+
"#templates/": "/components/templates/",
|
|
131
|
+
"#pages/": "/pages/"
|
|
125
132
|
}
|
|
126
133
|
}
|
|
127
134
|
</script>
|
|
@@ -139,6 +146,8 @@ declared in `src/index.html`.
|
|
|
139
146
|
2. Import map resolves `'hybrids'` → `/vendor/hybrids/index.js`.
|
|
140
147
|
3. Server serves the file from `src/vendor/hybrids/index.js`.
|
|
141
148
|
4. Hybrids' internal imports use relative paths — they resolve naturally.
|
|
149
|
+
5. `#prefix/` entries resolve cross-directory app imports without `../`.
|
|
150
|
+
For example, `import '#utils/formatDate.js'` resolves to `/utils/formatDate.js`.
|
|
142
151
|
|
|
143
152
|
### Rules
|
|
144
153
|
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { html, define, store } from 'hybrids';
|
|
8
|
-
import AppState from '
|
|
8
|
+
import AppState from '#store/AppState.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @typedef {Object} ThemeToggleHost
|
|
12
|
-
* @property {import('
|
|
12
|
+
* @property {import('#store/AppState.js').AppState} state
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -14,7 +14,14 @@
|
|
|
14
14
|
<script type="importmap">
|
|
15
15
|
{
|
|
16
16
|
"imports": {
|
|
17
|
-
"hybrids": "/vendor/hybrids/index.js"
|
|
17
|
+
"hybrids": "/vendor/hybrids/index.js",
|
|
18
|
+
"#store/": "/store/",
|
|
19
|
+
"#utils/": "/utils/",
|
|
20
|
+
"#atoms/": "/components/atoms/",
|
|
21
|
+
"#molecules/": "/components/molecules/",
|
|
22
|
+
"#organisms/": "/components/organisms/",
|
|
23
|
+
"#templates/": "/components/templates/",
|
|
24
|
+
"#pages/": "/pages/"
|
|
18
25
|
}
|
|
19
26
|
}
|
|
20
27
|
</script>
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { html, define, store } from 'hybrids';
|
|
7
|
-
import AppState from '
|
|
8
|
-
import '
|
|
7
|
+
import AppState from '#store/AppState.js';
|
|
8
|
+
import '#atoms/app-button/app-button.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @typedef {Object} HomeViewHost
|
|
12
|
-
* @property {import('
|
|
12
|
+
* @property {import('#store/AppState.js').AppState} state
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
/** @param {HomeViewHost & HTMLElement} host */
|