@canonical/summon-package 0.1.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/README.md +496 -0
- package/biome.json +6 -0
- package/package.json +42 -0
- package/src/__tests__/generators.test.ts +295 -0
- package/src/index.ts +14 -0
- package/src/package/index.ts +306 -0
- package/src/shared/index.ts +330 -0
- package/src/templates/README.md.ejs +29 -0
- package/src/templates/biome.json.ejs +6 -0
- package/src/templates/cli.ts.ejs +8 -0
- package/src/templates/index.css.ejs +5 -0
- package/src/templates/index.ts.ejs +7 -0
- package/src/templates/package.json.ejs +112 -0
- package/src/templates/storybook-main.ts.ejs +5 -0
- package/src/templates/storybook-preview.ts.ejs +26 -0
- package/src/templates/tsconfig-react.json.ejs +8 -0
- package/src/templates/tsconfig.json.ejs +8 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for package generator
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
import {
|
|
7
|
+
exists,
|
|
8
|
+
flatMap,
|
|
9
|
+
ifElseM,
|
|
10
|
+
pure,
|
|
11
|
+
readFile,
|
|
12
|
+
type Task,
|
|
13
|
+
} from "@canonical/summon";
|
|
14
|
+
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Types
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
export type PackageType = "tool-ts" | "library" | "css";
|
|
20
|
+
|
|
21
|
+
export type PackageManager = "bun" | "npm" | "yarn" | "pnpm";
|
|
22
|
+
|
|
23
|
+
export interface PackageAnswers {
|
|
24
|
+
/** Full package name (e.g., @canonical/my-package or my-package) */
|
|
25
|
+
name: string;
|
|
26
|
+
/** Package type */
|
|
27
|
+
type: PackageType;
|
|
28
|
+
/** Package description */
|
|
29
|
+
description: string;
|
|
30
|
+
/** Include React dependencies */
|
|
31
|
+
withReact: boolean;
|
|
32
|
+
/** Include Storybook setup */
|
|
33
|
+
withStorybook: boolean;
|
|
34
|
+
/** Include CLI binary entry point */
|
|
35
|
+
withCli: boolean;
|
|
36
|
+
/** Run package manager install after creation */
|
|
37
|
+
runInstall: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface MonorepoInfo {
|
|
41
|
+
isMonorepo: boolean;
|
|
42
|
+
version?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// =============================================================================
|
|
46
|
+
// Validation
|
|
47
|
+
// =============================================================================
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Validate npm package name
|
|
51
|
+
* Supports scoped packages (@scope/name) and unscoped packages
|
|
52
|
+
* Rules: lowercase, can contain hyphens, can't start/end with hyphen
|
|
53
|
+
*/
|
|
54
|
+
export const validatePackageName = (value: unknown): true | string => {
|
|
55
|
+
if (!value || typeof value !== "string") {
|
|
56
|
+
return "Package name is required";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Extract the package name (handle scoped packages)
|
|
60
|
+
const name = getPackageShortName(value);
|
|
61
|
+
|
|
62
|
+
if (!/^[a-z][a-z0-9-]*[a-z0-9]$|^[a-z]$/.test(name)) {
|
|
63
|
+
return "Package name must be lowercase, can contain hyphens, but cannot start or end with a hyphen";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (value.length > 214) {
|
|
67
|
+
return "Package name cannot be longer than 214 characters";
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return true;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Extract the short name from a package name (removes scope if present)
|
|
75
|
+
* @canonical/my-package -> my-package
|
|
76
|
+
* my-package -> my-package
|
|
77
|
+
*/
|
|
78
|
+
export const getPackageShortName = (fullName: string): string => {
|
|
79
|
+
const match = fullName.match(/^@[^/]+\/(.+)$/);
|
|
80
|
+
return match ? match[1] : fullName;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get the directory name for a package (short name, no scope)
|
|
85
|
+
*/
|
|
86
|
+
export const getPackageDir = (fullName: string): string => {
|
|
87
|
+
return getPackageShortName(fullName);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// =============================================================================
|
|
91
|
+
// String Helpers
|
|
92
|
+
// =============================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Convert string to kebab-case
|
|
96
|
+
*/
|
|
97
|
+
export const kebabCase = (str: string): string => {
|
|
98
|
+
return str
|
|
99
|
+
.replace(/([a-z])([A-Z])/g, "$1-$2")
|
|
100
|
+
.replace(/([A-Z])([A-Z][a-z])/g, "$1-$2")
|
|
101
|
+
.replace(/[\s_]+/g, "-")
|
|
102
|
+
.toLowerCase();
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Convert string to PascalCase
|
|
107
|
+
*/
|
|
108
|
+
export const pascalCase = (str: string): string => {
|
|
109
|
+
return str
|
|
110
|
+
.split(/[-_\s]+/)
|
|
111
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
112
|
+
.join("");
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// =============================================================================
|
|
116
|
+
// Detection Utilities
|
|
117
|
+
// =============================================================================
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Detect if running in a monorepo and get the version
|
|
121
|
+
*/
|
|
122
|
+
export const detectMonorepo = (cwd: string): Task<MonorepoInfo> => {
|
|
123
|
+
// Look for lerna.json in parent directories
|
|
124
|
+
const lernaPath = path.join(cwd, "lerna.json");
|
|
125
|
+
const parentLernaPath = path.join(cwd, "..", "lerna.json");
|
|
126
|
+
const grandparentLernaPath = path.join(cwd, "..", "..", "lerna.json");
|
|
127
|
+
|
|
128
|
+
const parseLerna = (content: string): MonorepoInfo => {
|
|
129
|
+
const lerna = JSON.parse(content);
|
|
130
|
+
return { isMonorepo: true, version: lerna.version };
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const notMonorepo: MonorepoInfo = { isMonorepo: false };
|
|
134
|
+
|
|
135
|
+
return flatMap(exists(lernaPath), (hasLerna) => {
|
|
136
|
+
if (hasLerna) {
|
|
137
|
+
return flatMap(readFile(lernaPath), (content) =>
|
|
138
|
+
pure(parseLerna(content)),
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
return flatMap(exists(parentLernaPath), (hasParent) => {
|
|
142
|
+
if (hasParent) {
|
|
143
|
+
return flatMap(readFile(parentLernaPath), (content) =>
|
|
144
|
+
pure(parseLerna(content)),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
return flatMap(exists(grandparentLernaPath), (hasGrandparent) => {
|
|
148
|
+
if (hasGrandparent) {
|
|
149
|
+
return flatMap(readFile(grandparentLernaPath), (content) =>
|
|
150
|
+
pure(parseLerna(content)),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
return pure(notMonorepo);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Detect the package manager in use
|
|
161
|
+
*/
|
|
162
|
+
export const detectPackageManager = (cwd: string): Task<PackageManager> => {
|
|
163
|
+
const bunLock = path.join(cwd, "bun.lockb");
|
|
164
|
+
const bunLock2 = path.join(cwd, "bun.lock");
|
|
165
|
+
const yarnLock = path.join(cwd, "yarn.lock");
|
|
166
|
+
const pnpmLock = path.join(cwd, "pnpm-lock.yaml");
|
|
167
|
+
|
|
168
|
+
// Also check parent directories for monorepo setup
|
|
169
|
+
const parentBunLock = path.join(cwd, "..", "..", "bun.lockb");
|
|
170
|
+
const parentBunLock2 = path.join(cwd, "..", "..", "bun.lock");
|
|
171
|
+
|
|
172
|
+
return ifElseM(
|
|
173
|
+
exists(bunLock),
|
|
174
|
+
pure("bun" as const),
|
|
175
|
+
ifElseM(
|
|
176
|
+
exists(bunLock2),
|
|
177
|
+
pure("bun" as const),
|
|
178
|
+
ifElseM(
|
|
179
|
+
exists(parentBunLock),
|
|
180
|
+
pure("bun" as const),
|
|
181
|
+
ifElseM(
|
|
182
|
+
exists(parentBunLock2),
|
|
183
|
+
pure("bun" as const),
|
|
184
|
+
ifElseM(
|
|
185
|
+
exists(yarnLock),
|
|
186
|
+
pure("yarn" as const),
|
|
187
|
+
ifElseM(
|
|
188
|
+
exists(pnpmLock),
|
|
189
|
+
pure("pnpm" as const),
|
|
190
|
+
pure("bun" as const),
|
|
191
|
+
),
|
|
192
|
+
),
|
|
193
|
+
),
|
|
194
|
+
),
|
|
195
|
+
),
|
|
196
|
+
);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// =============================================================================
|
|
200
|
+
// Configuration Helpers
|
|
201
|
+
// =============================================================================
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get the webarchitect ruleset based on package type and options
|
|
205
|
+
*/
|
|
206
|
+
export const getRuleset = (type: PackageType, withReact: boolean): string => {
|
|
207
|
+
if (withReact) return "package-react";
|
|
208
|
+
if (type === "css") return "base"; // CSS packages use base ruleset
|
|
209
|
+
return type; // "tool-ts" or "library"
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get license based on package type
|
|
214
|
+
*/
|
|
215
|
+
export const getLicense = (type: PackageType): string => {
|
|
216
|
+
if (type === "tool-ts") return "GPL-3.0";
|
|
217
|
+
return "LGPL-3.0"; // library and css use LGPL
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Get package entry points based on type
|
|
222
|
+
*/
|
|
223
|
+
export const getEntryPoints = (
|
|
224
|
+
type: PackageType,
|
|
225
|
+
): {
|
|
226
|
+
module: string;
|
|
227
|
+
types: string | null;
|
|
228
|
+
files: string[];
|
|
229
|
+
needsBuild: boolean;
|
|
230
|
+
} => {
|
|
231
|
+
if (type === "tool-ts") {
|
|
232
|
+
return {
|
|
233
|
+
module: "src/index.ts",
|
|
234
|
+
types: "src/index.ts",
|
|
235
|
+
files: ["src"],
|
|
236
|
+
needsBuild: false,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (type === "css") {
|
|
240
|
+
return {
|
|
241
|
+
module: "src/index.css",
|
|
242
|
+
types: null, // CSS packages don't have types
|
|
243
|
+
files: ["src"],
|
|
244
|
+
needsBuild: false,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
// library
|
|
248
|
+
return {
|
|
249
|
+
module: "dist/esm/index.js",
|
|
250
|
+
types: "dist/types/index.d.ts",
|
|
251
|
+
files: ["dist"],
|
|
252
|
+
needsBuild: true,
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// =============================================================================
|
|
257
|
+
// Template Context
|
|
258
|
+
// =============================================================================
|
|
259
|
+
|
|
260
|
+
export interface TemplateContext {
|
|
261
|
+
/** Package short name (without scope) */
|
|
262
|
+
shortName: string;
|
|
263
|
+
/** Full package name (as entered, e.g., @canonical/my-package) */
|
|
264
|
+
name: string;
|
|
265
|
+
/** Package description */
|
|
266
|
+
description: string;
|
|
267
|
+
/** Package type */
|
|
268
|
+
type: PackageType;
|
|
269
|
+
/** Package version */
|
|
270
|
+
version: string;
|
|
271
|
+
/** License */
|
|
272
|
+
license: string;
|
|
273
|
+
/** Module entry point */
|
|
274
|
+
module: string;
|
|
275
|
+
/** Types entry point (null for CSS packages) */
|
|
276
|
+
types: string | null;
|
|
277
|
+
/** Files to include */
|
|
278
|
+
files: string[];
|
|
279
|
+
/** Whether this package type needs a build step */
|
|
280
|
+
needsBuild: boolean;
|
|
281
|
+
/** Webarchitect ruleset */
|
|
282
|
+
ruleset: string;
|
|
283
|
+
/** Include React */
|
|
284
|
+
withReact: boolean;
|
|
285
|
+
/** Include Storybook */
|
|
286
|
+
withStorybook: boolean;
|
|
287
|
+
/** Include CLI */
|
|
288
|
+
withCli: boolean;
|
|
289
|
+
/** Monorepo version (if applicable) */
|
|
290
|
+
monorepoVersion?: string;
|
|
291
|
+
/** Generator name */
|
|
292
|
+
generatorName: string;
|
|
293
|
+
/** Generator version */
|
|
294
|
+
generatorVersion: string;
|
|
295
|
+
/** Index signature for EJS compatibility */
|
|
296
|
+
[key: string]: unknown;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Create template context from answers
|
|
301
|
+
*/
|
|
302
|
+
export const createTemplateContext = (
|
|
303
|
+
answers: PackageAnswers,
|
|
304
|
+
monorepoInfo: MonorepoInfo,
|
|
305
|
+
): TemplateContext => {
|
|
306
|
+
const entryPoints = getEntryPoints(answers.type);
|
|
307
|
+
const version = monorepoInfo.isMonorepo
|
|
308
|
+
? (monorepoInfo.version ?? "0.1.0")
|
|
309
|
+
: "0.1.0";
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
shortName: getPackageShortName(answers.name),
|
|
313
|
+
name: answers.name,
|
|
314
|
+
description: answers.description,
|
|
315
|
+
type: answers.type,
|
|
316
|
+
version,
|
|
317
|
+
license: getLicense(answers.type),
|
|
318
|
+
module: entryPoints.module,
|
|
319
|
+
types: entryPoints.types,
|
|
320
|
+
files: entryPoints.files,
|
|
321
|
+
needsBuild: entryPoints.needsBuild,
|
|
322
|
+
ruleset: getRuleset(answers.type, answers.withReact),
|
|
323
|
+
withReact: answers.withReact,
|
|
324
|
+
withStorybook: answers.withStorybook,
|
|
325
|
+
withCli: answers.withCli,
|
|
326
|
+
monorepoVersion: monorepoInfo.version,
|
|
327
|
+
generatorName: "@canonical/summon-package",
|
|
328
|
+
generatorVersion: "0.1.0",
|
|
329
|
+
};
|
|
330
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# <%= name %>
|
|
2
|
+
|
|
3
|
+
<%= description || 'TODO: Add description' %>
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add <%= name %>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { } from "<%= name %>";
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Development
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Run checks
|
|
21
|
+
bun run check
|
|
22
|
+
|
|
23
|
+
# Run tests
|
|
24
|
+
bun run test
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
|
|
29
|
+
<%= license %>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= name %>",
|
|
3
|
+
"description": "<%= description %>",
|
|
4
|
+
"version": "<%= version %>",
|
|
5
|
+
"type": "module",
|
|
6
|
+
<% if (type === 'tool-ts') { -%>
|
|
7
|
+
"module": "src/index.ts",
|
|
8
|
+
"types": "src/index.ts",
|
|
9
|
+
<% } else if (type === 'css') { -%>
|
|
10
|
+
"module": "src/index.css",
|
|
11
|
+
<% } else { -%>
|
|
12
|
+
"module": "dist/esm/index.js",
|
|
13
|
+
"types": "dist/types/index.d.ts",
|
|
14
|
+
<% } -%>
|
|
15
|
+
<% if (withCli && type !== 'css') { -%>
|
|
16
|
+
"bin": {
|
|
17
|
+
"<%= shortName %>": "src/cli.ts"
|
|
18
|
+
},
|
|
19
|
+
<% } -%>
|
|
20
|
+
"files": [
|
|
21
|
+
<% if (type === 'tool-ts' || type === 'css') { -%>
|
|
22
|
+
"src"
|
|
23
|
+
<% } else { -%>
|
|
24
|
+
"dist"
|
|
25
|
+
<% } -%>
|
|
26
|
+
],
|
|
27
|
+
"author": {
|
|
28
|
+
"email": "webteam@canonical.com",
|
|
29
|
+
"name": "Canonical Webteam"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/canonical/pragma"
|
|
34
|
+
},
|
|
35
|
+
"license": "<%= license %>",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/canonical/pragma/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/canonical/pragma#readme",
|
|
40
|
+
"scripts": {
|
|
41
|
+
<% if (type === 'tool-ts' || type === 'css') { -%>
|
|
42
|
+
"build": "echo 'No build needed'",
|
|
43
|
+
<% } else { -%>
|
|
44
|
+
"build": "tsc -p tsconfig.build.json",
|
|
45
|
+
<% } -%>
|
|
46
|
+
<% if (withStorybook) { -%>
|
|
47
|
+
"build:all": "bun run build && bun run build:storybook",
|
|
48
|
+
"build:storybook": "storybook build",
|
|
49
|
+
<% } else { -%>
|
|
50
|
+
"build:all": "bun run build",
|
|
51
|
+
<% } -%>
|
|
52
|
+
<% if (type === 'css') { -%>
|
|
53
|
+
"check": "bun run check:biome && bun run check:webarchitect",
|
|
54
|
+
"check:fix": "bun run check:biome:fix",
|
|
55
|
+
<% } else { -%>
|
|
56
|
+
"check": "bun run check:biome && bun run check:ts && bun run check:webarchitect",
|
|
57
|
+
"check:fix": "bun run check:biome:fix && bun run check:ts",
|
|
58
|
+
<% } -%>
|
|
59
|
+
"check:biome": "biome check",
|
|
60
|
+
"check:biome:fix": "biome check --write",
|
|
61
|
+
<% if (type !== 'css') { -%>
|
|
62
|
+
"check:ts": "tsc --noEmit",
|
|
63
|
+
<% } -%>
|
|
64
|
+
"check:webarchitect": "webarchitect <%= ruleset %>",
|
|
65
|
+
<% if (withStorybook) { -%>
|
|
66
|
+
"storybook": "storybook dev -p 6006 --no-open --host 0.0.0.0",
|
|
67
|
+
<% } -%>
|
|
68
|
+
<% if (type === 'css') { -%>
|
|
69
|
+
"test": "echo 'No tests for CSS package'"
|
|
70
|
+
<% } else { -%>
|
|
71
|
+
"test": "vitest run"
|
|
72
|
+
<% } -%>
|
|
73
|
+
},
|
|
74
|
+
<% if (type !== 'css') { -%>
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"@biomejs/biome": "2.3.11",
|
|
77
|
+
"@canonical/biome-config": "^<%= monorepoVersion || '0.1.0' %>",
|
|
78
|
+
<% if (withReact) { -%>
|
|
79
|
+
"@canonical/typescript-config-react": "^<%= monorepoVersion || '0.1.0' %>",
|
|
80
|
+
<% } else { -%>
|
|
81
|
+
"@canonical/typescript-config-base": "^<%= monorepoVersion || '0.1.0' %>",
|
|
82
|
+
<% } -%>
|
|
83
|
+
<% if (withStorybook) { -%>
|
|
84
|
+
"@chromatic-com/storybook": "^5.0.0",
|
|
85
|
+
<% } -%>
|
|
86
|
+
<% if (withReact) { -%>
|
|
87
|
+
"@types/react": "^19.0.0",
|
|
88
|
+
"@types/react-dom": "^19.0.0",
|
|
89
|
+
<% } -%>
|
|
90
|
+
"bun-types": "^1.0.0",
|
|
91
|
+
<% if (withStorybook) { -%>
|
|
92
|
+
"storybook": "^10.1.11",
|
|
93
|
+
<% } -%>
|
|
94
|
+
"typescript": "^5.9.3",
|
|
95
|
+
"vitest": "^3.2.4"
|
|
96
|
+
},
|
|
97
|
+
"dependencies": {
|
|
98
|
+
<% if (withStorybook) { -%>
|
|
99
|
+
"@canonical/storybook-config": "^<%= monorepoVersion || '0.1.0' %>",
|
|
100
|
+
<% } -%>
|
|
101
|
+
<% if (withReact) { -%>
|
|
102
|
+
"react": "^19.0.0",
|
|
103
|
+
"react-dom": "^19.0.0"
|
|
104
|
+
<% } -%>
|
|
105
|
+
}
|
|
106
|
+
<% } else { -%>
|
|
107
|
+
"devDependencies": {
|
|
108
|
+
"@biomejs/biome": "2.3.11",
|
|
109
|
+
"@canonical/biome-config": "^<%= monorepoVersion || '0.1.0' %>"
|
|
110
|
+
}
|
|
111
|
+
<% } -%>
|
|
112
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { withThemeByClassName } from "@storybook/addon-themes";
|
|
2
|
+
import type { Preview, ReactRenderer } from "@storybook/react-vite";
|
|
3
|
+
|
|
4
|
+
import "index.css";
|
|
5
|
+
import "@canonical/styles-debug/baseline-grid";
|
|
6
|
+
|
|
7
|
+
const preview: Preview = {
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
decorators: [
|
|
10
|
+
withThemeByClassName<ReactRenderer>({
|
|
11
|
+
themes: {
|
|
12
|
+
light: "is-light",
|
|
13
|
+
dark: "is-dark",
|
|
14
|
+
paper: "is-paper",
|
|
15
|
+
},
|
|
16
|
+
defaultTheme: "light",
|
|
17
|
+
}),
|
|
18
|
+
],
|
|
19
|
+
parameters: {
|
|
20
|
+
docs: {
|
|
21
|
+
codePanel: true,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default preview;
|