@planningcenter/tapestry-react 2.5.1 → 2.6.0-rc.1
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/Portal/Portal.js +9 -1
- package/dist/cjs/ThemeProvider/ThemeProvider.js +4 -2
- package/dist/cjs/ThemeProvider/styles.js +26 -11
- package/dist/cjs/system/default-theme.js +1 -0
- package/dist/esm/Portal/Portal.js +8 -0
- package/dist/esm/ThemeProvider/ThemeProvider.js +5 -3
- package/dist/esm/ThemeProvider/styles.js +24 -11
- package/dist/esm/system/default-theme.js +3 -2
- package/dist/types/Portal/Portal.d.ts +3 -0
- package/dist/types/ThemeProvider/ThemeProvider.d.ts +1 -1
- package/dist/types/ThemeProvider/styles.d.ts +2 -1
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/Portal/Portal.tsx +11 -0
- package/src/ThemeProvider/ThemeProvider.tsx +8 -3
- package/src/ThemeProvider/styles.ts +32 -11
- package/src/index.d.ts +1 -0
- package/src/system/default-theme.ts +3 -2
|
@@ -19,6 +19,10 @@ var React = _interopRequireWildcard(require("react"));
|
|
|
19
19
|
|
|
20
20
|
var _reactDom = require("react-dom");
|
|
21
21
|
|
|
22
|
+
var _styles = require("../ThemeProvider/styles");
|
|
23
|
+
|
|
24
|
+
var _react2 = require("@emotion/react");
|
|
25
|
+
|
|
22
26
|
/** Accepts any additional HTML attributes. */
|
|
23
27
|
var Portal = /*#__PURE__*/function (_React$Component) {
|
|
24
28
|
(0, _inheritsLoose2["default"])(Portal, _React$Component);
|
|
@@ -31,6 +35,7 @@ var Portal = /*#__PURE__*/function (_React$Component) {
|
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
_this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
|
|
38
|
+
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "context", void 0);
|
|
34
39
|
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_portalNode", null);
|
|
35
40
|
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_needsUpdate", false);
|
|
36
41
|
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_updated", false);
|
|
@@ -125,6 +130,8 @@ var Portal = /*#__PURE__*/function (_React$Component) {
|
|
|
125
130
|
_this2._portalNode.setAttribute(key, restProps[key]);
|
|
126
131
|
});
|
|
127
132
|
|
|
133
|
+
this._portalNode.setAttribute((0, _styles.getThemeDataAttribute)(this.context.id), 'true');
|
|
134
|
+
|
|
128
135
|
if (style) {
|
|
129
136
|
Object.keys(style).forEach(function (key) {
|
|
130
137
|
_this2._portalNode.style[key] = style[key];
|
|
@@ -163,4 +170,5 @@ exports.Portal = Portal;
|
|
|
163
170
|
(0, _defineProperty2["default"])(Portal, "defaultProps", {
|
|
164
171
|
renderTag: 'div',
|
|
165
172
|
renderTo: null
|
|
166
|
-
});
|
|
173
|
+
});
|
|
174
|
+
(0, _defineProperty2["default"])(Portal, "contextType", _react2.ThemeContext);
|
|
@@ -75,6 +75,8 @@ function mergeThemes(a, b) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function ThemeProvider(_ref) {
|
|
78
|
+
var _ref2;
|
|
79
|
+
|
|
78
80
|
var _ref$theme = _ref.theme,
|
|
79
81
|
theme = _ref$theme === void 0 ? emptyTheme : _ref$theme,
|
|
80
82
|
children = _ref.children;
|
|
@@ -87,7 +89,7 @@ function ThemeProvider(_ref) {
|
|
|
87
89
|
|
|
88
90
|
(0, _react.useLayoutEffect)(function () {
|
|
89
91
|
var nextTheme = mergeThemes(_defaultTheme["default"], theme);
|
|
90
|
-
(0, _styles.setRootStyles)((0, _utils.objectToCSSProperties)('colors', nextTheme.colors));
|
|
92
|
+
(0, _styles.setRootStyles)(nextTheme.id, (0, _utils.objectToCSSProperties)('colors', nextTheme.colors));
|
|
91
93
|
|
|
92
94
|
if (!(0, _utils.shallowEqual)(mergedTheme, nextTheme)) {
|
|
93
95
|
setMergedTheme(nextTheme);
|
|
@@ -97,7 +99,7 @@ function ThemeProvider(_ref) {
|
|
|
97
99
|
value: cache
|
|
98
100
|
}, /*#__PURE__*/_react["default"].createElement(_react2.ThemeProvider, {
|
|
99
101
|
theme: mergedTheme
|
|
100
|
-
}, children));
|
|
102
|
+
}, /*#__PURE__*/_react["default"].createElement("div", (_ref2 = {}, _ref2["" + (0, _styles.getThemeDataAttribute)(mergedTheme.id)] = true, _ref2), children)));
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
ThemeProvider.cache = cache;
|
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
+
exports.getThemeDataAttribute = getThemeDataAttribute;
|
|
4
5
|
exports.styleReset = exports.defaultColorProperties = exports.setRootStyles = void 0;
|
|
5
6
|
|
|
6
7
|
var _system = require("../system");
|
|
7
8
|
|
|
8
9
|
var _utils = require("../utils");
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
function getThemeDataAttribute(themeId) {
|
|
12
|
+
if (themeId) {
|
|
13
|
+
return "data-tapestry-react-theme-provider-" + themeId;
|
|
14
|
+
} else {
|
|
15
|
+
return 'data-tapestry-react-theme-provider';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var getRootStyles = function getRootStyles(id, styles) {
|
|
11
20
|
var styleString = Object.keys(styles).map(function (key) {
|
|
12
21
|
return key + ": " + styles[key];
|
|
13
22
|
}).join('; ');
|
|
14
|
-
return "
|
|
23
|
+
return "[" + getThemeDataAttribute(id) + "] { " + styleString + " }";
|
|
15
24
|
};
|
|
16
25
|
|
|
17
|
-
var setRootStyles = function setRootStyles(styles) {
|
|
18
|
-
|
|
26
|
+
var setRootStyles = function setRootStyles(themeId, styles) {
|
|
27
|
+
ensureStyleElement(themeId);
|
|
28
|
+
var styleElement = document.getElementById("tapestry-react-style-" + themeId);
|
|
19
29
|
var sheet = styleElement.sheet;
|
|
20
|
-
var styleString = getRootStyles(styles);
|
|
30
|
+
var styleString = getRootStyles(themeId, styles);
|
|
21
31
|
sheet.deleteRule(0);
|
|
22
32
|
sheet.insertRule(styleString, 0);
|
|
23
33
|
};
|
|
@@ -25,16 +35,21 @@ var setRootStyles = function setRootStyles(styles) {
|
|
|
25
35
|
exports.setRootStyles = setRootStyles;
|
|
26
36
|
var defaultColorProperties = (0, _utils.objectToCSSProperties)('colors', (0, _system.flattenPalette)(_system.defaultTheme.colors));
|
|
27
37
|
exports.defaultColorProperties = defaultColorProperties;
|
|
28
|
-
var styleReset = ("\n" + getRootStyles(defaultColorProperties) + "\n\n.tapestry-react-reset {\n appearance: none;\n box-sizing: border-box;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';\n font-weight: 400;\n text-decoration: none;\n flex: 0 0 auto;\n min-width: 0px;\n min-height: 0px;\n padding: 0px;\n margin: 0px;\n border: 0px solid transparent;\n background-color: transparent;\n color: inherit;\n}\n\n.tapestry-react-reset::-moz-focus-inner {\n padding: 0px;\n border: 0px;\n}\n\n.tapestry-react-reset:focus:not(.focus-visible) {\n outline: 0px;\n}\n" // minify string
|
|
38
|
+
var styleReset = ("\n" + getRootStyles(null, defaultColorProperties) + "\n\n.tapestry-react-reset {\n appearance: none;\n box-sizing: border-box;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';\n font-weight: 400;\n text-decoration: none;\n flex: 0 0 auto;\n min-width: 0px;\n min-height: 0px;\n padding: 0px;\n margin: 0px;\n border: 0px solid transparent;\n background-color: transparent;\n color: inherit;\n}\n\n.tapestry-react-reset::-moz-focus-inner {\n padding: 0px;\n border: 0px;\n}\n\n.tapestry-react-reset:focus:not(.focus-visible) {\n outline: 0px;\n}\n" // minify string
|
|
29
39
|
).replace(/\n/g, '').replace(/\s\s+/g, ' '); // we use our own global style implementation in place of Emotion Global
|
|
30
40
|
// so we can have more control over when styles are injected since multiple
|
|
31
41
|
// Providers can be used on a page
|
|
32
42
|
|
|
33
43
|
exports.styleReset = styleReset;
|
|
34
44
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
function ensureStyleElement(themeId) {
|
|
46
|
+
// we use our own global style implementation in place of Emotion Global
|
|
47
|
+
// so we can have more control over when styles are injected since multiple
|
|
48
|
+
// Providers can be used on a page
|
|
49
|
+
if (typeof window !== 'undefined' && !document.getElementById("tapestry-react-style-" + themeId)) {
|
|
50
|
+
var styleElement = document.createElement('style');
|
|
51
|
+
styleElement.id = "tapestry-react-style-" + themeId;
|
|
52
|
+
styleElement.innerHTML = styleReset;
|
|
53
|
+
document.head.insertAdjacentElement('afterbegin', styleElement);
|
|
54
|
+
}
|
|
40
55
|
}
|
|
@@ -4,6 +4,8 @@ import _inheritsLoose from "@babel/runtime/helpers/esm/inheritsLoose";
|
|
|
4
4
|
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
|
+
import { getThemeDataAttribute } from '../ThemeProvider/styles';
|
|
8
|
+
import { ThemeContext } from '@emotion/react';
|
|
7
9
|
|
|
8
10
|
/** Accepts any additional HTML attributes. */
|
|
9
11
|
var Portal = /*#__PURE__*/function (_React$Component) {
|
|
@@ -18,6 +20,8 @@ var Portal = /*#__PURE__*/function (_React$Component) {
|
|
|
18
20
|
|
|
19
21
|
_this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
|
|
20
22
|
|
|
23
|
+
_defineProperty(_assertThisInitialized(_this), "context", void 0);
|
|
24
|
+
|
|
21
25
|
_defineProperty(_assertThisInitialized(_this), "_portalNode", null);
|
|
22
26
|
|
|
23
27
|
_defineProperty(_assertThisInitialized(_this), "_needsUpdate", false);
|
|
@@ -116,6 +120,8 @@ var Portal = /*#__PURE__*/function (_React$Component) {
|
|
|
116
120
|
_this2._portalNode.setAttribute(key, restProps[key]);
|
|
117
121
|
});
|
|
118
122
|
|
|
123
|
+
this._portalNode.setAttribute(getThemeDataAttribute(this.context.id), 'true');
|
|
124
|
+
|
|
119
125
|
if (style) {
|
|
120
126
|
Object.keys(style).forEach(function (key) {
|
|
121
127
|
_this2._portalNode.style[key] = style[key];
|
|
@@ -155,4 +161,6 @@ _defineProperty(Portal, "defaultProps", {
|
|
|
155
161
|
renderTo: null
|
|
156
162
|
});
|
|
157
163
|
|
|
164
|
+
_defineProperty(Portal, "contextType", ThemeContext);
|
|
165
|
+
|
|
158
166
|
export { Portal };
|
|
@@ -12,7 +12,7 @@ import { merge } from 'lodash';
|
|
|
12
12
|
import defaultTheme from '../system/default-theme';
|
|
13
13
|
import { flattenPalette } from '../system';
|
|
14
14
|
import { objectToCSSProperties, shallowEqual } from '../utils';
|
|
15
|
-
import { setRootStyles, styleReset } from './styles';
|
|
15
|
+
import { getThemeDataAttribute, setRootStyles, styleReset } from './styles';
|
|
16
16
|
var STORAGE_KEY = 'tapestry-react-theme';
|
|
17
17
|
export var cache = createCache({
|
|
18
18
|
key: 'tapestry-react'
|
|
@@ -52,6 +52,8 @@ function mergeThemes(a, b) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
export function ThemeProvider(_ref) {
|
|
55
|
+
var _ref2;
|
|
56
|
+
|
|
55
57
|
var _ref$theme = _ref.theme,
|
|
56
58
|
theme = _ref$theme === void 0 ? emptyTheme : _ref$theme,
|
|
57
59
|
children = _ref.children;
|
|
@@ -64,7 +66,7 @@ export function ThemeProvider(_ref) {
|
|
|
64
66
|
|
|
65
67
|
useLayoutEffect(function () {
|
|
66
68
|
var nextTheme = mergeThemes(defaultTheme, theme);
|
|
67
|
-
setRootStyles(objectToCSSProperties('colors', nextTheme.colors));
|
|
69
|
+
setRootStyles(nextTheme.id, objectToCSSProperties('colors', nextTheme.colors));
|
|
68
70
|
|
|
69
71
|
if (!shallowEqual(mergedTheme, nextTheme)) {
|
|
70
72
|
setMergedTheme(nextTheme);
|
|
@@ -74,7 +76,7 @@ export function ThemeProvider(_ref) {
|
|
|
74
76
|
value: cache
|
|
75
77
|
}, /*#__PURE__*/React.createElement(EmotionThemeProvider, {
|
|
76
78
|
theme: mergedTheme
|
|
77
|
-
}, children));
|
|
79
|
+
}, /*#__PURE__*/React.createElement("div", (_ref2 = {}, _ref2["" + getThemeDataAttribute(mergedTheme.id)] = true, _ref2), children)));
|
|
78
80
|
}
|
|
79
81
|
ThemeProvider.cache = cache;
|
|
80
82
|
ThemeProvider.setRootStyles = setRootStyles;
|
|
@@ -1,29 +1,42 @@
|
|
|
1
1
|
import { defaultTheme, flattenPalette } from '../system';
|
|
2
2
|
import { objectToCSSProperties } from '../utils';
|
|
3
|
+
export function getThemeDataAttribute(themeId) {
|
|
4
|
+
if (themeId) {
|
|
5
|
+
return "data-tapestry-react-theme-provider-" + themeId;
|
|
6
|
+
} else {
|
|
7
|
+
return 'data-tapestry-react-theme-provider';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
3
10
|
|
|
4
|
-
var getRootStyles = function getRootStyles(styles) {
|
|
11
|
+
var getRootStyles = function getRootStyles(id, styles) {
|
|
5
12
|
var styleString = Object.keys(styles).map(function (key) {
|
|
6
13
|
return key + ": " + styles[key];
|
|
7
14
|
}).join('; ');
|
|
8
|
-
return "
|
|
15
|
+
return "[" + getThemeDataAttribute(id) + "] { " + styleString + " }";
|
|
9
16
|
};
|
|
10
17
|
|
|
11
|
-
export var setRootStyles = function setRootStyles(styles) {
|
|
12
|
-
|
|
18
|
+
export var setRootStyles = function setRootStyles(themeId, styles) {
|
|
19
|
+
ensureStyleElement(themeId);
|
|
20
|
+
var styleElement = document.getElementById("tapestry-react-style-" + themeId);
|
|
13
21
|
var sheet = styleElement.sheet;
|
|
14
|
-
var styleString = getRootStyles(styles);
|
|
22
|
+
var styleString = getRootStyles(themeId, styles);
|
|
15
23
|
sheet.deleteRule(0);
|
|
16
24
|
sheet.insertRule(styleString, 0);
|
|
17
25
|
};
|
|
18
26
|
export var defaultColorProperties = objectToCSSProperties('colors', flattenPalette(defaultTheme.colors));
|
|
19
|
-
export var styleReset = ("\n" + getRootStyles(defaultColorProperties) + "\n\n.tapestry-react-reset {\n appearance: none;\n box-sizing: border-box;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';\n font-weight: 400;\n text-decoration: none;\n flex: 0 0 auto;\n min-width: 0px;\n min-height: 0px;\n padding: 0px;\n margin: 0px;\n border: 0px solid transparent;\n background-color: transparent;\n color: inherit;\n}\n\n.tapestry-react-reset::-moz-focus-inner {\n padding: 0px;\n border: 0px;\n}\n\n.tapestry-react-reset:focus:not(.focus-visible) {\n outline: 0px;\n}\n" // minify string
|
|
27
|
+
export var styleReset = ("\n" + getRootStyles(null, defaultColorProperties) + "\n\n.tapestry-react-reset {\n appearance: none;\n box-sizing: border-box;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';\n font-weight: 400;\n text-decoration: none;\n flex: 0 0 auto;\n min-width: 0px;\n min-height: 0px;\n padding: 0px;\n margin: 0px;\n border: 0px solid transparent;\n background-color: transparent;\n color: inherit;\n}\n\n.tapestry-react-reset::-moz-focus-inner {\n padding: 0px;\n border: 0px;\n}\n\n.tapestry-react-reset:focus:not(.focus-visible) {\n outline: 0px;\n}\n" // minify string
|
|
20
28
|
).replace(/\n/g, '').replace(/\s\s+/g, ' '); // we use our own global style implementation in place of Emotion Global
|
|
21
29
|
// so we can have more control over when styles are injected since multiple
|
|
22
30
|
// Providers can be used on a page
|
|
23
31
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
function ensureStyleElement(themeId) {
|
|
33
|
+
// we use our own global style implementation in place of Emotion Global
|
|
34
|
+
// so we can have more control over when styles are injected since multiple
|
|
35
|
+
// Providers can be used on a page
|
|
36
|
+
if (typeof window !== 'undefined' && !document.getElementById("tapestry-react-style-" + themeId)) {
|
|
37
|
+
var styleElement = document.createElement('style');
|
|
38
|
+
styleElement.id = "tapestry-react-style-" + themeId;
|
|
39
|
+
styleElement.innerHTML = styleReset;
|
|
40
|
+
document.head.insertAdjacentElement('afterbegin', styleElement);
|
|
41
|
+
}
|
|
29
42
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as general from
|
|
2
|
-
import * as tapestry from
|
|
1
|
+
import * as general from '@planningcenter/icons/paths/general';
|
|
2
|
+
import * as tapestry from '@planningcenter/icons/paths/tapestry';
|
|
3
3
|
import { boxSizes } from './box-sizes';
|
|
4
4
|
import { buttonThemes } from './button-themes';
|
|
5
5
|
import { colors } from './colors';
|
|
@@ -11,6 +11,7 @@ var controlStyles = {
|
|
|
11
11
|
checkedStroke: 'primary'
|
|
12
12
|
};
|
|
13
13
|
var defaultTheme = {
|
|
14
|
+
id: 'default',
|
|
14
15
|
boxSizes: boxSizes,
|
|
15
16
|
colors: colors,
|
|
16
17
|
icons: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { Theme } from '../index';
|
|
2
3
|
export declare type PortalProps = {
|
|
3
4
|
children: any;
|
|
4
5
|
/** Styles to apply to the portal root element. */
|
|
@@ -18,6 +19,8 @@ declare class Portal extends React.Component<PortalProps> {
|
|
|
18
19
|
renderTag: string;
|
|
19
20
|
renderTo: any;
|
|
20
21
|
};
|
|
22
|
+
static contextType: import("react").Context<object>;
|
|
23
|
+
context: React.ContextType<React.Context<Theme>>;
|
|
21
24
|
_portalNode: HTMLElement;
|
|
22
25
|
_needsUpdate: boolean;
|
|
23
26
|
_updated: boolean;
|
|
@@ -13,7 +13,7 @@ export declare function ThemeProvider({ theme, children, }: {
|
|
|
13
13
|
}): JSX.Element;
|
|
14
14
|
export declare namespace ThemeProvider {
|
|
15
15
|
var cache: import("@emotion/utils").EmotionCache;
|
|
16
|
-
var setRootStyles: (styles: any) => void;
|
|
16
|
+
var setRootStyles: (themeId: any, styles: any) => void;
|
|
17
17
|
var styleReset: string;
|
|
18
18
|
var themeInitializerScript: string;
|
|
19
19
|
var themeStorage: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare function getThemeDataAttribute(themeId: any): string;
|
|
2
|
+
export declare const setRootStyles: (themeId: any, styles: any) => void;
|
|
2
3
|
export declare const defaultColorProperties: any;
|
|
3
4
|
export declare const styleReset: string;
|
package/dist/types/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/tapestry-react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0-rc.1",
|
|
4
4
|
"description": "A collection of flexible React components to help you build resilient, accessible user interfaces quickly and effectively.",
|
|
5
5
|
"author": "Front End Systems Engineering <frontend@pco.bz>",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
package/src/Portal/Portal.tsx
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { createPortal } from 'react-dom'
|
|
3
|
+
import { getThemeDataAttribute } from '../ThemeProvider/styles'
|
|
4
|
+
import { ThemeContext } from '@emotion/react'
|
|
5
|
+
import { Theme } from '../index'
|
|
3
6
|
|
|
4
7
|
export type PortalProps = {
|
|
5
8
|
children: any
|
|
@@ -27,6 +30,9 @@ class Portal extends React.Component<PortalProps> {
|
|
|
27
30
|
renderTo: null,
|
|
28
31
|
}
|
|
29
32
|
|
|
33
|
+
static contextType = ThemeContext
|
|
34
|
+
context: React.ContextType<React.Context<Theme>>
|
|
35
|
+
|
|
30
36
|
_portalNode: HTMLElement = null
|
|
31
37
|
_needsUpdate = false
|
|
32
38
|
_updated = false
|
|
@@ -105,6 +111,11 @@ class Portal extends React.Component<PortalProps> {
|
|
|
105
111
|
Object.keys(restProps).forEach((key) => {
|
|
106
112
|
this._portalNode.setAttribute(key, restProps[key])
|
|
107
113
|
})
|
|
114
|
+
this._portalNode.setAttribute(
|
|
115
|
+
getThemeDataAttribute(this.context.id),
|
|
116
|
+
'true'
|
|
117
|
+
)
|
|
118
|
+
|
|
108
119
|
if (style) {
|
|
109
120
|
Object.keys(style).forEach((key) => {
|
|
110
121
|
this._portalNode.style[key] = style[key]
|
|
@@ -8,7 +8,7 @@ import defaultTheme from '../system/default-theme'
|
|
|
8
8
|
import { flattenPalette } from '../system'
|
|
9
9
|
import { Theme } from '../index'
|
|
10
10
|
import { objectToCSSProperties, shallowEqual } from '../utils'
|
|
11
|
-
import { setRootStyles, styleReset } from './styles'
|
|
11
|
+
import { getThemeDataAttribute, setRootStyles, styleReset } from './styles'
|
|
12
12
|
|
|
13
13
|
const STORAGE_KEY = 'tapestry-react-theme'
|
|
14
14
|
|
|
@@ -65,7 +65,10 @@ export function ThemeProvider({
|
|
|
65
65
|
)
|
|
66
66
|
useLayoutEffect(() => {
|
|
67
67
|
const nextTheme = mergeThemes(defaultTheme, theme)
|
|
68
|
-
setRootStyles(
|
|
68
|
+
setRootStyles(
|
|
69
|
+
nextTheme.id,
|
|
70
|
+
objectToCSSProperties('colors', nextTheme.colors)
|
|
71
|
+
)
|
|
69
72
|
if (!shallowEqual(mergedTheme, nextTheme)) {
|
|
70
73
|
setMergedTheme(nextTheme)
|
|
71
74
|
}
|
|
@@ -73,7 +76,9 @@ export function ThemeProvider({
|
|
|
73
76
|
return (
|
|
74
77
|
<CacheProvider value={cache}>
|
|
75
78
|
<EmotionThemeProvider theme={mergedTheme}>
|
|
76
|
-
{
|
|
79
|
+
<div {...{ [`${getThemeDataAttribute(mergedTheme.id)}`]: true }}>
|
|
80
|
+
{children}
|
|
81
|
+
</div>
|
|
77
82
|
</EmotionThemeProvider>
|
|
78
83
|
</CacheProvider>
|
|
79
84
|
)
|
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
import { defaultTheme, flattenPalette } from '../system'
|
|
2
2
|
import { objectToCSSProperties } from '../utils'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
export function getThemeDataAttribute(themeId) {
|
|
5
|
+
if (themeId) {
|
|
6
|
+
return `data-tapestry-react-theme-provider-${themeId}`
|
|
7
|
+
} else {
|
|
8
|
+
return 'data-tapestry-react-theme-provider'
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const getRootStyles = (id, styles) => {
|
|
5
13
|
const styleString = Object.keys(styles)
|
|
6
14
|
.map((key) => `${key}: ${styles[key]}`)
|
|
7
15
|
.join('; ')
|
|
8
|
-
|
|
16
|
+
|
|
17
|
+
return `[${getThemeDataAttribute(id)}] { ${styleString} }`
|
|
9
18
|
}
|
|
10
19
|
|
|
11
|
-
export const setRootStyles = (styles) => {
|
|
12
|
-
|
|
20
|
+
export const setRootStyles = (themeId, styles) => {
|
|
21
|
+
ensureStyleElement(themeId)
|
|
22
|
+
const styleElement = <HTMLStyleElement>(
|
|
23
|
+
document.getElementById(`tapestry-react-style-${themeId}`)
|
|
24
|
+
)
|
|
25
|
+
|
|
13
26
|
const sheet = <CSSStyleSheet>styleElement.sheet
|
|
14
|
-
const styleString = getRootStyles(styles)
|
|
27
|
+
const styleString = getRootStyles(themeId, styles)
|
|
15
28
|
sheet.deleteRule(0)
|
|
16
29
|
sheet.insertRule(styleString, 0)
|
|
17
30
|
}
|
|
@@ -22,7 +35,7 @@ export const defaultColorProperties = objectToCSSProperties(
|
|
|
22
35
|
)
|
|
23
36
|
|
|
24
37
|
export const styleReset = `
|
|
25
|
-
${getRootStyles(defaultColorProperties)}
|
|
38
|
+
${getRootStyles(null, defaultColorProperties)}
|
|
26
39
|
|
|
27
40
|
.tapestry-react-reset {
|
|
28
41
|
appearance: none;
|
|
@@ -56,9 +69,17 @@ ${getRootStyles(defaultColorProperties)}
|
|
|
56
69
|
// we use our own global style implementation in place of Emotion Global
|
|
57
70
|
// so we can have more control over when styles are injected since multiple
|
|
58
71
|
// Providers can be used on a page
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
72
|
+
function ensureStyleElement(themeId) {
|
|
73
|
+
// we use our own global style implementation in place of Emotion Global
|
|
74
|
+
// so we can have more control over when styles are injected since multiple
|
|
75
|
+
// Providers can be used on a page
|
|
76
|
+
if (
|
|
77
|
+
typeof window !== 'undefined' &&
|
|
78
|
+
!document.getElementById(`tapestry-react-style-${themeId}`)
|
|
79
|
+
) {
|
|
80
|
+
const styleElement = document.createElement('style')
|
|
81
|
+
styleElement.id = `tapestry-react-style-${themeId}`
|
|
82
|
+
styleElement.innerHTML = styleReset
|
|
83
|
+
document.head.insertAdjacentElement('afterbegin', styleElement)
|
|
84
|
+
}
|
|
64
85
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as general from
|
|
2
|
-
import * as tapestry from
|
|
1
|
+
import * as general from '@planningcenter/icons/paths/general'
|
|
2
|
+
import * as tapestry from '@planningcenter/icons/paths/tapestry'
|
|
3
3
|
|
|
4
4
|
import { Theme } from '../index'
|
|
5
5
|
|
|
@@ -16,6 +16,7 @@ const controlStyles = {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
const defaultTheme: Theme = {
|
|
19
|
+
id: 'default',
|
|
19
20
|
boxSizes,
|
|
20
21
|
colors,
|
|
21
22
|
icons: {
|