@jsenv/navi 0.7.0 → 0.7.2
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/jsenv_navi.js
CHANGED
|
@@ -721,6 +721,9 @@ const pxProperties = [
|
|
|
721
721
|
"borderTopRightRadius",
|
|
722
722
|
"borderBottomLeftRadius",
|
|
723
723
|
"borderBottomRightRadius",
|
|
724
|
+
"gap",
|
|
725
|
+
"rowGap",
|
|
726
|
+
"columnGap",
|
|
724
727
|
];
|
|
725
728
|
|
|
726
729
|
// Properties that need deg units
|
|
@@ -840,13 +843,67 @@ const normalizeNumber = (value, context, unit, propertyName) => {
|
|
|
840
843
|
|
|
841
844
|
// Normalize styles for DOM application
|
|
842
845
|
const normalizeStyles = (styles, context = "js") => {
|
|
846
|
+
if (typeof styles === "string") {
|
|
847
|
+
styles = parseStyleString(styles);
|
|
848
|
+
return styles;
|
|
849
|
+
}
|
|
843
850
|
const normalized = {};
|
|
844
|
-
for (const
|
|
851
|
+
for (const key of Object.keys(styles)) {
|
|
852
|
+
const value = styles[key];
|
|
845
853
|
normalized[key] = normalizeStyle(value, key, context);
|
|
846
854
|
}
|
|
847
855
|
return normalized;
|
|
848
856
|
};
|
|
849
857
|
|
|
858
|
+
/**
|
|
859
|
+
* Parses a CSS style string into a style object.
|
|
860
|
+
* Handles CSS properties with proper camelCase conversion.
|
|
861
|
+
*
|
|
862
|
+
* @param {string} styleString - CSS style string like "color: red; font-size: 14px;"
|
|
863
|
+
* @returns {object} Style object with camelCase properties
|
|
864
|
+
*/
|
|
865
|
+
const parseStyleString = (styleString, context = "js") => {
|
|
866
|
+
const style = {};
|
|
867
|
+
|
|
868
|
+
if (!styleString || typeof styleString !== "string") {
|
|
869
|
+
return style;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
// Split by semicolon and process each declaration
|
|
873
|
+
const declarations = styleString.split(";");
|
|
874
|
+
|
|
875
|
+
for (let declaration of declarations) {
|
|
876
|
+
declaration = declaration.trim();
|
|
877
|
+
if (!declaration) continue;
|
|
878
|
+
|
|
879
|
+
const colonIndex = declaration.indexOf(":");
|
|
880
|
+
if (colonIndex === -1) continue;
|
|
881
|
+
|
|
882
|
+
const property = declaration.slice(0, colonIndex).trim();
|
|
883
|
+
const value = declaration.slice(colonIndex + 1).trim();
|
|
884
|
+
|
|
885
|
+
if (property && value) {
|
|
886
|
+
// CSS custom properties (starting with --) should NOT be converted to camelCase
|
|
887
|
+
if (property.startsWith("--")) {
|
|
888
|
+
style[property] = normalizeStyle(value, property, context);
|
|
889
|
+
} else {
|
|
890
|
+
// Convert kebab-case to camelCase (e.g., "font-size" -> "fontSize")
|
|
891
|
+
const camelCaseProperty = property.replace(
|
|
892
|
+
/-([a-z])/g,
|
|
893
|
+
(match, letter) => letter.toUpperCase(),
|
|
894
|
+
);
|
|
895
|
+
style[camelCaseProperty] = normalizeStyle(
|
|
896
|
+
value,
|
|
897
|
+
camelCaseProperty,
|
|
898
|
+
context,
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
return style;
|
|
905
|
+
};
|
|
906
|
+
|
|
850
907
|
// Convert transform object to CSS string
|
|
851
908
|
const stringifyCSSTransform = (transformObj) => {
|
|
852
909
|
const transforms = [];
|
|
@@ -1007,15 +1064,30 @@ const parseSimple2DMatrix = (a, b, c, d, e, f) => {
|
|
|
1007
1064
|
};
|
|
1008
1065
|
|
|
1009
1066
|
// Merge two style objects, handling special cases like transform
|
|
1010
|
-
const mergeStyles = (stylesA, stylesB) => {
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1067
|
+
const mergeStyles = (stylesA, stylesB, context = "js") => {
|
|
1068
|
+
if (!stylesA) {
|
|
1069
|
+
return normalizeStyles(stylesB, context);
|
|
1070
|
+
}
|
|
1071
|
+
if (!stylesB) {
|
|
1072
|
+
return normalizeStyles(stylesA, context);
|
|
1073
|
+
}
|
|
1074
|
+
const result = {};
|
|
1075
|
+
const aKeys = Object.keys(stylesA);
|
|
1076
|
+
// in case stylesB is a string we first parse it
|
|
1077
|
+
stylesB = normalizeStyles(stylesB, context);
|
|
1078
|
+
const bKeyToVisitSet = new Set(Object.keys(stylesB));
|
|
1079
|
+
for (const aKey of aKeys) {
|
|
1080
|
+
const bHasKey = bKeyToVisitSet.has(aKey);
|
|
1081
|
+
if (bHasKey) {
|
|
1082
|
+
bKeyToVisitSet.delete(aKey);
|
|
1083
|
+
result[aKey] = mergeOneStyle(stylesA[aKey], stylesB[aKey], aKey, context);
|
|
1015
1084
|
} else {
|
|
1016
|
-
result[
|
|
1085
|
+
result[aKey] = normalizeStyle(stylesA[aKey], aKey, context);
|
|
1017
1086
|
}
|
|
1018
1087
|
}
|
|
1088
|
+
for (const bKey of bKeyToVisitSet) {
|
|
1089
|
+
result[bKey] = stylesB[bKey];
|
|
1090
|
+
}
|
|
1019
1091
|
return result;
|
|
1020
1092
|
};
|
|
1021
1093
|
|
|
@@ -1177,9 +1249,9 @@ const createStyleController = (name = "anonymous") => {
|
|
|
1177
1249
|
throw new Error("styles must be an object");
|
|
1178
1250
|
}
|
|
1179
1251
|
|
|
1180
|
-
const normalizedStylesToSet = normalizeStyles(stylesToSet, "js");
|
|
1181
1252
|
const elementData = elementWeakMap.get(element);
|
|
1182
1253
|
if (!elementData) {
|
|
1254
|
+
const normalizedStylesToSet = normalizeStyles(stylesToSet, "js");
|
|
1183
1255
|
const animation = createAnimationForStyles(
|
|
1184
1256
|
element,
|
|
1185
1257
|
normalizedStylesToSet,
|
|
@@ -1194,7 +1266,7 @@ const createStyleController = (name = "anonymous") => {
|
|
|
1194
1266
|
}
|
|
1195
1267
|
|
|
1196
1268
|
const { styles, animation } = elementData;
|
|
1197
|
-
const mergedStyles = mergeStyles(styles,
|
|
1269
|
+
const mergedStyles = mergeStyles(styles, stylesToSet);
|
|
1198
1270
|
elementData.styles = mergedStyles;
|
|
1199
1271
|
updateAnimationStyles(animation, mergedStyles);
|
|
1200
1272
|
};
|
|
@@ -18510,89 +18582,27 @@ const useConstraints = (elementRef, constraints, targetSelector) => {
|
|
|
18510
18582
|
|
|
18511
18583
|
/**
|
|
18512
18584
|
* Merges a component's base style with style received from props.
|
|
18585
|
+
* Automatically normalizes style values (e.g., adds "px" units where needed).
|
|
18513
18586
|
*
|
|
18514
18587
|
* ```jsx
|
|
18515
18588
|
* const MyButton = ({ style, children }) => (
|
|
18516
|
-
* <button style={withPropsStyle({ padding:
|
|
18589
|
+
* <button style={withPropsStyle({ padding: 10 }, style)}>
|
|
18517
18590
|
* {children}
|
|
18518
18591
|
* </button>
|
|
18519
18592
|
* );
|
|
18520
18593
|
*
|
|
18521
18594
|
* // Usage:
|
|
18522
|
-
* <MyButton style={{ color: 'red', fontSize:
|
|
18595
|
+
* <MyButton style={{ color: 'red', fontSize: 14 }} />
|
|
18523
18596
|
* <MyButton style="color: blue; margin: 5px;" />
|
|
18524
18597
|
* <MyButton /> // Just base styles
|
|
18525
18598
|
* ```
|
|
18526
18599
|
*
|
|
18527
18600
|
* @param {string|object} baseStyle - The component's base style (string or object)
|
|
18528
18601
|
* @param {string|object} [styleFromProps] - Additional style from props (optional)
|
|
18529
|
-
* @returns {object} The merged style object
|
|
18602
|
+
* @returns {object} The merged and normalized style object
|
|
18530
18603
|
*/
|
|
18531
18604
|
const withPropsStyle = (baseStyle, styleFromProps) => {
|
|
18532
|
-
|
|
18533
|
-
return baseStyle;
|
|
18534
|
-
}
|
|
18535
|
-
if (!baseStyle) {
|
|
18536
|
-
return styleFromProps;
|
|
18537
|
-
}
|
|
18538
|
-
|
|
18539
|
-
// Parse base style to object if it's a string
|
|
18540
|
-
const parsedBaseStyle =
|
|
18541
|
-
typeof baseStyle === "string"
|
|
18542
|
-
? parseStyleString(baseStyle)
|
|
18543
|
-
: baseStyle || {};
|
|
18544
|
-
// Parse props style to object if it's a string
|
|
18545
|
-
const parsedPropsStyle =
|
|
18546
|
-
typeof styleFromProps === "string"
|
|
18547
|
-
? parseStyleString(styleFromProps)
|
|
18548
|
-
: styleFromProps;
|
|
18549
|
-
// Merge styles with props taking priority
|
|
18550
|
-
return { ...parsedBaseStyle, ...parsedPropsStyle };
|
|
18551
|
-
};
|
|
18552
|
-
|
|
18553
|
-
/**
|
|
18554
|
-
* Parses a CSS style string into a style object.
|
|
18555
|
-
* Handles CSS properties with proper camelCase conversion.
|
|
18556
|
-
*
|
|
18557
|
-
* @param {string} styleString - CSS style string like "color: red; font-size: 14px;"
|
|
18558
|
-
* @returns {object} Style object with camelCase properties
|
|
18559
|
-
*/
|
|
18560
|
-
const parseStyleString = (styleString) => {
|
|
18561
|
-
const style = {};
|
|
18562
|
-
|
|
18563
|
-
if (!styleString || typeof styleString !== "string") {
|
|
18564
|
-
return style;
|
|
18565
|
-
}
|
|
18566
|
-
|
|
18567
|
-
// Split by semicolon and process each declaration
|
|
18568
|
-
const declarations = styleString.split(";");
|
|
18569
|
-
|
|
18570
|
-
for (let declaration of declarations) {
|
|
18571
|
-
declaration = declaration.trim();
|
|
18572
|
-
if (!declaration) continue;
|
|
18573
|
-
|
|
18574
|
-
const colonIndex = declaration.indexOf(":");
|
|
18575
|
-
if (colonIndex === -1) continue;
|
|
18576
|
-
|
|
18577
|
-
const property = declaration.slice(0, colonIndex).trim();
|
|
18578
|
-
const value = declaration.slice(colonIndex + 1).trim();
|
|
18579
|
-
|
|
18580
|
-
if (property && value) {
|
|
18581
|
-
// CSS custom properties (starting with --) should NOT be converted to camelCase
|
|
18582
|
-
if (property.startsWith("--")) {
|
|
18583
|
-
style[property] = value;
|
|
18584
|
-
} else {
|
|
18585
|
-
// Convert kebab-case to camelCase (e.g., "font-size" -> "fontSize")
|
|
18586
|
-
const camelCaseProperty = property.replace(
|
|
18587
|
-
/-([a-z])/g,
|
|
18588
|
-
(match, letter) => letter.toUpperCase(),
|
|
18589
|
-
);
|
|
18590
|
-
style[camelCaseProperty] = value;
|
|
18591
|
-
}
|
|
18592
|
-
}
|
|
18593
|
-
}
|
|
18594
|
-
|
|
18595
|
-
return style;
|
|
18605
|
+
return mergeStyles(baseStyle, styleFromProps, "css");
|
|
18596
18606
|
};
|
|
18597
18607
|
|
|
18598
18608
|
const consumeSpacingProps = props => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/navi",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Library of components including navigation to create frontend applications",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"prepublishOnly": "npm run build"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@jsenv/dom": "0.5.
|
|
37
|
+
"@jsenv/dom": "0.5.2",
|
|
38
38
|
"@jsenv/humanize": "1.6.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
@@ -1,86 +1,26 @@
|
|
|
1
|
+
import { mergeStyles } from "@jsenv/dom";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Merges a component's base style with style received from props.
|
|
5
|
+
* Automatically normalizes style values (e.g., adds "px" units where needed).
|
|
3
6
|
*
|
|
4
7
|
* ```jsx
|
|
5
8
|
* const MyButton = ({ style, children }) => (
|
|
6
|
-
* <button style={withPropsStyle({ padding:
|
|
9
|
+
* <button style={withPropsStyle({ padding: 10 }, style)}>
|
|
7
10
|
* {children}
|
|
8
11
|
* </button>
|
|
9
12
|
* );
|
|
10
13
|
*
|
|
11
14
|
* // Usage:
|
|
12
|
-
* <MyButton style={{ color: 'red', fontSize:
|
|
15
|
+
* <MyButton style={{ color: 'red', fontSize: 14 }} />
|
|
13
16
|
* <MyButton style="color: blue; margin: 5px;" />
|
|
14
17
|
* <MyButton /> // Just base styles
|
|
15
18
|
* ```
|
|
16
19
|
*
|
|
17
20
|
* @param {string|object} baseStyle - The component's base style (string or object)
|
|
18
21
|
* @param {string|object} [styleFromProps] - Additional style from props (optional)
|
|
19
|
-
* @returns {object} The merged style object
|
|
22
|
+
* @returns {object} The merged and normalized style object
|
|
20
23
|
*/
|
|
21
24
|
export const withPropsStyle = (baseStyle, styleFromProps) => {
|
|
22
|
-
|
|
23
|
-
return baseStyle;
|
|
24
|
-
}
|
|
25
|
-
if (!baseStyle) {
|
|
26
|
-
return styleFromProps;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Parse base style to object if it's a string
|
|
30
|
-
const parsedBaseStyle =
|
|
31
|
-
typeof baseStyle === "string"
|
|
32
|
-
? parseStyleString(baseStyle)
|
|
33
|
-
: baseStyle || {};
|
|
34
|
-
// Parse props style to object if it's a string
|
|
35
|
-
const parsedPropsStyle =
|
|
36
|
-
typeof styleFromProps === "string"
|
|
37
|
-
? parseStyleString(styleFromProps)
|
|
38
|
-
: styleFromProps;
|
|
39
|
-
// Merge styles with props taking priority
|
|
40
|
-
return { ...parsedBaseStyle, ...parsedPropsStyle };
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Parses a CSS style string into a style object.
|
|
45
|
-
* Handles CSS properties with proper camelCase conversion.
|
|
46
|
-
*
|
|
47
|
-
* @param {string} styleString - CSS style string like "color: red; font-size: 14px;"
|
|
48
|
-
* @returns {object} Style object with camelCase properties
|
|
49
|
-
*/
|
|
50
|
-
const parseStyleString = (styleString) => {
|
|
51
|
-
const style = {};
|
|
52
|
-
|
|
53
|
-
if (!styleString || typeof styleString !== "string") {
|
|
54
|
-
return style;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Split by semicolon and process each declaration
|
|
58
|
-
const declarations = styleString.split(";");
|
|
59
|
-
|
|
60
|
-
for (let declaration of declarations) {
|
|
61
|
-
declaration = declaration.trim();
|
|
62
|
-
if (!declaration) continue;
|
|
63
|
-
|
|
64
|
-
const colonIndex = declaration.indexOf(":");
|
|
65
|
-
if (colonIndex === -1) continue;
|
|
66
|
-
|
|
67
|
-
const property = declaration.slice(0, colonIndex).trim();
|
|
68
|
-
const value = declaration.slice(colonIndex + 1).trim();
|
|
69
|
-
|
|
70
|
-
if (property && value) {
|
|
71
|
-
// CSS custom properties (starting with --) should NOT be converted to camelCase
|
|
72
|
-
if (property.startsWith("--")) {
|
|
73
|
-
style[property] = value;
|
|
74
|
-
} else {
|
|
75
|
-
// Convert kebab-case to camelCase (e.g., "font-size" -> "fontSize")
|
|
76
|
-
const camelCaseProperty = property.replace(
|
|
77
|
-
/-([a-z])/g,
|
|
78
|
-
(match, letter) => letter.toUpperCase(),
|
|
79
|
-
);
|
|
80
|
-
style[camelCaseProperty] = value;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return style;
|
|
25
|
+
return mergeStyles(baseStyle, styleFromProps, "css");
|
|
86
26
|
};
|