funuicss
Version:
React and Next.js component UI Library for creating Easy and good looking websites with fewer lines of code. Elevate your web development experience with our cutting-edge React/Next.js component UI Library. Craft stunning websites effortlessly, boasting b
1,213 lines (1,212 loc) • 45.1 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getVariableByName = exports.getAssetByName = exports.getUsedReferences = exports.needsInterpolation = exports.createAssetReference = exports.createVariableReference = exports.formatReferenceForDisplay = exports.isAssetReference = exports.isVariableReference = exports.useAssetUrl = exports.useAsset = exports.useVariable = exports.useValue = exports.getProjectAssets = exports.getProjectVariables = exports.getAvailableVariants = exports.hasComponentVariant = exports.useComponentProps = exports.useComponentConfiguration = exports.mergeComponentConfig = exports.getComponentConfig = void 0;
var theme_1 = require("../ui/theme/theme");
var react_1 = require("react");
/**
* Check if a variant name is valid (not empty or whitespace only)
*/
var isValidVariantName = function (variantName) {
return !!variantName && variantName.trim() !== '';
};
/**
* Filter out empty string and undefined values from component props
*/
var filterEmptyProps = function (props) {
if (!props)
return {};
var filtered = {};
for (var key in props) {
if (Object.prototype.hasOwnProperty.call(props, key)) {
var value = props[key];
// Only include props that are not undefined and not empty strings
if (value !== undefined && value !== '') {
filtered[key] = value;
}
}
}
return filtered;
};
/**
* Extract variable name from {{variable_name}} pattern
*/
var extractVariableName = function (value) {
if (typeof value !== 'string')
return null;
// Match exact {{variable}} pattern
var match = value.match(/^\{\{\s*([^}]+)\s*\}\}$/);
return match ? match[1].trim() : null;
};
/**
* Extract asset name from {{{asset_name}}} pattern
*/
var extractAssetName = function (value) {
if (typeof value !== 'string')
return null;
// Match exact {{{asset}}} pattern
var match = value.match(/^\{\{\{\s*([^}]+)\s*\}\}\}$/);
return match ? match[1].trim() : null;
};
/**
* Get variable value from project variables
*/
var getVariableValue = function (variableName, projectData) {
if (!(projectData === null || projectData === void 0 ? void 0 : projectData.variables) || !variableName)
return null;
var variable = projectData.variables.find(function (v) { return v.name === variableName; });
return (variable === null || variable === void 0 ? void 0 : variable.value) || null;
};
/**
* Get asset URL from project assets
*/
var getAssetUrl = function (assetName, projectData) {
if (!(projectData === null || projectData === void 0 ? void 0 : projectData.assets) || !assetName)
return null;
var asset = projectData.assets.find(function (a) { return a.name === assetName; });
return (asset === null || asset === void 0 ? void 0 : asset.url) || null;
};
/**
* Get asset by name
*/
var getAsset = function (assetName, projectData) {
if (!(projectData === null || projectData === void 0 ? void 0 : projectData.assets) || !assetName)
return null;
var asset = projectData.assets.find(function (a) { return a.name === assetName; });
return asset || null;
};
/**
* Check if a value is a bucket reference and extract bucket info
*/
var extractBucketInfo = function (value, props, projectData) {
if (typeof value !== 'string')
return null;
// Check if it's a bucket reference {{bucket_name}}
var bucketMatch = value.match(/^\{\{\s*([^}]+)\s*\}\}$/);
if (!bucketMatch)
return null;
var bucketReference = bucketMatch[1].trim();
// Try to get the actual bucket name from variables
var bucketName = getVariableValue(bucketReference, projectData) || bucketReference;
// Get bucketPage from props (with variable interpolation if needed)
var bucketPage = 1;
var bucketPageValue = props.bucketPage;
if (bucketPageValue !== undefined) {
if (typeof bucketPageValue === 'number') {
bucketPage = bucketPageValue;
}
else if (typeof bucketPageValue === 'string') {
// Check if bucketPage is also a variable reference
var pageVariableName = extractVariableName(bucketPageValue);
if (pageVariableName) {
var pageValue = getVariableValue(pageVariableName, projectData);
if (pageValue) {
var parsed = parseInt(pageValue, 10);
if (!isNaN(parsed) && parsed > 0) {
bucketPage = parsed;
}
}
}
else {
// Direct number string
var parsed = parseInt(bucketPageValue, 10);
if (!isNaN(parsed) && parsed > 0) {
bucketPage = parsed;
}
}
}
}
return {
bucketName: bucketName,
bucketPage: Math.max(1, bucketPage)
};
};
/**
* Interpolate values (variables, assets, and buckets) in props
*/
var interpolateValues = function (props, projectData) {
if (!props || Object.keys(props).length === 0) {
return props || {};
}
var result = {};
// Create lookup maps for faster access
var variableMap = {};
var assetMap = {};
if (projectData === null || projectData === void 0 ? void 0 : projectData.variables) {
projectData.variables.forEach(function (variable) {
variableMap[variable.name] = variable.value;
});
}
if (projectData === null || projectData === void 0 ? void 0 : projectData.assets) {
projectData.assets.forEach(function (asset) {
assetMap[asset.name] = asset.url;
});
}
for (var key in props) {
if (!Object.prototype.hasOwnProperty.call(props, key))
continue;
var value = props[key];
// Handle strings with interpolation
if (typeof value === 'string') {
// Check for asset reference first ({{{asset}}})
var assetName = extractAssetName(value);
if (assetName && assetMap[assetName]) {
result[key] = assetMap[assetName];
continue;
}
// Check for variable reference ({{variable}})
var variableName = extractVariableName(value);
if (variableName && variableMap[variableName]) {
result[key] = variableMap[variableName];
continue;
}
// Check for bucket reference (treated specially in components)
// We don't interpolate bucket references here - they stay as {{bucket_name}}
// for the component to handle
result[key] = value;
}
// Handle arrays - process string elements only
else if (Array.isArray(value)) {
result[key] = value.map(function (item) {
if (typeof item === 'string') {
// Check for asset reference
var assetName = extractAssetName(item);
if (assetName && assetMap[assetName]) {
return assetMap[assetName];
}
// Check for variable reference
var variableName = extractVariableName(item);
if (variableName && variableMap[variableName]) {
return variableMap[variableName];
}
}
return item;
});
}
// Handle objects - create shallow copy (no deep interpolation)
else if (value && typeof value === 'object' && !Array.isArray(value)) {
result[key] = __assign({}, value);
}
// Handle arrays that are objects - create shallow copy
else if (Array.isArray(value)) {
result[key] = __spreadArray([], value, true);
}
// All other values pass through
else {
result[key] = value;
}
}
return result;
};
/**
* Process props specifically for Store component to handle bucket references
*/
var processStoreProps = function (props, projectData) {
var result = __assign({}, props);
// Check if this is a Store component and has bucket prop
if (props.bucket) {
var bucketInfo = extractBucketInfo(props.bucket, props, projectData);
if (bucketInfo) {
// Replace bucket reference with actual bucket name
result.bucket = bucketInfo.bucketName;
// Ensure bucketPage is set (override if not provided or use extracted value)
if (props.bucketPage === undefined || typeof props.bucketPage === 'string') {
result.bucketPage = bucketInfo.bucketPage;
}
console.log("Processed bucket reference: ".concat(props.bucket, " -> ").concat(bucketInfo.bucketName, ", page: ").concat(bucketInfo.bucketPage));
}
}
return result;
};
/**
* Universal component config getter with interpolation
*/
var getComponentConfig = function (projectData, componentName, variantName) {
var _a;
if (variantName === void 0) { variantName = 'default'; }
// Early return if no component exists
if (!((_a = projectData === null || projectData === void 0 ? void 0 : projectData.components) === null || _a === void 0 ? void 0 : _a[componentName])) {
return {
componentProps: {},
variantExists: false,
actualVariant: variantName,
availableVariants: [],
metadata: {}
};
}
var component = projectData.components[componentName];
var availableVariants = Object.keys(component);
// Find the best variant match with fallback chain
var targetVariant = variantName;
var variantExists = availableVariants.includes(variantName);
if (!variantExists) {
// Fallback priority: default → first available → none
if (availableVariants.includes('default')) {
targetVariant = 'default';
variantExists = true;
}
else if (availableVariants.length > 0) {
targetVariant = availableVariants[0];
variantExists = true;
}
else {
return {
componentProps: {},
variantExists: false,
actualVariant: variantName,
availableVariants: [],
metadata: {}
};
}
}
var variantData = component[targetVariant];
// Filter out empty string and undefined props from config
var filteredComponentProps = filterEmptyProps((variantData === null || variantData === void 0 ? void 0 : variantData.componentProps) || {});
// Apply interpolation to component props
var interpolatedProps = interpolateValues(filteredComponentProps, projectData);
// Special processing for Store component bucket references
var processedProps = componentName === 'Store'
? processStoreProps(interpolatedProps, projectData)
: interpolatedProps;
return {
componentProps: processedProps,
variantExists: variantExists,
actualVariant: targetVariant,
availableVariants: availableVariants,
metadata: (variantData === null || variantData === void 0 ? void 0 : variantData.metadata) || {}
};
};
exports.getComponentConfig = getComponentConfig;
/**
* Smart merge utility - LOCAL PROPS OVERRIDE CONFIG PROPS
*/
var smartMergeWithLocalOverride = function (configProps, localProps, projectData, componentName) {
// Start with interpolated config props
var interpolatedConfigProps = interpolateValues(configProps, projectData);
// Simple merge: local props override config props
var result = __assign({}, interpolatedConfigProps);
// Apply local props (they will be interpolated in the final pass)
for (var key in localProps) {
if (Object.prototype.hasOwnProperty.call(localProps, key)) {
var value = localProps[key];
if (value !== undefined) {
result[key] = value;
}
}
}
// Final interpolation pass to handle any variable/asset references in local props
var interpolatedResult = interpolateValues(result, projectData);
// Special processing for Store component bucket references
return componentName === 'Store'
? processStoreProps(interpolatedResult, projectData)
: interpolatedResult;
};
/**
* Merge component config with local props
*/
var mergeComponentConfig = function (config, localProps, projectData, componentName) {
if (localProps === void 0) { localProps = {}; }
// Only apply config if variant exists and has actual configuration
var hasValidConfig = config.variantExists && Object.keys(config.componentProps).length > 0;
if (!hasValidConfig) {
// Still interpolate values in local props even if no config
var interpolatedLocalProps = interpolateValues(localProps, projectData);
// Special processing for Store component
var processedLocalProps = componentName === 'Store'
? processStoreProps(interpolatedLocalProps, projectData)
: interpolatedLocalProps;
return {
props: processedLocalProps,
variant: config.actualVariant,
hasConfig: false
};
}
return {
props: smartMergeWithLocalOverride(config.componentProps, localProps, projectData, componentName),
variant: config.actualVariant,
hasConfig: true
};
};
exports.mergeComponentConfig = mergeComponentConfig;
/**
* Hook for easy component config usage
*/
var useComponentConfiguration = function (componentName, variantName) {
var projectData = (0, theme_1.useTheme)().projectData;
// Memoize config computation
var config = (0, react_1.useMemo)(function () {
if (!isValidVariantName(variantName)) {
return {
componentProps: {},
variantExists: false,
actualVariant: '',
availableVariants: [],
metadata: {}
};
}
return (0, exports.getComponentConfig)(projectData, componentName, variantName);
}, [projectData, componentName, variantName]);
// Memoize merge function
var mergeWithLocal = (0, react_1.useMemo)(function () {
return function (localProps) {
if (localProps === void 0) { localProps = {}; }
if (!isValidVariantName(variantName)) {
var interpolatedLocalProps = interpolateValues(localProps, projectData);
var processedLocalProps = componentName === 'Store'
? processStoreProps(interpolatedLocalProps, projectData)
: interpolatedLocalProps;
return {
props: processedLocalProps,
variant: '',
hasConfig: false
};
}
return (0, exports.mergeComponentConfig)(config, localProps, projectData, componentName);
};
}, [config, variantName, projectData, componentName]);
// Memoize getProp function
var getProp = (0, react_1.useMemo)(function () {
return function (propName, defaultValue) {
var value = config.componentProps[propName];
return (value !== undefined ? value : defaultValue);
};
}, [config.componentProps]);
return __assign(__assign({}, config), { mergeWithLocal: mergeWithLocal, getProp: getProp, hasVariant: config.variantExists, isDefaultVariant: config.actualVariant === 'default' });
};
exports.useComponentConfiguration = useComponentConfiguration;
/**
* Hook that directly returns merged props with local override
*/
var useComponentProps = function (componentName, variantName, localProps) {
if (variantName === void 0) { variantName = 'default'; }
if (localProps === void 0) { localProps = {}; }
var projectData = (0, theme_1.useTheme)().projectData;
return (0, react_1.useMemo)(function () {
var config = (0, exports.getComponentConfig)(projectData, componentName, variantName);
var merged = (0, exports.mergeComponentConfig)(config, localProps, projectData, componentName);
return merged.props;
}, [projectData, componentName, variantName, localProps]);
};
exports.useComponentProps = useComponentProps;
/**
* Quick utility to check if a component variant exists
*/
var hasComponentVariant = function (projectData, componentName, variantName) {
var _a, _b;
return !!((_b = (_a = projectData === null || projectData === void 0 ? void 0 : projectData.components) === null || _a === void 0 ? void 0 : _a[componentName]) === null || _b === void 0 ? void 0 : _b[variantName]);
};
exports.hasComponentVariant = hasComponentVariant;
/**
* Get all available variants for a component
*/
var getAvailableVariants = function (projectData, componentName) {
var _a;
return Object.keys(((_a = projectData === null || projectData === void 0 ? void 0 : projectData.components) === null || _a === void 0 ? void 0 : _a[componentName]) || {});
};
exports.getAvailableVariants = getAvailableVariants;
/**
* Get all variables from project
*/
var getProjectVariables = function (projectData) {
var _a;
return ((_a = projectData === null || projectData === void 0 ? void 0 : projectData.variables) === null || _a === void 0 ? void 0 : _a.map(function (v) { return ({
name: v.name,
value: v.value
}); })) || [];
};
exports.getProjectVariables = getProjectVariables;
/**
* Get all assets from project
*/
var getProjectAssets = function (projectData) {
return (projectData === null || projectData === void 0 ? void 0 : projectData.assets) || [];
};
exports.getProjectAssets = getProjectAssets;
/**
* Hook to get interpolated value for a specific variable or asset reference
*/
var useValue = function (value) {
var projectData = (0, theme_1.useTheme)().projectData;
return (0, react_1.useMemo)(function () {
if (typeof value !== 'string')
return value;
// Check for asset reference ({{{asset}}})
var assetName = extractAssetName(value);
if (assetName) {
var assetUrl = getAssetUrl(assetName, projectData);
return assetUrl || value;
}
// Check for variable reference ({{variable}})
var variableName = extractVariableName(value);
if (variableName) {
var variableValue = getVariableValue(variableName, projectData);
return variableValue || value;
}
return value;
}, [value, projectData]);
};
exports.useValue = useValue;
/**
* Hook to get a specific variable value
*/
var useVariable = function (variableName) {
var projectData = (0, theme_1.useTheme)().projectData;
return (0, react_1.useMemo)(function () {
if (!variableName || !(projectData === null || projectData === void 0 ? void 0 : projectData.variables))
return null;
var variable = projectData.variables.find(function (v) { return v.name === variableName; });
return (variable === null || variable === void 0 ? void 0 : variable.value) || null;
}, [variableName, projectData]);
};
exports.useVariable = useVariable;
/**
* Hook to get a specific asset
*/
var useAsset = function (assetName) {
var projectData = (0, theme_1.useTheme)().projectData;
return (0, react_1.useMemo)(function () {
if (!assetName || !(projectData === null || projectData === void 0 ? void 0 : projectData.assets))
return null;
return getAsset(assetName, projectData);
}, [assetName, projectData]);
};
exports.useAsset = useAsset;
/**
* Hook to get a specific asset URL
*/
var useAssetUrl = function (assetName) {
var projectData = (0, theme_1.useTheme)().projectData;
return (0, react_1.useMemo)(function () {
if (!assetName || !(projectData === null || projectData === void 0 ? void 0 : projectData.assets))
return null;
return getAssetUrl(assetName, projectData);
}, [assetName, projectData]);
};
exports.useAssetUrl = useAssetUrl;
/**
* Check if a value is a variable reference
*/
var isVariableReference = function (value) {
return typeof value === 'string' && !!extractVariableName(value);
};
exports.isVariableReference = isVariableReference;
/**
* Check if a value is an asset reference
*/
var isAssetReference = function (value) {
return typeof value === 'string' && !!extractAssetName(value);
};
exports.isAssetReference = isAssetReference;
/**
* Helper to convert variable/asset references for UI display
*/
var formatReferenceForDisplay = function (value) {
if (!value || typeof value !== 'string') {
return { type: 'custom', display: value || '' };
}
var variableName = extractVariableName(value);
if (variableName) {
return { type: 'variable', display: variableName };
}
var assetName = extractAssetName(value);
if (assetName) {
return { type: 'asset', display: assetName };
}
return { type: 'custom', display: value };
};
exports.formatReferenceForDisplay = formatReferenceForDisplay;
/**
* Create a variable reference string
*/
var createVariableReference = function (variableName) {
return "{{".concat(variableName, "}}");
};
exports.createVariableReference = createVariableReference;
/**
* Create an asset reference string
*/
var createAssetReference = function (assetName) {
return "{{{".concat(assetName, "}}}");
};
exports.createAssetReference = createAssetReference;
/**
* Check if a prop value needs interpolation
*/
var needsInterpolation = function (value) {
if (typeof value !== 'string')
return false;
return (0, exports.isVariableReference)(value) || (0, exports.isAssetReference)(value);
};
exports.needsInterpolation = needsInterpolation;
/**
* Get all references (variables and assets) used in props
*/
var getUsedReferences = function (props, projectData) {
var variables = [];
var assets = [];
if (!props || !projectData)
return { variables: variables, assets: assets };
var processValue = function (value) {
if (typeof value === 'string') {
var variableName = extractVariableName(value);
if (variableName) {
variables.push(variableName);
return;
}
var assetName = extractAssetName(value);
if (assetName) {
assets.push(assetName);
}
}
else if (Array.isArray(value)) {
value.forEach(processValue);
}
};
Object.values(props).forEach(processValue);
return {
variables: Array.from(new Set(variables)),
assets: Array.from(new Set(assets))
};
};
exports.getUsedReferences = getUsedReferences;
/**
* Get asset by name (exported version)
*/
var getAssetByName = function (assetName, projectData) {
return getAsset(assetName, projectData);
};
exports.getAssetByName = getAssetByName;
/**
* Get variable by name (exported version)
*/
var getVariableByName = function (variableName, projectData) {
if (!(projectData === null || projectData === void 0 ? void 0 : projectData.variables) || !variableName)
return null;
var variable = projectData.variables.find(function (v) { return v.name === variableName; });
return variable ? { name: variable.name, value: variable.value } : null;
};
exports.getVariableByName = getVariableByName;
exports.default = {
getComponentConfig: exports.getComponentConfig,
mergeComponentConfig: exports.mergeComponentConfig,
useComponentConfiguration: exports.useComponentConfiguration,
useComponentProps: exports.useComponentProps,
hasComponentVariant: exports.hasComponentVariant,
getAvailableVariants: exports.getAvailableVariants,
getProjectVariables: exports.getProjectVariables,
getProjectAssets: exports.getProjectAssets,
useValue: exports.useValue,
useVariable: exports.useVariable,
useAsset: exports.useAsset,
useAssetUrl: exports.useAssetUrl,
isVariableReference: exports.isVariableReference,
isAssetReference: exports.isAssetReference,
formatReferenceForDisplay: exports.formatReferenceForDisplay,
createVariableReference: exports.createVariableReference,
createAssetReference: exports.createAssetReference,
needsInterpolation: exports.needsInterpolation,
getUsedReferences: exports.getUsedReferences,
getAssetByName: exports.getAssetByName,
getVariableByName: exports.getVariableByName
};
// import { useTheme } from "../ui/theme/theme"
// import { useMemo } from "react"
// // Type definitions
// export interface ComponentProps {
// [key: string]: any
// }
// export interface ComponentMetadata {
// createdAt?: Date
// updatedAt?: Date
// isCustom?: boolean
// baseVariant?: string
// }
// export interface ComponentVariant {
// componentProps: ComponentProps
// metadata?: ComponentMetadata
// }
// export interface ComponentConfig {
// componentProps: ComponentProps
// variantExists: boolean
// actualVariant: string
// availableVariants: string[]
// metadata: ComponentMetadata
// }
// // Define the Asset interface based on your actual Asset type
// export interface Asset {
// name: string;
// url: string;
// }
// export interface ProjectData {
// components?: {
// [componentName: string]: {
// [variantName: string]: ComponentVariant
// }
// }
// variables?: Array<{
// name: string;
// value: string;
// category?: string;
// createdBy?: string;
// createdAt?: number;
// updatedBy?: string;
// updatedAt?: number;
// }>
// assets?: Asset[] // Use the Asset interface
// }
// export interface MergedConfig {
// props: ComponentProps
// variant: string
// hasConfig: boolean
// }
// export interface UseComponentConfigReturn extends ComponentConfig {
// mergeWithLocal: (localProps?: ComponentProps) => MergedConfig
// getProp: <T = any>(propName: string, defaultValue?: T) => T
// hasVariant: boolean
// isDefaultVariant: boolean
// }
// /**
// * Check if a variant name is valid (not empty or whitespace only)
// */
// const isValidVariantName = (variantName: string | undefined): boolean => {
// return !!variantName && variantName.trim() !== '';
// }
// /**
// * Filter out empty string and undefined values from component props
// */
// const filterEmptyProps = (props: ComponentProps): ComponentProps => {
// if (!props) return {};
// const filtered: ComponentProps = {};
// for (const key in props) {
// if (Object.prototype.hasOwnProperty.call(props, key)) {
// const value = props[key];
// // Only include props that are not undefined and not empty strings
// if (value !== undefined && value !== '') {
// filtered[key] = value;
// }
// }
// }
// return filtered;
// }
// /**
// * Extract variable name from {{variable_name}} pattern
// */
// const extractVariableName = (value: string): string | null => {
// if (typeof value !== 'string') return null;
// // Match exact {{variable}} pattern
// const match = value.match(/^\{\{\s*([^}]+)\s*\}\}$/);
// return match ? match[1].trim() : null;
// }
// /**
// * Extract asset name from {{{asset_name}}} pattern
// */
// const extractAssetName = (value: string): string | null => {
// if (typeof value !== 'string') return null;
// // Match exact {{{asset}}} pattern
// const match = value.match(/^\{\{\{\s*([^}]+)\s*\}\}\}$/);
// return match ? match[1].trim() : null;
// }
// /**
// * Get variable value from project variables
// */
// const getVariableValue = (
// variableName: string,
// projectData: ProjectData | null | undefined
// ): string | null => {
// if (!projectData?.variables || !variableName) return null;
// const variable = projectData.variables.find(v => v.name === variableName);
// return variable?.value || null;
// }
// /**
// * Get asset URL from project assets
// */
// const getAssetUrl = (
// assetName: string,
// projectData: ProjectData | null | undefined
// ): string | null => {
// if (!projectData?.assets || !assetName) return null;
// const asset = projectData.assets.find(a => a.name === assetName);
// return asset?.url || null;
// }
// /**
// * Get asset by name
// */
// const getAsset = (
// assetName: string,
// projectData: ProjectData | null | undefined
// ): Asset | null => {
// if (!projectData?.assets || !assetName) return null;
// const asset = projectData.assets.find(a => a.name === assetName);
// return asset || null;
// }
// /**
// * Interpolate values (variables and assets) in props
// */
// const interpolateValues = (
// props: ComponentProps,
// projectData: ProjectData | null | undefined
// ): ComponentProps => {
// if (!props || Object.keys(props).length === 0) {
// return props || {};
// }
// const result: ComponentProps = {};
// // Create lookup maps for faster access
// const variableMap: Record<string, string> = {};
// const assetMap: Record<string, string> = {};
// if (projectData?.variables) {
// projectData.variables.forEach(variable => {
// variableMap[variable.name] = variable.value;
// });
// }
// if (projectData?.assets) {
// projectData.assets.forEach(asset => {
// assetMap[asset.name] = asset.url;
// });
// }
// for (const key in props) {
// if (!Object.prototype.hasOwnProperty.call(props, key)) continue;
// const value = props[key];
// // Handle strings with interpolation
// if (typeof value === 'string') {
// // Check for asset reference first ({{{asset}}})
// const assetName = extractAssetName(value);
// if (assetName && assetMap[assetName]) {
// result[key] = assetMap[assetName];
// continue;
// }
// // Check for variable reference ({{variable}})
// const variableName = extractVariableName(value);
// if (variableName && variableMap[variableName]) {
// result[key] = variableMap[variableName];
// continue;
// }
// // No interpolation needed
// result[key] = value;
// }
// // Handle arrays - process string elements only
// else if (Array.isArray(value)) {
// result[key] = value.map(item => {
// if (typeof item === 'string') {
// // Check for asset reference
// const assetName = extractAssetName(item);
// if (assetName && assetMap[assetName]) {
// return assetMap[assetName];
// }
// // Check for variable reference
// const variableName = extractVariableName(item);
// if (variableName && variableMap[variableName]) {
// return variableMap[variableName];
// }
// }
// return item;
// });
// }
// // Handle objects - create shallow copy (no deep interpolation)
// else if (value && typeof value === 'object' && !Array.isArray(value)) {
// result[key] = { ...value };
// }
// // Handle arrays that are objects - create shallow copy
// else if (Array.isArray(value)) {
// result[key] = [...value];
// }
// // All other values pass through
// else {
// result[key] = value;
// }
// }
// return result;
// }
// /**
// * Universal component config getter with interpolation
// */
// export const getComponentConfig = (
// projectData: ProjectData | null | undefined,
// componentName: string,
// variantName: string = 'default'
// ): ComponentConfig => {
// // Early return if no component exists
// if (!projectData?.components?.[componentName]) {
// return {
// componentProps: {},
// variantExists: false,
// actualVariant: variantName,
// availableVariants: [],
// metadata: {}
// };
// }
// const component = projectData.components[componentName];
// const availableVariants = Object.keys(component);
// // Find the best variant match with fallback chain
// let targetVariant = variantName;
// let variantExists = availableVariants.includes(variantName);
// if (!variantExists) {
// // Fallback priority: default → first available → none
// if (availableVariants.includes('default')) {
// targetVariant = 'default';
// variantExists = true;
// } else if (availableVariants.length > 0) {
// targetVariant = availableVariants[0];
// variantExists = true;
// } else {
// return {
// componentProps: {},
// variantExists: false,
// actualVariant: variantName,
// availableVariants: [],
// metadata: {}
// };
// }
// }
// const variantData = component[targetVariant];
// // Filter out empty string and undefined props from config
// const filteredComponentProps = filterEmptyProps(variantData?.componentProps || {});
// // Apply interpolation to component props
// const interpolatedProps = interpolateValues(filteredComponentProps, projectData);
// return {
// componentProps: interpolatedProps,
// variantExists,
// actualVariant: targetVariant,
// availableVariants,
// metadata: variantData?.metadata || {}
// };
// }
// /**
// * Smart merge utility - LOCAL PROPS OVERRIDE CONFIG PROPS
// */
// const smartMergeWithLocalOverride = (
// configProps: ComponentProps,
// localProps: ComponentProps,
// projectData: ProjectData | null | undefined
// ): ComponentProps => {
// // Start with interpolated config props
// const interpolatedConfigProps = interpolateValues(configProps, projectData);
// // Simple merge: local props override config props
// const result = { ...interpolatedConfigProps };
// // Apply local props (they will be interpolated in the final pass)
// for (const key in localProps) {
// if (Object.prototype.hasOwnProperty.call(localProps, key)) {
// const value = localProps[key];
// if (value !== undefined) {
// result[key] = value;
// }
// }
// }
// // Final interpolation pass to handle any variable/asset references in local props
// return interpolateValues(result, projectData);
// }
// /**
// * Merge component config with local props
// */
// export const mergeComponentConfig = (
// config: ComponentConfig,
// localProps: ComponentProps = {},
// projectData: ProjectData | null | undefined
// ): MergedConfig => {
// // Only apply config if variant exists and has actual configuration
// const hasValidConfig = config.variantExists && Object.keys(config.componentProps).length > 0;
// if (!hasValidConfig) {
// // Still interpolate values in local props even if no config
// const interpolatedLocalProps = interpolateValues(localProps, projectData);
// return {
// props: interpolatedLocalProps,
// variant: config.actualVariant,
// hasConfig: false
// };
// }
// return {
// props: smartMergeWithLocalOverride(config.componentProps, localProps, projectData),
// variant: config.actualVariant,
// hasConfig: true
// };
// }
// /**
// * Hook for easy component config usage
// */
// export const useComponentConfiguration = (
// componentName: string,
// variantName?: string
// ): UseComponentConfigReturn => {
// const { projectData } = useTheme();
// // Memoize config computation
// const config = useMemo(() => {
// if (!isValidVariantName(variantName)) {
// return {
// componentProps: {},
// variantExists: false,
// actualVariant: '',
// availableVariants: [],
// metadata: {}
// };
// }
// return getComponentConfig(projectData, componentName, variantName!);
// }, [projectData, componentName, variantName]);
// // Memoize merge function
// const mergeWithLocal = useMemo(() => {
// return (localProps: ComponentProps = {}): MergedConfig => {
// if (!isValidVariantName(variantName)) {
// const interpolatedLocalProps = interpolateValues(localProps, projectData);
// return {
// props: interpolatedLocalProps,
// variant: '',
// hasConfig: false
// };
// }
// return mergeComponentConfig(config, localProps, projectData);
// };
// }, [config, variantName, projectData]);
// // Memoize getProp function
// const getProp = useMemo(() => {
// return <T = any>(propName: string, defaultValue?: T): T => {
// const value = config.componentProps[propName];
// return (value !== undefined ? value : defaultValue) as T;
// };
// }, [config.componentProps]);
// return {
// ...config,
// mergeWithLocal,
// getProp,
// hasVariant: config.variantExists,
// isDefaultVariant: config.actualVariant === 'default'
// };
// }
// /**
// * Hook that directly returns merged props with local override
// */
// export const useComponentProps = (
// componentName: string,
// variantName: string = 'default',
// localProps: ComponentProps = {}
// ): ComponentProps => {
// const { projectData } = useTheme();
// return useMemo(() => {
// const config = getComponentConfig(projectData, componentName, variantName);
// const merged = mergeComponentConfig(config, localProps, projectData);
// return merged.props;
// }, [projectData, componentName, variantName, localProps]);
// }
// /**
// * Quick utility to check if a component variant exists
// */
// export const hasComponentVariant = (
// projectData: ProjectData | null | undefined,
// componentName: string,
// variantName: string
// ): boolean => {
// return !!projectData?.components?.[componentName]?.[variantName];
// }
// /**
// * Get all available variants for a component
// */
// export const getAvailableVariants = (
// projectData: ProjectData | null | undefined,
// componentName: string
// ): string[] => {
// return Object.keys(projectData?.components?.[componentName] || {});
// }
// /**
// * Get all variables from project
// */
// export const getProjectVariables = (
// projectData: ProjectData | null | undefined
// ): Array<{name: string; value: string}> => {
// return projectData?.variables?.map(v => ({
// name: v.name,
// value: v.value
// })) || [];
// }
// /**
// * Get all assets from project
// */
// export const getProjectAssets = (
// projectData: ProjectData | null | undefined
// ): Asset[] => {
// return projectData?.assets || [];
// }
// /**
// * Hook to get interpolated value for a specific variable or asset reference
// */
// export const useValue = (value: string): string => {
// const { projectData } = useTheme();
// return useMemo(() => {
// if (typeof value !== 'string') return value;
// // Check for asset reference ({{{asset}}})
// const assetName = extractAssetName(value);
// if (assetName) {
// const assetUrl = getAssetUrl(assetName, projectData);
// return assetUrl || value;
// }
// // Check for variable reference ({{variable}})
// const variableName = extractVariableName(value);
// if (variableName) {
// const variableValue = getVariableValue(variableName, projectData);
// return variableValue || value;
// }
// return value;
// }, [value, projectData]);
// }
// /**
// * Hook to get a specific variable value
// */
// export const useVariable = (variableName: string): string | null => {
// const { projectData } = useTheme();
// return useMemo(() => {
// if (!variableName || !projectData?.variables) return null;
// const variable = projectData.variables.find(v => v.name === variableName);
// return variable?.value || null;
// }, [variableName, projectData]);
// }
// /**
// * Hook to get a specific asset
// */
// export const useAsset = (assetName: string): Asset | null => {
// const { projectData } = useTheme();
// return useMemo(() => {
// if (!assetName || !projectData?.assets) return null;
// return getAsset(assetName, projectData);
// }, [assetName, projectData]);
// }
// /**
// * Hook to get a specific asset URL
// */
// export const useAssetUrl = (assetName: string): string | null => {
// const { projectData } = useTheme();
// return useMemo(() => {
// if (!assetName || !projectData?.assets) return null;
// return getAssetUrl(assetName, projectData);
// }, [assetName, projectData]);
// }
// /**
// * Check if a value is a variable reference
// */
// export const isVariableReference = (value: any): boolean => {
// return typeof value === 'string' && !!extractVariableName(value);
// }
// /**
// * Check if a value is an asset reference
// */
// export const isAssetReference = (value: any): boolean => {
// return typeof value === 'string' && !!extractAssetName(value);
// }
// /**
// * Helper to convert variable/asset references for UI display
// */
// export const formatReferenceForDisplay = (value: string): { type: 'variable' | 'asset' | 'custom', display: string } => {
// if (!value || typeof value !== 'string') {
// return { type: 'custom', display: value || '' };
// }
// const variableName = extractVariableName(value);
// if (variableName) {
// return { type: 'variable', display: variableName };
// }
// const assetName = extractAssetName(value);
// if (assetName) {
// return { type: 'asset', display: assetName };
// }
// return { type: 'custom', display: value };
// }
// /**
// * Create a variable reference string
// */
// export const createVariableReference = (variableName: string): string => {
// return `{{${variableName}}}`;
// }
// /**
// * Create an asset reference string
// */
// export const createAssetReference = (assetName: string): string => {
// return `{{{${assetName}}}}`;
// }
// /**
// * Check if a prop value needs interpolation
// */
// export const needsInterpolation = (value: any): boolean => {
// if (typeof value !== 'string') return false;
// return isVariableReference(value) || isAssetReference(value);
// }
// /**
// * Get all references (variables and assets) used in props
// */
// export const getUsedReferences = (
// props: ComponentProps,
// projectData: ProjectData | null | undefined
// ): { variables: string[]; assets: string[] } => {
// const variables: string[] = [];
// const assets: string[] = [];
// if (!props || !projectData) return { variables, assets };
// const processValue = (value: any) => {
// if (typeof value === 'string') {
// const variableName = extractVariableName(value);
// if (variableName) {
// variables.push(variableName);
// return;
// }
// const assetName = extractAssetName(value);
// if (assetName) {
// assets.push(assetName);
// }
// } else if (Array.isArray(value)) {
// value.forEach(processValue);
// }
// };
// Object.values(props).forEach(processValue);
// return {
// variables: Array.from(new Set(variables)),
// assets: Array.from(new Set(assets))
// };
// }
// /**
// * Get asset by name (exported version)
// */
// export const getAssetByName = (assetName: string, projectData: ProjectData | null | undefined): Asset | null => {
// return getAsset(assetName, projectData);
// }
// /**
// * Get variable by name (exported version)
// */
// export const getVariableByName = (variableName: string, projectData: ProjectData | null | undefined): { name: string; value: string } | null => {
// if (!projectData?.variables || !variableName) return null;
// const variable = projectData.variables.find(v => v.name === variableName);
// return variable ? { name: variable.name, value: variable.value } : null;
// }
// export default {
// getComponentConfig,
// mergeComponentConfig,
// useComponentConfiguration,
// useComponentProps,
// hasComponentVariant,
// getAvailableVariants,
// getProjectVariables,
// getProjectAssets,
// useValue,
// useVariable,
// useAsset,
// useAssetUrl,
// isVariableReference,
// isAssetReference,
// formatReferenceForDisplay,
// createVariableReference,
// createAssetReference,
// needsInterpolation,
// getUsedReferences,
// getAssetByName,
// getVariableByName
// };