@recursica/adapter-tester 5.1.4 → 5.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.
@@ -1,13 +1,18 @@
1
- import { mkdirSync as d, writeFileSync as o } from "node:fs";
1
+ import { mkdirSync as m, writeFileSync as n } from "node:fs";
2
2
  import { join as t } from "node:path";
3
- const n = "^8.0.0", a = "^10.3.3", c = "^19.0.0", p = {
3
+ const u = [
4
+ "recursica_variables_scoped.css",
5
+ "recursica_tokens.json",
6
+ "recursica_brand.json",
7
+ "recursica_ui-kit.json"
8
+ ], d = "^8.0.0", a = "^10.3.3", p = "^19.0.0", l = {
4
9
  "@storybook/addon-docs": a,
5
10
  "@storybook/addon-a11y": a,
6
11
  "storybook-dark-mode": "^5.0.0"
7
- }, l = {
12
+ }, f = {
8
13
  "react-markdown": "^10.1.0"
9
14
  };
10
- function m(r) {
15
+ function y(r) {
11
16
  return {
12
17
  name: "adapter-tester-mantine-source-of-truth-harness",
13
18
  private: !0,
@@ -21,20 +26,19 @@ function m(r) {
21
26
  dependencies: {
22
27
  "@recursica/adapter-mantine-v8": r.mantineAdapterVersion,
23
28
  "@recursica/storybook-template": r.storybookTemplateVersion,
24
- "@recursica/official-release": "latest",
25
29
  "@recursica/adapter-common": "latest",
26
- "@mantine/core": n,
27
- "@mantine/dates": n,
28
- react: c,
29
- "react-dom": c,
30
+ "@mantine/core": d,
31
+ "@mantine/dates": d,
32
+ react: p,
33
+ "react-dom": p,
30
34
  storybook: a,
31
35
  "@storybook/react-vite": a,
32
- ...p,
33
- ...l
36
+ ...l,
37
+ ...f
34
38
  }
35
39
  };
36
40
  }
37
- const u = `import { createMainConfig } from "@recursica/storybook-template/main";
41
+ const h = `import { createMainConfig } from "@recursica/storybook-template/main";
38
42
 
39
43
  const config = createMainConfig({
40
44
  stories: [
@@ -53,17 +57,19 @@ const config = createMainConfig({
53
57
  config.typescript = { ...config.typescript, reactDocgen: false };
54
58
 
55
59
  export default config;
56
- `, f = `import type { Preview } from "@storybook/react-vite";
60
+ `;
61
+ function g() {
62
+ return `import type { Preview } from "@storybook/react-vite";
57
63
  import { createPreviewConfig } from "@recursica/storybook-template/preview";
58
64
  import { MantineProvider } from "@mantine/core";
59
65
  import { Layer } from "@recursica/adapter-common";
60
66
  import "@mantine/core/styles.css";
61
67
  import "@mantine/dates/styles.css";
62
68
  import "@recursica/adapter-common/style.css";
63
- import "@recursica/official-release/recursica_variables_scoped.css";
64
- import recursicaTokens from "@recursica/official-release/recursica_tokens.json";
65
- import recursicaBrand from "@recursica/official-release/recursica_brand.json";
66
- import recursicaUIKit from "@recursica/official-release/recursica_ui-kit.json";
69
+ import "../recursica_variables_scoped.css";
70
+ import recursicaTokens from "../recursica_tokens.json";
71
+ import recursicaBrand from "../recursica_brand.json";
72
+ import recursicaUIKit from "../recursica_ui-kit.json";
67
73
 
68
74
  const basePreview = createPreviewConfig({
69
75
  defaultTheme: "light",
@@ -106,33 +112,61 @@ const preview: Preview = {
106
112
 
107
113
  export default preview;
108
114
  `;
109
- function y(r) {
115
+ }
116
+ function k(r, e, o) {
117
+ const s = r === "target" ? o : t(e, "node_modules/@recursica/adapter-mantine-v8");
118
+ return `import { copyFileSync } from "node:fs";
119
+ import { join } from "node:path";
120
+
121
+ const sourceDir = ${JSON.stringify(s)};
122
+ const destDir = ${JSON.stringify(e)};
123
+ const files = ${JSON.stringify(u, null, 2)};
124
+
125
+ for (const file of files) {
126
+ copyFileSync(join(sourceDir, file), join(destDir, file));
127
+ }
128
+
129
+ console.log(\`[adapter-tester] copied Recursica tokens from \${sourceDir}\`);
130
+ `;
131
+ }
132
+ function v(r) {
110
133
  const {
111
134
  dir: e,
112
- mantineAdapterVersion: s = "latest",
113
- storybookTemplateVersion: i = "latest"
135
+ mantineAdapterVersion: o = "latest",
136
+ storybookTemplateVersion: s = "latest",
137
+ tokensSource: i = "target",
138
+ targetDir: c
114
139
  } = r;
115
- return d(t(e, ".storybook"), { recursive: !0 }), o(
140
+ if (i === "target" && !c)
141
+ throw new Error(
142
+ `mantineSourceOfTruthWebServer: tokensSource "target" (the default) requires targetDir — the target adapter's own repo root, source of its 4 committed Recursica token files.`
143
+ );
144
+ return m(t(e, ".storybook"), { recursive: !0 }), n(
116
145
  t(e, "package.json"),
117
146
  JSON.stringify(
118
- m({
119
- mantineAdapterVersion: s,
120
- storybookTemplateVersion: i
147
+ y({
148
+ mantineAdapterVersion: o,
149
+ storybookTemplateVersion: s
121
150
  }),
122
151
  null,
123
152
  2
124
153
  ) + `
125
154
  `
126
- ), o(t(e, ".storybook/main.ts"), u), o(t(e, ".storybook/preview.tsx"), f), o(t(e, ".gitignore"), `node_modules
155
+ ), n(t(e, ".storybook/main.ts"), h), n(t(e, ".storybook/preview.tsx"), g()), n(
156
+ t(e, "copy-tokens.mjs"),
157
+ k(i, e, c)
158
+ ), n(t(e, ".gitignore"), `node_modules
159
+ *.json
160
+ *.css
127
161
  `), e;
128
162
  }
129
- function k(r) {
130
- const e = y(r), {
131
- mantineAdapterVersion: s = "latest",
132
- storybookTemplateVersion: i = "latest"
163
+ function S(r) {
164
+ const e = v(r), {
165
+ mantineAdapterVersion: o = "latest",
166
+ storybookTemplateVersion: s = "latest"
133
167
  } = r;
134
168
  return {
135
- command: `npm install @recursica/adapter-mantine-v8@${s} @recursica/storybook-template@${i} --no-audit --no-fund && npm run storybook`,
169
+ command: `npm install @recursica/adapter-mantine-v8@${o} @recursica/storybook-template@${s} --no-audit --no-fund && node copy-tokens.mjs && npm run storybook`,
136
170
  port: r.port,
137
171
  cwd: e,
138
172
  reuseExistingServer: !process.env.CI,
@@ -141,7 +175,7 @@ function k(r) {
141
175
  };
142
176
  }
143
177
  export {
144
- k as m,
145
- y as s
178
+ S as m,
179
+ v as s
146
180
  };
147
- //# sourceMappingURL=mantineSourceOfTruth-Ddaxq3m0.js.map
181
+ //# sourceMappingURL=mantineSourceOfTruth-CAKhcVCT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mantineSourceOfTruth-CAKhcVCT.js","sources":["../src/harness/mantineSourceOfTruth.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/** The 4 Recursica token files every real adapter commits at its own repo root. */\nconst TOKEN_FILES = [\n \"recursica_variables_scoped.css\",\n \"recursica_tokens.json\",\n \"recursica_brand.json\",\n \"recursica_ui-kit.json\",\n];\n\n/**\n * Generates a small, throwaway Storybook project that installs\n * `@recursica/adapter-mantine-v8` as a real npm dependency (not a workspace\n * link) and boots a real Storybook from its published `src/**\\/*.stories.tsx`\n * files, using `@recursica/storybook-template`'s exported factories.\n *\n * This lets any repo — including ones that never checked out the Recursica\n * monorepo — run adapter-tester's visual regression suite against Mantine\n * (Recursica's source-of-truth adapter) as one side of the comparison, while\n * the other side is that repo's own already-running local Storybook.\n *\n * See PROPOSAL-installed-package-harness.md for the verified prototype this\n * is built from, and the three upstream gaps it works around.\n */\n\n/**\n * Which Recursica token snapshot the harness's Mantine components render\n * with:\n *\n * - `\"target\"` (default): the target adapter's own committed\n * `recursica_variables_scoped.css`/`recursica_tokens.json`/\n * `recursica_brand.json`/`recursica_ui-kit.json` (read from `targetDir`,\n * copied into the harness once `npm install` finishes) — makes the\n * divergence check mean exactly \"given the *same* tokens this target\n * adapter is using, does it render the same as Mantine's own components,\"\n * isolating adapter-mapping correctness from any token-snapshot drift\n * between the two repos.\n * - `\"mantine-package\"`: `@recursica/adapter-mantine-v8`'s own bundled\n * token files (whatever it was last published with) — tests against\n * Mantine's own understanding of the tokens instead, which also (as a\n * side effect) flags a target repo whose own committed tokens have gone\n * stale relative to Mantine's.\n *\n * Never `@recursica/official-release` — confirmed live (not a theoretical\n * concern) to be a stale, deprecated, generic token snapshot unrelated to\n * either adapter's real ones: it resolves the brand's primary/secondary\n * fonts to Lexend/Bellota Text, not this design system's actual Dongle/\n * Nunito Sans. An earlier version of this harness imported from it\n * directly — this type/its two real options replace that entirely.\n */\nexport type MantineSourceOfTruthTokensSource = \"target\" | \"mantine-package\";\n\nexport interface MantineSourceOfTruthHarnessOptions {\n /**\n * Directory the harness project is scaffolded into. Regenerated on every\n * call — add it to your .gitignore rather than committing it.\n */\n dir: string;\n /** First-guess port, shown for `--dry-run` visibility only. The harness's\n * Storybook is never pinned to this — see `HarnessWebServerConfig.port`. */\n port: number;\n /** npm version/range for @recursica/adapter-mantine-v8. Defaults to \"latest\". */\n mantineAdapterVersion?: string;\n /** npm version/range for @recursica/storybook-template. Defaults to \"latest\". */\n storybookTemplateVersion?: string;\n /** See `MantineSourceOfTruthTokensSource`. Defaults to `\"target\"`. */\n tokensSource?: MantineSourceOfTruthTokensSource;\n /**\n * The target adapter's own repo root — required when `tokensSource` is\n * `\"target\"` (the default), the source the 4 token files are copied\n * from. Unused (and not required) for `\"mantine-package\"`.\n */\n targetDir?: string;\n}\n\nexport interface HarnessWebServerConfig {\n command: string;\n /** First-guess port, shown for `--dry-run` visibility only — not\n * authoritative. The real port is whatever this Storybook's own startup\n * banner reports once it's actually running (see portDiscovery.ts), since\n * Storybook silently falls back to an OS-assigned port whenever this one\n * is taken. */\n port: number;\n cwd: string;\n reuseExistingServer: boolean;\n /** File the real, detected port is cached in between runs, so a later\n * `reuseExistingServer` run can find this instance again. */\n cacheFile: string;\n timeout: number;\n}\n\n// Peer/dev ranges pinned to what @recursica/adapter-mantine-v8 and\n// @recursica/storybook-template themselves require, so the harness can't\n// drift onto an incompatible Mantine or Storybook major version.\nconst MANTINE_CORE_RANGE = \"^8.0.0\";\nconst STORYBOOK_RANGE = \"^10.3.3\";\nconst REACT_RANGE = \"^19.0.0\";\n\n// storybook-template's createMainConfig() defaults its addons list to these\n// three but doesn't declare them as peerDependencies (proposal gap 2) — a\n// harness that skips installing any of them gets a silent \"could not\n// resolve addon\" warning at boot, then a hard runtime crash later when Vite\n// pre-bundles preview.tsx's dependency graph. Installed explicitly here.\nconst DEFAULT_ADDON_DEPENDENCIES = {\n \"@storybook/addon-docs\": STORYBOOK_RANGE,\n \"@storybook/addon-a11y\": STORYBOOK_RANGE,\n \"storybook-dark-mode\": \"^5.0.0\",\n};\n\n// adapter-mantine-v8's Introduction.stories.tsx (Version.tsx/OverStyling.tsx)\n// needs react-markdown, but it's a devDependency there — Storybook-only,\n// never bundled into dist — so an external `npm install` of the published\n// package won't pull it in. The harness boots a real Storybook against\n// src/, so it must provide this itself. Installed explicitly here.\nconst WORKAROUND_DEPENDENCIES = {\n \"react-markdown\": \"^10.1.0\",\n};\n\nfunction harnessPackageJson(options: {\n mantineAdapterVersion: string;\n storybookTemplateVersion: string;\n}) {\n return {\n name: \"adapter-tester-mantine-source-of-truth-harness\",\n private: true,\n type: \"module\",\n scripts: {\n // No `-p` pin — Storybook silently falls back to an OS-assigned port\n // whenever its default is taken, so the caller detects the real port\n // from this process's own output rather than trusting a fixed one.\n storybook: `storybook dev`,\n },\n dependencies: {\n \"@recursica/adapter-mantine-v8\": options.mantineAdapterVersion,\n \"@recursica/storybook-template\": options.storybookTemplateVersion,\n \"@recursica/adapter-common\": \"latest\",\n \"@mantine/core\": MANTINE_CORE_RANGE,\n \"@mantine/dates\": MANTINE_CORE_RANGE,\n react: REACT_RANGE,\n \"react-dom\": REACT_RANGE,\n storybook: STORYBOOK_RANGE,\n \"@storybook/react-vite\": STORYBOOK_RANGE,\n ...DEFAULT_ADDON_DEPENDENCIES,\n ...WORKAROUND_DEPENDENCIES,\n },\n };\n}\n\nconst MAIN_TS = `import { createMainConfig } from \"@recursica/storybook-template/main\";\n\nconst config = createMainConfig({\n stories: [\n \"../node_modules/@recursica/adapter-mantine-v8/src/**/*.stories.@(js|jsx|mjs|ts|tsx)\",\n ],\n enableCORS: true,\n});\n\n// react-docgen-typescript can't resolve a TS project for a config file living\n// in .storybook/ when the component source it's docgen'ing lives three\n// directories down inside node_modules — it throws \"Cannot read properties\n// of undefined (reading 'fileExists')\", which surfaces as a plain 404 on\n// preview.tsx. Docgen only powers Storybook's Controls/Docs tables, which\n// this harness never renders, so disabling it is a safe workaround (see\n// PROPOSAL-installed-package-harness.md, gap 3).\nconfig.typescript = { ...config.typescript, reactDocgen: false };\n\nexport default config;\n`;\n\n// Both `tokensSource` modes copy the 4 token files into the harness's own\n// root (see `copyTokensScript()`) before Storybook boots, rather than\n// importing a package subpath directly — `@recursica/adapter-mantine-v8`'s\n// own `package.json` `exports` map only lists `\".\"`/`\"./style.css\"`, so a\n// bare `import \"@recursica/adapter-mantine-v8/recursica_tokens.json\"` would\n// fail to resolve under strict ESM exports-map enforcement even though the\n// file physically ships in the package (confirmed by reading that package's\n// real, installed `package.json` directly). Copying sidesteps that\n// entirely, and gives both modes the identical, simple `../recursica_*`\n// relative-import shape a real adapter's own `preview.tsx` already uses.\nfunction previewTsx(): string {\n return `import type { Preview } from \"@storybook/react-vite\";\nimport { createPreviewConfig } from \"@recursica/storybook-template/preview\";\nimport { MantineProvider } from \"@mantine/core\";\nimport { Layer } from \"@recursica/adapter-common\";\nimport \"@mantine/core/styles.css\";\nimport \"@mantine/dates/styles.css\";\nimport \"@recursica/adapter-common/style.css\";\nimport \"../recursica_variables_scoped.css\";\nimport recursicaTokens from \"../recursica_tokens.json\";\nimport recursicaBrand from \"../recursica_brand.json\";\nimport recursicaUIKit from \"../recursica_ui-kit.json\";\n\nconst basePreview = createPreviewConfig({\n defaultTheme: \"light\",\n recursicaTokensJsonPath: recursicaTokens,\n recursicaBrandJsonPath: recursicaBrand,\n recursicaUIKitJsonPath: recursicaUIKit,\n});\n\n// Mirrors adapter-mantine-v8's own .storybook/preview.tsx decorator (every story defaults to\n// withLayer: true, layer: 0, wrapped with 48px padding) — every real adapter's own preview.tsx\n// applies this same wrapping, so a target adapter's story renders inside the same Layer\n// chrome/padding the source-of-truth side does. Without this, target screenshots come out\n// dramatically smaller/differently-positioned than the source of truth's (no Layer padding,\n// background, or border-radius at all), which alone can blow past the pixel-diff threshold\n// regardless of whether the actual Recursica tokens match — a false positive, not a real\n// component bug. ColorSchemeWrapper (adapter-mantine-v8's dark-mode-toggle sync helper) is\n// intentionally not replicated — it only matters for the interactive dev-mode UI, not automated\n// screenshot diffing, which always runs in a single theme.\nconst preview: Preview = {\n ...basePreview,\n decorators: [\n (Story, context) => {\n const { withLayer = true, layer = 0 } = context.args;\n const content = <Story />;\n return (\n <MantineProvider>\n {withLayer ? (\n <Layer layer={layer as 0 | 1 | 2 | 3} style={{ padding: \"48px\" }}>\n {content}\n </Layer>\n ) : (\n content\n )}\n </MantineProvider>\n );\n },\n ...(basePreview.decorators || []),\n ],\n};\n\nexport default preview;\n`;\n}\n\n/**\n * Generates `copy-tokens.mjs` — run as its own step between `npm install`\n * and `npm run storybook` (see `mantineSourceOfTruthWebServer`'s `command`),\n * not inlined into `scaffoldMantineSourceOfTruthHarness` itself: for\n * `\"mantine-package\"` mode, the source files live inside\n * `node_modules/@recursica/adapter-mantine-v8`, which doesn't exist yet at\n * scaffold time (scaffolding runs before `npm install`) — this script only\n * runs once the package is actually on disk. `\"target\"` mode's source files\n * are already on disk at scaffold time, but uses the same after-install\n * timing for one consistent code path rather than two.\n */\nfunction copyTokensScript(\n tokensSource: MantineSourceOfTruthTokensSource,\n dir: string,\n targetDir: string | undefined,\n): string {\n const sourceDir =\n tokensSource === \"target\"\n ? targetDir!\n : join(dir, \"node_modules/@recursica/adapter-mantine-v8\");\n\n return `import { copyFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst sourceDir = ${JSON.stringify(sourceDir)};\nconst destDir = ${JSON.stringify(dir)};\nconst files = ${JSON.stringify(TOKEN_FILES, null, 2)};\n\nfor (const file of files) {\n copyFileSync(join(sourceDir, file), join(destDir, file));\n}\n\nconsole.log(\\`[adapter-tester] copied Recursica tokens from \\${sourceDir}\\`);\n`;\n}\n\n/** Writes the harness project's files to `options.dir` without booting it. */\nexport function scaffoldMantineSourceOfTruthHarness(\n options: MantineSourceOfTruthHarnessOptions,\n): string {\n const {\n dir,\n mantineAdapterVersion = \"latest\",\n storybookTemplateVersion = \"latest\",\n tokensSource = \"target\",\n targetDir,\n } = options;\n\n if (tokensSource === \"target\" && !targetDir) {\n throw new Error(\n 'mantineSourceOfTruthWebServer: tokensSource \"target\" (the default) requires targetDir — the target adapter\\'s own repo root, source of its 4 committed Recursica token files.',\n );\n }\n\n mkdirSync(join(dir, \".storybook\"), { recursive: true });\n writeFileSync(\n join(dir, \"package.json\"),\n JSON.stringify(\n harnessPackageJson({\n mantineAdapterVersion,\n storybookTemplateVersion,\n }),\n null,\n 2,\n ) + \"\\n\",\n );\n writeFileSync(join(dir, \".storybook/main.ts\"), MAIN_TS);\n writeFileSync(join(dir, \".storybook/preview.tsx\"), previewTsx());\n writeFileSync(\n join(dir, \"copy-tokens.mjs\"),\n copyTokensScript(tokensSource, dir, targetDir),\n );\n writeFileSync(join(dir, \".gitignore\"), \"node_modules\\n*.json\\n*.css\\n\");\n\n return dir;\n}\n\n/**\n * Scaffolds the harness and returns a Playwright `webServer` entry for it.\n * Spread the result directly into `playwright.config.ts`'s `webServer` array.\n */\nexport function mantineSourceOfTruthWebServer(\n options: MantineSourceOfTruthHarnessOptions,\n): HarnessWebServerConfig {\n const dir = scaffoldMantineSourceOfTruthHarness(options);\n const {\n mantineAdapterVersion = \"latest\",\n storybookTemplateVersion = \"latest\",\n } = options;\n\n // A bare `npm install` is satisfied by a package-lock.json already sitting\n // in `dir` from a prior run and skips re-resolving against the registry\n // entirely — no network call — so a run can silently keep testing against\n // a stale @recursica/adapter-mantine-v8/storybook-template even after a newer\n // version is published. Naming the two version-pinned packages as explicit\n // `pkg@specifier` CLI args instead forces npm to re-check just those two\n // against the registry every run, while the rest of node_modules stays\n // cached. `copy-tokens.mjs` runs after install completes (see its own doc\n // comment for why) and before Storybook boots, so `preview.tsx`'s own\n // `../recursica_*` imports resolve correctly on first render.\n const command = `npm install @recursica/adapter-mantine-v8@${mantineAdapterVersion} @recursica/storybook-template@${storybookTemplateVersion} --no-audit --no-fund && node copy-tokens.mjs && npm run storybook`;\n\n return {\n command,\n port: options.port,\n cwd: dir,\n reuseExistingServer: !process.env.CI,\n cacheFile: join(dir, \"last-port.json\"),\n timeout: 180 * 1000,\n };\n}\n"],"names":["TOKEN_FILES","MANTINE_CORE_RANGE","STORYBOOK_RANGE","REACT_RANGE","DEFAULT_ADDON_DEPENDENCIES","WORKAROUND_DEPENDENCIES","harnessPackageJson","options","MAIN_TS","previewTsx","copyTokensScript","tokensSource","dir","targetDir","sourceDir","join","scaffoldMantineSourceOfTruthHarness","mantineAdapterVersion","storybookTemplateVersion","mkdirSync","writeFileSync","mantineSourceOfTruthWebServer"],"mappings":"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"}
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "url": "git+https://github.com/borderux/recursica.git",
14
14
  "directory": "packages/adapter-tester"
15
15
  },
16
- "version": "5.1.4",
16
+ "version": "5.2.0",
17
17
  "type": "module",
18
18
  "main": "./dist/index.cjs",
19
19
  "module": "./dist/index.js",
@@ -57,6 +57,11 @@
57
57
  "storybookTemplateVersion": {
58
58
  "type": "string",
59
59
  "description": "npm version/tag of @recursica/storybook-template to install in the harness. Defaults to `latest`."
60
+ },
61
+ "tokensSource": {
62
+ "type": "string",
63
+ "enum": ["target", "mantine-package"],
64
+ "description": "Which Recursica token snapshot the harness's Mantine components render with. \"target\" (default): this project's own committed recursica_variables_scoped.css/recursica_tokens.json/recursica_brand.json/recursica_ui-kit.json — makes the divergence check mean exactly \"given the same tokens this project is using, does it render the same as Mantine's own components,\" isolating adapter-mapping correctness from any token-snapshot drift between repos. \"mantine-package\": @recursica/adapter-mantine-v8's own bundled token files instead (whatever it was last published with) — also flags, as a side effect, a project whose own committed tokens have gone stale relative to Mantine's. Never the deprecated @recursica/official-release package."
60
65
  }
61
66
  }
62
67
  },
@@ -1,75 +0,0 @@
1
- "use strict";const o=require("node:fs"),t=require("node:path"),n="^8.0.0",s="^10.3.3",c="^19.0.0",l={"@storybook/addon-docs":s,"@storybook/addon-a11y":s,"storybook-dark-mode":"^5.0.0"},p={"react-markdown":"^10.1.0"};function u(r){return{name:"adapter-tester-mantine-source-of-truth-harness",private:!0,type:"module",scripts:{storybook:"storybook dev"},dependencies:{"@recursica/adapter-mantine-v8":r.mantineAdapterVersion,"@recursica/storybook-template":r.storybookTemplateVersion,"@recursica/official-release":"latest","@recursica/adapter-common":"latest","@mantine/core":n,"@mantine/dates":n,react:c,"react-dom":c,storybook:s,"@storybook/react-vite":s,...l,...p}}}const m=`import { createMainConfig } from "@recursica/storybook-template/main";
2
-
3
- const config = createMainConfig({
4
- stories: [
5
- "../node_modules/@recursica/adapter-mantine-v8/src/**/*.stories.@(js|jsx|mjs|ts|tsx)",
6
- ],
7
- enableCORS: true,
8
- });
9
-
10
- // react-docgen-typescript can't resolve a TS project for a config file living
11
- // in .storybook/ when the component source it's docgen'ing lives three
12
- // directories down inside node_modules — it throws "Cannot read properties
13
- // of undefined (reading 'fileExists')", which surfaces as a plain 404 on
14
- // preview.tsx. Docgen only powers Storybook's Controls/Docs tables, which
15
- // this harness never renders, so disabling it is a safe workaround (see
16
- // PROPOSAL-installed-package-harness.md, gap 3).
17
- config.typescript = { ...config.typescript, reactDocgen: false };
18
-
19
- export default config;
20
- `,f=`import type { Preview } from "@storybook/react-vite";
21
- import { createPreviewConfig } from "@recursica/storybook-template/preview";
22
- import { MantineProvider } from "@mantine/core";
23
- import { Layer } from "@recursica/adapter-common";
24
- import "@mantine/core/styles.css";
25
- import "@mantine/dates/styles.css";
26
- import "@recursica/adapter-common/style.css";
27
- import "@recursica/official-release/recursica_variables_scoped.css";
28
- import recursicaTokens from "@recursica/official-release/recursica_tokens.json";
29
- import recursicaBrand from "@recursica/official-release/recursica_brand.json";
30
- import recursicaUIKit from "@recursica/official-release/recursica_ui-kit.json";
31
-
32
- const basePreview = createPreviewConfig({
33
- defaultTheme: "light",
34
- recursicaTokensJsonPath: recursicaTokens,
35
- recursicaBrandJsonPath: recursicaBrand,
36
- recursicaUIKitJsonPath: recursicaUIKit,
37
- });
38
-
39
- // Mirrors adapter-mantine-v8's own .storybook/preview.tsx decorator (every story defaults to
40
- // withLayer: true, layer: 0, wrapped with 48px padding) — every real adapter's own preview.tsx
41
- // applies this same wrapping, so a target adapter's story renders inside the same Layer
42
- // chrome/padding the source-of-truth side does. Without this, target screenshots come out
43
- // dramatically smaller/differently-positioned than the source of truth's (no Layer padding,
44
- // background, or border-radius at all), which alone can blow past the pixel-diff threshold
45
- // regardless of whether the actual Recursica tokens match — a false positive, not a real
46
- // component bug. ColorSchemeWrapper (adapter-mantine-v8's dark-mode-toggle sync helper) is
47
- // intentionally not replicated — it only matters for the interactive dev-mode UI, not automated
48
- // screenshot diffing, which always runs in a single theme.
49
- const preview: Preview = {
50
- ...basePreview,
51
- decorators: [
52
- (Story, context) => {
53
- const { withLayer = true, layer = 0 } = context.args;
54
- const content = <Story />;
55
- return (
56
- <MantineProvider>
57
- {withLayer ? (
58
- <Layer layer={layer as 0 | 1 | 2 | 3} style={{ padding: "48px" }}>
59
- {content}
60
- </Layer>
61
- ) : (
62
- content
63
- )}
64
- </MantineProvider>
65
- );
66
- },
67
- ...(basePreview.decorators || []),
68
- ],
69
- };
70
-
71
- export default preview;
72
- `;function d(r){const{dir:e,mantineAdapterVersion:a="latest",storybookTemplateVersion:i="latest"}=r;return o.mkdirSync(t.join(e,".storybook"),{recursive:!0}),o.writeFileSync(t.join(e,"package.json"),JSON.stringify(u({mantineAdapterVersion:a,storybookTemplateVersion:i}),null,2)+`
73
- `),o.writeFileSync(t.join(e,".storybook/main.ts"),m),o.writeFileSync(t.join(e,".storybook/preview.tsx"),f),o.writeFileSync(t.join(e,".gitignore"),`node_modules
74
- `),e}function y(r){const e=d(r),{mantineAdapterVersion:a="latest",storybookTemplateVersion:i="latest"}=r;return{command:`npm install @recursica/adapter-mantine-v8@${a} @recursica/storybook-template@${i} --no-audit --no-fund && npm run storybook`,port:r.port,cwd:e,reuseExistingServer:!process.env.CI,cacheFile:t.join(e,"last-port.json"),timeout:180*1e3}}exports.mantineSourceOfTruthWebServer=y;exports.scaffoldMantineSourceOfTruthHarness=d;
75
- //# sourceMappingURL=mantineSourceOfTruth-D79OOhom.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mantineSourceOfTruth-D79OOhom.cjs","sources":["../src/harness/mantineSourceOfTruth.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Generates a small, throwaway Storybook project that installs\n * `@recursica/adapter-mantine-v8` as a real npm dependency (not a workspace\n * link) and boots a real Storybook from its published `src/**\\/*.stories.tsx`\n * files, using `@recursica/storybook-template`'s exported factories.\n *\n * This lets any repo — including ones that never checked out the Recursica\n * monorepo — run adapter-tester's visual regression suite against Mantine\n * (Recursica's source-of-truth adapter) as one side of the comparison, while\n * the other side is that repo's own already-running local Storybook.\n *\n * See PROPOSAL-installed-package-harness.md for the verified prototype this\n * is built from, and the three upstream gaps it works around.\n */\n\nexport interface MantineSourceOfTruthHarnessOptions {\n /**\n * Directory the harness project is scaffolded into. Regenerated on every\n * call — add it to your .gitignore rather than committing it.\n */\n dir: string;\n /** First-guess port, shown for `--dry-run` visibility only. The harness's\n * Storybook is never pinned to this — see `HarnessWebServerConfig.port`. */\n port: number;\n /** npm version/range for @recursica/adapter-mantine-v8. Defaults to \"latest\". */\n mantineAdapterVersion?: string;\n /** npm version/range for @recursica/storybook-template. Defaults to \"latest\". */\n storybookTemplateVersion?: string;\n}\n\nexport interface HarnessWebServerConfig {\n command: string;\n /** First-guess port, shown for `--dry-run` visibility only — not\n * authoritative. The real port is whatever this Storybook's own startup\n * banner reports once it's actually running (see portDiscovery.ts), since\n * Storybook silently falls back to an OS-assigned port whenever this one\n * is taken. */\n port: number;\n cwd: string;\n reuseExistingServer: boolean;\n /** File the real, detected port is cached in between runs, so a later\n * `reuseExistingServer` run can find this instance again. */\n cacheFile: string;\n timeout: number;\n}\n\n// Peer/dev ranges pinned to what @recursica/adapter-mantine-v8 and\n// @recursica/storybook-template themselves require, so the harness can't\n// drift onto an incompatible Mantine or Storybook major version.\nconst MANTINE_CORE_RANGE = \"^8.0.0\";\nconst STORYBOOK_RANGE = \"^10.3.3\";\nconst REACT_RANGE = \"^19.0.0\";\n\n// storybook-template's createMainConfig() defaults its addons list to these\n// three but doesn't declare them as peerDependencies (proposal gap 2) — a\n// harness that skips installing any of them gets a silent \"could not\n// resolve addon\" warning at boot, then a hard runtime crash later when Vite\n// pre-bundles preview.tsx's dependency graph. Installed explicitly here.\nconst DEFAULT_ADDON_DEPENDENCIES = {\n \"@storybook/addon-docs\": STORYBOOK_RANGE,\n \"@storybook/addon-a11y\": STORYBOOK_RANGE,\n \"storybook-dark-mode\": \"^5.0.0\",\n};\n\n// adapter-mantine-v8's Introduction.stories.tsx (Version.tsx/OverStyling.tsx)\n// needs react-markdown, but it's a devDependency there — Storybook-only,\n// never bundled into dist — so an external `npm install` of the published\n// package won't pull it in. The harness boots a real Storybook against\n// src/, so it must provide this itself. Installed explicitly here.\nconst WORKAROUND_DEPENDENCIES = {\n \"react-markdown\": \"^10.1.0\",\n};\n\nfunction harnessPackageJson(options: {\n mantineAdapterVersion: string;\n storybookTemplateVersion: string;\n}) {\n return {\n name: \"adapter-tester-mantine-source-of-truth-harness\",\n private: true,\n type: \"module\",\n scripts: {\n // No `-p` pin — Storybook silently falls back to an OS-assigned port\n // whenever its default is taken, so the caller detects the real port\n // from this process's own output rather than trusting a fixed one.\n storybook: `storybook dev`,\n },\n dependencies: {\n \"@recursica/adapter-mantine-v8\": options.mantineAdapterVersion,\n \"@recursica/storybook-template\": options.storybookTemplateVersion,\n \"@recursica/official-release\": \"latest\",\n \"@recursica/adapter-common\": \"latest\",\n \"@mantine/core\": MANTINE_CORE_RANGE,\n \"@mantine/dates\": MANTINE_CORE_RANGE,\n react: REACT_RANGE,\n \"react-dom\": REACT_RANGE,\n storybook: STORYBOOK_RANGE,\n \"@storybook/react-vite\": STORYBOOK_RANGE,\n ...DEFAULT_ADDON_DEPENDENCIES,\n ...WORKAROUND_DEPENDENCIES,\n },\n };\n}\n\nconst MAIN_TS = `import { createMainConfig } from \"@recursica/storybook-template/main\";\n\nconst config = createMainConfig({\n stories: [\n \"../node_modules/@recursica/adapter-mantine-v8/src/**/*.stories.@(js|jsx|mjs|ts|tsx)\",\n ],\n enableCORS: true,\n});\n\n// react-docgen-typescript can't resolve a TS project for a config file living\n// in .storybook/ when the component source it's docgen'ing lives three\n// directories down inside node_modules — it throws \"Cannot read properties\n// of undefined (reading 'fileExists')\", which surfaces as a plain 404 on\n// preview.tsx. Docgen only powers Storybook's Controls/Docs tables, which\n// this harness never renders, so disabling it is a safe workaround (see\n// PROPOSAL-installed-package-harness.md, gap 3).\nconfig.typescript = { ...config.typescript, reactDocgen: false };\n\nexport default config;\n`;\n\nconst PREVIEW_TSX = `import type { Preview } from \"@storybook/react-vite\";\nimport { createPreviewConfig } from \"@recursica/storybook-template/preview\";\nimport { MantineProvider } from \"@mantine/core\";\nimport { Layer } from \"@recursica/adapter-common\";\nimport \"@mantine/core/styles.css\";\nimport \"@mantine/dates/styles.css\";\nimport \"@recursica/adapter-common/style.css\";\nimport \"@recursica/official-release/recursica_variables_scoped.css\";\nimport recursicaTokens from \"@recursica/official-release/recursica_tokens.json\";\nimport recursicaBrand from \"@recursica/official-release/recursica_brand.json\";\nimport recursicaUIKit from \"@recursica/official-release/recursica_ui-kit.json\";\n\nconst basePreview = createPreviewConfig({\n defaultTheme: \"light\",\n recursicaTokensJsonPath: recursicaTokens,\n recursicaBrandJsonPath: recursicaBrand,\n recursicaUIKitJsonPath: recursicaUIKit,\n});\n\n// Mirrors adapter-mantine-v8's own .storybook/preview.tsx decorator (every story defaults to\n// withLayer: true, layer: 0, wrapped with 48px padding) — every real adapter's own preview.tsx\n// applies this same wrapping, so a target adapter's story renders inside the same Layer\n// chrome/padding the source-of-truth side does. Without this, target screenshots come out\n// dramatically smaller/differently-positioned than the source of truth's (no Layer padding,\n// background, or border-radius at all), which alone can blow past the pixel-diff threshold\n// regardless of whether the actual Recursica tokens match — a false positive, not a real\n// component bug. ColorSchemeWrapper (adapter-mantine-v8's dark-mode-toggle sync helper) is\n// intentionally not replicated — it only matters for the interactive dev-mode UI, not automated\n// screenshot diffing, which always runs in a single theme.\nconst preview: Preview = {\n ...basePreview,\n decorators: [\n (Story, context) => {\n const { withLayer = true, layer = 0 } = context.args;\n const content = <Story />;\n return (\n <MantineProvider>\n {withLayer ? (\n <Layer layer={layer as 0 | 1 | 2 | 3} style={{ padding: \"48px\" }}>\n {content}\n </Layer>\n ) : (\n content\n )}\n </MantineProvider>\n );\n },\n ...(basePreview.decorators || []),\n ],\n};\n\nexport default preview;\n`;\n\n/** Writes the harness project's files to `options.dir` without booting it. */\nexport function scaffoldMantineSourceOfTruthHarness(\n options: MantineSourceOfTruthHarnessOptions,\n): string {\n const {\n dir,\n mantineAdapterVersion = \"latest\",\n storybookTemplateVersion = \"latest\",\n } = options;\n\n mkdirSync(join(dir, \".storybook\"), { recursive: true });\n writeFileSync(\n join(dir, \"package.json\"),\n JSON.stringify(\n harnessPackageJson({\n mantineAdapterVersion,\n storybookTemplateVersion,\n }),\n null,\n 2,\n ) + \"\\n\",\n );\n writeFileSync(join(dir, \".storybook/main.ts\"), MAIN_TS);\n writeFileSync(join(dir, \".storybook/preview.tsx\"), PREVIEW_TSX);\n writeFileSync(join(dir, \".gitignore\"), \"node_modules\\n\");\n\n return dir;\n}\n\n/**\n * Scaffolds the harness and returns a Playwright `webServer` entry for it.\n * Spread the result directly into `playwright.config.ts`'s `webServer` array.\n */\nexport function mantineSourceOfTruthWebServer(\n options: MantineSourceOfTruthHarnessOptions,\n): HarnessWebServerConfig {\n const dir = scaffoldMantineSourceOfTruthHarness(options);\n const {\n mantineAdapterVersion = \"latest\",\n storybookTemplateVersion = \"latest\",\n } = options;\n\n // A bare `npm install` is satisfied by a package-lock.json already sitting\n // in `dir` from a prior run and skips re-resolving against the registry\n // entirely — no network call — so a run can silently keep testing against\n // a stale @recursica/adapter-mantine-v8/storybook-template even after a newer\n // version is published. Naming the two version-pinned packages as explicit\n // `pkg@specifier` CLI args instead forces npm to re-check just those two\n // against the registry every run, while the rest of node_modules stays\n // cached.\n const command = `npm install @recursica/adapter-mantine-v8@${mantineAdapterVersion} @recursica/storybook-template@${storybookTemplateVersion} --no-audit --no-fund && npm run storybook`;\n\n return {\n command,\n port: options.port,\n cwd: dir,\n reuseExistingServer: !process.env.CI,\n cacheFile: join(dir, \"last-port.json\"),\n timeout: 180 * 1000,\n };\n}\n"],"names":["MANTINE_CORE_RANGE","STORYBOOK_RANGE","REACT_RANGE","DEFAULT_ADDON_DEPENDENCIES","WORKAROUND_DEPENDENCIES","harnessPackageJson","options","MAIN_TS","PREVIEW_TSX","scaffoldMantineSourceOfTruthHarness","dir","mantineAdapterVersion","storybookTemplateVersion","mkdirSync","join","writeFileSync","mantineSourceOfTruthWebServer"],"mappings":"+DAoDMA,EAAqB,SACrBC,EAAkB,UAClBC,EAAc,UAOdC,EAA6B,CACjC,wBAAyBF,EACzB,wBAAyBA,EACzB,sBAAuB,QACzB,EAOMG,EAA0B,CAC9B,iBAAkB,SACpB,EAEA,SAASC,EAAmBC,EAGzB,CACD,MAAO,CACL,KAAM,iDACN,QAAS,GACT,KAAM,SACN,QAAS,CAIP,UAAW,eAAA,EAEb,aAAc,CACZ,gCAAiCA,EAAQ,sBACzC,gCAAiCA,EAAQ,yBACzC,8BAA+B,SAC/B,4BAA6B,SAC7B,gBAAiBN,EACjB,iBAAkBA,EAClB,MAAOE,EACP,YAAaA,EACb,UAAWD,EACX,wBAAyBA,EACzB,GAAGE,EACH,GAAGC,CAAA,CACL,CAEJ,CAEA,MAAMG,EAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBVC,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuDb,SAASC,EACdH,EACQ,CACR,KAAM,CACJ,IAAAI,EACA,sBAAAC,EAAwB,SACxB,yBAAAC,EAA2B,QAAA,EACzBN,EAEJO,OAAAA,EAAAA,UAAUC,EAAAA,KAAKJ,EAAK,YAAY,EAAG,CAAE,UAAW,GAAM,EACtDK,EAAAA,cACED,EAAAA,KAAKJ,EAAK,cAAc,EACxB,KAAK,UACHL,EAAmB,CACjB,sBAAAM,EACA,yBAAAC,CAAA,CACD,EACD,KACA,CAAA,EACE;AAAA,CAAA,EAENG,EAAAA,cAAcD,EAAAA,KAAKJ,EAAK,oBAAoB,EAAGH,CAAO,EACtDQ,EAAAA,cAAcD,EAAAA,KAAKJ,EAAK,wBAAwB,EAAGF,CAAW,EAC9DO,EAAAA,cAAcD,EAAAA,KAAKJ,EAAK,YAAY,EAAG;AAAA,CAAgB,EAEhDA,CACT,CAMO,SAASM,EACdV,EACwB,CACxB,MAAMI,EAAMD,EAAoCH,CAAO,EACjD,CACJ,sBAAAK,EAAwB,SACxB,yBAAAC,EAA2B,QAAA,EACzBN,EAYJ,MAAO,CACL,QAHc,6CAA6CK,CAAqB,kCAAkCC,CAAwB,6CAI1I,KAAMN,EAAQ,KACd,IAAKI,EACL,oBAAqB,CAAC,QAAQ,IAAI,GAClC,UAAWI,EAAAA,KAAKJ,EAAK,gBAAgB,EACrC,QAAS,IAAM,GAAA,CAEnB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"mantineSourceOfTruth-Ddaxq3m0.js","sources":["../src/harness/mantineSourceOfTruth.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Generates a small, throwaway Storybook project that installs\n * `@recursica/adapter-mantine-v8` as a real npm dependency (not a workspace\n * link) and boots a real Storybook from its published `src/**\\/*.stories.tsx`\n * files, using `@recursica/storybook-template`'s exported factories.\n *\n * This lets any repo — including ones that never checked out the Recursica\n * monorepo — run adapter-tester's visual regression suite against Mantine\n * (Recursica's source-of-truth adapter) as one side of the comparison, while\n * the other side is that repo's own already-running local Storybook.\n *\n * See PROPOSAL-installed-package-harness.md for the verified prototype this\n * is built from, and the three upstream gaps it works around.\n */\n\nexport interface MantineSourceOfTruthHarnessOptions {\n /**\n * Directory the harness project is scaffolded into. Regenerated on every\n * call — add it to your .gitignore rather than committing it.\n */\n dir: string;\n /** First-guess port, shown for `--dry-run` visibility only. The harness's\n * Storybook is never pinned to this — see `HarnessWebServerConfig.port`. */\n port: number;\n /** npm version/range for @recursica/adapter-mantine-v8. Defaults to \"latest\". */\n mantineAdapterVersion?: string;\n /** npm version/range for @recursica/storybook-template. Defaults to \"latest\". */\n storybookTemplateVersion?: string;\n}\n\nexport interface HarnessWebServerConfig {\n command: string;\n /** First-guess port, shown for `--dry-run` visibility only — not\n * authoritative. The real port is whatever this Storybook's own startup\n * banner reports once it's actually running (see portDiscovery.ts), since\n * Storybook silently falls back to an OS-assigned port whenever this one\n * is taken. */\n port: number;\n cwd: string;\n reuseExistingServer: boolean;\n /** File the real, detected port is cached in between runs, so a later\n * `reuseExistingServer` run can find this instance again. */\n cacheFile: string;\n timeout: number;\n}\n\n// Peer/dev ranges pinned to what @recursica/adapter-mantine-v8 and\n// @recursica/storybook-template themselves require, so the harness can't\n// drift onto an incompatible Mantine or Storybook major version.\nconst MANTINE_CORE_RANGE = \"^8.0.0\";\nconst STORYBOOK_RANGE = \"^10.3.3\";\nconst REACT_RANGE = \"^19.0.0\";\n\n// storybook-template's createMainConfig() defaults its addons list to these\n// three but doesn't declare them as peerDependencies (proposal gap 2) — a\n// harness that skips installing any of them gets a silent \"could not\n// resolve addon\" warning at boot, then a hard runtime crash later when Vite\n// pre-bundles preview.tsx's dependency graph. Installed explicitly here.\nconst DEFAULT_ADDON_DEPENDENCIES = {\n \"@storybook/addon-docs\": STORYBOOK_RANGE,\n \"@storybook/addon-a11y\": STORYBOOK_RANGE,\n \"storybook-dark-mode\": \"^5.0.0\",\n};\n\n// adapter-mantine-v8's Introduction.stories.tsx (Version.tsx/OverStyling.tsx)\n// needs react-markdown, but it's a devDependency there — Storybook-only,\n// never bundled into dist — so an external `npm install` of the published\n// package won't pull it in. The harness boots a real Storybook against\n// src/, so it must provide this itself. Installed explicitly here.\nconst WORKAROUND_DEPENDENCIES = {\n \"react-markdown\": \"^10.1.0\",\n};\n\nfunction harnessPackageJson(options: {\n mantineAdapterVersion: string;\n storybookTemplateVersion: string;\n}) {\n return {\n name: \"adapter-tester-mantine-source-of-truth-harness\",\n private: true,\n type: \"module\",\n scripts: {\n // No `-p` pin — Storybook silently falls back to an OS-assigned port\n // whenever its default is taken, so the caller detects the real port\n // from this process's own output rather than trusting a fixed one.\n storybook: `storybook dev`,\n },\n dependencies: {\n \"@recursica/adapter-mantine-v8\": options.mantineAdapterVersion,\n \"@recursica/storybook-template\": options.storybookTemplateVersion,\n \"@recursica/official-release\": \"latest\",\n \"@recursica/adapter-common\": \"latest\",\n \"@mantine/core\": MANTINE_CORE_RANGE,\n \"@mantine/dates\": MANTINE_CORE_RANGE,\n react: REACT_RANGE,\n \"react-dom\": REACT_RANGE,\n storybook: STORYBOOK_RANGE,\n \"@storybook/react-vite\": STORYBOOK_RANGE,\n ...DEFAULT_ADDON_DEPENDENCIES,\n ...WORKAROUND_DEPENDENCIES,\n },\n };\n}\n\nconst MAIN_TS = `import { createMainConfig } from \"@recursica/storybook-template/main\";\n\nconst config = createMainConfig({\n stories: [\n \"../node_modules/@recursica/adapter-mantine-v8/src/**/*.stories.@(js|jsx|mjs|ts|tsx)\",\n ],\n enableCORS: true,\n});\n\n// react-docgen-typescript can't resolve a TS project for a config file living\n// in .storybook/ when the component source it's docgen'ing lives three\n// directories down inside node_modules — it throws \"Cannot read properties\n// of undefined (reading 'fileExists')\", which surfaces as a plain 404 on\n// preview.tsx. Docgen only powers Storybook's Controls/Docs tables, which\n// this harness never renders, so disabling it is a safe workaround (see\n// PROPOSAL-installed-package-harness.md, gap 3).\nconfig.typescript = { ...config.typescript, reactDocgen: false };\n\nexport default config;\n`;\n\nconst PREVIEW_TSX = `import type { Preview } from \"@storybook/react-vite\";\nimport { createPreviewConfig } from \"@recursica/storybook-template/preview\";\nimport { MantineProvider } from \"@mantine/core\";\nimport { Layer } from \"@recursica/adapter-common\";\nimport \"@mantine/core/styles.css\";\nimport \"@mantine/dates/styles.css\";\nimport \"@recursica/adapter-common/style.css\";\nimport \"@recursica/official-release/recursica_variables_scoped.css\";\nimport recursicaTokens from \"@recursica/official-release/recursica_tokens.json\";\nimport recursicaBrand from \"@recursica/official-release/recursica_brand.json\";\nimport recursicaUIKit from \"@recursica/official-release/recursica_ui-kit.json\";\n\nconst basePreview = createPreviewConfig({\n defaultTheme: \"light\",\n recursicaTokensJsonPath: recursicaTokens,\n recursicaBrandJsonPath: recursicaBrand,\n recursicaUIKitJsonPath: recursicaUIKit,\n});\n\n// Mirrors adapter-mantine-v8's own .storybook/preview.tsx decorator (every story defaults to\n// withLayer: true, layer: 0, wrapped with 48px padding) — every real adapter's own preview.tsx\n// applies this same wrapping, so a target adapter's story renders inside the same Layer\n// chrome/padding the source-of-truth side does. Without this, target screenshots come out\n// dramatically smaller/differently-positioned than the source of truth's (no Layer padding,\n// background, or border-radius at all), which alone can blow past the pixel-diff threshold\n// regardless of whether the actual Recursica tokens match — a false positive, not a real\n// component bug. ColorSchemeWrapper (adapter-mantine-v8's dark-mode-toggle sync helper) is\n// intentionally not replicated — it only matters for the interactive dev-mode UI, not automated\n// screenshot diffing, which always runs in a single theme.\nconst preview: Preview = {\n ...basePreview,\n decorators: [\n (Story, context) => {\n const { withLayer = true, layer = 0 } = context.args;\n const content = <Story />;\n return (\n <MantineProvider>\n {withLayer ? (\n <Layer layer={layer as 0 | 1 | 2 | 3} style={{ padding: \"48px\" }}>\n {content}\n </Layer>\n ) : (\n content\n )}\n </MantineProvider>\n );\n },\n ...(basePreview.decorators || []),\n ],\n};\n\nexport default preview;\n`;\n\n/** Writes the harness project's files to `options.dir` without booting it. */\nexport function scaffoldMantineSourceOfTruthHarness(\n options: MantineSourceOfTruthHarnessOptions,\n): string {\n const {\n dir,\n mantineAdapterVersion = \"latest\",\n storybookTemplateVersion = \"latest\",\n } = options;\n\n mkdirSync(join(dir, \".storybook\"), { recursive: true });\n writeFileSync(\n join(dir, \"package.json\"),\n JSON.stringify(\n harnessPackageJson({\n mantineAdapterVersion,\n storybookTemplateVersion,\n }),\n null,\n 2,\n ) + \"\\n\",\n );\n writeFileSync(join(dir, \".storybook/main.ts\"), MAIN_TS);\n writeFileSync(join(dir, \".storybook/preview.tsx\"), PREVIEW_TSX);\n writeFileSync(join(dir, \".gitignore\"), \"node_modules\\n\");\n\n return dir;\n}\n\n/**\n * Scaffolds the harness and returns a Playwright `webServer` entry for it.\n * Spread the result directly into `playwright.config.ts`'s `webServer` array.\n */\nexport function mantineSourceOfTruthWebServer(\n options: MantineSourceOfTruthHarnessOptions,\n): HarnessWebServerConfig {\n const dir = scaffoldMantineSourceOfTruthHarness(options);\n const {\n mantineAdapterVersion = \"latest\",\n storybookTemplateVersion = \"latest\",\n } = options;\n\n // A bare `npm install` is satisfied by a package-lock.json already sitting\n // in `dir` from a prior run and skips re-resolving against the registry\n // entirely — no network call — so a run can silently keep testing against\n // a stale @recursica/adapter-mantine-v8/storybook-template even after a newer\n // version is published. Naming the two version-pinned packages as explicit\n // `pkg@specifier` CLI args instead forces npm to re-check just those two\n // against the registry every run, while the rest of node_modules stays\n // cached.\n const command = `npm install @recursica/adapter-mantine-v8@${mantineAdapterVersion} @recursica/storybook-template@${storybookTemplateVersion} --no-audit --no-fund && npm run storybook`;\n\n return {\n command,\n port: options.port,\n cwd: dir,\n reuseExistingServer: !process.env.CI,\n cacheFile: join(dir, \"last-port.json\"),\n timeout: 180 * 1000,\n };\n}\n"],"names":["MANTINE_CORE_RANGE","STORYBOOK_RANGE","REACT_RANGE","DEFAULT_ADDON_DEPENDENCIES","WORKAROUND_DEPENDENCIES","harnessPackageJson","options","MAIN_TS","PREVIEW_TSX","scaffoldMantineSourceOfTruthHarness","dir","mantineAdapterVersion","storybookTemplateVersion","mkdirSync","join","writeFileSync","mantineSourceOfTruthWebServer"],"mappings":";;AAoDA,MAAMA,IAAqB,UACrBC,IAAkB,WAClBC,IAAc,WAOdC,IAA6B;AAAA,EACjC,yBAAyBF;AAAA,EACzB,yBAAyBA;AAAA,EACzB,uBAAuB;AACzB,GAOMG,IAA0B;AAAA,EAC9B,kBAAkB;AACpB;AAEA,SAASC,EAAmBC,GAGzB;AACD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA;AAAA;AAAA;AAAA,MAIP,WAAW;AAAA,IAAA;AAAA,IAEb,cAAc;AAAA,MACZ,iCAAiCA,EAAQ;AAAA,MACzC,iCAAiCA,EAAQ;AAAA,MACzC,+BAA+B;AAAA,MAC/B,6BAA6B;AAAA,MAC7B,iBAAiBN;AAAA,MACjB,kBAAkBA;AAAA,MAClB,OAAOE;AAAA,MACP,aAAaA;AAAA,MACb,WAAWD;AAAA,MACX,yBAAyBA;AAAA,MACzB,GAAGE;AAAA,MACH,GAAGC;AAAA,IAAA;AAAA,EACL;AAEJ;AAEA,MAAMG,IAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAqBVC,IAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuDb,SAASC,EACdH,GACQ;AACR,QAAM;AAAA,IACJ,KAAAI;AAAA,IACA,uBAAAC,IAAwB;AAAA,IACxB,0BAAAC,IAA2B;AAAA,EAAA,IACzBN;AAEJ,SAAAO,EAAUC,EAAKJ,GAAK,YAAY,GAAG,EAAE,WAAW,IAAM,GACtDK;AAAA,IACED,EAAKJ,GAAK,cAAc;AAAA,IACxB,KAAK;AAAA,MACHL,EAAmB;AAAA,QACjB,uBAAAM;AAAA,QACA,0BAAAC;AAAA,MAAA,CACD;AAAA,MACD;AAAA,MACA;AAAA,IAAA,IACE;AAAA;AAAA,EAAA,GAENG,EAAcD,EAAKJ,GAAK,oBAAoB,GAAGH,CAAO,GACtDQ,EAAcD,EAAKJ,GAAK,wBAAwB,GAAGF,CAAW,GAC9DO,EAAcD,EAAKJ,GAAK,YAAY,GAAG;AAAA,CAAgB,GAEhDA;AACT;AAMO,SAASM,EACdV,GACwB;AACxB,QAAMI,IAAMD,EAAoCH,CAAO,GACjD;AAAA,IACJ,uBAAAK,IAAwB;AAAA,IACxB,0BAAAC,IAA2B;AAAA,EAAA,IACzBN;AAYJ,SAAO;AAAA,IACL,SAHc,6CAA6CK,CAAqB,kCAAkCC,CAAwB;AAAA,IAI1I,MAAMN,EAAQ;AAAA,IACd,KAAKI;AAAA,IACL,qBAAqB,CAAC,QAAQ,IAAI;AAAA,IAClC,WAAWI,EAAKJ,GAAK,gBAAgB;AAAA,IACrC,SAAS,MAAM;AAAA,EAAA;AAEnB;"}