create-middag-ui 0.18.0 → 0.20.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/cli.js CHANGED
@@ -30,11 +30,9 @@ import {
30
30
  scaffoldDevShell,
31
31
  scaffoldEslintConfig,
32
32
  scaffoldGitignore,
33
- scaffoldInjectPlaceholders,
34
33
  scaffoldFreeAdapters,
35
34
  scaffoldFreeApp,
36
35
  scaffoldFreeRegister,
37
- scaffoldProAdapters,
38
36
  scaffoldHostEntry,
39
37
  scaffoldHostThemeCSS,
40
38
  scaffoldHostViteConfig,
@@ -171,12 +169,23 @@ if (!dirCreated) {
171
169
  heading(5, TOTAL_STEPS, "Scaffolding config files");
172
170
 
173
171
  const isPro = registryPath === "github";
174
- scaffoldPackageJson(targetDir, host, cwd, registryPath, hostKey);
172
+
173
+ // PRO only: @middag-io/licensing is a build-time delivery manifest, not a
174
+ // runtime gate. Not every PRO product needs it, so make it opt-in (default no).
175
+ const withLicensing =
176
+ isPro && !nonInteractive
177
+ ? await confirm(
178
+ "Include @middag-io/licensing (build-time delivery manifest)?",
179
+ false,
180
+ )
181
+ : false;
182
+
183
+ scaffoldPackageJson(targetDir, host, cwd, registryPath, hostKey, withLicensing);
175
184
  scaffoldTsconfig(targetDir);
176
185
  scaffoldViteConfig(targetDir, host, registryPath);
177
- scaffoldEslintConfig(targetDir, isPro);
186
+ scaffoldEslintConfig(targetDir);
178
187
  scaffoldPrettierConfig(targetDir);
179
- scaffoldGitignore(targetDir, isPro);
188
+ scaffoldGitignore(targetDir);
180
189
  scaffoldIndexHtml(targetDir);
181
190
 
182
191
  // ── Step 6: Scaffold ~/.npmrc (GitHub path only) ─────────────────────────
@@ -223,11 +232,7 @@ if (isPro) {
223
232
  pro.scaffoldMockEntities(targetDir);
224
233
  pro.scaffoldMockPageContracts(targetDir);
225
234
  pro.scaffoldMockRoutes(targetDir);
226
- // PRO Inertia adapters re-export from @middag-io/react/mock so usePage()
227
- // shares the same React context as MockPageProvider (no context mismatch).
228
- scaffoldProAdapters(targetDir);
229
- scaffoldInjectPlaceholders(targetDir);
230
- success("PRO: using MockProductShell from @middag-io/react/mock");
235
+ success("PRO: host-sim dev harness inherited from @middag-io/react-demo");
231
236
  } catch {
232
237
  // npm version — PRO file excluded, fall back to FREE
233
238
  info("PRO scaffold not available — using FREE path");
@@ -247,7 +252,7 @@ if (isPro) {
247
252
 
248
253
  // Host-specific production files (entry, vite config, theme CSS)
249
254
  scaffoldHostEntry(targetDir, hostKey);
250
- scaffoldHostViteConfig(targetDir, hostKey, host);
255
+ scaffoldHostViteConfig(targetDir, hostKey, host, withLicensing);
251
256
  scaffoldHostThemeCSS(targetDir, hostKey, host);
252
257
 
253
258
  // Moodle-specific: AMD plugin + Moodle adapters (ajax, strings, notification)
package/lib/scaffold.js CHANGED
@@ -91,7 +91,7 @@ export function createTargetDir(targetDir) {
91
91
  * @param {string} registryPath - "github" (PRO) or "public" (FREE)
92
92
  * @param {string} [hostKey] - 'wordpress' | 'moodle' | 'custom' (adds host build scripts)
93
93
  */
94
- export function scaffoldPackageJson(targetDir, host, cwd, registryPath, hostKey) {
94
+ export function scaffoldPackageJson(targetDir, host, cwd, registryPath, hostKey, withLicensing = false) {
95
95
  const filePath = join(targetDir, "package.json");
96
96
  if (skipIfExists(filePath, "package.json")) return;
97
97
 
@@ -103,7 +103,12 @@ export function scaffoldPackageJson(targetDir, host, cwd, registryPath, hostKey)
103
103
  "react-router": "^7.0.0",
104
104
  };
105
105
  if (isPro) {
106
+ deps["@middag-io/react-pro"] = `^${getLibVersion()}`;
106
107
  deps["sonner"] = "^2.0.0";
108
+ // Opt-in: build-time delivery manifest, not every PRO product needs it.
109
+ if (withLicensing) {
110
+ deps["@middag-io/licensing"] = "^0.1.0";
111
+ }
107
112
  }
108
113
 
109
114
  // Moodle AMD build needs Tailwind Vite plugin for CSS processing
@@ -113,6 +118,13 @@ export function scaffoldPackageJson(targetDir, host, cwd, registryPath, hostKey)
113
118
  moodleDevDeps["tailwindcss"] = "^4.0.0";
114
119
  }
115
120
 
121
+ // PRO: dev harness (host-sim shell, Inertia mocks, i18n) inherited at dev time
122
+ // from @middag-io/react-demo. Dev-only — production entry-*.tsx never imports it.
123
+ const proDevDeps = {};
124
+ if (isPro) {
125
+ proDevDeps["@middag-io/react-demo"] = `^${getLibVersion()}`;
126
+ }
127
+
116
128
  const scripts = {
117
129
  dev: "vite",
118
130
  build: "vite build",
@@ -127,24 +139,12 @@ export function scaffoldPackageJson(targetDir, host, cwd, registryPath, hostKey)
127
139
  if (hostKey === "wordpress") {
128
140
  scripts["build:wp"] = "vite build --config vite.config.wordpress.ts";
129
141
  scripts["watch:wp"] = "vite build --config vite.config.wordpress.ts --watch";
130
- if (isPro) {
131
- scripts["build:licensed"] =
132
- "vite build --config vite.config.wordpress.ts && node scripts/inject-placeholders.mjs";
133
- }
134
142
  } else if (hostKey === "moodle") {
135
143
  scripts["build:moodle"] = "vite build --config vite.config.moodle.ts";
136
144
  scripts["watch:moodle"] = "vite build --config vite.config.moodle.ts --watch";
137
- if (isPro) {
138
- scripts["build:licensed"] =
139
- "vite build --config vite.config.moodle.ts && node scripts/inject-placeholders.mjs";
140
- }
141
145
  } else if (hostKey === "custom") {
142
146
  scripts["build:host"] = "vite build --config vite.config.custom.ts";
143
147
  scripts["watch:host"] = "vite build --config vite.config.custom.ts --watch";
144
- if (isPro) {
145
- scripts["build:licensed"] =
146
- "vite build --config vite.config.custom.ts && node scripts/inject-placeholders.mjs";
147
- }
148
148
  }
149
149
 
150
150
  const pkg = {
@@ -173,6 +173,7 @@ export function scaffoldPackageJson(targetDir, host, cwd, registryPath, hostKey)
173
173
  prettier: "^3.0.0",
174
174
  "prettier-plugin-tailwindcss": "^0.6.0",
175
175
  ...moodleDevDeps,
176
+ ...proDevDeps,
176
177
  },
177
178
  };
178
179
 
@@ -220,9 +221,19 @@ export function scaffoldViteConfig(targetDir, host, registryPath) {
220
221
  const filePath = join(targetDir, "vite.config.ts");
221
222
  if (skipIfExists(filePath, "vite.config.ts")) return;
222
223
 
223
- const adapterComment = registryPath === "github"
224
- ? "// PRO: Inertia mocks re-exported from @middag-io/react/mock (same context)"
225
- : "// FREE: Inertia mocks from local adapters";
224
+ const optimizeInclude = registryPath === "github"
225
+ ? '["@middag-io/react", "@middag-io/react-pro", "@middag-io/react-demo"]'
226
+ : '["@middag-io/react"]';
227
+
228
+ // PRO inherits the dev harness (host-sim shell + Inertia mocks) from
229
+ // @middag-io/react-demo, so @inertiajs/* alias to it. FREE: local adapters.
230
+ const inertiaAlias = registryPath === "github"
231
+ ? '// PRO: Inertia mocks inherited from @middag-io/react-demo (dev harness)\n' +
232
+ ' "@inertiajs/react": "@middag-io/react-demo",\n' +
233
+ ' "@inertiajs/core": "@middag-io/react-demo",'
234
+ : '// FREE: Inertia mocks from local self-contained adapters\n' +
235
+ ' "@inertiajs/react": resolve(__dirname, "mock/adapters/inertia-react.ts"),\n' +
236
+ ' "@inertiajs/core": resolve(__dirname, "mock/adapters/inertia-core.ts"),';
226
237
 
227
238
  const content = `/**
228
239
  * Vite config \u2014 used by \`npm run dev\` and \`npm run build\`.
@@ -239,15 +250,13 @@ export default defineConfig({
239
250
  plugins: [react()],
240
251
  server: { port: ${host.port} },
241
252
  optimizeDeps: {
242
- include: ["@middag-io/react", "@middag-io/react/mock"],
253
+ include: ${optimizeInclude},
243
254
  },
244
255
  resolve: {
245
256
  alias: {
246
257
  "@/": resolve(__dirname, "src") + "/",
247
258
  "@mock/": resolve(__dirname, "mock") + "/",
248
- ${adapterComment}
249
- "@inertiajs/react": resolve(__dirname, "mock/adapters/inertia-react.ts"),
250
- "@inertiajs/core": resolve(__dirname, "mock/adapters/inertia-core.ts"),
259
+ ${inertiaAlias}
251
260
  },
252
261
  },
253
262
  });
@@ -259,11 +268,11 @@ export default defineConfig({
259
268
  /**
260
269
  * Scaffold eslint.config.js.
261
270
  */
262
- export function scaffoldEslintConfig(targetDir, isPro = false) {
271
+ export function scaffoldEslintConfig(targetDir) {
263
272
  const filePath = join(targetDir, "eslint.config.js");
264
273
  if (skipIfExists(filePath, "eslint.config.js")) return;
265
274
 
266
- const ignores = ["dist/", "node_modules/", "scripts/", ...(isPro ? ["dist-licensed/"] : [])];
275
+ const ignores = ["dist/", "node_modules/", "scripts/"];
267
276
  const ignoresStr = ignores.map((i) => `"${i}"`).join(", ");
268
277
 
269
278
  writeFile(
@@ -328,14 +337,13 @@ export function scaffoldPrettierConfig(targetDir) {
328
337
  /**
329
338
  * Scaffold .gitignore with UI-specific dist patterns.
330
339
  */
331
- export function scaffoldGitignore(targetDir, isPro = false) {
340
+ export function scaffoldGitignore(targetDir) {
332
341
  const filePath = join(targetDir, ".gitignore");
333
342
  if (skipIfExists(filePath, ".gitignore")) return;
334
343
 
335
344
  const lines = [
336
345
  "node_modules/",
337
346
  "dist/",
338
- ...(isPro ? ["dist-licensed/"] : []),
339
347
  "dist-master/",
340
348
  "dist-mock/",
341
349
  "dist-lib/",
@@ -345,79 +353,6 @@ export function scaffoldGitignore(targetDir, isPro = false) {
345
353
  writeFile(filePath, lines.join("\n") + "\n", ".gitignore");
346
354
  }
347
355
 
348
- /**
349
- * Scaffold scripts/inject-placeholders.mjs (PRO only).
350
- * Injects opaque placeholder variables into middag-* bundles for CDN delivery.
351
- * The Cloudflare Worker replaces placeholders with per-installation values.
352
- */
353
- export function scaffoldInjectPlaceholders(targetDir) {
354
- const scriptsDir = join(targetDir, "scripts");
355
- mkdirSync(scriptsDir, { recursive: true });
356
- const filePath = join(scriptsDir, "inject-placeholders.mjs");
357
- if (skipIfExists(filePath, "scripts/inject-placeholders.mjs")) return;
358
-
359
- writeFile(
360
- filePath,
361
- `/**
362
- * inject-placeholders — generate licensed bundles for CDN delivery.
363
- *
364
- * Takes compiled Vite output from dist/ and produces dist-licensed/ with
365
- * placeholder variables injected into middag-* bundles. The Cloudflare
366
- * Worker replaces these placeholders with real values per installation.
367
- *
368
- * Usage: node scripts/inject-placeholders.mjs
369
- * Called by: npm run build:licensed
370
- */
371
- import fs from "node:fs";
372
- import path from "node:path";
373
-
374
- const DIST_DIR = path.resolve(import.meta.dirname, "../dist");
375
- const LICENSED_DIR = path.resolve(import.meta.dirname, "../dist-licensed");
376
-
377
- // Variable names are intentionally opaque to discourage reverse engineering.
378
- // The mapping is documented only here and in the Worker source:
379
- // _0x7a3f → wwwroot (replaced by Worker with installation URL)
380
- // _0x9b1e → expiry (replaced by Worker with unix timestamp)
381
- // _0x4d2c → tier (replaced by Worker with license tier)
382
- // _0x6e8a → domain hash (replaced by Worker with HMAC of wwwroot)
383
- const PLACEHOLDER_HEADER = [
384
- 'var _0x7a3f="__PH_0x7a3f__";',
385
- "var _0x9b1e=0;",
386
- 'var _0x4d2c="__PH_0x4d2c__";',
387
- 'var _0x6e8a="__PH_0x6e8a__";',
388
- ].join("") + "\\n";
389
-
390
- if (fs.existsSync(LICENSED_DIR)) fs.rmSync(LICENSED_DIR, { recursive: true });
391
- fs.mkdirSync(LICENSED_DIR, { recursive: true });
392
-
393
- const files = fs.readdirSync(DIST_DIR).filter((f) => f.endsWith(".js"));
394
- let injected = 0;
395
- let copied = 0;
396
-
397
- for (const file of files) {
398
- const srcPath = path.join(DIST_DIR, file);
399
- const destPath = path.join(LICENSED_DIR, file);
400
- const content = fs.readFileSync(srcPath, "utf-8");
401
-
402
- if (file.startsWith("middag-")) {
403
- fs.writeFileSync(destPath, PLACEHOLDER_HEADER + content);
404
- injected++;
405
- console.log(\`[licensed] \${file} — placeholders injected\`);
406
- } else {
407
- fs.copyFileSync(srcPath, destPath);
408
- copied++;
409
- console.log(\`[licensed] \${file} — copied (vendor/shared)\`);
410
- }
411
- }
412
-
413
- console.log(\`\\nLicensed bundles ready in \${LICENSED_DIR}/\`);
414
- console.log(\` \${injected} bundle(s) with placeholders\`);
415
- console.log(\` \${copied} bundle(s) copied as-is\`);
416
- `,
417
- "scripts/inject-placeholders.mjs",
418
- );
419
- }
420
-
421
356
  /**
422
357
  * Scaffold index.html at project root.
423
358
  */
@@ -1043,132 +978,6 @@ export const settingsContract: PageContract = {
1043
978
  }
1044
979
  }
1045
980
 
1046
- // ── App files — PRO path (GitHub Packages) ─────────────────────────────
1047
-
1048
- /**
1049
- * Scaffold PRO app: src/main.tsx + src/app.tsx.
1050
- * Uses mock barrel from @middag-io/react/mock. No local adapters/shell.
1051
- */
1052
- export function scaffoldProApp(targetDir) {
1053
- ensureDir(join(targetDir, "src"));
1054
- ensureDir(join(targetDir, "mock", "adapters"));
1055
-
1056
- // Inertia adapter shims — re-export from pre-built mock bundle
1057
- // so usePage() shares the same MockPageContext as MockPageProvider.
1058
- const adapterReactPath = join(targetDir, "mock", "adapters", "inertia-react.ts");
1059
- if (!skipIfExists(adapterReactPath, "mock/adapters/inertia-react.ts")) {
1060
- writeFile(adapterReactPath, `/**
1061
- * Mock @inertiajs/react — re-exports from pre-built @middag-io/react/mock.
1062
- *
1063
- * This ensures usePage() reads from the same MockPageContext as
1064
- * MockPageProvider (both live in the pre-built ESM bundle).
1065
- */
1066
- export { usePage, Head, Link, router } from "@middag-io/react/mock";
1067
- `, "mock/adapters/inertia-react.ts");
1068
- }
1069
-
1070
- const adapterCorePath = join(targetDir, "mock", "adapters", "inertia-core.ts");
1071
- if (!skipIfExists(adapterCorePath, "mock/adapters/inertia-core.ts")) {
1072
- writeFile(adapterCorePath, `/**
1073
- * Mock @inertiajs/core — re-exports from pre-built @middag-io/react/mock.
1074
- */
1075
- export { router, setMockNavigate } from "@middag-io/react/mock";
1076
- `, "mock/adapters/inertia-core.ts");
1077
- }
1078
-
1079
- const mainPath = join(targetDir, "src", "main.tsx");
1080
- if (!skipIfExists(mainPath, "src/main.tsx")) {
1081
- writeFile(mainPath, `import { StrictMode } from "react";
1082
- import { createRoot } from "react-dom/client";
1083
- import { registerDefaults, registerShell } from "@middag-io/react";
1084
- import { MockProductShell } from "@middag-io/react/mock";
1085
- import "@middag-io/react/style.css";
1086
- import "./theme.css";
1087
- import "@fontsource-variable/figtree";
1088
- import { App } from "./app";
1089
-
1090
- registerDefaults();
1091
- registerShell("product", MockProductShell);
1092
-
1093
- createRoot(document.getElementById("root")!).render(
1094
- <StrictMode><App /></StrictMode>,
1095
- );
1096
- `, "src/main.tsx");
1097
- }
1098
-
1099
- const appPath = join(targetDir, "src", "app.tsx");
1100
- if (!skipIfExists(appPath, "src/app.tsx")) {
1101
- writeFile(appPath, `import { useEffect } from "react";
1102
- import { BrowserRouter, Routes, Route, useNavigate } from "react-router";
1103
- import { ContractPage, I18nProvider } from "@middag-io/react";
1104
- import { MockPageProvider, MockI18nProvider } from "@middag-io/react/mock";
1105
- import type { PageContract } from "@middag-io/react";
1106
- import { dashboardContract } from "./pages/dashboard";
1107
- import { connectorsContract } from "./pages/connectors";
1108
- import { settingsContract } from "./pages/settings";
1109
-
1110
- let _navigate: ((to: string) => void) | null = null;
1111
- function NavigateBridge() {
1112
- const navigate = useNavigate();
1113
- useEffect(() => { _navigate = (to: string) => navigate(to); }, [navigate]);
1114
- return null;
1115
- }
1116
- if (typeof window !== "undefined") {
1117
- (window as any).__MIDDAG_MOCK_NAVIGATE__ = (to: string) => { if (_navigate) _navigate(to); };
1118
- }
1119
-
1120
- const sharedProps = {
1121
- auth: { id: 1, name: "Dev User", email: "dev@localhost", capabilities: [] },
1122
- theme: { appearance: "light" as const, strings: {} as Record<string, string> },
1123
- flash: {},
1124
- locale: "en",
1125
- version: "0.0.0-dev",
1126
- scope: { extension: null, context: "global" },
1127
- };
1128
-
1129
- function buildNavigation(activeKey: string) {
1130
- return {
1131
- tree: [
1132
- { key: "overview.dashboard", label: "Dashboard", icon: "home", href: "/", children: [] },
1133
- { key: "integration.connectors", label: "Connectors", icon: "plug", href: "/connectors", children: [] },
1134
- ],
1135
- footer: [
1136
- { key: "system.settings", label: "Settings", icon: "settings", href: "/settings", children: [] },
1137
- ],
1138
- activeKey,
1139
- };
1140
- }
1141
-
1142
- function MockRoute({ contract, activeKey }: { contract: PageContract; activeKey: string }) {
1143
- return (
1144
- <MockPageProvider value={{ props: { ...sharedProps, contract, navigation: buildNavigation(activeKey) }, url: window.location.pathname }}>
1145
- <ContractPage contract={contract} />
1146
- </MockPageProvider>
1147
- );
1148
- }
1149
-
1150
- export function App() {
1151
- return (
1152
- <MockI18nProvider>
1153
- <MockPageProvider value={{ props: { ...sharedProps, contract: null, navigation: buildNavigation("") }, url: "/" }}>
1154
- <I18nProvider>
1155
- <BrowserRouter>
1156
- <NavigateBridge />
1157
- <Routes>
1158
- <Route path="/" element={<MockRoute contract={dashboardContract} activeKey="overview.dashboard" />} />
1159
- <Route path="/connectors" element={<MockRoute contract={connectorsContract} activeKey="integration.connectors" />} />
1160
- <Route path="/settings" element={<MockRoute contract={settingsContract} activeKey="system.settings" />} />
1161
- </Routes>
1162
- </BrowserRouter>
1163
- </I18nProvider>
1164
- </MockPageProvider>
1165
- </MockI18nProvider>
1166
- );
1167
- }
1168
- `, "src/app.tsx");
1169
- }
1170
- }
1171
-
1172
981
  /**
1173
982
  * Scaffold FREE adapters: mock/adapters/ with react-router.
1174
983
  */
@@ -1248,39 +1057,6 @@ export { router };
1248
1057
  }
1249
1058
  }
1250
1059
 
1251
- /**
1252
- * Scaffold PRO adapters: thin re-exports from @middag-io/react/mock.
1253
- *
1254
- * PRO uses MockPageProvider from the lib, so usePage() must read from the
1255
- * same React context. These adapters delegate to the lib mock instead of
1256
- * defining their own context (which would cause context mismatch).
1257
- */
1258
- export function scaffoldProAdapters(targetDir) {
1259
- ensureDir(join(targetDir, "mock", "adapters"));
1260
-
1261
- const corePath = join(targetDir, "mock", "adapters", "inertia-core.ts");
1262
- if (!skipIfExists(corePath, "mock/adapters/inertia-core.ts")) {
1263
- writeFile(corePath, `/**
1264
- * Mock @inertiajs/core — PRO re-export from @middag-io/react/mock.
1265
- * Shares the same navigate function as MockProductShell.
1266
- */
1267
- export { router, setMockNavigate } from "@middag-io/react/mock";
1268
- `, "mock/adapters/inertia-core.ts (PRO)");
1269
- }
1270
-
1271
- const reactPath = join(targetDir, "mock", "adapters", "inertia-react.ts");
1272
- if (!skipIfExists(reactPath, "mock/adapters/inertia-react.ts")) {
1273
- writeFile(reactPath, `/**
1274
- * Mock @inertiajs/react — PRO re-export from @middag-io/react/mock.
1275
- * Shares the same React context as MockPageProvider so usePage()
1276
- * returns the data set by the mock shell.
1277
- */
1278
- export { usePage, Head, Link } from "@middag-io/react/mock";
1279
- export { router } from "./inertia-core";
1280
- `, "mock/adapters/inertia-react.ts (PRO)");
1281
- }
1282
- }
1283
-
1284
1060
  /**
1285
1061
  * Scaffold FREE DevShell: src/shells/DevShell.tsx.
1286
1062
  */
@@ -1622,13 +1398,20 @@ ${postMountCode}
1622
1398
  * @param {string} targetDir - Absolute path to UI dir
1623
1399
  * @param {string} hostKey - 'wordpress' | 'moodle' | 'custom'
1624
1400
  * @param {object} host - HOSTS[hostKey] object
1401
+ * @param {boolean} withLicensing - Whether to emit @middag-io/licensing delivery manifest plugin
1625
1402
  */
1626
- export function scaffoldHostViteConfig(targetDir, hostKey, host) {
1403
+ export function scaffoldHostViteConfig(targetDir, hostKey, host, withLicensing = false) {
1627
1404
  const filePath = join(targetDir, `vite.config.${hostKey}.ts`);
1628
1405
  const label = `vite.config.${hostKey}.ts`;
1629
1406
  if (skipIfExists(filePath, label)) return;
1630
1407
 
1631
1408
  let outDir, formats, libName, fileName, extraRollup;
1409
+ const licensingImport = withLicensing
1410
+ ? `import { licensingPlugin } from "@middag-io/licensing/build";\n`
1411
+ : "";
1412
+ const licensingPluginEntry = withLicensing
1413
+ ? `,\n licensingPlugin({\n product: process.env.MIDDAG_PRODUCT ?? "middag-ui",\n release: process.env.MIDDAG_RELEASE ?? "local",\n buildId: process.env.MIDDAG_BUILD_ID ?? "local",\n modules: [],\n })`
1414
+ : "";
1632
1415
 
1633
1416
  if (hostKey === "wordpress") {
1634
1417
  outDir = `resolve(__dirname, "../assets/dist")`;
@@ -1662,10 +1445,11 @@ import { defineConfig } from "vite";
1662
1445
  import react from "@vitejs/plugin-react";
1663
1446
  import tailwindcss from "@tailwindcss/vite";
1664
1447
  import moodleAmd from "./plugins/vite-plugin-moodle-amd";
1448
+ ${licensingImport.trimEnd()}
1665
1449
  import { resolve } from "path";
1666
1450
 
1667
1451
  export default defineConfig({
1668
- plugins: [react(), tailwindcss(), moodleAmd()],
1452
+ plugins: [react(), tailwindcss(), moodleAmd()${licensingPluginEntry}],
1669
1453
  define: { "process.env.NODE_ENV": JSON.stringify("production") },
1670
1454
  resolve: { alias: { "@/": resolve(__dirname, "src") + "/" } },
1671
1455
  build: {
@@ -1734,10 +1518,11 @@ export default defineConfig({
1734
1518
  */
1735
1519
  import { defineConfig } from "vite";
1736
1520
  import react from "@vitejs/plugin-react";
1521
+ ${licensingImport.trimEnd()}
1737
1522
  import { resolve } from "path";
1738
1523
 
1739
1524
  export default defineConfig({
1740
- plugins: [react()],
1525
+ plugins: [react()${licensingPluginEntry}],
1741
1526
  define: { "process.env.NODE_ENV": JSON.stringify("production") },
1742
1527
  resolve: { alias: { "@/": resolve(__dirname, "src") + "/" } },
1743
1528
  build: {
@@ -5,11 +5,15 @@
5
5
  * mock/routes.tsx — route definitions
6
6
  * mock/navigation.ts — sidebar structure
7
7
  * mock/data.ts — synthetic page props
8
+ *
9
+ * The dev harness (host-sim shell, Inertia mocks, i18n) is inherited from
10
+ * @middag-io/react-demo — not generated locally. Vite aliases @inertiajs/*
11
+ * to it (see vite.config.ts).
8
12
  */
9
13
  import {useEffect} from "react";
10
14
  import {BrowserRouter, Routes, useNavigate} from "react-router";
11
15
  import {I18nProvider} from "@middag-io/react";
12
- import {MockI18nProvider, MockPageProvider, setMockNavigate} from "@middag-io/react/mock";
16
+ import {MockI18nProvider, MockPageProvider, setMockNavigate} from "@middag-io/react-demo";
13
17
  import {buildNavigation} from "../mock/navigation";
14
18
  import {sharedProps} from "../mock/data";
15
19
  import {AppRoutes} from "../mock/routes";
@@ -1,19 +1,24 @@
1
1
  import { StrictMode } from "react";
2
2
  import { createRoot } from "react-dom/client";
3
3
  import { registerDefaults, registerShell } from "@middag-io/react";
4
- import { MockProductShell } from "@middag-io/react/mock";
4
+ import { registerProDefaults } from "@middag-io/react-pro/runtime";
5
+ import { MockProductShell } from "@middag-io/react-demo";
5
6
  import "@middag-io/react/style.css";
6
7
  import "@middag-io/react/themes/classic.css";
7
- import "@middag-io/react/themes/enterprise.css";
8
- import "@middag-io/react/themes/soft.css";
9
- import "@middag-io/react/themes/midnight.css";
8
+ import "@middag-io/react-pro/themes/enterprise.css";
9
+ import "@middag-io/react-pro/themes/soft.css";
10
+ import "@middag-io/react-pro/themes/midnight.css";
10
11
  import "./theme.css";
11
12
  import "@fontsource-variable/figtree";
12
13
  import { App } from "./app";
13
14
 
14
- // Dev mode: register all blocks from the lib (19 blocks + fields + icons + cells).
15
- // In production, entry-*.tsx uses the selective register from ./app/register.
15
+ // Dev mode: register the free engine defaults (12 standard blocks + fields +
16
+ // icons + cells) plus the premium runtime (the 7 heavy blocks). Then override
17
+ // the "product" shell with the host-sim MockProductShell inherited from
18
+ // @middag-io/react-demo (Moodle/WP chrome, host switcher, theme/locale toggles).
19
+ // Dev-only — in production, entry-*.tsx uses the selective register from ./app/register.
16
20
  registerDefaults();
21
+ registerProDefaults();
17
22
  registerShell("product", MockProductShell);
18
23
 
19
24
  createRoot(document.getElementById("root")!).render(
@@ -6,7 +6,7 @@
6
6
  import { Route } from "react-router";
7
7
  import { type ReactNode } from "react";
8
8
  import { ContractPage, resolveShell, EntityRoutesProvider } from "@middag-io/react";
9
- import { MockPageProvider } from "@middag-io/react/mock";
9
+ import { MockPageProvider } from "@middag-io/react-demo";
10
10
  import type { PageContract } from "@middag-io/react";
11
11
  import { mockEntities } from "./entities";
12
12
  import { buildNavigation } from "./navigation";
@@ -1,12 +1,14 @@
1
1
  /**
2
- * register — selective registration for this plugin's UI.
2
+ * register — registration for this plugin's UI.
3
3
  *
4
- * Registers only the shells, layouts, blocks, cell renderers, form fields,
5
- * and icons this plugin uses. For IIFE bundles (WordPress/Moodle), selective
6
- * registration avoids pulling in heavy lazy-loaded blocks that bloat the bundle.
4
+ * Registers all 13 standard blocks plus shells, layouts, cell renderers, form
5
+ * fields and icons. Every block in @middag-io/react is free to use — there is no
6
+ * tiered block gating. The 6 heavy lazy-loaded blocks (chart_panel, kanban_board,
7
+ * flow_editor, form_builder, condition_tree, sentence_builder) are NOT registered
8
+ * here to keep the bundle lean; deep-import + registerBlock() them when a page
9
+ * needs one, or call registerDefaults() from @middag-io/react to register all 19.
7
10
  *
8
- * When adding a new page that needs a block not listed here,
9
- * add the import + registerBlock call.
11
+ * For lean IIFE bundles (WordPress/Moodle), trim the blocks you don't use.
10
12
  *
11
13
  * Full catalog: https://docs.middag.io/blocks
12
14
  */
@@ -31,10 +33,14 @@ import {
31
33
  MetricCardBlock,
32
34
  EmptyStateBlock,
33
35
  DetailPanelBlock,
34
- FormPanelBlock,
35
- CardGridBlock,
36
36
  StatusStripBlock,
37
+ FormPanelBlock,
37
38
  TabbedPanelBlock,
39
+ ActivityTimelineBlock,
40
+ WorkflowProgressBlock,
41
+ MarkdownPanelBlock,
42
+ CardGridBlock,
43
+ ActionGridBlock,
38
44
  LinkListBlock,
39
45
  } from "@middag-io/react";
40
46
 
@@ -59,10 +65,14 @@ export function registerDefaults(): void {
59
65
  registerBlock("metric_card", MetricCardBlock);
60
66
  registerBlock("empty_state", EmptyStateBlock);
61
67
  registerBlock("detail_panel", DetailPanelBlock);
62
- registerBlock("form_panel", FormPanelBlock);
63
- registerBlock("card_grid", CardGridBlock);
64
68
  registerBlock("status_strip", StatusStripBlock);
69
+ registerBlock("form_panel", FormPanelBlock);
65
70
  registerBlock("tabbed_panel", TabbedPanelBlock);
71
+ registerBlock("activity_timeline", ActivityTimelineBlock);
72
+ registerBlock("workflow_progress", WorkflowProgressBlock);
73
+ registerBlock("markdown_panel", MarkdownPanelBlock);
74
+ registerBlock("card_grid", CardGridBlock);
75
+ registerBlock("action_grid", ActionGridBlock);
66
76
  registerBlock("link_list", LinkListBlock);
67
77
 
68
78
  // Cell renderers (status, timestamp, link, boolean, etc.)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-middag-ui",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "type": "module",
5
5
  "description": "Bootstrap a MIDDAG React UI layer in your Moodle or WordPress plugin",
6
6
  "bin": {