@telus-uds/components-base 1.68.0 → 1.70.0
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/CHANGELOG.md +25 -2
- package/lib/ExpandCollapse/Panel.js +1 -1
- package/lib/TextInput/TextInputBase.js +20 -17
- package/lib/utils/index.js +12 -0
- package/lib/utils/ssr-media-query/create-stylesheet.js +76 -0
- package/lib/utils/ssr-media-query/hash.js +19 -0
- package/lib/utils/ssr-media-query/index.js +19 -0
- package/lib/utils/ssr-media-query/utils/common.js +25 -0
- package/lib/utils/ssr-media-query/utils/create-declaration-block.js +24 -0
- package/lib/utils/ssr-media-query/utils/create-media-query-styles.js +34 -0
- package/lib/utils/ssr-media-query/utils/hyphenate-style-name.js +19 -0
- package/lib/utils/ssr-media-query/utils/inject.js +36 -0
- package/lib/utils/ssr.js +2 -1
- package/lib-module/ExpandCollapse/Panel.js +1 -1
- package/lib-module/TextInput/TextInputBase.js +20 -17
- package/lib-module/utils/index.js +1 -0
- package/lib-module/utils/ssr-media-query/create-stylesheet.js +68 -0
- package/lib-module/utils/ssr-media-query/hash.js +13 -0
- package/lib-module/utils/ssr-media-query/index.js +6 -0
- package/lib-module/utils/ssr-media-query/utils/common.js +15 -0
- package/lib-module/utils/ssr-media-query/utils/create-declaration-block.js +16 -0
- package/lib-module/utils/ssr-media-query/utils/create-media-query-styles.js +30 -0
- package/lib-module/utils/ssr-media-query/utils/hyphenate-style-name.js +12 -0
- package/lib-module/utils/ssr-media-query/utils/inject.js +26 -0
- package/lib-module/utils/ssr.js +3 -1
- package/package.json +3 -2
- package/src/ExpandCollapse/Panel.jsx +1 -1
- package/src/TextInput/TextInputBase.jsx +16 -8
- package/src/utils/index.js +1 -1
- package/src/utils/ssr-media-query/create-stylesheet.js +61 -0
- package/src/utils/ssr-media-query/hash.js +16 -0
- package/src/utils/ssr-media-query/index.js +8 -0
- package/src/utils/ssr-media-query/utils/common.js +20 -0
- package/src/utils/ssr-media-query/utils/create-declaration-block.js +21 -0
- package/src/utils/ssr-media-query/utils/create-media-query-styles.js +31 -0
- package/src/utils/ssr-media-query/utils/hyphenate-style-name.js +15 -0
- package/src/utils/ssr-media-query/utils/inject.js +30 -0
- package/src/utils/ssr.jsx +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,35 @@
|
|
|
1
1
|
# Change Log - @telus-uds/components-base
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Mon, 27 Nov 2023 21:13:27 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 1.70.0
|
|
8
|
+
|
|
9
|
+
Mon, 27 Nov 2023 21:13:27 GMT
|
|
10
|
+
|
|
11
|
+
### Minor changes
|
|
12
|
+
|
|
13
|
+
- Add SSR support for media queries (wlsdud194@hotmail.com)
|
|
14
|
+
|
|
15
|
+
## 1.69.0
|
|
16
|
+
|
|
17
|
+
Sat, 18 Nov 2023 02:32:49 GMT
|
|
18
|
+
|
|
19
|
+
### Minor changes
|
|
20
|
+
|
|
21
|
+
- updating notification stories (srikanthkhari@gmail.com)
|
|
22
|
+
- Bump @telus-uds/system-theme-tokens to v2.46.0
|
|
23
|
+
|
|
24
|
+
### Patches
|
|
25
|
+
|
|
26
|
+
- `TermsAndConditions`: Fix unexpected state handling in `ExpandCollapse.Panel` (shahzaibkhalidmalik@outlook.com)
|
|
27
|
+
- fixes to getIcon method for card variant in TextInput (email not defined)
|
|
28
|
+
- removing koodo rebrand iconset from supports (srikanthkhari@gmail.com)
|
|
29
|
+
|
|
7
30
|
## 1.68.0
|
|
8
31
|
|
|
9
|
-
Wed, 15 Nov 2023 18:
|
|
32
|
+
Wed, 15 Nov 2023 18:45:58 GMT
|
|
10
33
|
|
|
11
34
|
### Minor changes
|
|
12
35
|
|
|
@@ -174,7 +174,7 @@ const ExpandCollapsePanel = /*#__PURE__*/(0, _react.forwardRef)((_ref4, ref) =>
|
|
|
174
174
|
},
|
|
175
175
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
|
|
176
176
|
style: selectContainerStyles(themeTokens),
|
|
177
|
-
children: children
|
|
177
|
+
children: isExpanded ? children : null
|
|
178
178
|
})
|
|
179
179
|
})
|
|
180
180
|
})]
|
|
@@ -152,26 +152,29 @@ const getIcon = function () {
|
|
|
152
152
|
visaIcon,
|
|
153
153
|
masterCardIcon
|
|
154
154
|
} = arguments.length > 1 ? arguments[1] : undefined;
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
testID: 'amex'
|
|
163
|
-
},
|
|
164
|
-
4: {
|
|
165
|
-
icon: masterCardIcon,
|
|
166
|
-
testID: 'mastercard'
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
const firstDigit = cardNumber ? cardNumber[0] : '';
|
|
170
|
-
const defaultIcon = {
|
|
155
|
+
const sanitizedCardNumber = cardNumber.replace(/[^0-9]/g, '');
|
|
156
|
+
const firstFourDigits = sanitizedCardNumber.slice(0, 4);
|
|
157
|
+
const number = Number(firstFourDigits);
|
|
158
|
+
const visaRange = number >= 4000 && number <= 4999;
|
|
159
|
+
const amexRange = number >= 3400 && number <= 3499 || number >= 3700 && number <= 3799;
|
|
160
|
+
const masterCardRange = number >= 5100 && number <= 5599 || number >= 2221 && number <= 2720;
|
|
161
|
+
let selectedIcon = {
|
|
171
162
|
icon: defaultCreditIcon,
|
|
172
163
|
testID: 'default'
|
|
173
164
|
};
|
|
174
|
-
const
|
|
165
|
+
const objVisaIcon = {
|
|
166
|
+
icon: visaIcon,
|
|
167
|
+
testID: 'visa'
|
|
168
|
+
};
|
|
169
|
+
const objAmexIcon = {
|
|
170
|
+
icon: amexIcon,
|
|
171
|
+
testID: 'amex'
|
|
172
|
+
};
|
|
173
|
+
const objMasterCardIcon = {
|
|
174
|
+
icon: masterCardIcon,
|
|
175
|
+
testID: 'mastercard'
|
|
176
|
+
};
|
|
177
|
+
if (visaRange) selectedIcon = objVisaIcon;else if (amexRange) selectedIcon = objAmexIcon;else if (masterCardRange) selectedIcon = objMasterCardIcon;
|
|
175
178
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
|
|
176
179
|
icon: selectedIcon.icon,
|
|
177
180
|
variant: {
|
package/lib/utils/index.js
CHANGED
|
@@ -168,6 +168,18 @@ Object.keys(_props).forEach(function (key) {
|
|
|
168
168
|
}
|
|
169
169
|
});
|
|
170
170
|
});
|
|
171
|
+
var _ssrMediaQuery = require("./ssr-media-query");
|
|
172
|
+
Object.keys(_ssrMediaQuery).forEach(function (key) {
|
|
173
|
+
if (key === "default" || key === "__esModule") return;
|
|
174
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
175
|
+
if (key in exports && exports[key] === _ssrMediaQuery[key]) return;
|
|
176
|
+
Object.defineProperty(exports, key, {
|
|
177
|
+
enumerable: true,
|
|
178
|
+
get: function () {
|
|
179
|
+
return _ssrMediaQuery[key];
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
});
|
|
171
183
|
var _info = _interopRequireDefault(require("./info"));
|
|
172
184
|
var _useCopy = _interopRequireDefault(require("./useCopy"));
|
|
173
185
|
var _useHash = _interopRequireDefault(require("./useHash"));
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _cssMediaquery = _interopRequireDefault(require("css-mediaquery"));
|
|
8
|
+
var _Dimensions = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Dimensions"));
|
|
9
|
+
var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
|
|
10
|
+
var _inject = require("./utils/inject");
|
|
11
|
+
var _createDeclarationBlock = _interopRequireDefault(require("./utils/create-declaration-block"));
|
|
12
|
+
var _hash = _interopRequireDefault(require("./hash"));
|
|
13
|
+
var _common = require("./utils/common");
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
const createStyleSheet = stylesWithQuery => {
|
|
16
|
+
if (!stylesWithQuery) return {
|
|
17
|
+
ids: {},
|
|
18
|
+
styles: {},
|
|
19
|
+
fullStyles: {}
|
|
20
|
+
};
|
|
21
|
+
let cleanStyles;
|
|
22
|
+
let ids = {};
|
|
23
|
+
Object.keys(stylesWithQuery).forEach(key => {
|
|
24
|
+
if (!(stylesWithQuery !== null && stylesWithQuery !== void 0 && stylesWithQuery[key])) return;
|
|
25
|
+
const mediaQueriesAndPseudoClasses = Object.keys(stylesWithQuery[key]).filter(_common.isMediaOrPseudo);
|
|
26
|
+
if (_Platform.default.OS === 'web') {
|
|
27
|
+
cleanStyles = (0, _common.deepClone)(stylesWithQuery);
|
|
28
|
+
mediaQueriesAndPseudoClasses.forEach(query => {
|
|
29
|
+
var _ids;
|
|
30
|
+
const css = (0, _createDeclarationBlock.default)(stylesWithQuery[key][query]);
|
|
31
|
+
const stringHash = `rnmq-${(0, _hash.default)(`${key}${query}${css}`)}`;
|
|
32
|
+
const rule = (0, _common.createCssRule)(query, stringHash, css);
|
|
33
|
+
(0, _inject.addCss)(`${stringHash}`, rule);
|
|
34
|
+
delete cleanStyles[key][query];
|
|
35
|
+
ids = {
|
|
36
|
+
...ids,
|
|
37
|
+
[key]: `${(_ids = ids) !== null && _ids !== void 0 && _ids[key] ? `${ids[key]} ` : ''}${stringHash}`
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
} else {
|
|
41
|
+
cleanStyles = JSON.parse(JSON.stringify(stylesWithQuery));
|
|
42
|
+
mediaQueriesAndPseudoClasses.forEach(str => {
|
|
43
|
+
if ((0, _common.isMedia)(str)) {
|
|
44
|
+
const mqStr = str.replace('@media', '');
|
|
45
|
+
const {
|
|
46
|
+
width,
|
|
47
|
+
height
|
|
48
|
+
} = _Dimensions.default.get('window');
|
|
49
|
+
const isMatchingMediaQuery = _cssMediaquery.default.match(mqStr, {
|
|
50
|
+
width,
|
|
51
|
+
height,
|
|
52
|
+
orientation: width > height ? 'landscape' : 'portrait',
|
|
53
|
+
'aspect-ratio': width / height
|
|
54
|
+
});
|
|
55
|
+
if (isMatchingMediaQuery) {
|
|
56
|
+
cleanStyles = {
|
|
57
|
+
...cleanStyles,
|
|
58
|
+
[key]: {
|
|
59
|
+
...cleanStyles[key],
|
|
60
|
+
...stylesWithQuery[key][str]
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
delete cleanStyles[key][str];
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
ids,
|
|
71
|
+
styles: cleanStyles,
|
|
72
|
+
fullStyles: stylesWithQuery
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
var _default = createStyleSheet;
|
|
76
|
+
exports.default = _default;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = hash;
|
|
7
|
+
/* eslint-disable no-bitwise */
|
|
8
|
+
function hash(text) {
|
|
9
|
+
if (!text) {
|
|
10
|
+
return '';
|
|
11
|
+
}
|
|
12
|
+
let hashValue = 5381;
|
|
13
|
+
let index = text.length - 1;
|
|
14
|
+
while (index) {
|
|
15
|
+
hashValue = hashValue * 33 ^ text.charCodeAt(index);
|
|
16
|
+
index -= 1;
|
|
17
|
+
}
|
|
18
|
+
return (hashValue >>> 0).toString(16);
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.StyleSheet = void 0;
|
|
7
|
+
Object.defineProperty(exports, "createMediaQueryStyles", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () {
|
|
10
|
+
return _createMediaQueryStyles.default;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
var _createStylesheet = _interopRequireDefault(require("./create-stylesheet"));
|
|
14
|
+
var _createMediaQueryStyles = _interopRequireDefault(require("./utils/create-media-query-styles"));
|
|
15
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
|
+
const StyleSheet = {
|
|
17
|
+
create: _createStylesheet.default
|
|
18
|
+
};
|
|
19
|
+
exports.StyleSheet = StyleSheet;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.isPseudo = exports.isMediaOrPseudo = exports.isMedia = exports.deepClone = exports.createCssRule = void 0;
|
|
7
|
+
const isMedia = query => query.indexOf('@media') === 0;
|
|
8
|
+
exports.isMedia = isMedia;
|
|
9
|
+
const isPseudo = query => query.indexOf(':') === 0;
|
|
10
|
+
exports.isPseudo = isPseudo;
|
|
11
|
+
const isMediaOrPseudo = query => isMedia(query) || isPseudo(query);
|
|
12
|
+
exports.isMediaOrPseudo = isMediaOrPseudo;
|
|
13
|
+
const deepClone = obj => JSON.parse(JSON.stringify(obj));
|
|
14
|
+
exports.deepClone = deepClone;
|
|
15
|
+
const createCssRule = (query, stringHash, css) => {
|
|
16
|
+
let rule;
|
|
17
|
+
const dataMediaSelector = `[data-media~="${stringHash}"]`;
|
|
18
|
+
if (isMedia(query)) {
|
|
19
|
+
rule = `${query} {${dataMediaSelector} ${css}}`;
|
|
20
|
+
} else {
|
|
21
|
+
rule = `${dataMediaSelector}${query} ${css}`;
|
|
22
|
+
}
|
|
23
|
+
return rule;
|
|
24
|
+
};
|
|
25
|
+
exports.createCssRule = createCssRule;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _createReactDOMStyle = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet/compiler/createReactDOMStyle"));
|
|
8
|
+
var _prefixStyles = _interopRequireDefault(require("react-native-web/dist/cjs/modules/prefixStyles"));
|
|
9
|
+
var _hyphenateStyleName = _interopRequireDefault(require("./hyphenate-style-name"));
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
const createDeclarationBlock = style => {
|
|
12
|
+
const domStyle = (0, _prefixStyles.default)((0, _createReactDOMStyle.default)(style));
|
|
13
|
+
const declarationsString = Object.keys(domStyle).map(property => {
|
|
14
|
+
const value = domStyle[property];
|
|
15
|
+
const prop = (0, _hyphenateStyleName.default)(property);
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
return value.map(v => `${prop}:${v}`).join(';');
|
|
18
|
+
}
|
|
19
|
+
return `${prop}:${value} !important`;
|
|
20
|
+
}).sort().join(';');
|
|
21
|
+
return `{${declarationsString};}`;
|
|
22
|
+
};
|
|
23
|
+
var _default = createDeclarationBlock;
|
|
24
|
+
exports.default = _default;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _systemConstants = require("@telus-uds/system-constants");
|
|
8
|
+
/**
|
|
9
|
+
* @typedef { Object } CssStyles
|
|
10
|
+
* @typedef { Record<"xs" | "sm" | "md" | "lg" | "xl", CssStyles> } ViewportStyles
|
|
11
|
+
* @typedef { Record<String, CssStyles> } MediaQueryStyles
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Generates media query styles based on specified viewport styles.
|
|
15
|
+
* @param {ViewportStyles} viewportStyles
|
|
16
|
+
* @returns { MediaQueryStyles }
|
|
17
|
+
*/
|
|
18
|
+
function createMediaQueryStyles(viewportStyles) {
|
|
19
|
+
const viewportsArray = Object.keys(viewportStyles);
|
|
20
|
+
const mediaQueries = Object.entries(viewportStyles).reduce((acc, _ref) => {
|
|
21
|
+
let [viewport, styles] = _ref;
|
|
22
|
+
const minWidth = _systemConstants.viewports.map.get(viewport);
|
|
23
|
+
const nextViewport = viewportsArray[viewportsArray.indexOf(viewport) + 1];
|
|
24
|
+
const maxWidth = _systemConstants.viewports.map.get(nextViewport);
|
|
25
|
+
const mediaQuery = `@media (min-width: ${minWidth}px)${maxWidth ? ` and (max-width: ${maxWidth}px)` : ''}`;
|
|
26
|
+
return {
|
|
27
|
+
...acc,
|
|
28
|
+
[mediaQuery]: styles
|
|
29
|
+
};
|
|
30
|
+
}, {});
|
|
31
|
+
return mediaQueries;
|
|
32
|
+
}
|
|
33
|
+
var _default = createMediaQueryStyles;
|
|
34
|
+
exports.default = _default;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
const uppercasePattern = /[A-Z]/g;
|
|
8
|
+
const msPattern = /^ms-/;
|
|
9
|
+
const cache = {};
|
|
10
|
+
const toHyphenLower = match => `-${match.toLowerCase()}`;
|
|
11
|
+
const hyphenateStyleName = name => {
|
|
12
|
+
if (Object.prototype.hasOwnProperty.call(cache, name)) {
|
|
13
|
+
return cache[name];
|
|
14
|
+
}
|
|
15
|
+
const hName = name.replace(uppercasePattern, toHyphenLower);
|
|
16
|
+
return cache[name] === msPattern.test(hName) ? `-${hName}` : hName;
|
|
17
|
+
};
|
|
18
|
+
var _default = hyphenateStyleName;
|
|
19
|
+
exports.default = _default;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.hasCss = exports.flush = exports.addCss = void 0;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
|
|
9
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
+
const rules = {};
|
|
11
|
+
const hasCss = (id, text) => {
|
|
12
|
+
var _rules$id$text, _rules$id$text$includ;
|
|
13
|
+
return !!rules[id] && !!((_rules$id$text = rules[id].text) !== null && _rules$id$text !== void 0 && (_rules$id$text$includ = _rules$id$text.includes) !== null && _rules$id$text$includ !== void 0 && _rules$id$text$includ.call(_rules$id$text, text));
|
|
14
|
+
};
|
|
15
|
+
exports.hasCss = hasCss;
|
|
16
|
+
const addCss = (id, text) => {
|
|
17
|
+
if (!hasCss(id, text)) {
|
|
18
|
+
var _rules$id;
|
|
19
|
+
rules[id] = (rules === null || rules === void 0 ? void 0 : rules[id]) || {};
|
|
20
|
+
rules[id].text = (((_rules$id = rules[id]) === null || _rules$id === void 0 ? void 0 : _rules$id.text) || '') + text;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
exports.addCss = addCss;
|
|
24
|
+
const flush = () => {
|
|
25
|
+
if (_Platform.default.OS === 'web') {
|
|
26
|
+
return /*#__PURE__*/_react.default.createElement('style', {
|
|
27
|
+
id: 'rnmq',
|
|
28
|
+
key: 'rnmq',
|
|
29
|
+
dangerouslySetInnerHTML: {
|
|
30
|
+
__html: Object.keys(rules).map(key => rules[key].text).join('\n')
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return {};
|
|
35
|
+
};
|
|
36
|
+
exports.flush = flush;
|
package/lib/utils/ssr.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.ssrStyles = exports.getSSRStyles = exports.getReactNativeWebSSRStyles = exports.default = void 0;
|
|
7
7
|
var _react = _interopRequireDefault(require("react"));
|
|
8
8
|
var _AppRegistry = _interopRequireDefault(require("react-native-web/dist/cjs/exports/AppRegistry"));
|
|
9
|
+
var _inject = require("./ssr-media-query/utils/inject");
|
|
9
10
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
11
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
12
|
/** @typedef {import('react').ComponentType} ReactComponent */
|
|
@@ -102,7 +103,7 @@ const ssrStyles = function () {
|
|
|
102
103
|
for (var _len = arguments.length, existingStyles = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
103
104
|
existingStyles[_key] = arguments[_key];
|
|
104
105
|
}
|
|
105
|
-
return [...existingStyles, ...styleGetters.flatMap(getter => getter())];
|
|
106
|
+
return [...existingStyles, ...styleGetters.flatMap(getter => getter()), (0, _inject.flush)()];
|
|
106
107
|
}
|
|
107
108
|
};
|
|
108
109
|
};
|
|
@@ -144,26 +144,29 @@ const getIcon = function () {
|
|
|
144
144
|
visaIcon,
|
|
145
145
|
masterCardIcon
|
|
146
146
|
} = arguments.length > 1 ? arguments[1] : undefined;
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
testID: 'amex'
|
|
155
|
-
},
|
|
156
|
-
4: {
|
|
157
|
-
icon: masterCardIcon,
|
|
158
|
-
testID: 'mastercard'
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
const firstDigit = cardNumber ? cardNumber[0] : '';
|
|
162
|
-
const defaultIcon = {
|
|
147
|
+
const sanitizedCardNumber = cardNumber.replace(/[^0-9]/g, '');
|
|
148
|
+
const firstFourDigits = sanitizedCardNumber.slice(0, 4);
|
|
149
|
+
const number = Number(firstFourDigits);
|
|
150
|
+
const visaRange = number >= 4000 && number <= 4999;
|
|
151
|
+
const amexRange = number >= 3400 && number <= 3499 || number >= 3700 && number <= 3799;
|
|
152
|
+
const masterCardRange = number >= 5100 && number <= 5599 || number >= 2221 && number <= 2720;
|
|
153
|
+
let selectedIcon = {
|
|
163
154
|
icon: defaultCreditIcon,
|
|
164
155
|
testID: 'default'
|
|
165
156
|
};
|
|
166
|
-
const
|
|
157
|
+
const objVisaIcon = {
|
|
158
|
+
icon: visaIcon,
|
|
159
|
+
testID: 'visa'
|
|
160
|
+
};
|
|
161
|
+
const objAmexIcon = {
|
|
162
|
+
icon: amexIcon,
|
|
163
|
+
testID: 'amex'
|
|
164
|
+
};
|
|
165
|
+
const objMasterCardIcon = {
|
|
166
|
+
icon: masterCardIcon,
|
|
167
|
+
testID: 'mastercard'
|
|
168
|
+
};
|
|
169
|
+
if (visaRange) selectedIcon = objVisaIcon;else if (amexRange) selectedIcon = objAmexIcon;else if (masterCardRange) selectedIcon = objMasterCardIcon;
|
|
167
170
|
return /*#__PURE__*/_jsx(Icon, {
|
|
168
171
|
icon: selectedIcon.icon,
|
|
169
172
|
variant: {
|
|
@@ -4,6 +4,7 @@ export * from './children';
|
|
|
4
4
|
export * from './input';
|
|
5
5
|
export * from './pressability';
|
|
6
6
|
export * from './props';
|
|
7
|
+
export * from './ssr-media-query';
|
|
7
8
|
export { default as info } from './info';
|
|
8
9
|
export { default as useCopy } from './useCopy';
|
|
9
10
|
export { default as useHash } from './useHash';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import mediaQuery from 'css-mediaquery';
|
|
2
|
+
import Dimensions from "react-native-web/dist/exports/Dimensions";
|
|
3
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
4
|
+
import { addCss } from './utils/inject';
|
|
5
|
+
import createDeclarationBlock from './utils/create-declaration-block';
|
|
6
|
+
import hash from './hash';
|
|
7
|
+
import { isMediaOrPseudo, isMedia, deepClone, createCssRule } from './utils/common';
|
|
8
|
+
const createStyleSheet = stylesWithQuery => {
|
|
9
|
+
if (!stylesWithQuery) return {
|
|
10
|
+
ids: {},
|
|
11
|
+
styles: {},
|
|
12
|
+
fullStyles: {}
|
|
13
|
+
};
|
|
14
|
+
let cleanStyles;
|
|
15
|
+
let ids = {};
|
|
16
|
+
Object.keys(stylesWithQuery).forEach(key => {
|
|
17
|
+
if (!(stylesWithQuery !== null && stylesWithQuery !== void 0 && stylesWithQuery[key])) return;
|
|
18
|
+
const mediaQueriesAndPseudoClasses = Object.keys(stylesWithQuery[key]).filter(isMediaOrPseudo);
|
|
19
|
+
if (Platform.OS === 'web') {
|
|
20
|
+
cleanStyles = deepClone(stylesWithQuery);
|
|
21
|
+
mediaQueriesAndPseudoClasses.forEach(query => {
|
|
22
|
+
var _ids;
|
|
23
|
+
const css = createDeclarationBlock(stylesWithQuery[key][query]);
|
|
24
|
+
const stringHash = `rnmq-${hash(`${key}${query}${css}`)}`;
|
|
25
|
+
const rule = createCssRule(query, stringHash, css);
|
|
26
|
+
addCss(`${stringHash}`, rule);
|
|
27
|
+
delete cleanStyles[key][query];
|
|
28
|
+
ids = {
|
|
29
|
+
...ids,
|
|
30
|
+
[key]: `${(_ids = ids) !== null && _ids !== void 0 && _ids[key] ? `${ids[key]} ` : ''}${stringHash}`
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
cleanStyles = JSON.parse(JSON.stringify(stylesWithQuery));
|
|
35
|
+
mediaQueriesAndPseudoClasses.forEach(str => {
|
|
36
|
+
if (isMedia(str)) {
|
|
37
|
+
const mqStr = str.replace('@media', '');
|
|
38
|
+
const {
|
|
39
|
+
width,
|
|
40
|
+
height
|
|
41
|
+
} = Dimensions.get('window');
|
|
42
|
+
const isMatchingMediaQuery = mediaQuery.match(mqStr, {
|
|
43
|
+
width,
|
|
44
|
+
height,
|
|
45
|
+
orientation: width > height ? 'landscape' : 'portrait',
|
|
46
|
+
'aspect-ratio': width / height
|
|
47
|
+
});
|
|
48
|
+
if (isMatchingMediaQuery) {
|
|
49
|
+
cleanStyles = {
|
|
50
|
+
...cleanStyles,
|
|
51
|
+
[key]: {
|
|
52
|
+
...cleanStyles[key],
|
|
53
|
+
...stylesWithQuery[key][str]
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
delete cleanStyles[key][str];
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return {
|
|
63
|
+
ids,
|
|
64
|
+
styles: cleanStyles,
|
|
65
|
+
fullStyles: stylesWithQuery
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
export default createStyleSheet;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/* eslint-disable no-bitwise */
|
|
2
|
+
export default function hash(text) {
|
|
3
|
+
if (!text) {
|
|
4
|
+
return '';
|
|
5
|
+
}
|
|
6
|
+
let hashValue = 5381;
|
|
7
|
+
let index = text.length - 1;
|
|
8
|
+
while (index) {
|
|
9
|
+
hashValue = hashValue * 33 ^ text.charCodeAt(index);
|
|
10
|
+
index -= 1;
|
|
11
|
+
}
|
|
12
|
+
return (hashValue >>> 0).toString(16);
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const isMedia = query => query.indexOf('@media') === 0;
|
|
2
|
+
const isPseudo = query => query.indexOf(':') === 0;
|
|
3
|
+
const isMediaOrPseudo = query => isMedia(query) || isPseudo(query);
|
|
4
|
+
const deepClone = obj => JSON.parse(JSON.stringify(obj));
|
|
5
|
+
const createCssRule = (query, stringHash, css) => {
|
|
6
|
+
let rule;
|
|
7
|
+
const dataMediaSelector = `[data-media~="${stringHash}"]`;
|
|
8
|
+
if (isMedia(query)) {
|
|
9
|
+
rule = `${query} {${dataMediaSelector} ${css}}`;
|
|
10
|
+
} else {
|
|
11
|
+
rule = `${dataMediaSelector}${query} ${css}`;
|
|
12
|
+
}
|
|
13
|
+
return rule;
|
|
14
|
+
};
|
|
15
|
+
export { isMedia, isPseudo, isMediaOrPseudo, deepClone, createCssRule };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import createReactDOMStyle from 'react-native-web/dist/cjs/exports/StyleSheet/compiler/createReactDOMStyle';
|
|
2
|
+
import prefixStyles from 'react-native-web/dist/cjs/modules/prefixStyles';
|
|
3
|
+
import hyphenateStyleName from './hyphenate-style-name';
|
|
4
|
+
const createDeclarationBlock = style => {
|
|
5
|
+
const domStyle = prefixStyles(createReactDOMStyle(style));
|
|
6
|
+
const declarationsString = Object.keys(domStyle).map(property => {
|
|
7
|
+
const value = domStyle[property];
|
|
8
|
+
const prop = hyphenateStyleName(property);
|
|
9
|
+
if (Array.isArray(value)) {
|
|
10
|
+
return value.map(v => `${prop}:${v}`).join(';');
|
|
11
|
+
}
|
|
12
|
+
return `${prop}:${value} !important`;
|
|
13
|
+
}).sort().join(';');
|
|
14
|
+
return `{${declarationsString};}`;
|
|
15
|
+
};
|
|
16
|
+
export default createDeclarationBlock;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { viewports } from '@telus-uds/system-constants';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef { Object } CssStyles
|
|
5
|
+
* @typedef { Record<"xs" | "sm" | "md" | "lg" | "xl", CssStyles> } ViewportStyles
|
|
6
|
+
* @typedef { Record<String, CssStyles> } MediaQueryStyles
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generates media query styles based on specified viewport styles.
|
|
11
|
+
* @param {ViewportStyles} viewportStyles
|
|
12
|
+
* @returns { MediaQueryStyles }
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
function createMediaQueryStyles(viewportStyles) {
|
|
16
|
+
const viewportsArray = Object.keys(viewportStyles);
|
|
17
|
+
const mediaQueries = Object.entries(viewportStyles).reduce((acc, _ref) => {
|
|
18
|
+
let [viewport, styles] = _ref;
|
|
19
|
+
const minWidth = viewports.map.get(viewport);
|
|
20
|
+
const nextViewport = viewportsArray[viewportsArray.indexOf(viewport) + 1];
|
|
21
|
+
const maxWidth = viewports.map.get(nextViewport);
|
|
22
|
+
const mediaQuery = `@media (min-width: ${minWidth}px)${maxWidth ? ` and (max-width: ${maxWidth}px)` : ''}`;
|
|
23
|
+
return {
|
|
24
|
+
...acc,
|
|
25
|
+
[mediaQuery]: styles
|
|
26
|
+
};
|
|
27
|
+
}, {});
|
|
28
|
+
return mediaQueries;
|
|
29
|
+
}
|
|
30
|
+
export default createMediaQueryStyles;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const uppercasePattern = /[A-Z]/g;
|
|
2
|
+
const msPattern = /^ms-/;
|
|
3
|
+
const cache = {};
|
|
4
|
+
const toHyphenLower = match => `-${match.toLowerCase()}`;
|
|
5
|
+
const hyphenateStyleName = name => {
|
|
6
|
+
if (Object.prototype.hasOwnProperty.call(cache, name)) {
|
|
7
|
+
return cache[name];
|
|
8
|
+
}
|
|
9
|
+
const hName = name.replace(uppercasePattern, toHyphenLower);
|
|
10
|
+
return cache[name] === msPattern.test(hName) ? `-${hName}` : hName;
|
|
11
|
+
};
|
|
12
|
+
export default hyphenateStyleName;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
3
|
+
const rules = {};
|
|
4
|
+
export const hasCss = (id, text) => {
|
|
5
|
+
var _rules$id$text, _rules$id$text$includ;
|
|
6
|
+
return !!rules[id] && !!((_rules$id$text = rules[id].text) !== null && _rules$id$text !== void 0 && (_rules$id$text$includ = _rules$id$text.includes) !== null && _rules$id$text$includ !== void 0 && _rules$id$text$includ.call(_rules$id$text, text));
|
|
7
|
+
};
|
|
8
|
+
export const addCss = (id, text) => {
|
|
9
|
+
if (!hasCss(id, text)) {
|
|
10
|
+
var _rules$id;
|
|
11
|
+
rules[id] = (rules === null || rules === void 0 ? void 0 : rules[id]) || {};
|
|
12
|
+
rules[id].text = (((_rules$id = rules[id]) === null || _rules$id === void 0 ? void 0 : _rules$id.text) || '') + text;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export const flush = () => {
|
|
16
|
+
if (Platform.OS === 'web') {
|
|
17
|
+
return /*#__PURE__*/React.createElement('style', {
|
|
18
|
+
id: 'rnmq',
|
|
19
|
+
key: 'rnmq',
|
|
20
|
+
dangerouslySetInnerHTML: {
|
|
21
|
+
__html: Object.keys(rules).map(key => rules[key].text).join('\n')
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return {};
|
|
26
|
+
};
|
package/lib-module/utils/ssr.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import AppRegistry from "react-native-web/dist/exports/AppRegistry";
|
|
3
|
+
import { flush } from './ssr-media-query/utils/inject';
|
|
3
4
|
/** @typedef {import('react').ComponentType} ReactComponent */
|
|
4
5
|
/** @typedef {import('react').ReactElement} ReactElement */
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Returns object with `renderApp` and `getStyles` functions.
|
|
7
9
|
* Weave these into your app's server-side render process:
|
|
@@ -94,7 +96,7 @@ export const ssrStyles = function () {
|
|
|
94
96
|
for (var _len = arguments.length, existingStyles = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
95
97
|
existingStyles[_key] = arguments[_key];
|
|
96
98
|
}
|
|
97
|
-
return [...existingStyles, ...styleGetters.flatMap(getter => getter())];
|
|
99
|
+
return [...existingStyles, ...styleGetters.flatMap(getter => getter()), flush()];
|
|
98
100
|
}
|
|
99
101
|
};
|
|
100
102
|
};
|
package/package.json
CHANGED
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
"@floating-ui/react-native": "^0.8.1",
|
|
12
12
|
"@gorhom/portal": "^1.0.14",
|
|
13
13
|
"@telus-uds/system-constants": "^1.3.0",
|
|
14
|
-
"@telus-uds/system-theme-tokens": "^2.
|
|
14
|
+
"@telus-uds/system-theme-tokens": "^2.46.0",
|
|
15
15
|
"airbnb-prop-types": "^2.16.0",
|
|
16
|
+
"css-mediaquery": "^0.1.2",
|
|
16
17
|
"lodash.debounce": "^4.0.8",
|
|
17
18
|
"lodash.merge": "^4.6.2",
|
|
18
19
|
"lodash.throttle": "^4.1.1",
|
|
@@ -73,5 +74,5 @@
|
|
|
73
74
|
"standard-engine": {
|
|
74
75
|
"skip": true
|
|
75
76
|
},
|
|
76
|
-
"version": "1.
|
|
77
|
+
"version": "1.70.0"
|
|
77
78
|
}
|
|
@@ -168,7 +168,7 @@ const ExpandCollapsePanel = forwardRef(
|
|
|
168
168
|
})
|
|
169
169
|
}}
|
|
170
170
|
>
|
|
171
|
-
<View style={selectContainerStyles(themeTokens)}>{children}</View>
|
|
171
|
+
<View style={selectContainerStyles(themeTokens)}>{isExpanded ? children : null}</View>
|
|
172
172
|
</View>
|
|
173
173
|
</Animated.View>
|
|
174
174
|
</View>
|
|
@@ -141,15 +141,23 @@ const selectButtonsContainerStyle = ({ buttonsPaddingRight }) => ({
|
|
|
141
141
|
})
|
|
142
142
|
|
|
143
143
|
const getIcon = (cardNumber = '', { defaultCreditIcon, amexIcon, visaIcon, masterCardIcon }) => {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
144
|
+
const sanitizedCardNumber = cardNumber.replace(/[^0-9]/g, '')
|
|
145
|
+
const firstFourDigits = sanitizedCardNumber.slice(0, 4)
|
|
146
|
+
const number = Number(firstFourDigits)
|
|
147
|
+
|
|
148
|
+
const visaRange = number >= 4000 && number <= 4999
|
|
149
|
+
const amexRange = (number >= 3400 && number <= 3499) || (number >= 3700 && number <= 3799)
|
|
150
|
+
const masterCardRange = (number >= 5100 && number <= 5599) || (number >= 2221 && number <= 2720)
|
|
151
|
+
|
|
152
|
+
let selectedIcon = { icon: defaultCreditIcon, testID: 'default' }
|
|
153
|
+
const objVisaIcon = { icon: visaIcon, testID: 'visa' }
|
|
154
|
+
const objAmexIcon = { icon: amexIcon, testID: 'amex' }
|
|
155
|
+
const objMasterCardIcon = { icon: masterCardIcon, testID: 'mastercard' }
|
|
156
|
+
|
|
157
|
+
if (visaRange) selectedIcon = objVisaIcon
|
|
158
|
+
else if (amexRange) selectedIcon = objAmexIcon
|
|
159
|
+
else if (masterCardRange) selectedIcon = objMasterCardIcon
|
|
149
160
|
|
|
150
|
-
const firstDigit = cardNumber ? cardNumber[0] : ''
|
|
151
|
-
const defaultIcon = { icon: defaultCreditIcon, testID: 'default' }
|
|
152
|
-
const selectedIcon = cardNumber.length > 4 ? cardType[firstDigit] || defaultIcon : defaultIcon
|
|
153
161
|
return <Icon icon={selectedIcon.icon} variant={{ size: 'large' }} testID={selectedIcon.testID} />
|
|
154
162
|
}
|
|
155
163
|
|
package/src/utils/index.js
CHANGED
|
@@ -4,7 +4,7 @@ export * from './children'
|
|
|
4
4
|
export * from './input'
|
|
5
5
|
export * from './pressability'
|
|
6
6
|
export * from './props'
|
|
7
|
-
|
|
7
|
+
export * from './ssr-media-query'
|
|
8
8
|
export { default as info } from './info'
|
|
9
9
|
export { default as useCopy } from './useCopy'
|
|
10
10
|
export { default as useHash } from './useHash'
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import mediaQuery from 'css-mediaquery'
|
|
2
|
+
import { Dimensions, Platform } from 'react-native'
|
|
3
|
+
import { addCss } from './utils/inject'
|
|
4
|
+
import createDeclarationBlock from './utils/create-declaration-block'
|
|
5
|
+
import hash from './hash'
|
|
6
|
+
import { isMediaOrPseudo, isMedia, deepClone, createCssRule } from './utils/common'
|
|
7
|
+
|
|
8
|
+
const createStyleSheet = (stylesWithQuery) => {
|
|
9
|
+
if (!stylesWithQuery) return { ids: {}, styles: {}, fullStyles: {} }
|
|
10
|
+
let cleanStyles
|
|
11
|
+
let ids = {}
|
|
12
|
+
Object.keys(stylesWithQuery).forEach((key) => {
|
|
13
|
+
if (!stylesWithQuery?.[key]) return
|
|
14
|
+
|
|
15
|
+
const mediaQueriesAndPseudoClasses = Object.keys(stylesWithQuery[key]).filter(isMediaOrPseudo)
|
|
16
|
+
if (Platform.OS === 'web') {
|
|
17
|
+
cleanStyles = deepClone(stylesWithQuery)
|
|
18
|
+
mediaQueriesAndPseudoClasses.forEach((query) => {
|
|
19
|
+
const css = createDeclarationBlock(stylesWithQuery[key][query])
|
|
20
|
+
const stringHash = `rnmq-${hash(`${key}${query}${css}`)}`
|
|
21
|
+
const rule = createCssRule(query, stringHash, css)
|
|
22
|
+
|
|
23
|
+
addCss(`${stringHash}`, rule)
|
|
24
|
+
delete cleanStyles[key][query]
|
|
25
|
+
|
|
26
|
+
ids = {
|
|
27
|
+
...ids,
|
|
28
|
+
[key]: `${ids?.[key] ? `${ids[key]} ` : ''}${stringHash}`
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
} else {
|
|
32
|
+
cleanStyles = JSON.parse(JSON.stringify(stylesWithQuery))
|
|
33
|
+
mediaQueriesAndPseudoClasses.forEach((str) => {
|
|
34
|
+
if (isMedia(str)) {
|
|
35
|
+
const mqStr = str.replace('@media', '')
|
|
36
|
+
const { width, height } = Dimensions.get('window')
|
|
37
|
+
|
|
38
|
+
const isMatchingMediaQuery = mediaQuery.match(mqStr, {
|
|
39
|
+
width,
|
|
40
|
+
height,
|
|
41
|
+
orientation: width > height ? 'landscape' : 'portrait',
|
|
42
|
+
'aspect-ratio': width / height
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
if (isMatchingMediaQuery) {
|
|
46
|
+
cleanStyles = {
|
|
47
|
+
...cleanStyles,
|
|
48
|
+
[key]: { ...cleanStyles[key], ...stylesWithQuery[key][str] }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
delete cleanStyles[key][str]
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
return { ids, styles: cleanStyles, fullStyles: stylesWithQuery }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default createStyleSheet
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/* eslint-disable no-bitwise */
|
|
2
|
+
export default function hash(text) {
|
|
3
|
+
if (!text) {
|
|
4
|
+
return ''
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let hashValue = 5381
|
|
8
|
+
let index = text.length - 1
|
|
9
|
+
|
|
10
|
+
while (index) {
|
|
11
|
+
hashValue = (hashValue * 33) ^ text.charCodeAt(index)
|
|
12
|
+
index -= 1
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return (hashValue >>> 0).toString(16)
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const isMedia = (query) => query.indexOf('@media') === 0
|
|
2
|
+
const isPseudo = (query) => query.indexOf(':') === 0
|
|
3
|
+
const isMediaOrPseudo = (query) => isMedia(query) || isPseudo(query)
|
|
4
|
+
|
|
5
|
+
const deepClone = (obj) => JSON.parse(JSON.stringify(obj))
|
|
6
|
+
|
|
7
|
+
const createCssRule = (query, stringHash, css) => {
|
|
8
|
+
let rule
|
|
9
|
+
const dataMediaSelector = `[data-media~="${stringHash}"]`
|
|
10
|
+
|
|
11
|
+
if (isMedia(query)) {
|
|
12
|
+
rule = `${query} {${dataMediaSelector} ${css}}`
|
|
13
|
+
} else {
|
|
14
|
+
rule = `${dataMediaSelector}${query} ${css}`
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return rule
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { isMedia, isPseudo, isMediaOrPseudo, deepClone, createCssRule }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import createReactDOMStyle from 'react-native-web/dist/cjs/exports/StyleSheet/compiler/createReactDOMStyle'
|
|
2
|
+
import prefixStyles from 'react-native-web/dist/cjs/modules/prefixStyles'
|
|
3
|
+
import hyphenateStyleName from './hyphenate-style-name'
|
|
4
|
+
|
|
5
|
+
const createDeclarationBlock = (style) => {
|
|
6
|
+
const domStyle = prefixStyles(createReactDOMStyle(style))
|
|
7
|
+
const declarationsString = Object.keys(domStyle)
|
|
8
|
+
.map((property) => {
|
|
9
|
+
const value = domStyle[property]
|
|
10
|
+
const prop = hyphenateStyleName(property)
|
|
11
|
+
if (Array.isArray(value)) {
|
|
12
|
+
return value.map((v) => `${prop}:${v}`).join(';')
|
|
13
|
+
}
|
|
14
|
+
return `${prop}:${value} !important`
|
|
15
|
+
})
|
|
16
|
+
.sort()
|
|
17
|
+
.join(';')
|
|
18
|
+
return `{${declarationsString};}`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default createDeclarationBlock
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { viewports } from '@telus-uds/system-constants'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef { Object } CssStyles
|
|
5
|
+
* @typedef { Record<"xs" | "sm" | "md" | "lg" | "xl", CssStyles> } ViewportStyles
|
|
6
|
+
* @typedef { Record<String, CssStyles> } MediaQueryStyles
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generates media query styles based on specified viewport styles.
|
|
11
|
+
* @param {ViewportStyles} viewportStyles
|
|
12
|
+
* @returns { MediaQueryStyles }
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
function createMediaQueryStyles(viewportStyles) {
|
|
16
|
+
const viewportsArray = Object.keys(viewportStyles)
|
|
17
|
+
const mediaQueries = Object.entries(viewportStyles).reduce((acc, [viewport, styles]) => {
|
|
18
|
+
const minWidth = viewports.map.get(viewport)
|
|
19
|
+
const nextViewport = viewportsArray[viewportsArray.indexOf(viewport) + 1]
|
|
20
|
+
const maxWidth = viewports.map.get(nextViewport)
|
|
21
|
+
|
|
22
|
+
const mediaQuery = `@media (min-width: ${minWidth}px)${
|
|
23
|
+
maxWidth ? ` and (max-width: ${maxWidth}px)` : ''
|
|
24
|
+
}`
|
|
25
|
+
return { ...acc, [mediaQuery]: styles }
|
|
26
|
+
}, {})
|
|
27
|
+
|
|
28
|
+
return mediaQueries
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default createMediaQueryStyles
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const uppercasePattern = /[A-Z]/g
|
|
2
|
+
const msPattern = /^ms-/
|
|
3
|
+
const cache = {}
|
|
4
|
+
|
|
5
|
+
const toHyphenLower = (match) => `-${match.toLowerCase()}`
|
|
6
|
+
|
|
7
|
+
const hyphenateStyleName = (name) => {
|
|
8
|
+
if (Object.prototype.hasOwnProperty.call(cache, name)) {
|
|
9
|
+
return cache[name]
|
|
10
|
+
}
|
|
11
|
+
const hName = name.replace(uppercasePattern, toHyphenLower)
|
|
12
|
+
return cache[name] === msPattern.test(hName) ? `-${hName}` : hName
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default hyphenateStyleName
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Platform } from 'react-native'
|
|
3
|
+
|
|
4
|
+
const rules = {}
|
|
5
|
+
|
|
6
|
+
export const hasCss = (id, text) => {
|
|
7
|
+
return !!rules[id] && !!rules[id].text?.includes?.(text)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const addCss = (id, text) => {
|
|
11
|
+
if (!hasCss(id, text)) {
|
|
12
|
+
rules[id] = rules?.[id] || {}
|
|
13
|
+
rules[id].text = (rules[id]?.text || '') + text
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const flush = () => {
|
|
18
|
+
if (Platform.OS === 'web') {
|
|
19
|
+
return React.createElement('style', {
|
|
20
|
+
id: 'rnmq',
|
|
21
|
+
key: 'rnmq',
|
|
22
|
+
dangerouslySetInnerHTML: {
|
|
23
|
+
__html: Object.keys(rules)
|
|
24
|
+
.map((key) => rules[key].text)
|
|
25
|
+
.join('\n')
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
return {}
|
|
30
|
+
}
|
package/src/utils/ssr.jsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { AppRegistry } from 'react-native'
|
|
3
|
+
import { flush } from './ssr-media-query/utils/inject'
|
|
3
4
|
/** @typedef {import('react').ComponentType} ReactComponent */
|
|
4
5
|
/** @typedef {import('react').ReactElement} ReactElement */
|
|
5
6
|
|
|
@@ -80,7 +81,8 @@ export const ssrStyles = (appName = 'UDS app', { styleGetters = [], collectStyle
|
|
|
80
81
|
*/
|
|
81
82
|
getStyles: (...existingStyles) => {
|
|
82
83
|
if (!hasAppRendered) throw new Error('Called getStyles before renderApp in ssrStyles')
|
|
83
|
-
|
|
84
|
+
|
|
85
|
+
return [...existingStyles, ...styleGetters.flatMap((getter) => getter()), flush()]
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
}
|