@airframeui/build 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,302 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createRequire } from 'node:module';
4
+ import { getFlag, hasFlag } from './theme-cli.js';
5
+ function resolveFromCwd(cwd, specifier) {
6
+ if (cwd) {
7
+ try {
8
+ return createRequire(path.join(cwd, 'package.json')).resolve(specifier);
9
+ }
10
+ catch {
11
+ // fall through to this package
12
+ }
13
+ }
14
+ try {
15
+ return createRequire(import.meta.url).resolve(specifier);
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ /**
22
+ * Prefer the project's `@airframeui/core/catalog`, then this package's core
23
+ * (same resolve order as the ESLint plugin).
24
+ */
25
+ export function loadCoreCatalog(cwd) {
26
+ const file = resolveFromCwd(cwd, '@airframeui/core/catalog');
27
+ if (!file)
28
+ return null;
29
+ try {
30
+ const catalog = JSON.parse(fs.readFileSync(file, 'utf8'));
31
+ if (!Array.isArray(catalog.components))
32
+ return null;
33
+ return catalog;
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ }
39
+ function tickList(names) {
40
+ return names.map((name) => `\`${name}\``).join(', ');
41
+ }
42
+ function catalogSummary(catalog) {
43
+ const layouts = (catalog?.layoutRecipes ?? [])
44
+ .map((recipe) => recipe.baseClass)
45
+ .filter(Boolean);
46
+ const components = catalog?.components ?? [];
47
+ const examples = ['button', 'card', 'field']
48
+ .map((name) => components.find((component) => component.name === name)?.baseClass)
49
+ .filter((name) => Boolean(name));
50
+ const formControls = components
51
+ .filter((component) => /already width:\s*100%/i.test(`${component.description ?? ''} ${component.note ?? ''}`))
52
+ .map((component) => component.baseClass);
53
+ const naming = catalog?.classNaming;
54
+ const namingRules = naming?.rules && naming.rules.length > 0
55
+ ? naming.rules.join('; ')
56
+ : 'Modifiers use `af-is-*`; BEM parts use `__`; responsive uses `@`';
57
+ const responsiveExample = catalog?.responsive?.example ?? 'af-grid-2@md';
58
+ const buttonNote = components.find((component) => component.name === 'button')?.note?.trim() ??
59
+ 'Stretch shrink-to-content patterns with `af-w-full`. There is no `af-is-block`, `af-is-full`, or `af-btn-block`.';
60
+ return {
61
+ layoutClasses: layouts.length > 0 ? tickList(layouts) : '`af-stack`, `af-inline`, `af-grid`',
62
+ examplePatterns: examples.length > 0 ? tickList(examples) : '`af-btn`, `af-card`, `af-field`',
63
+ patternCount: typeof catalog?.meta?.patternCount === 'number' ? String(catalog.meta.patternCount) : 'the',
64
+ namingRules,
65
+ responsiveExample,
66
+ formControls: formControls.length > 0
67
+ ? tickList(formControls)
68
+ : '`af-input`, `af-textarea`, `af-select`, `af-range`',
69
+ buttonNote,
70
+ };
71
+ }
72
+ export const AGENT_MARKER_START = '<!-- airframe-agents:start -->';
73
+ export const AGENT_MARKER_END = '<!-- airframe-agents:end -->';
74
+ export const AGENT_DOC_CANDIDATES = [
75
+ 'AGENTS.md',
76
+ path.join('.cursor', 'rules', 'airframe.mdc'),
77
+ path.join('.claude', 'CLAUDE.md'),
78
+ ];
79
+ export function parsePinnedCoreVersion(text) {
80
+ const match = text.match(/@airframeui\/core@([0-9][^`\s]*)/);
81
+ return match?.[1] ?? null;
82
+ }
83
+ export function resolveAgentTarget(raw) {
84
+ const value = (raw ?? 'agents').toLowerCase();
85
+ if (value === 'cursor' || value === 'claude' || value === 'codex' || value === 'agents') {
86
+ return value;
87
+ }
88
+ throw new Error(`Unknown --agent value "${raw}". Use agents | cursor | claude | codex.`);
89
+ }
90
+ export function defaultDocsPath(agent) {
91
+ switch (agent) {
92
+ case 'cursor':
93
+ return path.join('.cursor', 'rules', 'airframe.mdc');
94
+ case 'claude':
95
+ return path.join('.claude', 'CLAUDE.md');
96
+ case 'codex':
97
+ case 'agents':
98
+ default:
99
+ return 'AGENTS.md';
100
+ }
101
+ }
102
+ export function resolveCoreVersion(cwd) {
103
+ try {
104
+ const require = createRequire(path.join(cwd, 'package.json'));
105
+ const pkgPath = require.resolve('@airframeui/core/package.json');
106
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
107
+ return pkg.version ?? 'unknown';
108
+ }
109
+ catch {
110
+ try {
111
+ const pkgPath = path.join(cwd, 'node_modules', '@airframeui', 'core', 'package.json');
112
+ if (fs.existsSync(pkgPath)) {
113
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
114
+ return pkg.version ?? 'unknown';
115
+ }
116
+ }
117
+ catch {
118
+ // ignore
119
+ }
120
+ return 'unknown';
121
+ }
122
+ }
123
+ export function renderAgentDocs(options) {
124
+ const { coreVersion, agent } = options;
125
+ const summary = catalogSummary(options.catalog === undefined ? loadCoreCatalog() : options.catalog);
126
+ const cursorFrontmatter = agent === 'cursor'
127
+ ? `---
128
+ description: Airframe UI structural rules for coding agents
129
+ globs:
130
+ alwaysApply: true
131
+ ---
132
+
133
+ `
134
+ : '';
135
+ return `${cursorFrontmatter}${AGENT_MARKER_START}
136
+ # Airframe — agent context
137
+
138
+ Generated by \`af init --agents\` for \`@airframeui/core@${coreVersion}\`.
139
+ Re-run after upgrading Airframe (\`npx af doctor\`, then \`npx af init --agents\`) to refresh this file.
140
+
141
+ **Source of truth:** \`@airframeui/core/catalog\` (patterns + layouts) and \`@airframeui/core/classes\` (class list). Same files IntelliSense, ESLint, and Airframe MCP read. Do not invent \`af-*\` names. Do not dump the catalog into context — look up on demand.
142
+
143
+ ## Mission
144
+
145
+ Build UI with **Airframe structure**, not utility soup and not reinvented components.
146
+
147
+ Airframe is a **structural UI system**. Use it as the design system, or wrap a kit. Use as much or as little as you need.
148
+
149
+ - Import CSS: \`@import '@airframeui/core/core.css';\`
150
+ - Prefer layout recipes from the catalog: ${summary.layoutClasses}
151
+ - Prefer patterns from the catalog (${summary.patternCount} patterns). Examples: ${summary.examplePatterns}
152
+ - If the project has a UI kit, wrap those patterns (\`<my-button>\` is an \`af-btn\`). Do not restyle \`.ui-*\` as a second look
153
+ - Theme with \`--af-*\` CSS variables — do not invent unknown token names. Alias existing \`--color-*\` into \`--af-*\` once
154
+ - Semantic HTML first (\`<button>\`, \`<a>\`, \`<label>\`, real headings)
155
+ - ${summary.namingRules}
156
+ - Responsive example: \`${summary.responsiveExample}\`
157
+ - ${summary.buttonNote}
158
+ - Form controls already \`width: 100%\`: ${summary.formControls}. Do not add \`af-w-full\` there
159
+
160
+ ## Before writing markup
161
+
162
+ 1. \`search_patterns\` (MCP) or read \`@airframeui/core/catalog\` — find the pattern/layout
163
+ 2. \`get_pattern\` — classes, parts, example (dense by default; \`dense: false\` for the full class list)
164
+ 3. \`get_example\` when you need more markup samples
165
+ 4. Compose semantic HTML with those \`af-*\` classes — **do not reimplement styles**
166
+ 5. \`validate_markup\` on the result — fix unknown \`af-*\` classes before shipping
167
+
168
+ If MCP is unavailable, import:
169
+
170
+ - \`@airframeui/core/rules\` — authoritative rules
171
+ - \`@airframeui/core/catalog\` — all patterns
172
+ - \`@airframeui/core/classes\` — class reference
173
+ - Docs: https://airframeui.com/docs/ai-rules
174
+
175
+ ## CLI aliases
176
+
177
+ Prefer the npm script so the binary path is reliable:
178
+
179
+ \`\`\`bash
180
+ npm run af -- init --agents
181
+ npm run af -- theme lint theme.css
182
+ \`\`\`
183
+
184
+ Or: \`npx af …\` after \`npm install -D @airframeui/build\`.
185
+
186
+ ## MCP (recommended)
187
+
188
+ Live lookup against the same catalog. Cursor: \`.cursor/mcp.json\`. Claude Code: \`.mcp.json\`. Restart the **airframeui** server after saving.
189
+
190
+ \`\`\`json
191
+ {
192
+ "mcpServers": {
193
+ "airframeui": {
194
+ "command": "npx",
195
+ "args": ["-y", "@airframeui/mcp"]
196
+ }
197
+ }
198
+ }
199
+ \`\`\`
200
+
201
+ Docs: https://airframeui.com/docs/mcp
202
+
203
+ UI loop: \`search_patterns\` → \`get_pattern\` → \`get_example\` → compose \`af-*\` → \`validate_markup\`
204
+ Theme loop: \`generate_theme\` / \`map_tokens\` → \`lint_theme\` until clean
205
+
206
+ ## Anti-patterns
207
+
208
+ - Do not emit Tailwind or Bootstrap class names
209
+ - Do not invent \`af-*\` classes that are not in \`@airframeui/core/catalog\` / \`classes\`
210
+ - Do not dump the entire catalog into context — fetch on demand
211
+ - Do not wrap everything in cards; use layouts for structure
212
+ - Do not paint a second look beside Airframe (\`.ui-button\` that is not an \`af-btn\`)
213
+ - Do not add kit layout utilities that copy the catalog layout recipes
214
+ - Do not keep two token files (\`--color-*\` and \`--af-*\` as separate sources)
215
+ - In product templates, do not use \`af-btn\` when \`<my-button>\` exists
216
+ ${AGENT_MARKER_END}
217
+ `;
218
+ }
219
+ function ensureParentDir(filePath) {
220
+ const dir = path.dirname(filePath);
221
+ if (!fs.existsSync(dir)) {
222
+ fs.mkdirSync(dir, { recursive: true });
223
+ }
224
+ }
225
+ function upsertPackageScript(cwd) {
226
+ const pkgPath = path.join(cwd, 'package.json');
227
+ if (!fs.existsSync(pkgPath))
228
+ return false;
229
+ const raw = fs.readFileSync(pkgPath, 'utf8');
230
+ const pkg = JSON.parse(raw);
231
+ pkg.scripts ?? (pkg.scripts = {});
232
+ const desired = 'node ./node_modules/@airframeui/build/dist/cli.js';
233
+ if (pkg.scripts['af'] === desired)
234
+ return false;
235
+ pkg.scripts['af'] = desired;
236
+ const indent = raw.includes('\t') ? '\t' : 2;
237
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, indent) + '\n', 'utf8');
238
+ return true;
239
+ }
240
+ /**
241
+ * Write agent bootstrap docs into the consumer project.
242
+ */
243
+ export function runInitAgents(options = {}) {
244
+ const cwd = options.cwd ?? process.cwd();
245
+ const agent = options.agent ?? 'agents';
246
+ const relativePath = options.agentDocsPath ?? defaultDocsPath(agent);
247
+ const docsPath = path.isAbsolute(relativePath) ? relativePath : path.join(cwd, relativePath);
248
+ const messages = [];
249
+ const coreVersion = options.coreVersion ?? resolveCoreVersion(cwd);
250
+ const catalog = options.catalog !== undefined ? options.catalog : loadCoreCatalog(cwd);
251
+ const body = renderAgentDocs({ coreVersion, agent, catalog });
252
+ let wroteDocs = false;
253
+ if (fs.existsSync(docsPath) && !options.force) {
254
+ const existing = fs.readFileSync(docsPath, 'utf8');
255
+ if (existing.includes(AGENT_MARKER_START) && existing.includes(AGENT_MARKER_END)) {
256
+ const next = existing.replace(new RegExp(`${AGENT_MARKER_START}[\\s\\S]*?${AGENT_MARKER_END}`), body.trim());
257
+ fs.writeFileSync(docsPath, next.endsWith('\n') ? next : `${next}\n`, 'utf8');
258
+ wroteDocs = true;
259
+ messages.push(`Updated Airframe agent block in ${path.relative(cwd, docsPath) || docsPath}`);
260
+ }
261
+ else {
262
+ messages.push(`Skipped ${path.relative(cwd, docsPath) || docsPath} (exists). Re-run with --force to overwrite.`);
263
+ }
264
+ }
265
+ else {
266
+ ensureParentDir(docsPath);
267
+ fs.writeFileSync(docsPath, body.endsWith('\n') ? body : `${body}\n`, 'utf8');
268
+ wroteDocs = true;
269
+ messages.push(`Wrote ${path.relative(cwd, docsPath) || docsPath}`);
270
+ }
271
+ let scriptUpdated = false;
272
+ if (!options.noScript) {
273
+ scriptUpdated = upsertPackageScript(cwd);
274
+ if (scriptUpdated) {
275
+ messages.push('Added package.json script: "af" → @airframeui/build CLI');
276
+ }
277
+ }
278
+ if (wroteDocs || scriptUpdated) {
279
+ messages.push('Next: add npx -y @airframeui/mcp to .cursor/mcp.json (or .mcp.json), restart the server, then search_patterns → get_pattern → get_example → validate_markup before writing UI.');
280
+ }
281
+ return {
282
+ exitCode: 0,
283
+ docsPath,
284
+ wroteDocs,
285
+ scriptUpdated,
286
+ messages,
287
+ };
288
+ }
289
+ /** Parse `af init` argv after the `init` token. */
290
+ export function parseInitArgs(args) {
291
+ const agents = hasFlag(args, '--agents') || hasFlag(args, '--features=agents');
292
+ const agentRaw = getFlag(args, '--agent');
293
+ const agentDocsPath = getFlag(args, '--agent-docs-path');
294
+ return {
295
+ agents,
296
+ agent: resolveAgentTarget(agentRaw),
297
+ ...(agentDocsPath ? { agentDocsPath } : {}),
298
+ force: hasFlag(args, '--force'),
299
+ noScript: hasFlag(args, '--no-script'),
300
+ };
301
+ }
302
+ //# sourceMappingURL=init-agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-agents.js","sourceRoot":"","sources":["../src/init-agents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export type AirframeConfigFile = {
2
+ breakpoints?: Record<string, string>;
3
+ theme?: {
4
+ files?: string[];
5
+ };
6
+ /**
7
+ * Optional directory for generated CSS. Unset skips writing files.
8
+ * Prefer PostCSS with `@import "@airframeui/core/core.css"`.
9
+ */
10
+ outputDir?: string | false | null;
11
+ /** Merge listed breakpoints onto token defaults. Default true. */
12
+ useDefaultBreakpoints?: boolean;
13
+ [key: string]: unknown;
14
+ };
15
+ /**
16
+ * Load `airframe.config.js` from cwd. Missing explicit `--config` throws.
17
+ * No file found during default search returns `{}`.
18
+ */
19
+ export declare function loadConfig(cwd: string, configPath?: string): Promise<{
20
+ config: AirframeConfigFile;
21
+ path?: string;
22
+ }>;
23
+ //# sourceMappingURL=load-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-config.d.ts","sourceRoot":"","sources":["../src/load-config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;IAClC,kEAAkE;IAClE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAeF;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAcxD"}
@@ -0,0 +1,31 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ async function loadConfigFile(configPath) {
5
+ const ext = path.extname(configPath);
6
+ if (ext === '.json') {
7
+ const content = fs.readFileSync(configPath, 'utf-8');
8
+ return JSON.parse(content);
9
+ }
10
+ const configModule = (await import(pathToFileURL(configPath).href));
11
+ return configModule.default ?? configModule;
12
+ }
13
+ /**
14
+ * Load `airframe.config.js` from cwd. Missing explicit `--config` throws.
15
+ * No file found during default search returns `{}`.
16
+ */
17
+ export async function loadConfig(cwd, configPath) {
18
+ if (configPath) {
19
+ const fullPath = path.isAbsolute(configPath) ? configPath : path.join(cwd, configPath);
20
+ if (!fs.existsSync(fullPath)) {
21
+ throw new Error(`Config file not found: ${fullPath}`);
22
+ }
23
+ return { config: await loadConfigFile(fullPath), path: fullPath };
24
+ }
25
+ const fullPath = path.join(cwd, 'airframe.config.js');
26
+ if (!fs.existsSync(fullPath)) {
27
+ return { config: {} };
28
+ }
29
+ return { config: await loadConfigFile(fullPath), path: fullPath };
30
+ }
31
+ //# sourceMappingURL=load-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-config.js","sourceRoot":"","sources":["../src/load-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAezC,KAAK,UAAU,cAAc,CAAC,UAAkB;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAuB,CAAC;IACnD,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAE5C,CAAC;IACvB,OAAO,YAAY,CAAC,OAAO,IAAI,YAAY,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAW,EACX,UAAmB;IAEnB,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACvF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACpE,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;IACtD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACpE,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * PostCSS plugin for @airframeui/build
3
+ * Processes @af bp() / @af-apply and replaces inlined @layer af.responsive when
4
+ * breakpoints are customized. Writes generated CSS only when outputDir is set.
5
+ */
6
+ import { type AirframeThemeConfig } from '@airframeui/theme';
7
+ import type { Plugin } from 'postcss';
8
+ export interface AirframeBuildOptions {
9
+ /** Custom breakpoints. Merged with airframe.config.js unless ignoreConfig is set. */
10
+ breakpoints?: Record<string, string>;
11
+ /**
12
+ * Optional directory for generated CSS (e.g. `.airframeui`).
13
+ * Unset, `false`, or `null` skips writing files. Prefer PostCSS with
14
+ * `@import "@airframeui/core/core.css"` — the plugin transforms in memory.
15
+ */
16
+ outputDir?: string | false | null;
17
+ /**
18
+ * Merge custom breakpoints on top of the token defaults (`xs`/`sm`/`lg`/…).
19
+ * Default `true`. Set `false` when `breakpoints` is the entire scale.
20
+ */
21
+ useDefaultBreakpoints?: boolean;
22
+ /** Skip airframe.config.js (CLI already loaded it, or tests). */
23
+ ignoreConfig?: boolean;
24
+ /** Config search directory. Defaults to process.cwd(). */
25
+ cwd?: string;
26
+ /**
27
+ * `postcss-import` options (inlined before transforms). `false` skips inlining.
28
+ * Default: run `postcss-import` when the file still has `@import`.
29
+ */
30
+ import?: false | Record<string, unknown>;
31
+ }
32
+ export declare function isOutputDirEnabled(outputDir: string | false | null | undefined): outputDir is string;
33
+ export declare function resolveBuildOptions(options?: AirframeBuildOptions): Promise<{
34
+ breakpoints?: Record<string, string>;
35
+ useDefaultBreakpoints: boolean;
36
+ outputDir: string | false | null | undefined;
37
+ cwd: string;
38
+ finalBreakpoints: Record<string, string>;
39
+ hasCustomBreakpoints: boolean;
40
+ tokenConfig: AirframeThemeConfig;
41
+ }>;
42
+ export declare function postcssAirframe(options?: AirframeBuildOptions): Plugin;
43
+ export declare namespace postcssAirframe {
44
+ var postcss: boolean;
45
+ }
46
+ export default postcssAirframe;
47
+ //# sourceMappingURL=postcss-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postcss-plugin.d.ts","sourceRoot":"","sources":["../src/postcss-plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,KAAK,EAAE,MAAM,EAA8B,MAAM,SAAS,CAAC;AAQlE,MAAM,WAAW,oBAAoB;IACnC,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;IAClC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iEAAiE;IACjE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,GAC3C,SAAS,IAAI,MAAM,CAErB;AAMD,wBAAsB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,oBAAoB,EAAE,OAAO,CAAC;IAC9B,WAAW,EAAE,mBAAmB,CAAC;CAClC,CAAC,CA6BD;AA0GD,wBAAgB,eAAe,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAiK1E;yBAjKe,eAAe;;;AAoK/B,eAAe,eAAe,CAAC"}