@gem-sdk/system 1.56.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/cjs/component/createAttr.js +34 -0
- package/dist/cjs/component/createClass.js +38 -0
- package/dist/cjs/component/createContent.js +19 -0
- package/dist/cjs/component/createStateOrContext.js +55 -0
- package/dist/cjs/component/createStyle.js +42 -0
- package/dist/cjs/component/utils/toCamelCaseKeys.js +15 -0
- package/dist/cjs/index.js +21 -0
- package/dist/esm/component/createAttr.js +32 -0
- package/dist/esm/component/createClass.js +36 -0
- package/dist/esm/component/createContent.js +17 -0
- package/dist/esm/component/createStateOrContext.js +53 -0
- package/dist/esm/component/createStyle.js +39 -0
- package/dist/esm/component/utils/toCamelCaseKeys.js +13 -0
- package/dist/esm/index.js +11 -0
- package/dist/types/index.d.ts +42 -0
- package/package.json +27 -0
- package/src/component/__tests__/ template.test.tsx +76 -0
- package/src/component/__tests__/createAttr.test.ts +62 -0
- package/src/component/__tests__/createClass.test.ts +68 -0
- package/src/component/__tests__/createContent.test.ts +52 -0
- package/src/component/__tests__/createStateOrContext.test.ts +129 -0
- package/src/component/__tests__/createStyle.test.ts +63 -0
- package/src/component/createAttr.ts +44 -0
- package/src/component/createClass.ts +48 -0
- package/src/component/createContent.ts +20 -0
- package/src/component/createStateOrContext.ts +70 -0
- package/src/component/createStyle.ts +53 -0
- package/src/component/template.ts +119 -0
- package/src/component/types.ts +9 -0
- package/src/component/utils/__tests__/toCamelCaseKeys.test.ts +79 -0
- package/src/component/utils/toCamelCaseKeys.ts +20 -0
- package/src/e2e-tests/README.md +1 -0
- package/src/examples/components/text/DemoText.liquid.ts +49 -0
- package/src/examples/components/text/DemoText.tsx +50 -0
- package/src/examples/components/text/common/__tests__/globalTypoClasses.test.ts +11 -0
- package/src/examples/components/text/common/getAttr.ts +7 -0
- package/src/examples/components/text/common/getStyle.ts +5 -0
- package/src/examples/components/text/common/globalTypoClasses.ts +5 -0
- package/src/examples/components/text/e2e-tests/DemoText.spec.tsx +23 -0
- package/src/examples/components/text/e2e-tests/DemoText.tsx +23 -0
- package/src/index.ts +34 -0
- package/src/validator/README.md +1 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { describe, test, expect } from '@jest/globals';
|
|
2
|
+
|
|
3
|
+
import { toCamelCaseKeys } from '../toCamelCaseKeys';
|
|
4
|
+
|
|
5
|
+
describe('toCamelCaseKeys', () => {
|
|
6
|
+
test('should convert hyphenated keys to camelCase', () => {
|
|
7
|
+
const input = {
|
|
8
|
+
'background-color': 'blue',
|
|
9
|
+
'font-size': '12px',
|
|
10
|
+
padding: 10,
|
|
11
|
+
};
|
|
12
|
+
const expectedOutput = {
|
|
13
|
+
backgroundColor: 'blue',
|
|
14
|
+
fontSize: '12px',
|
|
15
|
+
padding: 10,
|
|
16
|
+
};
|
|
17
|
+
expect(toCamelCaseKeys(input)).toEqual(expectedOutput);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('should keep keys with "--" prefix as-is', () => {
|
|
21
|
+
const input = {
|
|
22
|
+
'--custom-var': '20px',
|
|
23
|
+
'--another-var': '15px',
|
|
24
|
+
};
|
|
25
|
+
const expectedOutput = {
|
|
26
|
+
'--custom-var': '20px',
|
|
27
|
+
'--another-var': '15px',
|
|
28
|
+
};
|
|
29
|
+
expect(toCamelCaseKeys(input)).toEqual(expectedOutput);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('should convert hyphenated keys in nested objects to camelCase', () => {
|
|
33
|
+
const input = {
|
|
34
|
+
nested: {
|
|
35
|
+
'border-radius': '5px',
|
|
36
|
+
'text-align': 'center',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
const expectedOutput = {
|
|
40
|
+
nested: {
|
|
41
|
+
borderRadius: '5px',
|
|
42
|
+
textAlign: 'center',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
expect(toCamelCaseKeys(input)).toEqual(expectedOutput);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('should handle mixed keys with hyphens and "--" prefix correctly', () => {
|
|
49
|
+
const input = {
|
|
50
|
+
'background-color': 'blue',
|
|
51
|
+
'--custom-var': '20px',
|
|
52
|
+
nested: {
|
|
53
|
+
'font-size': '12px',
|
|
54
|
+
'--nested-var': '5px',
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
const expectedOutput = {
|
|
58
|
+
backgroundColor: 'blue',
|
|
59
|
+
'--custom-var': '20px',
|
|
60
|
+
nested: {
|
|
61
|
+
fontSize: '12px',
|
|
62
|
+
'--nested-var': '5px',
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
expect(toCamelCaseKeys(input)).toEqual(expectedOutput);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('should leave keys without hyphens or "--" prefix unchanged', () => {
|
|
69
|
+
const input = {
|
|
70
|
+
padding: 10,
|
|
71
|
+
margin: '5px',
|
|
72
|
+
};
|
|
73
|
+
const expectedOutput = {
|
|
74
|
+
padding: 10,
|
|
75
|
+
margin: '5px',
|
|
76
|
+
};
|
|
77
|
+
expect(toCamelCaseKeys(input)).toEqual(expectedOutput);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const toCamelCaseKeys = (obj: { [key: string]: any }): { [key: string]: any } => {
|
|
2
|
+
const newObj: { [key: string]: any } = {};
|
|
3
|
+
|
|
4
|
+
for (const key in obj) {
|
|
5
|
+
const value = obj[key];
|
|
6
|
+
|
|
7
|
+
// If the key starts with "--", keep it as is
|
|
8
|
+
const newKey = key.startsWith('--')
|
|
9
|
+
? key
|
|
10
|
+
: key.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
11
|
+
|
|
12
|
+
// Recursively apply to nested objects
|
|
13
|
+
newObj[newKey] =
|
|
14
|
+
typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
15
|
+
? toCamelCaseKeys(value)
|
|
16
|
+
: value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return newObj;
|
|
20
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Đây là folder chưa các e2e-tests compare react vs liquid
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAttr,
|
|
3
|
+
createClass,
|
|
4
|
+
createContent,
|
|
5
|
+
createStateOrContext,
|
|
6
|
+
createStyle,
|
|
7
|
+
If,
|
|
8
|
+
} from '../../../index';
|
|
9
|
+
import { getAttr } from './common/getAttr';
|
|
10
|
+
import { getStyle } from './common/getStyle';
|
|
11
|
+
import { globalTypoClasses } from './common/globalTypoClasses';
|
|
12
|
+
import type { TextProps } from './DemoText';
|
|
13
|
+
import { template } from '@gem-sdk/core';
|
|
14
|
+
|
|
15
|
+
const Text = ({ product, text }: TextProps) => {
|
|
16
|
+
const state = createStateOrContext({
|
|
17
|
+
productId: product.id,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const attrs = createAttr({
|
|
21
|
+
...getAttr({ product }),
|
|
22
|
+
});
|
|
23
|
+
const styles = createStyle({
|
|
24
|
+
...getStyle(),
|
|
25
|
+
});
|
|
26
|
+
const classes = createClass({
|
|
27
|
+
...globalTypoClasses(),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const content = createContent(text);
|
|
31
|
+
|
|
32
|
+
return template`
|
|
33
|
+
<div ${attrs} gp-data="${state}">
|
|
34
|
+
${
|
|
35
|
+
If(product.id != "", `
|
|
36
|
+
<label class="${{ classes }}" style="${styles}">
|
|
37
|
+
${content}
|
|
38
|
+
</label>
|
|
39
|
+
`, `
|
|
40
|
+
<label class="${{ classes }}" style="${styles}">
|
|
41
|
+
${content}
|
|
42
|
+
</label>
|
|
43
|
+
`)
|
|
44
|
+
}
|
|
45
|
+
</div>
|
|
46
|
+
`;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default Text;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAttrReact,
|
|
3
|
+
createClassReact,
|
|
4
|
+
createContentReact,
|
|
5
|
+
createStyleReact,
|
|
6
|
+
If,
|
|
7
|
+
} from '../../../index';
|
|
8
|
+
import { globalTypoClasses } from './common/globalTypoClasses';
|
|
9
|
+
|
|
10
|
+
export type TextProps = {
|
|
11
|
+
product: {
|
|
12
|
+
id: string;
|
|
13
|
+
};
|
|
14
|
+
text: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const Text: React.FC<TextProps> = ({ product, text }) => {
|
|
18
|
+
const attrs = createAttrReact({
|
|
19
|
+
'data-gp-product-id': product.id,
|
|
20
|
+
});
|
|
21
|
+
const styles = createStyleReact({
|
|
22
|
+
'font-size': '16px',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const typoClasses = globalTypoClasses();
|
|
26
|
+
const classes = createClassReact({
|
|
27
|
+
'gp-text': true,
|
|
28
|
+
...typoClasses,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const content = createContentReact(text);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div {...attrs}>
|
|
35
|
+
{
|
|
36
|
+
If(product.id != "", (
|
|
37
|
+
<label className={classes} style={styles}>
|
|
38
|
+
{content}
|
|
39
|
+
</label>
|
|
40
|
+
), (
|
|
41
|
+
<label className={classes} style={styles}>
|
|
42
|
+
{content}
|
|
43
|
+
</label>
|
|
44
|
+
))
|
|
45
|
+
}
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default Text;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, test, expect } from '@jest/globals';
|
|
2
|
+
import { globalTypoClasses } from '../globalTypoClasses';
|
|
3
|
+
|
|
4
|
+
describe('globalTypoClasses', () => {
|
|
5
|
+
test('Test case 1', () => {
|
|
6
|
+
const classes = globalTypoClasses();
|
|
7
|
+
expect(classes).toEqual({
|
|
8
|
+
'gp-global-h1': true,
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { test, expect } from '@playwright/experimental-ct-react';
|
|
2
|
+
import type { TextProps } from "../DemoText";
|
|
3
|
+
import DemoText from "../DemoText"
|
|
4
|
+
import DemoTextLiquid from "../DemoText.liquid"
|
|
5
|
+
|
|
6
|
+
test('should work', async ({ mount }, testInfo) => {
|
|
7
|
+
const props: TextProps = {
|
|
8
|
+
product: {
|
|
9
|
+
id: "1"
|
|
10
|
+
},
|
|
11
|
+
text: "Demo test"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const component = await mount((
|
|
15
|
+
<div>
|
|
16
|
+
<div className='react-el'><DemoText {...props}/></div>
|
|
17
|
+
<div className='liquid-el'><div dangerouslySetInnerHTML={{__html: DemoTextLiquid(props)}}></div></div>
|
|
18
|
+
</div>
|
|
19
|
+
));
|
|
20
|
+
|
|
21
|
+
await expect(component.locator('.react-el')).toHaveScreenshot(`${testInfo.title}.png`);
|
|
22
|
+
await expect(component.locator('.liquid-el')).toHaveScreenshot(`${testInfo.title}.png`);
|
|
23
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { E2ETests } from '../../../../component/types';
|
|
2
|
+
import type { TextProps } from '../DemoText';
|
|
3
|
+
import DemoTextReact from '../DemoText';
|
|
4
|
+
import DemoTextLiquid from '../DemoText.liquid';
|
|
5
|
+
|
|
6
|
+
export const e2eDemoText = (): E2ETests => {
|
|
7
|
+
return {
|
|
8
|
+
'DemoText basic': async () => {
|
|
9
|
+
const props: TextProps = {
|
|
10
|
+
product: {
|
|
11
|
+
id: '1',
|
|
12
|
+
},
|
|
13
|
+
text: 'Demo test',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
props,
|
|
18
|
+
reactComponent: DemoTextReact,
|
|
19
|
+
liquidComponent: DemoTextLiquid,
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createAttr } from './component/createAttr';
|
|
2
|
+
const createAttrReact = createAttr;
|
|
3
|
+
|
|
4
|
+
import { createStyle, createStyleReact } from './component/createStyle';
|
|
5
|
+
|
|
6
|
+
import { createContent } from './component/createContent';
|
|
7
|
+
const createContentReact = createContent;
|
|
8
|
+
|
|
9
|
+
import { createClass } from './component/createClass';
|
|
10
|
+
const createClassReact = createClass;
|
|
11
|
+
|
|
12
|
+
import { createStateOrContext } from './component/createStateOrContext';
|
|
13
|
+
|
|
14
|
+
import { Liquid, If, LiquidIf, For, LiquidFor } from './component/template';
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
// Attr
|
|
18
|
+
createAttr,
|
|
19
|
+
createAttrReact,
|
|
20
|
+
createStyle,
|
|
21
|
+
createStyleReact,
|
|
22
|
+
createContent,
|
|
23
|
+
createContentReact,
|
|
24
|
+
createClass,
|
|
25
|
+
createClassReact,
|
|
26
|
+
createStateOrContext,
|
|
27
|
+
|
|
28
|
+
// Template
|
|
29
|
+
Liquid,
|
|
30
|
+
If,
|
|
31
|
+
LiquidIf,
|
|
32
|
+
For,
|
|
33
|
+
LiquidFor,
|
|
34
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Đây là folder chưa các func validate component setting
|