@herdingbits/trailhead-cloudscape 0.0.13 → 0.0.16
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/README.md +10 -1
- package/dist/adapter.d.ts +7 -2
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +9 -3
- package/dist/shell-app.d.ts.map +1 -1
- package/dist/shell-app.js +9 -10
- package/dist/shell-layout.d.ts +2 -7
- package/dist/shell-layout.d.ts.map +1 -1
- package/dist/shell-layout.js +22 -4
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ import '@herdingbits/trailhead-cloudscape/shell.css';
|
|
|
37
37
|
|
|
38
38
|
const shell = new Trailhead({
|
|
39
39
|
adapter: new CloudScapeAdapter(),
|
|
40
|
-
|
|
40
|
+
appBasePath: '/app',
|
|
41
41
|
apiUrl: 'https://api.example.com'
|
|
42
42
|
});
|
|
43
43
|
|
|
@@ -45,6 +45,15 @@ const root = createRoot(document.getElementById('app')!);
|
|
|
45
45
|
root.render(<ShellApp shell={shell} />);
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
To load the CloudScape global styles from a CDN instead of bundling via npm import, pass `cloudscapeUrl` to the adapter (and remove the `@cloudscape-design/global-styles/index.css` import from your entry point):
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
const shell = new Trailhead({
|
|
52
|
+
adapter: new CloudScapeAdapter({ cloudscapeUrl: 'https://unpkg.com/@cloudscape-design/global-styles@1.0.0/index.css' }),
|
|
53
|
+
appBasePath: '/app',
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
48
57
|
## What's Included
|
|
49
58
|
|
|
50
59
|
- **CloudScapeAdapter** - Implements the Trailhead adapter interface
|
package/dist/adapter.d.ts
CHANGED
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
* Uses CloudScape Flashbar, Modal, and Spinner components
|
|
4
4
|
*/
|
|
5
5
|
import type { DesignSystemAdapter, FeedbackAdapter } from '@herdingbits/trailhead-types/adapters';
|
|
6
|
+
export interface CloudScapeAdapterConfig {
|
|
7
|
+
/** URL for the CloudScape global-styles CSS. If provided, injected dynamically instead of requiring a hardcoded HTML link tag. */
|
|
8
|
+
cloudscapeUrl?: string;
|
|
9
|
+
}
|
|
6
10
|
export declare class CloudScapeAdapter implements DesignSystemAdapter {
|
|
7
11
|
name: string;
|
|
8
12
|
version: string;
|
|
9
13
|
feedback: FeedbackAdapter;
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
private readonly config?;
|
|
15
|
+
constructor(config?: CloudScapeAdapterConfig);
|
|
16
|
+
init(shellUrl: string): Promise<void>;
|
|
12
17
|
}
|
|
13
18
|
//# sourceMappingURL=adapter.d.ts.map
|
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAA4C,MAAM,uCAAuC,CAAC;AAyE5I,qBAAa,iBAAkB,YAAW,mBAAmB;IAC3D,IAAI,SAAgB;IACpB,OAAO,SAAW;IAClB,QAAQ,EAAE,eAAe,CAAC
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAA4C,MAAM,uCAAuC,CAAC;AAyE5I,MAAM,WAAW,uBAAuB;IACtC,kIAAkI;IAClI,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,iBAAkB,YAAW,mBAAmB;IAC3D,IAAI,SAAgB;IACpB,OAAO,SAAW;IAClB,QAAQ,EAAE,eAAe,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAA0B;gBAEtC,MAAM,CAAC,EAAE,uBAAuB;IAKtC,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQ5C"}
|
package/dist/adapter.js
CHANGED
|
@@ -52,12 +52,18 @@ class CloudScapeFeedbackAdapter {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
export class CloudScapeAdapter {
|
|
55
|
-
constructor() {
|
|
55
|
+
constructor(config) {
|
|
56
56
|
this.name = 'cloudscape';
|
|
57
57
|
this.version = '3.0.0';
|
|
58
|
+
this.config = config;
|
|
58
59
|
this.feedback = new CloudScapeFeedbackAdapter();
|
|
59
60
|
}
|
|
60
|
-
async init(
|
|
61
|
-
|
|
61
|
+
async init(shellUrl) {
|
|
62
|
+
if (this.config?.cloudscapeUrl) {
|
|
63
|
+
const link = document.createElement('link');
|
|
64
|
+
link.rel = 'stylesheet';
|
|
65
|
+
link.href = this.config.cloudscapeUrl;
|
|
66
|
+
document.head.appendChild(link);
|
|
67
|
+
}
|
|
62
68
|
}
|
|
63
69
|
}
|
package/dist/shell-app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell-app.d.ts","sourceRoot":"","sources":["../src/shell-app.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"shell-app.d.ts","sourceRoot":"","sources":["../src/shell-app.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAW,MAAM,6BAA6B,CAAC;AAEtE,UAAU,aAAa;IACrB,KAAK,EAAE,SAAS,CAAC;CAClB;AAiBD,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE,aAAa,2CAkNhD"}
|
package/dist/shell-app.js
CHANGED
|
@@ -21,8 +21,8 @@ export function ShellApp({ shell }) {
|
|
|
21
21
|
// Get current path without basePath
|
|
22
22
|
const getCurrentPath = () => {
|
|
23
23
|
let path = window.location.pathname;
|
|
24
|
-
if (shell.
|
|
25
|
-
path = path.substring(shell.
|
|
24
|
+
if (shell.appBasePath && path.startsWith(shell.appBasePath)) {
|
|
25
|
+
path = path.substring(shell.appBasePath.length) || '/';
|
|
26
26
|
}
|
|
27
27
|
return path;
|
|
28
28
|
};
|
|
@@ -70,21 +70,20 @@ export function ShellApp({ shell }) {
|
|
|
70
70
|
}
|
|
71
71
|
}, [navigation, currentPath]);
|
|
72
72
|
const handleRoute = (path) => {
|
|
73
|
-
// Normalize path by removing trailing slash for matching
|
|
74
73
|
const normalizedPath = path.endsWith('/') && path !== '/' ? path.slice(0, -1) : path;
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
77
|
-
loadApp(
|
|
74
|
+
const app = shell.getApps().find(entry => normalizedPath.startsWith(entry.basePath));
|
|
75
|
+
if (app && contentRef.current) {
|
|
76
|
+
loadApp(app.src, app.basePath);
|
|
78
77
|
}
|
|
79
78
|
};
|
|
80
79
|
const loadApp = async (appName, appPath) => {
|
|
81
80
|
if (!contentRef.current)
|
|
82
81
|
return;
|
|
83
82
|
contentRef.current.innerHTML = '<div>Loading...</div>';
|
|
84
|
-
const appBasePath = shell.
|
|
83
|
+
const appBasePath = shell.appBasePath + appPath;
|
|
85
84
|
try {
|
|
86
|
-
const pluginUrl = `${shell.
|
|
87
|
-
const pluginCss = `${shell.
|
|
85
|
+
const pluginUrl = `${shell.appBasePath}${appPath}/app.js`;
|
|
86
|
+
const pluginCss = `${shell.appBasePath}${appPath}/${appName}.css`;
|
|
88
87
|
// Load CSS
|
|
89
88
|
const link = document.createElement("link");
|
|
90
89
|
link.rel = "stylesheet";
|
|
@@ -148,5 +147,5 @@ export function ShellApp({ shell }) {
|
|
|
148
147
|
padding: '24px',
|
|
149
148
|
borderRadius: '8px',
|
|
150
149
|
textAlign: 'center',
|
|
151
|
-
}, children: [_jsx(Spinner, { size: "large" }), _jsx("div", { style: { marginTop: '16px' }, children: busyMessage })] }) })), _jsx(Modal, { visible: dialogState.visible, onDismiss: handleDialogDismiss, header: dialogState.title, footer: _jsx(Box, { float: "right", children: _jsx(SpaceBetween, { direction: "horizontal", size: "xs", children: dialogState.buttons.map((btn, idx) => (_jsx(Button, { variant: btn.variant === 'primary' ? 'primary' : 'normal', onClick: () => handleDialogButton(btn.value), children: btn.label }, idx))) }) }), children: dialogState.message }), _jsx(ShellLayout, { navigation: navigation, currentPath: currentPath, basePath: shell.
|
|
150
|
+
}, children: [_jsx(Spinner, { size: "large" }), _jsx("div", { style: { marginTop: '16px' }, children: busyMessage })] }) })), _jsx(Modal, { visible: dialogState.visible, onDismiss: handleDialogDismiss, header: dialogState.title, footer: _jsx(Box, { float: "right", children: _jsx(SpaceBetween, { direction: "horizontal", size: "xs", children: dialogState.buttons.map((btn, idx) => (_jsx(Button, { variant: btn.variant === 'primary' ? 'primary' : 'normal', onClick: () => handleDialogButton(btn.value), children: btn.label }, idx))) }) }), children: dialogState.message }), _jsx(ShellLayout, { navigation: navigation, currentPath: currentPath, basePath: shell.appBasePath, onNavigate: handleNavigate, children: _jsx("div", { id: "shell-content", ref: contentRef }) })] }));
|
|
152
151
|
}
|
package/dist/shell-layout.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
id: string;
|
|
4
|
-
label: string;
|
|
5
|
-
path: string;
|
|
6
|
-
icon?: string;
|
|
7
|
-
}
|
|
2
|
+
import type { NavItem } from '@herdingbits/trailhead-core';
|
|
8
3
|
interface ShellLayoutProps {
|
|
9
|
-
navigation:
|
|
4
|
+
navigation: NavItem[];
|
|
10
5
|
currentPath: string;
|
|
11
6
|
basePath: string;
|
|
12
7
|
onNavigate: (path: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell-layout.d.ts","sourceRoot":"","sources":["../src/shell-layout.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"shell-layout.d.ts","sourceRoot":"","sources":["../src/shell-layout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,KAAK,EAAE,OAAO,EAAW,MAAM,6BAA6B,CAAC;AAEpE,UAAU,gBAAgB;IACxB,UAAU,EAAE,OAAO,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,WAAW,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,gBAAgB,2CA+CxG"}
|
package/dist/shell-layout.js
CHANGED
|
@@ -4,12 +4,30 @@ import AppLayout from '@cloudscape-design/components/app-layout';
|
|
|
4
4
|
import SideNavigation from '@cloudscape-design/components/side-navigation';
|
|
5
5
|
export function ShellLayout({ navigation, currentPath, basePath, onNavigate, children }) {
|
|
6
6
|
const [navigationOpen, setNavigationOpen] = useState(true);
|
|
7
|
-
const
|
|
7
|
+
const isExternal = (href) => /^https?:\/\/|^\/\//.test(href);
|
|
8
|
+
const resolveHref = (href) => isExternal(href) ? href : basePath + href + '/';
|
|
9
|
+
const mapLink = (item) => ({
|
|
8
10
|
type: 'link',
|
|
9
11
|
text: item.label,
|
|
10
|
-
href:
|
|
11
|
-
})
|
|
12
|
-
|
|
12
|
+
href: resolveHref(item.href),
|
|
13
|
+
});
|
|
14
|
+
const navItems = [...navigation]
|
|
15
|
+
.sort((a, b) => a.order - b.order)
|
|
16
|
+
.map((item) => {
|
|
17
|
+
switch (item.type) {
|
|
18
|
+
case 'link':
|
|
19
|
+
return mapLink(item);
|
|
20
|
+
case 'section':
|
|
21
|
+
return {
|
|
22
|
+
type: 'section',
|
|
23
|
+
text: item.label,
|
|
24
|
+
items: [...item.children].sort((a, b) => a.order - b.order).map(mapLink),
|
|
25
|
+
};
|
|
26
|
+
case 'divider':
|
|
27
|
+
return { type: 'divider' };
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
return (_jsx(AppLayout, { navigationOpen: navigationOpen, onNavigationChange: ({ detail }) => setNavigationOpen(detail.open), navigation: _jsx(SideNavigation, { activeHref: basePath + currentPath + (currentPath.endsWith('/') ? '' : '/'), items: navItems, onFollow: (event) => {
|
|
13
31
|
event.preventDefault();
|
|
14
32
|
onNavigate(event.detail.href);
|
|
15
33
|
} }), content: children, toolsHide: true }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herdingbits/trailhead-cloudscape",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "AWS CloudScape adapter for Trailhead. React-based shell with CloudScape components. Supports React 19.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -21,16 +21,16 @@
|
|
|
21
21
|
"build": "npm run clean && tsc && cp src/shell.css dist/"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@herdingbits/trailhead-core": "^0.0.15",
|
|
25
24
|
"@cloudscape-design/components": "^3.0.0",
|
|
26
25
|
"@cloudscape-design/global-styles": "^1.0.0",
|
|
26
|
+
"@herdingbits/trailhead-core": "^0.0.16",
|
|
27
27
|
"react": "^19.0.0",
|
|
28
28
|
"react-dom": "^19.0.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@herdingbits/trailhead-types": "^0.0.12",
|
|
32
31
|
"@cloudscape-design/components": "^3.0.1297",
|
|
33
32
|
"@cloudscape-design/global-styles": "^1.0.59",
|
|
33
|
+
"@herdingbits/trailhead-types": "^0.0.14",
|
|
34
34
|
"@types/react": "^19.2.14",
|
|
35
35
|
"@types/react-dom": "^19.2.3",
|
|
36
36
|
"react": "^19.2.6",
|