app-studio 0.7.10 → 0.7.11
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/app-studio.cjs.development.js +255 -261
- package/dist/app-studio.cjs.development.js.map +1 -1
- package/dist/app-studio.cjs.production.min.js +1 -1
- package/dist/app-studio.esm.js +255 -261
- package/dist/app-studio.esm.js.map +1 -1
- package/dist/app-studio.umd.development.js +255 -261
- package/dist/app-studio.umd.development.js.map +1 -1
- package/dist/app-studio.umd.production.min.js +1 -1
- package/dist/utils/vendorPrefixes.d.ts +12 -2
- package/package.json +2 -1
|
@@ -789,91 +789,44 @@
|
|
|
789
789
|
const DARK_PREFIX = 'dark-';
|
|
790
790
|
const TRANSPARENT = 'transparent';
|
|
791
791
|
// --- CSS Variable Injection Helper ---
|
|
792
|
+
// Optimized: single-pass processing, minimal string allocations, minified output
|
|
792
793
|
const generateCSSVariables = (theme, lightColors, darkColors) => {
|
|
793
|
-
const
|
|
794
|
-
const
|
|
795
|
-
const
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
const
|
|
801
|
-
const
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
processObject(lightColors.palette, 'color', variables);
|
|
813
|
-
processObject(lightColors.main, 'light-color', lightVariables);
|
|
814
|
-
processObject(lightColors.palette, 'light-color', lightVariables);
|
|
815
|
-
processObject(darkColors.main, 'dark-color', darkVariables);
|
|
816
|
-
processObject(darkColors.palette, 'dark-color', darkVariables);
|
|
817
|
-
// We collect the names that need mapping
|
|
818
|
-
const genericColorVars = [];
|
|
819
|
-
const collectGenericNames = (obj, prefix) => {
|
|
820
|
-
Object.keys(obj).forEach(key => {
|
|
821
|
-
const value = obj[key];
|
|
822
|
-
const variableName = `${prefix}-${key}`.replace(/\./g, '-');
|
|
823
|
-
if (typeof value === 'object' && value !== null) {
|
|
824
|
-
collectGenericNames(value, variableName);
|
|
825
|
-
} else {
|
|
826
|
-
genericColorVars.push(variableName);
|
|
794
|
+
const rootVars = [];
|
|
795
|
+
const lightMappings = [];
|
|
796
|
+
const darkMappings = [];
|
|
797
|
+
// Single-pass helper: generates base, light, dark vars and theme-switch mappings together
|
|
798
|
+
const processColors = (lightObj, darkObj, prefix) => {
|
|
799
|
+
const keys = Object.keys(lightObj);
|
|
800
|
+
for (let i = 0; i < keys.length; i++) {
|
|
801
|
+
const key = keys[i];
|
|
802
|
+
const lightValue = lightObj[key];
|
|
803
|
+
const darkValue = darkObj?.[key];
|
|
804
|
+
const varName = `${prefix}-${key}`;
|
|
805
|
+
if (typeof lightValue === 'object' && lightValue !== null) {
|
|
806
|
+
processColors(lightValue, darkValue, varName);
|
|
807
|
+
} else if (typeof lightValue === 'string' || typeof lightValue === 'number') {
|
|
808
|
+
// :root gets base + light/dark prefixed vars
|
|
809
|
+
rootVars.push(`--${varName}:${lightValue};--light-${varName}:${lightValue};--dark-${varName}:${darkValue ?? lightValue}`);
|
|
810
|
+
// Theme-switching selectors
|
|
811
|
+
lightMappings.push(`--${varName}:var(--light-${varName})`);
|
|
812
|
+
darkMappings.push(`--${varName}:var(--dark-${varName})`);
|
|
827
813
|
}
|
|
828
|
-
}
|
|
829
|
-
};
|
|
830
|
-
collectGenericNames(lightColors.main, 'color');
|
|
831
|
-
collectGenericNames(lightColors.palette, 'color');
|
|
832
|
-
// 3. Process Theme variables (references)
|
|
833
|
-
// Theme config uses dash notation (color-blue-500, theme-primary)
|
|
834
|
-
const processTheme = (obj, prefix) => {
|
|
835
|
-
Object.keys(obj).forEach(key => {
|
|
836
|
-
const value = obj[key];
|
|
837
|
-
const variableName = `${prefix}-${key}`;
|
|
838
|
-
if (typeof value === 'object' && value !== null) {
|
|
839
|
-
processTheme(value, variableName);
|
|
840
|
-
} else if (typeof value === 'string') {
|
|
841
|
-
if (value.startsWith('color-') || value.startsWith('theme-')) {
|
|
842
|
-
// Convert 'color-blue-500' -> 'var(--color-blue-500)'
|
|
843
|
-
themeVariables.push(`--${variableName}: var(--${value});`);
|
|
844
|
-
} else {
|
|
845
|
-
themeVariables.push(`--${variableName}: ${value};`);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
});
|
|
814
|
+
}
|
|
849
815
|
};
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
//
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
${lightVariables.join('\n ')}
|
|
862
|
-
${darkVariables.join('\n ')}
|
|
863
|
-
|
|
864
|
-
/* Theme Variables (Structural) */
|
|
865
|
-
${themeVariables.join('\n ')}
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
[data-theme='light'] {
|
|
869
|
-
${lightMappings}
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
[data-theme='dark'] {
|
|
873
|
-
${darkMappings}
|
|
816
|
+
processColors(lightColors.main, darkColors.main, 'color');
|
|
817
|
+
processColors(lightColors.palette, darkColors.palette, 'color');
|
|
818
|
+
// Process theme variables
|
|
819
|
+
const themeVars = [];
|
|
820
|
+
const themeKeys = Object.keys(theme);
|
|
821
|
+
for (let i = 0; i < themeKeys.length; i++) {
|
|
822
|
+
const key = themeKeys[i];
|
|
823
|
+
const value = theme[key];
|
|
824
|
+
if (typeof value === 'string') {
|
|
825
|
+
themeVars.push(value.startsWith('color-') || value.startsWith('theme-') ? `--theme-${key}:var(--${value})` : `--theme-${key}:${value}`);
|
|
826
|
+
}
|
|
874
827
|
}
|
|
875
|
-
|
|
876
|
-
return
|
|
828
|
+
// Build minified CSS (no unnecessary whitespace)
|
|
829
|
+
return `:root{${rootVars.join(';')};${themeVars.join(';')}}[data-theme='light']{${lightMappings.join(';')}}[data-theme='dark']{${darkMappings.join(';')}}`;
|
|
877
830
|
};
|
|
878
831
|
// --- Default Configuration ---
|
|
879
832
|
// Theme values use dash notation (color-X or color-X-shade)
|
|
@@ -1780,9 +1733,10 @@
|
|
|
1780
1733
|
return vendorPrefixToKebabCase(property);
|
|
1781
1734
|
}
|
|
1782
1735
|
// Comprehensive list of CSS properties that should be converted to classes
|
|
1736
|
+
// NOTE: Uses a static set instead of document.createElement('div').style
|
|
1737
|
+
// to avoid DOM access at module load time (breaks SSR, adds startup overhead).
|
|
1738
|
+
// The manual list below is comprehensive and covers all commonly used CSS properties.
|
|
1783
1739
|
const cssProperties = /*#__PURE__*/new Set([
|
|
1784
|
-
// Standard CSS properties
|
|
1785
|
-
... /*#__PURE__*/Object.keys(/*#__PURE__*/document.createElement('div').style),
|
|
1786
1740
|
// Box model
|
|
1787
1741
|
'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'marginHorizontal', 'marginVertical', 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'paddingHorizontal', 'paddingVertical', 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',
|
|
1788
1742
|
// Positioning
|
|
@@ -1811,6 +1765,8 @@
|
|
|
1811
1765
|
'textJustify', 'lineClamp', 'textIndent', 'perspective']);
|
|
1812
1766
|
// Common React event handlers that should not be treated as style props
|
|
1813
1767
|
const commonEventHandlers = /*#__PURE__*/new Set(['onClick', 'onChange', 'onSubmit', 'onFocus', 'onBlur', 'onKeyDown', 'onKeyUp', 'onKeyPress', 'onMouseDown', 'onMouseUp', 'onMouseMove', 'onMouseEnter', 'onMouseLeave', 'onTouchStart', 'onTouchEnd', 'onTouchMove', 'onScroll', 'onWheel', 'onDrag', 'onDragStart', 'onDragEnd', 'onDrop']);
|
|
1768
|
+
// Cache for CSS.supports results to avoid repeated DOM queries
|
|
1769
|
+
const cssSupportCache = /*#__PURE__*/new Map();
|
|
1814
1770
|
// Non-hyphenated HTML/SVG attributes that must never be treated as style props.
|
|
1815
1771
|
// Hyphenated attributes (aria-*, data-*, etc.) are caught by a prefix/hyphen check below.
|
|
1816
1772
|
const htmlOnlyAttributes = /*#__PURE__*/new Set([
|
|
@@ -1863,11 +1819,17 @@
|
|
|
1863
1819
|
return true;
|
|
1864
1820
|
}
|
|
1865
1821
|
// Check if it's a valid CSS property using CSS.supports (browser environment)
|
|
1822
|
+
// Results are cached to avoid repeated CSS.supports calls
|
|
1866
1823
|
if (typeof CSS !== 'undefined' && CSS.supports) {
|
|
1824
|
+
const cached = cssSupportCache.get(prop);
|
|
1825
|
+
if (cached !== undefined) return cached;
|
|
1867
1826
|
try {
|
|
1868
1827
|
const kebabProp = vendorPrefixToKebabCase(prop);
|
|
1869
|
-
|
|
1828
|
+
const result = CSS.supports(kebabProp, 'inherit');
|
|
1829
|
+
cssSupportCache.set(prop, result);
|
|
1830
|
+
return result;
|
|
1870
1831
|
} catch {
|
|
1832
|
+
cssSupportCache.set(prop, false);
|
|
1871
1833
|
return false;
|
|
1872
1834
|
}
|
|
1873
1835
|
}
|
|
@@ -2001,67 +1963,25 @@
|
|
|
2001
1963
|
|
|
2002
1964
|
/**
|
|
2003
1965
|
* Mapping of standard CSS properties to their vendor-prefixed equivalents.
|
|
2004
|
-
*
|
|
2005
|
-
*
|
|
1966
|
+
*
|
|
1967
|
+
* Optimized for modern browsers (Chrome 100+, Safari 15+, Firefox 91+).
|
|
1968
|
+
* Most properties no longer need vendor prefixes in these browsers.
|
|
1969
|
+
* Only -webkit- prefixes are kept where still needed by Safari/WebKit.
|
|
1970
|
+
*
|
|
1971
|
+
* Removed prefixes:
|
|
1972
|
+
* - -moz- (Firefox 91+ supports all standard properties unprefixed)
|
|
1973
|
+
* - -ms- (IE/Edge Legacy no longer supported)
|
|
1974
|
+
* - -o- (Opera uses Blink engine, same as Chrome)
|
|
1975
|
+
* - -webkit- for animation, transform, transition, flexbox, boxShadow,
|
|
1976
|
+
* boxSizing, columns, borderImage, backgroundSize, backgroundOrigin,
|
|
1977
|
+
* perspective, hyphens (all unprefixed in Safari 15+)
|
|
2006
1978
|
*/
|
|
2007
|
-
// Properties that
|
|
1979
|
+
// Properties that still need vendor prefixes in modern browsers
|
|
2008
1980
|
const vendorPrefixedProperties = {
|
|
2009
|
-
//
|
|
2010
|
-
|
|
2011
|
-
animationDelay: ['-webkit-animation-delay', '-moz-animation-delay', '-o-animation-delay'],
|
|
2012
|
-
animationDirection: ['-webkit-animation-direction', '-moz-animation-direction', '-o-animation-direction'],
|
|
2013
|
-
animationDuration: ['-webkit-animation-duration', '-moz-animation-duration', '-o-animation-duration'],
|
|
2014
|
-
animationFillMode: ['-webkit-animation-fill-mode', '-moz-animation-fill-mode', '-o-animation-fill-mode'],
|
|
2015
|
-
animationIterationCount: ['-webkit-animation-iteration-count', '-moz-animation-iteration-count', '-o-animation-iteration-count'],
|
|
2016
|
-
animationName: ['-webkit-animation-name', '-moz-animation-name', '-o-animation-name'],
|
|
2017
|
-
animationPlayState: ['-webkit-animation-play-state', '-moz-animation-play-state', '-o-animation-play-state'],
|
|
2018
|
-
animationTimingFunction: ['-webkit-animation-timing-function', '-moz-animation-timing-function', '-o-animation-timing-function'],
|
|
2019
|
-
// Transform properties
|
|
2020
|
-
transform: ['-webkit-transform', '-moz-transform', '-ms-transform', '-o-transform'],
|
|
2021
|
-
transformOrigin: ['-webkit-transform-origin', '-moz-transform-origin', '-ms-transform-origin', '-o-transform-origin'],
|
|
2022
|
-
transformStyle: ['-webkit-transform-style', '-moz-transform-style', '-ms-transform-style'],
|
|
2023
|
-
// Transition properties
|
|
2024
|
-
transition: ['-webkit-transition', '-moz-transition', '-ms-transition', '-o-transition'],
|
|
2025
|
-
transitionDelay: ['-webkit-transition-delay', '-moz-transition-delay', '-ms-transition-delay', '-o-transition-delay'],
|
|
2026
|
-
transitionDuration: ['-webkit-transition-duration', '-moz-transition-duration', '-ms-transition-duration', '-o-transition-duration'],
|
|
2027
|
-
transitionProperty: ['-webkit-transition-property', '-moz-transition-property', '-ms-transition-property', '-o-transition-property'],
|
|
2028
|
-
transitionTimingFunction: ['-webkit-transition-timing-function', '-moz-transition-timing-function', '-ms-transition-timing-function', '-o-transition-timing-function'],
|
|
2029
|
-
// Flexbox properties
|
|
2030
|
-
flex: ['-webkit-flex', '-ms-flex'],
|
|
2031
|
-
flexBasis: ['-webkit-flex-basis', '-ms-flex-basis'],
|
|
2032
|
-
flexDirection: ['-webkit-flex-direction', '-ms-flex-direction'],
|
|
2033
|
-
flexFlow: ['-webkit-flex-flow', '-ms-flex-flow'],
|
|
2034
|
-
flexGrow: ['-webkit-flex-grow', '-ms-flex-positive'],
|
|
2035
|
-
flexShrink: ['-webkit-flex-shrink', '-ms-flex-negative'],
|
|
2036
|
-
flexWrap: ['-webkit-flex-wrap', '-ms-flex-wrap'],
|
|
2037
|
-
justifyContent: ['-webkit-justify-content', '-ms-flex-pack'],
|
|
2038
|
-
alignItems: ['-webkit-align-items', '-ms-flex-align'],
|
|
2039
|
-
alignContent: ['-webkit-align-content', '-ms-flex-line-pack'],
|
|
2040
|
-
alignSelf: ['-webkit-align-self', '-ms-flex-item-align'],
|
|
2041
|
-
order: ['-webkit-order', '-ms-flex-order'],
|
|
2042
|
-
// Other commonly prefixed properties
|
|
2043
|
-
appearance: ['-webkit-appearance', '-moz-appearance', '-ms-appearance'],
|
|
2044
|
-
backfaceVisibility: ['-webkit-backface-visibility', '-moz-backface-visibility'],
|
|
2045
|
-
backgroundClip: ['-webkit-background-clip', '-moz-background-clip'],
|
|
2046
|
-
backgroundOrigin: ['-webkit-background-origin', '-moz-background-origin'],
|
|
2047
|
-
backgroundSize: ['-webkit-background-size', '-moz-background-size', '-o-background-size'],
|
|
2048
|
-
borderImage: ['-webkit-border-image', '-moz-border-image', '-o-border-image'],
|
|
2049
|
-
boxShadow: ['-webkit-box-shadow', '-moz-box-shadow'],
|
|
2050
|
-
boxSizing: ['-webkit-box-sizing', '-moz-box-sizing'],
|
|
2051
|
-
columns: ['-webkit-columns', '-moz-columns'],
|
|
2052
|
-
columnCount: ['-webkit-column-count', '-moz-column-count'],
|
|
2053
|
-
columnGap: ['-webkit-column-gap', '-moz-column-gap'],
|
|
2054
|
-
columnRule: ['-webkit-column-rule', '-moz-column-rule'],
|
|
2055
|
-
columnWidth: ['-webkit-column-width', '-moz-column-width'],
|
|
2056
|
-
filter: ['-webkit-filter'],
|
|
2057
|
-
fontSmoothing: ['-webkit-font-smoothing', '-moz-osx-font-smoothing'],
|
|
2058
|
-
hyphens: ['-webkit-hyphens', '-moz-hyphens', '-ms-hyphens'],
|
|
1981
|
+
// Properties that still need -webkit- in Safari
|
|
1982
|
+
backgroundClip: ['-webkit-background-clip'],
|
|
2059
1983
|
maskImage: ['-webkit-mask-image'],
|
|
2060
|
-
|
|
2061
|
-
perspectiveOrigin: ['-webkit-perspective-origin', '-moz-perspective-origin'],
|
|
2062
|
-
textSizeAdjust: ['-webkit-text-size-adjust', '-moz-text-size-adjust', '-ms-text-size-adjust'],
|
|
2063
|
-
userSelect: ['-webkit-user-select', '-moz-user-select', '-ms-user-select'],
|
|
2064
|
-
// Special webkit-only properties
|
|
1984
|
+
// Webkit-only properties (no unprefixed equivalent)
|
|
2065
1985
|
textFillColor: ['-webkit-text-fill-color'],
|
|
2066
1986
|
textStroke: ['-webkit-text-stroke'],
|
|
2067
1987
|
textStrokeColor: ['-webkit-text-stroke-color'],
|
|
@@ -2301,20 +2221,18 @@
|
|
|
2301
2221
|
return processStyleProperty(property, value, getColor);
|
|
2302
2222
|
},
|
|
2303
2223
|
normalizeCssValue(value) {
|
|
2224
|
+
const str = typeof value === 'string' ? value : String(value);
|
|
2304
2225
|
// Handle CSS variables in values
|
|
2305
|
-
if (
|
|
2306
|
-
//
|
|
2307
|
-
return `var-${
|
|
2226
|
+
if (str.charCodeAt(0) === 45 && str.charCodeAt(1) === 45) {
|
|
2227
|
+
// starts with '--'
|
|
2228
|
+
return `var-${str.substring(2)}`;
|
|
2308
2229
|
}
|
|
2309
2230
|
// Handle vendor-prefixed values
|
|
2310
|
-
if (
|
|
2311
|
-
|
|
2312
|
-
const prefix = '-webkit-';
|
|
2313
|
-
const rest = value.substring(prefix.length);
|
|
2314
|
-
const normalizedRest = rest.replace(/\./g, 'p').replace(/\s+/g, '-').replace(/[^a-zA-Z0-9\-]/g, '').replace(/%/g, 'pct').replace(/vw/g, 'vw').replace(/vh/g, 'vh').replace(/em/g, 'em').replace(/rem/g, 'rem');
|
|
2315
|
-
return `webkit-${normalizedRest}`;
|
|
2231
|
+
if (str.startsWith('-webkit-')) {
|
|
2232
|
+
return `webkit-${str.substring(8).replace(/\./g, 'p').replace(/\s+/g, '-').replace(/[^a-zA-Z0-9-]/g, '')}`;
|
|
2316
2233
|
}
|
|
2317
|
-
|
|
2234
|
+
// Single-pass normalization: replace dots with 'p', spaces with '-', strip non-alphanumeric
|
|
2235
|
+
return str.replace(/\./g, 'p').replace(/\s+/g, '-').replace(/[^a-zA-Z0-9-]/g, '');
|
|
2318
2236
|
},
|
|
2319
2237
|
generateUniqueClassName(css) {
|
|
2320
2238
|
if (rawCssCache.has(css)) {
|
|
@@ -2678,21 +2596,24 @@
|
|
|
2678
2596
|
devices = {};
|
|
2679
2597
|
}
|
|
2680
2598
|
const classes = [];
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
}
|
|
2599
|
+
const activeManager = manager || utilityClassManager;
|
|
2600
|
+
// Pre-compute media queries for this modifier (only done once per call)
|
|
2601
|
+
let mediaQueriesForClass = [];
|
|
2602
|
+
if (context === 'media') {
|
|
2603
|
+
if (mediaQueries[modifier]) {
|
|
2604
|
+
mediaQueriesForClass = [mediaQueries[modifier]];
|
|
2605
|
+
} else if (devices[modifier]) {
|
|
2606
|
+
mediaQueriesForClass = devices[modifier].map(mq => mediaQueries[mq]).filter(mq => mq);
|
|
2690
2607
|
}
|
|
2608
|
+
}
|
|
2609
|
+
const keys = Object.keys(styles);
|
|
2610
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2611
|
+
const value = styles[keys[i]];
|
|
2691
2612
|
if (value !== undefined && value !== '') {
|
|
2692
|
-
const classNames =
|
|
2613
|
+
const classNames = activeManager.getClassNames(keys[i], value, context, modifier, getColor, mediaQueriesForClass);
|
|
2693
2614
|
classes.push(...classNames);
|
|
2694
2615
|
}
|
|
2695
|
-
}
|
|
2616
|
+
}
|
|
2696
2617
|
return classes;
|
|
2697
2618
|
}
|
|
2698
2619
|
// Add a function to handle nested pseudo-classes
|
|
@@ -2811,6 +2732,7 @@
|
|
|
2811
2732
|
const extractUtilityClasses = (props, getColor, mediaQueries, devices, manager) => {
|
|
2812
2733
|
const classes = [];
|
|
2813
2734
|
const computedStyles = {};
|
|
2735
|
+
const activeManager = manager || utilityClassManager;
|
|
2814
2736
|
// Handle widthHeight (shorthand for both width and height)
|
|
2815
2737
|
if (props.widthHeight || props.height !== undefined && props.width !== undefined && props.height === props.width) {
|
|
2816
2738
|
const widthHeightValue = props.widthHeight || props.width;
|
|
@@ -2818,21 +2740,30 @@
|
|
|
2818
2740
|
computedStyles.width = formattedValue;
|
|
2819
2741
|
computedStyles.height = formattedValue;
|
|
2820
2742
|
}
|
|
2821
|
-
// Handle padding and margin shorthands
|
|
2822
|
-
const
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
}
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2743
|
+
// Handle padding and margin shorthands (inlined to avoid Object.entries overhead)
|
|
2744
|
+
const ph = props.paddingHorizontal;
|
|
2745
|
+
if (ph !== undefined) {
|
|
2746
|
+
const v = typeof ph === 'number' ? `${ph}px` : ph;
|
|
2747
|
+
computedStyles.paddingLeft = v;
|
|
2748
|
+
computedStyles.paddingRight = v;
|
|
2749
|
+
}
|
|
2750
|
+
const pv = props.paddingVertical;
|
|
2751
|
+
if (pv !== undefined) {
|
|
2752
|
+
const v = typeof pv === 'number' ? `${pv}px` : pv;
|
|
2753
|
+
computedStyles.paddingTop = v;
|
|
2754
|
+
computedStyles.paddingBottom = v;
|
|
2755
|
+
}
|
|
2756
|
+
const mh = props.marginHorizontal;
|
|
2757
|
+
if (mh !== undefined) {
|
|
2758
|
+
const v = typeof mh === 'number' ? `${mh}px` : mh;
|
|
2759
|
+
computedStyles.marginLeft = v;
|
|
2760
|
+
computedStyles.marginRight = v;
|
|
2761
|
+
}
|
|
2762
|
+
const mv = props.marginVertical;
|
|
2763
|
+
if (mv !== undefined) {
|
|
2764
|
+
const v = typeof mv === 'number' ? `${mv}px` : mv;
|
|
2765
|
+
computedStyles.marginTop = v;
|
|
2766
|
+
computedStyles.marginBottom = v;
|
|
2836
2767
|
}
|
|
2837
2768
|
// Handle shadows
|
|
2838
2769
|
if (props.shadow !== undefined) {
|
|
@@ -2861,80 +2792,103 @@
|
|
|
2861
2792
|
const animations = Array.isArray(props.animate) ? props.animate : [props.animate];
|
|
2862
2793
|
Object.assign(computedStyles, AnimationUtils.processAnimations(animations, manager));
|
|
2863
2794
|
}
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
color: 'white',
|
|
2867
|
-
modeWithBg: 'overlay'
|
|
2868
|
-
};
|
|
2869
|
-
const setBlend = (props, style) => {
|
|
2795
|
+
// Handle default blend
|
|
2796
|
+
if (props.blend === true) {
|
|
2870
2797
|
if (props.bgColor) {
|
|
2871
|
-
|
|
2872
|
-
|
|
2798
|
+
computedStyles.mixBlendMode = 'overlay';
|
|
2799
|
+
computedStyles.color = 'white';
|
|
2873
2800
|
} else {
|
|
2874
|
-
|
|
2875
|
-
|
|
2801
|
+
computedStyles.mixBlendMode = 'difference';
|
|
2802
|
+
computedStyles.color = 'white';
|
|
2876
2803
|
}
|
|
2877
|
-
};
|
|
2878
|
-
// Handle default blend
|
|
2879
|
-
if (props.blend === true) {
|
|
2880
|
-
setBlend(props, computedStyles);
|
|
2881
|
-
Object.keys(props).forEach(property => {
|
|
2882
|
-
if (props[property]?.color === undefined && (property.startsWith('_') || property === 'on' || property === 'media')) {
|
|
2883
|
-
setBlend(props[property], props[property]);
|
|
2884
|
-
}
|
|
2885
|
-
});
|
|
2886
2804
|
}
|
|
2887
|
-
// Process base styles
|
|
2805
|
+
// Process base computed styles
|
|
2888
2806
|
classes.push(...processStyles(computedStyles, 'base', '', getColor, {}, {}, manager));
|
|
2889
|
-
//
|
|
2890
|
-
const
|
|
2891
|
-
|
|
2892
|
-
|
|
2807
|
+
// SINGLE PASS over props: classify each prop into style, event, or underscore
|
|
2808
|
+
const propKeys = Object.keys(props);
|
|
2809
|
+
for (let i = 0; i < propKeys.length; i++) {
|
|
2810
|
+
const property = propKeys[i];
|
|
2811
|
+
const value = props[property];
|
|
2812
|
+
// Handle underscore-prefixed event properties (_hover, _focus, etc.)
|
|
2813
|
+
if (property.charCodeAt(0) === 95 && property.length > 1) {
|
|
2814
|
+
// 95 = '_'
|
|
2893
2815
|
const eventName = property.substring(1);
|
|
2894
|
-
|
|
2816
|
+
classes.push(...processEventStyles(eventName, value, getColor, manager));
|
|
2817
|
+
// Handle blend for underscore props
|
|
2818
|
+
if (props.blend === true && value?.color === undefined) {
|
|
2819
|
+
if (props.bgColor) {
|
|
2820
|
+
value.mixBlendMode = 'overlay';
|
|
2821
|
+
value.color = 'white';
|
|
2822
|
+
} else {
|
|
2823
|
+
value.mixBlendMode = 'difference';
|
|
2824
|
+
value.color = 'white';
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
continue;
|
|
2895
2828
|
}
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
const value = props[property];
|
|
2829
|
+
// Skip non-style props
|
|
2830
|
+
if (property === 'style' || property === 'css') continue;
|
|
2831
|
+
if (property === 'on') {
|
|
2832
|
+
// Process event-based styles
|
|
2901
2833
|
if (typeof value === 'object' && value !== null) {
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
}
|
|
2834
|
+
const events = Object.keys(value);
|
|
2835
|
+
for (let j = 0; j < events.length; j++) {
|
|
2836
|
+
classes.push(...processEventStyles(events[j], value[events[j]], getColor, manager));
|
|
2837
|
+
}
|
|
2838
|
+
// Handle blend for 'on' prop
|
|
2839
|
+
if (props.blend === true && value?.color === undefined) {
|
|
2840
|
+
if (props.bgColor) {
|
|
2841
|
+
value.mixBlendMode = 'overlay';
|
|
2842
|
+
value.color = 'white';
|
|
2843
|
+
} else {
|
|
2844
|
+
value.mixBlendMode = 'difference';
|
|
2845
|
+
value.color = 'white';
|
|
2846
|
+
}
|
|
2912
2847
|
}
|
|
2913
|
-
} else if (value !== undefined && value !== '') {
|
|
2914
|
-
// Direct style property
|
|
2915
|
-
classes.push(...(manager || utilityClassManager).getClassNames(property, value, 'base', '', getColor, []));
|
|
2916
2848
|
}
|
|
2849
|
+
continue;
|
|
2917
2850
|
}
|
|
2918
|
-
|
|
2851
|
+
if (property === 'media') {
|
|
2852
|
+
// Process media query styles
|
|
2853
|
+
if (typeof value === 'object' && value !== null) {
|
|
2854
|
+
const screens = Object.keys(value);
|
|
2855
|
+
for (let j = 0; j < screens.length; j++) {
|
|
2856
|
+
classes.push(...processStyles(value[screens[j]], 'media', screens[j], getColor, mediaQueries, devices, manager));
|
|
2857
|
+
}
|
|
2858
|
+
// Handle blend for 'media' prop
|
|
2859
|
+
if (props.blend === true && value?.color === undefined) {
|
|
2860
|
+
if (props.bgColor) {
|
|
2861
|
+
value.mixBlendMode = 'overlay';
|
|
2862
|
+
value.color = 'white';
|
|
2863
|
+
} else {
|
|
2864
|
+
value.mixBlendMode = 'difference';
|
|
2865
|
+
value.color = 'white';
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
continue;
|
|
2870
|
+
}
|
|
2871
|
+
// Standard style props
|
|
2872
|
+
if (isStyleProp(property)) {
|
|
2873
|
+
if (value !== undefined && value !== '') {
|
|
2874
|
+
if (typeof value === 'object' && value !== null) {
|
|
2875
|
+
// Object-style props are not directly processed as base styles
|
|
2876
|
+
continue;
|
|
2877
|
+
}
|
|
2878
|
+
classes.push(...activeManager.getClassNames(property, value, 'base', '', getColor, []));
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2919
2882
|
// Handle raw CSS - uses 'override' context for higher specificity
|
|
2920
2883
|
if (props.css) {
|
|
2921
2884
|
if (typeof props.css === 'object') {
|
|
2922
|
-
// Object-style CSS gets processed with override context for higher priority
|
|
2923
|
-
Object.assign(computedStyles, props.css);
|
|
2924
2885
|
classes.push(...processStyles(props.css, 'override', '', getColor, {}, {}, manager));
|
|
2925
2886
|
} else if (typeof props.css === 'string') {
|
|
2926
|
-
// String-style CSS gets its own class in override context
|
|
2927
2887
|
const uniqueClassName = ValueUtils.generateUniqueClassName(props.css);
|
|
2928
|
-
|
|
2888
|
+
activeManager.injectRule(`.${uniqueClassName} { ${props.css} }`, 'override');
|
|
2929
2889
|
classes.push(uniqueClassName);
|
|
2930
2890
|
}
|
|
2931
2891
|
}
|
|
2932
|
-
// Process underscore-prefixed event properties
|
|
2933
|
-
if (Object.keys(underscoreProps).length > 0) {
|
|
2934
|
-
Object.keys(underscoreProps).forEach(event => {
|
|
2935
|
-
classes.push(...processEventStyles(event, underscoreProps[event], getColor, manager));
|
|
2936
|
-
});
|
|
2937
|
-
}
|
|
2938
2892
|
return classes;
|
|
2939
2893
|
};
|
|
2940
2894
|
|
|
@@ -3001,27 +2955,47 @@
|
|
|
3001
2955
|
}, children);
|
|
3002
2956
|
};
|
|
3003
2957
|
|
|
2958
|
+
// Set of special prop names that affect CSS generation
|
|
2959
|
+
const styleRelevantProps = /*#__PURE__*/new Set(['on', 'media', 'animate', 'css', 'shadow', 'blend', 'widthHeight', 'paddingHorizontal', 'paddingVertical', 'marginHorizontal', 'marginVertical']);
|
|
2960
|
+
// Skip these props from hash computation
|
|
2961
|
+
const skipHashProps = /*#__PURE__*/new Set(['children', 'ref', 'key', 'style']);
|
|
2962
|
+
/**
|
|
2963
|
+
* Fast serialization of a value for hashing purposes.
|
|
2964
|
+
* Avoids JSON.stringify overhead for common cases (strings, numbers, booleans).
|
|
2965
|
+
*/
|
|
2966
|
+
function fastSerialize(value) {
|
|
2967
|
+
if (value === null) return 'n';
|
|
2968
|
+
const t = typeof value;
|
|
2969
|
+
if (t === 'string') return `s${value}`;
|
|
2970
|
+
if (t === 'number') return `d${value}`;
|
|
2971
|
+
if (t === 'boolean') return value ? 'T' : 'F';
|
|
2972
|
+
// Fall back to JSON.stringify only for complex objects
|
|
2973
|
+
return JSON.stringify(value);
|
|
2974
|
+
}
|
|
3004
2975
|
/**
|
|
3005
2976
|
* Computes a stable hash of style-relevant props.
|
|
3006
|
-
*
|
|
2977
|
+
* Optimized: avoids sorting, uses fast serialization, feeds directly to hash.
|
|
3007
2978
|
*/
|
|
3008
2979
|
function hashStyleProps(props) {
|
|
3009
2980
|
// Build a deterministic string representation of style-relevant props
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
2981
|
+
// We use a single string accumulator instead of array + join
|
|
2982
|
+
let hashInput = '';
|
|
2983
|
+
const keys = Object.keys(props);
|
|
2984
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2985
|
+
const key = keys[i];
|
|
3013
2986
|
// Skip non-style props that don't affect CSS generation
|
|
3014
|
-
if (key
|
|
2987
|
+
if (skipHashProps.has(key)) continue;
|
|
3015
2988
|
// Include style-relevant props
|
|
3016
|
-
if (isStyleProp(key) || key.
|
|
2989
|
+
if (isStyleProp(key) || key.charCodeAt(0) === 95 ||
|
|
2990
|
+
// starts with '_'
|
|
2991
|
+
styleRelevantProps.has(key)) {
|
|
3017
2992
|
const value = props[key];
|
|
3018
2993
|
if (value !== undefined) {
|
|
3019
|
-
|
|
3020
|
-
parts.push(`${key}:${JSON.stringify(value)}`);
|
|
2994
|
+
hashInput += `|${key}:${fastSerialize(value)}`;
|
|
3021
2995
|
}
|
|
3022
2996
|
}
|
|
3023
2997
|
}
|
|
3024
|
-
return hash(
|
|
2998
|
+
return hash(hashInput);
|
|
3025
2999
|
}
|
|
3026
3000
|
/**
|
|
3027
3001
|
* Custom hook that memoizes style extraction based on a stable hash of props.
|
|
@@ -3031,8 +3005,9 @@
|
|
|
3031
3005
|
const cacheRef = React.useRef(null);
|
|
3032
3006
|
// Compute hash directly — no useMemo since propsToProcess is always a new
|
|
3033
3007
|
// reference (from destructuring), so the memo deps would always change.
|
|
3034
|
-
|
|
3035
|
-
const
|
|
3008
|
+
// Theme hash uses Object.values() concatenation instead of JSON.stringify
|
|
3009
|
+
const themeHash = theme ? hash(Object.values(theme).join('|')) : '';
|
|
3010
|
+
const currentHash = hashStyleProps(propsToProcess) + '|' + themeHash;
|
|
3036
3011
|
// Only recompute classes if hash changed
|
|
3037
3012
|
if (!cacheRef.current || cacheRef.current.hash !== currentHash) {
|
|
3038
3013
|
const classes = extractUtilityClasses(propsToProcess, getColor, mediaQueries, devices, manager);
|
|
@@ -3209,18 +3184,24 @@
|
|
|
3209
3184
|
after,
|
|
3210
3185
|
...otherProps
|
|
3211
3186
|
} = rest;
|
|
3212
|
-
//
|
|
3213
|
-
Object.keys(otherProps)
|
|
3214
|
-
|
|
3187
|
+
// Single pass: add event handlers and non-style props together
|
|
3188
|
+
const otherKeys = Object.keys(otherProps);
|
|
3189
|
+
for (let i = 0; i < otherKeys.length; i++) {
|
|
3190
|
+
const key = otherKeys[i];
|
|
3191
|
+
// Event handlers: start with "on" + uppercase letter
|
|
3192
|
+
if (key.charCodeAt(0) === 111 &&
|
|
3193
|
+
// 'o'
|
|
3194
|
+
key.charCodeAt(1) === 110 &&
|
|
3195
|
+
// 'n'
|
|
3196
|
+
key.length > 2 && key.charCodeAt(2) >= 65 && key.charCodeAt(2) <= 90 // uppercase A-Z
|
|
3197
|
+
) {
|
|
3215
3198
|
newProps[key] = otherProps[key];
|
|
3216
3199
|
}
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
Object.keys(otherProps).forEach(key => {
|
|
3220
|
-
if (!excludedKeys.has(key) && !isStyleProp(key) || includeKeys.has(key)) {
|
|
3200
|
+
// Non-style props (pass through to DOM)
|
|
3201
|
+
else if (!excludedKeys.has(key) && !isStyleProp(key) || includeKeys.has(key)) {
|
|
3221
3202
|
newProps[key] = otherProps[key];
|
|
3222
3203
|
}
|
|
3223
|
-
}
|
|
3204
|
+
}
|
|
3224
3205
|
if (style) {
|
|
3225
3206
|
newProps.style = style;
|
|
3226
3207
|
}
|
|
@@ -3307,11 +3288,17 @@
|
|
|
3307
3288
|
ref: ref
|
|
3308
3289
|
}))));
|
|
3309
3290
|
|
|
3310
|
-
const Image = /*#__PURE__*/React__default.forwardRef((props, ref) =>
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3291
|
+
const Image = /*#__PURE__*/React__default.forwardRef((props, ref) => {
|
|
3292
|
+
const imageProps = {
|
|
3293
|
+
...props,
|
|
3294
|
+
alt: props.alt || ''
|
|
3295
|
+
};
|
|
3296
|
+
return /*#__PURE__*/React__default.createElement(Element, Object.assign({
|
|
3297
|
+
as: "img"
|
|
3298
|
+
}, imageProps, {
|
|
3299
|
+
ref: ref
|
|
3300
|
+
}));
|
|
3301
|
+
});
|
|
3315
3302
|
const ImageBackground = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
3316
3303
|
let {
|
|
3317
3304
|
src,
|
|
@@ -3410,11 +3397,18 @@
|
|
|
3410
3397
|
}, props, {
|
|
3411
3398
|
ref: ref
|
|
3412
3399
|
}))));
|
|
3413
|
-
const Button = /*#__PURE__*/React__default.forwardRef((props, ref) =>
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3400
|
+
const Button = /*#__PURE__*/React__default.forwardRef((props, ref) => {
|
|
3401
|
+
{
|
|
3402
|
+
if (!props.children && !props['aria-label']) {
|
|
3403
|
+
console.warn('Accessibility Warning: Button is missing an accessible name. If it is an icon-only button, please provide an `aria-label`.');
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
return /*#__PURE__*/React__default.createElement(Element, Object.assign({
|
|
3407
|
+
as: "button"
|
|
3408
|
+
}, props, {
|
|
3409
|
+
ref: ref
|
|
3410
|
+
}));
|
|
3411
|
+
});
|
|
3418
3412
|
|
|
3419
3413
|
// animations.ts
|
|
3420
3414
|
const fadeIn = function (_temp) {
|