Socket
Socket
Sign inDemoInstall

@khanacademy/wonder-blocks-core

Package Overview
Dependencies
Maintainers
1
Versions
173
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@khanacademy/wonder-blocks-core - npm Package Compare versions

Comparing version 1.2.7 to 2.0.0

components/with-ssr-placeholder.js

18

components/unique-id-provider.js
// @flow
import * as React from "react";
import NoSSR from "./no-ssr.js";
import WithSSRPlaceholder from "./with-ssr-placeholder.js";

@@ -17,3 +17,4 @@ import UniqueIDFactory from "../util/unique-id-factory.js";

* If mockOnFirstRender is false, this is only called after
* the initial render has occurred and will always be called with the same
* the initial render has occurred -- it will be blank for the
* the first render -- and will always be called with the same
* IIdentifierFactory instance.

@@ -38,3 +39,3 @@ *

*/
mockOnFirstRender?: boolean,
mockOnFirstRender: boolean,

@@ -72,3 +73,3 @@ /**

// Note: `firstRender` will be `false` on the first render if this
// component is a descendant of a `NoSSR`.
// component is a descendant of a `WithSSRPlaceholder`.
if (firstRender) {

@@ -93,10 +94,11 @@ if (mockOnFirstRender) {

render() {
// Here we use the NoSSR component to control when we render and whether
// we provide a mock or real identifier factory.
// Here we use the WithSSRPlaceholder component to control
// when we render and whether we provide a mock or real
// identifier factory.
return (
<NoSSR placeholder={() => this._performRender(true)}>
<WithSSRPlaceholder placeholder={() => this._performRender(true)}>
{() => this._performRender(false)}
</NoSSR>
</WithSSRPlaceholder>
);
}
}

@@ -1,4 +0,4 @@

### mockOnFirstRender absent or false
### mockOnFirstRender false
When no `mockOnFirstRender` is `false` (the default), the `children` prop is only called after the initial render. Each call provides the same identifier factory, meaning the same identifier gets returned. Try it below.
When `mockOnFirstRender` is `false`, the `children` prop is only called after the initial render. Each call provides the same identifier factory, meaning the same identifier gets returned. Try it below.

@@ -14,3 +14,3 @@ ```jsx

const provider = (
<UniqueIDProvider ref={ref => providerRef = ref}>
<UniqueIDProvider mockOnFirstRender={false} ref={ref => providerRef = ref}>
{ids => {

@@ -99,7 +99,7 @@ renders.push(ids.get("my-unique-id"));

<HeadingSmall>First Provider with scope: first</HeadingSmall>
<UniqueIDProvider scope="first">
<UniqueIDProvider mockOnFirstRender={false} scope="first">
{children}
</UniqueIDProvider>
<HeadingSmall>Second Provider with scope: second</HeadingSmall>
<UniqueIDProvider scope="second">
<UniqueIDProvider mockOnFirstRender={false} scope="second">
{children}

@@ -106,0 +106,0 @@ </UniqueIDProvider>

@@ -12,3 +12,3 @@ // @flow

import UniqueIDProvider from "./unique-id-provider.js";
import NoSSR from "./no-ssr.js";
import WithSSRPlaceholder from "./with-ssr-placeholder.js";

@@ -24,3 +24,3 @@ describe("UniqueIDProvider", () => {

const children = jest.fn(() => null);
const nodes = <UniqueIDProvider>{children}</UniqueIDProvider>;
const nodes = <UniqueIDProvider mockOnFirstRender={false}>{children}</UniqueIDProvider>;

@@ -37,3 +37,3 @@ // Act

const children = jest.fn(() => null);
const nodes = <UniqueIDProvider>{children}</UniqueIDProvider>;
const nodes = <UniqueIDProvider mockOnFirstRender={false}>{children}</UniqueIDProvider>;

@@ -55,3 +55,3 @@ // Act

const children = jest.fn(() => <View />);
const nodes = <UniqueIDProvider>{children}</UniqueIDProvider>;
const nodes = <UniqueIDProvider mockOnFirstRender={false}>{children}</UniqueIDProvider>;
const wrapper = mount(nodes);

@@ -133,3 +133,3 @@

describe("inside a NoSSR", () => {
describe("inside a WithSSRPlaceholder", () => {
test("it should pass an id to its children", () => {

@@ -139,9 +139,9 @@ // Arrange

const nodes = (
<NoSSR>
<WithSSRPlaceholder placeholder={null}>
{() => (
<UniqueIDProvider>
<UniqueIDProvider mockOnFirstRender={false}>
{(ids) => foo(ids.get(""))}
</UniqueIDProvider>
)}
</NoSSR>
</WithSSRPlaceholder>
);

@@ -148,0 +148,0 @@

@@ -1185,4 +1185,19 @@ import React__default, { createElement, Component, Fragment, createContext } from 'react';

var HasHadFirstRenderContext = createContext(false);
/**
* This is the context that tracks who is doing what in our SSR component tree.
*
* root:
* no one has instigated an initial SSR render so the component that sees
* this "root" state is responsible for controlling initial versus standard
* rendering semantics
*
* initial:
* this means the SSR render has started, and all SSR components should act
* as though they are on the server
*
* standard:
* means that we're all now doing non-SSR rendering
*/
var RenderStateContext = createContext("root");
/**
* Defer or change rendering until the component did mount.

@@ -1196,7 +1211,8 @@ *

*
* If `NoSSR` components are nested within one another, the root `NoSSR`
* component will handle the initial render, but nested `NoSSR` components
* will delegate to the root one, meaning that we don't cascade delayed
* rendering down the component tree. This will also be the case across
* portal boundaries.
* If `WithSSRPlaceholder` components are nested within one another,
* the root `WithSSRPlaceholder` component will handle the initial
* render, but nested `WithSSRPlaceholder` components will delegate to
* the root one, meaning that we don't cascade delayed rendering down
* the component tree. This will also be the case across portal
* boundaries.
*

@@ -1206,14 +1222,14 @@ * Example:

* ```js
* <NoSSR placeholder={() => <div>This renders on the server.</div>}>
* {() => <div>This will not be rendered on the server.</div>}
* </NoSSR>
* <WithSSRPlaceholder placeholder={() => <div>Renders on the server!</div>}>
* {() => <div>Only renders on the client (after rehydration).</div>}
* </WithSSRPlaceholder>
* ```
*/
var NoSSR =
var WithSSRPlaceholder =
/*#__PURE__*/
function (_React$Component) {
_inherits(NoSSR, _React$Component);
_inherits(WithSSRPlaceholder, _React$Component);
function NoSSR() {
function WithSSRPlaceholder() {
var _getPrototypeOf2;

@@ -1223,3 +1239,3 @@

_classCallCheck(this, NoSSR);
_classCallCheck(this, WithSSRPlaceholder);

@@ -1230,3 +1246,3 @@ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {

_this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(NoSSR)).call.apply(_getPrototypeOf2, [this].concat(args)));
_this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(WithSSRPlaceholder)).call.apply(_getPrototypeOf2, [this].concat(args)));

@@ -1237,3 +1253,3 @@ _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "state", {

_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "_alreadyPerformedFirstRender", false);
_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "_isTheRootComponent", false);

@@ -1243,6 +1259,6 @@ return _this;

_createClass(NoSSR, [{
_createClass(WithSSRPlaceholder, [{
key: "componentDidMount",
value: function componentDidMount() {
if (!this._alreadyPerformedFirstRender) {
if (this._isTheRootComponent) {
// We only want to force a new render if we were responsible for

@@ -1257,33 +1273,30 @@ // the first render, so we guard that state change here.

}, {
key: "_maybeRenderPlaceholderOrChildren",
value: function _maybeRenderPlaceholderOrChildren(alreadyPerformedFirstRender) {
key: "_renderAsRootComponent",
value: function _renderAsRootComponent() {
var mounted = this.state.mounted;
var _this$props = this.props,
children = _this$props.children,
placeholder = _this$props.placeholder; // We just get on with rendering if we're passed truthiness as we
// are reliably told a NoSSR component further up the chain already
// handled our SSR case.
placeholder = _this$props.placeholder; // We are the first component in the tree.
// We are in control of instigating a second render for our
// component tree.
if (alreadyPerformedFirstRender) {
// We need to stop the forced second render and to do that, we have
// to influence our componentDidMount. Fortunately, that occurs
// after this, so let's save a member value to then use there.
this._alreadyPerformedFirstRender = alreadyPerformedFirstRender;
return children();
} // We are mounted and we no higher SSR component handled the first
// render so let's tell our children that we did.
this._isTheRootComponent = true;
if (mounted) {
return createElement(HasHadFirstRenderContext.Provider, {
value: true
// This is our second non-SSR render, so let's tell everyone to
// do their thing.
return createElement(RenderStateContext.Provider, {
value: "standard"
}, children());
} // We don't have a parent that handled SSR, and this must be our
// first render, and we have a placeholder, so render the placeholder.
} // OK, this is the very first render.
// If we have a placeholder, we render it, and ensure that any
// nested SSR components know we're still on that first render
// but they're not in charge of instigating the second render.
if (placeholder) {
return placeholder();
} // We don't have a parent that handled SSR, and this must be our
// first render and we don't have a placeholder, so return nothing.
return createElement(RenderStateContext.Provider, {
value: "initial"
}, placeholder());
} // Otherwise, we return nothing.

@@ -1294,2 +1307,38 @@

}, {
key: "_maybeRender",
value: function _maybeRender(renderState) {
var _this$props2 = this.props,
children = _this$props2.children,
placeholder = _this$props2.placeholder;
switch (renderState) {
case "root":
return this._renderAsRootComponent();
case "initial":
// We're not the root component, so we just have to either
// render our placeholder or nothing.
// The second render is going to be triggered for us.
if (placeholder) {
return placeholder();
} // Otherwise, we render nothing.
return null;
case "standard":
// We have covered the SSR render, we're now rendering with
// standard rendering semantics.
return children();
// We ignore this from coverage. It's a maintenance case to help
// us catch code changes that affect the control flow unexpectedly,
// but it's not something we need to write a test case for.
/* istanbul ignore next */
default:
throw new Error("We got a render state we don't understand");
}
}
}, {
key: "render",

@@ -1299,4 +1348,4 @@ value: function render() {

return createElement(HasHadFirstRenderContext.Consumer, null, function (value) {
return _this2._maybeRenderPlaceholderOrChildren(value);
return createElement(RenderStateContext.Consumer, null, function (value) {
return _this2._maybeRender(value);
});

@@ -1306,3 +1355,3 @@ }

return NoSSR;
return WithSSRPlaceholder;
}(Component);

@@ -1466,3 +1515,3 @@

// Note: `firstRender` will be `false` on the first render if this
// component is a descendant of a `NoSSR`.
// component is a descendant of a `WithSSRPlaceholder`.

@@ -1492,5 +1541,6 @@ if (firstRender) {

// Here we use the NoSSR component to control when we render and whether
// we provide a mock or real identifier factory.
return createElement(NoSSR, {
// Here we use the WithSSRPlaceholder component to control
// when we render and whether we provide a mock or real
// identifier factory.
return createElement(WithSSRPlaceholder, {
placeholder: function placeholder() {

@@ -1784,2 +1834,2 @@ return _this2._performRender(true);

export { ClickableBehavior, MediaLayout, Text, View, NoSSR, UniqueIDProvider, addStyle, getClickableBehavior, getElementIntersection, MediaLayoutWrapper, VALID_MEDIA_SIZES, MEDIA_DEFAULT_SPEC, MEDIA_INTERNAL_SPEC, MEDIA_MODAL_SPEC };
export { ClickableBehavior, MediaLayout, Text, View, WithSSRPlaceholder, UniqueIDProvider, addStyle, getClickableBehavior, getElementIntersection, MediaLayoutWrapper, VALID_MEDIA_SIZES, MEDIA_DEFAULT_SPEC, MEDIA_INTERNAL_SPEC, MEDIA_MODAL_SPEC };

@@ -13,212 +13,9 @@ // This file is auto-generated by gen-snapshot-tests.js

import MediaLayout from "./components/media-layout.js";
import NoSSR from "./components/no-ssr.js";
import Text from "./components/text.js";
import UniqueIDProvider from "./components/unique-id-provider.js";
import View from "./components/view.js";
import WithSSRPlaceholder from "./components/with-ssr-placeholder.js";
describe("wonder-blocks-core", () => {
it("example 1", () => {
const example = (
<NoSSR
placeholder={() => (
<View>
This gets rendered on client and server for the first
render call in the component tree
</View>
)}
>
{() => (
<View>
This is rendered only by the client for all but the very
first render of the component tree.
</View>
)}
</NoSSR>
);
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 2", () => {
const {
Body,
BodyMonospace,
} = require("@khanacademy/wonder-blocks-typography");
const trackingArray = [];
const resultsId = "nossr-example-2-results";
const newLi = (text) => {
const li = document.createElement("li");
li.appendChild(document.createTextNode(text));
return li;
};
const addTrackedRender = (text) => {
const el = document.getElementById(resultsId);
if (el) {
for (let i = 0; i < trackingArray.length; i++) {
el.append(newLi(trackingArray[i]));
}
trackingArray.length = 0;
el.append(newLi(text));
} else {
// We may not have rendered the results element yet, so if we haven't
// use an array to keep track of the things until we have.
trackingArray.push(text);
}
};
const trackAndRender = (text) => {
addTrackedRender(text);
return text;
};
const example = (
<View>
<Body>
The list below should have three render entries; root
placeholder, root children render, and child children
render. If there are two child renders that means that the
second forced render is still occurring for nested NoSSR
components, which would be a bug.
</Body>
<ul id={resultsId} />
<Body>
And below this is the actual NoSSR nesting, which should
just show the child render.
</Body>
<NoSSR
placeholder={() => (
<View>{trackAndRender("Root: placeholder")}</View>
)}
>
{() => {
addTrackedRender("Root: render");
return (
<NoSSR
placeholder={() => (
<View>
{trackAndRender(
"Child: placeholder (should never see me)",
)}
</View>
)}
>
{() => (
<View>
{trackAndRender("Child: render")}
</View>
)}
</NoSSR>
);
}}
</NoSSR>
</View>
);
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 3", () => {
const {
Body,
BodyMonospace,
} = require("@khanacademy/wonder-blocks-typography");
const trackingArray = [];
const resultsId = "nossr-example-3-results";
const newLi = (text) => {
const li = document.createElement("li");
li.appendChild(document.createTextNode(text));
return li;
};
const addTrackedRender = (text) => {
const el = document.getElementById(resultsId);
if (el) {
for (let i = 0; i < trackingArray.length; i++) {
el.append(newLi(trackingArray[i]));
}
trackingArray.length = 0;
el.append(newLi(text));
} else {
// We may not have rendered the results element yet, so if we haven't
// use an array to keep track of the things until we have.
trackingArray.push(text);
}
};
const trackAndRender = (text) => {
addTrackedRender(text);
return text;
};
const example = (
<View>
<Body>
The list below should have six render entries; 2 x root
placeholder, 2 x root children render, and 2 x child
children render.
</Body>
<ul id={resultsId} />
<Body>
And below this are the NoSSR component trees, which should
just show their child renders.
</Body>
<NoSSR
placeholder={() => (
<View>{trackAndRender("Root 1: placeholder")}</View>
)}
>
{() => {
addTrackedRender("Root 1: render");
return (
<NoSSR
placeholder={() => (
<View>
{trackAndRender(
"Child 1: placeholder (should never see me)",
)}
</View>
)}
>
{() => (
<View>
{trackAndRender("Child 1: render")}
</View>
)}
</NoSSR>
);
}}
</NoSSR>
<NoSSR
placeholder={() => (
<View>{trackAndRender("Root 2: placeholder")}</View>
)}
>
{() => {
addTrackedRender("Root 2: render");
return (
<NoSSR
placeholder={() => (
<View>
{trackAndRender(
"Child 2: placeholder (should never see me)",
)}
</View>
)}
>
{() => (
<View>
{trackAndRender("Child 2: render")}
</View>
)}
</NoSSR>
);
}}
</NoSSR>
</View>
);
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 4", () => {
const {StyleSheet} = require("aphrodite");

@@ -253,3 +50,3 @@

});
it("example 5", () => {
it("example 2", () => {
const example = (

@@ -267,3 +64,3 @@ <View>

});
it("example 6", () => {
it("example 3", () => {
const {

@@ -280,3 +77,6 @@ Body,

const provider = (
<UniqueIDProvider ref={(ref) => (providerRef = ref)}>
<UniqueIDProvider
mockOnFirstRender={false}
ref={(ref) => (providerRef = ref)}
>
{(ids) => {

@@ -317,3 +117,3 @@ renders.push(ids.get("my-unique-id"));

});
it("example 7", () => {
it("example 4", () => {
const {

@@ -361,3 +161,3 @@ Body,

});
it("example 8", () => {
it("example 5", () => {
const {

@@ -381,5 +181,9 @@ Body,

<HeadingSmall>First Provider with scope: first</HeadingSmall>
<UniqueIDProvider scope="first">{children}</UniqueIDProvider>
<UniqueIDProvider mockOnFirstRender={false} scope="first">
{children}
</UniqueIDProvider>
<HeadingSmall>Second Provider with scope: second</HeadingSmall>
<UniqueIDProvider scope="second">{children}</UniqueIDProvider>
<UniqueIDProvider mockOnFirstRender={false} scope="second">
{children}
</UniqueIDProvider>
</View>

@@ -390,3 +194,3 @@ );

});
it("example 9", () => {
it("example 6", () => {
const {

@@ -415,3 +219,3 @@ BodyMonospace,

});
it("example 10", () => {
it("example 7", () => {
const {StyleSheet} = require("aphrodite");

@@ -446,3 +250,3 @@

});
it("example 11", () => {
it("example 8", () => {
const example = (

@@ -460,2 +264,219 @@ <View>

});
it("example 9", () => {
const example = (
<WithSSRPlaceholder
placeholder={() => (
<View>
This gets rendered on server, and also on the client for
the very first render (the "rehydration" render)
</View>
)}
>
{() => (
<View>
This is rendered only by the client, for all renders
after the rehydration render.
</View>
)}
</WithSSRPlaceholder>
);
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 10", () => {
const example = (
<WithSSRPlaceholder placeholder={null}>
{() => (
<View>
This is rendered only by the client, while nothing was
rendered on the server.
</View>
)}
</WithSSRPlaceholder>
);
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 11", () => {
const {
Body,
BodyMonospace,
} = require("@khanacademy/wonder-blocks-typography");
const trackingArray = [];
const resultsId = "nossr-example-2-results";
const newLi = (text) => {
const li = document.createElement("li");
li.appendChild(document.createTextNode(text));
return li;
};
const addTrackedRender = (text) => {
const el = document.getElementById(resultsId);
if (el) {
for (let i = 0; i < trackingArray.length; i++) {
el.append(newLi(trackingArray[i]));
}
trackingArray.length = 0;
el.append(newLi(text));
} else {
// We may not have rendered the results element yet, so if we haven't
// use an array to keep track of the things until we have.
trackingArray.push(text);
}
};
const trackAndRender = (text) => {
addTrackedRender(text);
return text;
};
const example = (
<View>
<Body>
The list below should have three render entries; root
placeholder, root children render, and child children
render. If there are two child renders that means that the
second forced render is still occurring for nested
WithSSRPlaceholder components, which would be a bug.
</Body>
<ul id={resultsId} />
<Body>
And below this is the actual WithSSRPlaceholder nesting,
which should just show the child render.
</Body>
<WithSSRPlaceholder
placeholder={() => (
<View>{trackAndRender("Root: placeholder")}</View>
)}
>
{() => {
addTrackedRender("Root: render");
return (
<WithSSRPlaceholder
placeholder={() => (
<View>
{trackAndRender(
"Child: placeholder (should never see me)",
)}
</View>
)}
>
{() => (
<View>
{trackAndRender("Child: render")}
</View>
)}
</WithSSRPlaceholder>
);
}}
</WithSSRPlaceholder>
</View>
);
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
it("example 12", () => {
const {
Body,
BodyMonospace,
} = require("@khanacademy/wonder-blocks-typography");
const trackingArray = [];
const resultsId = "nossr-example-3-results";
const newLi = (text) => {
const li = document.createElement("li");
li.appendChild(document.createTextNode(text));
return li;
};
const addTrackedRender = (text) => {
const el = document.getElementById(resultsId);
if (el) {
for (let i = 0; i < trackingArray.length; i++) {
el.append(newLi(trackingArray[i]));
}
trackingArray.length = 0;
el.append(newLi(text));
} else {
// We may not have rendered the results element yet, so if we haven't
// use an array to keep track of the things until we have.
trackingArray.push(text);
}
};
const trackAndRender = (text) => {
addTrackedRender(text);
return text;
};
const example = (
<View>
<Body>
The list below should have six render entries; 2 x root
placeholder, 2 x root children render, and 2 x child
children render.
</Body>
<ul id={resultsId} />
<Body>
And below this are the WithSSRPlaceholder component trees,
which should just show their child renders.
</Body>
<WithSSRPlaceholder
placeholder={() => (
<View>{trackAndRender("Root 1: placeholder")}</View>
)}
>
{() => {
addTrackedRender("Root 1: render");
return (
<WithSSRPlaceholder
placeholder={() => (
<View>
{trackAndRender(
"Child 1: placeholder (should never see me)",
)}
</View>
)}
>
{() => (
<View>
{trackAndRender("Child 1: render")}
</View>
)}
</WithSSRPlaceholder>
);
}}
</WithSSRPlaceholder>
<WithSSRPlaceholder
placeholder={() => (
<View>{trackAndRender("Root 2: placeholder")}</View>
)}
>
{() => {
addTrackedRender("Root 2: render");
return (
<WithSSRPlaceholder
placeholder={() => (
<View>
{trackAndRender(
"Child 2: placeholder (should never see me)",
)}
</View>
)}
>
{() => (
<View>
{trackAndRender("Child 2: render")}
</View>
)}
</WithSSRPlaceholder>
);
}}
</WithSSRPlaceholder>
</View>
);
const tree = renderer.create(example).toJSON();
expect(tree).toMatchSnapshot();
});
});

@@ -17,3 +17,5 @@ // @flow

export {default as View} from "./components/view.js";
export {default as NoSSR} from "./components/no-ssr.js";
export {
default as WithSSRPlaceholder,
} from "./components/with-ssr-placeholder.js";
export {default as UniqueIDProvider} from "./components/unique-id-provider.js";

@@ -20,0 +22,0 @@ export {default as addStyle} from "./util/add-style.js";

@@ -17,3 +17,3 @@ // @flow

"View",
"NoSSR",
"WithSSRPlaceholder",
"addStyle",

@@ -20,0 +20,0 @@ "getClickableBehavior",

{
"name": "@khanacademy/wonder-blocks-core",
"version": "1.2.7",
"version": "2.0.0",
"design": "v1",

@@ -16,3 +16,3 @@ "publishConfig": {

"dependencies": {
"@khanacademy/wonder-blocks-spacing": "^2.0.12"
"@khanacademy/wonder-blocks-spacing": "^2.0.13"
},

@@ -19,0 +19,0 @@ "peerDependencies": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc