create-middag-ui 0.1.4 → 0.2.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 +43 -24
- package/cli.js +149 -287
- package/lib/auth.js +210 -0
- package/lib/detect.js +29 -0
- package/lib/install.js +92 -0
- package/lib/prompts.js +120 -0
- package/lib/scaffold.js +386 -0
- package/lib/ui.js +85 -0
- package/package.json +2 -1
package/lib/scaffold.js
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scaffold.js — File creation for all scaffolded files.
|
|
3
|
+
*
|
|
4
|
+
* Creates directory structure, config files, demo files, and mock files.
|
|
5
|
+
* Every I/O operation is wrapped with error handling.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { join, basename } from "node:path";
|
|
10
|
+
import { success, warn, error } from "./ui.js";
|
|
11
|
+
|
|
12
|
+
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
function writeFile(filePath, content, label) {
|
|
15
|
+
try {
|
|
16
|
+
writeFileSync(filePath, content);
|
|
17
|
+
success(`Created ${label}`);
|
|
18
|
+
return true;
|
|
19
|
+
} catch (err) {
|
|
20
|
+
error(`Failed to create ${label}: ${err.message}`);
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function ensureDir(dirPath) {
|
|
26
|
+
try {
|
|
27
|
+
mkdirSync(dirPath, { recursive: true });
|
|
28
|
+
return true;
|
|
29
|
+
} catch (err) {
|
|
30
|
+
error(`Failed to create directory ${dirPath}: ${err.message}`);
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function skipIfExists(filePath, label) {
|
|
36
|
+
if (existsSync(filePath)) {
|
|
37
|
+
warn(`${label} already exists \u2014 skipping`);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ── Create target directory ──────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Create the target directory.
|
|
47
|
+
* @param {string} targetDir - Absolute path
|
|
48
|
+
* @returns {boolean} true if directory exists/was created
|
|
49
|
+
*/
|
|
50
|
+
export function createTargetDir(targetDir) {
|
|
51
|
+
if (existsSync(targetDir)) {
|
|
52
|
+
warn(`${basename(targetDir)}/ directory already exists \u2014 will scaffold inside it`);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return ensureDir(targetDir);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ── Config files ─────────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Scaffold package.json.
|
|
62
|
+
*/
|
|
63
|
+
export function scaffoldPackageJson(targetDir, host, cwd) {
|
|
64
|
+
const filePath = join(targetDir, "package.json");
|
|
65
|
+
if (skipIfExists(filePath, "package.json")) return;
|
|
66
|
+
|
|
67
|
+
const projectName = basename(cwd) || "project";
|
|
68
|
+
const pkg = {
|
|
69
|
+
name: `${projectName}-ui`,
|
|
70
|
+
private: true,
|
|
71
|
+
type: "module",
|
|
72
|
+
scripts: {
|
|
73
|
+
dev: "vite --config vite.mock.config.ts",
|
|
74
|
+
"dev:mock": "vite --config vite.mock.config.ts",
|
|
75
|
+
build: "vite build",
|
|
76
|
+
"build:mock": "vite build --config vite.mock.config.ts",
|
|
77
|
+
typecheck: "tsc --noEmit",
|
|
78
|
+
lint: "eslint .",
|
|
79
|
+
"lint:fix": "eslint . --fix",
|
|
80
|
+
},
|
|
81
|
+
dependencies: {
|
|
82
|
+
"@middag-io/react": "^0.1.0",
|
|
83
|
+
},
|
|
84
|
+
devDependencies: {
|
|
85
|
+
"@types/react": "^19.0.0",
|
|
86
|
+
"@types/react-dom": "^19.0.0",
|
|
87
|
+
react: "^19.0.0",
|
|
88
|
+
"react-dom": "^19.0.0",
|
|
89
|
+
"@inertiajs/react": "^2.0.0",
|
|
90
|
+
"@inertiajs/core": "^2.0.0",
|
|
91
|
+
typescript: "^5.7.0",
|
|
92
|
+
vite: "^6.0.0",
|
|
93
|
+
"@vitejs/plugin-react": "^4.0.0",
|
|
94
|
+
tailwindcss: "^4.0.0",
|
|
95
|
+
"@tailwindcss/vite": "^4.0.0",
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
writeFile(filePath, JSON.stringify(pkg, null, 2) + "\n", "package.json");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Scaffold tsconfig.json.
|
|
104
|
+
*/
|
|
105
|
+
export function scaffoldTsconfig(targetDir) {
|
|
106
|
+
const filePath = join(targetDir, "tsconfig.json");
|
|
107
|
+
if (skipIfExists(filePath, "tsconfig.json")) return;
|
|
108
|
+
|
|
109
|
+
const tsconfig = {
|
|
110
|
+
compilerOptions: {
|
|
111
|
+
target: "ES2022",
|
|
112
|
+
module: "ESNext",
|
|
113
|
+
moduleResolution: "bundler",
|
|
114
|
+
jsx: "react-jsx",
|
|
115
|
+
strict: true,
|
|
116
|
+
noUnusedLocals: true,
|
|
117
|
+
noUnusedParameters: true,
|
|
118
|
+
skipLibCheck: true,
|
|
119
|
+
paths: { "@/*": ["./src/*"], "@mock/*": ["./mock/*"] },
|
|
120
|
+
baseUrl: ".",
|
|
121
|
+
},
|
|
122
|
+
include: ["src", "mock"],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
writeFile(filePath, JSON.stringify(tsconfig, null, 2) + "\n", "tsconfig.json");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Scaffold vite.mock.config.ts.
|
|
130
|
+
*/
|
|
131
|
+
export function scaffoldViteConfig(targetDir, host) {
|
|
132
|
+
const filePath = join(targetDir, "vite.mock.config.ts");
|
|
133
|
+
if (skipIfExists(filePath, "vite.mock.config.ts")) return;
|
|
134
|
+
|
|
135
|
+
const content = `import { defineConfig } from "vite";
|
|
136
|
+
import react from "@vitejs/plugin-react";
|
|
137
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
138
|
+
import { resolve } from "path";
|
|
139
|
+
|
|
140
|
+
export default defineConfig({
|
|
141
|
+
plugins: [react(), tailwindcss()],
|
|
142
|
+
root: "mock",
|
|
143
|
+
server: { port: ${host.port} },
|
|
144
|
+
resolve: {
|
|
145
|
+
alias: {
|
|
146
|
+
"@/": resolve(__dirname, "src") + "/",
|
|
147
|
+
"@mock/": resolve(__dirname, "mock") + "/",
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
`;
|
|
152
|
+
|
|
153
|
+
writeFile(filePath, content, "vite.mock.config.ts");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ── Demo files in src/ ──────────────────────────────────────────────────
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Scaffold demo files in src/ that teach the contract system.
|
|
160
|
+
*/
|
|
161
|
+
export function scaffoldDemoFiles(targetDir) {
|
|
162
|
+
ensureDir(join(targetDir, "src", "blocks"));
|
|
163
|
+
ensureDir(join(targetDir, "src", "components"));
|
|
164
|
+
|
|
165
|
+
// src/blocks/hello-block.tsx
|
|
166
|
+
const helloBlockPath = join(targetDir, "src", "blocks", "hello-block.tsx");
|
|
167
|
+
if (!skipIfExists(helloBlockPath, "src/blocks/hello-block.tsx")) {
|
|
168
|
+
writeFile(
|
|
169
|
+
helloBlockPath,
|
|
170
|
+
`// RENAME ME \u2014 This is an example custom block.
|
|
171
|
+
//
|
|
172
|
+
// It demonstrates how to create a block that integrates with
|
|
173
|
+
// the MIDDAG contract system via registerBlock().
|
|
174
|
+
//
|
|
175
|
+
// After renaming, update the registration in your setup code.
|
|
176
|
+
//
|
|
177
|
+
// Docs: https://docs.middag.io/blocks/custom-blocks
|
|
178
|
+
|
|
179
|
+
import type { BlockProps } from "@middag-io/react";
|
|
180
|
+
|
|
181
|
+
/** Data shape for this block \u2014 define what the backend sends. */
|
|
182
|
+
export interface HelloBlockData {
|
|
183
|
+
greeting: string;
|
|
184
|
+
name: string;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Custom block component. Receives data from the PageContract. */
|
|
188
|
+
export function HelloBlock({ data }: BlockProps<HelloBlockData>) {
|
|
189
|
+
return (
|
|
190
|
+
<div className="rounded-lg border bg-card p-6 text-card-foreground">
|
|
191
|
+
<h2 className="text-lg font-semibold text-foreground">
|
|
192
|
+
{data.greeting}
|
|
193
|
+
</h2>
|
|
194
|
+
<p className="mt-2 text-muted-foreground">
|
|
195
|
+
Welcome, {data.name}! This is a custom block.
|
|
196
|
+
</p>
|
|
197
|
+
<p className="mt-4 text-sm text-muted-foreground">
|
|
198
|
+
Edit this file at <code className="text-xs bg-muted px-1 py-0.5 rounded">src/blocks/hello-block.tsx</code>
|
|
199
|
+
</p>
|
|
200
|
+
</div>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
`,
|
|
204
|
+
"src/blocks/hello-block.tsx",
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/components/greeting.tsx
|
|
209
|
+
const greetingPath = join(targetDir, "src", "components", "greeting.tsx");
|
|
210
|
+
if (!skipIfExists(greetingPath, "src/components/greeting.tsx")) {
|
|
211
|
+
writeFile(
|
|
212
|
+
greetingPath,
|
|
213
|
+
`// RENAME ME \u2014 This is an example standalone component.
|
|
214
|
+
//
|
|
215
|
+
// It shows you can write normal React components alongside
|
|
216
|
+
// contract-driven blocks. Not everything needs to be a block.
|
|
217
|
+
//
|
|
218
|
+
// Use standalone components for UI that doesn't come from
|
|
219
|
+
// a PageContract \u2014 headers, sidebars, modals, etc.
|
|
220
|
+
|
|
221
|
+
interface GreetingProps {
|
|
222
|
+
name: string;
|
|
223
|
+
role?: string;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function Greeting({ name, role = "developer" }: GreetingProps) {
|
|
227
|
+
return (
|
|
228
|
+
<div className="flex items-center gap-3 rounded-md bg-muted px-4 py-3">
|
|
229
|
+
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary text-primary-foreground text-sm font-medium">
|
|
230
|
+
{name.charAt(0).toUpperCase()}
|
|
231
|
+
</div>
|
|
232
|
+
<div>
|
|
233
|
+
<p className="text-sm font-medium text-foreground">{name}</p>
|
|
234
|
+
<p className="text-xs text-muted-foreground">{role}</p>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
`,
|
|
240
|
+
"src/components/greeting.tsx",
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/contracts.ts
|
|
245
|
+
const contractsPath = join(targetDir, "src", "contracts.ts");
|
|
246
|
+
if (!skipIfExists(contractsPath, "src/contracts.ts")) {
|
|
247
|
+
writeFile(
|
|
248
|
+
contractsPath,
|
|
249
|
+
`// Re-export PageContract types from the lib for convenience.
|
|
250
|
+
// Import from here instead of directly from @middag-io/react.
|
|
251
|
+
//
|
|
252
|
+
// Example:
|
|
253
|
+
// import type { PageContract } from '@/contracts';
|
|
254
|
+
|
|
255
|
+
export type { PageContract, BlockDescriptor, SharedProps } from "@middag-io/react";
|
|
256
|
+
`,
|
|
257
|
+
"src/contracts.ts",
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// ── Mock files ──────────────────────────────────────────────────────────
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Scaffold mock/ files (hello-contract, main.tsx, index.html, tailwind.css).
|
|
266
|
+
*/
|
|
267
|
+
export function scaffoldMockFiles(targetDir) {
|
|
268
|
+
const mockDir = join(targetDir, "mock");
|
|
269
|
+
ensureDir(mockDir);
|
|
270
|
+
|
|
271
|
+
// mock/hello-contract.ts
|
|
272
|
+
const helloContractPath = join(mockDir, "hello-contract.ts");
|
|
273
|
+
if (!skipIfExists(helloContractPath, "mock/hello-contract.ts")) {
|
|
274
|
+
writeFile(
|
|
275
|
+
helloContractPath,
|
|
276
|
+
`import type { PageContract } from "@middag-io/react";
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Hello World contract \u2014 a minimal PageContract to verify your setup.
|
|
280
|
+
*
|
|
281
|
+
* This is what your backend will send via Inertia.
|
|
282
|
+
* Replace this with real data from your server.
|
|
283
|
+
*/
|
|
284
|
+
export const helloContract: PageContract = {
|
|
285
|
+
shell: "admin",
|
|
286
|
+
meta: {
|
|
287
|
+
title: "Hello MIDDAG",
|
|
288
|
+
breadcrumbs: [
|
|
289
|
+
{ label: "Home", href: "/" },
|
|
290
|
+
{ label: "Hello", href: "/hello" },
|
|
291
|
+
],
|
|
292
|
+
},
|
|
293
|
+
layout: {
|
|
294
|
+
template: "stack",
|
|
295
|
+
regions: {
|
|
296
|
+
content: [
|
|
297
|
+
{
|
|
298
|
+
key: "welcome_metrics",
|
|
299
|
+
type: "metric_card",
|
|
300
|
+
data: {
|
|
301
|
+
title: "Setup Complete",
|
|
302
|
+
value: "1",
|
|
303
|
+
subtitle: "@middag-io/react is working",
|
|
304
|
+
trend: { direction: "up", value: "100%", label: "Ready" },
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
key: "hello_table",
|
|
309
|
+
type: "dense_table",
|
|
310
|
+
data: {
|
|
311
|
+
title: "Example Data",
|
|
312
|
+
columns: [
|
|
313
|
+
{ key: "id", label: "ID", sortable: true },
|
|
314
|
+
{ key: "name", label: "Name", sortable: true },
|
|
315
|
+
{ key: "status", label: "Status" },
|
|
316
|
+
],
|
|
317
|
+
rows: [
|
|
318
|
+
{ id: 1, name: "First item", status: "Active" },
|
|
319
|
+
{ id: 2, name: "Second item", status: "Draft" },
|
|
320
|
+
{ id: 3, name: "Third item", status: "Active" },
|
|
321
|
+
],
|
|
322
|
+
pagination: { current: 1, total: 1, perPage: 10, totalRows: 3 },
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
],
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
`,
|
|
330
|
+
"mock/hello-contract.ts",
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// mock/main.tsx
|
|
335
|
+
const mainPath = join(mockDir, "main.tsx");
|
|
336
|
+
if (!skipIfExists(mainPath, "mock/main.tsx")) {
|
|
337
|
+
writeFile(
|
|
338
|
+
mainPath,
|
|
339
|
+
`import { StrictMode } from "react";
|
|
340
|
+
import { createRoot } from "react-dom/client";
|
|
341
|
+
import { ContractPage, registerDefaults } from "@middag-io/react";
|
|
342
|
+
import "@middag-io/react/style.css";
|
|
343
|
+
import "./tailwind.css";
|
|
344
|
+
import { helloContract } from "./hello-contract";
|
|
345
|
+
|
|
346
|
+
// Register all default shells, layouts, and blocks
|
|
347
|
+
registerDefaults();
|
|
348
|
+
|
|
349
|
+
createRoot(document.getElementById("root")!).render(
|
|
350
|
+
<StrictMode>
|
|
351
|
+
<ContractPage contract={helloContract} />
|
|
352
|
+
</StrictMode>,
|
|
353
|
+
);
|
|
354
|
+
`,
|
|
355
|
+
"mock/main.tsx",
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// mock/index.html
|
|
360
|
+
const indexPath = join(mockDir, "index.html");
|
|
361
|
+
if (!skipIfExists(indexPath, "mock/index.html")) {
|
|
362
|
+
writeFile(
|
|
363
|
+
indexPath,
|
|
364
|
+
`<!doctype html>
|
|
365
|
+
<html lang="en">
|
|
366
|
+
<head>
|
|
367
|
+
<meta charset="UTF-8" />
|
|
368
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
369
|
+
<title>MIDDAG React UI \u2014 Mock</title>
|
|
370
|
+
</head>
|
|
371
|
+
<body>
|
|
372
|
+
<div id="root"></div>
|
|
373
|
+
<script type="module" src="./main.tsx"></script>
|
|
374
|
+
</body>
|
|
375
|
+
</html>
|
|
376
|
+
`,
|
|
377
|
+
"mock/index.html",
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// mock/tailwind.css
|
|
382
|
+
const cssPath = join(mockDir, "tailwind.css");
|
|
383
|
+
if (!skipIfExists(cssPath, "mock/tailwind.css")) {
|
|
384
|
+
writeFile(cssPath, '@import "tailwindcss";\n', "mock/tailwind.css");
|
|
385
|
+
}
|
|
386
|
+
}
|
package/lib/ui.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/* global console, process, setInterval, clearInterval */
|
|
2
|
+
/**
|
|
3
|
+
* ui.js — ANSI output helpers (log, success, warn, error, spinner).
|
|
4
|
+
*
|
|
5
|
+
* Zero external deps — uses raw ANSI escape codes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const PREFIX = "\x1b[36mcreate-middag-ui\x1b[0m";
|
|
9
|
+
const RESET = "\x1b[0m";
|
|
10
|
+
const GREEN = "\x1b[32m";
|
|
11
|
+
const YELLOW = "\x1b[33m";
|
|
12
|
+
const RED = "\x1b[31m";
|
|
13
|
+
const DIM = "\x1b[2m";
|
|
14
|
+
const BOLD = "\x1b[1m";
|
|
15
|
+
const CYAN = "\x1b[36m";
|
|
16
|
+
|
|
17
|
+
export function log(msg) {
|
|
18
|
+
console.log(`${PREFIX} ${msg}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function success(msg) {
|
|
22
|
+
console.log(` ${GREEN}\u2713${RESET} ${msg}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function warn(msg) {
|
|
26
|
+
console.log(` ${YELLOW}\u26A0${RESET} ${msg}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function error(msg) {
|
|
30
|
+
console.log(` ${RED}\u2717${RESET} ${msg}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function info(msg) {
|
|
34
|
+
console.log(` ${DIM}${msg}${RESET}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function heading(step, total, msg) {
|
|
38
|
+
console.log(`\n${CYAN}[${step}/${total}]${RESET} ${BOLD}${msg}${RESET}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function blank() {
|
|
42
|
+
console.log("");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ── Spinner ──────────────────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
const FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Creates an inline spinner that overwrites the current line.
|
|
51
|
+
*
|
|
52
|
+
* Returns { stop(finalMsg) } — call stop() to clear the spinner
|
|
53
|
+
* and print a final message.
|
|
54
|
+
*/
|
|
55
|
+
export function createSpinner(msg) {
|
|
56
|
+
let i = 0;
|
|
57
|
+
const id = setInterval(() => {
|
|
58
|
+
const frame = FRAMES[i % FRAMES.length];
|
|
59
|
+
process.stdout.write(`\r ${CYAN}${frame}${RESET} ${msg}`);
|
|
60
|
+
i++;
|
|
61
|
+
}, 80);
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
/** Update the spinner message while it's running. */
|
|
65
|
+
update(newMsg) {
|
|
66
|
+
msg = newMsg;
|
|
67
|
+
},
|
|
68
|
+
/** Stop spinner and print final line. */
|
|
69
|
+
stop(finalMsg) {
|
|
70
|
+
clearInterval(id);
|
|
71
|
+
process.stdout.write(`\r\x1b[2K`); // clear line
|
|
72
|
+
if (finalMsg) {
|
|
73
|
+
success(finalMsg);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
/** Stop spinner and print error. */
|
|
77
|
+
fail(failMsg) {
|
|
78
|
+
clearInterval(id);
|
|
79
|
+
process.stdout.write(`\r\x1b[2K`);
|
|
80
|
+
if (failMsg) {
|
|
81
|
+
error(failMsg);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-middag-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Bootstrap a MIDDAG React UI layer in your Moodle or WordPress plugin",
|
|
6
6
|
"bin": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"cli.js",
|
|
11
|
+
"lib/",
|
|
11
12
|
"README.md"
|
|
12
13
|
],
|
|
13
14
|
"keywords": [
|