@khanacademy/wonder-blocks-core
Advanced tools
Comparing version 2.1.1 to 2.2.0
@@ -1,5 +0,3 @@ | ||
import React__default, { createElement, Component, Fragment, createContext } from 'react'; | ||
import Spacing from '@khanacademy/wonder-blocks-spacing'; | ||
import React__default, { createElement, Component, createContext } from 'react'; | ||
import { StyleSheet, css } from 'aphrodite'; | ||
import propTypes from 'prop-types'; | ||
import { withRouter } from 'react-router-dom'; | ||
@@ -618,53 +616,2 @@ | ||
// All possible valid media sizes | ||
var VALID_MEDIA_SIZES = ["small", "medium", "large"]; | ||
var mediaDefaultSpecLargeMarginWidth = Spacing.large; // The default spec for media layout, currently available in | ||
// three different settings (roughly mobile, tablet, and desktop). | ||
var MEDIA_DEFAULT_SPEC = { | ||
small: { | ||
query: "(max-width: 767px)", | ||
totalColumns: 4, | ||
gutterWidth: Spacing.medium, | ||
marginWidth: Spacing.medium | ||
}, | ||
medium: { | ||
query: "(min-width: 768px) and (max-width: 1023px)", | ||
totalColumns: 8, | ||
gutterWidth: Spacing.xLarge, | ||
marginWidth: Spacing.large | ||
}, | ||
large: { | ||
query: "(min-width: 1024px)", | ||
totalColumns: 12, | ||
gutterWidth: Spacing.xLarge, | ||
marginWidth: mediaDefaultSpecLargeMarginWidth, | ||
maxWidth: 1120 + mediaDefaultSpecLargeMarginWidth * 2 | ||
} | ||
}; // Used for internal tools | ||
var MEDIA_INTERNAL_SPEC = { | ||
large: { | ||
query: "(min-width: 1px)", | ||
totalColumns: 12, | ||
gutterWidth: Spacing.xLarge, | ||
marginWidth: Spacing.medium | ||
} | ||
}; // The default used for modals | ||
var MEDIA_MODAL_SPEC = { | ||
small: { | ||
query: "(max-width: 767px)", | ||
totalColumns: 4, | ||
gutterWidth: Spacing.medium, | ||
marginWidth: Spacing.medium | ||
}, | ||
large: { | ||
query: "(min-width: 768px)", | ||
totalColumns: 12, | ||
gutterWidth: Spacing.xLarge, | ||
marginWidth: Spacing.xxLarge | ||
} | ||
}; | ||
function flatten(list) { | ||
@@ -768,259 +715,3 @@ var result = []; | ||
} | ||
var mediaContextTypes = { | ||
mediaSize: propTypes.string, | ||
mediaSpec: propTypes.object | ||
}; | ||
function MediaLayoutWrapper(Component$$1) { | ||
var WrappedComponent = function WrappedComponent(props, _ref) { | ||
var mediaSize = _ref.mediaSize, | ||
mediaSpec = _ref.mediaSpec; | ||
return createElement(Component$$1, _extends({}, props, { | ||
mediaSize: mediaSize, | ||
mediaSpec: mediaSpec | ||
})); | ||
}; | ||
WrappedComponent.contextTypes = mediaContextTypes; | ||
return WrappedComponent; | ||
} | ||
/** | ||
* A MediaLayout wraps all parts of a page and tracks the browser viewport, toggling | ||
* the layout of the page based on viewport width changes. MediaLayout doesn't | ||
* impart any styling or layout, all of that is deferred to individual components | ||
* such as Row, Cell, FlexCell, and FixedWidthCell - or custom ones defined with | ||
* View or Text. | ||
* | ||
* By default the MediaLayout should be used with no properties. Optionally you can | ||
* specify the `size` of the layout. In doing so you will disable all readjustments | ||
* based on the size of the viewport (this property is mostly used for testing). | ||
* | ||
* Additionally you can specify `ssrSize` which will render a specific size of | ||
* layout when this component is Server-Side Renderered. Defaults to "large". | ||
* | ||
* If you wish to use a different set of layout sizes you can specify them as | ||
* part of the `spec` property. The Core package exports a couple of the most | ||
* commonly used ones: | ||
* | ||
* **Default Layout Spec (`MEDIA_DEFAULT_SPEC`)** | ||
* | ||
* | Size | Columns | Gutter | Margin | Breakpoint | | ||
* | ------ | ------- | ------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------- | | ||
* | small | 4 | 16px | 16px | `max-width: 767px` | | ||
* | medium | 8 | 32px | 24px | `min-width: 768px and max-width: 1023px` | | ||
* | large | 12 | 32px | 24px | `min-width: 1024px` (maximum content width: `1120px`, after which the margins will continue to expand and content remain centered) | | ||
* | ||
* Additionally, the following layout size specs are also available: | ||
* | ||
* **Internal Tools (`MEDIA_INTERNAL_SPEC`)** | ||
* | ||
* | Size | Columns | Gutter | Margin | Breakpoint | | ||
* | ----- | ------- | ------ | ------ | -------------------------------------------- | | ||
* | large | 12 | 32px | 16px | `min-width: 1px` (No maximum content width.) | | ||
* | ||
* **12-Column Modal (`MEDIA_MODAL_SPEC`)** | ||
* | ||
* | Size | Columns | Gutter | Margin | Breakpoint | | ||
* | ----- | ------- | ------ | ------ | ---------------------------------------------- | | ||
* | small | 4 | 16px | 16px | `max-width: 767px` | | ||
* | large | 12 | 32px | 64px | `min-width: 768px` (No maximum content width.) | | ||
*/ | ||
var MediaLayout = | ||
/*#__PURE__*/ | ||
function (_React$Component) { | ||
_inherits(MediaLayout, _React$Component); | ||
function MediaLayout(props) { | ||
var _this; | ||
_classCallCheck(this, MediaLayout); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(MediaLayout).call(this, props)); | ||
_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "watchHandlers", void 0); | ||
var ssrSize = props.ssrSize, | ||
size = props.size, | ||
spec = props.spec; // If a size was explicitly defined then we use that | ||
if (size) { | ||
_this.state = { | ||
size: size | ||
}; | ||
return _possibleConstructorReturn(_this); | ||
} // If we're rendering this on the server then we use the server-side | ||
// size (which defaults to "large") | ||
if (ssrSize && _this.isServerSide()) { | ||
_this.state = { | ||
size: ssrSize | ||
}; | ||
return _possibleConstructorReturn(_this); | ||
} // We then go through and set up matchMedia watchers for each breakpoint | ||
// (if they haven't been created already) and we add listeners to | ||
// watch for when the viewport changes size. | ||
_this.watchHandlers = {}; | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
var _loop = function _loop() { | ||
var size = _step.value; | ||
if (!spec[size]) { | ||
return "continue"; | ||
} | ||
var query = spec[size].query; // Don't watch sizes that don't have an associated query | ||
if (!query) { | ||
return "continue"; | ||
} // Create a new matchMedia watcher if one doesn't exist yet | ||
if (!MediaLayout.WATCHERS[query]) { | ||
MediaLayout.WATCHERS[query] = window.matchMedia(query); | ||
} | ||
var watcher = MediaLayout.WATCHERS[query]; // Attach a handler that watches for the change, saving a | ||
// references to it so we can remove it later | ||
var handler = _this.watchHandlers[query] = function (e) { | ||
if (e.matches) { | ||
_this.setState({ | ||
size: size | ||
}); | ||
} | ||
}; | ||
watcher.addListener(handler); // If the watcher already matches then we set the size immediately | ||
if (watcher.matches) { | ||
_this.state = { | ||
size: size | ||
}; | ||
} | ||
}; | ||
for (var _iterator = VALID_MEDIA_SIZES[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var _ret = _loop(); | ||
if (_ret === "continue") continue; | ||
} // If a size was never defined, or matched, then we complain! | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return != null) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
if (!_this.state || !_this.state.size) { | ||
throw new Error("Matching media query not found for MediaLayout."); | ||
} | ||
return _this; | ||
} | ||
_createClass(MediaLayout, [{ | ||
key: "componentWillUnmount", | ||
value: function componentWillUnmount() { | ||
if (this.isServerSide()) { | ||
return; | ||
} // We go through the component and remove all of the listeners | ||
// that this MediaLayout attached. | ||
var _arr = Object.keys(MediaLayout.WATCHERS); | ||
for (var _i = 0; _i < _arr.length; _i++) { | ||
var _query = _arr[_i]; | ||
var watcher = MediaLayout.WATCHERS[_query]; | ||
if (watcher) { | ||
var handler = this.watchHandlers[_query]; | ||
watcher.removeListener(handler); | ||
delete this.watchHandlers[_query]; | ||
} | ||
} | ||
} | ||
}, { | ||
key: "isServerSide", | ||
value: function isServerSide() { | ||
return typeof window === "undefined" || !window.matchMedia; | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
// eslint-disable-next-line no-unused-vars | ||
var _this$props = this.props, | ||
ssrSize = _this$props.ssrSize, | ||
size = _this$props.size, | ||
children = _this$props.children, | ||
otherProps = _objectWithoutProperties(_this$props, ["ssrSize", "size", "children"]); | ||
return createElement(MediaLayoutContext, _extends({}, otherProps, { | ||
size: this.state.size | ||
}), children); | ||
} | ||
}]); | ||
return MediaLayout; | ||
}(Component); | ||
/** | ||
* MediaLayoutContext is used to set the Context for all descendent children | ||
* to be able to adjust their rendering based on the viewport size. | ||
*/ | ||
_defineProperty(MediaLayout, "WATCHERS", {}); | ||
_defineProperty(MediaLayout, "defaultProps", { | ||
ssrSize: "large", | ||
spec: MEDIA_DEFAULT_SPEC | ||
}); | ||
var MediaLayoutContext = | ||
/*#__PURE__*/ | ||
function (_React$Component2) { | ||
_inherits(MediaLayoutContext, _React$Component2); | ||
function MediaLayoutContext() { | ||
_classCallCheck(this, MediaLayoutContext); | ||
return _possibleConstructorReturn(this, _getPrototypeOf(MediaLayoutContext).apply(this, arguments)); | ||
} | ||
_createClass(MediaLayoutContext, [{ | ||
key: "getChildContext", | ||
value: function getChildContext() { | ||
return { | ||
mediaSize: this.props.size, | ||
mediaSpec: this.props.spec | ||
}; | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
return createElement(Fragment, null, this.props.children); | ||
} | ||
}]); | ||
return MediaLayoutContext; | ||
}(Component); | ||
_defineProperty(MediaLayoutContext, "childContextTypes", mediaContextTypes); | ||
var isHeaderRegex = /^h[1-6]$/; | ||
@@ -1849,2 +1540,2 @@ var styles = StyleSheet.create({ | ||
export { ClickableBehavior, MediaLayout, Text, View, WithSSRPlaceholder, UniqueIDProvider, addStyle, getClickableBehavior, getElementIntersection, MediaLayoutWrapper, VALID_MEDIA_SIZES, MEDIA_DEFAULT_SPEC, MEDIA_INTERNAL_SPEC, MEDIA_MODAL_SPEC }; | ||
export { ClickableBehavior, Text, View, WithSSRPlaceholder, UniqueIDProvider, addStyle, getClickableBehavior, getElementIntersection }; |
@@ -12,3 +12,2 @@ // This file is auto-generated by gen-snapshot-tests.js | ||
import ClickableBehavior from "./components/clickable-behavior.js"; | ||
import MediaLayout from "./components/media-layout.js"; | ||
import Text from "./components/text.js"; | ||
@@ -15,0 +14,0 @@ import UniqueIDProvider from "./components/unique-id-provider.js"; |
13
index.js
// @flow | ||
import type {ClickableHandlers} from "./components/clickable-behavior.js"; | ||
import type { | ||
AriaProps, | ||
IIdentifierFactory, | ||
MediaSize, | ||
MediaSpec, | ||
StyleType, | ||
} from "./util/types.js"; | ||
import type {AriaProps, IIdentifierFactory, StyleType} from "./util/types.js"; | ||
import type {Intersection} from "./util/get-element-intersection.js"; | ||
export {default as ClickableBehavior} from "./components/clickable-behavior.js"; | ||
export {default as MediaLayout} from "./components/media-layout.js"; | ||
export {default as Text} from "./components/text.js"; | ||
@@ -27,4 +20,2 @@ export {default as View} from "./components/view.js"; | ||
} from "./util/get-element-intersection.js"; | ||
export * from "./util/specs.js"; | ||
export {MediaLayoutWrapper} from "./util/util.js"; | ||
@@ -36,5 +27,3 @@ export type { | ||
IIdentifierFactory, | ||
MediaSize, | ||
MediaSpec, | ||
StyleType, | ||
}; |
@@ -14,3 +14,2 @@ // @flow | ||
"ClickableBehavior", | ||
"MediaLayout", | ||
"Text", | ||
@@ -22,7 +21,2 @@ "View", | ||
"getElementIntersection", | ||
"VALID_MEDIA_SIZES", | ||
"MEDIA_DEFAULT_SPEC", | ||
"MEDIA_INTERNAL_SPEC", | ||
"MEDIA_MODAL_SPEC", | ||
"MediaLayoutWrapper", | ||
"UniqueIDProvider", | ||
@@ -29,0 +23,0 @@ ].sort(), |
{ | ||
"name": "@khanacademy/wonder-blocks-core", | ||
"version": "2.1.1", | ||
"version": "2.2.0", | ||
"design": "v1", | ||
@@ -16,3 +16,3 @@ "publishConfig": { | ||
"dependencies": { | ||
"@khanacademy/wonder-blocks-spacing": "^2.1.1" | ||
"@khanacademy/wonder-blocks-spacing": "^2.1.2" | ||
}, | ||
@@ -19,0 +19,0 @@ "peerDependencies": { |
@@ -224,21 +224,2 @@ // @flow | ||
export type MediaSize = "small" | "medium" | "large"; | ||
// TODO(kevinb): dedupe with wonder-blocks-grid | ||
// eslint-disable-next-line flowtype/require-exact-type | ||
export type MediaSpec = { | ||
[sizeName: MediaSize]: { | ||
/** The query to use to match the viewport against. */ | ||
query: string, | ||
/** The total number of columns to use for the layout. */ | ||
totalColumns: number, | ||
/** The width of the gutter between columns, in pixels. */ | ||
gutterWidth: number, | ||
/** The width of the margin, wrapping the row, in pixels. */ | ||
marginWidth: number, | ||
/** The maximum width for this spec, including margins, in pixels. */ | ||
maxWidth?: number, | ||
}, | ||
}; | ||
/** | ||
@@ -245,0 +226,0 @@ * Interface implemented by types that can provide identifiers. |
// @flow | ||
import {StyleSheet, css} from "aphrodite"; | ||
import * as React from "react"; | ||
import propTypes from "prop-types"; | ||
import type {CSSProperties} from "aphrodite"; | ||
import type {MediaSize, MediaSpec, StyleType} from "./types.js"; | ||
import type {StyleType} from "./types.js"; | ||
@@ -86,31 +84,1 @@ function flatten(list?: StyleType): Array<CSSProperties> { | ||
} | ||
export const mediaContextTypes = { | ||
mediaSize: propTypes.string, | ||
mediaSpec: propTypes.object, | ||
}; | ||
export function MediaLayoutWrapper<Props: {}>( | ||
Component: React.ComponentType<Props>, | ||
): React.ComponentType< | ||
$Diff<Props, {mediaSize: MediaSize | void, mediaSpec: MediaSpec | void}>, | ||
> { | ||
const WrappedComponent = ( | ||
props: Props, | ||
{ | ||
mediaSize, | ||
mediaSpec, | ||
}: { | ||
mediaSize: MediaSize, | ||
mediaSpec: MediaSpec, | ||
}, | ||
) => { | ||
return ( | ||
<Component {...props} mediaSize={mediaSize} mediaSpec={mediaSpec} /> | ||
); | ||
}; | ||
WrappedComponent.contextTypes = mediaContextTypes; | ||
return WrappedComponent; | ||
} |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
287310
37
6112