@riosst100/pwa-marketplace 1.4.5 → 1.4.7

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.
Files changed (46) hide show
  1. package/i18n/en_US.json +509 -509
  2. package/i18n/id_ID.json +29 -29
  3. package/package.json +1 -1
  4. package/src/componentOverrideMapping.js +3 -0
  5. package/src/components/BrandLandingPage/brandInfo.js +93 -0
  6. package/src/components/BrandLandingPage/brandLanding.js +255 -0
  7. package/src/components/BrandLandingPage/index.js +94 -0
  8. package/src/components/BrandLandingPage/menu.js +20 -0
  9. package/src/components/BrandListPage/banner_brands.png +0 -0
  10. package/src/components/BrandListPage/brandList.js +88 -0
  11. package/src/components/BrandListPage/index.js +57 -0
  12. package/src/components/BrandSlider/brandSlider.js +2 -2
  13. package/src/components/BrandSlider/item.js +24 -6
  14. package/src/components/CollectibleGameSets/collectibleGameSets.js +2 -1
  15. package/src/components/FilterTop/CustomFilters/customFilters.js +1 -1
  16. package/src/components/Modal/index.js +10 -0
  17. package/src/components/Modal/modal.js +48 -0
  18. package/src/components/ProductLineSlider/index.js +1 -0
  19. package/src/components/ProductLineSlider/item.js +38 -0
  20. package/src/components/ProductLineSlider/logo_nendoroid.png +0 -0
  21. package/src/components/ProductLineSlider/nendroid-image.png +0 -0
  22. package/src/components/ProductLineSlider/productLineSlider.js +91 -0
  23. package/src/components/SocialMediaShare/index.js +51 -0
  24. package/src/components/SocialMediaShare/share.js +94 -0
  25. package/src/intercept.js +41 -27
  26. package/src/overwrites/venia-ui/lib/components/FilterModal/CurrentFilters/currentFilter.js +1 -1
  27. package/src/overwrites/venia-ui/lib/components/FilterModal/CurrentFilters/currentFilter.module.css +5 -4
  28. package/src/overwrites/venia-ui/lib/components/FilterModal/CurrentFilters/currentFilters.module.css +3 -1
  29. package/src/overwrites/venia-ui/lib/components/Footer/footer.js +147 -0
  30. package/src/overwrites/venia-ui/lib/components/Footer/footer.module.css +70 -0
  31. package/src/overwrites/venia-ui/lib/components/Footer/index.js +1 -0
  32. package/src/overwrites/venia-ui/lib/components/Footer/sampleData.js +48 -0
  33. package/src/overwrites/venia-ui/lib/components/Gallery/gallery.module.css +1 -1
  34. package/src/overwrites/venia-ui/lib/components/Main/index.js +1 -0
  35. package/src/overwrites/venia-ui/lib/components/Main/main.js +39 -0
  36. package/src/overwrites/venia-ui/lib/components/Main/main.module.css +41 -0
  37. package/src/overwrites/venia-ui/lib/components/MegaMenu/submenuColumn.js +14 -4
  38. package/src/overwrites/venia-ui/lib/components/MegaMenu/submenuColumn.module.css +2 -2
  39. package/src/overwrites/venia-ui/lib/components/Newsletter/index.js +1 -0
  40. package/src/overwrites/venia-ui/lib/components/Newsletter/newsletter.js +156 -0
  41. package/src/overwrites/venia-ui/lib/components/Newsletter/newsletter.module.css +90 -0
  42. package/src/overwrites/venia-ui/lib/components/Newsletter/newsletter.shimmer.js +46 -0
  43. package/src/overwrites/venia-ui/lib/components/Newsletter/newsletter.shimmer.module.css +21 -0
  44. package/src/overwrites/venia-ui/lib/components/ProductFullDetail/productFullDetail.js +23 -12
  45. package/src/overwrites/venia-ui/lib/components/TextInput/textInput.js +9 -1
  46. package/src/theme/vars.js +2 -0
@@ -0,0 +1,57 @@
1
+ import React, { useState } from 'react';
2
+ import Content from './brandList';
3
+
4
+ const index = () => {
5
+
6
+ const [active, setActive] = useState('all')
7
+ const letters = Array.from({ length: 26 }, (_, i) => String.fromCharCode(i + 65));
8
+
9
+ const brands = [
10
+ { id: 1, name: "Bandai" },
11
+ { id: 2, name: "Hasbro" },
12
+ { id: 3, name: "Mattel" },
13
+ { id: 4, name: "NECA" },
14
+ { id: 5, name: "Beast Kingdom" },
15
+ { id: 5, name: "Beast Kingdom" },
16
+ { id: 5, name: "Beast Kingdom" },
17
+ { id: 5, name: "Beast Kingdom" },
18
+ { id: 5, name: "Beast Kingdom" },
19
+ { id: 5, name: "Beast Kingdom" },
20
+ { id: 5, name: "Beast Kingdom" },
21
+ { id: 5, name: "Beast Kingdom" },
22
+ { id: 5, name: "Beast Kingdom" },
23
+ { id: 6, name: "McFarlane Toys" },
24
+ { id: 7, name: "Good Smile Company" },
25
+ { id: 8, name: "Evolution Toy" },
26
+ ];
27
+
28
+ const groupBrandsByFirstLetter = (brands) => {
29
+ return brands.reduce((acc, brand) => {
30
+ const firstLetter = brand.name.charAt(0).toUpperCase();
31
+ acc[firstLetter] = acc[firstLetter] || [];
32
+ acc[firstLetter].push(brand);
33
+ return acc;
34
+ }, {});
35
+ }
36
+
37
+ const groupedBrands = groupBrandsByFirstLetter(brands);
38
+ const availableLetter = Object.keys(groupedBrands).sort();
39
+
40
+ const handleActive = (val) => {
41
+ setActive(val);
42
+ }
43
+
44
+ const contentProps = {
45
+ letters,
46
+ groupedBrands,
47
+ availableLetter,
48
+ active,
49
+ handleActive,
50
+ };
51
+
52
+ return (
53
+ <Content {...contentProps} />
54
+ )
55
+ }
56
+
57
+ export default index
@@ -40,7 +40,7 @@ const brandSlider = (props) => {
40
40
  {
41
41
  breakpoint: 1023,
42
42
  settings: {
43
- slidesToShow: 4,
43
+ slidesToShow: 3,
44
44
  slidesToScroll: 1,
45
45
  }
46
46
  },
@@ -68,7 +68,7 @@ const brandSlider = (props) => {
68
68
  <Slider {...settings}>
69
69
  {[...Array(9)].map(() => {
70
70
  return (
71
- <Item />
71
+ <Item {...props} />
72
72
  )
73
73
  })}
74
74
  </Slider>
@@ -1,14 +1,32 @@
1
1
  import React from 'react';
2
2
  import cn from 'classnames';
3
3
 
4
- const Item = () => {
4
+ const Item = (props) => {
5
+ const {
6
+ name = 'Tamashii Nations', rootClassName, onClick = () => { },
7
+ className = "",
8
+ } = props;
9
+
10
+ const initialName = (name) => {
11
+ if (!name) return ""; // Handle empty names
12
+
13
+ const words = name.split(" ");
14
+ let initials = "";
15
+
16
+ for (const word of words) {
17
+ initials += word.charAt(0).toUpperCase();
18
+ }
19
+
20
+ return initials;
21
+ }
5
22
  return (
6
- <div className='brand-item-container px-2 lg_px-4'>
23
+ <div className={cn('brand-item-container px-2 lg_px-4', rootClassName)} onClick={onClick}>
7
24
  <div
8
25
  className={cn(
9
26
  'm-auto flex flex-col',
10
27
  'w-full max-w-[250px]',
11
- 'relative rounded-lg border border-gray-100',
28
+ 'relative rounded-lg border border-gray-100 bg-white',
29
+ className,
12
30
  )}
13
31
  >
14
32
  <div className="brand_logo-wrapper w-full min-h-[120px] rounded-t-lg">
@@ -16,15 +34,15 @@ const Item = () => {
16
34
  </div>
17
35
  <div
18
36
  className={cn(
19
- 'bg-darkblue-900 text-white uppercase text-lg font-bold leading-5 absolute',
37
+ 'bg-darkblue-900 text-white uppercase text-lg font-bold leading-5 absolute min-w-[60px] text-center',
20
38
  'p-5 rounded-md top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2'
21
39
  )}
22
40
  >
23
- TN
41
+ {initialName(name)}
24
42
  </div>
25
43
  <div className='brand_name-wrapper flex items-center justify-center w-full min-h-[110px]'>
26
44
  <span className='text-base font-medium'>
27
- Tamashii Nations
45
+ {name}
28
46
  </span>
29
47
  </div>
30
48
  <style global jsx>
@@ -40,7 +40,8 @@ const CollectibleGameSets = props => {
40
40
 
41
41
  return (
42
42
  <Fragment>
43
- <StoreTitle>Magic: The Gathering | All Sets</StoreTitle>
43
+ <StoreTitle>Magic: The Gathering | Sets & Expansions</StoreTitle>
44
+ <h3>Sets & Expansions</h3>
44
45
  <div>{sets}</div>
45
46
  </Fragment>
46
47
  );
@@ -49,7 +49,7 @@ const CustomFilters = props => {
49
49
  }
50
50
  });
51
51
 
52
- if (value == "all") {
52
+ if (value != "all") {
53
53
  params[`${attribute_code}[filter]`] = `${label},${value}`;
54
54
  }
55
55
 
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import Content from './modal';
3
+
4
+ const index = (props) => {
5
+ return (
6
+ <Content {...props} />
7
+ )
8
+ }
9
+
10
+ export default index
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import cn from 'classnames';
3
+ import { blackTransparent } from '@riosst100/pwa-marketplace/src/theme/vars'
4
+
5
+ const modal = (props) => {
6
+ const {
7
+ open = false, setOpen = () => { }, children = null,
8
+ rootClassName = '', className = '', closeOutside = false,
9
+ } = props;
10
+
11
+
12
+ return (
13
+ <>
14
+ {open && (
15
+ <div
16
+ className={cn(
17
+ 'block overflow-hidden fixed top-0 right-0 left-0 z-dialog',
18
+ 'justify-center items-center w-full h-full bg-[#11182780]',
19
+ rootClassName,
20
+ )}
21
+ onClick={() => {
22
+ closeOutside ? setOpen(!open) : '';
23
+ }}
24
+ >
25
+ <div
26
+ className={cn(
27
+ 'relative p-4 w-full min-h-[360px] max-w-md max-h-full',
28
+ 'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-white rounded-lg',
29
+ className
30
+ )}
31
+ >
32
+
33
+ {children}
34
+ </div>
35
+ <style global jsx>
36
+ {`
37
+ body {
38
+ overflow: hidden !important;
39
+ }
40
+ `}
41
+ </style>
42
+ </div>
43
+ )}
44
+ </>
45
+ )
46
+ }
47
+
48
+ export default modal
@@ -0,0 +1 @@
1
+ export { default } from './productLineSlider';
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import cn from 'classnames';
3
+ import Image from '@magento/venia-ui/lib/components/Image';
4
+ import NendroidImage from './nendroid-image.png';
5
+ import NendroidLogo from './logo_nendoroid.png';
6
+
7
+ const Item = (props) => {
8
+ const {
9
+ name = 'Nendroid Series', rootClassName, onClick = () => { },
10
+ className = "",
11
+ } = props;
12
+
13
+ return (
14
+ <div className={cn('brand-item-container px-2 lg_px-4', rootClassName)} onClick={onClick}>
15
+ <div
16
+ className={cn(
17
+ 'm-auto flex flex-row justify-center items-center',
18
+ 'w-full max-w-[300px] px-5 py-2.5',
19
+ 'relative rounded-lg border border-gray-100 bg-white',
20
+ className,
21
+ )}
22
+ >
23
+ <Image
24
+ alt='image'
25
+ className="relative"
26
+ src={NendroidImage}
27
+ />
28
+ <Image
29
+ alt='logo'
30
+ className="relative"
31
+ src={NendroidLogo}
32
+ />
33
+ </div>
34
+ </div>
35
+ )
36
+ }
37
+
38
+ export default Item;
@@ -0,0 +1,91 @@
1
+ import React from 'react';
2
+ import Slider from "react-slick";
3
+ import { ArrowLeft2, ArrowRight2 } from 'iconsax-react';
4
+ import cn from 'classnames';
5
+ import Item from './item';
6
+ import { primary900 } from '@riosst100/pwa-marketplace/src/theme/vars';
7
+
8
+ const CustomArrow = (props) => {
9
+ const { isNext = true, onClick, className } = props;
10
+ return (
11
+ <span
12
+ className={cn(
13
+ className,
14
+ 'custom_arrow rounded-full w-10 h-10 p-2.5 bg-white hover_!bg-white z-[1] !border !border-solid !border-gray-100 before_hidden',
15
+ isNext ? 'right-2 lg_right-4' : 'left-2 lg_left-4',
16
+ )}
17
+ onClick={onClick}
18
+ >
19
+ {isNext ? (
20
+ <ArrowRight2 className='' size="20" color={primary900} />
21
+ ) : (
22
+ <ArrowLeft2 size="20" color={primary900} />
23
+ )}
24
+ </span>
25
+ )
26
+ }
27
+
28
+ const productSlider = (props) => {
29
+
30
+ const settings = {
31
+ dots: false,
32
+ infinite: false,
33
+ speed: 500,
34
+ slidesToShow: 4,
35
+ slidesToScroll: 1,
36
+ nextArrow: <CustomArrow />,
37
+ prevArrow: <CustomArrow isNext={false} />,
38
+ centerPadding: "60px",
39
+ responsive: [
40
+ {
41
+ breakpoint: 1023,
42
+ settings: {
43
+ slidesToShow: 3,
44
+ slidesToScroll: 1,
45
+ }
46
+ },
47
+ {
48
+ breakpoint: 767,
49
+ settings: {
50
+ slidesToShow: 3,
51
+ slidesToScroll: 1,
52
+ }
53
+ },
54
+ {
55
+ breakpoint: 576,
56
+ settings: {
57
+ slidesToShow: 2,
58
+ slidesToScroll: 1
59
+ }
60
+ }
61
+ ]
62
+ };
63
+ return (
64
+ <div className='product_line_items-container flex flex-col gap-x-4 gap-y-5 '>
65
+ <div className='text-[18px] font-medium'>
66
+ Product Line
67
+ </div>
68
+ <Slider {...settings}>
69
+ {[...Array(9)].map(() => {
70
+ return (
71
+ <Item {...props} />
72
+ )
73
+ })}
74
+ </Slider>
75
+ <style global jsx>
76
+ {`
77
+ .product_line_items-container .slick-slider {
78
+ margin: 0 -8px;
79
+ }
80
+ @media only screen and (min-width: 1024px) {
81
+ .product_line_items-container .slick-slider {
82
+ margin: 0 -16px;
83
+ }
84
+ }
85
+ `}
86
+ </style>
87
+ </div>
88
+ )
89
+ }
90
+
91
+ export default productSlider
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import Content from './share';
3
+ import { useToasts } from '@magento/peregrine';
4
+ import { Info } from 'react-feather';
5
+ import Icon from '@magento/venia-ui/lib/components/Icon';
6
+
7
+ const index = (props) => {
8
+
9
+ const [, { addToast }] = useToasts();
10
+
11
+ const InfoIcon = <Icon size={20} src={Info} />;
12
+
13
+ const location = window.location.href;
14
+ const encodedUrl = encodeURIComponent(location);
15
+ const subject = "Check out this awesome product!";
16
+ const messageCopyContent = "Link has been copied.";
17
+
18
+ const loginToastProps = {
19
+ type: 'info',
20
+ message: messageCopyContent,
21
+ timeout: 5000
22
+ }
23
+
24
+ const handleShareLink = (type) => {
25
+ switch (type) {
26
+ case 'wa':
27
+ window.open(`https://wa.me/?text=${encodedUrl}`);
28
+ break;
29
+ case 'fb':
30
+ window.open(`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(encodedUrl)}`);
31
+ break;
32
+ case 'email':
33
+ window.open(`mailto:?subject=${subject}&body=${encodedUrl}`);
34
+ break;
35
+ case 'link':
36
+ navigator.clipboard.writeText(location).then(() => {
37
+ addToast({ ...loginToastProps, icon: InfoIcon });
38
+ }, (err) => {
39
+ console.error('Failed to copy content:', err);
40
+ });
41
+ break;
42
+ default:
43
+ break;
44
+ }
45
+ }
46
+ return (
47
+ <Content handleShareLink={handleShareLink} {...props} />
48
+ )
49
+ }
50
+
51
+ export default index
@@ -0,0 +1,94 @@
1
+ import React from 'react';
2
+ import {
3
+ Sms, Whatsapp, Facebook, Link as LinkIcon
4
+ } from 'iconsax-react';
5
+ import cn from 'classnames';
6
+
7
+ const share = (props) => {
8
+ const { rootClassName, className, handleShareLink } = props
9
+ return (
10
+ <>
11
+ <div className={cn('button_share_group flex flex-wrap gap-4', rootClassName)}>
12
+ <button
13
+ type='button'
14
+ className={cn(
15
+ 'button_share border border-solid border-gray-100 p-2.5',
16
+ 'rounded-full flex justify-center items-center h-fitContent',
17
+ className
18
+ )}
19
+ onClick={() => {
20
+ handleShareLink('wa')
21
+ }}
22
+ >
23
+ <Whatsapp
24
+ size="20"
25
+ color="#25D366"
26
+ />
27
+ </button>
28
+ {/* <button
29
+ type='button'
30
+ className={cn(
31
+ 'button_share border border-solid border-gray-100 p-2.5',
32
+ 'rounded-full flex justify-center items-center h-fitContent',
33
+ className
34
+ )}
35
+ >
36
+ <Instagram
37
+ size="20"
38
+ color="#ee2a7b"
39
+ />
40
+ </button> */}
41
+ <button
42
+ type='button'
43
+ className={cn(
44
+ 'button_share border border-solid border-gray-100 p-2.5',
45
+ 'rounded-full flex justify-center items-center h-fitContent',
46
+ className
47
+ )}
48
+ onClick={() => {
49
+ handleShareLink('fb')
50
+ }}
51
+ >
52
+ <Facebook
53
+ size="20"
54
+ color="#4267B2"
55
+ />
56
+ </button>
57
+ <button
58
+ type='button'
59
+ className={cn(
60
+ 'button_share border border-solid border-gray-100 p-2.5',
61
+ 'rounded-full flex justify-center items-center h-fitContent',
62
+ className
63
+ )}
64
+ onClick={() => {
65
+ handleShareLink('email')
66
+ }}
67
+ >
68
+ <Sms
69
+ size="20"
70
+ color="#005947"
71
+ />
72
+ </button>
73
+ <button
74
+ type='button'
75
+ className={cn(
76
+ 'button_share border border-solid border-gray-100 p-2.5',
77
+ 'rounded-full flex justify-center items-center h-fitContent',
78
+ className
79
+ )}
80
+ onClick={() => {
81
+ handleShareLink('link')
82
+ }}
83
+ >
84
+ <LinkIcon
85
+ size="20"
86
+ color="#999999"
87
+ />
88
+ </button>
89
+ </div>
90
+ </>
91
+ )
92
+ }
93
+
94
+ export default share
package/src/intercept.js CHANGED
@@ -23,38 +23,38 @@ module.exports = targets => {
23
23
 
24
24
  // Tap into webpackCompiler
25
25
  targets.of('@magento/pwa-buildpack').webpackCompiler.tap(compiler => {
26
- // Check if the LocalizationPlugin is present
27
- if (compiler.options.plugins) {
28
- const localizationPlugin = compiler.options.plugins.find(
29
- plugin => plugin instanceof LocalizationPlugin
30
- );
26
+ // Check if the LocalizationPlugin is present
27
+ if (compiler.options.plugins) {
28
+ const localizationPlugin = compiler.options.plugins.find(
29
+ plugin => plugin instanceof LocalizationPlugin
30
+ );
31
31
 
32
- // Check if LocalizationPlugin is found
33
- if (localizationPlugin) {
34
- // Store the original mergeLocales function
35
- const originalMergeLocales = localizationPlugin.mergeLocales;
32
+ // Check if LocalizationPlugin is found
33
+ if (localizationPlugin) {
34
+ // Store the original mergeLocales function
35
+ const originalMergeLocales = localizationPlugin.mergeLocales;
36
36
 
37
- // Define your custom hook
38
- function myCustomMergeLocalesHook(current, update) {
39
- // Modify the mergedLocales data here
40
- Object.keys(update).forEach(key => {
41
- if (typeof current[key] === 'undefined') {
42
- current[key] = [];
43
- }
44
- if (Array.isArray(current[key]) && Array.isArray(update[key])) {
45
- if (update[key].toString().includes("venia-ui")) {
46
- delete update[key];
47
- }
48
- }
49
- });
50
-
51
- // Return the modified mergedLocales
52
- return originalMergeLocales.call(localizationPlugin, current, update);
37
+ // Define your custom hook
38
+ function myCustomMergeLocalesHook(current, update) {
39
+ // Modify the mergedLocales data here
40
+ Object.keys(update).forEach(key => {
41
+ if (typeof current[key] === 'undefined') {
42
+ current[key] = [];
43
+ }
44
+ if (Array.isArray(current[key]) && Array.isArray(update[key])) {
45
+ if (update[key].toString().includes("venia-ui")) {
46
+ delete update[key];
47
+ }
53
48
  }
49
+ });
54
50
 
55
- // Override mergeLocales with your custom hook
56
- localizationPlugin.mergeLocales = myCustomMergeLocalesHook;
51
+ // Return the modified mergedLocales
52
+ return originalMergeLocales.call(localizationPlugin, current, update);
57
53
  }
54
+
55
+ // Override mergeLocales with your custom hook
56
+ localizationPlugin.mergeLocales = myCustomMergeLocalesHook;
57
+ }
58
58
  }
59
59
  });
60
60
 
@@ -103,6 +103,20 @@ module.exports = targets => {
103
103
  path: require.resolve("./components/CollectibleGameSetsPage/index.js"),
104
104
  authed: false,
105
105
  },
106
+ {
107
+ exact: true,
108
+ name: "BrandListPage",
109
+ pattern: "/brands",
110
+ path: require.resolve("./components/BrandListPage/index.js"),
111
+ authed: false,
112
+ },
113
+ {
114
+ exact: true,
115
+ name: "BrandLandingPage",
116
+ pattern: "/brand",
117
+ path: require.resolve("./components/BrandLandingPage/index.js"),
118
+ authed: false,
119
+ },
106
120
  ];
107
121
 
108
122
  // Apply DefinePlugin using the results of the asynchronous operation
@@ -37,7 +37,7 @@ const CurrentFilter = props => {
37
37
  aria-label={ariaLabel}
38
38
  data-cy="CurrentFilter-trigger"
39
39
  >
40
- <Icon size={15} src={Remove} />
40
+ <Icon size={14} src={Remove} />
41
41
  </Trigger>
42
42
  <span className={classes.text}>
43
43
  {item.label ? item.label : item.title}
@@ -1,14 +1,15 @@
1
1
  .root {
2
2
  min-height: 24px;
3
- composes: bg-blue-700 from global;
4
- /* composes: font-semibold from global; */
3
+ composes: border from global;
4
+ composes: border-gray-100 from global;
5
+ composes: font-semibold from global;
5
6
  composes: gap-2xs from global;
6
7
  composes: grid-flow-col from global;
7
8
  composes: inline-grid from global;
8
9
  composes: items-center from global;
9
10
  composes: justify-center from global;
10
11
  composes: px-2 from global;
11
- composes: py-2 from global;
12
+ composes: py-1 from global;
12
13
  composes: rounded-md from global;
13
14
  /* composes: text-white from global; */
14
15
  composes: text-base from global;
@@ -17,5 +18,5 @@
17
18
  /* TODO @TW: cannot compose */
18
19
  .root svg {
19
20
  /* composes: stroke-white from global; */
20
- stroke: white;
21
+ stroke: rgb(var(--venia-global-color-gray-600));
21
22
  }
@@ -2,7 +2,9 @@
2
2
  composes: px-[10px] from global;
3
3
  composes: py-2 from global;
4
4
  composes: overflow-auto from global;
5
- composes: text-white from global;
5
+ composes: flex from global;
6
+ composes: flex-wrap from global;
7
+ composes: gap-2 from global;
6
8
  }
7
9
 
8
10
  /* TODO @TW: cannot compose */