-
Notifications
You must be signed in to change notification settings - Fork 110
Expand file tree
/
Copy pathoverride-components.ts
More file actions
129 lines (116 loc) · 3.45 KB
/
override-components.ts
File metadata and controls
129 lines (116 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* A plugin that lets users override TutorialKit's components.
*
* The virtual module can be imported as:
*
* ```ts
* import { TopBar } from 'tutorialkit:override-components';
*
* <TopBar />
* ```
*
* User can override the components in `astro.config.ts`:
*
* ```ts
* export default defineConfig({
* integrations: [
* tutorialkit({
* components: {
* TopBar: './CustomTopBar.astro',
* Dialog: './CustomDialog.tsx',
* HeadTags: './CustomHeadLinks.astro',
* },
* }),
* ],
* });
* ```
*/
import type { VitePlugin } from '../types.js';
export interface OverrideComponentsOptions {
/**
* Component for overriding the top bar.
*
* This component has slots that are used to pass TutorialKit's default components:
* - `logo`: Logo of the application
* - `open-in-stackblitz-link`: Link for opening current lesson in StackBlitz
* - `theme-switch`: Switch for changing the theme
* - `login-button`: For StackBlitz Enterprise user, the login button
*
* Usage:
*
* ```jsx
* <slot name="logo" />
* <slot name="open-in-stackblitz-link" />
* <slot name="theme-switch" />
* <slot name="login-button" />
* ```
*/
TopBar?: string;
/**
* Component for overriding confirmation dialogs.
*
* This component has to be a React component and be the default export of that module.
* It will receive same props that `@tutorialkit/react/dialog` supports.
*/
Dialog?: string;
/**
* Component for overriding title, links and metadata in the `<head>` tag.
*
* This component has slots that are used to pass TutorialKit's default tags:
*
* - `title`: The page title
* - `links`: Links for the favicon, fonts and other assets
* - `meta`: Metadata and Open Graph tags
*
* ```jsx
* <slot name="title" />
* <slot name="links" />
* <slot name="meta" />
* ```
*/
HeadTags?: string;
}
interface Options {
components?: OverrideComponentsOptions;
defaultRoutes: boolean;
}
const virtualModuleId = 'tutorialkit:override-components';
const resolvedId = `\0${virtualModuleId}`;
export function overrideComponents({ components, defaultRoutes }: Options): VitePlugin {
return {
name: 'tutorialkit-override-components-plugin',
resolveId(id) {
if (id === virtualModuleId) {
return resolvedId;
}
return undefined;
},
async load(id) {
if (id === resolvedId) {
const topBar = components?.TopBar || resolveDefaultTopBar(defaultRoutes);
const headTags = components?.HeadTags || resolveDefaultHeadTags(defaultRoutes);
const dialog = components?.Dialog || '@tutorialkit/react/dialog';
return `
export { default as TopBar } from '${topBar}';
export { default as Dialog } from '${dialog}';
export { default as HeadTags } from '${headTags}';
`;
}
return undefined;
},
};
}
function resolveDefaultTopBar(defaultRoutes: boolean) {
if (defaultRoutes) {
return '@tutorialkit/astro/default/components/TopBar.astro';
}
// default `TopBar` is used from local file when `defaultRoutes` is disabled
return './src/components/TopBar.astro';
}
function resolveDefaultHeadTags(defaultRoutes: boolean) {
if (defaultRoutes) {
return '@tutorialkit/astro/default/components/HeadTags.astro';
}
// default `HeadTags` is used from local file when `defaultRoutes` is disabled
return './src/components/HeadTags.astro';
}