@wavelengthusaf/client-router 0.0.1
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/.gitlab-ci.yml +84 -0
- package/.husky/pre-commit +38 -0
- package/.storybook/main.ts +16 -0
- package/.storybook/manager.ts +7 -0
- package/.storybook/preview.ts +23 -0
- package/.storybook/theme.ts +30 -0
- package/.storybook/vitest.setup.ts +7 -0
- package/README.md +556 -0
- package/dist/elements/RouteElement.d.ts +0 -0
- package/dist/elements/RouteElement.d.ts.map +0 -0
- package/dist/elements/RouteElement.js +0 -0
- package/dist/elements/RouteElement.js.map +0 -0
- package/dist/elements/RouterElement.d.ts +0 -0
- package/dist/elements/RouterElement.d.ts.map +0 -0
- package/dist/elements/RouterElement.js +0 -0
- package/dist/elements/RouterElement.js.map +0 -0
- package/dist/elements/__tests__/RouteElement.test.d.ts +0 -0
- package/dist/elements/__tests__/RouteElement.test.d.ts.map +0 -0
- package/dist/elements/__tests__/RouteElement.test.js +77 -0
- package/dist/elements/__tests__/RouteElement.test.js.map +0 -0
- package/dist/elements/__tests__/RouterElement.test.d.ts +0 -0
- package/dist/elements/__tests__/RouterElement.test.d.ts.map +0 -0
- package/dist/elements/__tests__/RouterElement.test.js +0 -0
- package/dist/elements/__tests__/RouterElement.test.js.map +0 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.d.ts.map +0 -0
- package/dist/index.js +0 -0
- package/dist/index.js.map +0 -0
- package/dist/models/CompiledRoute.d.ts +0 -0
- package/dist/models/CompiledRoute.d.ts.map +0 -0
- package/dist/models/CompiledRoute.js +0 -0
- package/dist/models/CompiledRoute.js.map +0 -0
- package/dist/models/MatchedRoute.d.ts +0 -0
- package/dist/models/MatchedRoute.d.ts.map +0 -0
- package/dist/models/MatchedRoute.js +0 -0
- package/dist/models/MatchedRoute.js.map +0 -0
- package/dist/models/RouteComponent.d.ts +0 -0
- package/dist/models/RouteComponent.d.ts.map +0 -0
- package/dist/models/RouteComponent.js +0 -0
- package/dist/models/RouteComponent.js.map +0 -0
- package/dist/models/RouteContext.d.ts +0 -0
- package/dist/models/RouteContext.d.ts.map +0 -0
- package/dist/models/RouteContext.js +0 -0
- package/dist/models/RouteContext.js.map +0 -0
- package/dist/models/RouteDefinition.d.ts +0 -0
- package/dist/models/RouteDefinition.d.ts.map +0 -0
- package/dist/models/RouteDefinition.js +0 -0
- package/dist/models/RouteDefinition.js.map +0 -0
- package/dist/models/RouteGuard.d.ts +0 -0
- package/dist/models/RouteGuard.d.ts.map +0 -0
- package/dist/models/RouteGuard.js +0 -0
- package/dist/models/RouteGuard.js.map +0 -0
- package/dist/models/RouteParams.d.ts +0 -0
- package/dist/models/RouteParams.d.ts.map +0 -0
- package/dist/models/RouteParams.js +0 -0
- package/dist/models/RouteParams.js.map +0 -0
- package/dist/models/index.d.ts +0 -0
- package/dist/models/index.d.ts.map +0 -0
- package/dist/models/index.js +0 -0
- package/dist/models/index.js.map +0 -0
- package/dist/prettier.config.d.ts +0 -0
- package/dist/prettier.config.d.ts.map +0 -0
- package/dist/router/Router.d.ts +0 -0
- package/dist/router/Router.d.ts.map +0 -0
- package/dist/router/Router.js +0 -0
- package/dist/router/Router.js.map +0 -0
- package/dist/router/__tests__/Router.test.d.ts +0 -0
- package/dist/router/__tests__/Router.test.d.ts.map +0 -0
- package/dist/router/__tests__/Router.test.js +0 -0
- package/dist/router/__tests__/Router.test.js.map +0 -0
- package/dist/src/elements/RouteElement.d.ts +0 -0
- package/dist/src/elements/RouteElement.d.ts.map +0 -0
- package/dist/src/elements/RouterElement.d.ts +0 -0
- package/dist/src/elements/RouterElement.d.ts.map +0 -0
- package/dist/src/elements/__tests__/RouteElement.test.d.ts +0 -0
- package/dist/src/elements/__tests__/RouteElement.test.d.ts.map +0 -0
- package/dist/src/elements/__tests__/RouterElement.test.d.ts +0 -0
- package/dist/src/elements/__tests__/RouterElement.test.d.ts.map +0 -0
- package/dist/src/index.d.ts +0 -0
- package/dist/src/index.d.ts.map +0 -0
- package/dist/src/models/CompiledRoute.d.ts +0 -0
- package/dist/src/models/CompiledRoute.d.ts.map +0 -0
- package/dist/src/models/MatchedRoute.d.ts +0 -0
- package/dist/src/models/MatchedRoute.d.ts.map +0 -0
- package/dist/src/models/RouteComponent.d.ts +0 -0
- package/dist/src/models/RouteComponent.d.ts.map +0 -0
- package/dist/src/models/RouteContext.d.ts +0 -0
- package/dist/src/models/RouteContext.d.ts.map +0 -0
- package/dist/src/models/RouteDefinition.d.ts +0 -0
- package/dist/src/models/RouteDefinition.d.ts.map +0 -0
- package/dist/src/models/RouteGuard.d.ts +0 -0
- package/dist/src/models/RouteGuard.d.ts.map +0 -0
- package/dist/src/models/RouteParams.d.ts +0 -0
- package/dist/src/models/RouteParams.d.ts.map +0 -0
- package/dist/src/models/index.d.ts +0 -0
- package/dist/src/models/index.d.ts.map +0 -0
- package/dist/src/router/Router.d.ts +0 -0
- package/dist/src/router/Router.d.ts.map +0 -0
- package/dist/src/router/__tests__/Router.test.d.ts +0 -0
- package/dist/src/router/__tests__/Router.test.d.ts.map +0 -0
- package/dist/src/stories/RouterElement.stories.d.ts +0 -0
- package/dist/src/stories/RouterElement.stories.d.ts.map +0 -0
- package/dist/src/stories/RouterElement.stories.test.d.ts +0 -0
- package/dist/src/stories/RouterElement.stories.test.d.ts.map +0 -0
- package/dist/src/utils/__tests__/compileRoute.test.d.ts +0 -0
- package/dist/src/utils/__tests__/compileRoute.test.d.ts.map +0 -0
- package/dist/src/utils/__tests__/matchRoute.test.d.ts +0 -0
- package/dist/src/utils/__tests__/matchRoute.test.d.ts.map +0 -0
- package/dist/src/utils/compileRoute.d.ts +0 -0
- package/dist/src/utils/compileRoute.d.ts.map +0 -0
- package/dist/src/utils/index.d.ts +0 -0
- package/dist/src/utils/index.d.ts.map +0 -0
- package/dist/src/utils/matchRoute.d.ts +0 -0
- package/dist/src/utils/matchRoute.d.ts.map +0 -0
- package/dist/stories/RouterElement.stories.d.ts +0 -0
- package/dist/stories/RouterElement.stories.d.ts.map +0 -0
- package/dist/stories/RouterElement.stories.js +0 -0
- package/dist/stories/RouterElement.stories.js.map +0 -0
- package/dist/utils/__tests__/compileRoute.test.d.ts +0 -0
- package/dist/utils/__tests__/compileRoute.test.d.ts.map +0 -0
- package/dist/utils/__tests__/compileRoute.test.js +0 -0
- package/dist/utils/__tests__/compileRoute.test.js.map +0 -0
- package/dist/utils/__tests__/matchRoute.test.d.ts +0 -0
- package/dist/utils/__tests__/matchRoute.test.d.ts.map +0 -0
- package/dist/utils/__tests__/matchRoute.test.js +0 -0
- package/dist/utils/__tests__/matchRoute.test.js.map +0 -0
- package/dist/utils/compileRoute.d.ts +0 -0
- package/dist/utils/compileRoute.d.ts.map +0 -0
- package/dist/utils/compileRoute.js +0 -0
- package/dist/utils/compileRoute.js.map +0 -0
- package/dist/utils/index.d.ts +0 -0
- package/dist/utils/index.d.ts.map +0 -0
- package/dist/utils/index.js +0 -0
- package/dist/utils/index.js.map +0 -0
- package/dist/utils/matchRoute.d.ts +0 -0
- package/dist/utils/matchRoute.d.ts.map +0 -0
- package/dist/utils/matchRoute.js +0 -0
- package/dist/utils/matchRoute.js.map +0 -0
- package/eslint.config.mjs +89 -0
- package/index.ts +15 -0
- package/package.json +54 -0
- package/prettier.config.ts +30 -0
- package/src/elements/RouteElement.ts +67 -0
- package/src/elements/RouterElement.ts +97 -0
- package/src/elements/__tests__/RouteElement.test.ts +89 -0
- package/src/elements/__tests__/RouterElement.test.ts +253 -0
- package/src/index.ts +15 -0
- package/src/models/CompiledRoute.ts +7 -0
- package/src/models/MatchedRoute.ts +7 -0
- package/src/models/RouteComponent.ts +6 -0
- package/src/models/RouteContext.ts +7 -0
- package/src/models/RouteDefinition.ts +6 -0
- package/src/models/RouteGuard.ts +6 -0
- package/src/models/RouteParams.ts +3 -0
- package/src/models/index.ts +17 -0
- package/src/router/Router.ts +225 -0
- package/src/router/__tests__/Router.test.ts +464 -0
- package/src/stories/RouterElement.stories.test.ts +310 -0
- package/src/stories/RouterElement.stories.ts +208 -0
- package/src/utils/__tests__/compileRoute.test.ts +97 -0
- package/src/utils/__tests__/matchRoute.test.ts +180 -0
- package/src/utils/compileRoute.ts +37 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/matchRoute.ts +37 -0
- package/tsconfig.build.json +20 -0
- package/tsconfig.json +55 -0
- package/vitest.config.ts +34 -0
- package/vitest.setup.ts +3 -0
- package/vitest.shims.d.ts +1 -0
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import prettier from 'eslint-config-prettier';
|
|
2
|
+
import sonarjs from 'eslint-plugin-sonarjs';
|
|
3
|
+
import storybook from 'eslint-plugin-storybook';
|
|
4
|
+
import wc from 'eslint-plugin-wc';
|
|
5
|
+
import globals from 'globals';
|
|
6
|
+
import tsEslint from 'typescript-eslint';
|
|
7
|
+
|
|
8
|
+
export default tsEslint.config(
|
|
9
|
+
{
|
|
10
|
+
ignores: ['dist/**', 'node_modules/**', 'coverage/**', '.storybook/**'],
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
...tsEslint.configs.recommended,
|
|
14
|
+
sonarjs.configs.recommended,
|
|
15
|
+
|
|
16
|
+
{
|
|
17
|
+
files: ['src/**/*.ts'],
|
|
18
|
+
plugins: {
|
|
19
|
+
wc,
|
|
20
|
+
},
|
|
21
|
+
languageOptions: {
|
|
22
|
+
parser: tsEslint.parser,
|
|
23
|
+
parserOptions: {
|
|
24
|
+
projectService: true,
|
|
25
|
+
tsconfigRootDir: import.meta.dirname,
|
|
26
|
+
},
|
|
27
|
+
globals: {
|
|
28
|
+
...globals.browser,
|
|
29
|
+
...globals.node,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
rules: {
|
|
33
|
+
'@typescript-eslint/explicit-member-accessibility': [
|
|
34
|
+
'error',
|
|
35
|
+
{
|
|
36
|
+
accessibility: 'explicit',
|
|
37
|
+
overrides: {
|
|
38
|
+
constructors: 'no-public',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
'@typescript-eslint/consistent-type-exports': 'error',
|
|
43
|
+
'@typescript-eslint/no-import-type-side-effects': 'error',
|
|
44
|
+
'@typescript-eslint/no-explicit-any': 'error',
|
|
45
|
+
|
|
46
|
+
...wc.configs.recommended.rules,
|
|
47
|
+
|
|
48
|
+
'wc/no-constructor-attributes': 'error',
|
|
49
|
+
'wc/no-invalid-element-name': 'error',
|
|
50
|
+
'wc/guard-super-call': 'error',
|
|
51
|
+
'wc/attach-shadow-constructor': 'off',
|
|
52
|
+
'wc/no-self-class': 'off',
|
|
53
|
+
|
|
54
|
+
'sonarjs/todo-tag': 'warn',
|
|
55
|
+
'sonarjs/no-selector-parameter': 'off',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
{
|
|
60
|
+
files: ['**/*.test.ts', '**/*.spec.ts', 'src/**/*.stories.ts'],
|
|
61
|
+
languageOptions: {
|
|
62
|
+
parserOptions: {
|
|
63
|
+
projectService: {
|
|
64
|
+
allowDefaultProject: ['*.ts', '*.tsx'],
|
|
65
|
+
extendedReports: true,
|
|
66
|
+
},
|
|
67
|
+
tsconfigRootDir: import.meta.dirname,
|
|
68
|
+
},
|
|
69
|
+
globals: {
|
|
70
|
+
...globals.node,
|
|
71
|
+
Bun: 'readonly',
|
|
72
|
+
describe: 'readonly',
|
|
73
|
+
it: 'readonly',
|
|
74
|
+
expect: 'readonly',
|
|
75
|
+
test: 'readonly',
|
|
76
|
+
beforeAll: 'readonly',
|
|
77
|
+
afterAll: 'readonly',
|
|
78
|
+
beforeEach: 'readonly',
|
|
79
|
+
afterEach: 'readonly',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
rules: {
|
|
83
|
+
'@typescript-eslint/no-unused-expressions': 'error',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
...storybook.configs['flat/recommended'],
|
|
88
|
+
prettier,
|
|
89
|
+
);
|
package/index.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { Router } from './src/router/Router.ts';
|
|
2
|
+
export { RouterElement } from './src/elements/RouterElement.ts';
|
|
3
|
+
export { RouteElement } from './src/elements/RouteElement.ts';
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
RouteComponent,
|
|
7
|
+
RouteContext,
|
|
8
|
+
RouteDefinition,
|
|
9
|
+
RouteGuard,
|
|
10
|
+
RouteParams,
|
|
11
|
+
CompiledRoute,
|
|
12
|
+
MatchedRoute,
|
|
13
|
+
} from './src/models/index.ts';
|
|
14
|
+
|
|
15
|
+
export { compileRoute, matchRoute } from './src/utils/index.ts';
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wavelengthusaf/client-router",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Native TypeScript Router",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc -p tsconfig.build.json",
|
|
9
|
+
"lint": "eslint .",
|
|
10
|
+
"lint:fix": "eslint . --fix",
|
|
11
|
+
"prettier": "prettier --write .",
|
|
12
|
+
"type-check": "tsc --noEmit",
|
|
13
|
+
"test": "vitest run --coverage",
|
|
14
|
+
"storybook": "storybook dev -p 6006",
|
|
15
|
+
"build-storybook": "storybook build",
|
|
16
|
+
"test-storybook": "test-storybook",
|
|
17
|
+
"prepare": "husky"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"router"
|
|
21
|
+
],
|
|
22
|
+
"author": "Wavelength",
|
|
23
|
+
"license": "ISC",
|
|
24
|
+
"type": "module",
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@happy-dom/global-registrator": "^20.9.0",
|
|
27
|
+
"@storybook/addon-a11y": "^10.3.5",
|
|
28
|
+
"@storybook/addon-docs": "^10.3.5",
|
|
29
|
+
"@storybook/addon-links": "^10.3.5",
|
|
30
|
+
"@storybook/addon-vitest": "^10.3.5",
|
|
31
|
+
"@storybook/testing-library": "^0.2.1",
|
|
32
|
+
"@storybook/web-components": "^10.3.5",
|
|
33
|
+
"@storybook/web-components-vite": "^10.3.5",
|
|
34
|
+
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
|
35
|
+
"@types/jsdom": "^28.0.1",
|
|
36
|
+
"@types/node": "^25.6.0",
|
|
37
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
38
|
+
"eslint": "^10.2.0",
|
|
39
|
+
"eslint-config-prettier": "^10.1.8",
|
|
40
|
+
"eslint-plugin-sonarjs": "^4.0.2",
|
|
41
|
+
"eslint-plugin-storybook": "^10.3.5",
|
|
42
|
+
"eslint-plugin-wc": "^3.1.0",
|
|
43
|
+
"globals": "^17.5.0",
|
|
44
|
+
"husky": "^9.1.7",
|
|
45
|
+
"jsdom": "^29.0.2",
|
|
46
|
+
"opencode-ai": "^1.4.6",
|
|
47
|
+
"playwright": "^1.59.1",
|
|
48
|
+
"prettier": "^3.8.2",
|
|
49
|
+
"storybook": "^10.3.5",
|
|
50
|
+
"typescript": "^6.0.2",
|
|
51
|
+
"typescript-eslint": "^8.58.2",
|
|
52
|
+
"vitest": "^4.1.4"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Config } from 'prettier';
|
|
2
|
+
|
|
3
|
+
const config: Config = {
|
|
4
|
+
endOfLine: 'lf',
|
|
5
|
+
arrowParens: 'always',
|
|
6
|
+
semi: true,
|
|
7
|
+
trailingComma: 'all',
|
|
8
|
+
singleQuote: true,
|
|
9
|
+
printWidth: 80,
|
|
10
|
+
tabWidth: 2,
|
|
11
|
+
useTabs: false,
|
|
12
|
+
plugins: ['@trivago/prettier-plugin-sort-imports'],
|
|
13
|
+
importOrder: [
|
|
14
|
+
'^bun.*$',
|
|
15
|
+
'<THIRD_PARTY_MODULES>',
|
|
16
|
+
'^@/(.*)$',
|
|
17
|
+
'^[../]',
|
|
18
|
+
'^[./]',
|
|
19
|
+
'(.css|.scss)$',
|
|
20
|
+
],
|
|
21
|
+
importOrderSeparation: true,
|
|
22
|
+
importOrderSortSpecifiers: true,
|
|
23
|
+
importOrderParserPlugins: [
|
|
24
|
+
'typescript',
|
|
25
|
+
'decorators-legacy',
|
|
26
|
+
'importAssertions',
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default config;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RouteComponent,
|
|
3
|
+
RouteContext,
|
|
4
|
+
RouteDefinition,
|
|
5
|
+
} from '../models/index.ts';
|
|
6
|
+
|
|
7
|
+
export interface RouteElementEnv {
|
|
8
|
+
document?: Document;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class RouteElement extends HTMLElement {
|
|
12
|
+
public static readonly tag = 'wavelength-route';
|
|
13
|
+
|
|
14
|
+
public get path(): string {
|
|
15
|
+
return this.getAttribute('path') ?? '*';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public get componentTag(): string {
|
|
19
|
+
return this.getAttribute('component') ?? '';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public toDefinition(env: RouteElementEnv = {}): RouteDefinition | null {
|
|
23
|
+
const tag: string = this.componentTag;
|
|
24
|
+
const doc: Document | undefined = env.document;
|
|
25
|
+
|
|
26
|
+
if (!tag) {
|
|
27
|
+
console.warn(
|
|
28
|
+
`[route] Missing 'component' attribute on path="${this.path}"`,
|
|
29
|
+
);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!doc) {
|
|
34
|
+
return {
|
|
35
|
+
path: this.path,
|
|
36
|
+
routeComponent: {
|
|
37
|
+
mount() {},
|
|
38
|
+
unmount() {},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const routeComponent: RouteComponent = {
|
|
44
|
+
mount: (container: HTMLElement, routeContext: RouteContext) => {
|
|
45
|
+
const element = doc.createElement(tag) as HTMLElement & {
|
|
46
|
+
routeContext?: RouteContext;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
element.routeContext = routeContext;
|
|
50
|
+
|
|
51
|
+
container.appendChild(element);
|
|
52
|
+
},
|
|
53
|
+
unmount: () => {
|
|
54
|
+
// optional: future cleanup hook
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
path: this.path,
|
|
60
|
+
routeComponent,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!customElements.get(RouteElement.tag)) {
|
|
66
|
+
customElements.define(RouteElement.tag, RouteElement);
|
|
67
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { RouteDefinition, RouteGuard } from '../models/index.ts';
|
|
2
|
+
import { Router } from '../router/Router.ts';
|
|
3
|
+
import type { RouteElement } from './RouteElement.ts';
|
|
4
|
+
|
|
5
|
+
export class RouterElement extends HTMLElement {
|
|
6
|
+
public static readonly tag = 'wavelength-router';
|
|
7
|
+
|
|
8
|
+
#router?: Router;
|
|
9
|
+
|
|
10
|
+
public static get observedAttributes(): string[] {
|
|
11
|
+
return ['hash-mode', 'guard'];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public connectedCallback(): void {
|
|
15
|
+
this.#bootstrap();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public disconnectedCallback(): void {
|
|
19
|
+
this.#teardown();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {
|
|
23
|
+
if (!this.isConnected || oldValue === newValue) return;
|
|
24
|
+
this.#bootstrap();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public navigate(path: string): void {
|
|
28
|
+
this.#router?.navigate(path);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public replace(path: string): void {
|
|
32
|
+
this.#router?.replace(path);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public back(): void {
|
|
36
|
+
this.#router?.back();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#bootstrap(): void {
|
|
40
|
+
this.#teardown();
|
|
41
|
+
|
|
42
|
+
const routes: RouteDefinition[] = this.#collectRoutes();
|
|
43
|
+
|
|
44
|
+
if (routes.length === 0) {
|
|
45
|
+
console.warn('[wavelength-router] No <wavelength-route> children found.');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const guard: RouteGuard | undefined =this.#resolveGuard();
|
|
50
|
+
this.#router = new Router(
|
|
51
|
+
routes,
|
|
52
|
+
{
|
|
53
|
+
outlet: this,
|
|
54
|
+
hashMode: this.hasAttribute('hash-mode'),
|
|
55
|
+
...(guard ? { beforeEach: guard } : {}),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
window: window,
|
|
59
|
+
document: document,
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
this.#router.start();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#teardown(): void {
|
|
67
|
+
this.#router?.destroy();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#collectRoutes(): RouteDefinition[] {
|
|
71
|
+
const routeElements: RouteElement[] = Array.from(
|
|
72
|
+
this.querySelectorAll<RouteElement>('wavelength-route'),
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return routeElements
|
|
76
|
+
.map((routeElement: RouteElement) => routeElement.toDefinition({ document }))
|
|
77
|
+
.filter((routeDefinition: RouteDefinition | null): routeDefinition is RouteDefinition => routeDefinition !== null);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
#resolveGuard(): RouteGuard | undefined {
|
|
81
|
+
const guardName: string | null = this.getAttribute('guard');
|
|
82
|
+
if (!guardName) return undefined;
|
|
83
|
+
|
|
84
|
+
const fn: unknown = (window as unknown as Record<string, unknown>)[guardName];
|
|
85
|
+
|
|
86
|
+
if (typeof fn !== 'function') {
|
|
87
|
+
console.warn(`[wavelength-router] Guard "${guardName}" not found on window.`);
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return fn as RouteGuard;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!customElements.get(RouterElement.tag)) {
|
|
96
|
+
customElements.define(RouterElement.tag, RouterElement);
|
|
97
|
+
}
|