@khanacademy/wonder-blocks-core 5.0.4 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/components/render-state-root.d.ts +1 -1
- package/dist/components/render-state-root.js.flow +1 -1
- package/dist/es/index.js +12 -9
- package/dist/hooks/use-latest-ref.d.ts +12 -0
- package/dist/hooks/use-latest-ref.js.flow +16 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +12 -8
- package/dist/index.js.flow +1 -0
- package/dist/util/add-style.d.ts +182 -2
- package/dist/util/add-style.js.flow +10 -18
- package/dist/util/types.d.ts +10 -0
- package/dist/util/types.js.flow +12 -0
- package/package.json +2 -2
- package/src/components/render-state-root.tsx +3 -9
- package/src/components/view.tsx +5 -5
- package/src/hooks/__tests__/use-force-update.test.tsx +1 -1
- package/src/hooks/__tests__/use-latest-ref.test.ts +40 -0
- package/src/hooks/use-latest-ref.js.flow +16 -0
- package/src/hooks/use-latest-ref.ts +17 -0
- package/src/index.ts +1 -0
- package/src/util/__tests__/add-style.test.tsx +21 -1
- package/src/util/add-style.js.flow +13 -0
- package/src/util/add-style.tsx +214 -11
- package/src/util/types.ts +12 -0
- package/tsconfig-build.tsbuildinfo +1 -0
- package/src/util/__docs__/add-style.stories.mdx +0 -158
- package/src/util/__docs__/server.stories.mdx +0 -34
- package/tsconfig.tsbuildinfo +0 -1
- /package/dist/util/{add-styles.flowtest.d.ts → add-styles.typestest.d.ts} +0 -0
- /package/dist/util/{add-styles.flowtest.js.flow → add-styles.typestest.js.flow} +0 -0
- /package/src/util/{add-styles.flowtest.tsx → add-styles.typestest.tsx} +0 -0
- /package/{tsconfig.json → tsconfig-build.json} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-core
|
|
2
2
|
|
|
3
|
+
## 5.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- fa70c895: Add 'lang', 'className' and 'htmlFor' properties to Text and View
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 19ab0408: Update flowgen to convert React.ForwardRefExoticComponent<> and React.FowardedRef<> properly
|
|
12
|
+
- fa70c895: Remove all TypeScript error suppressions on JSX attributes
|
|
13
|
+
|
|
14
|
+
## 5.1.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- 3c400719: Add useLatestRef hook to wonder-blocks-core
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- a6164ed0: Don't use React.FC<> for functional components
|
|
23
|
+
|
|
3
24
|
## 5.0.4
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/dist/es/index.js
CHANGED
|
@@ -119,7 +119,7 @@ Text.defaultProps = {
|
|
|
119
119
|
|
|
120
120
|
const _excluded$1 = ["className", "style"];
|
|
121
121
|
function addStyle(Component, defaultStyle) {
|
|
122
|
-
|
|
122
|
+
return React.forwardRef((props, ref) => {
|
|
123
123
|
const {
|
|
124
124
|
className,
|
|
125
125
|
style
|
|
@@ -131,11 +131,11 @@ function addStyle(Component, defaultStyle) {
|
|
|
131
131
|
style: inlineStyles
|
|
132
132
|
} = processStyleList([reset, defaultStyle, style]);
|
|
133
133
|
return React.createElement(Component, _extends({}, otherProps, {
|
|
134
|
+
ref: ref,
|
|
134
135
|
className: [aphroditeClassName, className].filter(Boolean).join(" "),
|
|
135
136
|
style: inlineStyles
|
|
136
137
|
}));
|
|
137
|
-
};
|
|
138
|
-
return StyleComponent;
|
|
138
|
+
});
|
|
139
139
|
}
|
|
140
140
|
const overrides = StyleSheet.create({
|
|
141
141
|
button: {
|
|
@@ -422,6 +422,12 @@ const useIsMounted = () => {
|
|
|
422
422
|
return React.useCallback(() => isMounted.current, []);
|
|
423
423
|
};
|
|
424
424
|
|
|
425
|
+
function useLatestRef(value) {
|
|
426
|
+
const ref = React.useRef(value);
|
|
427
|
+
ref.current = value;
|
|
428
|
+
return ref;
|
|
429
|
+
}
|
|
430
|
+
|
|
425
431
|
const useOnline = () => {
|
|
426
432
|
const forceUpdate = useForceUpdate();
|
|
427
433
|
useEffect$1(() => {
|
|
@@ -442,7 +448,7 @@ const {
|
|
|
442
448
|
} = React;
|
|
443
449
|
const RenderStateRoot = ({
|
|
444
450
|
children,
|
|
445
|
-
throwIfNested
|
|
451
|
+
throwIfNested: _throwIfNested = true
|
|
446
452
|
}) => {
|
|
447
453
|
const [firstRender, setFirstRender] = useState(true);
|
|
448
454
|
const renderState = useRenderState();
|
|
@@ -450,7 +456,7 @@ const RenderStateRoot = ({
|
|
|
450
456
|
setFirstRender(false);
|
|
451
457
|
}, []);
|
|
452
458
|
if (renderState !== RenderState.Root) {
|
|
453
|
-
if (
|
|
459
|
+
if (_throwIfNested) {
|
|
454
460
|
throw new Error("There's already a <RenderStateRoot> above this instance in " + "the render tree. This instance should be removed.");
|
|
455
461
|
}
|
|
456
462
|
return children;
|
|
@@ -460,8 +466,5 @@ const RenderStateRoot = ({
|
|
|
460
466
|
value: value
|
|
461
467
|
}, children);
|
|
462
468
|
};
|
|
463
|
-
RenderStateRoot.defaultProps = {
|
|
464
|
-
throwIfNested: true
|
|
465
|
-
};
|
|
466
469
|
|
|
467
|
-
export { IDProvider, RenderState, RenderStateRoot, server as Server, Text, UniqueIDProvider, View, WithSSRPlaceholder, addStyle, useForceUpdate, useIsMounted, useOnMountEffect, useOnline, useRenderState, useUniqueIdWithMock, useUniqueIdWithoutMock };
|
|
470
|
+
export { IDProvider, RenderState, RenderStateRoot, server as Server, Text, UniqueIDProvider, View, WithSSRPlaceholder, addStyle, useForceUpdate, useIsMounted, useLatestRef, useOnMountEffect, useOnline, useRenderState, useUniqueIdWithMock, useUniqueIdWithoutMock };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Return a ref that always contains the `value` passed.
|
|
4
|
+
*
|
|
5
|
+
* The useLatestRef hook returns a ref that always contains the `value` passed
|
|
6
|
+
* to the hook during the most recent render.
|
|
7
|
+
*
|
|
8
|
+
* It can be used to wrap a possibly-changing prop in a stable value that can
|
|
9
|
+
* be passed to useEffect without causing unnecessary re-renders. See the
|
|
10
|
+
* Storybook docs for a usage example.
|
|
11
|
+
*/
|
|
12
|
+
export declare function useLatestRef<T>(value: T): React.RefObject<T>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flowtype definitions for useLatestRef
|
|
3
|
+
* @flow
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Return a ref that always contains the `value` passed.
|
|
8
|
+
*
|
|
9
|
+
* The useLatestRef hook returns a ref that always contains the `value` passed
|
|
10
|
+
* to the hook during the most recent render.
|
|
11
|
+
*
|
|
12
|
+
* It can be used to wrap a possibly-changing prop in a stable value that can
|
|
13
|
+
* be passed to useEffect without causing unnecessary re-renders. See the
|
|
14
|
+
* Storybook docs for a usage example.
|
|
15
|
+
*/
|
|
16
|
+
declare export function useLatestRef<T>(value: T): {|current: T|};
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { default as Server } from "./util/server";
|
|
|
9
9
|
export { useUniqueIdWithMock, useUniqueIdWithoutMock, } from "./hooks/use-unique-id";
|
|
10
10
|
export { useForceUpdate } from "./hooks/use-force-update";
|
|
11
11
|
export { useIsMounted } from "./hooks/use-is-mounted";
|
|
12
|
+
export { useLatestRef } from "./hooks/use-latest-ref";
|
|
12
13
|
export { useOnMountEffect } from "./hooks/use-on-mount-effect";
|
|
13
14
|
export { useOnline } from "./hooks/use-online";
|
|
14
15
|
export { useRenderState } from "./hooks/use-render-state";
|
package/dist/index.js
CHANGED
|
@@ -142,7 +142,7 @@ Text.defaultProps = {
|
|
|
142
142
|
|
|
143
143
|
const _excluded$1 = ["className", "style"];
|
|
144
144
|
function addStyle(Component, defaultStyle) {
|
|
145
|
-
|
|
145
|
+
return React__namespace.forwardRef((props, ref) => {
|
|
146
146
|
const {
|
|
147
147
|
className,
|
|
148
148
|
style
|
|
@@ -154,11 +154,11 @@ function addStyle(Component, defaultStyle) {
|
|
|
154
154
|
style: inlineStyles
|
|
155
155
|
} = processStyleList([reset, defaultStyle, style]);
|
|
156
156
|
return React__namespace.createElement(Component, _extends({}, otherProps, {
|
|
157
|
+
ref: ref,
|
|
157
158
|
className: [aphroditeClassName, className].filter(Boolean).join(" "),
|
|
158
159
|
style: inlineStyles
|
|
159
160
|
}));
|
|
160
|
-
};
|
|
161
|
-
return StyleComponent;
|
|
161
|
+
});
|
|
162
162
|
}
|
|
163
163
|
const overrides = aphrodite.StyleSheet.create({
|
|
164
164
|
button: {
|
|
@@ -445,6 +445,12 @@ const useIsMounted = () => {
|
|
|
445
445
|
return React__namespace.useCallback(() => isMounted.current, []);
|
|
446
446
|
};
|
|
447
447
|
|
|
448
|
+
function useLatestRef(value) {
|
|
449
|
+
const ref = React__namespace.useRef(value);
|
|
450
|
+
ref.current = value;
|
|
451
|
+
return ref;
|
|
452
|
+
}
|
|
453
|
+
|
|
448
454
|
const useOnline = () => {
|
|
449
455
|
const forceUpdate = useForceUpdate();
|
|
450
456
|
React.useEffect(() => {
|
|
@@ -465,7 +471,7 @@ const {
|
|
|
465
471
|
} = React__namespace;
|
|
466
472
|
const RenderStateRoot = ({
|
|
467
473
|
children,
|
|
468
|
-
throwIfNested
|
|
474
|
+
throwIfNested: _throwIfNested = true
|
|
469
475
|
}) => {
|
|
470
476
|
const [firstRender, setFirstRender] = useState(true);
|
|
471
477
|
const renderState = useRenderState();
|
|
@@ -473,7 +479,7 @@ const RenderStateRoot = ({
|
|
|
473
479
|
setFirstRender(false);
|
|
474
480
|
}, []);
|
|
475
481
|
if (renderState !== RenderState.Root) {
|
|
476
|
-
if (
|
|
482
|
+
if (_throwIfNested) {
|
|
477
483
|
throw new Error("There's already a <RenderStateRoot> above this instance in " + "the render tree. This instance should be removed.");
|
|
478
484
|
}
|
|
479
485
|
return children;
|
|
@@ -483,9 +489,6 @@ const RenderStateRoot = ({
|
|
|
483
489
|
value: value
|
|
484
490
|
}, children);
|
|
485
491
|
};
|
|
486
|
-
RenderStateRoot.defaultProps = {
|
|
487
|
-
throwIfNested: true
|
|
488
|
-
};
|
|
489
492
|
|
|
490
493
|
exports.IDProvider = IDProvider;
|
|
491
494
|
exports.RenderState = RenderState;
|
|
@@ -498,6 +501,7 @@ exports.WithSSRPlaceholder = WithSSRPlaceholder;
|
|
|
498
501
|
exports.addStyle = addStyle;
|
|
499
502
|
exports.useForceUpdate = useForceUpdate;
|
|
500
503
|
exports.useIsMounted = useIsMounted;
|
|
504
|
+
exports.useLatestRef = useLatestRef;
|
|
501
505
|
exports.useOnMountEffect = useOnMountEffect;
|
|
502
506
|
exports.useOnline = useOnline;
|
|
503
507
|
exports.useRenderState = useRenderState;
|
package/dist/index.js.flow
CHANGED
|
@@ -18,6 +18,7 @@ declare export {
|
|
|
18
18
|
} from "./hooks/use-unique-id";
|
|
19
19
|
declare export { useForceUpdate } from "./hooks/use-force-update";
|
|
20
20
|
declare export { useIsMounted } from "./hooks/use-is-mounted";
|
|
21
|
+
declare export { useLatestRef } from "./hooks/use-latest-ref";
|
|
21
22
|
declare export { useOnMountEffect } from "./hooks/use-on-mount-effect";
|
|
22
23
|
declare export { useOnline } from "./hooks/use-online";
|
|
23
24
|
declare export { useRenderState } from "./hooks/use-render-state";
|
package/dist/util/add-style.d.ts
CHANGED
|
@@ -1,5 +1,185 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { StyleType } from "./types";
|
|
3
|
-
export default function addStyle<T extends React.ComponentType<any> | keyof JSX.IntrinsicElements
|
|
3
|
+
export default function addStyle<T extends React.ComponentType<any> | keyof JSX.IntrinsicElements, Props extends {
|
|
4
|
+
className?: string;
|
|
4
5
|
style?: StyleType;
|
|
5
|
-
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
} & Omit<React.ComponentProps<T>, "style">>(Component: T, defaultStyle?: StyleType): React.ForwardRefExoticComponent<React.PropsWithoutRef<Props> & React.RefAttributes<T extends keyof JSX.IntrinsicElements ? IntrinsicElementsMap[T] : T>>;
|
|
8
|
+
type IntrinsicElementsMap = {
|
|
9
|
+
a: HTMLAnchorElement;
|
|
10
|
+
abbr: HTMLElement;
|
|
11
|
+
address: HTMLElement;
|
|
12
|
+
area: HTMLAreaElement;
|
|
13
|
+
article: HTMLElement;
|
|
14
|
+
aside: HTMLElement;
|
|
15
|
+
audio: HTMLAudioElement;
|
|
16
|
+
b: HTMLElement;
|
|
17
|
+
base: HTMLBaseElement;
|
|
18
|
+
bdi: HTMLElement;
|
|
19
|
+
bdo: HTMLElement;
|
|
20
|
+
big: HTMLElement;
|
|
21
|
+
blockquote: HTMLElement;
|
|
22
|
+
body: HTMLBodyElement;
|
|
23
|
+
br: HTMLBRElement;
|
|
24
|
+
button: HTMLButtonElement;
|
|
25
|
+
canvas: HTMLCanvasElement;
|
|
26
|
+
caption: HTMLElement;
|
|
27
|
+
cite: HTMLElement;
|
|
28
|
+
code: HTMLElement;
|
|
29
|
+
col: HTMLTableColElement;
|
|
30
|
+
colgroup: HTMLTableColElement;
|
|
31
|
+
data: HTMLDataElement;
|
|
32
|
+
datalist: HTMLDataListElement;
|
|
33
|
+
dd: HTMLElement;
|
|
34
|
+
del: HTMLElement;
|
|
35
|
+
details: HTMLElement;
|
|
36
|
+
dfn: HTMLElement;
|
|
37
|
+
dialog: HTMLDialogElement;
|
|
38
|
+
div: HTMLDivElement;
|
|
39
|
+
dl: HTMLDListElement;
|
|
40
|
+
dt: HTMLElement;
|
|
41
|
+
em: HTMLElement;
|
|
42
|
+
embed: HTMLEmbedElement;
|
|
43
|
+
fieldset: HTMLFieldSetElement;
|
|
44
|
+
figcaption: HTMLElement;
|
|
45
|
+
figure: HTMLElement;
|
|
46
|
+
footer: HTMLElement;
|
|
47
|
+
form: HTMLFormElement;
|
|
48
|
+
h1: HTMLHeadingElement;
|
|
49
|
+
h2: HTMLHeadingElement;
|
|
50
|
+
h3: HTMLHeadingElement;
|
|
51
|
+
h4: HTMLHeadingElement;
|
|
52
|
+
h5: HTMLHeadingElement;
|
|
53
|
+
h6: HTMLHeadingElement;
|
|
54
|
+
head: HTMLHeadElement;
|
|
55
|
+
header: HTMLElement;
|
|
56
|
+
hgroup: HTMLElement;
|
|
57
|
+
hr: HTMLHRElement;
|
|
58
|
+
html: HTMLHtmlElement;
|
|
59
|
+
i: HTMLElement;
|
|
60
|
+
iframe: HTMLIFrameElement;
|
|
61
|
+
img: HTMLImageElement;
|
|
62
|
+
input: HTMLInputElement;
|
|
63
|
+
ins: HTMLModElement;
|
|
64
|
+
kbd: HTMLElement;
|
|
65
|
+
keygen: HTMLElement;
|
|
66
|
+
label: HTMLLabelElement;
|
|
67
|
+
legend: HTMLLegendElement;
|
|
68
|
+
li: HTMLLIElement;
|
|
69
|
+
link: HTMLLinkElement;
|
|
70
|
+
main: HTMLElement;
|
|
71
|
+
map: HTMLMapElement;
|
|
72
|
+
mark: HTMLElement;
|
|
73
|
+
menu: HTMLElement;
|
|
74
|
+
menuitem: HTMLElement;
|
|
75
|
+
meta: HTMLMetaElement;
|
|
76
|
+
meter: HTMLElement;
|
|
77
|
+
nav: HTMLElement;
|
|
78
|
+
noindex: HTMLElement;
|
|
79
|
+
noscript: HTMLElement;
|
|
80
|
+
object: HTMLObjectElement;
|
|
81
|
+
ol: HTMLOListElement;
|
|
82
|
+
optgroup: HTMLOptGroupElement;
|
|
83
|
+
option: HTMLOptionElement;
|
|
84
|
+
output: HTMLElement;
|
|
85
|
+
p: HTMLParagraphElement;
|
|
86
|
+
param: HTMLParamElement;
|
|
87
|
+
picture: HTMLElement;
|
|
88
|
+
pre: HTMLPreElement;
|
|
89
|
+
progress: HTMLProgressElement;
|
|
90
|
+
q: HTMLQuoteElement;
|
|
91
|
+
rp: HTMLElement;
|
|
92
|
+
rt: HTMLElement;
|
|
93
|
+
ruby: HTMLElement;
|
|
94
|
+
s: HTMLElement;
|
|
95
|
+
samp: HTMLElement;
|
|
96
|
+
slot: HTMLSlotElement;
|
|
97
|
+
script: HTMLScriptElement;
|
|
98
|
+
section: HTMLElement;
|
|
99
|
+
select: HTMLSelectElement;
|
|
100
|
+
small: HTMLElement;
|
|
101
|
+
source: HTMLSourceElement;
|
|
102
|
+
span: HTMLSpanElement;
|
|
103
|
+
strong: HTMLElement;
|
|
104
|
+
style: HTMLStyleElement;
|
|
105
|
+
sub: HTMLElement;
|
|
106
|
+
summary: HTMLElement;
|
|
107
|
+
sup: HTMLElement;
|
|
108
|
+
table: HTMLTableElement;
|
|
109
|
+
template: HTMLTemplateElement;
|
|
110
|
+
tbody: HTMLTableSectionElement;
|
|
111
|
+
td: HTMLElement;
|
|
112
|
+
textarea: HTMLTextAreaElement;
|
|
113
|
+
tfoot: HTMLTableSectionElement;
|
|
114
|
+
th: HTMLElement;
|
|
115
|
+
thead: HTMLTableSectionElement;
|
|
116
|
+
time: HTMLElement;
|
|
117
|
+
title: HTMLTitleElement;
|
|
118
|
+
tr: HTMLTableRowElement;
|
|
119
|
+
track: HTMLTrackElement;
|
|
120
|
+
u: HTMLElement;
|
|
121
|
+
ul: HTMLUListElement;
|
|
122
|
+
var: HTMLElement;
|
|
123
|
+
video: HTMLVideoElement;
|
|
124
|
+
wbr: HTMLElement;
|
|
125
|
+
webview: HTMLElement;
|
|
126
|
+
svg: SVGSVGElement;
|
|
127
|
+
animate: SVGElement;
|
|
128
|
+
animateMotion: SVGElement;
|
|
129
|
+
animateTransform: SVGElement;
|
|
130
|
+
circle: SVGCircleElement;
|
|
131
|
+
clipPath: SVGClipPathElement;
|
|
132
|
+
defs: SVGDefsElement;
|
|
133
|
+
desc: SVGDescElement;
|
|
134
|
+
ellipse: SVGEllipseElement;
|
|
135
|
+
feBlend: SVGFEBlendElement;
|
|
136
|
+
feColorMatrix: SVGFEColorMatrixElement;
|
|
137
|
+
feComponentTransfer: SVGFEComponentTransferElement;
|
|
138
|
+
feComposite: SVGFECompositeElement;
|
|
139
|
+
feConvolveMatrix: SVGFEConvolveMatrixElement;
|
|
140
|
+
feDiffuseLighting: SVGFEDiffuseLightingElement;
|
|
141
|
+
feDisplacementMap: SVGFEDisplacementMapElement;
|
|
142
|
+
feDistantLight: SVGFEDistantLightElement;
|
|
143
|
+
feDropShadow: SVGFEDropShadowElement;
|
|
144
|
+
feFlood: SVGFEFloodElement;
|
|
145
|
+
feFuncA: SVGFEFuncAElement;
|
|
146
|
+
feFuncB: SVGFEFuncBElement;
|
|
147
|
+
feFuncG: SVGFEFuncGElement;
|
|
148
|
+
feFuncR: SVGFEFuncRElement;
|
|
149
|
+
feGaussianBlur: SVGFEGaussianBlurElement;
|
|
150
|
+
feImage: SVGFEImageElement;
|
|
151
|
+
feMerge: SVGFEMergeElement;
|
|
152
|
+
feMergeNode: SVGFEMergeNodeElement;
|
|
153
|
+
feMorphology: SVGFEMorphologyElement;
|
|
154
|
+
feOffset: SVGFEOffsetElement;
|
|
155
|
+
fePointLight: SVGFEPointLightElement;
|
|
156
|
+
feSpecularLighting: SVGFESpecularLightingElement;
|
|
157
|
+
feSpotLight: SVGFESpotLightElement;
|
|
158
|
+
feTile: SVGFETileElement;
|
|
159
|
+
feTurbulence: SVGFETurbulenceElement;
|
|
160
|
+
filter: SVGFilterElement;
|
|
161
|
+
foreignObject: SVGForeignObjectElement;
|
|
162
|
+
g: SVGGElement;
|
|
163
|
+
image: SVGImageElement;
|
|
164
|
+
line: SVGLineElement;
|
|
165
|
+
linearGradient: SVGLinearGradientElement;
|
|
166
|
+
marker: SVGMarkerElement;
|
|
167
|
+
mask: SVGMaskElement;
|
|
168
|
+
metadata: SVGMetadataElement;
|
|
169
|
+
mpath: SVGElement;
|
|
170
|
+
path: SVGPathElement;
|
|
171
|
+
pattern: SVGPatternElement;
|
|
172
|
+
polygon: SVGPolygonElement;
|
|
173
|
+
polyline: SVGPolylineElement;
|
|
174
|
+
radialGradient: SVGRadialGradientElement;
|
|
175
|
+
rect: SVGRectElement;
|
|
176
|
+
stop: SVGStopElement;
|
|
177
|
+
switch: SVGSwitchElement;
|
|
178
|
+
symbol: SVGSymbolElement;
|
|
179
|
+
text: SVGTextElement;
|
|
180
|
+
textPath: SVGTextPathElement;
|
|
181
|
+
tspan: SVGTSpanElement;
|
|
182
|
+
use: SVGUseElement;
|
|
183
|
+
view: SVGViewElement;
|
|
184
|
+
};
|
|
185
|
+
export {};
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Flowtype definitions for data
|
|
3
|
-
* Generated by Flowgen from a Typescript Definition
|
|
4
|
-
* Flowgen v1.21.0
|
|
5
|
-
* @flow
|
|
6
|
-
*/
|
|
7
1
|
import * as React from "react";
|
|
8
|
-
import type {
|
|
2
|
+
import type {StyleType} from "./types";
|
|
3
|
+
|
|
9
4
|
declare export default function addStyle<
|
|
10
|
-
|
|
5
|
+
T: React.AbstractComponent<any> | string,
|
|
11
6
|
>(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
): React.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|}
|
|
20
|
-
>
|
|
21
|
-
>;
|
|
7
|
+
Component: T,
|
|
8
|
+
defaultStyle?: StyleType,
|
|
9
|
+
): React.AbstractComponent<{
|
|
10
|
+
...React.ElementConfig<T>,
|
|
11
|
+
style?: StyleType,
|
|
12
|
+
...
|
|
13
|
+
}>;
|
package/dist/util/types.d.ts
CHANGED
|
@@ -62,6 +62,16 @@ export type TextViewSharedProps = {
|
|
|
62
62
|
* Test ID used for e2e testing.
|
|
63
63
|
*/
|
|
64
64
|
testId?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Optional attribute to indicate to the Screen Reader which language the
|
|
67
|
+
* item text is in.
|
|
68
|
+
*/
|
|
69
|
+
lang?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Optional CSS classes for the entire dropdown component.
|
|
72
|
+
*/
|
|
73
|
+
className?: string;
|
|
74
|
+
htmlFor?: string;
|
|
65
75
|
tabIndex?: number;
|
|
66
76
|
id?: string;
|
|
67
77
|
"data-modal-launcher-portal"?: boolean;
|
package/dist/util/types.js.flow
CHANGED
|
@@ -82,6 +82,18 @@ export type TextViewSharedProps = {|
|
|
|
82
82
|
* Test ID used for e2e testing.
|
|
83
83
|
*/
|
|
84
84
|
testId?: string,
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Optional attribute to indicate to the Screen Reader which language the
|
|
88
|
+
* item text is in.
|
|
89
|
+
*/
|
|
90
|
+
lang?: string,
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Optional CSS classes for the entire dropdown component.
|
|
94
|
+
*/
|
|
95
|
+
className?: string,
|
|
96
|
+
htmlFor?: string,
|
|
85
97
|
tabIndex?: number,
|
|
86
98
|
id?: string,
|
|
87
99
|
"data-modal-launcher-portal"?: boolean,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-core",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"react-router-dom": "5.3.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"wb-dev-build-settings": "^0.9.
|
|
26
|
+
"wb-dev-build-settings": "^0.9.7"
|
|
27
27
|
},
|
|
28
28
|
"author": "",
|
|
29
29
|
"license": "MIT"
|
|
@@ -13,10 +13,10 @@ type Props = {
|
|
|
13
13
|
throwIfNested?: boolean;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
const RenderStateRoot
|
|
16
|
+
const RenderStateRoot = ({
|
|
17
17
|
children,
|
|
18
|
-
throwIfNested,
|
|
19
|
-
}): React.ReactElement => {
|
|
18
|
+
throwIfNested = true,
|
|
19
|
+
}: Props): React.ReactElement => {
|
|
20
20
|
const [firstRender, setFirstRender] = useState<boolean>(true);
|
|
21
21
|
const renderState = useRenderState();
|
|
22
22
|
useEffect(() => {
|
|
@@ -45,10 +45,4 @@ const RenderStateRoot: React.FC<Props> = ({
|
|
|
45
45
|
);
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
// We can set `defaultProps` on a functional component if we move the `export` to appear
|
|
49
|
-
// afterwards.
|
|
50
|
-
RenderStateRoot.defaultProps = {
|
|
51
|
-
throwIfNested: true,
|
|
52
|
-
};
|
|
53
|
-
|
|
54
48
|
export {RenderStateRoot};
|
package/src/components/view.tsx
CHANGED
|
@@ -37,11 +37,11 @@ type DefaultProps = {
|
|
|
37
37
|
tag: Props["tag"];
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
const StyledDiv = addStyle
|
|
41
|
-
const StyledArticle = addStyle
|
|
42
|
-
const StyledAside = addStyle
|
|
43
|
-
const StyledNav = addStyle
|
|
44
|
-
const StyledSection = addStyle
|
|
40
|
+
const StyledDiv = addStyle("div", styles.default);
|
|
41
|
+
const StyledArticle = addStyle("article", styles.default);
|
|
42
|
+
const StyledAside = addStyle("aside", styles.default);
|
|
43
|
+
const StyledNav = addStyle("nav", styles.default);
|
|
44
|
+
const StyledSection = addStyle("section", styles.default);
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* View is a building block for constructing other components. `View` roughly
|
|
@@ -24,7 +24,7 @@ describe("#useForceUpdate", () => {
|
|
|
24
24
|
|
|
25
25
|
it("should cause component to render", () => {
|
|
26
26
|
// Arrange
|
|
27
|
-
const Component
|
|
27
|
+
const Component = (): React.ReactElement => {
|
|
28
28
|
const countRef = React.useRef(0);
|
|
29
29
|
const forceUpdate = useForceUpdate();
|
|
30
30
|
React.useEffect(() => {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {renderHook} from "@testing-library/react-hooks";
|
|
2
|
+
import {useLatestRef} from "../use-latest-ref";
|
|
3
|
+
|
|
4
|
+
describe("useLatestRef", () => {
|
|
5
|
+
it("returns a ref to the value passed in", () => {
|
|
6
|
+
const {
|
|
7
|
+
result: {current: ref},
|
|
8
|
+
} = renderHook(() => useLatestRef(123));
|
|
9
|
+
expect(ref.current).toBe(123);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("returns a ref to the most recent value passed in", () => {
|
|
13
|
+
// Arrange: render the component with props {value: 123}
|
|
14
|
+
const {result, rerender} = renderHook(
|
|
15
|
+
({value}) => useLatestRef(value),
|
|
16
|
+
{initialProps: {value: 123}},
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// Act
|
|
20
|
+
rerender({value: 456});
|
|
21
|
+
|
|
22
|
+
// Assert
|
|
23
|
+
expect(result.current.current).toBe(456);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("returns a stable ref object for the lifetime of the component", () => {
|
|
27
|
+
// Arrange: render the component and remember the ref
|
|
28
|
+
const {result, rerender} = renderHook(
|
|
29
|
+
({value}) => useLatestRef(value),
|
|
30
|
+
{initialProps: {value: 123}},
|
|
31
|
+
);
|
|
32
|
+
const refFromFirstRender = result.current;
|
|
33
|
+
|
|
34
|
+
// Act
|
|
35
|
+
rerender({value: 456});
|
|
36
|
+
|
|
37
|
+
// Assert
|
|
38
|
+
expect(result.current).toBe(refFromFirstRender);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flowtype definitions for useLatestRef
|
|
3
|
+
* @flow
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Return a ref that always contains the `value` passed.
|
|
8
|
+
*
|
|
9
|
+
* The useLatestRef hook returns a ref that always contains the `value` passed
|
|
10
|
+
* to the hook during the most recent render.
|
|
11
|
+
*
|
|
12
|
+
* It can be used to wrap a possibly-changing prop in a stable value that can
|
|
13
|
+
* be passed to useEffect without causing unnecessary re-renders. See the
|
|
14
|
+
* Storybook docs for a usage example.
|
|
15
|
+
*/
|
|
16
|
+
declare export function useLatestRef<T>(value: T): {|current: T|};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Return a ref that always contains the `value` passed.
|
|
5
|
+
*
|
|
6
|
+
* The useLatestRef hook returns a ref that always contains the `value` passed
|
|
7
|
+
* to the hook during the most recent render.
|
|
8
|
+
*
|
|
9
|
+
* It can be used to wrap a possibly-changing prop in a stable value that can
|
|
10
|
+
* be passed to useEffect without causing unnecessary re-renders. See the
|
|
11
|
+
* Storybook docs for a usage example.
|
|
12
|
+
*/
|
|
13
|
+
export function useLatestRef<T>(value: T): React.RefObject<T> {
|
|
14
|
+
const ref = React.useRef(value);
|
|
15
|
+
ref.current = value;
|
|
16
|
+
return ref;
|
|
17
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ export {
|
|
|
13
13
|
} from "./hooks/use-unique-id";
|
|
14
14
|
export {useForceUpdate} from "./hooks/use-force-update";
|
|
15
15
|
export {useIsMounted} from "./hooks/use-is-mounted";
|
|
16
|
+
export {useLatestRef} from "./hooks/use-latest-ref";
|
|
16
17
|
export {useOnMountEffect} from "./hooks/use-on-mount-effect";
|
|
17
18
|
export {useOnline} from "./hooks/use-online";
|
|
18
19
|
export {useRenderState} from "./hooks/use-render-state";
|
|
@@ -4,7 +4,7 @@ import {screen, render} from "@testing-library/react";
|
|
|
4
4
|
|
|
5
5
|
import addStyle from "../add-style";
|
|
6
6
|
|
|
7
|
-
const StyledDiv = addStyle
|
|
7
|
+
const StyledDiv = addStyle("div");
|
|
8
8
|
|
|
9
9
|
const styles = StyleSheet.create({
|
|
10
10
|
foo: {
|
|
@@ -88,4 +88,24 @@ describe("addStyle", () => {
|
|
|
88
88
|
expect(classNames[0]).toEqual(expect.any(String));
|
|
89
89
|
expect(classNames[1]).toEqual("foo");
|
|
90
90
|
});
|
|
91
|
+
|
|
92
|
+
it("should forward a ref to the component", () => {
|
|
93
|
+
// Arrange
|
|
94
|
+
const ref = React.createRef<HTMLDivElement>();
|
|
95
|
+
|
|
96
|
+
render(
|
|
97
|
+
<StyledDiv
|
|
98
|
+
className="foo"
|
|
99
|
+
style={styles.foo}
|
|
100
|
+
data-test-id="styled-div"
|
|
101
|
+
ref={ref}
|
|
102
|
+
/>,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// Act
|
|
106
|
+
const div = screen.getByTestId("styled-div");
|
|
107
|
+
|
|
108
|
+
// Assert
|
|
109
|
+
expect(div).toBe(ref.current);
|
|
110
|
+
});
|
|
91
111
|
});
|