diff --git a/.gitignore b/.gitignore index f8c8df105..02f2ad202 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ esm examples/**/yarn.lock examples/**/out examples/**/.next +examples/**/node_modules diff --git a/package.json b/package.json index 6c8f49055..ee2009db3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geist-ui/core", - "version": "2.2.3", + "version": "2.2.4", "main": "dist/index.js", "module": "esm/index.js", "types": "esm/index.d.ts", @@ -38,10 +38,11 @@ "now-build": "yarn run docs-build", "build:rollup": "rollup -c scripts/rollup.config.js", "build:webpack": "webpack --config scripts/webpack.config.js", - "build:after": "node scripts/fix-styled-jsx.js", + "build:babel": "babel --config-file ./scripts/babel.config.js --extensions \".js,.ts,.tsx\" ./components --out-dir ./esm --ignore \"**/__tests__/**/*,**/*.d.ts\"", + "build:after": "node scripts/move-built-in.js", "build:types": "ttsc -p ./scripts & ttsc -p ./scripts --outDir ./esm", "build:esm-entry": "babel --config-file ./scripts/babel.config.js ./components/index.ts -o ./esm/index.js", - "build": "yarn clear && yarn build:rollup && yarn build:esm-entry && yarn build:types && yarn build:after", + "build": "yarn clear && yarn build:rollup && yarn build:babel && yarn build:types && yarn build:after", "release": "yarn build && yarn publish --access public --non-interactive" }, "files": [ @@ -50,13 +51,12 @@ ], "devDependencies": { "@babel/cli": "^7.14.5", - "@babel/runtime": "^7.16.7", "@babel/plugin-transform-runtime": "^7.14.5", "@babel/preset-env": "^7.14.7", "@babel/preset-react": "^7.14.5", "@babel/preset-typescript": "^7.14.5", - "@geist-ui/prettier-config": "^1.0.1", "@geist-ui/icons": "^1.0.1", + "@geist-ui/prettier-config": "^1.0.1", "@mapbox/rehype-prism": "^0.6.0", "@mdx-js/loader": "^1.6.22", "@next/mdx": "^12.0.8", @@ -71,15 +71,14 @@ "@types/react": "^17.0.38", "@types/react-color": "^3.0.4", "@types/react-dom": "^17.0.11", - "@types/styled-jsx": "^3.4.4", "@typescript-eslint/eslint-plugin": "^4.27.0", "@typescript-eslint/parser": "^4.27.0", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.2", "babel-jest": "^27.0.5", + "babel-plugin-transform-rename-import": "^2.3.0", "css-mediaquery": "^0.1.2", "enzyme": "^3.11.0", "eslint": "^7.29.0", - "styled-jsx": "^4.0.1", "eslint-config-prettier": "^6.11.0", "eslint-config-ts-lambdas": "^1.2.3", "eslint-plugin-react": "^7.22.0", @@ -103,6 +102,8 @@ "typescript-transform-paths": "^3.3.1" }, "dependencies": { + "@babel/runtime": "^7.16.7", + "styled-jsx": "4.0.1" }, "peerDependencies": { "react": ">=16.9.0", diff --git a/scripts/babel.config.js b/scripts/babel.config.js index 69ca71268..3ae176e7c 100644 --- a/scripts/babel.config.js +++ b/scripts/babel.config.js @@ -14,6 +14,16 @@ module.exports = { 'styled-jsx/babel', ['@babel/plugin-proposal-object-rest-spread', { loose: true }], ['@babel/plugin-transform-runtime', { useESModules: true }], + [ + 'transform-rename-import', + { + replacements: [ + { original: 'styled-jsx/style', replacement: '../styled-jsx.es.js' }, + { original: 'styled-jsx/server', replacement: '../styled-jsx-server.es.js' }, + ], + }, + ], ], + ignore: [/@babel[\\|/]runtime/], } diff --git a/scripts/built-in/styled-jsx-server.es.js b/scripts/built-in/styled-jsx-server.es.js new file mode 100644 index 000000000..3d56d3da5 --- /dev/null +++ b/scripts/built-in/styled-jsx-server.es.js @@ -0,0 +1,4 @@ +import { server } from './styled-jsx.es' + +export { server } +export default server diff --git a/scripts/built-in/styled-jsx.cjs.js b/scripts/built-in/styled-jsx.cjs.js new file mode 100644 index 000000000..f3132130f --- /dev/null +++ b/scripts/built-in/styled-jsx.cjs.js @@ -0,0 +1,748 @@ +'use strict' + +var React = require('react') + +function _interopDefaultLegacy(e) { + return e && typeof e === 'object' && 'default' in e ? e : { default: e } +} + +var React__default = /*#__PURE__*/ _interopDefaultLegacy(React) + +var style$1 = {} + +var stylesheetRegistry = {} + +function hash(str) { + var hash = 5381, + i = str.length + + while (i) { + hash = (hash * 33) ^ str.charCodeAt(--i) + } + + /* JavaScript does bitwise operations (like XOR, above) on 32-bit signed + * integers. Since we want the results to be always positive, convert the + * signed int to an unsigned by doing an unsigned bitshift. */ + return hash >>> 0 +} + +var stringHash = hash + +var stylesheet = {} + +;(function (exports) { + exports.__esModule = true + exports['default'] = void 0 + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i] + descriptor.enumerable = descriptor.enumerable || false + descriptor.configurable = true + if ('value' in descriptor) descriptor.writable = true + Object.defineProperty(target, descriptor.key, descriptor) + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps) + if (staticProps) _defineProperties(Constructor, staticProps) + return Constructor + } + + /* +Based on Glamor's sheet +https://github.com/threepointone/glamor/blob/667b480d31b3721a905021b26e1290ce92ca2879/src/sheet.js +*/ + var isProd = + typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'production' + + var isString = function isString(o) { + return Object.prototype.toString.call(o) === '[object String]' + } + + var StyleSheet = /*#__PURE__*/ (function () { + function StyleSheet(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + _ref$name = _ref.name, + name = _ref$name === void 0 ? 'stylesheet' : _ref$name, + _ref$optimizeForSpeed = _ref.optimizeForSpeed, + optimizeForSpeed = + _ref$optimizeForSpeed === void 0 ? isProd : _ref$optimizeForSpeed, + _ref$isBrowser = _ref.isBrowser, + isBrowser = + _ref$isBrowser === void 0 ? typeof window !== 'undefined' : _ref$isBrowser + + invariant(isString(name), '`name` must be a string') + this._name = name + this._deletedRulePlaceholder = '#' + name + '-deleted-rule____{}' + invariant( + typeof optimizeForSpeed === 'boolean', + '`optimizeForSpeed` must be a boolean', + ) + this._optimizeForSpeed = optimizeForSpeed + this._isBrowser = isBrowser + this._serverSheet = undefined + this._tags = [] + this._injected = false + this._rulesCount = 0 + var node = this._isBrowser && document.querySelector('meta[property="csp-nonce"]') + this._nonce = node ? node.getAttribute('content') : null + } + + var _proto = StyleSheet.prototype + + _proto.setOptimizeForSpeed = function setOptimizeForSpeed(bool) { + invariant(typeof bool === 'boolean', '`setOptimizeForSpeed` accepts a boolean') + invariant( + this._rulesCount === 0, + 'optimizeForSpeed cannot be when rules have already been inserted', + ) + this.flush() + this._optimizeForSpeed = bool + this.inject() + } + + _proto.isOptimizeForSpeed = function isOptimizeForSpeed() { + return this._optimizeForSpeed + } + + _proto.inject = function inject() { + var _this = this + + invariant(!this._injected, 'sheet already injected') + this._injected = true + + if (this._isBrowser && this._optimizeForSpeed) { + this._tags[0] = this.makeStyleTag(this._name) + this._optimizeForSpeed = 'insertRule' in this.getSheet() + + if (!this._optimizeForSpeed) { + if (!isProd) { + console.warn( + 'StyleSheet: optimizeForSpeed mode not supported falling back to standard mode.', + ) + } + + this.flush() + this._injected = true + } + + return + } + + this._serverSheet = { + cssRules: [], + insertRule: function insertRule(rule, index) { + if (typeof index === 'number') { + _this._serverSheet.cssRules[index] = { + cssText: rule, + } + } else { + _this._serverSheet.cssRules.push({ + cssText: rule, + }) + } + + return index + }, + deleteRule: function deleteRule(index) { + _this._serverSheet.cssRules[index] = null + }, + } + } + + _proto.getSheetForTag = function getSheetForTag(tag) { + if (tag.sheet) { + return tag.sheet + } // this weirdness brought to you by firefox + + for (var i = 0; i < document.styleSheets.length; i++) { + if (document.styleSheets[i].ownerNode === tag) { + return document.styleSheets[i] + } + } + } + + _proto.getSheet = function getSheet() { + return this.getSheetForTag(this._tags[this._tags.length - 1]) + } + + _proto.insertRule = function insertRule(rule, index) { + invariant(isString(rule), '`insertRule` accepts only strings') + + if (!this._isBrowser) { + if (typeof index !== 'number') { + index = this._serverSheet.cssRules.length + } + + this._serverSheet.insertRule(rule, index) + + return this._rulesCount++ + } + + if (this._optimizeForSpeed) { + var sheet = this.getSheet() + + if (typeof index !== 'number') { + index = sheet.cssRules.length + } // this weirdness for perf, and chrome's weird bug + // https://stackoverflow.com/questions/20007992/chrome-suddenly-stopped-accepting-insertrule + + try { + sheet.insertRule(rule, index) + } catch (error) { + if (!isProd) { + console.warn( + 'StyleSheet: illegal rule: \n\n' + + rule + + '\n\nSee https://stackoverflow.com/q/20007992 for more info', + ) + } + + return -1 + } + } else { + var insertionPoint = this._tags[index] + + this._tags.push(this.makeStyleTag(this._name, rule, insertionPoint)) + } + + return this._rulesCount++ + } + + _proto.replaceRule = function replaceRule(index, rule) { + if (this._optimizeForSpeed || !this._isBrowser) { + var sheet = this._isBrowser ? this.getSheet() : this._serverSheet + + if (!rule.trim()) { + rule = this._deletedRulePlaceholder + } + + if (!sheet.cssRules[index]) { + // @TBD Should we throw an error? + return index + } + + sheet.deleteRule(index) + + try { + sheet.insertRule(rule, index) + } catch (error) { + if (!isProd) { + console.warn( + 'StyleSheet: illegal rule: \n\n' + + rule + + '\n\nSee https://stackoverflow.com/q/20007992 for more info', + ) + } // In order to preserve the indices we insert a deleteRulePlaceholder + + sheet.insertRule(this._deletedRulePlaceholder, index) + } + } else { + var tag = this._tags[index] + invariant(tag, 'old rule at index `' + index + '` not found') + tag.textContent = rule + } + + return index + } + + _proto.deleteRule = function deleteRule(index) { + if (!this._isBrowser) { + this._serverSheet.deleteRule(index) + + return + } + + if (this._optimizeForSpeed) { + this.replaceRule(index, '') + } else { + var tag = this._tags[index] + invariant(tag, 'rule at index `' + index + '` not found') + tag.parentNode.removeChild(tag) + this._tags[index] = null + } + } + + _proto.flush = function flush() { + this._injected = false + this._rulesCount = 0 + + if (this._isBrowser) { + this._tags.forEach(function (tag) { + return tag && tag.parentNode.removeChild(tag) + }) + + this._tags = [] + } else { + // simpler on server + this._serverSheet.cssRules = [] + } + } + + _proto.cssRules = function cssRules() { + var _this2 = this + + if (!this._isBrowser) { + return this._serverSheet.cssRules + } + + return this._tags.reduce(function (rules, tag) { + if (tag) { + rules = rules.concat( + Array.prototype.map.call( + _this2.getSheetForTag(tag).cssRules, + function (rule) { + return rule.cssText === _this2._deletedRulePlaceholder ? null : rule + }, + ), + ) + } else { + rules.push(null) + } + + return rules + }, []) + } + + _proto.makeStyleTag = function makeStyleTag(name, cssString, relativeToTag) { + if (cssString) { + invariant( + isString(cssString), + 'makeStyleTag acceps only strings as second parameter', + ) + } + + var tag = document.createElement('style') + if (this._nonce) tag.setAttribute('nonce', this._nonce) + tag.type = 'text/css' + tag.setAttribute('data-' + name, '') + + if (cssString) { + tag.appendChild(document.createTextNode(cssString)) + } + + var head = document.head || document.getElementsByTagName('head')[0] + + if (relativeToTag) { + head.insertBefore(tag, relativeToTag) + } else { + head.appendChild(tag) + } + + return tag + } + + _createClass(StyleSheet, [ + { + key: 'length', + get: function get() { + return this._rulesCount + }, + }, + ]) + + return StyleSheet + })() + + exports['default'] = StyleSheet + + function invariant(condition, message) { + if (!condition) { + throw new Error('StyleSheet: ' + message + '.') + } + } +})(stylesheet) + +;(function (exports) { + exports.__esModule = true + exports['default'] = void 0 + + var _stringHash = _interopRequireDefault(stringHash) + + var _stylesheet = _interopRequireDefault(stylesheet) + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: obj } + } + + var sanitize = function sanitize(rule) { + return rule.replace(/\/style/gi, '\\/style') + } + + var StyleSheetRegistry = /*#__PURE__*/ (function () { + function StyleSheetRegistry(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + _ref$styleSheet = _ref.styleSheet, + styleSheet = _ref$styleSheet === void 0 ? null : _ref$styleSheet, + _ref$optimizeForSpeed = _ref.optimizeForSpeed, + optimizeForSpeed = + _ref$optimizeForSpeed === void 0 ? false : _ref$optimizeForSpeed, + _ref$isBrowser = _ref.isBrowser, + isBrowser = + _ref$isBrowser === void 0 ? typeof window !== 'undefined' : _ref$isBrowser + + this._sheet = + styleSheet || + new _stylesheet['default']({ + name: 'styled-jsx', + optimizeForSpeed: optimizeForSpeed, + }) + + this._sheet.inject() + + if (styleSheet && typeof optimizeForSpeed === 'boolean') { + this._sheet.setOptimizeForSpeed(optimizeForSpeed) + + this._optimizeForSpeed = this._sheet.isOptimizeForSpeed() + } + + this._isBrowser = isBrowser + this._fromServer = undefined + this._indices = {} + this._instancesCounts = {} + this.computeId = this.createComputeId() + this.computeSelector = this.createComputeSelector() + } + + var _proto = StyleSheetRegistry.prototype + + _proto.add = function add(props) { + var _this = this + + if (undefined === this._optimizeForSpeed) { + this._optimizeForSpeed = Array.isArray(props.children) + + this._sheet.setOptimizeForSpeed(this._optimizeForSpeed) + + this._optimizeForSpeed = this._sheet.isOptimizeForSpeed() + } + + if (this._isBrowser && !this._fromServer) { + this._fromServer = this.selectFromServer() + this._instancesCounts = Object.keys(this._fromServer).reduce(function ( + acc, + tagName, + ) { + acc[tagName] = 0 + return acc + }, + {}) + } + + var _this$getIdAndRules = this.getIdAndRules(props), + styleId = _this$getIdAndRules.styleId, + rules = _this$getIdAndRules.rules // Deduping: just increase the instances count. + + if (styleId in this._instancesCounts) { + this._instancesCounts[styleId] += 1 + return + } + + var indices = rules + .map(function (rule) { + return _this._sheet.insertRule(rule) + }) // Filter out invalid rules + .filter(function (index) { + return index !== -1 + }) + this._indices[styleId] = indices + this._instancesCounts[styleId] = 1 + } + + _proto.remove = function remove(props) { + var _this2 = this + + var _this$getIdAndRules2 = this.getIdAndRules(props), + styleId = _this$getIdAndRules2.styleId + + invariant(styleId in this._instancesCounts, 'styleId: `' + styleId + '` not found') + this._instancesCounts[styleId] -= 1 + + if (this._instancesCounts[styleId] < 1) { + var tagFromServer = this._fromServer && this._fromServer[styleId] + + if (tagFromServer) { + tagFromServer.parentNode.removeChild(tagFromServer) + delete this._fromServer[styleId] + } else { + this._indices[styleId].forEach(function (index) { + return _this2._sheet.deleteRule(index) + }) + + delete this._indices[styleId] + } + + delete this._instancesCounts[styleId] + } + } + + _proto.update = function update(props, nextProps) { + this.add(nextProps) + this.remove(props) + } + + _proto.flush = function flush() { + this._sheet.flush() + + this._sheet.inject() + + this._fromServer = undefined + this._indices = {} + this._instancesCounts = {} + this.computeId = this.createComputeId() + this.computeSelector = this.createComputeSelector() + } + + _proto.cssRules = function cssRules() { + var _this3 = this + + var fromServer = this._fromServer + ? Object.keys(this._fromServer).map(function (styleId) { + return [styleId, _this3._fromServer[styleId]] + }) + : [] + + var cssRules = this._sheet.cssRules() + + return fromServer.concat( + Object.keys(this._indices) + .map(function (styleId) { + return [ + styleId, + _this3._indices[styleId] + .map(function (index) { + return cssRules[index].cssText + }) + .join(_this3._optimizeForSpeed ? '' : '\n'), + ] + }) // filter out empty rules + .filter(function (rule) { + return Boolean(rule[1]) + }), + ) + } + /** + * createComputeId + * + * Creates a function to compute and memoize a jsx id from a basedId and optionally props. + */ + + _proto.createComputeId = function createComputeId() { + var cache = {} + return function (baseId, props) { + if (!props) { + return 'jsx-' + baseId + } + + var propsToString = String(props) + var key = baseId + propsToString // return `jsx-${hashString(`${baseId}-${propsToString}`)}` + + if (!cache[key]) { + cache[key] = 'jsx-' + (0, _stringHash['default'])(baseId + '-' + propsToString) + } + + return cache[key] + } + } + /** + * createComputeSelector + * + * Creates a function to compute and memoize dynamic selectors. + */ + + _proto.createComputeSelector = function createComputeSelector( + selectoPlaceholderRegexp, + ) { + if (selectoPlaceholderRegexp === void 0) { + selectoPlaceholderRegexp = /__jsx-style-dynamic-selector/g + } + + var cache = {} + return function (id, css) { + // Sanitize SSR-ed CSS. + // Client side code doesn't need to be sanitized since we use + // document.createTextNode (dev) and the CSSOM api sheet.insertRule (prod). + if (!this._isBrowser) { + css = sanitize(css) + } + + var idcss = id + css + + if (!cache[idcss]) { + cache[idcss] = css.replace(selectoPlaceholderRegexp, id) + } + + return cache[idcss] + } + } + + _proto.getIdAndRules = function getIdAndRules(props) { + var _this4 = this + + var css = props.children, + dynamic = props.dynamic, + id = props.id + + if (dynamic) { + var styleId = this.computeId(id, dynamic) + return { + styleId: styleId, + rules: Array.isArray(css) + ? css.map(function (rule) { + return _this4.computeSelector(styleId, rule) + }) + : [this.computeSelector(styleId, css)], + } + } + + return { + styleId: this.computeId(id), + rules: Array.isArray(css) ? css : [css], + } + } + /** + * selectFromServer + * + * Collects style tags from the document with id __jsx-XXX + */ + + _proto.selectFromServer = function selectFromServer() { + var elements = Array.prototype.slice.call( + document.querySelectorAll('[id^="__jsx-"]'), + ) + return elements.reduce(function (acc, element) { + var id = element.id.slice(2) + acc[id] = element + return acc + }, {}) + } + + return StyleSheetRegistry + })() + + exports['default'] = StyleSheetRegistry + + function invariant(condition, message) { + if (!condition) { + throw new Error('StyleSheetRegistry: ' + message + '.') + } + } +})(stylesheetRegistry) + +;(function (exports) { + exports.__esModule = true + exports['default'] = JSXStyle + exports.flush = flush + + var _react = React__default['default'] + + var _stylesheetRegistry = _interopRequireDefault(stylesheetRegistry) + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: obj } + } + + var styleSheetRegistry = new _stylesheetRegistry['default']() + + function JSXStyle(props) { + if (typeof window === 'undefined') { + styleSheetRegistry.add(props) + return null + } + + ;(0, _react.useLayoutEffect)( + function () { + styleSheetRegistry.add(props) + return function () { + styleSheetRegistry.remove(props) + } // props.children can be string[], will be striped since id is identical + }, + [props.id, String(props.dynamic)], + ) + return null + } + + JSXStyle.dynamic = function (info) { + return info + .map(function (tagInfo) { + var baseId = tagInfo[0] + var props = tagInfo[1] + return styleSheetRegistry.computeId(baseId, props) + }) + .join(' ') + } + + function flush() { + var cssRules = styleSheetRegistry.cssRules() + styleSheetRegistry.flush() + return cssRules + } +})(style$1) + +var style = style$1.default || style$1 +style.flush = style$1.flush + +var server$1 = {} + +;(function (exports) { + exports.__esModule = true + exports['default'] = flushToReact + exports.flushToHTML = flushToHTML + + var _react = _interopRequireDefault(React__default['default']) + + var _style = style$1.default || style$1 + _style.flush = style$1.flush + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: obj } + } + + function flushToReact(options) { + if (options === void 0) { + options = {} + } + + return (0, _style.flush)().map(function (args) { + var id = args[0] + var css = args[1] + return _react['default'].createElement('style', { + id: '__' + id, + // Avoid warnings upon render with a key + key: '__' + id, + nonce: options.nonce ? options.nonce : undefined, + dangerouslySetInnerHTML: { + __html: css, + }, + }) + }) + } + + function flushToHTML(options) { + if (options === void 0) { + options = {} + } + + return (0, _style.flush)().reduce(function (html, args) { + var id = args[0] + var css = args[1] + html += + '' + return html + }, '') + } +})(server$1) + +var server = server$1.default || server$1 +server.flushToHTML = server$1.flushToHTML + +exports.server = server +exports.style = style diff --git a/scripts/built-in/styled-jsx.es.js b/scripts/built-in/styled-jsx.es.js new file mode 100644 index 000000000..1d5deb581 --- /dev/null +++ b/scripts/built-in/styled-jsx.es.js @@ -0,0 +1,737 @@ +import React from 'react' + +var style$1 = {} + +var stylesheetRegistry = {} + +function hash(str) { + var hash = 5381, + i = str.length + + while (i) { + hash = (hash * 33) ^ str.charCodeAt(--i) + } + + /* JavaScript does bitwise operations (like XOR, above) on 32-bit signed + * integers. Since we want the results to be always positive, convert the + * signed int to an unsigned by doing an unsigned bitshift. */ + return hash >>> 0 +} + +var stringHash = hash + +var stylesheet = {} + +;(function (exports) { + exports.__esModule = true + exports['default'] = void 0 + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i] + descriptor.enumerable = descriptor.enumerable || false + descriptor.configurable = true + if ('value' in descriptor) descriptor.writable = true + Object.defineProperty(target, descriptor.key, descriptor) + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps) + if (staticProps) _defineProperties(Constructor, staticProps) + return Constructor + } + + /* + Based on Glamor's sheet + https://github.com/threepointone/glamor/blob/667b480d31b3721a905021b26e1290ce92ca2879/src/sheet.js + */ + var isProd = + typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'production' + + var isString = function isString(o) { + return Object.prototype.toString.call(o) === '[object String]' + } + + var StyleSheet = /*#__PURE__*/ (function () { + function StyleSheet(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + _ref$name = _ref.name, + name = _ref$name === void 0 ? 'stylesheet' : _ref$name, + _ref$optimizeForSpeed = _ref.optimizeForSpeed, + optimizeForSpeed = + _ref$optimizeForSpeed === void 0 ? isProd : _ref$optimizeForSpeed, + _ref$isBrowser = _ref.isBrowser, + isBrowser = + _ref$isBrowser === void 0 ? typeof window !== 'undefined' : _ref$isBrowser + + invariant(isString(name), '`name` must be a string') + this._name = name + this._deletedRulePlaceholder = '#' + name + '-deleted-rule____{}' + invariant( + typeof optimizeForSpeed === 'boolean', + '`optimizeForSpeed` must be a boolean', + ) + this._optimizeForSpeed = optimizeForSpeed + this._isBrowser = isBrowser + this._serverSheet = undefined + this._tags = [] + this._injected = false + this._rulesCount = 0 + var node = this._isBrowser && document.querySelector('meta[property="csp-nonce"]') + this._nonce = node ? node.getAttribute('content') : null + } + + var _proto = StyleSheet.prototype + + _proto.setOptimizeForSpeed = function setOptimizeForSpeed(bool) { + invariant(typeof bool === 'boolean', '`setOptimizeForSpeed` accepts a boolean') + invariant( + this._rulesCount === 0, + 'optimizeForSpeed cannot be when rules have already been inserted', + ) + this.flush() + this._optimizeForSpeed = bool + this.inject() + } + + _proto.isOptimizeForSpeed = function isOptimizeForSpeed() { + return this._optimizeForSpeed + } + + _proto.inject = function inject() { + var _this = this + + invariant(!this._injected, 'sheet already injected') + this._injected = true + + if (this._isBrowser && this._optimizeForSpeed) { + this._tags[0] = this.makeStyleTag(this._name) + this._optimizeForSpeed = 'insertRule' in this.getSheet() + + if (!this._optimizeForSpeed) { + if (!isProd) { + console.warn( + 'StyleSheet: optimizeForSpeed mode not supported falling back to standard mode.', + ) + } + + this.flush() + this._injected = true + } + + return + } + + this._serverSheet = { + cssRules: [], + insertRule: function insertRule(rule, index) { + if (typeof index === 'number') { + _this._serverSheet.cssRules[index] = { + cssText: rule, + } + } else { + _this._serverSheet.cssRules.push({ + cssText: rule, + }) + } + + return index + }, + deleteRule: function deleteRule(index) { + _this._serverSheet.cssRules[index] = null + }, + } + } + + _proto.getSheetForTag = function getSheetForTag(tag) { + if (tag.sheet) { + return tag.sheet + } // this weirdness brought to you by firefox + + for (var i = 0; i < document.styleSheets.length; i++) { + if (document.styleSheets[i].ownerNode === tag) { + return document.styleSheets[i] + } + } + } + + _proto.getSheet = function getSheet() { + return this.getSheetForTag(this._tags[this._tags.length - 1]) + } + + _proto.insertRule = function insertRule(rule, index) { + invariant(isString(rule), '`insertRule` accepts only strings') + + if (!this._isBrowser) { + if (typeof index !== 'number') { + index = this._serverSheet.cssRules.length + } + + this._serverSheet.insertRule(rule, index) + + return this._rulesCount++ + } + + if (this._optimizeForSpeed) { + var sheet = this.getSheet() + + if (typeof index !== 'number') { + index = sheet.cssRules.length + } // this weirdness for perf, and chrome's weird bug + // https://stackoverflow.com/questions/20007992/chrome-suddenly-stopped-accepting-insertrule + + try { + sheet.insertRule(rule, index) + } catch (error) { + if (!isProd) { + console.warn( + 'StyleSheet: illegal rule: \n\n' + + rule + + '\n\nSee https://stackoverflow.com/q/20007992 for more info', + ) + } + + return -1 + } + } else { + var insertionPoint = this._tags[index] + + this._tags.push(this.makeStyleTag(this._name, rule, insertionPoint)) + } + + return this._rulesCount++ + } + + _proto.replaceRule = function replaceRule(index, rule) { + if (this._optimizeForSpeed || !this._isBrowser) { + var sheet = this._isBrowser ? this.getSheet() : this._serverSheet + + if (!rule.trim()) { + rule = this._deletedRulePlaceholder + } + + if (!sheet.cssRules[index]) { + // @TBD Should we throw an error? + return index + } + + sheet.deleteRule(index) + + try { + sheet.insertRule(rule, index) + } catch (error) { + if (!isProd) { + console.warn( + 'StyleSheet: illegal rule: \n\n' + + rule + + '\n\nSee https://stackoverflow.com/q/20007992 for more info', + ) + } // In order to preserve the indices we insert a deleteRulePlaceholder + + sheet.insertRule(this._deletedRulePlaceholder, index) + } + } else { + var tag = this._tags[index] + invariant(tag, 'old rule at index `' + index + '` not found') + tag.textContent = rule + } + + return index + } + + _proto.deleteRule = function deleteRule(index) { + if (!this._isBrowser) { + this._serverSheet.deleteRule(index) + + return + } + + if (this._optimizeForSpeed) { + this.replaceRule(index, '') + } else { + var tag = this._tags[index] + invariant(tag, 'rule at index `' + index + '` not found') + tag.parentNode.removeChild(tag) + this._tags[index] = null + } + } + + _proto.flush = function flush() { + this._injected = false + this._rulesCount = 0 + + if (this._isBrowser) { + this._tags.forEach(function (tag) { + return tag && tag.parentNode.removeChild(tag) + }) + + this._tags = [] + } else { + // simpler on server + this._serverSheet.cssRules = [] + } + } + + _proto.cssRules = function cssRules() { + var _this2 = this + + if (!this._isBrowser) { + return this._serverSheet.cssRules + } + + return this._tags.reduce(function (rules, tag) { + if (tag) { + rules = rules.concat( + Array.prototype.map.call( + _this2.getSheetForTag(tag).cssRules, + function (rule) { + return rule.cssText === _this2._deletedRulePlaceholder ? null : rule + }, + ), + ) + } else { + rules.push(null) + } + + return rules + }, []) + } + + _proto.makeStyleTag = function makeStyleTag(name, cssString, relativeToTag) { + if (cssString) { + invariant( + isString(cssString), + 'makeStyleTag acceps only strings as second parameter', + ) + } + + var tag = document.createElement('style') + if (this._nonce) tag.setAttribute('nonce', this._nonce) + tag.type = 'text/css' + tag.setAttribute('data-' + name, '') + + if (cssString) { + tag.appendChild(document.createTextNode(cssString)) + } + + var head = document.head || document.getElementsByTagName('head')[0] + + if (relativeToTag) { + head.insertBefore(tag, relativeToTag) + } else { + head.appendChild(tag) + } + + return tag + } + + _createClass(StyleSheet, [ + { + key: 'length', + get: function get() { + return this._rulesCount + }, + }, + ]) + + return StyleSheet + })() + + exports['default'] = StyleSheet + + function invariant(condition, message) { + if (!condition) { + throw new Error('StyleSheet: ' + message + '.') + } + } +})(stylesheet) +;(function (exports) { + exports.__esModule = true + exports['default'] = void 0 + + var _stringHash = _interopRequireDefault(stringHash) + + var _stylesheet = _interopRequireDefault(stylesheet) + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: obj } + } + + var sanitize = function sanitize(rule) { + return rule.replace(/\/style/gi, '\\/style') + } + + var StyleSheetRegistry = /*#__PURE__*/ (function () { + function StyleSheetRegistry(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + _ref$styleSheet = _ref.styleSheet, + styleSheet = _ref$styleSheet === void 0 ? null : _ref$styleSheet, + _ref$optimizeForSpeed = _ref.optimizeForSpeed, + optimizeForSpeed = + _ref$optimizeForSpeed === void 0 ? false : _ref$optimizeForSpeed, + _ref$isBrowser = _ref.isBrowser, + isBrowser = + _ref$isBrowser === void 0 ? typeof window !== 'undefined' : _ref$isBrowser + + this._sheet = + styleSheet || + new _stylesheet['default']({ + name: 'styled-jsx', + optimizeForSpeed: optimizeForSpeed, + }) + + this._sheet.inject() + + if (styleSheet && typeof optimizeForSpeed === 'boolean') { + this._sheet.setOptimizeForSpeed(optimizeForSpeed) + + this._optimizeForSpeed = this._sheet.isOptimizeForSpeed() + } + + this._isBrowser = isBrowser + this._fromServer = undefined + this._indices = {} + this._instancesCounts = {} + this.computeId = this.createComputeId() + this.computeSelector = this.createComputeSelector() + } + + var _proto = StyleSheetRegistry.prototype + + _proto.add = function add(props) { + var _this = this + + if (undefined === this._optimizeForSpeed) { + this._optimizeForSpeed = Array.isArray(props.children) + + this._sheet.setOptimizeForSpeed(this._optimizeForSpeed) + + this._optimizeForSpeed = this._sheet.isOptimizeForSpeed() + } + + if (this._isBrowser && !this._fromServer) { + this._fromServer = this.selectFromServer() + this._instancesCounts = Object.keys(this._fromServer).reduce(function ( + acc, + tagName, + ) { + acc[tagName] = 0 + return acc + }, + {}) + } + + var _this$getIdAndRules = this.getIdAndRules(props), + styleId = _this$getIdAndRules.styleId, + rules = _this$getIdAndRules.rules // Deduping: just increase the instances count. + + if (styleId in this._instancesCounts) { + this._instancesCounts[styleId] += 1 + return + } + + var indices = rules + .map(function (rule) { + return _this._sheet.insertRule(rule) + }) // Filter out invalid rules + .filter(function (index) { + return index !== -1 + }) + this._indices[styleId] = indices + this._instancesCounts[styleId] = 1 + } + + _proto.remove = function remove(props) { + var _this2 = this + + var _this$getIdAndRules2 = this.getIdAndRules(props), + styleId = _this$getIdAndRules2.styleId + + invariant(styleId in this._instancesCounts, 'styleId: `' + styleId + '` not found') + this._instancesCounts[styleId] -= 1 + + if (this._instancesCounts[styleId] < 1) { + var tagFromServer = this._fromServer && this._fromServer[styleId] + + if (tagFromServer) { + tagFromServer.parentNode.removeChild(tagFromServer) + delete this._fromServer[styleId] + } else { + this._indices[styleId].forEach(function (index) { + return _this2._sheet.deleteRule(index) + }) + + delete this._indices[styleId] + } + + delete this._instancesCounts[styleId] + } + } + + _proto.update = function update(props, nextProps) { + this.add(nextProps) + this.remove(props) + } + + _proto.flush = function flush() { + this._sheet.flush() + + this._sheet.inject() + + this._fromServer = undefined + this._indices = {} + this._instancesCounts = {} + this.computeId = this.createComputeId() + this.computeSelector = this.createComputeSelector() + } + + _proto.cssRules = function cssRules() { + var _this3 = this + + var fromServer = this._fromServer + ? Object.keys(this._fromServer).map(function (styleId) { + return [styleId, _this3._fromServer[styleId]] + }) + : [] + + var cssRules = this._sheet.cssRules() + + return fromServer.concat( + Object.keys(this._indices) + .map(function (styleId) { + return [ + styleId, + _this3._indices[styleId] + .map(function (index) { + return cssRules[index].cssText + }) + .join(_this3._optimizeForSpeed ? '' : '\n'), + ] + }) // filter out empty rules + .filter(function (rule) { + return Boolean(rule[1]) + }), + ) + } + /** + * createComputeId + * + * Creates a function to compute and memoize a jsx id from a basedId and optionally props. + */ + + _proto.createComputeId = function createComputeId() { + var cache = {} + return function (baseId, props) { + if (!props) { + return 'jsx-' + baseId + } + + var propsToString = String(props) + var key = baseId + propsToString // return `jsx-${hashString(`${baseId}-${propsToString}`)}` + + if (!cache[key]) { + cache[key] = 'jsx-' + (0, _stringHash['default'])(baseId + '-' + propsToString) + } + + return cache[key] + } + } + /** + * createComputeSelector + * + * Creates a function to compute and memoize dynamic selectors. + */ + + _proto.createComputeSelector = function createComputeSelector( + selectoPlaceholderRegexp, + ) { + if (selectoPlaceholderRegexp === void 0) { + selectoPlaceholderRegexp = /__jsx-style-dynamic-selector/g + } + + var cache = {} + return function (id, css) { + // Sanitize SSR-ed CSS. + // Client side code doesn't need to be sanitized since we use + // document.createTextNode (dev) and the CSSOM api sheet.insertRule (prod). + if (!this._isBrowser) { + css = sanitize(css) + } + + var idcss = id + css + + if (!cache[idcss]) { + cache[idcss] = css.replace(selectoPlaceholderRegexp, id) + } + + return cache[idcss] + } + } + + _proto.getIdAndRules = function getIdAndRules(props) { + var _this4 = this + + var css = props.children, + dynamic = props.dynamic, + id = props.id + + if (dynamic) { + var styleId = this.computeId(id, dynamic) + return { + styleId: styleId, + rules: Array.isArray(css) + ? css.map(function (rule) { + return _this4.computeSelector(styleId, rule) + }) + : [this.computeSelector(styleId, css)], + } + } + + return { + styleId: this.computeId(id), + rules: Array.isArray(css) ? css : [css], + } + } + /** + * selectFromServer + * + * Collects style tags from the document with id __jsx-XXX + */ + + _proto.selectFromServer = function selectFromServer() { + var elements = Array.prototype.slice.call( + document.querySelectorAll('[id^="__jsx-"]'), + ) + return elements.reduce(function (acc, element) { + var id = element.id.slice(2) + acc[id] = element + return acc + }, {}) + } + + return StyleSheetRegistry + })() + + exports['default'] = StyleSheetRegistry + + function invariant(condition, message) { + if (!condition) { + throw new Error('StyleSheetRegistry: ' + message + '.') + } + } +})(stylesheetRegistry) +;(function (exports) { + exports.__esModule = true + exports['default'] = JSXStyle + exports.flush = flush + + var _react = React + + var _stylesheetRegistry = _interopRequireDefault(stylesheetRegistry) + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: obj } + } + + var styleSheetRegistry = new _stylesheetRegistry['default']() + + function JSXStyle(props) { + if (typeof window === 'undefined') { + styleSheetRegistry.add(props) + return null + } + + ;(0, _react.useLayoutEffect)( + function () { + styleSheetRegistry.add(props) + return function () { + styleSheetRegistry.remove(props) + } // props.children can be string[], will be striped since id is identical + }, + [props.id, String(props.dynamic)], + ) + return null + } + + JSXStyle.dynamic = function (info) { + return info + .map(function (tagInfo) { + var baseId = tagInfo[0] + var props = tagInfo[1] + return styleSheetRegistry.computeId(baseId, props) + }) + .join(' ') + } + + function flush() { + var cssRules = styleSheetRegistry.cssRules() + styleSheetRegistry.flush() + return cssRules + } +})(style$1) + +var style = style$1.default || style$1 +style.flush = style$1.flush + +var server = {} + +;(function (exports) { + exports.__esModule = true + exports['default'] = flushToReact + exports.flushToHTML = flushToHTML + + var _react = _interopRequireDefault(React) + + var _style = style$1.default || style$1 + _style.flush = style$1.flush + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: obj } + } + + function flushToReact(options) { + if (options === void 0) { + options = {} + } + + return (0, _style.flush)().map(function (args) { + var id = args[0] + var css = args[1] + return _react['default'].createElement('style', { + id: '__' + id, + // Avoid warnings upon render with a key + key: '__' + id, + nonce: options.nonce ? options.nonce : undefined, + dangerouslySetInnerHTML: { + __html: css, + }, + }) + }) + } + + function flushToHTML(options) { + if (options === void 0) { + options = {} + } + + return (0, _style.flush)().reduce(function (html, args) { + var id = args[0] + var css = args[1] + html += + '' + return html + }, '') + } +})(server) +var _server = server.default || server +_server.flushToHTML = server.flushToHTML + +export { style, _server as server } +export default style diff --git a/scripts/fix-styled-jsx.js b/scripts/fix-styled-jsx.js deleted file mode 100644 index 432986751..000000000 --- a/scripts/fix-styled-jsx.js +++ /dev/null @@ -1,55 +0,0 @@ -const { resolve } = require('path') -const fsp = require('fs').promises -const esmFilePath = resolve(__dirname, '../esm', 'styled-jsx.js') -const cjsFilePath = resolve(__dirname, '../dist', 'styled-jsx.js') -const styledNamedStatement = 'var style = style$1;' -const styledTargetStatement = - 'var style = style$1.default || style$1; style.flush = style$1.flush;' -const esmExportStatement = 'export { style as s };' -const esmTargetStatement = 'export { style as s, style as a };' -const cjsServerNamedStatement = 'var server = server$1;' -const cjsServerTargetStatement = 'var server = server$1.default || server$1;' - -const checkFile = async targetPath => { - try { - await fsp.access(targetPath) - } catch (err) { - console.log(`\nNot found styled-jsx chunk file (${targetPath}).\n`) - console.log(err) - process.exit(1) - } -} - -const checkStatements = (content = '') => { - const count = content.split(styledNamedStatement).length - 1 - if (count !== 1) { - console.log('\nMultiple export statements found, stop replacing.\n') - process.exit(1) - } -} - -const replaceContent = async (targetPath, isESM = false) => { - const content = await fsp.readFile(targetPath, 'utf-8') - checkStatements(content) - - let nextContent = content.replace(styledNamedStatement, styledTargetStatement) - if (isESM) { - nextContent = nextContent.replace(esmExportStatement, esmTargetStatement) - } else { - nextContent = nextContent.replace(cjsServerNamedStatement, cjsServerTargetStatement) - } - await fsp.writeFile(targetPath, nextContent) -} - -;(async () => { - await checkFile(esmFilePath) - await replaceContent(esmFilePath, true) - console.log('[esm]> Export of styled-jsx has been successfully replaced.') - - await checkFile(cjsFilePath) - await replaceContent(cjsFilePath) - console.log('[cjs]> Export of styled-jsx has been successfully replaced.\n') -})().catch(err => { - console.log(err) - process.exit(1) -}) diff --git a/scripts/move-built-in.js b/scripts/move-built-in.js new file mode 100644 index 000000000..b856d5a66 --- /dev/null +++ b/scripts/move-built-in.js @@ -0,0 +1,32 @@ +const { resolve, join } = require('path') +const fs = require('fs-extra') +const builtInPath = resolve(__dirname, 'built-in') +const esmFolderPath = resolve(__dirname, '../esm') +const cjsFolderPath = resolve(__dirname, '../dist') +const builtInFiles = { + esm: ['styled-jsx.es.js', 'styled-jsx-server.es.js'], + cjs: ['styled-jsx.cjs.js'], +} + +;(async () => { + await Promise.all( + builtInFiles.esm.map(async name => { + const filePath = join(builtInPath, name) + const target = join(esmFolderPath, name) + await fs.copy(filePath, target, { overwrite: true }) + }), + ) + console.log('[esm]> Export of styled-jsx has been successfully replaced.') + + await Promise.all( + builtInFiles.cjs.map(async name => { + const filePath = join(builtInPath, name) + const target = join(cjsFolderPath, name) + await fs.copy(filePath, target, { overwrite: true }) + }), + ) + console.log('[cjs]> Export of styled-jsx has been successfully replaced.\n') +})().catch(err => { + console.log(err) + process.exit(1) +}) diff --git a/scripts/rollup.config.js b/scripts/rollup.config.js index d662e035c..5824db949 100644 --- a/scripts/rollup.config.js +++ b/scripts/rollup.config.js @@ -41,7 +41,7 @@ const cjsOutput = { dir: distPath, manualChunks: id => { if (id.includes('node_modules/styled-jsx')) { - return 'styled-jsx' + return 'styled-jsx.cjs' } }, chunkFileNames: '[name].js', @@ -54,10 +54,10 @@ const esmOutput = { dir: esmPath, manualChunks: id => { if (id.includes('node_modules/styled-jsx/server')) { - return 'styled-jsx-server' + return 'styled-jsx-server.es' } if (id.includes('node_modules/styled-jsx')) { - return 'styled-jsx' + return 'styled-jsx.es' } }, chunkFileNames: '[name].js', @@ -93,7 +93,8 @@ export default (async () => { .filter(r => !!r) .map(({ name, url }) => ({ input: { [name]: url }, - output: [esmOutput, cjsOutput], + // output: [esmOutput, cjsOutput], + output: [cjsOutput], external, plugins, })), @@ -101,7 +102,6 @@ export default (async () => { { input: { index: path.join(componentsPath, 'index.ts') }, output: [ - // use yarn build:esm-entry instead of it // { // ...esmOutput, // diff --git a/yarn.lock b/yarn.lock index 53a23b0e6..ba63f3300 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1841,13 +1841,6 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== -"@types/styled-jsx@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@types/styled-jsx/-/styled-jsx-3.4.4.tgz#643b49a892f596ee8d8e588e0270d6c05947048d" - integrity sha512-PRRa7gU7ske4Vs7sKWrqfKnuIIS6E/Yj5oKyxuM11AwOKhH9HlbQ7cKGLluXkOXzpEoDJE+6kQMj3AE34/JooQ== - dependencies: - styled-jsx "*" - "@types/testing-library__jest-dom@^5.9.1": version "5.14.2" resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.2.tgz#564fb2b2dc827147e937a75b639a05d17ce18b44" @@ -2244,6 +2237,11 @@ babel-plugin-polyfill-regenerator@^0.3.0: dependencies: "@babel/helper-define-polyfill-provider" "^0.3.1" +babel-plugin-transform-rename-import@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-rename-import/-/babel-plugin-transform-rename-import-2.3.0.tgz#5d9d645f937b0ca5c26a24b2510a06277b6ffd9b" + integrity sha512-dPgJoT57XC0PqSnLgl2FwNvxFrWlspatX2dkk7yjKQj5HHGw071vAcOf+hqW8ClqcBDMvEbm6mevn5yHAD8mlQ== + babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -6021,7 +6019,7 @@ style-to-object@^0.2.1: dependencies: inline-style-parser "0.1.1" -styled-jsx@*, styled-jsx@^4.0.1: +styled-jsx@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-4.0.1.tgz#ae3f716eacc0792f7050389de88add6d5245b9e9" integrity sha512-Gcb49/dRB1k8B4hdK8vhW27Rlb2zujCk1fISrizCcToIs+55B4vmUM0N9Gi4nnVfFZWe55jRdWpAqH1ldAKWvQ==