@animus-ui/next-plugin 0.1.0-next.30
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/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +386 -0
- package/dist/loader.d.ts +20 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.mjs +53 -0
- package/dist/plugin.d.ts +48 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/singleton-BZ7W87Ir.mjs +31 -0
- package/dist/singleton.d.ts +13 -0
- package/dist/singleton.d.ts.map +1 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/with-animus.d.ts +33 -0
- package/dist/with-animus.d.ts.map +1 -0
- package/package.json +43 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { a as setManifestJson, i as setAnalysisPromise, o as __require, r as resetAnalysisPromise, t as getAnalysisPromise } from "./singleton-BZ7W87Ir.mjs";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
3
|
+
import { extname, join, relative, resolve } from "path";
|
|
4
|
+
import { createHash } from "crypto";
|
|
5
|
+
import { tmpdir } from "os";
|
|
6
|
+
import { applyPrefix, applyUnitFallback, detectRuntime, execSubprocess, extractSystemFilePackages, resolveGlobalStyles } from "@animus-ui/extract/pipeline";
|
|
7
|
+
//#region src/plugin.ts
|
|
8
|
+
const PLUGIN_NAME = "AnimusWebpackPlugin";
|
|
9
|
+
var AnimusWebpackPlugin = class {
|
|
10
|
+
options;
|
|
11
|
+
rootDir = null;
|
|
12
|
+
configJson = "";
|
|
13
|
+
groupRegistryJson = "";
|
|
14
|
+
themeJson = "";
|
|
15
|
+
variableMapJson = "";
|
|
16
|
+
variableCss = "";
|
|
17
|
+
contextualVarsJson = null;
|
|
18
|
+
globalCss = "";
|
|
19
|
+
systemResolveScript = null;
|
|
20
|
+
fileCache = /* @__PURE__ */ new Map();
|
|
21
|
+
lastCssHash = null;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.options = options;
|
|
24
|
+
}
|
|
25
|
+
initialized = false;
|
|
26
|
+
apply(compiler) {
|
|
27
|
+
compiler.hooks.run.tapPromise(PLUGIN_NAME, async (_compiler) => {
|
|
28
|
+
this.rootDir = _compiler.context;
|
|
29
|
+
const existing = getAnalysisPromise();
|
|
30
|
+
if (existing) {
|
|
31
|
+
await existing;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const promise = this.runFullPipeline();
|
|
35
|
+
setAnalysisPromise(promise);
|
|
36
|
+
await promise;
|
|
37
|
+
});
|
|
38
|
+
compiler.hooks.watchRun.tapPromise(PLUGIN_NAME, async (_compiler) => {
|
|
39
|
+
this.rootDir = _compiler.context;
|
|
40
|
+
if (!this.initialized) {
|
|
41
|
+
const existing = getAnalysisPromise();
|
|
42
|
+
if (existing) {
|
|
43
|
+
await existing;
|
|
44
|
+
this.initialized = true;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const promise = this.runFullPipeline();
|
|
48
|
+
setAnalysisPromise(promise);
|
|
49
|
+
await promise;
|
|
50
|
+
this.initialized = true;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
await this.handleWatchUpdate();
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async handleWatchUpdate() {
|
|
57
|
+
const rootDir = this.rootDir;
|
|
58
|
+
const resolvedSystemPath = resolve(rootDir, this.options.system);
|
|
59
|
+
try {
|
|
60
|
+
const systemSource = readFileSync(resolvedSystemPath, "utf-8");
|
|
61
|
+
const systemRelPath = relative(rootDir, resolvedSystemPath);
|
|
62
|
+
const cached = this.fileCache.get(systemRelPath);
|
|
63
|
+
const currentHash = createHash("md5").update(systemSource).digest("hex");
|
|
64
|
+
if (cached && cached.hash !== currentHash) {
|
|
65
|
+
this.resetForHmr();
|
|
66
|
+
this.initialized = false;
|
|
67
|
+
const promise = this.runFullPipeline();
|
|
68
|
+
setAnalysisPromise(promise);
|
|
69
|
+
await promise;
|
|
70
|
+
this.initialized = true;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
} catch {}
|
|
74
|
+
const excludePatterns = this.options.exclude ?? [
|
|
75
|
+
"node_modules",
|
|
76
|
+
"dist",
|
|
77
|
+
".test.",
|
|
78
|
+
".spec.",
|
|
79
|
+
".next",
|
|
80
|
+
".animus"
|
|
81
|
+
];
|
|
82
|
+
const files = this.discoverFiles(rootDir, rootDir, excludePatterns);
|
|
83
|
+
let hasChanges = false;
|
|
84
|
+
for (const filePath of files) {
|
|
85
|
+
const relPath = relative(rootDir, filePath);
|
|
86
|
+
const cached = this.fileCache.get(relPath);
|
|
87
|
+
const source = readFileSync(filePath, "utf-8");
|
|
88
|
+
const hash = createHash("md5").update(source).digest("hex");
|
|
89
|
+
if (!cached || cached.hash !== hash) {
|
|
90
|
+
hasChanges = true;
|
|
91
|
+
this.fileCache.set(relPath, {
|
|
92
|
+
hash,
|
|
93
|
+
source
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (hasChanges) {
|
|
98
|
+
resetAnalysisPromise();
|
|
99
|
+
const promise = this.runFullPipeline();
|
|
100
|
+
setAnalysisPromise(promise);
|
|
101
|
+
await promise;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async runFullPipeline() {
|
|
105
|
+
const rootDir = this.rootDir;
|
|
106
|
+
const resolvedSystemPath = resolve(rootDir, this.options.system);
|
|
107
|
+
this.loadSystem(rootDir, resolvedSystemPath);
|
|
108
|
+
const excludePatterns = this.options.exclude ?? [
|
|
109
|
+
"node_modules",
|
|
110
|
+
"dist",
|
|
111
|
+
".test.",
|
|
112
|
+
".spec.",
|
|
113
|
+
".next",
|
|
114
|
+
".animus"
|
|
115
|
+
];
|
|
116
|
+
const files = this.discoverFiles(rootDir, rootDir, excludePatterns);
|
|
117
|
+
const fileEntries = [];
|
|
118
|
+
for (const filePath of files) {
|
|
119
|
+
const source = readFileSync(filePath, "utf-8");
|
|
120
|
+
const relPath = relative(rootDir, filePath);
|
|
121
|
+
const hash = createHash("md5").update(source).digest("hex");
|
|
122
|
+
this.fileCache.set(relPath, {
|
|
123
|
+
hash,
|
|
124
|
+
source
|
|
125
|
+
});
|
|
126
|
+
fileEntries.push({
|
|
127
|
+
path: relPath,
|
|
128
|
+
source,
|
|
129
|
+
hash
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const packageNames = extractSystemFilePackages(resolvedSystemPath);
|
|
133
|
+
const packageMap = this.resolvePackagesByName(rootDir, packageNames);
|
|
134
|
+
const { analyzeProject } = __require("@animus-ui/extract");
|
|
135
|
+
const animusDirPath = join(rootDir, ".animus");
|
|
136
|
+
const emitterConfig = JSON.stringify({
|
|
137
|
+
runtime_import: "@animus-ui/system/runtime",
|
|
138
|
+
css_module_id: ".animus/styles.css",
|
|
139
|
+
system_props_module_id: join(animusDirPath, "system-props.js")
|
|
140
|
+
});
|
|
141
|
+
const manifestJson = analyzeProject(JSON.stringify(fileEntries), this.themeJson, this.variableMapJson, this.contextualVarsJson || null, this.configJson, this.groupRegistryJson, JSON.stringify(packageMap), false, this.options.prefix || null, emitterConfig);
|
|
142
|
+
const manifest = JSON.parse(manifestJson);
|
|
143
|
+
let componentCss = manifest?.css || "";
|
|
144
|
+
if (this.systemResolveScript && componentCss.includes("__TRANSFORM__")) componentCss = this.resolveTransforms(rootDir, componentCss);
|
|
145
|
+
componentCss = applyUnitFallback(componentCss);
|
|
146
|
+
const parts = [];
|
|
147
|
+
if (this.variableCss) parts.push(this.variableCss);
|
|
148
|
+
if (this.globalCss) parts.push(this.globalCss);
|
|
149
|
+
if (componentCss) parts.push(componentCss);
|
|
150
|
+
const fullCss = parts.join("\n\n");
|
|
151
|
+
const cssHash = createHash("md5").update(fullCss).digest("hex");
|
|
152
|
+
if (cssHash !== this.lastCssHash) {
|
|
153
|
+
const animusDir = join(rootDir, ".animus");
|
|
154
|
+
if (!existsSync(animusDir)) mkdirSync(animusDir, { recursive: true });
|
|
155
|
+
writeFileSync(join(animusDir, "styles.css"), fullCss);
|
|
156
|
+
this.lastCssHash = cssHash;
|
|
157
|
+
}
|
|
158
|
+
const systemPropMap = JSON.stringify(manifest?.system_prop_map ?? {});
|
|
159
|
+
const dynamicProps = manifest?.dynamic_props ?? {};
|
|
160
|
+
const dynamicPropConfig = {};
|
|
161
|
+
for (const [propName, meta] of Object.entries(dynamicProps)) dynamicPropConfig[propName] = {
|
|
162
|
+
varName: meta.var_name,
|
|
163
|
+
slotClass: meta.slot_class,
|
|
164
|
+
...meta.transform_name ? { transformName: meta.transform_name } : {},
|
|
165
|
+
...meta.scale_values && Object.keys(meta.scale_values).length > 0 ? { scaleValues: meta.scale_values } : {}
|
|
166
|
+
};
|
|
167
|
+
let transformsSource = "{}";
|
|
168
|
+
if (this.systemResolveScript) try {
|
|
169
|
+
const resolvedSystemPath = resolve(rootDir, this.options.system);
|
|
170
|
+
const tmpOut = join(tmpdir(), `animus-transforms-${Date.now()}.json`);
|
|
171
|
+
execSubprocess(`const m = require(${JSON.stringify(resolvedSystemPath)});\nconst ds = m.ds || m.default || m.system;\nconst cfg = ds.toConfig();\nconst out = {};\nfor (const [name, fn] of Object.entries(cfg.transforms || {})) {\n out[name] = fn.toString();\n}\nrequire('fs').writeFileSync(${JSON.stringify(tmpOut)}, JSON.stringify(out));\n`, rootDir);
|
|
172
|
+
const fnStrings = JSON.parse(readFileSync(tmpOut, "utf-8"));
|
|
173
|
+
try {
|
|
174
|
+
__require("fs").unlinkSync(tmpOut);
|
|
175
|
+
} catch {}
|
|
176
|
+
transformsSource = `{\n${Object.entries(fnStrings).map(([name, src]) => ` ${JSON.stringify(name)}: ${src}`).join(",\n")}\n}`;
|
|
177
|
+
} catch {}
|
|
178
|
+
const animusDir = join(rootDir, ".animus");
|
|
179
|
+
if (!existsSync(animusDir)) mkdirSync(animusDir, { recursive: true });
|
|
180
|
+
writeFileSync(join(animusDir, "system-props.js"), `export const systemPropMap = ${systemPropMap};\nexport const systemPropGroups = ${this.groupRegistryJson};\nexport const dynamicPropConfig = ${JSON.stringify(dynamicPropConfig)};\nexport const transforms = ${transformsSource};\n`);
|
|
181
|
+
setManifestJson(manifestJson);
|
|
182
|
+
}
|
|
183
|
+
loadSystem(rootDir, systemPath) {
|
|
184
|
+
const tmpOut = join(tmpdir(), `animus-system-${Date.now()}.json`);
|
|
185
|
+
execSubprocess(`const m = require(${JSON.stringify(systemPath)});\nconst ds = m.ds || m.default || m.system;\nif (!ds || !ds.toConfig) { throw new Error('Module does not export a SystemInstance with .serialize()'); }\nconst cfg = ds.toConfig();\nconst tokens = m.tokens || m.theme || null;\nconst serialized = tokens && typeof tokens.serialize === 'function' ? tokens.serialize() : null;\nconst globalStyleBlocks = {};\nfor (const [key, val] of Object.entries(m)) {\n if (val && typeof val === 'object' && val.__brand === 'GlobalStyleBlock') {\n globalStyleBlocks[key] = val.styles;\n }\n}\nrequire('fs').writeFileSync(${JSON.stringify(tmpOut)}, JSON.stringify({\n propConfig: cfg.propConfig,\n groupRegistry: cfg.groupRegistry,\n serialized: serialized,\n transformNames: Object.keys(cfg.transforms || {}),\n globalStyleBlocks: Object.keys(globalStyleBlocks).length > 0 ? globalStyleBlocks : null\n}));\n`, rootDir);
|
|
186
|
+
const result = readFileSync(tmpOut, "utf-8");
|
|
187
|
+
try {
|
|
188
|
+
__require("fs").unlinkSync(tmpOut);
|
|
189
|
+
} catch {}
|
|
190
|
+
const parsed = JSON.parse(result);
|
|
191
|
+
this.configJson = parsed.propConfig;
|
|
192
|
+
this.groupRegistryJson = parsed.groupRegistry;
|
|
193
|
+
if (parsed.serialized) {
|
|
194
|
+
this.themeJson = parsed.serialized.scalesJson;
|
|
195
|
+
this.variableMapJson = parsed.serialized.variableMapJson;
|
|
196
|
+
this.variableCss = parsed.serialized.variableCss;
|
|
197
|
+
this.contextualVarsJson = parsed.serialized.contextualVarsJson;
|
|
198
|
+
if (this.options.prefix) {
|
|
199
|
+
const prefixed = applyPrefix(this.options.prefix, this.variableMapJson, this.variableCss);
|
|
200
|
+
this.variableMapJson = prefixed.variableMapJson;
|
|
201
|
+
this.variableCss = prefixed.variableCss;
|
|
202
|
+
}
|
|
203
|
+
} else throw new Error("[animus-extract] Theme must be built with createTheme().build(). No .serialize() method found on tokens export.");
|
|
204
|
+
if (parsed.globalStyleBlocks) {
|
|
205
|
+
if (Object.keys(parsed.globalStyleBlocks).length > 0) try {
|
|
206
|
+
const flat = JSON.parse(this.themeJson);
|
|
207
|
+
const propConfig = JSON.parse(this.configJson);
|
|
208
|
+
const variableMap = {};
|
|
209
|
+
for (const [tokenPath, value] of Object.entries(flat)) if (typeof value === "string" && value.startsWith("var(") && value.endsWith(")")) variableMap[tokenPath] = value.slice(4, -1);
|
|
210
|
+
const gsResult = resolveGlobalStyles(parsed.globalStyleBlocks, propConfig, flat, variableMap, {});
|
|
211
|
+
const parts = Object.values(gsResult).filter(Boolean);
|
|
212
|
+
if (parts.length > 0) this.globalCss = `@layer global {\n${parts.join("\n\n")}\n}`;
|
|
213
|
+
} catch (e) {
|
|
214
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
215
|
+
if (this.options.strict) throw new Error(`[animus-extract] Global styles resolution failed: ${msg}`);
|
|
216
|
+
console.warn("[animus-extract] Global styles resolution failed:", msg);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (parsed.transformNames && parsed.transformNames.length > 0) {
|
|
220
|
+
const tmpResolve = join(tmpdir(), `animus-transforms-resolve-${Date.now()}.js`);
|
|
221
|
+
writeFileSync(tmpResolve, `const m = require(${JSON.stringify(systemPath)});\nconst ds = m.ds || m.default || m.system;\nconst cfg = ds.toConfig();\nconst css = require('fs').readFileSync(process.argv[2], 'utf-8');\nconst resolved = css.replace(/__TRANSFORM__(\\w+)__(.+?)__/g, (_, name, rawValue) => {\n const fn = cfg.transforms[name];\n if (!fn) return rawValue;\n const value = rawValue !== '' && !isNaN(Number(rawValue)) ? Number(rawValue) : rawValue;\n const result = fn(value);\n return typeof result === 'object' ? JSON.stringify(result) : String(result);\n});\nrequire('fs').writeFileSync(process.argv[3], resolved);\n`);
|
|
222
|
+
this.systemResolveScript = tmpResolve;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
resolveTransforms(rootDir, css) {
|
|
226
|
+
const { execSync } = __require("child_process");
|
|
227
|
+
const ts = Date.now();
|
|
228
|
+
const tmpIn = join(tmpdir(), `animus-css-${ts}.css`);
|
|
229
|
+
const tmpOut = join(tmpdir(), `animus-css-${ts}.out.css`);
|
|
230
|
+
writeFileSync(tmpIn, css);
|
|
231
|
+
execSync(`${detectRuntime()} run "${this.systemResolveScript}" "${tmpIn}" "${tmpOut}"`, {
|
|
232
|
+
cwd: rootDir,
|
|
233
|
+
encoding: "utf-8"
|
|
234
|
+
});
|
|
235
|
+
const resolved = readFileSync(tmpOut, "utf-8");
|
|
236
|
+
try {
|
|
237
|
+
__require("fs").unlinkSync(tmpIn);
|
|
238
|
+
__require("fs").unlinkSync(tmpOut);
|
|
239
|
+
} catch {}
|
|
240
|
+
return resolved;
|
|
241
|
+
}
|
|
242
|
+
discoverFiles(dir, rootDir, excludePatterns) {
|
|
243
|
+
const results = [];
|
|
244
|
+
const extensions = new Set([
|
|
245
|
+
".ts",
|
|
246
|
+
".tsx",
|
|
247
|
+
".js",
|
|
248
|
+
".jsx"
|
|
249
|
+
]);
|
|
250
|
+
const walk = (currentDir) => {
|
|
251
|
+
let entries;
|
|
252
|
+
try {
|
|
253
|
+
entries = readdirSync(currentDir);
|
|
254
|
+
} catch {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
for (const entry of entries) {
|
|
258
|
+
const fullPath = join(currentDir, entry);
|
|
259
|
+
const relPath = relative(rootDir, fullPath);
|
|
260
|
+
if (excludePatterns.some((p) => relPath.includes(p))) continue;
|
|
261
|
+
let stat;
|
|
262
|
+
try {
|
|
263
|
+
stat = statSync(fullPath);
|
|
264
|
+
} catch {
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
if (stat.isDirectory()) walk(fullPath);
|
|
268
|
+
else if (extensions.has(extname(entry))) results.push(fullPath);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
walk(dir);
|
|
272
|
+
return results;
|
|
273
|
+
}
|
|
274
|
+
resolvePackagesByName(rootDir, names) {
|
|
275
|
+
if (names.length === 0) return {};
|
|
276
|
+
const nameSet = new Set(names);
|
|
277
|
+
const packageMap = {};
|
|
278
|
+
try {
|
|
279
|
+
const workspaces = JSON.parse(readFileSync(join(rootDir, "package.json"), "utf-8")).workspaces || [];
|
|
280
|
+
for (const ws of workspaces) {
|
|
281
|
+
const wsDir = resolve(rootDir, ws);
|
|
282
|
+
if (!existsSync(wsDir)) continue;
|
|
283
|
+
try {
|
|
284
|
+
const pkg = JSON.parse(readFileSync(join(wsDir, "package.json"), "utf-8"));
|
|
285
|
+
const name = pkg.name || "";
|
|
286
|
+
if (nameSet.has(name)) {
|
|
287
|
+
const entryPath = resolve(wsDir, pkg.main || pkg.module || "index.ts");
|
|
288
|
+
if (existsSync(entryPath)) packageMap[name] = relative(rootDir, entryPath);
|
|
289
|
+
}
|
|
290
|
+
} catch {}
|
|
291
|
+
}
|
|
292
|
+
} catch {}
|
|
293
|
+
return packageMap;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Reset analysis state for HMR geological reset.
|
|
297
|
+
*/
|
|
298
|
+
resetForHmr() {
|
|
299
|
+
resetAnalysisPromise();
|
|
300
|
+
this.lastCssHash = null;
|
|
301
|
+
try {
|
|
302
|
+
const { clearAnalysisCache } = __require("@animus-ui/extract");
|
|
303
|
+
clearAnalysisCache();
|
|
304
|
+
} catch {}
|
|
305
|
+
}
|
|
306
|
+
/** Expose file cache for HMR change detection */
|
|
307
|
+
getFileCache() {
|
|
308
|
+
return this.fileCache;
|
|
309
|
+
}
|
|
310
|
+
/** Expose options for the loader */
|
|
311
|
+
getOptions() {
|
|
312
|
+
return this.options;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
//#endregion
|
|
316
|
+
//#region src/with-animus.ts
|
|
317
|
+
let warnedGitignore = false;
|
|
318
|
+
/**
|
|
319
|
+
* Wrap a Next.js config to enable Animus static CSS extraction.
|
|
320
|
+
*
|
|
321
|
+
* ```ts
|
|
322
|
+
* // next.config.ts
|
|
323
|
+
* import { withAnimus } from '@animus-ui/next-plugin';
|
|
324
|
+
* export default withAnimus({ system: './src/ds.ts' })({});
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
function withAnimus(options) {
|
|
328
|
+
if (!options.system) throw new Error("[animus-extract] Missing required option `system`. Provide the path to your SystemInstance module: withAnimus({ system: \"./src/ds.ts\" })");
|
|
329
|
+
return (nextConfig) => {
|
|
330
|
+
const existingWebpack = nextConfig.webpack;
|
|
331
|
+
return {
|
|
332
|
+
...nextConfig,
|
|
333
|
+
webpack(config, context) {
|
|
334
|
+
const rootDir = process.cwd();
|
|
335
|
+
const animusDir = join(rootDir, ".animus");
|
|
336
|
+
if (!existsSync(animusDir)) mkdirSync(animusDir, { recursive: true });
|
|
337
|
+
if (!warnedGitignore) {
|
|
338
|
+
warnedGitignore = true;
|
|
339
|
+
try {
|
|
340
|
+
const gitignorePath = join(rootDir, ".gitignore");
|
|
341
|
+
if (existsSync(gitignorePath)) {
|
|
342
|
+
if (!readFileSync(gitignorePath, "utf-8").includes(".animus")) console.warn("[animus-extract] Add `.animus/` to your .gitignore — it contains generated build artifacts.");
|
|
343
|
+
}
|
|
344
|
+
} catch {}
|
|
345
|
+
}
|
|
346
|
+
const plugin = new AnimusWebpackPlugin({
|
|
347
|
+
system: options.system,
|
|
348
|
+
exclude: options.exclude,
|
|
349
|
+
strict: options.strict,
|
|
350
|
+
verbose: options.verbose,
|
|
351
|
+
prefix: options.prefix
|
|
352
|
+
});
|
|
353
|
+
config.plugins = config.plugins || [];
|
|
354
|
+
config.plugins.push(plugin);
|
|
355
|
+
config.resolve = config.resolve || {};
|
|
356
|
+
config.resolve.alias = config.resolve.alias || {};
|
|
357
|
+
config.resolve.alias[".animus/styles.css"] = join(rootDir, ".animus", "styles.css");
|
|
358
|
+
const systemPropsPath = join(rootDir, ".animus", "system-props.js");
|
|
359
|
+
config.plugins.push({ apply(compiler) {
|
|
360
|
+
compiler.hooks.normalModuleFactory.tap("AnimusVirtualResolve", (nmf) => {
|
|
361
|
+
nmf.hooks.beforeResolve.tap("AnimusVirtualResolve", (resolveData) => {
|
|
362
|
+
if (resolveData.request === "virtual:animus/system-props") resolveData.request = systemPropsPath;
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
} });
|
|
366
|
+
const loaderPath = resolve(__dirname, "loader.mjs");
|
|
367
|
+
const actualLoaderPath = existsSync(loaderPath) ? loaderPath : resolve(__dirname, "loader.ts");
|
|
368
|
+
config.module = config.module || {};
|
|
369
|
+
config.module.rules = config.module.rules || [];
|
|
370
|
+
config.module.rules.push({
|
|
371
|
+
test: /\.(ts|tsx|js|jsx)$/,
|
|
372
|
+
exclude: /node_modules/,
|
|
373
|
+
enforce: "pre",
|
|
374
|
+
use: [{
|
|
375
|
+
loader: actualLoaderPath,
|
|
376
|
+
options: { strict: options.strict }
|
|
377
|
+
}]
|
|
378
|
+
});
|
|
379
|
+
if (typeof existingWebpack === "function") return existingWebpack(config, context);
|
|
380
|
+
return config;
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
//#endregion
|
|
386
|
+
export { withAnimus };
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
type LoaderContext = {
|
|
2
|
+
resourcePath: string;
|
|
3
|
+
rootContext: string;
|
|
4
|
+
getOptions: () => {
|
|
5
|
+
strict?: boolean;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Webpack loader for Animus source transformation.
|
|
10
|
+
* Runs with enforce: 'pre' to see original source before Babel/SWC.
|
|
11
|
+
* Replaces builder chains with createComponent() calls using the pre-built manifest.
|
|
12
|
+
*
|
|
13
|
+
* CSS handling: the Rust emitter injects `import '.animus/styles.css'` into every
|
|
14
|
+
* file with extracted components. Without intervention, webpack duplicates the full
|
|
15
|
+
* stylesheet into every route chunk. This loader strips those imports and re-injects
|
|
16
|
+
* a single CSS import in the root layout/app file, ensuring one copy for the whole app.
|
|
17
|
+
*/
|
|
18
|
+
export default function animusLoader(this: LoaderContext, source: string): string;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAIA,KAAK,aAAa,GAAG;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACxC,CAAC;AAoBF;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,MAAM,GACb,MAAM,CAwCR"}
|
package/dist/loader.mjs
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { n as getManifestJson, o as __require } from "./singleton-BZ7W87Ir.mjs";
|
|
2
|
+
import { relative } from "path";
|
|
3
|
+
//#region src/loader.ts
|
|
4
|
+
/**
|
|
5
|
+
* Regex matching CSS import lines injected by the Rust emitter.
|
|
6
|
+
* Catches both the alias form (`import '.animus/styles.css'`) and
|
|
7
|
+
* relative forms (`import '../.animus/styles.css'`).
|
|
8
|
+
*/
|
|
9
|
+
const CSS_IMPORT_RE = /import\s+['"][^'"]*\.animus\/styles\.css['"];\n?/g;
|
|
10
|
+
/**
|
|
11
|
+
* Root entry file patterns. CSS is imported ONLY here to prevent
|
|
12
|
+
* per-chunk duplication in Next.js builds.
|
|
13
|
+
*
|
|
14
|
+
* - App Router: `app/layout.tsx` (root layout wraps all routes)
|
|
15
|
+
* - Pages Router: `pages/_app.tsx` (custom App wraps all pages)
|
|
16
|
+
*
|
|
17
|
+
* The `(src\/)?` prefix handles projects that use a `src/` directory.
|
|
18
|
+
*/
|
|
19
|
+
const ROOT_ENTRY_RE = /^(src\/)?(?:app\/layout|pages\/_app)\.[tj]sx?$/;
|
|
20
|
+
/**
|
|
21
|
+
* Webpack loader for Animus source transformation.
|
|
22
|
+
* Runs with enforce: 'pre' to see original source before Babel/SWC.
|
|
23
|
+
* Replaces builder chains with createComponent() calls using the pre-built manifest.
|
|
24
|
+
*
|
|
25
|
+
* CSS handling: the Rust emitter injects `import '.animus/styles.css'` into every
|
|
26
|
+
* file with extracted components. Without intervention, webpack duplicates the full
|
|
27
|
+
* stylesheet into every route chunk. This loader strips those imports and re-injects
|
|
28
|
+
* a single CSS import in the root layout/app file, ensuring one copy for the whole app.
|
|
29
|
+
*/
|
|
30
|
+
function animusLoader(source) {
|
|
31
|
+
const manifestJson = getManifestJson();
|
|
32
|
+
if (!manifestJson) return source;
|
|
33
|
+
const filename = relative(this.rootContext, this.resourcePath);
|
|
34
|
+
const isRootEntry = ROOT_ENTRY_RE.test(filename);
|
|
35
|
+
try {
|
|
36
|
+
const { transformFile } = __require("@animus-ui/extract");
|
|
37
|
+
const result = transformFile(source, filename, manifestJson);
|
|
38
|
+
let code = result.hasComponents ? result.code : source;
|
|
39
|
+
code = code.replace(CSS_IMPORT_RE, "");
|
|
40
|
+
if (isRootEntry && !code.includes(".animus/styles.css")) if (code.startsWith("'use client'") || code.startsWith("\"use client\"")) {
|
|
41
|
+
const nl = code.indexOf("\n");
|
|
42
|
+
code = `${code.slice(0, nl + 1)}import '.animus/styles.css';\n${code.slice(nl + 1)}`;
|
|
43
|
+
} else code = `import '.animus/styles.css';\n${code}`;
|
|
44
|
+
return code;
|
|
45
|
+
} catch (e) {
|
|
46
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
47
|
+
if ((this.getOptions?.() ?? {}).strict) throw new Error(`[animus-extract] Transform failed for ${filename}: ${msg}`);
|
|
48
|
+
console.warn(`[animus-extract] Transform failed for ${filename}:`, msg);
|
|
49
|
+
return source;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { animusLoader as default };
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { AnimusNextOptions } from './types';
|
|
2
|
+
type Compiler = {
|
|
3
|
+
hooks: {
|
|
4
|
+
run: {
|
|
5
|
+
tapPromise: (name: string, fn: (c: Compiler) => Promise<void>) => void;
|
|
6
|
+
};
|
|
7
|
+
watchRun: {
|
|
8
|
+
tapPromise: (name: string, fn: (c: Compiler) => Promise<void>) => void;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
context: string;
|
|
12
|
+
};
|
|
13
|
+
export declare class AnimusWebpackPlugin {
|
|
14
|
+
private options;
|
|
15
|
+
private rootDir;
|
|
16
|
+
private configJson;
|
|
17
|
+
private groupRegistryJson;
|
|
18
|
+
private themeJson;
|
|
19
|
+
private variableMapJson;
|
|
20
|
+
private variableCss;
|
|
21
|
+
private contextualVarsJson;
|
|
22
|
+
private globalCss;
|
|
23
|
+
private systemResolveScript;
|
|
24
|
+
private fileCache;
|
|
25
|
+
private lastCssHash;
|
|
26
|
+
constructor(options: AnimusNextOptions);
|
|
27
|
+
private initialized;
|
|
28
|
+
apply(compiler: Compiler): void;
|
|
29
|
+
private handleWatchUpdate;
|
|
30
|
+
private runFullPipeline;
|
|
31
|
+
private loadSystem;
|
|
32
|
+
private resolveTransforms;
|
|
33
|
+
private discoverFiles;
|
|
34
|
+
private resolvePackagesByName;
|
|
35
|
+
/**
|
|
36
|
+
* Reset analysis state for HMR geological reset.
|
|
37
|
+
*/
|
|
38
|
+
resetForHmr(): void;
|
|
39
|
+
/** Expose file cache for HMR change detection */
|
|
40
|
+
getFileCache(): Map<string, {
|
|
41
|
+
hash: string;
|
|
42
|
+
source: string;
|
|
43
|
+
}>;
|
|
44
|
+
/** Expose options for the loader */
|
|
45
|
+
getOptions(): AnimusNextOptions;
|
|
46
|
+
}
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,KAAK,QAAQ,GAAG;IACd,KAAK,EAAE;QACL,GAAG,EAAE;YACH,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;SACxE,CAAC;QACF,QAAQ,EAAE;YACR,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;SACxE,CAAC;KACH,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,OAAO,CAAuB;IAGtC,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,mBAAmB,CAAuB;IAGlD,OAAO,CAAC,SAAS,CAAuD;IACxE,OAAO,CAAC,WAAW,CAAuB;gBAE9B,OAAO,EAAE,iBAAiB;IAItC,OAAO,CAAC,WAAW,CAAS;IAE5B,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;YA2CjB,iBAAiB;YAwDjB,eAAe;IAiJ7B,OAAO,CAAC,UAAU;IAiIlB,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,aAAa;IAyCrB,OAAO,CAAC,qBAAqB;IAuC7B;;OAEG;IACH,WAAW,IAAI,IAAI;IASnB,iDAAiD;IACjD,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAI7D,oCAAoC;IACpC,UAAU,IAAI,iBAAiB;CAGhC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/singleton.ts
|
|
6
|
+
/**
|
|
7
|
+
* Module-scope singleton for sharing analysis state between the webpack plugin and loader.
|
|
8
|
+
*
|
|
9
|
+
* Uses globalThis to survive the ESM/CJS module boundary: the plugin is loaded via ESM
|
|
10
|
+
* (next.config.ts import) while the loader is loaded by webpack via require(). Without
|
|
11
|
+
* globalThis, each module system gets its own singleton instance.
|
|
12
|
+
*/
|
|
13
|
+
const MANIFEST_KEY = "__animus_manifest_json__";
|
|
14
|
+
const PROMISE_KEY = "__animus_analysis_promise__";
|
|
15
|
+
function getManifestJson() {
|
|
16
|
+
return globalThis[MANIFEST_KEY];
|
|
17
|
+
}
|
|
18
|
+
function setManifestJson(json) {
|
|
19
|
+
globalThis[MANIFEST_KEY] = json;
|
|
20
|
+
}
|
|
21
|
+
function getAnalysisPromise() {
|
|
22
|
+
return globalThis[PROMISE_KEY];
|
|
23
|
+
}
|
|
24
|
+
function setAnalysisPromise(promise) {
|
|
25
|
+
globalThis[PROMISE_KEY] = promise;
|
|
26
|
+
}
|
|
27
|
+
function resetAnalysisPromise() {
|
|
28
|
+
globalThis[PROMISE_KEY] = null;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { setManifestJson as a, setAnalysisPromise as i, getManifestJson as n, __require as o, resetAnalysisPromise as r, getAnalysisPromise as t };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module-scope singleton for sharing analysis state between the webpack plugin and loader.
|
|
3
|
+
*
|
|
4
|
+
* Uses globalThis to survive the ESM/CJS module boundary: the plugin is loaded via ESM
|
|
5
|
+
* (next.config.ts import) while the loader is loaded by webpack via require(). Without
|
|
6
|
+
* globalThis, each module system gets its own singleton instance.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getManifestJson(): string | null;
|
|
9
|
+
export declare function setManifestJson(json: string): void;
|
|
10
|
+
export declare function getAnalysisPromise(): Promise<void> | null;
|
|
11
|
+
export declare function setAnalysisPromise(promise: Promise<void>): void;
|
|
12
|
+
export declare function resetAnalysisPromise(): void;
|
|
13
|
+
//# sourceMappingURL=singleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singleton.d.ts","sourceRoot":"","sources":["../src/singleton.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAIzD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAE/D;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface AnimusNextOptions {
|
|
2
|
+
/** Path to a module exporting a SystemInstance from `@animus-ui/system`. */
|
|
3
|
+
system: string;
|
|
4
|
+
/** Glob patterns to exclude from analysis. */
|
|
5
|
+
exclude?: string[];
|
|
6
|
+
/** When true, extraction failures throw instead of warning. */
|
|
7
|
+
strict?: boolean;
|
|
8
|
+
/** Enable verbose logging. */
|
|
9
|
+
verbose?: boolean;
|
|
10
|
+
/** Namespace prefix for CSS variables and class names. */
|
|
11
|
+
prefix?: string;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { AnimusNextOptions } from './types';
|
|
2
|
+
type WebpackConfig = {
|
|
3
|
+
plugins?: unknown[];
|
|
4
|
+
resolve?: {
|
|
5
|
+
alias?: Record<string, string>;
|
|
6
|
+
};
|
|
7
|
+
module?: {
|
|
8
|
+
rules?: Array<{
|
|
9
|
+
test?: RegExp;
|
|
10
|
+
exclude?: RegExp;
|
|
11
|
+
enforce?: string;
|
|
12
|
+
use?: Array<{
|
|
13
|
+
loader: string;
|
|
14
|
+
options?: Record<string, unknown>;
|
|
15
|
+
}>;
|
|
16
|
+
}>;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
type NextConfig = Record<string, unknown> & {
|
|
20
|
+
webpack?: (config: WebpackConfig, context: Record<string, unknown>) => WebpackConfig;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Wrap a Next.js config to enable Animus static CSS extraction.
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* // next.config.ts
|
|
27
|
+
* import { withAnimus } from '@animus-ui/next-plugin';
|
|
28
|
+
* export default withAnimus({ system: './src/ds.ts' })({});
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function withAnimus(options: AnimusNextOptions): (nextConfig: NextConfig) => NextConfig;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=with-animus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-animus.d.ts","sourceRoot":"","sources":["../src/with-animus.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,KAAK,aAAa,GAAG;IACnB,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAChC,CAAC;IACF,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,KAAK,CAAC;YACZ,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,GAAG,CAAC,EAAE,KAAK,CAAC;gBAAE,MAAM,EAAE,MAAM,CAAC;gBAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;aAAE,CAAC,CAAC;SACpE,CAAC,CAAC;KACJ,CAAC;CACH,CAAC;AAEF,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAC1C,OAAO,CAAC,EAAE,CACR,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,aAAa,CAAC;CACpB,CAAC;AAIF;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,iBAAiB,GACzB,CAAC,UAAU,EAAE,UAAU,KAAK,UAAU,CAkIxC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@animus-ui/next-plugin",
|
|
3
|
+
"version": "0.1.0-next.30",
|
|
4
|
+
"description": "Animus static CSS extraction for Next.js (webpack)",
|
|
5
|
+
"author": "codecaaron <airrobb@gmail.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./dist/index.mjs",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"default": "./dist/index.mjs"
|
|
15
|
+
},
|
|
16
|
+
"./loader": {
|
|
17
|
+
"types": "./dist/loader.d.ts",
|
|
18
|
+
"import": "./dist/loader.mjs",
|
|
19
|
+
"default": "./dist/loader.mjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/codecaaron/animus"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsdown && tsc -p tsconfig.build.json",
|
|
34
|
+
"compile": "tsc --noEmit"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"next": ">=14.0.0",
|
|
38
|
+
"webpack": ">=5.0.0"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@animus-ui/extract": "0.1.0-next.30"
|
|
42
|
+
}
|
|
43
|
+
}
|