UNPKG

igniteui-theming

Version:

A set of Sass variables, mixins, and functions for generating palettes, typography, and elevations used by Ignite UI components.

148 lines (146 loc) 5.98 kB
import { COMPONENT_METADATA, getComponentPlatformAvailability, getComponentSelector } from "../../knowledge/component-metadata.js"; import "../../knowledge/index.js"; //#region src/tools/handlers/layout.ts /** * Handlers for layout scale tools: set_size, set_spacing, set_roundness. */ var SIZE_KEYWORDS = { small: 1, medium: 2, large: 3 }; function normalizeComponentName(component) { return component ? component.toLowerCase().trim() : null; } function buildSelectorList(value) { return Array.isArray(value) ? value : [value]; } function resolveScope(component, scope, platform) { const notes = []; if (component) { const normalized = normalizeComponentName(component); if (!normalized || !COMPONENT_METADATA[normalized]) { const available = Object.keys(COMPONENT_METADATA); const suggestions = normalized ? available.filter((name) => name.includes(normalized)).slice(0, 10) : []; const list = suggestions.length > 0 ? suggestions : available.slice(0, 15); return { error: `**Error:** Component "${component}" not found. ${suggestions.length > 0 ? "**Similar components:**" : "**Available components:**"} ${list.map((name) => `- ${name}`).join("\n")}` }; } if (scope) notes.push("Scope ignored because component was provided."); const selectorsEntry = COMPONENT_METADATA[normalized].selectors; let selectors = []; if (!selectorsEntry) return { error: `**Error:** Component "${component}" does not have platform selectors. It may be a child sub-component — use its parent component for layout overrides.` }; if (platform && platform !== "generic") { selectors = getComponentSelector(normalized, platform); if (selectors.length === 0) { const availability = getComponentPlatformAvailability(normalized); const availablePlatforms = []; if (availability?.angular) availablePlatforms.push("angular"); if (availability?.webcomponents) availablePlatforms.push("webcomponents"); return { error: `**Error:** Component "${component}" is not available on platform "${platform}". ${availablePlatforms.length > 0 ? `Available platforms: ${availablePlatforms.join(", ")}.` : ""}` }; } } else { if (selectorsEntry.angular) selectors = selectors.concat(buildSelectorList(selectorsEntry.angular)); if (selectorsEntry.webcomponents) selectors = selectors.concat(buildSelectorList(selectorsEntry.webcomponents)); if (selectorsEntry.angular && selectorsEntry.webcomponents) notes.push("Platform not specified; output includes Angular and Web Components selectors."); } return { selectors: Array.from(new Set(selectors)), notes, scopeLabel: `component "${normalized}"` }; } if (scope) return { selectors: [scope], notes, scopeLabel: `scope "${scope}"` }; return { selectors: [":root"], notes, scopeLabel: "global scope (:root)" }; } function formatSelectorBlock(selectors, declarations) { return [ selectors.join(",\n"), "{", ...declarations.map((line) => ` ${line}`), "}" ].join("\n"); } function buildResponse(description, output, code, notes, guidance) { const responseParts = [description]; if (notes.length > 0) responseParts.push("", ...notes); if (guidance.length > 0) responseParts.push("", ...guidance); responseParts.push(""); responseParts.push(output === "sass" ? "```scss" : "```css"); responseParts.push(code); responseParts.push("```"); return { content: [{ type: "text", text: responseParts.join("\n") }] }; } function coerceSizeValue(size) { if (typeof size === "number") return { display: String(size), value: size }; const value = SIZE_KEYWORDS[size.toLowerCase()]; return { display: `${size} (${value})`, value }; } async function handleSetSize(params) { const { component, scope, platform, size, output = "css" } = params; const resolution = resolveScope(component, scope, platform); if ("error" in resolution) return { content: [{ type: "text", text: resolution.error }], isError: true }; const { selectors, notes, scopeLabel } = resolution; const { display, value } = coerceSizeValue(size); const code = formatSelectorBlock(selectors, [`--ig-size: ${value};`]); return buildResponse(`Set size to ${display} in ${scopeLabel}.`, output, code, notes, output === "sass" ? ["Sass note: sizable() requires @include sizable() in component styles.", "Components map --ig-size to --component-size internally."] : []); } async function handleSetSpacing(params) { const { component, scope, platform, spacing, inline, block, output = "css" } = params; const resolution = resolveScope(component, scope, platform); if ("error" in resolution) return { content: [{ type: "text", text: resolution.error }], isError: true }; const { selectors, notes, scopeLabel } = resolution; const declarations = []; if (spacing !== void 0) declarations.push(`--ig-spacing: ${spacing};`); if (inline !== void 0) declarations.push(`--ig-spacing-inline: ${inline};`); if (block !== void 0) declarations.push(`--ig-spacing-block: ${block};`); const code = formatSelectorBlock(selectors, declarations); return buildResponse(`Set spacing in ${scopeLabel}.`, output, code, notes, output === "sass" ? ["Sass note: pad() functions require @include spacing() once at root scope."] : []); } async function handleSetRoundness(params) { const { component, scope, platform, radiusFactor, output = "css" } = params; const resolution = resolveScope(component, scope, platform); if ("error" in resolution) return { content: [{ type: "text", text: resolution.error }], isError: true }; const { selectors, notes, scopeLabel } = resolution; const code = formatSelectorBlock(selectors, [`--ig-radius-factor: ${radiusFactor};`]); return buildResponse(`Set roundness factor to ${radiusFactor} in ${scopeLabel}.`, output, code, notes, output === "sass" ? ["Sass note: border-radius() responds to --ig-radius-factor without extra mixins."] : []); } //#endregion export { handleSetRoundness, handleSetSize, handleSetSpacing };